Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
Executable
+17
@@ -0,0 +1,17 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
# Created by Jörg Turla, SPDG, 2017-06-29
|
||||
#
|
||||
|
||||
ADD_SUBDIRECTORY(Gui)
|
||||
|
||||
#
|
||||
# Gui Plugin Interface
|
||||
#
|
||||
ADD_INTERFACE_LIBRARY(PlanOverlaysGuiPluginInterface
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/plan_overlays_plugin_interface.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/..
|
||||
GuiPluginInterface
|
||||
)
|
||||
Executable
+54
@@ -0,0 +1,54 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
# Created by Jörg Turla, SPDG, 2017-06-29
|
||||
#
|
||||
|
||||
ADD_SUBDIRECTORY(Test)
|
||||
|
||||
SET (PlanOverlaysGuiPlugin_SRCS
|
||||
flm_reply_handler.cpp
|
||||
flm_reply_handler.h
|
||||
plan_overlay_dialog.cpp
|
||||
plan_overlay_dialog.h
|
||||
plan_overlay_model.cpp
|
||||
plan_overlay_model.h
|
||||
plan_overlay_view.cpp
|
||||
plan_overlay_view.h
|
||||
plan_overlays_gui_plugin.cpp
|
||||
plan_overlays_gui_plugin.h
|
||||
|
||||
TopicEditor/topic_editor.h
|
||||
TopicEditor/topic_editor.cpp
|
||||
)
|
||||
|
||||
SET(EXE_UICS
|
||||
TopicEditor/topic_editor.ui
|
||||
)
|
||||
|
||||
QT5_WRAP_UI(EXE_SRCS ${EXE_UICS})
|
||||
|
||||
SOURCE_GROUP(PlanOverlaysPlugin FILES ${PlanOverlaysGuiPlugin_SRCS})
|
||||
|
||||
NGL_ADD_LIBRARY(WS PlanOverlaysGuiPlugin MODULE ${PlanOverlaysGuiPlugin_SRCS} ${EXE_SRCS})
|
||||
NGL_TARGET_LINK_LIBRARIES( PlanOverlaysGuiPlugin
|
||||
LtsSession
|
||||
LtsSessionData
|
||||
PlanOverlaysGuiPluginInterface
|
||||
situationMap
|
||||
situationMapObjects
|
||||
GuiPluginInterface
|
||||
FlmDataPluginInterface
|
||||
OpmDataPluginInterface
|
||||
ExmDataPluginInterface
|
||||
LtsFileDialog
|
||||
LtsUtilsGuiDds
|
||||
LtsWidgets
|
||||
NGLLogger
|
||||
Qt5::Widgets
|
||||
TopicEditorBase
|
||||
LtsScriptTimeline
|
||||
)
|
||||
|
||||
NGL_INSTALL_TARGET(PlanOverlaysGuiPlugin)
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
|
||||
# PlanOverlays Test Application
|
||||
|
||||
SET(EXE_SRCS
|
||||
main.cpp
|
||||
../plan_overlay_dialog.cpp
|
||||
../plan_overlay_dialog.h
|
||||
../plan_overlay_view.cpp
|
||||
../plan_overlay_view.h
|
||||
../plan_overlay_model.cpp
|
||||
../plan_overlay_model.h
|
||||
log4cxx_planOverlaysTest.props
|
||||
)
|
||||
|
||||
SET(EXE_HDRS
|
||||
)
|
||||
|
||||
SET(EXE_UICS
|
||||
)
|
||||
|
||||
NGL_WRAP_UI(EXE_SRCS ${EXE_UICS})
|
||||
|
||||
|
||||
SET(LOG4CXX_PROPS_FILE log4cxx_planOverlaysTest.props)
|
||||
|
||||
NGL_ADD_EXECUTABLE(WS NO_TRANSLATION planOverlaysTest ${EXE_SRCS} ${EXE_HDRS} ${EXE_UICS})
|
||||
NGL_TARGET_LINK_LIBRARIES(
|
||||
planOverlaysTest
|
||||
NGLLogger
|
||||
LtsSession
|
||||
LtsSessionData
|
||||
LtsWidgets
|
||||
nglapplication
|
||||
LtsPluginManager
|
||||
GuiPluginInterface
|
||||
FlmDataPluginInterface
|
||||
OpmDataPluginInterface
|
||||
ExmDataPluginInterface
|
||||
LtsFileDialog
|
||||
# ArcGIS::ArcGIS
|
||||
LtsPluginLoader
|
||||
LtsUtilsGuiDds
|
||||
Qt5::Gui
|
||||
)
|
||||
|
||||
IF(TARGET planOverlaysTest)
|
||||
|
||||
if(BUILD_PlanEditorCopyConfig)
|
||||
ADD_CUSTOM_COMMAND( TARGET planOverlaysTest POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
ARGS -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/${LOG4CXX_PROPS_FILE} $<TARGET_FILE_DIR:planOverlaysTest>/${LOG4CXX_PROPS_FILE}
|
||||
)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
IF(MSVC)
|
||||
# Configure the template file
|
||||
SET(VS_USER_FILE planOverlaysTest.vcxproj.user)
|
||||
configure_file( PlanOverlaysTest.vcxproj.user.in ${CMAKE_CURRENT_BINARY_DIR}/${VS_USER_FILE} @ONLY)
|
||||
ENDIF(MSVC)
|
||||
|
||||
NGL_INSTALL_TARGET_DEVEL(planOverlaysTest)
|
||||
NGL_INSTALL(FILES WS ${CMAKE_CURRENT_SOURCE_DIR}/${LOG4CXX_PROPS_FILE} DESTINATION "bin" COMPONENT Devel)
|
||||
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LocalDebuggerEnvironment>PATH=C:\ExtFW\bin;%PATH%</LocalDebuggerEnvironment>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
<LocalDebuggerCommandArguments>
|
||||
</LocalDebuggerCommandArguments>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
|
||||
<LocalDebuggerEnvironment>PATH=C:\ExtFW\bin;%PATH%</LocalDebuggerEnvironment>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LocalDebuggerEnvironment>PATH=C:\ExtFW\bin;%PATH%</LocalDebuggerEnvironment>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
|
||||
<LocalDebuggerEnvironment>PATH=C:\ExtFW\bin;%PATH%</LocalDebuggerEnvironment>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LocalDebuggerEnvironment>PATH=C:\ExtFW\bin;%PATH%</LocalDebuggerEnvironment>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
<LocalDebuggerCommandArguments>
|
||||
</LocalDebuggerCommandArguments>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|x64'">
|
||||
<LocalDebuggerEnvironment>PATH=C:\ExtFW\bin;%PATH%</LocalDebuggerEnvironment>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LocalDebuggerEnvironment>PATH=C:\ExtFW\bin;%PATH%</LocalDebuggerEnvironment>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|x64'">
|
||||
<LocalDebuggerEnvironment>PATH=C:\ExtFW\bin;%PATH%</LocalDebuggerEnvironment>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,138 @@
|
||||
log4j.reset=true
|
||||
log4j.rootLogger=WARN, file
|
||||
|
||||
# SituationMap
|
||||
###########################################################
|
||||
|
||||
log4j.logger.PlanEditor=DEBUG
|
||||
log4j.logger.PlanEditor.SymbolAdjustDialog=TRACE
|
||||
|
||||
|
||||
|
||||
|
||||
log4j.logger.SituationMap.SitMapTestApp=ERROR
|
||||
log4j.logger.SituationMap.SitMap=ERROR
|
||||
|
||||
log4j.logger.SituationMap.MapImpl=ERROR
|
||||
log4j.logger.SituationMap.MapSettings=WARN
|
||||
log4j.logger.SituationMap.MapInitializer=WARN
|
||||
log4j.logger.SituationMap.LayerFactoryImpl=ERROR
|
||||
log4j.logger.SituationMap.CoordTranslationFunctorImpl=ERROR
|
||||
log4j.logger.SituationMap.GridImpl=ERROR
|
||||
log4j.logger.SituationMap.ObjectFactory=ERROR
|
||||
log4j.logger.SituationMap.IdGenerator=ERROR
|
||||
log4j.logger.SituationMap.ObjectContainer=ERROR
|
||||
log4j.logger.SituationMap.ObjectContainerCTC=ERROR
|
||||
log4j.logger.SituationMap.SymbolDictionary=ERROR
|
||||
log4j.logger.SituationMap.SymbolDictionaryImpl=ERROR
|
||||
log4j.logger.SituationMap.SymbolDictionaryExtendedImpl=ERROR
|
||||
log4j.logger.SituationMap.Sidc2525Delta=ERROR
|
||||
|
||||
log4j.logger.SituationMap.AbstractMapObjectImpl=ERROR
|
||||
log4j.logger.SituationMap.AbstractEffectSimulationImpl=ERROR
|
||||
log4j.logger.SituationMap.OriginTranslated=ERROR
|
||||
log4j.logger.SituationMap.PositionsTranslated=ERROR
|
||||
log4j.logger.SituationMap.AbstractMultiPointMapObjectImpl=ERROR
|
||||
log4j.logger.SituationMap.AbstractSinglePointMapObjectImpl=ERROR
|
||||
log4j.logger.SituationMap.BasicPathObjectImpl=ERROR
|
||||
|
||||
log4j.logger.SituationMap.PolygonImpl=ERROR
|
||||
log4j.logger.SituationMap.PolylineImpl=ERROR
|
||||
log4j.logger.SituationMap.TextImpl=ERROR
|
||||
|
||||
log4j.logger.SituationMap.AreaFireImpl=ERROR
|
||||
log4j.logger.SituationMap.BiologicalAgentImpl=ERROR
|
||||
log4j.logger.SituationMap.BuildingOutlineImpl=ERROR
|
||||
log4j.logger.SituationMap.ChemicalAgentImpl=ERROR
|
||||
log4j.logger.SituationMap.DangerAreaImpl=ERROR
|
||||
log4j.logger.SituationMap.FunctionalAreaImpl=ERROR
|
||||
log4j.logger.SituationMap.HitLineImpl=ERROR
|
||||
log4j.logger.SituationMap.MineImpl=ERROR
|
||||
log4j.logger.SituationMap.ParticipantImpl=ERROR
|
||||
log4j.logger.SituationMap.SingleFireImpl=ERROR
|
||||
log4j.logger.SituationMap.IndicationContainer=ERROR
|
||||
|
||||
log4j.logger.SituationMap.AbstractGraphicalObject=ERROR
|
||||
log4j.logger.SituationMap.GraphicalObjectEllipse=ERROR
|
||||
log4j.logger.SituationMap.GraphicalObjectPath=ERROR
|
||||
log4j.logger.SituationMap.GraphicalObjectMultiPath=ERROR
|
||||
log4j.logger.SituationMap.GraphicalObjectPictureMarker=ERROR
|
||||
log4j.logger.SituationMap.GraphicalObjectRange=ERROR
|
||||
log4j.logger.SituationMap.GraphicalObjectText=ERROR
|
||||
log4j.logger.SituationMap.TacticalAppearance=ERROR
|
||||
log4j.logger.SituationMap.MessageBase=ERROR
|
||||
|
||||
log4j.logger.SituationMap.EventDispatcher=ERROR
|
||||
log4j.logger.SituationMap.RubberbandFactory=DEBUG
|
||||
|
||||
# Appnd_File
|
||||
###########################################################
|
||||
log4j.appender.file=org.apache.log4j.RollingFileAppender
|
||||
log4j.appender.file.MaxFileSize=1MB
|
||||
log4j.appender.file.MaxBackupIndex=9
|
||||
log4j.appender.file.file=${LOG4QT_LOGDIR}/${LOG4QT_USER}_SituationMapTestApp.log
|
||||
log4j.appender.file.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.file.layout.ConversionPattern=%d %-5p %c |#| %m (%.50F:%L) %n
|
||||
|
||||
|
||||
# Appnd_Console
|
||||
###########################################################
|
||||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.ConversionPattern= %d %-5p %c{1} |#| %m (%-.30F:%L) %n
|
||||
|
||||
#log4j.appender.stdout.layout.ConversionPattern= %d %-5p %-30c |#| %m (%-.30F:%L) %n
|
||||
|
||||
|
||||
# Appnd_Syslog
|
||||
###########################################################
|
||||
log4j.appender.syslog=org.apache.log4j.SyslogAppender
|
||||
log4j.appender.syslog.Threshold=ERROR
|
||||
log4j.appender.syslog.SysLogHost=localhost
|
||||
log4j.appender.syslog.Facility=LOCAL7
|
||||
log4j.appender.syslog.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.syslog.layout.ConversionPattern= %-4r %-5p %c %x - %m
|
||||
log4j.appender.syslog.LevelRangeFilter.AcceptOnMatch=true
|
||||
log4j.appender.syslog.LevelRangeFilter.LevelMin=FATAL
|
||||
log4j.appender.syslog.LevelRangeFilter.LevelMax=FATAL
|
||||
|
||||
###########################################################
|
||||
###########################################################
|
||||
###########################################################
|
||||
# 1) Available Levels in LOG4CXX Version 0.10.0:
|
||||
# TRACE,
|
||||
# DEBUG,
|
||||
# INFO,
|
||||
# WARN,
|
||||
# ERROR
|
||||
# FATAL
|
||||
#
|
||||
# d = date/time
|
||||
# p = priority (Level)
|
||||
# c = category/channel
|
||||
# m = message
|
||||
# F = file
|
||||
# L = line
|
||||
# n = platform dependent line separator character or characters.
|
||||
# ....
|
||||
#
|
||||
# Examples for console:
|
||||
# a)
|
||||
# %d %p %c #%m# (%.50F:%L)%n
|
||||
# date/time
|
||||
# priority
|
||||
# category/channel
|
||||
# #message#
|
||||
# (Maximal 50Character des Filename von rechts:Line)
|
||||
# line separator
|
||||
#
|
||||
# b)
|
||||
# %d (%.15F:%L) %-5p %c |#| %m%n
|
||||
# date/time
|
||||
# (Maximal 15Character des Filename von rechts:Line)
|
||||
# priority, Right pad with spaces if the priority name is less than 5 characters long.
|
||||
# category/channel
|
||||
# message
|
||||
# line separator
|
||||
#
|
||||
|
||||
Executable
+182
@@ -0,0 +1,182 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* main
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#include <nglapplication/nglapplication.h>
|
||||
#include <NGLLogger/INGLLogger.h>
|
||||
|
||||
#include "../plan_overlay_dialog.h"
|
||||
|
||||
#include "../plan_overlay_model.h"
|
||||
#include "../plan_overlay_view.h"
|
||||
|
||||
#include <LtsWidgets/lts_base_layout_widget.h>
|
||||
#include <LtsPluginManager/lts_plugin_loader.h>
|
||||
#include <PluginInterfaces/style_plugin_interface.h>
|
||||
#include <PluginInterfaces/project_plugin_interface.h>
|
||||
|
||||
#include <Plugins/SituationMapPlugin/situation_map_gui_plugin_interface.h>
|
||||
|
||||
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QPointer>
|
||||
#include <QtCore/QStandardPaths>
|
||||
|
||||
#include <QtGui/QSurface>
|
||||
|
||||
#include <QtWidgets/QMainWindow>
|
||||
#include <QtWidgets/QDesktopWidget>
|
||||
#include <QtWidgets/QDialog>
|
||||
#include <QtWidgets/QHBoxLayout>
|
||||
#include <QtWidgets/QMessageBox>
|
||||
#include <QtWidgets/QLabel>
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
int main (int argc, char* argv[])
|
||||
{
|
||||
// ESRI :
|
||||
#ifdef Q_OS_WIN
|
||||
// Force usage of OpenGL ES through ANGLE on Windows
|
||||
QCoreApplication::setAttribute(Qt::AA_UseOpenGLES);
|
||||
#endif
|
||||
// : ESRI
|
||||
|
||||
NGLApplication app ( argc, argv );
|
||||
|
||||
|
||||
app.createLogger("planOverlayTest", "log4cxx_planOverlayTest.props");
|
||||
TRACE_LOG(app.baseLogger()) << LOGFUNCTION << " START";
|
||||
|
||||
STARTUP_LOG(app.baseLogger());
|
||||
|
||||
app.setOrganizationName(QLatin1String("RME"));
|
||||
app.setApplicationName(QLatin1String("Plan Overlay Test Application"));
|
||||
|
||||
|
||||
LtsPluginManager::LtsPluginLoader *pluginLoader = LtsPluginManager::LtsPluginLoader::getInstance();
|
||||
|
||||
pluginLoader->loadPlugins( LtsPluginManager::PluginType::STYLE , nullptr, QStringList() << QStringLiteral("rme.light") );
|
||||
pluginLoader->loadPlugins( LtsPluginManager::PluginType::PROJECT, nullptr, QStringList() << QStringLiteral("legatus") );
|
||||
|
||||
|
||||
// .. to keep some compatibility to old resource structure TODO: rm !
|
||||
QDir::setSearchPaths( QLatin1String( "icon" ), QStringList( QLatin1String( ":/style/icons/" ) ) );
|
||||
QDir::setSearchPaths( QLatin1String( "icon" ), QStringList( QLatin1String( ":/style/" ) ) ); // FIXME: does qt check for recursion ??
|
||||
|
||||
|
||||
|
||||
#ifdef BUILD_STATIC_LIBRARIES
|
||||
// For static linking under windows:
|
||||
Q_INIT_RESOURCE(lts_resources);
|
||||
#endif
|
||||
|
||||
#define USE_QDIALOG
|
||||
//#define USE_LTSFRAMELESS
|
||||
//#define CHECK_ERROR
|
||||
|
||||
PlanOverlaysPlugin::PlanOverlayModel * planOverlayModel = new PlanOverlaysPlugin::PlanOverlayModel();
|
||||
|
||||
#ifdef USE_QDIALOG
|
||||
PlanOverlaysPlugin::PlanOverlayDialog<QDialog> * dialog = new PlanOverlaysPlugin::PlanOverlayDialog<QDialog>( nullptr, planOverlayModel, nullptr, nullptr );
|
||||
#endif
|
||||
|
||||
#ifdef USE_LTSFRAMELESS
|
||||
PlanOverlaysPlugin::PlanOverlayDialog<LtsWidgets::LtsFramelessDialog> * dialog = new PlanOverlaysPlugin::PlanOverlayDialog<LtsWidgets::LtsFramelessDialog>( nullptr, planOverlayModel, nullptr );
|
||||
#endif
|
||||
|
||||
#ifdef CHECK_ERROR
|
||||
PlanOverlaysPlugin::PlanOverlayDialog<QWidget> * dialog = new PlanOverlaysPlugin::PlanOverlayDialog<QWidget>( nullptr, planOverlayModel, nullptr ); // test static_assert
|
||||
#endif
|
||||
|
||||
unsigned int counter = 1;
|
||||
|
||||
auto doReadFile = [dialog,&counter]( int /*selectedFileId*/ )
|
||||
{
|
||||
PlanOverlaysPlugin::PlanOverlayModel::PlanItem planItem = dialog->dialogWidget()->planOverlayModel()->planItem(counter++);
|
||||
|
||||
planItem.m_folderId = 6;
|
||||
planItem.m_fileId = 42;
|
||||
planItem.m_dirPath = QString();
|
||||
planItem.m_fileName = QStringLiteral("Hugo_%1").arg(planItem.m_fileId);
|
||||
planItem.m_minScale = 250000;
|
||||
planItem.m_maxScale = 12000;
|
||||
planItem.m_opacity = 1;
|
||||
planItem.m_visibility = true;
|
||||
|
||||
dialog->dialogWidget()->planOverlayModel()->updatePlanItem( planItem );
|
||||
};
|
||||
|
||||
auto doReloadPlan = [](unsigned int planId)
|
||||
{
|
||||
Q_UNUSED(planId);
|
||||
QMessageBox::information(nullptr,QObject::tr("Reload Plan"),QObject::tr("doReloadPlan has been called"),QMessageBox::StandardButton::Ok);
|
||||
};
|
||||
|
||||
auto doUnloadPlan = [dialog](unsigned int planId)
|
||||
{
|
||||
dialog->dialogWidget()->planOverlayModel()->removeOverlay(planId);
|
||||
};
|
||||
|
||||
|
||||
dialog->dialogWidget()->initFileManagement( nullptr, nullptr, nullptr, doReadFile, doReloadPlan, doUnloadPlan );
|
||||
|
||||
//QDialog * dialog = new QDialog();
|
||||
|
||||
//QVBoxLayout * layout = new QVBoxLayout(dialog);
|
||||
|
||||
//PlanOverlaysPlugin::PlanOverlayModel * planOverlayModel = new PlanOverlaysPlugin::PlanOverlayModel(nullptr);
|
||||
//PlanOverlaysPlugin::PlanOverlayView * planOverlayView = new PlanOverlaysPlugin::PlanOverlayView( planOverlayModel, dialog );
|
||||
//
|
||||
//PlanOverlaysPlugin::PlanOverlayModel::PlanItem planItem = planOverlayModel->planItem(1);
|
||||
//
|
||||
//planItem.m_folderId = 6;
|
||||
//planItem.m_fileId = 42;
|
||||
//planItem.m_dirPath = QStringLiteral("");
|
||||
//planItem.m_fileName = QStringLiteral("Hugo");
|
||||
//planItem.m_planName = QStringLiteral("Hugo");
|
||||
//planItem.m_minScale = 250000;
|
||||
//planItem.m_maxScale = 12000;
|
||||
//planItem.m_opacity = 1;
|
||||
//planItem.m_visibilty = true;
|
||||
|
||||
//planOverlayModel->updatePlanItem( planItem );
|
||||
|
||||
//planItem.m_id = 2;
|
||||
//planItem.m_fileId = 43;
|
||||
//planItem.m_fileName = QStringLiteral("Soda");
|
||||
//planItem.m_planName = QStringLiteral("Soda");
|
||||
|
||||
//planOverlayModel->updatePlanItem( planItem );
|
||||
|
||||
//planItem.m_id = 3;
|
||||
//planItem.m_fileId = 44;
|
||||
//planItem.m_fileName = QStringLiteral("0815");
|
||||
//planItem.m_planName = QStringLiteral("0815");
|
||||
|
||||
//planOverlayModel->updatePlanItem( planItem );
|
||||
|
||||
|
||||
//layout->addWidget(planOverlayView);
|
||||
|
||||
dialog->show();
|
||||
|
||||
app.setQuitOnLastWindowClosed(true);
|
||||
|
||||
int retval = app.exec();
|
||||
|
||||
SHUTDOWN_LOG(app.baseLogger());
|
||||
|
||||
return retval;
|
||||
}
|
||||
+178
@@ -0,0 +1,178 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Topic Editor for the Plan Topic in the Script Editor
|
||||
* $Id: topic_editor.cpp 48499 2019-09-26 07:56:34Z ojog_i $
|
||||
* $HeadURL: svn://slssvn/TDS/branches/product/devel/trunk/Lts/Plugins/FileManagement/Gui/Explorer/TopicEditor/topic_editor.cpp $
|
||||
* $Author: ojog_i $
|
||||
*
|
||||
* Created by Mike Wille, NLE, 2019-11-11
|
||||
*/
|
||||
|
||||
#include "topic_editor.h"
|
||||
#include "ui_topic_editor.h"
|
||||
#include "../plan_overlays_gui_plugin.h"
|
||||
|
||||
#include <LtsSession/lts_session_data.h>
|
||||
#include <NGLLogger/NGLLoggerBootstrap.h>
|
||||
#include <TopicEditorBase/topic_previewer.h>
|
||||
|
||||
#include <QInputDialog>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
|
||||
|
||||
namespace PlanOverlaysPlugin
|
||||
{
|
||||
|
||||
PlanTopicEditor::PlanTopicEditor(
|
||||
ForeignGuiInterface **ifc, const std::shared_ptr<FileManagement::Interface::Dtc> &flmDtc, QWidget *parent
|
||||
)
|
||||
: TopicEditorBase::TopicEditor(parent)
|
||||
, m_ifc(ifc)
|
||||
, m_flmDtc(flmDtc)
|
||||
, m_model(nullptr)
|
||||
, m_ui(new Ui::PlanTopicEditor)
|
||||
, m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("PlanTopicEditor"))
|
||||
{
|
||||
// init UI
|
||||
m_ui->setupUi(this);
|
||||
init(m_ui->widget);
|
||||
|
||||
m_buttonBox->setText(LtsWidgets::DialogButton::Edit, tr("Manage Plan Overlays"));
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Edit, this, &PlanTopicEditor::onOpenPlanOverlayDialog);
|
||||
if ((*m_ifc) == nullptr)
|
||||
{
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Edit, false);
|
||||
return;
|
||||
}
|
||||
else
|
||||
m_ui->lblReadOnly->hide();
|
||||
|
||||
m_model = (*m_ifc)->planOverlayModel();
|
||||
|
||||
#ifndef LTS_DEBUG
|
||||
if (LtsSessionData::LtsSessionData::getInstance()->debugFlagValue(QStringLiteral("PlanOverlays.TopicEditor.ShowFakeButton")) == QVariant(true))
|
||||
#endif
|
||||
{
|
||||
QPushButton *pb = new QPushButton(QStringLiteral("[fake compatibility mode data]"));
|
||||
layout()->addWidget(pb);
|
||||
connect(pb, &QPushButton::clicked,
|
||||
this, [this]()
|
||||
{
|
||||
// fake data to test compatibility mode:
|
||||
m_topicData.properties = QJsonObject();
|
||||
bool k = true;
|
||||
int fileId = QInputDialog::getInt(this, QStringLiteral("fileId"), QStringLiteral("Enter the file id of an existing plan overlay"), 1003, 0, 999999, 1, &k);
|
||||
if (!k)
|
||||
{
|
||||
QMessageBox::critical(this, QStringLiteral("nan"), QStringLiteral("nan!"));
|
||||
return;
|
||||
}
|
||||
m_topicData.properties[QStringLiteral("FileId")] = fileId;
|
||||
updateInternalData();
|
||||
});
|
||||
}
|
||||
|
||||
setOnlineHelpFilename(QStringLiteral("Script_Editor-Add_Tactical_Plan_Topic"));
|
||||
}
|
||||
|
||||
PlanTopicEditor::~PlanTopicEditor()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// PRIVATE
|
||||
|
||||
void PlanTopicEditor::updateInternalData()
|
||||
{
|
||||
if (!hasTopicDataProperties())
|
||||
return;
|
||||
|
||||
m_planItems = QJsonArray(); // reset
|
||||
|
||||
// compatibility for old plan type topics (old topic only had ONE plan and was determined by only its 'FileId')
|
||||
int fileId = getTopicDataValue(QStringLiteral("FileId")).toInt(-1);
|
||||
|
||||
if (fileId != -1)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "topic compatibility mode - converting..";
|
||||
|
||||
QJsonObject fakePlanItem;
|
||||
fakePlanItem[QStringLiteral("keyId")] = 0;
|
||||
fakePlanItem[QStringLiteral("fileId")] = fileId;
|
||||
QString fileName;
|
||||
if (m_flmDtc)
|
||||
fileName = QString::fromStdString(m_flmDtc->fileContent(fileId).name());
|
||||
if (fileName.isEmpty())
|
||||
fileName = tr("Plan file id %1").arg(fileId);
|
||||
fakePlanItem[QStringLiteral("fileName")] = fileName;
|
||||
fakePlanItem[QStringLiteral("opacity")] = 1.0; // otherwise opacity is 0 and the user can't see it
|
||||
m_planItems += fakePlanItem;
|
||||
}
|
||||
else
|
||||
m_planItems = getTopicDataValue(QStringLiteral("PlanItems")).toArray();
|
||||
|
||||
|
||||
if (m_planItems.isEmpty())
|
||||
{
|
||||
WARNING_LOG(m_logger) << "topic empty";
|
||||
return;
|
||||
}
|
||||
|
||||
retable();
|
||||
}
|
||||
|
||||
void PlanTopicEditor::retranslate()
|
||||
{
|
||||
translate(m_ui, tr("Plan Topic Editor"));
|
||||
}
|
||||
|
||||
|
||||
void PlanTopicEditor::retable()
|
||||
{
|
||||
while (m_ui->plans->rowCount())
|
||||
m_ui->plans->removeRow(m_ui->plans->rowCount() - 1);
|
||||
|
||||
for (auto i = m_planItems.constBegin(); i != m_planItems.constEnd(); ++i)
|
||||
{
|
||||
m_ui->plans->insertRow(0);
|
||||
m_ui->plans->setItem(0, 0, new QTableWidgetItem((*i).toObject()[QStringLiteral("fileName")].toString(tr("(unknown)"))));
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// PRIVATE SLOTS
|
||||
|
||||
bool PlanTopicEditor::apply2()
|
||||
{
|
||||
m_topicData.properties.remove(QStringLiteral("FileId")); // remove old plan file id (if available)
|
||||
setTopicDataProperty(QStringLiteral("PlanItems"), m_planItems);
|
||||
setDescription(m_ui->widget->description());
|
||||
m_ui->widget->previewer()->setTopicData(m_topicData);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void PlanTopicEditor::onOpenPlanOverlayDialog()
|
||||
{
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Edit, false); // disable until already opened plan overlay dialog was closed or fully disable because essentials view was closed
|
||||
|
||||
if ((*m_ifc) == nullptr)
|
||||
{
|
||||
new LtsWidgets::LtsMessageDialogNew(this, tr("Plans can't be edited because essentials view was closed"));
|
||||
return;
|
||||
}
|
||||
|
||||
connect((*m_ifc)->openPlanOverlayDialog(m_planItems, true), &QWidget::destroyed, this, [this]()
|
||||
{
|
||||
m_planItems = m_model->toJson();
|
||||
retable();
|
||||
slotChangesMade();
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Edit);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace PlanOverlaysPlugin
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Topic Editor for the Situation Topic in the Script Editor
|
||||
* $Id: topic_editor.h 47904 2019-08-09 09:11:38Z ehrlicher $
|
||||
* $HeadURL: svn://slssvn/TDS/branches/product/devel/trunk/Lts/Plugins/FileManagement/Gui/Explorer/TopicEditor/topic_editor.h $
|
||||
* $Author: ehrlicher $
|
||||
*
|
||||
* Created by Mike Wille, NLE, 2019-11-11
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <FileManagement/logger.h>
|
||||
#include <FileManagement/Data/flm_data_plugin.h>
|
||||
#include <LtsSession/lts_session.h>
|
||||
#include <TopicEditorBase/topic_editor_base.h>
|
||||
|
||||
#include <QJsonArray>
|
||||
|
||||
|
||||
namespace Ui { class PlanTopicEditor; }
|
||||
|
||||
|
||||
namespace PlanOverlaysPlugin
|
||||
{
|
||||
|
||||
class ForeignGuiInterface;
|
||||
class PlanOverlayModel;
|
||||
|
||||
|
||||
class PlanTopicEditor : public TopicEditorBase::TopicEditor
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit PlanTopicEditor(
|
||||
ForeignGuiInterface **ifc, const std::shared_ptr<FileManagement::Interface::Dtc> &flmDtc, QWidget *parent = nullptr
|
||||
);
|
||||
~PlanTopicEditor();
|
||||
|
||||
// void updatePreview();
|
||||
|
||||
private:
|
||||
void updateInternalData() override final;
|
||||
void retranslate() override final;
|
||||
|
||||
void retable();
|
||||
void enaDisa();
|
||||
|
||||
private slots:
|
||||
bool apply2() override final;
|
||||
|
||||
void onOpenPlanOverlayDialog();
|
||||
|
||||
private:
|
||||
ForeignGuiInterface **m_ifc { nullptr };
|
||||
std::shared_ptr<FileManagement::Interface::Dtc> m_flmDtc { nullptr };
|
||||
|
||||
QJsonArray m_planItems;
|
||||
PlanOverlayModel *m_model { nullptr };
|
||||
|
||||
Ui::PlanTopicEditor *m_ui { nullptr };
|
||||
NGL::INGLLogger &m_logger;
|
||||
|
||||
};
|
||||
|
||||
} // namespace PlanOverlaysPlugin
|
||||
@@ -0,0 +1,92 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>PlanTopicEditor</class>
|
||||
<widget class="QWidget" name="PlanTopicEditor">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>623</width>
|
||||
<height>357</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">File Topic Editor</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="3" column="0">
|
||||
<widget class="TopicEditorBase::TopicPreviewWidget" name="widget" native="true"/>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QTableWidget" name="plans">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Plan name</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Selected Plans:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="lblReadOnly">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><span style=" color:#d69545;">Start the essentials view before opening this topic editor to be able to edit plans.</span></p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>TopicEditorBase::TopicPreviewWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>TopicEditorBase/topic_preview_widget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** plan_editor.h
|
||||
** $Id$
|
||||
** $HeadURL$
|
||||
** $Author$
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Hardware-Environment: Intel-PC
|
||||
** Software-Environment: Windows 7, Qt 5.7. ArcGIS 100
|
||||
**
|
||||
** Language ........: C++ 11
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Author ...........: Jörg Turla, SPD G, Tel. 3132
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Notes .........:
|
||||
**
|
||||
** 09.05.2017, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#include "flm_reply_handler.h"
|
||||
|
||||
#include <LtsUtilsGuiDds/request_helper.h>
|
||||
|
||||
|
||||
namespace PlanOverlaysPlugin
|
||||
{
|
||||
|
||||
FileManagementReplyHandler::FileManagementReplyHandler( LtsUtils::RequestHelper * requestHelper )
|
||||
: m_requestHelper(requestHelper)
|
||||
{
|
||||
qRegisterMetaType<Core::FunctionReply>("Core::FunctionReply");
|
||||
} // FileManagementReplyHandler::FileManagementReplyHandler( LtsUtils::RequestHelper * requestHelper )
|
||||
|
||||
|
||||
void FileManagementReplyHandler::requestReply( const Core::FunctionReplyObject & replyObject )
|
||||
{
|
||||
m_requestHelper->requestReply(replyObject);
|
||||
} // void FileManagementReplyHandler::requestReply( const Core::FunctionReplyObject & replyObject )
|
||||
|
||||
|
||||
void FileManagementReplyHandler::onGetFileContentDataReply( const FileManagement::GetFileContentDataReply & replyObject )
|
||||
{
|
||||
m_content = replyObject.content();
|
||||
m_requestHelper->requestReply(replyObject);
|
||||
} // void FileManagementReplyHandler::onGetFileContentDataReply( const FileManagement::GetFileContentDataReply & replyObject )
|
||||
|
||||
} // namespace PlanOverlaysPlugin
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** flm_reply_handler.h
|
||||
** $Id$
|
||||
** $HeadURL$
|
||||
** $Author$
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Hardware-Environment: Intel-PC
|
||||
** Software-Environment: Windows 7, Qt 5.7. ArcGIS 100
|
||||
**
|
||||
** Language ........: C++ 11
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Author ...........: Jörg Turla, SPD G, Tel. 3132
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Notes .........:
|
||||
**
|
||||
** 09.05.2017, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <FileManagement/flm_ftc.h>
|
||||
#include <FileManagement/flm_ftc_types.h>
|
||||
|
||||
#include <DDS/DDSConnector/dds_connector.h>
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
class RequestHelper;
|
||||
}
|
||||
|
||||
namespace PlanOverlaysPlugin
|
||||
{
|
||||
class FileManagementReplyHandler
|
||||
: public QObject
|
||||
, public FileManagement::Interface::Ftc::FileContentModifyReplyHandler
|
||||
, public FileManagement::Interface::Ftc::FileContentChangeStatusReplyHandler
|
||||
, public FileManagement::Interface::Ftc::FileContentRemoveReplyHandler
|
||||
, public FileManagement::Interface::Ftc::GetFileContentDataReplyHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit FileManagementReplyHandler( LtsUtils::RequestHelper * );
|
||||
~FileManagementReplyHandler() = default;
|
||||
|
||||
const std::vector<uint8_t> &getContent() const { return m_content; }
|
||||
|
||||
protected:
|
||||
|
||||
// file content
|
||||
void onFileContentModifyReply ( const Core::FunctionReplyObject & replyObject) override final { requestReply(replyObject); }
|
||||
void onFileContentRemoveReply ( const Core::FunctionReplyObject & replyObject) override final { requestReply(replyObject); }
|
||||
void onFileContentChangeStatusReply ( const Core::FunctionReplyObject & replyObject) override final { requestReply(replyObject); }
|
||||
|
||||
void onGetFileContentDataReply( const FileManagement::GetFileContentDataReply & replyObject) override final;
|
||||
|
||||
private:
|
||||
|
||||
void requestReply(const Core::FunctionReplyObject &replyObject);
|
||||
|
||||
LtsUtils::RequestHelper *m_requestHelper;
|
||||
std::vector<uint8_t> m_content;
|
||||
|
||||
}; // FileManagementReplyHandler
|
||||
|
||||
} // namespace PlanOverlaysPlugin
|
||||
+336
@@ -0,0 +1,336 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** plan_overlay_dialog.h
|
||||
** $Id$
|
||||
** $HeadURL$
|
||||
** $Author$
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Hardware-Environment: Intel-PC
|
||||
** Software-Environment: Windows 7, Qt 5.7. ArcGIS 100
|
||||
**
|
||||
** Language ........: C++ 11
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Author ...........: Jörg Turla, SPD G, Tel. 3132
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Notes .........:
|
||||
**
|
||||
** 14.07.2017, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "plan_overlay_dialog.h"
|
||||
|
||||
#include "plan_overlay_model.h"
|
||||
#include "plan_overlay_view.h"
|
||||
|
||||
#include <LtsSession/lts_session.h>
|
||||
#include <LtsWidgets/lts_base_layout_widget.h>
|
||||
|
||||
#include <LtsWidgets/lts_drag_icon.h>
|
||||
#include <LtsWidgets/lts_dialog_button_box.h>
|
||||
|
||||
#include <Viewer/LtsFileDialog/lts_file_dialog_widget.h>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <QtWidgets/QDesktopWidget>
|
||||
#include <QtWidgets/QDialog>
|
||||
#include <QtWidgets/QLabel>
|
||||
#include <QtWidgets/QPushButton>
|
||||
#include <QtWidgets/QSplitter>
|
||||
|
||||
#include <QtWidgets/QVBoxLayout>
|
||||
#include <QtWidgets/QHBoxLayout>
|
||||
|
||||
namespace PlanOverlaysPlugin
|
||||
{
|
||||
//const int PlanFolderID = 30;
|
||||
|
||||
struct PlanOverlayDialogWidget::InternalData
|
||||
{
|
||||
LtsSession::LtsSession *m_session = nullptr;
|
||||
LtsWidgets::LtsFileDialogWidget *m_fileDialogWidget = nullptr;
|
||||
PlanOverlaysPlugin::PlanOverlayModel *m_planOverlayModel = nullptr;
|
||||
PlanOverlaysPlugin::PlanOverlayView *m_planOverlayView = nullptr;
|
||||
SituationMap::ForeignGuiInterface *m_situationMapGui = nullptr;
|
||||
QWidget *m_overlaySection = nullptr;
|
||||
bool m_isInModalDialog = false;
|
||||
|
||||
}; // PlanOverlayDialog::InternalData
|
||||
|
||||
|
||||
PlanOverlayDialogWidget::PlanOverlayDialogWidget(LtsSession::LtsSession *session,
|
||||
SituationMap::ForeignGuiInterface *situationMapGui,
|
||||
PlanOverlayModel *planOverlayModel,
|
||||
QWidget *parent)
|
||||
: QWidget(parent), m_internal(new InternalData())
|
||||
{
|
||||
m_internal->m_session = session;
|
||||
m_internal->m_situationMapGui = situationMapGui;
|
||||
m_internal->m_planOverlayModel = planOverlayModel;
|
||||
|
||||
const QString &title = tr("Managing Plan Overlays");
|
||||
|
||||
setObjectName(QLatin1String("PlanOverlaysPlugin::PlanOverlayDialog"));
|
||||
|
||||
QSplitter *splitter = new QSplitter(this);
|
||||
QWidget *overlays = new QWidget(this);
|
||||
QWidget *ctrlArea = new QWidget(overlays);
|
||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||
QLabel *titleWidget = new QLabel(title, this);
|
||||
|
||||
m_internal->m_fileDialogWidget = new LtsWidgets::LtsFileDialogWidget(this);
|
||||
m_internal->m_planOverlayView = new PlanOverlayView(m_internal->m_planOverlayModel, overlays);
|
||||
|
||||
m_internal->m_planOverlayModel->setFileDialogMimeType(m_internal->m_fileDialogWidget->dragMimeType());
|
||||
|
||||
connect(m_internal->m_planOverlayView, &PlanOverlayView::requestMinScale, this, &PlanOverlayDialogWidget::onRequestMinScaleFromUser);
|
||||
connect(m_internal->m_planOverlayView, &PlanOverlayView::requestMaxScale, this, &PlanOverlayDialogWidget::onRequestMaxScaleFromUser);
|
||||
|
||||
titleWidget->setAlignment(Qt::AlignCenter);
|
||||
// titleWidget->setStyleSheet(QStringLiteral("font-size: 18pt;"));
|
||||
QFont boldFont;
|
||||
boldFont.setBold(true);
|
||||
boldFont.setPointSize(18);
|
||||
titleWidget->setFont(boldFont);
|
||||
layout->addWidget(titleWidget);
|
||||
#ifdef LTS_DEBUG
|
||||
if ((session) && (session->exerciseId() > 0))
|
||||
{
|
||||
const QString &subtitle = tr("Exercise: %1 / Phase: %2").arg(session->exerciseId()).arg(session->exerciseData()->phId);
|
||||
QLabel *subtitleWidget = new QLabel(subtitle, this);
|
||||
subtitleWidget->setAlignment(Qt::AlignCenter);
|
||||
layout->addWidget(subtitleWidget);
|
||||
}
|
||||
#endif
|
||||
layout->addWidget(splitter, 2);
|
||||
layout->setMargin(0);
|
||||
|
||||
splitter->setOrientation(Qt::Orientation::Vertical); // or is Horizontal better here
|
||||
|
||||
splitter->addWidget(m_internal->m_fileDialogWidget);
|
||||
splitter->addWidget(overlays);
|
||||
splitter->setStretchFactor(0, 2);
|
||||
splitter->setStretchFactor(1, 4);
|
||||
|
||||
QPixmap icon(QLatin1String("icon:overlay_load_plan.svg")); // better use left and right buttons
|
||||
|
||||
LtsWidgets::LtsDragIcon *pbAddOverlay = new LtsWidgets::LtsDragIcon(ctrlArea);
|
||||
|
||||
pbAddOverlay->setIcon(QIcon(icon));
|
||||
pbAddOverlay->setText(QString());
|
||||
pbAddOverlay->setIconSize(LtsWidgets::ButtonSize::eDefault);
|
||||
pbAddOverlay->setButtonStyle(LtsWidgets::ButtonStyle::eIconOnly);
|
||||
pbAddOverlay->setToolTip(tr("Load selected plan file and create new plan overlayer at end of display order"));
|
||||
|
||||
connect(pbAddOverlay, &LtsWidgets::LtsDragIcon::clicked, this, &PlanOverlayDialogWidget::onLoadPlan);
|
||||
|
||||
#ifdef DISABLE_ADD_OVERLAY
|
||||
pbAddOverlay->setDisabled(true);
|
||||
connect(m_internal->m_fileDialogWidget, &LtsWidgets::LtsFileDialogWidget::readyToAccept, pbAddOverlay, [pbAddOverlay]()
|
||||
{
|
||||
pbAddOverlay->setDisabled(false);
|
||||
});
|
||||
#endif
|
||||
|
||||
QVBoxLayout *layoutOverlays = new QVBoxLayout(overlays); // or is QHBoxLayout better here
|
||||
|
||||
QHBoxLayout *layoutCtrl = new QHBoxLayout();
|
||||
|
||||
layoutOverlays->addSpacing(5);
|
||||
layoutOverlays->addLayout(layoutCtrl, 0);
|
||||
layoutOverlays->addSpacing(5);
|
||||
layoutOverlays->addWidget(m_internal->m_planOverlayView, 2);
|
||||
|
||||
layoutCtrl->addStretch(2);
|
||||
layoutCtrl->addSpacing(20);
|
||||
layoutCtrl->addWidget(pbAddOverlay);
|
||||
layoutCtrl->addSpacing(20);
|
||||
layoutCtrl->addStretch(2);
|
||||
|
||||
m_internal->m_overlaySection = overlays;
|
||||
|
||||
if (m_internal->m_situationMapGui)
|
||||
{
|
||||
auto mapIsReady = [this]() { onEnableOverlaySection(true); };
|
||||
if (!m_internal->m_situationMapGui->setMapReadyCallback(this, mapIsReady))
|
||||
qCritical() << " setMapReadyCallback failed";
|
||||
|
||||
}
|
||||
|
||||
onEnableOverlaySection(true);
|
||||
|
||||
// setMinimumHeight(int(QApplication::desktop()->availableGeometry().height()*0.9));
|
||||
|
||||
|
||||
} // PlanOverlayDialogWidget::PlanOverlayDialogWidget( QWidget * parent )
|
||||
|
||||
|
||||
PlanOverlayDialogWidget::~PlanOverlayDialogWidget()
|
||||
{
|
||||
delete m_internal;
|
||||
} // PlanOverlayDialogWidget::~PlanOverlayDialogWidget()
|
||||
|
||||
|
||||
|
||||
bool PlanOverlayDialogWidget::isInModalDialog() const { return m_internal->m_isInModalDialog; }
|
||||
|
||||
|
||||
void PlanOverlayDialogWidget::setIsInModalDialog(bool on) { m_internal->m_isInModalDialog = on; }
|
||||
|
||||
|
||||
bool PlanOverlayDialogWidget::initFileManagement(const std::shared_ptr<FileManagement::Interface::Dtc> &dtc
|
||||
, const std::shared_ptr<OperatorManagement::Interface::Dtc> &opmDtc
|
||||
, const std::shared_ptr<ExerciseManagement::Interface::Dtc> &exmDtc
|
||||
, const std::function<void(int selectedFileId)> &doRead
|
||||
, const std::function<void(int planId)> &doReload
|
||||
, const std::function<void(int planId)> &doUnload
|
||||
, bool isOc)
|
||||
{
|
||||
int parentFolderId = 0;
|
||||
if (isOc)
|
||||
{
|
||||
//search for exercise folder instead of global plans
|
||||
parentFolderId = dtc->getExerciseFolderId(m_internal->m_session->exerciseId());
|
||||
}
|
||||
|
||||
int planFolderId = dtc->findFolder(parentFolderId, QStringLiteral("Tactical Plans"));
|
||||
|
||||
connect(m_internal->m_fileDialogWidget, &LtsWidgets::LtsFileDialogWidget::readSelectedFile, m_internal->m_fileDialogWidget, [doRead](int fileId)
|
||||
{
|
||||
doRead(fileId);
|
||||
});
|
||||
|
||||
connect(m_internal->m_planOverlayView, &PlanOverlayView::requestUnloadPlan, this, [doUnload](int planId)
|
||||
{
|
||||
doUnload(planId);
|
||||
});
|
||||
|
||||
connect(m_internal->m_planOverlayView, &PlanOverlayView::requestReloadPlanById, this, [doReload](int planId)
|
||||
{
|
||||
doReload(planId);
|
||||
});
|
||||
|
||||
// TODO: init parameter with desired MainFolders
|
||||
QVector<FileManagement::MainFolder> mainFolders;
|
||||
// remove next comment to hide Globald File Structure on OC
|
||||
if (!isOc)
|
||||
mainFolders.append(FileManagement::MainFolder::GlobalDocuments);
|
||||
mainFolders.append(FileManagement::MainFolder::ExerciseDocuments);
|
||||
mainFolders.append(FileManagement::MainFolder::UserDocuments);
|
||||
|
||||
if (!m_internal->m_fileDialogWidget->init(m_internal->m_session, dtc, opmDtc, exmDtc, LtsWidgets::FileDialogMode::modeOpenFile,
|
||||
mainFolders,{FileManagement::FileType::TacticalPlan}, planFolderId))
|
||||
return false;
|
||||
return true;
|
||||
} // bool PlanOverlayDialogWidget::initFileManagement(...)
|
||||
|
||||
|
||||
void PlanOverlayDialogWidget::onEnableOverlaySection(bool on)
|
||||
{
|
||||
m_internal->m_overlaySection->setEnabled(((m_internal->m_situationMapGui) ? m_internal->m_situationMapGui->isMapReady() : true) && on);
|
||||
} // void PlanOverlayDialogWidget::onEnableOverlaySection(bool on)
|
||||
|
||||
|
||||
void PlanOverlayDialogWidget::onLoadPlan()
|
||||
{
|
||||
m_internal->m_fileDialogWidget->requestReadingSelectedFile();
|
||||
}
|
||||
|
||||
void PlanOverlayDialogWidget::onRequestMinScaleFromUser(int planId, const QString &planName)
|
||||
{
|
||||
if (isInModalDialog()) return;
|
||||
|
||||
QHash<LtsWidgets::Button, QString> btnTxt;
|
||||
btnTxt[LtsWidgets::Button::Yes] = tr("Set to current");
|
||||
btnTxt[LtsWidgets::Button::No] = tr("Clear");
|
||||
btnTxt[LtsWidgets::Button::Cancel] = tr("Cancel");
|
||||
|
||||
const LtsWidgets::Button resultBNtn = LtsWidgets::LtsMessageDialog::showMessage(this
|
||||
, tr("Set current scale of map as minimum scale of plan overlay %1?").arg(planName)
|
||||
, tr("Redefine maximum scale of plan overlay")
|
||||
, LtsWidgets::Behaviour::Modal
|
||||
, LtsWidgets::Button::Yes | LtsWidgets::Button::No | LtsWidgets::Button::Cancel
|
||||
, btnTxt);
|
||||
if (resultBNtn == LtsWidgets::Button::Yes)
|
||||
{
|
||||
double minScale = m_internal->m_situationMapGui->getCurrentMapScale();
|
||||
if (minScale > 0.0)
|
||||
{
|
||||
const auto maxScale = m_internal->m_situationMapGui->planOverlayMaxScale(planId);
|
||||
if (minScale < maxScale || qFuzzyIsNull(maxScale))
|
||||
{
|
||||
int row = m_internal->m_planOverlayModel->getRowOfId(planId);
|
||||
m_internal->m_planOverlayModel->setMinScale(row, minScale);
|
||||
}
|
||||
else
|
||||
{
|
||||
QString msg = tr("The value of %1 is not allowed as minimum scale").arg(minScale);
|
||||
LtsWidgets::LtsMessageDialog::showMessage(this, msg, tr("Illegal value of minimum scale"));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (resultBNtn == LtsWidgets::Button::No)
|
||||
{
|
||||
// clear / undefined
|
||||
int row = m_internal->m_planOverlayModel->getRowOfId(planId);
|
||||
m_internal->m_planOverlayModel->setMinScale(row, 0); // 0 == undefined
|
||||
}
|
||||
emit requestDialogShow();
|
||||
} // void PlanOverlayDialogWidget::onSetMinScale( int planId )
|
||||
|
||||
|
||||
void PlanOverlayDialogWidget::onRequestMaxScaleFromUser(int planId, const QString &planName)
|
||||
{
|
||||
if (isInModalDialog()) return;
|
||||
|
||||
QHash<LtsWidgets::Button, QString> btnTxt;
|
||||
btnTxt[LtsWidgets::Button::Yes] = tr("Set to current");
|
||||
btnTxt[LtsWidgets::Button::No] = tr("Clear");
|
||||
btnTxt[LtsWidgets::Button::Cancel] = tr("Cancel");
|
||||
|
||||
const LtsWidgets::Button resultBNtn = LtsWidgets::LtsMessageDialog::showMessage(this
|
||||
, tr("Set current scale of map as maximum scale of plan overlay %1?").arg(planName)
|
||||
, tr("Redefine maximum scale of plan overlay")
|
||||
, LtsWidgets::Behaviour::Modal
|
||||
, LtsWidgets::Button::Yes | LtsWidgets::Button::No | LtsWidgets::Button::Cancel
|
||||
, btnTxt);
|
||||
if (resultBNtn == LtsWidgets::Button::Yes)
|
||||
{
|
||||
double maxScale = m_internal->m_situationMapGui->getCurrentMapScale();
|
||||
if (maxScale > 0)
|
||||
{
|
||||
if (maxScale > m_internal->m_situationMapGui->planOverlayMinScale(planId))
|
||||
{
|
||||
int row = m_internal->m_planOverlayModel->getRowOfId(planId);
|
||||
m_internal->m_planOverlayModel->setMaxScale(row, maxScale);
|
||||
}
|
||||
else
|
||||
{
|
||||
QString msg = tr("The value of %1 is not allowed as maximum scale").arg(maxScale);
|
||||
LtsWidgets::LtsMessageDialog::showMessage(this, msg, tr("Illegal Value of Maximum Scale"));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (resultBNtn == LtsWidgets::Button::No)
|
||||
{
|
||||
// clear / undefined
|
||||
int row = m_internal->m_planOverlayModel->getRowOfId(planId);
|
||||
m_internal->m_planOverlayModel->setMaxScale(row, 0); // 0 == undefined
|
||||
}
|
||||
emit requestDialogShow();
|
||||
}// void PlanOverlayDialogWidget::onSetMaxScale( int planId )
|
||||
|
||||
|
||||
PlanOverlayModel *PlanOverlayDialogWidget::planOverlayModel() const { return m_internal->m_planOverlayModel; }
|
||||
|
||||
} // namespace PlanOverlaysPlugin
|
||||
|
||||
+235
@@ -0,0 +1,235 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** plan_overlay_dialog.h
|
||||
** $Id$
|
||||
** $HeadURL$
|
||||
** $Author$
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Hardware-Environment: Intel-PC
|
||||
** Software-Environment: Windows 7, Qt 5.7. ArcGIS 100
|
||||
**
|
||||
** Language ........: C++ 11
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Author ...........: Jörg Turla, SPD G, Tel. 3132
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Notes .........:
|
||||
**
|
||||
** 14.07.2017, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LtsSession/lts_session.h>
|
||||
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
#include <LtsWidgets/lts_frameless_dialog.h>
|
||||
|
||||
#include <Services/FileManagement/flm_dtc.h>
|
||||
#include <Services/OperatorManagement/opm_dtc.h>
|
||||
#include <Services/ExerciseManagement/exm_dtc.h>
|
||||
|
||||
#include <QtWidgets/QVBoxLayout>
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <QtWidgets/QDesktopWidget>
|
||||
#include <QtWidgets/QDialog>
|
||||
#include <QtWidgets/QPushButton>
|
||||
|
||||
|
||||
namespace SituationMap
|
||||
{
|
||||
class ForeignGuiInterface;
|
||||
}
|
||||
|
||||
|
||||
namespace PlanOverlaysPlugin
|
||||
{
|
||||
class PlanOverlayModel;
|
||||
|
||||
//
|
||||
// class PlanOverlayDialogWidget
|
||||
//
|
||||
class PlanOverlayDialogWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit PlanOverlayDialogWidget(LtsSession::LtsSession *session, SituationMap::ForeignGuiInterface *situationMapGui, PlanOverlayModel *planOverlayModel, QWidget *parent);
|
||||
virtual ~PlanOverlayDialogWidget();
|
||||
|
||||
bool initFileManagement(const std::shared_ptr<FileManagement::Interface::Dtc> &dtc
|
||||
, const std::shared_ptr<OperatorManagement::Interface::Dtc> &opmDtc
|
||||
, const std::shared_ptr<ExerciseManagement::Interface::Dtc> &exmDtc
|
||||
, const std::function<void(int selectedFileId)> &doRead
|
||||
, const std::function<void(int planId)> &doReload
|
||||
, const std::function<void(int planId)> &doUnload
|
||||
, bool isOc = false);
|
||||
|
||||
PlanOverlayModel *planOverlayModel() const;
|
||||
|
||||
bool isInModalDialog() const;
|
||||
void setIsInModalDialog(bool on = true);
|
||||
|
||||
|
||||
private slots:
|
||||
|
||||
void onLoadPlan();
|
||||
|
||||
void onRequestMinScaleFromUser(int planId, const QString &planName);
|
||||
void onRequestMaxScaleFromUser(int planId, const QString &planName);
|
||||
|
||||
void onEnableOverlaySection(bool on);
|
||||
|
||||
signals:
|
||||
|
||||
void requestDialogShow();
|
||||
|
||||
private:
|
||||
|
||||
struct InternalData;
|
||||
|
||||
InternalData *m_internal;
|
||||
|
||||
}; // PlanOverlayDialogWidget
|
||||
|
||||
|
||||
//
|
||||
// Dialog
|
||||
//
|
||||
|
||||
class Dialog : public LtsWidgets::LtsDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit Dialog(QWidget *parent, LtsWidgets::ButtonCombination buttonCombination = LtsWidgets::ButtonCombination::CloseOnly, bool closeable = true)
|
||||
: LtsWidgets::LtsDialog(parent, buttonCombination, closeable)
|
||||
{
|
||||
setUnchangeable();
|
||||
} // Dialog
|
||||
|
||||
virtual ~Dialog() = default;
|
||||
|
||||
void retranslate() {;}
|
||||
|
||||
}; // Dialog
|
||||
|
||||
|
||||
template<class DialogClass> void createPlanOverlayDialog(DialogClass *&dlgPtr, QWidget *parent);
|
||||
|
||||
template<> inline void createPlanOverlayDialog<QDialog>(QDialog *&dlgPtr, QWidget *parent)
|
||||
{
|
||||
dlgPtr = new QDialog(parent);
|
||||
dlgPtr -> setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowStaysOnTopHint | Qt::Dialog);
|
||||
dlgPtr -> setWindowTitle(QObject::tr("Plan Overlays"));
|
||||
} // template<> void createPlanOverlayDialog<QDialog>( QDialog *& dlgPtr, QWidget * parent )
|
||||
|
||||
|
||||
template<> inline void createPlanOverlayDialog<LtsWidgets::LtsFramelessDialog>(LtsWidgets::LtsFramelessDialog *&dlgPtr, QWidget *parent)
|
||||
{
|
||||
dlgPtr = new LtsWidgets::LtsFramelessDialog(parent, LtsWidgets::Behaviour::Modal);
|
||||
} // template<> void createPlanOverlayDialog<LtsWidgets::LtsFramelessDialog>( LtsWidgets::LtsFramelessDialog *&dlgPtr, QWidget * parent )
|
||||
|
||||
|
||||
//
|
||||
// PlanOverlayDialog
|
||||
//
|
||||
template<class DialogClass> class PlanOverlayDialog
|
||||
{
|
||||
DialogClass *m_dialog;
|
||||
PlanOverlayDialogWidget *m_dialogWidget;
|
||||
LtsSession::LtsSession *m_session;
|
||||
|
||||
public:
|
||||
|
||||
// explicit PlanOverlayDialog(LtsSession::LtsSession *session, SituationMap::ForeignGuiInterface *situationMapGui, PlanOverlayModel *planOverlayModel, QWidget *parent)
|
||||
// : m_dialog(nullptr), m_dialogWidget(nullptr), m_session(session)
|
||||
// {
|
||||
// static_assert(std::is_same<DialogClass, LtsWidgets::LtsDialog>::value, "This ctor of template class PlanOverlayDialog can only be used with LtsWidgets::LtsDialog");
|
||||
|
||||
// Dialog *dlg = new Dialog(parent);
|
||||
// PlanOverlayDialogWidget *m_dialogWidget = new PlanOverlayDialogWidget(session, situationMapGui, planOverlayModel, dlg);
|
||||
|
||||
// //QObject::connect(situationMapGui->map(), &QObject::destroyed, m_dialogWidget, &QObject::deleteLater);
|
||||
|
||||
// session->addWidget(dlg, m_dialogWidget->windowTitle(), QLatin1String("PlanOverlayDialog"), LtsWidgets::LayoutArea::eDialogTab, false);
|
||||
|
||||
// m_dialog = dlg;
|
||||
|
||||
// QObject::connect(m_dialogWidget, &PlanOverlayDialogWidget::requestDialogShow, m_dialog, &DialogClass::show);
|
||||
|
||||
// m_dialogWidget->setIsInModalDialog(false);
|
||||
|
||||
// m_dialog->setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
|
||||
// } // PlanOverlayDialog( LtsSession::LtsSession * session, SituationMap::ForeignGuiInterface * situationMapGui, PlanOverlayModel * planOverlayModel, QWidget * parent)
|
||||
|
||||
|
||||
explicit PlanOverlayDialog(SituationMap::ForeignGuiInterface *situationMapGui, PlanOverlayModel *planOverlayModel, QWidget *parent, LtsSession::LtsSession *session)
|
||||
: m_dialog(nullptr), m_dialogWidget(nullptr), m_session(session)
|
||||
{
|
||||
static_assert(std::is_same<DialogClass, LtsWidgets::LtsFramelessDialog>::value || std::is_same<DialogClass, QDialog>::value
|
||||
, "This ctor of template class PlanOverlayDialog can only be used with QDialog and LtsWidgets::LtsFramelessDialog");
|
||||
|
||||
createPlanOverlayDialog(m_dialog, parent);
|
||||
|
||||
m_dialogWidget = new PlanOverlayDialogWidget(m_session, situationMapGui, planOverlayModel, m_dialog);
|
||||
|
||||
//QObject::connect(situationMapGui->map(), &QObject::destroyed, m_dialogWidget, &QObject::deleteLater);
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout(m_dialog);
|
||||
LtsWidgets::LtsDialogButtonBox *buttonBox = new LtsWidgets::LtsDialogButtonBox(parent);
|
||||
|
||||
QPushButton *btn = buttonBox->getButton(LtsWidgets::DialogButton::Help);
|
||||
if (btn && m_session)
|
||||
{
|
||||
QObject::connect(btn, &QPushButton::clicked, m_dialog, [this]() // 'this' can´t be used as 3rd para. So use m_dialog instead
|
||||
{
|
||||
if (m_session)
|
||||
m_session->slotShowOnlineHelp(QStringLiteral("Situation-Plan_Overlays"));
|
||||
});
|
||||
|
||||
btn->setVisible(true);
|
||||
}
|
||||
|
||||
layout->addWidget(m_dialogWidget, 2);
|
||||
layout->addWidget(buttonBox);
|
||||
|
||||
buttonBox->setButtonVisible(LtsWidgets::DialogButton::Apply, false);
|
||||
buttonBox->setButtonVisible(LtsWidgets::DialogButton::Ok, false);
|
||||
|
||||
QObject::connect(buttonBox->getButton(LtsWidgets::DialogButton::Close), &QPushButton::clicked, m_dialog, &DialogClass::close);
|
||||
|
||||
m_dialog->setMinimumHeight(int(QApplication::desktop()->availableGeometry(m_dialogWidget).height() * 0.9));
|
||||
|
||||
QObject::connect(m_dialogWidget, &PlanOverlayDialogWidget::requestDialogShow, m_dialog, &DialogClass::show);
|
||||
|
||||
|
||||
m_dialogWidget->setIsInModalDialog(std::is_same<DialogClass, LtsWidgets::LtsFramelessDialog>::value);
|
||||
|
||||
m_dialog->setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
} // PlanOverlayDialog( SituationMap::ForeignGuiInterface * situationMapGui, PlanOverlayModel * planOverlayModel, QWidget * parent )
|
||||
|
||||
|
||||
virtual ~PlanOverlayDialog() = default;
|
||||
PlanOverlayDialog(const PlanOverlayDialog &) = delete;
|
||||
PlanOverlayDialog &operator = (const PlanOverlayDialog &) = delete;
|
||||
|
||||
PlanOverlayDialogWidget *dialogWidget() const { return m_dialogWidget; }
|
||||
void show() { if (m_dialog) m_dialog->show(); }
|
||||
|
||||
}; // PlanOverlayDialog
|
||||
|
||||
|
||||
|
||||
} // namespace PlanOverlaysPlugin
|
||||
+616
@@ -0,0 +1,616 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** plan_overlay_model.h
|
||||
** $Id$
|
||||
** $HeadURL$
|
||||
** $Author$
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Hardware-Environment: Intel-PC
|
||||
** Software-Environment: Windows 7, Qt 5.7. ArcGIS 100
|
||||
**
|
||||
** Language ........: C++ 11
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Author ...........: Jörg Turla, SPD G, Tel. 3132
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Notes .........:
|
||||
**
|
||||
** 10.07.2017, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "plan_overlay_model.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QDataStream>
|
||||
#include <QMimeData>
|
||||
#include <QJsonArray>
|
||||
|
||||
#include <FileManagement/flm_dtc.h>
|
||||
#include <NGLLogger/NGLLoggerBootstrap.h>
|
||||
|
||||
template<class _Ty, class _Other = _Ty> inline _Ty doExchange(_Ty &_Val, _Other && _New_val)
|
||||
{
|
||||
// assign _New_val to _Val, return previous _Val
|
||||
_Ty _Old_val = std::move(_Val);
|
||||
_Val = std::forward<_Other>(_New_val);
|
||||
return (_Old_val);
|
||||
}
|
||||
|
||||
|
||||
namespace PlanOverlaysPlugin
|
||||
{
|
||||
|
||||
const QLatin1String REORDER_MIMETYPE("application/LtsPlanOverlayItemData/Reorder");
|
||||
|
||||
class PlanOverlayModel::InternalData
|
||||
{
|
||||
public:
|
||||
|
||||
QMap<unsigned int, PlanOverlayModel::PlanItem> m_planStore;
|
||||
QVector<int> m_planOrder;
|
||||
QString m_fileDialogMimeType;
|
||||
|
||||
InternalData()
|
||||
: m_planStore(), m_planOrder(), m_fileDialogMimeType()
|
||||
{
|
||||
} // InternalData(const std::shared_ptr<SituationMap::ForeignGuiInterface> & sitMapGui)
|
||||
|
||||
~InternalData() = default;
|
||||
|
||||
}; // PlanOverLayModel::InternalData
|
||||
|
||||
|
||||
PlanOverlayModel::PlanOverlayModel() : QAbstractItemModel(), m_internal(new InternalData())
|
||||
, m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("PlanOverlayModel"))
|
||||
{;}
|
||||
|
||||
PlanOverlayModel::~PlanOverlayModel()
|
||||
{
|
||||
delete m_internal;
|
||||
} // PlanOverlayModel::~PlanOverlayModel
|
||||
|
||||
#ifdef LTS_DEBUG
|
||||
// show exercise id and phase id, last 2 columns in Debug mode
|
||||
int PlanOverlayModel::columnCount(const QModelIndex &) const { return int(ColumnSection::CustomSection) + 3; }
|
||||
#else
|
||||
int PlanOverlayModel::columnCount(const QModelIndex &) const { return int(ColumnSection::CustomSection) + 1; }
|
||||
#endif
|
||||
int PlanOverlayModel::rowCount(const QModelIndex &) const { return m_internal->m_planStore.size(); }
|
||||
int PlanOverlayModel::size() const { return m_internal->m_planStore.size(); }
|
||||
QMap<unsigned int, PlanOverlayModel::PlanItem> PlanOverlayModel::planStore() const { return m_internal->m_planStore; }
|
||||
|
||||
bool PlanOverlayModel::isEmpty() const { return m_internal->m_planStore.isEmpty(); }
|
||||
|
||||
|
||||
QVariant PlanOverlayModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (role != Qt::DisplayRole ||
|
||||
orientation == Qt::Orientation::Vertical)
|
||||
return QVariant();
|
||||
|
||||
switch (static_cast<ColumnSection>(section))
|
||||
{
|
||||
case ColumnSection::OrderButtons:
|
||||
return QVariant();
|
||||
case ColumnSection::PlanName:
|
||||
return tr("Plan");
|
||||
case ColumnSection::MinScale:
|
||||
return tr("Min. Scale");
|
||||
case ColumnSection::MaxScale:
|
||||
return tr("Max. Scale");
|
||||
case ColumnSection::Opacity:
|
||||
return tr("Opacity");
|
||||
case ColumnSection::CustomSection:
|
||||
return QVariant();
|
||||
case ColumnSection::ExerciseId:
|
||||
return tr("Exercise");
|
||||
case ColumnSection::PhaseId:
|
||||
return tr("Phase");
|
||||
}
|
||||
return QVariant();
|
||||
} // QVariant PlanOverlayModel::headerData( int section, Qt::Orientation orientation, int role ) const
|
||||
|
||||
|
||||
QVariant PlanOverlayModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (index.row() < 0 || index.row() >= m_internal->m_planOrder.size())
|
||||
return QVariant();
|
||||
|
||||
if (Qt::ItemDataRole::TextAlignmentRole == role)
|
||||
{
|
||||
switch (static_cast<ColumnSection>(index.column()))
|
||||
{
|
||||
case ColumnSection::PlanName:
|
||||
return QVariant(Qt::Alignment::enum_type::AlignCenter);
|
||||
case ColumnSection::MinScale:
|
||||
return QVariant(Qt::Alignment::enum_type::AlignRight | Qt::Alignment::enum_type::AlignHCenter);
|
||||
case ColumnSection::MaxScale:
|
||||
return QVariant(Qt::Alignment::enum_type::AlignRight | Qt::Alignment::enum_type::AlignHCenter);
|
||||
case ColumnSection::OrderButtons:
|
||||
case ColumnSection::Opacity:
|
||||
case ColumnSection::CustomSection:
|
||||
case ColumnSection::ExerciseId:
|
||||
case ColumnSection::PhaseId:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
if (Qt::ItemDataRole::DisplayRole == role)
|
||||
{
|
||||
const PlanItem &planItem = m_internal->m_planStore[m_internal->m_planOrder.at(index.row())];
|
||||
switch (static_cast<ColumnSection>(index.column()))
|
||||
{
|
||||
case ColumnSection::OrderButtons:
|
||||
return QString();
|
||||
case ColumnSection::PlanName:
|
||||
return planItem.m_fileName;
|
||||
case ColumnSection::MinScale:
|
||||
return (planItem.m_minScale > 0) ? QStringLiteral("1:%1").arg(planItem.m_minScale) : tr("undefined");
|
||||
case ColumnSection::MaxScale:
|
||||
return (planItem.m_maxScale > 0) ? QStringLiteral("1:%1").arg(planItem.m_maxScale) : tr("undefined");
|
||||
case ColumnSection::Opacity:
|
||||
return planItem.m_opacity;
|
||||
case ColumnSection::CustomSection:
|
||||
return QString();
|
||||
case ColumnSection::ExerciseId:
|
||||
return planItem.m_exerciseId > 0 ? QVariant(planItem.m_exerciseId) : QVariant();
|
||||
case ColumnSection::PhaseId:
|
||||
return planItem.m_phaseId > 0 ? QVariant(planItem.m_phaseId) : QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
|
||||
} // QVariant PlanOverlayModel::data( const QModelIndex & index, int role ) const
|
||||
|
||||
|
||||
QStringList PlanOverlayModel::mimeTypes() const
|
||||
{
|
||||
QStringList typeList;
|
||||
typeList << REORDER_MIMETYPE;
|
||||
if (!m_internal->m_fileDialogMimeType.isEmpty())
|
||||
typeList << m_internal->m_fileDialogMimeType;
|
||||
return typeList;
|
||||
} // QStringList PlanOverlayModel::mimeTypes() const
|
||||
|
||||
|
||||
void PlanOverlayModel::setFileDialogMimeType(const QString &mimeType)
|
||||
{
|
||||
m_internal->m_fileDialogMimeType = mimeType;
|
||||
} // void PlanOverlayModel::setFileDialogMimeType( const QString & mimeType )
|
||||
|
||||
|
||||
QMimeData *PlanOverlayModel::mimeData(const QModelIndexList &indexes) const
|
||||
{
|
||||
if (indexes.isEmpty()) return nullptr;
|
||||
|
||||
int row = indexes.first().row();
|
||||
unsigned int keyId = m_internal->m_planOrder.at(row);
|
||||
QMimeData *mimeData = new QMimeData();
|
||||
QByteArray encodedData;
|
||||
|
||||
mimeData->setData(REORDER_MIMETYPE, encodedData.setNum(keyId));
|
||||
|
||||
return mimeData;
|
||||
} // QMimeData * PlanOverlayModel::mimeData( const QModelIndexList & indexes ) const
|
||||
|
||||
|
||||
bool PlanOverlayModel::canDropMimeData(const QMimeData *data, Qt::DropAction, int row, int, const QModelIndex &) const
|
||||
{
|
||||
if ((row >= 0) && (row < m_internal->m_planOrder.size()))
|
||||
{
|
||||
if (data->hasFormat(REORDER_MIMETYPE))
|
||||
{
|
||||
QByteArray encodedData = data->data(REORDER_MIMETYPE);
|
||||
bool ok = false;
|
||||
unsigned int keyId = encodedData.toUInt(&ok);
|
||||
|
||||
if (ok) return (m_internal->m_planOrder.indexOf(keyId) != row);
|
||||
}
|
||||
|
||||
if ((!m_internal->m_fileDialogMimeType.isEmpty()) && (data->hasFormat(m_internal->m_fileDialogMimeType)))
|
||||
{
|
||||
QByteArray encodedData = data->data(m_internal->m_fileDialogMimeType);
|
||||
bool ok = false;
|
||||
int keyId = encodedData.toUInt(&ok);
|
||||
|
||||
if (ok) return (keyId > 0);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} // bool PlanOverlayModel::canDropMimeData( const QMimeData * data, Qt::DropAction, int, int, const QModelIndex & ) const
|
||||
|
||||
|
||||
bool PlanOverlayModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
|
||||
{
|
||||
if (!canDropMimeData(data, action, row, column, parent)) return false;
|
||||
|
||||
if (action == Qt::IgnoreAction) return true;
|
||||
|
||||
emit dropPlanAccepted();
|
||||
|
||||
if (data->hasFormat(REORDER_MIMETYPE))
|
||||
{
|
||||
QByteArray encodedData = data->data(REORDER_MIMETYPE);
|
||||
bool ok = false;
|
||||
int keyId = encodedData.toInt(&ok);
|
||||
|
||||
if (!ok) return false;
|
||||
|
||||
int rowToMove = m_internal->m_planOrder.indexOf(keyId);
|
||||
|
||||
if (row != rowToMove)
|
||||
{
|
||||
if (row < rowToMove)
|
||||
{
|
||||
for (; row <= rowToMove; ++row)
|
||||
{
|
||||
unsigned int idSwap = m_internal->m_planOrder[row];
|
||||
m_internal->m_planOrder[row] = keyId;
|
||||
keyId = idSwap;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (--row; row >= rowToMove; --row)
|
||||
{
|
||||
unsigned int idSwap = m_internal->m_planOrder[row];
|
||||
m_internal->m_planOrder[row] = keyId;
|
||||
keyId = idSwap;
|
||||
}
|
||||
}
|
||||
emit dataChanged(createIndex(0, 0), createIndex(m_internal->m_planOrder.size() - 1, columnCount(QModelIndex()) - 1));
|
||||
emit layoutChanged();
|
||||
emit planOrderChanged(m_internal->m_planOrder);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((!m_internal->m_fileDialogMimeType.isEmpty()) && (data->hasFormat(m_internal->m_fileDialogMimeType)))
|
||||
{
|
||||
QByteArray encodedData = data->data(m_internal->m_fileDialogMimeType);
|
||||
bool ok = false;
|
||||
int fileId = encodedData.toInt(&ok);
|
||||
|
||||
if ((ok) && (fileId > 0))
|
||||
{
|
||||
emit requestLoadPlan(fileId);
|
||||
|
||||
// so the plan is now loaded at end of overlay list, move it a the right position
|
||||
|
||||
int rowToMove = m_internal->m_planOrder.size() - 1;
|
||||
int keyId = m_internal->m_planOrder[rowToMove];
|
||||
|
||||
if (row != rowToMove)
|
||||
{
|
||||
for (; row <= rowToMove; ++row)
|
||||
keyId = doExchange(m_internal->m_planOrder[row], keyId);
|
||||
emit dataChanged(createIndex(0, 0), createIndex(m_internal->m_planOrder.size() - 1, columnCount(QModelIndex()) - 1));
|
||||
emit layoutChanged();
|
||||
emit planOrderChanged(m_internal->m_planOrder);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
QJsonArray PlanOverlayModel::toJson() const
|
||||
{
|
||||
QJsonArray result;
|
||||
|
||||
if (m_internal->m_planStore.count() != m_internal->m_planOrder.count())
|
||||
{
|
||||
Q_ASSERT(m_internal->m_planStore.count() == m_internal->m_planOrder.count());
|
||||
return result;
|
||||
}
|
||||
|
||||
// save in reverse order, because loadPlan appends plans instead of prepending
|
||||
for (int i = m_internal->m_planStore.count() - 1; i >= 0; i--)
|
||||
{
|
||||
PlanItem planItem = m_internal->m_planStore[m_internal->m_planOrder.at(i)];
|
||||
result += planItem.toJson();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
PlanOverlayModel::PlanItem PlanOverlayModel::planItem(int keyId)
|
||||
{
|
||||
if (keyId < 1)
|
||||
{
|
||||
static int nextKey = 1;
|
||||
|
||||
keyId = nextKey++;
|
||||
}
|
||||
|
||||
PlanItem &planItem = m_internal->m_planStore[keyId];
|
||||
planItem.m_keyId = keyId;
|
||||
return planItem;
|
||||
}
|
||||
|
||||
|
||||
PlanOverlayModel::PlanItem &PlanOverlayModel::planItemRef(int keyId)
|
||||
{
|
||||
return m_internal->m_planStore[keyId];
|
||||
}
|
||||
|
||||
|
||||
PlanOverlayModel::PlanItem PlanOverlayModel::planItemValue(int keyId)
|
||||
{
|
||||
QMap<unsigned int, PlanOverlayModel::PlanItem>::Iterator found = m_internal->m_planStore.find(keyId);
|
||||
|
||||
return (found == m_internal->m_planStore.end()) ? PlanItem() : found.value();
|
||||
}
|
||||
|
||||
|
||||
PlanOverlayModel::PlanItem PlanOverlayModel::planItemAtRow(int row)
|
||||
{
|
||||
if ((row < 0) || (row >= m_internal->m_planOrder.size())) return PlanItem();
|
||||
unsigned int planKeyId = m_internal->m_planOrder.at(row);
|
||||
return m_internal->m_planStore[planKeyId];
|
||||
}
|
||||
|
||||
|
||||
PlanOverlayModel::PlanItem PlanOverlayModel::findPlanItemByFileId(int fileId)
|
||||
{
|
||||
if (fileId < 1)
|
||||
return PlanItem();
|
||||
|
||||
QMap<unsigned int, PlanOverlayModel::PlanItem>::const_iterator it;
|
||||
for (it = m_internal->m_planStore.constBegin(); it != m_internal->m_planStore.constEnd(); ++it)
|
||||
{
|
||||
if (it.value().m_fileId == fileId)
|
||||
return it.value();
|
||||
}
|
||||
|
||||
return PlanItem();
|
||||
}
|
||||
|
||||
|
||||
Qt::ItemFlags PlanOverlayModel::flags(const QModelIndex &modelIndex) const
|
||||
{
|
||||
Qt::ItemFlags flags = QAbstractItemModel::flags(modelIndex) | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
|
||||
|
||||
switch (static_cast<ColumnSection>(modelIndex.column()))
|
||||
{
|
||||
case ColumnSection::OrderButtons:
|
||||
case ColumnSection::PlanName:
|
||||
case ColumnSection::MinScale:
|
||||
case ColumnSection::MaxScale:
|
||||
case ColumnSection::Opacity:
|
||||
flags |= Qt::ItemIsEditable;
|
||||
break;
|
||||
case ColumnSection::CustomSection:
|
||||
case ColumnSection::ExerciseId:
|
||||
case ColumnSection::PhaseId:
|
||||
break;
|
||||
}
|
||||
|
||||
return flags;
|
||||
} // Qt::ItemFlags PlanOverlayModel::flags( const QModelIndex & modelIndex ) const
|
||||
|
||||
|
||||
void PlanOverlayModel::updatePlanItem(const PlanItem &planItem)
|
||||
{
|
||||
if (!planItem.isValid())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "planItem has invalid key";
|
||||
return;
|
||||
}
|
||||
|
||||
m_internal->m_planStore[planItem.m_keyId] = planItem;
|
||||
|
||||
beginResetModel();
|
||||
{
|
||||
if (!m_internal->m_planOrder.contains(planItem.m_keyId))
|
||||
m_internal->m_planOrder.prepend(planItem.m_keyId);
|
||||
}
|
||||
endResetModel();
|
||||
|
||||
int row = m_internal->m_planOrder.size() - 1;
|
||||
emit dataChanged(index(row, 0, QModelIndex()), index(row, columnCount(QModelIndex()) - 1, QModelIndex()));
|
||||
emit layoutChanged();
|
||||
} // void PlanOverlayModel::updatePlanItem(PlanItem & planItem)
|
||||
|
||||
|
||||
void PlanOverlayModel::swapRow(int row1, int row2)
|
||||
{
|
||||
if (row1 < 0) return;
|
||||
if (row2 < 0) return;
|
||||
if (row1 >= m_internal->m_planOrder.size()) return;
|
||||
if (row2 >= m_internal->m_planOrder.size()) return;
|
||||
|
||||
m_internal->m_planOrder[row2] = doExchange(m_internal->m_planOrder[row1], m_internal->m_planOrder[row2]);
|
||||
|
||||
QModelIndex topLeftIndex;
|
||||
QModelIndex bottomRightIndex;
|
||||
|
||||
if (row1 < row2)
|
||||
{
|
||||
topLeftIndex = createIndex(row1, 0);
|
||||
bottomRightIndex = createIndex(row2, columnCount(QModelIndex()) - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
topLeftIndex = createIndex(row2, 0);
|
||||
bottomRightIndex = createIndex(row1, columnCount(QModelIndex()) - 1);
|
||||
}
|
||||
|
||||
emit dataChanged(topLeftIndex, bottomRightIndex);
|
||||
emit planOrderChanged(m_internal->m_planOrder);
|
||||
|
||||
} // void PlanOverlayModel::swapRow(int row1, int row2)
|
||||
|
||||
|
||||
int PlanOverlayModel::getRowOfId(int keyId) const
|
||||
{
|
||||
return m_internal->m_planOrder.indexOf(keyId);
|
||||
} // PlanOverlayModel::getRowOfId( int id )
|
||||
|
||||
|
||||
void PlanOverlayModel::setMinScale(int row, double scale)
|
||||
{
|
||||
if (row < 0) return;
|
||||
if (row >= m_internal->m_planOrder.size()) return;
|
||||
|
||||
const int id = m_internal->m_planOrder[row];
|
||||
|
||||
planItemRef(id).m_minScale = scale;
|
||||
|
||||
emit planMinScaleChanged(id, scale);
|
||||
|
||||
const QModelIndex &modelIndex = createIndex(row, int(ColumnSection::MinScale));
|
||||
emit dataChanged(modelIndex, modelIndex);
|
||||
} // void PlanOverlayModel::setMinScale( int row, double scale )
|
||||
|
||||
|
||||
void PlanOverlayModel::setMaxScale(int row, double scale)
|
||||
{
|
||||
if (row < 0) return;
|
||||
if (row >= m_internal->m_planOrder.size()) return;
|
||||
|
||||
const int id = m_internal->m_planOrder[row];
|
||||
|
||||
planItemRef(id).m_maxScale = scale;
|
||||
|
||||
emit planMaxScaleChanged(id, scale);
|
||||
|
||||
const QModelIndex &modelIndex = createIndex(row, int(ColumnSection::MaxScale));
|
||||
emit dataChanged(modelIndex, modelIndex);
|
||||
} // void PlanOverlayModel::setMaxScale( int row, double scale )
|
||||
|
||||
|
||||
void PlanOverlayModel::setOpacity(int row, double opacity)
|
||||
{
|
||||
if (row < 0) return;
|
||||
if (row >= m_internal->m_planOrder.size()) return;
|
||||
|
||||
if (opacity < 0) opacity = 0.0;
|
||||
if (opacity > 1) opacity = 1.0;
|
||||
|
||||
const int id = m_internal->m_planOrder[row];
|
||||
|
||||
planItemRef(id).m_opacity = opacity;
|
||||
|
||||
emit planOpacityChanged(id, opacity);
|
||||
|
||||
const QModelIndex &modelIndex = createIndex(row, int(ColumnSection::Opacity));
|
||||
emit dataChanged(modelIndex, modelIndex);
|
||||
} // void PlanOverlayModel::setAlpha( int row, double alpha )
|
||||
|
||||
|
||||
void PlanOverlayModel::updateOverlay(int keyId)
|
||||
{
|
||||
// keep in mimd fileId is same as planId here
|
||||
int row = m_internal->m_planOrder.indexOf(keyId);
|
||||
|
||||
if (row < 0) return;
|
||||
if (row >= m_internal->m_planOrder.size()) return;
|
||||
|
||||
emit dataChanged(createIndex(row, 0), createIndex(row, columnCount(QModelIndex()) - 1));
|
||||
emit requestUpdatePlan(keyId);
|
||||
|
||||
} // void PlanOverlayModel::updateOverlay(int fileId)
|
||||
|
||||
|
||||
void PlanOverlayModel::renewPlanItem(const PlanItem &planItem)
|
||||
{
|
||||
int row = m_internal->m_planOrder.indexOf(planItem.m_keyId);
|
||||
|
||||
if (row < 0) return;
|
||||
if (row >= m_internal->m_planOrder.size()) return;
|
||||
|
||||
m_internal->m_planStore[planItem.m_keyId] = planItem;
|
||||
emit dataChanged(createIndex(row, 0), createIndex(row, columnCount(QModelIndex()) - 1));
|
||||
|
||||
} // void PlanOverlayModel::renewPlanItem( const PlanItem & planItem )
|
||||
|
||||
|
||||
void PlanOverlayModel::removeOverlay(int keyId)
|
||||
{
|
||||
int row = m_internal->m_planOrder.indexOf(keyId);
|
||||
|
||||
if (row < 0) return;
|
||||
if (row >= m_internal->m_planOrder.size()) return;
|
||||
|
||||
emit requestRemovePlan(keyId); // Important: remove first from situation map and there for we need information from model entry
|
||||
|
||||
beginResetModel();
|
||||
{
|
||||
m_internal->m_planStore.remove(keyId);
|
||||
m_internal->m_planOrder.remove(row);
|
||||
}
|
||||
endResetModel();
|
||||
|
||||
|
||||
|
||||
emit dataChanged(createIndex(0, 0), createIndex(m_internal->m_planOrder.size() - 1, columnCount(QModelIndex()) - 1));
|
||||
emit layoutChanged();
|
||||
|
||||
} // void PlanOverlayModel::removeOverlay( int keyId )
|
||||
|
||||
|
||||
bool PlanOverlayModel::reInitModel(int exerciseId, int phaseId)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "ReInit Model for exerciseId = " << exerciseId << ", phaseId = " << phaseId;
|
||||
|
||||
if ((exerciseId < 1) || (phaseId < 1))
|
||||
{
|
||||
// what's to do here??
|
||||
WARNING_LOG(m_logger) << LOGFUNCTION << " has been called with undefined exercise and/or phaseId";
|
||||
return false;
|
||||
}
|
||||
|
||||
QVector<int> removeList;
|
||||
|
||||
removeList.reserve(m_internal->m_planOrder.size());
|
||||
|
||||
QMap<unsigned int, PlanOverlayModel::PlanItem>::const_iterator it;
|
||||
for (it = m_internal->m_planStore.constBegin(); it != m_internal->m_planStore.constEnd(); ++it)
|
||||
{
|
||||
int planExId = it.value().m_exerciseId;
|
||||
int planPhId = it.value().m_phaseId;
|
||||
|
||||
DEBUG_LOG(m_logger) << "Plan name = " << it.value().m_fileName << " exercise = " << planExId << " phase = " << planPhId;
|
||||
|
||||
if ((planExId < 1) || (planPhId < 1) || ((planExId == exerciseId) && (planPhId == phaseId)))
|
||||
{
|
||||
// nothing to do, exercise and phase did not change or it is a global or user plan
|
||||
continue;
|
||||
}
|
||||
|
||||
bool removeFromModel(false);
|
||||
|
||||
emit requestReloadPlanByName(it.value(), exerciseId, phaseId, &removeFromModel);
|
||||
|
||||
if (removeFromModel) removeList << it.value().m_keyId;
|
||||
} // for m_planOder
|
||||
|
||||
// remove all plans which doesn't exist any more from model
|
||||
for (auto id : qAsConst(removeList)) removeOverlay(id);
|
||||
|
||||
emit dataChanged(createIndex(0, 0), createIndex(m_internal->m_planOrder.size() - 1, columnCount(QModelIndex()) - 1));
|
||||
emit layoutChanged();
|
||||
|
||||
return true;
|
||||
} // void PlanOverlayModel::reInitModel(int exerciseId, int phaseId)
|
||||
|
||||
|
||||
void PlanOverlayModel::updateOrderOfPlans() const
|
||||
{
|
||||
emit const_cast<PlanOverlayModel *>(this)->planOrderChanged(m_internal->m_planOrder);
|
||||
} // void PlanOverlayModel::updateOrderOfPlans() const
|
||||
|
||||
|
||||
} // namespace PlanOverlaysPlugin
|
||||
+215
@@ -0,0 +1,215 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** plan_overlay_model.h
|
||||
** $Id$
|
||||
** $HeadURL$
|
||||
** $Author$
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Hardware-Environment: Intel-PC
|
||||
** Software-Environment: Windows 7, Qt 5.7. ArcGIS 100
|
||||
**
|
||||
** Language ........: C++ 11
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Author ...........: Jörg Turla, SPD G, Tel. 3132
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Notes .........:
|
||||
**
|
||||
** 10.07.2017, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Plugins/SituationMapPlugin/situation_map_gui_plugin_interface.h>
|
||||
#include <NGLLogger/INGLLogger.h>
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QJsonObject>
|
||||
|
||||
|
||||
namespace PlanOverlaysPlugin
|
||||
{
|
||||
|
||||
class PlanOverlayModel final : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
enum class ColumnSection
|
||||
{
|
||||
OrderButtons = 0,
|
||||
PlanName,
|
||||
MinScale,
|
||||
MaxScale,
|
||||
Opacity,
|
||||
CustomSection,
|
||||
ExerciseId,
|
||||
PhaseId
|
||||
};
|
||||
|
||||
PlanOverlayModel();
|
||||
~PlanOverlayModel();
|
||||
|
||||
/**
|
||||
@name Overloaded function from AbstractItemModel
|
||||
@{
|
||||
*/
|
||||
int columnCount(const QModelIndex &) const override;
|
||||
int rowCount(const QModelIndex &) const override;
|
||||
int size() const;
|
||||
|
||||
bool isEmpty() const;
|
||||
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::ItemDataRole::DisplayRole) const override;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::ItemDataRole::DisplayRole) const override;
|
||||
|
||||
QModelIndex index(int row, int column, const QModelIndex &) const override { return createIndex(row, column); }
|
||||
QModelIndex parent(const QModelIndex &) const override { return QModelIndex(); }
|
||||
Qt::ItemFlags flags(const QModelIndex &modelIndex) const override;
|
||||
QModelIndex index(int row, int column) const { return index(row, column, QModelIndex()); }
|
||||
|
||||
QStringList mimeTypes() const override;
|
||||
|
||||
QMimeData *mimeData(const QModelIndexList &indexes) const override;
|
||||
|
||||
Qt::DropActions supportedDragActions() const override { return Qt::CopyAction | Qt::MoveAction; }
|
||||
Qt::DropActions supportedDropActions() const override { return Qt::CopyAction | Qt::MoveAction; }
|
||||
|
||||
bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &) const override;
|
||||
|
||||
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &) override;
|
||||
/**
|
||||
@}
|
||||
*/
|
||||
|
||||
struct PlanItem
|
||||
{
|
||||
int m_keyId = -1;
|
||||
int m_folderId = -1;
|
||||
int m_fileId = -1;
|
||||
int m_exerciseId = -1;
|
||||
int m_phaseId = -1;
|
||||
QString m_dirPath;
|
||||
QString m_fileName;
|
||||
double m_minScale = 0.0;
|
||||
double m_maxScale = 0.0;
|
||||
double m_opacity = 0.0;
|
||||
bool m_visibility = true;
|
||||
|
||||
bool isValid() const { return m_keyId > 0; }
|
||||
QJsonObject toJson() const
|
||||
{
|
||||
QJsonObject obj;
|
||||
|
||||
obj[QStringLiteral("keyId")] = m_keyId;
|
||||
obj[QStringLiteral("folderId")] = m_folderId;
|
||||
obj[QStringLiteral("fileId")] = m_fileId;
|
||||
obj[QStringLiteral("fileName")] = m_fileName;
|
||||
|
||||
obj[QStringLiteral("exerciseId")] = m_exerciseId;
|
||||
obj[QStringLiteral("phaseId")] = m_phaseId;
|
||||
|
||||
obj[QStringLiteral("opacity")] = m_opacity;
|
||||
obj[QStringLiteral("maxScale")] = m_maxScale;
|
||||
obj[QStringLiteral("minScale")] = m_minScale;
|
||||
obj[QStringLiteral("visibility")] = m_visibility;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
static PlanItem fromJson(const QJsonObject &obj)
|
||||
{
|
||||
PlanItem pi;
|
||||
|
||||
pi.m_keyId = obj[QStringLiteral("keyId")].toInt();
|
||||
pi.m_folderId = obj[QStringLiteral("folderId")].toInt();
|
||||
pi.m_fileId = obj[QStringLiteral("fileId")].toInt();
|
||||
pi.m_fileName = obj[QStringLiteral("fileName")].toInt();
|
||||
|
||||
pi.m_exerciseId = obj[QStringLiteral("exerciseId")].toInt();
|
||||
pi.m_phaseId = obj[QStringLiteral("phaseId")].toInt();
|
||||
|
||||
pi.m_opacity = obj[QStringLiteral("opacity")].toDouble();
|
||||
pi.m_maxScale = obj[QStringLiteral("maxScale")].toDouble();
|
||||
pi.m_minScale = obj[QStringLiteral("minScale")].toDouble();
|
||||
pi.m_visibility = obj[QStringLiteral("visibility")].toBool();
|
||||
|
||||
return pi;
|
||||
}
|
||||
|
||||
}; // PlanItem
|
||||
|
||||
QMap<unsigned int, PlanItem> planStore() const;
|
||||
|
||||
PlanItem planItem(int keyId);
|
||||
|
||||
PlanItem planItemValue(int keyId);
|
||||
|
||||
PlanItem planItemAtRow(int row);
|
||||
|
||||
PlanItem findPlanItemByFileId(int fileId);
|
||||
|
||||
int getRowOfId(int keyId) const;
|
||||
|
||||
void updatePlanItem(const PlanItem &planItem);
|
||||
|
||||
void renewPlanItem(const PlanItem &planItem);
|
||||
|
||||
void setMinScale(int row, double scale);
|
||||
void setMaxScale(int row, double scale);
|
||||
void setOpacity(int row, double opacity);
|
||||
|
||||
void swapRow(int row1, int row2);
|
||||
|
||||
void removeOverlay(int keyId);
|
||||
|
||||
void setFileDialogMimeType(const QString &mimeType);
|
||||
|
||||
void updateOverlay(int keyId);
|
||||
|
||||
bool reInitModel(int exerciseId, int phaseId);
|
||||
|
||||
void updateOrderOfPlans() const;
|
||||
|
||||
QJsonArray toJson() const;
|
||||
|
||||
signals:
|
||||
|
||||
void requestLoadPlan(int keyId);
|
||||
void requestReloadPlan(int keyId);
|
||||
void requestUpdatePlan(int keyId);
|
||||
void requestRemovePlan(int keyId);
|
||||
|
||||
void requestReloadPlanByName(const PlanOverlaysPlugin::PlanOverlayModel::PlanItem &planItem, int exerciseId, int phaseId, bool *removeFromModel);
|
||||
|
||||
void planMinScaleChanged(int keyId, double minScale);
|
||||
void planMaxScaleChanged(int keyId, double maxScale);
|
||||
void planOpacityChanged(int keyId, double opacity);
|
||||
|
||||
void planOrderChanged(const QVector<int> &newIdOrder);
|
||||
|
||||
void dropPlanAccepted();
|
||||
|
||||
private:
|
||||
|
||||
PlanItem &planItemRef(int keyId);
|
||||
|
||||
class InternalData;
|
||||
|
||||
InternalData *m_internal;
|
||||
|
||||
NGL::INGLLogger &m_logger;
|
||||
|
||||
}; // PlanOverlayModel
|
||||
|
||||
} // namespace PlanOverlaysPlugin
|
||||
+621
@@ -0,0 +1,621 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** plan_overlay_view.h
|
||||
** $Id$
|
||||
** $HeadURL$
|
||||
** $Author$
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Hardware-Environment: Intel-PC
|
||||
** Software-Environment: Windows 7, Qt 5.7. ArcGIS 100
|
||||
**
|
||||
** Language ........: C++ 11
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Author ...........: Jörg Turla, SPD G, Tel. 3132
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Notes .........:
|
||||
**
|
||||
** 11.07.2017, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "plan_overlay_view.h"
|
||||
#include "plan_overlay_model.h"
|
||||
|
||||
#include <LtsWidgets/lts_drag_icon.h>
|
||||
|
||||
#include <QtCore/QByteArray>
|
||||
|
||||
#include <QtGui/QGuiApplication>
|
||||
#include <QtGui/QPainter>
|
||||
#include <QtGui/QTransform>
|
||||
|
||||
#include <QtWidgets/QHeaderView>
|
||||
#include <QtWidgets/QLabel>
|
||||
#include <QtWidgets/QPushButton>
|
||||
#include <QtWidgets/QSlider>
|
||||
#include <QtWidgets/QStyledItemDelegate>
|
||||
#include <QtWidgets/QVBoxLayout>
|
||||
#include <QtWidgets/QWidget>
|
||||
|
||||
|
||||
namespace PlanOverlaysPlugin
|
||||
{
|
||||
|
||||
class WidgetItemDelegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
|
||||
PlanOverlayView *m_planOverlayView;
|
||||
|
||||
mutable QMap<QByteArray, QWidget *> m_widgetMap;
|
||||
mutable QMap<QByteArray, QSize> m_sizeHints;
|
||||
|
||||
QByteArray buildKey(const QModelIndex &index) const
|
||||
{
|
||||
return QByteArray::number(index.row()) + ',' + QByteArray::number(index.column());
|
||||
} // QByteArray buildKey(const QModelIndex & index) const
|
||||
|
||||
|
||||
void removeKey(const QByteArray &indexKey, QObject *qobj) const
|
||||
{
|
||||
QWidget *widget = qobject_cast<QWidget *>(qobj);
|
||||
|
||||
if (nullptr == widget) return;
|
||||
if (!m_widgetMap.contains(indexKey)) return;
|
||||
if (widget != m_widgetMap[indexKey]) return;
|
||||
|
||||
// qCritical() << "remove key " << indexKey << " --> " << widget;
|
||||
|
||||
m_sizeHints.remove(indexKey);
|
||||
m_widgetMap.remove(indexKey);
|
||||
} // removeKey
|
||||
|
||||
public:
|
||||
|
||||
explicit WidgetItemDelegate(PlanOverlayView *planOverlayView) : QStyledItemDelegate(planOverlayView), m_planOverlayView(planOverlayView) {;}
|
||||
~WidgetItemDelegate() = default;
|
||||
|
||||
|
||||
void destroyEditor(QWidget *editor, const QModelIndex &index) const override
|
||||
{
|
||||
if (!index.isValid()) return;
|
||||
if (m_planOverlayView->model()->rowCount() <= index.row()) return; // do not destroy will be needed again
|
||||
|
||||
const QByteArray &indexKey = buildKey(index);
|
||||
removeKey(indexKey, editor);
|
||||
if (editor) editor-> deleteLater();
|
||||
|
||||
// qCritical() << "Destroy widget " << indexKey << " --> " << editor;
|
||||
} // void destroyEditor(QWidget* editor, const QModelIndex & index) const
|
||||
|
||||
|
||||
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override
|
||||
{
|
||||
const QByteArray &indexKey = buildKey(index);
|
||||
|
||||
const QVariant &modelData = index.model()->data(index, Qt::DisplayRole);
|
||||
|
||||
if (m_widgetMap.contains(indexKey))
|
||||
{
|
||||
QWidget *w = m_widgetMap[indexKey];
|
||||
removeKey(indexKey, w);
|
||||
if (w) w->deleteLater();
|
||||
}
|
||||
|
||||
const QString &backgroundStyle = QStringLiteral("background-color: %1; color: %2; border:none;").arg(QGuiApplication::palette().color(QPalette::ColorRole::Base).name(),
|
||||
m_planOverlayView->palette().text().color().name());
|
||||
const QString &backgroundDisabledStyle = QStringLiteral("background-color: %1; color: %2; border:none;").arg(QGuiApplication::palette().color(QPalette::ColorGroup::Disabled, QPalette::ColorRole::Base).name(),
|
||||
m_planOverlayView->palette().text().color().name());
|
||||
const QString &buttonStyleSheet = QStringLiteral("QPushButton:!disabled {%1}\nQPushButton:disabled {%2}").arg(backgroundStyle, backgroundDisabledStyle);
|
||||
|
||||
switch (static_cast<PlanOverlayModel::ColumnSection>(index.column()))
|
||||
{
|
||||
case PlanOverlayModel::ColumnSection::OrderButtons:
|
||||
{
|
||||
if (index.model()->rowCount() > 1)
|
||||
{
|
||||
QWidget *orderButtons = new QWidget(parent);
|
||||
QVBoxLayout *orderLayout = new QVBoxLayout(orderButtons);
|
||||
|
||||
QPixmap icon(QStringLiteral("icon:media-vcr-normal.svg")); // better use up and down buttons
|
||||
|
||||
LtsWidgets::LtsDragIcon *up = nullptr;
|
||||
|
||||
if (index.row() > 0)
|
||||
{
|
||||
up = new LtsWidgets::LtsDragIcon(orderButtons);
|
||||
|
||||
//up->setIcon(QIcon(QStringLiteral("icon:overlay_up.svg"))); // looks not very nice --> use simple arrow
|
||||
up->setIcon(QIcon(icon.transformed(QTransform().rotate(-90).scale(0.5, 0.5))));
|
||||
up->setText(QString());
|
||||
up->setIconSize(LtsWidgets::ButtonSize::eDefault);
|
||||
up->setButtonStyle(LtsWidgets::ButtonStyle::eIconOnly);
|
||||
up->setProperty("row", index.row());
|
||||
up->setToolTip(tr("Move layer up in display order"));
|
||||
|
||||
connect(up, &LtsWidgets::LtsDragIcon::clicked, m_planOverlayView, &PlanOverlayView::onChangeLayerOrderUp);
|
||||
}
|
||||
|
||||
LtsWidgets::LtsDragIcon *down = nullptr;
|
||||
|
||||
if ((index.row() + 1) < index.model()->rowCount())
|
||||
{
|
||||
down = new LtsWidgets::LtsDragIcon(orderButtons);
|
||||
|
||||
//down->setIcon(QIcon(QStringLiteral("icon:overlay_down.svg"))); // looks not very nice --> use simple arrow
|
||||
down->setIcon(QIcon(icon.transformed(QTransform().rotate(90).scale(0.5, 0.5))));
|
||||
down->setText(QString());
|
||||
down->setIconSize(LtsWidgets::ButtonSize::eDefault);
|
||||
down->setButtonStyle(LtsWidgets::ButtonStyle::eIconOnly);
|
||||
down->setProperty("row", index.row());
|
||||
down->setToolTip(tr("Move layer down in display order"));
|
||||
connect(down, &LtsWidgets::LtsDragIcon::clicked, m_planOverlayView, &PlanOverlayView::onChangeLayerOrderDown);
|
||||
}
|
||||
|
||||
orderLayout->addStretch();
|
||||
orderLayout->addSpacing(5);
|
||||
if (up) orderLayout->addWidget(up);
|
||||
if (down) orderLayout->addWidget(down);
|
||||
orderLayout->addSpacing(5);
|
||||
orderLayout->addStretch();
|
||||
|
||||
orderButtons->setAutoFillBackground(true);
|
||||
|
||||
connect(orderButtons, &QObject::destroyed, orderButtons, [this, indexKey](QObject * qobj) { removeKey(indexKey, qobj); });
|
||||
|
||||
m_sizeHints[indexKey] = orderButtons->sizeHint();
|
||||
m_widgetMap[indexKey] = orderButtons;
|
||||
|
||||
// qCritical() << "setup " << indexKey << " --> " << orderButtons;
|
||||
|
||||
return orderButtons;
|
||||
}
|
||||
break;
|
||||
};
|
||||
|
||||
case PlanOverlayModel::ColumnSection::PlanName:
|
||||
{
|
||||
QLabel *laName = new QLabel(modelData.toString(), parent);
|
||||
|
||||
laName->setAlignment(Qt::AlignCenter);
|
||||
laName->setStyleSheet(QStringLiteral("QLabel:!disabled {%1}\nQLabel:disabled {%2}").arg(backgroundStyle, backgroundDisabledStyle));
|
||||
|
||||
m_sizeHints[indexKey] = laName->sizeHint();
|
||||
m_widgetMap[indexKey] = laName;
|
||||
|
||||
return laName;
|
||||
|
||||
};
|
||||
|
||||
case PlanOverlayModel::ColumnSection::MinScale:
|
||||
{
|
||||
QPushButton *pbScaleMin = new QPushButton(parent);
|
||||
pbScaleMin->setStyleSheet(buttonStyleSheet);
|
||||
pbScaleMin->setPalette(m_planOverlayView->palette());
|
||||
pbScaleMin->setAutoFillBackground(true);
|
||||
pbScaleMin->setProperty("row", index.row());
|
||||
pbScaleMin->setText(modelData.toString());
|
||||
pbScaleMin->setToolTip(tr("Get minimum scale from current map settings to limit zoom out"));
|
||||
|
||||
connect(pbScaleMin, &QPushButton::clicked, m_planOverlayView, &PlanOverlayView::onSetMinScale);
|
||||
connect(pbScaleMin, &QObject::destroyed, pbScaleMin, [this, indexKey](QObject * qobj) { removeKey(indexKey, qobj); });
|
||||
|
||||
m_sizeHints[indexKey] = pbScaleMin->sizeHint();
|
||||
m_widgetMap[indexKey] = pbScaleMin;
|
||||
|
||||
// qCritical() << "setup " << indexKey << " --> " << pbScaleMin;
|
||||
|
||||
return pbScaleMin;
|
||||
};
|
||||
|
||||
case PlanOverlayModel::ColumnSection::MaxScale:
|
||||
{
|
||||
QPushButton *pbScaleMax = new QPushButton(parent);
|
||||
pbScaleMax->setStyleSheet(buttonStyleSheet);
|
||||
pbScaleMax->setAutoFillBackground(true);
|
||||
pbScaleMax->setProperty("row", index.row());
|
||||
pbScaleMax->setText(modelData.toString());
|
||||
pbScaleMax->setToolTip(tr("Get maximum scale from current map settings to limit zoom in"));
|
||||
|
||||
connect(pbScaleMax, &QPushButton::clicked, m_planOverlayView, &PlanOverlayView::onSetMaxScale);
|
||||
connect(pbScaleMax, &QObject::destroyed, pbScaleMax, [this, indexKey](QObject * qobj) { removeKey(indexKey, qobj); });
|
||||
|
||||
m_sizeHints[indexKey] = pbScaleMax->sizeHint();
|
||||
m_widgetMap[indexKey] = pbScaleMax;
|
||||
|
||||
// qCritical() << "setup " << indexKey << " --> " << pbScaleMax;
|
||||
|
||||
return pbScaleMax;
|
||||
};
|
||||
|
||||
case PlanOverlayModel::ColumnSection::Opacity:
|
||||
{
|
||||
QSlider *slOpacity = new QSlider(parent);
|
||||
|
||||
slOpacity->setAutoFillBackground(true);
|
||||
slOpacity->setOrientation(Qt::Horizontal);
|
||||
slOpacity->setRange(0, 100);
|
||||
slOpacity->setValue(int(modelData.toDouble() * 100));
|
||||
slOpacity->setProperty("row", index.row());
|
||||
slOpacity->setToolTip(tr("Adjust overlays opacity"));
|
||||
|
||||
connect(slOpacity, &QSlider::sliderMoved, m_planOverlayView, &PlanOverlayView::onChangeLayerOpacity);
|
||||
connect(slOpacity, &QObject::destroyed, slOpacity, [this, indexKey](QObject * qobj) { removeKey(indexKey, qobj); });
|
||||
|
||||
m_sizeHints[indexKey] = slOpacity->sizeHint();
|
||||
m_widgetMap[indexKey] = slOpacity;
|
||||
|
||||
return slOpacity;
|
||||
};
|
||||
|
||||
case PlanOverlayModel::ColumnSection::CustomSection:
|
||||
{
|
||||
QWidget *containerWidget = new QWidget(parent);
|
||||
QVBoxLayout *layout = new QVBoxLayout(containerWidget);
|
||||
QHBoxLayout *layoutBtnRow = new QHBoxLayout();
|
||||
|
||||
LtsWidgets::LtsDragIcon *pbReload = new LtsWidgets::LtsDragIcon(containerWidget);
|
||||
|
||||
pbReload->setIcon(QPixmap(QStringLiteral("icon:overlay_reload_plan.svg")));
|
||||
pbReload->setText(QString());
|
||||
pbReload->setIconSize(LtsWidgets::ButtonSize::eDefault);
|
||||
pbReload->setButtonStyle(LtsWidgets::ButtonStyle::eIconOnly);
|
||||
pbReload->setProperty("row", index.row());
|
||||
pbReload->setAutoFillBackground(true);
|
||||
pbReload->setToolTip(tr("Reload plan"));
|
||||
|
||||
LtsWidgets::LtsDragIcon *pbUnload = new LtsWidgets::LtsDragIcon(containerWidget);
|
||||
|
||||
pbUnload->setIcon(QPixmap(QStringLiteral("icon:overlay_unload_plan.svg")));
|
||||
pbUnload->setText(QString());
|
||||
pbUnload->setIconSize(LtsWidgets::ButtonSize::eDefault);
|
||||
pbUnload->setButtonStyle(LtsWidgets::ButtonStyle::eIconOnly);
|
||||
pbUnload->setProperty("row", index.row());
|
||||
pbUnload->setAutoFillBackground(true);
|
||||
pbUnload->setToolTip(tr("Unload plan and remove overlayer"));
|
||||
|
||||
layoutBtnRow->addWidget(pbReload);
|
||||
layoutBtnRow->addWidget(pbUnload);
|
||||
|
||||
layout->addStretch(2);
|
||||
layout->addLayout(layoutBtnRow);
|
||||
layout->addStretch(2);
|
||||
|
||||
containerWidget->setAutoFillBackground(true);
|
||||
|
||||
connect(pbReload, &LtsWidgets::LtsDragIcon::clicked, m_planOverlayView, &PlanOverlayView::onReloadOverlayById);
|
||||
connect(pbUnload, &LtsWidgets::LtsDragIcon::clicked, m_planOverlayView, &PlanOverlayView::onUnloadOverlay);
|
||||
|
||||
m_sizeHints[indexKey] = containerWidget->sizeHint();
|
||||
m_widgetMap[indexKey] = containerWidget;
|
||||
|
||||
return containerWidget;
|
||||
};
|
||||
case PlanOverlayModel::ColumnSection::ExerciseId:
|
||||
case PlanOverlayModel::ColumnSection::PhaseId:
|
||||
break;
|
||||
|
||||
} // switch
|
||||
|
||||
const QString &labelText = m_planOverlayView->model()->data(index, Qt::ItemDataRole::DisplayRole).toString();
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
|
||||
int labelWidth = option.fontMetrics.width(labelText);
|
||||
#else
|
||||
int labelWidth = option.fontMetrics.horizontalAdvance(labelText);
|
||||
#endif
|
||||
labelWidth = (option.rect.width() > labelWidth) ? option.rect.width() : labelWidth + labelWidth / 5;
|
||||
|
||||
m_sizeHints[indexKey] = QSize(labelWidth, option.rect.height());
|
||||
|
||||
return nullptr;
|
||||
} // QWidget * createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const
|
||||
|
||||
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
|
||||
{
|
||||
const QByteArray &indexKey = buildKey(index);
|
||||
|
||||
if (m_widgetMap.contains(indexKey))
|
||||
{
|
||||
QWidget *w = m_widgetMap[indexKey];
|
||||
if (w)
|
||||
{
|
||||
w->setGeometry(option.rect);
|
||||
painter->drawPixmap(option.rect.x(), option.rect.y(), w->grab());
|
||||
return;
|
||||
}
|
||||
}
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
} // void paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const
|
||||
|
||||
|
||||
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
|
||||
{
|
||||
Q_UNUSED(option);
|
||||
const QByteArray &indexKey = buildKey(index);
|
||||
return (m_sizeHints.contains(indexKey)) ? m_sizeHints[indexKey] : QSize();
|
||||
} // QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const
|
||||
|
||||
|
||||
void setEditorData(QWidget *editor, const QModelIndex &index) const override
|
||||
{
|
||||
const QVariant &modelData = index.model()->data(index, Qt::ItemDataRole::DisplayRole);
|
||||
switch (static_cast<PlanOverlayModel::ColumnSection>(index.column()))
|
||||
{
|
||||
case PlanOverlayModel::ColumnSection::PlanName:
|
||||
{
|
||||
QLabel *laName = qobject_cast<QLabel *>(editor);
|
||||
if (laName) laName->setText(modelData.toString());
|
||||
break;
|
||||
}
|
||||
|
||||
case PlanOverlayModel::ColumnSection::MinScale:
|
||||
{
|
||||
QPushButton *pbMinScale = qobject_cast<QPushButton *>(editor);
|
||||
if (pbMinScale) pbMinScale->setText(modelData.toString());
|
||||
break;
|
||||
}
|
||||
|
||||
case PlanOverlayModel::ColumnSection::MaxScale:
|
||||
{
|
||||
QPushButton *pbMaxScale = qobject_cast<QPushButton *>(editor);
|
||||
if (pbMaxScale) pbMaxScale->setText(modelData.toString());
|
||||
break;
|
||||
}
|
||||
|
||||
case PlanOverlayModel::ColumnSection::Opacity:
|
||||
{
|
||||
QSlider *slOpacity = qobject_cast<QSlider *>(editor);
|
||||
if (slOpacity) slOpacity->setValue(int(modelData.toDouble() * 100));
|
||||
break;
|
||||
}
|
||||
case PlanOverlayModel::ColumnSection::ExerciseId:
|
||||
case PlanOverlayModel::ColumnSection::PhaseId:
|
||||
case PlanOverlayModel::ColumnSection::OrderButtons:
|
||||
case PlanOverlayModel::ColumnSection::CustomSection:
|
||||
break;
|
||||
}
|
||||
} // void setEditorData(QWidget * editor, const QModelIndex & index) const
|
||||
|
||||
|
||||
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override
|
||||
{
|
||||
Q_UNUSED(editor);
|
||||
Q_UNUSED(model);
|
||||
Q_UNUSED(index);
|
||||
} // void setModelData(QWidget * editor, QAbstractItemModel * model; const QModelIndex & index) const
|
||||
|
||||
|
||||
}; // WidgetItemDelegate
|
||||
|
||||
|
||||
PlanOverlayView::PlanOverlayView(PlanOverlayModel *model, QWidget *parent)
|
||||
: QTableView(parent)
|
||||
{
|
||||
setModel(model);
|
||||
connect(model, &PlanOverlayModel::dropPlanAccepted, this, [this]()
|
||||
{
|
||||
setCurrentIndex(QModelIndex());
|
||||
PlanOverlayView::clearSelection();
|
||||
});
|
||||
connect (model, &PlanOverlayModel::layoutChanged, this, &PlanOverlayView::onLayoutChanged);
|
||||
|
||||
setSelectionMode(SelectionMode::SingleSelection); // selection have to be enabled to get drag working
|
||||
setSelectionBehavior(SelectionBehavior::SelectRows);
|
||||
|
||||
setItemDelegate(new WidgetItemDelegate(this));
|
||||
setEditTriggers(QAbstractItemView::AllEditTriggers);
|
||||
|
||||
setDragEnabled(true);
|
||||
setAcceptDrops(true);
|
||||
setDragDropMode(QAbstractItemView::DragDrop);
|
||||
setDragDropOverwriteMode(false);
|
||||
setDropIndicatorShown(true);
|
||||
setSortingEnabled(false);
|
||||
setShowGrid(false);
|
||||
|
||||
horizontalHeader()->setSectionResizeMode(int(PlanOverlayModel::ColumnSection::PlanName), QHeaderView::ResizeMode::Stretch);
|
||||
resizeColumnsToContents();
|
||||
resizeRowsToContents();
|
||||
horizontalHeader()->reset();
|
||||
//allways persistent editor
|
||||
onLayoutChanged();
|
||||
} // PlanOverlayView::PlanOverlayView()
|
||||
|
||||
|
||||
PlanOverlayView::~PlanOverlayView()
|
||||
{
|
||||
} // PlanOverlayView::~PlanOverlayView()
|
||||
|
||||
|
||||
void PlanOverlayView::onLayoutChanged()
|
||||
{
|
||||
clearSelection();
|
||||
if (model() != nullptr)
|
||||
{
|
||||
for (int row = 0; row < model()->rowCount(); ++row)
|
||||
{
|
||||
for (int col = 0; col < model()->columnCount(); ++col)
|
||||
openPersistentEditor(model()->index(row, col, QModelIndex()));
|
||||
}
|
||||
}
|
||||
|
||||
resizeRowsToContents();
|
||||
resizeColumnsToContents();
|
||||
horizontalHeader()->setSectionResizeMode(int(PlanOverlayModel::ColumnSection::PlanName), QHeaderView::ResizeMode::Stretch);
|
||||
} // void PlanOverlayView::updateGeometries()
|
||||
|
||||
|
||||
int PlanOverlayView::getPlanKeyIdOfRow(int row) const
|
||||
{
|
||||
PlanOverlayModel *poModel = dynamic_cast<PlanOverlayModel *>(model());
|
||||
|
||||
if (nullptr == poModel) return -1;
|
||||
|
||||
if (row < 0) return -1;
|
||||
if (row >= poModel->rowCount(QModelIndex())) return -1;
|
||||
|
||||
const PlanOverlayModel::PlanItem &planItem = poModel->planItemAtRow(row);
|
||||
|
||||
return (planItem.isValid()) ? planItem.m_keyId : -1;
|
||||
|
||||
} // int PlanOverlayView::getPlanKeyIdOfRow(int row) const
|
||||
|
||||
|
||||
QString PlanOverlayView::getPlanNameOfRow(int row) const
|
||||
{
|
||||
PlanOverlayModel *poModel = dynamic_cast<PlanOverlayModel *>(model());
|
||||
|
||||
if (nullptr == poModel) return QString();
|
||||
|
||||
if (row < 0) return QString();
|
||||
if (row >= poModel->rowCount(QModelIndex())) return QString();
|
||||
|
||||
const PlanOverlayModel::PlanItem &planItem = poModel->planItemAtRow(row);
|
||||
|
||||
return (planItem.isValid()) ? planItem.m_fileName : QString();
|
||||
|
||||
} // int PlanOverlayView::getPlanNameOfRow(int row) const
|
||||
|
||||
|
||||
void PlanOverlayView::onSetMinScale()
|
||||
{
|
||||
QPushButton *senderButton = qobject_cast<QPushButton *>(sender());
|
||||
if (nullptr == senderButton) return;
|
||||
|
||||
int row = senderButton->property("row").toInt();
|
||||
int keyId = getPlanKeyIdOfRow(row);
|
||||
|
||||
if (keyId < 0) return;
|
||||
|
||||
emit requestMinScale(keyId, model()->data(model()->index(row, int(PlanOverlayModel::ColumnSection::PlanName), QModelIndex()), Qt::ItemDataRole::DisplayRole).toString());
|
||||
|
||||
} // void PlanOverlayView::onSetMinScale()
|
||||
|
||||
|
||||
void PlanOverlayView::onSetMaxScale()
|
||||
{
|
||||
QPushButton *senderButton = qobject_cast<QPushButton *>(sender());
|
||||
if (nullptr == senderButton) return;
|
||||
|
||||
int row = senderButton->property("row").toInt();
|
||||
int keyId = getPlanKeyIdOfRow(row);
|
||||
|
||||
if (keyId < 0) return;
|
||||
|
||||
emit requestMaxScale(keyId, model()->data(model()->index(row, int(PlanOverlayModel::ColumnSection::PlanName), QModelIndex()), Qt::ItemDataRole::DisplayRole).toString());
|
||||
|
||||
} // void PlanOverlayView::onSetMaxScale()
|
||||
|
||||
|
||||
void PlanOverlayView::onReloadOverlayById()
|
||||
{
|
||||
LtsWidgets::LtsDragIcon *senderButton = qobject_cast<LtsWidgets::LtsDragIcon *>(sender());
|
||||
if (nullptr == senderButton) return;
|
||||
|
||||
int row = senderButton->property("row").toInt();
|
||||
int keyId = getPlanKeyIdOfRow(row);
|
||||
|
||||
if (keyId < 0) return;
|
||||
|
||||
emit requestReloadPlanById(keyId);
|
||||
|
||||
} // void PlanOverlayView::onReloadOverlayById()
|
||||
|
||||
|
||||
void PlanOverlayView::onReloadOverlayByName()
|
||||
{
|
||||
LtsWidgets::LtsDragIcon *senderButton = qobject_cast<LtsWidgets::LtsDragIcon *>(sender());
|
||||
if (nullptr == senderButton) return;
|
||||
|
||||
int row = senderButton->property("row").toInt();
|
||||
QString planName = getPlanNameOfRow(row);
|
||||
|
||||
if (planName.isEmpty()) return;
|
||||
|
||||
emit requestReloadPlanByName(planName);
|
||||
|
||||
} // void PlanOverlayView::onReloadOverlayById()
|
||||
|
||||
|
||||
|
||||
void PlanOverlayView::onUnloadOverlay()
|
||||
{
|
||||
LtsWidgets::LtsDragIcon *senderButton = qobject_cast<LtsWidgets::LtsDragIcon *>(sender());
|
||||
if (nullptr == senderButton) return;
|
||||
|
||||
int keyId = getPlanKeyIdOfRow(senderButton->property("row").toInt());
|
||||
|
||||
if (keyId >= 0)
|
||||
emit requestUnloadPlan(keyId);
|
||||
} // void PlanOverlayView::onUnloadOverlay()
|
||||
|
||||
|
||||
void PlanOverlayView::onChangeLayerOpacity(int sliderValue)
|
||||
{
|
||||
QSlider *senderSlider = qobject_cast<QSlider *>(sender());
|
||||
if (nullptr == senderSlider) return;
|
||||
|
||||
int row = senderSlider->property("row").toInt();
|
||||
|
||||
PlanOverlayModel *poModel = dynamic_cast<PlanOverlayModel *>(model());
|
||||
|
||||
if (nullptr == poModel) return;
|
||||
if (row < 0) return;
|
||||
if (row >= poModel->rowCount(QModelIndex())) return;
|
||||
|
||||
poModel->setOpacity(row, double(sliderValue) / 100.0);
|
||||
|
||||
} // void PlanOverlayView::onChangeLayerOpacity(int sliderValue)
|
||||
|
||||
|
||||
void PlanOverlayView::onChangeLayerOrderUp()
|
||||
{
|
||||
LtsWidgets::LtsDragIcon *senderButton = qobject_cast<LtsWidgets::LtsDragIcon *>(sender());
|
||||
if (nullptr == senderButton) return;
|
||||
|
||||
int row = senderButton->property("row").toInt();
|
||||
|
||||
PlanOverlayModel *poModel = dynamic_cast<PlanOverlayModel *>(model());
|
||||
|
||||
if (nullptr == poModel) return;
|
||||
if (row < 1) return;
|
||||
if (row >= poModel->rowCount(QModelIndex())) return;
|
||||
|
||||
poModel->swapRow(row, row - 1);
|
||||
|
||||
} // void PlanOverlayView::onChangeLayerOrderUp()
|
||||
|
||||
|
||||
void PlanOverlayView::onChangeLayerOrderDown()
|
||||
{
|
||||
LtsWidgets::LtsDragIcon *senderButton = qobject_cast<LtsWidgets::LtsDragIcon *>(sender());
|
||||
if (nullptr == senderButton) return;
|
||||
|
||||
int row = senderButton->property("row").toInt();
|
||||
|
||||
PlanOverlayModel *poModel = dynamic_cast<PlanOverlayModel *>(model());
|
||||
|
||||
if (nullptr == poModel) return;
|
||||
if (row < 0) return;
|
||||
if (row + 1 >= poModel->rowCount(QModelIndex())) return;
|
||||
|
||||
poModel->swapRow(row, row + 1);
|
||||
|
||||
} // void PlanOverlayView::onChangeLayerOrderDown()
|
||||
|
||||
|
||||
} // namespace PlanOverlaysPlugin
|
||||
|
||||
|
||||
#include <plan_overlay_view.moc>
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** plan_overlay_view.h
|
||||
** $Id$
|
||||
** $HeadURL$
|
||||
** $Author$
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Hardware-Environment: Intel-PC
|
||||
** Software-Environment: Windows 7, Qt 5.7. ArcGIS 100
|
||||
**
|
||||
** Language ........: C++ 11
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Author ...........: Jörg Turla, SPD G, Tel. 3132
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Notes .........:
|
||||
**
|
||||
** 11.07.2017, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtWidgets/QTableView>
|
||||
|
||||
|
||||
namespace PlanOverlaysPlugin
|
||||
{
|
||||
class PlanOverlayModel;
|
||||
|
||||
class PlanOverlayView final : public QTableView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit PlanOverlayView(PlanOverlayModel *model, QWidget *parent = nullptr);
|
||||
~PlanOverlayView();
|
||||
|
||||
signals:
|
||||
|
||||
void requestReloadPlanById(int planId);
|
||||
void requestReloadPlanByName(const QString &planName);
|
||||
void requestUnloadPlan(int planId);
|
||||
|
||||
void requestMinScale(int planId, const QString &planName);
|
||||
void requestMaxScale(int planId, const QString &planName);
|
||||
|
||||
public slots:
|
||||
|
||||
void onSetMinScale();
|
||||
void onSetMaxScale();
|
||||
void onChangeLayerOrderUp();
|
||||
void onChangeLayerOrderDown();
|
||||
void onChangeLayerOpacity(int);
|
||||
|
||||
void onReloadOverlayById();
|
||||
void onReloadOverlayByName();
|
||||
void onUnloadOverlay();
|
||||
|
||||
protected:
|
||||
|
||||
void onLayoutChanged();
|
||||
|
||||
int getPlanKeyIdOfRow(int row) const;
|
||||
QString getPlanNameOfRow(int row) const;
|
||||
|
||||
}; // PlanOverlayView
|
||||
|
||||
} // namespace PlanOverlaysPlugin
|
||||
+954
@@ -0,0 +1,954 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** plan_editor_gui_plugin.cpp
|
||||
** $Id$
|
||||
** $HeadURL$
|
||||
** $Author$
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Hardware-Environment: Intel-PC
|
||||
** Software-Environment: Windows 7, Qt 5.7. ArcGIS 100
|
||||
**
|
||||
** Language ........: C++ 11
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Author ...........: Jörg Turla, SPD G, Tel. 3132
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Notes .........:
|
||||
**
|
||||
** 24.04.2017, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "plan_overlays_gui_plugin.h"
|
||||
#include "plan_overlay_model.h"
|
||||
#include "plan_overlay_dialog.h"
|
||||
#include "TopicEditor/topic_editor.h"
|
||||
#include "flm_reply_handler.h"
|
||||
|
||||
#include <LtsUtilsCore/pgarray.h>
|
||||
#include <LtsUtilsCore/dds_vector.h>
|
||||
#include <NGLLogger/INGLLogger.h>
|
||||
#include <NGLLogger/NGLLoggerBootstrap.h>
|
||||
#include <LtsWidgets/lts_base_layout_widget.h>
|
||||
#include <LtsWidgets/lts_message_dialog.h>
|
||||
#include <LtsSession/lts_session.h>
|
||||
#include <LtsSession/lts_session_data.h>
|
||||
#include <LtsUtilsGuiDds/request_helper.h>
|
||||
#include <PluginInterfaces/style_plugin_interface.h>
|
||||
#include <PluginInterfaces/project_plugin_interface.h>
|
||||
#include <Services/OperatorManagement/opm_dtc.h>
|
||||
#include <Services/ExerciseManagement/exm_dtc.h>
|
||||
#include <Services/PlanEditor/ped_operator_rights.h>
|
||||
#include <Plugins/OperatorManagement/opm_data_plugin_interface.h>
|
||||
#include <Plugins/ExerciseManagement/exm_data_plugin_interface.h>
|
||||
#include <Plugins/FileManagement/flm_data_plugin_interface.h>
|
||||
#include <Plugins/FileManagement/flm_explorer_gui_plugin_interface.h>
|
||||
#include <Plugins/FileManagement/Gui/Explorer/TopicEditor/topic_editor.h>
|
||||
#include <Plugins/SituationMapPlugin/situation_map_gui_plugin_interface.h>
|
||||
#include <Viewer/SituationMap/Map/map.h>
|
||||
#include <Viewer/SituationMap/GeometryModel/geometry_model_factory.h>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDateTime>
|
||||
#include <QFile>
|
||||
#include <QPointer>
|
||||
#include <QStandardPaths>
|
||||
#include <QHBoxLayout>
|
||||
#include <QMainWindow>
|
||||
#include <QtGlobal>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
||||
namespace PlanOverlaysPlugin
|
||||
{
|
||||
|
||||
std::shared_ptr<GuiPluginBase::Interface> PlanOverlaysGuiPlugin::createGuiInterface(LtsSession::LtsSession * session)
|
||||
{
|
||||
return std::make_shared<InterfaceImpl>(session);
|
||||
}
|
||||
|
||||
|
||||
static NGL::INGLLogger &getLogger()
|
||||
{
|
||||
try
|
||||
{
|
||||
return NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("PlanOverLaysPlugin");
|
||||
}
|
||||
catch (const std::exception &ex)
|
||||
{
|
||||
fprintf(stderr, "Error retrieving logger: %s", ex.what());
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class InterfaceImpl::InternalData
|
||||
{
|
||||
public:
|
||||
|
||||
FileManagement::FileContent m_planContent;
|
||||
|
||||
std::shared_ptr<FileManagement::Interface::Dtc> m_dtc;
|
||||
std::shared_ptr<FileManagement::Interface::Ftc> m_ftc;
|
||||
|
||||
std::shared_ptr<OperatorManagement::Interface::Dtc> m_opmDtc;
|
||||
std::shared_ptr<ExerciseManagement::Interface::Dtc> m_exmDtc;
|
||||
|
||||
LtsUtils::RequestHelper * m_requestHelper;
|
||||
FileManagementReplyHandler * m_flmReplyHandler;
|
||||
|
||||
PlanOverlayModel * m_overlayModel;
|
||||
|
||||
std::shared_ptr<SituationMap::ForeignGuiInterface> m_situationMapGui;
|
||||
|
||||
SituationMap::ForeignGuiInterface * m_foreignSitmapIfc;
|
||||
|
||||
QString m_messageBoxTitle;
|
||||
|
||||
InternalData()
|
||||
: m_requestHelper(nullptr)
|
||||
, m_flmReplyHandler(nullptr)
|
||||
, m_overlayModel(nullptr)
|
||||
, m_foreignSitmapIfc(nullptr)
|
||||
{} // InternalData
|
||||
|
||||
~InternalData() = default;
|
||||
|
||||
};
|
||||
|
||||
|
||||
InterfaceImpl::InterfaceImpl(LtsSession::LtsSession * session)
|
||||
: QObject()
|
||||
, GuiPluginBase::Interface(session, getLogger())
|
||||
, m_internal(new InternalData())
|
||||
, m_foreignIfc(nullptr)
|
||||
|
||||
{
|
||||
m_internal->m_requestHelper = new LtsUtils::RequestHelper(this);
|
||||
m_internal->m_flmReplyHandler = new FileManagementReplyHandler(m_internal->m_requestHelper);
|
||||
|
||||
m_internal->m_messageBoxTitle = tr("Plan Overlays");
|
||||
}
|
||||
|
||||
|
||||
bool InterfaceImpl::fetchInterfaces()
|
||||
{
|
||||
// Initialize file mamangement
|
||||
if (!m_session->getDtc<FileManagement::DataInterface>(m_internal->m_dtc))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "getDtc for FileManagement::DataInterface failed.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_session->getDtc<OperatorManagement::DataInterface>(m_internal->m_opmDtc))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "getDtc for OperatorManagement::DataInterface failed.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_session->getDtc<ExerciseManagement::DataInterface>(m_internal->m_exmDtc))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "getDtc for ExerciseManagement::DataInterface failed.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_session->getFtc<FileManagement::DataInterface>(m_internal->m_ftc))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "getFtc for FileManagement::DataInterface failed.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_session->getForeignGuiInterface(m_internal->m_situationMapGui))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "getForeignGuiInterface for SituationMap::ForeignGuiInterface failed.";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
m_internal->m_foreignSitmapIfc = m_internal->m_situationMapGui.get();
|
||||
|
||||
|
||||
delete m_internal->m_overlayModel;
|
||||
m_internal->m_overlayModel = new PlanOverlayModel();
|
||||
|
||||
connect(m_internal->m_overlayModel, &PlanOverlayModel::requestLoadPlan , this, &InterfaceImpl::loadPlanByUser, Qt::ConnectionType::DirectConnection);
|
||||
connect(m_internal->m_overlayModel, &PlanOverlayModel::requestUpdatePlan , this, &InterfaceImpl::onUpdatePlan , Qt::ConnectionType::DirectConnection);
|
||||
connect(m_internal->m_overlayModel, &PlanOverlayModel::requestRemovePlan , this, QOverload<int>::of(&InterfaceImpl::removePlan) , Qt::ConnectionType::DirectConnection);
|
||||
connect(m_internal->m_overlayModel, &PlanOverlayModel::planMinScaleChanged , this, &InterfaceImpl::onChangePlanMinScaleOnMap , Qt::ConnectionType::DirectConnection);
|
||||
connect(m_internal->m_overlayModel, &PlanOverlayModel::planMaxScaleChanged , this, &InterfaceImpl::onChangePlanMaxScaleOnMap , Qt::ConnectionType::DirectConnection);
|
||||
connect(m_internal->m_overlayModel, &PlanOverlayModel::planOpacityChanged , this, &InterfaceImpl::onChangePlanOpacityOnMap , Qt::ConnectionType::DirectConnection);
|
||||
connect(m_internal->m_overlayModel, &PlanOverlayModel::planOrderChanged , this, &InterfaceImpl::onChangePlanOrderOnMap , Qt::ConnectionType::DirectConnection);
|
||||
|
||||
connect(m_internal->m_overlayModel, &PlanOverlayModel::requestReloadPlanByName, this, &InterfaceImpl::onReloadPlanByName, static_cast<Qt::ConnectionType>(Qt::DirectConnection|Qt::UniqueConnection));
|
||||
|
||||
m_internal->m_ftc->enableFileContentModify();
|
||||
m_internal->m_ftc->enableGetFileContentData();
|
||||
|
||||
connect(m_internal->m_dtc.get(), &FileManagement::Interface::Dtc::fileContentChanged, this, &InterfaceImpl::onPlanContentChanged, Qt::UniqueConnection);
|
||||
connect(m_internal->m_exmDtc.get(), &ExerciseManagement::Interface::Dtc::exerciseChanged, this, &InterfaceImpl::onExerciseChanged, Qt::UniqueConnection);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void InterfaceImpl::setForeignSitMapGuiIfc(SituationMap::ForeignGuiInterface *foreignSitmapIfc)
|
||||
{
|
||||
//qWarning() << (void *)this << "setSitMapGuiIfc";
|
||||
m_internal->m_foreignSitmapIfc = foreignSitmapIfc;
|
||||
}
|
||||
|
||||
|
||||
void InterfaceImpl::setForeignPlanOverlaysGuiIfc(ForeignGuiInterface *ifc)
|
||||
{
|
||||
m_foreignIfc = ifc;
|
||||
}
|
||||
|
||||
|
||||
void InterfaceImpl::clearInterfaces()
|
||||
{
|
||||
if (!m_internal)
|
||||
return;
|
||||
|
||||
m_internal->m_dtc.reset();
|
||||
m_internal->m_opmDtc.reset();
|
||||
m_internal->m_exmDtc.reset();
|
||||
m_internal->m_ftc.reset();
|
||||
m_internal->m_situationMapGui.reset();
|
||||
m_internal->m_foreignSitmapIfc = nullptr; // it's just a raw pointer
|
||||
}
|
||||
|
||||
|
||||
PlanOverlayModel *InterfaceImpl::planOverlayModel()
|
||||
{
|
||||
return m_internal->m_overlayModel;
|
||||
}
|
||||
|
||||
bool InterfaceImpl::loadPlanByUser(int planFileId)
|
||||
{
|
||||
return loadPlan(planFileId, true, nullptr);
|
||||
}
|
||||
|
||||
|
||||
bool InterfaceImpl::loadPlan(int planFileId)
|
||||
{
|
||||
return loadPlan(planFileId, QJsonObject());
|
||||
}
|
||||
|
||||
bool InterfaceImpl::loadPlan(int planFileId, const QJsonObject &planItemObject)
|
||||
{
|
||||
return loadPlan(planFileId, false, nullptr, planItemObject);
|
||||
}
|
||||
|
||||
|
||||
bool InterfaceImpl::loadPlan(int planFileId,
|
||||
bool applyMinMaxScaleOfMetadata,
|
||||
SituationMap::ForeignGuiInterface* overrideSitMapIfc,
|
||||
const QJsonObject &planItemObject)
|
||||
{
|
||||
// Important: the parameter planFileId is the file id of the plan in FMS and NOT the planKeyId !!!!!
|
||||
|
||||
if (overrideSitMapIfc == nullptr)
|
||||
overrideSitMapIfc = m_internal->m_foreignSitmapIfc;
|
||||
|
||||
if (overrideSitMapIfc == nullptr) // still paranoid
|
||||
{
|
||||
ERROR_LOG(m_logger) << "no sit map ifc to load a plan on!";
|
||||
return false;
|
||||
}
|
||||
|
||||
// NLDEVCTRL-1414:
|
||||
// Pläne/Overlays wiederherstellen schlug fehl nach Aus-/Einloggen
|
||||
m_internal->m_dtc->waitForHistoricalDataFileContent(5000);
|
||||
FileManagement::FileContent fileContent = m_internal->m_dtc->fileContent(planFileId);
|
||||
|
||||
// TODO: FIXME: but normally 0 is a valid id ?!
|
||||
if (fileContent.id() <= 0) // not found
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Could not find plan with id " << planFileId << " in filemanagement - removing";
|
||||
return false;
|
||||
}
|
||||
|
||||
QString nameOfPlan = QString::fromStdString(fileContent.name());
|
||||
|
||||
std::function<void(const Core::FunctionReply &baseReply)> handleContent = [this, fileContent, applyMinMaxScaleOfMetadata, nameOfPlan, overrideSitMapIfc, planItemObject](const Core::FunctionReply &)
|
||||
{
|
||||
const QByteArray &planXMLContent = LtsUtils::toQByteArray(m_internal->m_flmReplyHandler->getContent());
|
||||
|
||||
int planFileId = fileContent.id();
|
||||
|
||||
// use 'planId' as 'id' (internal name: key)
|
||||
if (!overrideSitMapIfc->planOverlaySetContent(planFileId, nameOfPlan, planXMLContent))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "no sit map ifc to load a plan on!";
|
||||
return false;
|
||||
}
|
||||
|
||||
PlanOverlaysPlugin::PlanOverlayModel::PlanItem planItem = m_internal->m_overlayModel->findPlanItemByFileId(planFileId);
|
||||
|
||||
if (!planItem.isValid())
|
||||
planItem = m_internal->m_overlayModel->planItem(-1);
|
||||
|
||||
planItem.m_folderId = fileContent.folderId();
|
||||
if (fileContent.exerciseId().is_set())
|
||||
{
|
||||
planItem.m_exerciseId = fileContent.exerciseId().get();
|
||||
if (fileContent.phaseId().is_set())
|
||||
planItem.m_phaseId = fileContent.phaseId().get();
|
||||
}
|
||||
planItem.m_fileId = planFileId;
|
||||
planItem.m_fileName = nameOfPlan;
|
||||
|
||||
|
||||
if (applyMinMaxScaleOfMetadata)
|
||||
{
|
||||
|
||||
QScopedPointer<SituationMap::GeometryModel> geoModel(SituationMap::GeometryModelFactory::singleton()->create());
|
||||
if (geoModel->fromByteArray(planXMLContent))
|
||||
{
|
||||
const QString &minScaleStr = geoModel->getModelAttribute(SituationMap::GeometryModel::Attribute::MetaDataMinScale).toString();
|
||||
const QString &maxScaleStr = geoModel->getModelAttribute(SituationMap::GeometryModel::Attribute::MetaDataMaxScale).toString();
|
||||
|
||||
bool ok = false;
|
||||
double minScale = minScaleStr.toDouble(&ok);
|
||||
if (ok)
|
||||
planItem.m_minScale = minScale;
|
||||
else
|
||||
planItem.m_minScale = 0.0;
|
||||
|
||||
double maxScale = maxScaleStr.toDouble(&ok);
|
||||
if (ok)
|
||||
planItem.m_maxScale = maxScale;
|
||||
else
|
||||
planItem.m_maxScale = 0.0;
|
||||
|
||||
DEBUG_LOG(m_logger) << " load plan and set minMaxScale:"
|
||||
<< " minScaleStr = " << minScaleStr
|
||||
<< " maxScaleStr = " << maxScaleStr
|
||||
<< " planItem.m_minScale = " << planItem.m_minScale
|
||||
<< " planItem.m_maxScale = " << planItem.m_maxScale;
|
||||
|
||||
overrideSitMapIfc->setPlanOverlayMinScale(planFileId, planItem.m_minScale);
|
||||
overrideSitMapIfc->setPlanOverlayMaxScale(planFileId, planItem.m_maxScale);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (planItemObject.isEmpty())
|
||||
{
|
||||
// Get plan settings from SituationMap and store them as initial value in plan item
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
planItem.m_opacity = overrideSitMapIfc->planOverlayOpacity(planFileId);
|
||||
planItem.m_maxScale = overrideSitMapIfc->planOverlayMaxScale(planFileId);
|
||||
planItem.m_minScale = overrideSitMapIfc->planOverlayMinScale(planFileId);
|
||||
planItem.m_visibility = overrideSitMapIfc->planOverlayVisibility(planFileId);
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
}
|
||||
else
|
||||
{
|
||||
planItem.m_opacity = planItemObject[QStringLiteral("opacity")].toDouble(0.);
|
||||
planItem.m_maxScale = planItemObject[QStringLiteral("maxScale")].toDouble(0.);
|
||||
planItem.m_minScale = planItemObject[QStringLiteral("minScale")].toDouble(0.);
|
||||
planItem.m_visibility = planItemObject[QStringLiteral("visibility")].toBool(true);
|
||||
|
||||
overrideSitMapIfc->setPlanOverlayOpacity(planFileId, planItem.m_opacity);
|
||||
overrideSitMapIfc->setPlanOverlayMaxScale(planFileId, planItem.m_maxScale);
|
||||
overrideSitMapIfc->setPlanOverlayMinScale(planFileId, planItem.m_minScale);
|
||||
overrideSitMapIfc->setPlanOverlayVisibility(planFileId, planItem.m_visibility);
|
||||
}
|
||||
|
||||
m_internal->m_overlayModel->updatePlanItem(planItem); // Write back plan item to model
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
bool ok = m_internal->m_requestHelper->startSingleRequest([this, planFileId]()
|
||||
{
|
||||
FileManagement::GetFileContentDataRequest req;
|
||||
req.fileContentId(planFileId);
|
||||
return m_internal->m_ftc->getFileContentDataRequest(req, m_internal->m_flmReplyHandler);
|
||||
}, handleContent);
|
||||
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool InterfaceImpl::unloadAllPlans()
|
||||
{
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
|
||||
const QMap<unsigned int, PlanOverlayModel::PlanItem> &planStore = m_internal->m_overlayModel->planStore();
|
||||
|
||||
QMapIterator<unsigned int, PlanOverlayModel::PlanItem> mapIt(planStore);
|
||||
while (mapIt.hasNext())
|
||||
{
|
||||
mapIt.next();
|
||||
unsigned int planId = mapIt.key();
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << " removeOverlay, planId=" << planId;
|
||||
|
||||
// update model, signal requestRemovePlan, slot removePlan
|
||||
m_internal->m_overlayModel->removeOverlay(planId);
|
||||
}
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << " END";
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void InterfaceImpl::onUpdatePlan(int planId)
|
||||
{
|
||||
PlanOverlaysPlugin::PlanOverlayModel::PlanItem planItem = m_internal->m_overlayModel->planItemValue(planId);
|
||||
if (!planItem.isValid())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "plan item with id " << planId << " not found in model";
|
||||
return;
|
||||
}
|
||||
|
||||
int planFileId = planItem.m_fileId;
|
||||
FileManagement::FileContent fileContent = m_internal->m_dtc->fileContent(planFileId);
|
||||
|
||||
planItem.m_fileName = QString::fromStdString(fileContent.name());
|
||||
|
||||
std::function<void(const Core::FunctionReply &baseReply)> handleContent = [this,planFileId,planItem](const Core::FunctionReply &baseReply)
|
||||
{
|
||||
const FileManagement::GetFileContentDataReply &reply = static_cast<const FileManagement::GetFileContentDataReply &>(baseReply);
|
||||
|
||||
const QByteArray &planXMLContent = LtsUtils::toQByteArray(reply.content());
|
||||
|
||||
// use 'planId' as 'id' (internal name: key)
|
||||
if (!m_internal->m_foreignSitmapIfc->planOverlaySetContent(planFileId, planItem.m_fileName, planXMLContent))
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << "Error rendering planContent [" << planItem.m_fileName << "]";
|
||||
return false;
|
||||
}
|
||||
|
||||
m_internal->m_overlayModel->renewPlanItem(planItem);
|
||||
|
||||
return true;
|
||||
}; // std::function
|
||||
|
||||
bool ok = m_internal->m_requestHelper->startSingleRequest([this, planFileId]()
|
||||
{
|
||||
FileManagement::GetFileContentDataRequest req;
|
||||
req.fileContentId(planFileId);
|
||||
return m_internal->m_ftc->getFileContentDataRequest(req, m_internal->m_flmReplyHandler);
|
||||
}, handleContent);
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << "Error reading planContent [" << planItem.m_fileName << "]";
|
||||
LtsWidgets::LtsMessageDialog::showMessage(m_session->baseLayout(), tr("Reading plan '%1' from database failed").arg(planItem.m_fileName), m_internal->m_messageBoxTitle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
InterfaceImpl::~InterfaceImpl()
|
||||
{
|
||||
delete m_internal->m_requestHelper;
|
||||
delete m_internal->m_flmReplyHandler;
|
||||
delete m_internal->m_overlayModel;
|
||||
delete m_internal; m_internal = nullptr;
|
||||
}
|
||||
|
||||
|
||||
QString InterfaceImpl::menuGroup() const { return tr("Situation Map"); }
|
||||
|
||||
|
||||
QVector<LtsWidgets::PluginData> InterfaceImpl::getActions()
|
||||
{
|
||||
QVector<LtsWidgets::PluginData> actionVector;
|
||||
|
||||
{
|
||||
LtsWidgets::PluginData pluginAction;
|
||||
|
||||
pluginAction.menuGroup = menuGroup();
|
||||
|
||||
pluginAction.menuText = tr("Managing Plan Overlays");
|
||||
pluginAction.menuIcon = QIcon(QStringLiteral("icon:overlay_plans.svg"));
|
||||
pluginAction.identifier = QStringLiteral("manage_plan_overlay");
|
||||
pluginAction.tooltip = tr("Loading plan overlays, changing order of plan overlays and modifying overlay settings");
|
||||
pluginAction.operatorRight = OperatorRights::PlanEditor::TacticalPlansShow;
|
||||
pluginAction.exercisePart = LtsWidgets::ExercisePart::eSpecial;
|
||||
pluginAction.directFunc = [this](const LtsWidgets::PluginData &)
|
||||
{
|
||||
if (m_planOverlayDialog)
|
||||
{
|
||||
m_planOverlayDialog->show();
|
||||
m_planOverlayDialog->raise();
|
||||
} else {
|
||||
m_planOverlayDialog = openPlanOverlayDialog();
|
||||
}
|
||||
};
|
||||
|
||||
actionVector << pluginAction;
|
||||
}
|
||||
return actionVector;
|
||||
}
|
||||
|
||||
|
||||
QWidget *InterfaceImpl::openPlanOverlayDialog(const QJsonArray &planItems, bool removePlansOnClose)
|
||||
{
|
||||
auto doReadFile = [this](int selectedFileId) // note: parameter is fileId@FileManagement
|
||||
{
|
||||
if (selectedFileId > 0)
|
||||
loadPlanByUser(selectedFileId);
|
||||
};
|
||||
|
||||
auto doUnloadPlan = [this](int planId) // note: planId != fileId@FileManagement
|
||||
{
|
||||
if (planId > 0)
|
||||
m_internal->m_overlayModel->removeOverlay(planId);
|
||||
};
|
||||
|
||||
auto doReloadPlan = [this](int planId) // note: planId != fileId@FileManagement
|
||||
{
|
||||
if (planId > 0)
|
||||
onReloadPlanById(planId);
|
||||
};
|
||||
|
||||
|
||||
for (const QJsonValue &planItemValue : qAsConst(planItems))
|
||||
{
|
||||
if (!planItemValue.isObject())
|
||||
{
|
||||
WARNING_LOG(m_logger) << "planItem from json array is not an object! " << planItemValue.type();
|
||||
continue;
|
||||
}
|
||||
|
||||
QJsonObject planItemObj(planItemValue.toObject());
|
||||
int planFileId = planItemObj[QStringLiteral("fileId")].toInt(-1);
|
||||
|
||||
if (!loadPlan(planFileId, planItemObj))
|
||||
ERROR_LOG(m_logger) << "could not load plan with file id " << planFileId;
|
||||
}
|
||||
|
||||
|
||||
#define USE_QDIALOG 1
|
||||
|
||||
#ifdef USE_QDIALOG
|
||||
PlanOverlayDialog<QDialog> * overlayDialog = new PlanOverlayDialog<QDialog>(m_internal->m_foreignSitmapIfc, m_internal->m_overlayModel, m_session->baseLayout(), m_session);
|
||||
#else
|
||||
PlanOverlayDialog<LtsWidgets::LtsDialog> * overlayDialog = new PlanOverlayDialog<LtsWidgets::LtsDialog>(m_session, sitMapIfc, m_internal->m_overlayModel, m_session->baseLayout());
|
||||
#endif
|
||||
|
||||
overlayDialog->dialogWidget()->initFileManagement(m_internal->m_dtc, m_internal->m_opmDtc, m_internal->m_exmDtc, doReadFile, doReloadPlan, doUnloadPlan, appId() == LtsAppDescriptor::App::OC );
|
||||
overlayDialog->show();
|
||||
|
||||
|
||||
if (removePlansOnClose)
|
||||
{
|
||||
connect(overlayDialog->dialogWidget(), &QObject::destroyed,
|
||||
this, [this]()
|
||||
{
|
||||
auto planStore = m_internal->m_overlayModel->planStore();
|
||||
for (auto i = planStore.constBegin(); i != planStore.constEnd(); ++i)
|
||||
{
|
||||
//m_internal->m_overlayModel->removeOverlay(i.key());
|
||||
removePlan(i.key());
|
||||
}
|
||||
});
|
||||
}
|
||||
connect(overlayDialog->dialogWidget(), &QObject::destroyed,
|
||||
this, [overlayDialog]() { delete overlayDialog; });
|
||||
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* The overlay dialog will be removed automatically when the user close the dialog or when underlying map will be destroyed.
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
return overlayDialog->dialogWidget();
|
||||
}
|
||||
|
||||
|
||||
void InterfaceImpl::onReloadPlanById(int planId) // note: planId != fileId@FileManagement
|
||||
{
|
||||
const PlanOverlaysPlugin::PlanOverlayModel::PlanItem & planItem = m_internal->m_overlayModel->planItem(planId);
|
||||
if (planItem.isValid())
|
||||
{
|
||||
int fileId = planItem.m_fileId;
|
||||
FileManagement::FileContent fileContent = m_internal->m_dtc->fileContent(fileId);
|
||||
QString nameOfPlan = QString::fromStdString(fileContent.name());
|
||||
|
||||
std::function<void(const Core::FunctionReply &baseReply)> handleContent = [this,planId,nameOfPlan](const Core::FunctionReply &baseReply)
|
||||
{
|
||||
const FileManagement::GetFileContentDataReply &reply = static_cast<const FileManagement::GetFileContentDataReply &>(baseReply);
|
||||
|
||||
const QByteArray &planXMLContent = LtsUtils::toQByteArray(reply.content());
|
||||
if (planXMLContent.isEmpty())
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << "Error plan [" << nameOfPlan << "] is empty";
|
||||
return false;
|
||||
}
|
||||
|
||||
PlanOverlaysPlugin::PlanOverlayModel::PlanItem planItem = m_internal->m_overlayModel->planItem(planId);
|
||||
|
||||
if (!m_internal->m_foreignSitmapIfc->planOverlaySetContent(planItem.m_fileId, planItem.m_fileName, planXMLContent))
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << "Error rendering planContent [" << nameOfPlan << "]";
|
||||
return false;
|
||||
}
|
||||
|
||||
planItem.m_fileName = nameOfPlan;
|
||||
|
||||
planItem.m_opacity = m_internal->m_foreignSitmapIfc->planOverlayOpacity(planItem.m_fileId);
|
||||
planItem.m_maxScale = m_internal->m_foreignSitmapIfc->planOverlayMaxScale(planItem.m_fileId);
|
||||
planItem.m_minScale = m_internal->m_foreignSitmapIfc->planOverlayMinScale(planItem.m_fileId);
|
||||
planItem.m_visibility = m_internal->m_foreignSitmapIfc->planOverlayVisibility(planItem.m_fileId);
|
||||
|
||||
m_internal->m_overlayModel->updatePlanItem(planItem);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
bool ok = m_internal->m_requestHelper->startSingleRequest([this,fileId]() -> bool
|
||||
{
|
||||
FileManagement::GetFileContentDataRequest req;
|
||||
req.fileContentId(fileId);
|
||||
return m_internal->m_ftc->getFileContentDataRequest(req, m_internal->m_flmReplyHandler);
|
||||
}, handleContent);
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << "Error reading planContent [" << nameOfPlan << "]";
|
||||
const QString & msg = tr("Reading plan '%1' from database failed").arg(nameOfPlan);
|
||||
LtsWidgets::LtsMessageDialog::showMessage(m_session->baseLayout(), msg, m_internal->m_messageBoxTitle);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool InterfaceImpl::removePlan(int planId)
|
||||
{
|
||||
return removePlan(planId, nullptr);
|
||||
}
|
||||
|
||||
|
||||
bool InterfaceImpl::removePlan(int planId, SituationMap::ForeignGuiInterface* overrideSitMapIfc)
|
||||
{
|
||||
if (overrideSitMapIfc == nullptr)
|
||||
overrideSitMapIfc = m_internal->m_foreignSitmapIfc;
|
||||
|
||||
if (overrideSitMapIfc == nullptr) // still paranoid
|
||||
{
|
||||
ERROR_LOG(m_logger) << "no sit map ifc to remove a plan from for planId " << planId;
|
||||
return false;
|
||||
}
|
||||
|
||||
const PlanOverlaysPlugin::PlanOverlayModel::PlanItem & planItem = m_internal->m_overlayModel->planItem(planId);
|
||||
if (!planItem.isValid())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "plan item invalid for planId " << planId;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!overrideSitMapIfc->planOverlayRemove(planItem.m_fileId))
|
||||
{
|
||||
// HACK: try removing the playn overlay by planId, finally
|
||||
if (!overrideSitMapIfc->planOverlayRemove(planId))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void InterfaceImpl::onChangePlanMinScaleOnMap(int planId, double minScale)
|
||||
{
|
||||
const PlanOverlaysPlugin::PlanOverlayModel::PlanItem & planItem = m_internal->m_overlayModel->planItem(planId);
|
||||
if (planItem.isValid())
|
||||
m_internal->m_foreignSitmapIfc->setPlanOverlayMinScale(planItem.m_fileId, minScale);
|
||||
}
|
||||
|
||||
void InterfaceImpl::onChangePlanMaxScaleOnMap(int planId, double maxScale)
|
||||
{
|
||||
const PlanOverlaysPlugin::PlanOverlayModel::PlanItem & planItem = m_internal->m_overlayModel->planItem(planId);
|
||||
if (planItem.isValid())
|
||||
m_internal->m_foreignSitmapIfc->setPlanOverlayMaxScale(planItem.m_fileId, maxScale);
|
||||
}
|
||||
|
||||
|
||||
void InterfaceImpl::onChangePlanOpacityOnMap(int planId, double opacity)
|
||||
{
|
||||
const PlanOverlaysPlugin::PlanOverlayModel::PlanItem & planItem = m_internal->m_overlayModel->planItem(planId);
|
||||
if (planItem.isValid())
|
||||
m_internal->m_foreignSitmapIfc->setPlanOverlayOpacity(planItem.m_fileId, opacity);
|
||||
}
|
||||
|
||||
|
||||
void InterfaceImpl::onChangePlanOrderOnMap(const QVector<int> &newIdOrder)
|
||||
{
|
||||
QVector<int> layerOrder;
|
||||
|
||||
// The layer in SituationMap layer factory are ordered from bottom to top. To get the correct order
|
||||
// we have to change the direction of ordering in the id list ...
|
||||
|
||||
layerOrder.reserve(newIdOrder.size());
|
||||
for (int planId : newIdOrder)
|
||||
{
|
||||
const PlanOverlaysPlugin::PlanOverlayModel::PlanItem & planItem = m_internal->m_overlayModel->planItem(planId);
|
||||
if (planItem.isValid())
|
||||
{
|
||||
layerOrder.push_front(planItem.m_fileId);
|
||||
}
|
||||
}
|
||||
|
||||
m_internal->m_foreignSitmapIfc->planOverlayChangeOrder(layerOrder);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void InterfaceImpl::onPlanContentChanged(const FileManagement::FileContent &data, DataModification modType)
|
||||
{
|
||||
if (data.fileType() != FileManagement::FileType::TacticalPlan) return;
|
||||
|
||||
const PlanOverlaysPlugin::PlanOverlayModel::PlanItem &planItem = m_internal->m_overlayModel->findPlanItemByFileId(data.id());
|
||||
|
||||
if (planItem.isValid())
|
||||
{
|
||||
switch (modType)
|
||||
{
|
||||
case DataModification::eModified : m_internal->m_overlayModel->updateOverlay(planItem.m_keyId); break;
|
||||
case DataModification::eRemoved : m_internal->m_overlayModel->removeOverlay(planItem.m_keyId); break;
|
||||
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void InterfaceImpl::onExerciseChanged(const ExerciseManagement::Exercise &data, DataModification modType)
|
||||
{
|
||||
switch (modType)
|
||||
{
|
||||
case DataModification::eModified:
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "onExerciseChanged - Modified";
|
||||
m_internal->m_overlayModel->reInitModel(data.id(), data.activePhaseId());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void InterfaceImpl::onReloadPlanByName(const PlanOverlaysPlugin::PlanOverlayModel::PlanItem &planItem, int exerciseId, int phaseId, bool *removeFromModel)
|
||||
{
|
||||
if (removeFromModel)
|
||||
*removeFromModel = false;
|
||||
|
||||
if (planItem.isValid())
|
||||
{
|
||||
int planFileId = m_internal->m_dtc->getFileId(FileManagement::FileType::TacticalPlan, planItem.m_fileName, exerciseId, phaseId);
|
||||
|
||||
DEBUG_LOG(m_logger) << "Plan File Id = " << planFileId;
|
||||
|
||||
if (planFileId < 1)
|
||||
{
|
||||
if (removeFromModel) *removeFromModel = true;
|
||||
INFO_LOG(m_logger) << "Plan overlay will be removed: name = " << planItem.m_fileName;
|
||||
return;
|
||||
}
|
||||
|
||||
FileManagement::FileContent fileContent = m_internal->m_dtc->fileContent(planFileId);
|
||||
QString nameOfPlan = QString::fromStdString(fileContent.name());
|
||||
int planId = planItem.m_keyId;
|
||||
|
||||
std::function<void(const Core::FunctionReply &baseReply)> handleContent = [this, planId, nameOfPlan, fileContent](const Core::FunctionReply &baseReply)
|
||||
{
|
||||
const FileManagement::GetFileContentDataReply &reply = static_cast<const FileManagement::GetFileContentDataReply &>(baseReply);
|
||||
|
||||
const QByteArray &planXMLContent = LtsUtils::toQByteArray(reply.content());
|
||||
if (planXMLContent.isEmpty())
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << "Error plan [" << nameOfPlan << "] is empty";
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
PlanOverlaysPlugin::PlanOverlayModel::PlanItem pi = m_internal->m_overlayModel->planItem(planId); // get copy of planItem from model
|
||||
|
||||
// file id has changed remove the old plan first
|
||||
if (!m_internal->m_foreignSitmapIfc->planOverlayRemove(pi.m_fileId))
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << "Error removing plan overlay from map failed [" << nameOfPlan << "]";
|
||||
}
|
||||
|
||||
// now load the new version of the plan
|
||||
if (!m_internal->m_foreignSitmapIfc->planOverlaySetContent(fileContent.id(), nameOfPlan, planXMLContent))
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << "Error rendering planContent [" << nameOfPlan << "]";
|
||||
return false;
|
||||
}
|
||||
|
||||
// re-write rest of properties, in case fileId changed, using same file name
|
||||
|
||||
pi.m_fileName = nameOfPlan;
|
||||
pi.m_fileId = fileContent.id();
|
||||
pi.m_folderId = fileContent.folderId();
|
||||
if (fileContent.exerciseId().is_set())
|
||||
{
|
||||
pi.m_exerciseId = fileContent.exerciseId().get();
|
||||
if (fileContent.phaseId().is_set())
|
||||
pi.m_phaseId = fileContent.phaseId().get();
|
||||
}
|
||||
// don't change the attributes opacity, minScale, maxScale and visibility
|
||||
|
||||
m_internal->m_overlayModel->updatePlanItem(pi);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
bool ok = m_internal->m_requestHelper->startSingleRequest([this,planFileId]() -> bool
|
||||
{
|
||||
FileManagement::GetFileContentDataRequest req;
|
||||
req.fileContentId(planFileId);
|
||||
return m_internal->m_ftc->getFileContentDataRequest(req, m_internal->m_flmReplyHandler);
|
||||
}, handleContent);
|
||||
|
||||
m_internal->m_overlayModel->updateOrderOfPlans();
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << "Error reading planContent [" << nameOfPlan << "]";
|
||||
const QString & msg = tr("Reading plan '%1' from database failed").arg(nameOfPlan);
|
||||
LtsWidgets::LtsMessageDialog::showMessage(m_session->baseLayout(), msg, m_internal->m_messageBoxTitle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TopicEditorBase::TopicEditor *InterfaceImpl::createTopicEditor(const TopicEditorBase::TopicData &data)
|
||||
{
|
||||
std::shared_ptr<FileManagement::Interface::Dtc> flmDtc;
|
||||
if (!m_session->getDtc<FileManagement::DataInterface>(flmDtc))
|
||||
WARNING_LOG(m_logger) << "flm dtc missing - plan topic compatibility mode file name resolution not available";
|
||||
|
||||
PlanTopicEditor *editor = new PlanTopicEditor(&m_foreignIfc, flmDtc);
|
||||
editor->setTopicData(data);
|
||||
return editor;
|
||||
}
|
||||
|
||||
|
||||
TopicReplay::Interface *InterfaceImpl::createInterface(TopicEditorBase::TopicType)
|
||||
{
|
||||
return new TopicReplayInterface(m_internal->m_foreignSitmapIfc, this);
|
||||
}
|
||||
|
||||
|
||||
InterfaceImpl::TopicReplayInterface::TopicReplayInterface(SituationMap::ForeignGuiInterface *foreignSitmapIfc, InterfaceImpl *ovr)
|
||||
: m_ovr(ovr)
|
||||
, m_foreignSitmapIfc(foreignSitmapIfc)
|
||||
, m_logger(getLogger())
|
||||
{}
|
||||
|
||||
InterfaceImpl::TopicReplayInterface::~TopicReplayInterface()
|
||||
{
|
||||
playbackStop();
|
||||
}
|
||||
|
||||
|
||||
bool InterfaceImpl::TopicReplayInterface::playbackInit(const QJsonObject &attributes)
|
||||
{
|
||||
if (!m_foreignSitmapIfc)
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << "No foreign sitMapIfc, use PlanOverlaysPlugin::ForeignGuiInterface::setForeignSitMapGuiIfc() to define SituationMapGuiPlugin interface. Can't load tactical plan for playback ...";
|
||||
return false;
|
||||
}
|
||||
|
||||
// there exist one single plan per topic, get file id of plan from attributes
|
||||
|
||||
int planFileId = attributes[QStringLiteral("fileId")].toInt(-1);
|
||||
|
||||
if (planFileId != -1) // compatibility mode
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Plan Overlays topic in compatibility mode!";
|
||||
DEBUG_LOG(m_logger) << "Loading plan id = " << planFileId;
|
||||
|
||||
if (!m_ovr->loadPlan(planFileId, false, m_foreignSitmapIfc))
|
||||
return false;
|
||||
|
||||
m_loadedPlanFileIds += planFileId; // store planFileId to remove plan when playback stops
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto plans = attributes[QStringLiteral("PlanItems")].toArray();
|
||||
for (const QJsonValue &planItemValue : plans)
|
||||
{
|
||||
if (!planItemValue.isObject())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "PlanItem from json array is not an object! " << planItemValue.type();
|
||||
continue;
|
||||
}
|
||||
|
||||
const QJsonObject planItemObj(planItemValue.toObject());
|
||||
planFileId = planItemObj[QStringLiteral("fileId")].toInt(-1);
|
||||
|
||||
if (!m_ovr->loadPlan(planFileId, planItemObj))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "could not load plan with file id " << planFileId;
|
||||
continue;
|
||||
}
|
||||
|
||||
m_loadedPlanFileIds += planFileId;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool InterfaceImpl::TopicReplayInterface::playbackStop()
|
||||
{
|
||||
if (nullptr == m_foreignSitmapIfc)
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << "Use PlanOverlaysPlugin::ForeignGuiInterface::setForeignSitMapGuiIfc() to define SituationMapGuiPlugin interface ...";
|
||||
return false;
|
||||
}
|
||||
|
||||
while (!m_loadedPlanFileIds.isEmpty())
|
||||
{
|
||||
int planFileId = m_loadedPlanFileIds.takeFirst();
|
||||
DEBUG_LOG(m_logger) << " removePlan with file id " << planFileId;
|
||||
if (!m_ovr->removePlan(planFileId, m_foreignSitmapIfc)) // remove plan created in playbackInit()
|
||||
ERROR_LOG(m_logger) << "could not unload plan with file id " << planFileId;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QVector<TopicEditorBase::TopicData> InterfaceImpl::TopicReplayInterface::additionalTrackEntries(const QJsonObject &attributes, bool &keepOriginalTopic) const
|
||||
{
|
||||
keepOriginalTopic = false;
|
||||
const auto plans = attributes[QStringLiteral("PlanItems")].toArray();
|
||||
QVector<TopicEditorBase::TopicData> ret;
|
||||
ret.reserve(plans.size());
|
||||
for (const QJsonValue &ele : plans)
|
||||
{
|
||||
const auto pi = PlanOverlayModel::PlanItem::fromJson(ele.toObject());
|
||||
if (!pi.isValid())
|
||||
continue;
|
||||
|
||||
TopicEditorBase::TopicData data;
|
||||
data.topicType = TopicEditorBase::TopicType::TacticalPlan;
|
||||
data.properties = QJsonObject({{QStringLiteral("FileId"), pi.m_fileId}});
|
||||
ret += data;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace PlanOverlaysPlugin
|
||||
+253
@@ -0,0 +1,253 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** plan_editor_gui_plugin.h
|
||||
** $Id$
|
||||
** $HeadURL$
|
||||
** $Author$
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Hardware-Environment: Intel-PC
|
||||
** Software-Environment: Windows 7, Qt 5.7. ArcGIS 100
|
||||
**
|
||||
** Language ........: C++ 11
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Author ...........: Jörg Turla, SPD G, Tel. 3132
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Notes .........:
|
||||
**
|
||||
** 24.04.2017, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "plan_overlay_model.h"
|
||||
|
||||
#include <PluginInterfaces/gui_plugin_interface.h>
|
||||
#include <TopicEditorBase/topic_editor_interface.h>
|
||||
#include <Common/ProjectConfig/project_defines.h>
|
||||
#include <Plugins/PlanOverlays/plan_overlays_plugin_interface.h>
|
||||
#include <Plugins/FileManagement/flm_data_plugin_interface.h>
|
||||
#include <Plugins/ExerciseManagement/exm_data_plugin_interface.h>
|
||||
|
||||
#include <QObject>
|
||||
|
||||
|
||||
namespace Core
|
||||
{
|
||||
class FunctionReplyObject;
|
||||
}
|
||||
|
||||
namespace SituationMap
|
||||
{
|
||||
class ScriptFilterForeignGuiInterface;
|
||||
}
|
||||
|
||||
|
||||
namespace PlanOverlaysPlugin
|
||||
{
|
||||
/**
|
||||
@class PlanEOverlaysPlugin
|
||||
Implementation of plugin base to create interface instance. To use the plugin it has to be configured
|
||||
in apps.json configuration file. The Type and IID habe to be set to:
|
||||
|
||||
- "Type": "gui"
|
||||
- "IID": "planoverlays"
|
||||
|
||||
The PlanEditorGuiPlugin uses the file manager data plugin to read and store data with file manager service.
|
||||
|
||||
@see InterfaceImpl, PlanEditor, SituationMap
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
// PlanOverlaysGuiPlugin
|
||||
//------------------------------------------------------------------------------
|
||||
class PlanOverlaysGuiPlugin final : public QObject, public GuiPluginBase::Plugin
|
||||
{
|
||||
Q_PLUGIN_METADATA(IID "gui:3:planoverlays")
|
||||
Q_INTERFACES(GuiPluginBase::Plugin)
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit PlanOverlaysGuiPlugin() = default;
|
||||
~PlanOverlaysGuiPlugin() = default;
|
||||
|
||||
QString pluginName() override { return QStringLiteral("PlanOverlaysPlugin"); }
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// InterfaceImpl
|
||||
//------------------------------------------------------------------------------
|
||||
class InterfaceImpl final : public QObject, public ForeignGuiInterface, public GuiPluginBase::Interface
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class InternalData;
|
||||
InternalData *m_internal;
|
||||
|
||||
public:
|
||||
explicit InterfaceImpl(LtsSession::LtsSession *session);
|
||||
~InterfaceImpl();
|
||||
|
||||
QVector<LtsWidgets::PluginData> getActions() override;
|
||||
|
||||
QString menuGroup() const override;
|
||||
bool fetchInterfaces() override;
|
||||
void clearInterfaces() override;
|
||||
|
||||
/**
|
||||
Set SituationMapGuiPlugin interface from forgein session. Is used by ScriptEditor to define map view displaying plans.
|
||||
@param foreignSitMapIfc Pointer to SituationMapGuiPlugin interface used to load plan into map when used by ScriptEditor
|
||||
*/
|
||||
void setForeignSitMapGuiIfc(SituationMap::ForeignGuiInterface *foreignSitmapIfc) override;
|
||||
void setForeignPlanOverlaysGuiIfc(ForeignGuiInterface *ifc) override;
|
||||
|
||||
|
||||
|
||||
bool loadPlanByUser(int planFileId);
|
||||
|
||||
/**
|
||||
@brief Load a plan as overlay into map
|
||||
@param planFileId File-Id of plan in file management service
|
||||
@return
|
||||
*/
|
||||
bool loadPlan(int planFileId) override; // TODO: move to slots
|
||||
|
||||
/**
|
||||
Load a plan as overlay into map
|
||||
@param planFileId File-Id of plan in file management service
|
||||
@param applyMinMaxScaleOfMetadata The xmlContent may contain minScale, maxScale. Apply them?
|
||||
*/
|
||||
bool loadPlan(int planFileId, const QJsonObject &planItemObject) override;
|
||||
|
||||
/**
|
||||
bool loadPlan(int planFileId) override;
|
||||
Load a plan as overlay into map
|
||||
@param planFileId File-Id of plan in file management service
|
||||
@param applyMinMaxScaleOfMetadata The xmlContent may contain minScale, maxScale. Apply them?
|
||||
@param overrideSitMapIfc Pointer to SituationMapGuiPlugin interface used to load plan into map
|
||||
*/
|
||||
bool loadPlan(int planFileId, bool applyMinMaxScaleOfMetadata, SituationMap::ForeignGuiInterface *overrideSitMapIfc, const QJsonObject &planItemObject = QJsonObject());
|
||||
|
||||
/**
|
||||
* @brief unloadAllPlans
|
||||
* Unload all plans: remove from update model (update GUI), removePlan from sitMap
|
||||
* (Usefull for SnapshotDialog::showSnapshotInternal)
|
||||
* @return true
|
||||
*/
|
||||
bool unloadAllPlans() override;
|
||||
|
||||
|
||||
TopicEditorBase::TopicEditor *createTopicEditor(const TopicEditorBase::TopicData &data) override;
|
||||
|
||||
QWidget *openPlanOverlayDialog(const QJsonArray &planItems = QJsonArray(), bool removePlansOnClose = false) override;
|
||||
|
||||
PlanOverlayModel *planOverlayModel() override;
|
||||
|
||||
|
||||
private:
|
||||
/**
|
||||
Reload an already loaded plan.
|
||||
@param planId Id of the plan (keyId) from PlanOverlayModel
|
||||
*/
|
||||
void onReloadPlanById(int planId);
|
||||
|
||||
/**
|
||||
Reload an already loaded plan.
|
||||
@param planId Id of the plan (keyId) from PlanOverlayModel
|
||||
*/
|
||||
void onUpdatePlan(int planId);
|
||||
|
||||
/**
|
||||
Remove a plan from map
|
||||
@param planId Id of the plan (keyId) from PlanOverlayModel
|
||||
*/
|
||||
bool removePlan(int planId);
|
||||
|
||||
/**
|
||||
Remove a plan from map
|
||||
@param planId Id of the plan (keyId) from PlanOverlayModel
|
||||
@param overrideSitMapIfc Pointer to SituationMapGuiPlugin interface used to remove plan from map
|
||||
*/
|
||||
bool removePlan(int planId, SituationMap::ForeignGuiInterface *overrideSitMapIfc);
|
||||
|
||||
void onChangePlanMinScaleOnMap(int planId, double minScale);
|
||||
void onChangePlanMaxScaleOnMap(int planId, double maxScale);
|
||||
|
||||
/**
|
||||
Change opacity of a plan
|
||||
@param planId Id of the plan (keyId) from PlanOverlayModel
|
||||
*/
|
||||
void onChangePlanOpacityOnMap(int planId, double opacity);
|
||||
|
||||
/**
|
||||
Change order of plans on map.
|
||||
@param newIdOrder Order of plan ids
|
||||
*/
|
||||
void onChangePlanOrderOnMap(const QVector<int> & newIdOrder);
|
||||
|
||||
void onPlanContentChanged(const FileManagement::FileContent &data, DataModification modType);
|
||||
void onExerciseChanged(const ExerciseManagement::Exercise &data, DataModification modType);
|
||||
|
||||
void onReloadPlanByName(const PlanOverlayModel::PlanItem &planItem, int exerciseId, int phaseId, bool *removeFromModel);
|
||||
|
||||
|
||||
// Script Player
|
||||
class TopicReplayInterface : public TopicReplay::Interface
|
||||
{
|
||||
public:
|
||||
TopicReplayInterface(SituationMap::ForeignGuiInterface* overrideSitmapIfc,
|
||||
InterfaceImpl *ovr);
|
||||
|
||||
~TopicReplayInterface();
|
||||
|
||||
bool playbackInit(const QJsonObject &attributes) override;
|
||||
bool playbackStop() override;
|
||||
|
||||
// overlays are treated special, not exported here atm
|
||||
bool exportTopic(const QJsonObject &,
|
||||
const QString &,
|
||||
TopicEditorBase::ExportNotifier *) override
|
||||
{
|
||||
Q_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
QVector<TopicEditorBase::TopicData> additionalTrackEntries(const QJsonObject &attributes, bool &keepOriginalTopic) const override;
|
||||
|
||||
private:
|
||||
InterfaceImpl *m_ovr;
|
||||
SituationMap::ForeignGuiInterface *m_foreignSitmapIfc;
|
||||
//int m_planFileId;
|
||||
QVector<int> m_loadedPlanFileIds;
|
||||
NGL::INGLLogger &m_logger;
|
||||
}; // TopicReplayInterface
|
||||
|
||||
|
||||
TopicReplay::Interface *createInterface(TopicEditorBase::TopicType) override;
|
||||
ForeignGuiInterface *m_foreignIfc;
|
||||
QPointer<QWidget> m_planOverlayDialog;
|
||||
|
||||
};
|
||||
|
||||
} // namespace PlanOverlaysPlugin
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** plan_editor.h
|
||||
** $Id$
|
||||
** $HeadURL$
|
||||
** $Author$
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Hardware-Environment: Intel-PC
|
||||
** Software-Environment: Windows 7, Qt 5.7. ArcGIS 100
|
||||
**
|
||||
** Language ........: C++ 11
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Author ...........: Jörg Turla, SPD G, Tel. 3132
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Notes .........:
|
||||
**
|
||||
** 29.06.2017, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <PluginInterfaces/topic_replay_interface.h>
|
||||
#include <TopicEditorBase/topic_editor_interface.h>
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
|
||||
|
||||
namespace SituationMap
|
||||
{
|
||||
class ForeignGuiInterface;
|
||||
}
|
||||
|
||||
namespace PlanOverlaysPlugin
|
||||
{
|
||||
class PlanOverlayModel;
|
||||
|
||||
class ForeignGuiInterface : public TopicReplay::Factory, public TopicEditorBase::Interface
|
||||
{
|
||||
public:
|
||||
|
||||
ForeignGuiInterface() = default;
|
||||
virtual ~ForeignGuiInterface() = default;
|
||||
|
||||
static QString pluginName() { return QStringLiteral("PlanOverlaysGuiPlugin"); }
|
||||
|
||||
/**
|
||||
Set SituationMapGuiPlugin interface from forgein session. Is used by ScriptEditor to define map view displaying plans.
|
||||
@param foreignSitMapIfc Pointer to SituationMapGuiPlugin interface used to load plan into map when used by ScriptEditor
|
||||
*/
|
||||
virtual void setForeignSitMapGuiIfc(SituationMap::ForeignGuiInterface *foreignSitMapIfc) = 0;
|
||||
|
||||
virtual void setForeignPlanOverlaysGuiIfc(ForeignGuiInterface *ifc) = 0;
|
||||
|
||||
virtual QWidget *openPlanOverlayDialog(const QJsonArray &planItems = QJsonArray(), bool removePlansOnClose = false) = 0;
|
||||
|
||||
/**
|
||||
Load a plan as overlay into map
|
||||
@param planFileId File-Id of plan in file management service
|
||||
*/
|
||||
virtual bool loadPlan(int planFileId, const QJsonObject &planItemObject) = 0;
|
||||
virtual bool loadPlan(int planFileId) = 0;
|
||||
|
||||
/**
|
||||
* @brief unloadAllPlans
|
||||
* Unload all plans: remove from update model (update GUI), removePlan from sitMap
|
||||
* (Usefull for SnapshotDialog::showSnapshotInternal)
|
||||
* @return true
|
||||
*/
|
||||
virtual bool unloadAllPlans() = 0;
|
||||
|
||||
virtual PlanOverlayModel *planOverlayModel() = 0;
|
||||
|
||||
}; // ForeignGuiInterface
|
||||
|
||||
} // namespace PlanOverlaysPlugin
|
||||
Reference in new issue
Block a user