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

+61
View File
@@ -0,0 +1,61 @@
#
# @RDE_HEADER@
# $Id$
# $HeadURL$
# $Author$
# Created by Christian Ehrlicher, SLSE, 2017-06-16
#
ADD_SUBDIRECTORY(Data)
ADD_SUBDIRECTORY(Gui/FilterChange)
ADD_SUBDIRECTORY(Gui/Aes)
ADD_SUBDIRECTORY(Gui/Participant)
ADD_SUBDIRECTORY(Gui/BuildingComponents)
#
# Data Plugin Interface
#
ADD_INTERFACE_LIBRARY(
FltDataPluginInterface
${CMAKE_CURRENT_SOURCE_DIR}/flt_data_plugin_interface.h
${CMAKE_CURRENT_SOURCE_DIR}/..
DataPluginInterface
svcFltCommon
svcAesCommon
)
add_dependencies(FltDataPluginInterface svcAesCommon)
TARGET_SOURCES(FltDataPluginInterface
INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}/flt_building_cmpnt_settings.h
${CMAKE_CURRENT_SOURCE_DIR}/flt_data_plugin_aes_display_filter.h
${CMAKE_CURRENT_SOURCE_DIR}/flt_symbol_appearance_settings.h
)
#
# Building-Component Filter Gui Plugin Interface
#
ADD_INTERFACE_LIBRARY(FltBldgCmpntGuiPluginInterface
${CMAKE_CURRENT_SOURCE_DIR}/flt_building_cmpnt_plugin_interface.h
${CMAKE_CURRENT_SOURCE_DIR}/..
GuiPluginInterface
FltDataPluginInterface
)
#
# Aes Filter Gui Plugin Interface
#
ADD_INTERFACE_LIBRARY(FltAesGuiPluginInterface
${CMAKE_CURRENT_SOURCE_DIR}/flt_aes_plugin_interface.h
${CMAKE_CURRENT_SOURCE_DIR}/..
GuiPluginInterface
FltDataPluginInterface
)
#
# Participant Filter Gui Plugin Interface
#
ADD_INTERFACE_LIBRARY(FltParticipantGuiPluginInterface
${CMAKE_CURRENT_SOURCE_DIR}/flt_participant_plugin_interface.h
${CMAKE_CURRENT_SOURCE_DIR}/..
GuiPluginInterface
)
+28
View File
@@ -0,0 +1,28 @@
#
# @RDE_HEADER@
# $Id$
# $HeadURL$
# $Author$
#
# Created by Christian Ehrlicher, SLSE, 2017-06-19
#
#
# Data Plugin
#
SET(SRCS
flt_data_plugin.cpp
flt_data_plugin.h
)
NGL_ADD_LIBRARY(WS FltDataPlugin MODULE ${SRCS})
NGL_TARGET_LINK_LIBRARIES(FltDataPlugin
Qt5::Core
FltDataPluginInterface
PpmDataPluginInterface
svcFltClient
svcAesCommon # generated header only ...
NGLLogger
LtsSessionData
LtsSessionDataDds
)
NGL_INSTALL_TARGET(FltDataPlugin)
+42
View File
@@ -0,0 +1,42 @@
/**
* @RDE_HEADER@
* Data Plugin for FilterManangement
* $Id$
* $HeadURL$
* $Author$
* Created by Mike Wille, SLSE, 2017-03-31
*/
#include "flt_data_plugin.h"
#include <DDS/DDSConnector/dds_connector.h>
#include <LtsSession/lts_session_data_dds.h>
namespace FilterManagement
{
//
// DataPlugin
//
std::shared_ptr<DataPluginBase::Interface> DataPlugin::createDataInterface(LtsSession::LtsSessionDataDds *session)
{
std::shared_ptr<Interface::Dtc> dtc;
std::shared_ptr<Interface::Ftc> ftc;
if (!session->createTopicClient(dtc, ftc))
return std::shared_ptr<DataPluginBase::Interface>();
return std::make_shared<DataInterfaceImpl>(dtc, ftc);
}
//
// DataInterfaceImpl
//
DataInterfaceImpl::DataInterfaceImpl(const std::shared_ptr<FilterManagement::Interface::Dtc> &dtc,
const std::shared_ptr<FilterManagement::Interface::Ftc> &ftc)
: DataInterface()
, m_dtc(dtc)
, m_ftc(ftc)
{}
} // namespace FilterManagement
+61
View File
@@ -0,0 +1,61 @@
/**
* @RDE_HEADER@
* Data Plugin for FilterManangement
* $Id$
* $HeadURL$
* $Author$
* Created by Mike Wille, SLSE, 2017-03-31
*/
#pragma once
#include <PluginInterfaces/data_plugin_interface.h>
#include <Plugins/FilterManagement/flt_data_plugin_interface.h>
#include <FilterManagement/logger.h>
#include <memory>
namespace FilterManagement
{
//
// DataPlugin
//
class DataPlugin final : public QObject, public DataPluginBase::Plugin
{
Q_PLUGIN_METADATA(IID "data:3:flt")
Q_INTERFACES(DataPluginBase::Plugin)
Q_OBJECT
public:
DataPlugin() = default;
~DataPlugin() = default;
QString pluginName() const override { return QStringLiteral("FilterManagement"); }
std::shared_ptr<DataPluginBase::Interface> createDataInterface(LtsSession::LtsSessionDataDds *session) override;
bool availableInPartition(IDL::PartitionType partition) const override
{
return partition == IDL::PartitionType::Exercise ||
partition == IDL::PartitionType::Global ||
partition == IDL::PartitionType::Replay;
}
};
//
// DataInterfaceImpl
//
class DataInterfaceImpl final : public QObject, public DataInterface
{
Q_OBJECT
public:
DataInterfaceImpl(const std::shared_ptr<FilterManagement::Interface::Dtc> &dtc,
const std::shared_ptr<FilterManagement::Interface::Ftc> &ftc);
std::shared_ptr<FilterManagement::Interface::Dtc> getDtc() override { return m_dtc; }
std::shared_ptr<FilterManagement::Interface::Ftc> getFtc() override { return m_ftc; }
private:
std::shared_ptr<FilterManagement::Interface::Dtc> m_dtc;
std::shared_ptr<FilterManagement::Interface::Ftc> m_ftc;
};
} // namespace FilterManagement
+58
View File
@@ -0,0 +1,58 @@
#
# $Id$
# $HeadURL$
# $Author$
# Created by Christian Ehrlicher, SLSE, 2017-06-16
#
ADD_SUBDIRECTORY(Common)
SET(flt_aes_widget_SRCS
flt_aes_filter_widget.cpp
flt_aes_filter_widget.h
)
NGL_WRAP_UI(flt_aes_widget_SRCS
flt_aes_filter_widget.ui
)
NGL_ADD_LIBRARY(WS FltAesWidget STATIC ${flt_aes_widget_SRCS})
NGL_TARGET_LINK_LIBRARIES(FltAesWidget
PRIVATE
svcFltCommon
LtsProjectionWorkstation
PUBLIC
FltDataPluginInterface
LtsSessionData
PdmGuiPluginInterface
PpmGuiComboboxPluginInterface
Qt5::Widgets
)
NGL_TARGET_INCLUDE_DIRECTORIES(FltAesWidget
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../../..
)
SET(flt_aes_gui_SRCS
flt_aes_filter_dialog.cpp
flt_aes_filter_dialog.h
flt_aes_gui_plugin.cpp
flt_aes_gui_plugin.h
)
NGL_ADD_LIBRARY(WS FltAesGuiPlugin MODULE ${flt_aes_gui_SRCS})
NGL_TARGET_LINK_LIBRARIES(FltAesGuiPlugin
FltAesGuiCommon
FltAesGuiPluginInterface
FltAesWidget
FltFilterChange
LtsSession
LtsSessionData
LtsUtilsGuiDds
LtsUtilsSettings
LtsWidgets
Qt5::Widgets
)
NGL_INSTALL_TARGET(FltAesGuiPlugin)
+31
View File
@@ -0,0 +1,31 @@
#
# $Id$
# $HeadURL$
# $Author$
#
# Created by Mike Wille, SLSE, 2017-11-27
#
SET(flt_aes_gui_common_SRCS
common.h
aes_display_filter_impl.h
aes_display_filter_impl.cpp
building_cmpnt_settings_impl.cpp
building_cmpnt_settings_impl.h
symbol_appearance_settings_impl.h
symbol_appearance_settings_impl.cpp
)
NGL_ADD_LIBRARY2(WS FltAesGuiCommon SHARED ${flt_aes_gui_common_SRCS})
NGL_TARGET_LINK_LIBRARIES(FltAesGuiCommon
PRIVATE
svcPpmCommon
PUBLIC
FltDataPluginInterface
Qt5::Core
Qt5::Widgets # ifdef LTS_DEBUG QMessageBox
svcFltCommon
svcAesCommon
)
NGL_INSTALL_TARGET(FltAesGuiCommon)
@@ -0,0 +1,480 @@
/**
* @RDE_HEADER@
* Data Plugin for FilterManangement
* $Id$
* $HeadURL$
* $Author$
* Created by Mike Wille, SLSE, 2017-03-31
*/
#include "aes_display_filter_impl.h"
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonDocument>
namespace FilterManagement
{
static inline std::vector<AreaEffectSimulation::AesType> aesTypes()
{
return { AreaEffectSimulation::AesType::AtNContamination,
AreaEffectSimulation::AesType::AtBCContamination,
AreaEffectSimulation::AesType::AtExplosionArea,
AreaEffectSimulation::AesType::AtExplosionSingle,
AreaEffectSimulation::AesType::AtMineArea,
AreaEffectSimulation::AesType::AtMineCorridor,
AreaEffectSimulation::AesType::AtDangerArea,
AreaEffectSimulation::AesType::AtFunctionalArea,
AreaEffectSimulation::AesType::AtBorderline,
AreaEffectSimulation::AesType::AtMineAreaSingleMines, // Only IED-Filter
AreaEffectSimulation::AesType::AtDusSingleMine,
AreaEffectSimulation::AesType::AtGasPipe,
AreaEffectSimulation::AesType::AtTechnicalArea,
AreaEffectSimulation::AesType::AtAirSupportImpact
};
}
//
// AesDisplayFilterImpl
//
AesDisplayFilterImpl::AesDisplayFilterImpl()
: AesDisplayFilter()
, m_visiblePartiesCheck(nullptr)
, m_logger(getLogger("AesDisplayFilterImpl"))
{
resetAesDisplayFilter();
}
void AesDisplayFilterImpl::resetAesDisplayFilter()
{
resetAesDisplayFilterInternal(true);
}
void AesDisplayFilterImpl::resetAesDisplayFilterInternal(bool executeCallback)
{
m_effectStateMap.clear();
for (AreaEffectSimulation::AesType aesType : aesTypes())
{
m_effectStateMap.insert(aesType, EffectStateStruct());
// set default to false;
if (AreaEffectSimulation::AesType::AtTechnicalArea == aesType.underlying())
m_effectStateMap[AreaEffectSimulation::AesType::AtTechnicalArea].displayActivated = false;
if (executeCallback)
callFilterChangedCb(aesType);
}
}
AesDisplayFilterImpl::~AesDisplayFilterImpl()
{}
bool AesDisplayFilterImpl::setFilterFromData(const AesFilter &filterData)
{
if (m_ddsFilterContent.id() == 0)
m_ddsFilterContent = filterData;
else
m_ddsFilterContent.content(filterData.content());
const QByteArray content(QByteArray::fromRawData(m_ddsFilterContent.content().c_str(), m_ddsFilterContent.content().size()));
if (content.isEmpty())
return true;
QJsonParseError parserError;
const QJsonDocument doc(QJsonDocument::fromJson(content, &parserError));
if (parserError.error != QJsonParseError::NoError)
{
WARNING_LOG(m_logger) << "Error parsing json document: " << parserError.errorString();
return false;
}
DEBUG_LOG(m_logger) << "json to parse: " << doc.toJson(QJsonDocument::Compact);
const QJsonObject obj(doc.object());
return setFilterFromData(obj);
}
bool AesDisplayFilterImpl::setFilterFromData(const QJsonObject &filterData)
{
if (filterData.isEmpty())
{
resetAesDisplayFilterInternal(true);
return false;
}
const auto oldEffectStateMap(m_effectStateMap);
// GUEZE-3266 Playback Wirksimulationsfilter
// clear after if(content.isEmpty()) or else we are deleting the default filter
// Do not use clear() and remove all entries. Just clear/reset the values:
// // m_effectStateMap.clear();
resetAesDisplayFilterInternal(false);
// 1st: recognize which aesType has changes...
std::vector<AreaEffectSimulation::AesType> aesTypesWithChanges;
aesTypesWithChanges.reserve(aesTypes().size());
for (AreaEffectSimulation::AesType aesType : aesTypes())
if (parseFilterData(filterData, aesType, oldEffectStateMap))
aesTypesWithChanges.emplace_back(aesType);
// 2nd: AFTERWARDS call callbacks:
// Benefit: (GUEZE-3266)
// The callback (especially AesFilterWidget, AesFilterDialog)
// gets updated with a _completed_ m_effectStateMap
for (AreaEffectSimulation::AesType aesType : qAsConst(aesTypesWithChanges))
callFilterChangedCb(aesType);
return true;
}
QJsonObject AesDisplayFilterImpl::filterToJson() const
{
QJsonObject obj;
for (AreaEffectSimulation::AesType aesType : aesTypes())
addFilterData(obj, aesType);
return obj;
}
AesFilter AesDisplayFilterImpl::filterToData() const
{
AesFilter ret(m_ddsFilterContent);
const QJsonDocument doc(filterToJson());
ret.content(doc.toJson(QJsonDocument::Compact).constData());
return ret;
}
// check isCentral:
bool displayCentralPeripheralHelper(const AesDisplayFilter::EffectStateStruct &ess, const bool isCentral)
{
if (isCentral)
return ess.displayCentral;
else
return ess.displayPeripheral;
return true;
}
bool AesDisplayFilterImpl::isVisible(AreaEffectSimulation::AesType aesType,
AreaEffectSimulation::AesEffectState aesState,
int chargeTypeId,
int partyId,
bool isCentral,
qint64 effectStart,
qint64 effectDuration,
qint64 currentTimeMSec) const
{
DEBUG_LOG(m_logger) << "visible check for " << aesType << " - state: " << aesState
<< ", charge: " << chargeTypeId << ", party: " << partyId
<< ", isCentral: " << isCentral
<< ", effectstart: " << effectStart
<< ", duration: " << effectDuration
<< ", now: " << currentTimeMSec
<< ", ==> age: " << currentTimeMSec - effectStart;
// check if party is visible to operator
if ((partyId > -1) && (m_visiblePartiesCheck && !m_visiblePartiesCheck(partyId)))
{
DEBUG_LOG(m_logger) << "Operator is not allowed to see aes for party " << partyId;
return false;
}
if ((partyId > -1) && (m_visiblePartiesCheck && !m_visiblePartiesCheck(partyId)))
{
DEBUG_LOG(m_logger) << "Operator is not allowed to see aes for party " << partyId;
return false;
}
auto it = m_effectStateMap.find(aesType);
// not found -> visible every time
if (it == m_effectStateMap.end())
{
DEBUG_LOG(m_logger) << "No filter entry for " << aesType << " - always visible";
return true;
}
const EffectStateStruct &ess = *it;
// filter auf chargeTypeId und chargeTypeId nicht in container -> nicht sichtbar
if (ess.limitOnChargeTypes && chargeTypeId > 0)
{
DEBUG_LOG(m_logger) << "filtering for chargeType... ";
if (!ess.visibleChargeTypeIds.contains(chargeTypeId))
{
DEBUG_LOG(m_logger) << "... is NOT allowed";
return false;
}
else
DEBUG_LOG(m_logger) << "... is allowed";
}
if (!displayCentralPeripheralHelper(ess, isCentral))
return false;
if (ess.limitOnParties && partyId > 0)
{
DEBUG_LOG(m_logger) << "filtering for partyId... ";
if (!ess.visiblePartyIds.contains(partyId))
{
DEBUG_LOG(m_logger) << "... is NOT allowed";
return false;
}
else
DEBUG_LOG(m_logger) << "... is allowed";
}
DEBUG_LOG(m_logger) << "filtering for state ... ";
switch (aesState.underlying())
{
case AreaEffectSimulation::AesEffectState_def::EsCreated:
case AreaEffectSimulation::AesEffectState_def::EsReceived:
DEBUG_LOG(m_logger) << "... created/received visible: " << ess.displayCreated;
return ess.displayCreated;
case AreaEffectSimulation::AesEffectState_def::EsPrepared:
case AreaEffectSimulation::AesEffectState_def::EsFired:
DEBUG_LOG(m_logger) << "... prepared/fired visible: " << ess.displayPrepared;
return ess.displayPrepared;
case AreaEffectSimulation::AesEffectState_def::EsActivated:
case AreaEffectSimulation::AesEffectState_def::EsPaused:
DEBUG_LOG(m_logger) << "... active/paused visible: " << ess.displayActivated;
return ess.displayActivated;
case AreaEffectSimulation::AesEffectState_def::EsExpired:
{
// afterglow only supported for some types
if (aesType != AreaEffectSimulation::AesType::AtAirSupportImpact &&
aesType != AreaEffectSimulation::AesType::AtExplosionSingle &&
aesType != AreaEffectSimulation::AesType::AtExplosionArea &&
aesType != AreaEffectSimulation::AesType::AtMineCorridor &&
aesType != AreaEffectSimulation::AesType::AtMineAreaSingleMines &&
aesType != AreaEffectSimulation::AesType::AtDusSingleMine &&
aesType != AreaEffectSimulation::AesType::AtGasPipe &&
aesType != AreaEffectSimulation::AesType::AtMineArea
)
return false;
const auto displayEnd = effectStart + effectDuration + ess.expiredAfterglowDurationMSec;
DEBUG_LOG(m_logger) << "... expired visible: " << (currentTimeMSec < displayEnd)
<< ", calc expiry time: " << displayEnd
<< ", return: " << (currentTimeMSec < displayEnd);
return (currentTimeMSec < displayEnd);
}
case AreaEffectSimulation::AesEffectState_def::EsRemoved:
DEBUG_LOG(m_logger) << "... removed - NOT visible";
return false;
case AreaEffectSimulation::AesEffectState_def::EsUnknown:
case AreaEffectSimulation::AesEffectState_def::EsError:
break; // unknown -> display
}
DEBUG_LOG(m_logger) << "... unknown - visible";
return true;
}
bool AesDisplayFilterImpl::showDetails(AreaEffectSimulation::AesType aesType) const
{
auto it = m_effectStateMap.find(aesType);
// not found -> visible every time
if (it == m_effectStateMap.end())
return true;
const EffectStateStruct &ess = *it;
return ess.showDetails;
}
bool AesDisplayFilterImpl::showDetails2(AreaEffectSimulation::AesType aesType) const
{
auto it = m_effectStateMap.find(aesType);
// not found -> visible every time
if (it == m_effectStateMap.end())
return true;
const EffectStateStruct &ess = *it;
return ess.showDetails2;
}
bool AesDisplayFilterImpl::showDetails3(AreaEffectSimulation::AesType aesType) const
{
auto it = m_effectStateMap.find(aesType);
// not found -> visible every time
if (it == m_effectStateMap.end())
return true;
const EffectStateStruct &ess = *it;
return ess.showDetails3;
}
bool AesDisplayFilterImpl::showDetails4(AreaEffectSimulation::AesType aesType) const
{
auto it = m_effectStateMap.find(aesType);
// not found -> visible every time
if (it == m_effectStateMap.end())
return true;
const EffectStateStruct &ess = *it;
return ess.showDetails4;
}
bool AesDisplayFilterImpl::showDetails5(AreaEffectSimulation::AesType aesType) const
{
auto it = m_effectStateMap.find(aesType);
// not found -> visible every time
if (it == m_effectStateMap.end())
return true;
const EffectStateStruct &ess = *it;
return ess.showDetails5;
}
bool AesDisplayFilterImpl::showExplosionClusterMeanHitPoint() const
{
return showDetails2(AreaEffectSimulation::AesType::AtExplosionArea);
}
bool AesDisplayFilterImpl::showExplosionClusterGunToTargetLine() const
{
return showDetails3(AreaEffectSimulation::AesType::AtExplosionArea);
}
bool AesDisplayFilterImpl::showExplosionClusterTrajectory() const
{
return showDetails4(AreaEffectSimulation::AesType::AtExplosionArea);
}
bool AesDisplayFilterImpl::showExplosionClusterDetonationSphere() const
{
return showDetails5(AreaEffectSimulation::AesType::AtExplosionArea);
}
bool AesDisplayFilterImpl::showNotTriggeredCDMine() const
{
return showDetails2(AreaEffectSimulation::AesType::AtMineArea);
}
AesDisplayFilterImpl::EffectStateStruct AesDisplayFilterImpl::effectStateFilter(AreaEffectSimulation::AesType aesType) const
{
// if (m_logger.isDebugEnabled())
if (!m_effectStateMap.contains(aesType.underlying()))
WARNING_LOG(m_logger) << "AesType not found!!! " << aesType;
return m_effectStateMap.value(aesType.underlying());
}
void AesDisplayFilterImpl::setEffectStateFilter(AreaEffectSimulation::AesType aesType, const EffectStateStruct &ess)
{
auto it = m_effectStateMap.find(aesType);
if (it != m_effectStateMap.end())
{
if (*it == ess)
return;
*it = ess;
}
else
m_effectStateMap[aesType] = ess;
callFilterChangedCb(aesType);
}
void AesDisplayFilterImpl::addChangedCallback(FilterChangedCallback *cb)
{
m_filterChangedCb.removeAll(cb); // avoid duplicates
m_filterChangedCb.push_back(cb);
}
void AesDisplayFilterImpl::removeChangedCallback(FilterChangedCallback *cb)
{
m_filterChangedCb.removeAll(cb);
}
static inline QSet<int> fromJsonIntArray(const QJsonValue &obj)
{
QSet<int> ret;
const QJsonArray arrayContent = obj.toArray();
for (const auto &ele : arrayContent)
ret.insert(ele.toInt());
return ret;
}
static inline QJsonArray toJsonIntArray(const QSet<int> &data)
{
QJsonArray ret;
for (int i : data)
ret += i;
return ret;
}
bool AesDisplayFilterImpl::parseFilterData(const QJsonObject &obj,
AreaEffectSimulation::AesType aesType,
const QMap<AreaEffectSimulation::AesType, EffectStateStruct> &orig)
{
const QString strType = QString::number(static_cast<int>(aesType.underlying()));
const QJsonObject inner = obj.value(strType).toObject();
if (inner.isEmpty())
return false;
DEBUG_LOG(m_logger) << "Parsing filter data for " << aesType
<< ", json: " << QJsonDocument(inner).toJson();
EffectStateStruct &ess = m_effectStateMap[aesType];
ess.displayCreated = inner.value(QStringLiteral("created")).toBool(ess.displayCreated);
ess.displayPrepared = inner.value(QStringLiteral("prepared")).toBool(ess.displayPrepared);
ess.displayActivated = inner.value(QStringLiteral("activated")).toBool(ess.displayActivated);
ess.displayCentral = inner.value(QStringLiteral("central")).toBool(ess.displayCentral);
ess.displayPeripheral = inner.value(QStringLiteral("peripheral")).toBool(ess.displayPeripheral);
ess.showDetails2 = inner.value(QStringLiteral("showDetails2")).toBool(ess.showDetails2);
ess.showDetails3 = inner.value(QStringLiteral("showDetails3")).toBool(ess.showDetails3);
ess.showDetails4 = inner.value(QStringLiteral("showDetails4")).toBool(ess.showDetails4);
ess.showDetails5 = inner.value(QStringLiteral("showDetails5")).toBool(ess.showDetails5);
ess.limitOnChargeTypes = inner.value(QStringLiteral("limitOnChargeTypes")).toBool(ess.limitOnChargeTypes);
ess.limitOnParties = inner.value(QStringLiteral("limitOnParties")).toBool(ess.limitOnParties);
ess.showDetails = inner.value(QStringLiteral("showDetails")).toBool(ess.showDetails);
ess.expiredAfterglowDurationMSec = inner.value(QStringLiteral("afterglow")).toInt(ess.expiredAfterglowDurationMSec);
if (ess.expiredAfterglowDurationMSec < 0)
ess.expiredAfterglowDurationMSec = 10 * 1000;
ess.visibleChargeTypeIds = fromJsonIntArray(inner.value(QStringLiteral("chargeTypes")));
ess.visiblePartyIds = fromJsonIntArray(inner.value(QStringLiteral("partyIds")));
return (ess != orig.value(aesType));
// if (ess != orig.value(aesType))
// callFilterChangedCb(aesType);
}
void AesDisplayFilterImpl::addFilterData(QJsonObject &obj, AreaEffectSimulation::AesType aesType) const
{
auto it = m_effectStateMap.find(aesType);
if (it == m_effectStateMap.end())
return;
const EffectStateStruct &ess = *it;
QJsonObject inner;
inner[QStringLiteral("created")] = ess.displayCreated;
inner[QStringLiteral("prepared")] = ess.displayPrepared;
inner[QStringLiteral("activated")] = ess.displayActivated;
inner[QStringLiteral("central")] = ess.displayCentral;
inner[QStringLiteral("peripheral")] = ess.displayPeripheral;
inner[QStringLiteral("showDetails2")] = ess.showDetails2;
inner[QStringLiteral("showDetails3")] = ess.showDetails3;
inner[QStringLiteral("showDetails4")] = ess.showDetails4;
inner[QStringLiteral("showDetails5")] = ess.showDetails5;
inner[QStringLiteral("limitOnChargeTypes")] = ess.limitOnChargeTypes;
inner[QStringLiteral("limitOnParties")] = ess.limitOnParties;
inner[QStringLiteral("showDetails")] = ess.showDetails;
inner[QStringLiteral("afterglow")] = ess.expiredAfterglowDurationMSec;
if (!ess.visibleChargeTypeIds.isEmpty())
inner[QStringLiteral("chargeTypes")] = toJsonIntArray(ess.visibleChargeTypeIds);
if (!ess.visiblePartyIds.isEmpty())
inner[QStringLiteral("partyIds")] = toJsonIntArray(ess.visiblePartyIds);
const QString strType = QString::number(static_cast<int>(aesType.underlying()));
obj[strType] = inner;
}
void AesDisplayFilterImpl::callFilterChangedCb(AreaEffectSimulation::AesType aesType)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << ", call cbs, START, size=" << m_filterChangedCb.size();
for (auto *ptr : qAsConst(m_filterChangedCb)){
ptr->onAesDisplayFilterChanged(aesType);
}
DEBUG_LOG(m_logger) << LOGFUNCTION << ", call cbs, END, size=" << m_filterChangedCb.size();
}
} // namespace FilterManagement
@@ -0,0 +1,95 @@
/**
* @RDE_HEADER@
* Data Plugin for FilterManangement
* $Id$
* $HeadURL$
* $Author$
* Created by Mike Wille, SLSE, 2017-03-31
*/
#pragma once
#include <Plugins/FilterManagement/Gui/Aes/Common/fltaesguicommon_export.h>
#include <FilterManagement/flt_data_plugin_aes_display_filter.h>
#include <FilterManagement/logger.h>
#include <QVector>
namespace FilterManagement
{
//
// AesDisplayFilterImpl
//
class FLTAESGUICOMMON_EXPORT AesDisplayFilterImpl final : public AesDisplayFilter
{
public:
AesDisplayFilterImpl();
~AesDisplayFilterImpl();
virtual void resetAesDisplayFilter() override;
bool setFilterFromData(const AesFilter &filterData) override;
bool setFilterFromData(const QJsonObject &filterData) override;
QJsonObject filterToJson() const override;
AesFilter filterToData() const override;
bool isVisible(AreaEffectSimulation::AesType aesType,
AreaEffectSimulation::AesEffectState aesState,
int chargeTypeId,
int partyId,
bool isCentral,
qint64 effectStart,
qint64 effectDuration,
qint64 currentTimeMSec) const override;
bool showDetails(AreaEffectSimulation::AesType aesType) const override;
EffectStateStruct effectStateFilter(AreaEffectSimulation::AesType aesType) const override;
void setEffectStateFilter(AreaEffectSimulation::AesType aesType,
const EffectStateStruct &ess) override;
int maxAfterglowDurationMSec() const override { return 4 * 60 * 1000; } // 1h -> 4min
void addChangedCallback(FilterChangedCallback *cb) override;
void removeChangedCallback(FilterChangedCallback *cb) override;
void setVisiblePartiesCheck(const std::function<bool(int)> &cb) override
{
m_visiblePartiesCheck = cb;
}
bool hasChangedCallbacks() { return !m_filterChangedCb.empty() ;}
int changedCallbackCount() { return m_filterChangedCb.size() ;}
/*! ExplosionCluster */
//@{
bool showExplosionClusterGunToTargetLine() const override;
bool showExplosionClusterMeanHitPoint() const override;
bool showExplosionClusterTrajectory() const override;
bool showExplosionClusterDetonationSphere() const override;
bool showNotTriggeredCDMine() const override;
protected:
bool showDetails2(AreaEffectSimulation::AesType aesType) const;
bool showDetails3(AreaEffectSimulation::AesType aesType) const;
bool showDetails4(AreaEffectSimulation::AesType aesType) const;
bool showDetails5(AreaEffectSimulation::AesType aesType) const;
//@}
private:
// returns true if filter changed
bool parseFilterData(const QJsonObject &obj,
AreaEffectSimulation::AesType aesType,
const QMap<AreaEffectSimulation::AesType, EffectStateStruct> &orig);
void addFilterData(QJsonObject &obj, AreaEffectSimulation::AesType aesType) const;
void callFilterChangedCb(AreaEffectSimulation::AesType aesType);
void resetAesDisplayFilterInternal(bool executeCallback);
private:
QMap<AreaEffectSimulation::AesType, EffectStateStruct> m_effectStateMap;
QVector<FilterChangedCallback *> m_filterChangedCb;
AesFilter m_ddsFilterContent;
std::function<bool(int)> m_visiblePartiesCheck;
LOGGER_T m_logger;
};
} // namespace FilterManagement
@@ -0,0 +1,203 @@
/**
* @RDE_HEADER@
* Data Plugin for FilterManangement
* $Id$
* $HeadURL$
* $Author$
* Created by Mike Wille, SLSE, 2017-03-31
*/
#include "building_cmpnt_settings_impl.h"
#include "common.h"
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonDocument>
namespace FilterManagement
{
//
// BuildingComponentSettingsImpl
//
BuildingComponentSettingsImpl::BuildingComponentSettingsImpl(const QString &workspaceId)
: BuildingComponentSettings()
, m_workspaceId(workspaceId)
, m_logger(getLogger("BuildingComponentSettingsImpl"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, this=" << this;
resetBuildingComponentSettings();
TRACE_LOG(m_logger) << LOGFUNCTION << " END, this=" << this;
}
BuildingComponentSettingsImpl::~BuildingComponentSettingsImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, this=" << this;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, this=" << this;
}
void BuildingComponentSettingsImpl::resetBuildingComponentSettings()
{
setBldCmpSettings(BldCmpSettings());
}
bool BuildingComponentSettingsImpl::setBldCmpSettingsFromData(const BuildingComponentFilter &filterData)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, this=" << this;
m_ddsFilterContent = filterData;
const QByteArray content(QByteArray::fromRawData(m_ddsFilterContent.content().c_str(), m_ddsFilterContent.content().size()));
if (content.isEmpty())
return true;
QJsonParseError parserError;
const QJsonDocument doc(QJsonDocument::fromJson(content, &parserError));
if (parserError.error != QJsonParseError::NoError)
{
WARNING_LOG(m_logger) << "Error parsing json document: " << parserError.errorString();
return false;
}
DEBUG_LOG(m_logger) << "json to parse: " << doc.toJson();
const QJsonObject obj(doc.object());
if (obj.isEmpty())
return false;
DEBUG_LOG(m_logger) << "json to parse: " << doc.toJson();
BldCmpSettings settings;
if (!settingsFromJsonInternal(doc.object(), settings))
{
ERROR_LOG(m_logger) << "json to parse: " << doc.toJson();
return false;
}
setBldCmpSettings(settings); // will update callbacks
TRACE_LOG(m_logger) << LOGFUNCTION << " END, this=" << this;
return true;
}
QJsonObject BuildingComponentSettingsImpl::bldCmpSettingsToJson() const
{
QJsonObject obj;
const BuildingComponentSettings::BldCmpSettings::BuildingSettings &buildingSettings = m_bldCmpSettings.buildingSettings;
QJsonObject bldg;
bldg[QStringLiteral("hiddenFloorIds")] = toJsonArray(buildingSettings.hiddenFloorIds);
bldg[QStringLiteral("showBuildingOutline")] = buildingSettings.showBuildingOutline;
bldg[QStringLiteral("showBuildingName")] = buildingSettings.showBuildingName;
obj[QStringLiteral("BuildingSettings")] = bldg;
const BuildingComponentSettings::BldCmpSettings::ComponentSettings &componentSettings = m_bldCmpSettings.componentSettings;
QJsonObject comp;
comp[QStringLiteral("showBuildingSensorModule")] = componentSettings.showBuildingSensorModule;
comp[QStringLiteral("showBuildingControlUnit")] = componentSettings.showBuildingControlUnit;
comp[QStringLiteral("showOutdoorCamera")] = componentSettings.showOutdoorCamera;
comp[QStringLiteral("showIndoorCamera")] = componentSettings.showIndoorCamera;
comp[QStringLiteral("showOutdoorIPS")] = componentSettings.showOutdoorIPS;
comp[QStringLiteral("showIndoorIPS")] = componentSettings.showIndoorIPS;
comp[QStringLiteral("showMeteoDataUnit")] = componentSettings.showMeteoDataUnit;
comp[QStringLiteral("showAnnouncementUnit")] = componentSettings.showAnnouncementUnit;
comp[QStringLiteral("showVirtualIPS")] = componentSettings.showVirtualIPS;
comp[QStringLiteral("showEffectGenerationControlUnit")] = componentSettings.showEffectGenerationControlUnit;
comp[QStringLiteral("showOutdoorControlUnit")] = componentSettings.showOutdoorControlUnit;
comp[QStringLiteral("showBuildingNetworkSwitch")] = componentSettings.showBuildingNetworkSwitch;
obj[QStringLiteral("ComponentSettings")] = comp;
return obj;
}
BuildingComponentFilter BuildingComponentSettingsImpl::bldCmpSettingsToData() const
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, this=" << this;
BuildingComponentFilter ret(m_ddsFilterContent);
const QJsonDocument doc(bldCmpSettingsToJson());
ret.content(doc.toJson(QJsonDocument::Compact).constData());
TRACE_LOG(m_logger) << LOGFUNCTION << " END, this=" << this;
return ret;
}
bool BuildingComponentSettingsImpl::settingsFromJsonInternal(const QJsonObject &obj, BuildingComponentSettings::BldCmpSettings &settings)
{
// BuildingSettings
BuildingComponentSettings::BldCmpSettings::BuildingSettings &buildingSettings = settings.buildingSettings;
QJsonObject bldg = obj[QStringLiteral("BuildingSettings")].toObject();
buildingSettings.hiddenFloorIds = fromJsonArray(bldg.value(QStringLiteral("hiddenFloorIds")).toArray());
buildingSettings.showBuildingOutline = bldg[QStringLiteral("showBuildingOutline")].toBool();
buildingSettings.showBuildingName = bldg[QStringLiteral("showBuildingName")].toBool();
// ComponentSettings
BuildingComponentSettings::BldCmpSettings::ComponentSettings &componentSettings = settings.componentSettings;
QJsonObject comp = obj[QStringLiteral("ComponentSettings")].toObject();
componentSettings.showBuildingSensorModule = comp[QStringLiteral("showBuildingSensorModule")].toBool();
componentSettings.showBuildingControlUnit = comp[QStringLiteral("showBuildingControlUnit")].toBool();
componentSettings.showOutdoorCamera = comp[QStringLiteral("showOutdoorCamera")].toBool();
componentSettings.showIndoorCamera = comp[QStringLiteral("showIndoorCamera")].toBool();
componentSettings.showOutdoorIPS = comp[QStringLiteral("showOutdoorIPS")].toBool();
componentSettings.showIndoorIPS = comp[QStringLiteral("showIndoorIPS")].toBool();
componentSettings.showMeteoDataUnit = comp[QStringLiteral("showMeteoDataUnit")].toBool();
componentSettings.showAnnouncementUnit = comp[QStringLiteral("showAnnouncementUnit")].toBool();
componentSettings.showVirtualIPS = comp[QStringLiteral("showVirtualIPS")].toBool();
componentSettings.showEffectGenerationControlUnit = comp[QStringLiteral("showEffectGenerationControlUnit")].toBool();
componentSettings.showOutdoorControlUnit = comp[QStringLiteral("showOutdoorControlUnit")].toBool();
componentSettings.showBuildingNetworkSwitch = comp[QStringLiteral("showBuildingNetworkSwitch")].toBool();
return true;
}
bool BuildingComponentSettingsImpl::setBldCmpSettings(const QJsonObject &obj)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, this=" << this;
BldCmpSettings settings;
if (!settingsFromJsonInternal(obj, settings))
return false;
return setBldCmpSettings(settings);
}
bool BuildingComponentSettingsImpl::setBldCmpSettings(const BuildingComponentSettings::BldCmpSettings &s)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, this=" << this << "; workspace " << m_workspaceId << "'";
if (s == m_bldCmpSettings)
{
DEBUG_LOG(m_logger) << " Settings 's' and m_bldCmpSettings are equal -> return (workspace " << m_workspaceId << ")";
return true;
}
DEBUG_LOG(m_logger) << " Settings 's' and m_bldCmpSettings are different -> update (workspace " << m_workspaceId << ")";
// update data...
m_bldCmpSettings = s; // <<< ------------ !!! JUST HERE!!!
// call callbacks
callSettingsChangedCb();
return true;
}
void BuildingComponentSettingsImpl::addChangedCallback(SettingsChangedCallback *cb)
{
m_settingsChangedCb.removeAll(cb); // avoid duplicates
m_settingsChangedCb.push_back(cb);
}
void BuildingComponentSettingsImpl::removeChangedCallback(SettingsChangedCallback *cb)
{
m_settingsChangedCb.removeAll(cb);
}
bool BuildingComponentSettingsImpl::isChangedCallbackRegistered(BuildingComponentSettings::SettingsChangedCallback *cb) const
{
return m_settingsChangedCb.contains(cb);
}
void BuildingComponentSettingsImpl::callSettingsChangedCb()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, this=" << this << "; workspace " << m_workspaceId << "'"
<< " call cbs now: size=" << m_settingsChangedCb.size();
for (auto *ptr : qAsConst(m_settingsChangedCb))
ptr->onBuildingComponentSettingsChanged();
TRACE_LOG(m_logger) << LOGFUNCTION << " END, this=" << this << "; workspace " << m_workspaceId << "'"
<< " call cbs now: size=" << m_settingsChangedCb.size();
}
} // namespace FilterManagement
@@ -0,0 +1,62 @@
/**
* @RDE_HEADER@
* Data Plugin for FilterManangement
* $Id$
* $HeadURL$
* $Author$
* Created by Mike Wille, SLSE, 2017-03-31
*/
#pragma once
#include <Plugins/FilterManagement/Gui/Aes/Common/fltaesguicommon_export.h>
#include <FilterManagement/flt_building_cmpnt_settings.h>
#include <FilterManagement/logger.h>
#include <QVector>
namespace FilterManagement
{
//
// BuildingComponentSettingsImpl
//
class FLTAESGUICOMMON_EXPORT BuildingComponentSettingsImpl final : public BuildingComponentSettings
{
public:
BuildingComponentSettingsImpl(const QString &workspaceId = QString());
~BuildingComponentSettingsImpl();
virtual void resetBuildingComponentSettings() override;
//DDS == BuildingComponentFilter
bool setBldCmpSettingsFromData(const BuildingComponentFilter &filterData) override;
QJsonObject bldCmpSettingsToJson() const override;
BuildingComponentFilter bldCmpSettingsToData() const override;
static bool settingsFromJsonInternal(const QJsonObject &obj, BldCmpSettings &settings);
// C++struct
bool setBldCmpSettings(const QJsonObject &obj) override;
bool setBldCmpSettings(const BldCmpSettings &s) override; // calls callbacks
const BldCmpSettings &bldCmpSettings() const override { return m_bldCmpSettings; }
void addChangedCallback(SettingsChangedCallback *cb) override;
void removeChangedCallback(SettingsChangedCallback *cb) override;
bool hasChangedCallbacks() { return !m_settingsChangedCb.empty() ;}
int changedCallbackCount() { return m_settingsChangedCb.size() ;}
bool isChangedCallbackRegistered(SettingsChangedCallback *cb) const override;
private:
void callSettingsChangedCb();
private:
BuildingComponentFilter m_ddsFilterContent;
BldCmpSettings m_bldCmpSettings;
QVector<SettingsChangedCallback *> m_settingsChangedCb;
QString m_workspaceId;
LOGGER_T m_logger;
};
} // namespace FilterManagement
+23
View File
@@ -0,0 +1,23 @@
#pragma once
#include <QSet>
#include <QJsonArray>
namespace FilterManagement
{
static inline QSet<int> fromJsonArray(const QJsonArray &arr)
{
QSet<int> ret;
ret.reserve(arr.size());
for (const auto &elem : arr)
ret.insert(elem.toInt());
return ret;
}
static inline QJsonArray toJsonArray(const QSet<int> &ids)
{
QJsonArray arr;
for (int id : ids)
arr.push_back(id);
return arr;
}
}
@@ -0,0 +1,462 @@
/**
* @RDE_HEADER@
* Data Plugin for FilterManangement
* $Id$
* $HeadURL$
* $Author$
* Created by Mike Wille, SLSE, 2017-03-31
*/
#include "symbol_appearance_settings_impl.h"
#include "common.h"
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonDocument>
#include <QTimer>
#include <QMessageBox>
namespace FilterManagement
{
SymbolAppearanceSettingsImpl::SymbolAppearanceSettingsImpl(const std::shared_ptr<ParticipantManagement::Interface::Dtc> &dtcPpm, const QString &workspaceId)
: m_colExpandDirtyTimer(new QTimer(this))
, m_dtcPpm(dtcPpm)
, m_workspaceId(workspaceId)
, m_logger(getLogger("SymbolAppearanceSettings"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, this=" << this;
if (m_dtcPpm)
{
connect(m_dtcPpm.get(), &ParticipantManagement::Interface::Dtc::participantChanged,
this, &SymbolAppearanceSettingsImpl::onParticipantChanged);
m_colExpandDirtyTimer->setSingleShot(true);
m_colExpandDirtyTimer->setInterval(10);
connect(m_colExpandDirtyTimer, &QTimer::timeout,
this, &SymbolAppearanceSettingsImpl::onRebuildCollapsExpandFilter);
m_dtcPpm->participants([this](const ParticipantManagement::Participant &p) {onParticipantChanged(p, DataModification::eAdded);});
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END, this=" << this;
}
SymbolAppearanceSettingsImpl::~SymbolAppearanceSettingsImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, this=" << this;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, this=" << this;
}
void SymbolAppearanceSettingsImpl::resetSymbolAppearanceSettings()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, this=" << this;
setSettings(Settings(), Part::All);
TRACE_LOG(m_logger) << LOGFUNCTION << " END, this=" << this;
}
bool SymbolAppearanceSettingsImpl::setSettingsFromData(const SymbolAppearance &data)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, this=" << this
<< ", m_settingsChangedCb.size()=" << m_settingsChangedCb.size();
DEBUG_LOG(m_logger) << " old symbolTransparency is " << m_settings.symbolSettings.symbolTransparency;
// Maybe data contains values which are equal to "Settings()"
// In that case the following operations lead to setSettings()
// and there the identity will be checked and callCallbacks will be skipped :-(
// To avoid this, set a single value to invalid: symbolTransparency
// Szenario: Create Snap with default filter setting; show snap; modify filter settings (like transparency); show snap again
m_ddsSettings = data;
m_settings = Settings();
// // m_settings.symbolSettings.symbolTransparency = -1.23; // invalid value (avoid "QColor::setAlpha": invalid value 568)
m_filteredParticipantsColExp.clear(); // NLDEVCTRL-805; m_filteredParticipantsColExp depends on m_settings -> clear also
const QByteArray content(QByteArray::fromRawData(m_ddsSettings.content().c_str(), m_ddsSettings.content().size()));
if (content.isEmpty())
return true;
QJsonParseError parserError;
const QJsonDocument doc(QJsonDocument::fromJson(content, &parserError));
if (parserError.error != QJsonParseError::NoError)
{
WARNING_LOG(m_logger) << "Error parsing json document: " << parserError.errorString();
return false;
}
DEBUG_LOG(m_logger) << "json to parse: " << doc.toJson();
Settings settings;
if (!settingsFromJsonInternal(doc.object(), settings))
return false;
m_settings.symbolSettings.symbolTransparency = -1.23; // invalid value (avoid "QColor::setAlpha": invalid value 568)
setSettings(settings, Part::All);
TRACE_LOG(m_logger) << LOGFUNCTION << " END, this=" << this;
return true;
}
bool SymbolAppearanceSettingsImpl::settingsFromJsonInternal(const QJsonObject &obj, Settings &settings) const
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, this=" << this;
auto &sym = settings.symbolSettings;
// Part::Symbol
QJsonObject symApp = obj[QStringLiteral("SymbolAppearances")].toObject();
sym.symbolScale = symApp[QStringLiteral("scale")].toDouble(sym.symbolScale);
DEBUG_LOG(m_logger) << "set symbolScale to " << sym.symbolScale << " for workspace " << m_workspaceId;
sym.symbolTransparency = symApp[QStringLiteral("transparency")].toDouble(sym.symbolTransparency);
DEBUG_LOG(m_logger) << "set symbolTransparency to " << sym.symbolTransparency << " for workspace " << m_workspaceId;
sym.symbolFireEventFlashingMSec = symApp[QStringLiteral("fireEventFlashing")].toDouble(sym.symbolFireEventFlashingMSec);
sym.hitLineDisplayLengthMSec = symApp[QStringLiteral("hitLineDisplayLength")].toDouble(sym.hitLineDisplayLengthMSec);
sym.lrfLineDisplayLengthMSec = symApp[QStringLiteral("lrfLineDisplayLength")].toDouble(sym.lrfLineDisplayLengthMSec);
sym.ltdLineDisplayLengthMSec = symApp[QStringLiteral("ltdLineDisplayLength")].toDouble(sym.ltdLineDisplayLengthMSec);
sym.movementTrackLengthMSec = symApp[QStringLiteral("movementTrackLengthMSec")].toInt(sym.movementTrackLengthMSec);
sym.showBuildingOutline = symApp[QStringLiteral("showBuildingOutline")].toBool(sym.showBuildingOutline);
sym.showBuildingIdentifier = symApp[QStringLiteral("showBuildingIdentifier")].toBool(sym.showBuildingIdentifier);
sym.showTrainingAreaBorder = symApp[QStringLiteral("showTrainingAreaBorder")].toBool(sym.showTrainingAreaBorder);
sym.showSpecialAreas = symApp[QStringLiteral("showSpecialAreas")].toBool(sym.showSpecialAreas);
sym.showFiringUnits = symApp[QStringLiteral("showFiringUnits")].toBool(sym.showFiringUnits);
sym.nasatNineLinerDisplayLengthMSec = symApp[QStringLiteral("nasatNineLinerDisplayLength")].toInt(sym.nasatNineLinerDisplayLengthMSec);
sym.bitErrorVisibility = readSymbolVisibility(symApp, QStringLiteral("bitErrorVisibility"), sym.bitErrorVisibility);
sym.manipulationVisibility = readSymbolVisibility(symApp, QStringLiteral("manipulationVisibility"), sym.manipulationVisibility);
sym.positionOutOfDateVisibility = readSymbolVisibility(symApp, QStringLiteral("positionOutOfDateVisibility"), sym.positionOutOfDateVisibility);
sym.simulatedPositionVisibility = readSymbolVisibility(symApp, QStringLiteral("simulatedPositionVisibility"), sym.simulatedPositionVisibility);
sym.unitSymbolPosition = readUnitSymbolPosition(symApp, QStringLiteral("unitSymbolPosition"), sym.unitSymbolPosition);
const QJsonArray arr(obj.value(QStringLiteral("SymbolTeamAppearances")).toArray());
for (const auto &ele : arr)
parseSymbolTeamAppearance(settings, ele.toObject());
// Part::Types
settings.hiddenTypeFilter.clear();
const auto hiddenTypeFilter(obj.value(QStringLiteral("hiddenTypeFilter")).toArray());
for(const QJsonValue &party : hiddenTypeFilter)
{
const QJsonObject obj(party.toObject());
settings.hiddenTypeFilter.insert(obj.value(QStringLiteral("partyId")).toInt(),
fromJsonArray(obj.value(QStringLiteral("filter")).toArray()));
}
settings.hiddenStateFilter.clear();
const auto hiddenStateFilter(obj.value(QStringLiteral("hiddenStateFilter")).toArray());
for(const QJsonValue &party : hiddenStateFilter)
{
const QJsonObject obj(party.toObject());
settings.hiddenStateFilter.insert(obj.value(QStringLiteral("partyId")).toInt(),
fromJsonArray(obj.value(QStringLiteral("stateId")).toArray()));
}
// Part::CollapseExpand
settings.colExpand.collapsedParticipantIds = fromJsonArray(obj.value(QStringLiteral("colExpCollapsed")).toArray());
settings.colExpand.hiddenParticipantIds = fromJsonArray(obj.value(QStringLiteral("colExpHidden")).toArray());
settings.bIsValid = true;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, this=" << this;
return true;
}
QJsonObject SymbolAppearanceSettingsImpl::settingsToJson() const
{
QJsonObject obj;
const auto &sym = m_settings.symbolSettings;
QJsonObject symApp;
symApp[QStringLiteral("scale")] = sym.symbolScale;
symApp[QStringLiteral("transparency")] = sym.symbolTransparency;
symApp[QStringLiteral("fireEventFlashing")] = sym.symbolFireEventFlashingMSec;
symApp[QStringLiteral("hitLineDisplayLength")] = sym.hitLineDisplayLengthMSec;
symApp[QStringLiteral("lrfLineDisplayLength")] = sym.lrfLineDisplayLengthMSec;
symApp[QStringLiteral("ltdLineDisplayLength")] = sym.ltdLineDisplayLengthMSec;
symApp[QStringLiteral("movementTrackLengthMSec")] = sym.movementTrackLengthMSec;
symApp[QStringLiteral("showBuildingOutline")] = sym.showBuildingOutline;
symApp[QStringLiteral("showBuildingIdentifier")] = sym.showBuildingIdentifier;
symApp[QStringLiteral("showTrainingAreaBorder")] = sym.showTrainingAreaBorder;
symApp[QStringLiteral("showSpecialAreas")] = sym.showSpecialAreas;
symApp[QStringLiteral("showFiringUnits")] = sym.showFiringUnits;
symApp[QStringLiteral("nasatNineLinerDisplayLength")] = sym.nasatNineLinerDisplayLengthMSec;
symApp[QStringLiteral("bitErrorVisibility")] = static_cast<int>(sym.bitErrorVisibility);
symApp[QStringLiteral("manipulationVisibility")] = static_cast<int>(sym.manipulationVisibility);
symApp[QStringLiteral("positionOutOfDateVisibility")] = static_cast<int>(sym.positionOutOfDateVisibility);
symApp[QStringLiteral("simulatedPositionVisibility")] = static_cast<int>(sym.simulatedPositionVisibility);
symApp[QStringLiteral("unitSymbolPosition")] = static_cast<int>(sym.unitSymbolPosition);
obj[QStringLiteral("SymbolAppearances")] = symApp;
QJsonArray arr;
for (auto it = sym.symbolPartyAppearance.begin(); it != sym.symbolPartyAppearance.end(); ++it)
{
QJsonObject inner;
const SymbolPartyAppearance &sta = it.value();
inner[QStringLiteral("id")] = it.key();
inner[QStringLiteral("isVisible")] = sta.isVisible;
inner[QStringLiteral("showDesignator")] = sta.showDesignator;
inner[QStringLiteral("showTacticalIdentifier")] = sta.showTacticalIdentifier;
arr += inner;
}
obj[QStringLiteral("SymbolTeamAppearances")] = arr;
QJsonArray typeArr;
for (auto it = m_settings.hiddenTypeFilter.constBegin(); it != m_settings.hiddenTypeFilter.constEnd(); ++it)
{
QJsonObject inner;
inner[QStringLiteral("partyId")] = it.key();
inner[QStringLiteral("filter")] = toJsonArray(it.value());
typeArr += inner;
}
obj[QStringLiteral("hiddenTypeFilter")] = typeArr;
QJsonArray stateArr;
for (auto it = m_settings.hiddenStateFilter.begin(); it != m_settings.hiddenStateFilter.end(); ++it)
{
QJsonObject inner;
inner[QStringLiteral("partyId")] = it.key();
inner[QStringLiteral("stateId")] = toJsonArray(it.value());
stateArr += inner;
}
obj[QStringLiteral("hiddenStateFilter")] = stateArr;
obj[QStringLiteral("colExpCollapsed")] = toJsonArray(m_settings.colExpand.collapsedParticipantIds);
obj[QStringLiteral("colExpHidden")] = toJsonArray(m_settings.colExpand.hiddenParticipantIds);
return obj;
}
SymbolAppearance SymbolAppearanceSettingsImpl::settingsToData() const
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, this=" << this;
SymbolAppearance ret(m_ddsSettings);
const QJsonDocument doc(settingsToJson());
ret.content(doc.toJson(QJsonDocument::Compact).constData());
TRACE_LOG(m_logger) << LOGFUNCTION << " END, this=" << this;
return ret;
}
bool SymbolAppearanceSettingsImpl::setSettings(const QJsonObject &obj, Part part)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, this=" << this;
Settings settings;
if (!settingsFromJsonInternal(obj, settings))
return false;
return setSettings(settings, part);
}
bool SymbolAppearanceSettingsImpl::setSettings(const Settings &s, Part part)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, this=" << this << ", part=" << (int)part;
bool bNeedRebuildCollapsExpandFilter = false;
switch (part)
{
case Part::All:
if (s == m_settings)
{
DEBUG_LOG(m_logger) << " Settings 's' and m_settings are equal -> return (workspace " << m_workspaceId << ")";
return true;
}
bNeedRebuildCollapsExpandFilter = s.colExpand != m_settings.colExpand;
m_settings = s;
INFO_LOG(m_logger) << "set symbol scale (?) of " << s.symbolSettings.symbolScale << " in workspace " << m_workspaceId;
break;
case Part::Symbol:
if (s.symbolSettings == m_settings.symbolSettings)
return true;
m_settings.symbolSettings = s.symbolSettings;
INFO_LOG(m_logger) << "set symbol scale of " << s.symbolSettings.symbolScale << " in workspace " << m_workspaceId;
break;
case Part::Types:
if (s.hiddenTypeFilter == m_settings.hiddenTypeFilter &&
s.hiddenStateFilter == m_settings.hiddenStateFilter)
return true;
m_settings.hiddenTypeFilter = s.hiddenTypeFilter;
m_settings.hiddenStateFilter = s.hiddenStateFilter;
break;
case Part::CollapseExpand:
if (s.colExpand == m_settings.colExpand)
return true;
bNeedRebuildCollapsExpandFilter = true;
m_settings.colExpand = s.colExpand;
break;
}
if (bNeedRebuildCollapsExpandFilter)
onRebuildCollapsExpandFilter();
callSettingsChangedCb(part);
return true;
}
bool SymbolAppearanceSettingsImpl::isParticipantVisibileCollapseExpand(int participantId) const
{
return m_filteredParticipantsColExp.contains(participantId);
}
void SymbolAppearanceSettingsImpl::addChangedCallback(SettingsChangedCallback *cb)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << ", add cb=" << cb;
m_settingsChangedCb.removeAll(cb); // avoid duplicates
m_settingsChangedCb.push_back(cb);
DEBUG_LOG(m_logger) << LOGFUNCTION << ", add cb=" << cb << " done";
}
void SymbolAppearanceSettingsImpl::removeChangedCallback(SettingsChangedCallback *cb)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << ", remove cb=" << cb << " current size=" << m_settingsChangedCb.size();
m_settingsChangedCb.removeAll(cb);
DEBUG_LOG(m_logger) << LOGFUNCTION << ", remove cb=" << cb << " done, current size=" << m_settingsChangedCb.size();
}
bool SymbolAppearanceSettingsImpl::isChangedCallbackRegistered(SymbolAppearanceSettings::SettingsChangedCallback *cb) const
{
return m_settingsChangedCb.contains(cb);
}
void SymbolAppearanceSettingsImpl::callSettingsChangedCb(Part part)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << ", call cbs, START , part=" << (int)part << ", size=" << m_settingsChangedCb.size();
for (auto *ptr : qAsConst(m_settingsChangedCb))
ptr->onSymbolAppearanceSettingsChanged(part);
DEBUG_LOG(m_logger) << LOGFUNCTION << ", call cbs, END , part=" << (int)part << ", size=" << m_settingsChangedCb.size();
}
SymbolAppearanceSettingsImpl::SymbolVisibility SymbolAppearanceSettingsImpl::readSymbolVisibility(const QJsonObject &obj,
const QString &val,
SymbolVisibility def)
{
if (!obj.contains(val))
return def;
int r = obj[val].toInt();
if (r < static_cast<int>(SymbolVisibility::Standard) ||
r > static_cast<int>(SymbolVisibility::AdditionalSymbol))
return def;
return static_cast<SymbolVisibility>(r);
}
SymbolAppearanceSettingsImpl::UnitSymbolPosition SymbolAppearanceSettingsImpl::readUnitSymbolPosition(const QJsonObject &obj,
const QString &val,
UnitSymbolPosition def)
{
if (!obj.contains(val))
return def;
int r = obj[val].toInt();
if (r < static_cast<int>(UnitSymbolPosition::Center) ||
r > static_cast<int>(UnitSymbolPosition::Leader))
return def;
return static_cast<UnitSymbolPosition>(r);
}
void SymbolAppearanceSettingsImpl::parseSymbolTeamAppearance(Settings &settings, const QJsonObject &obj)
{
int id = obj.value(QStringLiteral("id")).toInt();
SymbolPartyAppearance sta;
sta.isVisible = obj.value(QStringLiteral("isVisible")).toBool(sta.isVisible);
sta.showDesignator = obj.value(QStringLiteral("showDesignator")).toBool(sta.showDesignator);
sta.showTacticalIdentifier = obj.value(QStringLiteral("showTacticalIdentifier")).toBool(sta.showTacticalIdentifier);
settings.symbolSettings.symbolPartyAppearance.insert(id, sta);
}
void SymbolAppearanceSettingsImpl::onParticipantChanged(const ParticipantManagement::Participant &data, DataModification mod)
{
switch (mod)
{
case DataModification::eAdded:
case DataModification::eModified:
{
auto it = m_participantId2SuperiorId.find(data.id());
if (it != m_participantId2SuperiorId.end())
{
if (it.value() != data.superiorId())
{
it.value() = data.superiorId();
m_colExpandDirtyTimer->start();
}
}
else
{
m_participantId2SuperiorId[data.id()] = data.superiorId();
// Starte SituationReplay (leere Map, NOCH kein Orbat in der ReplayPartition)
// Doppelklick auf eine Marke (in der eingeklappten Tlns hinterlegt sind)
// -> Filter (SymbolAppearanceSettingsImpl) wird geladen
// Orbat ist allerdings noch leer!!!
// (KEIN onParticipantChanged -> m_participantId2SuperiorId ist leer)
// Race Condition: wird erst hier 'onParticipantChanged' aufgerufen
// ODER im participant2Map???
// Daher nutzen wird den dirtyTimer auch hier.
// Sollte also dieses onParticipantChanged zuletzt aufgerufen werden,
// werden die Callbacks via 'onRebuildCollapsExpandFilter' aufgerufen :-)
m_colExpandDirtyTimer->start();
}
break;
}
case DataModification::eRemoved:
{
auto it = m_participantId2SuperiorId.constFind(data.id());
if (it != m_participantId2SuperiorId.constEnd())
{
m_participantId2SuperiorId.erase(it);
//m_colExpandDirtyTimer->start(); // really needed?
}
break;
}
}
}
void SymbolAppearanceSettingsImpl::onRebuildCollapsExpandFilter()
{
DEBUG_LOG(m_logger) << "Rebuilding CollapseExpand filter, participant2Superior size: " << m_participantId2SuperiorId.size();
QSet<int> filteredParticipantsColExp = m_settings.colExpand.hiddenParticipantIds;
for (auto it = m_participantId2SuperiorId.begin(); it != m_participantId2SuperiorId.end(); ++it)
{
const int participantId = it.key();
if (filteredParticipantsColExp.contains(participantId))
continue;
const int superiorId = it.value();
QSet<int> visitedIds;
if (isInCollapsedTree(superiorId, visitedIds))
filteredParticipantsColExp += participantId;
}
if (m_logger.isDebugEnabled())
{
QStringList sl;
sl.reserve(20);
for(int i : qAsConst(m_settings.colExpand.hiddenParticipantIds))
sl += QString::number(i);
DEBUG_LOG(m_logger) << "Hidden participant ids: " << sl.join(QLatin1Char(' '));
sl.clear();
for(int i : qAsConst(m_settings.colExpand.collapsedParticipantIds))
sl += QString::number(i);
DEBUG_LOG(m_logger) << "Collapsed participant ids: " << sl.join(QLatin1Char(' '));
sl.clear();
for(int i : qAsConst(filteredParticipantsColExp))
sl += QString::number(i);
DEBUG_LOG(m_logger) << "Result: " << sl.join(QLatin1Char(' '));
}
if (m_filteredParticipantsColExp == filteredParticipantsColExp)
return;
m_filteredParticipantsColExp = filteredParticipantsColExp;
callSettingsChangedCb(Part::Types);
}
bool SymbolAppearanceSettingsImpl::isInCollapsedTree(int participantId, QSet<int> &visitedIds) const
{
if (participantId == 0)
return false;
if (m_settings.colExpand.collapsedParticipantIds.contains(participantId))
return true;
const int superiorId = m_participantId2SuperiorId.value(participantId);
if (visitedIds.contains(superiorId))
{
WARNING_LOG(m_logger) << "Recursion detected - participant with id " << participantId << ", superiorId: " << superiorId;
return false;
}
visitedIds.insert(superiorId);
return isInCollapsedTree(superiorId, visitedIds);
}
} // namespace FilterManagement
@@ -0,0 +1,82 @@
/**
* @RDE_HEADER@
* Data Plugin for FilterManangement
* $Id$
* $HeadURL$
* $Author$
* Created by Mike Wille, SLSE, 2017-03-31
*/
#pragma once
#include <Plugins/FilterManagement/Gui/Aes/Common/fltaesguicommon_export.h>
#include <FilterManagement/flt_symbol_appearance_settings.h>
#include <ParticipantManagement/ppm_dtc.h>
#include <FilterManagement/logger.h>
#include <QObject>
#include <QVector>
#include <QHash>
class QTimer;
namespace FilterManagement
{
//
// SymbolAppearanceSettingsImpl
//
class FLTAESGUICOMMON_EXPORT SymbolAppearanceSettingsImpl final : public QObject, public SymbolAppearanceSettings
{
Q_OBJECT
public:
explicit SymbolAppearanceSettingsImpl(const std::shared_ptr<ParticipantManagement::Interface::Dtc> &dtcPpm, const QString &workspaceId = QString());
~SymbolAppearanceSettingsImpl();
void resetSymbolAppearanceSettings() override;
bool setSettingsFromData(const SymbolAppearance &data) override;
QJsonObject settingsToJson() const override;
SymbolAppearance settingsToData() const override;
bool settingsFromJsonInternal(const QJsonObject &obj, Settings &settings) const;
bool setSettings(const QJsonObject &obj, Part part) override;
bool setSettings(const Settings &s, Part part) override;
const Settings &settings() const override { return m_settings; }
bool isParticipantVisibileCollapseExpand(int participantId) const override;
void addChangedCallback(SettingsChangedCallback *cb) override;
void removeChangedCallback(SettingsChangedCallback *cb) override;
bool isChangedCallbackRegistered(SettingsChangedCallback *cb) const override;
bool hasChangedCallbacks() { return !m_settingsChangedCb.empty() ;}
int changedCallbackCount() { return m_settingsChangedCb.size() ;}
private:
void callSettingsChangedCb(Part part);
static SymbolVisibility readSymbolVisibility(const QJsonObject &obj,
const QString &val,
SymbolVisibility def);
static UnitSymbolPosition readUnitSymbolPosition(const QJsonObject &obj,
const QString &val,
UnitSymbolPosition def);
static void parseSymbolTeamAppearance(Settings &settings, const QJsonObject &obj);
private Q_SLOTS:
void onParticipantChanged(const ParticipantManagement::Participant &data, DataModification mod);
void onRebuildCollapsExpandFilter();
private:
bool isInCollapsedTree(int participantId, QSet<int> &visitedIds) const;
private:
QVector<SettingsChangedCallback *> m_settingsChangedCb;
// <participantId, superiorParticipantId>
QHash<int, int> m_participantId2SuperiorId;
QTimer *m_colExpandDirtyTimer;
Settings m_settings;
SymbolAppearance m_ddsSettings;
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_dtcPpm;
QSet<int> m_filteredParticipantsColExp;
QString m_workspaceId;
LOGGER_T m_logger;
};
} // namespace FilterManagement
@@ -0,0 +1,153 @@
/**
* @RDE_HEADER@
* FilterManagement - Aes Filter Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#include "flt_aes_filter_dialog.h"
#include <LtsSession/lts_session_data.h>
#include <LtsWidgets/lts_message_dialog.h>
#include <FilterManagement/flt_symbol_appearance_settings.h>
#include <PluginInterfaces/gui_plugin_interface.h>
#include <FilterManagement/Gui/FilterChange/flt_filter_change.h>
#include <QGridLayout>
#include <QTimer>
namespace FilterManagement
{
//
// AesFilterDialog
//
AesFilterDialog::AesFilterDialog(QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
, m_widget(new AesFilterWidget(this))
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_session(nullptr)
, m_unknowChangesNotifiyTimer(new QTimer(this))
, m_logger(getLogger("AesFilterDialog"))
{
connect(m_widget, &AesFilterWidget::changesMade, this, &AesFilterDialog::slotChangesMade);
QGridLayout *gl = new QGridLayout(this);
gl->setMargin(0);
gl->addWidget(m_widget, 0, 0);
setOnlineHelpFilename(QStringLiteral("Situation-Situation_Filter"));
// prepare notifiyTimer: (GUEZE-3266)
m_unknowChangesNotifiyTimer->setInterval(50);
m_unknowChangesNotifiyTimer->setSingleShot(true);
connect(m_unknowChangesNotifiyTimer, &QTimer::timeout,
this, &AesFilterDialog::onProcessUnknownChanges);
}
AesFilterDialog::~AesFilterDialog()
{}
bool AesFilterDialog::init(LtsSession::LtsSession *session)
{
m_session = session;
if (!session->getForeignGuiInterface(m_fltIfc))
{
WARNING_LOG(m_logger) << "Can not get Foreign data interface for FilterManagement";
return false;
}
if (!session->getFtc<FilterManagement::DataInterface>(m_fltFtc))
{
WARNING_LOG(m_logger) << "Can not get Foreign data interface for FilterManagement";
return false;
}
std::shared_ptr<ParticipantManagement::ForeignGuiComboboxInterface> ifcPpmCbx;
std::shared_ptr<ProjectDataManagement::ForeignGuiInterface> ifcPdmCbx;
std::shared_ptr<AesDisplayFilter> filter;
if (!session->getForeignGuiInterface(ifcPpmCbx))
return false;
if (!session->getForeignGuiInterface(ifcPdmCbx))
return false;
filter = m_fltIfc->aesFilterForOperator(LtsSessionData::LtsSessionData::getInstance()->getOperatorId(), m_session->workspaceId());
bool success = m_widget->init(ifcPpmCbx, ifcPdmCbx, filter, m_session->app() == LtsAppDescriptor::App::OC);
// In case of LoadingFilter or user selects another replay (and therefore other filter):
connect(m_widget, &AesFilterWidget::unknownChangesRecognized, this, &AesFilterDialog::onUnknownChangesRecognized, Qt::UniqueConnection);
if (FilterChangeDialog::isAvailableAtApp(m_session->app()))
{
m_buttonBox->getButton(LtsWidgets::DialogButton::Load)->setText(tr("Load filter"));
m_buttonBox->connectButton(LtsWidgets::DialogButton::Load,
this, &AesFilterDialog::onLoadButtonClicked);
}
return success;
}
void AesFilterDialog::retranslate()
{
// lupdate doesn't like translate(tr("foo")) ...
const QString txt(tr("Filter Area Effect Simulation"));
translate(txt);
m_widget->retranslate();
m_uiRequirements->retranslate();
}
bool AesFilterDialog::apply()
{
m_widget->apply();
return m_requestHelper->startSingleRequest([this]()
{
const AesFilter &filterData = m_widget->filter()->filterToData();
return m_fltFtc->aesFilterUpdateRequest(filterData, this);
});
}
void AesFilterDialog::dialogCanceled()
{
m_widget->dialogCanceled();
}
void AesFilterDialog::onAesFilterUpdateReply(const Core::FunctionReplyObject &replyObject)
{
m_requestHelper->requestReply(replyObject);
}
void AesFilterDialog::onUnknownChangesRecognized()
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " START";
m_unknowChangesNotifiyTimer->start();
DEBUG_LOG(m_logger) << LOGFUNCTION << " END";
}
void AesFilterDialog::onProcessUnknownChanges()
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " START";
m_widget->updateGuiToFilter();
// the data can be changed if another replay is selected or filter are loaded.
// So our widget has to be updated:
__unchange__();
DEBUG_LOG(m_logger) << LOGFUNCTION << " END";
}
void AesFilterDialog::onLoadButtonClicked()
{
FilterChangeDialog *dialog = new FilterChangeDialog(this);
if (!dialog->init(m_session, SymbolAppearanceSettings::Part::All, true, false, false))
{
delete dialog;
return;
}
dialog->setAttribute(Qt::WA_DeleteOnClose);
QObject::connect(dialog, &FilterChangeDialog::rejected, dialog, &FilterChangeDialog::deleteLater);
dialog->show();
}
} // namespace FilterManagement
@@ -0,0 +1,59 @@
/**
* @RDE_HEADER@
* FilterManagement - Aes Filter Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#pragma once
#include "flt_aes_filter_widget.h"
#include <LtsWidgets/lts_dialog.h>
#include <LtsUtilsGuiDds/request_helper.h>
#include <FilterManagement/logger.h>
#include <LtsSession/lts_session.h>
#include <Plugins/FilterManagement/flt_data_plugin_interface.h>
#include <Plugins/FilterManagement/flt_aes_plugin_interface.h>
namespace FilterManagement
{
class DataInterface;
// --------------------------------------------------------
// AesFilterDialog
// --------------------------------------------------------
class AesFilterDialog final : public LtsWidgets::LtsDialog
, private FilterManagement::Interface::Ftc::AesFilterUpdateReplyHandler
{
Q_OBJECT
public:
explicit AesFilterDialog(QWidget *parent = nullptr);
~AesFilterDialog();
bool init(LtsSession::LtsSession *session);
void retranslate() override;
private:
bool apply() override;
void dialogCanceled() override;
private Q_SLOTS:
void onAesFilterUpdateReply(const Core::FunctionReplyObject &replyObject) override;
void onUnknownChangesRecognized();
void onProcessUnknownChanges();
void onLoadButtonClicked();
private:
AesFilterWidget *m_widget{nullptr};
LtsUtils::RequestHelper *m_requestHelper{nullptr};
LtsSession::LtsSession *m_session{nullptr};
QTimer *m_unknowChangesNotifiyTimer{nullptr};
std::shared_ptr<FilterManagement::ForeignAesGuiInterface> m_fltIfc;
std::shared_ptr<FilterManagement::Interface::Ftc> m_fltFtc;
NGL::INGLLogger &m_logger;
};
}
@@ -0,0 +1,704 @@
/**
* @RDE_HEADER@
* FilterManagement - Aes Filter Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#include "flt_aes_filter_widget.h"
#include "ui_flt_aes_filter_widget.h"
#include <FilterManagement/logger.h>
#include <LtsUtilsSettings/settings.h>
#include <LtsSession/lts_session_data.h>
namespace FilterManagement
{
static inline void setFixedWidthForWidgetHelper(QWidget *w)
{
int width = w->sizeHint().width();
w->setMinimumWidth(width);
w->setMaximumWidth(width);
}
static inline void setConditional(QCheckBox *chb, bool bChecked)
{
if (chb->isEnabled())
chb->setChecked(bChecked);
else
chb->setChecked(false);
}
class UpdateGuard
{
public:
explicit UpdateGuard(AesFilterWidget *w)
: m_w(w)
{
if (m_w)
m_w->m_doUpdateViaCallback = false;
}
~UpdateGuard()
{
if (m_w)
m_w->m_doUpdateViaCallback = true;
}
private:
AesFilterWidget *m_w;
};
AesFilterWidget::AesFilterWidget(QWidget *parent)
: QWidget(parent)
, m_doUpdateViaCallback(true)
, m_ui(new Ui::AesFilterWidget)
, m_logger(getLogger("AesFilterDialog"))
{
LtsUtils::ProjectSettings *ps = LtsUtils::ProjectSettings::getInstance();
const bool enableGasPipes = ps->value(QStringLiteral("aes"),
QStringLiteral("enableGasPipes")).toBool();
const bool enableAirSupport = ps->value(QStringLiteral("aes"),
QStringLiteral("enableAirSupport")).toBool();
const bool enableTechnicalAreas = ps->value(QStringLiteral("aes"),
QStringLiteral("enableTechnicalAreas")).toBool();
const bool enableDusSingleMine = ps->value(QStringLiteral("aes"),
QStringLiteral("enableDusSingleMine")).toBool();
const bool enableSingleExplosionArtillery = ps->value(QStringLiteral("aes"),
QStringLiteral("enableSingleExplosionArtillery")).toBool();
m_ui->setupUi(this);
if (!enableSingleExplosionArtillery)
{
m_ui->chbCreatedExplosionSingle->hide();
m_ui->chbPreparedExplosionSingle->hide();
m_ui->chbActiveExplosionSingle->hide();
m_ui->sldAfterglowSingleFire->hide();
m_ui->lbSingleFire->hide();
m_ui->lbAfterGlowSingleFire->hide();
m_ui->lblAfterglowSingleFire->hide();
}
if (!enableGasPipes)
{
m_ui->lb_GasPipes->hide();
m_ui->chbCreatedGasPipes->hide();
m_ui->chbActiveGasPipes->hide();
m_ui->chbPreparedGasPipes->hide();
m_ui->label_GasPipes->hide();
m_ui->sldAfterglowGasPipes->hide();
m_ui->lblAfterglowGasPipes->hide();
}
if (!enableAirSupport)
{
m_ui->lb_AirSupport->hide();
m_ui->chbCreatedAirSupport->hide();
m_ui->chbPreparedAirSupport->hide();
m_ui->chbActiveAirSupport->hide();
m_ui->sldAfterglowAirSupport->hide();
m_ui->lblAfterglowAirSupport->hide();
}
if (!enableTechnicalAreas)
{
m_ui->lb_TechnicalAreas->hide();
m_ui->chbCreatedTechnicalArea->hide();
m_ui->chbPreparedTechnicalArea->hide();
m_ui->chbActiveTechnicalArea->hide();
}
m_checkBoxes =
{
{AreaEffectSimulation::AesType::AtBCContamination, Checkboxes(m_ui->chbCreatedBCContamination, m_ui->chbPreparedBCContamination, m_ui->chbActiveBCContamination)},
{AreaEffectSimulation::AesType::AtNContamination, Checkboxes(m_ui->chbCreatedNContamination, m_ui->chbPreparedNContamination, m_ui->chbActiveNContamination)},
{AreaEffectSimulation::AesType::AtDangerArea, Checkboxes(m_ui->chbCreatedDangerArea, m_ui->chbPreparedDangerArea, m_ui->chbActiveDangerArea)},
{AreaEffectSimulation::AesType::AtMineArea, Checkboxes(m_ui->chbCreatedMineArea, m_ui->chbPreparedMineArea, m_ui->chbActiveMineArea)},
{AreaEffectSimulation::AesType::AtMineCorridor, Checkboxes(m_ui->chbCreatedMineCorridor, m_ui->chbPreparedMineCorridor, m_ui->chbActiveMineCorridor)},
{AreaEffectSimulation::AesType::AtExplosionSingle, Checkboxes(m_ui->chbCreatedExplosionSingle, m_ui->chbPreparedExplosionSingle, m_ui->chbActiveExplosionSingle)},
{AreaEffectSimulation::AesType::AtExplosionArea, Checkboxes(m_ui->chbCreatedExplosionArea, m_ui->chbPreparedExplosionArea, m_ui->chbActiveExplosionArea)},
{AreaEffectSimulation::AesType::AtFunctionalArea, Checkboxes(m_ui->chbCreatedFunctionalArea, m_ui->chbPreparedFunctionalArea, m_ui->chbActiveFunctionalArea)},
{AreaEffectSimulation::AesType::AtBorderline, Checkboxes(m_ui->chbCreatedBorderline, m_ui->chbPreparedBorderline, m_ui->chbActiveBorderline)},
{AreaEffectSimulation::AesType::AtMineAreaSingleMines, Checkboxes(m_ui->chbCreatedIed, m_ui->chbPreparedIed, m_ui->chbActiveIed)},
{AreaEffectSimulation::AesType::AtDusSingleMine, Checkboxes(m_ui->chbCreatedDusSingleMine, m_ui->chbPreparedDusSingleMine, m_ui->chbActiveDusSingleMine)},
{AreaEffectSimulation::AesType::AtGasPipe, Checkboxes(m_ui->chbCreatedGasPipes, m_ui->chbPreparedGasPipes, m_ui->chbActiveGasPipes)},
{AreaEffectSimulation::AesType::AtTechnicalArea, Checkboxes(m_ui->chbCreatedTechnicalArea, m_ui->chbPreparedTechnicalArea, m_ui->chbActiveTechnicalArea)},
{AreaEffectSimulation::AesType::AtAirSupportImpact, Checkboxes(m_ui->chbCreatedAirSupport, m_ui->chbPreparedAirSupport, m_ui->chbActiveAirSupport)}
};
m_ui->chbCreatedIed->hide();
m_ui->chbPreparedDusSingleMine->hide();
m_ui->chbCreatedDusSingleMine->hide();
if (!enableDusSingleMine)
{
m_ui->label_19->hide();
m_ui->label_21->hide();
m_ui->chbPreparedDusSingleMine->hide();
m_ui->chbCreatedDusSingleMine->hide();
m_ui->chbActiveDusSingleMine->hide();
m_ui->sldAfterglowDusSingleMine->hide();
m_ui->lblAfterglowDusSingleMine->hide();
}
for (const auto &p : m_checkBoxes)
{
const auto type = p.first;
const Checkboxes *chb = &p.second;
connect(chb->chbCreated, &QCheckBox::clicked, this, [this, type]() { onCheckboxChanged(type);});
connect(chb->chbPrepared, &QCheckBox::clicked, this, [this, type]() { onCheckboxChanged(type);});
connect(chb->chbActive, &QCheckBox::clicked, this, [this, type]() { onCheckboxChanged(type);});
}
// don't know why this was added in the first place - there is no ongoing filtering for it
// and danger areas don't have a party atm
m_ui->chbPartiesDangerArea->hide();
m_ui->pbPartiesDangerArea->hide();
connect(m_ui->chbPartiesDangerArea, &QCheckBox::clicked,
this, &AesFilterWidget::onChbPartiesDangerAreaClicked);
connect(m_ui->pbPartiesDangerArea, &QPushButton::clicked,
this, &AesFilterWidget::onPbPartiesDangerAreaClicked);
connect(m_ui->chbChargeTypesMineArea, &QCheckBox::clicked,
this, &AesFilterWidget::onChbMineAreaChargeTypesClicked);
connect(m_ui->pbChargeTypesMineArea, &QPushButton::clicked,
this, &AesFilterWidget::onPbChargTypesMineAreaClicked);
connect(m_ui->chbSingleMinesMineArea, &QCheckBox::clicked,
this, &AesFilterWidget::onChbMineAreSingleMinesClicked);
connect(m_ui->chbCDMineArea, &QCheckBox::clicked,
this, &AesFilterWidget::onChbMineAreSingleMinesClicked);
connect(m_ui->sldAfterglowMineCorridor, &QSlider::valueChanged,
this, &AesFilterWidget::onSldMineCorridorChanged);
connect(m_ui->sldAfterglowSingleFire, &QSlider::valueChanged,
this, &AesFilterWidget::onSldSingleFireChanged);
connect(m_ui->sldAfterglowMineArea, &QSlider::valueChanged,
this, &AesFilterWidget::onSldMineAreaChanged);
connect(m_ui->sldAfterglowMineAreaSingleMines_IED, &QSlider::valueChanged,
this, &AesFilterWidget::onSldMineAreaSingleMinesChanged);
connect(m_ui->sldAfterglowDusSingleMine, &QSlider::valueChanged,
this, &AesFilterWidget::onSldDusSingleMineChanged);
connect(m_ui->sldAfterglowGasPipes, &QSlider::valueChanged,
this, &AesFilterWidget::onSldGasPipesChanged);
connect(m_ui->sldAfterglowAirSupport, &QSlider::valueChanged,
this, &AesFilterWidget::onSldAirSupportChanged);
connect(m_ui->sldAfterglowAreaFire, &QSlider::valueChanged,
this, &AesFilterWidget::onSldAreaFireChanged);
connect(m_ui->chbCentral, &QCheckBox::clicked, this, &AesFilterWidget::onChCentralClicked);
connect(m_ui->chbPeripheral, &QCheckBox::clicked, this, &AesFilterWidget::onChPeripheralClicked);
connect(m_ui->chbMeanHitPointAreaFire, &QCheckBox::clicked, this, &AesFilterWidget::onChbMeanHitPointAreaFireClicked);
connect(m_ui->chbGunToTargetLineAreaFire, &QCheckBox::clicked, this, &AesFilterWidget::onChbGunToTargetLineAreaFireClicked);
connect(m_ui->chbTrajectoryAreaFire, &QCheckBox::clicked, this, &AesFilterWidget::onChbTrajectoryAreaFireClicked);
connect(m_ui->chbDetonationSphereAreaFire, &QCheckBox::clicked, this, &AesFilterWidget::onChbDetonationSphereAreaFireClicked);
// after connect so the slots for setting the labels are executed
m_ui->sldAfterglowSingleFire->setValue(m_ui->sldAfterglowSingleFire->maximum());
setFixedWidthForWidgetHelper(m_ui->lblAfterglowSingleFire);
m_ui->sldAfterglowMineArea->setValue(m_ui->sldAfterglowMineArea->maximum());
setFixedWidthForWidgetHelper(m_ui->lblAfterglowMineArea);
m_ui->sldAfterglowMineCorridor->setValue(m_ui->sldAfterglowMineCorridor->maximum());
setFixedWidthForWidgetHelper(m_ui->lblAfterglowMineCorridor);
m_ui->sldAfterglowMineAreaSingleMines_IED->setValue(m_ui->sldAfterglowMineAreaSingleMines_IED->maximum());
setFixedWidthForWidgetHelper(m_ui->lblAfterglowMineAreaSingleMines);
m_ui->sldAfterglowDusSingleMine->setValue(m_ui->sldAfterglowDusSingleMine->maximum());
setFixedWidthForWidgetHelper(m_ui->lblAfterglowDusSingleMine);
m_ui->sldAfterglowGasPipes->setValue(m_ui->sldAfterglowGasPipes->maximum());
setFixedWidthForWidgetHelper(m_ui->lblAfterglowGasPipes);
m_ui->sldAfterglowAirSupport->setValue(m_ui->sldAfterglowAirSupport->maximum());
setFixedWidthForWidgetHelper(m_ui->lblAfterglowAirSupport);
}
AesFilterWidget::~AesFilterWidget()
{
m_filter->removeChangedCallback(this);
delete m_ui;
}
bool AesFilterWidget::init(const std::shared_ptr<ParticipantManagement::ForeignGuiComboboxInterface> &ifcPpmCbx,
const std::shared_ptr<ProjectDataManagement::ForeignGuiInterface> &ifcPdmCbx,
const std::shared_ptr<AesDisplayFilter> &filter,
bool isOc)
{
m_ifcPpmCbx = ifcPpmCbx;
m_ifcPdmCbx = ifcPdmCbx;
m_filter = filter;
m_originalFilterSettings = m_filter->filterToData();
setFilter();
if (isOc)
{
m_ui->pbChargeTypesMineArea->setVisible(false);
m_ui->chbChargeTypesMineArea->setVisible(false);
m_ui->lblCreated->setVisible(false);
m_ui->chbCreatedFunctionalArea->setVisible(false);
m_ui->chbCreatedBCContamination->setVisible(false);
m_ui->chbCreatedDusSingleMine->setVisible(false);
m_ui->chbCreatedExplosionArea->setVisible(false);
m_ui->chbCreatedExplosionSingle->setVisible(false);
m_ui->chbCreatedDangerArea->setVisible(false);
m_ui->chbCreatedGasPipes->setVisible(false);
m_ui->chbCreatedMineArea->setVisible(false);
m_ui->chbCreatedNContamination->setVisible(false);
m_ui->chbCreatedTechnicalArea->setVisible(false);
//no mine corridor at all!
m_ui->label_17->setVisible(false);
m_ui->chbCreatedMineCorridor->setVisible(false);
m_ui->chbPreparedMineCorridor->setVisible(false);
m_ui->chbActiveMineCorridor->setVisible(false);
m_ui->sldAfterglowMineCorridor->setVisible(false);
m_ui->label_18->setVisible(false);
m_ui->lblAfterglowMineCorridor->setVisible(false);
// No Air support at all
m_ui->chbCreatedAirSupport->setVisible(false);
m_ui->chbPreparedAirSupport->setVisible(false);
m_ui->chbActiveAirSupport->setVisible(false);
m_ui->lblAfterglowAirSupport->setVisible(false);
m_ui->sldAfterglowAirSupport->setVisible(false);
m_ui->label_23->setVisible(false);
m_ui->lb_AirSupport->setVisible(false);
// no IED at all
m_ui->chbCreatedIed->setVisible(false);
m_ui->chbPreparedIed->setVisible(false);
m_ui->chbActiveIed->setVisible(false);
m_ui->sldAfterglowMineAreaSingleMines_IED->setVisible(false);
m_ui->lblAfterglowMineAreaSingleMines->setVisible(false);
m_ui->label_13->setVisible(false);
m_ui->label_14->setVisible(false);
m_ui->label_15->setVisible(false);
m_ui->label_16->setVisible(false);
m_ui->label_21->setVisible(false);
//no Borderline at all?
m_ui->chbCreatedBorderline->setVisible(false);
m_ui->chbPreparedBorderline->setVisible(false);
m_ui->chbActiveBorderline->setVisible(false);
m_ui->lblBorderLine->setVisible(false);
}
m_filter->addChangedCallback(this);
return true;
}
void AesFilterWidget::retranslate()
{
m_ui->retranslateUi(this);
onUpdateSliderTextSingleFire();
onUpdateSliderTextMineCorridor();
onUpdateSliderTextMineAreaSingleMines();
onUpdateSliderTextDusSingleMine();
onUpdateSliderTextGasPipes();
onUpdateSliderTextAirSupport();
onUpdateSliderTextMineArea();
onUpdateSliderTextAreaFire();
}
void AesFilterWidget::apply()
{
// nothing to do here atm
}
void AesFilterWidget::dialogCanceled()
{
m_filter->setFilterFromData(m_originalFilterSettings);
}
void AesFilterWidget::setFilter()
{
m_ui->chbChargeTypesMineArea->setChecked(m_filter->effectStateFilter(AreaEffectSimulation::AesType::AtMineArea).limitOnChargeTypes);
m_ui->chbPartiesDangerArea->setChecked(m_filter->effectStateFilter(AreaEffectSimulation::AesType::AtDangerArea).limitOnParties);
m_ui->chbSingleMinesMineArea->setChecked(m_filter->effectStateFilter(AreaEffectSimulation::AesType::AtMineArea).showDetails);
m_ui->chbCDMineArea->setChecked(m_filter->effectStateFilter(AreaEffectSimulation::AesType::AtMineArea).showDetails2);
m_ui->chbMeanHitPointAreaFire->setChecked(m_filter->effectStateFilter(AreaEffectSimulation::AesType::AtExplosionArea).showDetails2);
m_ui->chbGunToTargetLineAreaFire->setChecked(m_filter->effectStateFilter(AreaEffectSimulation::AesType::AtExplosionArea).showDetails3);
m_ui->chbTrajectoryAreaFire->setChecked(m_filter->effectStateFilter(AreaEffectSimulation::AesType::AtExplosionArea).showDetails4);
m_ui->chbDetonationSphereAreaFire->setChecked(m_filter->effectStateFilter(AreaEffectSimulation::AesType::AtExplosionArea).showDetails5);
QSignalBlocker b(this);
for (const auto &p : m_checkBoxes)
{
const AesDisplayFilter::EffectStateStruct ess(m_filter->effectStateFilter(p.first));
DEBUG_LOG(m_logger) << "Set Filter for " << p.first << ": "
<< ess.displayCreated << ", "
<< ess.displayPrepared << ", "
<< ess.displayActivated;
const Checkboxes *chb = &p.second;
setConditional(chb->chbCreated, ess.displayCreated);
setConditional(chb->chbPrepared, ess.displayPrepared);
setConditional(chb->chbActive, ess.displayActivated);
}
{
const AesDisplayFilter::EffectStateStruct essMineArea(m_filter->effectStateFilter(AreaEffectSimulation::AesType::AtMineArea));
m_ui->sldAfterglowMineArea->setValue(essMineArea.expiredAfterglowDurationMSec / 1000);
m_ui->chbCentral->setChecked(essMineArea.displayCentral);
m_ui->chbPeripheral->setChecked(essMineArea.displayPeripheral);
}
{
const AesDisplayFilter::EffectStateStruct essMc(m_filter->effectStateFilter(AreaEffectSimulation::AesType::AtMineCorridor));
m_ui->sldAfterglowMineCorridor->setValue(essMc.expiredAfterglowDurationMSec / 1000);
}
{
const AesDisplayFilter::EffectStateStruct essEs(m_filter->effectStateFilter(AreaEffectSimulation::AesType::AtExplosionSingle));
m_ui->sldAfterglowSingleFire->setValue(essEs.expiredAfterglowDurationMSec / 1000);
}
{
const AesDisplayFilter::EffectStateStruct essAreaFire(m_filter->effectStateFilter(AreaEffectSimulation::AesType::AtExplosionArea));
m_ui->sldAfterglowAreaFire->setValue(essAreaFire.expiredAfterglowDurationMSec / 1000);
}
{
const AesDisplayFilter::EffectStateStruct essGP(m_filter->effectStateFilter(AreaEffectSimulation::AesType::AtGasPipe));
m_ui->sldAfterglowGasPipes->setValue(essGP.expiredAfterglowDurationMSec / 1000);
}
{
const AesDisplayFilter::EffectStateStruct essAS(m_filter->effectStateFilter(AreaEffectSimulation::AesType::AtAirSupportImpact));
m_ui->sldAfterglowAirSupport->setValue(essAS.expiredAfterglowDurationMSec / 1000);
}
{ // IED
const AesDisplayFilter::EffectStateStruct essMa(m_filter->effectStateFilter(AreaEffectSimulation::AesType::AtMineAreaSingleMines));
m_ui->sldAfterglowMineAreaSingleMines_IED->setValue(essMa.expiredAfterglowDurationMSec / 1000);
}
{
const AesDisplayFilter::EffectStateStruct essDsm(m_filter->effectStateFilter(AreaEffectSimulation::AesType::AtDusSingleMine));
m_ui->sldAfterglowDusSingleMine->setValue(essDsm.expiredAfterglowDurationMSec / 1000);
}
onSldSingleFireChanged();
onSldMineCorridorChanged();
onSldMineAreaSingleMinesChanged();
onSldDusSingleMineChanged();
onSldGasPipesChanged();
onSldAirSupportChanged();
onChbMineAreaChargeTypesClicked();
onChbPartiesDangerAreaClicked();
onChbGunToTargetLineAreaFireClicked();
onChbMeanHitPointAreaFireClicked();
onChbTrajectoryAreaFireClicked();
onChbDetonationSphereAreaFireClicked();
}
void AesFilterWidget::onCheckboxChanged(AreaEffectSimulation::AesType t)
{
if (!m_filter)
return;
auto it = m_checkBoxes.find(t);
if (it == m_checkBoxes.end())
return;
const Checkboxes *chb = &it->second;
AesDisplayFilter::EffectStateStruct ess = m_filter->effectStateFilter(t);
ess.displayCreated = chb->chbCreated->isChecked();
ess.displayPrepared = chb->chbPrepared->isChecked();
ess.displayActivated = chb->chbActive->isChecked();
ess.displayCentral = m_ui->chbCentral->isChecked();
ess.displayPeripheral = m_ui->chbPeripheral->isChecked();
ess.showDetails2 = m_ui->chbMeanHitPointAreaFire->isChecked();
ess.showDetails3 = m_ui->chbGunToTargetLineAreaFire->isChecked();
ess.showDetails4 = m_ui->chbTrajectoryAreaFire->isChecked();
ess.showDetails5 = m_ui->chbDetonationSphereAreaFire->isChecked();
UpdateGuard guard(this);
m_filter->setEffectStateFilter(t, ess);
}
void AesFilterWidget::onPbPartiesDangerAreaClicked()
{
const AreaEffectSimulation::AesType t(AreaEffectSimulation::AesType::AtDangerArea);
AesDisplayFilter::EffectStateStruct ess = m_filter->effectStateFilter(t);
auto cb = [this, t](const QSet<int> &selectedParties)
{
if (!this->m_filter)
return;
AesDisplayFilter::EffectStateStruct ess = m_filter->effectStateFilter(t);
if (ess.visiblePartyIds == selectedParties)
return;
ess.visiblePartyIds = selectedParties;
UpdateGuard guard(this);
m_filter->setEffectStateFilter(t, ess);
emit changesMade();
};
m_ifcPpmCbx->partySelector(ess.visiblePartyIds, cb, this);
}
void AesFilterWidget::onPbChargTypesMineAreaClicked()
{
const AreaEffectSimulation::AesType t(AreaEffectSimulation::AesType::AtMineArea);
AesDisplayFilter::EffectStateStruct ess = m_filter->effectStateFilter(t);
auto cb = [this, t](const QSet<int> &selectedCharges)
{
if (!this->m_filter)
return;
AesDisplayFilter::EffectStateStruct ess = m_filter->effectStateFilter(t);
if (ess.visibleChargeTypeIds == selectedCharges)
return;
ess.visibleChargeTypeIds = selectedCharges;
UpdateGuard guard(this);
m_filter->setEffectStateFilter(t, ess);
emit changesMade();
};
m_ifcPdmCbx->chargeSelector(ess.visibleChargeTypeIds, ProjectDataManagement::GearClass::MineArea, cb, this);
}
void AesFilterWidget::onChbMineAreSingleMinesClicked()
{
const AreaEffectSimulation::AesType t(AreaEffectSimulation::AesType::AtMineArea);
AesDisplayFilter::EffectStateStruct ess = m_filter->effectStateFilter(t);
ess.displayPeripheral = m_ui->chbPeripheral->isChecked();
ess.displayCentral = m_ui->chbCentral->isChecked();
ess.showDetails = m_ui->chbSingleMinesMineArea->isChecked();
ess.showDetails2 = m_ui->chbCDMineArea->isChecked();
UpdateGuard guard(this);
m_filter->setEffectStateFilter(t, ess);
emit changesMade();
}
void AesFilterWidget::onUpdateSliderTextMineArea()
{
m_ui->lblAfterglowMineArea->setText(tr("%1 [s]").arg(m_ui->sldAfterglowMineArea->value()));
}
void AesFilterWidget::onUpdateSliderTextAreaFire()
{
m_ui->lblAfterglowAreaFire->setText(tr("%1 [s]").arg(m_ui->sldAfterglowAreaFire->value()));
}
void AesFilterWidget::onUpdateSliderTextSingleFire()
{
m_ui->lblAfterglowSingleFire->setText(tr("%1 [s]").arg(m_ui->sldAfterglowSingleFire->value()));
}
void AesFilterWidget::onUpdateSliderTextMineCorridor()
{
m_ui->lblAfterglowMineCorridor->setText(tr("%1 [s]").arg(m_ui->sldAfterglowMineCorridor->value()));
}
void AesFilterWidget::onUpdateSliderTextMineAreaSingleMines()
{
m_ui->lblAfterglowMineAreaSingleMines->setText(tr("%1 [s]").arg(m_ui->sldAfterglowMineAreaSingleMines_IED->value()));
}
void AesFilterWidget::onUpdateSliderTextDusSingleMine()
{
m_ui->lblAfterglowDusSingleMine->setText(tr("%1 [s]").arg(m_ui->sldAfterglowDusSingleMine->value()));
}
void AesFilterWidget::onUpdateSliderTextGasPipes()
{
m_ui->lblAfterglowGasPipes->setText(tr("%1 [s]").arg(m_ui->sldAfterglowGasPipes->value()));
}
void AesFilterWidget::onUpdateSliderTextAirSupport()
{
m_ui->lblAfterglowAirSupport->setText(tr("%1 [s]").arg(m_ui->sldAfterglowAirSupport->value()));
}
void AesFilterWidget::onSldSingleFireChanged()
{
onUpdateSliderTextSingleFire();
if (!m_filter)
return;
const AreaEffectSimulation::AesType t(AreaEffectSimulation::AesType::AtExplosionSingle);
AesDisplayFilter::EffectStateStruct ess = m_filter->effectStateFilter(t);
ess.expiredAfterglowDurationMSec = m_ui->sldAfterglowSingleFire->value() * 1000;
UpdateGuard guard(this);
m_filter->setEffectStateFilter(t, ess);
}
void AesFilterWidget::onSldMineAreaChanged()
{
onUpdateSliderTextMineArea();
if (!m_filter)
return;
const AreaEffectSimulation::AesType t(AreaEffectSimulation::AesType::AtMineArea);
AesDisplayFilter::EffectStateStruct ess = m_filter->effectStateFilter(t);
ess.expiredAfterglowDurationMSec = m_ui->sldAfterglowMineArea->value() * 1000;
UpdateGuard guard(this);
m_filter->setEffectStateFilter(t, ess);
}
void AesFilterWidget::onSldAreaFireChanged()
{
onUpdateSliderTextAreaFire();
DEBUG_LOG(m_logger)<<">> slider area fire changed";
if(!m_filter)
return;
const AreaEffectSimulation::AesType t(AreaEffectSimulation::AesType::AtExplosionArea);
AesDisplayFilter::EffectStateStruct ess = m_filter->effectStateFilter(t);
ess.showDetails2 = m_ui->chbMeanHitPointAreaFire->isChecked();
ess.showDetails3 = m_ui->chbGunToTargetLineAreaFire->isChecked();
ess.showDetails4 = m_ui->chbTrajectoryAreaFire->isChecked();
ess.showDetails5 = m_ui->chbDetonationSphereAreaFire->isChecked();
ess.expiredAfterglowDurationMSec = m_ui->sldAfterglowAreaFire->value() * 1000;
UpdateGuard guard(this);
m_filter->setEffectStateFilter(t, ess);
}
void AesFilterWidget::onSldMineCorridorChanged()
{
onUpdateSliderTextMineCorridor();
if (!m_filter)
return;
const AreaEffectSimulation::AesType t(AreaEffectSimulation::AesType::AtMineCorridor);
AesDisplayFilter::EffectStateStruct ess = m_filter->effectStateFilter(t);
ess.expiredAfterglowDurationMSec = m_ui->sldAfterglowMineCorridor->value() * 1000;
UpdateGuard guard(this);
m_filter->setEffectStateFilter(t, ess);
}
void AesFilterWidget::onSldMineAreaSingleMinesChanged()
{
onUpdateSliderTextMineAreaSingleMines();
if (!m_filter)
return;
const AreaEffectSimulation::AesType t(AreaEffectSimulation::AesType::AtMineAreaSingleMines);
AesDisplayFilter::EffectStateStruct ess = m_filter->effectStateFilter(t);
ess.expiredAfterglowDurationMSec = m_ui->sldAfterglowMineAreaSingleMines_IED->value() * 1000;
UpdateGuard guard(this);
m_filter->setEffectStateFilter(t, ess);
}
void AesFilterWidget::onSldDusSingleMineChanged()
{
onUpdateSliderTextDusSingleMine();
if (!m_filter)
return;
const AreaEffectSimulation::AesType t(AreaEffectSimulation::AesType::AtDusSingleMine);
AesDisplayFilter::EffectStateStruct ess = m_filter->effectStateFilter(t);
ess.expiredAfterglowDurationMSec = m_ui->sldAfterglowDusSingleMine->value() * 1000;
UpdateGuard guard(this);
m_filter->setEffectStateFilter(t, ess);
}
void AesFilterWidget::onSldGasPipesChanged()
{
onUpdateSliderTextGasPipes();
if (!m_filter)
return;
const AreaEffectSimulation::AesType t(AreaEffectSimulation::AesType::AtGasPipe);
AesDisplayFilter::EffectStateStruct ess = m_filter->effectStateFilter(t);
ess.expiredAfterglowDurationMSec = m_ui->sldAfterglowGasPipes->value() * 1000;
UpdateGuard guard(this);
m_filter->setEffectStateFilter(t, ess);
}
void AesFilterWidget::onSldAirSupportChanged()
{
onUpdateSliderTextAirSupport();
if (!m_filter)
return;
const AreaEffectSimulation::AesType t(AreaEffectSimulation::AesType::AtAirSupportImpact);
AesDisplayFilter::EffectStateStruct ess = m_filter->effectStateFilter(t);
ess.expiredAfterglowDurationMSec = m_ui->sldAfterglowAirSupport->value() * 1000;
UpdateGuard guard(this);
m_filter->setEffectStateFilter(t, ess);
}
void AesFilterWidget::onChbMeanHitPointAreaFireClicked()
{
const AreaEffectSimulation::AesType t(AreaEffectSimulation::AesType::AtExplosionArea);
AesDisplayFilter::EffectStateStruct ess = m_filter->effectStateFilter(t);
ess.showDetails2 = m_ui->chbMeanHitPointAreaFire->isChecked();
UpdateGuard guard(this);
m_filter->setEffectStateFilter(t, ess);
}
void AesFilterWidget::onChbGunToTargetLineAreaFireClicked()
{
const AreaEffectSimulation::AesType t(AreaEffectSimulation::AesType::AtExplosionArea);
AesDisplayFilter::EffectStateStruct ess = m_filter->effectStateFilter(t);
ess.showDetails3 = m_ui->chbGunToTargetLineAreaFire->isChecked();
UpdateGuard guard(this);
m_filter->setEffectStateFilter(t, ess);
}
void AesFilterWidget::onChbTrajectoryAreaFireClicked()
{
const AreaEffectSimulation::AesType t(AreaEffectSimulation::AesType::AtExplosionArea);
AesDisplayFilter::EffectStateStruct ess = m_filter->effectStateFilter(t);
ess.showDetails4 = m_ui->chbTrajectoryAreaFire->isChecked();
UpdateGuard guard(this);
m_filter->setEffectStateFilter(t, ess);
}
void AesFilterWidget::onChbDetonationSphereAreaFireClicked()
{
const AreaEffectSimulation::AesType t(AreaEffectSimulation::AesType::AtExplosionArea);
AesDisplayFilter::EffectStateStruct ess = m_filter->effectStateFilter(t);
ess.showDetails5 = m_ui->chbDetonationSphereAreaFire->isChecked();
UpdateGuard guard(this);
m_filter->setEffectStateFilter(t, ess);
}
void AesFilterWidget::onChbMineAreaChargeTypesClicked()
{
const AreaEffectSimulation::AesType t(AreaEffectSimulation::AesType::AtMineArea);
AesDisplayFilter::EffectStateStruct ess = m_filter->effectStateFilter(t);
ess.limitOnChargeTypes = m_ui->chbChargeTypesMineArea->isChecked();
m_ui->pbChargeTypesMineArea->setEnabled(ess.limitOnChargeTypes);
UpdateGuard guard(this);
m_filter->setEffectStateFilter(t, ess);
}
void AesFilterWidget::onChbPartiesDangerAreaClicked()
{
const AreaEffectSimulation::AesType t(AreaEffectSimulation::AesType::AtDangerArea);
AesDisplayFilter::EffectStateStruct ess = m_filter->effectStateFilter(t);
ess.limitOnParties = m_ui->chbPartiesDangerArea->isChecked();
m_ui->pbPartiesDangerArea->setEnabled(ess.limitOnParties);
UpdateGuard guard(this);
m_filter->setEffectStateFilter(t, ess);
}
void AesFilterWidget::onChCentralClicked()
{
for (const auto &p : m_checkBoxes)
{
const auto type = p.first;
onCheckboxChanged(type);
}
}
void AesFilterWidget::onChPeripheralClicked()
{
for (const auto &p : m_checkBoxes)
{
const auto type = p.first;
onCheckboxChanged(type);
}
}
void AesFilterWidget::onChbTriggeredCDMineAreaClicked()
{
const AreaEffectSimulation::AesType t(AreaEffectSimulation::AesType::AtMineArea);
AesDisplayFilter::EffectStateStruct ess = m_filter->effectStateFilter(t);
ess.showDetails2 = m_ui->chbCDMineArea->isChecked();
UpdateGuard guard(this);
m_filter->setEffectStateFilter(t, ess);
}
void AesFilterWidget::onAesDisplayFilterChanged(AreaEffectSimulation::AesType aesType)
{
Q_UNUSED(aesType);
DEBUG_LOG(m_logger) << LOGFUNCTION << " START, m_doUpdateViaCallback=" << m_doUpdateViaCallback;
if (m_doUpdateViaCallback)
emit unknownChangesRecognized();
DEBUG_LOG(m_logger) << LOGFUNCTION << " END, m_doUpdateViaCallback=" << m_doUpdateViaCallback;
}
} // namespace FilterManagement
@@ -0,0 +1,113 @@
/**
* @RDE_HEADER@
* FilterManagement - Aes Filter Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#pragma once
#include <QWidget>
#include <Plugins/FilterManagement/flt_data_plugin_aes_display_filter.h>
#include <Plugins/ParticipantManagement/ppm_gui_combobox_plugin_interface.h>
#include <Plugins/ProjectDataManagement/pdm_gui_plugin_interface.h>
class QCheckBox;
namespace NGL
{
class INGLLogger;
}
namespace Ui
{
class AesFilterWidget;
}
namespace FilterManagement
{
class AesFilterWidget : public QWidget,
protected AesDisplayFilter::FilterChangedCallback
{
Q_OBJECT
public:
explicit AesFilterWidget(QWidget *parent = nullptr);
~AesFilterWidget();
bool init(const std::shared_ptr<ParticipantManagement::ForeignGuiComboboxInterface> &ifcPpmCbx,
const std::shared_ptr<ProjectDataManagement::ForeignGuiInterface> &ifcPdmCbx,
const std::shared_ptr<AesDisplayFilter> &filter, bool isOc = false);
void retranslate();
void apply();
void dialogCanceled();
std::shared_ptr<AesDisplayFilter> filter() const { return m_filter; }
void updateGuiToFilter() { setFilter(); }
signals:
void changesMade();
void unknownChangesRecognized();
private:
void setFilter();
private slots:
void onCheckboxChanged(AreaEffectSimulation::AesType t);
void onPbPartiesDangerAreaClicked();
void onPbChargTypesMineAreaClicked();
void onChbMineAreSingleMinesClicked();
void onUpdateSliderTextMineArea();
void onUpdateSliderTextAreaFire();
void onUpdateSliderTextSingleFire();
void onUpdateSliderTextMineCorridor();
void onUpdateSliderTextMineAreaSingleMines();
void onUpdateSliderTextDusSingleMine();
void onUpdateSliderTextGasPipes();
void onUpdateSliderTextAirSupport();
void onSldSingleFireChanged();
void onSldMineAreaChanged();
void onSldAreaFireChanged();
void onSldMineCorridorChanged();
void onSldMineAreaSingleMinesChanged();
void onSldDusSingleMineChanged();
void onSldGasPipesChanged();
void onSldAirSupportChanged();
void onChbMineAreaChargeTypesClicked();
void onChbPartiesDangerAreaClicked();
void onChCentralClicked();
void onChbGunToTargetLineAreaFireClicked();
void onChbMeanHitPointAreaFireClicked();
void onChbTrajectoryAreaFireClicked();
void onChbDetonationSphereAreaFireClicked();
void onChPeripheralClicked();
void onChbTriggeredCDMineAreaClicked();
void onAesDisplayFilterChanged(AreaEffectSimulation::AesType aesType) override;
private:
struct Checkboxes
{
QCheckBox *chbCreated = nullptr;
QCheckBox *chbPrepared = nullptr;
QCheckBox *chbActive = nullptr;
Checkboxes(QCheckBox *_creat, QCheckBox *_prep, QCheckBox *_act)
: chbCreated(_creat)
, chbPrepared(_prep)
, chbActive(_act)
{}
};
std::map<AreaEffectSimulation::AesType, Checkboxes> m_checkBoxes;
std::shared_ptr<ParticipantManagement::ForeignGuiComboboxInterface> m_ifcPpmCbx;
std::shared_ptr<ProjectDataManagement::ForeignGuiInterface> m_ifcPdmCbx;
std::shared_ptr<AesDisplayFilter> m_filter;
AesFilter m_originalFilterSettings;
friend class UpdateGuard;
bool m_doUpdateViaCallback;
Ui::AesFilterWidget *m_ui;
NGL::INGLLogger &m_logger;
};
}
File diff suppressed because it is too large. Load diff
+181
View File
@@ -0,0 +1,181 @@
/**
* @RDE_HEADER@
* Gui Plugin for FilterManagement (AES)
* $Id: flt_aes_plugin.cpp 50305 2020-03-10 08:30:39Z ehrlicher $
* $HeadURL: svn://slssvn/TDS/branches/product/devel/trunk/Lts/Plugins/FilterManagement/Gui/Aes/flt_aes_plugin.cpp $
* $Author: ehrlicher $
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#include "flt_aes_gui_plugin.h"
#include "flt_aes_filter_dialog.h"
#include <LtsSession/lts_session.h>
#include <LtsSession/lts_session_data.h>
#include <LtsProjectionWorkstation/lts_projection_workstation.h>
#include <LtsUtilsSettings/settings.h>
#include <FilterManagement/flt_operator_rights.h>
#include <Plugins/FilterManagement/Gui/Aes/Common/symbol_appearance_settings_impl.h>
#include <Plugins/FilterManagement/Gui/Aes/Common/aes_display_filter_impl.h>
#include <Plugins/ParticipantManagement/ppm_data_plugin_interface.h>
#include <QDebug>
namespace FilterManagement
{
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.Interface"))
{}
bool InterfaceImpl::fetchInterfaces()
{
std::shared_ptr<ParticipantManagement::ForeignGuiComboboxInterface> ifcPpmCbx;
std::shared_ptr<ProjectDataManagement::ForeignGuiInterface> ifcPdmCbx;
if (!m_session->getForeignGuiInterface(ifcPpmCbx) ||
!m_session->getForeignGuiInterface(ifcPdmCbx) ||
!m_session->getDtc<FilterManagement::DataInterface>(m_fltDtc))
return false;
connect(m_fltDtc.get(), &FilterManagement::Interface::Dtc::aesFilterChanged,
this, &InterfaceImpl::onAesFilterChanged, Qt::UniqueConnection);
// NLDEVCTRL-445: Projektion Filter und Kartenausschnitt
// filterPresetLoadUnsaved at PWS leads to race condition
// (create dtc and update data via request)
// enable AesFilter and SymbolAppearance already here
// 22.01.2025, Thoden: Nachtrag zu NLDEVCTRL-445: Projektion Filter und Kartenausschnitt
// GUEZE-3459: Hannas OPW: Hänger beim Login
// 1. waitForHistoricalData{SymbolAppearance|AesFilter|buildingComponentFilters}
// gehört eingentlich VOR fltDtc->{SymbolAppearance|AesFilter|buildingComponentFilters}
// 2. Da diese aber auf der PWS wohl wichtig waren, wird fetchInterfaces jeweils
// angepasst:
// waitForHistoricalData{SymbolAppearance|AesFilter|buildingComponentFilters} wird
// nicht mehr grundsätzlich, sondern nur auf der PWS ausgeführt:
// if (LtsProjectionWorkstation::LtsProjectionWorkstation::hasInstance())
// m_fltDtc->waitForHistoricalDataXXX(1000);
if (LtsProjectionWorkstation::LtsProjectionWorkstation::hasInstance())
m_fltDtc->waitForHistoricalDataAesFilter(1000);
return true;
}
QVector<LtsWidgets::PluginData> InterfaceImpl::getActions()
{
QVector<LtsWidgets::PluginData> ret;
LtsUtils::ProjectSettings *ps = LtsUtils::ProjectSettings::getInstance();
const bool enableAES_FilterEdit = ps->value(QStringLiteral("flt"),
QStringLiteral("enableAES_FilterEdit")).toBool();
// GUEZE-1624: not in ResourceManagerApp:
const bool bResourceManager = m_session->app() == LtsAppDescriptor::App::ResourceManager;
if (enableAES_FilterEdit && !bResourceManager)
{
LtsWidgets::PluginData plData;
plData.menuGroup = menuGroup();
plData.menuText = tr("Filter Area Effect Simulation");
plData.identifier = QLatin1String("fltAesFilter");
plData.menuIcon = QIcon(QLatin1String("icon:filter_effect_simulation.svg"));
plData.operatorRight = OperatorRights::FilterManagement::AesFilterEdit;
plData.exercisePart = LtsWidgets::ExercisePart::eSpecial;
plData.createWidgetFunc = [this](QWidget * parent)
{
return onShowAesFilterDialog(parent);
};
ret.append(plData);
}
return ret;
}
std::shared_ptr<AesDisplayFilter> InterfaceImpl::aesFilterForOperator(int operatorId, const QString &context)
{
std::shared_ptr<AesDisplayFilterImpl> ret;
auto it = m_aesFilterMap.find({operatorId, context.toStdString()});
if (it != m_aesFilterMap.end())
ret = it->second.lock();
if (!ret)
{
FilterManagement::AesFilter filterData;
// it's 0 when there is not yet a filter for this operator, so set it here and use it for comparision
filterData.operatorId(operatorId);
filterData.ctx(context.toStdString());
std::function<bool(const FilterManagement::AesFilter &)> func = [&filterData](const FilterManagement::AesFilter &f)
{
if (f.operatorId() == filterData.operatorId() &&
f.ctx() == filterData.ctx())
{
filterData = f;
return true;
}
return false;
};
// 22.01.2025, Thoden: Nachtrag zu NLDEVCTRL-445: Projektion Filter und Kartenausschnitt
// GUEZE-3459: Hannas OPW: Hänger beim Login
// 1. waitForHistoricalData{SymbolAppearance|AesFilter|buildingComponentFilters}
// gehört eingentlich VOR fltDtc->{SymbolAppearance|AesFilter|buildingComponentFilters}
// 2. Da diese aber auf der PWS wohl wichtig waren, wird fetchInterfaces jeweils
// angepasst:
// waitForHistoricalData{SymbolAppearance|AesFilter|buildingComponentFilters} wird
// nicht mehr grundsätzlich, sondern nur auf der PWS ausgeführt:
// if (LtsProjectionWorkstation::LtsProjectionWorkstation::hasInstance())
// m_fltDtc->waitForHistoricalDataXXX(1000);
m_fltDtc->waitForHistoricalDataAesFilter(1000);
m_fltDtc->aesFilters(func);
ret = std::make_shared<AesDisplayFilterImpl>();
ret->setFilterFromData(filterData);
ret->setVisiblePartiesCheck([this](int id) -> bool { return LtsSessionData::LtsSessionData::getInstance()->isVisibleParty(m_session->exerciseId(), id); });
m_aesFilterMap[FilterKey(operatorId, context.toStdString())] = ret;
}
return ret;
}
void InterfaceImpl::onAesFilterChanged(const FilterManagement::AesFilter &data, DataModification mod)
{
auto it = m_aesFilterMap.find(FilterKey{data.operatorId(), data.ctx()});
if (it != m_aesFilterMap.end())
{
std::shared_ptr<AesDisplayFilterImpl> ret = it->second.lock();
if (ret && mod != DataModification::eRemoved)
ret->setFilterFromData(data);
else
{
// Maybe the scvFilterManagement (hosted at svcExerciseEventManagement)
// is restarted. In that case the topics are removed from DDS.
// But when the svc is starting again, the data is inserted into this
// map again - but the callbacks are lost!! So some related dialog do
// not work anymore... :-(
// To avoid this, prevent 'used' AesDisplayFilterImpl from
// being removed:
if (!(ret && ret->hasChangedCallbacks()))
m_aesFilterMap.erase(it);
}
}
}
//private
LtsWidgets::LtsDialog *InterfaceImpl::onShowAesFilterDialog(QWidget *parent)
{
return LtsWidgets::initDialog(new AesFilterDialog(parent),
m_session);
}
} //namespace FilterManagement
+90
View File
@@ -0,0 +1,90 @@
/**
* @RDE_HEADER@
* Gui Plugin for FilterManagement (AES)
* $Id: flt_aes_plugin.h 46043 2019-03-14 14:07:28Z hjl $
* $HeadURL: svn://slssvn/TDS/branches/product/devel/trunk/Lts/Plugins/FilterManagement/Gui/Aes/flt_aes_plugin.h $
* $Author: hjl $
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#pragma once
#include <PluginInterfaces/gui_plugin_interface.h>
#include <Plugins/FilterManagement/flt_aes_plugin_interface.h>
#include <Plugins/FilterManagement/flt_data_plugin_interface.h>
//#include <Services/FilterManagement/logger.h>
namespace FilterManagement
{
class FilterKey;
class SymbolAppearanceSettingsImpl;
class AesDisplayFilterImpl;
class GuiPlugin final : public QObject, public GuiPluginBase::Plugin
{
Q_PLUGIN_METADATA(IID "gui:3:flt.aes")
Q_INTERFACES(GuiPluginBase::Plugin)
Q_OBJECT
public:
GuiPlugin() = default;
~GuiPlugin() = default;
QString pluginName() override { return QLatin1String("FilterManagementAesGuiPlugin"); }
std::shared_ptr<GuiPluginBase::Interface> createGuiInterface(LtsSession::LtsSession *session) override;
bool availableInPartition(IDL::PartitionType partition) const override
{
return (partition == IDL::PartitionType::Global) ||
(partition == IDL::PartitionType::Exercise) ||
(partition == IDL::PartitionType::Replay);
}
};
class InterfaceImpl final : public QObject, public ForeignAesGuiInterface, public GuiPluginBase::Interface
{
Q_OBJECT
public:
explicit InterfaceImpl(LtsSession::LtsSession *session);
bool fetchInterfaces() override;
QString menuGroup() const override { return tr("Situation Map"); }
QVector<LtsWidgets::PluginData> getActions() override;
// std::shared_ptr<SymbolAppearanceSettings> symbolAppearanceForOperator(int operatorId, const QString &context) override final;
std::shared_ptr<AesDisplayFilter> aesFilterForOperator(int operatorId, const QString &context) override;
private slots:
void onAesFilterChanged(const FilterManagement::AesFilter &data, DataModification mod);
// void onSymbolAppearanceChanged(const SymbolAppearance &data, DataModification mod);
private:
// <operatorId, filter>
struct FilterKey
{
int operatorId = 0;
std::string context;
FilterKey() = default;
FilterKey(int _operatorId, const std::string &_context)
: operatorId(_operatorId)
, context(_context)
{}
bool operator<(const FilterKey &o) const
{
if (operatorId != o.operatorId)
return operatorId < o.operatorId;
return context < o.context;
}
};
// std::map<FilterKey, std::weak_ptr<SymbolAppearanceSettingsImpl>> m_symbolAppearanceMap;
std::map<FilterKey, std::weak_ptr<AesDisplayFilterImpl>> m_aesFilterMap;
std::shared_ptr<FilterManagement::Interface::Dtc> m_fltDtc;
// std::shared_ptr<FilterManagement::Interface::Ftc> m_fltFtc;
LtsWidgets::LtsDialog *onShowAesFilterDialog(QWidget *parent);
};
} // namespace FilterManagement
@@ -0,0 +1,58 @@
#
# $Id$
# $HeadURL$
# $Author$
# Created by Christian Ehrlicher, SLSE, 2017-06-16
#
SET(flt_bldg_cmpnt_widget_SRCS
flt_building_component_settings_widget.cpp
flt_building_component_settings_widget.h
)
NGL_WRAP_UI(flt_bldg_cmpnt_widget_SRCS
flt_building_component_settings_widget.ui
)
NGL_ADD_LIBRARY(WS FltBldgCmpntWidget STATIC ${flt_bldg_cmpnt_widget_SRCS})
NGL_TARGET_LINK_LIBRARIES(FltBldgCmpntWidget
PRIVATE
svcFltCommon
IsmDataPluginInterface
LtsProjectionWorkstation
PUBLIC
FltDataPluginInterface
LtsSessionData
PdmGuiPluginInterface
PpmGuiComboboxPluginInterface
Qt5::Widgets
)
NGL_TARGET_INCLUDE_DIRECTORIES(FltBldgCmpntWidget
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../../..
)
SET(flt_bldg_cmpnt_gui_SRCS
flt_building_component_filter_dialog.cpp
flt_building_component_filter_dialog.h
flt_building_components_gui_plugin.cpp
flt_building_components_gui_plugin.h
)
NGL_ADD_LIBRARY(WS Fltbldg_cmpntGuiPlugin MODULE ${flt_bldg_cmpnt_gui_SRCS})
NGL_TARGET_LINK_LIBRARIES(Fltbldg_cmpntGuiPlugin
FltAesGuiCommon
FltBldgCmpntGuiPluginInterface
FltBldgCmpntWidget
FltFilterChange
LtsSession
LtsSessionData
LtsUtilsGuiDds
LtsUtilsSettings
LtsWidgets
Qt5::Widgets
)
NGL_INSTALL_TARGET(Fltbldg_cmpntGuiPlugin)
@@ -0,0 +1,145 @@
/**
* @RDE_HEADER@
* FilterManagement - Aes Filter Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#include "flt_building_component_filter_dialog.h"
#include <LtsSession/lts_session_data.h>
#include <LtsWidgets/lts_message_dialog.h>
#include <FilterManagement/flt_building_cmpnt_settings.h>
#include <PluginInterfaces/gui_plugin_interface.h>
#include <QGridLayout>
#include <FilterManagement/Gui/FilterChange/flt_filter_change.h>
#include <InfrastructureManagement/ism_data_plugin_interface.h>
namespace FilterManagement
{
//
// BuildingComponentFilterDialog
//
BuildingComponentFilterDialog::BuildingComponentFilterDialog(QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
, m_widget(new BuildingComponentSettingsWidget(this))
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_session(nullptr)
, m_logger(getLogger("BuildingComponentFilterDialog"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
connect(m_widget, &BuildingComponentSettingsWidget::changesMade, this, &BuildingComponentFilterDialog::slotChangesMade);
QGridLayout *gl = new QGridLayout(this);
gl->setMargin(0);
gl->addWidget(m_widget, 0, 0);
setOnlineHelpFilename(QStringLiteral("Situation-Situation_Filter"));
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
BuildingComponentFilterDialog::~BuildingComponentFilterDialog()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
bool BuildingComponentFilterDialog::init(LtsSession::LtsSession *session)
{
m_session = session;
if (!session->getForeignGuiInterface(m_fltIfc))
{
WARNING_LOG(m_logger) << "Can not get Foreign data interface for FilterManagement";
return false;
}
if (!session->getFtc<FilterManagement::DataInterface>(m_fltFtc))
{
WARNING_LOG(m_logger) << "Can not get Foreign data interface for FilterManagement";
return false;
}
std::shared_ptr<BuildingComponentSettings> filter;
filter = m_fltIfc->buildingComponentSettingsForOperator(LtsSessionData::LtsSessionData::getInstance()->getOperatorId(), m_session->workspaceId());
std::shared_ptr<InfrastructureManagement::Interface::Dtc> m_ismDtc;
if (!session->getDtc<InfrastructureManagement::DataInterface>(m_ismDtc))
{
WARNING_LOG(m_logger) << "Can not get Foreign data interface for FilterManagement";
return false;
}
bool success = m_widget->init(filter, m_ismDtc /*, m_session->app() == LtsAppDescriptor::App::OC*/);
// In case of LoadingFilter or user selects another replay (and therefore other filter):
connect(m_widget, &BuildingComponentSettingsWidget::unknownChangesRecognized,
this, &BuildingComponentFilterDialog::onUnknownChangesRecognized, Qt::UniqueConnection);
if (FilterChangeDialog::isAvailableAtApp(m_session->app()))
{
m_buttonBox->getButton(LtsWidgets::DialogButton::Load)->setText(tr("Load filter"));
m_buttonBox->connectButton(LtsWidgets::DialogButton::Load,
this, &BuildingComponentFilterDialog::onLoadButtonClicked);
}
return success;
}
void BuildingComponentFilterDialog::retranslate()
{
// lupdate doesn't like translate(tr("foo")) ...
const QString txt(tr("Filter Building/Components"));
translate(txt);
m_widget->retranslate();
m_uiRequirements->retranslate();
}
bool BuildingComponentFilterDialog::apply()
{
m_widget->apply();
return m_requestHelper->startSingleRequest([this]()
{
const BuildingComponentFilter filterData = m_widget->filter()->bldCmpSettingsToData();
return m_fltFtc->buildingComponentFilterUpdateRequest(filterData, this);
});
}
void BuildingComponentFilterDialog::dialogCanceled()
{
m_widget->dialogCanceled();
}
void BuildingComponentFilterDialog::onBuildingComponentFilterUpdateReply(const Core::FunctionReplyObject &replyObject)
{
m_requestHelper->requestReply(replyObject);
}
void BuildingComponentFilterDialog::onUnknownChangesRecognized()
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " START";
m_widget->updateGuiToFilter();
// the data can be changed if another replay is selected or filter are loaded.
// So our widget has to be updated:
__unchange__();
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void BuildingComponentFilterDialog::onLoadButtonClicked()
{
FilterChangeDialog *dialog = new FilterChangeDialog(this);
if (!dialog->init(m_session, SymbolAppearanceSettings::Part::All, false, true, false))
{
delete dialog;
return;
}
dialog->setAttribute(Qt::WA_DeleteOnClose);
QObject::connect(dialog, &FilterChangeDialog::rejected, dialog, &FilterChangeDialog::deleteLater);
dialog->show();
}
} // namespace FilterManagement
@@ -0,0 +1,54 @@
/**
* @RDE_HEADER@
* FilterManagement - Aes Filter Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#pragma once
#include "flt_building_component_settings_widget.h"
#include <LtsWidgets/lts_dialog.h>
#include <LtsUtilsGuiDds/request_helper.h>
#include <FilterManagement/logger.h>
#include <LtsSession/lts_session.h>
#include <Plugins/FilterManagement/flt_data_plugin_interface.h>
#include <Plugins/FilterManagement/flt_building_cmpnt_plugin_interface.h>
namespace FilterManagement
{
class DataInterface;
// --------------------------------------------------------
// BuildingComponentFilterDialog
// --------------------------------------------------------
class BuildingComponentFilterDialog final : public LtsWidgets::LtsDialog
, private FilterManagement::Interface::Ftc::BuildingComponentFilterUpdateReplyHandler
{
Q_OBJECT
public:
explicit BuildingComponentFilterDialog(QWidget *parent = nullptr);
~BuildingComponentFilterDialog();
bool init(LtsSession::LtsSession *session);
void retranslate() override;
private:
bool apply() override;
void dialogCanceled() override;
void onBuildingComponentFilterUpdateReply(const Core::FunctionReplyObject &replyObject) override;
void onUnknownChangesRecognized();
void onLoadButtonClicked();
private:
BuildingComponentSettingsWidget *m_widget{nullptr};
LtsUtils::RequestHelper *m_requestHelper{nullptr};
LtsSession::LtsSession *m_session{nullptr};
std::shared_ptr<FilterManagement::ForeignFltBuildingComponentGuiInterface> m_fltIfc;
std::shared_ptr<FilterManagement::Interface::Ftc> m_fltFtc;
NGL::INGLLogger &m_logger;
};
}
@@ -0,0 +1,412 @@
/**
* @RDE_HEADER@
* FilterManagement - Aes Filter Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#include "flt_building_component_settings_widget.h"
#include "ui_flt_building_component_settings_widget.h"
#include <ParticipantManagement/ppm.hpp>
#include <ParticipantManagement/ppm_translation.h>
#include <QJsonDocument>
#include <QJsonObject>
#include <QMenu>
#include <LtsWidgets/lts_dialog.h>
#include <LtsUtilsSettings/settings.h>
#include <Plugins/InfrastructureManagement/ism_data_plugin_interface.h>
namespace FilterManagement
{
//----------------------------------------------------------------------------
const char FloorIdProperty[] = "floorId";
//----------------------------------------------------------------------------
class BoolLocker
{
public:
explicit BoolLocker(bool &b)
: m_b(b)
{
m_b = true;
}
~BoolLocker()
{
m_b = false;
}
private:
bool &m_b;
};
BuildingComponentSettingsWidget::BuildingComponentSettingsWidget(QWidget *parent)
: QWidget(parent)
, m_bIgnoreUiSignals(false)
, m_ui(new Ui::BuildingComponentSettingsWidget)
, m_doUpdateViaCallback(true)
, m_logger(getLogger("BuildingComponentSettingsWidget"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_ui->setupUi(this);
// Today following should be hidden bc not useful for any project:
m_ui->lblComponent_BuildingControlUnit->hide();
m_ui->cbshowBuildingControlUnit->hide();
m_ui->lblComponent_VirtualIPS->hide();
m_ui->cbshowVirtualIPS->hide();
m_ui->lblComponent_MeteoDataUnit->hide();
m_ui->cbshowMeteoDataUnit->hide();
#ifdef GUEZ_MODE
// SWPÄ 2/22 - Hannes: BuildingNetworkSwitch werden ignoriert: GUEZE-1548
m_ui->cbshowBuildingNetworkSwitch->hide();
m_ui->lblComponent_BuildingNetworkSwitch->hide();
m_ui->cbshowAnnouncementUnit->hide();
m_ui->lblComponent_AnnouncementUnit->hide();
m_ui->cbshowOutdoorControlUnit->hide();
m_ui->lblComponent_OutdoorControlUnit->hide();
// : Today following should be hidden bc not useful for any project
#endif
m_checkBoxesComponents = findChildren<QCheckBox*>();
// for every component CheckBox
for (QCheckBox* cb : qAsConst(m_checkBoxesComponents))
{
// evaluate every component QCheckBox immediatly:
connect(cb , &QCheckBox::clicked, this, &BuildingComponentSettingsWidget::readUpdateFilterFromUi);
TRACE_LOG(m_logger) << LOGFUNCTION << " STARTXXXX";
// enable ContextMenu - if (cb->isVisible()) does not work since whole gui is not visible yet:
cb->setContextMenuPolicy(Qt::CustomContextMenu);
connect(cb, &QCheckBox::customContextMenuRequested, this, &BuildingComponentSettingsWidget::onContextMenuComponentRequested);
} // for
// for every component Label
// use findChildren from widget, from gridLayout will not work
const QList<QLabel*> labelComponents = findChildren<QLabel*>();
for (QLabel* lbl : qAsConst(labelComponents))
{
// hopefully better maintainance:
if (lbl->objectName().startsWith(QStringLiteral("lblComponent_")))
{
lbl->setContextMenuPolicy(Qt::CustomContextMenu);
connect(lbl, &QLabel::customContextMenuRequested, this, &BuildingComponentSettingsWidget::onContextMenuComponentRequested);
}
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END, m_checkBoxesComponents.size = " << m_checkBoxesComponents.size()
<< ", labelComponents.size()=" << labelComponents.size();
}
BuildingComponentSettingsWidget::~BuildingComponentSettingsWidget()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (m_buildingComponentSettings)
m_buildingComponentSettings->removeChangedCallback(this);
delete m_ui;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
bool BuildingComponentSettingsWidget::init(const std::shared_ptr<BuildingComponentSettings> &filter,
const std::shared_ptr<InfrastructureManagement::Interface::Dtc> ismDtc)
{
if (!ismDtc)
{
WARNING_LOG(m_logger) << "Can not get Foreign data interface for InfrastructureManagement";
return false;
}
m_buildingComponentSettings = filter;
m_originalBldCmp = m_buildingComponentSettings->bldCmpSettings();
// FloorIds :
// build floorIds via MainStructureElements and those StructureElements:
QSet<int> floorIds;
if (ismDtc)
{
const QMap<int, InfrastructureManagement::MainStructureElement> &mses = ismDtc->mainStructureElements();
for (const InfrastructureManagement::MainStructureElement &mse : mses)
{
// only buildings
if (mse.structureElementTypeId() != InfrastructureManagement::StructureElementType::Building)
continue;
for (const InfrastructureManagement::StructureElement &currentElement : mse.elements())
{
if (currentElement.structureElementTypeId() != InfrastructureManagement::StructureElementType::Floor)
continue;
// just floors now:
int floorInt = QString::fromStdString(currentElement.name()).split(QStringLiteral("_")).value(1, QStringLiteral("-10")).toInt();
floorIds += floorInt;
} //
} // for
}
QVector<int> floorIdsVec = floorIds.values().toVector();
floorIdsVec.append(-10); // -10 -> Outdoor/Exterior
std::sort(floorIdsVec.begin(), floorIdsVec.end());
// : FloorIds
setupFloorUi(floorIdsVec);
setBuildingComponentSettings();
TRACE_LOG(m_logger) << LOGFUNCTION << " isChangedCallbackRegistered 1 =" << m_buildingComponentSettings->isChangedCallbackRegistered(this);
m_buildingComponentSettings->addChangedCallback(this); // callback: onBuildingComponentSettingsChanged
TRACE_LOG(m_logger) << LOGFUNCTION << " isChangedCallbackRegistered 2 =" << m_buildingComponentSettings->isChangedCallbackRegistered(this);
return true;
}
void BuildingComponentSettingsWidget::retranslate()
{
BoolLocker l(m_bIgnoreUiSignals);
m_ui->retranslateUi(this);
}
void BuildingComponentSettingsWidget::setBuildingComponentSettings()
{
BoolLocker l(m_bIgnoreUiSignals);
const BuildingComponentSettings::BldCmpSettings &settingsRef = m_buildingComponentSettings->bldCmpSettings();
// BuildingSettings
const BuildingComponentSettings::BldCmpSettings::BuildingSettings &bldg = settingsRef.buildingSettings;
const QSet<int> &hiddenFloorIdsRef = bldg.hiddenFloorIds;
for (QCheckBox *cb : qAsConst(m_checkBoxesFloors))
{
int floor = cb->property(FloorIdProperty).toInt();
cb->setChecked(!hiddenFloorIdsRef.contains(floor));
}
// ComponentSettings
const BuildingComponentSettings::BldCmpSettings::ComponentSettings &comp = settingsRef.componentSettings;
m_ui->cbshowAnnouncementUnit->setChecked(comp.showAnnouncementUnit);
m_ui->cbshowBuildingControlUnit->setChecked(comp.showBuildingControlUnit);
m_ui->cbshowBuildingNetworkSwitch->setChecked(comp.showBuildingNetworkSwitch);
m_ui->cbshowBuildingSensorModule->setChecked(comp.showBuildingSensorModule);
m_ui->cbshowEffectGenerationControlUnit->setChecked(comp.showEffectGenerationControlUnit);
m_ui->cbshowIndoorCamera->setChecked(comp.showIndoorCamera);
m_ui->cbshowMeteoDataUnit->setChecked(comp.showMeteoDataUnit);
m_ui->cbshowOutdoorCamera->setChecked(comp.showOutdoorCamera);
m_ui->cbshowOutdoorControlUnit->setChecked(comp.showOutdoorControlUnit);
m_ui->cbshowVirtualIPS->setChecked(comp.showVirtualIPS);
// In und Out werden zusammengefasst (GUEZE-1478)
// m_ui->cbshowIndoorIPS->setChecked(comp.showIndoorIPS);
// m_ui->cbshowOutdoorIPS->setChecked(comp.showOutdoorIPS);
m_ui->cbshowIPS->setChecked(comp.showIndoorIPS);
}
BuildingComponentSettings::BldCmpSettings BuildingComponentSettingsWidget::getCurrentUiSettings() const
{
BuildingComponentSettings::BldCmpSettings settings = m_buildingComponentSettings->bldCmpSettings();
// BldCmpSettings
BuildingComponentSettings::BldCmpSettings::BuildingSettings &bldg = settings.buildingSettings;
QSet<int> hiddenFloorIdsTemp;
for (QCheckBox *cb : m_checkBoxesFloors)
{
if (!cb->isChecked())
{
int floor = cb->property(FloorIdProperty).toInt();
hiddenFloorIdsTemp.insert(floor);
}
}
bldg.hiddenFloorIds = hiddenFloorIdsTemp;
// ComponentSettings
BuildingComponentSettings::BldCmpSettings::ComponentSettings &comp = settings.componentSettings;
comp.showAnnouncementUnit = m_ui->cbshowAnnouncementUnit->isChecked();
comp.showBuildingControlUnit = m_ui->cbshowBuildingControlUnit->isChecked();
comp.showBuildingNetworkSwitch = m_ui->cbshowBuildingNetworkSwitch->isChecked();
comp.showBuildingSensorModule = m_ui->cbshowBuildingSensorModule->isChecked();
comp.showEffectGenerationControlUnit = m_ui->cbshowEffectGenerationControlUnit->isChecked();
comp.showIndoorCamera = m_ui->cbshowIndoorCamera->isChecked();
comp.showMeteoDataUnit = m_ui->cbshowMeteoDataUnit->isChecked();
comp.showOutdoorCamera = m_ui->cbshowOutdoorCamera->isChecked();
comp.showOutdoorControlUnit = m_ui->cbshowOutdoorControlUnit->isChecked();
comp.showVirtualIPS = m_ui->cbshowVirtualIPS->isChecked();
// In und Out werden zusammengefasst (GUEZE-1478)
comp.showIndoorIPS = m_ui->cbshowIPS->isChecked();
comp.showOutdoorIPS = m_ui->cbshowIPS->isChecked();
return settings;
}
void BuildingComponentSettingsWidget::onBuildingComponentSettingsChanged()
{
// callback from m_buildingComponentSettings / BuildingComponentSettings
DEBUG_LOG(m_logger) << LOGFUNCTION << " START, m_doUpdateViaCallback=" << m_doUpdateViaCallback;
if (m_doUpdateViaCallback)
{
updateGuiToFilter();
emit unknownChangesRecognized();
}
DEBUG_LOG(m_logger) << LOGFUNCTION << " END, m_doUpdateViaCallback=" << m_doUpdateViaCallback;
}
void BuildingComponentSettingsWidget::updateGuiToFilter()
{
this->onDataChanged(m_buildingComponentSettings);
}
void BuildingComponentSettingsWidget::readUpdateFilterFromUi()
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " START";
if (!m_buildingComponentSettings || m_bIgnoreUiSignals)
return;
m_doUpdateViaCallback = false;
const BuildingComponentSettings::BldCmpSettings &settings = getCurrentUiSettings();
m_buildingComponentSettings->setBldCmpSettings(settings);
m_doUpdateViaCallback = true;
}
void BuildingComponentSettingsWidget::onContextMenuFloorRequested(const QPoint &position)
{
QWidget *widget = qobject_cast<QWidget *>(sender());
if (!widget)
return;
QMenu menu(widget);
menu.addAction(tr("Select All"), this, &BuildingComponentSettingsWidget::onFloorSelectAll);
menu.addAction(tr("Unselect All"), this, &BuildingComponentSettingsWidget::onFloorUnselectAll);
menu.exec(widget->mapToGlobal(position));
}
void BuildingComponentSettingsWidget::onContextMenuComponentRequested(const QPoint &position)
{
QWidget *widget = qobject_cast<QWidget *>(sender());
if (!widget)
return;
QMenu menu(widget);
menu.addAction(tr("Select All"), this, &BuildingComponentSettingsWidget::onComponentSelectAll);
menu.addAction(tr("Unselect All"), this, &BuildingComponentSettingsWidget::onComponentUnselectAll);
menu.exec(widget->mapToGlobal(position));
}
void BuildingComponentSettingsWidget::onFloorSelectAll()
{
onFloorSelection(true);
}
void BuildingComponentSettingsWidget::onFloorUnselectAll()
{
onFloorSelection(false);
}
void BuildingComponentSettingsWidget::onFloorSelection(bool onOff)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " START, m_checkBoxesFloors.size()=" << m_checkBoxesFloors.size();
for (QCheckBox *cb : qAsConst(m_checkBoxesFloors))
{
if (cb->isVisible())
cb->setChecked(onOff); // signal 'QCheckBox::clicked' will NOT be emitted...
} // for
// ... call once:
readUpdateFilterFromUi();
}
void BuildingComponentSettingsWidget::onComponentSelectAll()
{
onComponentSelection(true);
}
void BuildingComponentSettingsWidget::onComponentUnselectAll()
{
onComponentSelection(false);
}
void BuildingComponentSettingsWidget::onComponentSelection(bool onOff)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " START, m_checkBoxesComponents.size()=" << m_checkBoxesComponents.size();
// evaluate every QCheckBox immediatly:
for (QCheckBox* cb : qAsConst(m_checkBoxesComponents))
{
if (cb->isVisible())
{
cb->setChecked(onOff); // signal 'QCheckBox::clicked' will NOT be emitted...
}
} // for
// ... call once:
readUpdateFilterFromUi();
}
bool BuildingComponentSettingsWidget::setupFloorUi(const QVector<int> &floorIds)
{
if (!m_ui)
return false;
m_checkBoxesFloors.clear();
int row = floorIds.size();
for (auto floorId : floorIds)
{
QLabel *lbl = new QLabel(this);
QCheckBox *cb = new QCheckBox(this);
if (floorId == -10)
lbl->setText(tr("Exterior:"));
else
lbl->setText(tr("Floor") + QString(QStringLiteral(" %1:")).arg(floorId));
cb->setObjectName(lbl->text());
cb->setProperty(FloorIdProperty, floorId);
connect(cb , &QCheckBox::clicked, this, &BuildingComponentSettingsWidget::readUpdateFilterFromUi);
{
lbl->setContextMenuPolicy(Qt::CustomContextMenu);
connect(lbl, &QLabel::customContextMenuRequested, this, &BuildingComponentSettingsWidget::onContextMenuFloorRequested);
cb->setContextMenuPolicy(Qt::CustomContextMenu);
connect(cb, &QCheckBox::customContextMenuRequested, this, &BuildingComponentSettingsWidget::onContextMenuFloorRequested);
}
m_checkBoxesFloors.append(cb);
m_ui->gridLayoutFloor->addWidget(lbl, row, 0);
m_ui->gridLayoutFloor->addWidget(cb, row, 1);
--row;
} // for
return true;
}
void BuildingComponentSettingsWidget::apply()
{
readUpdateFilterFromUi();
}
void BuildingComponentSettingsWidget::dialogCanceled()
{
m_buildingComponentSettings->setBldCmpSettings(m_originalBldCmp);
}
void BuildingComponentSettingsWidget::onDataChanged(const std::shared_ptr<BuildingComponentSettings> &newFilter)
{
m_buildingComponentSettings = newFilter;
m_originalBldCmp = newFilter->bldCmpSettings();
DEBUG_LOG(m_logger) << "onDataChanged ... " << QJsonDocument(newFilter->bldCmpSettingsToJson()).toJson();
setBuildingComponentSettings();
}
} // namespace FilterManagement
@@ -0,0 +1,95 @@
/**
* @RDE_HEADER@
* FilterManagement - Participant Symbol Appearance Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#pragma once
#include <FilterManagement/logger.h>
#include <FilterManagement/flt_building_cmpnt_plugin_interface.h>
#include <FilterManagement/flt_building_cmpnt_settings.h>
#include <QWidget>
#include <QVector>
#include <QCheckBox>
class QComboBox;
class QTimer;
namespace InfrastructureManagement
{
namespace Interface
{
class Dtc;
}
}
namespace Ui
{
class BuildingComponentSettingsWidget;
}
namespace FilterManagement
{
class DataInterface;
// --------------------------------------------------------
//
// --------------------------------------------------------
class BuildingComponentSettingsWidget final : public QWidget, public BuildingComponentSettings::SettingsChangedCallback
{
Q_OBJECT
public:
explicit BuildingComponentSettingsWidget(QWidget *parent = nullptr);
~BuildingComponentSettingsWidget();
void retranslate();
bool init(const std::shared_ptr<BuildingComponentSettings> &filter, const std::shared_ptr<InfrastructureManagement::Interface::Dtc> ismDtc);
void apply();
void dialogCanceled();
std::shared_ptr<BuildingComponentSettings> filter() const { return m_buildingComponentSettings; }
void onDataChanged(const std::shared_ptr<BuildingComponentSettings> &newFilter);
BuildingComponentSettings::BldCmpSettings getCurrentUiSettings() const;
void onBuildingComponentSettingsChanged(); // callback function
void updateGuiToFilter();
signals:
void changesMade();
void unknownChangesRecognized();
private slots:
void readUpdateFilterFromUi();
void onContextMenuFloorRequested(const QPoint &position);
void onContextMenuComponentRequested(const QPoint &position);
void onFloorSelectAll();
void onFloorUnselectAll();
void onFloorSelection(bool onOff);
void onComponentSelectAll();
void onComponentUnselectAll();
void onComponentSelection(bool onOff);
private:
bool setupFloorUi(const QVector<int> &floorIds);
void setBuildingComponentSettings();
private:
QList<QCheckBox*> m_checkBoxesComponents;
QList<QCheckBox*> m_checkBoxesFloors;
std::shared_ptr<BuildingComponentSettings> m_buildingComponentSettings;
BuildingComponentSettings::BldCmpSettings m_originalBldCmp;
bool m_bIgnoreUiSignals;
Ui::BuildingComponentSettingsWidget *m_ui;
bool m_doUpdateViaCallback;
NGL::INGLLogger &m_logger;
};
}
@@ -0,0 +1,232 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>BuildingComponentSettingsWidget</class>
<widget class="QWidget" name="BuildingComponentSettingsWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>792</width>
<height>370</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Building Component Settings</string>
</property>
<layout class="QGridLayout" name="gridLayout_6">
<item row="0" column="0" rowspan="2">
<layout class="QGridLayout" name="gridLayout_3">
<item row="1" column="0">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>185</width>
<height>148</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayoutFloor"/>
</item>
</layout>
</item>
<item row="0" column="1" rowspan="2">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item row="0" column="2">
<layout class="QGridLayout" name="gridLayoutComponents">
<item row="10" column="1">
<widget class="QCheckBox" name="cbshowBuildingNetworkSwitch">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="cbshowBuildingSensorModule">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QCheckBox" name="cbshowIPS">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QCheckBox" name="cbshowOutdoorCamera">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="lblComponent_MeteoDataUnit">
<property name="text">
<string>showMeteoDataUnit:</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QCheckBox" name="cbshowAnnouncementUnit">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="lblComponent_OutdoorCamera">
<property name="text">
<string>showOutdoorCamera:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="lblComponent_BuildingControlUnit">
<property name="text">
<string>showBuildingControlUnit:</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="lblComponent_VirtualIPS">
<property name="text">
<string>showVirtualIPS:</string>
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QLabel" name="lblComponent_BuildingNetworkSwitch">
<property name="text">
<string>showBuildingNetworkSwitch:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="cbshowOutdoorControlUnit">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="lblComponent_AnnouncementUnit">
<property name="text">
<string>showAnnouncementUnit:</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QCheckBox" name="cbshowIndoorCamera">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="lblComponent_BuildingSensorModule">
<property name="text">
<string>showBuildingSensorModule:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="cbshowBuildingControlUnit">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="lblComponent_OutdoorControlUnit">
<property name="text">
<string>showOutdoorControlUnit:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QCheckBox" name="cbshowVirtualIPS">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="cbshowEffectGenerationControlUnit">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="lblComponent_EffectGenerationControlUnit">
<property name="text">
<string>showEffectGenerationControlUnit:</string>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QCheckBox" name="cbshowMeteoDataUnit">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="lblComponent_IPS">
<property name="text">
<string>showIPS:</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="lblComponent_IndoorCamera">
<property name="text">
<string>showIndoorCamera:</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="3">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>356</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>41</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,176 @@
/**
* @RDE_HEADER@
* Gui Plugin for FilterManagement (Participant)
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#include "flt_building_components_gui_plugin.h"
#include "flt_building_component_filter_dialog.h"
#include <Plugins/FilterManagement/Gui/Aes/Common/building_cmpnt_settings_impl.h>
#include <LtsSession/lts_session.h>
#include <LtsUtilsSettings/settings.h>
#include <LtsProjectionWorkstation/lts_projection_workstation.h>
#include <FilterManagement/flt_operator_rights.h>
namespace FilterManagement
{
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.Interface"))
, m_logger(getLogger("BuildingComponentInterfaceImpl"))
{}
bool InterfaceImpl::fetchInterfaces()
{
if (!m_session->getDtc<FilterManagement::DataInterface>(m_fltDtc))
return false;
connect(m_fltDtc.get(), &FilterManagement::Interface::Dtc::buildingComponentFilterChanged,
this, &InterfaceImpl::onBuildingComponentFilterChanged, Qt::UniqueConnection);
// NLDEVCTRL-445: Projektion Filter und Kartenausschnitt
// filterPresetLoadUnsaved at PWS leads to race condition
// (create dtc and update data via request)
// enable AesFilter and SymbolAppearance already here
// 22.01.2025, Thoden: Nachtrag zu NLDEVCTRL-445: Projektion Filter und Kartenausschnitt
// GUEZE-3459: Hannas OPW: Hänger beim Login
// 1. waitForHistoricalData{SymbolAppearance|AesFilter|buildingComponentFilters}
// gehört eingentlich VOR fltDtc->{SymbolAppearance|AesFilter|buildingComponentFilters}
// 2. Da diese aber auf der PWS wohl wichtig waren, wird fetchInterfaces jeweils
// angepasst:
// waitForHistoricalData{SymbolAppearance|AesFilter|buildingComponentFilters} wird
// nicht mehr grundsätzlich, sondern nur auf der PWS ausgeführt:
// if (LtsProjectionWorkstation::LtsProjectionWorkstation::hasInstance())
// m_fltDtc->waitForHistoricalDataXXX(1000);
if (LtsProjectionWorkstation::LtsProjectionWorkstation::hasInstance())
m_fltDtc->waitForHistoricalDataBuildingComponentFilter(1000); // wait... contains enable
return true;
}
QVector<LtsWidgets::PluginData> InterfaceImpl::getActions()
{
QVector<LtsWidgets::PluginData> ret;
LtsWidgets::PluginData plData;
// this plugin 'flt.building_cmpnt' has to be add to apps.json to get 'getActions' be executed.
// But the filterFlaf "BuildingName" is also in the SymbolAppearance.
// To ensure not to show both, use ProjectSettings: 'enableBuildingComponentFilterEdit'
LtsUtils::ProjectSettings *ps = LtsUtils::ProjectSettings::getInstance();
const bool enableBuildingComponentFilterEdit = ps->value(QStringLiteral("flt"),
QStringLiteral("enableBuildingComponentFilterEdit"), false).toBool();
if (enableBuildingComponentFilterEdit)
{
plData.menuGroup = menuGroup();
plData.menuText = tr("Building/Components");
plData.identifier = QLatin1String("fltBuildingComponentFilter");
plData.menuIcon = QIcon(QLatin1String("icon:filter_map_settings.svg")); // ToDo: passendes Icon erstellen
plData.operatorRight = OperatorRights::FilterManagement::SymbolAppearanceEdit;
plData.exercisePart = LtsWidgets::ExercisePart::eSpecial;
plData.createWidgetFunc = [this](QWidget * parent)
{
return LtsWidgets::initDialog(new BuildingComponentFilterDialog(parent), m_session);
};
ret.append(plData);
}
return ret;
}
void InterfaceImpl::onBuildingComponentFilterChanged(const FilterManagement::BuildingComponentFilter &data, DataModification mod)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
auto it = m_buildingComponentFilterMap.find(FilterKey{data.operatorId(), data.ctx()});
if (it != m_buildingComponentFilterMap.end())
{
std::shared_ptr<BuildingComponentSettingsImpl> ret = it->second.lock();
if (ret && mod != DataModification::eRemoved)
ret->setBldCmpSettingsFromData(data);
else
{
// Maybe the scvFilterManagement (hosted at svcExerciseEventManagement)
// is restarted. In that case the topics are removed from DDS.
// But when the svc is starting again, the data is inserted into this
// map again - but the callbacks are lost!! So some related dialog do
// not work anymore... :-(
// To avoid this, prevent 'used' SymbolAppearanceSettingsImpl from
// being removed:
if (!(ret && ret->hasChangedCallbacks()))
m_buildingComponentFilterMap.erase(it);
}
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
std::shared_ptr<BuildingComponentSettings> InterfaceImpl::buildingComponentSettingsForOperator(int operatorId, const QString &context)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< ", operatorId=" << operatorId
<< ", context=" << context;
std::shared_ptr<BuildingComponentSettingsImpl> ret;
auto it = m_buildingComponentFilterMap.find({operatorId, context.toStdString()});
if (it != m_buildingComponentFilterMap.end())
ret = it->second.lock();
if (!ret)
{
FilterManagement::BuildingComponentFilter filterData;
// it's 0 when there is not yet a filter for this operator, so set it here and use it for comparision
filterData.operatorId(operatorId);
filterData.ctx(context.toStdString());
std::function<bool(const FilterManagement::BuildingComponentFilter &)> func = [&filterData](const FilterManagement::BuildingComponentFilter &f)
{
if (f.operatorId() == filterData.operatorId() &&
f.ctx() == filterData.ctx())
{
filterData = f;
return true;
}
return false;
};
// 22.01.2025, Thoden: Nachtrag zu NLDEVCTRL-445: Projektion Filter und Kartenausschnitt
// GUEZE-3459: Hannas OPW: Hänger beim Login
// 1. waitForHistoricalData{SymbolAppearance|AesFilter|buildingComponentFilters}
// gehört eingentlich VOR fltDtc->{SymbolAppearance|AesFilter|buildingComponentFilters}
// 2. Da diese aber auf der PWS wohl wichtig waren, wird fetchInterfaces jeweils
// angepasst:
// waitForHistoricalData{SymbolAppearance|AesFilter|buildingComponentFilters} wird
// nicht mehr grundsätzlich, sondern nur auf der PWS ausgeführt:
// if (LtsProjectionWorkstation::LtsProjectionWorkstation::hasInstance())
// m_fltDtc->waitForHistoricalDataXXX(1000);
m_fltDtc->waitForHistoricalDataBuildingComponentFilter(1000); // wait... contains enable
m_fltDtc->buildingComponentFilters(func);
ret = std::make_shared<BuildingComponentSettingsImpl>(m_session->workspaceId());
ret->setBldCmpSettingsFromData(filterData);
m_buildingComponentFilterMap[FilterKey(operatorId, context.toStdString())] = ret;
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< ", operatorId=" << operatorId
<< ", context=" << context;
return ret;
}
} //namespace FilterManagement
@@ -0,0 +1,87 @@
/**
* @RDE_HEADER@
* Gui Plugin for FilterManagement (Participant)
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#pragma once
#include <PluginInterfaces/gui_plugin_interface.h>
#include <Plugins/FilterManagement/flt_building_cmpnt_plugin_interface.h>
#include <Plugins/FilterManagement/flt_data_plugin_interface.h>
namespace FilterManagement
{
class BuildingComponentSettingsImpl;
class GuiPlugin final : public QObject, public GuiPluginBase::Plugin
{
Q_PLUGIN_METADATA(IID "gui:3:flt.building_cmpnt")
Q_INTERFACES(GuiPluginBase::Plugin)
Q_OBJECT
public:
GuiPlugin() = default;
~GuiPlugin() = default;
QString pluginName() override { return QLatin1String("FilterManagementBuildingComponentGuiPlugin"); }
std::shared_ptr<GuiPluginBase::Interface> createGuiInterface(LtsSession::LtsSession *session) override;
bool availableInPartition(IDL::PartitionType partition) const override
{
// GUEZE-1769: Schnappschuss und ABT: Entfernen Filter für Etagen / Komponenten
// Nachtrag zu r 59394 (branch 23_1_guez_bugfixing)
// Wenn das Plugin flt.building_cmpnt nur in Global geladen wird (ResourceApp),
// dann muss es im plugin_provider_lts_session.cpp optional sein.
return (partition == IDL::PartitionType::Global);
}
};
// ...
class InterfaceImpl final : public QObject, public ForeignFltBuildingComponentGuiInterface, public GuiPluginBase::Interface
{
Q_OBJECT
public:
explicit InterfaceImpl(LtsSession::LtsSession *session);
bool fetchInterfaces() override;
QString menuGroup() const override { return tr("Situation Map"); }
QVector<LtsWidgets::PluginData> getActions() override;
std::shared_ptr<BuildingComponentSettings> buildingComponentSettingsForOperator(int operatorId, const QString &context) override;
private slots:
void onBuildingComponentFilterChanged(const BuildingComponentFilter &data, DataModification mod);
private:
// <operatorId, filter>
struct FilterKey
{
int operatorId = 0;
std::string context;
FilterKey() = default;
FilterKey(int _operatorId, const std::string &_context)
: operatorId(_operatorId)
, context(_context)
{}
bool operator<(const FilterKey &o) const
{
if (operatorId != o.operatorId)
return operatorId < o.operatorId;
return context < o.context;
}
};
std::map<FilterKey, std::weak_ptr<BuildingComponentSettingsImpl>> m_buildingComponentFilterMap;
std::shared_ptr<FilterManagement::Interface::Dtc> m_fltDtc;
NGL::INGLLogger &m_logger;
};
} // namespace FilterManagement
@@ -0,0 +1,42 @@
#
# $Id$
# $HeadURL$
# $Author$
#
# Created by Norbert Thoden, NLE, 2019-02-25
#
SET(flt_filter_change_SRCS
flt_filter_change.cpp
flt_filter_change.h
)
NGL_WRAP_UI(flt_filter_change_SRCS
flt_filter_change.ui
)
NGL_ADD_LIBRARY2(WS FltFilterChange SHARED ${flt_filter_change_SRCS})
NGL_TARGET_INCLUDE_DIRECTORIES(FltFilterChange
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../
${CMAKE_CURRENT_BINARY_DIR}/../
)
NGL_TARGET_LINK_LIBRARIES(FltFilterChange
PRIVATE
LtsSession
LtsSessionData
LtsUtilsGuiDds # requestHelper
FltAesGuiCommon
LtsMultiMonitor
LtsUtilsSettings
PUBLIC
LtsWidgets
FltDataPluginInterface
FltAesGuiPluginInterface
FltBldgCmpntGuiPluginInterface
OpmGuiPluginInterface
Qt5::Core
Qt5::Widgets
)
NGL_INSTALL_TARGET(FltFilterChange)
@@ -0,0 +1,586 @@
/**
* @RDE_HEADER@
* FilterManagement - Select filter settings from other operator
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna Rathje, SLSE, 2017-11-20
*/
#include "flt_filter_change.h"
#include "ui_flt_filter_change.h"
#include <LtsSession/lts_session_data.h>
#include <LtsSession/lts_session.h>
#include <LtsMultiMonitor/lts_multi_monitor.h>
#include <LtsMultiMonitor/lts_screen_base.h>
#include <LtsMultiMonitor/lts_screen_normal.h>
#include <LtsMultiMonitor/lts_screen_wide.h>
#include <LtsUtilsSettings/settings.h>
#include <Plugins/FilterManagement/flt_data_plugin_aes_display_filter.h>
#include <Plugins/SituationMapPlugin/situation_map_gui_plugin_interface.h>
#include <Plugins/FilterManagement/Gui/Aes/Common/symbol_appearance_settings_impl.h>
namespace FilterManagement
{
FilterChangeDialog::FilterChangeDialog(QWidget *parent)
: LtsWidgets::LtsFramelessDialog(parent, LtsWidgets::Behaviour::Modal)
, m_session(nullptr)
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_ui(new Ui::FilterChangeDialog)
, m_logger(getLogger("FilterChangeDialog"))
{
m_ui->setupUi(this);
connect(m_ui->buttonBox->getButton(LtsWidgets::DialogButton::Ok), &QPushButton::clicked, this, &FilterChangeDialog::apply);
connect(m_ui->buttonBox->getButton(LtsWidgets::DialogButton::Close), &QPushButton::clicked, this, &FilterChangeDialog::close);
// Since FilterChange is only available for App:Situation
// and within this app, BuildingComponentFilter gui ist not added to accordeonMenue,
// suppress in any case:
// LtsUtils::ProjectSettings *ps = LtsUtils::ProjectSettings::getInstance();
// const bool enableBuildingComponentFilterEdit = ps->value(QStringLiteral("flt"),
// QStringLiteral("enableBuildingComponentFilterEdit"), false).toBool();
// m_ui->line_overBuildingComponentFilter->setVisible(enableBuildingComponentFilterEdit);
// m_ui->cbBuildingComponentFilter->setVisible(enableBuildingComponentFilterEdit);
m_ui->line_overBuildingComponentFilter->hide();
m_ui->cbBuildingComponentFilter->hide();
// GUEZE-1586: Guez hat derzeit per Definition keine ScreenContainer (WideScreenMonitore)
if (strcmp(PROJECTBUILD, "guez") == 0)
{
#ifndef DEBUGGING
m_ui->label_ScreenContainer->hide();
m_ui->cbxScreenContainer->hide();
#endif
}
}
FilterChangeDialog::~FilterChangeDialog()
{
delete m_ui;
}
bool FilterChangeDialog::init(LtsSession::LtsSession *session,
SymbolAppearanceSettings::Part preSelectSymbolAppearanceSettings,
bool preSelectAesFilter,
bool preSelectBuildingComponentSettings,
bool preSelectOperatorMapSettings)
{
m_session = session;
if (!m_session)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no session";
return false;
}
{
int myOperatorId = LtsSessionData::LtsSessionData::getInstance()->getOperatorId();
int myScreenId = m_session->screenId();
DEBUG_LOG(m_logger) << LOGFUNCTION << " my operatorId=" << myOperatorId << " my screenId=" << myScreenId;
}
if (!m_session->getForeignGuiInterface(m_fltParticipantGuiIfc))
{
WARNING_LOG(m_logger) << "Can not get Foreign gui interface for FilterManagement/Participant";
return false;
}
if (!m_session->getForeignGuiInterface(m_fltAesIfc))
{
WARNING_LOG(m_logger) << "Can not get Foreign gui interface for FilterManagement/AES";
return false;
}
if (!m_session->getForeignGuiInterface(m_fltBuildingComponentIfc))
{
WARNING_LOG(m_logger) << "Can not get Foreign gui interface for FilterManagement/BuildingComponent";
// return false; // since GUEZE-1769: it´s optional
}
if (!m_session->getForeignGuiInterface<OperatorManagement::ForeignGuiComboboxInterface>(m_opmCbxDtc))
{
DEBUG_LOG(m_logger) << "getForeignGuiInterface for OperatorManagement failed.";
return false;
}
if (!m_session->getFtc<FilterManagement::DataInterface>(m_fltFtc))
{
DEBUG_LOG(m_logger) << "getFtc for FilterManagement failed.";
return false;
}
if (!m_session->getDtc<FilterManagement::DataInterface>(m_fltDtc))
{
DEBUG_LOG(m_logger) << "getDtc for FilterManagement failed.";
return false;
}
m_fltDtc->enableFilterData();
connect(m_fltDtc.get(), &FilterManagement::Interface::Dtc::filterDataChanged,
this, &FilterChangeDialog::onFilterDataChanged, Qt::UniqueConnection);
// PreSelection:
switch (preSelectSymbolAppearanceSettings)
{
case SymbolAppearanceSettings::Part::Symbol:
m_ui->cbSymbolappear->setChecked(true);
break;
case SymbolAppearanceSettings::Part::Types:
m_ui->cbTypeFilter->setChecked(true);
break;
case SymbolAppearanceSettings::Part::CollapseExpand:
m_ui->cbCollapseExpand->setChecked(true);
break;
case SymbolAppearanceSettings::Part::All:
// All is used as 'nothing'
break;
} // switch
m_ui->cbAesFilter->setChecked(preSelectAesFilter);
m_ui->cbBuildingComponentFilter->setChecked(preSelectBuildingComponentSettings);
m_ui->cbOperatorMapSettings->setChecked(preSelectOperatorMapSettings);
// Operator:
// focus on LtsAppDescriptor::App::Situation and ...:
// Check: take OC into account?
const int currentAppId = static_cast<int>(m_session->app());
connect(m_ui->cbxOperator, &LtsWidgets::LtsComboBox::currentTextChanged,
this, &FilterChangeDialog::onOperatorChanged, Qt::UniqueConnection);
connect(m_ui->cbxScreen, &LtsWidgets::LtsComboBox::currentTextChanged,
this, &FilterChangeDialog::onScreenChanged, Qt::UniqueConnection);
connect(m_ui->cbxScreenContainer, &LtsWidgets::LtsComboBox::currentTextChanged,
this, &FilterChangeDialog::onScreenContainerChanged, Qt::UniqueConnection);
onOperatorChanged();
enableDisable();
m_symbolAppearanceSettings = m_fltParticipantGuiIfc->symbolAppearanceForOperator(LtsSessionData::LtsSessionData::getInstance()->getOperatorId(), m_session->workspaceId());
m_aesDisplayFilter = m_fltAesIfc->aesFilterForOperator(LtsSessionData::LtsSessionData::getInstance()->getOperatorId(), m_session->workspaceId());
// Nachtrag zu GUEZE-1769: since fltBuildingComponentIfc is optional:
if (m_fltBuildingComponentIfc)
m_buildingComponentSettings = m_fltBuildingComponentIfc->buildingComponentSettingsForOperator(LtsSessionData::LtsSessionData::getInstance()->getOperatorId(), m_session->workspaceId());
if (!m_opmCbxDtc->fillActiveAppOperatorComboBox(m_ui->cbxOperator,
currentAppId,
m_session->exerciseId(),
LtsSessionData::LtsSessionData::getInstance()->getOperatorId()))
ERROR_LOG(m_logger) << LOGFUNCTION << " fillActiveAppOperatorComboBox failed";
return true;
}
void FilterChangeDialog::onOperatorChanged()
{
const int operatorId = m_ui->cbxOperator->currentData().toInt();
DEBUG_LOG(m_logger) << LOGFUNCTION << " START, change to operatorId=" << operatorId
<< ", m_session->exerciseId()=" << m_session->exerciseId();
if (!m_opmCbxDtc)
return;
m_filterDataPerScreen.clear();
enableDisable();
// focus on LtsAppDescriptor::App::Situation and...:
const int currentAppId = static_cast<int>(m_session->app());
m_opmCbxDtc->fillActiveAppScreenComboBox(m_ui->cbxScreen,
currentAppId,
operatorId,
m_session->exerciseId(),
true); // preSelectTopmost
//It´s me?
if (operatorId == LtsSessionData::LtsSessionData::getInstance()->getOperatorId())
{
// disable our/current screenId:
const int ourScreenId = m_session->screenId();
int idx = m_ui->cbxScreen->findData(ourScreenId);
if (idx >= 0)
m_ui->cbxScreen->removeItem(idx);
}
// publish FLT to trigger updating the FilterData of the selected User/WS:
auto cb = [this, operatorId]() -> bool
{
FilterManagement::TriggerFilterData req;
req.operatorId(operatorId);
req.requestTime(m_session->partitionTime());
INFO_LOG(m_logger) << LOGFUNCTION << "TriggerFilterData: " << req;
return m_fltFtc->triggerFilterDataUpdateRequest(req, this);
};
m_requestHelper->startSingleRequest(cb);
// req 'TriggerFilterData' will trigger call of 'onFilterDataChanged'
// which will fill m_filterDataPerScreen
DEBUG_LOG(m_logger) << LOGFUNCTION << " END, change to operatorId=" << operatorId;
}
void FilterChangeDialog::onScreenChanged()
{
m_ui->cbxScreenContainer->clear();
const int screenId = m_ui->cbxScreen->currentData().toInt();
DEBUG_LOG(m_logger) << LOGFUNCTION << " START, change to ScreenId=" << screenId;
if (!m_opmCbxDtc)
return;
QMapIterator<QPair<int /*ScreenId*/, int /*ScreenContainerId*/>, FilterData> it(m_filterDataPerScreen);
QSet<int> containers;
int screenTypeId = -1; // FIXME: super ugly - determining screen type id
while (it.hasNext())
{
it.next();
if (it.key().first != screenId)
continue;
screenTypeId = it.value().screenTypeId();
containers.insert(it.key().second);
}
if (containers.contains(0))
m_ui->cbxScreenContainer->addItem(tr("Fullscreen"), 0);
// FIXME: un-static.....
switch (screenTypeId)
{
case 0: // normal
break;
case 1: // wide
{
if (containers.contains(1))
m_ui->cbxScreenContainer->addItem(tr("Left side"), 1);
if (containers.contains(2))
m_ui->cbxScreenContainer->addItem(tr("Right side"), 2);
break;
}
default:
break;
}
#ifdef DEBUGGING
if (m_ui->cbxScreenContainer->count() == 0)
{
m_ui->cbxScreenContainer->addItem(QString(QStringLiteral("Container'-2'")), -2);
m_ui->cbxScreenContainer->addItem(QString(QStringLiteral("Container'-1'")), -1);
m_ui->cbxScreenContainer->addItem(QString(QStringLiteral("Container'0'")), 0);
}
#endif // DEBUGGING
enableDisable();
DEBUG_LOG(m_logger) << LOGFUNCTION << " END, change to ScreenId=" << screenId;
}
void FilterChangeDialog::onScreenContainerChanged()
{
const int screenContainerId = m_ui->cbxScreen->currentData().toInt();
DEBUG_LOG(m_logger) << LOGFUNCTION << " START, change to ScreenContainerId=" << screenContainerId;
if (!m_opmCbxDtc)
return;
enableDisable();
DEBUG_LOG(m_logger) << LOGFUNCTION << " END, change to ScreenContainerId=" << screenContainerId;
}
void FilterChangeDialog::onFilterDataChanged(const FilterData &data, DataModification modType)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " START, we got FilterData " << data
<< ", modType " << modType;
if ((modType != DataModification::eAdded) && (modType != DataModification::eModified))
return;
if (data.operatorId() <= 0)
return;
const int requestedOperatorId = m_ui->cbxOperator->currentData().toInt();
if (requestedOperatorId <= 0)
return;
if (data.operatorId() != requestedOperatorId)
return;
DEBUG_LOG(m_logger) << LOGFUNCTION << " START, we got new FilterData for 'our' operator: " << data;
// check age here???
// FIXME: hack: we need to know what screen is of which type (normal, wide) to determine what containers are selectable
//m_screenTypes.insert(data.screenId(), data.screenTypeId());
const int screenId = data.screenId();
const int screenContainerId = data.screenContainerId();
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " insert " << " QPair<> "
<< "(screenId, " << screenId
<< "(screenContainerId, " << screenContainerId << ")"
<< " -> dara " << data;
m_filterDataPerScreen[QPair<int,int>(screenId, screenContainerId)] = data;
enableDisable();
DEBUG_LOG(m_logger) << LOGFUNCTION << " END";
}
bool FilterChangeDialog::apply()
{
const int screenId = m_ui->cbxScreen->currentData().toInt();
const int screenContainerId = m_ui->cbxScreenContainer->currentData().toInt();
if (!m_filterDataPerScreen.contains(QPair<int,int>(screenId, screenContainerId)))
{
ERROR_LOG(m_logger) << LOGFUNCTION << " not found: "
<< " screenId=" << screenId
<< ", screenContainerId=" << screenContainerId
<< "; available screenId count = " << m_filterDataPerScreen.count();
return false;
}
const FilterData &fData = m_filterDataPerScreen[QPair<int,int>(screenId, screenContainerId)];
//
// SymbolAppearance
//
if (m_ui->cbSymbolappear->isChecked() ||
m_ui->cbTypeFilter->isChecked() ||
m_ui->cbCollapseExpand->isChecked())
{
if (fData.symbolAppearanceContent().size() <= 0)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " FilterData (SymbolAppearance) is empty";
return false;
}
// N. Thoden, Aug 2021:
// Beim Laden der Filter aus einer anderen App wurden auch die nicht
// angewählten Anteil aus der entfernten App übernommen :-(
// Ablauf ist vereinacht:
// merge a) checked part of other/remote settings into b) own:
// fData into symbolAppearanceUpdateRequest
SymbolAppearanceSettings::Settings s;
{
SymbolAppearance symbolAppearanceDDS;
symbolAppearanceDDS.content(fData.symbolAppearanceContent());
// convert content to settings:
FilterManagement::SymbolAppearanceSettingsImpl impl(nullptr);
impl.setSettingsFromData(symbolAppearanceDDS); // will trransfer content to m_settings
s = impl.settings(); // retrive settings
}
DEBUG_LOG(m_logger) << " set SymbolAppearance..."
<< " m_ui->cbSymbolappear->isChecked()=" << m_ui->cbSymbolappear->isChecked()
<< " m_ui->cbTypeFilter->isChecked()=" << m_ui->cbTypeFilter->isChecked()
<< " m_ui->cbCollapseExpand->isChecked()=" << m_ui->cbCollapseExpand->isChecked();
if (m_ui->cbSymbolappear->isChecked())
m_symbolAppearanceSettings->setSettings(s, FilterManagement::SymbolAppearanceSettings::Part::Symbol);
if (m_ui->cbTypeFilter->isChecked())
m_symbolAppearanceSettings->setSettings(s, FilterManagement::SymbolAppearanceSettings::Part::Types);
if (m_ui->cbCollapseExpand->isChecked())
m_symbolAppearanceSettings->setSettings(s, FilterManagement::SymbolAppearanceSettings::Part::CollapseExpand);
auto cb = [this]() -> bool
{
const SymbolAppearance &symbolAppearance = m_symbolAppearanceSettings->settingsToData();
INFO_LOG(m_logger) << "symbolAppearance content " << symbolAppearance.content();
return m_fltFtc->symbolAppearanceUpdateRequest(symbolAppearance, this);
};
m_requestHelper->addRequest(cb);
}
//
// AesFilter
//
if (m_ui->cbAesFilter->isChecked())
{
if (fData.aesFilterContent().size() <= 0)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " FilterData (AesFilter) is empty";
return false;
}
// get current:
AesFilter aesFilter = m_aesDisplayFilter->filterToData();
// update content:
aesFilter.content(fData.aesFilterContent());
// write back:
m_aesDisplayFilter->setFilterFromData(aesFilter);
auto cb = [this]() -> bool
{
const AesFilter &aesFilter = m_aesDisplayFilter->filterToData();
INFO_LOG(m_logger) << "AesFilter content " << aesFilter.content();
return m_fltFtc->aesFilterUpdateRequest(aesFilter, this);
};
m_requestHelper->addRequest(cb);
}
//
// BuildingComponentFilter
//
if (m_ui->cbBuildingComponentFilter->isChecked() && m_ui->cbBuildingComponentFilter->isVisible())
{
if (fData.buildingComponentsFilterContent().size() <= 0)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " FilterData (BuildingComponentFilter) is empty";
return false;
}
// get current:
BuildingComponentFilter buildingComponentFilter = m_buildingComponentSettings->bldCmpSettingsToData();
// update content:
buildingComponentFilter.content(fData.buildingComponentsFilterContent());
// write back:
m_buildingComponentSettings->setBldCmpSettingsFromData(buildingComponentFilter);
auto cb = [this]() -> bool
{
const BuildingComponentFilter &filterData = m_buildingComponentSettings->bldCmpSettingsToData();
INFO_LOG(m_logger) << "BuildingComponentFilter content " << filterData.content();
return m_fltFtc->buildingComponentFilterUpdateRequest(filterData, this);
};
m_requestHelper->addRequest(cb);
}
//
// OperatorMapSettings
//
if (m_ui->cbOperatorMapSettings->isChecked())
{
if (fData.operatorMapSettingsContent().size() <= 0)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " FilterData (OperatorMapSettings) is empty";
return false;
}
std::shared_ptr<SituationMap::ForeignGuiInterface> sitMapIfc;
if (!m_session->getForeignGuiInterface<SituationMap::ForeignGuiInterface>(sitMapIfc))
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no SituationMap::ForeignGuiInterface";
return false;
}
sitMapIfc->setOperatorMapSettingsJson(QByteArray::fromRawData(fData.operatorMapSettingsContent().c_str(), fData.operatorMapSettingsContent().size()));
}
bool ret = true;
if (m_requestHelper->hasRequests())
ret = m_requestHelper->startRequests();
close();
return ret;
}
void FilterChangeDialog::onSymbolAppearanceUpdateReply(const Core::FunctionReplyObject &replyObject)
{
m_requestHelper->requestReply(replyObject);
}
void FilterChangeDialog::onAesFilterUpdateReply(const Core::FunctionReplyObject &replyObject)
{
m_requestHelper->requestReply(replyObject);
}
void FilterChangeDialog::onBuildingComponentFilterUpdateReply(const Core::FunctionReplyObject &replyObject)
{
m_requestHelper->requestReply(replyObject);
}
void FilterChangeDialog::onTriggerFilterDataUpdateReply(const Core::FunctionReplyObject &replyObject)
{
m_requestHelper->requestReply(replyObject);
}
void FilterChangeDialog::enableDisable()
{
// qCritical() << " enableDisable";
{
int myOperatorId = LtsSessionData::LtsSessionData::getInstance()->getOperatorId();
int myScreenId = m_session->screenId();
DEBUG_LOG(m_logger) << LOGFUNCTION << " my operatorId=" << myOperatorId << " my screenId=" << myScreenId;
}
const int cbxOperatorId = m_ui->cbxOperator->currentData().toInt();
const int cbxScreenId = m_ui->cbxScreen->currentData().toInt();
const int cbxScreenContainerId = m_ui->cbxScreenContainer->currentData().toInt();
//const QList<QPair<int,int> > availableScreenIds = m_filterDataPerScreen.keys();
// const int cnt = m_ui->cbxScreen->count();
// qCritical() << " yyyyyyyyy" << cnt;
const bool screenOk = (cbxScreenId >=0) && (cbxScreenId <=4) && (m_ui->cbxScreen->count() > 0);
const bool ena = (cbxOperatorId > 0) && screenOk && m_filterDataPerScreen.contains(QPair<int,int>(cbxScreenId, cbxScreenContainerId));
m_ui->buttonBox->getButton(LtsWidgets::DialogButton::Ok)->setEnabled(ena);
// qCritical() << " yyyyyyyyy" << ena;
dump();
DEBUG_LOG(m_logger) << LOGFUNCTION << " cbxScreenId=" << cbxScreenId
<< " cbxScreenContainerId=" << cbxScreenContainerId
<< ", availableScreenId count=" << m_filterDataPerScreen.count()
<< ", DialogButton::Ok: enabled=" << m_ui->buttonBox->getButton(LtsWidgets::DialogButton::Ok)->isEnabled();
}
void FilterChangeDialog::dump()
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " -------------------------";
{
int myOperatorId = LtsSessionData::LtsSessionData::getInstance()->getOperatorId();
int myScreenId = m_session->screenId();
DEBUG_LOG(m_logger)<< ", myOperatorId=" << myOperatorId << ", myScreenId=" << myScreenId;
}
{
const int cbxOperatorId = m_ui->cbxOperator->currentData().toInt();
const int cbxScreenId = m_ui->cbxScreen->currentData().toInt();
const int cbxScreenContainerId = m_ui->cbxScreenContainer->currentData().toInt();
DEBUG_LOG(m_logger)<< ", cbxOperatorId=" << cbxOperatorId << ", cbxScreenId=" << cbxScreenId << ", cbxScreenContainerId=" << cbxScreenContainerId;
}
QMapIterator<QPair<int /*ScreenId*/, int /*ScreenContainerId*/>, FilterData> it(m_filterDataPerScreen);
while (it.hasNext())
{
it.next();
QPair<int,int> key = it.key();
DEBUG_LOG(m_logger) << " ScreenId=" << key.first << ", ScreenContainerId=" << key.second;
}
DEBUG_LOG(m_logger) << LOGFUNCTION << " -------------------------";
}
} // namespace FilterManagement
@@ -0,0 +1,106 @@
/**
* @RDE_HEADER@
* FilterManagement - Select filter settings from other operator
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna Rathje, SLSE, 2017-11-20
*/
#pragma once
#include <Plugins/FilterManagement/Gui/FilterChange/fltfilterchange_export.h>
#include <LtsWidgets/lts_dialog.h>
#include <LtsUtilsGuiDds/request_helper.h>
#include <FilterManagement/logger.h>
#include <PluginInterfaces/gui_plugin_interface.h>
#include <OperatorManagement/opm_gui_combobox_plugin_interface.h>
#include <FilterManagement/flt_data_plugin_interface.h>
#include <FilterManagement/flt_participant_plugin_interface.h>
#include <FilterManagement/flt_aes_plugin_interface.h>
#include <FilterManagement/flt_symbol_appearance_settings.h>
#include <FilterManagement/flt_building_cmpnt_plugin_interface.h>
#include <FilterManagement/flt_building_cmpnt_settings.h>
namespace Ui
{
class FilterChangeDialog;
}
namespace LtsSession
{
class LtsSession;
}
namespace FilterManagement
{
class FLTFILTERCHANGE_EXPORT FilterChangeDialog final : public LtsWidgets::LtsFramelessDialog
, private FilterManagement::Interface::Ftc::SymbolAppearanceUpdateReplyHandler
, private FilterManagement::Interface::Ftc::AesFilterUpdateReplyHandler
, private FilterManagement::Interface::Ftc::BuildingComponentFilterUpdateReplyHandler
, private FilterManagement::Interface::Ftc::TriggerFilterDataUpdateReplyHandler
{
Q_OBJECT
public:
explicit FilterChangeDialog(QWidget *parent = nullptr);
~FilterChangeDialog();
bool init(LtsSession::LtsSession *session,
SymbolAppearanceSettings::Part preSelectSymbolAppearanceSettings = SymbolAppearanceSettings::Part::All,
bool preSelectAesFilter = false,
bool preSelectBuildingComponentSettings = false,
bool preSelectOperatorMapSettings = false);
static bool isAvailableAtApp(const LtsAppDescriptor::App app)
{
// GUEZE-1771: Plan Overlay: Kein Speichern von Filtern / Arbeitsbereichen möglich
return (app == LtsAppDescriptor::App::Situation) ||
(app == LtsAppDescriptor::App::ScriptEditorEssentialsView) ||
(app == LtsAppDescriptor::App::PlanEditor)
;
}
private:
bool apply();
void onSymbolAppearanceUpdateReply(const Core::FunctionReplyObject &replyObject) override;
void onAesFilterUpdateReply(const Core::FunctionReplyObject &replyObject) override;
void onBuildingComponentFilterUpdateReply(const Core::FunctionReplyObject &replyObject) override;
void onTriggerFilterDataUpdateReply(const Core::FunctionReplyObject &replyObject) override;
void enableDisable();
void dump();
private Q_SLOTS:
void onOperatorChanged();
void onScreenChanged();
void onScreenContainerChanged();
void onFilterDataChanged(const FilterManagement::FilterData &data, DataModification modType);
private:
LtsSession::LtsSession *m_session;
std::shared_ptr<OperatorManagement::ForeignGuiComboboxInterface> m_opmCbxDtc;
std::shared_ptr<FilterManagement::ForeignFltParticipantGuiInterface> m_fltParticipantGuiIfc;
std::shared_ptr<FilterManagement::ForeignAesGuiInterface> m_fltAesIfc;
std::shared_ptr<FilterManagement::ForeignFltBuildingComponentGuiInterface> m_fltBuildingComponentIfc;
std::shared_ptr<FilterManagement::Interface::Ftc> m_fltFtc;
std::shared_ptr<FilterManagement::Interface::Dtc> m_fltDtc;
QMap<int, int> m_screenTypes;
QMap<QPair<int /*ScreenId*/, int /*ScreenContainerId*/>, FilterData> m_filterDataPerScreen; // NOTE: contains the filter data of the requested operator!
std::shared_ptr<SymbolAppearanceSettings> m_symbolAppearanceSettings;
std::shared_ptr<AesDisplayFilter> m_aesDisplayFilter;
std::shared_ptr<BuildingComponentSettings> m_buildingComponentSettings;
LtsUtils::RequestHelper *m_requestHelper;
Ui::FilterChangeDialog *m_ui;
NGL::INGLLogger &m_logger;
};
}
@@ -0,0 +1,175 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FilterChangeDialog</class>
<widget class="QWidget" name="FilterChangeDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>321</width>
<height>326</height>
</rect>
</property>
<property name="windowTitle">
<string>Load Operator Settings</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<widget class="LtsWidgets::LtsComboBox" name="cbxOperator">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="const" stdset="0">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="LtsWidgets::LtsComboBox" name="cbxScreen">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="const" stdset="0">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Screen:</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Operator:</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_ScreenContainer">
<property name="text">
<string>Container:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="LtsWidgets::LtsComboBox" name="cbxScreenContainer">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="const" stdset="0">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="2" column="0">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QCheckBox" name="cbSymbolappear">
<property name="text">
<string>Symbol appearance</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cbTypeFilter">
<property name="text">
<string>Type filter</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cbCollapseExpand">
<property name="text">
<string>Collapse / Expand Participants</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="0">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="cbOperatorMapSettings">
<property name="text">
<string>Operator Map Settings</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QCheckBox" name="cbAesFilter">
<property name="text">
<string>Aes Filter</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="Line" name="line_overBuildingComponentFilter">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QCheckBox" name="cbBuildingComponentFilter">
<property name="text">
<string>Building Component Filter</string>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="LtsWidgets::LtsDialogButtonBox" name="buttonBox" native="true"/>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsWidgets::LtsDialogButtonBox</class>
<extends>QWidget</extends>
<header>LtsWidgets/lts_dialog_button_box.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>LtsWidgets::LtsComboBox</class>
<extends>QComboBox</extends>
<header>LtsWidgets/lts_combo_box.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,75 @@
# $Id$
# $HeadURL$
# $Author$
# Created by Christian Ehrlicher, SLSE, 2017-06-16
#
SET(flt_part_widget_SRCS
flt_collapse_expand_participants_widget.cpp
flt_collapse_expand_participants_widget.h
flt_symbol_appearance_widget.cpp
flt_symbol_appearance_widget.h
flt_type_filter_widget.cpp
flt_type_filter_widget.h
)
NGL_WRAP_UI(flt_part_widget_SRCS
flt_collapse_expand_participants_widget.ui
flt_symbol_appearance_widget.ui
flt_type_filter_widget.ui
)
NGL_ADD_LIBRARY(WS FltParticipantWidget STATIC ${flt_part_widget_SRCS})
NGL_TARGET_LINK_LIBRARIES(FltParticipantWidget
PRIVATE
svcFltCommon
PpmCommon
LtsProjectionWorkstation
PUBLIC
AsbDataPluginInterface
FltDataPluginInterface
PdmGuiPluginInterface
PpmGuiComboboxPluginInterface
Qt5::Widgets
)
NGL_TARGET_INCLUDE_DIRECTORIES(FltParticipantWidget
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../../..
)
SET(flt_part_gui_SRCS
flt_collapse_expand_participants_dialog.cpp
flt_collapse_expand_participants_dialog.h
flt_participant_gui_plugin.cpp
flt_participant_gui_plugin.h
flt_symbol_appearance_dialog.cpp
flt_symbol_appearance_dialog.h
flt_type_filter_dialog.cpp
flt_type_filter_dialog.h
)
NGL_ADD_LIBRARY(WS FltParticipantGuiPlugin MODULE ${flt_part_gui_SRCS})
NGL_TARGET_LINK_LIBRARIES(FltParticipantGuiPlugin
AsbDataPluginInterface
LtsPrinting
FltFilterChange
FltDataPluginInterface
FltParticipantGuiPluginInterface
FltParticipantWidget
PdmGuiPluginInterface
PpmGuiComboboxPluginInterface
PpmDataPluginInterface
PpmCommon
FlmDataPluginInterface
FltAesGuiCommon
svcFltCommon
LtsSession
LtsSessionData
LtsUtilsGuiDds
LtsUtilsSettings
LtsWidgets
Qt5::Widgets
)
NGL_INSTALL_TARGET(FltParticipantGuiPlugin)
@@ -0,0 +1,147 @@
/**
* @RDE_HEADER@
* FilterManagement - Collapse/Expand Participants
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#include "flt_collapse_expand_participants_dialog.h"
#include <FilterManagement/Gui/FilterChange/flt_filter_change.h>
#include <AdvancedSymbology/asb_data_plugin_interface.h>
#include <LtsSession/lts_session_data.h>
#include <LtsPrinting/printing.h>
#include <QGridLayout>
#include <QTreeView>
namespace FilterManagement
{
CollapseExpandParticipantDialog::CollapseExpandParticipantDialog(QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
, m_widget(new CollapseExpandParticipantWidget)
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_session(nullptr)
, m_logger(getLogger("CollapseExpandParticipantDialog"))
{
QGridLayout *gl = new QGridLayout(this);
gl->setMargin(0);
gl->addWidget(m_widget, 0, 0);
connect(m_widget, &CollapseExpandParticipantWidget::changesMade,
this, &CollapseExpandParticipantDialog::slotChangesMade);
connect(m_widget, &CollapseExpandParticipantWidget::modelResetted,
this, &CollapseExpandParticipantDialog::__unchange__);
m_buttonBox->connectButton(LtsWidgets::DialogButton::Print, this, &CollapseExpandParticipantDialog::onPrint);
setOnlineHelpFilename(QStringLiteral("Situation-Collapse-Expand"));
}
CollapseExpandParticipantDialog::~CollapseExpandParticipantDialog()
{
delete m_widget;
}
void CollapseExpandParticipantDialog::retranslate()
{
m_widget->retranslate();
// lupdate doesn't like translate(tr("foo")) ...
const QString txt(tr("Collapse/Expand Participants"));
translate(txt);
m_uiRequirements->retranslate();
}
bool CollapseExpandParticipantDialog::init(LtsSession::LtsSession *session)
{
m_session = session;
if (!session->getForeignGuiInterface<ParticipantManagement::ForeignGuiComboboxInterface>(m_ppmGuiCbxIfc) ||
!session->getDtc<ParticipantManagement::DataInterface>(m_ppmDtc) ||
!session->getForeignGuiInterface(m_fltParticipantIfc) ||
!session->getDtc<FilterManagement::DataInterface>(m_fltDtc) ||
!session->getFtc<FilterManagement::DataInterface>(m_fltFtc))
return false;
connect(m_fltDtc.get(), &FilterManagement::Interface::Dtc::symbolAppearanceChanged,
this, &CollapseExpandParticipantDialog::onDataChanged);
std::shared_ptr<AdvancedSymbology::ForeignDataInterface> asb;
session->getForeignDataInterface<AdvancedSymbology::DataInterface>(asb);
auto symbolAppearanceSettings = m_fltParticipantIfc->symbolAppearanceForOperator(LtsSessionData::LtsSessionData::getInstance()->getOperatorId(),
m_session->workspaceId());
m_widget->init(m_ppmDtc, m_ppmGuiCbxIfc, asb, /*m_fltParticipantIfc,*/ symbolAppearanceSettings);
if (FilterChangeDialog::isAvailableAtApp(m_session->app()))
{
m_buttonBox->getButton(LtsWidgets::DialogButton::Load)->setText(tr("Load filter"));
m_buttonBox->connectButton(LtsWidgets::DialogButton::Load,
this, &CollapseExpandParticipantDialog::onLoadButtonClicked);
}
return true;
}
bool CollapseExpandParticipantDialog::apply()
{
m_widget->apply();
const SymbolAppearance symbolAppearance = m_widget->filter()->settingsToData();
auto cb = [symbolAppearance, this]() -> bool
{
return m_fltFtc->symbolAppearanceUpdateRequest(symbolAppearance, this);
};
m_requestHelper->addRequest(cb);
return m_requestHelper->startRequests();
}
void CollapseExpandParticipantDialog::dialogCanceled()
{
m_widget->dialogCanceled();
}
void CollapseExpandParticipantDialog::onSymbolAppearanceUpdateReply(const Core::FunctionReplyObject &replyObject)
{
m_requestHelper->requestReply(replyObject);
}
void CollapseExpandParticipantDialog::onLoadButtonClicked()
{
FilterChangeDialog *dialog = new FilterChangeDialog(this);
if (!dialog->init(m_session, SymbolAppearanceSettings::Part::CollapseExpand))
{
delete dialog;
return;
}
dialog->setAttribute(Qt::WA_DeleteOnClose);
QObject::connect(dialog, &FilterChangeDialog::rejected, dialog, &FilterChangeDialog::deleteLater);
dialog->show();
}
void CollapseExpandParticipantDialog::onDataChanged(const SymbolAppearance &data, DataModification modType)
{
DEBUG_LOG(m_logger) << "onDataChanged ... " << data;
if (modType != DataModification::eRemoved &&
data.operatorId() == LtsSessionData::LtsSessionData::getInstance()->getOperatorId())
{
auto symbolAppearanceSettings = m_fltParticipantIfc->symbolAppearanceForOperator(LtsSessionData::LtsSessionData::getInstance()->getOperatorId(),
m_session->workspaceId());
m_widget->onDataChanged(symbolAppearanceSettings);
// the data can be changed if another replay is selected or filter are loaded.
// So our widget has to be updated:
__unchange__();
}
}
void CollapseExpandParticipantDialog::onPrint()
{
LtsPrinting::printView(m_session, this, m_widget->treeView());
}
} // namespace FilterManagement
@@ -0,0 +1,68 @@
/**
* @RDE_HEADER@
* FilterManagement - Collapse/Expand Participants
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#pragma once
#include "flt_collapse_expand_participants_widget.h"
#include <ParticipantManagement/ppm_dtc.h>
#include <ParticipantManagement/ppm_data_plugin_interface.h>
#include <ParticipantManagement/ppm_gui_combobox_plugin_interface.h>
#include <LtsSession/lts_session.h>
#include <PluginInterfaces/gui_plugin_interface.h>
#include <LtsWidgets/lts_dialog.h>
#include <LtsUtilsGuiDds/request_helper.h>
#include <FilterManagement/logger.h>
#include <FilterManagement/flt_participant_plugin_interface.h>
#include <FilterManagement/flt_ftc.h>
namespace LtsSession
{
class LtsSession;
}
namespace ParticipantManagement
{
class ParticipantEditModel;
}
namespace FilterManagement
{
class CollapseExpandParticipantDialog final : public LtsWidgets::LtsDialog
, private FilterManagement::Interface::Ftc::SymbolAppearanceUpdateReplyHandler
{
Q_OBJECT
public:
explicit CollapseExpandParticipantDialog(QWidget *parent = nullptr);
~CollapseExpandParticipantDialog();
void retranslate() override;
bool init(LtsSession::LtsSession *session);
protected:
bool apply() override;
void dialogCanceled() override;
private slots:
void onLoadButtonClicked();
void onDataChanged(const FilterManagement::SymbolAppearance &data, DataModification modType);
void onPrint();
private:
void onSymbolAppearanceUpdateReply(const Core::FunctionReplyObject &replyObject) override;
private:
CollapseExpandParticipantWidget *m_widget;
LtsUtils::RequestHelper *m_requestHelper;
LtsSession::LtsSession *m_session;
std::shared_ptr<FilterManagement::ForeignFltParticipantGuiInterface> m_fltParticipantIfc;
std::shared_ptr<FilterManagement::Interface::Dtc> m_fltDtc;
std::shared_ptr<FilterManagement::Interface::Ftc> m_fltFtc;
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_ppmDtc;
std::shared_ptr<ParticipantManagement::ForeignGuiComboboxInterface> m_ppmGuiCbxIfc;
NGL::INGLLogger &m_logger;
};
} // namespace FilterManagement
@@ -0,0 +1,265 @@
/**
* @RDE_HEADER@
* FilterManagement - Collapse/Expand Participants
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#include "flt_collapse_expand_participants_widget.h"
#include "ui_flt_collapse_expand_participants_widget.h"
#include <FilterManagement/Gui/FilterChange/flt_filter_change.h>
#include <ParticipantManagement/Gui/Common/participant_edit_model.h>
#include <ParticipantManagement/ppm_gui_combobox_plugin_interface.h>
#include <nglwidgets/ngltreeitem.h>
#include <LtsWidgets/lts_message_dialog.h>
#include <QMenu>
#include <QJsonDocument>
#include <QJsonObject>
namespace FilterManagement
{
int CollapseExpandParticipantWidget::s_preselectedParty = -1;
CollapseExpandParticipantWidget::CollapseExpandParticipantWidget(QWidget *parent)
: QWidget(parent)
, m_model(nullptr)
, m_ui(new Ui::CollapseExpandParticipantWidget)
, m_logger(getLogger("CollapseExpandParticipantWidget"))
{
m_ui->setupUi(this);
connect(m_ui->tvParticipants, &QTreeView::customContextMenuRequested,
this, &CollapseExpandParticipantWidget::showContextMenu);
connect(m_ui->tvParticipants, &QTreeView::expanded,
this, &CollapseExpandParticipantWidget::changesMade);
connect(m_ui->tvParticipants, &QTreeView::collapsed,
this, &CollapseExpandParticipantWidget::changesMade);
connect(this, &CollapseExpandParticipantWidget::changesMade,
this, [this]() { setWindowModified(true); });
connect(m_ui->cbParty, static_cast<void (LtsWidgets::LtsComboBox::*)(int)>(&LtsWidgets::LtsComboBox::currentIndexChanged),
this, &CollapseExpandParticipantWidget::onPartyChanged);
}
CollapseExpandParticipantWidget::~CollapseExpandParticipantWidget()
{
delete m_ui;
}
void CollapseExpandParticipantWidget::retranslate()
{
m_ui->retranslateUi(this);
}
bool CollapseExpandParticipantWidget::init(const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc,
const std::shared_ptr<ParticipantManagement::ForeignGuiComboboxInterface> &ppmIfc,
const std::shared_ptr<AdvancedSymbology::ForeignDataInterface> &asbIfc,
// const std::shared_ptr<FilterManagement::ForeignFltParticipantGuiInterface> &fltParticipantIfc,
const std::shared_ptr<SymbolAppearanceSettings> &filter)
{
m_ppmDtc = ppmDtc;
m_ppmGuiCbxIfc = ppmIfc;
// m_fltParticipantIfc = fltParticipantIfc;
m_symbolAppearanceSettings = filter;
#ifdef TABLET_MODE
//css didn"t worked
m_ui->tvParticipants->setIconSize(QSize(50,50));
#endif
m_model = new ParticipantManagement::ParticipantEditModel(this, m_ppmDtc, asbIfc);
m_model->setRowsCheckable(true);
m_ui->tvParticipants->setModel(m_model);
#ifndef LTS_DEBUG
m_ui->tvParticipants->hideColumn(ParticipantManagement::ParticipantEditModel::ColParticipantId);
#endif
connect(m_model, &ParticipantManagement::ParticipantEditModel::dataChanged,
this, &CollapseExpandParticipantWidget::onModelDataChanged, Qt::UniqueConnection);
m_originalSymbolAppearance = m_symbolAppearanceSettings->settings();
m_currentSymbolAppearance = m_originalSymbolAppearance;
m_ppmGuiCbxIfc->fillPartyComboBox(m_ui->cbParty, ParticipantManagement::ForeignGuiComboboxInterface::CbxPartyFilter::NormalOc);
const int idx = m_ui->cbParty->findData(s_preselectedParty);
if (idx >= 0)
m_ui->cbParty->setCurrentIndex(idx);
onPartyChanged();
return true;
}
static void mergeParticipantIds(QSet<int> &idsToUpdate, const QSet<int> &affectedIds, const QSet<int> &idsToAdd)
{
// remove all currently affectedIds (= ids for a specific party) from the
// idSet to update
auto it = idsToUpdate.begin();
while (it != idsToUpdate.end())
{
if (affectedIds.contains(*it))
it = idsToUpdate.erase(it);
else
++it;
}
// now add the new ids to the idSet to update
idsToUpdate += idsToAdd;
}
void CollapseExpandParticipantWidget::apply()
{
const QSet<int> currentParticipantIds = m_model->participantIds();
const QSet<int> newHiddenParticipantIds = m_model->checkStateForParticipants(Qt::Unchecked);
const QSet<int> collapsedParticipantIds = collapsedParticipants(m_ui->tvParticipants->rootIndex());
mergeParticipantIds(m_currentSymbolAppearance.colExpand.hiddenParticipantIds, currentParticipantIds, newHiddenParticipantIds);
mergeParticipantIds(m_currentSymbolAppearance.colExpand.collapsedParticipantIds, currentParticipantIds, collapsedParticipantIds);
if (m_logger.isDebugEnabled())
{
QStringList sl;
sl.reserve(m_currentSymbolAppearance.colExpand.hiddenParticipantIds.size());
for (int i : qAsConst(m_currentSymbolAppearance.colExpand.hiddenParticipantIds))
sl += QString::number(i);
DEBUG_LOG(m_logger) << "Hidden participant ids: " << sl.join(QLatin1Char(' '));
sl.clear();
for (int i : qAsConst(m_currentSymbolAppearance.colExpand.collapsedParticipantIds))
sl += QString::number(i);
DEBUG_LOG(m_logger) << "Collapsed participant ids: " << sl.join(QLatin1Char(' '));
}
m_symbolAppearanceSettings->setSettings(m_currentSymbolAppearance, SymbolAppearanceSettings::Part::CollapseExpand);
setWindowModified(false);
}
void CollapseExpandParticipantWidget::dialogCanceled()
{
m_symbolAppearanceSettings->setSettings(m_originalSymbolAppearance, SymbolAppearanceSettings::Part::CollapseExpand);
}
QTreeView *CollapseExpandParticipantWidget::treeView()
{
return m_ui->tvParticipants;
}
void CollapseExpandParticipantWidget::onModelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles)
{
Q_UNUSED(topLeft);
Q_UNUSED(bottomRight);
if (roles.isEmpty() || roles.contains(Qt::CheckStateRole))
emit changesMade();
}
void CollapseExpandParticipantWidget::onPartyChanged()
{
const int newPartyId = m_ui->cbParty->currentData().toInt();
s_preselectedParty = newPartyId;
if (m_model->partyId() == newPartyId)
return;
if (isWindowModified())
{
switch (LtsWidgets::LtsMessageDialog::askApplyDiscardCancel(this))
{
case LtsWidgets::Button::Apply:
apply();
doReinitModel(newPartyId);
break;
case LtsWidgets::Button::Cancel:
m_ui->cbParty->setCurrentIndex(m_ui->cbParty->findData(m_model->partyId(), Qt::UserRole));
s_preselectedParty = m_ui->cbParty->currentData().toInt();
break;
case LtsWidgets::Button::Discard:
m_currentSymbolAppearance = m_originalSymbolAppearance;
doReinitModel(newPartyId);
break;
default:
break;
}
}
else
doReinitModel(newPartyId);
}
void CollapseExpandParticipantWidget::doReinitModel(int newPartyId)
{
m_model->onReinitModel(newPartyId,
m_currentSymbolAppearance.colExpand.hiddenParticipantIds,
Qt::Unchecked);
m_ui->tvParticipants->setUpdatesEnabled(false);
collapseExpand(m_ui->tvParticipants->rootIndex());
for (int i = 0; i < m_model->columnCount(QModelIndex()); ++i)
m_ui->tvParticipants->resizeColumnToContents(i);
m_ui->tvParticipants->header()->resizeSection(0, m_ui->tvParticipants->columnWidth(0) + m_ui->tvParticipants->iconSize().width() + 10);
m_ui->tvParticipants->setUpdatesEnabled(true);
emit modelResetted();
setWindowModified(false);
}
void CollapseExpandParticipantWidget::collapseExpand(const QModelIndex &idx)
{
auto *item = static_cast<ParticipantManagement::ParticipantEditModel::CheckedTreeItem *>(m_model->privateData(idx));
const auto &data = item->participant;
if (m_currentSymbolAppearance.colExpand.collapsedParticipantIds.contains(data.id()))
m_ui->tvParticipants->collapse(idx);
else
m_ui->tvParticipants->expand(idx);
for (int row = 0; row < m_model->rowCount(idx); ++row)
collapseExpand(m_model->index(row, 0, idx));
}
QSet<int> CollapseExpandParticipantWidget::collapsedParticipants(const QModelIndex &idx) const
{
QSet<int> collapsedParticipantIds;
if (!m_ui->tvParticipants->isExpanded(idx))
{
ParticipantManagement::ParticipantEditModel::CheckedTreeItem *item = m_model->privateData(idx);
if (item && item->participant.id() != 0)
collapsedParticipantIds += item->participant.id();
}
for (int row = 0; row < m_model->rowCount(idx); ++row)
collapsedParticipantIds += collapsedParticipants(m_model->index(row, 0, idx));
return collapsedParticipantIds;
}
void CollapseExpandParticipantWidget::showContextMenu(const QPoint &position)
{
QTreeView *tv = qobject_cast<QTreeView *>(sender());
if (!tv)
return;
const QModelIndex idx = tv->currentIndex();
if (!idx.isValid())
return;
if (m_model->rowCount(idx) == 0)
return;
QMenu menu;
if (tv->isExpanded(idx))
{
QAction *collapseAction = new QAction(tr("Collapse"), &menu);
connect(collapseAction, &QAction::triggered, this, [tv, idx]() { tv->collapse(idx);});
menu.addAction(collapseAction);
}
else
{
QAction *expandAction = new QAction(tr("Expand"), &menu);
connect(expandAction, &QAction::triggered, this, [tv, idx]() { tv->expand(idx);});
menu.addAction(expandAction);
}
menu.exec(tv->viewport()->mapToGlobal(position));
}
void CollapseExpandParticipantWidget::onDataChanged(const std::shared_ptr<SymbolAppearanceSettings> &newFilter)
{
m_originalSymbolAppearance = newFilter->settings();
m_symbolAppearanceSettings = newFilter;
DEBUG_LOG(m_logger) << "onDataChanged ... " << QJsonDocument(newFilter->settingsToJson()).toJson();
collapseExpand(m_ui->tvParticipants->rootIndex());
m_model->setCheckStateForParticipants(m_originalSymbolAppearance.colExpand.hiddenParticipantIds, Qt::Unchecked);
}
} // namespace FilterManagement
@@ -0,0 +1,86 @@
/**
* @RDE_HEADER@
* FilterManagement - Collapse/Expand Participants
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#pragma once
#include <QWidget>
#include <FilterManagement/logger.h>
#include <FilterManagement/flt_symbol_appearance_settings.h>
class QTreeView;
namespace AdvancedSymbology
{
class ForeignDataInterface;
}
namespace Ui
{
class CollapseExpandParticipantWidget;
}
namespace ParticipantManagement
{
namespace Interface
{
class Dtc;
}
class ForeignGuiComboboxInterface;
class ParticipantEditModel;
}
namespace FilterManagement
{
class ForeignFltParticipantGuiInterface;
class CollapseExpandParticipantWidget final : public QWidget
{
Q_OBJECT
public:
explicit CollapseExpandParticipantWidget(QWidget *parent = nullptr);
~CollapseExpandParticipantWidget();
void retranslate();
bool init(const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc,
const std::shared_ptr<ParticipantManagement::ForeignGuiComboboxInterface> &ppmIfc,
const std::shared_ptr<AdvancedSymbology::ForeignDataInterface> &asbIfc,
// const std::shared_ptr<FilterManagement::ForeignFltParticipantGuiInterface> &fltParticipantIfc,
const std::shared_ptr<SymbolAppearanceSettings> &filter);
void apply();
void dialogCanceled();
std::shared_ptr<SymbolAppearanceSettings> filter() const { return m_symbolAppearanceSettings; }
void onDataChanged(const std::shared_ptr<SymbolAppearanceSettings> &newFilter);
QTreeView *treeView();
signals:
void changesMade();
void modelResetted();
private slots:
void onModelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles);
void onPartyChanged();
void doReinitModel(int newPartyId);
void showContextMenu(const QPoint &position);
private:
void collapseExpand(const QModelIndex &idx);
QSet<int> collapsedParticipants(const QModelIndex &idx) const;
private:
ParticipantManagement::ParticipantEditModel *m_model;
// std::shared_ptr<FilterManagement::ForeignFltParticipantGuiInterface> m_fltParticipantIfc;
std::shared_ptr<SymbolAppearanceSettings> m_symbolAppearanceSettings;
SymbolAppearanceSettings::Settings m_originalSymbolAppearance;
SymbolAppearanceSettings::Settings m_currentSymbolAppearance;
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_ppmDtc;
std::shared_ptr<ParticipantManagement::ForeignGuiComboboxInterface> m_ppmGuiCbxIfc;
static int s_preselectedParty;
Ui::CollapseExpandParticipantWidget *m_ui;
NGL::INGLLogger &m_logger;
};
} // namespace FilterManagement
@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CollapseExpandParticipantWidget</class>
<widget class="QWidget" name="CollapseExpandParticipantWidget">
<property name="windowTitle">
<string notr="true">Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0" colspan="3">
<widget class="QTreeView" name="tvParticipants">
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="iconSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="LtsWidgets::LtsComboBox" name="cbParty">
<property name="const" stdset="0">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Party:</string>
</property>
</widget>
</item>
<item row="0" column="2">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>132</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsWidgets::LtsComboBox</class>
<extends>QComboBox</extends>
<header>LtsWidgets/lts_combo_box.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,215 @@
/**
* @RDE_HEADER@
* Gui Plugin for FilterManagement (Participant)
* $Id: flt_participant_plugin.cpp 50305 2020-03-10 08:30:39Z ehrlicher $
* $HeadURL: svn://slssvn/TDS/branches/product/devel/trunk/Lts/Plugins/FilterManagement/Gui/Participant/flt_participant_plugin.cpp $
* $Author: ehrlicher $
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#include "flt_collapse_expand_participants_dialog.h"
#include "flt_participant_gui_plugin.h"
#include "flt_symbol_appearance_dialog.h"
#include "flt_type_filter_dialog.h"
#include <Plugins/FilterManagement/Gui/Aes/Common/symbol_appearance_settings_impl.h>
#include <LtsProjectionWorkstation/lts_projection_workstation.h>
#include <LtsSession/lts_session.h>
#include <FilterManagement/flt_operator_rights.h>
namespace FilterManagement
{
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.Interface"))
, m_logger(getLogger("ParticipantInterfaceImpl"))
{}
bool InterfaceImpl::fetchInterfaces()
{
if (!m_session->getDtc<FilterManagement::DataInterface>(m_fltDtc))
return false;
connect(m_fltDtc.get(), &FilterManagement::Interface::Dtc::symbolAppearanceChanged,
this, &InterfaceImpl::onSymbolAppearanceChanged, Qt::UniqueConnection);
// NLDEVCTRL-445: Projektion Filter und Kartenausschnitt
// filterPresetLoadUnsaved at PWS leads to race condition
// (create dtc and update data via request)
// enable AesFilter and SymbolAppearance already here
// 22.01.2025, Thoden: Nachtrag zu NLDEVCTRL-445: Projektion Filter und Kartenausschnitt
// GUEZE-3459: Hannas OPW: Hänger beim Login
// 1. waitForHistoricalData{SymbolAppearance|AesFilter|buildingComponentFilters}
// gehört eingentlich VOR fltDtc->{SymbolAppearance|AesFilter|buildingComponentFilters}
// 2. Da diese aber auf der PWS wohl wichtig waren, wird fetchInterfaces jeweils
// angepasst:
// waitForHistoricalData{SymbolAppearance|AesFilter|buildingComponentFilters} wird
// nicht mehr grundsätzlich, sondern nur auf der PWS ausgeführt:
// if (LtsProjectionWorkstation::LtsProjectionWorkstation::hasInstance())
// m_fltDtc->waitForHistoricalDataXXX(1000);
if (LtsProjectionWorkstation::LtsProjectionWorkstation::hasInstance())
m_fltDtc->waitForHistoricalDataSymbolAppearance(1000); // wait... contains enable
return true;
}
QVector<LtsWidgets::PluginData> InterfaceImpl::getActions()
{
QVector<LtsWidgets::PluginData> ret;
LtsWidgets::PluginData plData;
const bool bShowSymApp =
(m_session->partitionType() != IDL::PartitionType::Global) ||
(m_session->app() == LtsAppDescriptor::App::ResourceManager);
const bool bShowTypeStateColExp =
(m_session->partitionType() != IDL::PartitionType::Global);
if (bShowSymApp)
{
plData.menuGroup = menuGroup();
plData.menuText = tr("Symbol Appearance");
plData.identifier = QLatin1String("fltParticipantFilter");
plData.menuIcon = QIcon(QLatin1String("icon:filter_map_settings.svg")); // ToDo: passendes Icon erstellen
plData.operatorRight = OperatorRights::FilterManagement::SymbolAppearanceEdit;
plData.exercisePart = LtsWidgets::ExercisePart::eSpecial;
plData.createWidgetFunc = [this](QWidget * parent)
{
return LtsWidgets::initDialog(new SymbolAppearanceDialog(parent, appId() == LtsAppDescriptor::App::OC),
m_session);
};
ret.append(plData);
}
if (bShowTypeStateColExp)
{
plData.menuGroup = menuGroup();
plData.menuText = tr("Type/State Filter");
plData.identifier = QLatin1String("fltTypeFilter");
plData.menuIcon = QIcon(QLatin1String("icon:filter_player.svg")); // ToDo: passendes Icon erstellen
plData.operatorRight = OperatorRights::FilterManagement::SymbolAppearanceEdit;
plData.exercisePart = LtsWidgets::ExercisePart::eSpecial;
plData.createWidgetFunc = [this](QWidget * parent)
{
return LtsWidgets::initDialog(new TypeFilterDialog(parent),
m_session);
};
ret.append(plData);
if (m_session->app() != LtsAppDescriptor::App::OC)
{
plData.menuGroup = menuGroup();
plData.menuText = tr("Collapse/Expand Participants");
plData.identifier = QLatin1String("fltColExpand");
plData.menuIcon = QIcon(QLatin1String("icon:filter_collapse_expand.svg"));
plData.operatorRight = OperatorRights::FilterManagement::SymbolAppearanceEdit; // FIXME!
plData.exercisePart = LtsWidgets::ExercisePart::eSpecial;
plData.createWidgetFunc = [this](QWidget * parent)
{
return LtsWidgets::initDialog(new CollapseExpandParticipantDialog(parent),
m_session);
};
ret.append(plData);
}
} // if (showTypeStateColExp)
return ret;
}
void InterfaceImpl::onSymbolAppearanceChanged(const FilterManagement::SymbolAppearance &data, DataModification mod)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
auto it = m_symbolAppearanceMap.find(FilterKey{data.operatorId(), data.ctx()});
if (it != m_symbolAppearanceMap.end())
{
std::shared_ptr<SymbolAppearanceSettingsImpl> ret = it->second.lock();
if (ret && mod != DataModification::eRemoved)
ret->setSettingsFromData(data);
else
{
// Maybe the scvFilterManagement (hosted at svcExerciseEventManagement)
// is restarted. In that case the topics are removed from DDS.
// But when the svc is starting again, the data is inserted into this
// map again - but the callbacks are lost!! So some related dialog do
// not work anymore... :-(
// To avoid this, prevent 'used' SymbolAppearanceSettingsImpl from
// being removed:
if (!(ret && ret->hasChangedCallbacks()))
m_symbolAppearanceMap.erase(it);
}
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
std::shared_ptr<SymbolAppearanceSettings> InterfaceImpl::symbolAppearanceForOperator(int operatorId, const QString &context)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< ", operatorId=" << operatorId
<< ", context=" << context
<< ", m_session->toString " << m_session->toString();
std::shared_ptr<SymbolAppearanceSettingsImpl> ret;
auto it = m_symbolAppearanceMap.find({operatorId, context.toStdString()});
if (it != m_symbolAppearanceMap.end())
ret = it->second.lock();
if (!ret)
{
FilterManagement::SymbolAppearance filterData;
// it's 0 when there is not yet a filter for this operator, so set it here and use it for comparision
filterData.operatorId(operatorId);
filterData.ctx(context.toStdString());
std::function<bool(const FilterManagement::SymbolAppearance &)> func = [&filterData](const FilterManagement::SymbolAppearance &f)
{
if (f.operatorId() == filterData.operatorId() &&
f.ctx() == filterData.ctx())
{
filterData = f;
return true;
}
return false;
};
// 22.01.2025, Thoden: Nachtrag zu NLDEVCTRL-445: Projektion Filter und Kartenausschnitt
// GUEZE-3459: Hannas OPW: Hänger beim Login
// 1. waitForHistoricalData{SymbolAppearance|AesFilter|buildingComponentFilters}
// gehört eingentlich VOR fltDtc->{SymbolAppearance|AesFilter|buildingComponentFilters}
// 2. Da diese aber auf der PWS wohl wichtig waren, wird fetchInterfaces jeweils
// angepasst:
// waitForHistoricalData{SymbolAppearance|AesFilter|buildingComponentFilters} wird
// nicht mehr grundsätzlich, sondern nur auf der PWS ausgeführt:
// if (LtsProjectionWorkstation::LtsProjectionWorkstation::hasInstance())
// m_fltDtc->waitForHistoricalDataXXX(1000);
m_fltDtc->waitForHistoricalDataSymbolAppearance(1000);
m_fltDtc->symbolAppearances(func);
std::shared_ptr<ParticipantManagement::Interface::Dtc> dtcPpm;
m_session->getDtc<ParticipantManagement::DataInterface>(dtcPpm);
ret = std::make_shared<SymbolAppearanceSettingsImpl>(dtcPpm, m_session->workspaceId());
ret->setSettingsFromData(filterData);
m_symbolAppearanceMap[FilterKey(operatorId, context.toStdString())] = ret;
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< ", operatorId=" << operatorId
<< ", context=" << context;
return ret;
}
} //namespace FilterManagement
@@ -0,0 +1,85 @@
/**
* @RDE_HEADER@
* Gui Plugin for FilterManagement (Participant)
* $Id: flt_participant_plugin.h 50296 2020-03-09 15:45:03Z ehrlicher $
* $HeadURL: svn://slssvn/TDS/branches/product/devel/trunk/Lts/Plugins/FilterManagement/Gui/Participant/flt_participant_plugin.h $
* $Author: ehrlicher $
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#pragma once
#include <PluginInterfaces/gui_plugin_interface.h>
#include <Plugins/FilterManagement/flt_participant_plugin_interface.h>
#include <Plugins/FilterManagement/flt_data_plugin_interface.h>
namespace FilterManagement
{
class SymbolAppearanceSettingsImpl;
class GuiPlugin final : public QObject, public GuiPluginBase::Plugin
{
Q_PLUGIN_METADATA(IID "gui:3:flt.participant")
Q_INTERFACES(GuiPluginBase::Plugin)
Q_OBJECT
public:
GuiPlugin() = default;
~GuiPlugin() = default;
QString pluginName() override { return QLatin1String("FilterManagementParticipantGuiPlugin"); }
std::shared_ptr<GuiPluginBase::Interface> createGuiInterface(LtsSession::LtsSession *session) override;
bool availableInPartition(IDL::PartitionType partition) const override
{
return (partition == IDL::PartitionType::Global) ||
(partition == IDL::PartitionType::Exercise) ||
(partition == IDL::PartitionType::Replay);
}
};
// ...
class InterfaceImpl final : public QObject, public ForeignFltParticipantGuiInterface, public GuiPluginBase::Interface
{
Q_OBJECT
public:
explicit InterfaceImpl(LtsSession::LtsSession *session);
bool fetchInterfaces() override;
QString menuGroup() const override { return tr("Situation Map"); }
QVector<LtsWidgets::PluginData> getActions() override;
std::shared_ptr<SymbolAppearanceSettings> symbolAppearanceForOperator(int operatorId, const QString &context) override;
private slots:
void onSymbolAppearanceChanged(const SymbolAppearance &data, DataModification mod);
private:
// <operatorId, filter>
struct FilterKey
{
int operatorId = 0;
std::string context;
FilterKey() = default;
FilterKey(int _operatorId, const std::string &_context)
: operatorId(_operatorId)
, context(_context)
{}
bool operator<(const FilterKey &o) const
{
if (operatorId != o.operatorId)
return operatorId < o.operatorId;
return context < o.context;
}
};
std::map<FilterKey, std::weak_ptr<SymbolAppearanceSettingsImpl>> m_symbolAppearanceMap;
std::shared_ptr<FilterManagement::Interface::Dtc> m_fltDtc;
NGL::INGLLogger &m_logger;
};
} // namespace FilterManagement
@@ -0,0 +1,231 @@
/**
* @RDE_HEADER@
* FilterManagement - Aes Filter Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#include "flt_symbol_appearance_dialog.h"
#include "flt_symbol_appearance_widget.h"
#include <FilterManagement/Gui/FilterChange/flt_filter_change.h>
#include <LtsSession/lts_session_data.h>
#include <PluginInterfaces/gui_plugin_interface.h>
#include <ParticipantManagement/ppm_data_plugin_interface.h>
#include <FileManagement/flm_translation.h>
#include <QGridLayout>
#include <QJsonDocument>
namespace FilterManagement
{
SymbolAppearanceDialog::SymbolAppearanceDialog(QWidget *parent, bool isOc)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
, m_widget(new SymbolAppearanceWidget(this, isOc))
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_session(nullptr)
, m_logger(getLogger("SymbolAppearanceDialog"))
{
QGridLayout *gl = new QGridLayout(this);
gl->setMargin(0);
gl->addWidget(m_widget, 0, 0);
setOnlineHelpFilename(QStringLiteral("Situation-Symbol_Appearance"));
}
SymbolAppearanceDialog::~SymbolAppearanceDialog()
{
delete m_widget;
}
bool SymbolAppearanceDialog::init(LtsSession::LtsSession *session)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " m_session = " << session->toString();
m_session = session;
if (!session->getForeignGuiInterface(m_fltParticipantGuiIfc) ||
!session->getDtc<FilterManagement::DataInterface>(m_fltDtc) ||
!session->getFtc<FilterManagement::DataInterface>(m_fltFtc))
{
WARNING_LOG(m_logger) << "Can not use Filter Management";
return false;
}
// Save/Load from Library Button
m_buttonBox->connectLibraryButton(this,
&SymbolAppearanceDialog::onImportButtonClicked,
&SymbolAppearanceDialog::onExportButtonClicked);
if (!m_session->getForeignGuiInterface<FileManagement::ForeignGuiInterface>(m_flmGui))
{
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Library, false);
}
else
{
connect(m_fltDtc.get(), &Interface::Dtc::symbolAppearanceChanged,
this, &SymbolAppearanceDialog::onDataChanged);
}
std::shared_ptr<ParticipantManagement::Interface::Dtc> ppmDtc;
if (!session->getDtc<ParticipantManagement::DataInterface>(ppmDtc))
{
WARNING_LOG(m_logger) << "Can not get data interface for ParticipantManagement";
return false;
}
QMap<qint32, ParticipantManagement::Party> parties;
if (!ppmDtc->visibleParties(parties, LtsSessionData::LtsSessionData::getInstance()->getVisibleParties(m_session->exerciseId())))
return false;
auto symbolAppearanceSettings = m_fltParticipantGuiIfc->symbolAppearanceForOperator(LtsSessionData::LtsSessionData::getInstance()->getOperatorId(),
m_session->workspaceId());
if (FilterChangeDialog::isAvailableAtApp(m_session->app()))
{
m_buttonBox->getButton(LtsWidgets::DialogButton::Load)->setText(tr("Load filter"));
m_buttonBox->connectButton(LtsWidgets::DialogButton::Load,
this, &SymbolAppearanceDialog::onLoadButtonClicked);
}
// First init widget:
bool success = m_widget->init(parties, symbolAppearanceSettings);
// then connect:
connect(m_widget, &SymbolAppearanceWidget::changesMade,
this, &SymbolAppearanceDialog::slotChangesMade, Qt::UniqueConnection);
connect(m_widget, &SymbolAppearanceWidget::unknownChangesRecognized,
this, &SymbolAppearanceDialog::onUnknownChangesRecognized, Qt::UniqueConnection);
return success;
}
void SymbolAppearanceDialog::retranslate()
{
m_widget->retranslate();
// lupdate doesn't like translate(tr("foo")) ...
const QString txt(tr("Symbol Appearance"));
translate(txt);
m_uiRequirements->retranslate();
}
bool SymbolAppearanceDialog::apply()
{
m_widget->apply();
const SymbolAppearance symbolAppearance = m_widget->filter()->settingsToData();
auto cb = [symbolAppearance, this]() -> bool
{
return m_fltFtc->symbolAppearanceUpdateRequest(symbolAppearance, this);
};
m_requestHelper->addRequest(cb);
return m_requestHelper->startRequests();
}
void SymbolAppearanceDialog::dialogCanceled()
{
m_widget->dialogCanceled();
}
void SymbolAppearanceDialog::onSymbolAppearanceUpdateReply(const Core::FunctionReplyObject &replyObject)
{
m_requestHelper->requestReply(replyObject);
}
void SymbolAppearanceDialog::onLoadButtonClicked()
{
FilterChangeDialog *dialog = new FilterChangeDialog(this);
if (!dialog->init(m_session, SymbolAppearanceSettings::Part::Symbol))
{
delete dialog;
return;
}
dialog->setAttribute(Qt::WA_DeleteOnClose);
QObject::connect(dialog, &FilterChangeDialog::rejected, dialog, &FilterChangeDialog::deleteLater);
dialog->show();
}
void SymbolAppearanceDialog::onDataChanged(const FilterManagement::SymbolAppearance &data, DataModification modType)
{
if (modType != DataModification::eRemoved &&
data.operatorId() == LtsSessionData::LtsSessionData::getInstance()->getOperatorId())
{
auto symbolAppearanceSettings = m_fltParticipantGuiIfc->symbolAppearanceForOperator(LtsSessionData::LtsSessionData::getInstance()->getOperatorId(), m_session->workspaceId());
m_widget->onDataChanged(symbolAppearanceSettings);
// the data can be changed if another replay is selected or filter are loaded.
// So our widget has to be updated:
__unchange__();
}
}
void SymbolAppearanceDialog::onExportButtonClicked()
{
m_widget->apply();
const auto s = m_widget->filter();
QJsonObject saveObject;
saveObject[QStringLiteral("XmlType")] = FileManagement::toString(FileManagement::XmlType::FLTSymbolAppearance);
saveObject[QStringLiteral("content")] = s->settingsToJson();
const QJsonDocument saveDoc(saveObject);
DEBUG_LOG(m_logger) << "Saving: " << saveDoc.toJson();
int fileId = m_flmGui->saveFileContent(this, FileManagement::FileType::Xml, m_session->exerciseId(), saveDoc.toJson(QJsonDocument::Compact));
if (fileId > 0)
DEBUG_LOG(m_logger) << "Saved file with id = " << fileId;
else
ERROR_LOG(m_logger) << "Could not save file in library ";
}
void SymbolAppearanceDialog::onImportButtonClicked()
{
DEBUG_LOG(m_logger) << " onImportButtonClicked() ";
QByteArray content;
int fileId = m_flmGui->loadFileContent(this, content, {FileManagement::FileType::Xml}, m_session->exerciseId(), FileManagement::toString(FileManagement::XmlType::FLTSymbolAppearance));
if (fileId > 0)
{
if (!m_flmGui->isXmlType(content, FileManagement::toString(FileManagement::XmlType::FLTSymbolAppearance)))
{
QHash<LtsWidgets::Button, QString> texts({{LtsWidgets::Button::Yes, tr("Ok")}});
LtsWidgets::LtsMessageDialog::showMessage(this,
tr("Invalid xml file content"),
windowTitle(),
LtsWidgets::Behaviour::Modal,
LtsWidgets::Button::Yes,
texts);
}
else
{
const QJsonDocument loadDoc(QJsonDocument::fromJson(content));
DEBUG_LOG(m_logger) << "Loading: " << loadDoc.toJson();
m_widget->filter()->setSettings(loadDoc.object().value(QStringLiteral("content")).toObject(),
FilterManagement::SymbolAppearanceSettings::Part::Symbol);
const SymbolAppearance symbolAppearance = m_widget->filter()->settingsToData();
auto cb = [symbolAppearance, this]()
{
return m_fltFtc->symbolAppearanceUpdateRequest(symbolAppearance, this);
};
m_requestHelper->addRequest(cb);
m_requestHelper->startRequests();
}
}
}
void SymbolAppearanceDialog::onUnknownChangesRecognized()
{
DEBUG_LOG(m_logger) << " onUnknownChangesRecognized() ";
m_widget->updateGuiToFilter();
__unchange__();
}
} // namespace FilterManagement
@@ -0,0 +1,70 @@
/**
* @RDE_HEADER@
* FilterManagement - Participant Symbol Appearance Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#pragma once
#include "flt_symbol_appearance_widget.h"
#include <LtsWidgets/lts_dialog.h>
#include <LtsUtilsGuiDds/request_helper.h>
#include <FilterManagement/logger.h>
#include <LtsSession/lts_session.h>
#include <FilterManagement/flt_data_plugin_interface.h>
#include <FilterManagement/flt_participant_plugin_interface.h>
#include <FilterManagement/flt_aes_plugin_interface.h>
#include <FilterManagement/flt_symbol_appearance_settings.h>
#include <Plugins/FileManagement/flm_explorer_gui_plugin_interface.h>
namespace Ui
{
class SymbolAppearanceDialog;
}
namespace FilterManagement
{
// --------------------------------------------------------
// AesFilterDialog
// --------------------------------------------------------
class SymbolAppearanceDialog final : public LtsWidgets::LtsDialog
, private FilterManagement::Interface::Ftc::SymbolAppearanceUpdateReplyHandler
{
Q_OBJECT
public:
explicit SymbolAppearanceDialog(QWidget *parent = nullptr, bool isOc = false);
~SymbolAppearanceDialog();
bool init(LtsSession::LtsSession *session);
void retranslate() override;
private:
bool apply() override;
void dialogCanceled() override;
void onSymbolAppearanceUpdateReply(const Core::FunctionReplyObject &replyObject) override;
private Q_SLOTS:
void onLoadButtonClicked();
void onDataChanged(const FilterManagement::SymbolAppearance &data, DataModification modType);
void onExportButtonClicked();
void onImportButtonClicked();
void onUnknownChangesRecognized();
private:
std::shared_ptr<FilterManagement::Interface::Dtc> m_fltDtc;
std::shared_ptr<FilterManagement::Interface::Ftc> m_fltFtc;
std::shared_ptr<FilterManagement::ForeignFltParticipantGuiInterface> m_fltParticipantGuiIfc;
std::shared_ptr<FilterManagement::ForeignAesGuiInterface> m_fltAesIfc;
std::shared_ptr<FileManagement::ForeignGuiInterface> m_flmGui;
SymbolAppearanceWidget *m_widget;
LtsUtils::RequestHelper *m_requestHelper;
LtsSession::LtsSession *m_session;
NGL::INGLLogger &m_logger;
};
}
@@ -0,0 +1,528 @@
/**
* @RDE_HEADER@
* FilterManagement - Aes Filter Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#include "flt_symbol_appearance_widget.h"
#include "ui_flt_symbol_appearance_widget.h"
#include <ParticipantManagement/ppm.hpp>
#include <ParticipantManagement/ppm_translation.h>
#include <QTimer>
#include <QJsonDocument>
#include <QJsonObject>
#include <LtsWidgets/lts_dialog.h>
#include <LtsUtilsSettings/settings.h>
namespace FilterManagement
{
class PartyCheckBox final : public QCheckBox
{
Q_OBJECT
public:
explicit PartyCheckBox(int partyId, QWidget *parent = nullptr)
: QCheckBox(parent)
, m_partyId(partyId)
{}
int partyId() const { return m_partyId; }
private:
int m_partyId;
};
class BoolLocker
{
public:
explicit BoolLocker(bool &b)
: m_b(b)
{
m_b = true;
}
~BoolLocker()
{
m_b = false;
}
private:
bool &m_b;
};
SymbolAppearanceWidget::SymbolAppearanceWidget(QWidget *parent, bool isOC)
: QWidget(parent)
, m_bIgnoreUiSignals(false)
, m_ui(new Ui::SymbolAppearanceWidget)
, m_updateTimer(new QTimer(this))
, m_doUpdateViaCallback(true)
, m_logger(getLogger("SymbolAppearanceWidget"))
{
m_ui->setupUi(this);
initUiElements();
m_updateTimer->setSingleShot(true);
m_updateTimer->setInterval(500);
connect(m_updateTimer, &QTimer::timeout,
this, &SymbolAppearanceWidget::readUpdateFilterFromUi);
// GUEZE-1474: Name nur, wenn Umriss:
// the slots are executed in order of creation!?
connect(m_ui->cbShowBuildingOutline, &QCheckBox::clicked, this, [this] {
if (m_ui->cbShowBuildingOutline->isChecked())
{
m_ui->cbShowBuildingIdentifier->setEnabled(true);
}
else
{
m_ui->cbShowBuildingIdentifier->setEnabled(false);
m_ui->cbShowBuildingIdentifier->setChecked(false);
}
});
connect(m_ui->slSymbolScale, &QSlider::valueChanged,
this, &SymbolAppearanceWidget::onSymbolScaleChanged);
connect(m_ui->slSymbolTransparency, &QSlider::valueChanged,
this, &SymbolAppearanceWidget::onSymbolTransparencyChanged);
connect(m_ui->slSymbolFireEvenFlashing, &QSlider::valueChanged,
this, &SymbolAppearanceWidget::onSymbolFireEventFlashingChanged);
connect(m_ui->slHitLineDisplayLength, &QSlider::valueChanged,
this, &SymbolAppearanceWidget::onHitLineDisplayLengthChanged);
connect(m_ui->slLRFDisplayLength, &QSlider::valueChanged,
this, &SymbolAppearanceWidget::onLRFDisplayLengthChanged);
connect(m_ui->slLTDDisplayLength, &QSlider::valueChanged,
this, &SymbolAppearanceWidget::onLTDDisplayLengthChanged);
connect(m_ui->slMovementTrackLength, &QSlider::valueChanged,
this, &SymbolAppearanceWidget::onMovementTrackLengthChanged);
connect(m_ui->cbShowBuildingOutline, &QCheckBox::stateChanged,
this, &SymbolAppearanceWidget::readUpdateFilterFromUi);
connect(m_ui->cbShowBuildingIdentifier, &QCheckBox::stateChanged,
this, &SymbolAppearanceWidget::readUpdateFilterFromUi);
connect(m_ui->cbShowTrainingAreaBorder, &QCheckBox::stateChanged,
this, &SymbolAppearanceWidget::readUpdateFilterFromUi);
connect(m_ui->cbShowSpecialAreas, &QCheckBox::stateChanged,
this, &SymbolAppearanceWidget::readUpdateFilterFromUi);
connect(m_ui->cbShowFiringUnits, &QCheckBox::stateChanged,
this, &SymbolAppearanceWidget::readUpdateFilterFromUi);
connect(m_ui->slNasatNineLinerDisplayLength, &QSlider::valueChanged,
this, &SymbolAppearanceWidget::onNasatNineLinerDisplayLengthChanged);
for (QComboBox *cbx : {m_ui->cbBitError, m_ui->cbManipulation, m_ui->cbInvalidPosition, m_ui->cbSimulatedPosition, m_ui->cbUnitSymbols})
connect(cbx, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
this, &SymbolAppearanceWidget::readUpdateFilterFromUi);
// after connect so the slots for setting the labels are executed
m_ui->slSymbolScale->setValue(m_ui->slSymbolScale->maximum());
LtsWidgets::LtsDialog::setMinWidthForWidgetHelper(m_ui->lbSymbolScaleVal);
m_ui->slSymbolTransparency->setValue(m_ui->slSymbolTransparency->minimum());
LtsWidgets::LtsDialog::setMinWidthForWidgetHelper(m_ui->lbSymbolTransparencyVal);
m_ui->slSymbolFireEvenFlashing->setValue(m_ui->slSymbolFireEvenFlashing->maximum());
LtsWidgets::LtsDialog::setMinWidthForWidgetHelper(m_ui->lbSymbolFireEventFlashingVal);
m_ui->slHitLineDisplayLength->setValue(m_ui->slHitLineDisplayLength->maximum());
LtsWidgets::LtsDialog::setMinWidthForWidgetHelper(m_ui->lbHitLineDisplayLengthVal);
m_ui->slLRFDisplayLength->setValue(m_ui->slLRFDisplayLength->maximum());
LtsWidgets::LtsDialog::setMinWidthForWidgetHelper(m_ui->lbLRFDisplayLengthVal);
m_ui->slLTDDisplayLength->setValue(m_ui->slLTDDisplayLength->maximum());
LtsWidgets::LtsDialog::setMinWidthForWidgetHelper(m_ui->lbLTDDisplayLengthVal);
m_ui->slMovementTrackLength->setValue(m_ui->slMovementTrackLength->maximum());
LtsWidgets::LtsDialog::setMinWidthForWidgetHelper(m_ui->lbMovementTrackLengthVal);
m_ui->slNasatNineLinerDisplayLength->setValue(m_ui->slNasatNineLinerDisplayLength->maximum());
LtsWidgets::LtsDialog::setMinWidthForWidgetHelper(m_ui->lbNasatNineLinerDisplayLengthVal);
// show / hide TrainingAreaBorder
LtsUtils::ProjectSettings *ps = LtsUtils::ProjectSettings::getInstance();
const bool enableTrainingAreaBorder =
ps->value(QStringLiteral("SituationMap"), QStringLiteral("enableTrainingAreaBorder"), false).toBool();
m_ui->lblShowTrainingAreaBorder->setVisible(enableTrainingAreaBorder);
m_ui->cbShowTrainingAreaBorder->setVisible(enableTrainingAreaBorder);
// const bool enableBuildingComponentFilterEdit = ps->value(QStringLiteral("flt"),
// QStringLiteral("enableBuildingComponentFilterEdit"), false).toBool();
// m_ui->lblShowBuildingIdentifier->setVisible(!enableBuildingComponentFilterEdit);
// m_ui->cbShowBuildingIdentifier->setVisible(!enableBuildingComponentFilterEdit);
// show / hide Guez NASAT
const bool enableGuezNasat = ps->value(QStringLiteral("gna"),
QStringLiteral("enableGuezNasat")).toBool();
m_ui->lblShowNasatNineLiner->setVisible(enableGuezNasat);
m_ui->slNasatNineLinerDisplayLength->setVisible(enableGuezNasat);
m_ui->lbNasatNineLinerDisplayLengthVal->setVisible(enableGuezNasat);
//Additionally hide specific things in OC:
if (isOC)
{
// no training area border
m_ui->lblShowTrainingAreaBorder->setVisible(false);
m_ui->cbShowTrainingAreaBorder->setVisible(false);
// no nasat
m_ui->lblShowNasatNineLiner->setVisible(false);
m_ui->slNasatNineLinerDisplayLength->setVisible(false);
m_ui->lbNasatNineLinerDisplayLengthVal->setVisible(false);
// no hitline
m_ui->lblHitlineDisplay->setVisible(false);
m_ui->slHitLineDisplayLength->setVisible(false);
m_ui->lbHitLineDisplayLengthVal->setVisible(false);
m_ui->lblLRFDisplay->setVisible(false);
m_ui->slLRFDisplayLength->setVisible(false);
m_ui->lblLTDDisplay->setVisible(false);
m_ui->slLTDDisplayLength->setVisible(false);
//no blink
m_ui->lblSymbolFireEventFlashing->setVisible(false);
m_ui->slSymbolFireEvenFlashing->setVisible(false);
m_ui->lbSymbolFireEventFlashingVal->setVisible(false);
//no bit error
m_ui->lblBitError->setVisible(false);
m_ui->cbBitError->setVisible(false);
//no sim pos
m_ui->lblSimPos->setVisible(false);
m_ui->cbSimulatedPosition->setVisible(false);
//no manipulation
m_ui->lblManipulation->setVisible(false);
m_ui->cbManipulation->setVisible(false);
//no manipulation
m_ui->lblInvalidPos->setVisible(false);
m_ui->cbInvalidPosition->setVisible(false);
//in Guez we don't use unit symbols right now
if (strcmp(PROJECTBUILD, "guez") == 0)
{
m_ui->lblUnitSymbols->setVisible(false);
m_ui->cbUnitSymbols->setVisible(false);
}
}
}
SymbolAppearanceWidget::~SymbolAppearanceWidget()
{
if (m_symbolAppearanceSettings)
m_symbolAppearanceSettings->removeChangedCallback(this);
delete m_ui;
}
bool SymbolAppearanceWidget::init(const QMap<int, ParticipantManagement::Party> &parties,
const std::shared_ptr<SymbolAppearanceSettings> &filter)
{
m_symbolAppearanceSettings = filter;
m_originalSymbolAppearance = m_symbolAppearanceSettings->settings();
buildPartyTable(parties);
setSymbolAppearanceSettings();
m_symbolAppearanceSettings->addChangedCallback(this);
return true;
}
void SymbolAppearanceWidget::retranslate()
{
BoolLocker l(m_bIgnoreUiSignals);
m_ui->retranslateUi(this);
initUiElements();
onSymbolScaleChanged();
onSymbolTransparencyChanged();
onSymbolFireEventFlashingChanged();
onHitLineDisplayLengthChanged();
onLRFDisplayLengthChanged();
onLTDDisplayLengthChanged();
onMovementTrackLengthChanged();
onNasatNineLinerDisplayLengthChanged();
}
template <typename T>
static void setComboBoxData(QComboBox *cbx, T val)
{
const int idxForVal = cbx->findData(static_cast<int>(val));
cbx->setCurrentIndex(idxForVal);
}
template <typename T>
static void readComboBoxData(QComboBox *cbx, T &val)
{
const QVariant v = cbx->currentData();
if (v.isValid())
val = static_cast<T>(v.toInt());
else
val = T();
}
void SymbolAppearanceWidget::setSymbolAppearanceSettings()
{
BoolLocker l(m_bIgnoreUiSignals);
const SymbolAppearanceSettings::Settings settings = m_symbolAppearanceSettings->settings();
const auto &s = settings.symbolSettings;
m_ui->slSymbolScale->setValue(qRound(s.symbolScale * 100)); // percent
m_ui->slSymbolTransparency->setValue(qRound(s.symbolTransparency * 100)); // percent
m_ui->slSymbolFireEvenFlashing->setValue(s.symbolFireEventFlashingMSec / 1000); // sec
m_ui->slHitLineDisplayLength->setValue(s.hitLineDisplayLengthMSec / 1000); // sec
m_ui->slLRFDisplayLength->setValue(s.lrfLineDisplayLengthMSec / 1000); // sec
m_ui->slLTDDisplayLength->setValue(s.ltdLineDisplayLengthMSec / 1000); // sec
m_ui->slMovementTrackLength->setValue(s.movementTrackLengthMSec / (60 * 1000)); // min
m_ui->cbShowBuildingOutline->setChecked(s.showBuildingOutline);
m_ui->cbShowBuildingIdentifier->setChecked(s.showBuildingIdentifier);
m_ui->cbShowTrainingAreaBorder->setChecked(s.showTrainingAreaBorder);
m_ui->cbShowSpecialAreas->setChecked(s.showSpecialAreas);
m_ui->cbShowFiringUnits->setChecked(s.showFiringUnits);
m_ui->slNasatNineLinerDisplayLength->setValue(s.nasatNineLinerDisplayLengthMSec / 1000);
setComboBoxData(m_ui->cbBitError, s.bitErrorVisibility);
setComboBoxData(m_ui->cbManipulation, s.manipulationVisibility);
setComboBoxData(m_ui->cbInvalidPosition, s.positionOutOfDateVisibility);
setComboBoxData(m_ui->cbSimulatedPosition, s.simulatedPositionVisibility);
setComboBoxData(m_ui->cbUnitSymbols, s.unitSymbolPosition);
for (PartyCheckBox *cb : qAsConst(m_visibleCont))
cb->setChecked(s.symbolPartyAppearance[cb->partyId()].isVisible);
for (PartyCheckBox *cb : qAsConst(m_designatorCont))
cb->setChecked(s.symbolPartyAppearance[cb->partyId()].showDesignator);
for (PartyCheckBox *cb : qAsConst(m_tactIdentCont))
cb->setChecked(s.symbolPartyAppearance[cb->partyId()].showTacticalIdentifier);
}
void SymbolAppearanceWidget::onSymbolScaleChanged()
{
m_ui->lbSymbolScaleVal->setText(tr("%1 %").arg(m_ui->slSymbolScale->value()));
m_updateTimer->start(); // restart
}
void SymbolAppearanceWidget::onSymbolTransparencyChanged()
{
m_ui->lbSymbolTransparencyVal->setText(tr("%1 %").arg(m_ui->slSymbolTransparency->value()));
m_updateTimer->start(); // restart
}
void SymbolAppearanceWidget::onSymbolFireEventFlashingChanged()
{
m_ui->lbSymbolFireEventFlashingVal->setText(tr("%1 sec").arg(m_ui->slSymbolFireEvenFlashing->value()));
m_updateTimer->start(); // restart
}
void SymbolAppearanceWidget::onHitLineDisplayLengthChanged()
{
m_ui->lbHitLineDisplayLengthVal->setText(tr("%1 sec").arg(m_ui->slHitLineDisplayLength->value()));
m_updateTimer->start(); // restart
}
void SymbolAppearanceWidget::onLRFDisplayLengthChanged()
{
m_ui->lbLRFDisplayLengthVal->setText(tr("%1 sec").arg(m_ui->slLRFDisplayLength->value()));
m_updateTimer->start(); // restart
}
void SymbolAppearanceWidget::onLTDDisplayLengthChanged()
{
m_ui->lbLTDDisplayLengthVal->setText(tr("%1 sec").arg(m_ui->slLTDDisplayLength->value()));
m_updateTimer->start(); // restart
}
void SymbolAppearanceWidget::onMovementTrackLengthChanged()
{
m_ui->lbMovementTrackLengthVal->setText(tr("%1 min").arg(m_ui->slMovementTrackLength->value()));
m_updateTimer->start(); // restart
}
void SymbolAppearanceWidget::onNasatNineLinerDisplayLengthChanged()
{
m_ui->lbNasatNineLinerDisplayLengthVal->setText(tr("%1 sec").arg(m_ui->slNasatNineLinerDisplayLength->value()));
m_updateTimer->start(); // restart
}
SymbolAppearanceSettings::Settings SymbolAppearanceWidget::getCurrentUiSettings() const
{
SymbolAppearanceSettings::Settings settings = m_symbolAppearanceSettings->settings();
auto &s = settings.symbolSettings;
s.symbolScale = m_ui->slSymbolScale->value() / 100.; // percent -> float
s.symbolTransparency = m_ui->slSymbolTransparency->value() / 100.; // percent -> float
s.symbolFireEventFlashingMSec = m_ui->slSymbolFireEvenFlashing->value() * 1000; // ms
s.hitLineDisplayLengthMSec = m_ui->slHitLineDisplayLength->value() * 1000; // ms
s.lrfLineDisplayLengthMSec = m_ui->slLRFDisplayLength->value() * 1000; // ms
s.ltdLineDisplayLengthMSec = m_ui->slLTDDisplayLength->value() * 1000; // ms
s.movementTrackLengthMSec = m_ui->slMovementTrackLength->value() * 60 * 1000; // ms
s.showBuildingOutline = m_ui->cbShowBuildingOutline->isChecked();
s.showBuildingIdentifier = m_ui->cbShowBuildingIdentifier->isChecked();
s.showTrainingAreaBorder = m_ui->cbShowTrainingAreaBorder->isChecked();
s.showSpecialAreas = m_ui->cbShowSpecialAreas->isChecked();
s.showFiringUnits = m_ui->cbShowFiringUnits->isChecked();
s.nasatNineLinerDisplayLengthMSec = m_ui->slNasatNineLinerDisplayLength->value() * 1000; // ms
readComboBoxData(m_ui->cbBitError, s.bitErrorVisibility);
readComboBoxData(m_ui->cbManipulation, s.manipulationVisibility);
readComboBoxData(m_ui->cbInvalidPosition, s.positionOutOfDateVisibility);
readComboBoxData(m_ui->cbSimulatedPosition, s.simulatedPositionVisibility);
readComboBoxData(m_ui->cbUnitSymbols, s.unitSymbolPosition);
for (PartyCheckBox *cb : qAsConst(m_visibleCont))
s.symbolPartyAppearance[cb->partyId()].isVisible = cb->isChecked();
for (PartyCheckBox *cb : qAsConst(m_designatorCont))
s.symbolPartyAppearance[cb->partyId()].showDesignator = cb->isChecked();
for (PartyCheckBox *cb : qAsConst(m_tactIdentCont))
s.symbolPartyAppearance[cb->partyId()].showTacticalIdentifier = cb->isChecked();
return settings;
}
void SymbolAppearanceWidget::onSymbolAppearanceSettingsChanged(SymbolAppearanceSettings::Part part)
{
Q_UNUSED(part);
DEBUG_LOG(m_logger) << LOGFUNCTION << " START, m_doUpdateViaCallback=" << m_doUpdateViaCallback;
if (m_doUpdateViaCallback)
{
updateGuiToFilter();
emit unknownChangesRecognized();
}
DEBUG_LOG(m_logger) << LOGFUNCTION << " END, m_doUpdateViaCallback=" << m_doUpdateViaCallback;
}
void SymbolAppearanceWidget::updateGuiToFilter()
{
this->onDataChanged(m_symbolAppearanceSettings);
}
void SymbolAppearanceWidget::readUpdateFilterFromUi()
{
if (!m_symbolAppearanceSettings || m_bIgnoreUiSignals)
return;
m_doUpdateViaCallback = false;
const SymbolAppearanceSettings::Settings &settings = getCurrentUiSettings();
m_symbolAppearanceSettings->setSettings(settings, FilterManagement::SymbolAppearanceSettings::Part::Symbol);
m_doUpdateViaCallback = true;
}
static void addSpacerItem(QGridLayout *gridLayout, int row, int col)
{
gridLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding), row, col, 1, 1, Qt::AlignHCenter | Qt::AlignVCenter);
}
void SymbolAppearanceWidget::buildPartyTable(const QMap<int, ParticipantManagement::Party> &parties)
{
m_visibleCont.clear();
m_designatorCont.clear();
m_tactIdentCont.clear();
QGridLayout *glParty = m_ui->glParty;
// first row is header
// remove all other rows (for reinit)
for (int row = glParty->rowCount() - 1; row > 0; --row)
{
for (int col = 0; col < glParty->columnCount(); ++col)
{
QLayoutItem *item = glParty->itemAtPosition(row, col);
if (!item)
continue;
delete item->widget();
}
}
const SymbolAppearanceSettings::Settings settings = m_symbolAppearanceSettings->settings();
const auto &s = settings.symbolSettings;
// <name> <spc> <cbDesignator> <spc> <spc> <cbTactIdent> <spc> <spc> <cbSimu> <spc>
int row = 1;
for (const ParticipantManagement::Party &party : parties)
{
const int partyId = party.id();
QLabel *lblParty = new QLabel(ParticipantManagement::trPartyName(party.name()), this);
int col = 0;
glParty->addWidget(lblParty, row, col++, 1, 1, Qt::AlignHCenter | Qt::AlignVCenter);
// <spc>
addSpacerItem(glParty, row, col++);
// <cbVisible>
{
PartyCheckBox *cbVisible = new PartyCheckBox(partyId, this);
cbVisible->setChecked(s.symbolPartyAppearance[partyId].showDesignator);
connect(cbVisible, &PartyCheckBox::stateChanged, this, &SymbolAppearanceWidget::readUpdateFilterFromUi);
glParty->addWidget(cbVisible, row, col++, 1, 1, Qt::AlignHCenter | Qt::AlignVCenter);
m_visibleCont += cbVisible;
}
// <spc>
addSpacerItem(glParty, row, col++);
// <spc>
addSpacerItem(glParty, row, col++);
// <cbDesignator>
{
PartyCheckBox *cbDesignator = new PartyCheckBox(partyId, this);
cbDesignator->setChecked(s.symbolPartyAppearance[partyId].showDesignator);
connect(cbDesignator, &PartyCheckBox::stateChanged, this, &SymbolAppearanceWidget::readUpdateFilterFromUi);
glParty->addWidget(cbDesignator, row, col++, 1, 1, Qt::AlignHCenter | Qt::AlignVCenter);
m_designatorCont += cbDesignator;
}
// <spc>
addSpacerItem(glParty, row, col++);
// <spc>
addSpacerItem(glParty, row, col++);
// <cbTactIdent>
{
PartyCheckBox *cbTactIdent = new PartyCheckBox(partyId, this);
cbTactIdent->setChecked(s.symbolPartyAppearance[partyId].showTacticalIdentifier);
connect(cbTactIdent, &PartyCheckBox::stateChanged, this, &SymbolAppearanceWidget::readUpdateFilterFromUi);
glParty->addWidget(cbTactIdent, row, col++, 1, 1, Qt::AlignHCenter | Qt::AlignVCenter);
m_tactIdentCont += cbTactIdent;
}
// <spc>
addSpacerItem(glParty, row, col++);
++row;
}
for (auto cb : qAsConst(m_visibleCont))
connect(cb, &QCheckBox::stateChanged, this, &SymbolAppearanceWidget::changesMade);
for (auto cb : qAsConst(m_designatorCont))
connect(cb, &QCheckBox::stateChanged, this, &SymbolAppearanceWidget::changesMade);
for (auto cb : qAsConst(m_tactIdentCont))
connect(cb, &QCheckBox::stateChanged, this, &SymbolAppearanceWidget::changesMade);
}
void SymbolAppearanceWidget::fillCbSymbolVisibility(QComboBox *cbx, int defaultValue)
{
const int idx = cbx->currentIndex();
cbx->clear();
cbx->addItem(tr("No change"), static_cast<int>(SymbolAppearanceSettings::SymbolVisibility::Standard));
cbx->addItem(tr("Fade"), static_cast<int>(SymbolAppearanceSettings::SymbolVisibility::Faded));
cbx->addItem(tr("Hide"), static_cast<int>(SymbolAppearanceSettings::SymbolVisibility::Hidden));
cbx->addItem(tr("Additional Symbol"), static_cast<int>(SymbolAppearanceSettings::SymbolVisibility::AdditionalSymbol));
cbx->setCurrentIndex(idx < 0 ? defaultValue : idx);
}
void SymbolAppearanceWidget::apply()
{
readUpdateFilterFromUi();
}
void SymbolAppearanceWidget::dialogCanceled()
{
m_symbolAppearanceSettings->setSettings(m_originalSymbolAppearance, FilterManagement::SymbolAppearanceSettings::Part::Symbol);
}
void SymbolAppearanceWidget::initUiElements()
{
fillCbSymbolVisibility(m_ui->cbBitError);
fillCbSymbolVisibility(m_ui->cbManipulation);
fillCbSymbolVisibility(m_ui->cbSimulatedPosition, static_cast<int>(SymbolAppearanceSettings::SymbolVisibility::AdditionalSymbol));
fillCbSymbolVisibility(m_ui->cbInvalidPosition);
const int idx = m_ui->cbUnitSymbols->currentIndex();
m_ui->cbUnitSymbols->clear();
m_ui->cbUnitSymbols->addItem(tr("Center"), static_cast<int>(SymbolAppearanceSettings::UnitSymbolPosition::Center));
m_ui->cbUnitSymbols->addItem(tr("Leader"), static_cast<int>(SymbolAppearanceSettings::UnitSymbolPosition::Leader));
m_ui->cbUnitSymbols->setCurrentIndex(idx < 0 ? 0 : idx);
}
void SymbolAppearanceWidget::onDataChanged(const std::shared_ptr<SymbolAppearanceSettings> &newFilter)
{
m_originalSymbolAppearance = newFilter->settings();
m_symbolAppearanceSettings = newFilter;
DEBUG_LOG(m_logger) << "onDataChanged ... " << QJsonDocument(newFilter->settingsToJson()).toJson();
setSymbolAppearanceSettings();
}
} // namespace FilterManagement
#include "flt_symbol_appearance_widget.moc"
@@ -0,0 +1,97 @@
/**
* @RDE_HEADER@
* FilterManagement - Participant Symbol Appearance Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#pragma once
#include <FilterManagement/logger.h>
#include <FilterManagement/flt_aes_plugin_interface.h>
#include <FilterManagement/flt_symbol_appearance_settings.h>
#include <QWidget>
#include <QVector>
class QComboBox;
class QTimer;
namespace ParticipantManagement
{
class Party;
}
namespace Ui
{
class SymbolAppearanceWidget;
}
namespace FilterManagement
{
class PartyCheckBox;
class DataInterface;
// --------------------------------------------------------
// AesFilterDialog
// --------------------------------------------------------
class SymbolAppearanceWidget final : public QWidget, public SymbolAppearanceSettings::SettingsChangedCallback
{
Q_OBJECT
public:
explicit SymbolAppearanceWidget(QWidget *parent = nullptr, bool isOC = false);
~SymbolAppearanceWidget();
void retranslate();
bool init(const QMap<int, ParticipantManagement::Party> &parties,
const std::shared_ptr<SymbolAppearanceSettings> &filter);
void apply();
void dialogCanceled();
std::shared_ptr<SymbolAppearanceSettings> filter() const { return m_symbolAppearanceSettings; }
void onDataChanged(const std::shared_ptr<SymbolAppearanceSettings> &newFilter);
SymbolAppearanceSettings::Settings getCurrentUiSettings() const;
void onSymbolAppearanceSettingsChanged(SymbolAppearanceSettings::Part part);
void updateGuiToFilter();
signals:
void changesMade();
void unknownChangesRecognized();
private slots:
void onSymbolScaleChanged();
void onSymbolTransparencyChanged();
void onSymbolFireEventFlashingChanged();
void onHitLineDisplayLengthChanged();
void onLRFDisplayLengthChanged();
void onLTDDisplayLengthChanged();
void onMovementTrackLengthChanged();
void onNasatNineLinerDisplayLengthChanged();
void readUpdateFilterFromUi();
private:
void setSymbolAppearanceSettings();
void buildPartyTable(const QMap<int, ParticipantManagement::Party> &parties);
static void fillCbSymbolVisibility(QComboBox *cbx, int defaultValue = 0);
void initUiElements();
private:
std::shared_ptr<SymbolAppearanceSettings> m_symbolAppearanceSettings;
SymbolAppearanceSettings::Settings m_originalSymbolAppearance;
QVector<PartyCheckBox *> m_visibleCont;
QVector<PartyCheckBox *> m_designatorCont;
QVector<PartyCheckBox *> m_tactIdentCont;
bool m_bIgnoreUiSignals;
Ui::SymbolAppearanceWidget *m_ui;
QTimer *m_updateTimer;
bool m_doUpdateViaCallback;
NGL::INGLLogger &m_logger;
};
}
@@ -0,0 +1,675 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SymbolAppearanceWidget</class>
<widget class="QWidget" name="SymbolAppearanceWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1024</width>
<height>326</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Symbol Apperance</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="1">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item row="0" column="2">
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="3">
<widget class="QLabel" name="lbSymbolTransparencyVal">
<property name="text">
<string notr="true">%1 %</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="8" column="2">
<widget class="QCheckBox" name="cbShowBuildingOutline">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLabel" name="lbSymbolScaleVal">
<property name="text">
<string notr="true">%1 %</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="11" column="0">
<widget class="QLabel" name="lblShowSpecialAreas">
<property name="text">
<string>Special Areas:</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QSlider" name="slSymbolTransparency">
<property name="minimumSize">
<size>
<width>150</width>
<height>0</height>
</size>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>90</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="5" column="3">
<widget class="QLabel" name="lbLTDDisplayLengthVal">
<property name="text">
<string>%1 sec</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QLabel" name="lblHitlineDisplay">
<property name="text">
<string>Hit Line Display Length:</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QSlider" name="slHitLineDisplayLength">
<property name="maximum">
<number>120</number>
</property>
<property name="singleStep">
<number>5</number>
</property>
<property name="value">
<number>10</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickInterval">
<number>5</number>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QSlider" name="slLRFDisplayLength">
<property name="maximum">
<number>120</number>
</property>
<property name="singleStep">
<number>5</number>
</property>
<property name="value">
<number>10</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickInterval">
<number>5</number>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Symbol Scale:</string>
</property>
</widget>
</item>
<item row="11" column="2">
<widget class="QCheckBox" name="cbShowSpecialAreas">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="4" column="3">
<widget class="QLabel" name="lbLRFDisplayLengthVal">
<property name="text">
<string>%1 sec</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="lblLRFDisplay">
<property name="text">
<string>LRF Display Length:</string>
</property>
</widget>
</item>
<item row="6" column="3">
<widget class="QLabel" name="lbNasatNineLinerDisplayLengthVal">
<property name="text">
<string>%1 sec</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QLabel" name="lblSymbolFireEventFlashing">
<property name="text">
<string>Symbol Flashing:</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="lblShowNasatNineLiner">
<property name="text">
<string>NASAT Nine-Liner:</string>
</property>
</widget>
</item>
<item row="13" column="1">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>32</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="3">
<widget class="QLabel" name="lbSymbolFireEventFlashingVal">
<property name="text">
<string>%1 sec</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QLabel" name="lblShowTrainingAreaBorder">
<property name="text">
<string>Training Area Border:</string>
</property>
</widget>
</item>
<item row="9" column="2">
<widget class="QCheckBox" name="cbShowBuildingIdentifier">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="lblMovementTrack">
<property name="text">
<string>Movement Track Length:</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QSlider" name="slSymbolFireEvenFlashing">
<property name="maximum">
<number>120</number>
</property>
<property name="singleStep">
<number>5</number>
</property>
<property name="value">
<number>10</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickInterval">
<number>5</number>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="lblShowBuildingOutline">
<property name="text">
<string>Building Outline:</string>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QSlider" name="slLTDDisplayLength">
<property name="maximum">
<number>120</number>
</property>
<property name="singleStep">
<number>5</number>
</property>
<property name="value">
<number>10</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickInterval">
<number>5</number>
</property>
</widget>
</item>
<item row="10" column="2">
<widget class="QCheckBox" name="cbShowTrainingAreaBorder">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QSlider" name="slSymbolScale">
<property name="minimumSize">
<size>
<width>150</width>
<height>0</height>
</size>
</property>
<property name="minimum">
<number>10</number>
</property>
<property name="maximum">
<number>400</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="6" column="2">
<widget class="QSlider" name="slNasatNineLinerDisplayLength">
<property name="maximum">
<number>200</number>
</property>
<property name="singleStep">
<number>5</number>
</property>
<property name="value">
<number>100</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickInterval">
<number>5</number>
</property>
</widget>
</item>
<item row="7" column="2">
<widget class="QSlider" name="slMovementTrackLength">
<property name="minimumSize">
<size>
<width>150</width>
<height>0</height>
</size>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>30</number>
</property>
<property name="value">
<number>1</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="lblLTDDisplay">
<property name="text">
<string>LTD Display Length:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Symbol Transparency:</string>
</property>
</widget>
</item>
<item row="7" column="3">
<widget class="QLabel" name="lbMovementTrackLengthVal">
<property name="text">
<string notr="true">%1 min</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="lblShowBuildingIdentifier">
<property name="text">
<string>Building Name:</string>
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="QLabel" name="lbHitLineDisplayLengthVal">
<property name="text">
<string>%1 sec</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="12" column="0">
<widget class="QLabel" name="lblShowSpecialAreas_2">
<property name="text">
<string>Firing Units:</string>
</property>
</widget>
</item>
<item row="12" column="2">
<widget class="QCheckBox" name="cbShowFiringUnits">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="4">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="lblBitError">
<property name="text">
<string>BIT-Error:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="LtsWidgets::LtsComboBox" name="cbBitError"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="lblManipulation">
<property name="text">
<string>Manipulation:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="LtsWidgets::LtsComboBox" name="cbManipulation"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="lblInvalidPos">
<property name="text">
<string>Invalid Position:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="LtsWidgets::LtsComboBox" name="cbInvalidPosition"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="lblUnitSymbols">
<property name="text">
<string>Unit Symbols:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="LtsWidgets::LtsComboBox" name="cbUnitSymbols"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="lblSimPos">
<property name="text">
<string>Simulated Position:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="LtsWidgets::LtsComboBox" name="cbSimulatedPosition"/>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="0" column="5">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>2</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QGridLayout" name="glParty">
<item row="1" column="1">
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>13</width>
<height>14</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="4">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>13</width>
<height>14</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="4" colspan="3">
<widget class="QLabel" name="label">
<property name="text">
<string>Designator</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="1" column="6">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>13</width>
<height>14</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="7" colspan="3">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Tact. Identifier</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string notr="true">Party 1</string>
</property>
</widget>
</item>
<item row="1" column="9">
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>13</width>
<height>14</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="5">
<widget class="QCheckBox" name="cbDesignator">
<property name="text">
<string notr="true"/>
</property>
</widget>
</item>
<item row="1" column="8">
<widget class="QCheckBox" name="cbTactIdentifier">
<property name="text">
<string notr="true"/>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QCheckBox" name="cbDesignator_2">
<property name="text">
<string notr="true"/>
</property>
</widget>
</item>
<item row="1" column="7">
<spacer name="horizontalSpacer_7">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>13</width>
<height>14</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="3">
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>13</width>
<height>14</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1" colspan="3">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Visible</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="0" column="3">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsWidgets::LtsComboBox</class>
<extends>QComboBox</extends>
<header>LtsWidgets/lts_combo_box.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>cbDesignator_2</tabstop>
<tabstop>cbDesignator</tabstop>
<tabstop>cbTactIdentifier</tabstop>
<tabstop>slSymbolScale</tabstop>
<tabstop>slSymbolTransparency</tabstop>
<tabstop>slSymbolFireEvenFlashing</tabstop>
<tabstop>slHitLineDisplayLength</tabstop>
<tabstop>cbBitError</tabstop>
<tabstop>cbManipulation</tabstop>
<tabstop>cbInvalidPosition</tabstop>
<tabstop>cbSimulatedPosition</tabstop>
<tabstop>cbUnitSymbols</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,216 @@
#include "flt_type_filter_dialog.h"
#include <FilterManagement/Gui/FilterChange/flt_filter_change.h>
#include <LtsSession/lts_session_data.h>
#include <LtsSession/lts_session_manager.h>
#include <FileManagement/flm_translation.h>
#include <QVBoxLayout>
#include <QGroupBox>
#include <QJsonDocument>
#include <QCheckBox>
namespace FilterManagement
{
TypeFilterDialog::TypeFilterDialog(QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
, m_session(nullptr)
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_widget(new TypeFilterWidget(this))
, m_logger(getLogger("TypeFilterDialog"))
{
QGridLayout *gl = new QGridLayout(this);
gl->setMargin(0);
gl->addWidget(m_widget, 0, 0);
connect(m_widget, &TypeFilterWidget::partyChanged, this, &TypeFilterDialog::__unchange__);
connect(m_widget, &TypeFilterWidget::typeFilterChanged, this, &TypeFilterDialog::onTypeFilterClicked);
setOnlineHelpFilename(QStringLiteral("Situation-Type-State_Filter"));
}
TypeFilterDialog::~TypeFilterDialog()
{}
void TypeFilterDialog::retranslate()
{
// lupdate doesn't like translate(tr("foo")) ...
const QString txt(tr("Type/State Filter"));
translate(txt);
m_widget->retranslate();
m_uiRequirements->retranslate();
}
bool TypeFilterDialog::init(LtsSession::LtsSession *session)
{
m_session = session;
std::shared_ptr<ParticipantManagement::Interface::Dtc> ppmDtc;
std::shared_ptr<ParticipantManagement::ForeignGuiComboboxInterface> ppmGuiCbxIfc;
if (!session->getForeignGuiInterface<ParticipantManagement::ForeignGuiComboboxInterface>(ppmGuiCbxIfc) ||
!session->getForeignGuiInterface(m_fltParticipantIfc) ||
!session->getDtc<FilterManagement::DataInterface>(m_fltDtc) ||
!session->getFtc<FilterManagement::DataInterface>(m_fltFtc))
{
WARNING_LOG(m_logger) << "Can not use Filter Management";
return false;
}
if (!session->getDtc<ParticipantManagement::DataInterface>(ppmDtc))
{
WARNING_LOG(m_logger) << "Can not get data interface for Participant Management";
return false;
}
// Save/Load from Library Button
m_buttonBox->connectLibraryButton(this,
&TypeFilterDialog::onImportButtonClicked,
&TypeFilterDialog::onExportButtonClicked);
if (!m_session->getForeignGuiInterface<FileManagement::ForeignGuiInterface>(m_flmGui))
{
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Library, false);
}
else
{
connect(m_fltDtc.get(), &Interface::Dtc::symbolAppearanceChanged,
this, &TypeFilterDialog::onDataChanged);
}
if (FilterChangeDialog::isAvailableAtApp(m_session->app()))
{
m_buttonBox->getButton(LtsWidgets::DialogButton::Load)->setText(tr("Load filter"));
m_buttonBox->connectButton(LtsWidgets::DialogButton::Load,
this, &TypeFilterDialog::onLoadButtonClicked);
}
auto symbolAppearanceSettings = m_fltParticipantIfc->symbolAppearanceForOperator(LtsSessionData::LtsSessionData::getInstance()->getOperatorId(),
m_session->workspaceId());
#ifdef GUEZ_MODE
bool success = m_widget->init(ppmDtc, ppmGuiCbxIfc, symbolAppearanceSettings,
(m_session->app() == LtsAppDescriptor::App::OC) || (LtsSessionData::LtsSessionData::getInstance()->isTablet()));
#else
bool success = m_widget->init(ppmDtc, ppmGuiCbxIfc, symbolAppearanceSettings, false); //in AHCT we have units!
#endif
return success;
}
bool TypeFilterDialog::apply()
{
m_widget->apply();
const SymbolAppearance symbolAppearance = m_widget->filter()->settingsToData();
auto cb = [this, symbolAppearance]()
{
return m_fltFtc->symbolAppearanceUpdateRequest(symbolAppearance, this);
};
m_requestHelper->addRequest(cb);
return m_requestHelper->startRequests();
}
void TypeFilterDialog::onSymbolAppearanceUpdateReply(const Core::FunctionReplyObject &replyObject)
{
m_requestHelper->requestReply(replyObject);
}
void TypeFilterDialog::dialogCanceled()
{
m_widget->dialogCanceled();
}
void TypeFilterDialog::onTypeFilterClicked()
{
m_buttonBox->getButton(LtsWidgets::DialogButton::Ok)->setEnabled(true);
m_buttonBox->getButton(LtsWidgets::DialogButton::Apply)->setEnabled(true);
}
void TypeFilterDialog::onLoadButtonClicked()
{
FilterChangeDialog *dialog = new FilterChangeDialog(this);
if (!dialog->init(m_session, SymbolAppearanceSettings::Part::Types))
{
delete dialog;
return;
}
dialog->setAttribute(Qt::WA_DeleteOnClose);
QObject::connect(dialog, &FilterChangeDialog::rejected, dialog, &FilterChangeDialog::deleteLater);
dialog->show();
}
void TypeFilterDialog::onDataChanged(const FilterManagement::SymbolAppearance &data, DataModification modType)
{
if (modType != DataModification::eRemoved &&
data.operatorId() == LtsSessionData::LtsSessionData::getInstance()->getOperatorId())
{
auto symbolAppearanceSettings = m_fltParticipantIfc->symbolAppearanceForOperator(LtsSessionData::LtsSessionData::getInstance()->getOperatorId(),
m_session->workspaceId());
m_widget->onDataChanged(symbolAppearanceSettings);
// the data can be changed if another replay is selected or filter are loaded.
// So our widget has to be updated:
__unchange__();
}
}
void TypeFilterDialog::onExportButtonClicked()
{
m_widget->apply();
const auto s = m_widget->filter();
QJsonObject saveObject;
saveObject[QStringLiteral("XmlType")] = FileManagement::toString(FileManagement::XmlType::FLTTypeFilter);
saveObject[QStringLiteral("content")] = s->settingsToJson();
const QJsonDocument saveDoc(saveObject);
DEBUG_LOG(m_logger) << "Saving: " << saveDoc.toJson();
int fileId = m_flmGui->saveFileContent(this, FileManagement::FileType::Xml, m_session->exerciseId(), saveDoc.toJson(QJsonDocument::Compact));
if (fileId > 0)
DEBUG_LOG(m_logger) << "Saved file with id = " << fileId;
else
ERROR_LOG(m_logger) << "Could not save file in library ";
}
void TypeFilterDialog::onImportButtonClicked()
{
DEBUG_LOG(m_logger) << " onImportButtonClicked() ";
QByteArray content;
int fileId = m_flmGui->loadFileContent(this, content, {FileManagement::FileType::Xml}, m_session->exerciseId(), FileManagement::toString(FileManagement::XmlType::FLTTypeFilter));
if (fileId > 0)
{
if (!m_flmGui->isXmlType(content, FileManagement::toString(FileManagement::XmlType::FLTTypeFilter)))
{
QHash<LtsWidgets::Button, QString> texts({{LtsWidgets::Button::Yes, tr("Ok")}});
LtsWidgets::LtsMessageDialog::showMessage(this,
tr("Invalid xml file content"),
windowTitle(),
LtsWidgets::Behaviour::Modal,
LtsWidgets::Button::Yes,
texts);
}
else
{
const QJsonDocument loadDoc(QJsonDocument::fromJson(content));
DEBUG_LOG(m_logger) << "Loading: " << loadDoc.toJson();
m_widget->filter()->setSettings(loadDoc.object().value(QStringLiteral("content")).toObject(),
FilterManagement::SymbolAppearanceSettings::Part::Types);
const SymbolAppearance symbolAppearance = m_widget->filter()->settingsToData();
auto cb = [symbolAppearance, this]()
{
return m_fltFtc->symbolAppearanceUpdateRequest(symbolAppearance, this);
};
m_requestHelper->addRequest(cb);
m_requestHelper->startRequests();
}
}
}
} // namespace FilterManagement
@@ -0,0 +1,62 @@
/**
* @RDE_HEADER@
* FilterManagement - Type Filter Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#pragma once
#include <LtsWidgets/lts_dialog.h>
#include <LtsUtilsGuiDds/request_helper.h>
#include <FilterManagement/logger.h>
#include <Plugins/ParticipantManagement/ppm_data_plugin_interface.h>
#include <LtsSession/lts_session.h>
#include <FilterManagement/flt_data_plugin_interface.h>
#include <FilterManagement/flt_participant_plugin_interface.h>
#include <FilterManagement/flt_symbol_appearance_settings.h>
#include <FileManagement/flm_explorer_gui_plugin_interface.h>
#include <ParticipantManagement/ppm_gui_combobox_plugin_interface.h>
#include "flt_type_filter_widget.h"
namespace FilterManagement
{
class TypeFilterDialog final : public LtsWidgets::LtsDialog
, private FilterManagement::Interface::Ftc::SymbolAppearanceUpdateReplyHandler
{
Q_OBJECT
public:
explicit TypeFilterDialog(QWidget *parent = nullptr);
~TypeFilterDialog();
bool init(LtsSession::LtsSession *session);
void retranslate() override;
private:
bool apply() override;
void dialogCanceled() override;
void onSymbolAppearanceUpdateReply(const Core::FunctionReplyObject &replyObject) override;
private Q_SLOTS:
void onTypeFilterClicked();
void onLoadButtonClicked();
void onDataChanged(const FilterManagement::SymbolAppearance &data, DataModification modType);
void onExportButtonClicked();
void onImportButtonClicked();
private:
LtsSession::LtsSession *m_session;
std::shared_ptr<FilterManagement::Interface::Dtc> m_fltDtc;
std::shared_ptr<FilterManagement::Interface::Ftc> m_fltFtc;
std::shared_ptr<FilterManagement::ForeignFltParticipantGuiInterface> m_fltParticipantIfc;
std::shared_ptr<FileManagement::ForeignGuiInterface> m_flmGui;
LtsUtils::RequestHelper *m_requestHelper;
TypeFilterWidget *m_widget;
NGL::INGLLogger &m_logger;
};
}
@@ -0,0 +1,405 @@
/**
* @RDE_HEADER@
* FilterManagement - Type Filter Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#include "flt_type_filter_widget.h"
#include "ui_flt_type_filter_widget.h"
#include <ParticipantManagement/ppm_translation.h>
#include <ProjectDataManagement/pdm_translation.h>
#include <LtsWidgets/lts_message_dialog.h>
#include <QCheckBox>
#include <QGroupBox>
#include <QPushButton>
#include <QVBoxLayout>
namespace FilterManagement
{
TypeFilterWidget::TypeFilterWidget(QWidget *parent)
: QWidget(parent)
, m_hiddenTypeFilter(QSet<int>())
, m_hiddenStateFilter(QSet<int>())
, m_partyId(0)
, m_gridLayout(new QGridLayout)
, m_ui(new Ui::TypeFilterWidget)
, m_logger(getLogger("TypeFilterWidget"))
{
m_ui->setupUi(this);
initStateElements();
connect(m_ui->cbParty, &LtsWidgets::LtsComboBox::currentTextChanged, this, &TypeFilterWidget::onPartyChanged);
}
TypeFilterWidget::~TypeFilterWidget()
{
delete m_ui;
}
void TypeFilterWidget::retranslate()
{
m_ui->retranslateUi(this);
}
void TypeFilterWidget::initTypeClassElements(bool ocMode)
{
static const auto typeClassesUnit = {ParticipantManagement::TypeClass_def::Unit,
ParticipantManagement::TypeClass_def::SupportUnit,
};
static const auto typeClasses = {ParticipantManagement::TypeClass_def::SupportEntity,
ParticipantManagement::TypeClass_def::Human,
ParticipantManagement::TypeClass_def::GroundVehicle,
ParticipantManagement::TypeClass_def::VehicleWithGear,
ParticipantManagement::TypeClass_def::WeaponSystem,
ParticipantManagement::TypeClass_def::Aircraft,
ParticipantManagement::TypeClass_def::Vessel,
};
if (!ocMode)
{
for (auto typeClass : typeClassesUnit)
createTypeClass(typeClass);
}
for (auto typeClass : typeClasses)
createTypeClass(typeClass);
m_ui->gBTypes->setLayout(m_gridLayout);
}
void TypeFilterWidget::initStateElements()
{
QVBoxLayout *vBox = new QVBoxLayout;
// Getting the states from the enum definition (without the last three, which have other purposes)
for (int enumIt = 0; enumIt <= ProjectDataManagement::VulnerabilityState_def::TemporarySeverance; ++enumIt)
{
QCheckBox *chb = new QCheckBox(m_ui->gBStates);
// Set the text for the checkbox = name of enum value
chb->setText(ProjectDataManagement::toString(
static_cast<ProjectDataManagement::VulnerabilityState_def::type>(enumIt)));
// Name the object as 'chb' + name of enum value; e.g. chbCombatReady
chb->setObjectName(QStringLiteral("chb%1").arg(ProjectDataManagement::toString(
static_cast<ProjectDataManagement::VulnerabilityState_def::type>(enumIt))));
chb->setProperty("stateId", enumIt);
connect(chb, &QCheckBox::clicked, this, &TypeFilterWidget::onTypeFilterChanged);
vBox->addWidget(chb);
}
vBox->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding));
m_ui->gBStates->setLayout(vBox);
}
bool TypeFilterWidget::init(const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc,
const std::shared_ptr<ParticipantManagement::ForeignGuiComboboxInterface> &ppmIfc,
const std::shared_ptr<SymbolAppearanceSettings> &filter,
bool ocMode)
{
m_ppmDtc = ppmDtc;
m_symbolAppearanceSettings = filter;
m_originalSymbolAppearance = m_symbolAppearanceSettings->settings();
setSymbolAppearanceSettings();
initTypeClassElements(ocMode);
ppmIfc->fillPartyComboBox(m_ui->cbParty, ParticipantManagement::ForeignGuiComboboxInterface::CbxPartyFilter::NormalOc);
onPartyChanged();
return true;
}
void TypeFilterWidget::createTypeClass(ParticipantManagement::TypeClass typeClass)
{
QGroupBox *gb = new QGroupBox;
m_gbTypes.insert(typeClass, gb);
QGridLayout *gridLayout = new QGridLayout;
gb->setTitle(ParticipantManagement::toString(typeClass));
gb->setLayout(gridLayout);
// Button to check/uncheck all checkboxes
QPushButton *btnCheckAll = new QPushButton(gb);
connect(btnCheckAll, &QPushButton::clicked, this, &TypeFilterWidget::onCheckUncheckAllClicked);
// Small horizontal layout, so the button doesn't take full width
QHBoxLayout *btnHBL = new QHBoxLayout;
btnHBL->addWidget(btnCheckAll);
btnHBL->addStretch();
gridLayout->addLayout(btnHBL, 0, 0, 1, 5);
const QMap<qint32, ParticipantManagement::Type> typeMap = m_ppmDtc->types();
const int maxRow = 25;
int iRow = 1;
int iCol = 0;
QMap<std::string, ParticipantManagement::Type> typeMapOrder;
for (const ParticipantManagement::Type &type : typeMap)
typeMapOrder.insert(type.name(), type);
for (const ParticipantManagement::Type &type : qAsConst(typeMapOrder))
{
//removed types are still in the list! ignore deleted!
if (type.isDeleted())
continue;
// skip types not in use in this exercise
if (!m_ppmDtc->isTypeInUse(type.id()))
continue;
if (type.typeClass() == typeClass)
{
QCheckBox *cb = new QCheckBox(gb);
cb->setText(ParticipantManagement::trTypeName(type.name()));
cb->setProperty("typeId", type.id());
cb->setProperty("typeClassId", typeClass.underlying());
if (!m_hiddenTypeFilter.contains(type.id()))
cb->setChecked(true);
connect(cb, &QCheckBox::clicked, this, &TypeFilterWidget::onTypeFilterChanged);
gridLayout->addWidget(cb, iRow, iCol);
++iRow;
if (iRow > maxRow)
{
iRow = 1;
++iCol;
}
}
}
iRow = iCol == 0 ? iRow : maxRow;
gridLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding), iRow, 0);
m_gridLayout->addWidget(gb, 0, m_gridLayout->columnCount());
}
void TypeFilterWidget::setGroupBoxesVisible(const bool bShowOC)
{
for (auto it = m_gbTypes.cbegin(); it != m_gbTypes.cend(); ++it)
{
QGroupBox *gb = it.value();
const auto tc = it.key();
const bool bIsOc = tc == ParticipantManagement::TypeClass_def::SupportEntity ||
tc == ParticipantManagement::TypeClass_def::SupportUnit;
bool bShow = bShowOC ? bIsOc : !bIsOc;
if (bShow && !gb->findChild<QCheckBox*>())
bShow = false;
gb->setVisible(bShow);
}
}
void TypeFilterWidget::setSymbolAppearanceSettings()
{
const SymbolAppearanceSettings::Settings &s = m_symbolAppearanceSettings->settings();
m_hiddenTypeFilter = s.hiddenTypeFilter.value(m_partyId);
m_hiddenStateFilter = s.hiddenStateFilter.value(m_partyId);
}
void TypeFilterWidget::apply()
{
const SymbolAppearanceSettings::Settings &s = getCurrentUiSettings();
m_symbolAppearanceSettings->setSettings(s, FilterManagement::SymbolAppearanceSettings::Part::Types);
setWindowModified(false);
}
SymbolAppearanceSettings::Settings TypeFilterWidget::getCurrentUiSettings()
{
const auto gbs(m_ui->gBTypes->findChildren<QGroupBox *>(QString(), Qt::FindDirectChildrenOnly));
for (QGroupBox *gb : gbs)
setHiddenTypeFilter(gb);
setHiddenStateFilter();
SymbolAppearanceSettings::Settings s = m_symbolAppearanceSettings->settings();
s.hiddenTypeFilter.insert(m_partyId, m_hiddenTypeFilter);
s.hiddenStateFilter.insert(m_partyId, m_hiddenStateFilter);
return s;
}
void TypeFilterWidget::dialogCanceled()
{
m_symbolAppearanceSettings->setSettings(m_originalSymbolAppearance, FilterManagement::SymbolAppearanceSettings::Part::Types);
}
void TypeFilterWidget::onDataChanged(const std::shared_ptr<SymbolAppearanceSettings> &newFilter)
{
m_originalSymbolAppearance = newFilter->settings();
m_symbolAppearanceSettings = newFilter;
setSymbolAppearanceSettings();
onReinitTypeFilterCbx();
updateStateFilter();
}
void TypeFilterWidget::setHiddenTypeFilter(QGroupBox *gb)
{
if (gb)
{
const QList<QCheckBox *> listCbs = gb->findChildren<QCheckBox *>();
for (QCheckBox *cb : listCbs)
{
int typeId = cb->property("typeId").toInt();
if (cb->checkState() == Qt::Checked)
m_hiddenTypeFilter.remove(typeId);
else
m_hiddenTypeFilter.insert(typeId);
}
}
}
void TypeFilterWidget::setHiddenStateFilter()
{
const auto cbs(m_ui->gBStates->findChildren<QCheckBox *>(QString(), Qt::FindDirectChildrenOnly));
for (QCheckBox *chb : cbs)
{
if (chb->isChecked())
m_hiddenStateFilter.remove(chb->property("stateId").toInt());
else
m_hiddenStateFilter.insert(chb->property("stateId").toInt());
}
}
void TypeFilterWidget::updateStateFilter()
{
const auto cbs(m_ui->gBStates->findChildren<QCheckBox *>(QString(), Qt::FindDirectChildrenOnly));
for (QCheckBox *chb : cbs)
chb->setChecked(!m_hiddenStateFilter.contains(chb->property("stateId").toInt()));
}
void TypeFilterWidget::onReinitTypeFilterCbx()
{
int partyId = m_ui->cbParty->currentData().toInt();
for (QGroupBox *gb : qAsConst(m_gbTypes))
{
const QList<QCheckBox *> checkBoxes = gb->findChildren<QCheckBox *>();
bool bAtLeastOneUnchecked = false;
for (QCheckBox *cb : checkBoxes)
{
const bool bIsChecked = !m_hiddenTypeFilter.contains(cb->property("typeId").toInt());
cb->setChecked(bIsChecked);
if (!bIsChecked)
bAtLeastOneUnchecked = true;
}
adjustCheckButtonText(gb, bAtLeastOneUnchecked);
}
setGroupBoxesVisible(partyId == 1);
}
void TypeFilterWidget::onTypeFilterChanged()
{
setWindowModified(true);
emit typeFilterChanged();
// Used to handle CheckAll button text
QGroupBox *gb = qobject_cast<QGroupBox *>(QObject::sender()->parent());
if (!gb)
return;
const QList<QCheckBox *> chbs = gb->findChildren<QCheckBox *>();
if (chbs.isEmpty())
return;
bool bAtLeastOneUnchecked = false;
for (const QCheckBox *chb : chbs)
{
if (!chb->isChecked())
{
bAtLeastOneUnchecked = true;
break;
}
}
adjustCheckButtonText(gb, bAtLeastOneUnchecked);
}
void TypeFilterWidget::onPartyChanged()
{
const int newPartyId = m_ui->cbParty->currentData().toInt();
if (m_partyId == newPartyId)
return;
if (isWindowModified())
{
switch (LtsWidgets::LtsMessageDialog::askApplyDiscardCancel(this))
{
case LtsWidgets::Button::Apply:
apply();
doReinitModel(newPartyId);
break;
case LtsWidgets::Button::Cancel:
m_ui->cbParty->setCurrentIndex(m_ui->cbParty->findData(m_partyId, Qt::UserRole));
break;
case LtsWidgets::Button::Discard:
doReinitModel(newPartyId);
break;
default:
break;
}
}
else
doReinitModel(newPartyId);
}
void TypeFilterWidget::doReinitModel(int newPartyId)
{
m_partyId = newPartyId;
setSymbolAppearanceSettings();
onReinitTypeFilterCbx();
updateStateFilter();
emit partyChanged(); // __unchange__();
setWindowModified(false);
}
void TypeFilterWidget::onCheckUncheckAllClicked()
{
QGroupBox *gb = qobject_cast<QGroupBox *>(QObject::sender()->parent());
if (!gb)
return;
const QList<QCheckBox *> chbs = gb->findChildren<QCheckBox *>();
if (chbs.isEmpty())
return;
bool bAtLeastOneUnchecked = false;
for (const QCheckBox *chb : chbs)
{
if (!chb->isChecked())
{
bAtLeastOneUnchecked = true;
break;
}
}
setWindowModified(true);
for (QCheckBox *chb : chbs)
chb->setChecked(bAtLeastOneUnchecked);
// negate bAtLeastOneUnchecked - we just toggled this state
adjustCheckButtonText(gb, !bAtLeastOneUnchecked);
}
void TypeFilterWidget::adjustCheckButtonText(QGroupBox *gb, bool bAtLeastOneUnchecked)
{
// Set CheckAll button text to 'on' if at least one entry is unchecked
QPushButton *btn = gb->findChild<QPushButton *>();
if (btn)
{
static int s_minWidth = -1;
if (s_minWidth < 0)
{
btn->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
btn->setText(tr("Switch all on"));
const int w1 = btn->minimumSizeHint().width();
btn->setText(tr("Switch all off"));
const int w2 = btn->minimumSizeHint().width();
s_minWidth = std::max(w1, w2);
}
btn->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
btn->setMinimumWidth(s_minWidth);
btn->setText(bAtLeastOneUnchecked ? tr("Switch all on") : tr("Switch all off"));
}
}
} // namespace FilterManagement
@@ -0,0 +1,87 @@
/**
* @RDE_HEADER@
* FilterManagement - Type Filter Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#pragma once
#include <QWidget>
#include <FilterManagement/logger.h>
#include <FilterManagement/flt_data_plugin_interface.h>
#include <FilterManagement/flt_symbol_appearance_settings.h>
#include <ParticipantManagement/ppm_data_plugin_interface.h>
#include <ParticipantManagement/ppm_gui_combobox_plugin_interface.h>
class QGroupBox;
class QGridLayout;
namespace Ui
{
class TypeFilterWidget;
}
namespace FilterManagement
{
class TypeFilterWidget final : public QWidget
{
Q_OBJECT
public:
explicit TypeFilterWidget(QWidget *parent = nullptr);
~TypeFilterWidget();
bool init(const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc,
const std::shared_ptr<ParticipantManagement::ForeignGuiComboboxInterface> &ppmIfc,
const std::shared_ptr<SymbolAppearanceSettings> &filter,
bool ocMode = false);
void retranslate();
void apply();
void dialogCanceled();
void onDataChanged(const std::shared_ptr<SymbolAppearanceSettings> &newFilter);
SymbolAppearanceSettings::Settings getCurrentUiSettings();
std::shared_ptr<SymbolAppearanceSettings> filter() const { return m_symbolAppearanceSettings; }
Q_SIGNALS:
void partyChanged();
void typeFilterChanged();
private:
void initTypeClassElements(bool ocMode);
void initStateElements();
void setSymbolAppearanceSettings();
void setHiddenTypeFilter(QGroupBox *gb);
void onReinitTypeFilterCbx();
void setHiddenStateFilter();
void updateStateFilter();
void createTypeClass(ParticipantManagement::TypeClass typeClass);
void setGroupBoxesVisible(const bool bShowOC);
void adjustCheckButtonText(QGroupBox *gb, bool bAtLeastOneUnchecked);
private Q_SLOTS:
void onTypeFilterChanged();
void onPartyChanged();
void doReinitModel(int newPartyId);
void onCheckUncheckAllClicked();
private:
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_ppmDtc;
std::shared_ptr<SymbolAppearanceSettings> m_symbolAppearanceSettings;
SymbolAppearanceSettings::Settings m_originalSymbolAppearance;
QSet<int> m_hiddenTypeFilter;
QSet<int> m_hiddenStateFilter;
qint32 m_partyId;
QMap<ParticipantManagement::TypeClass, QGroupBox *> m_gbTypes;
QGridLayout *m_gridLayout;
Ui::TypeFilterWidget *m_ui;
NGL::INGLLogger &m_logger;
};
}
@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TypeFilterWidget</class>
<widget class="QWidget" name="TypeFilterWidget">
<property name="windowTitle">
<string notr="true">Type/State Filter</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="lbParty">
<property name="text">
<string>Party:</string>
</property>
</widget>
</item>
<item>
<widget class="LtsWidgets::LtsComboBox" name="cbParty">
<property name="const" stdset="0">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QGroupBox" name="gBStates">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="title">
<string>Participant State Filter</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QGroupBox" name="gBTypes">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Participant Type Filter</string>
</property>
</widget>
</item>
<item row="1" column="2">
<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>
</widget>
<customwidgets>
<customwidget>
<class>LtsWidgets::LtsComboBox</class>
<extends>QComboBox</extends>
<header>LtsWidgets/lts_combo_box.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
+37
View File
@@ -0,0 +1,37 @@
/**
* @RDE_HEADER@
* HMI Plugin for FilterManagement - Aes Filter (Interface for access from other Plugins)
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#pragma once
#include <LtsUtilsCore/data_modification_enum.h>
#include <Services/FilterManagement/flt.hpp>
#include <memory>
namespace FilterManagement
{
class AesDisplayFilter;
class ForeignAesGuiInterface
{
public:
ForeignAesGuiInterface() = default;
virtual ~ForeignAesGuiInterface() = default;
// START :
// moved to ForeignFltParticipantGuiInterface
// at flt_participant_plugin_interface.h
// virtual std::shared_ptr<SymbolAppearanceSettings> symbolAppearanceForOperator(int operatorId, const QString &context) = 0;
// : END
virtual std::shared_ptr<AesDisplayFilter> aesFilterForOperator(int operatorId, const QString &context) = 0;
};
} // namespace FilterManagement
+46
View File
@@ -0,0 +1,46 @@
/**
* @RDE_HEADER@
* Filtermanagement Interface for access from other Plugins - SymbolAppearance
* $Id$
* $HeadURL$
* $Author$
* Created by Norbert Thodenr, SLSE, 2022-11-25
*/
#pragma once
#include <FilterManagement/flt_building_cmpnt_settings.h>
#include <InfrastructureManagement/ism_enums.hpp>
#include <QSet>
namespace FilterManagement
{
// just a headerfile for small helper:
// to avoid redefinition, use template:
template <class UNUSED = void>
QSet<InfrastructureManagement::MountingPointType> getVisibleTypesOfFilter(const FilterManagement::BuildingComponentSettings::BldCmpSettings &bldCmpSettings)
{
QSet<InfrastructureManagement::MountingPointType> visibleTypes;
const FilterManagement::BuildingComponentSettings::BldCmpSettings::ComponentSettings &compSettings =
bldCmpSettings.componentSettings;
if (compSettings.showAnnouncementUnit) visibleTypes.insert(InfrastructureManagement::MountingPointType_def::type::AnnouncementUnit);
if (compSettings.showBuildingControlUnit) visibleTypes.insert(InfrastructureManagement::MountingPointType_def::type::BuildingControlUnit);
if (compSettings.showBuildingNetworkSwitch) visibleTypes.insert(InfrastructureManagement::MountingPointType_def::type::BuildingNetworkSwitch);
if (compSettings.showBuildingSensorModule) visibleTypes.insert(InfrastructureManagement::MountingPointType_def::type::BuildingSensorModule);
if (compSettings.showEffectGenerationControlUnit) visibleTypes.insert(InfrastructureManagement::MountingPointType_def::type::EffectGenerationControlUnit);
if (compSettings.showIndoorCamera) visibleTypes.insert(InfrastructureManagement::MountingPointType_def::type::IndoorCamera);
if (compSettings.showIndoorIPS) visibleTypes.insert(InfrastructureManagement::MountingPointType_def::type::IndoorIPS);
if (compSettings.showMeteoDataUnit) visibleTypes.insert(InfrastructureManagement::MountingPointType_def::type::MeteoDataUnit);
if (compSettings.showOutdoorCamera) visibleTypes.insert(InfrastructureManagement::MountingPointType_def::type::OutdoorCamera);
if (compSettings.showOutdoorControlUnit) visibleTypes.insert(InfrastructureManagement::MountingPointType_def::type::OutdoorControlUnit);
if (compSettings.showOutdoorIPS) visibleTypes.insert(InfrastructureManagement::MountingPointType_def::type::OutdoorIPS);
if (compSettings.showVirtualIPS) visibleTypes.insert(InfrastructureManagement::MountingPointType_def::type::VirtualIPS);
return visibleTypes;
}
} // namespace FilterManagement
@@ -0,0 +1,31 @@
/**
* @RDE_HEADER@
* HMI Plugin for FilterManagement - Participant Filter (Interface for access from other Plugins)
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#pragma once
#include <Services/FilterManagement/flt.hpp>
#include <memory>
namespace FilterManagement
{
class BuildingComponentSettings;
class ForeignFltBuildingComponentGuiInterface
{
public:
ForeignFltBuildingComponentGuiInterface() = default;
virtual ~ForeignFltBuildingComponentGuiInterface() = default;
virtual std::shared_ptr<BuildingComponentSettings> buildingComponentSettingsForOperator(int operatorId, const QString &context) = 0;
};
}
+135
View File
@@ -0,0 +1,135 @@
/**
* @RDE_HEADER@
* Filtermanagement Interface for access from other Plugins - SymbolAppearance
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2017-06-19
*/
#pragma once
#include <FilterManagement/flt_dtc.h>
#include <functional>
#include <QSet>
namespace FilterManagement
{
class BuildingComponentSettings
{
protected:
BuildingComponentSettings() = default;
virtual ~BuildingComponentSettings() = default;
public:
virtual void resetBuildingComponentSettings() = 0;
struct BldCmpSettings
{
bool bIsValid = false;
// Building/Floors
struct BuildingSettings
{
// GUEZE-1478
// QSet<int> visibleFloorIds;
// If QSet ist empty -> show all floors.
// So use 'hidden..' instead of 'visible..':
QSet<int> hiddenFloorIds;
bool showBuildingOutline = true;
bool showBuildingName = false;
bool operator==(const BuildingSettings &o) const
{
return
hiddenFloorIds == o.hiddenFloorIds &&
showBuildingOutline == o.showBuildingOutline &&
showBuildingName == o.showBuildingName;
}
bool operator !=(const BuildingSettings &o) const
{
return !operator==(o);
}
} buildingSettings;
// ISM / Components (MountingPointType)
struct ComponentSettings
{
bool showBuildingSensorModule = true;
bool showBuildingControlUnit = true;
bool showOutdoorCamera = true;
bool showIndoorCamera = true;
bool showOutdoorIPS = true;
bool showIndoorIPS = true;
bool showMeteoDataUnit = true;
bool showAnnouncementUnit = true;
bool showVirtualIPS = true;
bool showEffectGenerationControlUnit = true;
bool showOutdoorControlUnit = true;
bool showBuildingNetworkSwitch = true;
bool operator==(const ComponentSettings &o) const
{
return
showBuildingSensorModule == o.showBuildingSensorModule &&
showBuildingControlUnit == o.showBuildingControlUnit &&
showOutdoorCamera == o.showOutdoorCamera &&
showIndoorCamera == o.showIndoorCamera &&
showOutdoorIPS == o.showOutdoorIPS &&
showIndoorIPS == o.showIndoorIPS &&
showMeteoDataUnit == o.showMeteoDataUnit &&
showAnnouncementUnit == o.showAnnouncementUnit &&
showVirtualIPS == o.showVirtualIPS &&
showEffectGenerationControlUnit == o.showEffectGenerationControlUnit &&
showOutdoorControlUnit == o.showOutdoorControlUnit &&
showBuildingNetworkSwitch == o.showBuildingNetworkSwitch;
;
}
bool operator!=(const ComponentSettings &o) const
{
return !operator==(o);
}
} componentSettings;
// over all / BldCmpSettings
bool operator==(const BldCmpSettings &o) const
{
return buildingSettings == o.buildingSettings &&
componentSettings == o.componentSettings;
}
bool operator!=(const BldCmpSettings &o) const
{
return !operator ==(o);
}
bool isValid() const
{
return bIsValid;
}
}; // BldCmpSettings
// DDS
virtual bool setBldCmpSettingsFromData(const BuildingComponentFilter &filterData) = 0; // BuildingComponentFilter == DDS
virtual QJsonObject bldCmpSettingsToJson() const = 0;
virtual BuildingComponentFilter bldCmpSettingsToData() const = 0;
// C++struct
virtual bool setBldCmpSettings(const QJsonObject &obj) = 0;
virtual bool setBldCmpSettings(const BldCmpSettings &s) = 0;
virtual const BldCmpSettings &bldCmpSettings() const = 0;
class SettingsChangedCallback
{
public:
virtual ~SettingsChangedCallback() = default;
virtual void onBuildingComponentSettingsChanged() = 0;
};
virtual void addChangedCallback(SettingsChangedCallback *cb) = 0;
virtual void removeChangedCallback(SettingsChangedCallback *cb) = 0;
virtual bool isChangedCallbackRegistered(SettingsChangedCallback *cb) const = 0;
};
} // namespace FilterManagement
@@ -0,0 +1,117 @@
/**
* @RDE_HEADER@
* Filtermanagement Interface for access from other Plugins - AesDisplayFilter
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2017-06-19
*/
#pragma once
#include <PluginInterfaces/data_plugin_interface.h>
#include <FilterManagement/flt_dtc.h>
#include <AreaEffectSimulation/aes_enums.hpp>
#include <functional>
#include <QSet>
namespace FilterManagement
{
class AesDisplayFilter
{
protected:
AesDisplayFilter() = default;
virtual ~AesDisplayFilter() = default;
public:
virtual void resetAesDisplayFilter() = 0;
struct EffectStateStruct
{
bool displayCreated = true;
bool displayPrepared = true;
bool displayActivated = true;
bool limitOnChargeTypes = false;
bool limitOnParties = false;
bool showDetails = true; // used at MineArea setMineVisibility
bool showDetails2 = true; // ExplosionClusterMeanHitPoint - MHP - MittlererTrefferPunkt
bool showDetails3 = true; // ExplosionClusterGunToTargetLine
bool showDetails4 = true; // ExplosionClusterTrajectory
bool showDetails5 = false; // ExplosionClusterDetonationSphere
bool displayCentral = true;
bool displayPeripheral = true;
int expiredAfterglowDurationMSec = 10 * 1000;
QSet<int> visibleChargeTypeIds;
QSet<int> visiblePartyIds;
bool operator==(const EffectStateStruct &o) const
{
return displayCreated == o.displayCreated &&
displayPrepared == o.displayPrepared &&
displayActivated == o.displayActivated &&
limitOnChargeTypes == o.limitOnChargeTypes &&
limitOnParties == o.limitOnParties &&
showDetails == o.showDetails &&
showDetails2 == o.showDetails2 &&
showDetails3 == o.showDetails3 &&
showDetails4 == o.showDetails4 &&
showDetails5 == o.showDetails5 &&
displayCentral == o.displayCentral &&
displayPeripheral == o.displayPeripheral &&
expiredAfterglowDurationMSec == o.expiredAfterglowDurationMSec &&
visibleChargeTypeIds == o.visibleChargeTypeIds &&
visiblePartyIds == o.visiblePartyIds;
}
bool operator!=(const EffectStateStruct &o) const
{
return !operator ==(o);
}
};
virtual bool setFilterFromData(const AesFilter &filterData) = 0;
virtual bool setFilterFromData(const QJsonObject &filterData) = 0;
virtual QJsonObject filterToJson() const = 0;
virtual AesFilter filterToData() const = 0;
virtual bool isVisible(AreaEffectSimulation::AesType aesType,
AreaEffectSimulation::AesEffectState aesState,
int chargeTypeId,
int partyId,
bool isCentral,
qint64 effectStart,
qint64 effectDuration,
qint64 currentTimeMSec) const = 0;
virtual bool showDetails(AreaEffectSimulation::AesType aesType) const = 0;
/*! ExplosionCluster */
//@{
virtual bool showExplosionClusterMeanHitPoint() const = 0; // MHP - MeanHitPoint - MittlererTrefferPunkt
virtual bool showExplosionClusterGunToTargetLine() const = 0;
virtual bool showExplosionClusterTrajectory() const = 0;
virtual bool showExplosionClusterDetonationSphere() const = 0;
virtual bool showNotTriggeredCDMine() const = 0;
//@}
virtual EffectStateStruct effectStateFilter(AreaEffectSimulation::AesType aesType) const = 0;
virtual void setEffectStateFilter(AreaEffectSimulation::AesType aesType,
const EffectStateStruct &ess) = 0;
virtual int maxAfterglowDurationMSec() const = 0;
class FilterChangedCallback
{
public:
virtual void onAesDisplayFilterChanged(AreaEffectSimulation::AesType aesType) = 0;
};
virtual void addChangedCallback(FilterChangedCallback *cb) = 0;
virtual void removeChangedCallback(FilterChangedCallback *cb) = 0;
virtual void setVisiblePartiesCheck(const std::function<bool(int)> &cb) = 0;
};
} // namespace FilterManagement
+31
View File
@@ -0,0 +1,31 @@
/**
* @RDE_HEADER@
* Filtermanagement Interface for access from other Plugins
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2017-06-19
*/
#pragma once
#include <PluginInterfaces/data_plugin_interface.h>
#include <FilterManagement/flt_dtc.h>
#include <FilterManagement/flt_ftc.h>
namespace FilterManagement
{
/**
* @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<FilterManagement::Interface::Dtc> getDtc() = 0;
virtual std::shared_ptr<FilterManagement::Interface::Ftc> getFtc() = 0;
};
} // namespace FilterManagement
@@ -0,0 +1,32 @@
/**
* @RDE_HEADER@
* HMI Plugin for FilterManagement - Participant Filter (Interface for access from other Plugins)
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#pragma once
#include <Services/FilterManagement/flt.hpp>
#include <memory>
namespace FilterManagement
{
class SymbolAppearanceSettings;
class ForeignFltParticipantGuiInterface
{
public:
ForeignFltParticipantGuiInterface() = default;
virtual ~ForeignFltParticipantGuiInterface() = default;
// moved from AES (ForeignAesGuiInterface)
virtual std::shared_ptr<SymbolAppearanceSettings> symbolAppearanceForOperator(int operatorId, const QString &context) = 0;
};
}
@@ -0,0 +1,224 @@
/**
* @RDE_HEADER@
* Filtermanagement Interface for access from other Plugins - SymbolAppearance
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2017-06-19
*/
#pragma once
#include <FilterManagement/flt_dtc.h>
#include <AreaEffectSimulation/aes_enums.hpp>
#include <functional>
#include <QSet>
namespace FilterManagement
{
class SymbolAppearanceSettings
{
protected:
SymbolAppearanceSettings() = default;
virtual ~SymbolAppearanceSettings() = default;
public:
virtual void resetSymbolAppearanceSettings() = 0;
enum class SymbolVisibility
{
Standard = 0,
Faded = 1,
Hidden = 2,
AdditionalSymbol = 3
};
enum class UnitSymbolPosition
{
Center,
Leader
};
struct SymbolPartyAppearance
{
bool isVisible = true;
bool showDesignator = true;
bool showTacticalIdentifier = true;
bool operator==(const SymbolPartyAppearance &o) const
{
return isVisible == o.isVisible &&
showDesignator == o.showDesignator &&
showTacticalIdentifier == o.showTacticalIdentifier;
}
bool operator !=(const SymbolPartyAppearance &o) const
{
return !operator==(o);
}
};
struct Settings
{
bool bIsValid = false;
// Part::Symbol
struct SymbolSettings
{
float symbolScale = 1;
float symbolTransparency = 0;
int symbolFireEventFlashingMSec = 10 * 1000; // 10 sec
int hitLineDisplayLengthMSec = 10 * 1000; // 10 sec
int lrfLineDisplayLengthMSec = 10 * 1000; /// Laser range finder 10 sec
int ltdLineDisplayLengthMSec = 10 * 1000; /// Laser Target designator 10 sec
int movementTrackLengthMSec = 60 * 10 * 1000; // 10min
bool showBuildingOutline = true;
bool showBuildingIdentifier = false;
bool showTrainingAreaBorder = false;
bool showSpecialAreas = false;
bool showFiringUnits = false; // feuereinheiten
// bool showNasatNineLiner = true; // GUEZ NASAT / GNA // replaced by slider (GUEZE-1676)
int nasatNineLinerDisplayLengthMSec = 100 * 1000; // 100 sec
SymbolVisibility bitErrorVisibility = SymbolVisibility::Standard;
SymbolVisibility manipulationVisibility = SymbolVisibility::Standard;
SymbolVisibility positionOutOfDateVisibility = SymbolVisibility::Standard;
SymbolVisibility simulatedPositionVisibility = SymbolVisibility::AdditionalSymbol; // default AdditionalSymbol
UnitSymbolPosition unitSymbolPosition = UnitSymbolPosition::Center;
QMap<int, SymbolPartyAppearance> symbolPartyAppearance;
bool operator==(const SymbolSettings &o) const
{
bool identicalPart1 =
qFuzzyCompare(symbolScale, o.symbolScale) &&
qFuzzyCompare(symbolTransparency, o.symbolTransparency) &&
symbolFireEventFlashingMSec == o.symbolFireEventFlashingMSec &&
hitLineDisplayLengthMSec == o.hitLineDisplayLengthMSec &&
lrfLineDisplayLengthMSec == o.lrfLineDisplayLengthMSec &&
ltdLineDisplayLengthMSec == o.ltdLineDisplayLengthMSec &&
movementTrackLengthMSec == o.movementTrackLengthMSec &&
showBuildingOutline == o.showBuildingOutline &&
showBuildingIdentifier == o.showBuildingIdentifier &&
showTrainingAreaBorder == o.showTrainingAreaBorder &&
showSpecialAreas == o.showSpecialAreas &&
showFiringUnits == o.showFiringUnits &&
nasatNineLinerDisplayLengthMSec == o.nasatNineLinerDisplayLengthMSec &&
bitErrorVisibility == o.bitErrorVisibility &&
manipulationVisibility == o.manipulationVisibility &&
positionOutOfDateVisibility == o.positionOutOfDateVisibility &&
simulatedPositionVisibility == o.simulatedPositionVisibility &&
unitSymbolPosition == o.unitSymbolPosition;
if (!identicalPart1)
return false;
if (symbolPartyAppearance == o.symbolPartyAppearance)
return true;
{
// check if all entries are defaultValues:
static SymbolPartyAppearance defaultItem;
for (const SymbolPartyAppearance &item : symbolPartyAppearance)
if (item != defaultItem)
return false;
for (const SymbolPartyAppearance &item : o.symbolPartyAppearance)
if (item != defaultItem)
return false;
}
return true;
}
bool operator !=(const SymbolSettings &o) const
{
return !operator==(o);
}
} symbolSettings;
// Part::Types
QMap<qint32, QSet<int>> hiddenTypeFilter;
QMap<qint32, QSet<int>> hiddenStateFilter;
static bool semanticCompare(const QMap<qint32, QSet<int>> &val1, const QMap<qint32, QSet<int>> &val2)
{
if (val1 == val2)
return true;
for (const QSet<int> &item : val1)
if (!item.isEmpty())
return false;
for (const QSet<int> &item : val2)
if (!item.isEmpty())
return false;
return true;
}
// Part::CollapseExpand
// do not use directly, use isParticipantFiltered()
struct ColExpand
{
QSet<int> hiddenParticipantIds;
QSet<int> collapsedParticipantIds;
bool operator==(const ColExpand &o) const
{
return hiddenParticipantIds == o.hiddenParticipantIds &&
collapsedParticipantIds == o.collapsedParticipantIds;
}
bool operator!=(const ColExpand &o) const
{
return !operator==(o);
}
} colExpand;
bool operator==(const Settings &o) const
{
return symbolSettings == o.symbolSettings &&
hiddenTypeFilter == o.hiddenTypeFilter &&
hiddenStateFilter == o.hiddenStateFilter &&
colExpand == o.colExpand;
}
bool operator!=(const Settings &o) const
{
return !operator ==(o);
}
bool isValid() const
{
return bIsValid;
}
};
enum class Part
{
Symbol,
Types,
CollapseExpand,
All
};
virtual bool setSettingsFromData(const SymbolAppearance &filterData) = 0; // SymbolAppearance == DDS
virtual QJsonObject settingsToJson() const = 0;
virtual SymbolAppearance settingsToData() const = 0;
virtual bool setSettings(const QJsonObject &obj, Part part) = 0;
virtual bool setSettings(const Settings &s, Part part) = 0;
virtual const Settings &settings() const = 0;
virtual bool isParticipantVisibileCollapseExpand(int participantId) const = 0;
class SettingsChangedCallback
{
public:
virtual ~SettingsChangedCallback() = default;
virtual void onSymbolAppearanceSettingsChanged(Part part) = 0;
};
virtual void addChangedCallback(SettingsChangedCallback *cb) = 0;
virtual void removeChangedCallback(SettingsChangedCallback *cb) = 0;
virtual bool isChangedCallbackRegistered(SettingsChangedCallback *cb) const = 0;
};
} // namespace FilterManagement