Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
638a37a252 |
No files matched your search
-11
@@ -1,11 +0,0 @@
|
||||
build-rti-full
|
||||
build-rti-off
|
||||
build-rti-off-notests
|
||||
build-*
|
||||
build_*
|
||||
CMakeFiles
|
||||
fix_qt6_gui_deps2.py
|
||||
fix_qt6_gui_deps.py
|
||||
fix_rti_conditionals.py
|
||||
fix_target_checks.py
|
||||
build
|
||||
@@ -1,9 +0,0 @@
|
||||
build-rti-full
|
||||
build-rti-off
|
||||
build-rti-off-notests
|
||||
build-*
|
||||
CMakeFiles
|
||||
fix_qt6_gui_deps2.py
|
||||
fix_qt6_gui_deps.py
|
||||
fix_rti_conditionals.py
|
||||
fix_target_checks.py
|
||||
@@ -1 +0,0 @@
|
||||
../../external
|
||||
@@ -1,54 +0,0 @@
|
||||
---
|
||||
BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -2
|
||||
AlignTrailingComments: true
|
||||
AlignAfterOpenBracket: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortFunctionsOnASingleLine: Inline
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BreakBeforeBinaryOperators: false
|
||||
BreakBeforeBraces: Allman
|
||||
BreakConstructorInitializers: BeforeComma
|
||||
BreakInheritanceList: BeforeComma
|
||||
ColumnLimit: 170
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
IncludeCategories:
|
||||
- Regex: '^".*"$'
|
||||
Priority: 1
|
||||
- Regex: '^<.*>$'
|
||||
Priority: 2
|
||||
IndentCaseLabels: true
|
||||
IndentWidth: 2
|
||||
InsertNewlineAtEOF: true
|
||||
Language: Cpp
|
||||
MaxEmptyLinesToKeep: 2
|
||||
NamespaceIndentation: All
|
||||
PenaltyBreakBeforeFirstCallParameter: 1000
|
||||
PenaltyReturnTypeOnItsOwnLine: 1000
|
||||
PointerAlignment: Right
|
||||
PointerBindsToType: false
|
||||
SortIncludes: false
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpacesInAngles: false
|
||||
SpacesInParentheses: false
|
||||
Standard: c++20
|
||||
UseTab: Never
|
||||
TabWidth: 2
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
CompactNamespaces: false
|
||||
DerivePointerAlignment: false
|
||||
ReflowComments: false
|
||||
SortUsingDeclarations: false
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
FixNamespaceComments: false
|
||||
@@ -1,3 +0,0 @@
|
||||
export MIGRATE_PIPELINE_ROOT="/home/torsten/sandbox/qt6-migration-pipeline"
|
||||
export LANG=C.UTF-8
|
||||
export LC_ALL=C.UTF-8
|
||||
@@ -1,17 +0,0 @@
|
||||
build-rti-full
|
||||
build-rti-off
|
||||
build-rti-off-notests
|
||||
build-*
|
||||
CMakeFiles
|
||||
fix_qt6_gui_deps2.py
|
||||
fix_qt6_gui_deps.py
|
||||
fix_rti_conditionals.py
|
||||
fix_target_checks.py
|
||||
Lts/Tools/ArAssetsV2/build
|
||||
Lts/Tools/ArAssetsV3/build
|
||||
Lts/Tools/ArAssetsV3_Qatar/build
|
||||
build/
|
||||
build2/
|
||||
.envrc
|
||||
build4
|
||||
coverage-out/
|
||||
Whitespace-only changes.
@@ -1,675 +0,0 @@
|
||||
#
|
||||
# Haupt CMakeLists.txt für das Projekt TDS
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
# Setzen von CMAKE_INSTALL_PREFIX auf "/shd/CTC" falls nicht über Kommandozeile angegeben
|
||||
#
|
||||
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 3.16)
|
||||
IF(POLICY CMP0069)
|
||||
CMAKE_POLICY(SET CMP0069 NEW) # cmake >= 3.9.0 - INTERPROCEDURAL_OPTIMIZATION behavior
|
||||
ENDIF()
|
||||
IF(POLICY CMP0071)
|
||||
CMAKE_POLICY(SET CMP0071 NEW) # cmake >= 3.10.0 - automatically process generated sources with AUTOMOC
|
||||
ENDIF()
|
||||
IF(POLICY CMP0072)
|
||||
CMAKE_POLICY(SET CMP0072 NEW) # cmake >= 3.11.0 - prefer libOpenGL.so over legacy libGL.so
|
||||
ENDIF()
|
||||
|
||||
|
||||
IF(NOT DEFINED CMAKE_INSTALL_PREFIX)
|
||||
SET(CMAKE_INSTALL_PREFIX "/shd/CTC" CACHE STRING "Install path prefix, prepended onto install directories." FORCE)
|
||||
ENDIF()
|
||||
#
|
||||
# # Setzen von CMAKE_BUILD_TYPE auf "Debug" falls nicht über Kommandozeile angegeben
|
||||
#
|
||||
IF(NOT DEFINED CMAKE_BUILD_TYPE)
|
||||
SET(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel." FORCE)
|
||||
ENDIF()
|
||||
ADD_DEFINITIONS(-DEXPORT_BDV_TOPIC_AS_JSON)
|
||||
SET(_ver "1.2.0")
|
||||
IF(DEFINED LTS_VERSION_MAJOR AND DEFINED LTS_VERSION_MINOR AND DEFINED LTS_VERSION_PATCH)
|
||||
SET(_ver "${LTS_VERSION_MAJOR}.${LTS_VERSION_MINOR}.${LTS_VERSION_PATCH}")
|
||||
ENDIF()
|
||||
PROJECT(LTS VERSION ${_ver})
|
||||
MESSAGE(STATUS "LTS Version: ${LTS_VERSION_MAJOR}.${LTS_VERSION_MINOR}.${LTS_VERSION_PATCH}")
|
||||
|
||||
# Enable CTest integration for unit tests
|
||||
include(CTest)
|
||||
|
||||
# Release scope: subdirectories are added unconditionally (no per-module migration builds)
|
||||
function(NGL_ADD_SUBDIR_GUARDED subdir)
|
||||
add_subdirectory(${subdir})
|
||||
endfunction()
|
||||
|
||||
SET(LTS_VERSION_DATE "01.01.2018" CACHE STRING "The date when this software was compiled")
|
||||
ADD_DEFINITIONS(-DLTS_VERSION_MAJOR=\"${LTS_VERSION_MAJOR}\")
|
||||
ADD_DEFINITIONS(-DLTS_VERSION_MINOR=\"${LTS_VERSION_MINOR}\")
|
||||
ADD_DEFINITIONS(-DLTS_VERSION_PATCH=\"${LTS_VERSION_PATCH}\")
|
||||
ADD_DEFINITIONS(-DLTS_VERSION_DATE=\"${LTS_VERSION_DATE}\")
|
||||
IF(JENKINS_BUILD_NUMBER)
|
||||
ADD_DEFINITIONS(-DJENKINS_BUILD_NUMBER=\"${JENKINS_BUILD_NUMBER}\")
|
||||
ELSE()
|
||||
ADD_DEFINITIONS(-DJENKINS_BUILD_NUMBER=\"unknown\")
|
||||
ENDIF()
|
||||
|
||||
ADD_DEFINITIONS(-DAPP6C)
|
||||
SET(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
# Resolve <DDS/...> and other framework includes to the real headers under
|
||||
# Lts/ BEFORE the migration stub tree in include/. The stub tree shadows them
|
||||
# otherwise and opens namespace DDSGeneric around framework includes, which
|
||||
# pulls Qt/std definitions into that namespace and breaks every consumer.
|
||||
# (The qt5 legacy has no include/ tree; Lts/ is the real include root.)
|
||||
include_directories(BEFORE ${CMAKE_SOURCE_DIR})
|
||||
include_directories(${CMAKE_SOURCE_DIR}/include)
|
||||
# Include directory for generated export headers
|
||||
include_directories(${CMAKE_BINARY_DIR})
|
||||
include_directories(${CMAKE_SOURCE_DIR}/Z/src)
|
||||
# Include directories for external dependencies and internal modules
|
||||
include_directories(${CMAKE_SOURCE_DIR}/Z/src)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/Z/src/ngltools)
|
||||
# Lts/Viewer is outside the release scope; only add the include paths when
|
||||
# present to avoid -Wmissing-include-dirs warnings on validation-scope trees
|
||||
if(EXISTS "${CMAKE_SOURCE_DIR}/Lts/Viewer/SituationMap/Symbology")
|
||||
include_directories(${CMAKE_SOURCE_DIR}/Lts/Viewer/SituationMap/Symbology)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/Lts/Viewer/LtsDataView)
|
||||
endif()
|
||||
include_directories(${CMAKE_SOURCE_DIR}/Lts/Proxies/TrainingAreaBase)
|
||||
# Release scope: include path for ProjectDataManagement stub headers
|
||||
IF(RELEASE_BUILD)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/Lts/Services/ProjectDataManagement/stubs)
|
||||
ENDIF()
|
||||
include_directories(${CMAKE_SOURCE_DIR}/Lts/Common)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/Lts/Common/LtsUtils)
|
||||
include_directories(${CMAKE_BINARY_DIR}/Lts/Common/LtsUtils/LtsUtilsCore)
|
||||
# LtsUtilsSettings's generated ltsutilssettings_export.h is included by bare name from
|
||||
# settings.h. Consumer targets that reach settings.h transitively (without linking
|
||||
# LtsUtilsSettings themselves) cannot see it through the target's PUBLIC interface, so the
|
||||
# directory holding the generated header has to be visible tree-wide. The directory contains
|
||||
# only that generated header, so appending it cannot shadow an existing include.
|
||||
include_directories(${CMAKE_BINARY_DIR}/Lts/Common/LtsUtils/LtsUtilsSettings)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/Z/src/NGLLogger)
|
||||
SET(CMAKE_CXX_STANDARD 17)
|
||||
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
SET(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
|
||||
SET(CMAKE_CXX_VISIBILITY_PRESET hidden)
|
||||
# Qt6 Migration: Removed CMAKE_POSITION_INDEPENDENT_CODE - Qt6 handles PIC automatically
|
||||
# and this setting conflicts with Qt6's reduce_relocations feature
|
||||
# SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
IF(CMAKE_VERSION VERSION_GREATER 3.15.9)
|
||||
OPTION(USE_UNITY_BUILDS "Use Unity builds to speed up compilation (cmake 3.16 or newer required!)" OFF)
|
||||
IF (USE_UNITY_BUILDS)
|
||||
SET(CMAKE_UNITY_BUILD ON)
|
||||
SET(CMAKE_UNITY_BUILD_BATCH_SIZE 40)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
# Add Lts/ include path globally for QosProfile and other Lts headers
|
||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/Lts)
|
||||
|
||||
OPTION(BUILD_LTSWEBSOCKET "Build LtsWebSocket module (requires NGLLogger)" ON)
|
||||
|
||||
# Set CMAKE_MODULE_PATH early so FIND_PACKAGE can find our custom Find modules
|
||||
SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
||||
INCLUDE(FindLibraryWithDebug)
|
||||
|
||||
ENABLE_TESTING()
|
||||
INCLUDE(CTest)
|
||||
CONFIGURE_FILE(CTestCustom.ctest ${CMAKE_BINARY_DIR}/CTestCustom.ctest COPYONLY)
|
||||
CONFIGURE_FILE(lts-cc.conf ${CMAKE_BINARY_DIR}/lts-cc.conf.distrib COPYONLY)
|
||||
|
||||
# Add bundled GeographicLib cmake config to find modern targets (GeographicLib::GeographicLib_SHARED)
|
||||
LIST(APPEND CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/include/GeographicLib/lib/cmake")
|
||||
SET(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
|
||||
IF(WIN32)
|
||||
SET(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
|
||||
ELSE(WIN32)
|
||||
SET(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib)
|
||||
ENDIF()
|
||||
|
||||
#
|
||||
# Disallow in-source build
|
||||
#
|
||||
INCLUDE(MacroEnsureOutOfSourceBuild)
|
||||
|
||||
macro_ensure_out_of_source_build("In-Source build nicht erlaubt!")
|
||||
|
||||
#
|
||||
# Qt ist wichtig - zuerst suchen
|
||||
#
|
||||
SET(CMAKE_AUTOMOC TRUE)
|
||||
SET(CMAKE_AUTOUIC TRUE)
|
||||
SET(QT_USE_IMPORTED_TARGETS TRUE)
|
||||
|
||||
# Check for OpenGL first (required by Qt6Gui)
|
||||
find_package(OpenGL)
|
||||
|
||||
# Prefer Qt6, fallback to Qt5. Create Qt6::*-aliases when Qt6 is found so existing CMakeLists continue to work.
|
||||
# Try to find Qt6 with GUI components first
|
||||
set(QT6_GUI_AVAILABLE FALSE)
|
||||
set(QT6_FOUND FALSE)
|
||||
set(QT6_CORE5COMPAT_AVAILABLE FALSE)
|
||||
|
||||
# First check if Core5Compat is available
|
||||
find_package(Qt6 6.2 COMPONENTS Core5Compat QUIET)
|
||||
if(Qt6Core5Compat_FOUND)
|
||||
set(QT6_CORE5COMPAT_AVAILABLE TRUE)
|
||||
message(STATUS "Found Qt6Core5Compat")
|
||||
endif()
|
||||
|
||||
# Find Qt6 core components first (without OpenGL which may not be available)
|
||||
# WebSockets is required by the migrated services (FileManagement's THP script
|
||||
# server uses QWebSocketServer; LtsWebSocket/httq enable their real websocket
|
||||
# paths via QT6_WEBSOCKETS_AVAILABLE when the module is found).
|
||||
find_package(Qt6 6.2 COMPONENTS Concurrent Core LinguistTools Network
|
||||
Multimedia Sql SerialPort Test Xml Positioning Svg WebSockets PrintSupport OpenGL QUIET)
|
||||
|
||||
if(Qt6_FOUND)
|
||||
# Check if OpenGL was found (GUI support available)
|
||||
if(OpenGL_FOUND)
|
||||
set(QT6_GUI_AVAILABLE TRUE)
|
||||
message(STATUS "Found Qt6 with GUI support (OpenGL): ${Qt6Core_VERSION}")
|
||||
else()
|
||||
# Skip GUI find_package - it fails without OpenGL. We'll create manual targets below.
|
||||
set(QT6_GUI_AVAILABLE FALSE)
|
||||
message(STATUS "Found Qt6 (GUI will be manually configured): ${Qt6Core_VERSION}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# If Qt6 not found yet, try with full component list including OpenGL
|
||||
if(NOT Qt6_FOUND)
|
||||
find_package(Qt6 6.2 COMPONENTS Concurrent Core LinguistTools Network OpenGL PrintSupport
|
||||
Multimedia Sql Svg SerialPort Test UiTools WebSockets WebEngineCore WebEngineWidgets
|
||||
Widgets Xml Positioning QUIET)
|
||||
if(Qt6_FOUND AND OpenGL_FOUND)
|
||||
set(QT6_GUI_AVAILABLE TRUE)
|
||||
message(STATUS "Found Qt6 with GUI support (OpenGL): ${Qt6Core_VERSION}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT Qt6_FOUND)
|
||||
# Final fallback - try to find Qt6 with minimum required components
|
||||
find_package(Qt6 6.2 COMPONENTS Core REQUIRED)
|
||||
message(STATUS "Found Qt6 (minimal): ${Qt6Core_VERSION}")
|
||||
endif()
|
||||
|
||||
# Manual Qt6 configuration - create imported targets for available libraries
|
||||
if(NOT TARGET Qt6::Core)
|
||||
find_package(Qt6 6.2 COMPONENTS Core REQUIRED)
|
||||
endif()
|
||||
|
||||
# Create imported targets for all available Qt6 libraries
|
||||
# Use Qt6 installation path from find_package or fall back to system paths
|
||||
if(Qt6Core_DIR)
|
||||
# <Qt6Core_DIR> is the cmake package dir: <prefix>/lib/cmake/Qt6Core in the
|
||||
# standard Qt layout and <prefix>/<multiarch>/cmake/Qt6Core in the Debian/
|
||||
# Ubuntu layout — so the library dir is two levels up in both. (Going three
|
||||
# levels up and appending /lib only matches the standard layout; in the
|
||||
# Debian validation container it resolved to /usr/lib/lib and every manual
|
||||
# target below was silently skipped, breaking all targets linking
|
||||
# Qt6::Sql / Qt6::Xml / Qt6::Test.)
|
||||
get_filename_component(QT6_LIB_DIR "${Qt6Core_DIR}/../.." ABSOLUTE)
|
||||
get_filename_component(QT6_ARCH_DIR "${QT6_LIB_DIR}" NAME)
|
||||
# The standard layout keeps headers in <prefix>/include; Debian/Ubuntu keeps
|
||||
# them in <prefix>/include/<multiarch>/qt6 — probe the multiarch form first.
|
||||
if(EXISTS "${QT6_LIB_DIR}/../../include/${QT6_ARCH_DIR}/qt6")
|
||||
get_filename_component(QT6_INC_DIR "${QT6_LIB_DIR}/../../include/${QT6_ARCH_DIR}/qt6" ABSOLUTE)
|
||||
else()
|
||||
get_filename_component(QT6_INC_DIR "${QT6_LIB_DIR}/../include" ABSOLUTE)
|
||||
endif()
|
||||
elseif(DEFINED ENV{QT_BASE_DIR} AND DEFINED ENV{QT_VERSION} AND DEFINED ENV{QT_ARCH_DIR})
|
||||
set(QT6_LIB_DIR "$ENV{QT_BASE_DIR}/$ENV{QT_VERSION}/$ENV{QT_ARCH_DIR}/lib")
|
||||
set(QT6_INC_DIR "$ENV{QT_BASE_DIR}/$ENV{QT_VERSION}/$ENV{QT_ARCH_DIR}/include")
|
||||
else()
|
||||
set(QT6_LIB_DIR "/usr/lib/x86_64-linux-gnu")
|
||||
set(QT6_INC_DIR "/usr/include/x86_64-linux-gnu/qt6")
|
||||
endif()
|
||||
|
||||
# Qt6::DBus
|
||||
if(NOT TARGET Qt6::DBus AND EXISTS "${QT6_LIB_DIR}/libQt6DBus.so.6")
|
||||
add_library(Qt6::DBus SHARED IMPORTED)
|
||||
set_target_properties(Qt6::DBus PROPERTIES
|
||||
IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6DBus.so.6"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtDBus;${QT6_INC_DIR}"
|
||||
INTERFACE_LINK_LIBRARIES "Qt6::Core"
|
||||
)
|
||||
endif()
|
||||
|
||||
# Qt6::Gui (needs OpenGL libs, X11, EGL)
|
||||
if(NOT TARGET Qt6::Gui AND EXISTS "${QT6_LIB_DIR}/libQt6Gui.so.6")
|
||||
add_library(Qt6::Gui SHARED IMPORTED)
|
||||
set_target_properties(Qt6::Gui PROPERTIES
|
||||
IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6Gui.so.6"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtGui;${QT6_INC_DIR}"
|
||||
INTERFACE_LINK_LIBRARIES "Qt6::Core;Qt6::DBus;${QT6_LIB_DIR}/libQt6OpenGL.so.6;${QT6_LIB_DIR}/libEGL.so.1;${QT6_LIB_DIR}/libGLX.so.0;${QT6_LIB_DIR}/libX11.so.6;${CMAKE_DL_LIBS};pthread"
|
||||
)
|
||||
endif()
|
||||
|
||||
# Set variable for legacy code that uses ${Qt6_Gui} — like Qt6_Widgets below,
|
||||
# subdirectory CMakeLists contain `set(Qt6_Gui ${Qt6_Gui})` optional-guard
|
||||
# no-ops that keep this root-scope value.
|
||||
if(TARGET Qt6::Gui)
|
||||
set(Qt6_Gui Qt6::Gui)
|
||||
endif()
|
||||
|
||||
# Qt6::Widgets - create manual target (find_package fails without OpenGL)
|
||||
if(EXISTS "${QT6_LIB_DIR}/libQt6Widgets.so.6")
|
||||
if(NOT TARGET Qt6::Widgets)
|
||||
add_library(Qt6::Widgets SHARED IMPORTED)
|
||||
endif()
|
||||
set_target_properties(Qt6::Widgets PROPERTIES
|
||||
IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6Widgets.so.6"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "/usr/include/x86_64-linux-gnu/qt6/QtWidgets;/usr/include/x86_64-linux-gnu/qt6"
|
||||
INTERFACE_LINK_LIBRARIES "Qt6::Core;Qt6::Gui"
|
||||
)
|
||||
# Set variable for legacy code that uses ${Qt6_Widgets}
|
||||
set(Qt6_Widgets Qt6::Widgets)
|
||||
set(QT6_GUI_AVAILABLE TRUE)
|
||||
message(STATUS "Manually configured Qt6 Widgets target")
|
||||
endif()
|
||||
|
||||
# Qt6::Sql - create manual target if not found
|
||||
if(NOT TARGET Qt6::Sql AND EXISTS "${QT6_LIB_DIR}/libQt6Sql.so.6")
|
||||
add_library(Qt6::Sql SHARED IMPORTED)
|
||||
set_target_properties(Qt6::Sql PROPERTIES
|
||||
IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6Sql.so.6"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtSql;${QT6_INC_DIR}"
|
||||
INTERFACE_LINK_LIBRARIES "Qt6::Core"
|
||||
)
|
||||
message(STATUS "Manually configured Qt6 Sql target")
|
||||
endif()
|
||||
|
||||
# Qt6::Xml - create manual target if not found
|
||||
if(NOT TARGET Qt6::Xml AND EXISTS "${QT6_LIB_DIR}/libQt6Xml.so.6")
|
||||
add_library(Qt6::Xml SHARED IMPORTED)
|
||||
set_target_properties(Qt6::Xml PROPERTIES
|
||||
IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6Xml.so.6"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtXml;${QT6_INC_DIR}"
|
||||
INTERFACE_LINK_LIBRARIES "Qt6::Core"
|
||||
)
|
||||
message(STATUS "Manually configured Qt6 Xml target")
|
||||
endif()
|
||||
|
||||
# Qt6::Network - create manual target if not found
|
||||
if(NOT TARGET Qt6::Network AND EXISTS "${QT6_LIB_DIR}/libQt6Network.so.6")
|
||||
add_library(Qt6::Network SHARED IMPORTED)
|
||||
set_target_properties(Qt6::Network PROPERTIES
|
||||
IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6Network.so.6"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtNetwork;${QT6_INC_DIR}"
|
||||
INTERFACE_LINK_LIBRARIES "Qt6::Core"
|
||||
)
|
||||
message(STATUS "Manually configured Qt6 Network target")
|
||||
endif()
|
||||
|
||||
# Qt6::Test - create manual target if not found
|
||||
if(NOT TARGET Qt6::Test AND EXISTS "${QT6_LIB_DIR}/libQt6Test.so.6")
|
||||
add_library(Qt6::Test SHARED IMPORTED)
|
||||
set_target_properties(Qt6::Test PROPERTIES
|
||||
IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6Test.so.6"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtTest;${QT6_INC_DIR}"
|
||||
INTERFACE_LINK_LIBRARIES "Qt6::Core"
|
||||
)
|
||||
message(STATUS "Manually configured Qt6 Test target")
|
||||
endif()
|
||||
|
||||
# Qt6::Multimedia - create manual target if not found
|
||||
if(NOT TARGET Qt6::Multimedia AND EXISTS "${QT6_LIB_DIR}/libQt6Multimedia.so.6")
|
||||
add_library(Qt6::Multimedia SHARED IMPORTED)
|
||||
set_target_properties(Qt6::Multimedia PROPERTIES
|
||||
IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6Multimedia.so.6"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtMultimedia;${QT6_INC_DIR}"
|
||||
INTERFACE_LINK_LIBRARIES "Qt6::Core;Qt6::Gui"
|
||||
)
|
||||
message(STATUS "Manually configured Qt6 Multimedia target")
|
||||
endif()
|
||||
|
||||
# Stub Qt6::Multimedia target if not available (needed by OscSystemGuiPlugin, etc.)
|
||||
if(NOT TARGET Qt6::Multimedia)
|
||||
add_library(Qt6::Multimedia INTERFACE IMPORTED)
|
||||
set_target_properties(Qt6::Multimedia PROPERTIES
|
||||
INTERFACE_COMPILE_DEFINITIONS "QT_NO_MULTIMEDIA"
|
||||
)
|
||||
message(STATUS "Created stub target for Qt6::Multimedia (library not available)")
|
||||
endif()
|
||||
|
||||
# Qt6::Svg - create manual target if not found. Also require the headers:
|
||||
# the container can ship the runtime library (libqt6svg6 via Recommends)
|
||||
# without qt6-svg-dev, and an imported target with a non-existent
|
||||
# INTERFACE_INCLUDE_DIRECTORIES entry fails the CMake generate step for
|
||||
# every Svg consumer. Without headers the stub below is used instead.
|
||||
if(NOT TARGET Qt6::Svg AND EXISTS "${QT6_LIB_DIR}/libQt6Svg.so.6" AND EXISTS "${QT6_INC_DIR}/QtSvg")
|
||||
add_library(Qt6::Svg SHARED IMPORTED)
|
||||
set_target_properties(Qt6::Svg PROPERTIES
|
||||
IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6Svg.so.6"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtSvg;${QT6_INC_DIR}"
|
||||
INTERFACE_LINK_LIBRARIES "Qt6::Core;Qt6::Gui"
|
||||
)
|
||||
message(STATUS "Manually configured Qt6 Svg target")
|
||||
endif()
|
||||
|
||||
# Stub Qt6::Svg target if not available (needed by various plugins)
|
||||
if(NOT TARGET Qt6::Svg)
|
||||
add_library(Qt6::Svg INTERFACE IMPORTED)
|
||||
message(STATUS "Created stub target for Qt6::Svg (library not available)")
|
||||
endif()
|
||||
|
||||
# Qt6::SerialPort - create manual target if not found
|
||||
if(NOT TARGET Qt6::SerialPort AND EXISTS "${QT6_LIB_DIR}/libQt6SerialPort.so.6")
|
||||
add_library(Qt6::SerialPort SHARED IMPORTED)
|
||||
set_target_properties(Qt6::SerialPort PROPERTIES
|
||||
IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6SerialPort.so.6"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtSerialPort;${QT6_INC_DIR}"
|
||||
INTERFACE_LINK_LIBRARIES "Qt6::Core"
|
||||
)
|
||||
message(STATUS "Manually configured Qt6 SerialPort target")
|
||||
endif()
|
||||
|
||||
# Stub Qt6::SerialPort target if not available (needed by TrainingAreaBaseOC)
|
||||
if(NOT TARGET Qt6::SerialPort)
|
||||
add_library(Qt6::SerialPort INTERFACE IMPORTED)
|
||||
set_target_properties(Qt6::SerialPort PROPERTIES
|
||||
INTERFACE_COMPILE_DEFINITIONS "QT_NO_SERIALPORT"
|
||||
)
|
||||
message(STATUS "Created stub target for Qt6::SerialPort (library not available)")
|
||||
endif()
|
||||
|
||||
# Stub Qt6::WebEngineCore target if not available (needed by thp_viewer)
|
||||
if(NOT TARGET Qt6::WebEngineCore)
|
||||
add_library(Qt6::WebEngineCore INTERFACE IMPORTED)
|
||||
set_target_properties(Qt6::WebEngineCore PROPERTIES
|
||||
INTERFACE_COMPILE_DEFINITIONS "QT_NO_WEBENGINE"
|
||||
)
|
||||
message(STATUS "Created stub target for Qt6::WebEngineCore (library not available)")
|
||||
endif()
|
||||
|
||||
# Stub Qt6::WebEngineWidgets target if not available (needed by thp_viewer)
|
||||
if(NOT TARGET Qt6::WebEngineWidgets)
|
||||
add_library(Qt6::WebEngineWidgets INTERFACE IMPORTED)
|
||||
set_target_properties(Qt6::WebEngineWidgets PROPERTIES
|
||||
INTERFACE_COMPILE_DEFINITIONS "QT_NO_WEBENGINE"
|
||||
)
|
||||
message(STATUS "Created stub target for Qt6::WebEngineWidgets (library not available)")
|
||||
endif()
|
||||
|
||||
# Stub Qt6::Core5Compat target if not available (needed by textEditorTest)
|
||||
if(NOT TARGET Qt6::Core5Compat)
|
||||
add_library(Qt6::Core5Compat INTERFACE IMPORTED)
|
||||
set_target_properties(Qt6::Core5Compat PROPERTIES
|
||||
INTERFACE_COMPILE_DEFINITIONS "QT_NO_CORE5COMPAT"
|
||||
)
|
||||
message(STATUS "Created stub target for Qt6::Core5Compat (library not available)")
|
||||
endif()
|
||||
|
||||
# Qt6::WebSockets - create manual target if not found (the container's Qt6
|
||||
# discovery takes the minimal path, so find_package never creates the
|
||||
# component targets). The migrated FileManagement service (THP script
|
||||
# server) needs the real module.
|
||||
if(NOT TARGET Qt6::WebSockets AND EXISTS "${QT6_LIB_DIR}/libQt6WebSockets.so.6")
|
||||
add_library(Qt6::WebSockets SHARED IMPORTED)
|
||||
set_target_properties(Qt6::WebSockets PROPERTIES
|
||||
IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6WebSockets.so.6"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtWebSockets;${QT6_INC_DIR}"
|
||||
INTERFACE_LINK_LIBRARIES "Qt6::Core;Qt6::Network"
|
||||
)
|
||||
set(QT6_WEBSOCKETS_REAL_FOUND TRUE)
|
||||
message(STATUS "Manually configured Qt6 WebSockets target")
|
||||
endif()
|
||||
|
||||
# Stub Qt6::WebSockets target if not available (needed by LtsWebSocket, httq, etc.)
|
||||
if(NOT TARGET Qt6::WebSockets)
|
||||
add_library(Qt6::WebSockets INTERFACE IMPORTED)
|
||||
set_target_properties(Qt6::WebSockets PROPERTIES
|
||||
INTERFACE_COMPILE_DEFINITIONS "QT_NO_WEBSOCKETS"
|
||||
)
|
||||
message(STATUS "Created stub target for Qt6::WebSockets (library not available)")
|
||||
endif()
|
||||
|
||||
# Qt6::PrintSupport - create manual target if not found
|
||||
if(NOT TARGET Qt6::PrintSupport AND EXISTS "${QT6_LIB_DIR}/libQt6PrintSupport.so.6")
|
||||
add_library(Qt6::PrintSupport SHARED IMPORTED)
|
||||
set_target_properties(Qt6::PrintSupport PROPERTIES
|
||||
IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6PrintSupport.so.6"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtPrintSupport;${QT6_INC_DIR}"
|
||||
INTERFACE_LINK_LIBRARIES "Qt6::Core;Qt6::Gui;Qt6::Widgets"
|
||||
)
|
||||
message(STATUS "Manually configured Qt6 PrintSupport target")
|
||||
endif()
|
||||
|
||||
# Stub Qt6::PrintSupport target if not available (needed by textEditorTest, thp_viewer)
|
||||
if(NOT TARGET Qt6::PrintSupport)
|
||||
add_library(Qt6::PrintSupport INTERFACE IMPORTED)
|
||||
set_target_properties(Qt6::PrintSupport PROPERTIES
|
||||
INTERFACE_COMPILE_DEFINITIONS "QT_NO_PRINTSUPPORT"
|
||||
)
|
||||
message(STATUS "Created stub target for Qt6::PrintSupport (library not available)")
|
||||
endif()
|
||||
|
||||
# Qt6::OpenGL - create manual target if not found
|
||||
if(NOT TARGET Qt6::OpenGL AND EXISTS "${QT6_LIB_DIR}/libQt6OpenGL.so.6")
|
||||
add_library(Qt6::OpenGL SHARED IMPORTED)
|
||||
set_target_properties(Qt6::OpenGL PROPERTIES
|
||||
IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6OpenGL.so.6"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtOpenGL;${QT6_INC_DIR}"
|
||||
INTERFACE_LINK_LIBRARIES "Qt6::Core;Qt6::Gui"
|
||||
)
|
||||
message(STATUS "Manually configured Qt6 OpenGL target")
|
||||
endif()
|
||||
|
||||
# Stub Qt6::OpenGL target if not available (needed by PwsGuiPlugin)
|
||||
if(NOT TARGET Qt6::OpenGL)
|
||||
add_library(Qt6::OpenGL INTERFACE IMPORTED)
|
||||
set_target_properties(Qt6::OpenGL PROPERTIES
|
||||
INTERFACE_COMPILE_DEFINITIONS "QT_NO_OPENGL"
|
||||
)
|
||||
message(STATUS "Created stub target for Qt6::OpenGL (library not available)")
|
||||
endif()
|
||||
|
||||
# Set variable for legacy code that uses ${Qt6_WebSockets} — subdirectory
|
||||
# CMakeLists contain `set(Qt6_WebSockets ${Qt6_WebSockets})` optional-guard
|
||||
# no-ops that keep this root-scope value.
|
||||
if(TARGET Qt6::WebSockets)
|
||||
set(Qt6_WebSockets Qt6::WebSockets)
|
||||
endif()
|
||||
|
||||
# The real Qt6 WebSockets module is available (either via find_package or the
|
||||
# manual import above): enable the real websocket code paths in httq,
|
||||
# LtsWebSocket and the migrated services (they check this macro; without it
|
||||
# they fall back to websocket-less operation).
|
||||
if(Qt6WebSockets_FOUND OR QT6_WEBSOCKETS_REAL_FOUND)
|
||||
add_compile_definitions(QT6_WEBSOCKETS_AVAILABLE)
|
||||
endif()
|
||||
|
||||
MESSAGE(STATUS "Qt version is ${Qt6Core_VERSION}, GUI available: ${QT6_GUI_AVAILABLE}")
|
||||
|
||||
#
|
||||
ADD_DEFINITIONS(-DQT_USE_QSTRINGBUILDER)
|
||||
ADD_DEFINITIONS(-DQT_NO_CAST_TO_ASCII)
|
||||
ADD_DEFINITIONS(-DQT_NO_CAST_FROM_ASCII)
|
||||
ADD_DEFINITIONS(-DQT_NO_URL_CAST_FROM_STRING)
|
||||
ADD_DEFINITIONS(-DQT_DEPRECATED_WARNINGS)
|
||||
ADD_DEFINITIONS(-DQT_NO_CAST_FROM_BYTEARRAY)
|
||||
#ADD_DEFINITIONS(-DQT_NO_DEPRECATED)
|
||||
ADD_DEFINITIONS(-DQT_DISABLE_DEPRECATED_BEFORE=0x050900)
|
||||
ADD_DEFINITIONS(-DQT_NO_FOREACH)
|
||||
IF(NOT WIN32)
|
||||
ADD_DEFINITIONS(-DQT_STRICT_ITERATORS)
|
||||
ENDIF()
|
||||
|
||||
#
|
||||
# Ein paar NGL-spezifische Macros
|
||||
#
|
||||
INCLUDE(NGLMacros)
|
||||
|
||||
#
|
||||
# Projektspezifische Einstellungen?
|
||||
#
|
||||
NGL_INSTALL(SV AAR WS FILES lts-cc.conf DESTINATION . RENAME lts-cc.conf.distrib)
|
||||
|
||||
OPTION(GUEZ_MODE "Build for GUEZ " ON)
|
||||
IF(GUEZ_MODE)
|
||||
ADD_DEFINITIONS(-DGUEZ_MODE)
|
||||
ENDIF()
|
||||
|
||||
#
|
||||
# Doxygen
|
||||
#
|
||||
INCLUDE(DoxygenMacros)
|
||||
IF(NOT DOXYGEN_OUT_DIR)
|
||||
SET(DOXYGEN_OUT_DIR ${CMAKE_BINARY_DIR}/doxygen)
|
||||
ENDIF()
|
||||
ADD_DOXYGEN_TARGET(TDS ${CMAKE_SOURCE_DIR}/doxygen/Doxyfile.in ${CMAKE_BINARY_DIR}/Doxyfile
|
||||
${CMAKE_SOURCE_DIR}/doxygen/rheinmetall_defence_logo.jpg
|
||||
${DOXYGEN_OUT_DIR})
|
||||
|
||||
IF(NOT DOXYGEN_OUT_DIR_2025)
|
||||
SET(DOXYGEN_OUT_DIR_2025 ${CMAKE_BINARY_DIR}/doxygen2025)
|
||||
ENDIF()
|
||||
ADD_DOXYGEN_TARGET(TDS2025 ${CMAKE_SOURCE_DIR}/doxygen/Doxyfile2025.in ${CMAKE_BINARY_DIR}/Doxyfile
|
||||
${CMAKE_SOURCE_DIR}/doxygen/rheinmetall_defence_logo.jpg
|
||||
${DOXYGEN_OUT_DIR_2025})
|
||||
|
||||
#
|
||||
# Compilerflags
|
||||
#
|
||||
IF(WIN32)
|
||||
ADD_DEFINITIONS(-DWIN32 -D_USE_MATH_DEFINES -D_WIN32_WINNT=0x0501 -DUNICODE)
|
||||
ELSE()
|
||||
ADD_DEFINITIONS(-D_LINUX)
|
||||
ENDIF()
|
||||
|
||||
IF(MSVC)
|
||||
# C4250: 'class1' : inherits 'class2::member' via dominance
|
||||
# C4251: 'identifier' : class 'type' needs to have dll-interface to be used by clients of class 'type2'
|
||||
# C4290: C++ exception specification ignored except to indicate a function is not __declspec(nothrow)
|
||||
# C4496: 'function': was declared deprecated
|
||||
# C4267: 'var' : conversion from 'size_t' to 'type', possible loss of data
|
||||
ADD_DEFINITIONS(-wd4250
|
||||
-wd4251
|
||||
-wd4290
|
||||
-wd4496
|
||||
-wd4267
|
||||
-D_CRT_SECURE_NO_DEPRECATE
|
||||
-D_CRT_NONSTDC_NO_DEPRECATE
|
||||
-D_SCL_SECURE_NO_WARNINGS
|
||||
-D_WINSOCK_DEPRECATED_NO_WARNINGS
|
||||
/bigobj
|
||||
)
|
||||
# komplette Programmoptimierung
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP")
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
|
||||
# .pdb - Datei nicht gefunden
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /IGNORE:4099")
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /IGNORE:4099")
|
||||
# min() und max() nicht als Macros
|
||||
ADD_DEFINITIONS(-DNOMINMAX)
|
||||
SET(CMAKE_MSVCIDE_RUN_PATH "" CACHE PATH "Run path to use when starting programs from MSVC")
|
||||
ENDIF()
|
||||
|
||||
IF(UNIX)
|
||||
# Alle Warnungen aktivieren
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra -Wmissing-include-dirs")
|
||||
# disable
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-overloaded-virtual")
|
||||
IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
IF(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8.0)
|
||||
MESSAGE(FATAL_ERROR "gcc 4.8 or higher is required to build TDS: ${CMAKE_CXX_COMPILER_VERSION}")
|
||||
ENDIF()
|
||||
IF(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.9.99)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-strict-aliasing")
|
||||
# SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsuggest-attribute=const")
|
||||
# SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsuggest-final-types")
|
||||
# SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsuggest-final-methods")
|
||||
# SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsuggest-override")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
OPTION(USE_IPO "Use interprocedural optimizations (cmake 3.9 or higher required)" OFF)
|
||||
IF (USE_IPO AND CMAKE_VERSION VERSION_GREATER 3.8.9)
|
||||
INCLUDE(CheckIPOSupported)
|
||||
check_ipo_supported(RESULT result OUTPUT output)
|
||||
IF(result)
|
||||
SET(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||
ELSE()
|
||||
MESSAGE(WARNING "IPO is not supported: ${output}")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
OPTION(USE_ASAN "Use Address Sanitizer (current Clang only)" OFF)
|
||||
IF (USE_ASAN)
|
||||
IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
MESSAGE(STATUS "enable Address Sanitizer with Clang (is: ${CMAKE_CXX_COMPILER_ID})")
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-optimize-sibling-calls -fsanitize-address-use-after-scope -fno-omit-frame-pointer -g -O1")
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-optimize-sibling-calls -fsanitize-address-use-after-scope -fno-omit-frame-pointer -g -O1")
|
||||
ELSE()
|
||||
MESSAGE(STATUS "Address Sanitizer only supported with Clang (is: ${CMAKE_CXX_COMPILER_ID})")
|
||||
ENDIF()
|
||||
ENDIF(USE_ASAN)
|
||||
|
||||
OPTION(USE_UBSAN "Use UndefinedBehavior Sanitizer (current Clang only)" OFF)
|
||||
IF (USE_UBSAN)
|
||||
IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined")
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined")
|
||||
ELSE()
|
||||
MESSAGE(STATUS "UndefinedBehavior only supported with Clang (is: ${CMAKE_CXX_COMPILER_ID})")
|
||||
ENDIF()
|
||||
ENDIF(USE_UBSAN)
|
||||
|
||||
OPTION(BUILD_RPM "Build a RPM - install script in scripts subdir" OFF)
|
||||
|
||||
# Build component options for NGL_ADD_LIBRARY
|
||||
OPTION(BUILD_ALL "Build all components" ON)
|
||||
OPTION(BUILD_SV "Build SV component" ON)
|
||||
OPTION(BUILD_WS "Build WS component" ON)
|
||||
OPTION(BUILD_AAR "Build AAR component" ON)
|
||||
OPTION(BUILD_TOOLSWS "Build TOOLSWS component" ON)
|
||||
OPTION(BUILD_TOOLSSV "Build TOOLSSV component" ON)
|
||||
OPTION(BUILD_HLA "Build HLA component" ON)
|
||||
|
||||
# If BUILD_ALL is ON, enable all individual component flags
|
||||
IF(BUILD_ALL)
|
||||
SET(BUILD_SV ON CACHE BOOL "Build SV component" FORCE)
|
||||
SET(BUILD_WS ON CACHE BOOL "Build WS component" FORCE)
|
||||
SET(BUILD_AAR ON CACHE BOOL "Build AAR component" FORCE)
|
||||
SET(BUILD_TOOLSWS ON CACHE BOOL "Build TOOLSWS component" FORCE)
|
||||
SET(BUILD_TOOLSSV ON CACHE BOOL "Build TOOLSSV component" FORCE)
|
||||
SET(BUILD_HLA ON CACHE BOOL "Build HLA component" FORCE)
|
||||
ENDIF()
|
||||
|
||||
IF(BUILD_RPM)
|
||||
ADD_SUBDIRECTORY(scripts)
|
||||
ELSE()
|
||||
ADD_DEFINITIONS(-DLTS_DEBUG)
|
||||
ENDIF()
|
||||
|
||||
IF (NOT DEFINED _pname)
|
||||
IF(GUEZ_MODE)
|
||||
SET (_pname "guez")
|
||||
ADD_DEFINITIONS(-DPROJECTBUILD="guez")
|
||||
MESSAGE(STATUS "NO ProjectName givin! BUT GUEZ_MODE set PROJECTBUILD to guez")
|
||||
ELSE()
|
||||
MESSAGE(WARNING "NO ProjectName givin! Can't install coresponding lts-cc.conf! and PROJECTBUILD is empty")
|
||||
ADD_DEFINITIONS(-DPROJECTBUILD="")
|
||||
ENDIF()
|
||||
ELSE()
|
||||
MESSAGE(STATUS "ProjectName givin! PROJECTBUILD is ${_pname} ")
|
||||
ADD_DEFINITIONS(-DPROJECTBUILD=\"${_pname}\")
|
||||
ENDIF()
|
||||
|
||||
|
||||
# Release scope: always build only TetraIF, Z/src, and Lts/Common
|
||||
# (TrainingAreaBase is included via Lts/Proxies when Lts is processed)
|
||||
NGL_ADD_SUBDIR_GUARDED(TetraIF)
|
||||
NGL_ADD_SUBDIR_GUARDED(Z/src)
|
||||
NGL_ADD_SUBDIR_GUARDED(Lts)
|
||||
|
||||
# at last, to make sure we get all targets in NGL_TS_TARGETS property
|
||||
NGL_ADD_SUBDIR_GUARDED(translations)
|
||||
#-----------------------------------------------------------------------------------------------------
|
||||
@@ -1,2 +0,0 @@
|
||||
# Minimal CTestCustom.ctest placeholder
|
||||
# Created to satisfy top-level CMake configure step
|
||||
@@ -1,47 +0,0 @@
|
||||
# Prebuilt build image for the release validation-scope branch
|
||||
# (Ubuntu 26.04 + Qt6 + all dependencies for the legatus release build).
|
||||
#
|
||||
# Built by new_docker_build.sh --build-prebuilt-image, which passes the
|
||||
# package list and Qt settings as build args (see build_prebuilt_image()).
|
||||
|
||||
FROM ubuntu:26.04
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
ARG APT_PACKAGES
|
||||
ARG QT_VERSION=6.10.2
|
||||
ARG QT_ARCH=linux_gcc_64
|
||||
ARG QT_BASE_DIR=/opt/Qt
|
||||
|
||||
RUN apt-get update -qq && \
|
||||
apt-get install -y -qq \
|
||||
${APT_PACKAGES} \
|
||||
libqt6svg6-dev \
|
||||
libgtest-dev \
|
||||
libgmock-dev \
|
||||
python3-pip && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install Qt6 packages via aqtinstall
|
||||
RUN pip3 install --break-system-packages --quiet aqtinstall && \
|
||||
aqt install-qt linux desktop ${QT_VERSION} ${QT_ARCH} \
|
||||
-m qtmultimedia qtserialport qtimageformats qtwebsockets qtwebengine \
|
||||
qtpdf qtwebview qt5compat qtwebchannel qtpositioning qtlocation qtsensors \
|
||||
--outputdir ${QT_BASE_DIR} && \
|
||||
rm -rf /root/.cache/Aqt
|
||||
|
||||
# Install KDReports from source (apt package not available in Ubuntu 22.04/26.04)
|
||||
# Try apt install first (will fail), then build from KDAB GitHub mirror
|
||||
RUN apt-get install -y -qq libkdreports-dev 2>/dev/null || \
|
||||
(git clone --depth 1 https://github.com/KDAB/KDReports.git /tmp/KDReports && \
|
||||
cd /tmp/KDReports && \
|
||||
mkdir build && cd build && \
|
||||
cmake -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_PREFIX_PATH=${QT_BASE_DIR} .. && \
|
||||
make -j$(nproc) && \
|
||||
make install && \
|
||||
cd / && rm -rf /tmp/KDReports)
|
||||
|
||||
# Legacy sources include <KDReports/...>
|
||||
RUN ln -sfn KDReports-qt6 /usr/local/include/KDReports
|
||||
|
||||
CMD ["/bin/bash"]
|
||||
@@ -1,35 +0,0 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(LtsPlaceholder)
|
||||
SET(DOXYGEN_OUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/doxygen_Lts)
|
||||
if (EXISTS "${CMAKE_SOURCE_DIR}/doxygen/DoxyfileLts.in")
|
||||
ADD_DOXYGEN_TARGET(Lts ${CMAKE_SOURCE_DIR}/doxygen/DoxyfileLts.in ${CMAKE_BINARY_DIR}/DoxyfileLts
|
||||
${CMAKE_SOURCE_DIR}/doxygen/rheinmetall_defence_logo.jpg
|
||||
${DOXYGEN_OUT_DIR})
|
||||
else()
|
||||
message(WARNING "Doxygen config ${CMAKE_SOURCE_DIR}/doxygen/DoxyfileLts.in not found; skipping ADD_DOXYGEN_TARGET(Lts)")
|
||||
endif()
|
||||
|
||||
# Release scope: only build Lts/Common and Lts/Proxies/TrainingAreaBase (tabTelegrams library)
|
||||
# Excludes: Tools, Application, DDS, Services, most of Proxies, Plugins, Viewer, Projects
|
||||
message(STATUS "Building Lts/Common and Lts/Proxies/TrainingAreaBase")
|
||||
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/Common")
|
||||
NGL_ADD_SUBDIR_GUARDED(Common)
|
||||
else()
|
||||
message(STATUS "Skipping missing Lts subdirectory: Common")
|
||||
endif()
|
||||
# TrainingAreaBase provides tabTelegrams library needed by TetraIF/CoPrtCnv
|
||||
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/Proxies/TrainingAreaBase")
|
||||
NGL_ADD_SUBDIR_GUARDED(Proxies/TrainingAreaBase)
|
||||
else()
|
||||
message(STATUS "Skipping missing Lts subdirectory: Proxies/TrainingAreaBase")
|
||||
endif()
|
||||
|
||||
# Export headers included by bare name from module sources (release scope)
|
||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../include/NGLLogger/)
|
||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../include/LtsUtilsGuiDds/)
|
||||
@@ -1,25 +0,0 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
|
||||
# Core modules needed for TetraIF and Z
|
||||
ADD_SUBDIRECTORY(CommonUnitTestsPlaceholder)
|
||||
ADD_SUBDIRECTORY(httq)
|
||||
ADD_SUBDIRECTORY(LtsAppDescriptor)
|
||||
ADD_SUBDIRECTORY(LtsCommandLineParser)
|
||||
ADD_SUBDIRECTORY(LtsCoordTrans)
|
||||
ADD_SUBDIRECTORY(LtsLicence)
|
||||
ADD_SUBDIRECTORY(LtsNotification)
|
||||
ADD_SUBDIRECTORY(LtsRestClient)
|
||||
ADD_SUBDIRECTORY(LtsSerialPortQuerry)
|
||||
# Excluded: LtsTimeline (depends on LtsWidgets which has DDS dependencies)
|
||||
ADD_SUBDIRECTORY(LtsUtils)
|
||||
ADD_SUBDIRECTORY(LtsWebSocket)
|
||||
ADD_SUBDIRECTORY(PluginInterfaces)
|
||||
ADD_SUBDIRECTORY(ProjectConfig)
|
||||
# Excluded: CodeGen, LtsAppManager, LtsBotan, LtsCoordinate, LtsElevation, LtsLogin,
|
||||
# LtsMultiMonitor, LtsPluginManager, LtsPrinting, LtsProjectionWorkstation,
|
||||
# LtsScriptTimeline, LtsSession, LtsTimelineClassic, LtsVirtualKeyboard, LtsWidgets,
|
||||
# TopicEditorBase
|
||||
@@ -1,34 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(CommonUnitTestsPlaceholder)
|
||||
|
||||
include(FetchContent)
|
||||
|
||||
option(BUILD_SMOKE_TESTS "Build QtTest smoke tests" OFF)
|
||||
option(BUILD_GTEST_SMOKE "Build GTest smoke tests" OFF)
|
||||
|
||||
add_subdirectory(mocks)
|
||||
|
||||
if(BUILD_SMOKE_TESTS)
|
||||
if(NOT TARGET Qt6::Test)
|
||||
find_package(Qt6 REQUIRED COMPONENTS Test)
|
||||
endif()
|
||||
add_executable(coordTransTests_smoke coordTransTests_smoke.cpp)
|
||||
target_link_libraries(coordTransTests_smoke PRIVATE Qt6::Test MockCoordTrans::MockCoordTrans)
|
||||
add_test(NAME coordTransTests_smoke COMMAND coordTransTests_smoke)
|
||||
endif()
|
||||
|
||||
if(BUILD_GTEST_SMOKE)
|
||||
find_package(GTest QUIET)
|
||||
if(NOT GTest_FOUND)
|
||||
FetchContent_Declare(
|
||||
googletest
|
||||
GIT_REPOSITORY https://github.com/google/googletest.git
|
||||
GIT_TAG release-1.12.1
|
||||
)
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
FetchContent_MakeAvailable(googletest)
|
||||
endif()
|
||||
add_executable(coordTransTests_gtest coordTransTests_gtest.cpp)
|
||||
target_link_libraries(coordTransTests_gtest PRIVATE GTest::gtest_main MockCoordTrans::MockCoordTrans)
|
||||
add_test(NAME coordTransTests_gtest COMMAND coordTransTests_gtest)
|
||||
endif()
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
TEST(CoordTransSmokeTest, StubTest)
|
||||
{
|
||||
EXPECT_TRUE(true);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
|
||||
#include <QTest>
|
||||
|
||||
class CoordTransSmokeTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
void stubTest() { QVERIFY(true); }
|
||||
};
|
||||
|
||||
QTEST_APPLESS_MAIN(CoordTransSmokeTest)
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
add_library(MockCoordTrans STATIC MockCoordTrans.h)
|
||||
target_include_directories(MockCoordTrans PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
# Export header-only semantics by providing an interface target
|
||||
add_library(MockCoordTrans::MockCoordTrans ALIAS MockCoordTrans)
|
||||
-19
@@ -1,19 +0,0 @@
|
||||
|
||||
#ifndef MOCK_COORD_TRANS_H
|
||||
#define MOCK_COORD_TRANS_H
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QPointF>
|
||||
|
||||
// Minimal stub to satisfy linker requirements
|
||||
namespace LtsCoordTrans
|
||||
{
|
||||
// Placeholder types
|
||||
struct UtmCoordinate
|
||||
{
|
||||
static UtmCoordinate fromMgrs(const QString &) { return UtmCoordinate(); }
|
||||
QPointF geographic() const { return QPointF(); }
|
||||
};
|
||||
}
|
||||
|
||||
#endif // MOCK_COORD_TRANS_H
|
||||
@@ -1,65 +0,0 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
# Created by Mike Wille, SLSE, 2016-10-24
|
||||
#
|
||||
|
||||
|
||||
# LtsAppDescriptor (lib)
|
||||
# Make ${Qt6_Widgets} optional
|
||||
if(QT6_GUI_AVAILABLE AND TARGET Qt6::Widgets)
|
||||
set(Qt6_Widgets ${Qt6_Widgets})
|
||||
else()
|
||||
set(Qt6_Widgets "")
|
||||
endif()
|
||||
|
||||
|
||||
SET(LtsAppDescriptor_SRCS
|
||||
lts_app_descriptor.cpp
|
||||
lts_app_descriptor.h
|
||||
)
|
||||
|
||||
NGL_ADD_LIBRARY2(WS LtsAppDescriptor SHARED ${LtsAppDescriptor_SRCS})
|
||||
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(LtsAppDescriptor
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../
|
||||
)
|
||||
|
||||
NGL_TARGET_LINK_LIBRARIES(LtsAppDescriptor
|
||||
PUBLIC
|
||||
Qt6::Core
|
||||
)
|
||||
|
||||
NGL_INSTALL_TARGET(LtsAppDescriptor)
|
||||
|
||||
# LtsAppDescriptorChecker
|
||||
SET(LtsAppDescriptorChecker_SRCS
|
||||
checker/main.cpp
|
||||
)
|
||||
|
||||
NGL_ADD_EXECUTABLE(WS LtsAppDescriptorChecker ${LtsAppDescriptorChecker_SRCS})
|
||||
|
||||
NGL_TARGET_LINK_LIBRARIES(LtsAppDescriptorChecker
|
||||
PRIVATE
|
||||
LtsAppDescriptor
|
||||
PUBLIC
|
||||
Qt6::Core
|
||||
)
|
||||
|
||||
if(QT6_GUI_AVAILABLE)
|
||||
#NGL_TARGET_LINK_LIBRARIES(LtsAppDescriptorEditor
|
||||
# PUBLIC
|
||||
# Qt6::Core
|
||||
# ${Qt6_Widgets}
|
||||
# LtsAppDescriptor
|
||||
#)
|
||||
endif()
|
||||
|
||||
#NGL_INSTALL_TARGET(LtsAppDescriptorEditor) #not visible for end-user
|
||||
|
||||
## Executable:
|
||||
#NGL_ADD_EXECUTABLE(WS NO_TRANSLATION LtsAppDescriptorEditorApp main.cpp)
|
||||
#NGL_TARGET_LINK_LIBRARIES(LtsAppDescriptorEditorApp LtsAppDescriptorEditor)
|
||||
@@ -1,116 +0,0 @@
|
||||
#include <LtsAppDescriptor/lts_app_descriptor.h>
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QDirIterator>
|
||||
#include <QtCore/QFile>
|
||||
#include <QFileInfoList>
|
||||
#include <QtCore/QRegularExpression>
|
||||
#include <QtCore/QRegularExpressionMatch>
|
||||
#include <QtCore/QTextStream>
|
||||
#include <cstdio>
|
||||
#include <utility>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QCoreApplication a(argc, argv);
|
||||
|
||||
const QStringList args(a.arguments());
|
||||
|
||||
if (args.count() != 3)
|
||||
{
|
||||
printf("usage: %s <current source directory> <apps.json>\n", args.at(0).toStdString().c_str());
|
||||
return -1;
|
||||
}
|
||||
|
||||
const QString currentSrcDir(a.arguments().at(1));
|
||||
|
||||
const QString appsJsonFilePath(QStringLiteral("%1/%2").arg(currentSrcDir, a.arguments().at(2)));
|
||||
QFile f(appsJsonFilePath);
|
||||
|
||||
if (!f.open(QFile::ReadOnly))
|
||||
{
|
||||
printf("LtsAppDescriptorChecker: cannot open apps.json at %s: %s\n", appsJsonFilePath.toStdString().c_str(), f.errorString().toStdString().c_str());
|
||||
return -2;
|
||||
}
|
||||
|
||||
printf("LtsAppDescriptorChecker: checking %s\n", appsJsonFilePath.toStdString().c_str());
|
||||
|
||||
QStringList lastErrors;
|
||||
QStringList dummy1;
|
||||
QString dummy2;
|
||||
LtsAppDescriptor::AppDescriptionVector adv = LtsAppDescriptor::LtsAppDescriptor::getAppDescriptionVector(f.readAll(), lastErrors, dummy1, dummy2);
|
||||
|
||||
if (!lastErrors.isEmpty())
|
||||
{
|
||||
printf("LtsAppDescriptorChecker: apps.json at %s invalid:\n%s\n",
|
||||
appsJsonFilePath.toStdString().c_str(),
|
||||
lastErrors.join(QStringLiteral("\r\n\r\n")).toStdString().c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
QFileInfoList guiPluginFiles;
|
||||
QDirIterator it(QStringLiteral("%1/../../Plugins/").arg(currentSrcDir), QDirIterator::Subdirectories);
|
||||
|
||||
while (it.hasNext())
|
||||
{
|
||||
QString filename(it.next());
|
||||
QFileInfo file(filename);
|
||||
|
||||
if (file.isDir())
|
||||
continue;
|
||||
|
||||
if (file.fileName().endsWith(QStringLiteral("_gui_plugin.h"), Qt::CaseInsensitive))
|
||||
guiPluginFiles.append(file);
|
||||
}
|
||||
|
||||
QStringList filenames;
|
||||
filenames.reserve(guiPluginFiles.size());
|
||||
for (const QFileInfo &fi : std::as_const(guiPluginFiles))
|
||||
{
|
||||
filenames += fi.absoluteFilePath();
|
||||
}
|
||||
|
||||
QStringList guiPluginIIDs;
|
||||
for (const QFileInfo &fi : std::as_const(guiPluginFiles))
|
||||
{
|
||||
QFile f2(fi.absoluteFilePath());
|
||||
|
||||
if (!f2.open(QFile::ReadOnly))
|
||||
continue;
|
||||
|
||||
QTextStream ts(&f2);
|
||||
while (!ts.atEnd())
|
||||
{
|
||||
QString line(ts.readLine().trimmed().simplified());
|
||||
static QString iidIdentifier(QStringLiteral("Q_PLUGIN_METADATA"));
|
||||
|
||||
if (line.contains(iidIdentifier))
|
||||
{
|
||||
QRegularExpression re(QStringLiteral("(?<=gui:3:).*(?=\"\\))"));
|
||||
QRegularExpressionMatch match = re.match(line);
|
||||
if (match.hasMatch())
|
||||
{
|
||||
QString matched = match.captured(0);
|
||||
|
||||
guiPluginIIDs += matched;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ok = true;
|
||||
|
||||
for (const LtsAppDescriptor::AppDescription &appdesc : std::as_const(adv))
|
||||
{
|
||||
for (const LtsAppDescriptor::PluginInfo &pi : std::as_const(appdesc.pluginInfos))
|
||||
{
|
||||
if (!guiPluginIIDs.contains(pi.iid))
|
||||
{
|
||||
printf("LtsAppDescriptorChecker: apps.json at '%s' uses unknown IID '%s'\n", appsJsonFilePath.toStdString().c_str(), pi.iid.toStdString().c_str());
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return !ok;
|
||||
}
|
||||
@@ -1,200 +0,0 @@
|
||||
|
||||
|
||||
#include "lts_app_descriptor.h"
|
||||
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtCore/QJsonArray>
|
||||
#include <QtCore/QJsonDocument>
|
||||
#include <QtCore/QJsonObject>
|
||||
#include <QJsonParseError>
|
||||
#include <QtCore/QJsonValue>
|
||||
|
||||
namespace LtsAppDescriptor
|
||||
{
|
||||
static void addOptionToPlugin(PluginInfo &pluginInfo, const PluginInfo::Flag &flag)
|
||||
{
|
||||
pluginInfo.flags |= flag;
|
||||
}
|
||||
|
||||
static void addOptionToPlugin(QVector<PluginInfo> &pluginInfos, const PluginInfo::Flag &flag, const QString &pluginName)
|
||||
{
|
||||
for (PluginInfo &pi : pluginInfos)
|
||||
{
|
||||
if (pi.iid == pluginName)
|
||||
{
|
||||
addOptionToPlugin(pi, flag);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
PluginInfo pi;
|
||||
pi.iid = pluginName;
|
||||
pi.type = PluginInfo::PluginType::GUI;
|
||||
addOptionToPlugin(pi, flag);
|
||||
pluginInfos.append(pi);
|
||||
}
|
||||
|
||||
static bool addOptionsToPlugin(AppDescription &appDesc,
|
||||
const QString &optionIdentifier,
|
||||
const QStringList &ignoredPlugins,
|
||||
const QJsonObject &optionsObject,
|
||||
const PluginInfo::Flag flag,
|
||||
QStringList &lastErrors,
|
||||
bool atLeastOnePluginNeeded)
|
||||
{
|
||||
bool hasPlugins = false;
|
||||
auto optionsObjectIt = optionsObject.constFind(optionIdentifier);
|
||||
if (optionsObjectIt != optionsObject.constEnd())
|
||||
{
|
||||
const QJsonArray plugins((*optionsObjectIt).toObject()[QStringLiteral("Plugins")].toArray());
|
||||
|
||||
for (const auto &pluginElem : plugins)
|
||||
{
|
||||
const QString pluginName = pluginElem.toString();
|
||||
if (!ignoredPlugins.contains(pluginName))
|
||||
{
|
||||
addOptionToPlugin(appDesc.pluginInfos, flag, pluginName);
|
||||
hasPlugins = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (atLeastOnePluginNeeded && !hasPlugins)
|
||||
{
|
||||
lastErrors.append(QCoreApplication::tr("No plugins specified for '%1' option for app '%2'").arg(optionIdentifier, appDesc.appName));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
App LtsAppDescriptor::appFromInteger(int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case int(App::Login):
|
||||
case int(App::Situation):
|
||||
case int(App::ResourceManager):
|
||||
case int(App::PlanEditor):
|
||||
case int(App::BuildingViewer):
|
||||
case int(App::OC):
|
||||
case int(App::OrgChart):
|
||||
case int(App::Scripts):
|
||||
|
||||
case int(App::Snapshot):
|
||||
case int(App::SystemMonitor):
|
||||
case int(App::Timeline):
|
||||
case int(App::SymbolEditor):
|
||||
case int(App::ScriptEditorEssentialsView):
|
||||
case int(App::BaseDownloader):
|
||||
case int(App::OnlineHelp):
|
||||
case int(App::ThpSituationReplay):
|
||||
case int(App::SituationTablet):
|
||||
case int(App::SilhouetteEditor):
|
||||
case int(App::Shootback):
|
||||
case int(App::SAAs):
|
||||
return static_cast<App>(i);
|
||||
}
|
||||
Q_ASSERT_X(false, "LtsAppDescriptor::appFromInteger", qPrintable(QStringLiteral("Unknown app id: %1").arg(i)));
|
||||
return App::Login;
|
||||
}
|
||||
|
||||
AppDescriptionVector LtsAppDescriptor::getAppDescriptionVector(const QByteArray &jsonDocument,
|
||||
QStringList &lastErrors,
|
||||
const QStringList &ignoredPlugins,
|
||||
QString &loginPluginIid)
|
||||
{
|
||||
|
||||
AppDescriptionVector appDescriptions;
|
||||
|
||||
QJsonParseError parseError;
|
||||
QJsonDocument appsDoc(QJsonDocument::fromJson(jsonDocument, &parseError));
|
||||
|
||||
if (parseError.error != QJsonParseError::NoError)
|
||||
{
|
||||
|
||||
int row = 0;
|
||||
int column = 0;
|
||||
QChar x = QLatin1Char('\n');
|
||||
|
||||
for (int i = 0; i < jsonDocument.size(); i++)
|
||||
{
|
||||
if (i == parseError.offset)
|
||||
break;
|
||||
|
||||
if (QChar::fromLatin1(jsonDocument[i]) == x)
|
||||
{
|
||||
row++;
|
||||
column = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
column++;
|
||||
}
|
||||
}
|
||||
|
||||
lastErrors.append(QCoreApplication::tr("JSON: %1<br>Row: %2, Column: %3").arg(parseError.errorString()).arg(row + 1).arg(column + 1));
|
||||
return appDescriptions;
|
||||
}
|
||||
|
||||
const QJsonObject root(appsDoc.object());
|
||||
|
||||
loginPluginIid = root[QStringLiteral("LoginPlugin")].toString();
|
||||
|
||||
const QJsonArray appArray(root[QStringLiteral("Apps")].toArray());
|
||||
if (appArray.isEmpty())
|
||||
{
|
||||
lastErrors.append(QCoreApplication::tr("Invalid json: Could not find 'Apps' array"));
|
||||
return appDescriptions;
|
||||
}
|
||||
|
||||
for (const auto &appElem : appArray)
|
||||
{
|
||||
AppDescription appDesc;
|
||||
const QJsonObject appObject = appElem.toObject();
|
||||
|
||||
appDesc.id = appFromInteger(appObject.value(QStringLiteral("Id")).toInt(-1));
|
||||
if (appDesc.id == App::Login)
|
||||
{
|
||||
lastErrors.append(QCoreApplication::tr("App '%1': no App Id or invalid App Id given").arg(appDesc.appName));
|
||||
return appDescriptions;
|
||||
}
|
||||
|
||||
appDesc.appName = appObject.value(QStringLiteral("AppName")).toString();
|
||||
|
||||
const QJsonValue valueActive = appObject.value(QStringLiteral("Active"));
|
||||
if (!valueActive.isUndefined())
|
||||
{
|
||||
if (valueActive.type() != QJsonValue::Type::Bool)
|
||||
{
|
||||
lastErrors.append(QCoreApplication::tr("App '%1': value App.Active is not a bool (%2)").arg(appDesc.appName).arg((int)valueActive.type()));
|
||||
return appDescriptions;
|
||||
}
|
||||
}
|
||||
appDesc.active = valueActive.toBool(false);
|
||||
|
||||
const QJsonValue valueVisible = appObject.value(QStringLiteral("Visible"));
|
||||
if (!valueVisible.isUndefined() && valueVisible.type() != QJsonValue::Type::Bool)
|
||||
{
|
||||
lastErrors.append(QCoreApplication::tr("App '%1': value App.Visible is not a bool (%2)").arg(appDesc.appName).arg((int)valueVisible.type()));
|
||||
return appDescriptions;
|
||||
}
|
||||
appDesc.visible = valueVisible.toBool(true);
|
||||
|
||||
const QJsonArray array(appObject.value(QStringLiteral("ACLs")).toArray());
|
||||
for (const QJsonValue &value : array)
|
||||
appDesc.requiredAcls.append(value.toInt());
|
||||
|
||||
const QJsonObject optionsObject(appObject.value(QStringLiteral("Options")).toObject());
|
||||
|
||||
addOptionsToPlugin(appDesc, QStringLiteral("Payloads"), ignoredPlugins, optionsObject, PluginInfo::Flag::PAYLOAD, lastErrors, false);
|
||||
addOptionsToPlugin(appDesc, QStringLiteral("Actions"), ignoredPlugins, optionsObject, PluginInfo::Flag::ACTIONS, lastErrors, true);
|
||||
addOptionsToPlugin(appDesc, QStringLiteral("Main"), ignoredPlugins, optionsObject, PluginInfo::Flag::MAIN, lastErrors, false);
|
||||
|
||||
appDescriptions.append(appDesc);
|
||||
}
|
||||
|
||||
return appDescriptions;
|
||||
}
|
||||
|
||||
} // namespace LtsAppDescriptor
|
||||
@@ -1,106 +0,0 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* App Descriptor - Class to modify App Descriptor JSON Documents
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*
|
||||
* Created by Mike Wille, SLSE, 2016-10-24
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QVector>
|
||||
#include <QStringList>
|
||||
|
||||
#ifndef LTSAPPDESCRIPTOR_EXPORT
|
||||
#ifdef BUILD_STATIC_LIBRARIES
|
||||
#define LTSAPPDESCRIPTOR_EXPORT
|
||||
#else
|
||||
#if defined(MAKE_LTSAPPDESCRIPTOR_LIB)
|
||||
#define LTSAPPDESCRIPTOR_EXPORT Q_DECL_EXPORT
|
||||
#else
|
||||
#define LTSAPPDESCRIPTOR_EXPORT Q_DECL_IMPORT
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
namespace LtsAppDescriptor
|
||||
{
|
||||
|
||||
enum class App
|
||||
{
|
||||
Login = -1,
|
||||
Situation = 0,
|
||||
ResourceManager = 1,
|
||||
PlanEditor = 2,
|
||||
BuildingViewer = 3,
|
||||
OC = 4,
|
||||
OrgChart = 5,
|
||||
Scripts = 6,
|
||||
// merged into Scripts (aka. ScriptEditor) ScriptPlayer = 7,
|
||||
Snapshot = 8,
|
||||
SystemMonitor = 9,
|
||||
Timeline = 10,
|
||||
SymbolEditor = 11,
|
||||
ScriptEditorEssentialsView = 12,
|
||||
BaseDownloader = 13,
|
||||
OnlineHelp = 14,
|
||||
ThpSituationReplay = 15,
|
||||
SituationTablet = 17,
|
||||
SilhouetteEditor = 18, // for L400P2
|
||||
Shootback = 19, // for L400P2
|
||||
SAAs = 20, //Schnittstelle Adapter Adler
|
||||
};
|
||||
|
||||
struct PluginInfo
|
||||
{
|
||||
enum class PluginType
|
||||
{
|
||||
UNKNOWN,
|
||||
DATA,
|
||||
GUI,
|
||||
GUI_ELEMENT,
|
||||
};
|
||||
|
||||
enum class Flag
|
||||
{
|
||||
UNKNOWN = 1 << 0,
|
||||
ACTIONS = 1 << 1,
|
||||
MAIN = 1 << 2,
|
||||
PAYLOAD = 1 << 3,
|
||||
OPTION = 1 << 4,
|
||||
};
|
||||
|
||||
PluginType type = PluginType::UNKNOWN;
|
||||
QString iid;
|
||||
QFlags<Flag> flags;
|
||||
QStringList options;
|
||||
};
|
||||
|
||||
struct AppDescription
|
||||
{
|
||||
App id = App::Login;
|
||||
bool active = false;
|
||||
bool visible = true;
|
||||
QString appName;
|
||||
QVector<int> requiredAcls;
|
||||
QVector<PluginInfo> pluginInfos;
|
||||
|
||||
bool isValid() const { return !appName.isEmpty(); }
|
||||
};
|
||||
|
||||
typedef QVector<AppDescription> AppDescriptionVector;
|
||||
|
||||
|
||||
namespace LtsAppDescriptor // TODO: make qobject class singleton - for tr
|
||||
{
|
||||
LTSAPPDESCRIPTOR_EXPORT App appFromInteger(int i);
|
||||
LTSAPPDESCRIPTOR_EXPORT AppDescriptionVector getAppDescriptionVector(const QByteArray &jsonDocument,
|
||||
QStringList &lastErrors,
|
||||
const QStringList &ignoredPlugins,
|
||||
QString &loginPluginIid);
|
||||
}
|
||||
|
||||
} // namespace LtsAppDescriptor
|
||||
-532
@@ -1,532 +0,0 @@
|
||||
#include "lts_app_descriptor_editor.h"
|
||||
|
||||
#include "ui_lts_app_descriptor_editor.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QFile>
|
||||
#include <QtWidgets/QFileDialog>
|
||||
#include <QtCore/QJsonDocument>
|
||||
#include <QtWidgets/QMessageBox>
|
||||
#include <QStringListModel>
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtWidgets/QListView>
|
||||
#include <QtWidgets/QLineEdit>
|
||||
#include <QtWidgets/QPushButton>
|
||||
|
||||
LtsAppDescriptorEditor::LtsAppDescriptorEditor(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, m_ui(new Ui_LtsAppDescriptionEditor)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
m_vector = LtsAppDescriptor::AppDescriptionVector();
|
||||
m_appIndex = QModelIndex();
|
||||
m_pluginIndex = QModelIndex();
|
||||
m_fileName = QString();
|
||||
m_changed = false;
|
||||
|
||||
connect(m_ui->lvApps, &QListView::clicked, this, &LtsAppDescriptorEditor::onAppsClicked);
|
||||
connect(m_ui->lvPlugins, &QListView::clicked, this, &LtsAppDescriptorEditor::onPluginsClicked);
|
||||
connect(m_ui->lePluginType, &QLineEdit::editingFinished, this, &LtsAppDescriptorEditor::pluginTypeChanged);
|
||||
connect(m_ui->pbAddApp, &QPushButton::pressed, this, &LtsAppDescriptorEditor::onAppAddClicked);
|
||||
connect(m_ui->pbAddPlugin, &QPushButton::pressed, this, &LtsAppDescriptorEditor::onPluginAddClicked);
|
||||
connect(m_ui->pbDeleteApp, &QPushButton::pressed, this, &LtsAppDescriptorEditor::onAppDeleteClicked);
|
||||
connect(m_ui->pbDeletePlugin, &QPushButton::pressed, this, &LtsAppDescriptorEditor::onPluginDeletedClicked);
|
||||
connect(m_ui->pbUpdate, &QPushButton::pressed, this, &LtsAppDescriptorEditor::onUpdateClicked);
|
||||
connect(m_ui->pbNewPlugin, &QPushButton::pressed, this, &LtsAppDescriptorEditor::onNewpluginClicked);
|
||||
connect(m_ui->pbNewApp, &QPushButton::pressed, this, &LtsAppDescriptorEditor::onNewAppClicked);
|
||||
connect(m_ui->lePluginName, &QLineEdit::textChanged, this, &LtsAppDescriptorEditor::enableNewPlugin);
|
||||
connect(m_ui->lePluginType, &QLineEdit::textChanged, this, &LtsAppDescriptorEditor::enableNewPlugin);
|
||||
|
||||
m_ui->gbPlugins->setEnabled(false);
|
||||
m_ui->pbDeletePlugin->setEnabled(false);
|
||||
m_ui->pbDeleteApp->setEnabled(false);
|
||||
m_ui->pbAddPlugin->setEnabled(false);
|
||||
m_ui->pbUpdate->setEnabled(false);
|
||||
m_ui->pbNewPlugin->setEnabled(false);
|
||||
m_ui->pbNewApp->setEnabled(false);
|
||||
QTimer::singleShot(0, this, &LtsAppDescriptorEditor::getAppDescriptionVector);
|
||||
}
|
||||
|
||||
LtsAppDescriptorEditor::~LtsAppDescriptorEditor()
|
||||
{
|
||||
checkSave();
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
void LtsAppDescriptorEditor::getAppDescriptionVector()
|
||||
{
|
||||
m_fileName =
|
||||
QFileDialog::getOpenFileName(this, tr("Open JSON"), QLatin1Literal("/shd/CTC/TOOLS/TDS/TDS-source/Lts/Projects/Legatus/resources/"), tr("JSON File (*.json)"));
|
||||
if (m_fileName.isEmpty())
|
||||
return;
|
||||
|
||||
QFile file;
|
||||
file.setFileName(m_fileName);
|
||||
file.open(QIODevice::ReadOnly | QIODevice::Text);
|
||||
QString val(QString::fromUtf8(file.readAll()));
|
||||
file.close();
|
||||
|
||||
QStringList errors;
|
||||
m_vector = LtsAppDescriptor::LtsAppDescriptor::getAppDescriptionVector(val.toUtf8(), errors);
|
||||
|
||||
updateAppModel();
|
||||
}
|
||||
|
||||
void LtsAppDescriptorEditor::onAppsClicked(const QModelIndex &index)
|
||||
{
|
||||
m_ui->gbPlugins->setEnabled(true);
|
||||
m_ui->pbDeleteApp->setEnabled(true);
|
||||
m_ui->pbAddPlugin->setEnabled(true);
|
||||
m_ui->pbNewApp->setEnabled(true);
|
||||
m_appIndex = index;
|
||||
|
||||
QStringList pluginList;
|
||||
Q_FOREACH (const LtsAppDescriptor::PluginInfo &reqPlugin, m_vector.at(m_appIndex.row()).requiredPlugins)
|
||||
{
|
||||
LtsAppDescriptor::PluginInfo::PluginType pluginType = reqPlugin.type;
|
||||
QString type;
|
||||
if (pluginType == LtsAppDescriptor::PluginInfo::PluginType::DATA)
|
||||
type = QLatin1String("data");
|
||||
else if (pluginType == LtsAppDescriptor::PluginInfo::PluginType::GUI)
|
||||
type = QLatin1String("gui");
|
||||
else
|
||||
type = QLatin1String("unknown");
|
||||
|
||||
if (type == QLatin1String("data"))
|
||||
pluginList << QString(type + QLatin1String(": ") + reqPlugin.iid);
|
||||
else
|
||||
{
|
||||
QString strFlags;
|
||||
QFlags<LtsAppDescriptor::PluginInfo::Flag> flags = reqPlugin.flags;
|
||||
|
||||
bool actionsFlag = flags.testFlag(LtsAppDescriptor::PluginInfo::Flag::ACTIONS);
|
||||
if (actionsFlag)
|
||||
strFlags.append(QLatin1String("actions "));
|
||||
bool mainFlag = flags.testFlag(LtsAppDescriptor::PluginInfo::Flag::MAIN);
|
||||
if (mainFlag)
|
||||
strFlags.append(QLatin1String("main "));
|
||||
bool payloadFlag = flags.testFlag(LtsAppDescriptor::PluginInfo::Flag::PAYLOAD);
|
||||
if (payloadFlag)
|
||||
strFlags.append(QLatin1String("payload "));
|
||||
bool optionalFlag = flags.testFlag(LtsAppDescriptor::PluginInfo::Flag::OPTION);
|
||||
if (optionalFlag)
|
||||
strFlags.append(QLatin1String("optional "));
|
||||
|
||||
pluginList << QString(type + QLatin1String(": ") + reqPlugin.iid + QLatin1String(" [ ") + strFlags + QLatin1String("]"));
|
||||
}
|
||||
}
|
||||
updatePluginModel(pluginList);
|
||||
|
||||
m_ui->chbAppActive->setChecked(m_vector.at(m_appIndex.row()).active);
|
||||
m_ui->leAppName->setText(m_vector.at(m_appIndex.row()).appName);
|
||||
}
|
||||
|
||||
void LtsAppDescriptorEditor::onPluginsClicked(const QModelIndex &index)
|
||||
{
|
||||
m_pluginIndex = index;
|
||||
m_ui->pbDeletePlugin->setEnabled(true);
|
||||
m_ui->pbUpdate->setEnabled(true);
|
||||
m_ui->pbNewPlugin->setEnabled(true);
|
||||
|
||||
const LtsAppDescriptor::PluginInfo plugin = m_vector.at(m_appIndex.row()).requiredPlugins.at(m_pluginIndex.row());
|
||||
QString pluginName = plugin.iid;
|
||||
m_ui->lePluginName->setText(pluginName);
|
||||
|
||||
LtsAppDescriptor::PluginInfo::PluginType pluginType = plugin.type;
|
||||
QString type;
|
||||
if (pluginType == LtsAppDescriptor::PluginInfo::PluginType::DATA)
|
||||
type = QLatin1String("data");
|
||||
else if (pluginType == LtsAppDescriptor::PluginInfo::PluginType::GUI)
|
||||
type = QLatin1String("gui");
|
||||
else
|
||||
type = QLatin1String("unknown");
|
||||
m_ui->lePluginType->setText(type);
|
||||
|
||||
if (type == QLatin1String("gui"))
|
||||
{
|
||||
m_ui->chbActions->setEnabled(true);
|
||||
m_ui->chbMain->setEnabled(true);
|
||||
m_ui->chbPayload->setEnabled(true);
|
||||
|
||||
QFlags<LtsAppDescriptor::PluginInfo::Flag> flags = plugin.flags;
|
||||
bool actionsFlag = flags.testFlag(LtsAppDescriptor::PluginInfo::Flag::ACTIONS);
|
||||
m_ui->chbActions->setChecked(actionsFlag);
|
||||
bool mainFlag = flags.testFlag(LtsAppDescriptor::PluginInfo::Flag::MAIN);
|
||||
m_ui->chbMain->setChecked(mainFlag);
|
||||
bool payloadFlag = flags.testFlag(LtsAppDescriptor::PluginInfo::Flag::PAYLOAD);
|
||||
m_ui->chbPayload->setChecked(payloadFlag);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ui->chbActions->setChecked(false);
|
||||
m_ui->chbActions->setEnabled(false);
|
||||
m_ui->chbMain->setChecked(false);
|
||||
m_ui->chbMain->setEnabled(false);
|
||||
m_ui->chbPayload->setChecked(false);
|
||||
m_ui->chbPayload->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void LtsAppDescriptorEditor::pluginTypeChanged()
|
||||
{
|
||||
if (m_ui->lePluginType->text().isEmpty())
|
||||
return;
|
||||
|
||||
if (m_ui->lePluginType->text() == QLatin1String("gui"))
|
||||
{
|
||||
m_ui->chbActions->setEnabled(true);
|
||||
m_ui->chbMain->setEnabled(true);
|
||||
m_ui->chbPayload->setEnabled(true);
|
||||
}
|
||||
else if (m_ui->lePluginType->text() == QLatin1String("data"))
|
||||
{
|
||||
m_ui->chbActions->setChecked(false);
|
||||
m_ui->chbActions->setEnabled(false);
|
||||
m_ui->chbMain->setChecked(false);
|
||||
m_ui->chbMain->setEnabled(false);
|
||||
m_ui->chbPayload->setChecked(false);
|
||||
m_ui->chbPayload->setEnabled(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox msgBox(QMessageBox::Information, tr("Error"), tr("Plugin Type must either be \"gui\" or \"data\"."));
|
||||
msgBox.exec();
|
||||
m_ui->lePluginType->setText(QString());
|
||||
}
|
||||
}
|
||||
|
||||
void LtsAppDescriptorEditor::onAppAddClicked()
|
||||
{
|
||||
m_changed = true;
|
||||
|
||||
if (m_ui->leAppName->text().isEmpty())
|
||||
{
|
||||
QMessageBox msgBox(QMessageBox::Critical, tr("Error"), tr("The App needs to have a name."));
|
||||
msgBox.exec();
|
||||
return;
|
||||
}
|
||||
|
||||
QStringList appList;
|
||||
Q_FOREACH (const LtsAppDescriptor::AppDescription &appDesc, m_vector)
|
||||
{
|
||||
appList << appDesc.appName;
|
||||
}
|
||||
|
||||
if (appList.contains(m_ui->leAppName->text(), Qt::CaseInsensitive))
|
||||
{
|
||||
QMessageBox msgBox(QMessageBox::Critical, tr("Error"), tr("There already exists an app named \"%1\".").arg(m_ui->leAppName->text()));
|
||||
msgBox.exec();
|
||||
return;
|
||||
}
|
||||
|
||||
LtsAppDescriptor::AppDescription newApp;
|
||||
newApp.appName = m_ui->leAppName->text();
|
||||
newApp.active = m_ui->chbAppActive->isChecked();
|
||||
m_vector.append(newApp);
|
||||
|
||||
updateAppModel();
|
||||
}
|
||||
|
||||
void LtsAppDescriptorEditor::onPluginAddClicked()
|
||||
{
|
||||
m_changed = true;
|
||||
|
||||
if (m_ui->lePluginType->text().isEmpty())
|
||||
{
|
||||
QMessageBox msgBox(QMessageBox::Critical, tr("Error"), tr("The Plugin needs to contain a type."));
|
||||
msgBox.exec();
|
||||
return;
|
||||
}
|
||||
if (m_ui->lePluginName->text().isEmpty())
|
||||
{
|
||||
QMessageBox msgBox(QMessageBox::Critical, tr("Error"), tr("The Plugin needs to have a name."));
|
||||
msgBox.exec();
|
||||
return;
|
||||
}
|
||||
|
||||
QStringList pluginList;
|
||||
Q_FOREACH (const LtsAppDescriptor::PluginInfo &pluginDesc, m_vector.at(m_appIndex.row()).requiredPlugins)
|
||||
{
|
||||
pluginList << pluginDesc.iid;
|
||||
}
|
||||
|
||||
if (pluginList.contains(m_ui->lePluginName->text(), Qt::CaseInsensitive))
|
||||
{
|
||||
QMessageBox msgBox(QMessageBox::Critical, tr("Error"), tr("There already exists an plugin named \"%1\".").arg(m_ui->lePluginName->text()));
|
||||
msgBox.exec();
|
||||
return;
|
||||
}
|
||||
|
||||
LtsAppDescriptor::PluginInfo newPlugin;
|
||||
|
||||
newPlugin.iid = m_ui->lePluginName->text();
|
||||
|
||||
if (m_ui->lePluginType->text() == QLatin1String("gui"))
|
||||
newPlugin.type = LtsAppDescriptor::PluginInfo::PluginType::GUI;
|
||||
else if (m_ui->lePluginType->text() == QLatin1String("data"))
|
||||
newPlugin.type = LtsAppDescriptor::PluginInfo::PluginType::DATA;
|
||||
else
|
||||
newPlugin.type = LtsAppDescriptor::PluginInfo::PluginType::UNKNOWN;
|
||||
|
||||
if (m_ui->chbActions->isChecked())
|
||||
newPlugin.flags |= LtsAppDescriptor::PluginInfo::Flag::ACTIONS;
|
||||
if (m_ui->chbMain->isChecked())
|
||||
newPlugin.flags |= LtsAppDescriptor::PluginInfo::Flag::MAIN;
|
||||
if (m_ui->chbPayload->isChecked())
|
||||
newPlugin.flags |= LtsAppDescriptor::PluginInfo::Flag::PAYLOAD;
|
||||
|
||||
m_vector[m_appIndex.row()].requiredPlugins.append(newPlugin);
|
||||
|
||||
onAppsClicked(m_appIndex);
|
||||
onNewpluginClicked();
|
||||
}
|
||||
|
||||
void LtsAppDescriptorEditor::onAppDeleteClicked()
|
||||
{
|
||||
m_changed = true;
|
||||
|
||||
if (!m_appIndex.isValid())
|
||||
return;
|
||||
|
||||
QMessageBox msgBox(tr("Warning"),
|
||||
tr("The App \n\"%1\" \nwill be removed. Continue?").arg(m_appIndex.data().toString()),
|
||||
QMessageBox::Warning,
|
||||
QMessageBox::Yes | QMessageBox::Default,
|
||||
QMessageBox::No | QMessageBox::Escape,
|
||||
QMessageBox::NoButton);
|
||||
|
||||
if (msgBox.exec() == QMessageBox::No)
|
||||
return;
|
||||
|
||||
m_vector.remove(m_appIndex.row());
|
||||
|
||||
updateAppModel();
|
||||
}
|
||||
|
||||
void LtsAppDescriptorEditor::onPluginDeletedClicked()
|
||||
{
|
||||
m_changed = true;
|
||||
|
||||
if (!m_pluginIndex.isValid())
|
||||
return;
|
||||
|
||||
QMessageBox msgBox(tr("Warning"),
|
||||
tr("The Plugin \n\"%1\" \nwill be removed. Continue?").arg(m_pluginIndex.data().toString()),
|
||||
QMessageBox::Warning,
|
||||
QMessageBox::Yes | QMessageBox::Default,
|
||||
QMessageBox::No | QMessageBox::Escape,
|
||||
QMessageBox::NoButton);
|
||||
|
||||
if (msgBox.exec() == QMessageBox::No)
|
||||
return;
|
||||
|
||||
m_vector[m_appIndex.row()].requiredPlugins.remove(m_pluginIndex.row());
|
||||
m_pluginIndex = QModelIndex();
|
||||
m_ui->lePluginName->setText(QString());
|
||||
m_ui->lePluginType->setText(QString());
|
||||
m_ui->chbActions->setChecked(false);
|
||||
m_ui->chbMain->setChecked(false);
|
||||
m_ui->chbPayload->setChecked(false);
|
||||
|
||||
m_ui->pbDeletePlugin->setEnabled(false);
|
||||
m_ui->pbUpdate->setEnabled(false);
|
||||
m_ui->pbNewPlugin->setEnabled(false);
|
||||
|
||||
onAppsClicked(m_appIndex);
|
||||
}
|
||||
|
||||
void LtsAppDescriptorEditor::onUpdateClicked()
|
||||
{
|
||||
m_changed = true;
|
||||
|
||||
if (m_ui->lePluginType->text().isEmpty())
|
||||
{
|
||||
QMessageBox msgBox(QMessageBox::Critical, tr("Error"), tr("The Plugin needs to contain a type."));
|
||||
msgBox.exec();
|
||||
return;
|
||||
}
|
||||
if (m_ui->lePluginName->text().isEmpty())
|
||||
{
|
||||
QMessageBox msgBox(QMessageBox::Critical, tr("Error"), tr("The Plugin needs to have a name."));
|
||||
msgBox.exec();
|
||||
return;
|
||||
}
|
||||
|
||||
m_vector[m_appIndex.row()].requiredPlugins[m_pluginIndex.row()].iid = m_ui->lePluginName->text();
|
||||
|
||||
if (m_ui->lePluginType->text() == QLatin1String("gui"))
|
||||
m_vector[m_appIndex.row()].requiredPlugins[m_pluginIndex.row()].type = LtsAppDescriptor::PluginInfo::PluginType::GUI;
|
||||
else if (m_ui->lePluginType->text() == QLatin1String("data"))
|
||||
m_vector[m_appIndex.row()].requiredPlugins[m_pluginIndex.row()].type = LtsAppDescriptor::PluginInfo::PluginType::DATA;
|
||||
else
|
||||
m_vector[m_appIndex.row()].requiredPlugins[m_pluginIndex.row()].type = LtsAppDescriptor::PluginInfo::PluginType::UNKNOWN;
|
||||
|
||||
m_vector[m_appIndex.row()].requiredPlugins[m_pluginIndex.row()].flags = QFlags<LtsAppDescriptor::PluginInfo::Flag>();
|
||||
|
||||
if (m_ui->chbActions->isChecked())
|
||||
m_vector[m_appIndex.row()].requiredPlugins[m_pluginIndex.row()].flags |= LtsAppDescriptor::PluginInfo::Flag::ACTIONS;
|
||||
if (m_ui->chbMain->isChecked())
|
||||
m_vector[m_appIndex.row()].requiredPlugins[m_pluginIndex.row()].flags |= LtsAppDescriptor::PluginInfo::Flag::MAIN;
|
||||
if (m_ui->chbPayload->isChecked())
|
||||
m_vector[m_appIndex.row()].requiredPlugins[m_pluginIndex.row()].flags |= LtsAppDescriptor::PluginInfo::Flag::PAYLOAD;
|
||||
|
||||
onAppsClicked(m_appIndex);
|
||||
onNewpluginClicked();
|
||||
}
|
||||
|
||||
void LtsAppDescriptorEditor::onNewpluginClicked()
|
||||
{
|
||||
m_ui->lePluginName->setText(QString());
|
||||
m_ui->lePluginType->setText(QString());
|
||||
m_ui->chbActions->setEnabled(true);
|
||||
m_ui->chbMain->setEnabled(true);
|
||||
m_ui->chbPayload->setEnabled(true);
|
||||
m_ui->chbActions->setChecked(false);
|
||||
m_ui->chbMain->setChecked(false);
|
||||
m_ui->chbPayload->setChecked(false);
|
||||
m_ui->pbUpdate->setEnabled(false);
|
||||
m_ui->pbNewPlugin->setEnabled(false);
|
||||
m_ui->pbDeletePlugin->setEnabled(false);
|
||||
|
||||
if (m_pluginIndex.isValid())
|
||||
m_ui->lvPlugins->selectionModel()->select(m_pluginIndex, QItemSelectionModel::Deselect);
|
||||
m_pluginIndex = QModelIndex();
|
||||
}
|
||||
|
||||
void LtsAppDescriptorEditor::onNewAppClicked()
|
||||
{
|
||||
updatePluginModel(QStringList());
|
||||
|
||||
m_ui->gbPlugins->setEnabled(false);
|
||||
m_ui->pbDeletePlugin->setEnabled(false);
|
||||
m_ui->pbDeleteApp->setEnabled(false);
|
||||
m_ui->pbAddPlugin->setEnabled(false);
|
||||
m_ui->pbUpdate->setEnabled(false);
|
||||
m_ui->pbNewPlugin->setEnabled(false);
|
||||
m_ui->leAppName->setText(QString());
|
||||
m_ui->chbAppActive->setChecked(false);
|
||||
m_ui->lePluginName->setText(QString());
|
||||
m_ui->lePluginType->setText(QString());
|
||||
m_ui->chbActions->setChecked(false);
|
||||
m_ui->chbMain->setChecked(false);
|
||||
m_ui->chbPayload->setChecked(false);
|
||||
m_ui->pbNewApp->setEnabled(false);
|
||||
|
||||
if (m_appIndex.isValid())
|
||||
m_ui->lvApps->selectionModel()->select(m_appIndex, QItemSelectionModel::Deselect);
|
||||
m_appIndex = QModelIndex();
|
||||
}
|
||||
|
||||
void LtsAppDescriptorEditor::updateAppModel()
|
||||
{
|
||||
onNewAppClicked();
|
||||
QStringList appList;
|
||||
Q_FOREACH (const LtsAppDescriptor::AppDescription &appDesc, m_vector)
|
||||
{
|
||||
appList << appDesc.appName;
|
||||
}
|
||||
|
||||
if (!m_ui->lvApps->model())
|
||||
m_ui->lvApps->setModel(new QStringListModel(this));
|
||||
QStringListModel *m = qobject_cast<QStringListModel *>(m_ui->lvApps->model());
|
||||
if (!m)
|
||||
return;
|
||||
m->setStringList(appList);
|
||||
}
|
||||
|
||||
void LtsAppDescriptorEditor::updatePluginModel(const QStringList &list)
|
||||
{
|
||||
if (!m_ui->lvPlugins->model())
|
||||
m_ui->lvPlugins->setModel(new QStringListModel(this));
|
||||
QStringListModel *m = qobject_cast<QStringListModel *>(m_ui->lvPlugins->model());
|
||||
if (!m)
|
||||
return;
|
||||
m->setStringList(list);
|
||||
}
|
||||
|
||||
void LtsAppDescriptorEditor::checkSave()
|
||||
{
|
||||
if (m_changed)
|
||||
{
|
||||
QMessageBox msgBox(tr("Warning"),
|
||||
tr("The Data has been modified.\nDo you want to save your changes?"),
|
||||
QMessageBox::Warning,
|
||||
QMessageBox::Yes | QMessageBox::Default,
|
||||
QMessageBox::No | QMessageBox::Escape,
|
||||
QMessageBox::NoButton);
|
||||
|
||||
if (msgBox.exec() == QMessageBox::Yes)
|
||||
onSaveAsClicked();
|
||||
}
|
||||
}
|
||||
|
||||
void LtsAppDescriptorEditor::onSaveAsClicked()
|
||||
{
|
||||
QString fileName =
|
||||
QFileDialog::getSaveFileName(this, tr("Save JSON"), QLatin1Literal("/shd/CTC/TOOLS/TDS/TDS-source/Lts/Projects/Legatus/resources/"), tr("JSON File (*.json)"));
|
||||
if (fileName.isEmpty())
|
||||
return;
|
||||
|
||||
QByteArray jsonByteArray;
|
||||
jsonByteArray = LtsAppDescriptor::LtsAppDescriptor::createJson(m_vector);
|
||||
|
||||
QFile f(fileName);
|
||||
f.open(QIODevice::WriteOnly);
|
||||
f.write(jsonByteArray);
|
||||
f.close();
|
||||
|
||||
m_changed = false;
|
||||
|
||||
QMessageBox msgBox(QMessageBox::Information, tr("Success"), tr("Your file has been saved."));
|
||||
msgBox.exec();
|
||||
}
|
||||
|
||||
void LtsAppDescriptorEditor::onSaveClicked()
|
||||
{
|
||||
const QByteArray jsonByteArray(LtsAppDescriptor::LtsAppDescriptor::createJson(m_vector));
|
||||
|
||||
QFile f(m_fileName);
|
||||
f.open(QIODevice::WriteOnly);
|
||||
f.write(jsonByteArray);
|
||||
f.close();
|
||||
|
||||
m_changed = false;
|
||||
|
||||
QMessageBox msgBox(QMessageBox::Information, tr("Success"), tr("Your file has been saved."));
|
||||
msgBox.exec();
|
||||
}
|
||||
|
||||
void LtsAppDescriptorEditor::onOpenClicked()
|
||||
{
|
||||
checkSave();
|
||||
getAppDescriptionVector();
|
||||
m_changed = false;
|
||||
}
|
||||
|
||||
void LtsAppDescriptorEditor::onNewClicked()
|
||||
{
|
||||
checkSave();
|
||||
m_ui->chbActions->setChecked(false);
|
||||
m_ui->chbMain->setChecked(false);
|
||||
m_ui->chbPayload->setChecked(false);
|
||||
m_ui->chbAppActive->setChecked(false);
|
||||
m_ui->leAppName->setText(QString());
|
||||
m_ui->lePluginName->setText(QString());
|
||||
m_ui->lePluginType->setText(QString());
|
||||
m_ui->gbPlugins->setEnabled(false);
|
||||
|
||||
m_vector = LtsAppDescriptor::AppDescriptionVector();
|
||||
|
||||
updateAppModel();
|
||||
updatePluginModel(QStringList());
|
||||
}
|
||||
|
||||
void LtsAppDescriptorEditor::enableNewPlugin()
|
||||
{
|
||||
m_ui->pbNewPlugin->setEnabled(true);
|
||||
}
|
||||
|
||||
void LtsAppDescriptorEditor::onQuitClicked()
|
||||
{
|
||||
QApplication::quit();
|
||||
}
|
||||
-65
@@ -1,65 +0,0 @@
|
||||
#pragma once
|
||||
#include "lts_app_descriptor.h"
|
||||
|
||||
#include <QtCore/QModelIndex>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtWidgets/QWidget>
|
||||
|
||||
#ifndef LTSAPPDESCRIPTOREDITOR_EXPORT
|
||||
#ifdef BUILD_STATIC_LIBRARIES
|
||||
#define LTSAPPDESCRIPTOREDITOR_EXPORT
|
||||
#else
|
||||
#if defined(MAKE_LTSAPPDESCRIPTOREDITOR_LIB)
|
||||
#define LTSAPPDESCRIPTOREDITOR_EXPORT Q_DECL_EXPORT
|
||||
#else
|
||||
#define LTSAPPDESCRIPTOREDITOR_EXPORT Q_DECL_IMPORT
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
class Ui_LtsAppDescriptionEditor;
|
||||
|
||||
class LTSAPPDESCRIPTOREDITOR_EXPORT LtsAppDescriptorEditor : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LtsAppDescriptorEditor(QWidget *parent = 0);
|
||||
~LtsAppDescriptorEditor();
|
||||
|
||||
private:
|
||||
Ui_LtsAppDescriptionEditor *m_ui;
|
||||
LtsAppDescriptor::AppDescriptionVector m_vector;
|
||||
QModelIndex m_appIndex;
|
||||
QModelIndex m_pluginIndex;
|
||||
|
||||
QString m_fileName;
|
||||
|
||||
bool m_changed;
|
||||
|
||||
void getAppDescriptionVector();
|
||||
void setupMainWindow();
|
||||
void updateAppModel();
|
||||
void updatePluginModel(const QStringList &list);
|
||||
void checkSave();
|
||||
|
||||
private slots:
|
||||
void onAppsClicked(const QModelIndex &index);
|
||||
void onPluginsClicked(const QModelIndex &index);
|
||||
void pluginTypeChanged();
|
||||
void onAppAddClicked();
|
||||
void onPluginAddClicked();
|
||||
void onAppDeleteClicked();
|
||||
void onPluginDeletedClicked();
|
||||
void onUpdateClicked();
|
||||
void onNewpluginClicked();
|
||||
void onNewAppClicked();
|
||||
void enableNewPlugin();
|
||||
|
||||
public slots:
|
||||
void onSaveClicked();
|
||||
void onSaveAsClicked();
|
||||
void onOpenClicked();
|
||||
void onNewClicked();
|
||||
void onQuitClicked();
|
||||
};
|
||||
-434
@@ -1,434 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>LtsAppDescriptionEditor</class>
|
||||
<widget class="QWidget" name="LtsAppDescriptionEditor">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>865</width>
|
||||
<height>337</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="3" column="3" colspan="2">
|
||||
<widget class="QLabel" name="Plugins">
|
||||
<property name="text">
|
||||
<string>Required Plugins:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QLabel" name="AppLabel">
|
||||
<property name="text">
|
||||
<string>App:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" rowspan="4" colspan="3">
|
||||
<widget class="QListView" name="lvApps">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="7">
|
||||
<widget class="QPushButton" name="pbNewPlugin">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>New</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3" colspan="2">
|
||||
<widget class="QLabel" name="AppName">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Name:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="6">
|
||||
<widget class="QPushButton" name="pbDeletePlugin">
|
||||
<property name="text">
|
||||
<string>Delete</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="7" rowspan="4" colspan="3">
|
||||
<widget class="QGroupBox" name="gbPlugins">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>New Plugin Requirements</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="PluginType">
|
||||
<property name="text">
|
||||
<string>Type:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="lePluginType">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>210</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>gui/data</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="PluginName">
|
||||
<property name="text">
|
||||
<string>IID:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="lePluginName">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>210</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Name of the Plugin</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="PluginFlags">
|
||||
<property name="text">
|
||||
<string>Flags:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="chbActions">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Actions</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QCheckBox" name="chbMain">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Main</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QCheckBox" name="chbPayload">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Payload</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3" colspan="2">
|
||||
<widget class="QLabel" name="AppActive">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Active:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QPushButton" name="pbDeleteApp">
|
||||
<property name="text">
|
||||
<string>Delete</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="3" colspan="4">
|
||||
<widget class="QListView" name="lvPlugins">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>300</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="9">
|
||||
<widget class="QPushButton" name="pbUpdate">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Update</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="5">
|
||||
<widget class="QLineEdit" name="leAppName">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Name of the App</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="8">
|
||||
<widget class="QPushButton" name="pbAddPlugin">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QPushButton" name="pbNewApp">
|
||||
<property name="text">
|
||||
<string>New</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="5">
|
||||
<widget class="QCheckBox" name="chbAppActive">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QPushButton" name="pbAddApp">
|
||||
<property name="text">
|
||||
<string>Add</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>List of Apps</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="6" rowspan="3">
|
||||
<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>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>lvApps</tabstop>
|
||||
<tabstop>pbNewApp</tabstop>
|
||||
<tabstop>pbAddApp</tabstop>
|
||||
<tabstop>pbDeleteApp</tabstop>
|
||||
<tabstop>chbAppActive</tabstop>
|
||||
<tabstop>leAppName</tabstop>
|
||||
<tabstop>lvPlugins</tabstop>
|
||||
<tabstop>pbDeletePlugin</tabstop>
|
||||
<tabstop>pbNewPlugin</tabstop>
|
||||
<tabstop>lePluginType</tabstop>
|
||||
<tabstop>lePluginName</tabstop>
|
||||
<tabstop>chbPayload</tabstop>
|
||||
<tabstop>chbMain</tabstop>
|
||||
<tabstop>chbActions</tabstop>
|
||||
<tabstop>pbAddPlugin</tabstop>
|
||||
<tabstop>pbUpdate</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,55 +0,0 @@
|
||||
|
||||
|
||||
#include "lts_app_descriptor_editor.h"
|
||||
|
||||
#include <QtGui/QAction>
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <QtWidgets/QMainWindow>
|
||||
#include <QtWidgets/QMenuBar>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
|
||||
QMainWindow *mainWindow = new QMainWindow();
|
||||
QMenu *fileMenu = mainWindow->menuBar()->addMenu(QObject::tr("&File"));
|
||||
|
||||
QAction *openAct = new QAction(QObject::tr("&Open"), mainWindow);
|
||||
openAct->setShortcuts(QKeySequence::Open);
|
||||
openAct->setStatusTip(QObject::tr("Open an existing file"));
|
||||
fileMenu->addAction(openAct);
|
||||
|
||||
QAction *newAct = new QAction(QObject::tr("&New"), mainWindow);
|
||||
newAct->setShortcuts(QKeySequence::New);
|
||||
newAct->setStatusTip(QObject::tr("Create a new App"));
|
||||
fileMenu->addAction(newAct);
|
||||
|
||||
QAction *saveAct = new QAction(QObject::tr("&Save"), mainWindow);
|
||||
saveAct->setShortcuts(QKeySequence::Save);
|
||||
saveAct->setStatusTip(QObject::tr("Save modified file"));
|
||||
fileMenu->addAction(saveAct);
|
||||
|
||||
QAction *saveAsAct = new QAction(QObject::tr("&SaveAs"), mainWindow);
|
||||
saveAsAct->setShortcuts(QKeySequence::SaveAs);
|
||||
saveAsAct->setStatusTip(QObject::tr("Save modified file as"));
|
||||
fileMenu->addAction(saveAsAct);
|
||||
|
||||
QAction *quitAct = new QAction(QObject::tr("&Quit"), mainWindow);
|
||||
quitAct->setShortcuts(QKeySequence::Quit);
|
||||
quitAct->setStatusTip(QObject::tr("Quit the Application"));
|
||||
fileMenu->addAction(quitAct);
|
||||
|
||||
LtsAppDescriptorEditor *editor = new LtsAppDescriptorEditor(mainWindow);
|
||||
mainWindow->setCentralWidget(editor);
|
||||
QObject::connect(openAct, &QAction::triggered, editor, &LtsAppDescriptorEditor::onOpenClicked);
|
||||
QObject::connect(newAct, &QAction::triggered, editor, &LtsAppDescriptorEditor::onNewClicked);
|
||||
QObject::connect(saveAct, &QAction::triggered, editor, &LtsAppDescriptorEditor::onSaveClicked);
|
||||
QObject::connect(saveAsAct, &QAction::triggered, editor, &LtsAppDescriptorEditor::onSaveAsClicked);
|
||||
QObject::connect(quitAct, &QAction::triggered, editor, &LtsAppDescriptorEditor::onQuitClicked);
|
||||
|
||||
mainWindow->show();
|
||||
|
||||
int ret = a.exec();
|
||||
delete mainWindow;
|
||||
return ret;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
|
||||
NGL_ADD_LIBRARY2(ALL LtsCommandLineParser SHARED
|
||||
LtsCommandLineParser.cpp
|
||||
LtsCommandLineParser.h
|
||||
)
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(LtsCommandLineParser
|
||||
INTERFACE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../
|
||||
)
|
||||
NGL_TARGET_LINK_LIBRARIES(LtsCommandLineParser
|
||||
PRIVATE
|
||||
ngltools
|
||||
Qt6::Network
|
||||
PUBLIC
|
||||
Qt6::Core
|
||||
)
|
||||
-175
@@ -1,175 +0,0 @@
|
||||
|
||||
|
||||
#include "LtsCommandLineParser.h"
|
||||
|
||||
#include <QtCore/QFlags>
|
||||
#include <QNetworkInterface>
|
||||
#include <QtCore/QSettings>
|
||||
#include <QtCore/QUrl>
|
||||
#include <ngltools/ngltools_filesystem.h>
|
||||
|
||||
namespace LtsCommandLineParser
|
||||
{
|
||||
static constexpr int s_maxDomainId = 232;
|
||||
|
||||
LtsCommandLineParser::LtsCommandLineParser(ProvideCommandLineParameterOptions opts)
|
||||
: QCommandLineParser()
|
||||
, m_enabledOptions(opts)
|
||||
{
|
||||
if (NGL::isAppInBuildBasePath() || m_enabledOptions.testFlag(CreateDomainIdFromIp))
|
||||
{
|
||||
const QList<QHostAddress> addresses = QNetworkInterface::allAddresses();
|
||||
for (const QHostAddress &address : addresses)
|
||||
{
|
||||
if (address.isLoopback() || address.isNull())
|
||||
continue;
|
||||
if (address.protocol() != QAbstractSocket::IPv4Protocol)
|
||||
continue;
|
||||
|
||||
m_generatedDomainId = (address.toIPv4Address() & 0x000000ff) % 232;
|
||||
if (m_generatedDomainId == 0)
|
||||
m_generatedDomainId = s_maxDomainId;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_enabledOptions.testFlag(ExerciseId))
|
||||
addOption({{QStringLiteral("e"), QStringLiteral("exerciseid")},
|
||||
QStringLiteral("Default: -1 (invalid, get from lts-cc.conf)"),
|
||||
QStringLiteral("exerciseId"),
|
||||
QStringLiteral("-1")});
|
||||
if (m_enabledOptions.testFlag(DomainId))
|
||||
addOption({{QStringLiteral("d"), QStringLiteral("domainid")},
|
||||
QStringLiteral("Default: ") + QString::number(m_generatedDomainId),
|
||||
QStringLiteral("domainId"),
|
||||
QString::number(m_generatedDomainId)});
|
||||
if (m_enabledOptions.testFlag(CustomConfigFile))
|
||||
{
|
||||
const QString cf(NGL::findProjectConfigFile());
|
||||
addOption({{QStringLiteral("i"), QStringLiteral("ini")}, QStringLiteral("Default: ") + cf, QStringLiteral("filename"), cf});
|
||||
}
|
||||
if (m_enabledOptions.testFlag(TcpConnectionUrl))
|
||||
{
|
||||
const QString defaultTcpUrl(QStringLiteral("EXCTDS01:7400"));
|
||||
addOption({{QStringLiteral("t"), QStringLiteral("tcpurl")}, QStringLiteral("Default: ") + defaultTcpUrl, QStringLiteral("hostname:port"), defaultTcpUrl});
|
||||
}
|
||||
addHelpOption();
|
||||
|
||||
if (!m_enabledOptions.testFlag(NoVersion))
|
||||
addVersionOption();
|
||||
}
|
||||
|
||||
int LtsCommandLineParser::domainId() const
|
||||
{
|
||||
if (m_domainId == 0 && m_generatedDomainId != 0 && !m_domainIdSetByFunction)
|
||||
{
|
||||
#ifdef WIN32
|
||||
|
||||
fprintf(stdout,
|
||||
"\n\nAttention: using a default domain id != 0 because executable is run inside builddir - default "
|
||||
"domainid is %d\n\n",
|
||||
m_generatedDomainId);
|
||||
#else
|
||||
fprintf(stdout,
|
||||
"\n\n\e[31mAttention: using a default domain id != 0 because executable is run inside builddir - "
|
||||
"default domainid is %d\e[0m\n\n",
|
||||
m_generatedDomainId);
|
||||
#endif
|
||||
return m_generatedDomainId;
|
||||
}
|
||||
return m_domainId;
|
||||
}
|
||||
|
||||
void LtsCommandLineParser::setDomainId(int id)
|
||||
{
|
||||
m_domainIdSetByFunction = true;
|
||||
m_domainId = id;
|
||||
}
|
||||
|
||||
bool LtsCommandLineParser::iniFileSet() const
|
||||
{
|
||||
if (!m_enabledOptions.testFlag(CustomConfigFile))
|
||||
return false;
|
||||
return isSet(QStringLiteral("i"));
|
||||
}
|
||||
|
||||
bool LtsCommandLineParser::useTcpConnection() const
|
||||
{
|
||||
if (!m_enabledOptions.testFlag(TcpConnectionUrl))
|
||||
return false;
|
||||
return isSet(QStringLiteral("t"));
|
||||
}
|
||||
|
||||
QUrl LtsCommandLineParser::tcpConnectionUrl() const
|
||||
{
|
||||
if (!m_enabledOptions.testFlag(TcpConnectionUrl))
|
||||
return QUrl();
|
||||
if (!useTcpConnection())
|
||||
return QUrl();
|
||||
QString str = value(QStringLiteral("t"));
|
||||
|
||||
str.replace(QLatin1String("tcpv4_lan"), QLatin1String("tcpv4lan"));
|
||||
QUrl url = QUrl::fromUserInput(str);
|
||||
if (url.scheme() == QLatin1String("http") || url.scheme() == QLatin1String("file"))
|
||||
url.setScheme(QStringLiteral("tcpv4lan"));
|
||||
return url;
|
||||
}
|
||||
|
||||
bool LtsCommandLineParser::init(bool bParseHelp)
|
||||
{
|
||||
if (!parse(QCoreApplication::arguments()))
|
||||
{
|
||||
fprintf(stdout, "\nBad option: %s \n", qPrintable(errorText()));
|
||||
if (!m_unitModuleTestMode)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_enabledOptions.testFlag(ExerciseId))
|
||||
m_exerciseId = value(QStringLiteral("e")).toInt();
|
||||
if (m_enabledOptions.testFlag(DomainId))
|
||||
m_domainId = value(QStringLiteral("d")).toInt();
|
||||
if (m_enabledOptions.testFlag(CustomConfigFile))
|
||||
m_iniFile = value(QStringLiteral("i"));
|
||||
|
||||
if (bParseHelp && isSet(QStringLiteral("h")))
|
||||
showHelp();
|
||||
if (!m_unitModuleTestMode && isSet(QStringLiteral("v")))
|
||||
showVersion();
|
||||
if (!domainIdProvided())
|
||||
{
|
||||
const QString iniFile = m_iniFile.isEmpty() ? NGL::findProjectConfigFile() : m_iniFile;
|
||||
if (!iniFile.isEmpty())
|
||||
{
|
||||
QSettings s(iniFile, QSettings::IniFormat);
|
||||
bool bOk;
|
||||
int domainId = s.value(QStringLiteral("Global/DomainId"), m_domainId).toInt(&bOk);
|
||||
if (bOk && domainId > 0 && domainId <= s_maxDomainId)
|
||||
m_domainId = domainId;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void LtsCommandLineParser::showHelp(int exitCode)
|
||||
{
|
||||
if (!m_additionalHelpStr.isEmpty())
|
||||
fprintf(stdout, "%s", qPrintable(m_additionalHelpStr));
|
||||
|
||||
QCommandLineParser::showHelp(exitCode);
|
||||
}
|
||||
|
||||
bool LtsCommandLineParser::domainIdProvided() const
|
||||
{
|
||||
if (!m_enabledOptions.testFlag(DomainId))
|
||||
return false;
|
||||
return isSet(QStringLiteral("d"));
|
||||
}
|
||||
|
||||
bool LtsCommandLineParser::exerciseIdProvided() const
|
||||
{
|
||||
if (!m_enabledOptions.testFlag(ExerciseId))
|
||||
return false;
|
||||
return isSet(QStringLiteral("e"));
|
||||
}
|
||||
|
||||
} // namespace LtsCommandLineParser
|
||||
@@ -1,61 +0,0 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ltscommandlineparser_export.h"
|
||||
|
||||
#include <QCommandLineParser>
|
||||
|
||||
class QUrl;
|
||||
|
||||
namespace LtsCommandLineParser
|
||||
{
|
||||
class LTSCOMMANDLINEPARSER_EXPORT LtsCommandLineParser : public QCommandLineParser
|
||||
{
|
||||
public:
|
||||
enum ProvideCommandLineParameterOptions
|
||||
{
|
||||
None = 0x0000,
|
||||
CreateDomainIdFromIp = 0x0001,
|
||||
DomainId = 0x0002,
|
||||
ExerciseId = 0x0004,
|
||||
CustomConfigFile = 0x0008,
|
||||
TcpConnectionUrl = 0x0010,
|
||||
NoVersion = 0x0020
|
||||
};
|
||||
|
||||
explicit LtsCommandLineParser(ProvideCommandLineParameterOptions opts = ProvideCommandLineParameterOptions(CreateDomainIdFromIp | DomainId | ExerciseId |
|
||||
CustomConfigFile));
|
||||
virtual ~LtsCommandLineParser() = default;
|
||||
int domainId() const;
|
||||
void setDomainId(int id);
|
||||
|
||||
int exerciseId() const { return m_exerciseId; }
|
||||
|
||||
QString iniFile() const { return m_iniFile; }
|
||||
|
||||
bool iniFileSet() const;
|
||||
bool useTcpConnection() const;
|
||||
QUrl tcpConnectionUrl() const;
|
||||
virtual bool init(bool bParseHelp = true);
|
||||
|
||||
void showHelp(int exitCode = 0);
|
||||
bool domainIdProvided() const;
|
||||
bool exerciseIdProvided() const;
|
||||
|
||||
void setUnitModuleTestMode(bool onOff) { m_unitModuleTestMode = onOff; }
|
||||
|
||||
protected:
|
||||
QString m_additionalHelpStr;
|
||||
|
||||
private:
|
||||
QFlags<ProvideCommandLineParameterOptions> m_enabledOptions;
|
||||
int m_exerciseId{0};
|
||||
int m_domainId{0};
|
||||
int m_generatedDomainId{0};
|
||||
bool m_domainIdSetByFunction{false};
|
||||
bool m_unitModuleTestMode{false};
|
||||
QString m_iniFile;
|
||||
};
|
||||
|
||||
} // namespace LtsCommandLineParser
|
||||
@@ -1,104 +0,0 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
# Created by Christian Ehrlicher, SLSE, 2016-08-31
|
||||
#
|
||||
|
||||
# Make ${Qt6_Widgets} optional
|
||||
if(QT6_GUI_AVAILABLE AND TARGET Qt6::Widgets)
|
||||
set(Qt6_Widgets ${Qt6_Widgets})
|
||||
else()
|
||||
set(Qt6_Widgets "")
|
||||
endif()
|
||||
|
||||
|
||||
# Add system GeographicLib Find module path
|
||||
list(APPEND CMAKE_MODULE_PATH /usr/share/cmake/geographiclib)
|
||||
FIND_PACKAGE(GeographicLib)
|
||||
NGL_ADD_LIBRARY2(LtsCoordTrans WS AAR SV HLA SHARED
|
||||
lts_coord_trans.h
|
||||
lts_coord_trans.cpp
|
||||
)
|
||||
NGL_TARGET_LINK_LIBRARIES(LtsCoordTrans
|
||||
PUBLIC
|
||||
Qt6::Core
|
||||
)
|
||||
if (GeographicLib_FOUND)
|
||||
TARGET_LINK_LIBRARIES(LtsCoordTrans
|
||||
PRIVATE ${GeographicLib_LIBRARIES}
|
||||
)
|
||||
TARGET_INCLUDE_DIRECTORIES(LtsCoordTrans PRIVATE ${GeographicLib_INCLUDE_DIRS})
|
||||
LINK_DIRECTORIES(${GeographicLib_LIBRARY_DIRS})
|
||||
else()
|
||||
message(STATUS "GeographicLib not found; building LtsCoordTrans without it")
|
||||
endif()
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(LtsCoordTrans
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
SET(ltsCoordWidget_SRCS
|
||||
lts_coord_widget.cpp
|
||||
lts_coord_widget.h
|
||||
lts_coord_widget_p.cpp
|
||||
lts_coord_widget_p.h
|
||||
)
|
||||
NGL_WRAP_UI(ltsCoordWidget_SRCS
|
||||
lts_coord_widget_mgrs.ui
|
||||
lts_coord_widget_wgs84.ui
|
||||
)
|
||||
NGL_ADD_LIBRARY2(ltsCoordWidget WS AAR SV SHARED ${ltsCoordWidget_SRCS})
|
||||
if(QT6_GUI_AVAILABLE)
|
||||
NGL_TARGET_LINK_LIBRARIES(ltsCoordWidget
|
||||
PRIVATE
|
||||
LtsCoordTrans
|
||||
PUBLIC
|
||||
Qt6::Core
|
||||
${Qt6_Widgets}
|
||||
)
|
||||
endif()
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(ltsCoordWidget
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../LtsUtils/LtsUtilsCore
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
IF(TARGET LtsCoordTrans)
|
||||
SET(_tools lonlat2mgrs mgrs2lonlat)
|
||||
FOREACH(_tool ${_tools})
|
||||
NGL_ADD_EXECUTABLE(ALL ${_tool} ${_tool}.cpp)
|
||||
TARGET_LINK_LIBRARIES(${_tool}
|
||||
Qt6::Core
|
||||
${GeographicLib_LIBRARIES}
|
||||
)
|
||||
TARGET_INCLUDE_DIRECTORIES(${_tool} PRIVATE ${GeographicLib_INCLUDE_DIRS})
|
||||
LINK_DIRECTORIES(${GeographicLib_LIBRARY_DIRS})
|
||||
NGL_INSTALL_TARGET(${_tool})
|
||||
ENDFOREACH()
|
||||
ENDIF()
|
||||
|
||||
IF(BUILD_TESTING AND TARGET ltsCoordWidget)
|
||||
ADD_EXECUTABLE(lts_coord_widget_test lts_coord_widget_test.cpp)
|
||||
TARGET_LINK_LIBRARIES(lts_coord_widget_test
|
||||
ltsCoordWidget
|
||||
LtsCoordTrans
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
IF(BUILD_TESTING AND TARGET LtsCoordTrans)
|
||||
ADD_EXECUTABLE(lts_coord_trans_unit_test
|
||||
lts_coord_trans_unit_test.cpp
|
||||
lts_coord_trans_unit_test.h
|
||||
)
|
||||
TARGET_LINK_LIBRARIES(lts_coord_trans_unit_test
|
||||
LtsCoordTrans
|
||||
Qt6::Test
|
||||
${GeographicLib_LIBRARIES}
|
||||
)
|
||||
TARGET_INCLUDE_DIRECTORIES(lts_coord_trans_unit_test PRIVATE ${GeographicLib_INCLUDE_DIRS})
|
||||
LINK_DIRECTORIES(${GeographicLib_LIBRARY_DIRS})
|
||||
ADD_TEST(NAME lts_coord_trans_unit_test COMMAND $<TARGET_FILE:lts_coord_trans_unit_test>)
|
||||
ENDIF()
|
||||
@@ -1,74 +0,0 @@
|
||||
|
||||
|
||||
#include <GeographicLib/MGRS.hpp>
|
||||
#include <GeographicLib/UTMUPS.hpp>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc < 3 || argc > 5)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s <lon_degree> <lat_degree> [<precision>]\n", argv[0]);
|
||||
fprintf(stderr, "Usage: %s <lon_rad> <lat_rad> -r [<precision>]\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool lonLatInRad = false;
|
||||
double lon = atof(argv[1]);
|
||||
double lat = atof(argv[2]);
|
||||
int prec = 5;
|
||||
if (argc >= 4)
|
||||
{
|
||||
int precArgId = -1;
|
||||
if (strcmp(argv[3], "-r") == 0)
|
||||
{
|
||||
lonLatInRad = true;
|
||||
if (argc == 5)
|
||||
precArgId = 4;
|
||||
}
|
||||
else
|
||||
precArgId = 3;
|
||||
if (precArgId > 0)
|
||||
prec = atoi(argv[precArgId]);
|
||||
}
|
||||
|
||||
std::string mgrs;
|
||||
|
||||
int zone;
|
||||
bool northp;
|
||||
double x, y;
|
||||
try
|
||||
{
|
||||
const double latDeg = lonLatInRad ? lat * 180 / M_PI : lat;
|
||||
const double lonDeg = lonLatInRad ? lon * 180 / M_PI : lon;
|
||||
GeographicLib::UTMUPS::Forward(latDeg, lonDeg, zone, northp, x, y);
|
||||
GeographicLib::MGRS::Forward(zone, northp, x, y, prec, mgrs);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
fprintf(stderr, "Error converting %9.6f, %9.6f to MGRS coords\n", lat, lon);
|
||||
return -2;
|
||||
}
|
||||
std::string part1, part2, part3, part4;
|
||||
part1 = mgrs.substr(0, 3);
|
||||
part2 = mgrs.substr(3, 2);
|
||||
if (prec > 0)
|
||||
{
|
||||
part3 = mgrs.substr(5, prec);
|
||||
part4 = mgrs.substr(5 + prec, prec);
|
||||
}
|
||||
fprintf(stdout,
|
||||
"%13.10f, %13.10f = %s %s %s %s (UTM: %d %.2f, %.2f %c)\n",
|
||||
lon,
|
||||
lat,
|
||||
part1.c_str(),
|
||||
part2.c_str(),
|
||||
part3.c_str(),
|
||||
part4.c_str(),
|
||||
zone,
|
||||
x,
|
||||
y,
|
||||
northp ? 'N' : 'S');
|
||||
return 0;
|
||||
}
|
||||
@@ -1,437 +0,0 @@
|
||||
|
||||
|
||||
#include "lts_coord_trans.h"
|
||||
|
||||
#include <GeographicLib/Geocentric.hpp>
|
||||
#include <GeographicLib/MGRS.hpp>
|
||||
#include <GeographicLib/UTMUPS.hpp>
|
||||
#include <QtCore/QPointF>
|
||||
#include <QtCore/QRectF>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QStringList>
|
||||
#include <iomanip>
|
||||
#include <utility>
|
||||
|
||||
namespace LtsCoordTrans
|
||||
{
|
||||
|
||||
static long s_conversion_counter_MGRS_Forward = 0;
|
||||
static long s_conversion_counter_MGRS_Reverse = 0;
|
||||
|
||||
static long s_conversion_counter_WGS84_Forward = 0;
|
||||
static long s_conversion_counter_WGS84_Reverse = 0;
|
||||
|
||||
static long s_conversion_counter_UTMUPS_Forward = 0;
|
||||
static long s_conversion_counter_UTMUPS_Reverse = 0;
|
||||
|
||||
inline void incrementCounter(long &counterRef)
|
||||
{
|
||||
#ifdef LTS_DEBUG
|
||||
++counterRef;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline std::string cleanupMgrsString(const QString &in)
|
||||
{
|
||||
const QByteArray ba(in.toLatin1());
|
||||
std::string ret;
|
||||
ret.reserve(ba.size());
|
||||
for (const char c : ba)
|
||||
{
|
||||
if (c != ' ')
|
||||
ret += c;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString UtmCoordinate::mgrs(int prec, bool withSpaces) const
|
||||
{
|
||||
if (prec < 0)
|
||||
prec = 0;
|
||||
if (prec > 11)
|
||||
prec = 11;
|
||||
|
||||
std::string mgrs;
|
||||
try
|
||||
{
|
||||
GeographicLib::MGRS::Forward(zone, northp, x, y, prec, mgrs);
|
||||
incrementCounter(s_conversion_counter_MGRS_Forward);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
fprintf(stderr, "Error while calculating mgrs from utm %d, %9.6f, %9.6f: %s\n", zone, x, y, e.what());
|
||||
mgrs.clear();
|
||||
}
|
||||
|
||||
QString ret;
|
||||
if (withSpaces && mgrs.size() == static_cast<size_t>(5 + 2 * prec))
|
||||
{
|
||||
|
||||
const char *ptr = mgrs.c_str();
|
||||
|
||||
ret = QString::fromLatin1(ptr, 3) + QLatin1Char(' ') + QString::fromLatin1(ptr + 3, 2);
|
||||
if (prec > 0)
|
||||
{
|
||||
ret += QLatin1Char(' ') + QString::fromLatin1(ptr + 5, prec) + QLatin1Char(' ') + QString::fromLatin1(ptr + 5 + prec, prec);
|
||||
}
|
||||
}
|
||||
else
|
||||
ret = QString::fromLatin1(mgrs.c_str(), mgrs.size());
|
||||
return ret;
|
||||
}
|
||||
|
||||
QPointF UtmCoordinate::toPoint() const
|
||||
{
|
||||
return {x, y};
|
||||
}
|
||||
|
||||
QPointF UtmCoordinate::geographic(double offsetX, double offsetY) const
|
||||
{
|
||||
QPointF ret;
|
||||
try
|
||||
{
|
||||
GeographicLib::UTMUPS::Reverse(zone, northp, x + offsetX, y + offsetY, ret.ry(), ret.rx());
|
||||
incrementCounter(s_conversion_counter_UTMUPS_Reverse);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
fprintf(stderr, "Error while calculating geographic from utm %d, %9.6f, %9.6f: %s\n", zone, x + offsetX, y + offsetY, e.what());
|
||||
ret = QPointF();
|
||||
}
|
||||
return ret * deg2rad();
|
||||
}
|
||||
|
||||
QPointF UtmCoordinate::geographic(const QPointF &offset) const
|
||||
{
|
||||
return geographic(offset.x(), offset.y());
|
||||
}
|
||||
|
||||
QPointF UtmCoordinate::relativeTo(const UtmCoordinate &other) const
|
||||
{
|
||||
if (zone == other.zone)
|
||||
return QPointF(x - other.x, y - other.y);
|
||||
|
||||
UtmCoordinate otherInMyZone = fromGeographic(other.geographic(), zone);
|
||||
return QPointF(x - otherInMyZone.x, y - otherInMyZone.y);
|
||||
}
|
||||
|
||||
UtmCoordinate UtmCoordinate::fromGeographic(double lon, double lat, int setZone)
|
||||
{
|
||||
|
||||
lon *= rad2deg();
|
||||
lat *= rad2deg();
|
||||
|
||||
UtmCoordinate ret;
|
||||
try
|
||||
{
|
||||
|
||||
GeographicLib::UTMUPS::Forward(lat, lon, ret.zone, ret.northp, ret.x, ret.y, setZone);
|
||||
incrementCounter(s_conversion_counter_UTMUPS_Forward);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
fprintf(stderr, "Error while calculating mgrs base point from %9.6f, %9.6f: %s\n", lat, lon, e.what());
|
||||
ret = UtmCoordinate();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
UtmCoordinate UtmCoordinate::fromGeographic(const QPointF &lonLat, int setZone)
|
||||
{
|
||||
return fromGeographic(lonLat.x(), lonLat.y(), setZone);
|
||||
}
|
||||
|
||||
UtmCoordinate UtmCoordinate::fromMgrs(const QString &mgrs)
|
||||
{
|
||||
UtmCoordinate utm;
|
||||
try
|
||||
{
|
||||
int prec;
|
||||
|
||||
GeographicLib::MGRS::Reverse(cleanupMgrsString(mgrs), utm.zone, utm.northp, utm.x, utm.y, prec, true);
|
||||
incrementCounter(s_conversion_counter_MGRS_Reverse);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
fprintf(stderr, "Error while converting mgrs coordinate %s to utm: %s\n", qPrintable(mgrs), e.what());
|
||||
utm = UtmCoordinate();
|
||||
}
|
||||
return utm;
|
||||
}
|
||||
|
||||
QString mgrsFromGeographic(double lon, double lat, int prec, bool withSpaces)
|
||||
{
|
||||
return UtmCoordinate::fromGeographic(lon, lat, -1).mgrs(prec, withSpaces);
|
||||
}
|
||||
|
||||
QPointF geographicFromMgrs(const QString &mgrs)
|
||||
{
|
||||
return UtmCoordinate::fromMgrs(mgrs).geographic();
|
||||
}
|
||||
|
||||
QVector<UtmCoordinate> &staticDefaultSquaresHelper()
|
||||
{
|
||||
static QVector<UtmCoordinate> s_defaultMgrsSquares;
|
||||
return s_defaultMgrsSquares;
|
||||
}
|
||||
|
||||
UtmCoordinate &staticPreferedMgrsSquareHelper()
|
||||
{
|
||||
static UtmCoordinate s_preferedMgrsSquare;
|
||||
return s_preferedMgrsSquare;
|
||||
}
|
||||
|
||||
QVector<UtmCoordinate> &staticMgrsSquaresWithOffsetsHelper()
|
||||
{
|
||||
static QVector<UtmCoordinate> s_mgrsSquaresWithOffsets;
|
||||
return s_mgrsSquaresWithOffsets;
|
||||
}
|
||||
|
||||
QRectF addMarginToArea(const QRectF &rect_LatLon_radiant, const QSize &marginMeter)
|
||||
{
|
||||
double lonMin, lonMax, latMin, latMmax;
|
||||
rect_LatLon_radiant.normalized().getCoords(&lonMin, &latMin, &lonMax, &latMmax);
|
||||
|
||||
LtsCoordTrans::UtmCoordinate basePoint;
|
||||
{
|
||||
|
||||
const QPointF centerRad = rect_LatLon_radiant.center();
|
||||
QString mgrs = LtsCoordTrans::mgrsFromGeographic(centerRad.x(), centerRad.y(), -1);
|
||||
mgrs += QStringLiteral("00000000000000");
|
||||
|
||||
basePoint = LtsCoordTrans::UtmCoordinate::fromMgrs(mgrs);
|
||||
}
|
||||
|
||||
const UtmCoordinate lowerLeft(UtmCoordinate::fromGeographic(lonMin, latMin, basePoint.zone));
|
||||
const UtmCoordinate upperRight(UtmCoordinate::fromGeographic(lonMax, latMmax, basePoint.zone));
|
||||
|
||||
int offsetX = marginMeter.width();
|
||||
int offsetY = marginMeter.height();
|
||||
|
||||
const QPointF topLeft(lowerLeft.geographic(-offsetX, -offsetY));
|
||||
const QPointF bottomRight(upperRight.geographic(offsetX, offsetY));
|
||||
|
||||
QRectF res = QRectF(topLeft, bottomRight);
|
||||
return res;
|
||||
}
|
||||
|
||||
QVector<UtmCoordinate> getMgrsSquares(const QRectF &rect, bool setAsDefaultSquares, bool setAsPreferedSquare, bool setAsSquareWithMargin)
|
||||
{
|
||||
QVector<UtmCoordinate> ret = getMgrsSquaresInternal(rect);
|
||||
|
||||
if (setAsDefaultSquares)
|
||||
staticDefaultSquaresHelper() = ret;
|
||||
|
||||
if (setAsPreferedSquare)
|
||||
staticPreferedMgrsSquareHelper() = LtsCoordTrans::UtmCoordinate::fromGeographic(rect.center());
|
||||
|
||||
if (setAsSquareWithMargin)
|
||||
staticMgrsSquaresWithOffsetsHelper() = ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QVector<UtmCoordinate> getMgrsSquaresInternal(const QRectF &rect)
|
||||
{
|
||||
QVector<UtmCoordinate> ret;
|
||||
QVector<QString> tmpMgrsSquares;
|
||||
|
||||
double lonMin, lonMax, latMin, latMmax;
|
||||
rect.normalized().getCoords(&lonMin, &latMin, &lonMax, &latMmax);
|
||||
|
||||
bool withInSingleUtmSquare = true;
|
||||
{
|
||||
const UtmCoordinate upperRight(UtmCoordinate::fromGeographic(lonMax, latMmax));
|
||||
const UtmCoordinate lowerLeft(UtmCoordinate::fromGeographic(lonMin, latMin));
|
||||
withInSingleUtmSquare = upperRight.zone == lowerLeft.zone;
|
||||
}
|
||||
|
||||
LtsCoordTrans::UtmCoordinate basePoint;
|
||||
{
|
||||
|
||||
QPointF centerRad = rect.center();
|
||||
QString mgrs = LtsCoordTrans::mgrsFromGeographic(centerRad.x(), centerRad.y(), -1);
|
||||
mgrs += QStringLiteral("00000000000000");
|
||||
|
||||
basePoint = LtsCoordTrans::UtmCoordinate::fromMgrs(mgrs);
|
||||
}
|
||||
|
||||
const UtmCoordinate upperRight(UtmCoordinate::fromGeographic(lonMax, latMmax, basePoint.zone));
|
||||
const UtmCoordinate lowerLeft(UtmCoordinate::fromGeographic(lonMin, latMin, basePoint.zone));
|
||||
|
||||
const double maxX(upperRight.x - lowerLeft.x);
|
||||
const double maxY(upperRight.y - lowerLeft.y);
|
||||
|
||||
const int increment = withInSingleUtmSquare ? 10000 : 1000;
|
||||
for (double x = 0; x <= maxX + increment; x += increment)
|
||||
{
|
||||
const double xOfs = std::min(x, maxX);
|
||||
for (double y = 0; y <= maxY + increment; y += increment)
|
||||
{
|
||||
const double yOfs = std::min(y, maxY);
|
||||
|
||||
const UtmCoordinate utm(UtmCoordinate::fromGeographic(lowerLeft.geographic(xOfs, yOfs)));
|
||||
const QString mgrs(utm.mgrs(0));
|
||||
|
||||
if (!tmpMgrsSquares.contains(mgrs))
|
||||
{
|
||||
tmpMgrsSquares += mgrs;
|
||||
ret += utm;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
QStringList getMgrsSurroundingSquares(const QRectF &geoRect, const QSize &offsetMeter)
|
||||
{
|
||||
|
||||
const QVector<UtmCoordinate> mainUtms = getMgrsSquaresInternal(geoRect);
|
||||
QStringList mainSquares;
|
||||
mainSquares.reserve(mainUtms.count());
|
||||
for (const auto &utm : mainUtms)
|
||||
mainSquares.append(utm.mgrs(0));
|
||||
|
||||
const QRectF rectWithOffset = addMarginToArea(geoRect, offsetMeter);
|
||||
|
||||
QVector<UtmCoordinate> mainUtmsWithOffset = getMgrsSquaresInternal(rectWithOffset);
|
||||
QStringList mainSquaresWithOffset;
|
||||
mainSquaresWithOffset.reserve(mainUtmsWithOffset.count());
|
||||
for (const auto &utm : std::as_const(mainUtmsWithOffset))
|
||||
mainSquaresWithOffset.append(utm.mgrs(0));
|
||||
|
||||
QStringList surroundingSquares;
|
||||
surroundingSquares.reserve(mainSquaresWithOffset.count());
|
||||
for (const auto &mgrs0 : mainSquaresWithOffset)
|
||||
{
|
||||
if (!mainSquares.contains(mgrs0))
|
||||
surroundingSquares.append(mgrs0);
|
||||
}
|
||||
|
||||
return surroundingSquares;
|
||||
}
|
||||
|
||||
QVector<UtmCoordinate> defaultMgrsSquareWithOffsets()
|
||||
{
|
||||
return staticMgrsSquaresWithOffsetsHelper();
|
||||
}
|
||||
|
||||
void setDefaultMgrsSquares(const QVector<QString> &squares)
|
||||
{
|
||||
QVector<UtmCoordinate> coords;
|
||||
coords.reserve(squares.size());
|
||||
for (const QString &s : squares)
|
||||
coords += UtmCoordinate::fromMgrs(s + QStringLiteral("00000000000000"));
|
||||
staticDefaultSquaresHelper() = coords;
|
||||
}
|
||||
|
||||
QVector<UtmCoordinate> defaultMgrsSquares()
|
||||
{
|
||||
return staticDefaultSquaresHelper();
|
||||
}
|
||||
|
||||
UtmCoordinate preferedMgrsSquare()
|
||||
{
|
||||
return staticPreferedMgrsSquareHelper();
|
||||
}
|
||||
|
||||
bool lonLatAltToGeocentric(double lon, double lat, double altitude, double &xOut, double &yOut, double &zOut)
|
||||
{
|
||||
|
||||
lon *= rad2deg();
|
||||
lat *= rad2deg();
|
||||
|
||||
try
|
||||
{
|
||||
GeographicLib::Geocentric::WGS84().Forward(lat, lon, altitude, xOut, yOut, zOut);
|
||||
incrementCounter(s_conversion_counter_WGS84_Forward);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
xOut = 0;
|
||||
yOut = 0;
|
||||
zOut = 0;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool geocentric2LonLatAlt(double x, double y, double z, double &lon, double &lat, double &altitude)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
GeographicLib::Geocentric::WGS84().Reverse(x, y, z, lat, lon, altitude);
|
||||
incrementCounter(s_conversion_counter_WGS84_Reverse);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
lon = 0;
|
||||
lat = 0;
|
||||
altitude = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
lon *= deg2rad();
|
||||
lat *= deg2rad();
|
||||
return true;
|
||||
}
|
||||
|
||||
double distance(const QPointF &p1, const QPointF &p2)
|
||||
{
|
||||
return distance(p1.x(), p1.y(), p2.x(), p2.y());
|
||||
}
|
||||
|
||||
double squareDistance(const QPointF &p1, const QPointF &p2)
|
||||
{
|
||||
return squareDistance(p1.x(), p1.y(), p2.x(), p2.y());
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &stream, const UtmCoordinate &coord)
|
||||
{
|
||||
|
||||
stream << "UtmCoordinate(" << std::setprecision(8) << coord.x << "#" << std::setprecision(8) << coord.y << " zone=" << coord.zone << ")";
|
||||
return stream;
|
||||
}
|
||||
|
||||
void dumpConversionCounter()
|
||||
{
|
||||
fprintf(stderr, "LtsCoordTrans: s_conversion_counter_MGRS_Forward : - mgrs : %ld\n", s_conversion_counter_MGRS_Forward);
|
||||
fprintf(stderr, "LtsCoordTrans: s_conversion_counter_MGRS_Reverse - fromMgrs : %ld\n", s_conversion_counter_MGRS_Reverse);
|
||||
fprintf(stderr, "LtsCoordTrans: s_conversion_counter_WGS84_Forward - lonLatAltToGeocentric : %ld\n", s_conversion_counter_WGS84_Forward);
|
||||
fprintf(stderr, "LtsCoordTrans: s_conversion_counter_WGS84_Reverse - geocentric2LonLatAlt : %ld\n", s_conversion_counter_WGS84_Reverse);
|
||||
fprintf(stderr, "LtsCoordTrans: s_conversion_counter_UTMUPS_Forward - fromGeographic : %ld\n", s_conversion_counter_UTMUPS_Forward);
|
||||
fprintf(stderr, "LtsCoordTrans: s_conversion_counter_UTMUPS_Reverse - geographic : %ld\n", s_conversion_counter_UTMUPS_Reverse);
|
||||
}
|
||||
|
||||
long getConversionCounter_MGRS_Forward()
|
||||
{
|
||||
return s_conversion_counter_MGRS_Forward;
|
||||
}
|
||||
|
||||
long getConversionCounter_MGRS_Reverse()
|
||||
{
|
||||
return s_conversion_counter_MGRS_Reverse;
|
||||
}
|
||||
|
||||
long getConversionCounter_WGS84_Forward()
|
||||
{
|
||||
return s_conversion_counter_WGS84_Forward;
|
||||
}
|
||||
|
||||
long getConversionCounter_WGS84_Reverse()
|
||||
{
|
||||
return s_conversion_counter_WGS84_Reverse;
|
||||
}
|
||||
|
||||
long getConversionCounter_UTMUPS_Forward()
|
||||
{
|
||||
return s_conversion_counter_UTMUPS_Forward;
|
||||
}
|
||||
|
||||
long getConversionCounter_UTMUPS_Reverse()
|
||||
{
|
||||
return s_conversion_counter_UTMUPS_Reverse;
|
||||
}
|
||||
|
||||
} // namespace LtsCoordTrans
|
||||
@@ -1,183 +0,0 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QVector>
|
||||
#include <cmath>
|
||||
#include "ltscoordtrans_export.h"
|
||||
#include <string>
|
||||
class QPointF;
|
||||
class QRectF;
|
||||
class QSize;
|
||||
class QString;
|
||||
|
||||
namespace LtsCoordTrans
|
||||
{
|
||||
|
||||
inline Q_CONSTEXPR double pi()
|
||||
{
|
||||
return M_PI;
|
||||
}
|
||||
|
||||
inline Q_CONSTEXPR double deg2rad()
|
||||
{
|
||||
return pi() / 180.;
|
||||
}
|
||||
|
||||
inline Q_CONSTEXPR double rad2deg()
|
||||
{
|
||||
return 1. / deg2rad();
|
||||
}
|
||||
|
||||
struct LTSCOORDTRANS_EXPORT UtmCoordinate
|
||||
{
|
||||
int zone = -1;
|
||||
bool northp = true;
|
||||
double x = 0.;
|
||||
double y = 0.;
|
||||
|
||||
UtmCoordinate() = default;
|
||||
|
||||
UtmCoordinate(int zone_, double x_, double y_, bool northp_ = true)
|
||||
: zone(zone_)
|
||||
, northp(northp_)
|
||||
, x(x_)
|
||||
, y(y_)
|
||||
{
|
||||
}
|
||||
|
||||
bool isValid() const { return zone > 0 && zone <= 60; }
|
||||
|
||||
QString mgrs(int prec = 5, bool withSpaces = true) const;
|
||||
|
||||
QPointF toPoint() const;
|
||||
|
||||
QPointF geographic(double offsetX = 0., double offsetY = 0.) const;
|
||||
|
||||
QPointF geographic(const QPointF &offset) const;
|
||||
|
||||
QPointF relativeTo(const UtmCoordinate &other) const;
|
||||
|
||||
static UtmCoordinate fromGeographic(double lon, double lat, int setZone = -1);
|
||||
|
||||
static UtmCoordinate fromGeographic(const QPointF &lonLat, int setZone = -1);
|
||||
|
||||
static UtmCoordinate fromMgrs(const QString &mgrs);
|
||||
};
|
||||
|
||||
LTSCOORDTRANS_EXPORT QString mgrsFromGeographic(double lon, double lat, int prec = 5, bool withSpaces = true);
|
||||
|
||||
LTSCOORDTRANS_EXPORT QPointF geographicFromMgrs(const QString &mgrs);
|
||||
|
||||
LTSCOORDTRANS_EXPORT QRectF addMarginToArea(const QRectF &rect_LatLon_radiant, const QSize &marginMeter);
|
||||
|
||||
LTSCOORDTRANS_EXPORT QVector<UtmCoordinate> getMgrsSquares(const QRectF &rect, bool setAsDefaultSquares, bool setAsPreferedSquare, bool setAsSquareWithMargin = false);
|
||||
|
||||
QVector<UtmCoordinate> getMgrsSquaresInternal(const QRectF &rect);
|
||||
|
||||
QStringList getMgrsSurroundingSquares(const QRectF &geoRect, const QSize &offsetMeter);
|
||||
|
||||
LTSCOORDTRANS_EXPORT QVector<UtmCoordinate> defaultMgrsSquareWithOffsets();
|
||||
|
||||
LTSCOORDTRANS_EXPORT void setDefaultMgrsSquares(const QVector<QString> &squares);
|
||||
|
||||
LTSCOORDTRANS_EXPORT QVector<UtmCoordinate> defaultMgrsSquares();
|
||||
|
||||
LTSCOORDTRANS_EXPORT UtmCoordinate preferedMgrsSquare();
|
||||
|
||||
LTSCOORDTRANS_EXPORT bool lonLatAltToGeocentric(double lon, double lat, double altitude, double &xOut, double &yOut, double &zOut);
|
||||
|
||||
LTSCOORDTRANS_EXPORT bool geocentric2LonLatAlt(double x, double y, double z, double &lon, double &lat, double &altitude);
|
||||
|
||||
inline double squareDistance(const UtmCoordinate &p1, const UtmCoordinate &p2)
|
||||
{
|
||||
if (p1.zone != p2.zone)
|
||||
{
|
||||
Q_ASSERT(false);
|
||||
return std::nan("");
|
||||
}
|
||||
return std::pow(p1.x - p2.x, 2) + std::pow(p1.y - p2.y, 2);
|
||||
}
|
||||
|
||||
LTSCOORDTRANS_EXPORT double squareDistance(const QPointF &p1, const QPointF &p2);
|
||||
|
||||
inline double squareDistance(const double lon1, const double lat1, const double lon2, const double lat2)
|
||||
{
|
||||
const auto p1(UtmCoordinate::fromGeographic(lon1, lat1));
|
||||
const auto p2(UtmCoordinate::fromGeographic(lon2, lat2, p1.zone));
|
||||
return squareDistance(p1, p2);
|
||||
}
|
||||
|
||||
inline double squareDistance(const UtmCoordinate &p1, const double lon2, const double lat2)
|
||||
{
|
||||
const auto p2(UtmCoordinate::fromGeographic(lon2, lat2, p1.zone));
|
||||
return squareDistance(p1, p2);
|
||||
}
|
||||
|
||||
inline double distance(const UtmCoordinate &p1, const UtmCoordinate &p2)
|
||||
{
|
||||
if (p1.zone != p2.zone)
|
||||
{
|
||||
Q_ASSERT(false);
|
||||
return std::nan("");
|
||||
}
|
||||
return sqrt(squareDistance(p1, p2));
|
||||
}
|
||||
|
||||
LTSCOORDTRANS_EXPORT double distance(const QPointF &p1, const QPointF &p2);
|
||||
|
||||
inline double distance(const double lon1, const double lat1, const double lon2, const double lat2)
|
||||
{
|
||||
return sqrt(squareDistance(lon1, lat1, lon2, lat2));
|
||||
}
|
||||
|
||||
inline double distance(const UtmCoordinate &p1, const double lon2, const double lat2)
|
||||
{
|
||||
return sqrt(squareDistance(p1, lon2, lat2));
|
||||
}
|
||||
|
||||
LTSCOORDTRANS_EXPORT void dumpConversionCounter();
|
||||
|
||||
LTSCOORDTRANS_EXPORT long getConversionCounter_MGRS_Forward();
|
||||
LTSCOORDTRANS_EXPORT long getConversionCounter_MGRS_Reverse();
|
||||
LTSCOORDTRANS_EXPORT long getConversionCounter_WGS84_Forward();
|
||||
LTSCOORDTRANS_EXPORT long getConversionCounter_WGS84_Reverse();
|
||||
LTSCOORDTRANS_EXPORT long getConversionCounter_UTMUPS_Forward();
|
||||
LTSCOORDTRANS_EXPORT long getConversionCounter_UTMUPS_Reverse();
|
||||
|
||||
LTSCOORDTRANS_EXPORT std::ostream &operator<<(std::ostream &stream, const UtmCoordinate &coord);
|
||||
|
||||
class LTSCOORDTRANS_EXPORT UtmCoordinate3D : public LtsCoordTrans::UtmCoordinate
|
||||
{
|
||||
using BaseClass = LtsCoordTrans::UtmCoordinate;
|
||||
|
||||
public:
|
||||
UtmCoordinate3D() { reset(); }
|
||||
|
||||
explicit UtmCoordinate3D(const LtsCoordTrans::UtmCoordinate &utm2d, double _zValue = std::nan(""))
|
||||
: BaseClass()
|
||||
{
|
||||
zone = utm2d.zone;
|
||||
northp = utm2d.northp;
|
||||
x = utm2d.x;
|
||||
y = utm2d.y;
|
||||
zValue = _zValue;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
zone = -1;
|
||||
northp = true;
|
||||
|
||||
x = 0.;
|
||||
y = 0.;
|
||||
zValue = std::nan("");
|
||||
}
|
||||
|
||||
double z() const { return zValue; }
|
||||
|
||||
protected:
|
||||
double zValue{std::nan("")};
|
||||
};
|
||||
|
||||
} // namespace LtsCoordTrans
|
||||
-414
@@ -1,414 +0,0 @@
|
||||
|
||||
|
||||
#include "lts_coord_trans_unit_test.h"
|
||||
|
||||
#include "lts_coord_trans.h"
|
||||
|
||||
#include <GeographicLib/Math.hpp>
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtTest/QTest>
|
||||
#include <utility>
|
||||
|
||||
QTEST_MAIN(coordtrans_test)
|
||||
|
||||
void coordtrans_test::initTestCase()
|
||||
{
|
||||
qDebug("sizeof(UtmCoordinate) = %lu", sizeof(LtsCoordTrans::UtmCoordinate));
|
||||
}
|
||||
|
||||
void coordtrans_test::cleanupTestCase() {}
|
||||
|
||||
void coordtrans_test::testFromGeographic()
|
||||
{
|
||||
|
||||
LtsCoordTrans::UtmCoordinate utm;
|
||||
QPointF lonlat;
|
||||
|
||||
lonlat = QPointF(8.6264954126, 53.1138437183) * LtsCoordTrans::deg2rad();
|
||||
utm = LtsCoordTrans::UtmCoordinate::fromGeographic(lonlat.x(), lonlat.y(), -1);
|
||||
QCOMPARE(utm.mgrs(0), QStringLiteral("32U MD"));
|
||||
utm = LtsCoordTrans::UtmCoordinate::fromGeographic(lonlat.x(), lonlat.y());
|
||||
QCOMPARE(utm.mgrs(8), QStringLiteral("32U MD 74999999 84999999"));
|
||||
|
||||
lonlat = QPointF(11.3003696521, 52.8224535191) * LtsCoordTrans::deg2rad();
|
||||
utm = LtsCoordTrans::UtmCoordinate::fromGeographic(lonlat.x(), lonlat.y(), -1);
|
||||
QCOMPARE(utm.mgrs(0), QStringLiteral("32U PD"));
|
||||
utm = LtsCoordTrans::UtmCoordinate::fromGeographic(lonlat.x(), lonlat.y());
|
||||
QCOMPARE(utm.mgrs(5), QStringLiteral("32U PD 55000 55000"));
|
||||
|
||||
lonlat = QPointF(54.8821607021, 24.2631973752) * LtsCoordTrans::deg2rad();
|
||||
utm = LtsCoordTrans::UtmCoordinate::fromGeographic(lonlat.x(), lonlat.y(), -1);
|
||||
QCOMPARE(utm.mgrs(0), QStringLiteral("40R BM"));
|
||||
utm = LtsCoordTrans::UtmCoordinate::fromGeographic(lonlat.x(), lonlat.y());
|
||||
QCOMPARE(utm.mgrs(5), QStringLiteral("40R BM 85000 85000"));
|
||||
|
||||
utm = LtsCoordTrans::UtmCoordinate::fromMgrs(QStringLiteral("40R BM 00000 00000"));
|
||||
QCOMPARE(utm.mgrs(0), QStringLiteral("40Q BM"));
|
||||
}
|
||||
|
||||
void coordtrans_test::testMgrsFromGeographic()
|
||||
{
|
||||
|
||||
QString mgrs;
|
||||
QPointF lonlat;
|
||||
|
||||
lonlat = QPointF(8.6191049344, 53.1048309844) * LtsCoordTrans::deg2rad();
|
||||
mgrs = LtsCoordTrans::mgrsFromGeographic(lonlat.x(), lonlat.y(), 9);
|
||||
QCOMPARE(mgrs, QStringLiteral("32U MD 745000000 840000000"));
|
||||
|
||||
mgrs = LtsCoordTrans::mgrsFromGeographic(lonlat.x(), lonlat.y(), 8, false);
|
||||
QCOMPARE(mgrs, QStringLiteral("32UMD7450000084000000"));
|
||||
}
|
||||
|
||||
void coordtrans_test::testRelativeMetricalOffet_data()
|
||||
{
|
||||
|
||||
QTest::addColumn<QPoint>("offset");
|
||||
QTest::addColumn<QString>("correctMgrs");
|
||||
|
||||
QTest::newRow("set 1") << QPoint(5, 5) << QStringLiteral("32U PD 99995 99995");
|
||||
|
||||
QTest::newRow("set 2") << QPoint(100, 100) << QStringLiteral("32U QE 00090 00090");
|
||||
QTest::newRow("set 3") << QPoint(500, 500) << QStringLiteral("32U QE 00490 00490");
|
||||
}
|
||||
|
||||
void coordtrans_test::testRelativeMetricalOffet()
|
||||
{
|
||||
QFETCH(QPoint, offset);
|
||||
QFETCH(QString, correctMgrs);
|
||||
|
||||
const LtsCoordTrans::UtmCoordinate &utmRef = LtsCoordTrans::UtmCoordinate::fromMgrs(QStringLiteral("32U PD 99990 99990"));
|
||||
qDebug() << "utmRef = " << utmRef.mgrs();
|
||||
|
||||
{
|
||||
LtsCoordTrans::UtmCoordinate utmRaw;
|
||||
utmRaw.x = utmRef.x + offset.x();
|
||||
utmRaw.y = utmRef.y + offset.y();
|
||||
utmRaw.zone = utmRef.zone;
|
||||
qDebug() << "offset = " << offset << " - utmRaw = " << utmRaw.mgrs();
|
||||
|
||||
QCOMPARE(utmRaw.mgrs(), correctMgrs);
|
||||
}
|
||||
|
||||
{
|
||||
const LtsCoordTrans::UtmCoordinate utmSimple(utmRef.zone, utmRef.x + offset.x(), utmRef.y + offset.y());
|
||||
|
||||
qDebug() << "offset = " << offset << " - utmSimple = " << utmSimple.mgrs();
|
||||
QCOMPARE(utmSimple.mgrs(), correctMgrs);
|
||||
}
|
||||
}
|
||||
|
||||
QRectF createArea(const QString &base, int xCenter, int yCenter, int width, int height)
|
||||
{
|
||||
|
||||
QRectF areaRect = QRectF(xCenter - width / 2, yCenter - height / 2, width, height);
|
||||
LtsCoordTrans::UtmCoordinate utmBase(LtsCoordTrans::UtmCoordinate::fromGeographic(LtsCoordTrans::geographicFromMgrs(base)));
|
||||
const QPointF topLeft(utmBase.geographic(areaRect.left(), areaRect.top()));
|
||||
const QPointF bottomRight(utmBase.geographic(areaRect.right(), areaRect.bottom()));
|
||||
|
||||
QRectF rect(topLeft, bottomRight);
|
||||
return rect;
|
||||
}
|
||||
|
||||
void coordtrans_test::testAddMarginToArea()
|
||||
{
|
||||
|
||||
{
|
||||
qDebug() << "Altmark";
|
||||
QRectF area = createArea(QStringLiteral("32U PD 0000000000"), 50000, 10000, 30000, 30000);
|
||||
QRectF area1Increased = LtsCoordTrans::addMarginToArea(area, QSize(5000, 20000));
|
||||
|
||||
qDebug() << "topLeft : " << qSetRealNumberPrecision(15) << area.topLeft() << " - degree:" << area.topLeft() * LtsCoordTrans::rad2deg();
|
||||
qDebug() << "topLeftInc : " << qSetRealNumberPrecision(15) << area1Increased.topLeft() << " - degree:" << area1Increased.topLeft() * LtsCoordTrans::rad2deg();
|
||||
|
||||
qDebug() << "bottomRight : " << qSetRealNumberPrecision(15) << area.bottomRight() << " - degree:" << area.bottomRight() * LtsCoordTrans::rad2deg();
|
||||
qDebug() << "bottomRightInc : " << qSetRealNumberPrecision(15) << area1Increased.bottomRight()
|
||||
<< " - degree:" << area1Increased.bottomRight() * LtsCoordTrans::rad2deg();
|
||||
|
||||
QVERIFY2(area1Increased.topLeft().x() < area.topLeft().x(), "addMarginToArea topLeft X failed");
|
||||
QVERIFY2(area1Increased.topLeft().y() < area.topLeft().y(), "addMarginToArea topLeft Y failed");
|
||||
|
||||
QVERIFY2(area1Increased.bottomRight().x() > area.bottomRight().x(), "addMarginToArea bottomRight X failed");
|
||||
QVERIFY2(area1Increased.bottomRight().y() > area.bottomRight().y(), "addMarginToArea bottomRight Y failed");
|
||||
}
|
||||
|
||||
{
|
||||
qDebug() << "Luxemburg";
|
||||
QRectF area = createArea(QStringLiteral("32U LA 0000000000"), 100, 100, 5000, 5000);
|
||||
QRectF area1Increased = LtsCoordTrans::addMarginToArea(area, QSize(50000, 20000));
|
||||
|
||||
qDebug() << "topLeft : " << qSetRealNumberPrecision(15) << area.topLeft() << " - degree:" << area.topLeft() * LtsCoordTrans::rad2deg();
|
||||
qDebug() << "topLeftInc : " << qSetRealNumberPrecision(15) << area1Increased.topLeft() << " - degree:" << area1Increased.topLeft() * LtsCoordTrans::rad2deg();
|
||||
|
||||
qDebug() << "bottomRight : " << qSetRealNumberPrecision(15) << area.bottomRight() << " - degree:" << area.bottomRight() * LtsCoordTrans::rad2deg();
|
||||
qDebug() << "bottomRightInc : " << qSetRealNumberPrecision(15) << area1Increased.bottomRight()
|
||||
<< " - degree:" << area1Increased.bottomRight() * LtsCoordTrans::rad2deg();
|
||||
|
||||
QVERIFY2(area1Increased.topLeft().x() < area.topLeft().x(), "addMarginToArea topLeft X failed");
|
||||
QVERIFY2(area1Increased.topLeft().y() < area.topLeft().y(), "addMarginToArea topLeft Y failed");
|
||||
|
||||
QVERIFY2(area1Increased.bottomRight().x() > area.bottomRight().x(), "addMarginToArea bottomRight X failed");
|
||||
QVERIFY2(area1Increased.bottomRight().y() > area.bottomRight().y(), "addMarginToArea bottomRight Y failed");
|
||||
}
|
||||
}
|
||||
|
||||
void coordtrans_test::testIncreaseRect()
|
||||
{
|
||||
|
||||
QPointF lonlat = QPointF(8.6191049344, 53.1048309844) * LtsCoordTrans::deg2rad();
|
||||
QString mgrs = LtsCoordTrans::mgrsFromGeographic(lonlat.x(), lonlat.y(), 9);
|
||||
QCOMPARE(mgrs, QStringLiteral("32U MD 745000000 840000000"));
|
||||
|
||||
const LtsCoordTrans::UtmCoordinate centerPoint = LtsCoordTrans::UtmCoordinate::fromGeographic(lonlat.x(), lonlat.y());
|
||||
|
||||
LtsCoordTrans::UtmCoordinate topLeftUtm;
|
||||
LtsCoordTrans::UtmCoordinate topLeftUtm2;
|
||||
|
||||
{
|
||||
QPointF topLeftGeo = centerPoint.geographic(-1111, 2222);
|
||||
QPointF bottomRightGeo = centerPoint.geographic(3000, -4000);
|
||||
|
||||
topLeftUtm = LtsCoordTrans::UtmCoordinate::fromGeographic(topLeftGeo);
|
||||
const LtsCoordTrans::UtmCoordinate bottomRightUtm = LtsCoordTrans::UtmCoordinate::fromGeographic(bottomRightGeo);
|
||||
qDebug() << "topLeftUtm: " << topLeftUtm.x << " - " << qSetRealNumberPrecision(15) << topLeftUtm.y;
|
||||
qDebug() << "bottomRightUtm: " << bottomRightUtm.x << " - " << qSetRealNumberPrecision(15) << bottomRightUtm.y;
|
||||
}
|
||||
|
||||
{
|
||||
topLeftUtm2.x = centerPoint.x - 1111;
|
||||
topLeftUtm2.y = centerPoint.y + 2222;
|
||||
|
||||
LtsCoordTrans::UtmCoordinate bottomRightUtm2;
|
||||
bottomRightUtm2.x = centerPoint.x + 3000;
|
||||
bottomRightUtm2.y = centerPoint.y - 4000;
|
||||
|
||||
qDebug() << "topLeftUtm2: " << topLeftUtm2.x << " - " << qSetRealNumberPrecision(15) << topLeftUtm2.y;
|
||||
qDebug() << "bottomRightUtm2: " << bottomRightUtm2.x << " - " << qSetRealNumberPrecision(15) << bottomRightUtm2.y;
|
||||
}
|
||||
|
||||
QVERIFY2(qFuzzyCompare(topLeftUtm.x, topLeftUtm2.x), "testIncreaseRect x failed");
|
||||
QVERIFY2(qFuzzyCompare(topLeftUtm.y, topLeftUtm2.y), "testIncreaseRect y failed");
|
||||
}
|
||||
|
||||
void coordtrans_test::testIncreaseRect2()
|
||||
{
|
||||
|
||||
QPointF lonlat = QPointF(8.6191049344, 53.1048309844) * LtsCoordTrans::deg2rad();
|
||||
QString mgrs = LtsCoordTrans::mgrsFromGeographic(lonlat.x(), lonlat.y(), 9);
|
||||
QCOMPARE(mgrs, QStringLiteral("32U MD 745000000 840000000"));
|
||||
|
||||
QRectF myRect;
|
||||
QRectF myRectIncreased;
|
||||
|
||||
{
|
||||
const LtsCoordTrans::UtmCoordinate centerPoint = LtsCoordTrans::UtmCoordinate::fromGeographic(lonlat.x(), lonlat.y());
|
||||
|
||||
QPointF topLeftGeo = centerPoint.geographic(-3000, 2000);
|
||||
QPointF bottomRightGeo = centerPoint.geographic(3000, -2000);
|
||||
myRect = QRectF(topLeftGeo, bottomRightGeo).normalized();
|
||||
|
||||
qDebug() << "myRect : " << myRect;
|
||||
qDebug() << "myRect center : " << myRect.center();
|
||||
qDebug() << "myRect height : " << myRect.height();
|
||||
}
|
||||
|
||||
{
|
||||
const QPointF centerGeo = myRect.center();
|
||||
const LtsCoordTrans::UtmCoordinate centerUtm = LtsCoordTrans::UtmCoordinate::fromGeographic(centerGeo);
|
||||
|
||||
QPointF topLeftGeo = centerUtm.geographic(-6000, 4000);
|
||||
QPointF bottomRightGeo = centerUtm.geographic(6000, -4000);
|
||||
|
||||
myRectIncreased = QRectF(topLeftGeo, bottomRightGeo).normalized();
|
||||
|
||||
qDebug() << "myRectIncreased : " << myRectIncreased;
|
||||
qDebug() << "myRectIncreased center: " << myRectIncreased.center();
|
||||
qDebug() << "myRectIncreased height: " << myRectIncreased.height();
|
||||
}
|
||||
|
||||
QVERIFY2((int)(myRectIncreased.center().x() * 10000) == (int)(myRect.center().x() * 10000), "testIncreaseRect2 centerX failed");
|
||||
QVERIFY2((int)(myRectIncreased.center().y() * 10000) == (int)(myRect.center().y() * 10000), "testIncreaseRect2 centerY failed");
|
||||
|
||||
QVERIFY2(myRectIncreased.width() > myRect.width(), "testIncreaseRect2 width failed");
|
||||
QVERIFY2(myRectIncreased.height() > myRect.height(), "testIncreaseRect2 height failed");
|
||||
}
|
||||
|
||||
void coordtrans_test::testGeographicFromMgrs()
|
||||
{
|
||||
|
||||
QString mgrs(QStringLiteral("32UPD7654398765"));
|
||||
|
||||
QPointF geographic = LtsCoordTrans::geographicFromMgrs(mgrs);
|
||||
QCOMPARE(geographic, QPointF(11.6436815550, 53.2088411454) * LtsCoordTrans::deg2rad());
|
||||
}
|
||||
|
||||
void coordtrans_test::testMgrsSquares()
|
||||
{
|
||||
|
||||
checkArea(QStringLiteral("32U PD 0000000000"), 50000, 10000, 30000, 30000, {QStringLiteral("32U PC"), QStringLiteral("32U PD")});
|
||||
checkArea(QStringLiteral("32U MD 0000000000"), 50000, 10000, 30000, 30000, {QStringLiteral("32U MC"), QStringLiteral("32U MD")});
|
||||
checkArea(QStringLiteral("32U MD 0000000000"),
|
||||
89999,
|
||||
89999,
|
||||
21000,
|
||||
21000,
|
||||
{QStringLiteral("32U MD"), QStringLiteral("32U ME"), QStringLiteral("32U ND"), QStringLiteral("32U NE")});
|
||||
|
||||
checkArea(QStringLiteral("39Q XG 0000000000"), 40000, 35000, 60000, 70000, {QStringLiteral("39Q XG"), QStringLiteral("39R XG")});
|
||||
checkArea(QStringLiteral("40R CP 0000000000"), 94000, 9000, 7000, 16000, {QStringLiteral("40R CP")});
|
||||
checkArea(QStringLiteral("40R DN 0000000000"), 500, 95500, 12000, 7000, {QStringLiteral("40R CN"), QStringLiteral("40R DN")});
|
||||
checkArea(QStringLiteral("40R DN 0000000000"),
|
||||
500,
|
||||
96760,
|
||||
30000,
|
||||
30000,
|
||||
{QStringLiteral("40R CN"), QStringLiteral("40R CP"), QStringLiteral("40R DN"), QStringLiteral("40R DP")});
|
||||
checkArea(QStringLiteral("40R BM 0000000000"), 59000, 59500, 46000, 40000, {QStringLiteral("40Q BM"), QStringLiteral("40R BM")});
|
||||
|
||||
checkArea(QStringLiteral("32U LA 0000000000"),
|
||||
10000,
|
||||
10000,
|
||||
5000,
|
||||
5000,
|
||||
{
|
||||
QStringLiteral("32U LA"),
|
||||
});
|
||||
|
||||
checkArea(QStringLiteral("32U LA 0000000000"),
|
||||
100,
|
||||
100,
|
||||
60000,
|
||||
60000,
|
||||
{QStringLiteral("31U GQ"), QStringLiteral("31U GR"), QStringLiteral("32U KA"), QStringLiteral("32U KV"), QStringLiteral("32U LA"), QStringLiteral("32U LV")});
|
||||
|
||||
checkArea(QStringLiteral("32U LA 0000000000"),
|
||||
100,
|
||||
100,
|
||||
150000,
|
||||
150000,
|
||||
{QStringLiteral("31U FQ"),
|
||||
QStringLiteral("31U FR"),
|
||||
QStringLiteral("31U GQ"),
|
||||
QStringLiteral("31U GR"),
|
||||
QStringLiteral("32U KA"),
|
||||
QStringLiteral("32U KV"),
|
||||
QStringLiteral("32U LA"),
|
||||
QStringLiteral("32U LV")});
|
||||
|
||||
checkArea(QStringLiteral("32U LA 0000000000"),
|
||||
100,
|
||||
100,
|
||||
200000,
|
||||
200000,
|
||||
{QStringLiteral("31U FP"),
|
||||
QStringLiteral("31U FQ"),
|
||||
QStringLiteral("31U FR"),
|
||||
QStringLiteral("31U GP"),
|
||||
QStringLiteral("31U GQ"),
|
||||
QStringLiteral("31U GR"),
|
||||
QStringLiteral("31U GS"),
|
||||
QStringLiteral("32U KA"),
|
||||
QStringLiteral("32U KB"),
|
||||
QStringLiteral("32U KV"),
|
||||
QStringLiteral("32U LA"),
|
||||
QStringLiteral("32U LB"),
|
||||
QStringLiteral("32U LV"),
|
||||
QStringLiteral("32U MA"),
|
||||
QStringLiteral("32U MB"),
|
||||
QStringLiteral("32U MV")});
|
||||
}
|
||||
|
||||
QVector<LtsCoordTrans::UtmCoordinate> checkAreaGetMgrsSquares(const QString &base, int xCenter, int yCenter, int width, int height)
|
||||
{
|
||||
|
||||
QRectF areaRect = QRectF(xCenter - width / 2, yCenter - height / 2, width, height);
|
||||
LtsCoordTrans::UtmCoordinate utmBase(LtsCoordTrans::UtmCoordinate::fromGeographic(LtsCoordTrans::geographicFromMgrs(base)));
|
||||
const QPointF topLeft(utmBase.geographic(areaRect.left(), areaRect.top()));
|
||||
const QPointF bottomRight(utmBase.geographic(areaRect.right(), areaRect.bottom()));
|
||||
|
||||
const auto squares = LtsCoordTrans::getMgrsSquares(QRectF(topLeft, bottomRight), false, false);
|
||||
|
||||
QStringList src;
|
||||
src.reserve(squares.size());
|
||||
for (const auto &utm : squares)
|
||||
src += utm.mgrs(0);
|
||||
src.sort();
|
||||
|
||||
return squares;
|
||||
}
|
||||
|
||||
void coordtrans_test::testMgrsSquaresWithSurrounding()
|
||||
{
|
||||
|
||||
int initialSize = 5000;
|
||||
|
||||
QVector<LtsCoordTrans::UtmCoordinate> squares1 = checkAreaGetMgrsSquares(QStringLiteral("32U NC 0000000000"), 50000, 50000, initialSize, initialSize);
|
||||
|
||||
QVERIFY2(squares1.size() == 1, "checkAreaGetMgrsSquares failed");
|
||||
|
||||
int biggerSize = initialSize + (1 * 110000);
|
||||
QVector<LtsCoordTrans::UtmCoordinate> squares9 = checkAreaGetMgrsSquares(QStringLiteral("32U NC 0000000000"), 50000, 50000, biggerSize, biggerSize);
|
||||
|
||||
QVERIFY2(squares9.size() == 9, "checkAreaGetMgrsSquares biggerSize failed");
|
||||
|
||||
int muchBiggerSize = initialSize + (3 * 110000);
|
||||
QVector<LtsCoordTrans::UtmCoordinate> square33 = checkAreaGetMgrsSquares(QStringLiteral("32U NC 0000000000"), 50000, 50000, muchBiggerSize, muchBiggerSize);
|
||||
|
||||
QVERIFY2(square33.size() == 33, "checkAreaGetMgrsSquares muchBiggerSize failed");
|
||||
|
||||
QStringList string1;
|
||||
string1.reserve(squares1.size());
|
||||
for (const LtsCoordTrans::UtmCoordinate &item : std::as_const(squares1))
|
||||
string1.append(item.mgrs(0));
|
||||
|
||||
QStringList string9;
|
||||
string9.reserve(squares9.size());
|
||||
for (const LtsCoordTrans::UtmCoordinate &item : std::as_const(squares9))
|
||||
string9.append(item.mgrs(0));
|
||||
|
||||
QStringList string33;
|
||||
string33.reserve(square33.size());
|
||||
for (const LtsCoordTrans::UtmCoordinate &item : std::as_const(square33))
|
||||
string33.append(item.mgrs(0));
|
||||
|
||||
{
|
||||
QStringList surroundingStrings;
|
||||
surroundingStrings.reserve(squares9.size());
|
||||
for (const QString &str : std::as_const(string9))
|
||||
if (!string1.contains(str))
|
||||
surroundingStrings.append(str);
|
||||
|
||||
QVERIFY2(surroundingStrings.size() == 8, "checkAreaGetMgrsSquares squaresDiff failed");
|
||||
}
|
||||
|
||||
{
|
||||
QStringList surroundingStrings;
|
||||
surroundingStrings.reserve(string33.size());
|
||||
for (const QString &str : std::as_const(string33))
|
||||
if (!string1.contains(str))
|
||||
surroundingStrings.append(str);
|
||||
|
||||
QVERIFY2(surroundingStrings.size() == 32, "checkAreaGetMgrsSquares squaresDiff failed");
|
||||
}
|
||||
}
|
||||
|
||||
void coordtrans_test::checkArea(const QString &base, int xCenter, int yCenter, int width, int height, const QStringList &coords)
|
||||
{
|
||||
qDebug() << "checkArea : base: " << base;
|
||||
QRectF areaRect = QRectF(xCenter - width / 2, yCenter - height / 2, width, height);
|
||||
LtsCoordTrans::UtmCoordinate utmBase(LtsCoordTrans::UtmCoordinate::fromGeographic(LtsCoordTrans::geographicFromMgrs(base)));
|
||||
const QPointF topLeft(utmBase.geographic(areaRect.left(), areaRect.top()));
|
||||
const QPointF bottomRight(utmBase.geographic(areaRect.right(), areaRect.bottom()));
|
||||
qDebug() << "TopLeft: " << topLeft * LtsCoordTrans::rad2deg();
|
||||
qDebug() << "BottomRight: " << bottomRight * LtsCoordTrans::rad2deg();
|
||||
|
||||
const auto squares = LtsCoordTrans::getMgrsSquares(QRectF(topLeft, bottomRight), false, false);
|
||||
|
||||
QStringList src;
|
||||
src.reserve(squares.size());
|
||||
for (const auto &utm : squares)
|
||||
src += utm.mgrs(0);
|
||||
src.sort();
|
||||
qDebug() << "src: '" << src << "' expected: '" << coords << "'";
|
||||
QCOMPARE(src, coords);
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QStringList>
|
||||
|
||||
class coordtrans_test : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private Q_SLOTS:
|
||||
void initTestCase();
|
||||
void cleanupTestCase();
|
||||
void testFromGeographic();
|
||||
void testMgrsFromGeographic();
|
||||
|
||||
void testRelativeMetricalOffet_data();
|
||||
void testRelativeMetricalOffet();
|
||||
|
||||
void testAddMarginToArea();
|
||||
void testIncreaseRect();
|
||||
void testIncreaseRect2();
|
||||
|
||||
void testGeographicFromMgrs();
|
||||
void testMgrsSquares();
|
||||
|
||||
void testMgrsSquaresWithSurrounding();
|
||||
|
||||
private:
|
||||
void checkArea(const QString &base, int xCenter, int yCenter, int width, int height, const QStringList &coords);
|
||||
};
|
||||
@@ -1,186 +0,0 @@
|
||||
|
||||
|
||||
#include "lts_coord_widget.h"
|
||||
|
||||
#include "lts_coord_widget_p.h"
|
||||
|
||||
#include <LtsCoordTrans/lts_coord_trans.h>
|
||||
#include <QtWidgets/QToolButton>
|
||||
|
||||
namespace LtsCoordWidget
|
||||
{
|
||||
|
||||
LtsCoordWidget::LtsCoordWidget(DisplayType dt, QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, m_displayType(dt)
|
||||
{
|
||||
setFocusPolicy(Qt::StrongFocus);
|
||||
rebuildUi();
|
||||
}
|
||||
|
||||
void LtsCoordWidget::setCoordinate(const QPointF &geoCoord, bool bUseAsDefaultValue)
|
||||
{
|
||||
if (m_coordinate != geoCoord)
|
||||
emit coordinateChanged(geoCoord);
|
||||
if (bUseAsDefaultValue)
|
||||
m_defaultCoordinate = geoCoord;
|
||||
if (m_inputWidgetHandler)
|
||||
m_inputWidgetHandler->setCoordinate(geoCoord);
|
||||
}
|
||||
|
||||
void LtsCoordWidget::clear()
|
||||
{
|
||||
if (m_inputWidgetHandler)
|
||||
m_inputWidgetHandler->clear();
|
||||
}
|
||||
|
||||
void LtsCoordWidget::setCoordinate(double lon, double lat, bool bUseAsDefaultValue)
|
||||
{
|
||||
setCoordinate(QPointF(lon, lat), bUseAsDefaultValue);
|
||||
}
|
||||
|
||||
QPointF LtsCoordWidget::coordinate() const
|
||||
{
|
||||
if (!m_inputWidgetHandler)
|
||||
return QPointF();
|
||||
return m_inputWidgetHandler->coordinate();
|
||||
}
|
||||
|
||||
LtsCoordWidget::DisplayType LtsCoordWidget::displayType() const
|
||||
{
|
||||
return m_displayType;
|
||||
}
|
||||
|
||||
void LtsCoordWidget::setDisplayType(LtsCoordWidget::DisplayType dt)
|
||||
{
|
||||
if (m_displayType == dt)
|
||||
return;
|
||||
m_displayType = dt;
|
||||
rebuildUi();
|
||||
}
|
||||
|
||||
bool LtsCoordWidget::withResetButton() const
|
||||
{
|
||||
return m_bWithResetButton;
|
||||
}
|
||||
|
||||
void LtsCoordWidget::setWithResetButton(bool bWith)
|
||||
{
|
||||
if (m_bWithResetButton == bWith)
|
||||
return;
|
||||
m_bWithResetButton = bWith;
|
||||
if (m_inputWidgetHandler)
|
||||
m_inputWidgetHandler->resetButton()->setVisible(m_bWithResetButton);
|
||||
}
|
||||
|
||||
bool LtsCoordWidget::showToolTip() const
|
||||
{
|
||||
return m_bShowToolTip;
|
||||
}
|
||||
|
||||
void LtsCoordWidget::setShowToolTip(bool bShow)
|
||||
{
|
||||
if (m_bShowToolTip == bShow)
|
||||
return;
|
||||
m_bShowToolTip = bShow;
|
||||
|
||||
updateToolTip();
|
||||
}
|
||||
|
||||
bool LtsCoordWidget::mgrsSquareEditable() const
|
||||
{
|
||||
return m_bMgrsSquareEditable;
|
||||
}
|
||||
|
||||
void LtsCoordWidget::setMgrsSquareEditable(bool bEditable)
|
||||
{
|
||||
if (m_bMgrsSquareEditable == bEditable)
|
||||
return;
|
||||
m_bMgrsSquareEditable = bEditable;
|
||||
if (m_inputWidgetHandler)
|
||||
m_inputWidgetHandler->setSquaresEditable(bEditable);
|
||||
}
|
||||
|
||||
void LtsCoordWidget::setWithSurroundingMgrsSquares(bool bEnable)
|
||||
{
|
||||
if (m_inputWidgetHandler)
|
||||
m_inputWidgetHandler->setWithSurroundingSquare(bEnable);
|
||||
}
|
||||
|
||||
void LtsCoordWidget::setMgrsSquares(const QVector<LtsCoordTrans::UtmCoordinate> &geoCoords)
|
||||
{
|
||||
if (m_inputWidgetHandler)
|
||||
m_inputWidgetHandler->setMgrsSquares(geoCoords);
|
||||
}
|
||||
|
||||
bool LtsCoordWidget::event(QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::ToolTip)
|
||||
updateToolTip();
|
||||
return QWidget::event(event);
|
||||
}
|
||||
|
||||
void LtsCoordWidget::rebuildUi()
|
||||
{
|
||||
|
||||
if (m_inputWidgetHandler)
|
||||
{
|
||||
m_inputWidgetHandler->cleanup();
|
||||
delete m_inputWidgetHandler;
|
||||
delete layout();
|
||||
}
|
||||
|
||||
switch (m_displayType)
|
||||
{
|
||||
case DisplayType::MGRS5:
|
||||
m_inputWidgetHandler = new MgrsEdit(5, this);
|
||||
break;
|
||||
case DisplayType::MGRS7:
|
||||
m_inputWidgetHandler = new MgrsEdit(7, this);
|
||||
break;
|
||||
case DisplayType::UTM:
|
||||
|
||||
qt_assert("DisplayType::UTM not yet implemented", __FILE__, __LINE__);
|
||||
break;
|
||||
case DisplayType::WGS84:
|
||||
m_inputWidgetHandler = new Wgs84Edit(this);
|
||||
break;
|
||||
}
|
||||
if (!m_inputWidgetHandler)
|
||||
return;
|
||||
|
||||
m_inputWidgetHandler->setSquaresEditable(m_bMgrsSquareEditable);
|
||||
m_inputWidgetHandler->resetButton()->setVisible(m_bWithResetButton);
|
||||
connect(m_inputWidgetHandler->resetButton(), &QToolButton::clicked, this, &LtsCoordWidget::onResetToDefaultCoordinate);
|
||||
connect(m_inputWidgetHandler, &LtsCoordInputWidgetHandler::coordinateChanged, this, &LtsCoordWidget::coordinateChanged);
|
||||
connect(m_inputWidgetHandler, &LtsCoordInputWidgetHandler::invalidCoordinate, this, &LtsCoordWidget::invalidCoordinate);
|
||||
if (!m_defaultCoordinate.isNull())
|
||||
m_inputWidgetHandler->setCoordinate(m_defaultCoordinate);
|
||||
}
|
||||
|
||||
void LtsCoordWidget::updateToolTip()
|
||||
{
|
||||
QString tt;
|
||||
if (m_bShowToolTip)
|
||||
{
|
||||
const QPointF p(coordinate());
|
||||
if (!p.isNull())
|
||||
{
|
||||
const QString mgrs = LtsCoordTrans::mgrsFromGeographic(p.x(), p.y());
|
||||
const QPointF p2(p * LtsCoordTrans::rad2deg());
|
||||
tt = tr("MGRS: %1\nlat/lon: %2/%3").arg(mgrs).arg(p2.y(), 0, 'f', 10).arg(p2.x(), 0, 'f', 10);
|
||||
}
|
||||
}
|
||||
setToolTip(tt);
|
||||
}
|
||||
|
||||
void LtsCoordWidget::onResetToDefaultCoordinate()
|
||||
{
|
||||
if (!m_inputWidgetHandler)
|
||||
return;
|
||||
if (m_defaultCoordinate.isNull())
|
||||
m_inputWidgetHandler->clear();
|
||||
m_inputWidgetHandler->setCoordinate(m_defaultCoordinate);
|
||||
}
|
||||
|
||||
} // namespace LtsCoordWidget
|
||||
@@ -1,77 +0,0 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
#include <LtsCoordTrans/lts_coord_trans.h>
|
||||
#include <LtsCoordTrans/ltscoordwidget_export.h>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtWidgets/QWidget>
|
||||
|
||||
class QToolButton;
|
||||
|
||||
namespace LtsCoordWidget
|
||||
{
|
||||
class LtsCoordInputWidgetHandler;
|
||||
|
||||
class LTSCOORDWIDGET_EXPORT LtsCoordWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum class DisplayType
|
||||
{
|
||||
MGRS5,
|
||||
MGRS7,
|
||||
UTM,
|
||||
WGS84,
|
||||
MGRS = DisplayType::MGRS5
|
||||
};
|
||||
Q_ENUM(DisplayType)
|
||||
Q_PROPERTY(DisplayType displayType READ displayType WRITE setDisplayType)
|
||||
Q_PROPERTY(bool withResetButton READ withResetButton WRITE setWithResetButton)
|
||||
Q_PROPERTY(bool showToolTip READ showToolTip WRITE setShowToolTip)
|
||||
Q_PROPERTY(bool mgrsSquareEditable READ mgrsSquareEditable WRITE setMgrsSquareEditable)
|
||||
|
||||
explicit LtsCoordWidget(QWidget *parent = nullptr)
|
||||
: LtsCoordWidget(LtsCoordWidget::DisplayType::MGRS, parent)
|
||||
{
|
||||
}
|
||||
|
||||
explicit LtsCoordWidget(DisplayType dt, QWidget *parent = nullptr);
|
||||
|
||||
QPointF coordinate() const;
|
||||
DisplayType displayType() const;
|
||||
bool withResetButton() const;
|
||||
bool showToolTip() const;
|
||||
bool mgrsSquareEditable() const;
|
||||
bool event(QEvent *event) override;
|
||||
public Q_SLOTS:
|
||||
|
||||
void setCoordinate(const QPointF &geoCoord, bool bUseAsDefaultValue = true);
|
||||
void setCoordinate(double lon, double lat, bool bUseAsDefaultValue = true);
|
||||
void setDisplayType(LtsCoordWidget::DisplayType dt);
|
||||
void setWithResetButton(bool bWith);
|
||||
void setShowToolTip(bool bShow);
|
||||
void setMgrsSquareEditable(bool bEditable);
|
||||
void setWithSurroundingMgrsSquares(bool bEnable);
|
||||
void setMgrsSquares(const QVector<LtsCoordTrans::UtmCoordinate> &geoCoords);
|
||||
void clear();
|
||||
|
||||
Q_SIGNALS:
|
||||
void coordinateChanged(const QPointF &newGeoCoord);
|
||||
void invalidCoordinate();
|
||||
|
||||
private:
|
||||
void rebuildUi();
|
||||
void updateToolTip();
|
||||
private Q_SLOTS:
|
||||
void onResetToDefaultCoordinate();
|
||||
|
||||
private:
|
||||
bool m_bWithResetButton = false;
|
||||
bool m_bShowToolTip = true;
|
||||
bool m_bMgrsSquareEditable = false;
|
||||
LtsCoordWidget::DisplayType m_displayType = LtsCoordWidget::DisplayType::MGRS;
|
||||
LtsCoordInputWidgetHandler *m_inputWidgetHandler = nullptr;
|
||||
QPointF m_coordinate;
|
||||
QPointF m_defaultCoordinate;
|
||||
};
|
||||
} // namespace LtsCoordWidget
|
||||
@@ -1,55 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Mgrs</class>
|
||||
<widget class="QWidget" name="Mgrs">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>322</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cbxZone"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="leEast">
|
||||
<property name="toolTip">
|
||||
<string>Pos X</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="leNorth">
|
||||
<property name="toolTip">
|
||||
<string>Pos Y</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="tbReset">
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:/style/arrow_back.svg</normaloff>:/style/arrow_back.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,304 +0,0 @@
|
||||
|
||||
|
||||
#include "lts_coord_widget_p.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace LtsCoordWidget
|
||||
{
|
||||
|
||||
void LtsCoordInputWidgetHandler::onCoordinateDataChanged()
|
||||
{
|
||||
const QPointF coord(coordinate());
|
||||
if (coord.isNull())
|
||||
{
|
||||
emit invalidCoordinate();
|
||||
return;
|
||||
}
|
||||
emit coordinateChanged(coord);
|
||||
}
|
||||
|
||||
MgrsEdit::MgrsEdit(int precision, QWidget *widget)
|
||||
: LtsCoordInputWidgetHandler(widget)
|
||||
, m_precision(precision)
|
||||
, m_ui(new Ui::Mgrs)
|
||||
{
|
||||
m_ui->setupUi(widget);
|
||||
|
||||
if (m_precision < 0)
|
||||
m_precision = 0;
|
||||
if (m_precision > 11)
|
||||
m_precision = 11;
|
||||
const int upperLimit = pow(10, m_precision) - 1;
|
||||
m_ui->leEast->setValidator(new QIntValidator(0, upperLimit, m_ui->leEast));
|
||||
m_ui->leNorth->setValidator(new QIntValidator(0, upperLimit, m_ui->leNorth));
|
||||
setDefaultMgrsSquares();
|
||||
|
||||
connect(m_ui->cbxZone, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &MgrsEdit::onCoordinateDataChanged);
|
||||
connect(m_ui->leEast, &QLineEdit::editingFinished, this, &MgrsEdit::onCoordinateDataChanged);
|
||||
connect(m_ui->leNorth, &QLineEdit::editingFinished, this, &MgrsEdit::onCoordinateDataChanged);
|
||||
}
|
||||
|
||||
MgrsEdit::~MgrsEdit()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
bool MgrsEdit::isValid()
|
||||
{
|
||||
|
||||
const QString &east = m_ui->leEast->text();
|
||||
if (east.size() != m_precision)
|
||||
return false;
|
||||
|
||||
const QString &north = m_ui->leNorth->text();
|
||||
if (north.size() != m_precision)
|
||||
return false;
|
||||
|
||||
if (m_ui->cbxZone->currentIndex() < 0)
|
||||
return false;
|
||||
|
||||
if (m_ui->cbxZone->currentText().isEmpty())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MgrsEdit::setCoordinate(const QPointF &geoCoord)
|
||||
{
|
||||
const QString mgrsString = LtsCoordTrans::mgrsFromGeographic(geoCoord.x(), geoCoord.y(), m_precision, false);
|
||||
if (mgrsString.isEmpty())
|
||||
{
|
||||
m_ui->leEast->clear();
|
||||
m_ui->leNorth->clear();
|
||||
return;
|
||||
}
|
||||
|
||||
m_ui->leEast->setText(QString());
|
||||
m_ui->leNorth->setText(QString());
|
||||
|
||||
const QString mgrsSquare = mgrsString.left(3) + QLatin1Char(' ') + mgrsString.mid(3, 2);
|
||||
QString east = mgrsString.mid(5, m_precision);
|
||||
QString north = mgrsString.mid(5 + m_precision, m_precision);
|
||||
int idx = m_ui->cbxZone->findText(mgrsSquare);
|
||||
if (idx < 0)
|
||||
{
|
||||
addMgrsSquare(mgrsSquare);
|
||||
idx = m_ui->cbxZone->findText(mgrsSquare);
|
||||
}
|
||||
m_ui->cbxZone->setCurrentIndex(idx);
|
||||
m_ui->leEast->setText(east);
|
||||
m_ui->leNorth->setText(north);
|
||||
}
|
||||
|
||||
static inline QString getMgrsCoord(QLineEdit *le, int prec)
|
||||
{
|
||||
QString ret = le->text();
|
||||
if (ret.isEmpty())
|
||||
return ret;
|
||||
while (ret.size() < prec)
|
||||
ret += QLatin1Char('0');
|
||||
le->setText(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
QPointF MgrsEdit::coordinate() const
|
||||
{
|
||||
const QString east = getMgrsCoord(m_ui->leEast, m_precision);
|
||||
const QString north = getMgrsCoord(m_ui->leNorth, m_precision);
|
||||
if (east.isEmpty() || north.isEmpty() || m_ui->cbxZone->currentIndex() < 0)
|
||||
return QPointF();
|
||||
|
||||
const QString mgrsString(m_ui->cbxZone->currentText() + east + north);
|
||||
return LtsCoordTrans::geographicFromMgrs(mgrsString);
|
||||
}
|
||||
|
||||
QToolButton *MgrsEdit::resetButton()
|
||||
{
|
||||
return m_ui->tbReset;
|
||||
}
|
||||
|
||||
void MgrsEdit::cleanup()
|
||||
{
|
||||
|
||||
delete m_ui->horizontalLayout;
|
||||
delete m_ui->cbxZone;
|
||||
delete m_ui->leEast;
|
||||
delete m_ui->leNorth;
|
||||
delete m_ui->tbReset;
|
||||
}
|
||||
|
||||
void MgrsEdit::clear()
|
||||
{
|
||||
m_ui->cbxZone->clear();
|
||||
m_ui->leEast->clear();
|
||||
m_ui->leNorth->clear();
|
||||
setDefaultMgrsSquares();
|
||||
}
|
||||
|
||||
void MgrsEdit::setSquaresEditable(bool bEditable)
|
||||
{
|
||||
m_ui->cbxZone->setEditable(bEditable);
|
||||
}
|
||||
|
||||
void MgrsEdit::setWithSurroundingSquare(bool bEnabled)
|
||||
{
|
||||
m_withMgrsSquareOffset = bEnabled;
|
||||
}
|
||||
|
||||
static QStringList defaultMgrsSquares()
|
||||
{
|
||||
const QVector<LtsCoordTrans::UtmCoordinate> squares(LtsCoordTrans::defaultMgrsSquares());
|
||||
QStringList sl;
|
||||
sl.reserve(squares.size());
|
||||
for (const LtsCoordTrans::UtmCoordinate &c : squares)
|
||||
sl += c.mgrs(0);
|
||||
std::sort(sl.begin(), sl.end());
|
||||
return sl;
|
||||
}
|
||||
|
||||
static QString preferedMgrsSquare()
|
||||
{
|
||||
const LtsCoordTrans::UtmCoordinate c(LtsCoordTrans::preferedMgrsSquare());
|
||||
return c.mgrs(0);
|
||||
}
|
||||
|
||||
void MgrsEdit::setDefaultMgrsSquares()
|
||||
{
|
||||
m_ui->cbxZone->addItems(defaultMgrsSquares());
|
||||
m_ui->cbxZone->setCurrentIndex(m_ui->cbxZone->findText(preferedMgrsSquare()));
|
||||
}
|
||||
|
||||
void MgrsEdit::addMgrsSquare(const QString &newMgrsSquare)
|
||||
{
|
||||
QStringList sl = defaultMgrsSquares();
|
||||
sl += newMgrsSquare;
|
||||
if (m_withMgrsSquareOffset)
|
||||
{
|
||||
QStringList squares = utmCoordsToList(LtsCoordTrans::defaultMgrsSquareWithOffsets());
|
||||
|
||||
for (const auto &sq : std::as_const(squares))
|
||||
if (!sl.contains(sq))
|
||||
sl.append(sq);
|
||||
}
|
||||
std::sort(sl.begin(), sl.end());
|
||||
m_ui->cbxZone->clear();
|
||||
m_ui->cbxZone->addItems(sl);
|
||||
}
|
||||
|
||||
QStringList MgrsEdit::utmCoordsToList(const QVector<LtsCoordTrans::UtmCoordinate> &coords)
|
||||
{
|
||||
QStringList list;
|
||||
list.reserve(coords.count());
|
||||
for (const auto &utm : coords)
|
||||
list.append(utm.mgrs(0));
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
void MgrsEdit::setMgrsSquares(const QVector<LtsCoordTrans::UtmCoordinate> &geoCoords)
|
||||
{
|
||||
QStringList sl = utmCoordsToList(geoCoords);
|
||||
if (sl.isEmpty())
|
||||
return;
|
||||
|
||||
std::sort(sl.begin(), sl.end());
|
||||
m_ui->cbxZone->clear();
|
||||
m_ui->cbxZone->addItems(sl);
|
||||
}
|
||||
|
||||
Wgs84Edit::Wgs84Edit(QWidget *widget)
|
||||
: LtsCoordInputWidgetHandler(widget)
|
||||
, m_ui(new Ui::Wgs84)
|
||||
{
|
||||
m_ui->setupUi(widget);
|
||||
|
||||
DoubleValidator *v = new DoubleValidator(-180, 180, 9, m_ui->leLon);
|
||||
v->setNotation(QDoubleValidator::StandardNotation);
|
||||
m_ui->leLon->setValidator(v);
|
||||
|
||||
v = new DoubleValidator(-180, 180, 9, m_ui->leLat);
|
||||
v->setNotation(QDoubleValidator::StandardNotation);
|
||||
m_ui->leLat->setValidator(v);
|
||||
|
||||
connect(m_ui->leLon, &QLineEdit::editingFinished, this, &Wgs84Edit::onCoordinateDataChanged);
|
||||
connect(m_ui->leLat, &QLineEdit::editingFinished, this, &Wgs84Edit::onCoordinateDataChanged);
|
||||
}
|
||||
|
||||
Wgs84Edit::~Wgs84Edit()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
bool Wgs84Edit::isValid()
|
||||
{
|
||||
|
||||
return (!m_ui->leLon->text().isEmpty()) && (!m_ui->leLat->text().isEmpty());
|
||||
}
|
||||
|
||||
void Wgs84Edit::setCoordinate(const QPointF &geoCoord)
|
||||
{
|
||||
const QPointF coord(geoCoord * LtsCoordTrans::rad2deg());
|
||||
const QLocale l;
|
||||
m_ui->leLon->setText(l.toString(coord.x(), 'f', 9));
|
||||
m_ui->leLat->setText(l.toString(coord.y(), 'f', 9));
|
||||
}
|
||||
|
||||
QPointF Wgs84Edit::coordinate() const
|
||||
{
|
||||
QPointF ret;
|
||||
const QLocale l;
|
||||
|
||||
const QString lonStr = m_ui->leLon->text().remove(l.groupSeparator());
|
||||
const QString latStr = m_ui->leLat->text().remove(l.groupSeparator());
|
||||
if (lonStr.isEmpty() || latStr.isEmpty())
|
||||
return ret;
|
||||
|
||||
ret.rx() = l.toDouble(lonStr);
|
||||
ret.ry() = l.toDouble(latStr);
|
||||
|
||||
return ret * LtsCoordTrans::deg2rad();
|
||||
}
|
||||
|
||||
QToolButton *Wgs84Edit::resetButton()
|
||||
{
|
||||
return m_ui->tbReset;
|
||||
}
|
||||
|
||||
void Wgs84Edit::cleanup()
|
||||
{
|
||||
|
||||
delete m_ui->horizontalLayout;
|
||||
delete m_ui->leLon;
|
||||
delete m_ui->leLat;
|
||||
delete m_ui->tbReset;
|
||||
delete m_ui->lblLon;
|
||||
delete m_ui->lblLat;
|
||||
}
|
||||
|
||||
void Wgs84Edit::clear()
|
||||
{
|
||||
m_ui->leLon->clear();
|
||||
m_ui->leLat->clear();
|
||||
}
|
||||
|
||||
DoubleValidator::DoubleValidator(double bottom, double top, int decimals, QObject *parent)
|
||||
: QDoubleValidator(bottom, top, decimals, parent)
|
||||
{
|
||||
}
|
||||
|
||||
QValidator::State DoubleValidator::validate(QString &input, int &pos) const
|
||||
{
|
||||
const QValidator::State ret = QDoubleValidator::validate(input, pos);
|
||||
if (ret != QValidator::Acceptable)
|
||||
return ret;
|
||||
QLocale l;
|
||||
const QChar gs = l.groupSeparator().at(0);
|
||||
if (gs.isNull())
|
||||
return ret;
|
||||
if (input.contains(gs))
|
||||
return QValidator::Invalid;
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace LtsCoordWidget
|
||||
@@ -1,101 +0,0 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ui_lts_coord_widget_mgrs.h"
|
||||
#include "ui_lts_coord_widget_wgs84.h"
|
||||
|
||||
#include <LtsCoordTrans/lts_coord_trans.h>
|
||||
#include <QtWidgets/QComboBox>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtWidgets/QVBoxLayout>
|
||||
#include <QtWidgets/QWidget>
|
||||
|
||||
namespace LtsCoordWidget
|
||||
{
|
||||
class LtsCoordInputWidgetHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit LtsCoordInputWidgetHandler(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool isValid() = 0;
|
||||
virtual void setCoordinate(const QPointF &geoCoord) = 0;
|
||||
virtual QPointF coordinate() const = 0;
|
||||
virtual QToolButton *resetButton() = 0;
|
||||
virtual void cleanup() = 0;
|
||||
virtual void clear() = 0;
|
||||
virtual void setSquaresEditable(bool bEditable) = 0;
|
||||
virtual void setWithSurroundingSquare(bool bEnabled) = 0;
|
||||
virtual void setMgrsSquares(const QVector<LtsCoordTrans::UtmCoordinate> &geoCoords) = 0;
|
||||
protected Q_SLOTS:
|
||||
void onCoordinateDataChanged();
|
||||
Q_SIGNALS:
|
||||
void coordinateChanged(const QPointF &newGeoCoord);
|
||||
void invalidCoordinate();
|
||||
};
|
||||
|
||||
class MgrsEdit final : public LtsCoordInputWidgetHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit MgrsEdit(int precision, QWidget *widget);
|
||||
~MgrsEdit();
|
||||
|
||||
bool isValid() override;
|
||||
void setCoordinate(const QPointF &geoCoord) override;
|
||||
QPointF coordinate() const override;
|
||||
QToolButton *resetButton() override;
|
||||
void cleanup() override;
|
||||
void clear() override;
|
||||
void setSquaresEditable(bool bEditable) override;
|
||||
void setWithSurroundingSquare(bool bEnabled) override;
|
||||
void setMgrsSquares(const QVector<LtsCoordTrans::UtmCoordinate> &geoCoords) override;
|
||||
|
||||
private:
|
||||
void setDefaultMgrsSquares();
|
||||
void addMgrsSquare(const QString &newMgrsSquare);
|
||||
QStringList utmCoordsToList(const QVector<LtsCoordTrans::UtmCoordinate> &coords);
|
||||
|
||||
private:
|
||||
int m_precision;
|
||||
bool m_withMgrsSquareOffset = false;
|
||||
Ui::Mgrs *m_ui;
|
||||
};
|
||||
|
||||
class Wgs84Edit final : public LtsCoordInputWidgetHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit Wgs84Edit(QWidget *widget);
|
||||
~Wgs84Edit();
|
||||
|
||||
bool isValid() override;
|
||||
void setCoordinate(const QPointF &geoCoord) override;
|
||||
QPointF coordinate() const override;
|
||||
QToolButton *resetButton() override;
|
||||
void cleanup() override;
|
||||
void clear() override;
|
||||
|
||||
void setSquaresEditable(bool bEditable) override { Q_UNUSED(bEditable); }
|
||||
|
||||
void setWithSurroundingSquare(bool bEnabled) override { Q_UNUSED(bEnabled); }
|
||||
|
||||
void setMgrsSquares(const QVector<LtsCoordTrans::UtmCoordinate> &geoCoords) override { Q_UNUSED(geoCoords); }
|
||||
|
||||
private:
|
||||
Ui::Wgs84 *m_ui;
|
||||
};
|
||||
|
||||
class DoubleValidator final : public QDoubleValidator
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
DoubleValidator(double bottom, double top, int decimals, QObject *parent = nullptr);
|
||||
|
||||
QValidator::State validate(QString &input, int &pos) const override;
|
||||
};
|
||||
} // namespace LtsCoordWidget
|
||||
@@ -1,100 +0,0 @@
|
||||
|
||||
|
||||
#include "lts_coord_widget.h"
|
||||
|
||||
#include <LtsCoordTrans/lts_coord_trans.h>
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <QtWidgets/QDialog>
|
||||
#include <QtWidgets/QLabel>
|
||||
#include <QtWidgets/QPushButton>
|
||||
#include <QtWidgets/QVBoxLayout>
|
||||
|
||||
static void updateLabel(const QPointF &coord, QLabel *lbl, int prec)
|
||||
{
|
||||
QString mgrs = LtsCoordTrans::mgrsFromGeographic(coord.x(), coord.y(), prec);
|
||||
QString str =
|
||||
QStringLiteral("mgrs: %1, lon: %2, lat: %3").arg(mgrs).arg(coord.x() * LtsCoordTrans::rad2deg(), 0, 'f', 10).arg(coord.y() * LtsCoordTrans::rad2deg(), 0, 'f', 10);
|
||||
lbl->setText(str);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
|
||||
LtsCoordTrans::UtmCoordinate base(LtsCoordTrans::UtmCoordinate::fromMgrs(QStringLiteral("32UMD00")));
|
||||
QPointF topLeft(base.geographic(+50000, -50000));
|
||||
QPointF bottomRight(base.geographic(-50000, 50000));
|
||||
LtsCoordTrans::getMgrsSquares(QRectF(topLeft, bottomRight), true, true);
|
||||
|
||||
QDialog *dialog(new QDialog);
|
||||
QVBoxLayout *lay(new QVBoxLayout(dialog));
|
||||
|
||||
const QPointF defCoord(QPointF(53.0, 8.0) * LtsCoordTrans::deg2rad());
|
||||
|
||||
LtsCoordWidget::LtsCoordWidget *wMgrs5(new LtsCoordWidget::LtsCoordWidget(LtsCoordWidget::LtsCoordWidget::DisplayType::MGRS, dialog));
|
||||
wMgrs5->setWithResetButton(true);
|
||||
wMgrs5->setCoordinate(defCoord, true);
|
||||
lay->addWidget(wMgrs5);
|
||||
QLabel *lbl5(new QLabel(dialog));
|
||||
lay->addWidget(lbl5);
|
||||
QObject::connect(wMgrs5, &LtsCoordWidget::LtsCoordWidget::coordinateChanged, lbl5, [lbl5](const QPointF &coord) { updateLabel(coord, lbl5, 5); });
|
||||
|
||||
LtsCoordWidget::LtsCoordWidget *wMgrs7(new LtsCoordWidget::LtsCoordWidget(LtsCoordWidget::LtsCoordWidget::DisplayType::MGRS7, dialog));
|
||||
wMgrs7->setWithResetButton(true);
|
||||
wMgrs7->setCoordinate(defCoord, true);
|
||||
lay->addWidget(wMgrs7);
|
||||
QLabel *lbl7(new QLabel(dialog));
|
||||
lay->addWidget(lbl7);
|
||||
QObject::connect(wMgrs7, &LtsCoordWidget::LtsCoordWidget::coordinateChanged, wMgrs7, [lbl7](const QPointF &coord) { updateLabel(coord, lbl7, 7); });
|
||||
|
||||
LtsCoordWidget::LtsCoordWidget *w84(new LtsCoordWidget::LtsCoordWidget(LtsCoordWidget::LtsCoordWidget::DisplayType::WGS84, dialog));
|
||||
w84->setWithResetButton(true);
|
||||
w84->setCoordinate(defCoord, true);
|
||||
lay->addWidget(w84);
|
||||
QLabel *lbl84(new QLabel(dialog));
|
||||
lay->addWidget(lbl84);
|
||||
QObject::connect(w84, &LtsCoordWidget::LtsCoordWidget::coordinateChanged, w84, [lbl84](const QPointF &coord) { updateLabel(coord, lbl84, 11); });
|
||||
|
||||
QHBoxLayout *hLay = new QHBoxLayout;
|
||||
lay->addLayout(hLay);
|
||||
LtsCoordWidget::LtsCoordWidget *wChange(new LtsCoordWidget::LtsCoordWidget(LtsCoordWidget::LtsCoordWidget::DisplayType::WGS84, dialog));
|
||||
wChange->setWithResetButton(true);
|
||||
wChange->setCoordinate(defCoord, true);
|
||||
hLay->addWidget(wChange);
|
||||
QPushButton *pbReset(new QPushButton(QStringLiteral("With Reset"), dialog));
|
||||
hLay->addWidget(pbReset);
|
||||
QObject::connect(pbReset, &QPushButton::clicked, wChange, [wChange]() { wChange->setWithResetButton(!wChange->withResetButton()); });
|
||||
QPushButton *pbNext(new QPushButton(QStringLiteral("Next Type"), dialog));
|
||||
hLay->addWidget(pbNext);
|
||||
QObject::connect(pbNext,
|
||||
&QPushButton::clicked,
|
||||
wChange,
|
||||
[wChange]()
|
||||
{
|
||||
LtsCoordWidget::LtsCoordWidget::DisplayType dt = wChange->displayType();
|
||||
switch (dt)
|
||||
{
|
||||
case LtsCoordWidget::LtsCoordWidget::DisplayType::MGRS5:
|
||||
dt = LtsCoordWidget::LtsCoordWidget::DisplayType::MGRS7;
|
||||
break;
|
||||
case LtsCoordWidget::LtsCoordWidget::DisplayType::MGRS7:
|
||||
dt = LtsCoordWidget::LtsCoordWidget::DisplayType::WGS84;
|
||||
break;
|
||||
case LtsCoordWidget::LtsCoordWidget::DisplayType::WGS84:
|
||||
dt = LtsCoordWidget::LtsCoordWidget::DisplayType::MGRS5;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
wChange->setDisplayType(dt);
|
||||
});
|
||||
|
||||
QPushButton *pb(new QPushButton(QStringLiteral("Quit"), dialog));
|
||||
lay->addWidget(pb);
|
||||
QObject::connect(pb, &QPushButton::clicked, qApp, QCoreApplication::quit);
|
||||
|
||||
dialog->show();
|
||||
int ret = app.exec();
|
||||
delete dialog;
|
||||
return ret;
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Wgs84</class>
|
||||
<widget class="QWidget" name="Wgs84">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>293</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="lblLat">
|
||||
<property name="text">
|
||||
<string>Lat:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="leLat"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lblLon">
|
||||
<property name="text">
|
||||
<string>Lon:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="leLon"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="tbReset">
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>icon:arrow_back.svg</normaloff>icon:arrow_back.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,52 +0,0 @@
|
||||
|
||||
|
||||
#include <GeographicLib/MGRS.hpp>
|
||||
#include <GeographicLib/UTMUPS.hpp>
|
||||
#include <string>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc != 2)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s <mgrs>\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::string mgrs = argv[1];
|
||||
mgrs.erase(remove_if(mgrs.begin(), mgrs.end(), isspace), mgrs.end());
|
||||
|
||||
int prec;
|
||||
double lonDeg, latDeg;
|
||||
try
|
||||
{
|
||||
int zone;
|
||||
bool northp;
|
||||
double x, y;
|
||||
GeographicLib::MGRS::Reverse(mgrs, zone, northp, x, y, prec, true);
|
||||
GeographicLib::UTMUPS::Reverse(zone, northp, x, y, latDeg, lonDeg);
|
||||
|
||||
GeographicLib::UTMUPS::Forward(latDeg, lonDeg, zone, northp, x, y);
|
||||
GeographicLib::MGRS::Forward(zone, northp, x, y, prec, mgrs);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
fprintf(stderr, "Error converting %s to Lon/Lat coords\n", mgrs.c_str());
|
||||
return -2;
|
||||
}
|
||||
std::string part1, part2, part3, part4;
|
||||
part1 = mgrs.substr(0, 3);
|
||||
part2 = mgrs.substr(3, 2);
|
||||
part3 = mgrs.substr(5, prec);
|
||||
part4 = mgrs.substr(5 + prec, prec);
|
||||
fprintf(stdout,
|
||||
"%s %s %s %s = %13.10f, %13.10f ( %13.10f, %13.10f )\n",
|
||||
part1.c_str(),
|
||||
part2.c_str(),
|
||||
part3.c_str(),
|
||||
part4.c_str(),
|
||||
lonDeg,
|
||||
latDeg,
|
||||
lonDeg / 180. * M_PI,
|
||||
latDeg / 180. * M_PI);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
# Created by hjl, SLSE, 2016-05-31
|
||||
#
|
||||
|
||||
FIND_PACKAGE(OpenSSL)
|
||||
|
||||
SET(ltslicence_SRCS
|
||||
aes_crypt.cpp
|
||||
aes_crypt.h
|
||||
lts_licence.cpp
|
||||
lts_licence.h
|
||||
)
|
||||
|
||||
if(OPENSSL_FOUND)
|
||||
NGL_ADD_LIBRARY2(AAR SV WS LtsLicence SHARED ${ltslicence_SRCS})
|
||||
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(LtsLicence
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../
|
||||
)
|
||||
NGL_TARGET_LINK_LIBRARIES(LtsLicence
|
||||
PRIVATE
|
||||
${OPENSSL_LIBRARIES}
|
||||
Qt6::Xml
|
||||
NGLLogger
|
||||
PUBLIC
|
||||
Qt6::Core
|
||||
)
|
||||
|
||||
IF (BUILD_TESTING AND TARGET LtsLicence)
|
||||
ADD_EXECUTABLE(aes_crypt_test aes_crypt_test.cpp aes_crypt_test.h)
|
||||
TARGET_LINK_LIBRARIES(aes_crypt_test
|
||||
LtsLicence
|
||||
NGLLogger
|
||||
Qt6::Core
|
||||
Qt6::Test
|
||||
)
|
||||
ADD_TEST(NAME aes_crypt_test COMMAND $<TARGET_FILE:aes_crypt_test>)
|
||||
ENDIF()
|
||||
else()
|
||||
message(WARNING "LtsLicence skipped: OpenSSL not found")
|
||||
endif()
|
||||
@@ -1,185 +0,0 @@
|
||||
|
||||
|
||||
#include "aes_crypt.h"
|
||||
|
||||
#include <NGLLogger/NGLLoggerBootstrap.h>
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QRandomGenerator>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
|
||||
namespace LtsLicence
|
||||
{
|
||||
struct AesCryptPrivate
|
||||
{
|
||||
AesCryptPrivate()
|
||||
: passPhrase(QLatin1String("LTS " LTS_VERSION_MAJOR "." LTS_VERSION_MINOR))
|
||||
, logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("LtsLicenceLib.AesCrypt"))
|
||||
{
|
||||
#if OPENSSL_VERSION_NUMBER < 0x1010000fL
|
||||
ERR_load_crypto_strings();
|
||||
#endif
|
||||
}
|
||||
|
||||
~AesCryptPrivate()
|
||||
{
|
||||
#if OPENSSL_VERSION_NUMBER < 0x1010000fL
|
||||
ERR_free_strings();
|
||||
#endif
|
||||
}
|
||||
|
||||
QString passPhrase;
|
||||
NGL::INGLLogger &logger;
|
||||
};
|
||||
Q_GLOBAL_STATIC(AesCryptPrivate, s_Private)
|
||||
|
||||
void setPassPhrase(const QString &passPhrase)
|
||||
{
|
||||
s_Private->passPhrase = passPhrase;
|
||||
}
|
||||
|
||||
QString passPhrase()
|
||||
{
|
||||
return s_Private->passPhrase;
|
||||
}
|
||||
|
||||
QByteArray decryptData(const QByteArray &dataToDecrypt, const QString &pw, bool *bOk)
|
||||
{
|
||||
if (bOk)
|
||||
*bOk = false;
|
||||
|
||||
int ret;
|
||||
int outSize1 = 0;
|
||||
int outSize2 = 0;
|
||||
unsigned char key[32];
|
||||
|
||||
const QByteArray baPassword = pw.toUtf8();
|
||||
const unsigned char *dataPw = reinterpret_cast<const unsigned char *>(baPassword.data());
|
||||
int i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), nullptr, dataPw, baPassword.size(), 5, key, nullptr);
|
||||
if (i != 32)
|
||||
{
|
||||
ERROR_LOG(s_Private->logger) << "Wrong key size - should be 256 bits";
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
const QByteArray baSalt = dataToDecrypt.left(EVP_MAX_IV_LENGTH);
|
||||
const unsigned char *salt = reinterpret_cast<const unsigned char *>(baSalt.data());
|
||||
|
||||
const QByteArray bufEncrypted = dataToDecrypt.mid(EVP_MAX_IV_LENGTH);
|
||||
|
||||
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
|
||||
ret = EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, key, salt);
|
||||
if (ret == 0)
|
||||
{
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
char errbuf[256];
|
||||
ERR_error_string_n(ERR_get_error(), errbuf, sizeof(errbuf));
|
||||
ERROR_LOG(s_Private->logger) << "EVP_DecryptInit_ex failed";
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QByteArray bufDecrypted;
|
||||
bufDecrypted.resize(bufEncrypted.size() + EVP_CIPHER_CTX_block_size(ctx));
|
||||
const unsigned char *dataIn = reinterpret_cast<const unsigned char *>(bufEncrypted.data());
|
||||
unsigned char *dataOut = reinterpret_cast<unsigned char *>(bufDecrypted.data());
|
||||
|
||||
ret = EVP_DecryptUpdate(ctx, dataOut, &outSize1, dataIn, bufEncrypted.size());
|
||||
if (ret == 0)
|
||||
{
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
char errbuf[256];
|
||||
ERR_error_string_n(ERR_get_error(), errbuf, sizeof(errbuf));
|
||||
ERROR_LOG(s_Private->logger) << "EVP_DecryptUpdate failed";
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
ret = EVP_DecryptFinal_ex(ctx, dataOut + outSize1, &outSize2);
|
||||
if (ret == 0)
|
||||
{
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
char errbuf[256];
|
||||
ERR_error_string_n(ERR_get_error(), errbuf, sizeof(errbuf));
|
||||
ERROR_LOG(s_Private->logger) << "EVP_DecryptFinal_ex failed";
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
|
||||
bufDecrypted.resize(outSize1 + outSize2);
|
||||
|
||||
if (bOk)
|
||||
*bOk = true;
|
||||
return bufDecrypted;
|
||||
}
|
||||
|
||||
QByteArray encryptData(const QByteArray &dataToEncrypt, const QString &pw, bool *bOk)
|
||||
{
|
||||
if (bOk)
|
||||
*bOk = false;
|
||||
|
||||
int ret;
|
||||
int outSize1 = 0;
|
||||
int outSize2 = 0;
|
||||
unsigned char key[32];
|
||||
QByteArray bufEncrypted;
|
||||
|
||||
const QByteArray baPassword = pw.toUtf8();
|
||||
const unsigned char *dataPw = reinterpret_cast<const unsigned char *>(baPassword.data());
|
||||
int i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), nullptr, dataPw, baPassword.size(), 5, key, nullptr);
|
||||
if (i != 32)
|
||||
{
|
||||
ERROR_LOG(s_Private->logger) << "Wrong key size - should be 256 bits";
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QByteArray baSalt(EVP_MAX_IV_LENGTH, 0);
|
||||
for (int i = 0; i < EVP_MAX_IV_LENGTH; ++i)
|
||||
baSalt[i] = static_cast<char>(QRandomGenerator::global()->bounded(256));
|
||||
const unsigned char *salt = reinterpret_cast<const unsigned char *>(baSalt.data());
|
||||
|
||||
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
|
||||
ret = EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, key, salt);
|
||||
if (ret == 0)
|
||||
{
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
char errbuf[256];
|
||||
ERR_error_string_n(ERR_get_error(), errbuf, sizeof(errbuf));
|
||||
ERROR_LOG(s_Private->logger) << "EVP_EncryptInit_ex failed";
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
bufEncrypted = QByteArray::fromRawData(reinterpret_cast<const char *>(salt), EVP_MAX_IV_LENGTH);
|
||||
bufEncrypted.resize(bufEncrypted.size() + dataToEncrypt.size() + EVP_CIPHER_CTX_block_size(ctx));
|
||||
const unsigned char *dataIn = reinterpret_cast<const unsigned char *>(dataToEncrypt.data());
|
||||
unsigned char *dataOut = reinterpret_cast<unsigned char *>(bufEncrypted.data());
|
||||
dataOut += baSalt.size();
|
||||
ret = EVP_EncryptUpdate(ctx, dataOut, &outSize1, dataIn, dataToEncrypt.size());
|
||||
if (ret == 0)
|
||||
{
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
char errbuf[256];
|
||||
ERR_error_string_n(ERR_get_error(), errbuf, sizeof(errbuf));
|
||||
ERROR_LOG(s_Private->logger) << "EVP_EncryptUpdate failed";
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
ret = EVP_EncryptFinal_ex(ctx, dataOut + outSize1, &outSize2);
|
||||
if (ret == 0)
|
||||
{
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
char errbuf[256];
|
||||
ERR_error_string_n(ERR_get_error(), errbuf, sizeof(errbuf));
|
||||
ERROR_LOG(s_Private->logger) << "EVP_EncryptFinal_ex failed";
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
|
||||
bufEncrypted.resize(outSize1 + outSize2 + baSalt.size());
|
||||
|
||||
if (bOk)
|
||||
*bOk = true;
|
||||
return bufEncrypted;
|
||||
}
|
||||
|
||||
} // namespace LtsLicence
|
||||
@@ -1,18 +0,0 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ltslicence_export.h"
|
||||
|
||||
#include <QtCore/QString>
|
||||
|
||||
namespace LtsLicence
|
||||
{
|
||||
|
||||
LTSLICENCE_EXPORT void setPassPhrase(const QString &passPhrase);
|
||||
LTSLICENCE_EXPORT QString passPhrase();
|
||||
|
||||
LTSLICENCE_EXPORT QByteArray decryptData(const QByteArray &dataToDecrypt, const QString &pw = passPhrase(), bool *bOk = nullptr);
|
||||
|
||||
LTSLICENCE_EXPORT QByteArray encryptData(const QByteArray &dataToEncrypt, const QString &pw = passPhrase(), bool *bOk = nullptr);
|
||||
} // namespace LtsLicence
|
||||
@@ -1,53 +0,0 @@
|
||||
|
||||
|
||||
#include "aes_crypt_test.h"
|
||||
|
||||
#include "aes_crypt.h"
|
||||
|
||||
#include <NGLLogger/NGLLoggerBootstrap.h>
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtTest/QTest>
|
||||
#include <openssl/evp.h>
|
||||
|
||||
QTEST_MAIN(aes_crypt_test)
|
||||
|
||||
void aes_crypt_test::initTestCase()
|
||||
{
|
||||
NGL::NGLLoggerBootstrap::createNGLRootLogger("log4cxx.props", false);
|
||||
}
|
||||
|
||||
void aes_crypt_test::truePassTest()
|
||||
{
|
||||
qDebug("Simple TestCase");
|
||||
bool bOk;
|
||||
const QByteArray content("30.06.2013");
|
||||
const QString pw(QStringLiteral("aes_crypt_test"));
|
||||
const QByteArray enc = LtsLicence::encryptData(content, pw, &bOk);
|
||||
QVERIFY2(bOk, "Error encrypting data...");
|
||||
|
||||
QCOMPARE(((content.size() + 15 + EVP_MAX_IV_LENGTH) / 18) * 16, enc.size());
|
||||
const QByteArray dec = LtsLicence::decryptData(enc, pw, &bOk);
|
||||
QVERIFY2(bOk, "Error encrypting data...");
|
||||
QCOMPARE(dec, content);
|
||||
|
||||
const QByteArray bigContent(12345, '1');
|
||||
const QByteArray bigEnc = LtsLicence::encryptData(bigContent, pw, &bOk);
|
||||
QVERIFY2(bOk, "Error encrypting data...");
|
||||
|
||||
QCOMPARE(((bigContent.size() + 15 + EVP_MAX_IV_LENGTH) / 16) * 16, bigEnc.size());
|
||||
}
|
||||
|
||||
void aes_crypt_test::falsePassTest()
|
||||
{
|
||||
qDebug("False Password TestCase");
|
||||
bool bOk;
|
||||
const QByteArray content("30.06.2013");
|
||||
const QString pw(QStringLiteral("aes_crypt_test"));
|
||||
const QString pw2(QStringLiteral("aes_crypt_test2"));
|
||||
const QByteArray enc = LtsLicence::encryptData(content, pw, &bOk);
|
||||
QVERIFY2(bOk, "Error encrypting data...");
|
||||
QVERIFY2(enc.size() != 20, "Error encrypting data...");
|
||||
const QByteArray dec = LtsLicence::decryptData(enc, pw2, &bOk);
|
||||
QVERIFY2(!bOk, "Error encrypting data...");
|
||||
QVERIFY2(dec.isEmpty(), "decrypted data is not empty...");
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QObject>
|
||||
|
||||
class aes_crypt_test : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private Q_SLOTS:
|
||||
void initTestCase();
|
||||
void truePassTest();
|
||||
void falsePassTest();
|
||||
};
|
||||
@@ -1,146 +0,0 @@
|
||||
|
||||
|
||||
#include "lts_licence.h"
|
||||
|
||||
#include <NGLLogger/NGLLoggerBootstrap.h>
|
||||
#include <QtXml/QDomDocument>
|
||||
#include <QtCore/QObject>
|
||||
|
||||
namespace LtsLicence
|
||||
{
|
||||
static bool extractLicence(const QDomElement &licenceElement, QVector<Licence> &licenceVec);
|
||||
|
||||
static NGL::INGLLogger &getLogger()
|
||||
{
|
||||
return NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("LtsLicence");
|
||||
}
|
||||
|
||||
QVector<Licence> readLicences(const QByteArray &unencryptedXmlData)
|
||||
{
|
||||
QVector<Licence> licenceVec;
|
||||
|
||||
QDomDocument xmlDoc;
|
||||
|
||||
const auto parseResult = xmlDoc.setContent(unencryptedXmlData);
|
||||
if (!parseResult)
|
||||
{
|
||||
ERROR_LOG(getLogger()) << "Error reading xml data, "
|
||||
<< "error in line " << int(parseResult.errorLine) << ", column " << int(parseResult.errorColumn)
|
||||
<< ", message: " << parseResult.errorMessage;
|
||||
return licenceVec;
|
||||
}
|
||||
|
||||
INFO_LOG(getLogger()) << "Try to extract licences";
|
||||
|
||||
QDomElement licenceElement = xmlDoc.documentElement().firstChildElement(QLatin1String("licence"));
|
||||
|
||||
while (!licenceElement.isNull())
|
||||
{
|
||||
if (!extractLicence(licenceElement, licenceVec))
|
||||
{
|
||||
licenceVec.clear();
|
||||
return licenceVec;
|
||||
}
|
||||
|
||||
licenceElement = licenceElement.nextSiblingElement(QLatin1String("licence"));
|
||||
}
|
||||
return licenceVec;
|
||||
}
|
||||
|
||||
QByteArray writeUnencryptedLicences(const QVector<Licence> &licences)
|
||||
{
|
||||
QDomDocument xmlDoc;
|
||||
|
||||
QDomProcessingInstruction instr = xmlDoc.createProcessingInstruction(QLatin1String("xml"), QLatin1String("version='1.0' encoding='UTF-8' standalone='yes'"));
|
||||
xmlDoc.appendChild(instr);
|
||||
|
||||
QDomElement root = xmlDoc.createElement(QLatin1String("licences"));
|
||||
xmlDoc.appendChild(root);
|
||||
|
||||
for (int i = 0; i < licences.size(); ++i)
|
||||
{
|
||||
QDomElement lic = xmlDoc.createElement(QLatin1String("licence"));
|
||||
root.appendChild(lic);
|
||||
|
||||
QDomElement element = xmlDoc.createElement(QLatin1String("name"));
|
||||
QDomText text = xmlDoc.createTextNode(licences[i].name);
|
||||
element.appendChild(text);
|
||||
lic.appendChild(element);
|
||||
|
||||
element = xmlDoc.createElement(QLatin1String("ignoreMaxCount"));
|
||||
text = xmlDoc.createTextNode(QString::number(licences[i].ignoreMaxCount));
|
||||
element.appendChild(text);
|
||||
lic.appendChild(element);
|
||||
|
||||
element = xmlDoc.createElement(QLatin1String("ignoreExpiration"));
|
||||
text = xmlDoc.createTextNode(QString::number(licences[i].ignoreExpiration));
|
||||
element.appendChild(text);
|
||||
lic.appendChild(element);
|
||||
|
||||
element = xmlDoc.createElement(QLatin1String("maxCount"));
|
||||
text = xmlDoc.createTextNode(QString::number(licences[i].maxCount));
|
||||
element.appendChild(text);
|
||||
lic.appendChild(element);
|
||||
|
||||
const QLatin1String format("dd.MM.yyyy hh:mm:ss");
|
||||
const QString qs = licences[i].expiration.toString(format);
|
||||
|
||||
element = xmlDoc.createElement(QLatin1String("expiration"));
|
||||
text = xmlDoc.createTextNode(qs);
|
||||
element.appendChild(text);
|
||||
lic.appendChild(element);
|
||||
}
|
||||
INFO_LOG(getLogger()) << "Generated XML Data...\n" << xmlDoc.toByteArray();
|
||||
return xmlDoc.toByteArray();
|
||||
}
|
||||
|
||||
bool extractLicence(const QDomElement &licenceElement, QVector<Licence> &licenceVec)
|
||||
{
|
||||
Licence licence;
|
||||
|
||||
QDomElement tag = licenceElement.firstChildElement(QLatin1String("name"));
|
||||
licence.name = tag.text();
|
||||
|
||||
tag = licenceElement.firstChildElement(QLatin1String("ignoreMaxCount"));
|
||||
licence.ignoreMaxCount = tag.text().toInt();
|
||||
|
||||
tag = licenceElement.firstChildElement(QLatin1String("ignoreExpiration"));
|
||||
licence.ignoreExpiration = tag.text().toInt();
|
||||
|
||||
tag = licenceElement.firstChildElement(QLatin1String("maxCount"));
|
||||
licence.maxCount = tag.text().toInt();
|
||||
|
||||
tag = licenceElement.firstChildElement(QLatin1String("expiration"));
|
||||
|
||||
const QString qs(tag.text());
|
||||
|
||||
const QLatin1String format("dd.MM.yyyy hh:mm:ss");
|
||||
const QDateTime qdt = QDateTime::fromString(qs, format);
|
||||
|
||||
if (!qdt.isValid())
|
||||
{
|
||||
ERROR_LOG(getLogger()) << "Invalid expiration format! " << qs << " used format: " << format;
|
||||
return false;
|
||||
}
|
||||
|
||||
licence.expiration = qdt;
|
||||
INFO_LOG(getLogger()) << "Read licence for:'" << licence.name << "'"
|
||||
<< " IgnoreMaxCount: " << licence.ignoreMaxCount << " IgnoreExpiration: " << licence.ignoreExpiration << " MaxCount: " << licence.maxCount
|
||||
<< " Expiration: " << licence.expiration.date().toString() << " " << licence.expiration.time().toString()
|
||||
<< " RefCount: " << licence.licenceRefCount;
|
||||
|
||||
licenceVec.append(licence);
|
||||
return true;
|
||||
}
|
||||
|
||||
QString Licence::toString() const
|
||||
{
|
||||
return QObject::tr("Name: %1, Count: %2, ExpireDate: %3, Expires: %4, UseMaxCount: %5")
|
||||
.arg(name)
|
||||
.arg(maxCount)
|
||||
.arg(expiration.toString())
|
||||
.arg(ignoreExpiration)
|
||||
.arg(ignoreMaxCount);
|
||||
}
|
||||
|
||||
} // namespace LtsLicence
|
||||
@@ -1,29 +0,0 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ltslicence_export.h"
|
||||
|
||||
#include <QtCore/QDateTime>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QVector>
|
||||
|
||||
namespace LtsLicence
|
||||
{
|
||||
|
||||
struct LTSLICENCE_EXPORT Licence
|
||||
{
|
||||
QString name;
|
||||
bool ignoreMaxCount = false;
|
||||
bool ignoreExpiration = false;
|
||||
int maxCount = 0;
|
||||
QDateTime expiration;
|
||||
int licenceRefCount = 0;
|
||||
|
||||
QString toString() const;
|
||||
};
|
||||
|
||||
LTSLICENCE_EXPORT QVector<Licence> readLicences(const QByteArray &unencryptedXmlData);
|
||||
|
||||
LTSLICENCE_EXPORT QByteArray writeUnencryptedLicences(const QVector<Licence> &licences);
|
||||
} // namespace LtsLicence
|
||||
@@ -1,38 +0,0 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
# Created by Mike Wille, SLSE, 2016-01-13
|
||||
#
|
||||
|
||||
|
||||
# Make ${Qt6_Widgets} optional
|
||||
if(QT6_GUI_AVAILABLE AND TARGET Qt6::Widgets)
|
||||
set(Qt6_Widgets ${Qt6_Widgets})
|
||||
else()
|
||||
set(Qt6_Widgets "")
|
||||
endif()
|
||||
|
||||
|
||||
SET(LtsNoti_SRCS
|
||||
lts_notification.h
|
||||
lts_notification.cpp
|
||||
lts_notification_ctl.h
|
||||
lts_notification_ctl.cpp
|
||||
)
|
||||
|
||||
NGL_ADD_LIBRARY2(WS LtsNotification SHARED ${LtsNoti_SRCS})
|
||||
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(LtsNotification
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../
|
||||
${CMAKE_CURRENT_BINARY_DIR}/../
|
||||
)
|
||||
|
||||
if(QT6_GUI_AVAILABLE)
|
||||
NGL_TARGET_LINK_LIBRARIES(LtsNotification
|
||||
${Qt6_Widgets}
|
||||
)
|
||||
endif()
|
||||
|
||||
NGL_INSTALL_TARGET(LtsNotification)
|
||||
@@ -1,66 +0,0 @@
|
||||
|
||||
|
||||
#include "lts_notification.h"
|
||||
|
||||
#include "lts_notification_ctl.h"
|
||||
|
||||
#include <QtGui/QIcon>
|
||||
|
||||
namespace LtsNotification
|
||||
{
|
||||
|
||||
LtsNotification::LtsNotification(LtsNotificationController *ctl)
|
||||
: QObject()
|
||||
, m_controller(ctl)
|
||||
{
|
||||
connect(ctl, &LtsNotificationController::destroyed, this, &LtsNotification::slotCtlDestroyed);
|
||||
}
|
||||
|
||||
LtsNotification::~LtsNotification()
|
||||
{
|
||||
delete m_controller;
|
||||
}
|
||||
|
||||
void LtsNotification::setIcon(const QIcon &icon)
|
||||
{
|
||||
m_controller->setIcon(icon);
|
||||
}
|
||||
|
||||
void LtsNotification::setAction(const std::function<void(void)> &action)
|
||||
{
|
||||
m_controller->setAction(action);
|
||||
}
|
||||
|
||||
void LtsNotification::setToolTip(const QString &toolTip)
|
||||
{
|
||||
m_controller->setToolTip(toolTip);
|
||||
}
|
||||
|
||||
const QString &LtsNotification::tooltip() const
|
||||
{
|
||||
return m_controller->tooltip();
|
||||
}
|
||||
|
||||
void LtsNotification::setCount(const int count)
|
||||
{
|
||||
m_controller->setCount(count);
|
||||
}
|
||||
|
||||
void LtsNotification::setEnabled(bool enable)
|
||||
{
|
||||
m_controller->setEnabled(enable);
|
||||
}
|
||||
|
||||
void LtsNotification::setBackground(const int r, const int g, const int b)
|
||||
{
|
||||
m_controller->setBackground(r, g, b);
|
||||
}
|
||||
|
||||
void LtsNotification::slotCtlDestroyed(QObject *obj)
|
||||
{
|
||||
(void)obj;
|
||||
|
||||
m_controller = nullptr;
|
||||
}
|
||||
|
||||
} // namespace LtsNotification
|
||||
@@ -1,45 +0,0 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lts_notification_export.h"
|
||||
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QObject>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
namespace LtsSession
|
||||
{
|
||||
class LtsSession;
|
||||
}
|
||||
|
||||
namespace LtsNotification
|
||||
{
|
||||
class LtsNotificationController;
|
||||
|
||||
class LTSNOTIFICATION_EXPORT LtsNotification : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LtsNotification(LtsNotificationController *ctl);
|
||||
~LtsNotification();
|
||||
|
||||
void setIcon(const QIcon &icon);
|
||||
void setAction(const std::function<void(void)> &action);
|
||||
void setToolTip(const QString &toolTip);
|
||||
void setCount(const int count);
|
||||
void setEnabled(bool enable);
|
||||
void setBackground(const int r, const int g, const int b);
|
||||
|
||||
const QString &tooltip() const;
|
||||
|
||||
private:
|
||||
LtsNotificationController *m_controller;
|
||||
|
||||
private slots:
|
||||
void slotCtlDestroyed(QObject *obj);
|
||||
};
|
||||
|
||||
} // namespace LtsNotification
|
||||
@@ -1,160 +0,0 @@
|
||||
|
||||
|
||||
#include "lts_notification_ctl.h"
|
||||
|
||||
#include <QtGui/QColor>
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtGui/QIcon>
|
||||
#include <QtGui/QImage>
|
||||
#include <QtGui/QPainter>
|
||||
#include <QtWidgets/QToolButton>
|
||||
#include <utility>
|
||||
|
||||
namespace LtsNotification
|
||||
{
|
||||
|
||||
LtsNotificationController::LtsNotificationController(const QString &identifier)
|
||||
: QObject()
|
||||
, m_count(0)
|
||||
, m_identifier(QStringLiteral("LtsNotification%1").arg(identifier))
|
||||
{
|
||||
}
|
||||
|
||||
LtsNotificationController::~LtsNotificationController()
|
||||
{
|
||||
qDeleteAll(m_notiList);
|
||||
}
|
||||
|
||||
void LtsNotificationController::setIcon(const QIcon &icon)
|
||||
{
|
||||
m_icon = icon;
|
||||
|
||||
setAllIcons();
|
||||
}
|
||||
|
||||
void LtsNotificationController::setCount(const int count)
|
||||
{
|
||||
m_count = count;
|
||||
|
||||
setAllIcons();
|
||||
}
|
||||
|
||||
void LtsNotificationController::setBackground(const int r, const int g, const int b)
|
||||
{
|
||||
|
||||
for (QToolButton *tb : std::as_const(m_notiList))
|
||||
{
|
||||
|
||||
QString stylesheet;
|
||||
|
||||
if (r == -1 && g == -1 && b == -1)
|
||||
stylesheet = QStringLiteral("");
|
||||
else
|
||||
stylesheet = QStringLiteral("QToolButton {background-color: rgb(") + QString::number(r) + QStringLiteral(",") + QString::number(g) + QStringLiteral(",") +
|
||||
QString::number(b) + QStringLiteral(");}");
|
||||
|
||||
tb->setStyleSheet(stylesheet);
|
||||
}
|
||||
}
|
||||
|
||||
void LtsNotificationController::setEnabled(bool enable)
|
||||
{
|
||||
m_enable = enable;
|
||||
|
||||
setAllIcons();
|
||||
}
|
||||
|
||||
void LtsNotificationController::setAction(const std::function<void(void)> &action)
|
||||
{
|
||||
m_action = action;
|
||||
}
|
||||
|
||||
void LtsNotificationController::setToolTip(const QString &toolTip)
|
||||
{
|
||||
m_toolTip = toolTip;
|
||||
|
||||
for (QToolButton *tb : std::as_const(m_notiList))
|
||||
{
|
||||
tb->setToolTip(toolTip);
|
||||
tb->setIconSize(QSize(30, 30));
|
||||
}
|
||||
}
|
||||
|
||||
void LtsNotificationController::setAllIcons()
|
||||
{
|
||||
if (m_icon.isNull())
|
||||
return;
|
||||
|
||||
QIcon icon = modifyIcon(m_icon);
|
||||
|
||||
for (QToolButton *tb : std::as_const(m_notiList))
|
||||
{
|
||||
tb->setIcon(icon);
|
||||
tb->setIconSize(QSize(30, 30));
|
||||
tb->setEnabled(m_enable);
|
||||
}
|
||||
}
|
||||
|
||||
#define SIZE 40
|
||||
|
||||
QIcon LtsNotificationController::modifyIcon(const QIcon &icon)
|
||||
{
|
||||
|
||||
if (m_count < 1)
|
||||
return icon;
|
||||
|
||||
QPixmap iconImage(icon.pixmap(SIZE * 8 / 10, SIZE * 8 / 10));
|
||||
QPainter painter(&iconImage);
|
||||
|
||||
painter.save();
|
||||
painter.setRenderHints(QPainter::TextAntialiasing | QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
|
||||
|
||||
QFont f;
|
||||
f.setFamily(QStringLiteral("Monospace"));
|
||||
f.setPointSize(16);
|
||||
f.setBold(true);
|
||||
painter.setFont(f);
|
||||
|
||||
QColor color(Qt::red);
|
||||
painter.setBrush(color);
|
||||
painter.setPen(QPen(color, 3.1));
|
||||
painter.drawText(QRect(0, 0, 30, 30), QString::number(m_count));
|
||||
painter.restore();
|
||||
|
||||
return iconImage;
|
||||
}
|
||||
|
||||
QToolButton *LtsNotificationController::createWidget()
|
||||
{
|
||||
QToolButton *b = new QToolButton();
|
||||
b->setToolButtonStyle(Qt::ToolButtonIconOnly);
|
||||
b->setObjectName(m_identifier);
|
||||
|
||||
b->setMinimumSize(SIZE, SIZE);
|
||||
b->setMaximumSize(SIZE, SIZE);
|
||||
|
||||
connect(b, &QToolButton::destroyed, this, &LtsNotificationController::slotNotiWidgetDestroyed);
|
||||
connect(b,
|
||||
&QToolButton::clicked,
|
||||
this,
|
||||
[this]()
|
||||
{
|
||||
if (m_action)
|
||||
m_action();
|
||||
});
|
||||
|
||||
if (!m_icon.isNull())
|
||||
b->setIcon(modifyIcon(m_icon));
|
||||
|
||||
b->setToolTip(m_toolTip);
|
||||
|
||||
m_notiList.append(b);
|
||||
return b;
|
||||
}
|
||||
|
||||
void LtsNotificationController::slotNotiWidgetDestroyed(QObject *obj)
|
||||
{
|
||||
m_notiList.removeAll(static_cast<QToolButton *>(obj));
|
||||
}
|
||||
|
||||
} // namespace LtsNotification
|
||||
@@ -1,63 +0,0 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "lts_notification_export.h"
|
||||
|
||||
#include <QtGui/QIcon>
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QObject>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
class QToolButton;
|
||||
|
||||
namespace LtsSession
|
||||
{
|
||||
class LtsSession;
|
||||
}
|
||||
|
||||
namespace LtsNotification
|
||||
{
|
||||
class LtsNotificationWidget;
|
||||
|
||||
class LTSNOTIFICATION_EXPORT LtsNotificationController : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LtsNotificationController(const QString &identifier);
|
||||
~LtsNotificationController();
|
||||
|
||||
QToolButton *createWidget();
|
||||
|
||||
void setIcon(const QIcon &icon);
|
||||
void setAction(const std::function<void(void)> &action);
|
||||
void setToolTip(const QString &toolTip);
|
||||
void setCount(const int count);
|
||||
void setBackground(const int r, const int g, const int b);
|
||||
|
||||
const QString &identifier() const { return m_identifier; }
|
||||
|
||||
const QString &tooltip() const { return m_toolTip; }
|
||||
|
||||
void setEnabled(bool enable);
|
||||
|
||||
private:
|
||||
QList<QToolButton *> m_notiList;
|
||||
|
||||
QIcon m_icon;
|
||||
std::function<void(void)> m_action;
|
||||
QString m_toolTip;
|
||||
int m_count;
|
||||
bool m_enable{true};
|
||||
QString m_identifier;
|
||||
|
||||
void setAllIcons();
|
||||
QIcon modifyIcon(const QIcon &icon);
|
||||
|
||||
private slots:
|
||||
void slotNotiWidgetDestroyed(QObject *obj);
|
||||
};
|
||||
|
||||
} // namespace LtsNotification
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#ifndef LTSNOTIFICATION_EXPORT
|
||||
#ifdef BUILD_STATIC_LIBRARIES
|
||||
#define LTSNOTIFICATION_EXPORT
|
||||
#else
|
||||
#if defined(MAKE_LTSNOTIFICATION_LIB)
|
||||
#define LTSNOTIFICATION_EXPORT Q_DECL_EXPORT
|
||||
#else
|
||||
#define LTSNOTIFICATION_EXPORT Q_DECL_IMPORT
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,27 +0,0 @@
|
||||
#
|
||||
# Lightweight REST Client Framework
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
# Created by Hannes Fritsche, ESZS, 2026-08-21
|
||||
|
||||
#
|
||||
# --- Library LtsRestClient --------------------------------------------------------------------------------
|
||||
#
|
||||
SET(LtsRestClient_SRCS
|
||||
lts_rest_client.cpp
|
||||
lts_rest_client.h
|
||||
)
|
||||
|
||||
NGL_ADD_LIBRARY2(ALL LtsRestClient SHARED ${LtsRestClient_SRCS})
|
||||
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(LtsRestClient
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../
|
||||
)
|
||||
|
||||
NGL_TARGET_LINK_LIBRARIES(LtsRestClient
|
||||
PUBLIC
|
||||
Qt6::Core
|
||||
Qt6::Network
|
||||
)
|
||||
@@ -1,175 +0,0 @@
|
||||
/**
|
||||
* Lightweight REST Client Framework
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Hannes Fritsche, ESZS, 2026-08-21
|
||||
*/
|
||||
|
||||
#include "lts_rest_client.h"
|
||||
#include <QTimer>
|
||||
#include <QUrl>
|
||||
#include <QtNetwork/QNetworkAccessManager>
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
#include <QtNetwork/QNetworkRequest>
|
||||
|
||||
namespace LtsCommon
|
||||
{
|
||||
|
||||
LtsRestClient::LtsRestClient(const QString &baseUrl, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_baseUrl(baseUrl)
|
||||
, m_manager(new QNetworkAccessManager(this))
|
||||
{
|
||||
}
|
||||
|
||||
void LtsRestClient::ping(PingSuccessCallback onSuccess, ErrorCallback onError, int timeoutMs)
|
||||
{
|
||||
const QNetworkRequest request((QUrl(m_baseUrl)));
|
||||
QNetworkReply *reply = m_manager->head(request);
|
||||
|
||||
if (!reply)
|
||||
{
|
||||
if (onError)
|
||||
onError(QStringLiteral("Failed to initiate ping."));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. Setup the timer (parented to reply for auto-cleanup)
|
||||
QTimer *timeoutTimer = new QTimer(reply);
|
||||
timeoutTimer->setSingleShot(true);
|
||||
|
||||
// 2. Connect the timeout signal to abort the request
|
||||
connect(timeoutTimer,
|
||||
&QTimer::timeout,
|
||||
this,
|
||||
[reply]()
|
||||
{
|
||||
if (reply && reply->isRunning())
|
||||
reply->abort(); // Triggers finished() with OperationCanceledError
|
||||
});
|
||||
|
||||
// 3. Connect the finished signal to handle the response
|
||||
connect(reply,
|
||||
&QNetworkReply::finished,
|
||||
this,
|
||||
[reply, timeoutTimer, onSuccess, onError]()
|
||||
{
|
||||
timeoutTimer->stop();
|
||||
reply->deleteLater();
|
||||
|
||||
if (reply->error() != QNetworkReply::NoError)
|
||||
{
|
||||
if (onError)
|
||||
{
|
||||
if (reply->error() == QNetworkReply::OperationCanceledError)
|
||||
onError(QStringLiteral("Ping timed out."));
|
||||
else
|
||||
onError(reply->errorString());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
|
||||
if (onSuccess)
|
||||
onSuccess(statusCode);
|
||||
});
|
||||
|
||||
// 4. Start the timer only after all connections are successfully established
|
||||
timeoutTimer->start(timeoutMs);
|
||||
}
|
||||
|
||||
void LtsRestClient::get(const QString &endpoint, SuccessCallback onSuccess, ErrorCallback onError)
|
||||
{
|
||||
sendRequest(QStringLiteral("GET"), endpoint, QByteArray(), onSuccess, onError);
|
||||
}
|
||||
|
||||
void LtsRestClient::post(const QString &endpoint, const QJsonDocument &json, SuccessCallback onSuccess, ErrorCallback onError)
|
||||
{
|
||||
sendRequest(QStringLiteral("POST"), endpoint, json.toJson(), onSuccess, onError);
|
||||
}
|
||||
|
||||
void LtsRestClient::put(const QString &endpoint, const QJsonDocument &json, SuccessCallback onSuccess, ErrorCallback onError)
|
||||
{
|
||||
sendRequest(QStringLiteral("PUT"), endpoint, json.toJson(), onSuccess, onError);
|
||||
}
|
||||
|
||||
void LtsRestClient::del(const QString &endpoint, SuccessCallback onSuccess, ErrorCallback onError)
|
||||
{
|
||||
sendRequest(QStringLiteral("DELETE"), endpoint, QByteArray(), onSuccess, onError);
|
||||
}
|
||||
|
||||
void LtsRestClient::sendRequest(const QString &method, const QString &endpoint, const QByteArray &data, SuccessCallback onSuccess, ErrorCallback onError)
|
||||
{
|
||||
QUrl url(m_baseUrl);
|
||||
url.setPath(url.path() + endpoint);
|
||||
|
||||
QNetworkRequest request(url);
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, QStringLiteral("application/json"));
|
||||
|
||||
QNetworkReply *reply = nullptr;
|
||||
|
||||
if (method == QStringLiteral("GET"))
|
||||
reply = m_manager->get(request);
|
||||
else if (method == QStringLiteral("POST"))
|
||||
reply = m_manager->post(request, data);
|
||||
else if (method == QStringLiteral("PUT"))
|
||||
reply = m_manager->put(request, data);
|
||||
else if (method == QStringLiteral("DELETE"))
|
||||
reply = m_manager->deleteResource(request);
|
||||
|
||||
if (!reply)
|
||||
{
|
||||
if (onError)
|
||||
onError(QStringLiteral("Failed to initiate request."));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
connect(reply,
|
||||
&QNetworkReply::finished,
|
||||
this,
|
||||
[reply, onSuccess, onError]()
|
||||
{
|
||||
reply->deleteLater();
|
||||
|
||||
// Handle network errors
|
||||
if (reply->error() != QNetworkReply::NoError)
|
||||
{
|
||||
if (onError)
|
||||
onError(reply->errorString());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle HTTP errors
|
||||
const int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
if (statusCode >= 400)
|
||||
{
|
||||
if (onError)
|
||||
onError(QStringLiteral("HTTP Error %1").arg(statusCode));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse JSON safely
|
||||
QJsonParseError parseError;
|
||||
const QJsonDocument doc = QJsonDocument::fromJson(reply->readAll(), &parseError);
|
||||
|
||||
if (parseError.error != QJsonParseError::NoError)
|
||||
{
|
||||
if (onError)
|
||||
onError(QStringLiteral("JSON Parse Error: ") + parseError.errorString());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (onSuccess)
|
||||
onSuccess(doc);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace LtsCommon
|
||||
@@ -1,51 +0,0 @@
|
||||
/**
|
||||
* Lightweight REST Client Framework
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Hannes Fritsche, ESZS, 2026-08-21
|
||||
*/
|
||||
|
||||
// Short documentation on how to use it can be found at https://confluence-classified.rh-int.de/spaces/LEG/pages/207915647/HOWTO+LtsRestClient
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <functional>
|
||||
#include <LtsRestClient/ltsrestclient_export.h>
|
||||
|
||||
class QNetworkAccessManager;
|
||||
|
||||
namespace LtsCommon
|
||||
{
|
||||
|
||||
class LTSRESTCLIENT_EXPORT LtsRestClient : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LtsRestClient(const QString &baseUrl, QObject *parent = nullptr);
|
||||
|
||||
// type aliases
|
||||
using PingSuccessCallback = std::function<void(int statusCode)>;
|
||||
using SuccessCallback = std::function<void(const QJsonDocument &)>;
|
||||
using ErrorCallback = std::function<void(const QString &)>;
|
||||
|
||||
// HTTP Header Ping to m_baseUrl to check server availability
|
||||
void ping(PingSuccessCallback onSuccess, ErrorCallback onError = nullptr, int timeoutMs = 3000);
|
||||
|
||||
// HTTP Methods
|
||||
void get(const QString &endpoint, SuccessCallback onSuccess, ErrorCallback onError = nullptr);
|
||||
void post(const QString &endpoint, const QJsonDocument &json, SuccessCallback onSuccess, ErrorCallback onError = nullptr);
|
||||
void put(const QString &endpoint, const QJsonDocument &json, SuccessCallback onSuccess, ErrorCallback onError = nullptr);
|
||||
void del(const QString &endpoint, SuccessCallback onSuccess, ErrorCallback onError = nullptr);
|
||||
|
||||
private:
|
||||
void sendRequest(const QString &method, const QString &endpoint, const QByteArray &data, SuccessCallback onSuccess, ErrorCallback onError);
|
||||
|
||||
QString m_baseUrl;
|
||||
QNetworkAccessManager *m_manager;
|
||||
}; // class RestClient
|
||||
} // namespace LtsCommon
|
||||
@@ -1,31 +0,0 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
|
||||
#
|
||||
# Lts SerialPortQuerry library
|
||||
#
|
||||
|
||||
SET(ltsspq_SRCS
|
||||
lts_serial_port_querry.h
|
||||
lts_serial_port_querry.cpp
|
||||
logger.h
|
||||
logger.cpp
|
||||
)
|
||||
|
||||
|
||||
NGL_ADD_LIBRARY2(AAR SV LtsSerialPortQuerry SHARED ${ltsspq_SRCS} )
|
||||
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(LtsSerialPortQuerry
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../
|
||||
)
|
||||
|
||||
NGL_TARGET_LINK_LIBRARIES(LtsSerialPortQuerry
|
||||
PRIVATE
|
||||
PUBLIC
|
||||
NGLLogger
|
||||
$<IF:$<TARGET_EXISTS:Qt6::SerialPort>,Qt6::SerialPort,>
|
||||
)
|
||||
@@ -1,30 +0,0 @@
|
||||
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
#include <NGLLogger/NGLLoggerBootstrap.h>
|
||||
|
||||
namespace LtsSerialPortQuerry
|
||||
{
|
||||
|
||||
LOGGER_T getLogger(const char *name)
|
||||
{
|
||||
static const char ns[] = "SPQ.";
|
||||
std::string loggerName;
|
||||
const size_t len = strlen(name);
|
||||
loggerName.reserve(sizeof(ns) + len);
|
||||
loggerName.append(ns, sizeof(ns) - 1);
|
||||
loggerName.append(name, len);
|
||||
|
||||
try
|
||||
{
|
||||
return NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger(loggerName);
|
||||
}
|
||||
catch (const std::exception &ex)
|
||||
{
|
||||
fprintf(stderr, "Error retrieving logger: %s", ex.what());
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace LtsSerialPortQuerry
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <NGLLogger/INGLLogger.h>
|
||||
|
||||
namespace LtsSerialPortQuerry
|
||||
{
|
||||
typedef NGL::INGLLogger &LOGGER_T;
|
||||
|
||||
LOGGER_T getLogger(const char *name);
|
||||
|
||||
inline LOGGER_T getLogger(const QString &loggerName)
|
||||
{
|
||||
return getLogger(loggerName.toUtf8().constData());
|
||||
}
|
||||
} // namespace LtsSerialPortQuerry
|
||||
@@ -1,50 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "lts_seri"
|
||||
#include "ltsserialportquerry_export.h"
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtSerialPort/QSerialPortInfo>
|
||||
#include <QtSerialPort/QtSerialPort>
|
||||
|
||||
namespace LtsSerialPortQuerry
|
||||
{
|
||||
class LTSSERIALPORTQUERRY_EXPORT LtsSerialPortQuerry : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit LtsSerialPortQuerry(QObject *parent = nullptr);
|
||||
|
||||
void setSerialPortSettings(const QSerialPort::BaudRate &baudRate,
|
||||
const QSerialPort::OpenModeFlag &openModeFlag,
|
||||
const QSerialPort::DataBits &dataBits,
|
||||
const QSerialPort::FlowControl &flowControll,
|
||||
const QSerialPort::Parity &parity,
|
||||
const QSerialPort::StopBits &stopBits);
|
||||
void continueQuerry();
|
||||
void restartQuerry();
|
||||
QSerialPort *currentSerialPort();
|
||||
|
||||
signals:
|
||||
void connectionEstablished();
|
||||
|
||||
private:
|
||||
void querrySerialPort(const QSerialPortInfo &info);
|
||||
void closeAndDeleteCurrentPort();
|
||||
|
||||
private:
|
||||
void onSerialPortError(QSerialPort::SerialPortError serialPortError);
|
||||
|
||||
private:
|
||||
QList<QSerialPortInfo> m_serialPortInfos;
|
||||
int m_currentQuerry;
|
||||
QSerialPort::BaudRate m_baudRate;
|
||||
QSerialPort::OpenModeFlag m_openModeFlag;
|
||||
QSerialPort::DataBits m_dataBits;
|
||||
QSerialPort::FlowControl m_flowControll;
|
||||
QSerialPort::Parity m_parity;
|
||||
QSerialPort::StopBits m_stopBits;
|
||||
QSerialPort *m_currentSerialPort;
|
||||
};
|
||||
|
||||
} // namespace LtsSerialPortQuerry
|
||||
-147
@@ -1,147 +0,0 @@
|
||||
#include "lts_serial_port_querry.h"
|
||||
|
||||
#include <QtSerialPort/QSerialPortInfo>
|
||||
|
||||
namespace LtsSerialPortQuerry
|
||||
{
|
||||
|
||||
LtsSerialPortQuerry::LtsSerialPortQuerry(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_logger(getLogger("LtsSerialPortQuerry"))
|
||||
, m_currentQuerry(0)
|
||||
, m_baudRate(QSerialPort::Baud115200)
|
||||
, m_openModeFlag(QSerialPort::ReadWrite)
|
||||
, m_dataBits(QSerialPort::Data8)
|
||||
, m_flowControll(QSerialPort::NoFlowControl)
|
||||
, m_parity(QSerialPort::NoParity)
|
||||
, m_stopBits(QSerialPort::OneStop)
|
||||
, m_currentSerialPort(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
void LtsSerialPortQuerry::setSerialPortSettings(const QSerialPort::BaudRate &baudRate,
|
||||
const QIODevice::OpenModeFlag &openModeFlag,
|
||||
const QSerialPort::DataBits &dataBits,
|
||||
const QSerialPort::FlowControl &flowControll,
|
||||
const QSerialPort::Parity &parity,
|
||||
const QSerialPort::StopBits &stopBits)
|
||||
{
|
||||
m_baudRate = baudRate;
|
||||
m_openModeFlag = openModeFlag;
|
||||
m_dataBits = dataBits;
|
||||
m_flowControll = flowControll;
|
||||
m_parity = parity;
|
||||
m_stopBits = stopBits;
|
||||
}
|
||||
|
||||
void LtsSerialPortQuerry::continueQuerry()
|
||||
{
|
||||
m_currentQuerry++;
|
||||
if (m_currentQuerry >= m_serialPortInfos.size())
|
||||
{
|
||||
|
||||
restartQuerry();
|
||||
return;
|
||||
}
|
||||
querrySerialPort(m_serialPortInfos.at(m_currentQuerry));
|
||||
}
|
||||
|
||||
void LtsSerialPortQuerry::restartQuerry()
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "restart querry ";
|
||||
m_serialPortInfos = QSerialPortInfo::availablePorts();
|
||||
m_currentQuerry = 0;
|
||||
if (m_serialPortInfos.size())
|
||||
querrySerialPort(m_serialPortInfos.at(m_currentQuerry));
|
||||
else
|
||||
QTimer::singleShot(1000, this, &LtsSerialPortQuerry::restartQuerry);
|
||||
}
|
||||
|
||||
QSerialPort *LtsSerialPortQuerry::currentSerialPort()
|
||||
{
|
||||
return m_currentSerialPort;
|
||||
}
|
||||
|
||||
void LtsSerialPortQuerry::querrySerialPort(const QSerialPortInfo &info)
|
||||
{
|
||||
closeAndDeleteCurrentPort();
|
||||
m_currentSerialPort = new QSerialPort(info, this);
|
||||
m_currentSerialPort->setBaudRate(m_baudRate);
|
||||
m_currentSerialPort->setDataBits(m_dataBits);
|
||||
m_currentSerialPort->setParity(m_parity);
|
||||
m_currentSerialPort->setStopBits(m_stopBits);
|
||||
m_currentSerialPort->setFlowControl(m_flowControll);
|
||||
|
||||
DEBUG_LOG(m_logger) << "Try opening Comport:" << m_currentSerialPort->portName() << " index is: " << m_currentQuerry;
|
||||
|
||||
if (!m_currentSerialPort->open(QSerialPort::ReadWrite))
|
||||
{
|
||||
|
||||
DEBUG_LOG(m_logger) << "Oppening failed query next";
|
||||
|
||||
continueQuerry();
|
||||
}
|
||||
else
|
||||
{
|
||||
connect(m_currentSerialPort, &QSerialPort::errorOccurred, this, &LtsSerialPortQuerry::onSerialPortError, Qt::UniqueConnection);
|
||||
DEBUG_LOG(m_logger) << "Oppened comport" << m_currentSerialPort->portName();
|
||||
emit connectionEstablished();
|
||||
}
|
||||
}
|
||||
|
||||
void LtsSerialPortQuerry::closeAndDeleteCurrentPort()
|
||||
{
|
||||
if (m_currentSerialPort)
|
||||
{
|
||||
m_currentSerialPort->disconnect();
|
||||
if (m_currentSerialPort->isOpen())
|
||||
m_currentSerialPort->close();
|
||||
m_currentSerialPort->deleteLater();
|
||||
|
||||
m_currentSerialPort = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void LtsSerialPortQuerry::onSerialPortError(QSerialPort::SerialPortError serialPortError)
|
||||
{
|
||||
|
||||
if (!m_currentSerialPort)
|
||||
return;
|
||||
DEBUG_LOG(m_logger) << "Spontaneous error " << serialPortError << " doesn't have to be an error ...";
|
||||
|
||||
const QString errStr(QStringLiteral("QSerialPort::SerialPortError ") + QString::number(serialPortError) + QStringLiteral(" from serial port ") +
|
||||
m_currentSerialPort->portName() + QStringLiteral(" error: ") + m_currentSerialPort->errorString());
|
||||
|
||||
switch (serialPortError)
|
||||
{
|
||||
case QSerialPort::SerialPortError::NoError:
|
||||
{
|
||||
|
||||
break;
|
||||
}
|
||||
case QSerialPort::SerialPortError::DeviceNotFoundError:
|
||||
case QSerialPort::SerialPortError::PermissionError:
|
||||
case QSerialPort::SerialPortError::OpenError:
|
||||
case QSerialPort::SerialPortError::NotOpenError:
|
||||
case QSerialPort::SerialPortError::UnknownError:
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Closing port and try to reopen it. " << m_currentSerialPort->portName();
|
||||
continueQuerry();
|
||||
|
||||
Q_FALLTHROUGH();
|
||||
}
|
||||
case QSerialPort::SerialPortError::UnsupportedOperationError:
|
||||
{
|
||||
ERROR_LOG(m_logger) << errStr;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Got an Error> " << errStr << "restarting";
|
||||
continueQuerry();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace LtsSerialPortQuerry
|
||||
-50
@@ -1,50 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "logger.h"
|
||||
#include "ltsserialportquerry_export.h"
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtSerialPort/QSerialPortInfo>
|
||||
#include <QtSerialPort/QtSerialPort>
|
||||
|
||||
namespace LtsSerialPortQuerry
|
||||
{
|
||||
class LTSSERIALPORTQUERRY_EXPORT LtsSerialPortQuerry : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit LtsSerialPortQuerry(QObject *parent = nullptr);
|
||||
|
||||
void setSerialPortSettings(const QSerialPort::BaudRate &baudRate,
|
||||
const QSerialPort::OpenModeFlag &openModeFlag,
|
||||
const QSerialPort::DataBits &dataBits,
|
||||
const QSerialPort::FlowControl &flowControll,
|
||||
const QSerialPort::Parity &parity,
|
||||
const QSerialPort::StopBits &stopBits);
|
||||
|
||||
void restartQuerry();
|
||||
QSerialPort *currentSerialPort();
|
||||
|
||||
public slots:
|
||||
void continueQuerry();
|
||||
|
||||
signals:
|
||||
void connectionEstablished();
|
||||
|
||||
private:
|
||||
NGL::INGLLogger &m_logger;
|
||||
void querrySerialPort(const QSerialPortInfo &info);
|
||||
void closeAndDeleteCurrentPort();
|
||||
void onSerialPortError(QSerialPort::SerialPortError serialPortError);
|
||||
QList<QSerialPortInfo> m_serialPortInfos;
|
||||
int m_currentQuerry;
|
||||
QSerialPort::BaudRate m_baudRate;
|
||||
QSerialPort::OpenModeFlag m_openModeFlag;
|
||||
QSerialPort::DataBits m_dataBits;
|
||||
QSerialPort::FlowControl m_flowControll;
|
||||
QSerialPort::Parity m_parity;
|
||||
QSerialPort::StopBits m_stopBits;
|
||||
QSerialPort *m_currentSerialPort;
|
||||
};
|
||||
|
||||
} // namespace LtsSerialPortQuerry
|
||||
@@ -1,11 +0,0 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
# Created by Mike Wille, SLSE, 2016-09-19
|
||||
#
|
||||
|
||||
|
||||
ADD_SUBDIRECTORY(LtsUtilsCore)
|
||||
ADD_SUBDIRECTORY(LtsUtilsSettings)
|
||||
@@ -1,50 +0,0 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
|
||||
SET(SRCS_hdr_only
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/data_modification_enum.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/dds_bitarray.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/dds_vector.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/connection.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/json_object.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/json.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/outdated_position.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/qbytearray_byteaccess.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/qpoint3d.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/await.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lts_translatable_identifier.h
|
||||
)
|
||||
ADD_LIBRARY(LtsUtilsCoreHeaderOnly INTERFACE)
|
||||
TARGET_INCLUDE_DIRECTORIES(LtsUtilsCoreHeaderOnly
|
||||
INTERFACE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../
|
||||
${CMAKE_CURRENT_BINARY_DIR}/../
|
||||
)
|
||||
TARGET_SOURCES(LtsUtilsCoreHeaderOnly INTERFACE ${SRCS_hdr_only})
|
||||
|
||||
SET(SRCS
|
||||
pgarray.cpp
|
||||
qplane3d.cpp
|
||||
qpoint3d.cpp
|
||||
scoped_connection.cpp
|
||||
sfm_bytemessage_converter.cpp
|
||||
promise.cpp
|
||||
lts_translatable_identifier.cpp
|
||||
lts_portrange.cpp
|
||||
#variant_operators.h
|
||||
)
|
||||
|
||||
NGL_ADD_LIBRARY2(ALL LtsUtilsCore SHARED ${SRCS})
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(LtsUtilsCore
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../
|
||||
${CMAKE_CURRENT_BINARY_DIR}/../
|
||||
)
|
||||
NGL_TARGET_LINK_LIBRARIES(LtsUtilsCore
|
||||
PUBLIC
|
||||
Qt6::Core
|
||||
LtsUtilsCoreHeaderOnly
|
||||
)
|
||||
-1149
File diff suppressed because it is too large.
Load diff
-55
@@ -1,55 +0,0 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
class LtsUtilsTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private Q_SLOTS:
|
||||
|
||||
void test_toIntArray();
|
||||
void test_fromIntArray();
|
||||
void test_toBigintArray();
|
||||
void test_fromBigintArray();
|
||||
void test_toIntArray2D();
|
||||
void test_fromIntArray2D();
|
||||
void test_toBigintArray2D();
|
||||
void test_fromBigintArray2D();
|
||||
|
||||
void test_QPoint3D();
|
||||
|
||||
void test_bitArray();
|
||||
|
||||
void test_convert();
|
||||
|
||||
void test_connection();
|
||||
void test_queuedConnection();
|
||||
void test_signalSignalConnection();
|
||||
void test_danglingConnection1();
|
||||
void test_danglingConnection2();
|
||||
void test_danglingConnection3();
|
||||
|
||||
void test_jsonObject_fromJson();
|
||||
void test_jsonObject_contains();
|
||||
void test_jsonObject_value();
|
||||
void test_jsonObject_valueWithError();
|
||||
void test_jsonObject_valueOr();
|
||||
void test_jsonObject_integers();
|
||||
void test_jsonObject_nullValues();
|
||||
void test_jsonArray_fromJson();
|
||||
void test_jsonArray();
|
||||
void test_jsonArray_nullArray();
|
||||
|
||||
void test_byteStreamFromSfmMessage();
|
||||
void test_byteStreamFromSfmMessage2();
|
||||
void test_byteStreamToSfmMessage();
|
||||
|
||||
void test_promise();
|
||||
void test_promise_example1();
|
||||
void test_promise_example2();
|
||||
void test_promise_example3();
|
||||
|
||||
void byteAccess();
|
||||
};
|
||||
@@ -1,87 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QEventLoop>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QTimer>
|
||||
#include <memory>
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
template <typename Func> void addConnect(QEventLoop &x, bool &success, const typename QtPrivate::FunctionPointer<Func>::Object *sender, Func signal, bool isSuccess)
|
||||
{
|
||||
if (isSuccess)
|
||||
{
|
||||
QObject::connect(sender, signal, &x, [&success]() { success = true; });
|
||||
}
|
||||
|
||||
QObject::connect(sender, signal, &x, &QEventLoop::quit, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
template <typename Func, typename... Connect>
|
||||
void addConnect(QEventLoop &x, bool &success, const typename QtPrivate::FunctionPointer<Func>::Object *sender, Func signal, bool isSuccess, Connect... connects)
|
||||
{
|
||||
addConnect(x, success, sender, signal, isSuccess);
|
||||
addConnect(x, success, connects...);
|
||||
}
|
||||
|
||||
template <typename... Connect> void await(Connect... connects) noexcept(false)
|
||||
{
|
||||
QEventLoop x;
|
||||
bool success = false;
|
||||
|
||||
addConnect(x, success, connects...);
|
||||
|
||||
x.exec();
|
||||
|
||||
if (!success)
|
||||
{
|
||||
|
||||
throw std::runtime_error("Failed.");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename... Connect> void awaitTimeout(const int timeoutMs, Connect... connects) noexcept(false)
|
||||
{
|
||||
std::unique_ptr<QTimer> t(new QTimer);
|
||||
bool timeout = false;
|
||||
|
||||
if (timeoutMs > -1)
|
||||
{
|
||||
t->setInterval(timeoutMs);
|
||||
t->setSingleShot(true);
|
||||
QObject::connect(t.get(),
|
||||
&QTimer::timeout,
|
||||
t.get(),
|
||||
[&timeout]()
|
||||
{
|
||||
fprintf(stderr, "awaitTimeout: timed out!\n");
|
||||
timeout = true;
|
||||
});
|
||||
t->start();
|
||||
}
|
||||
|
||||
await(t.get(), &QTimer::timeout, false, connects...);
|
||||
|
||||
if (timeout)
|
||||
{
|
||||
|
||||
throw std::runtime_error("Timeout.");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Func1, typename Func2>
|
||||
void awaitWithCancelationSignal(const typename QtPrivate::FunctionPointer<Func1>::Object *sender1,
|
||||
Func1 signal1,
|
||||
const typename QtPrivate::FunctionPointer<Func2>::Object *sender2,
|
||||
Func2 signal2,
|
||||
const int timeoutMs = 0) noexcept(false)
|
||||
{
|
||||
if (timeoutMs > 0)
|
||||
{
|
||||
awaitTimeout(timeoutMs, sender1, signal1, true, sender2, signal2, false);
|
||||
return;
|
||||
}
|
||||
|
||||
await(sender1, signal1, true, sender2, signal2, false);
|
||||
}
|
||||
} // namespace LtsUtils
|
||||
@@ -1,107 +0,0 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QMetaObject>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QPointer>
|
||||
#include <QtGlobal>
|
||||
#include <type_traits>
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
|
||||
class IConnection
|
||||
{
|
||||
public:
|
||||
virtual ~IConnection() = default;
|
||||
virtual void connect(Qt::ConnectionType = Qt::AutoConnection) = 0;
|
||||
virtual void disconnect() = 0;
|
||||
};
|
||||
|
||||
class DummyConnection : public IConnection
|
||||
{
|
||||
public:
|
||||
void connect(Qt::ConnectionType = Qt::AutoConnection) override {}
|
||||
|
||||
void disconnect() override {}
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <class T> struct ExtractClass;
|
||||
|
||||
template <class T, class Member> struct ExtractClass<Member T::*>
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class Signal, class Slot> class Connection : public IConnection
|
||||
{
|
||||
static_assert(std::is_member_function_pointer_v<Signal>, "Must be a pointer to method");
|
||||
static_assert(std::is_member_function_pointer_v<Slot>, "Must be a pointer to method");
|
||||
|
||||
using Emitter = typename detail::ExtractClass<Signal>::type;
|
||||
using Target = typename detail::ExtractClass<Slot>::type;
|
||||
|
||||
static_assert(std::is_base_of_v<QObject, Emitter>, "Must be derived from QObject");
|
||||
static_assert(std::is_base_of_v<QObject, Target>, "Must be derived from QObject");
|
||||
|
||||
public:
|
||||
Connection(Emitter *emitter, Signal signal, Target *target, Slot slot)
|
||||
: m_emitter(emitter)
|
||||
, m_signal(signal)
|
||||
, m_target(target)
|
||||
, m_slot(slot)
|
||||
{
|
||||
Q_ASSERT(emitter);
|
||||
Q_ASSERT(signal);
|
||||
Q_ASSERT(target);
|
||||
Q_ASSERT(slot);
|
||||
}
|
||||
|
||||
void connect(Qt::ConnectionType connectionType = Qt::AutoConnection) override
|
||||
{
|
||||
Q_ASSERT(!m_connected);
|
||||
|
||||
m_connected = true;
|
||||
|
||||
if (!m_emitter || !m_target)
|
||||
return;
|
||||
|
||||
m_conn = QObject::connect(m_emitter.data(), m_signal, m_target.data(), m_slot, connectionType);
|
||||
Q_ASSERT(m_conn);
|
||||
}
|
||||
|
||||
void disconnect() override
|
||||
{
|
||||
Q_ASSERT(m_connected);
|
||||
|
||||
if (m_conn)
|
||||
QObject::disconnect(m_conn);
|
||||
|
||||
m_connected = false;
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_connected{false};
|
||||
QPointer<Emitter> m_emitter;
|
||||
Signal m_signal;
|
||||
QPointer<Target> m_target;
|
||||
Slot m_slot;
|
||||
QMetaObject::Connection m_conn;
|
||||
};
|
||||
|
||||
template <class Signal, class Slot>
|
||||
Connection<Signal, Slot> *createConnection(typename detail::ExtractClass<Signal>::type *emitter,
|
||||
Signal signal,
|
||||
typename detail::ExtractClass<Slot>::type *target,
|
||||
Slot slot)
|
||||
{
|
||||
return new Connection<Signal, Slot>(emitter, signal, target, slot);
|
||||
}
|
||||
|
||||
} // namespace LtsUtils
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ostream>
|
||||
|
||||
enum class DataModification
|
||||
{
|
||||
eAdded,
|
||||
eModified,
|
||||
eRemoved
|
||||
};
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &str, DataModification mod)
|
||||
{
|
||||
switch (mod)
|
||||
{
|
||||
case DataModification::eAdded:
|
||||
str << "DataModification::eAdded";
|
||||
break;
|
||||
case DataModification::eModified:
|
||||
str << "DataModification::eModified";
|
||||
break;
|
||||
case DataModification::eRemoved:
|
||||
str << "DataModification::eRemoved";
|
||||
break;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef SUPPORT_QBITARRAY
|
||||
#include <QtCore/QBitArray>
|
||||
#endif
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
|
||||
namespace BitArray
|
||||
{
|
||||
constexpr inline int bitNumber(int position)
|
||||
{
|
||||
return 7 - (position % 8);
|
||||
}
|
||||
|
||||
template <typename T> inline bool testBit(const T &bitField, int position, bool *oob = nullptr)
|
||||
{
|
||||
const size_t byteNum = position / 8;
|
||||
if (byteNum >= bitField.size())
|
||||
{
|
||||
if (oob)
|
||||
*oob = true;
|
||||
return false;
|
||||
}
|
||||
if (oob)
|
||||
*oob = false;
|
||||
|
||||
const typename T::value_type mask = 1 << bitNumber(position);
|
||||
return ((bitField.at(byteNum) & mask) == mask);
|
||||
}
|
||||
|
||||
template <typename T> inline bool setBit(T &bitField, int position, bool set = true)
|
||||
{
|
||||
const size_t byteNum = position / 8;
|
||||
if (byteNum >= bitField.size())
|
||||
return false;
|
||||
|
||||
const typename T::value_type mask = 1 << bitNumber(position);
|
||||
if (set)
|
||||
bitField[byteNum] |= mask;
|
||||
else
|
||||
bitField[byteNum] &= ~mask;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T> inline bool clearBit(T &bitField, int position)
|
||||
{
|
||||
return setBit(bitField, position, false);
|
||||
}
|
||||
|
||||
#ifdef SUPPORT_QBITARRAY
|
||||
template <typename T> inline T convert(const QBitArray &bitArray)
|
||||
{
|
||||
T ret;
|
||||
ret.resize((bitArray.size() + 7) / 8, 0);
|
||||
|
||||
for (int i = 0; i < bitArray.size(); ++i)
|
||||
{
|
||||
const size_t byteNum = i / 8;
|
||||
const typename T::value_type mask = (1 << bitNumber(i));
|
||||
if (bitArray[i])
|
||||
ret[byteNum] |= mask;
|
||||
else
|
||||
ret[byteNum] &= ~mask;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename T> inline QBitArray convert(T &bitField, int realSize)
|
||||
{
|
||||
QBitArray ba(realSize);
|
||||
for (int32_t i = 0; i < realSize; ++i)
|
||||
{
|
||||
const size_t byteNum = i / 8;
|
||||
const typename T::value_type mask = (1 << bitNumber(i));
|
||||
bool bit = ((bitField[byteNum] & mask) == mask);
|
||||
ba[i] = bit;
|
||||
}
|
||||
return ba;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace BitArray
|
||||
|
||||
} // namespace LtsUtils
|
||||
@@ -1,37 +0,0 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QString>
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
|
||||
template <typename T, typename S> inline void convert(const S &in, T &out)
|
||||
{
|
||||
static_assert(!std::is_same_v<S, T>, "Try to convert a type to the same type - is useless");
|
||||
out.reserve(static_cast<int>(in.size()));
|
||||
std::copy(in.begin(), in.end(), std::back_inserter(out));
|
||||
}
|
||||
|
||||
template <typename T, typename S> inline T convert(const S &in)
|
||||
{
|
||||
static_assert(!std::is_same_v<S, T>, "Try to convert a type to the same type - is useless");
|
||||
T out;
|
||||
convert(in, out);
|
||||
return out;
|
||||
}
|
||||
|
||||
template <typename T> inline QByteArray toQByteArray(const T &in)
|
||||
{
|
||||
return convert<QByteArray>(in);
|
||||
}
|
||||
|
||||
template <typename T, typename V = typename T::value_type> bool isInVector(const T &vec, const V &valueToSearch)
|
||||
{
|
||||
const auto end = vec.end();
|
||||
return std::find(vec.begin(), end, valueToSearch) != end;
|
||||
}
|
||||
|
||||
} // namespace LtsUtils
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ltsutilscore_export.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
class QByteArray;
|
||||
class QPixmap;
|
||||
class QImage;
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
|
||||
LTSUTILSCORE_EXPORT QPixmap getPixmap(const std::vector<uint8_t> &data);
|
||||
LTSUTILSCORE_EXPORT QPixmap getPixmap(const QByteArray &data);
|
||||
LTSUTILSCORE_EXPORT QImage getImage(const std::vector<uint8_t> &data);
|
||||
LTSUTILSCORE_EXPORT QImage getImage(const QByteArray &data);
|
||||
LTSUTILSCORE_EXPORT std::vector<uint8_t> fromPixmap(const QPixmap &pixmap, bool *bIsPng = nullptr);
|
||||
LTSUTILSCORE_EXPORT std::vector<uint8_t> fromImage(const QImage &image, bool *bIsPng = nullptr);
|
||||
|
||||
} // namespace LtsUtils
|
||||
@@ -1 +0,0 @@
|
||||
#include <LtsUtilsCore/json_object.h>
|
||||
@@ -1,579 +0,0 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QJsonArray>
|
||||
#include <QtCore/QJsonDocument>
|
||||
#include <QtCore/QJsonObject>
|
||||
#include <QJsonParseError>
|
||||
#include <QtCore/QJsonValue>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QVector>
|
||||
#include <cstdint>
|
||||
#include <exception>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
|
||||
class JsonParseError : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
JsonParseError(const QJsonParseError &err)
|
||||
: std::runtime_error("json parse error: " + err.errorString().toStdString() + " - at offset " + std::to_string(err.offset))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class JsonError : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
class JsonKeyError : public JsonError
|
||||
{
|
||||
public:
|
||||
using JsonError::JsonError;
|
||||
};
|
||||
|
||||
class JsonRangeError : public JsonError
|
||||
{
|
||||
public:
|
||||
using JsonError::JsonError;
|
||||
};
|
||||
|
||||
class JsonTypeError : public JsonError
|
||||
{
|
||||
public:
|
||||
using JsonError::JsonError;
|
||||
};
|
||||
|
||||
class JsonObject
|
||||
{
|
||||
public:
|
||||
class Key;
|
||||
|
||||
JsonObject() = default;
|
||||
|
||||
explicit JsonObject(const QJsonObject &json)
|
||||
: m_json(json)
|
||||
, m_jsonIsSet(true)
|
||||
{
|
||||
}
|
||||
|
||||
explicit JsonObject(QJsonObject &&json)
|
||||
: m_json(std::move(json))
|
||||
, m_jsonIsSet(true)
|
||||
{
|
||||
}
|
||||
|
||||
static inline JsonObject fromJson(const char *json, int len = -1);
|
||||
|
||||
static inline JsonObject fromJson(const QByteArray &json) { return fromJson(json.data(), json.size()); }
|
||||
|
||||
static inline JsonObject fromJson(const std::string &json) { return fromJson(json.c_str(), json.size()); }
|
||||
|
||||
static inline JsonObject fromJsonSafe(const char *json, int len = -1) noexcept(false);
|
||||
|
||||
static inline JsonObject fromJsonSafe(const QByteArray &json) noexcept(false) { return fromJsonSafe(json.data(), json.size()); }
|
||||
|
||||
static inline JsonObject fromJsonSafe(const std::string &json) noexcept(false) { return fromJsonSafe(json.c_str(), json.size()); }
|
||||
|
||||
template <class T> [[nodiscard]] bool contains(const Key &key) const;
|
||||
|
||||
[[nodiscard]] bool isNull(const Key &key) const { return contains<void>(key); }
|
||||
|
||||
[[nodiscard]] bool isEmpty() const { return m_json.isEmpty(); }
|
||||
|
||||
[[nodiscard]] bool isValid() const { return m_jsonIsSet; }
|
||||
|
||||
template <class T> T value(const Key &key) const noexcept(false);
|
||||
|
||||
template <class T> T valueOr(const Key &key, const T &defaultValue) const noexcept(false);
|
||||
|
||||
template <class T> [[nodiscard]] bool isMap() const;
|
||||
|
||||
template <class T> QMap<QString, T> toMap() const noexcept(false);
|
||||
|
||||
template <class T> std::map<std::string, T> toStdMap() const;
|
||||
|
||||
bool operator==(const JsonObject &other) const { return m_json == other.m_json; }
|
||||
|
||||
bool operator!=(const JsonObject &other) const { return !(*this == other); }
|
||||
|
||||
class Key
|
||||
{
|
||||
public:
|
||||
Key(QString s)
|
||||
: m_s(std::move(s))
|
||||
{
|
||||
}
|
||||
|
||||
Key(const std::string &s)
|
||||
: m_s(QString::fromStdString(s))
|
||||
{
|
||||
}
|
||||
|
||||
Key(const char *s)
|
||||
: m_s(QString::fromUtf8(s))
|
||||
{
|
||||
}
|
||||
|
||||
operator const QString &() const { return m_s; }
|
||||
|
||||
private:
|
||||
const QString m_s;
|
||||
};
|
||||
|
||||
operator const QJsonObject &() const { return m_json; }
|
||||
|
||||
[[nodiscard]] const QJsonObject &object() const { return m_json; }
|
||||
|
||||
private:
|
||||
[[nodiscard]] bool containsAny(const QString &key) const { return m_json.contains(key); }
|
||||
|
||||
QJsonObject m_json;
|
||||
bool m_jsonIsSet = false;
|
||||
};
|
||||
|
||||
JsonObject JsonObject::fromJson(const char *json, int len)
|
||||
{
|
||||
if (len < 0)
|
||||
len = strlen(json);
|
||||
QJsonParseError error;
|
||||
const auto doc = QJsonDocument::fromJson(QByteArray::fromRawData(json, len), &error);
|
||||
if (error.error != QJsonParseError::NoError)
|
||||
return {};
|
||||
|
||||
if (!doc.isObject())
|
||||
return {};
|
||||
|
||||
return JsonObject(doc.object());
|
||||
}
|
||||
|
||||
JsonObject JsonObject::fromJsonSafe(const char *json, int len) noexcept(false)
|
||||
{
|
||||
if (len < 0)
|
||||
len = strlen(json);
|
||||
QJsonParseError error;
|
||||
const auto doc = QJsonDocument::fromJson(QByteArray::fromRawData(json, len), &error);
|
||||
if (error.error != QJsonParseError::NoError)
|
||||
throw JsonParseError(error);
|
||||
|
||||
if (!doc.isObject())
|
||||
throw JsonTypeError("JSON root is not an object");
|
||||
|
||||
return JsonObject(doc.object());
|
||||
}
|
||||
|
||||
class JsonArray
|
||||
{
|
||||
public:
|
||||
JsonArray() = default;
|
||||
|
||||
explicit JsonArray(const QJsonArray &json)
|
||||
: m_json(json)
|
||||
, m_jsonIsSet(true)
|
||||
{
|
||||
}
|
||||
|
||||
explicit JsonArray(QJsonArray &&json)
|
||||
: m_json(std::move(json))
|
||||
, m_jsonIsSet(true)
|
||||
{
|
||||
}
|
||||
|
||||
static inline JsonArray fromJson(const char *json, int len = -1);
|
||||
|
||||
static inline JsonArray fromJson(const QByteArray &json) { return fromJson(json.data(), json.size()); }
|
||||
|
||||
static inline JsonArray fromJson(const std::string &json) { return fromJson(json.c_str(), json.size()); }
|
||||
|
||||
static inline JsonArray fromJsonSafe(const char *json, int len = -1) noexcept(false);
|
||||
|
||||
static inline JsonArray fromJsonSafe(const QByteArray &json) noexcept(false) { return fromJson(json.data(), json.size()); }
|
||||
|
||||
static inline JsonArray fromJsonSafe(const std::string &json) noexcept(false) { return fromJson(json.c_str(), json.size()); }
|
||||
|
||||
[[nodiscard]] int size() const { return m_json.size(); }
|
||||
|
||||
[[nodiscard]] bool isEmpty() const { return m_json.isEmpty(); }
|
||||
|
||||
[[nodiscard]] bool isValid() const { return m_jsonIsSet; }
|
||||
|
||||
template <class T> [[nodiscard]] bool contains(int index) const noexcept(false);
|
||||
|
||||
[[nodiscard]] bool isNull(int index) const noexcept(false) { return contains<void>(index); }
|
||||
|
||||
template <class T> T at(int index) const noexcept(false);
|
||||
|
||||
template <class T> [[nodiscard]] bool isVector() const;
|
||||
|
||||
template <class T> QVector<T> toVector() const noexcept(false);
|
||||
|
||||
template <class T> std::vector<T> toStdVector() const;
|
||||
|
||||
bool operator==(const JsonArray &other) const { return m_json == other.m_json; }
|
||||
|
||||
bool operator!=(const JsonArray &other) const { return !(*this == other); }
|
||||
|
||||
const QJsonArray &operator()() const { return m_json; }
|
||||
|
||||
private:
|
||||
QJsonArray m_json;
|
||||
bool m_jsonIsSet = false;
|
||||
};
|
||||
|
||||
JsonArray JsonArray::fromJson(const char *json, int len)
|
||||
{
|
||||
if (len < 0)
|
||||
len = strlen(json);
|
||||
QJsonParseError error;
|
||||
QJsonDocument doc = QJsonDocument::fromJson(QByteArray::fromRawData(json, len), &error);
|
||||
if (error.error != QJsonParseError::NoError)
|
||||
return {};
|
||||
|
||||
if (!doc.isArray())
|
||||
return {};
|
||||
|
||||
return JsonArray(doc.array());
|
||||
}
|
||||
|
||||
JsonArray JsonArray::fromJsonSafe(const char *json, int len) noexcept(false)
|
||||
{
|
||||
if (len < 0)
|
||||
len = strlen(json);
|
||||
QJsonParseError error;
|
||||
const auto doc = QJsonDocument::fromJson(QByteArray::fromRawData(json, len), &error);
|
||||
if (error.error != QJsonParseError::NoError)
|
||||
throw JsonParseError(error);
|
||||
|
||||
if (!doc.isArray())
|
||||
throw JsonTypeError("JSON root is not an array");
|
||||
|
||||
return JsonArray(doc.array());
|
||||
}
|
||||
|
||||
template <class T> struct JsonValue;
|
||||
|
||||
template <class Int> struct JsonLimits
|
||||
{
|
||||
static constexpr Int lowest() { return std::numeric_limits<Int>::lowest(); }
|
||||
|
||||
static constexpr Int max() { return std::numeric_limits<Int>::max(); }
|
||||
};
|
||||
|
||||
template <> struct JsonLimits<int64_t>
|
||||
{
|
||||
static constexpr int64_t lowest() { return -(static_cast<int64_t>(1) << 53) + 1; }
|
||||
|
||||
static constexpr int64_t max() { return (static_cast<int64_t>(1) << 53) - 1; }
|
||||
};
|
||||
|
||||
template <> struct JsonLimits<uint64_t>
|
||||
{
|
||||
static constexpr uint64_t lowest() { return 0; }
|
||||
|
||||
static constexpr uint64_t max() { return JsonLimits<int64_t>::max(); }
|
||||
};
|
||||
|
||||
template <class Int> struct JsonIntValue
|
||||
{
|
||||
static bool matchesType(const QJsonValue &value)
|
||||
{
|
||||
if (!value.isDouble())
|
||||
return false;
|
||||
double val = value.toDouble();
|
||||
|
||||
if (val < JsonLimits<Int>::lowest())
|
||||
return false;
|
||||
if (val > JsonLimits<Int>::max())
|
||||
return false;
|
||||
|
||||
double wholeInt = static_cast<Int>(val);
|
||||
return val == wholeInt;
|
||||
}
|
||||
|
||||
static Int value(const QJsonValue &value) noexcept(false)
|
||||
{
|
||||
if (!matchesType(value))
|
||||
throw JsonTypeError("JSON value not of type Int");
|
||||
return static_cast<Int>(value.toDouble());
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct JsonValue<int16_t> : JsonIntValue<int16_t>
|
||||
{
|
||||
};
|
||||
|
||||
template <> struct JsonValue<uint16_t> : JsonIntValue<uint16_t>
|
||||
{
|
||||
};
|
||||
|
||||
template <> struct JsonValue<int32_t> : JsonIntValue<int32_t>
|
||||
{
|
||||
};
|
||||
|
||||
template <> struct JsonValue<uint32_t> : JsonIntValue<uint32_t>
|
||||
{
|
||||
};
|
||||
|
||||
template <> struct JsonValue<int64_t> : JsonIntValue<int64_t>
|
||||
{
|
||||
};
|
||||
|
||||
template <> struct JsonValue<uint64_t> : JsonIntValue<uint64_t>
|
||||
{
|
||||
};
|
||||
|
||||
template <> struct JsonValue<double>
|
||||
{
|
||||
static bool matchesType(const QJsonValue &value) { return value.isDouble(); }
|
||||
|
||||
static double value(const QJsonValue &value) noexcept(false)
|
||||
{
|
||||
if (!matchesType(value))
|
||||
throw JsonTypeError("JSON value not of type Double");
|
||||
return value.toDouble();
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct JsonValue<bool>
|
||||
{
|
||||
static bool matchesType(const QJsonValue &value) { return value.isBool(); }
|
||||
|
||||
static bool value(const QJsonValue &value) noexcept(false)
|
||||
{
|
||||
if (!matchesType(value))
|
||||
throw JsonTypeError("JSON value not of type Bool");
|
||||
return value.toBool();
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct JsonValue<QString>
|
||||
{
|
||||
static bool matchesType(const QJsonValue &value) { return value.isString(); }
|
||||
|
||||
static QString value(const QJsonValue &value) noexcept(false)
|
||||
{
|
||||
if (!matchesType(value))
|
||||
throw JsonTypeError("JSON value not of type String");
|
||||
return value.toString();
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct JsonValue<std::string>
|
||||
{
|
||||
static bool matchesType(const QJsonValue &value) { return value.isString(); }
|
||||
|
||||
static std::string value(const QJsonValue &value) { return JsonValue<QString>::value(value).toStdString(); }
|
||||
};
|
||||
|
||||
template <> struct JsonValue<QJsonObject>
|
||||
{
|
||||
static bool matchesType(const QJsonValue &value) { return value.isObject(); }
|
||||
|
||||
static QJsonObject value(const QJsonValue &value) noexcept(false)
|
||||
{
|
||||
if (!matchesType(value))
|
||||
throw JsonTypeError("JSON value not of type Object");
|
||||
return value.toObject();
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct JsonValue<JsonObject>
|
||||
{
|
||||
static bool matchesType(const QJsonValue &value) { return value.isObject(); }
|
||||
|
||||
static JsonObject value(const QJsonValue &value) { return JsonObject(JsonValue<QJsonObject>::value(value)); }
|
||||
};
|
||||
|
||||
template <> struct JsonValue<void>
|
||||
{
|
||||
static bool matchesType(const QJsonValue &value) { return value.isNull(); }
|
||||
};
|
||||
|
||||
template <> struct JsonValue<QJsonArray>
|
||||
{
|
||||
static bool matchesType(const QJsonValue &value) { return value.isArray(); }
|
||||
|
||||
static QJsonArray value(const QJsonValue &value) noexcept(false)
|
||||
{
|
||||
if (!matchesType(value))
|
||||
throw JsonTypeError("JSON value not of type Array");
|
||||
return value.toArray();
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct JsonValue<JsonArray>
|
||||
{
|
||||
static bool matchesType(const QJsonValue &value) { return value.isArray(); }
|
||||
|
||||
static JsonArray value(const QJsonValue &value) { return JsonArray(JsonValue<QJsonArray>::value(value)); }
|
||||
};
|
||||
|
||||
template <class T> struct JsonValue<QVector<T>>
|
||||
{
|
||||
static bool matchesType(const QJsonValue &value)
|
||||
{
|
||||
if (!value.isArray())
|
||||
return false;
|
||||
|
||||
const JsonArray array(value.toArray());
|
||||
return array.isVector<T>();
|
||||
}
|
||||
|
||||
static QVector<T> value(const QJsonValue &value)
|
||||
{
|
||||
const JsonArray array(JsonValue<QJsonArray>::value(value));
|
||||
return array.toVector<T>();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T> struct JsonValue<std::vector<T>>
|
||||
{
|
||||
static bool matchesType(const QJsonValue &value) { return JsonValue<QVector<T>>::matchesType(value); }
|
||||
|
||||
static std::vector<T> value(const QJsonValue &value)
|
||||
{
|
||||
const JsonArray array(JsonValue<QJsonArray>::value(value));
|
||||
return array.toStdVector<T>();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T> struct JsonValue<QMap<QString, T>>
|
||||
{
|
||||
static bool matchesType(const QJsonValue &value)
|
||||
{
|
||||
if (!value.isObject())
|
||||
return false;
|
||||
|
||||
const JsonObject obj(JsonValue<QJsonObject>::value(value));
|
||||
return obj.isMap<T>();
|
||||
}
|
||||
|
||||
static QMap<QString, T> value(const QJsonValue &value)
|
||||
{
|
||||
const JsonObject obj(JsonValue<QJsonObject>::value(value));
|
||||
return obj.toMap<T>();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T> struct JsonValue<std::map<std::string, T>>
|
||||
{
|
||||
static bool matchesType(const QJsonValue &value) { return JsonValue<QMap<QString, T>>::matchesType(value); }
|
||||
|
||||
static std::map<std::string, T> value(const QJsonValue &value)
|
||||
{
|
||||
const JsonObject obj(JsonValue<QJsonObject>::value(value));
|
||||
return obj.toStdMap<T>();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T> bool JsonObject::contains(const Key &key) const
|
||||
{
|
||||
if (!m_json.contains(key))
|
||||
return false;
|
||||
return JsonValue<T>::matchesType(m_json.value(key));
|
||||
}
|
||||
|
||||
template <class T> T JsonObject::value(const Key &key) const noexcept(false)
|
||||
{
|
||||
if (!containsAny(key))
|
||||
throw JsonKeyError("no element with key: " + static_cast<const QString &>(key).toStdString());
|
||||
try
|
||||
{
|
||||
return JsonValue<T>::value(m_json.value(key));
|
||||
}
|
||||
catch (const JsonTypeError &typeError)
|
||||
{
|
||||
throw JsonTypeError(std::string(typeError.what()) + " - key: " + static_cast<const QString &>(key).toStdString());
|
||||
}
|
||||
}
|
||||
|
||||
template <class T> T JsonObject::valueOr(const Key &key, const T &defaultValue) const
|
||||
{
|
||||
try
|
||||
{
|
||||
return value<T>(key);
|
||||
}
|
||||
|
||||
catch (const JsonKeyError &)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T> bool JsonObject::isMap() const
|
||||
{
|
||||
const QStringList keys = m_json.keys();
|
||||
for (const auto &key : keys)
|
||||
if (!JsonValue<T>::matchesType(m_json.value(key)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T> QMap<QString, T> JsonObject::toMap() const
|
||||
{
|
||||
QMap<QString, T> result;
|
||||
for (auto current = m_json.begin(); current != m_json.end(); ++current)
|
||||
result.insert(current.key(), JsonValue<T>::value(current.value()));
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T> std::map<std::string, T> JsonObject::toStdMap() const
|
||||
{
|
||||
std::map<std::string, T> result;
|
||||
for (auto current = m_json.begin(); current != m_json.end(); ++current)
|
||||
result.insert({current.key().toStdString(), JsonValue<T>::value(current.value())});
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T> bool JsonArray::contains(int index) const noexcept(false)
|
||||
{
|
||||
if (index < 0 || index >= m_json.size())
|
||||
throw JsonRangeError("index out of range: " + std::to_string(index));
|
||||
return JsonValue<T>::matchesType(m_json.at(index));
|
||||
}
|
||||
|
||||
template <class T> T JsonArray::at(int index) const noexcept(false)
|
||||
{
|
||||
if (index < 0 || index >= m_json.size())
|
||||
throw JsonRangeError("index out of range: " + std::to_string(index));
|
||||
return JsonValue<T>::value(m_json.at(index));
|
||||
}
|
||||
|
||||
template <class T> bool JsonArray::isVector() const
|
||||
{
|
||||
for (const QJsonValue &value : m_json)
|
||||
if (!JsonValue<T>::matchesType(value))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T> QVector<T> JsonArray::toVector() const
|
||||
{
|
||||
QVector<T> result;
|
||||
result.reserve(m_json.size());
|
||||
for (const QJsonValue &value : m_json)
|
||||
result.push_back(JsonValue<T>::value(value));
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T> std::vector<T> JsonArray::toStdVector() const
|
||||
{
|
||||
std::vector<T> result;
|
||||
result.reserve(m_json.size());
|
||||
for (const QJsonValue &value : m_json)
|
||||
result.push_back(JsonValue<T>::value(value));
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace LtsUtils
|
||||
@@ -1,14 +0,0 @@
|
||||
#include "lts_portrange.h"
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
|
||||
LtsUtils::LtsPortRange fromQPoint(const QPoint &point)
|
||||
{
|
||||
if (point.x() < 1025 || point.y() > 65535 || point.x() > point.y())
|
||||
return {};
|
||||
|
||||
return {static_cast<quint16>(point.x()), static_cast<quint16>(point.y())};
|
||||
}
|
||||
|
||||
} // namespace LtsUtils
|
||||
@@ -1,13 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "ltsutilscore_export.h"
|
||||
|
||||
#include <QtCore/QPair>
|
||||
#include <QtCore/QPoint>
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
typedef QPair<quint16, quint16> LtsPortRange;
|
||||
|
||||
LTSUTILSCORE_EXPORT LtsPortRange fromQPoint(const QPoint &point);
|
||||
} // namespace LtsUtils
|
||||
-22
@@ -1,22 +0,0 @@
|
||||
|
||||
|
||||
#include "lts_translatable_identifier.h"
|
||||
|
||||
#include <QtCore/QCoreApplication>
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
LtsTranslatableIdentifier::LtsTranslatableIdentifier(const QString &identifier, const QObject *context, const char *translatableText)
|
||||
: m_identifier(identifier)
|
||||
, m_translationContext(context->metaObject()->className())
|
||||
, m_translatableText(translatableText)
|
||||
{
|
||||
}
|
||||
|
||||
const QString LtsTranslatableIdentifier::translatedText(const char *disambiguation, int n) const
|
||||
{
|
||||
if (m_identifier.isEmpty() || m_translationContext == nullptr || m_translatableText == nullptr)
|
||||
return {};
|
||||
return QCoreApplication::translate(m_translationContext, m_translatableText, disambiguation, n);
|
||||
}
|
||||
} // namespace LtsUtils
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "ltsutilscore_export.h"
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QString>
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
class LTSUTILSCORE_EXPORT LtsTranslatableIdentifier
|
||||
{
|
||||
public:
|
||||
LtsTranslatableIdentifier()
|
||||
: m_translationContext(nullptr)
|
||||
, m_translatableText("")
|
||||
{
|
||||
}
|
||||
|
||||
LtsTranslatableIdentifier(const QString &identifier, const QObject *context, const char *translatableText);
|
||||
|
||||
const QString &identifier() const { return m_identifier; }
|
||||
|
||||
const QString translatedText(const char *disambiguation = nullptr, int n = -1) const;
|
||||
|
||||
const QString _context() const { return QString::fromUtf8(m_translationContext); }
|
||||
|
||||
private:
|
||||
QString m_identifier;
|
||||
const char *m_translationContext;
|
||||
|
||||
const char *m_translatableText;
|
||||
};
|
||||
} // namespace LtsUtils
|
||||
@@ -1,21 +0,0 @@
|
||||
/**
|
||||
* Export definitions for LtsUtilsCore
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#ifndef LTSUTILSCORE_EXPORT
|
||||
#ifdef BUILD_STATIC_LIBRARIES
|
||||
#define LTSUTILSCORE_EXPORT
|
||||
#else
|
||||
#if defined(MAKE_LTSUTILSCORE_LIB)
|
||||
#define LTSUTILSCORE_EXPORT Q_DECL_EXPORT
|
||||
#else
|
||||
#define LTSUTILSCORE_EXPORT Q_DECL_IMPORT
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,14 +0,0 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <qglobal.h>
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
inline bool isPositionTimeOutdated(qint64 curTime, qint64 posTime)
|
||||
{
|
||||
|
||||
return curTime > posTime + 11 * 60 * 1000;
|
||||
}
|
||||
} // namespace LtsUtils
|
||||
@@ -1,145 +0,0 @@
|
||||
|
||||
|
||||
#include "pgarray.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QStringView>
|
||||
#include <QtCore/QVector>
|
||||
#include <functional>
|
||||
#include <ltsutilscore_export.h>
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
|
||||
template <typename T> static inline QString convertToPgString(const std::vector<T> &data)
|
||||
{
|
||||
if (data.size() == 0)
|
||||
return QLatin1String("{}");
|
||||
QString ret(QLatin1Char('{'));
|
||||
for (T i : data)
|
||||
ret += QString::number(i) + QLatin1Char(',');
|
||||
ret.chop(1);
|
||||
ret += QLatin1Char('}');
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <> LTSUTILSCORE_EXPORT QString IntArray::toPgString() const
|
||||
{
|
||||
return convertToPgString(m_data);
|
||||
}
|
||||
|
||||
template <> LTSUTILSCORE_EXPORT QString BigintArray::toPgString() const
|
||||
{
|
||||
return convertToPgString(m_data);
|
||||
}
|
||||
|
||||
template <typename T> static inline T convertFromPgString(const QString &str, const std::function<typename T::Type(QStringView val, bool *bOk)> &convertFunc)
|
||||
{
|
||||
typename T::ContainerType result;
|
||||
|
||||
int idxStart = str.indexOf(QLatin1Char('{'));
|
||||
int idxEnd = str.lastIndexOf(QLatin1Char('}'));
|
||||
if (idxEnd < idxStart)
|
||||
return T(result);
|
||||
if (idxStart < 0 && idxEnd < 0)
|
||||
{
|
||||
|
||||
idxStart = -1;
|
||||
idxEnd = str.length() + 1;
|
||||
}
|
||||
|
||||
const QStringView strRef = QStringView(str).mid(idxStart + 1, idxEnd - idxStart - 1);
|
||||
const QVector<QStringView> vec = strRef.split(QLatin1Char(','), Qt::SkipEmptyParts);
|
||||
result.reserve(vec.size());
|
||||
for (const QStringView &s : vec)
|
||||
{
|
||||
bool ok = false;
|
||||
const typename T::Type i = convertFunc(s, &ok);
|
||||
if (ok)
|
||||
result.push_back(i);
|
||||
}
|
||||
|
||||
return T(result);
|
||||
}
|
||||
|
||||
template <> LTSUTILSCORE_EXPORT IntArray IntArray::fromPgString(const QString &str)
|
||||
{
|
||||
return convertFromPgString<IntArray>(str, [](QStringView val, bool *bOk) { return val.toString().toInt(bOk); });
|
||||
}
|
||||
|
||||
template <> LTSUTILSCORE_EXPORT BigintArray BigintArray::fromPgString(const QString &str)
|
||||
{
|
||||
return convertFromPgString<BigintArray>(str, [](QStringView val, bool *bOk) { return val.toString().toLongLong(bOk); });
|
||||
}
|
||||
|
||||
template <typename T> static inline QString convertToPgString(const std::map<T, T> &data)
|
||||
{
|
||||
if (data.size() == 0)
|
||||
return QLatin1String("{}");
|
||||
QString ret(QLatin1Char('{'));
|
||||
for (const auto &it : data)
|
||||
{
|
||||
ret += QLatin1Char('{') + QString::number(it.first) + QLatin1Char(',') + QString::number(it.second) + QLatin1String("},");
|
||||
}
|
||||
ret.chop(1);
|
||||
ret += QLatin1Char('}');
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <> LTSUTILSCORE_EXPORT QString IntArray2D::toPgString() const
|
||||
{
|
||||
return convertToPgString<IntArray2D::Type>(m_data);
|
||||
}
|
||||
|
||||
template <> LTSUTILSCORE_EXPORT QString BigintArray2D::toPgString() const
|
||||
{
|
||||
return convertToPgString<BigintArray2D::Type>(m_data);
|
||||
}
|
||||
|
||||
template <typename T> static inline T convertFromPgString2D(const QString &str, const std::function<typename T::Type(QStringView val)> &convertFunc)
|
||||
{
|
||||
typename T::ContainerType ret;
|
||||
int idxStart = str.indexOf(QLatin1Char('{'));
|
||||
int idxEnd = str.lastIndexOf(QLatin1Char('}'));
|
||||
if (idxEnd < idxStart)
|
||||
return T(ret);
|
||||
if (idxStart < 0 && idxEnd < 0)
|
||||
{
|
||||
|
||||
idxStart = -1;
|
||||
idxEnd = str.length() + 1;
|
||||
}
|
||||
|
||||
const QStringView strRef = QStringView(str).mid(idxStart + 1, idxEnd - idxStart - 1);
|
||||
idxStart = strRef.indexOf(QLatin1Char('{'));
|
||||
while (idxStart >= 0)
|
||||
{
|
||||
idxEnd = strRef.indexOf(QLatin1Char('}'), idxStart);
|
||||
if (idxEnd < 0)
|
||||
break;
|
||||
|
||||
const QStringView keyValueStr = strRef.mid(idxStart + 1, idxEnd - idxStart - 1);
|
||||
const QVector<QStringView> keyValuePair = keyValueStr.split(QLatin1Char(','), Qt::SkipEmptyParts);
|
||||
if (keyValuePair.size() != 2)
|
||||
break;
|
||||
const typename T::Type key = convertFunc(keyValuePair.at(0).trimmed());
|
||||
const typename T::Type value = convertFunc(keyValuePair.at(1).trimmed());
|
||||
ret.insert(std::make_pair(key, value));
|
||||
|
||||
idxStart = strRef.indexOf(QLatin1Char('{'), idxEnd + 1);
|
||||
}
|
||||
|
||||
return T(ret);
|
||||
}
|
||||
|
||||
template <> LTSUTILSCORE_EXPORT IntArray2D IntArray2D::fromPgString(const QString &str)
|
||||
{
|
||||
return convertFromPgString2D<IntArray2D>(str, [](QStringView val) { return val.toString().toInt(); });
|
||||
}
|
||||
|
||||
template <> LTSUTILSCORE_EXPORT BigintArray2D BigintArray2D::fromPgString(const QString &str)
|
||||
{
|
||||
return convertFromPgString2D<BigintArray2D>(str, [](QStringView val) { return val.toString().toLongLong(); });
|
||||
}
|
||||
|
||||
} // namespace LtsUtils
|
||||
@@ -1,40 +0,0 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
#include <QtCore/QString>
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
|
||||
template <typename T, typename C> class PgArray
|
||||
{
|
||||
public:
|
||||
using Type = T;
|
||||
using ContainerType = C;
|
||||
|
||||
PgArray() = default;
|
||||
|
||||
Q_DECL_CONSTEXPR explicit PgArray(const C &data)
|
||||
: m_data(data)
|
||||
{
|
||||
}
|
||||
|
||||
Q_DECL_CONSTEXPR C operator()() const { return m_data; }
|
||||
|
||||
[[nodiscard]] QString toPgString() const;
|
||||
static PgArray fromPgString(const QString &str);
|
||||
|
||||
private:
|
||||
C m_data;
|
||||
};
|
||||
|
||||
using IntArray = PgArray<int, std::vector<int>>;
|
||||
using BigintArray = PgArray<int64_t, std::vector<int64_t>>;
|
||||
|
||||
using IntArray2D = PgArray<int, std::map<int, int>>;
|
||||
using BigintArray2D = PgArray<int64_t, std::map<int64_t, int64_t>>;
|
||||
|
||||
} // namespace LtsUtils
|
||||
@@ -1,82 +0,0 @@
|
||||
|
||||
|
||||
#include "promise.h"
|
||||
|
||||
#include <QtCore/QTimer>
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
|
||||
Promise::Promise(const std::function<void(ResultFunction resolve, ResultFunction reject)> &function, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_functionAlreadySet(false)
|
||||
, m_timeout(new QTimer(this))
|
||||
, m_resultSet(false)
|
||||
, m_timeoutSet(false)
|
||||
{
|
||||
m_timeout->setSingleShot(true);
|
||||
connect(m_timeout, &QTimer::timeout, this, &Promise::slotTimeout);
|
||||
setFunction(function);
|
||||
}
|
||||
|
||||
void Promise::setFunction(const std::function<void(ResultFunction resolve, ResultFunction reject)> &function)
|
||||
{
|
||||
if (!function || m_functionAlreadySet)
|
||||
return;
|
||||
|
||||
m_functionAlreadySet = true;
|
||||
|
||||
if (m_timeoutSet)
|
||||
m_timeout->start();
|
||||
|
||||
QTimer::singleShot(0, this, [this, function]() { function([this](const QVariant &value) { resolve(value); }, [this](const QVariant &value) { reject(value); }); });
|
||||
}
|
||||
|
||||
void Promise::setTimeout(int interval)
|
||||
{
|
||||
m_timeout->stop();
|
||||
m_timeout->setInterval(interval);
|
||||
m_timeoutSet = (interval != 0);
|
||||
|
||||
if (interval != 0 && m_functionAlreadySet)
|
||||
m_timeout->start();
|
||||
}
|
||||
|
||||
void Promise::slotTimeout()
|
||||
{
|
||||
reject(QStringLiteral("timeout"));
|
||||
}
|
||||
|
||||
void Promise::resolve(const QVariant &value)
|
||||
{
|
||||
if (m_resultSet)
|
||||
return;
|
||||
m_resultSet = true;
|
||||
|
||||
m_timeout->stop();
|
||||
m_resolveFn(value);
|
||||
}
|
||||
|
||||
void Promise::reject(const QVariant &value)
|
||||
{
|
||||
if (m_resultSet)
|
||||
return;
|
||||
m_resultSet = true;
|
||||
|
||||
m_timeout->stop();
|
||||
m_rejectFn(value);
|
||||
}
|
||||
|
||||
Promise &Promise::resolved(ResultFunction resolveFn)
|
||||
{
|
||||
m_resolveFn = resolveFn;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Promise &Promise::rejected(ResultFunction rejectFn)
|
||||
{
|
||||
m_rejectFn = rejectFn;
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace LtsUtils
|
||||
@@ -1,47 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "ltsutilscore_export.h"
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QVariant>
|
||||
#include <functional>
|
||||
|
||||
class QTimer;
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
typedef std::function<void(const QVariant &value)> RawResultFunction;
|
||||
typedef const RawResultFunction &ResultFunction;
|
||||
|
||||
class LTSUTILSCORE_EXPORT Promise : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Promise(const std::function<void(ResultFunction resolve, ResultFunction reject)> &function, QObject *parent = nullptr);
|
||||
|
||||
void setFunction(const std::function<void(ResultFunction resolve, ResultFunction reject)> &function);
|
||||
|
||||
void resolve(const QVariant &value = QVariant());
|
||||
|
||||
void reject(const QVariant &value = QVariant());
|
||||
|
||||
void setTimeout(int interval);
|
||||
|
||||
Promise &resolved(ResultFunction resolveFn);
|
||||
|
||||
Promise &rejected(ResultFunction rejectFn);
|
||||
|
||||
private:
|
||||
RawResultFunction m_resolveFn;
|
||||
RawResultFunction m_rejectFn;
|
||||
bool m_functionAlreadySet;
|
||||
QTimer *m_timeout;
|
||||
bool m_resultSet;
|
||||
bool m_timeoutSet;
|
||||
|
||||
private slots:
|
||||
void slotTimeout();
|
||||
};
|
||||
|
||||
} // namespace LtsUtils
|
||||
@@ -1,122 +0,0 @@
|
||||
#include "promise_examples.h"
|
||||
|
||||
#include "promise.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtTest/QTest>
|
||||
#include <QtCore/QTimer>
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
|
||||
void PromiseExample1_Class::doSomethingAsync1()
|
||||
{
|
||||
QTimer::singleShot(200, this, [this]() { emit signalDone1(true); });
|
||||
}
|
||||
|
||||
void PromiseExample1_Class::doSomethingAsync2()
|
||||
{
|
||||
QTimer::singleShot(450, this, [this]() { emit signalDone2(true, 1234); });
|
||||
}
|
||||
|
||||
PromiseExample1::PromiseExample1(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_success(false)
|
||||
{
|
||||
|
||||
auto func = [this](ResultFunction resolve, ResultFunction reject)
|
||||
{
|
||||
PromiseExample1_Class *c = new PromiseExample1_Class(this);
|
||||
|
||||
connect(c,
|
||||
&PromiseExample1_Class::signalDone1,
|
||||
this,
|
||||
[this, c, resolve, reject](bool didThisWork)
|
||||
{
|
||||
if (!didThisWork)
|
||||
{
|
||||
|
||||
reject(QStringLiteral("First Action did not succeed"));
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
connect(c,
|
||||
&PromiseExample1_Class::signalDone2,
|
||||
this,
|
||||
[resolve, reject](bool didThisWork, int someNumberThatReturns)
|
||||
{
|
||||
if (didThisWork)
|
||||
resolve(someNumberThatReturns);
|
||||
else
|
||||
reject(QStringLiteral("Second Action did not succeed"));
|
||||
});
|
||||
|
||||
c->doSomethingAsync2();
|
||||
}
|
||||
});
|
||||
|
||||
c->doSomethingAsync1();
|
||||
};
|
||||
Promise *p = new Promise(func, this);
|
||||
|
||||
p->resolved(
|
||||
[this](const QVariant &value)
|
||||
{
|
||||
qDebug() << "example1 promise succeeded! 'someNumberThatReturns' was" << value;
|
||||
|
||||
m_success = true;
|
||||
})
|
||||
.rejected([](const QVariant &value) { qDebug() << "example1 promise failed.." << value; });
|
||||
}
|
||||
|
||||
PromiseExample2::PromiseExample2(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_success(false)
|
||||
{
|
||||
|
||||
Promise* p = new Promise(
|
||||
[](ResultFunction, ResultFunction) {
|
||||
|
||||
},
|
||||
this);
|
||||
|
||||
p->setTimeout(1000);
|
||||
|
||||
p->resolved([](const QVariant &) { QFAIL("This test case's promise should never resolve"); });
|
||||
|
||||
p->rejected(
|
||||
[this](const QVariant &val)
|
||||
{
|
||||
QVERIFY2(val == QStringLiteral("timeout"), "Promise didn't reject with string \"timeout\"");
|
||||
qDebug() << "Promise rejected as expected";
|
||||
m_success = true;
|
||||
});
|
||||
}
|
||||
|
||||
PromiseExample3::PromiseExample3(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_success(true)
|
||||
, m_alreadyRejected(false)
|
||||
{
|
||||
|
||||
Promise *p = new Promise([](ResultFunction, ResultFunction reject) { reject(QString()); }, this);
|
||||
|
||||
p->setTimeout(1000);
|
||||
|
||||
p->resolved([](const QVariant &) { QFAIL("This test case's promise should never resolve"); });
|
||||
|
||||
p->rejected(
|
||||
[this](const QVariant &val)
|
||||
{
|
||||
qDebug() << "rejected with val" << val;
|
||||
QVERIFY2(val == QString(), "Promise didn't reject with an expected empty string.");
|
||||
QVERIFY2(!m_alreadyRejected, "Promise rejected more than once");
|
||||
|
||||
m_alreadyRejected = true;
|
||||
qDebug() << "Promise rejected as expected";
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace LtsUtils
|
||||
@@ -1,59 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
|
||||
class PromiseExample1_Class : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
using QObject::QObject;
|
||||
|
||||
void doSomethingAsync1();
|
||||
void doSomethingAsync2();
|
||||
|
||||
signals:
|
||||
void signalDone1(bool didThisWork);
|
||||
void signalDone2(bool didThisWork, int someNumberThatReturns);
|
||||
};
|
||||
|
||||
class PromiseExample1 : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit PromiseExample1(QObject *parent = nullptr);
|
||||
|
||||
[[nodiscard]] bool isSuccess() const { return m_success; }
|
||||
|
||||
private:
|
||||
bool m_success;
|
||||
};
|
||||
|
||||
class PromiseExample2 : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit PromiseExample2(QObject *parent = nullptr);
|
||||
|
||||
[[nodiscard]] bool isSuccess() const { return m_success; }
|
||||
|
||||
private:
|
||||
bool m_success;
|
||||
};
|
||||
|
||||
class PromiseExample3 : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit PromiseExample3(QObject *parent = nullptr);
|
||||
|
||||
[[nodiscard]] bool isSuccess() const { return m_success; }
|
||||
|
||||
private:
|
||||
bool m_success;
|
||||
bool m_alreadyRejected;
|
||||
};
|
||||
|
||||
} // namespace LtsUtils
|
||||
-243
@@ -1,243 +0,0 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QByteArray>
|
||||
#include <limits>
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
|
||||
template <typename T> void inline set8Byte(const T in, QByteArray &out)
|
||||
{
|
||||
static_assert(std::is_integral_v<T> || std::is_enum_v<T>, "Only integrals allowed for raw byte accessd");
|
||||
out += (in & 0xFF00000000000000UL) >> 56;
|
||||
out += (in & 0x00FF000000000000UL) >> 48;
|
||||
out += (in & 0x0000FF0000000000UL) >> 40;
|
||||
out += (in & 0x000000FF00000000UL) >> 32;
|
||||
out += (in & 0x00000000FF000000UL) >> 24;
|
||||
out += (in & 0x0000000000FF0000UL) >> 16;
|
||||
out += (in & 0x000000000000FF00UL) >> 8;
|
||||
out += (in & 0x00000000000000FFUL);
|
||||
}
|
||||
|
||||
template <> void inline set8Byte(const double in, QByteArray &out)
|
||||
{
|
||||
union hack
|
||||
{
|
||||
double d;
|
||||
int64_t i;
|
||||
} h;
|
||||
|
||||
h.d = in;
|
||||
set8Byte(h.i, out);
|
||||
}
|
||||
|
||||
template <typename T> bool inline get8Byte(const QByteArray &baData, size_t &pos, T &out)
|
||||
{
|
||||
static_assert(std::is_integral_v<T> || std::is_enum_v<T>, "Only integrals allowed for raw byte accessd");
|
||||
static_assert(sizeof(T) >= 8, "sizeof(out) is smaller than 8 bytes - will not fit");
|
||||
out = T();
|
||||
|
||||
if (size_t(baData.size()) < pos + 8)
|
||||
return false;
|
||||
|
||||
const char *data = baData.data() + pos;
|
||||
|
||||
if (std::numeric_limits<T>::is_signed)
|
||||
out |= static_cast<signed long long>(data[0]) << 56;
|
||||
else
|
||||
out |= (data[0] & 0xFFULL) << 56;
|
||||
out |= (data[1] & 0xFFULL) << 48;
|
||||
out |= (data[2] & 0xFFULL) << 40;
|
||||
out |= (data[3] & 0xFFULL) << 32;
|
||||
out |= (data[4] & 0xFFULL) << 24;
|
||||
out |= (data[5] & 0xFFULL) << 16;
|
||||
out |= (data[6] & 0xFFULL) << 8;
|
||||
out |= (data[7] & 0xFFULL);
|
||||
|
||||
pos += 8;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <> bool inline get8Byte(const QByteArray &baData, size_t &pos, double &out)
|
||||
{
|
||||
out = 0.;
|
||||
|
||||
union hack
|
||||
{
|
||||
double d;
|
||||
int64_t i;
|
||||
} h;
|
||||
|
||||
if (!get8Byte(baData, pos, h.i))
|
||||
return false;
|
||||
out = h.d;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T> bool inline get8Byte(const QByteArray &data, T &out)
|
||||
{
|
||||
size_t pos = 0;
|
||||
return get8Byte(data, pos, out);
|
||||
}
|
||||
|
||||
template <typename T> void inline set4Byte(const T in, QByteArray &out)
|
||||
{
|
||||
static_assert(std::is_integral_v<T> || std::is_enum_v<T>, "Only integrals allowed for raw byte accessd");
|
||||
out += (in & 0xFF000000) >> 24;
|
||||
out += (in & 0x00FF0000) >> 16;
|
||||
out += (in & 0x0000FF00) >> 8;
|
||||
out += (in & 0x000000FF);
|
||||
}
|
||||
|
||||
template <> void inline set4Byte(const double in, QByteArray &out)
|
||||
{
|
||||
int tmp = qRound(in);
|
||||
return set4Byte(tmp, out);
|
||||
}
|
||||
|
||||
template <typename T> bool inline get4Byte(const QByteArray &baData, size_t &pos, T &out)
|
||||
{
|
||||
static_assert(std::is_integral_v<T> || std::is_enum_v<T>, "Only integrals allowed for raw byte accessd");
|
||||
static_assert(sizeof(T) >= 4, "sizeof(out) is smaller than 4 bytes - will not fit");
|
||||
out = T();
|
||||
|
||||
if (size_t(baData.size()) < pos + 4)
|
||||
return false;
|
||||
|
||||
const char *data = baData.data() + pos;
|
||||
|
||||
if (std::numeric_limits<T>::is_signed)
|
||||
out |= data[0] << 24;
|
||||
else
|
||||
out |= (data[0] & 0xFFU) << 24;
|
||||
out |= (data[1] & 0xFFU) << 16;
|
||||
out |= (data[2] & 0xFFU) << 8;
|
||||
out |= (data[3] & 0xFFU);
|
||||
|
||||
pos += 4;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <> bool inline get4Byte(const QByteArray &baData, size_t &pos, double &out)
|
||||
{
|
||||
out = 0.;
|
||||
int tmp;
|
||||
if (!get4Byte(baData, pos, tmp))
|
||||
return false;
|
||||
out = tmp;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T> bool inline get4Byte(const QByteArray &data, T &out)
|
||||
{
|
||||
size_t pos = 0;
|
||||
return get4Byte(data, pos, out);
|
||||
}
|
||||
|
||||
template <typename T> void inline set3Byte(const T in, QByteArray &out)
|
||||
{
|
||||
static_assert(std::is_integral_v<T> || std::is_enum_v<T>, "Only integrals allowed for raw byte accessd");
|
||||
out += (in & 0x00FF0000) >> 16;
|
||||
out += (in & 0x0000FF00) >> 8;
|
||||
out += (in & 0x000000FF);
|
||||
}
|
||||
|
||||
template <typename T> bool inline get3Byte(const QByteArray &baData, size_t &pos, T &out)
|
||||
{
|
||||
static_assert(std::is_integral_v<T> || std::is_enum_v<T>, "Only integrals allowed for raw byte accessd");
|
||||
static_assert(sizeof(T) >= 3, "sizeof(out) is smaller than 3 bytes - will not fit");
|
||||
out = T();
|
||||
|
||||
if (size_t(baData.size()) < pos + 3)
|
||||
return false;
|
||||
|
||||
const char *data = baData.data() + pos;
|
||||
|
||||
if (std::numeric_limits<T>::is_signed)
|
||||
out |= data[0] << 16;
|
||||
else
|
||||
out |= (data[0] & 0xFFU) << 16;
|
||||
out |= (data[1] & 0xFFU) << 8;
|
||||
out |= (data[2] & 0xFFU);
|
||||
|
||||
pos += 3;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T> bool inline get3Byte(const QByteArray &data, T &out)
|
||||
{
|
||||
size_t pos = 0;
|
||||
return get3Byte(data, pos, out);
|
||||
}
|
||||
|
||||
template <typename T> void inline set2Byte(const T in, QByteArray &out)
|
||||
{
|
||||
static_assert(std::is_integral_v<T> || std::is_enum_v<T>, "Only integrals allowed for raw byte accessd");
|
||||
out += (in & 0x0000FF00) >> 8;
|
||||
out += (in & 0x000000FF);
|
||||
}
|
||||
|
||||
template <typename T> bool inline get2Byte(const QByteArray &baData, size_t &pos, T &out)
|
||||
{
|
||||
static_assert(std::is_integral_v<T> || std::is_enum_v<T>, "Only integrals allowed for raw byte accessd");
|
||||
static_assert(sizeof(T) >= 2, "sizeof(out) is smaller than 2 bytes - will not fit");
|
||||
out = T();
|
||||
|
||||
if (size_t(baData.size()) < pos + 2)
|
||||
return false;
|
||||
|
||||
const char *data = baData.data() + pos;
|
||||
|
||||
if (std::numeric_limits<T>::is_signed)
|
||||
out |= data[0] << 8;
|
||||
else
|
||||
out |= (data[0] & 0xFFU) << 8;
|
||||
out |= data[1] & 0xFFU;
|
||||
|
||||
pos += 2;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T> bool inline get2Byte(const QByteArray &data, T &out)
|
||||
{
|
||||
size_t pos = 0;
|
||||
return get2Byte(data, pos, out);
|
||||
}
|
||||
|
||||
template <typename T> void inline set1Byte(const T in, QByteArray &out)
|
||||
{
|
||||
static_assert(std::is_integral_v<T> || std::is_enum_v<T>, "Only integrals allowed for raw byte accessd");
|
||||
unsigned char c = static_cast<unsigned char>(in);
|
||||
out += c;
|
||||
}
|
||||
|
||||
template <typename T> bool inline get1Byte(const QByteArray &baData, size_t &pos, T &out)
|
||||
{
|
||||
static_assert(std::is_integral_v<T> || std::is_enum_v<T>, "Only integrals allowed for raw byte accessd");
|
||||
out = T();
|
||||
|
||||
if (size_t(baData.size()) < pos + 1)
|
||||
return false;
|
||||
|
||||
if (std::numeric_limits<T>::is_signed)
|
||||
out = (T)(baData.at(pos));
|
||||
else
|
||||
out = (T)(baData.at(pos) & 0xFF);
|
||||
|
||||
pos += 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T> bool inline get1Byte(const QByteArray &data, T &out)
|
||||
{
|
||||
size_t pos = 0;
|
||||
return get1Byte(data, pos, out);
|
||||
}
|
||||
} // namespace LtsUtils
|
||||
@@ -1,76 +0,0 @@
|
||||
#include "qplane3d.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
|
||||
QPlane3D::QPlane3D(const QPoint3D &pos, const QPoint3D &vec1, const QPoint3D &vec2)
|
||||
: m_pos(pos)
|
||||
, m_vec1(vec1)
|
||||
, m_vec2(vec2)
|
||||
{
|
||||
m_normal = QPoint3D::crossProduct(m_vec1, m_vec2);
|
||||
m_planeC = QPoint3D::dotProduct(m_pos, m_normal);
|
||||
}
|
||||
|
||||
QPoint3D QPlane3D::intersection(const QPoint3D &point, const QPoint3D &direction) const
|
||||
{
|
||||
const double dotProduct = QPoint3D::dotProduct(direction, m_normal);
|
||||
if (qFuzzyIsNull(dotProduct))
|
||||
return inPlane(point) ? point : QPoint3D();
|
||||
const double distance = distanceTo(point) / std::abs(dotProduct);
|
||||
return point + distance * direction;
|
||||
}
|
||||
|
||||
bool QPlane3D::intersects(const QPoint3D &direction) const
|
||||
{
|
||||
return !isParallel(direction);
|
||||
}
|
||||
|
||||
bool QPlane3D::isParallel(const QPoint3D &direction) const
|
||||
{
|
||||
return qFuzzyIsNull(QPoint3D::dotProduct(m_normal, direction));
|
||||
}
|
||||
|
||||
bool QPlane3D::inPlane(const QPoint3D &point) const
|
||||
{
|
||||
if (point == m_pos)
|
||||
return true;
|
||||
return qFuzzyIsNull(QPoint3D::dotProduct(m_normal, point - m_pos));
|
||||
}
|
||||
|
||||
double QPlane3D::distanceTo(const QPoint3D &point) const
|
||||
{
|
||||
return QPoint3D::dotProduct(point - m_pos, m_normal);
|
||||
}
|
||||
|
||||
QPolygon3D::QPolygon3D(const QVector<QPoint3D> &vertices)
|
||||
: QPlane3D(vertices[0], vertices[1], vertices[2])
|
||||
, m_vertices(vertices)
|
||||
{
|
||||
}
|
||||
|
||||
bool QPolygon3D::containsPoint(const QPoint3D &point) const
|
||||
{
|
||||
if (!inPlane(point))
|
||||
return false;
|
||||
|
||||
if (contains(point))
|
||||
return true;
|
||||
|
||||
double angleSum = 0.;
|
||||
double cosTheta = 0.;
|
||||
const int numberOfVertices = m_vertices.size();
|
||||
for (int i = 0; i < m_vertices.size(); ++i)
|
||||
{
|
||||
const QPoint3D &first = m_vertices[i % numberOfVertices] - point;
|
||||
const QPoint3D &second = m_vertices[(i + 1) % numberOfVertices] - point;
|
||||
|
||||
cosTheta = QPoint3D::dotProduct(first, second) / (first.length() * second.length());
|
||||
angleSum += acos(cosTheta);
|
||||
}
|
||||
return qFuzzyIsNull(M_2_PI - angleSum);
|
||||
}
|
||||
|
||||
} // namespace LtsUtils
|
||||
@@ -1,58 +0,0 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ltsutilscore_export.h"
|
||||
#include "qpoint3d.h"
|
||||
|
||||
#include <QtCore/QPointF>
|
||||
#include <QtCore/QVector>
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
|
||||
class LTSUTILSCORE_EXPORT QPlane3D
|
||||
{
|
||||
|
||||
public:
|
||||
QPlane3D(const QPoint3D &pos, const QPoint3D &vec1, const QPoint3D &vec2);
|
||||
|
||||
QPoint3D intersection(const QPoint3D &point, const QPoint3D &direction) const;
|
||||
bool intersects(const QPoint3D &direction) const;
|
||||
bool isParallel(const QPoint3D &direction) const;
|
||||
bool inPlane(const QPoint3D &point) const;
|
||||
double distanceTo(const QPoint3D &point) const;
|
||||
|
||||
const QPoint3D &pos() const { return m_pos; }
|
||||
|
||||
const QPoint3D &vec1() const { return m_vec1; }
|
||||
|
||||
const QPoint3D &vec2() const { return m_vec2; }
|
||||
|
||||
const QPoint3D &normal() const { return m_normal; }
|
||||
|
||||
double planeC() const { return m_planeC; }
|
||||
|
||||
protected:
|
||||
QPoint3D m_pos;
|
||||
QPoint3D m_vec1;
|
||||
QPoint3D m_vec2;
|
||||
QPoint3D m_normal;
|
||||
double m_planeC;
|
||||
};
|
||||
|
||||
class LTSUTILSCORE_EXPORT QPolygon3D : public QPlane3D
|
||||
{
|
||||
|
||||
public:
|
||||
QPolygon3D(const QVector<QPoint3D> &vertices);
|
||||
|
||||
bool contains(const QPoint3D &point) const { return m_vertices.contains(point); }
|
||||
|
||||
bool containsPoint(const QPoint3D &point) const;
|
||||
|
||||
private:
|
||||
QVector<QPoint3D> m_vertices;
|
||||
};
|
||||
|
||||
} // namespace LtsUtils
|
||||
@@ -1,28 +0,0 @@
|
||||
|
||||
|
||||
#include "qpoint3d.h"
|
||||
|
||||
#include <QtCore/QDataStream>
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
|
||||
QDataStream &operator<<(QDataStream &s, const QPoint3D &p)
|
||||
{
|
||||
s << p.x() << p.y() << p.z();
|
||||
return s;
|
||||
}
|
||||
|
||||
QDataStream &operator>>(QDataStream &s, QPoint3D &p)
|
||||
{
|
||||
double x, y, z;
|
||||
s >> x;
|
||||
p.rx() = x;
|
||||
s >> y;
|
||||
p.ry() = y;
|
||||
s >> z;
|
||||
p.rz() = z;
|
||||
return s;
|
||||
}
|
||||
|
||||
} // namespace LtsUtils
|
||||
@@ -1,287 +0,0 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ltsutilscore_export.h"
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
#include <QtCore/qpoint.h>
|
||||
#include <QtCore/qdatastream.h>
|
||||
#include <cmath>
|
||||
#include <sstream>
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
|
||||
class QPoint3D
|
||||
{
|
||||
public:
|
||||
enum class Axis
|
||||
{
|
||||
X,
|
||||
Y,
|
||||
Z
|
||||
};
|
||||
|
||||
constexpr QPoint3D() = default;
|
||||
constexpr QPoint3D(double xpos, double ypos, double zpos);
|
||||
|
||||
template <typename T>
|
||||
explicit QPoint3D(const T &data)
|
||||
: xp(data.offsetX())
|
||||
, yp(data.offsetY())
|
||||
, zp(data.offsetZ())
|
||||
{
|
||||
}
|
||||
|
||||
inline bool isNull() const;
|
||||
|
||||
constexpr inline double x() const;
|
||||
constexpr inline double y() const;
|
||||
constexpr inline double z() const;
|
||||
constexpr inline void setX(double xpos);
|
||||
constexpr inline void setY(double ypos);
|
||||
constexpr inline void setZ(double zpos);
|
||||
|
||||
constexpr inline double &rx();
|
||||
constexpr inline double &ry();
|
||||
constexpr inline double &rz();
|
||||
|
||||
constexpr inline QPointF toPointF() const;
|
||||
|
||||
static QPoint3D fromQPointF(const QPointF &p) { return QPoint3D(p.x(), p.y(), .0); }
|
||||
|
||||
inline double lengthSquared() const { return (xp * xp) + (yp * yp) + (zp * zp); }
|
||||
|
||||
inline double length() const { return std::sqrt(lengthSquared()); }
|
||||
|
||||
inline void normalize()
|
||||
{
|
||||
double len = xp * xp + yp * yp + zp * zp;
|
||||
if (qFuzzyIsNull(len - 1.0f) || qFuzzyIsNull(len))
|
||||
return;
|
||||
|
||||
len = std::sqrt(len);
|
||||
|
||||
xp /= len;
|
||||
yp /= len;
|
||||
zp /= len;
|
||||
}
|
||||
|
||||
inline QPoint3D normalized() const
|
||||
{
|
||||
double len = xp * xp + yp * yp + zp * zp;
|
||||
if (qFuzzyIsNull(len - 1.0f))
|
||||
return *this;
|
||||
else if (!qFuzzyIsNull(len))
|
||||
return *this / std::sqrt(len);
|
||||
else
|
||||
return QPoint3D(*this);
|
||||
}
|
||||
|
||||
inline void rotate(const double &phi, const Axis &axis)
|
||||
{
|
||||
const double sin = std::sin(phi);
|
||||
const double cos = std::cos(phi);
|
||||
switch (axis)
|
||||
{
|
||||
case Axis::X:
|
||||
{
|
||||
const double _yp = (cos * yp) - (sin * zp);
|
||||
const double _zp = (sin * yp) + (cos * zp);
|
||||
yp = _yp;
|
||||
zp = _zp;
|
||||
break;
|
||||
}
|
||||
case Axis::Y:
|
||||
{
|
||||
const double _xp = (cos * xp) + (sin * zp);
|
||||
const double _zp = (-sin * xp) + (cos * zp);
|
||||
xp = _xp;
|
||||
zp = _zp;
|
||||
break;
|
||||
}
|
||||
case Axis::Z:
|
||||
{
|
||||
const double _xp = (cos * xp) - (sin * yp);
|
||||
const double _yp = (sin * xp) + (cos * yp);
|
||||
xp = _xp;
|
||||
yp = _yp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline QPoint3D rotated(const double &phi, const Axis &axis) const
|
||||
{
|
||||
QPoint3D p(*this);
|
||||
p.rotate(phi, axis);
|
||||
return p;
|
||||
}
|
||||
|
||||
inline double distanceToLine(const QPoint3D &point, const QPoint3D &direction) const
|
||||
{
|
||||
if (direction.isNull())
|
||||
return (*this - point).length();
|
||||
QPoint3D p = point + dotProduct(*this - point, direction) * direction;
|
||||
return (*this - p).length();
|
||||
}
|
||||
inline double distanceToPlane(const QPoint3D &plane, const QPoint3D &normal) const { return dotProduct(*this - plane, normal); }
|
||||
inline double distanceToPlane(const QPoint3D &plane1, const QPoint3D &plane2, const QPoint3D &plane3) const
|
||||
{
|
||||
QPoint3D n = normal(plane2 - plane1, plane3 - plane1);
|
||||
return dotProduct(*this - plane1, n);
|
||||
}
|
||||
inline double distanceToPoint(const QPoint3D &point) const { return (*this - point).length(); }
|
||||
|
||||
friend constexpr inline bool operator==(const QPoint3D &p1, const QPoint3D &p2);
|
||||
friend constexpr inline bool operator!=(const QPoint3D &p1, const QPoint3D &p2);
|
||||
|
||||
friend constexpr inline QPoint3D operator+(const QPoint3D &p1, const QPoint3D &p2) { return QPoint3D(p1.xp + p2.xp, p1.yp + p2.yp, p1.zp + p2.zp); }
|
||||
|
||||
friend constexpr inline QPoint3D operator-(const QPoint3D &p1, const QPoint3D &p2) { return QPoint3D(p1.xp - p2.xp, p1.yp - p2.yp, p1.zp - p2.zp); }
|
||||
|
||||
friend constexpr inline QPoint3D operator*(const QPoint3D &p1, double factor) { return QPoint3D(p1.xp * factor, p1.yp * factor, p1.zp * factor); }
|
||||
|
||||
friend constexpr inline QPoint3D operator*(double factor, const QPoint3D &p1) { return QPoint3D(p1.xp * factor, p1.yp * factor, p1.zp * factor); }
|
||||
|
||||
friend constexpr inline QPoint3D operator/(const QPoint3D &p1, double factor) { return QPoint3D(p1.xp / factor, p1.yp / factor, p1.zp / factor); }
|
||||
|
||||
constexpr inline QPoint3D &operator+=(const QPoint3D &o)
|
||||
{
|
||||
xp += o.xp;
|
||||
yp += o.yp;
|
||||
zp += o.zp;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr inline QPoint3D &operator-=(const QPoint3D &o)
|
||||
{
|
||||
xp -= o.xp;
|
||||
yp -= o.yp;
|
||||
zp -= o.zp;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr inline QPoint3D &operator*=(double factor)
|
||||
{
|
||||
xp *= factor;
|
||||
yp *= factor;
|
||||
zp *= factor;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr inline QPoint3D &operator/=(double divisor)
|
||||
{
|
||||
xp /= divisor;
|
||||
yp /= divisor;
|
||||
zp /= divisor;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr static inline double dotProduct(const QPoint3D &v1, const QPoint3D &v2) { return v1.xp * v2.xp + v1.yp * v2.yp + v1.zp * v2.zp; }
|
||||
|
||||
constexpr static inline QPoint3D crossProduct(const QPoint3D &v1, const QPoint3D &v2)
|
||||
{
|
||||
return QPoint3D(v1.yp * v2.zp - v1.zp * v2.yp, v1.zp * v2.xp - v1.xp * v2.zp, v1.xp * v2.yp - v1.yp * v2.xp);
|
||||
}
|
||||
|
||||
static inline QPoint3D normal(const QPoint3D &v1, const QPoint3D &v2) { return crossProduct(v1, v2).normalized(); }
|
||||
|
||||
static inline QPoint3D normal(const QPoint3D &v1, const QPoint3D &v2, const QPoint3D &v3) { return crossProduct((v2 - v1), (v3 - v1)).normalized(); }
|
||||
|
||||
friend inline bool qFuzzyCompare(const QPoint3D &v1, const QPoint3D &v2)
|
||||
{
|
||||
return ::qFuzzyCompare(v1.xp, v2.xp) && ::qFuzzyCompare(v1.yp, v2.yp) && ::qFuzzyCompare(v1.zp, v2.zp);
|
||||
}
|
||||
|
||||
private:
|
||||
double xp = 0;
|
||||
double yp = 0;
|
||||
double zp = 0;
|
||||
};
|
||||
|
||||
// QDataStream& operator<<(QDataStream& s, const QPoint3D& p);
|
||||
// QDataStream& operator>>(QDataStream& s, QPoint3D& p);
|
||||
|
||||
constexpr inline QPoint3D::QPoint3D(double xpos, double ypos, double zpos)
|
||||
: xp(xpos)
|
||||
, yp(ypos)
|
||||
, zp(zpos)
|
||||
{
|
||||
}
|
||||
|
||||
inline bool QPoint3D::isNull() const
|
||||
{
|
||||
return qIsNull(xp) && qIsNull(yp) && qIsNull(zp);
|
||||
}
|
||||
|
||||
constexpr inline double QPoint3D::x() const
|
||||
{
|
||||
return xp;
|
||||
}
|
||||
|
||||
constexpr inline double QPoint3D::y() const
|
||||
{
|
||||
return yp;
|
||||
}
|
||||
|
||||
constexpr inline double QPoint3D::z() const
|
||||
{
|
||||
return zp;
|
||||
}
|
||||
|
||||
constexpr inline void QPoint3D::setX(double xpos)
|
||||
{
|
||||
xp = xpos;
|
||||
}
|
||||
|
||||
constexpr inline void QPoint3D::setY(double ypos)
|
||||
{
|
||||
yp = ypos;
|
||||
}
|
||||
|
||||
constexpr inline void QPoint3D::setZ(double zpos)
|
||||
{
|
||||
zp = zpos;
|
||||
}
|
||||
|
||||
constexpr inline double &QPoint3D::rx()
|
||||
{
|
||||
return xp;
|
||||
}
|
||||
|
||||
constexpr inline double &QPoint3D::ry()
|
||||
{
|
||||
return yp;
|
||||
}
|
||||
|
||||
constexpr inline double &QPoint3D::rz()
|
||||
{
|
||||
return zp;
|
||||
}
|
||||
|
||||
constexpr inline QPointF QPoint3D::toPointF() const
|
||||
{
|
||||
return QPointF(xp, yp);
|
||||
}
|
||||
|
||||
constexpr inline bool operator==(const QPoint3D &p1, const QPoint3D &p2)
|
||||
{
|
||||
return p1.xp == p2.xp && p1.yp == p2.yp && p1.zp == p2.zp;
|
||||
}
|
||||
|
||||
constexpr inline bool operator!=(const QPoint3D &p1, const QPoint3D &p2)
|
||||
{
|
||||
return p1.xp != p2.xp || p1.yp != p2.yp || p1.zp != p2.zp;
|
||||
}
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &stream, const QPoint3D &pos)
|
||||
{
|
||||
stream << "(" << pos.x() << "," << pos.y() << "," << pos.z() << ")";
|
||||
return stream;
|
||||
}
|
||||
|
||||
} // namespace LtsUtils
|
||||
|
||||
// Q_DECLARE_METATYPE(LtsUtils::QPoint3D)
|
||||
@@ -1,22 +0,0 @@
|
||||
|
||||
|
||||
#include "scoped_connection.h"
|
||||
|
||||
#include "connection.h"
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
|
||||
ScopedConnection::ScopedConnection(IConnection *connection, Qt::ConnectionType connType)
|
||||
: m_conn(connection)
|
||||
{
|
||||
Q_ASSERT(connection);
|
||||
m_conn->connect(connType);
|
||||
}
|
||||
|
||||
ScopedConnection::~ScopedConnection()
|
||||
{
|
||||
m_conn->disconnect();
|
||||
}
|
||||
|
||||
} // namespace LtsUtils
|
||||
@@ -1,24 +0,0 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ltsutilscore_export.h"
|
||||
|
||||
#include <Qt>
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
|
||||
class IConnection;
|
||||
|
||||
class LTSUTILSCORE_EXPORT ScopedConnection
|
||||
{
|
||||
public:
|
||||
explicit ScopedConnection(IConnection *connection, Qt::ConnectionType = Qt::AutoConnection);
|
||||
~ScopedConnection();
|
||||
|
||||
private:
|
||||
IConnection *m_conn;
|
||||
};
|
||||
|
||||
} // namespace LtsUtils
|
||||
-283
@@ -1,283 +0,0 @@
|
||||
|
||||
|
||||
#include "sfm_bytemessage_converter.h"
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
|
||||
static constexpr unsigned char XON = 0x11;
|
||||
static constexpr unsigned char XOFF = 0x13;
|
||||
static constexpr unsigned char STX = 0x02;
|
||||
static constexpr unsigned char ETX = 0x03;
|
||||
static constexpr unsigned char SUBST = 0x80;
|
||||
|
||||
static constexpr unsigned char SUB_XON = 0x91;
|
||||
static constexpr unsigned char SUB_XOFF = 0x93;
|
||||
static constexpr unsigned char SUB_STX = 0x82;
|
||||
static constexpr unsigned char SUB_ETX = 0x83;
|
||||
static constexpr unsigned char SUB_SUBST = 0x00;
|
||||
|
||||
static constexpr int HEADER_SIZE = 3;
|
||||
static constexpr int CHECKSUM_SIZE = 1;
|
||||
static constexpr int MINIMUM_BYTE_SIZE = 1 + HEADER_SIZE + CHECKSUM_SIZE + 1;
|
||||
|
||||
static SfmMessage getSfmMessage(const QByteArray &p_data)
|
||||
{
|
||||
|
||||
unsigned short id = 0;
|
||||
id |= (((unsigned short)p_data[0]) & 0x7F) << 8;
|
||||
id |= (((unsigned short)p_data[1]) & 0xFF) << 0;
|
||||
|
||||
SfmMessage msg;
|
||||
msg.setId(id);
|
||||
msg.setRtr(p_data[0] & 0x80);
|
||||
msg.setPayload(p_data.right(p_data.size() - HEADER_SIZE));
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
static QByteArray getHeader(const SfmMessage &p_msg)
|
||||
{
|
||||
QByteArray header(2, Qt::Uninitialized);
|
||||
|
||||
header[0] = ((p_msg.id() >> 8) & 0x7f) | (p_msg.rtr() << 7);
|
||||
|
||||
header[1] = (p_msg.id() >> 0) & 0xff;
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
static inline char getChecksum(const QByteArray &p_data)
|
||||
{
|
||||
char sum = 0;
|
||||
|
||||
for (const char c : p_data)
|
||||
sum += c;
|
||||
|
||||
return sum ^ 0xff;
|
||||
}
|
||||
|
||||
static QByteArray removeChecksum(const QByteArray &p_data)
|
||||
{
|
||||
QByteArray withoutChecksum(p_data);
|
||||
ConversionError error("Checksum error");
|
||||
|
||||
if (p_data.size() >= CHECKSUM_SIZE)
|
||||
{
|
||||
withoutChecksum.chop(1);
|
||||
|
||||
if (p_data.at(p_data.size() - 1) != getChecksum(withoutChecksum))
|
||||
throw error;
|
||||
}
|
||||
else
|
||||
throw error;
|
||||
|
||||
return withoutChecksum;
|
||||
}
|
||||
|
||||
static QByteArray maskData(const QByteArray &p_data)
|
||||
{
|
||||
QByteArray maskData;
|
||||
maskData.reserve(p_data.size() * 8 / 6);
|
||||
|
||||
for (const unsigned char byte : p_data)
|
||||
{
|
||||
switch (byte)
|
||||
{
|
||||
case XON:
|
||||
maskData.append(SUBST);
|
||||
maskData.append(SUB_XON);
|
||||
break;
|
||||
case XOFF:
|
||||
maskData.append(SUBST);
|
||||
maskData.append(SUB_XOFF);
|
||||
break;
|
||||
case STX:
|
||||
maskData.append(SUBST);
|
||||
maskData.append(SUB_STX);
|
||||
break;
|
||||
case ETX:
|
||||
maskData.append(SUBST);
|
||||
maskData.append(SUB_ETX);
|
||||
break;
|
||||
case SUBST:
|
||||
maskData.append(SUBST);
|
||||
maskData.append(static_cast<char>(SUB_SUBST));
|
||||
break;
|
||||
default:
|
||||
maskData.append(byte);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return maskData;
|
||||
}
|
||||
|
||||
static bool mustBeMasked(const unsigned char byte)
|
||||
{
|
||||
switch (byte)
|
||||
{
|
||||
case XON:
|
||||
case XOFF:
|
||||
case STX:
|
||||
case ETX:
|
||||
case SUBST:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int lenMaskedData(const QByteArray &data)
|
||||
{
|
||||
int ret = data.length();
|
||||
const unsigned char upperLen = ((data.length() & 0xff00) >> 8);
|
||||
const unsigned char lowerLen = ((data.length() & 0x00ff) >> 0);
|
||||
if (mustBeMasked(upperLen))
|
||||
++ret;
|
||||
if (mustBeMasked(lowerLen))
|
||||
++ret;
|
||||
for (const unsigned char byte : data)
|
||||
{
|
||||
if (mustBeMasked(byte))
|
||||
++ret;
|
||||
}
|
||||
if (mustBeMasked(getChecksum(data)))
|
||||
++ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static QByteArray unmaskData(const QByteArray &p_data)
|
||||
{
|
||||
QByteArray unmaskData;
|
||||
unmaskData.reserve(p_data.size());
|
||||
|
||||
for (int position = 0; position < p_data.size(); ++position)
|
||||
{
|
||||
unsigned char byte = p_data.at(position);
|
||||
if (byte == SUBST)
|
||||
{
|
||||
++position;
|
||||
byte = p_data.at(position);
|
||||
|
||||
switch (byte)
|
||||
{
|
||||
case SUB_XON:
|
||||
unmaskData.append(XON);
|
||||
break;
|
||||
case SUB_XOFF:
|
||||
unmaskData.append(XOFF);
|
||||
break;
|
||||
case SUB_STX:
|
||||
unmaskData.append(STX);
|
||||
break;
|
||||
case SUB_ETX:
|
||||
unmaskData.append(ETX);
|
||||
break;
|
||||
case SUB_SUBST:
|
||||
unmaskData.append(SUBST);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
unmaskData.append(byte);
|
||||
}
|
||||
return unmaskData;
|
||||
}
|
||||
|
||||
static QByteArray addFrame(const QByteArray &p_data)
|
||||
{
|
||||
QByteArray ret;
|
||||
ret.reserve(2 + p_data.size());
|
||||
ret.append(STX);
|
||||
ret.append(p_data);
|
||||
ret.append(ETX);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static QByteArray removeFrame(const QByteArray &p_data)
|
||||
{
|
||||
|
||||
if (p_data[0] == STX && p_data[p_data.size() - 1] == ETX)
|
||||
{
|
||||
|
||||
return p_data.mid(1, p_data.size() - 2);
|
||||
}
|
||||
else
|
||||
throw ConversionError("Framing Error");
|
||||
}
|
||||
|
||||
static void checkLength(const QByteArray &p_data)
|
||||
{
|
||||
if (p_data.size() < HEADER_SIZE)
|
||||
throw ConversionError("Telegram too short");
|
||||
|
||||
unsigned char length = p_data[HEADER_SIZE - 1];
|
||||
if (length != p_data.size() - HEADER_SIZE)
|
||||
throw ConversionError("Telegram length does not match");
|
||||
}
|
||||
|
||||
QByteArray byteStreamFromSfmMessage(const SfmMessage &message)
|
||||
{
|
||||
QByteArray byteData(getHeader(message));
|
||||
|
||||
byteData.append(message.payload().size());
|
||||
byteData.append(message.payload());
|
||||
byteData.append(getChecksum(byteData));
|
||||
|
||||
return addFrame(maskData(byteData));
|
||||
}
|
||||
|
||||
SfmMessage byteStreamToSfmMessage(const QByteArray &datastream)
|
||||
{
|
||||
if (datastream.size() < MINIMUM_BYTE_SIZE)
|
||||
throw ConversionError("Can't convert an QByteArray that hasn't the minimum size!");
|
||||
|
||||
QByteArray checkMsg;
|
||||
|
||||
checkMsg = removeFrame(datastream);
|
||||
checkMsg = unmaskData(checkMsg);
|
||||
|
||||
checkMsg = removeChecksum(checkMsg);
|
||||
|
||||
checkLength(checkMsg);
|
||||
|
||||
return getSfmMessage(checkMsg);
|
||||
}
|
||||
|
||||
QByteArray byteStreamFromEscMessage(const QByteArray &message)
|
||||
{
|
||||
QByteArray byteData = message;
|
||||
if (message.size() == 1)
|
||||
{
|
||||
|
||||
byteData.append(message);
|
||||
}
|
||||
else
|
||||
byteData.append(getChecksum(byteData));
|
||||
|
||||
byteData = maskData(byteData);
|
||||
byteData = addFrame(byteData);
|
||||
|
||||
return byteData;
|
||||
}
|
||||
|
||||
QByteArray byteStreamToEscMessage(const QByteArray &datastream)
|
||||
{
|
||||
if (datastream.size() < 2)
|
||||
return QByteArray("ERROR");
|
||||
|
||||
QByteArray checkMsg;
|
||||
|
||||
checkMsg = removeFrame(datastream);
|
||||
checkMsg = unmaskData(checkMsg);
|
||||
|
||||
checkMsg.chop(1);
|
||||
return checkMsg;
|
||||
}
|
||||
|
||||
} // namespace LtsUtils
|
||||
-51
@@ -1,51 +0,0 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ltsutilscore_export.h"
|
||||
|
||||
#include <QtCore/QByteArray>
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
|
||||
class LTSUTILSCORE_EXPORT SfmMessage
|
||||
{
|
||||
public:
|
||||
unsigned int id() const { return m_id; }
|
||||
|
||||
void setId(unsigned int id) { m_id = id; }
|
||||
|
||||
bool rtr() const { return m_rtr; }
|
||||
|
||||
void setRtr(bool rtr) { m_rtr = rtr; }
|
||||
|
||||
QByteArray payload() const { return m_payload; }
|
||||
|
||||
void setPayload(const QByteArray &payload) { m_payload = payload; }
|
||||
|
||||
bool operator==(const SfmMessage &msg) const { return (m_id == msg.id() && m_rtr == msg.rtr() && m_payload == msg.payload()); }
|
||||
|
||||
protected:
|
||||
unsigned int m_id = 0;
|
||||
bool m_rtr = false;
|
||||
QByteArray m_payload;
|
||||
};
|
||||
|
||||
class ConversionError : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
LTSUTILSCORE_EXPORT QByteArray byteStreamFromSfmMessage(const SfmMessage &message);
|
||||
|
||||
LTSUTILSCORE_EXPORT SfmMessage byteStreamToSfmMessage(const QByteArray &datastream);
|
||||
|
||||
LTSUTILSCORE_EXPORT QByteArray byteStreamFromEscMessage(const QByteArray &message);
|
||||
|
||||
LTSUTILSCORE_EXPORT QByteArray byteStreamToEscMessage(const QByteArray &datastream);
|
||||
|
||||
LTSUTILSCORE_EXPORT int lenMaskedData(const QByteArray &data);
|
||||
|
||||
} // namespace LtsUtils
|
||||
@@ -1,37 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QDateTime>
|
||||
#include <QtCore/QVariant>
|
||||
#include <ngltools/ngltools_dtg.h>
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
|
||||
inline bool lessThan(const QVariant &var1, const QVariant &var2)
|
||||
{
|
||||
if (var1.canConvert<QString>() && var2.canConvert<QString>())
|
||||
{
|
||||
QString str1(var1.toString());
|
||||
QString str2(var2.toString());
|
||||
|
||||
bool k1 = false;
|
||||
double d1 = str1.toDouble(&k1);
|
||||
|
||||
if (!k1)
|
||||
return str1 < str2;
|
||||
|
||||
bool k2 = false;
|
||||
double d2 = str2.toDouble(&k2);
|
||||
|
||||
if (!k2)
|
||||
return str1 < str2;
|
||||
|
||||
return d1 < d2;
|
||||
}
|
||||
else if (var1.canConvert<double>() && var2.canConvert<double>())
|
||||
return var1.toDouble() < var2.toDouble();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace LtsUtils
|
||||
@@ -1,15 +0,0 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
# Created by Mike Wille, SLSE, 2016-09-19
|
||||
#
|
||||
|
||||
# LtsUtilsGuiDds is needed by LtsMultiMonitor regardless of BUILD_RTI
|
||||
# Exclude from release scope - requires DDS headers, only used by LtsMultiMonitor
|
||||
if(NOT RELEASE_BUILD)
|
||||
ADD_SUBDIRECTORY(LtsUtilsGuiDds)
|
||||
endif()
|
||||
ADD_SUBDIRECTORY(ConnectDialog)
|
||||
ADD_SUBDIRECTORY(StyleManager)
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
# Created by Mike Wille, SLSE, 2016-05-12
|
||||
#
|
||||
|
||||
# Make ${Qt6_Widgets} optional
|
||||
if(QT6_GUI_AVAILABLE AND TARGET Qt6::Widgets)
|
||||
set(Qt6_Widgets ${Qt6_Widgets})
|
||||
else()
|
||||
set(Qt6_Widgets "")
|
||||
endif()
|
||||
|
||||
|
||||
SET(srcs
|
||||
connect_dialog.h
|
||||
connect_dialog.cpp
|
||||
connect_dialog_nt.h
|
||||
connect_dialog_nt.cpp
|
||||
)
|
||||
|
||||
NGL_WRAP_UI(srcs
|
||||
connect_dialog.ui
|
||||
)
|
||||
|
||||
NGL_ADD_LIBRARY2(WS LtsUtilsGuiConnectDialog SHARED ${srcs})
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(LtsUtilsGuiConnectDialog
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../
|
||||
${CMAKE_CURRENT_BINARY_DIR}/../
|
||||
)
|
||||
if(QT6_GUI_AVAILABLE)
|
||||
NGL_TARGET_LINK_LIBRARIES(LtsUtilsGuiConnectDialog
|
||||
${Qt6_Widgets}
|
||||
LtsWidgets
|
||||
)
|
||||
endif()
|
||||
Loaded 100 of 1364 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user