Compare commits

...
Author SHA1 Message Date
berrux-dev d130c55be5 Fix Qt6 resource compilation so LogView icons are embedded at runtime
- QT5_ADD_RESOURCES was a no-op stub under Qt6, silently dropping .qrc
  files: LogView's :/image/* icons were never compiled into the binary.
  Map the stub onto qt6_add_resources() (outfiles-variable form, which
  appends the generated qrc_*.cpp to the source list). LogView is the
  only caller of the stub.
- nglwidgets' Qt6 branch only processed rme_light_style.qrc;
  nglresources.qrc (which provides :icons/16x16/* toolbar/window icons)
  was left as a raw file in the source list and never compiled
  (CMAKE_AUTORCC is off). Process both qrcs.
- LogView never loads libnglwidgets.so at runtime (--as-needed drops it:
  the code uses no nglwidgets symbols), so its :icons/16x16 resources
  were never registered for the app. Embed the 20 icons LogView actually
  uses directly into LogViewResources.qrc with explicit aliases (rcc
  rejects XML comments in .qrc and, without an alias, registers the full
  relative path as the resource name).
2026-11-03 13:31:02 +01:00
berrux-dev 0e2100f383 reset Jenkins file 2026-10-15 20:43:46 +02:00
berrux-dev 26f702b7a4 reset jenkins file 2026-10-15 20:40:29 +02:00
berrux-dev 37bd700564 Fixed make error 2026-10-15 12:21:52 +02:00
berrux-dev 684e05109d Add lcov code coverage to the release pipeline and Jenkins
- new_docker_build.sh: new --run-coverage mode (mutually exclusive with
  --run-jenkins-builder). Instruments the release-scope build with
  -O0 -g --coverage -fPIC -DNDEBUG (RELEASE flag override keeps -DNDEBUG
  and -fPIC so behavior and PIC match the green baseline), runs ctest,
  then collects the lcov report: capture --external -> extract on the
  four release dirs -> remove test sources -> summary -> genhtml, all
  with --ignore-errors mismatch,inconsistent,unused (GCC 15 + lcov 2.4).
  Report lands in --coverage-output-dir (default ./coverage-out):
  html/index.html, coverage.info, coverage_summary.txt.
- Dockerfile image gains lcov via APT_PACKAGES (genhtml ships in the
  same package).
- Jenkinsfile: RunCoverage parameter (default on) + per-OS Coverage
  stage running the driver on the agent and archiving
  coverage/<project>/<os>/**.
- release-16-10-2026.sh: same coverage step, gated by DRYRUN_COVERAGE
  (default ON, mirrors the Jenkins default).
- README: Step 6 (code coverage) and options/env reference entries.
- .gitignore: coverage-out/
2026-10-15 09:00:33 +02:00
berrux-dev 676ae05335 Rewrite the build README without excluded-module sections
Scope is now described only as what the release build contains
(TetraIF, Z/src, Lts/Common, TrainingAreaBase). All steps (image,
compile, tests, DEB packaging, Jenkins) kept and refreshed; the
license note is reduced to 'no license file is required'.
2026-10-14 20:40:05 +02:00
berrux-dev a17b431669 Trim stub header comments and redundant explanations
- Drop the 'Stub file ... BUILD_RTI=OFF / Auto-generated' headers from the
  tab_* and pdm_* stub files (RTI is gone on this branch; the names say it)
- Drop stub comments from MockCoordTrans.h and the coordTransTests placeholders
- Drop the DDS exclusion list comment from Lts/Common/CMakeLists.txt
- Shorten the staging and packages-out comments in new_docker_build.sh
2026-10-14 20:30:09 +02:00
berrux-dev 493893d2e6 Reduce make_rpm_ubuntu26.py line count (925 to 526) without changing behavior
- Merge build_single_deb and build_single_deb_nobuild into one build_deb()
- Add build_nobuild_package() factory for the 4 no-build packages
- Extract run(), prune_dirs() and write_deb_file() helpers
- Drop the unreachable release_scope copy branch (all call sites used the
  full-tree copy; the --release_scope CLI flag is kept)
- Trim pipeline_files to the 8 files that actually exist and are packaged
- Remove unused imports (configparser, getpass, re, datetime, Path, stat),
  unused vars (test_patterns, script_extensions) and a duplicated write block
2026-10-14 20:25:51 +02:00
berrux-dev 8976b5aedb Remove dead CMake configuration from the release validation scope
- Top-level CMakeLists.txt: drop RTI/Connext DDS config and placeholder targets,
  MIGRATE_MODULE guarded-subdir machinery (now unconditional add_subdirectory),
  BUILD_QAV, BUILD_PLUGINS_*, KDReports stub, ArcGIS option and FindRTI placeholder loop
- Lts/CMakeLists.txt: release scope now unconditional (Common + Proxies/TrainingAreaBase),
  codegen/DDS/test/docs blocks removed
- Lts/Common: drop DDS/RTI-gated plugin and utils test blocks
- Lts/Proxies/TrainingAreaBase: remove RTI codegen, svcTabClient/svcTabServer, RTI plugins,
  sTAB; keep stub-only svcTabCommon + tabTelegrams + tabPluginInterface
- TetraIF/PrtCnv: remove out-of-scope TetraTestServer/LastTest subdirs
- Z/src/nglcompression: remove nglcomp_test (pre-existing Qt6 failure, no longer registered)
- Delete 16 unused cmake/ helper modules and the tests/ scaffolding dir
- new_docker_build.sh: drop BUILD_ARCGIS and nglcomp_test from the release build
- README: update ctest baseline to 7/7 and remove license/exception mentions
2026-10-14 18:39:18 +02:00
berrux-dev 6e7b09cf6f Remove include/ entries and LogView files unused by the release-scope build
Audited the release-scope compilation (TetraIF, Z/src, Lts/Common +
TrainingAreaBase, BUILD_RTI=OFF) for every file under include/:

Removed (zero references from release-scope sources or CMake):
- service-stub header dirs (AlarmManagement, AreaEffectSimulation,
  AssetManagement, AudioVideoManagement, Core, ExerciseEventManagement,
  ExerciseManagement, GuezNasat, InfrastructureManagement, Lts,
  LtsProjectionWorkstation, LtsScriptTimeline, LtsSession,
  MarkerManagement, NotificationManagement, OperatorManagement,
  ParticipantManagement, ProjectDataManagement, ReportManagement,
  Services, SituationReplay, TopicEditorBase, Viewer)
- include/grantlee (codegen modules excluded from the release build)
- include/nglapplication (all headers duplicate Z/src/nglapplication)
- include/poppler (Qt5 header; the build includes poppler/qt6 from the
  system package)
- include/rti (142 Connext DDS headers; only consumers are behind
  BUILD_RTI, which is OFF for this branch)
- TetraIF/LogView zsksxd_tetraForLogView{,_guez}.cpp and
  zsksxd_tetraForLogView_guez.x (the build compiles the .x; the guez
  variant is referenced nowhere; LogView loads the .x from the app dir)

Kept (actively included): include/GeographicLib, include/LtsUtilsGuiDds,
include/NGLLogger.

Also drop the now-dangling include_directories for the removed dirs in
the top-level CMakeLists (include/Viewer/SituationMap) and
Lts/CMakeLists.txt (six stub dirs) - otherwise GCC warns
-Wmissing-include-dirs for every compile.

Verified with a full pipeline rebuild (scope-rebuild15): 0 warnings,
ctest baseline unchanged, all 5 DEBs produced.
2026-10-14 16:51:32 +02:00
berrux-dev 11501ff7bb Drop the rti_license.dat requirement from the release scope build
The release validation scope (TetraIF, Z/src, Lts/Common +
TrainingAreaBase) never consumes an RTI license: no CMake file or
build step reads RTI_LICENSE_FILE, and the only RTI Connext DDS
consumers are all behind BUILD_RTI (OFF for this branch, stubs
compiled instead). The license was pure plumbing:

- new_docker_build.sh: remove the require_file validation, the
  bind mount and the in-container RTI_LICENSE_FILE export
- jenkins-ci-rme: remove the RTI_LICENSE_FILE export and the
  Jenkinsfile workspace-layout comment
- README: document that no license file is needed

Verified with a full pipeline rebuild (scope-rebuild12) run while
rti_license.dat was absent: 0 warnings, ctest baseline unchanged,
all 5 DEBs produced, none of them containing the license.
2026-10-14 16:28:03 +02:00
berrux-dev 59f0c025e5 Add a step-by-step build and test README for the release scope
Document the full flow: prebuilt Docker image build, release-scope
compilation (mandatory CMake flags), running the unit tests (ctest
baseline plus direct execution of the test binaries), DEB package
production with the in-tree rpmbuild script, the Jenkins/CI entry
points, the options reference and troubleshooting notes.
2026-10-14 16:28:03 +02:00
berrux-dev cebc456bc1 Add unit tests for the TetraIF modules in a unit-test folder
New TetraIF/unit-test/ directory with one QtTest executable per
TetraIF release-scope module, wired into ctest and the DEB pipeline:

- coprtcnv_unit_test: central and radio telegram header fields,
  payload access, length checks, fragmentation/reassembly roundtrip,
  telegram-id string helpers
- logview_unit_test: IntegerCalculator arithmetic, operator priority,
  parentheses, error codes and variables (compiles the LogView class
  source directly; the class otherwise lives in the LogView
  executable)
- prtcnv_unit_test: PrtCnvMember state and fragmented-telegram
  handling (compiles the class source directly because PrtCnvLib is
  built with hidden visibility)

TetraIF/CMakeLists.txt adds the unit-test subdirectory and
new_docker_build.sh builds and ctest-runs the three new targets.
2026-10-14 16:28:03 +02:00
berrux-dev 2d1b12b5d8 Copy jenkins-ci-rme into the source tree and adapt it to this project
- Jenkinsfile: guez-only release pipeline; the prebuilt build image is
  built from the in-tree Dockerfile (via new_docker_build.sh
  --build-prebuilt-image) instead of a pre-pulled harbor image; the
  builder runs inside the container with the workspace mounted at
  /workspace; the post-publish cleanup stage was dropped so the DEBs
  stay under ${WORKSPACE}/rpms/... (the documented output location)
- jenkins_builder_ubuntu26.sh: uses the in-tree rpmbuild/
  make_rpm_ubuntu26.py instead of the outer-repo copy; same-file guard
  on the packages-out copy (host output dir == make_rpm output dir)
- jenkins_publisher_ubuntu26.sh: uploads rpms/${PROJECT}/${OS_VERSION}/
  directly - make_rpm_ubuntu26.py writes the DEBs there without a TDS
  subfolder
- release-16-10-2026.sh: local driver adapted to the current
  new_docker_build.sh interface (drops the no-longer-existing
  --use-prebuilt-image option, builds the image on demand, outputs to
  ${WORKSPACE}/rpms/${PROJECT}/${OS_VERSION}/)
- make_rpm_ubuntu26.py: stage the new jenkins-ci-rme/ files (Jenkinsfile,
  builder, publisher) into the build-pipeline DEB (release-16-10-2026.sh
  was already listed)

Not copied (superseded): openSUSE builder/publisher, the old Dockerfile
recipes (replaced by the in-tree Dockerfile), Bitbucket notification
(jenkins_notifier.sh is not part of this project)
2026-10-14 16:28:03 +02:00
berrux-dev bf3fecf5c0 Use the Jenkins-style DEB output path and fix the copy to the packages-out mount
- Document --package-output-dir "${WORKSPACE}/rpms/${PROJECT}/${OS_VERSION}/"
  (Jenkins convention) in the usage examples
- The in-container copy step now copies to the real mount point
  /workspace/packages-out instead of ${PACKAGE_OUTPUT_DIR}, which is a host
  path that does not exist inside the container (the copy was a silent
  no-op; packages reached the host directly via make_rpm's
  --output_dir /workspace/rpms/... on the workspace mount)
- Skip the copy when the host output directory is the same directory as
  make_rpm's output dir (stat device:inode guard) - which is exactly the
  case for the Jenkins-style path above, where make_rpm already writes the
  packages in place
2026-10-14 16:28:03 +02:00
torsten 5c012ba228 Adds minimal format changing clang-format file 2026-10-14 13:28:55 +00:00
torsten 5644914fe3 Formats minimally release source files based on former clang-format 2026-10-14 13:28:01 +00:00
torsten b662e4daf9 Reinserts original comments 2026-10-14 12:56:16 +00:00
berrux-dev 1dd1e86355 Auto-derive MIGRATE_PIPELINE_ROOT in new_docker_build.sh
Resolution order (highest precedence first):
  1. exported MIGRATE_PIPELINE_ROOT (e.g. from a Jenkinsfile)
  2. MIGRATE_PIPELINE_ROOT set by .envrc in this directory
  3. derived from the script location (three levels up)

The script always lives at <root>/qt-migration-legatus/qt6-after/
qt6-migrated-legatus, so the pipeline root is three levels up. This
makes the script work in a fresh Jenkins checkout with no environment
setup at all, and .envrc is no longer required.
2026-10-14 00:24:36 +02:00
berrux-dev 52df1c8ae9 Fix TetraIF build warnings
- LogViewModels: replace deprecated invalidateFilter() with
  begin/endFilterChange() (11 sites)
- LogViewTelegramEdit: move m_logger to match member declaration order
  (-Wreorder) and consume QFile::open results
- PrtCnvBroadcastMgr: move m_logger to match member declaration order
  (-Wreorder)
- PrtCnvCentralThread: add remaining AreaEffectSimulationType values to
  the silent-ignore switch group (-Wswitch)
- PrtCnvMain: consume freopen results in daemonize (-Wunused-result)
2026-10-14 00:23:59 +02:00
berrux-dev 23e694afc2 Build the TetraIF targets in the release scope 2026-10-14 00:23:14 +02:00
berrux-dev 217bb54bc0 Build the DEB packages with the in-tree rpmbuild script
The container script now runs the packaging flow itself instead of
calling the outer-repo jenkins_builder_ubuntu26.sh:

- Stage the workspace to deb_stage (same tar/excludes as the verified
  jenkins flow; the workspace itself is never deleted)
- Run the in-tree rpmbuild/make_rpm_ubuntu26.py from the staged source
  tree with the same cmake flags and arguments as before
- Copy the produced DEBs to the package output mount
- A packaging failure now fails the build instead of being logged and
  swallowed
- Drop the now-unneeded MIGRATE_PIPELINE_ROOT/WORKSPACE/PROJECT_BASE_DIR
  container env plumbing

The branch is now fully self-contained: new_docker_build.sh + Dockerfile
+ rpmbuild/. The build-pipeline DEB additionally ships
rpmbuild/make_rpm_ubuntu26.py (the staging list already named it).
Verified: zero-warning build, 5 DEBs with identical contents.
2026-10-13 23:08:37 +02:00
berrux-dev ba99b74608 Copy rpmbuild into the source tree with only what the release flow needs
Keep make_rpm_ubuntu26.py (byte-identical to the validated working tree,
including the package-content validator fixes). It is self-contained
(standard library only, no helpers.py import) and its staging artifacts
land in the workspace root, so nothing else from the outer rpmbuild/
directory is needed:

- helpers.py: zero references from the Ubuntu 26 script (belongs to the
  other platform variants)
- make_rpm.py / make_rpm7.py / make_rpm15.1.py / make_rpm15.2.py:
  other platform packaging (base, RHEL7, CentOS 15.x)
- make_rpmModule.py / make_rpmModule7.py: module packaging
- make_rpmSVOnly.py: SV-only packaging
- make_rpm_extfw.py: external framework packaging
- make_tag.py: release tagging tool
- make_license_rpm.sh + ctc_TDS_license.spec.in + ctc_WMS_license.spec.in:
  CTC license RPM flow
- .git (submodule pointer) and .gitignore (no artifacts are created in
  this directory)
2026-10-13 22:33:37 +02:00
berrux-dev 862d0dbe2b Simplify Dockerfile comments 2026-10-13 22:20:11 +02:00
berrux-dev 5554704174 Strip leading blank lines from cmake modules (pipeline staging normalization) 2026-10-13 22:15:38 +02:00
berrux-dev 14dde18e8a Remove OFF-switched machinery and everything not built by this branch
- new_docker_build.sh (665 -> 528 lines): drop the OFF-fixed build
  variables and their redundant cmake flags (BUILD_RTI/GRANTLEE/
  VIEWER_ONLY/CODIFICATION default OFF, BUILD_ALL/SV/WS/AAR default ON -
  all matching this branch's configuration); the container cmake now
  passes only the flags that override CMake defaults (-DBUILD_ARCGIS=OFF,
  -DRELEASE_BUILD=ON, -DBUILD_TESTING=ON).
- Drop the non-prebuilt base-image path (in-container apt-get install +
  aqtinstall fallback, --use-prebuilt-image/--no-prebuilt-image) and
  --cmake_build_flags: the branch only ever builds inside the prebuilt
  image.
- Drop ensure_database(): the PostgreSQL server only served the DB tools
  (Lts/Tools), which are not built in this branch; the build links
  against the header-only dev packages baked into the image.
- Drop libvlc-dev/vlc-plugin-base from the image packages: VLC existed
  only for thp_viewer (Lts/Application, out of scope).
- --build-prebuilt-image now builds the image from ./Dockerfile and
  exits, matching the documented two-step flow.
2026-10-13 22:13:30 +02:00
berrux-dev 65ca0d8b5e Split the prebuilt-image recipe out of new_docker_build.sh into a Dockerfile
- Dockerfile: the prebuilt build image recipe (Ubuntu 26.04 + apt deps +
  aqtinstall Qt6 + KDReports), parameterized via ARG APT_PACKAGES /
  QT_VERSION / QT_ARCH / QT_BASE_DIR.
- new_docker_build.sh: build_prebuilt_image() now runs
  docker build -f Dockerfile with the package list and Qt settings passed
  as build args, using an empty build context (the Dockerfile has no
  COPY/ADD).
2026-10-13 21:47:38 +02:00
berrux-dev 23cf641d36 Trim leftover blank lines in nglapplication sources 2026-10-13 21:22:47 +02:00
745 changed files with 44146 additions and 99938 deletions

No files matched your search

@@ -0,0 +1,54 @@
---
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
@@ -14,3 +14,4 @@ build/
build2/
.envrc
build4
coverage-out/
+7 -353
View File
@@ -40,26 +40,9 @@ MESSAGE(STATUS "LTS Version: ${LTS_VERSION_MAJOR}.${LTS_VERSION_MINOR}.${LTS_VER
# 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)
if(MIGRATE_MODULE STREQUAL "")
add_subdirectory(${subdir})
else()
# normalize to forward slashes
string(REPLACE "\\" "/" _mig "${MIGRATE_MODULE}")
string(REPLACE "\\" "/" _sub "${subdir}")
# also compare basenames so MIGRATE_MODULE=Lts/DDS matches subdir 'DDS' when called from Lts
get_filename_component(_mig_base "${_mig}" NAME)
get_filename_component(_sub_base "${_sub}" NAME)
# If MIGRATE_MODULE either starts with the subdir, equals it, contains it as a path component,
# or the basename matches, include the subdir. This makes nested paths like
# 'Lts/Proxies/TrainingAreaBase' include both 'Lts' and its child 'Proxies'.
if(_mig MATCHES "^${_sub}(/|$)" OR _sub MATCHES "^${_mig}(/|$)" OR _mig MATCHES ".*/${_sub}(/|$)" OR _sub MATCHES ".*/${_mig}(/|$)" OR _mig_base STREQUAL _sub OR _sub_base STREQUAL _mig)
message(STATUS "Including subdir ${subdir} because MIGRATE_MODULE=${MIGRATE_MODULE}")
add_subdirectory(${subdir})
else()
message(STATUS "Skipping subdir ${subdir} because MIGRATE_MODULE=${MIGRATE_MODULE}")
endif()
endif()
add_subdirectory(${subdir})
endfunction()
SET(LTS_VERSION_DATE "01.01.2018" CACHE STRING "The date when this software was compiled")
@@ -95,51 +78,6 @@ if(EXISTS "${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: exclude Services, DDS, and Plugins include paths
IF(NOT RELEASE_BUILD)
include_directories(${CMAKE_BINARY_DIR}/Lts/Services/ProjectDataManagement)
include_directories(${CMAKE_SOURCE_DIR}/Lts/Services)
include_directories(${CMAKE_SOURCE_DIR}/include/ProjectDataManagement)
include_directories(${CMAKE_BINARY_DIR}/Lts/Services/InfrastructureManagement)
include_directories(${CMAKE_SOURCE_DIR}/include/InfrastructureManagement)
include_directories(${CMAKE_BINARY_DIR}/Lts/Plugins/InfrastructureManagement/Shared)
include_directories(${CMAKE_BINARY_DIR}/Lts/Services/AssetManagement)
include_directories(${CMAKE_SOURCE_DIR}/include/AssetManagement)
include_directories(${CMAKE_BINARY_DIR}/Lts/Services/AudioVideoManagement)
include_directories(${CMAKE_SOURCE_DIR}/include/AudioVideoManagement)
include_directories(${CMAKE_BINARY_DIR}/Lts/Services/ExerciseEventManagement)
include_directories(${CMAKE_SOURCE_DIR}/include/ExerciseEventManagement)
include_directories(${CMAKE_BINARY_DIR}/Lts/Services/ExerciseManagement)
include_directories(${CMAKE_SOURCE_DIR}/include/ExerciseManagement)
include_directories(${CMAKE_BINARY_DIR}/Lts/Services/FileManagement)
include_directories(${CMAKE_BINARY_DIR}/Lts/Services/NotificationManagement)
include_directories(${CMAKE_SOURCE_DIR}/include/NotificationManagement)
include_directories(${CMAKE_BINARY_DIR}/Lts/Services/ParticipantManagement)
include_directories(${CMAKE_SOURCE_DIR}/include/ParticipantManagement)
include_directories(${CMAKE_BINARY_DIR}/Lts/Services/ReportManagement)
include_directories(${CMAKE_SOURCE_DIR}/include/ReportManagement)
include_directories(${CMAKE_BINARY_DIR}/Lts/Services/SituationReplay)
include_directories(${CMAKE_SOURCE_DIR}/include/SituationReplay)
# Evaluations' generated evl_db_structs.h includes <evl_enums.hpp> by bare name, and that
# header is consumed from OcBaseDownload as well, so its build dir must be visible tree-wide
# like the services above. There is no include/Evaluations stub tree, so only the build dir
# is added (same shape as FileManagement above, which has no stub tree either).
include_directories(${CMAKE_BINARY_DIR}/Lts/Services/Evaluations)
include_directories(${CMAKE_SOURCE_DIR}/Lts/Proxies/GuezNasat)
include_directories(${CMAKE_SOURCE_DIR}/Lts/DDS)
include_directories(${CMAKE_SOURCE_DIR}/Lts/DDS/QosProfile)
# Generated DDS headers (BUILD_RTI=ON)
include_directories(${CMAKE_BINARY_DIR}/Lts)
# <Core/core.hpp> consumers (LtsCoordinate, AES/CES, HLA proxies) resolve the
# rtiddsgen-generated core.hpp from the DDS build dir (the qt5 include order);
# the OFF-era stub copies in include/Core/ have been removed.
include_directories(${CMAKE_BINARY_DIR}/Lts/DDS)
include_directories(${CMAKE_BINARY_DIR}/Lts/DDS/DDSConnector)
include_directories(${CMAKE_BINARY_DIR}/Lts/Services/Messaging)
include_directories(${CMAKE_SOURCE_DIR}/include/OperatorManagement)
include_directories(${CMAKE_BINARY_DIR}/Lts/Services/OperatorManagement)
include_directories(${CMAKE_SOURCE_DIR}/Lts/Plugins)
ENDIF()
# Release scope: include path for ProjectDataManagement stub headers
IF(RELEASE_BUILD)
include_directories(${CMAKE_SOURCE_DIR}/Lts/Services/ProjectDataManagement/stubs)
@@ -154,7 +92,6 @@ include_directories(${CMAKE_BINARY_DIR}/Lts/Common/LtsUtils/LtsUtilsCore)
# 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)
include_directories(${CMAKE_SOURCE_DIR}/include/Viewer/SituationMap)
SET(CMAKE_CXX_STANDARD 17)
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
SET(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
@@ -171,78 +108,15 @@ IF(CMAKE_VERSION VERSION_GREATER 3.15.9)
ENDIF()
ENDIF()
# Qt6 Migration: Options to disable modules with missing dependencies (WebEngine, XmlPatterns, ArcGIS)
# These can be enabled once the required system dependencies are available in the build environment
OPTION(BUILD_PLUGINS_PLANEDITOR "Build PlanEditor plugin (requires Qt6 WebEngine + ArcGIS SDK)" OFF)
OPTION(BUILD_PLUGINS_ONLINEHELP "Build OnlineHelp plugin (requires Qt6 WebEngine)" OFF)
OPTION(BUILD_PLUGINS_SERVICEMONITOR "Build ServiceMonitor plugin (requires Qt6 WebEngine)" OFF)
OPTION(BUILD_PLUGINS_PARTICIPANT_ORG_CHART "Build ParticipantOrgChart (requires Qt6 WebEngine)" OFF)
OPTION(BUILD_PLUGINS_MSDL "Build MSDL module (requires Qt6 XmlPatterns)" OFF)
OPTION(BUILD_PLUGINS_SAAB "Build Saab module (requires Qt6 XmlPatterns)" OFF)
OPTION(BUILD_RTI "Build RTI Connext DDS dependent modules" OFF)
OPTION(BUILD_VIEWER_ONLY "Build only Viewer module (no RTI required)" OFF)
# Add Lts/ include path globally for QosProfile and other Lts headers
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/Lts)
IF(BUILD_RTI)
# Define BUILD_RTI as preprocessor macro for all targets
ADD_COMPILE_DEFINITIONS(BUILD_RTI)
ENDIF()
OPTION(BUILD_ARCGIS "Build ArcGIS SDK dependent modules" ON)
OPTION(BUILD_FILTERMANAGEMENT "Build FilterManagement plugins (temporarily disabled for migration)" OFF)
OPTION(BUILD_CODIFICATION "Build CodificationManagement plugins (requires KDReports)" OFF)
OPTION(BUILD_GRANTLEE "Build CodeGen SQL files using KTextTemplate parser (KF6::TextTemplate)" ON)
# If BUILD_GRANTLEE is OFF but ngl_codegen is needed (for IDL codegen),
# provide it as an imported executable target from pre-built location
# Skip this for RELEASE_BUILD since CodeGen is excluded and ngl_codegen is not needed
IF(NOT BUILD_GRANTLEE AND NOT RELEASE_BUILD)
# ngl_codegen is copied to build/bin/ by run_final_migration.sh
# Create an imported target so MacroCodeGenIdl.cmake can find it
IF(NOT TARGET ngl_codegen)
ADD_EXECUTABLE(ngl_codegen IMPORTED GLOBAL)
SET_TARGET_PROPERTIES(ngl_codegen PROPERTIES
IMPORTED_LOCATION "${CMAKE_BINARY_DIR}/bin/ngl_codegen"
)
MESSAGE(STATUS "Using pre-built ngl_codegen from ${CMAKE_BINARY_DIR}/bin/ngl_codegen")
ENDIF()
ENDIF()
OPTION(BUILD_LTSWEBSOCKET "Build LtsWebSocket module (requires NGLLogger)" ON)
IF(WIN32)
SET(EXTERNAL_LIBRARY_DIR "C:/Development/Projekte/SituationMap/ExtFw" CACHE STRING "Library dir with all external dependencies")
LIST(APPEND CMAKE_PREFIX_PATH "${EXTERNAL_LIBRARY_DIR}")
LIST(APPEND CMAKE_PROGRAM_PATH "${EXTERNAL_LIBRARY_DIR}/bin;${EXTERNAL_LIBRARY_DIR}/dev-utils/bin")
ELSE()
# Linux: ArcGIS SDK Pfad konfigurieren (nur wenn BUILD_ARCGIS=ON)
IF(BUILD_ARCGIS)
# Use environment variable ARCGIS_ROOT if set, otherwise default to /workspace/external/... (Docker) or host path
IF(DEFINED ENV{ARCGIS_ROOT})
SET(ARCGIS_SDK_DIR "$ENV{ARCGIS_ROOT}" CACHE STRING "ArcGIS Runtime SDK for Qt directory")
ELSEIF(EXISTS "/workspace/external/ArcGIS/MapsSDK_Qt_300.0.0/ArcGIS_Maps_SDK_Qt_300.0.0/qt300.0.0/sdk")
SET(ARCGIS_SDK_DIR "/workspace/external/ArcGIS/MapsSDK_Qt_300.0.0/ArcGIS_Maps_SDK_Qt_300.0.0/qt300.0.0/sdk" CACHE STRING "ArcGIS Runtime SDK for Qt directory")
ELSE()
SET(ARCGIS_SDK_DIR "/repo/external/ArcGIS/MapsSDK_Qt_300.0.0/ArcGIS_Maps_SDK_Qt_300.0.0/qt300.0.0/sdk" CACHE STRING "ArcGIS Runtime SDK for Qt directory")
ENDIF()
IF(EXISTS "${ARCGIS_SDK_DIR}")
LIST(APPEND CMAKE_PREFIX_PATH "${ARCGIS_SDK_DIR}")
MESSAGE(STATUS "ArcGIS SDK found at: ${ARCGIS_SDK_DIR}")
ELSE()
MESSAGE(WARNING "ArcGIS SDK not found at: ${ARCGIS_SDK_DIR}")
ENDIF()
ENDIF()
ENDIF()
# Set CMAKE_MODULE_PATH early so FIND_PACKAGE can find our custom Find modules
SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
INCLUDE(FindLibraryWithDebug)
# Find ArcGIS SDK globally if BUILD_ARCGIS is enabled
# This creates ArcGIS::ArcGIS target for all modules to use
IF(BUILD_ARCGIS)
FIND_PACKAGE(ArcGIS REQUIRED)
ENDIF()
ENABLE_TESTING()
INCLUDE(CTest)
CONFIGURE_FILE(CTestCustom.ctest ${CMAKE_BINARY_DIR}/CTestCustom.ctest COPYONLY)
@@ -521,17 +395,6 @@ if(NOT TARGET Qt6::WebEngineWidgets)
message(STATUS "Created stub target for Qt6::WebEngineWidgets (library not available)")
endif()
# Stub KDReports::KDReports target if not available (needed by LtsReportDisplay)
# UNKNOWN (not INTERFACE) so FindKDReports.cmake can upgrade it with a real
# IMPORTED_LOCATION; an INTERFACE imported target ignores IMPORTED_LOCATION.
if(NOT TARGET KDReports::KDReports)
add_library(KDReports::KDReports UNKNOWN IMPORTED)
set_target_properties(KDReports::KDReports PROPERTIES
INTERFACE_COMPILE_DEFINITIONS "NO_KDREPORTS"
)
message(STATUS "Created stub target for KDReports::KDReports (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)
@@ -623,140 +486,6 @@ endif()
MESSAGE(STATUS "Qt version is ${Qt6Core_VERSION}, GUI available: ${QT6_GUI_AVAILABLE}")
#
# RTI Connext DDS - manuelle Konfiguration da keine CMake Config Files vorhanden
#
IF(BUILD_RTI)
# Support environment variable override, otherwise use relative path from repo root
IF(DEFINED ENV{DDS_PATH})
SET(RTI_INSTALL_DIR "$ENV{DDS_PATH}" CACHE PATH "RTI Connext DDS installation directory")
ELSE()
# In Docker container: /workspace/external/rti_connext_dds-7.7.0
# On host: ${CMAKE_SOURCE_DIR}/../../../external/rti_connext_dds-7.7.0
IF(EXISTS "/workspace/external/rti_connext_dds-7.7.0")
SET(RTI_INSTALL_DIR "/workspace/external/rti_connext_dds-7.7.0" CACHE PATH "RTI Connext DDS installation directory")
ELSEIF(EXISTS "${CMAKE_SOURCE_DIR}/../../../external/rti_connext_dds-7.7.0")
SET(RTI_INSTALL_DIR "${CMAKE_SOURCE_DIR}/../../../external/rti_connext_dds-7.7.0" CACHE PATH "RTI Connext DDS installation directory")
ELSE()
SET(RTI_INSTALL_DIR "/opt/RTI" CACHE PATH "RTI Connext DDS installation directory")
ENDIF()
ENDIF()
# Also set RTI_DIR for FindRTI.cmake compatibility (used by subdirectories)
SET(RTI_DIR "${RTI_INSTALL_DIR}" CACHE PATH "RTI base path" FORCE)
IF(EXISTS "${RTI_INSTALL_DIR}")
SET(RTI_LIB_DIR "${RTI_INSTALL_DIR}/lib/x64Linux4gcc8.5.0")
SET(RTI_INCLUDE_DIR "${RTI_INSTALL_DIR}/include/ndds/hpp")
# RTI hat vier Include-Pfade:
# - include/ für ndds/... und andere Top-Level Headers (z.B. ndds/ndds_config_common.h)
# - include/ndds/ für osapi/... Headers (z.B. osapi/osapi_platform.h)
# - include/ndds/hpp für C++ Headers (dds/..., rti/...)
# - include/rti für rti/... Headers
SET(RTI_INCLUDE_DIRS
"${RTI_INSTALL_DIR}/include"
"${RTI_INSTALL_DIR}/include/ndds"
"${RTI_INSTALL_DIR}/include/ndds/hpp"
"${RTI_INSTALL_DIR}/include/rti"
)
# RTI Include-Pfade global hinzufügen (auch für Tests die keine RTI Libraries linken)
INCLUDE_DIRECTORIES(${RTI_INCLUDE_DIRS})
# RTI Include-Pfade auch an MOC weitergeben (für Q_OBJECT Header mit RTI Types)
SET(CMAKE_AUTOMOC_INCLUDE_DIRECTORIES ${CMAKE_AUTOMOC_INCLUDE_DIRECTORIES} ${RTI_INCLUDE_DIRS})
# The generated <svc>_topic_type_plugin.h / <svc>_record_replay_plugin.h
# headers use Q_INTERFACES(DDSGeneric::TopicTypePlugin), so moc must see
# the Q_DECLARE_INTERFACE in Lts/DDS/... (resolved through the Lts include
# root). Without this path every <svc>TopicTypePlugin fails with
# "Undefined interface" even though the compiler sees the header.
SET(CMAKE_AUTOMOC_INCLUDE_DIRECTORIES ${CMAKE_AUTOMOC_INCLUDE_DIRECTORIES} ${CMAKE_SOURCE_DIR}/Lts)
# The ElevationMapManager stub header (include/Viewer/SituationMap/ElevationMap/)
# lives apart from its source (src/...), so moc needs its directory explicitly.
# NOTE: this must be set at root scope - subdir-scope appends do not reach
# the AutogenInfo MOC_INCLUDES.
SET(CMAKE_AUTOMOC_INCLUDE_DIRECTORIES ${CMAKE_AUTOMOC_INCLUDE_DIRECTORIES} ${CMAKE_SOURCE_DIR}/include/Viewer/SituationMap/ElevationMap)
# The migrated Projects declare Q_INTERFACES(ProjectPlugin::Plugin) and include
# <PluginInterfaces/project_plugin_interface.h>. That include dir
# (Lts/Common/PluginInterfaces/..) is only a target-level PUBLIC include of
# ProjectPluginInterface and is NOT part of the global include_directories that
# reach the AutogenInfo MOC_INCLUDES, so moc fails with "Undefined interface".
# Add the Lts/Common root explicitly (mirrors the Lts append above) so moc can
# resolve the interface. Must be set at root scope - subdir appends do not
# reach the AutogenInfo MOC_INCLUDES.
SET(CMAKE_AUTOMOC_INCLUDE_DIRECTORIES ${CMAKE_AUTOMOC_INCLUDE_DIRECTORIES} ${CMAKE_SOURCE_DIR}/Lts/Common)
# IMPORTED Targets für RTI Libraries erstellen
# Debug und Release Varianten korrekt konfigurieren
FOREACH(lib nddsc nddscore nddscpp nddscpp2 nddsctesthelpers)
ADD_LIBRARY(RTI::${lib} SHARED IMPORTED)
# Debug Library
IF(EXISTS "${RTI_LIB_DIR}/lib${lib}d.so")
SET_TARGET_PROPERTIES(RTI::${lib} PROPERTIES
IMPORTED_LOCATION_DEBUG "${RTI_LIB_DIR}/lib${lib}d.so"
)
ENDIF()
# Release Library
IF(EXISTS "${RTI_LIB_DIR}/lib${lib}.so")
SET_TARGET_PROPERTIES(RTI::${lib} PROPERTIES
IMPORTED_LOCATION_RELEASE "${RTI_LIB_DIR}/lib${lib}.so"
IMPORTED_LOCATION_RELWITHDEBINFO "${RTI_LIB_DIR}/lib${lib}.so"
IMPORTED_LOCATION_MINSIZEREL "${RTI_LIB_DIR}/lib${lib}.so"
)
ENDIF()
# Include Verzeichnisse für alle Varianten
# RTI_UNIX required for basic types (RTI_INT32, RTI_UINT32, etc.)
# RTI_POSIX_THREADS required for pthread support
SET_TARGET_PROPERTIES(RTI::${lib} PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${RTI_INCLUDE_DIRS}"
INTERFACE_COMPILE_DEFINITIONS "RTI_LINUX;RTI_UNIX;RTI_POSIX_THREADS"
)
ENDFOREACH()
MESSAGE(STATUS "RTI Connext DDS found at: ${RTI_INSTALL_DIR}")
MESSAGE(STATUS "RTI Libraries: ${RTI_LIB_DIR}")
MESSAGE(STATUS "RTI Platform: RTI_LINUX")
ELSE()
MESSAGE(WARNING "RTI Connext DDS not found at: ${RTI_INSTALL_DIR}, BUILD_RTI will fail")
ENDIF()
ENDIF(BUILD_RTI)
# Alias Targets für RTI Libraries (für Abwärtskompatibilität)
# Ermöglicht Verwendung von "ddscore" statt "RTI::nddscore" in CMakeLists.txt Files
# HINWEIS: ddscore, ddsftc, ddsfts, ddsconnector werden von Lts/DDS Modulen als echte Targets erstellt
# Daher hier KEINE ALIAS für diese Targets erstellen um Kollisionen zu vermeiden
IF(BUILD_RTI)
# BUILD_RTI=ON: Targets werden von Lts/DDS/Core/CMakeLists.txt erstellt - hier keine Stubs!
# Alias-Typen werden später erstellt, wenn RTI:: Targets verfügbar sind
IF(TARGET RTI::nddsc)
ADD_LIBRARY(ddsc ALIAS RTI::nddsc)
# ddscore wird von Lts/DDS/Core/CMakeLists.txt als echtes Target erstellt - kein Alias hier!
ADD_LIBRARY(ddscpp2 ALIAS RTI::nddscpp2)
# Optionale Targets nur als ALIAS erstellen wenn verfügbar (RTI 7.x hat nicht alle Legacy-Bibliotheken)
IF(TARGET RTI::nddscpp)
ADD_LIBRARY(ddscpp ALIAS RTI::nddscpp)
ENDIF()
IF(TARGET RTI::nddsctesthelpers)
ADD_LIBRARY(nddsctesthelpers ALIAS RTI::nddsctesthelpers)
ENDIF()
ENDIF()
# HINWEIS: ddsftc, ddsfts, ddsconnector werden von Lts/DDS/FTC Modulen als INTERFACE Targets erstellt
# Hier KEINE ALIAS erstellen um Target-Kollisionen zu vermeiden
ELSE()
# BUILD_RTI=OFF: Leere Interface-Libraries als Platzhalter
ADD_LIBRARY(ddsc INTERFACE)
ADD_LIBRARY(ddscore INTERFACE)
ADD_LIBRARY(ddscpp INTERFACE)
ADD_LIBRARY(ddscpp2 INTERFACE)
ADD_LIBRARY(nddsctesthelpers INTERFACE)
# HINWEIS: ddsftc, ddsfts, ddsconnector werden von Lts/DDS/FTC Modulen als INTERFACE Targets erstellt
# Hier KEINE Platzhalter erstellen um Target-Kollisionen zu vermeiden
ENDIF(BUILD_RTI)
ADD_DEFINITIONS(-DQT_USE_QSTRINGBUILDER)
ADD_DEFINITIONS(-DQT_NO_CAST_TO_ASCII)
ADD_DEFINITIONS(-DQT_NO_CAST_FROM_ASCII)
@@ -774,25 +503,12 @@ ENDIF()
# Ein paar NGL-spezifische Macros
#
INCLUDE(NGLMacros)
# Skip MacroCodeGenIdl for release builds as CodeGen module is excluded
IF(NOT RELEASE_BUILD)
INCLUDE(MacroCodeGenIdl)
ENDIF()
#
# Projektspezifische Einstellungen?
#
NGL_INSTALL(SV AAR WS FILES lts-cc.conf DESTINATION . RENAME lts-cc.conf.distrib)
OPTION(ETS_MODE "Build for ETS (No B-Contamination etc)" OFF)
IF(ETS_MODE)
ADD_DEFINITIONS(-DETS_MODE)
ENDIF()
OPTION(TABLET_MODE "Build for TABLET " OFF)
IF(TABLET_MODE)
ADD_DEFINITIONS(-DTABLET_MODE)
ENDIF()
OPTION(GUEZ_MODE "Build for GUEZ " ON)
IF(GUEZ_MODE)
ADD_DEFINITIONS(-DGUEZ_MODE)
@@ -948,74 +664,12 @@ ELSE()
ENDIF()
#
# DDS benoetigt zwingend RTI
#
FIND_PACKAGE(RTI QUIET)
if(NOT RTI_FOUND)
message(WARNING "RTI not found; creating placeholder RTI::* imported targets to allow configure without RTI installation")
set(_rti_libs nddscore nddsc nddscpp2 rtiroutingservice)
foreach(_lib ${_rti_libs})
if(NOT TARGET RTI::${_lib})
add_library(RTI::${_lib} UNKNOWN IMPORTED)
set_property(TARGET RTI::${_lib} PROPERTY INTERFACE_INCLUDE_DIRECTORIES "")
endif()
endforeach()
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)
# Respect MIGRATE_MODULE: when set to a relative path (e.g. "Lts/Common"), only add
# the top-level subdirectories required to configure/build that module. This allows
# per-module migration builds via -DMIGRATE_MODULE=<path>.
if(NOT DEFINED MIGRATE_MODULE)
set(MIGRATE_MODULE "" CACHE STRING "If set, only add subdirectories covering this module (path relative to repo root)")
endif()
# RELEASE_BUILD: when ON, only build the first release modules (TetraIF, Z, Lts/Common)
# This excludes Lts/Services, Lts/DDS, Lts/Tools, Lts/Application, Lts/Proxies, Lts/Plugins, Lts/Viewer, Lts/Projects
if(NOT DEFINED RELEASE_BUILD)
set(RELEASE_BUILD OFF CACHE BOOL "Build only the first release modules (TetraIF, Z, Lts/Common)")
endif()
# For release builds, disable ArcGIS (not in release scope, requires Qt6Location which is not available)
if(RELEASE_BUILD)
set(BUILD_ARCGIS OFF CACHE BOOL "Build ArcGIS SDK dependent modules" FORCE)
endif()
# Add only guarded subdirectories
if(RELEASE_BUILD)
message(STATUS "RELEASE_BUILD=ON: Building only TetraIF, Z/src, and Lts/Common")
NGL_ADD_SUBDIR_GUARDED(TetraIF)
NGL_ADD_SUBDIR_GUARDED(Z/src)
NGL_ADD_SUBDIR_GUARDED(Lts)
else()
NGL_ADD_SUBDIR_GUARDED(TetraIF)
NGL_ADD_SUBDIR_GUARDED(Z/src)
# Services are included before plugins via Lts/CMakeLists.txt (LTS_SUBDIRS order)
NGL_ADD_SUBDIR_GUARDED(Lts)
endif()
# Add migration tests - skip when MIGRATE_MODULE targets specific Lts modules (tests need full codebase)
# MUST be after Lts configuration so tests can access Lts targets (LtsTimelineClassic, codegen_base, etc.)
if(NOT DEFINED MIGRATE_MODULE OR MIGRATE_MODULE STREQUAL "" OR MIGRATE_MODULE STREQUAL "tests")
ADD_SUBDIRECTORY(tests)
else()
message(STATUS "MIGRATE_MODULE=${MIGRATE_MODULE} - skipping tests (need full codebase)")
endif()
# TrainingAreaBase is included via Lts/Proxies when Lts is processed
# Special-case: when migrating TetraIF, also include ProjectDataManagement so generated headers
# and internal logger target are available in the same build tree for TetraIF dependents.
if(DEFINED MIGRATE_MODULE AND MIGRATE_MODULE STREQUAL "TetraIF")
message(STATUS "Including helper modules for TetraIF migration: Lts/Plugins/ProjectDataManagement")
# Services already included above when BUILD_RTI=ON
add_subdirectory(Lts/Plugins/ProjectDataManagement)
endif()
# at last, to make sure we get all targets in NGL_TS_TARGETS property
NGL_ADD_SUBDIR_GUARDED(translations)
#-----------------------------------------------------------------------------------------------------
OPTION(BUILD_QAV "Build script for local QAV analysis" OFF)
IF (BUILD_QAV)
ADD_SUBDIRECTORY(qav)
ENDIF()
+47
View File
@@ -0,0 +1,47 @@
# 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"]
@@ -15,64 +15,21 @@ else()
message(WARNING "Doxygen config ${CMAKE_SOURCE_DIR}/doxygen/DoxyfileLts.in not found; skipping ADD_DOXYGEN_TARGET(Lts)")
endif()
# Add only existing subdirectories to allow partial checkouts / incremental migration
if(RELEASE_BUILD)
# For first release: only build Lts/Common and Lts/Proxies/TrainingAreaBase (tabTelegrams library)
# Excludes: Tools, Application, DDS, Services, most of Proxies, Plugins, Viewer, Projects
message(STATUS "RELEASE_BUILD=ON: 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()
# 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()
set(LTS_SUBDIRS Tools Application DDS Common Services Proxies Plugins Viewer Projects)
foreach(dir IN LISTS LTS_SUBDIRS)
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${dir}")
# Use guarded add so top-level MIGRATE_MODULE can restrict which Lts subdirs are included
NGL_ADD_SUBDIR_GUARDED(${dir})
else()
message(STATUS "Skipping missing Lts subdirectory: ${dir}")
endif()
endforeach()
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()
IF (BUILD_TESTING)
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/Tests")
ADD_SUBDIRECTORY(Tests)
else()
message(STATUS "Skipping missing Tests directory under Lts (BUILD_TESTING is ON)")
endif()
ENDIF()
OPTION(BUILD_DOCS "Build documentation as html files from Lts/Documentation" OFF)
IF (BUILD_DOCS)
ADD_SUBDIRECTORY(Documentation)
ENDIF()
# Ensure codegen macros are available before calling CODEGEN_* helpers
# Skip for release builds as CodeGen module is excluded and not needed
IF(NOT RELEASE_BUILD)
INCLUDE(MacroCodeGenIdl)
ENDIF()
# Add stub headers for non-RTI/non-FilterManagement builds
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../include/AudioVideoManagement/)
# 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/LtsSession/)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../include/TopicEditorBase/)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../include/OperatorManagement/)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../include/LtsScriptTimeline/)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../include/LtsUtilsGuiDds/)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../include/Services/PresentationManagement/)
IF(NOT RELEASE_BUILD)
CODEGEN_WRITE_SERVICEFILE_INFO()
ENDIF()
@@ -4,59 +4,22 @@
# $Author$
#
# RELEASE_BUILD: exclude modules with DDS/RTI dependencies not needed for TetraIF/Z
# DDS-dependent modules: CodeGen, LtsAppManager, LtsBotan, LtsCoordinate, LtsElevation,
# LtsLogin, LtsMultiMonitor, LtsPluginManager, LtsPrinting, LtsProjectionWorkstation,
# 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,
# PluginInterfaces (TopicReplayInterface, RecordReplayPlugin), TopicEditorBase
if(RELEASE_BUILD)
# 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
else()
ADD_SUBDIRECTORY(CodeGen)
ADD_SUBDIRECTORY(CommonUnitTestsPlaceholder)
ADD_SUBDIRECTORY(httq)
ADD_SUBDIRECTORY(LtsAppDescriptor)
ADD_SUBDIRECTORY(LtsAppManager)
ADD_SUBDIRECTORY(LtsCommandLineParser)
ADD_SUBDIRECTORY(LtsCoordinate)
ADD_SUBDIRECTORY(LtsCoordTrans)
ADD_SUBDIRECTORY(LtsElevation)
ADD_SUBDIRECTORY(LtsLicence)
ADD_SUBDIRECTORY(LtsLogin)
ADD_SUBDIRECTORY(LtsMultiMonitor)
ADD_SUBDIRECTORY(LtsNotification)
ADD_SUBDIRECTORY(LtsPluginManager)
ADD_SUBDIRECTORY(LtsPrinting)
ADD_SUBDIRECTORY(LtsProjectionWorkstation)
ADD_SUBDIRECTORY(LtsRestClient)
ADD_SUBDIRECTORY(LtsScriptTimeline)
ADD_SUBDIRECTORY(LtsSerialPortQuerry)
ADD_SUBDIRECTORY(LtsSession)
ADD_SUBDIRECTORY(LtsTimeline)
ADD_SUBDIRECTORY(LtsUtils)
ADD_SUBDIRECTORY(LtsVirtualKeyboard)
ADD_SUBDIRECTORY(LtsWebSocket)
ADD_SUBDIRECTORY(LtsWidgets)
ADD_SUBDIRECTORY(PluginInterfaces)
ADD_SUBDIRECTORY(ProjectConfig)
ADD_SUBDIRECTORY(TopicEditorBase)
endif()
# TopicEditorBase
@@ -1,11 +1,13 @@
// Stub GTest smoke test for coordTrans
#include <gtest/gtest.h>
TEST(CoordTransSmokeTest, StubTest) {
EXPECT_TRUE(true);
TEST(CoordTransSmokeTest, StubTest)
{
EXPECT_TRUE(true);
}
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
int main(int argc, char **argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
@@ -1,14 +1,12 @@
// Stub QtTest smoke test for coordTrans
#include <QTest>
class CoordTransSmokeTest : public QObject
{
Q_OBJECT
Q_OBJECT
private slots:
void stubTest() {
QVERIFY(true);
}
void stubTest() { QVERIFY(true); }
};
QTEST_APPLESS_MAIN(CoordTransSmokeTest)
QTEST_APPLESS_MAIN(CoordTransSmokeTest)
@@ -1,5 +1,3 @@
// MockCoordTrans.h - Stub mock for CoordTrans functionality
// This is a placeholder to allow builds without full CoordTrans implementation
#ifndef MOCK_COORD_TRANS_H
#define MOCK_COORD_TRANS_H
@@ -8,12 +6,14 @@
#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(); }
};
namespace LtsCoordTrans
{
// Placeholder types
struct UtmCoordinate
{
static UtmCoordinate fromMgrs(const QString &) { return UtmCoordinate(); }
QPointF geographic() const { return QPointF(); }
};
}
#endif // MOCK_COORD_TRANS_H
#endif // MOCK_COORD_TRANS_H
@@ -35,8 +35,6 @@ NGL_TARGET_LINK_LIBRARIES(LtsAppDescriptor
NGL_INSTALL_TARGET(LtsAppDescriptor)
# LtsAppDescriptorChecker
SET(LtsAppDescriptorChecker_SRCS
checker/main.cpp
@@ -51,27 +49,6 @@ NGL_TARGET_LINK_LIBRARIES(LtsAppDescriptorChecker
Qt6::Core
)
# LtsAppDescriptorEditor => Hat niemand benutzt, wird keiner benutzen, also wird der bis auf Weiteres auch nicht an die neue Syntax angepasst.
#SET(LtsAppDescriptorEditor_SRCS
# lts_app_descriptor_editor.cpp
# lts_app_descriptor_editor.h
#)
#NGL_WRAP_UI(LtsAppDescriptorEditor_SRCS
# lts_app_descriptor_editor.ui
#)
#NGL_ADD_LIBRARY2(WS NO_TRANSLATION LtsAppDescriptorEditor SHARED ${LtsAppDescriptorEditor_SRCS})
#NGL_TARGET_INCLUDE_DIRECTORIES(LtsAppDescriptorEditor
# PUBLIC
# ${CMAKE_CURRENT_SOURCE_DIR}/../
#)
if(QT6_GUI_AVAILABLE)
#NGL_TARGET_LINK_LIBRARIES(LtsAppDescriptorEditor
# PUBLIC
@@ -9,110 +9,108 @@
#include <cstdio>
#include <utility>
int main(int argc, char* argv[])
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QCoreApplication a(argc, argv);
const QStringList args(a.arguments());
const QStringList args(a.arguments());
if (args.count() != 3)
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())
{
printf("usage: %s <current source directory> <apps.json>\n", args.at(0).toStdString().c_str());
return -1;
}
QString line(ts.readLine().trimmed().simplified());
static QString iidIdentifier(QStringLiteral("Q_PLUGIN_METADATA"));
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())
if (line.contains(iidIdentifier))
{
QRegularExpression re(QStringLiteral("(?<=gui:3:).*(?=\"\\))"));
QRegularExpressionMatch match = re.match(line);
if (match.hasMatch())
{
QString line(ts.readLine().trimmed().simplified());
static QString iidIdentifier(QStringLiteral("Q_PLUGIN_METADATA"));
QString matched = match.captured(0);
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;
}
guiPluginIIDs += matched;
}
break;
}
}
}
bool ok = true;
bool ok = true;
for (const LtsAppDescriptor::AppDescription& appdesc : std::as_const(adv))
for (const LtsAppDescriptor::AppDescription &appdesc : std::as_const(adv))
{
for (const LtsAppDescriptor::PluginInfo &pi : std::as_const(appdesc.pluginInfos))
{
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;
}
}
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;
return !ok;
}
@@ -11,20 +11,20 @@
namespace LtsAppDescriptor
{
static void addOptionToPlugin(PluginInfo& pluginInfo, const PluginInfo::Flag& flag)
{
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)
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;
}
if (pi.iid == pluginName)
{
addOptionToPlugin(pi, flag);
return;
}
}
PluginInfo pi;
@@ -32,74 +32,78 @@ static void addOptionToPlugin(QVector<PluginInfo>& pluginInfos, const PluginInfo
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)
{
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());
const QJsonArray plugins((*optionsObjectIt).toObject()[QStringLiteral("Plugins")].toArray());
for (const auto& pluginElem : plugins)
for (const auto &pluginElem : plugins)
{
const QString pluginName = pluginElem.toString();
if (!ignoredPlugins.contains(pluginName))
{
const QString pluginName = pluginElem.toString();
if (!ignoredPlugins.contains(pluginName))
{
addOptionToPlugin(appDesc.pluginInfos, flag, pluginName);
hasPlugins = true;
}
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;
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)
{
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::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);
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 LtsAppDescriptor::getAppDescriptionVector(const QByteArray &jsonDocument,
QStringList &lastErrors,
const QStringList &ignoredPlugins,
QString &loginPluginIid)
{
AppDescriptionVector appDescriptions;
@@ -109,31 +113,28 @@ AppDescriptionVector LtsAppDescriptor::getAppDescriptionVector(const QByteArray&
if (parseError.error != QJsonParseError::NoError)
{
int row = 0;
int column = 0;
QChar x = QLatin1Char('\n');
int row = 0;
int column = 0;
QChar x = QLatin1Char('\n');
for (int i = 0; i < jsonDocument.size(); i++)
for (int i = 0; i < jsonDocument.size(); i++)
{
if (i == parseError.offset)
break;
if (QChar::fromLatin1(jsonDocument[i]) == x)
{
if (i == parseError.offset)
break;
if (QChar::fromLatin1(jsonDocument[i]) == x)
{
row++;
column = 0;
}
else
{
column++;
}
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;
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());
@@ -143,64 +144,57 @@ AppDescriptionVector LtsAppDescriptor::getAppDescriptionVector(const QByteArray&
const QJsonArray appArray(root[QStringLiteral("Apps")].toArray());
if (appArray.isEmpty())
{
lastErrors.append(QCoreApplication::tr("Invalid json: Could not find 'Apps' array"));
return appDescriptions;
lastErrors.append(QCoreApplication::tr("Invalid json: Could not find 'Apps' array"));
return appDescriptions;
}
for (const auto& appElem : appArray)
for (const auto &appElem : appArray)
{
AppDescription appDesc;
const QJsonObject appObject = appElem.toObject();
AppDescription appDesc;
const QJsonObject appObject = appElem.toObject();
appDesc.id = appFromInteger(appObject.value(QStringLiteral("Id")).toInt(-1));
if (appDesc.id == App::Login)
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': no App Id or invalid App Id given").arg(appDesc.appName));
return appDescriptions;
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);
appDesc.appName = appObject.value(QStringLiteral("AppName")).toString();
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 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 QJsonArray array(appObject.value(QStringLiteral("ACLs")).toArray());
for (const QJsonValue &value : array)
appDesc.requiredAcls.append(value.toInt());
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 QJsonObject optionsObject(appObject.value(QStringLiteral("Options")).toObject());
const QJsonArray array(appObject.value(QStringLiteral("ACLs")).toArray());
for (const QJsonValue& value : array)
appDesc.requiredAcls.append(value.toInt());
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);
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);
appDescriptions.append(appDesc);
}
return appDescriptions;
}
}
} // namespace LtsAppDescriptor
@@ -14,91 +14,93 @@
#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
#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
enum class App
{
UNKNOWN,
DATA,
GUI,
GUI_ELEMENT,
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
};
enum class Flag
struct PluginInfo
{
UNKNOWN = 1 << 0,
ACTIONS = 1 << 1,
MAIN = 1 << 2,
PAYLOAD = 1 << 3,
OPTION = 1 << 4,
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;
};
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;
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(); }
};
bool isValid() const { return !appName.isEmpty(); }
};
typedef QVector<AppDescription> AppDescriptionVector;
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 // 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
@@ -13,524 +13,520 @@
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QPushButton>
LtsAppDescriptorEditor::LtsAppDescriptorEditor(QWidget* parent) : QWidget(parent), m_ui(new Ui_LtsAppDescriptionEditor)
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;
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);
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);
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;
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;
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();
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);
QStringList errors;
m_vector = LtsAppDescriptor::LtsAppDescriptor::getAppDescriptionVector(val.toUtf8(), errors);
updateAppModel();
updateAppModel();
}
void LtsAppDescriptorEditor::onAppsClicked(const QModelIndex& index)
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;
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;
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");
type = QLatin1String("data");
else if (pluginType == LtsAppDescriptor::PluginInfo::PluginType::GUI)
type = QLatin1String("gui");
type = QLatin1String("gui");
else
type = QLatin1String("unknown");
m_ui->lePluginType->setText(type);
type = QLatin1String("unknown");
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);
}
if (type == QLatin1String("data"))
pluginList << QString(type + QLatin1String(": ") + reqPlugin.iid);
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);
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().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());
}
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;
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;
}
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;
}
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;
}
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);
LtsAppDescriptor::AppDescription newApp;
newApp.appName = m_ui->leAppName->text();
newApp.active = m_ui->chbAppActive->isChecked();
m_vector.append(newApp);
updateAppModel();
updateAppModel();
}
void LtsAppDescriptorEditor::onPluginAddClicked()
{
m_changed = true;
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;
}
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;
}
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;
}
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;
LtsAppDescriptor::PluginInfo newPlugin;
newPlugin.iid = m_ui->lePluginName->text();
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->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;
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);
m_vector[m_appIndex.row()].requiredPlugins.append(newPlugin);
onAppsClicked(m_appIndex);
onNewpluginClicked();
onAppsClicked(m_appIndex);
onNewpluginClicked();
}
void LtsAppDescriptorEditor::onAppDeleteClicked()
{
m_changed = true;
m_changed = true;
if (!m_appIndex.isValid())
return;
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);
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;
if (msgBox.exec() == QMessageBox::No)
return;
m_vector.remove(m_appIndex.row());
m_vector.remove(m_appIndex.row());
updateAppModel();
updateAppModel();
}
void LtsAppDescriptorEditor::onPluginDeletedClicked()
{
m_changed = true;
m_changed = true;
if (!m_pluginIndex.isValid())
return;
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);
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;
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_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);
m_ui->pbDeletePlugin->setEnabled(false);
m_ui->pbUpdate->setEnabled(false);
m_ui->pbNewPlugin->setEnabled(false);
onAppsClicked(m_appIndex);
onAppsClicked(m_appIndex);
}
void LtsAppDescriptorEditor::onUpdateClicked()
{
m_changed = true;
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;
}
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();
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;
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>();
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;
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();
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);
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();
if (m_pluginIndex.isValid())
m_ui->lvPlugins->selectionModel()->select(m_pluginIndex, QItemSelectionModel::Deselect);
m_pluginIndex = QModelIndex();
}
void LtsAppDescriptorEditor::onNewAppClicked()
{
updatePluginModel(QStringList());
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);
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();
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;
}
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);
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)
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);
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 (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();
}
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;
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);
QByteArray jsonByteArray;
jsonByteArray = LtsAppDescriptor::LtsAppDescriptor::createJson(m_vector);
QFile f(fileName);
f.open(QIODevice::WriteOnly);
f.write(jsonByteArray);
f.close();
QFile f(fileName);
f.open(QIODevice::WriteOnly);
f.write(jsonByteArray);
f.close();
m_changed = false;
m_changed = false;
QMessageBox msgBox(QMessageBox::Information, tr("Success"), tr("Your file has been saved."));
msgBox.exec();
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));
const QByteArray jsonByteArray(LtsAppDescriptor::LtsAppDescriptor::createJson(m_vector));
QFile f(m_fileName);
f.open(QIODevice::WriteOnly);
f.write(jsonByteArray);
f.close();
QFile f(m_fileName);
f.open(QIODevice::WriteOnly);
f.write(jsonByteArray);
f.close();
m_changed = false;
m_changed = false;
QMessageBox msgBox(QMessageBox::Information, tr("Success"), tr("Your file has been saved."));
msgBox.exec();
QMessageBox msgBox(QMessageBox::Information, tr("Success"), tr("Your file has been saved."));
msgBox.exec();
}
void LtsAppDescriptorEditor::onOpenClicked()
{
checkSave();
getAppDescriptionVector();
m_changed = false;
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);
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();
m_vector = LtsAppDescriptor::AppDescriptionVector();
updateAppModel();
updatePluginModel(QStringList());
updateAppModel();
updatePluginModel(QStringList());
}
void LtsAppDescriptorEditor::enableNewPlugin()
{
m_ui->pbNewPlugin->setEnabled(true);
m_ui->pbNewPlugin->setEnabled(true);
}
void LtsAppDescriptorEditor::onQuitClicked()
{
QApplication::quit();
QApplication::quit();
}
@@ -21,45 +21,45 @@ class Ui_LtsAppDescriptionEditor;
class LTSAPPDESCRIPTOREDITOR_EXPORT LtsAppDescriptorEditor : public QWidget
{
Q_OBJECT
Q_OBJECT
public:
explicit LtsAppDescriptorEditor(QWidget* parent = 0);
~LtsAppDescriptorEditor();
public:
explicit LtsAppDescriptorEditor(QWidget *parent = 0);
~LtsAppDescriptorEditor();
private:
Ui_LtsAppDescriptionEditor* m_ui;
LtsAppDescriptor::AppDescriptionVector m_vector;
QModelIndex m_appIndex;
QModelIndex m_pluginIndex;
private:
Ui_LtsAppDescriptionEditor *m_ui;
LtsAppDescriptor::AppDescriptionVector m_vector;
QModelIndex m_appIndex;
QModelIndex m_pluginIndex;
QString m_fileName;
QString m_fileName;
bool m_changed;
bool m_changed;
void getAppDescriptionVector();
void setupMainWindow();
void updateAppModel();
void updatePluginModel(const QStringList& list);
void checkSave();
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();
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();
public slots:
void onSaveClicked();
void onSaveAsClicked();
void onOpenClicked();
void onNewClicked();
void onQuitClicked();
};
@@ -7,49 +7,49 @@
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QMenuBar>
int main(int argc, char* argv[])
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QApplication a(argc, argv);
QMainWindow* mainWindow = new QMainWindow();
QMenu* fileMenu = mainWindow->menuBar()->addMenu(QObject::tr("&File"));
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 *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 *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 *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 *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);
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);
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();
mainWindow->show();
int ret = a.exec();
delete mainWindow;
return ret;
int ret = a.exec();
delete mainWindow;
return ret;
}
@@ -10,171 +10,166 @@
namespace LtsCommandLineParser
{
static constexpr int s_maxDomainId = 232;
static constexpr int s_maxDomainId = 232;
LtsCommandLineParser::LtsCommandLineParser(ProvideCommandLineParameterOptions opts)
: QCommandLineParser(), m_enabledOptions(opts)
{
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;
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;
}
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")});
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)});
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});
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});
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();
}
addVersionOption();
}
int LtsCommandLineParser::domainId() const
{
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);
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);
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_generatedDomainId;
}
return m_domainId;
}
}
void LtsCommandLineParser::setDomainId(int id)
{
void LtsCommandLineParser::setDomainId(int id)
{
m_domainIdSetByFunction = true;
m_domainId = id;
}
}
bool LtsCommandLineParser::iniFileSet() const
{
bool LtsCommandLineParser::iniFileSet() const
{
if (!m_enabledOptions.testFlag(CustomConfigFile))
return false;
return false;
return isSet(QStringLiteral("i"));
}
}
bool LtsCommandLineParser::useTcpConnection() const
{
bool LtsCommandLineParser::useTcpConnection() const
{
if (!m_enabledOptions.testFlag(TcpConnectionUrl))
return false;
return false;
return isSet(QStringLiteral("t"));
}
}
QUrl LtsCommandLineParser::tcpConnectionUrl() const
{
QUrl LtsCommandLineParser::tcpConnectionUrl() const
{
if (!m_enabledOptions.testFlag(TcpConnectionUrl))
return QUrl();
return QUrl();
if (!useTcpConnection())
return QUrl();
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"));
url.setScheme(QStringLiteral("tcpv4lan"));
return url;
}
}
bool LtsCommandLineParser::init(bool bParseHelp)
{
bool LtsCommandLineParser::init(bool bParseHelp)
{
if (!parse(QCoreApplication::arguments()))
{
fprintf(stdout, "\nBad option: %s \n", qPrintable(errorText()));
if (!m_unitModuleTestMode)
return false;
fprintf(stdout, "\nBad option: %s \n", qPrintable(errorText()));
if (!m_unitModuleTestMode)
return false;
}
if (m_enabledOptions.testFlag(ExerciseId))
m_exerciseId = value(QStringLiteral("e")).toInt();
m_exerciseId = value(QStringLiteral("e")).toInt();
if (m_enabledOptions.testFlag(DomainId))
m_domainId = value(QStringLiteral("d")).toInt();
m_domainId = value(QStringLiteral("d")).toInt();
if (m_enabledOptions.testFlag(CustomConfigFile))
m_iniFile = value(QStringLiteral("i"));
m_iniFile = value(QStringLiteral("i"));
if (bParseHelp && isSet(QStringLiteral("h")))
showHelp();
showHelp();
if (!m_unitModuleTestMode && isSet(QStringLiteral("v")))
showVersion();
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;
}
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)
{
void LtsCommandLineParser::showHelp(int exitCode)
{
if (!m_additionalHelpStr.isEmpty())
fprintf(stdout, "%s", qPrintable(m_additionalHelpStr));
fprintf(stdout, "%s", qPrintable(m_additionalHelpStr));
QCommandLineParser::showHelp(exitCode);
}
}
bool LtsCommandLineParser::domainIdProvided() const
{
bool LtsCommandLineParser::domainIdProvided() const
{
if (!m_enabledOptions.testFlag(DomainId))
return false;
return false;
return isSet(QStringLiteral("d"));
}
}
bool LtsCommandLineParser::exerciseIdProvided() const
{
bool LtsCommandLineParser::exerciseIdProvided() const
{
if (!m_enabledOptions.testFlag(ExerciseId))
return false;
return false;
return isSet(QStringLiteral("e"));
}
}
} // namespace LtsCommandLineParser
@@ -10,34 +10,29 @@ class QUrl;
namespace LtsCommandLineParser
{
class LTSCOMMANDLINEPARSER_EXPORT LtsCommandLineParser : public QCommandLineParser
{
class LTSCOMMANDLINEPARSER_EXPORT LtsCommandLineParser : public QCommandLineParser
{
public:
enum ProvideCommandLineParameterOptions {
None = 0x0000,
CreateDomainIdFromIp = 0x0001,
DomainId = 0x0002,
ExerciseId = 0x0004,
CustomConfigFile = 0x0008,
TcpConnectionUrl = 0x0010,
NoVersion = 0x0020
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));
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;
}
int exerciseId() const { return m_exerciseId; }
QString iniFile() const
{
return m_iniFile;
}
QString iniFile() const { return m_iniFile; }
bool iniFileSet() const;
bool useTcpConnection() const;
@@ -48,10 +43,7 @@ class LTSCOMMANDLINEPARSER_EXPORT LtsCommandLineParser : public QCommandLinePars
bool domainIdProvided() const;
bool exerciseIdProvided() const;
void setUnitModuleTestMode(bool onOff)
{
m_unitModuleTestMode = onOff;
}
void setUnitModuleTestMode(bool onOff) { m_unitModuleTestMode = onOff; }
protected:
QString m_additionalHelpStr;
@@ -64,6 +56,6 @@ class LTSCOMMANDLINEPARSER_EXPORT LtsCommandLineParser : public QCommandLinePars
bool m_domainIdSetByFunction{false};
bool m_unitModuleTestMode{false};
QString m_iniFile;
};
};
} // namespace LtsCommandLineParser
@@ -5,60 +5,70 @@
#include <cstring>
#include <string>
int main(int argc, char** argv)
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;
}
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)
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)
{
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]);
lonLatInRad = true;
if (argc == 5)
precArgId = 4;
}
else
precArgId = 3;
if (precArgId > 0)
prec = atoi(argv[precArgId]);
}
std::string mgrs;
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;
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;
}
@@ -15,110 +15,108 @@
namespace LtsCoordTrans
{
static long s_conversion_counter_MGRS_Forward = 0;
static long s_conversion_counter_MGRS_Reverse = 0;
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_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;
static long s_conversion_counter_UTMUPS_Forward = 0;
static long s_conversion_counter_UTMUPS_Reverse = 0;
inline void incrementCounter(long& counterRef)
{
inline void incrementCounter(long &counterRef)
{
#ifdef LTS_DEBUG
++counterRef;
#endif
}
}
static inline std::string cleanupMgrsString(const QString& in)
{
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;
if (c != ' ')
ret += c;
}
return ret;
}
}
QString UtmCoordinate::mgrs(int prec, bool withSpaces) const
{
QString UtmCoordinate::mgrs(int prec, bool withSpaces) const
{
if (prec < 0)
prec = 0;
prec = 0;
if (prec > 11)
prec = 11;
prec = 11;
std::string mgrs;
try
{
GeographicLib::MGRS::Forward(zone, northp, x, y, prec, mgrs);
incrementCounter(s_conversion_counter_MGRS_Forward);
GeographicLib::MGRS::Forward(zone, northp, x, y, prec, mgrs);
incrementCounter(s_conversion_counter_MGRS_Forward);
}
catch (const std::exception& e)
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();
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();
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);
}
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());
ret = QString::fromLatin1(mgrs.c_str(), mgrs.size());
return ret;
}
}
QPointF UtmCoordinate::toPoint() const
{
QPointF UtmCoordinate::toPoint() const
{
return {x, y};
}
}
QPointF UtmCoordinate::geographic(double offsetX, double offsetY) const
{
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);
GeographicLib::UTMUPS::Reverse(zone, northp, x + offsetX, y + offsetY, ret.ry(), ret.rx());
incrementCounter(s_conversion_counter_UTMUPS_Reverse);
}
catch (const std::exception& e)
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();
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
{
QPointF UtmCoordinate::geographic(const QPointF &offset) const
{
return geographic(offset.x(), offset.y());
}
}
QPointF UtmCoordinate::relativeTo(const UtmCoordinate& other) const
{
QPointF UtmCoordinate::relativeTo(const UtmCoordinate &other) const
{
if (zone == other.zone)
return QPointF(x - other.x, y - other.y);
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)
{
UtmCoordinate UtmCoordinate::fromGeographic(double lon, double lat, int setZone)
{
lon *= rad2deg();
lat *= rad2deg();
@@ -127,81 +125,81 @@ UtmCoordinate UtmCoordinate::fromGeographic(double lon, double lat, int setZone)
try
{
GeographicLib::UTMUPS::Forward(lat, lon, ret.zone, ret.northp, ret.x, ret.y, setZone);
incrementCounter(s_conversion_counter_UTMUPS_Forward);
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)
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();
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)
{
UtmCoordinate UtmCoordinate::fromGeographic(const QPointF &lonLat, int setZone)
{
return fromGeographic(lonLat.x(), lonLat.y(), setZone);
}
}
UtmCoordinate UtmCoordinate::fromMgrs(const QString& mgrs)
{
UtmCoordinate UtmCoordinate::fromMgrs(const QString &mgrs)
{
UtmCoordinate utm;
try
{
int prec;
int prec;
GeographicLib::MGRS::Reverse(cleanupMgrsString(mgrs), utm.zone, utm.northp, utm.x, utm.y, prec, true);
incrementCounter(s_conversion_counter_MGRS_Reverse);
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)
catch (const std::exception &e)
{
fprintf(stderr, "Error while converting mgrs coordinate %s to utm: %s\n", qPrintable(mgrs), e.what());
utm = UtmCoordinate();
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)
{
QString mgrsFromGeographic(double lon, double lat, int prec, bool withSpaces)
{
return UtmCoordinate::fromGeographic(lon, lat, -1).mgrs(prec, withSpaces);
}
}
QPointF geographicFromMgrs(const QString& mgrs)
{
QPointF geographicFromMgrs(const QString &mgrs)
{
return UtmCoordinate::fromMgrs(mgrs).geographic();
}
}
QVector<UtmCoordinate>& staticDefaultSquaresHelper()
{
QVector<UtmCoordinate> &staticDefaultSquaresHelper()
{
static QVector<UtmCoordinate> s_defaultMgrsSquares;
return s_defaultMgrsSquares;
}
}
UtmCoordinate& staticPreferedMgrsSquareHelper()
{
UtmCoordinate &staticPreferedMgrsSquareHelper()
{
static UtmCoordinate s_preferedMgrsSquare;
return s_preferedMgrsSquare;
}
}
QVector<UtmCoordinate>& staticMgrsSquaresWithOffsetsHelper()
{
QVector<UtmCoordinate> &staticMgrsSquaresWithOffsetsHelper()
{
static QVector<UtmCoordinate> s_mgrsSquaresWithOffsets;
return s_mgrsSquaresWithOffsets;
}
}
QRectF addMarginToArea(const QRectF& rect_LatLon_radiant, const QSize& marginMeter)
{
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");
const QPointF centerRad = rect_LatLon_radiant.center();
QString mgrs = LtsCoordTrans::mgrsFromGeographic(centerRad.x(), centerRad.y(), -1);
mgrs += QStringLiteral("00000000000000");
basePoint = LtsCoordTrans::UtmCoordinate::fromMgrs(mgrs);
basePoint = LtsCoordTrans::UtmCoordinate::fromMgrs(mgrs);
}
const UtmCoordinate lowerLeft(UtmCoordinate::fromGeographic(lonMin, latMin, basePoint.zone));
@@ -215,27 +213,26 @@ QRectF addMarginToArea(const QRectF& rect_LatLon_radiant, const QSize& marginMet
QRectF res = QRectF(topLeft, bottomRight);
return res;
}
}
QVector<UtmCoordinate> getMgrsSquares(const QRectF& rect, bool setAsDefaultSquares, bool setAsPreferedSquare,
bool setAsSquareWithMargin)
{
QVector<UtmCoordinate> getMgrsSquares(const QRectF &rect, bool setAsDefaultSquares, bool setAsPreferedSquare, bool setAsSquareWithMargin)
{
QVector<UtmCoordinate> ret = getMgrsSquaresInternal(rect);
if (setAsDefaultSquares)
staticDefaultSquaresHelper() = ret;
staticDefaultSquaresHelper() = ret;
if (setAsPreferedSquare)
staticPreferedMgrsSquareHelper() = LtsCoordTrans::UtmCoordinate::fromGeographic(rect.center());
staticPreferedMgrsSquareHelper() = LtsCoordTrans::UtmCoordinate::fromGeographic(rect.center());
if (setAsSquareWithMargin)
staticMgrsSquaresWithOffsetsHelper() = ret;
staticMgrsSquaresWithOffsetsHelper() = ret;
return ret;
}
}
QVector<UtmCoordinate> getMgrsSquaresInternal(const QRectF& rect)
{
QVector<UtmCoordinate> getMgrsSquaresInternal(const QRectF &rect)
{
QVector<UtmCoordinate> ret;
QVector<QString> tmpMgrsSquares;
@@ -244,19 +241,19 @@ QVector<UtmCoordinate> getMgrsSquaresInternal(const QRectF& rect)
bool withInSingleUtmSquare = true;
{
const UtmCoordinate upperRight(UtmCoordinate::fromGeographic(lonMax, latMmax));
const UtmCoordinate lowerLeft(UtmCoordinate::fromGeographic(lonMin, latMin));
withInSingleUtmSquare = upperRight.zone == lowerLeft.zone;
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");
QPointF centerRad = rect.center();
QString mgrs = LtsCoordTrans::mgrsFromGeographic(centerRad.x(), centerRad.y(), -1);
mgrs += QStringLiteral("00000000000000");
basePoint = LtsCoordTrans::UtmCoordinate::fromMgrs(mgrs);
basePoint = LtsCoordTrans::UtmCoordinate::fromMgrs(mgrs);
}
const UtmCoordinate upperRight(UtmCoordinate::fromGeographic(lonMax, latMmax, basePoint.zone));
@@ -268,180 +265,173 @@ QVector<UtmCoordinate> getMgrsSquaresInternal(const QRectF& rect)
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 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))
{
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;
}
tmpMgrsSquares += mgrs;
ret += utm;
}
}
}
return ret;
}
}
QStringList getMgrsSurroundingSquares(const QRectF& geoRect, const QSize& offsetMeter)
{
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));
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));
for (const auto &utm : std::as_const(mainUtmsWithOffset))
mainSquaresWithOffset.append(utm.mgrs(0));
QStringList surroundingSquares;
surroundingSquares.reserve(mainSquaresWithOffset.count());
for (const auto& mgrs0 : mainSquaresWithOffset)
for (const auto &mgrs0 : mainSquaresWithOffset)
{
if (!mainSquares.contains(mgrs0))
surroundingSquares.append(mgrs0);
if (!mainSquares.contains(mgrs0))
surroundingSquares.append(mgrs0);
}
return surroundingSquares;
}
}
QVector<UtmCoordinate> defaultMgrsSquareWithOffsets()
{
QVector<UtmCoordinate> defaultMgrsSquareWithOffsets()
{
return staticMgrsSquaresWithOffsetsHelper();
}
}
void setDefaultMgrsSquares(const QVector<QString>& squares)
{
void setDefaultMgrsSquares(const QVector<QString> &squares)
{
QVector<UtmCoordinate> coords;
coords.reserve(squares.size());
for (const QString& s : squares)
coords += UtmCoordinate::fromMgrs(s + QStringLiteral("00000000000000"));
for (const QString &s : squares)
coords += UtmCoordinate::fromMgrs(s + QStringLiteral("00000000000000"));
staticDefaultSquaresHelper() = coords;
}
}
QVector<UtmCoordinate> defaultMgrsSquares()
{
QVector<UtmCoordinate> defaultMgrsSquares()
{
return staticDefaultSquaresHelper();
}
}
UtmCoordinate preferedMgrsSquare()
{
UtmCoordinate preferedMgrsSquare()
{
return staticPreferedMgrsSquareHelper();
}
}
bool lonLatAltToGeocentric(double lon, double lat, double altitude, double& xOut, double& yOut, double& zOut)
{
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);
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;
xOut = 0;
yOut = 0;
zOut = 0;
return false;
}
return true;
}
}
bool geocentric2LonLatAlt(double x, double y, double z, double& lon, double& lat, double& altitude)
{
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);
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 = 0;
lat = 0;
altitude = 0;
return false;
}
lon *= deg2rad();
lat *= deg2rad();
return true;
}
}
double distance(const QPointF& p1, const QPointF& p2)
{
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)
{
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)
{
std::ostream &operator<<(std::ostream &stream, const UtmCoordinate &coord)
{
stream << "UtmCoordinate(" << std::setprecision(8) << coord.x << "#" << std::setprecision(8) << coord.y
<< " zone=" << coord.zone << ")";
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);
}
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()
{
long getConversionCounter_MGRS_Forward()
{
return s_conversion_counter_MGRS_Forward;
}
}
long getConversionCounter_MGRS_Reverse()
{
long getConversionCounter_MGRS_Reverse()
{
return s_conversion_counter_MGRS_Reverse;
}
}
long getConversionCounter_WGS84_Forward()
{
long getConversionCounter_WGS84_Forward()
{
return s_conversion_counter_WGS84_Forward;
}
}
long getConversionCounter_WGS84_Reverse()
{
long getConversionCounter_WGS84_Reverse()
{
return s_conversion_counter_WGS84_Reverse;
}
}
long getConversionCounter_UTMUPS_Forward()
{
long getConversionCounter_UTMUPS_Forward()
{
return s_conversion_counter_UTMUPS_Forward;
}
}
long getConversionCounter_UTMUPS_Reverse()
{
long getConversionCounter_UTMUPS_Reverse()
{
return s_conversion_counter_UTMUPS_Reverse;
}
}
} // namespace LtsCoordTrans
@@ -14,23 +14,23 @@ class QString;
namespace LtsCoordTrans
{
inline Q_CONSTEXPR double pi()
{
inline Q_CONSTEXPR double pi()
{
return M_PI;
}
}
inline Q_CONSTEXPR double deg2rad()
{
inline Q_CONSTEXPR double deg2rad()
{
return pi() / 180.;
}
}
inline Q_CONSTEXPR double rad2deg()
{
inline Q_CONSTEXPR double rad2deg()
{
return 1. / deg2rad();
}
}
struct LTSCOORDTRANS_EXPORT UtmCoordinate
{
struct LTSCOORDTRANS_EXPORT UtmCoordinate
{
int zone = -1;
bool northp = true;
double x = 0.;
@@ -38,152 +38,146 @@ struct LTSCOORDTRANS_EXPORT UtmCoordinate
UtmCoordinate() = default;
UtmCoordinate(int zone_, double x_, double y_, bool northp_ = true) : zone(zone_), northp(northp_), x(x_), y(y_) {}
bool isValid() const
UtmCoordinate(int zone_, double x_, double y_, bool northp_ = true)
: zone(zone_)
, northp(northp_)
, x(x_)
, y(y_)
{
return zone > 0 && zone <= 60;
}
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 geographic(const QPointF &offset) const;
QPointF relativeTo(const UtmCoordinate& other) 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 fromGeographic(const QPointF &lonLat, int setZone = -1);
static UtmCoordinate fromMgrs(const QString& mgrs);
};
static UtmCoordinate fromMgrs(const QString &mgrs);
};
LTSCOORDTRANS_EXPORT QString mgrsFromGeographic(double lon, double lat, int prec = 5, bool withSpaces = true);
LTSCOORDTRANS_EXPORT QString mgrsFromGeographic(double lon, double lat, int prec = 5, bool withSpaces = true);
LTSCOORDTRANS_EXPORT QPointF geographicFromMgrs(const QString& mgrs);
LTSCOORDTRANS_EXPORT QPointF geographicFromMgrs(const QString &mgrs);
LTSCOORDTRANS_EXPORT QRectF addMarginToArea(const QRectF& rect_LatLon_radiant, const QSize& marginMeter);
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);
LTSCOORDTRANS_EXPORT QVector<UtmCoordinate> getMgrsSquares(const QRectF &rect, bool setAsDefaultSquares, bool setAsPreferedSquare, bool setAsSquareWithMargin = false);
QVector<UtmCoordinate> getMgrsSquaresInternal(const QRectF& rect);
QVector<UtmCoordinate> getMgrsSquaresInternal(const QRectF &rect);
QStringList getMgrsSurroundingSquares(const QRectF& geoRect, const QSize& offsetMeter);
QStringList getMgrsSurroundingSquares(const QRectF &geoRect, const QSize &offsetMeter);
LTSCOORDTRANS_EXPORT QVector<UtmCoordinate> defaultMgrsSquareWithOffsets();
LTSCOORDTRANS_EXPORT QVector<UtmCoordinate> defaultMgrsSquareWithOffsets();
LTSCOORDTRANS_EXPORT void setDefaultMgrsSquares(const QVector<QString>& squares);
LTSCOORDTRANS_EXPORT void setDefaultMgrsSquares(const QVector<QString> &squares);
LTSCOORDTRANS_EXPORT QVector<UtmCoordinate> defaultMgrsSquares();
LTSCOORDTRANS_EXPORT QVector<UtmCoordinate> defaultMgrsSquares();
LTSCOORDTRANS_EXPORT UtmCoordinate preferedMgrsSquare();
LTSCOORDTRANS_EXPORT UtmCoordinate preferedMgrsSquare();
LTSCOORDTRANS_EXPORT bool lonLatAltToGeocentric(double lon, double lat, double altitude, double& xOut, double& yOut,
double& zOut);
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);
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)
{
inline double squareDistance(const UtmCoordinate &p1, const UtmCoordinate &p2)
{
if (p1.zone != p2.zone)
{
Q_ASSERT(false);
return std::nan("");
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);
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)
{
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)
{
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)
{
inline double distance(const UtmCoordinate &p1, const UtmCoordinate &p2)
{
if (p1.zone != p2.zone)
{
Q_ASSERT(false);
return std::nan("");
Q_ASSERT(false);
return std::nan("");
}
return sqrt(squareDistance(p1, p2));
}
}
LTSCOORDTRANS_EXPORT double distance(const QPointF& p1, const QPointF& 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)
{
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)
{
inline double distance(const UtmCoordinate &p1, const double lon2, const double lat2)
{
return sqrt(squareDistance(p1, lon2, lat2));
}
}
LTSCOORDTRANS_EXPORT void dumpConversionCounter();
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 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);
LTSCOORDTRANS_EXPORT std::ostream &operator<<(std::ostream &stream, const UtmCoordinate &coord);
class LTSCOORDTRANS_EXPORT UtmCoordinate3D : public LtsCoordTrans::UtmCoordinate
{
class LTSCOORDTRANS_EXPORT UtmCoordinate3D : public LtsCoordTrans::UtmCoordinate
{
using BaseClass = LtsCoordTrans::UtmCoordinate;
public:
UtmCoordinate3D()
{
reset();
}
UtmCoordinate3D() { reset(); }
explicit UtmCoordinate3D(const LtsCoordTrans::UtmCoordinate& utm2d, double _zValue = std::nan("")) : BaseClass()
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;
zone = utm2d.zone;
northp = utm2d.northp;
x = utm2d.x;
y = utm2d.y;
zValue = _zValue;
}
void reset()
{
zone = -1;
northp = true;
zone = -1;
northp = true;
x = 0.;
y = 0.;
zValue = std::nan("");
x = 0.;
y = 0.;
zValue = std::nan("");
}
double z() const
{
return zValue;
}
double z() const { return zValue; }
protected:
double zValue{std::nan("")};
};
};
} // namespace LtsCoordTrans
@@ -13,7 +13,7 @@ QTEST_MAIN(coordtrans_test)
void coordtrans_test::initTestCase()
{
qDebug("sizeof(UtmCoordinate) = %lu", sizeof(LtsCoordTrans::UtmCoordinate));
qDebug("sizeof(UtmCoordinate) = %lu", sizeof(LtsCoordTrans::UtmCoordinate));
}
void coordtrans_test::cleanupTestCase() {}
@@ -21,380 +21,394 @@ void coordtrans_test::cleanupTestCase() {}
void coordtrans_test::testFromGeographic()
{
LtsCoordTrans::UtmCoordinate utm;
QPointF lonlat;
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(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(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"));
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"));
utm = LtsCoordTrans::UtmCoordinate::fromMgrs(QStringLiteral("40R BM 00000 00000"));
QCOMPARE(utm.mgrs(0), QStringLiteral("40Q BM"));
}
void coordtrans_test::testMgrsFromGeographic()
{
QString mgrs;
QPointF lonlat;
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"));
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"));
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::addColumn<QPoint>("offset");
QTest::addColumn<QString>("correctMgrs");
QTest::newRow("set 1") << QPoint(5, 5) << QStringLiteral("32U PD 99995 99995");
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");
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);
QFETCH(QPoint, offset);
QFETCH(QString, correctMgrs);
const LtsCoordTrans::UtmCoordinate& utmRef =
LtsCoordTrans::UtmCoordinate::fromMgrs(QStringLiteral("32U PD 99990 99990"));
qDebug() << "utmRef = " << utmRef.mgrs();
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();
{
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);
}
QCOMPARE(utmRaw.mgrs(), correctMgrs);
}
{
const LtsCoordTrans::UtmCoordinate utmSimple(utmRef.zone, utmRef.x + offset.x(), utmRef.y + offset.y());
{
const LtsCoordTrans::UtmCoordinate utmSimple(utmRef.zone, utmRef.x + offset.x(), utmRef.y + offset.y());
qDebug() << "offset = " << offset << " - utmSimple = " << utmSimple.mgrs();
QCOMPARE(utmSimple.mgrs(), correctMgrs);
}
qDebug() << "offset = " << offset << " - utmSimple = " << utmSimple.mgrs();
QCOMPARE(utmSimple.mgrs(), correctMgrs);
}
}
QRectF createArea(const QString& base, int xCenter, int yCenter, int width, int height)
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 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;
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() << "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() << "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();
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.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");
}
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() << "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() << "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();
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.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");
}
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"));
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());
const LtsCoordTrans::UtmCoordinate centerPoint = LtsCoordTrans::UtmCoordinate::fromGeographic(lonlat.x(), lonlat.y());
LtsCoordTrans::UtmCoordinate topLeftUtm;
LtsCoordTrans::UtmCoordinate topLeftUtm2;
LtsCoordTrans::UtmCoordinate topLeftUtm;
LtsCoordTrans::UtmCoordinate topLeftUtm2;
{
QPointF topLeftGeo = centerPoint.geographic(-1111, 2222);
QPointF bottomRightGeo = centerPoint.geographic(3000, -4000);
{
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;
}
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;
{
topLeftUtm2.x = centerPoint.x - 1111;
topLeftUtm2.y = centerPoint.y + 2222;
LtsCoordTrans::UtmCoordinate bottomRightUtm2;
bottomRightUtm2.x = centerPoint.x + 3000;
bottomRightUtm2.y = centerPoint.y - 4000;
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;
}
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");
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"));
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;
QRectF myRect;
QRectF myRectIncreased;
{
const LtsCoordTrans::UtmCoordinate centerPoint =
LtsCoordTrans::UtmCoordinate::fromGeographic(lonlat.x(), lonlat.y());
{
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();
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();
}
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);
{
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);
QPointF topLeftGeo = centerUtm.geographic(-6000, 4000);
QPointF bottomRightGeo = centerUtm.geographic(6000, -4000);
myRectIncreased = QRectF(topLeftGeo, bottomRightGeo).normalized();
myRectIncreased = QRectF(topLeftGeo, bottomRightGeo).normalized();
qDebug() << "myRectIncreased : " << myRectIncreased;
qDebug() << "myRectIncreased center: " << myRectIncreased.center();
qDebug() << "myRectIncreased height: " << myRectIncreased.height();
}
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((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");
QVERIFY2(myRectIncreased.width() > myRect.width(), "testIncreaseRect2 width failed");
QVERIFY2(myRectIncreased.height() > myRect.height(), "testIncreaseRect2 height failed");
}
void coordtrans_test::testGeographicFromMgrs()
{
QString mgrs(QStringLiteral("32UPD7654398765"));
QString mgrs(QStringLiteral("32UPD7654398765"));
QPointF geographic = LtsCoordTrans::geographicFromMgrs(mgrs);
QCOMPARE(geographic, QPointF(11.6436815550, 53.2088411454) * LtsCoordTrans::deg2rad());
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("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("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"),
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,
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,
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")});
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)
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()));
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);
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();
QStringList src;
src.reserve(squares.size());
for (const auto &utm : squares)
src += utm.mgrs(0);
src.sort();
return squares;
return squares;
}
void coordtrans_test::testMgrsSquaresWithSurrounding()
{
int initialSize = 5000;
int initialSize = 5000;
QVector<LtsCoordTrans::UtmCoordinate> squares1 =
checkAreaGetMgrsSquares(QStringLiteral("32U NC 0000000000"), 50000, 50000, initialSize, initialSize);
QVector<LtsCoordTrans::UtmCoordinate> squares1 = checkAreaGetMgrsSquares(QStringLiteral("32U NC 0000000000"), 50000, 50000, initialSize, initialSize);
QVERIFY2(squares1.size() == 1, "checkAreaGetMgrsSquares failed");
QVERIFY2(squares1.size() == 1, "checkAreaGetMgrsSquares failed");
int biggerSize = initialSize + (1 * 110000);
QVector<LtsCoordTrans::UtmCoordinate> squares9 =
checkAreaGetMgrsSquares(QStringLiteral("32U NC 0000000000"), 50000, 50000, biggerSize, biggerSize);
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");
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);
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");
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 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 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 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);
{
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");
}
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);
{
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");
}
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)
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();
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);
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);
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);
}
@@ -7,25 +7,25 @@
class coordtrans_test : public QObject
{
Q_OBJECT
private Q_SLOTS:
void initTestCase();
void cleanupTestCase();
void testFromGeographic();
void testMgrsFromGeographic();
Q_OBJECT
private Q_SLOTS:
void initTestCase();
void cleanupTestCase();
void testFromGeographic();
void testMgrsFromGeographic();
void testRelativeMetricalOffet_data();
void testRelativeMetricalOffet();
void testRelativeMetricalOffet_data();
void testRelativeMetricalOffet();
void testAddMarginToArea();
void testIncreaseRect();
void testIncreaseRect2();
void testAddMarginToArea();
void testIncreaseRect();
void testIncreaseRect2();
void testGeographicFromMgrs();
void testMgrsSquares();
void testGeographicFromMgrs();
void testMgrsSquares();
void testMgrsSquaresWithSurrounding();
void testMgrsSquaresWithSurrounding();
private:
void checkArea(const QString& base, int xCenter, int yCenter, int width, int height, const QStringList& coords);
private:
void checkArea(const QString &base, int xCenter, int yCenter, int width, int height, const QStringList &coords);
};
@@ -10,178 +10,177 @@
namespace LtsCoordWidget
{
LtsCoordWidget::LtsCoordWidget(DisplayType dt, QWidget* parent) : QWidget(parent), m_displayType(dt)
{
LtsCoordWidget::LtsCoordWidget(DisplayType dt, QWidget *parent)
: QWidget(parent)
, m_displayType(dt)
{
setFocusPolicy(Qt::StrongFocus);
rebuildUi();
}
}
void LtsCoordWidget::setCoordinate(const QPointF& geoCoord, bool bUseAsDefaultValue)
{
void LtsCoordWidget::setCoordinate(const QPointF &geoCoord, bool bUseAsDefaultValue)
{
if (m_coordinate != geoCoord)
emit coordinateChanged(geoCoord);
emit coordinateChanged(geoCoord);
if (bUseAsDefaultValue)
m_defaultCoordinate = geoCoord;
m_defaultCoordinate = geoCoord;
if (m_inputWidgetHandler)
m_inputWidgetHandler->setCoordinate(geoCoord);
}
m_inputWidgetHandler->setCoordinate(geoCoord);
}
void LtsCoordWidget::clear()
{
void LtsCoordWidget::clear()
{
if (m_inputWidgetHandler)
m_inputWidgetHandler->clear();
}
m_inputWidgetHandler->clear();
}
void LtsCoordWidget::setCoordinate(double lon, double lat, bool bUseAsDefaultValue)
{
void LtsCoordWidget::setCoordinate(double lon, double lat, bool bUseAsDefaultValue)
{
setCoordinate(QPointF(lon, lat), bUseAsDefaultValue);
}
}
QPointF LtsCoordWidget::coordinate() const
{
QPointF LtsCoordWidget::coordinate() const
{
if (!m_inputWidgetHandler)
return QPointF();
return QPointF();
return m_inputWidgetHandler->coordinate();
}
}
LtsCoordWidget::DisplayType LtsCoordWidget::displayType() const
{
LtsCoordWidget::DisplayType LtsCoordWidget::displayType() const
{
return m_displayType;
}
}
void LtsCoordWidget::setDisplayType(LtsCoordWidget::DisplayType dt)
{
void LtsCoordWidget::setDisplayType(LtsCoordWidget::DisplayType dt)
{
if (m_displayType == dt)
return;
return;
m_displayType = dt;
rebuildUi();
}
}
bool LtsCoordWidget::withResetButton() const
{
bool LtsCoordWidget::withResetButton() const
{
return m_bWithResetButton;
}
}
void LtsCoordWidget::setWithResetButton(bool bWith)
{
void LtsCoordWidget::setWithResetButton(bool bWith)
{
if (m_bWithResetButton == bWith)
return;
return;
m_bWithResetButton = bWith;
if (m_inputWidgetHandler)
m_inputWidgetHandler->resetButton()->setVisible(m_bWithResetButton);
}
m_inputWidgetHandler->resetButton()->setVisible(m_bWithResetButton);
}
bool LtsCoordWidget::showToolTip() const
{
bool LtsCoordWidget::showToolTip() const
{
return m_bShowToolTip;
}
}
void LtsCoordWidget::setShowToolTip(bool bShow)
{
void LtsCoordWidget::setShowToolTip(bool bShow)
{
if (m_bShowToolTip == bShow)
return;
return;
m_bShowToolTip = bShow;
updateToolTip();
}
}
bool LtsCoordWidget::mgrsSquareEditable() const
{
bool LtsCoordWidget::mgrsSquareEditable() const
{
return m_bMgrsSquareEditable;
}
}
void LtsCoordWidget::setMgrsSquareEditable(bool bEditable)
{
void LtsCoordWidget::setMgrsSquareEditable(bool bEditable)
{
if (m_bMgrsSquareEditable == bEditable)
return;
return;
m_bMgrsSquareEditable = bEditable;
if (m_inputWidgetHandler)
m_inputWidgetHandler->setSquaresEditable(bEditable);
}
m_inputWidgetHandler->setSquaresEditable(bEditable);
}
void LtsCoordWidget::setWithSurroundingMgrsSquares(bool bEnable)
{
void LtsCoordWidget::setWithSurroundingMgrsSquares(bool bEnable)
{
if (m_inputWidgetHandler)
m_inputWidgetHandler->setWithSurroundingSquare(bEnable);
}
m_inputWidgetHandler->setWithSurroundingSquare(bEnable);
}
void LtsCoordWidget::setMgrsSquares(const QVector<LtsCoordTrans::UtmCoordinate>& geoCoords)
{
void LtsCoordWidget::setMgrsSquares(const QVector<LtsCoordTrans::UtmCoordinate> &geoCoords)
{
if (m_inputWidgetHandler)
m_inputWidgetHandler->setMgrsSquares(geoCoords);
}
m_inputWidgetHandler->setMgrsSquares(geoCoords);
}
bool LtsCoordWidget::event(QEvent* event)
{
bool LtsCoordWidget::event(QEvent *event)
{
if (event->type() == QEvent::ToolTip)
updateToolTip();
updateToolTip();
return QWidget::event(event);
}
}
void LtsCoordWidget::rebuildUi()
{
void LtsCoordWidget::rebuildUi()
{
if (m_inputWidgetHandler)
{
m_inputWidgetHandler->cleanup();
delete m_inputWidgetHandler;
delete layout();
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:
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;
qt_assert("DisplayType::UTM not yet implemented", __FILE__, __LINE__);
break;
case DisplayType::WGS84:
m_inputWidgetHandler = new Wgs84Edit(this);
break;
}
if (!m_inputWidgetHandler)
return;
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);
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);
}
m_inputWidgetHandler->setCoordinate(m_defaultCoordinate);
}
void LtsCoordWidget::updateToolTip()
{
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);
}
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()
{
void LtsCoordWidget::onResetToDefaultCoordinate()
{
if (!m_inputWidgetHandler)
return;
return;
if (m_defaultCoordinate.isNull())
m_inputWidgetHandler->clear();
m_inputWidgetHandler->clear();
m_inputWidgetHandler->setCoordinate(m_defaultCoordinate);
}
}
} // namespace LtsCoordWidget
@@ -10,43 +10,53 @@ class QToolButton;
namespace LtsCoordWidget
{
class LtsCoordInputWidgetHandler;
class LtsCoordInputWidgetHandler;
class LTSCOORDWIDGET_EXPORT LtsCoordWidget : public QWidget
{
class LTSCOORDWIDGET_EXPORT LtsCoordWidget : public QWidget
{
Q_OBJECT
public:
enum class DisplayType { MGRS5, MGRS7, UTM, WGS84, MGRS = DisplayType::MGRS5 };
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(QWidget *parent = nullptr)
: LtsCoordWidget(LtsCoordWidget::DisplayType::MGRS, parent)
{
}
explicit LtsCoordWidget(DisplayType dt, QWidget* parent = nullptr);
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;
bool event(QEvent *event) override;
public Q_SLOTS:
void setCoordinate(const QPointF& geoCoord, bool bUseAsDefaultValue = true);
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 setMgrsSquares(const QVector<LtsCoordTrans::UtmCoordinate> &geoCoords);
void clear();
Q_SIGNALS:
void coordinateChanged(const QPointF& newGeoCoord);
void coordinateChanged(const QPointF &newGeoCoord);
void invalidCoordinate();
private:
@@ -60,8 +70,8 @@ class LTSCOORDWIDGET_EXPORT LtsCoordWidget : public QWidget
bool m_bShowToolTip = true;
bool m_bMgrsSquareEditable = false;
LtsCoordWidget::DisplayType m_displayType = LtsCoordWidget::DisplayType::MGRS;
LtsCoordInputWidgetHandler* m_inputWidgetHandler = nullptr;
LtsCoordInputWidgetHandler *m_inputWidgetHandler = nullptr;
QPointF m_coordinate;
QPointF m_defaultCoordinate;
};
};
} // namespace LtsCoordWidget
@@ -7,70 +7,71 @@
namespace LtsCoordWidget
{
void LtsCoordInputWidgetHandler::onCoordinateDataChanged()
{
void LtsCoordInputWidgetHandler::onCoordinateDataChanged()
{
const QPointF coord(coordinate());
if (coord.isNull())
{
emit invalidCoordinate();
return;
emit invalidCoordinate();
return;
}
emit coordinateChanged(coord);
}
}
MgrsEdit::MgrsEdit(int precision, QWidget* widget)
: LtsCoordInputWidgetHandler(widget), m_precision(precision), m_ui(new Ui::Mgrs)
{
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;
m_precision = 0;
if (m_precision > 11)
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->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()
{
MgrsEdit::~MgrsEdit()
{
delete m_ui;
}
}
bool MgrsEdit::isValid()
{
bool MgrsEdit::isValid()
{
const QString& east = m_ui->leEast->text();
const QString &east = m_ui->leEast->text();
if (east.size() != m_precision)
return false;
return false;
const QString& north = m_ui->leNorth->text();
const QString &north = m_ui->leNorth->text();
if (north.size() != m_precision)
return false;
return false;
if (m_ui->cbxZone->currentIndex() < 0)
return false;
return false;
if (m_ui->cbxZone->currentText().isEmpty())
return false;
return false;
return true;
}
}
void MgrsEdit::setCoordinate(const QPointF& geoCoord)
{
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->clear();
m_ui->leNorth->clear();
return;
}
m_ui->leEast->setText(QString());
@@ -82,135 +83,137 @@ void MgrsEdit::setCoordinate(const QPointF& geoCoord)
int idx = m_ui->cbxZone->findText(mgrsSquare);
if (idx < 0)
{
addMgrsSquare(mgrsSquare);
idx = m_ui->cbxZone->findText(mgrsSquare);
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)
{
static inline QString getMgrsCoord(QLineEdit *le, int prec)
{
QString ret = le->text();
if (ret.isEmpty())
return ret;
return ret;
while (ret.size() < prec)
ret += QLatin1Char('0');
ret += QLatin1Char('0');
le->setText(ret);
return ret;
}
}
QPointF MgrsEdit::coordinate() const
{
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();
return QPointF();
const QString mgrsString(m_ui->cbxZone->currentText() + east + north);
return LtsCoordTrans::geographicFromMgrs(mgrsString);
}
}
QToolButton* MgrsEdit::resetButton()
{
QToolButton *MgrsEdit::resetButton()
{
return m_ui->tbReset;
}
}
void MgrsEdit::cleanup()
{
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()
{
void MgrsEdit::clear()
{
m_ui->cbxZone->clear();
m_ui->leEast->clear();
m_ui->leNorth->clear();
setDefaultMgrsSquares();
}
}
void MgrsEdit::setSquaresEditable(bool bEditable)
{
void MgrsEdit::setSquaresEditable(bool bEditable)
{
m_ui->cbxZone->setEditable(bEditable);
}
}
void MgrsEdit::setWithSurroundingSquare(bool bEnabled)
{
void MgrsEdit::setWithSurroundingSquare(bool bEnabled)
{
m_withMgrsSquareOffset = bEnabled;
}
}
static QStringList defaultMgrsSquares()
{
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);
for (const LtsCoordTrans::UtmCoordinate &c : squares)
sl += c.mgrs(0);
std::sort(sl.begin(), sl.end());
return sl;
}
}
static QString preferedMgrsSquare()
{
static QString preferedMgrsSquare()
{
const LtsCoordTrans::UtmCoordinate c(LtsCoordTrans::preferedMgrsSquare());
return c.mgrs(0);
}
}
void MgrsEdit::setDefaultMgrsSquares()
{
void MgrsEdit::setDefaultMgrsSquares()
{
m_ui->cbxZone->addItems(defaultMgrsSquares());
m_ui->cbxZone->setCurrentIndex(m_ui->cbxZone->findText(preferedMgrsSquare()));
}
}
void MgrsEdit::addMgrsSquare(const QString& newMgrsSquare)
{
void MgrsEdit::addMgrsSquare(const QString &newMgrsSquare)
{
QStringList sl = defaultMgrsSquares();
sl += newMgrsSquare;
if (m_withMgrsSquareOffset)
{
QStringList squares = utmCoordsToList(LtsCoordTrans::defaultMgrsSquareWithOffsets());
QStringList squares = utmCoordsToList(LtsCoordTrans::defaultMgrsSquareWithOffsets());
for (const auto& sq : std::as_const(squares))
if (!sl.contains(sq))
sl.append(sq);
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 MgrsEdit::utmCoordsToList(const QVector<LtsCoordTrans::UtmCoordinate> &coords)
{
QStringList list;
list.reserve(coords.count());
for (const auto& utm : coords)
list.append(utm.mgrs(0));
for (const auto &utm : coords)
list.append(utm.mgrs(0));
return list;
}
}
void MgrsEdit::setMgrsSquares(const QVector<LtsCoordTrans::UtmCoordinate>& geoCoords)
{
void MgrsEdit::setMgrsSquares(const QVector<LtsCoordTrans::UtmCoordinate> &geoCoords)
{
QStringList sl = utmCoordsToList(geoCoords);
if (sl.isEmpty())
return;
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)
{
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);
DoubleValidator *v = new DoubleValidator(-180, 180, 9, m_ui->leLon);
v->setNotation(QDoubleValidator::StandardNotation);
m_ui->leLon->setValidator(v);
@@ -220,50 +223,50 @@ Wgs84Edit::Wgs84Edit(QWidget* widget) : LtsCoordInputWidgetHandler(widget), m_ui
connect(m_ui->leLon, &QLineEdit::editingFinished, this, &Wgs84Edit::onCoordinateDataChanged);
connect(m_ui->leLat, &QLineEdit::editingFinished, this, &Wgs84Edit::onCoordinateDataChanged);
}
}
Wgs84Edit::~Wgs84Edit()
{
Wgs84Edit::~Wgs84Edit()
{
delete m_ui;
}
}
bool Wgs84Edit::isValid()
{
bool Wgs84Edit::isValid()
{
return (!m_ui->leLon->text().isEmpty()) && (!m_ui->leLat->text().isEmpty());
}
}
void Wgs84Edit::setCoordinate(const QPointF& geoCoord)
{
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 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;
return ret;
ret.rx() = l.toDouble(lonStr);
ret.ry() = l.toDouble(latStr);
return ret * LtsCoordTrans::deg2rad();
}
}
QToolButton* Wgs84Edit::resetButton()
{
QToolButton *Wgs84Edit::resetButton()
{
return m_ui->tbReset;
}
}
void Wgs84Edit::cleanup()
{
void Wgs84Edit::cleanup()
{
delete m_ui->horizontalLayout;
delete m_ui->leLon;
@@ -271,31 +274,31 @@ void Wgs84Edit::cleanup()
delete m_ui->tbReset;
delete m_ui->lblLon;
delete m_ui->lblLat;
}
}
void Wgs84Edit::clear()
{
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)
{
}
DoubleValidator::DoubleValidator(double bottom, double top, int decimals, QObject *parent)
: QDoubleValidator(bottom, top, decimals, parent)
{
}
QValidator::State DoubleValidator::validate(QString& input, int& pos) const
{
QValidator::State DoubleValidator::validate(QString &input, int &pos) const
{
const QValidator::State ret = QDoubleValidator::validate(input, pos);
if (ret != QValidator::Acceptable)
return ret;
return ret;
QLocale l;
const QChar gs = l.groupSeparator().at(0);
if (gs.isNull())
return ret;
return ret;
if (input.contains(gs))
return QValidator::Invalid;
return QValidator::Invalid;
return ret;
}
}
} // namespace LtsCoordWidget
@@ -13,95 +13,89 @@
namespace LtsCoordWidget
{
class LtsCoordInputWidgetHandler : public QObject
{
class LtsCoordInputWidgetHandler : public QObject
{
Q_OBJECT
public:
explicit LtsCoordInputWidgetHandler(QObject* parent) : QObject(parent) {}
explicit LtsCoordInputWidgetHandler(QObject *parent)
: QObject(parent)
{
}
virtual bool isValid() = 0;
virtual void setCoordinate(const QPointF& geoCoord) = 0;
virtual void setCoordinate(const QPointF &geoCoord) = 0;
virtual QPointF coordinate() const = 0;
virtual QToolButton* resetButton() = 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;
virtual void setMgrsSquares(const QVector<LtsCoordTrans::UtmCoordinate> &geoCoords) = 0;
protected Q_SLOTS:
void onCoordinateDataChanged();
Q_SIGNALS:
void coordinateChanged(const QPointF& newGeoCoord);
void coordinateChanged(const QPointF &newGeoCoord);
void invalidCoordinate();
};
};
class MgrsEdit final : public LtsCoordInputWidgetHandler
{
class MgrsEdit final : public LtsCoordInputWidgetHandler
{
Q_OBJECT
public:
explicit MgrsEdit(int precision, QWidget* widget);
explicit MgrsEdit(int precision, QWidget *widget);
~MgrsEdit();
bool isValid() override;
void setCoordinate(const QPointF& geoCoord) override;
void setCoordinate(const QPointF &geoCoord) override;
QPointF coordinate() const override;
QToolButton* resetButton() 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;
void setMgrsSquares(const QVector<LtsCoordTrans::UtmCoordinate> &geoCoords) override;
private:
void setDefaultMgrsSquares();
void addMgrsSquare(const QString& newMgrsSquare);
QStringList utmCoordsToList(const QVector<LtsCoordTrans::UtmCoordinate>& coords);
void addMgrsSquare(const QString &newMgrsSquare);
QStringList utmCoordsToList(const QVector<LtsCoordTrans::UtmCoordinate> &coords);
private:
int m_precision;
bool m_withMgrsSquareOffset = false;
Ui::Mgrs* m_ui;
};
Ui::Mgrs *m_ui;
};
class Wgs84Edit final : public LtsCoordInputWidgetHandler
{
class Wgs84Edit final : public LtsCoordInputWidgetHandler
{
Q_OBJECT
public:
explicit Wgs84Edit(QWidget* widget);
explicit Wgs84Edit(QWidget *widget);
~Wgs84Edit();
bool isValid() override;
void setCoordinate(const QPointF& geoCoord) override;
void setCoordinate(const QPointF &geoCoord) override;
QPointF coordinate() const override;
QToolButton* resetButton() override;
QToolButton *resetButton() override;
void cleanup() override;
void clear() override;
void setSquaresEditable(bool bEditable) override
{
Q_UNUSED(bEditable);
}
void setSquaresEditable(bool bEditable) override { Q_UNUSED(bEditable); }
void setWithSurroundingSquare(bool bEnabled) override
{
Q_UNUSED(bEnabled);
}
void setWithSurroundingSquare(bool bEnabled) override { Q_UNUSED(bEnabled); }
void setMgrsSquares(const QVector<LtsCoordTrans::UtmCoordinate>& geoCoords) override
{
Q_UNUSED(geoCoords);
}
void setMgrsSquares(const QVector<LtsCoordTrans::UtmCoordinate> &geoCoords) override { Q_UNUSED(geoCoords); }
private:
Ui::Wgs84* m_ui;
};
Ui::Wgs84 *m_ui;
};
class DoubleValidator final : public QDoubleValidator
{
class DoubleValidator final : public QDoubleValidator
{
Q_OBJECT
public:
DoubleValidator(double bottom, double top, int decimals, QObject* parent = nullptr);
DoubleValidator(double bottom, double top, int decimals, QObject *parent = nullptr);
QValidator::State validate(QString& input, int& pos) const override;
};
QValidator::State validate(QString &input, int &pos) const override;
};
} // namespace LtsCoordWidget
@@ -9,98 +9,92 @@
#include <QtWidgets/QPushButton>
#include <QtWidgets/QVBoxLayout>
static void updateLabel(const QPointF& coord, QLabel* lbl, int prec)
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);
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)
int main(int argc, char **argv)
{
QApplication app(argc, 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);
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));
QDialog *dialog(new QDialog);
QVBoxLayout *lay(new QVBoxLayout(dialog));
const QPointF defCoord(QPointF(53.0, 8.0) * LtsCoordTrans::deg2rad());
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 *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 *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); });
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);
});
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);
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;
dialog->show();
int ret = app.exec();
delete dialog;
return ret;
}
@@ -4,41 +4,49 @@
#include <GeographicLib/UTMUPS.hpp>
#include <string>
int main(int argc, char** argv)
int main(int argc, char **argv)
{
if (argc != 2)
{
fprintf(stderr, "Usage: %s <mgrs>\n", argv[0]);
return -1;
}
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());
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);
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;
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;
}
@@ -10,43 +10,43 @@
namespace LtsLicence
{
struct AesCryptPrivate
{
struct AesCryptPrivate
{
AesCryptPrivate()
: passPhrase(QLatin1String("LTS " LTS_VERSION_MAJOR "." LTS_VERSION_MINOR)),
logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("LtsLicenceLib.AesCrypt"))
: 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();
ERR_load_crypto_strings();
#endif
}
~AesCryptPrivate()
{
#if OPENSSL_VERSION_NUMBER < 0x1010000fL
ERR_free_strings();
ERR_free_strings();
#endif
}
QString passPhrase;
NGL::INGLLogger& logger;
};
Q_GLOBAL_STATIC(AesCryptPrivate, s_Private)
NGL::INGLLogger &logger;
};
Q_GLOBAL_STATIC(AesCryptPrivate, s_Private)
void setPassPhrase(const QString& passPhrase)
{
void setPassPhrase(const QString &passPhrase)
{
s_Private->passPhrase = passPhrase;
}
}
QString passPhrase()
{
QString passPhrase()
{
return s_Private->passPhrase;
}
}
QByteArray decryptData(const QByteArray& dataToDecrypt, const QString& pw, bool* bOk)
{
QByteArray decryptData(const QByteArray &dataToDecrypt, const QString &pw, bool *bOk)
{
if (bOk)
*bOk = false;
*bOk = false;
int ret;
int outSize1 = 0;
@@ -54,53 +54,53 @@ QByteArray decryptData(const QByteArray& dataToDecrypt, const QString& pw, bool*
unsigned char key[32];
const QByteArray baPassword = pw.toUtf8();
const unsigned char* dataPw = reinterpret_cast<const unsigned char*>(baPassword.data());
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();
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 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();
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();
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());
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();
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);
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);
@@ -108,14 +108,14 @@ QByteArray decryptData(const QByteArray& dataToDecrypt, const QString& pw, bool*
bufDecrypted.resize(outSize1 + outSize2);
if (bOk)
*bOk = true;
*bOk = true;
return bufDecrypted;
}
}
QByteArray encryptData(const QByteArray& dataToEncrypt, const QString& pw, bool* bOk)
{
QByteArray encryptData(const QByteArray &dataToEncrypt, const QString &pw, bool *bOk)
{
if (bOk)
*bOk = false;
*bOk = false;
int ret;
int outSize1 = 0;
@@ -124,53 +124,53 @@ QByteArray encryptData(const QByteArray& dataToEncrypt, const QString& pw, bool*
QByteArray bufEncrypted;
const QByteArray baPassword = pw.toUtf8();
const unsigned char* dataPw = reinterpret_cast<const unsigned char*>(baPassword.data());
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();
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());
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();
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();
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 = 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());
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();
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);
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);
@@ -178,8 +178,8 @@ QByteArray encryptData(const QByteArray& dataToEncrypt, const QString& pw, bool*
bufEncrypted.resize(outSize1 + outSize2 + baSalt.size());
if (bOk)
*bOk = true;
*bOk = true;
return bufEncrypted;
}
}
} // namespace LtsLicence
@@ -9,12 +9,10 @@
namespace LtsLicence
{
LTSLICENCE_EXPORT void setPassPhrase(const QString& passPhrase);
LTSLICENCE_EXPORT QString passPhrase();
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 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);
LTSLICENCE_EXPORT QByteArray encryptData(const QByteArray &dataToEncrypt, const QString &pw = passPhrase(), bool *bOk = nullptr);
} // namespace LtsLicence
@@ -13,41 +13,41 @@ QTEST_MAIN(aes_crypt_test)
void aes_crypt_test::initTestCase()
{
NGL::NGLLoggerBootstrap::createNGLRootLogger("log4cxx.props", false);
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...");
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);
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...");
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());
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...");
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...");
}
@@ -6,9 +6,9 @@
class aes_crypt_test : public QObject
{
Q_OBJECT
private Q_SLOTS:
void initTestCase();
void truePassTest();
void falsePassTest();
Q_OBJECT
private Q_SLOTS:
void initTestCase();
void truePassTest();
void falsePassTest();
};
@@ -8,15 +8,15 @@
namespace LtsLicence
{
static bool extractLicence(const QDomElement& licenceElement, QVector<Licence>& licenceVec);
static bool extractLicence(const QDomElement &licenceElement, QVector<Licence> &licenceVec);
static NGL::INGLLogger& getLogger()
{
static NGL::INGLLogger &getLogger()
{
return NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("LtsLicence");
}
}
QVector<Licence> readLicences(const QByteArray& unencryptedXmlData)
{
QVector<Licence> readLicences(const QByteArray &unencryptedXmlData)
{
QVector<Licence> licenceVec;
QDomDocument xmlDoc;
@@ -24,10 +24,10 @@ QVector<Licence> readLicences(const QByteArray& unencryptedXmlData)
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;
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";
@@ -36,23 +36,22 @@ QVector<Licence> readLicences(const QByteArray& unencryptedXmlData)
while (!licenceElement.isNull())
{
if (!extractLicence(licenceElement, licenceVec))
{
licenceVec.clear();
return licenceVec;
}
if (!extractLicence(licenceElement, licenceVec))
{
licenceVec.clear();
return licenceVec;
}
licenceElement = licenceElement.nextSiblingElement(QLatin1String("licence"));
licenceElement = licenceElement.nextSiblingElement(QLatin1String("licence"));
}
return licenceVec;
}
}
QByteArray writeUnencryptedLicences(const QVector<Licence>& licences)
{
QByteArray writeUnencryptedLicences(const QVector<Licence> &licences)
{
QDomDocument xmlDoc;
QDomProcessingInstruction instr = xmlDoc.createProcessingInstruction(
QLatin1String("xml"), QLatin1String("version='1.0' encoding='UTF-8' standalone='yes'"));
QDomProcessingInstruction instr = xmlDoc.createProcessingInstruction(QLatin1String("xml"), QLatin1String("version='1.0' encoding='UTF-8' standalone='yes'"));
xmlDoc.appendChild(instr);
QDomElement root = xmlDoc.createElement(QLatin1String("licences"));
@@ -60,43 +59,43 @@ QByteArray writeUnencryptedLicences(const QVector<Licence>& licences)
for (int i = 0; i < licences.size(); ++i)
{
QDomElement lic = xmlDoc.createElement(QLatin1String("licence"));
root.appendChild(lic);
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);
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("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("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);
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);
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);
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)
{
bool extractLicence(const QDomElement &licenceElement, QVector<Licence> &licenceVec)
{
Licence licence;
QDomElement tag = licenceElement.firstChildElement(QLatin1String("name"));
@@ -120,29 +119,28 @@ bool extractLicence(const QDomElement& licenceElement, QVector<Licence>& licence
if (!qdt.isValid())
{
ERROR_LOG(getLogger()) << "Invalid expiration format! " << qs << " used format: " << format;
return false;
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;
<< " 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
{
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
@@ -11,8 +11,8 @@
namespace LtsLicence
{
struct LTSLICENCE_EXPORT Licence
{
struct LTSLICENCE_EXPORT Licence
{
QString name;
bool ignoreMaxCount = false;
bool ignoreExpiration = false;
@@ -21,9 +21,9 @@ struct LTSLICENCE_EXPORT Licence
int licenceRefCount = 0;
QString toString() const;
};
};
LTSLICENCE_EXPORT QVector<Licence> readLicences(const QByteArray& unencryptedXmlData);
LTSLICENCE_EXPORT QVector<Licence> readLicences(const QByteArray &unencryptedXmlData);
LTSLICENCE_EXPORT QByteArray writeUnencryptedLicences(const QVector<Licence>& licences);
LTSLICENCE_EXPORT QByteArray writeUnencryptedLicences(const QVector<Licence> &licences);
} // namespace LtsLicence
@@ -9,56 +9,58 @@
namespace LtsNotification
{
LtsNotification::LtsNotification(LtsNotificationController* ctl) : QObject(), m_controller(ctl)
{
LtsNotification::LtsNotification(LtsNotificationController *ctl)
: QObject()
, m_controller(ctl)
{
connect(ctl, &LtsNotificationController::destroyed, this, &LtsNotification::slotCtlDestroyed);
}
}
LtsNotification::~LtsNotification()
{
LtsNotification::~LtsNotification()
{
delete m_controller;
}
}
void LtsNotification::setIcon(const QIcon& icon)
{
void LtsNotification::setIcon(const QIcon &icon)
{
m_controller->setIcon(icon);
}
}
void LtsNotification::setAction(const std::function<void(void)>& action)
{
void LtsNotification::setAction(const std::function<void(void)> &action)
{
m_controller->setAction(action);
}
}
void LtsNotification::setToolTip(const QString& toolTip)
{
void LtsNotification::setToolTip(const QString &toolTip)
{
m_controller->setToolTip(toolTip);
}
}
const QString& LtsNotification::tooltip() const
{
const QString &LtsNotification::tooltip() const
{
return m_controller->tooltip();
}
}
void LtsNotification::setCount(const int count)
{
void LtsNotification::setCount(const int count)
{
m_controller->setCount(count);
}
}
void LtsNotification::setEnabled(bool enable)
{
void LtsNotification::setEnabled(bool enable)
{
m_controller->setEnabled(enable);
}
}
void LtsNotification::setBackground(const int r, const int g, const int b)
{
void LtsNotification::setBackground(const int r, const int g, const int b)
{
m_controller->setBackground(r, g, b);
}
}
void LtsNotification::slotCtlDestroyed(QObject* obj)
{
void LtsNotification::slotCtlDestroyed(QObject *obj)
{
(void)obj;
m_controller = nullptr;
}
}
} // namespace LtsNotification
@@ -11,35 +11,35 @@
namespace LtsSession
{
class LtsSession;
class LtsSession;
}
namespace LtsNotification
{
class LtsNotificationController;
class LtsNotificationController;
class LTSNOTIFICATION_EXPORT LtsNotification : public QObject
{
class LTSNOTIFICATION_EXPORT LtsNotification : public QObject
{
Q_OBJECT
public:
explicit LtsNotification(LtsNotificationController* ctl);
explicit LtsNotification(LtsNotificationController *ctl);
~LtsNotification();
void setIcon(const QIcon& icon);
void setAction(const std::function<void(void)>& action);
void setToolTip(const QString& toolTip);
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;
const QString &tooltip() const;
private:
LtsNotificationController* m_controller;
LtsNotificationController *m_controller;
private slots:
void slotCtlDestroyed(QObject* obj);
};
void slotCtlDestroyed(QObject *obj);
};
} // namespace LtsNotification
@@ -13,94 +13,95 @@
namespace LtsNotification
{
LtsNotificationController::LtsNotificationController(const QString& identifier)
: QObject(), m_count(0), m_identifier(QStringLiteral("LtsNotification%1").arg(identifier))
{
}
LtsNotificationController::LtsNotificationController(const QString &identifier)
: QObject()
, m_count(0)
, m_identifier(QStringLiteral("LtsNotification%1").arg(identifier))
{
}
LtsNotificationController::~LtsNotificationController()
{
LtsNotificationController::~LtsNotificationController()
{
qDeleteAll(m_notiList);
}
}
void LtsNotificationController::setIcon(const QIcon& icon)
{
void LtsNotificationController::setIcon(const QIcon &icon)
{
m_icon = icon;
setAllIcons();
}
}
void LtsNotificationController::setCount(const int count)
{
void LtsNotificationController::setCount(const int count)
{
m_count = count;
setAllIcons();
}
}
void LtsNotificationController::setBackground(const int r, const int g, const int b)
{
void LtsNotificationController::setBackground(const int r, const int g, const int b)
{
for (QToolButton* tb : std::as_const(m_notiList))
for (QToolButton *tb : std::as_const(m_notiList))
{
QString stylesheet;
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(");}");
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);
tb->setStyleSheet(stylesheet);
}
}
}
void LtsNotificationController::setEnabled(bool enable)
{
void LtsNotificationController::setEnabled(bool enable)
{
m_enable = enable;
setAllIcons();
}
}
void LtsNotificationController::setAction(const std::function<void(void)>& action)
{
void LtsNotificationController::setAction(const std::function<void(void)> &action)
{
m_action = action;
}
}
void LtsNotificationController::setToolTip(const QString& toolTip)
{
void LtsNotificationController::setToolTip(const QString &toolTip)
{
m_toolTip = toolTip;
for (QToolButton* tb : std::as_const(m_notiList))
for (QToolButton *tb : std::as_const(m_notiList))
{
tb->setToolTip(toolTip);
tb->setIconSize(QSize(30, 30));
tb->setToolTip(toolTip);
tb->setIconSize(QSize(30, 30));
}
}
}
void LtsNotificationController::setAllIcons()
{
void LtsNotificationController::setAllIcons()
{
if (m_icon.isNull())
return;
return;
QIcon icon = modifyIcon(m_icon);
for (QToolButton* tb : std::as_const(m_notiList))
for (QToolButton *tb : std::as_const(m_notiList))
{
tb->setIcon(icon);
tb->setIconSize(QSize(30, 30));
tb->setEnabled(m_enable);
tb->setIcon(icon);
tb->setIconSize(QSize(30, 30));
tb->setEnabled(m_enable);
}
}
}
#define SIZE 40
QIcon LtsNotificationController::modifyIcon(const QIcon& icon)
{
QIcon LtsNotificationController::modifyIcon(const QIcon &icon)
{
if (m_count < 1)
return icon;
return icon;
QPixmap iconImage(icon.pixmap(SIZE * 8 / 10, SIZE * 8 / 10));
QPainter painter(&iconImage);
@@ -121,11 +122,11 @@ QIcon LtsNotificationController::modifyIcon(const QIcon& icon)
painter.restore();
return iconImage;
}
}
QToolButton* LtsNotificationController::createWidget()
{
QToolButton* b = new QToolButton();
QToolButton *LtsNotificationController::createWidget()
{
QToolButton *b = new QToolButton();
b->setToolButtonStyle(Qt::ToolButtonIconOnly);
b->setObjectName(m_identifier);
@@ -133,23 +134,27 @@ QToolButton* LtsNotificationController::createWidget()
b->setMaximumSize(SIZE, SIZE);
connect(b, &QToolButton::destroyed, this, &LtsNotificationController::slotNotiWidgetDestroyed);
connect(b, &QToolButton::clicked, this, [this]() {
if (m_action)
m_action();
});
connect(b,
&QToolButton::clicked,
this,
[this]()
{
if (m_action)
m_action();
});
if (!m_icon.isNull())
b->setIcon(modifyIcon(m_icon));
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));
}
void LtsNotificationController::slotNotiWidgetDestroyed(QObject *obj)
{
m_notiList.removeAll(static_cast<QToolButton *>(obj));
}
} // namespace LtsNotification
@@ -14,43 +14,37 @@ class QToolButton;
namespace LtsSession
{
class LtsSession;
class LtsSession;
}
namespace LtsNotification
{
class LtsNotificationWidget;
class LtsNotificationWidget;
class LTSNOTIFICATION_EXPORT LtsNotificationController : public QObject
{
class LTSNOTIFICATION_EXPORT LtsNotificationController : public QObject
{
Q_OBJECT
public:
explicit LtsNotificationController(const QString& identifier);
explicit LtsNotificationController(const QString &identifier);
~LtsNotificationController();
QToolButton* createWidget();
QToolButton *createWidget();
void setIcon(const QIcon& icon);
void setAction(const std::function<void(void)>& action);
void setToolTip(const QString& toolTip);
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 &identifier() const { return m_identifier; }
const QString& tooltip() const
{
return m_toolTip;
}
const QString &tooltip() const { return m_toolTip; }
void setEnabled(bool enable);
private:
QList<QToolButton*> m_notiList;
QList<QToolButton *> m_notiList;
QIcon m_icon;
std::function<void(void)> m_action;
@@ -60,10 +54,10 @@ class LTSNOTIFICATION_EXPORT LtsNotificationController : public QObject
QString m_identifier;
void setAllIcons();
QIcon modifyIcon(const QIcon& icon);
QIcon modifyIcon(const QIcon &icon);
private slots:
void slotNotiWidgetDestroyed(QObject* obj);
};
void slotNotiWidgetDestroyed(QObject *obj);
};
} // namespace LtsNotification
@@ -16,157 +16,160 @@
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)
LtsRestClient::LtsRestClient(const QString &baseUrl, QObject *parent)
: QObject(parent)
, m_baseUrl(baseUrl)
, m_manager(new QNetworkAccessManager(this))
{
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]()
void LtsRestClient::ping(PingSuccessCallback onSuccess, ErrorCallback onError, int timeoutMs)
{
if (reply && reply->isRunning())
reply->abort(); // Triggers finished() with OperationCanceledError
});
const QNetworkRequest request((QUrl(m_baseUrl)));
QNetworkReply *reply = m_manager->head(request);
// 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 (!reply)
{
if (onError)
{
if (reply->error() == QNetworkReply::OperationCanceledError)
onError(QStringLiteral("Ping timed out."));
else
onError(reply->errorString());
}
onError(QStringLiteral("Failed to initiate ping."));
return;
}
const int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
// 1. Setup the timer (parented to reply for auto-cleanup)
QTimer *timeoutTimer = new QTimer(reply);
timeoutTimer->setSingleShot(true);
if (onSuccess)
onSuccess(statusCode);
});
// 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
});
// 4. Start the timer only after all connections are successfully established
timeoutTimer->start(timeoutMs);
}
// 3. Connect the finished signal to handle the response
connect(reply,
&QNetworkReply::finished,
this,
[reply, timeoutTimer, onSuccess, onError]()
{
timeoutTimer->stop();
reply->deleteLater();
void LtsRestClient::get(const QString &endpoint, SuccessCallback onSuccess, ErrorCallback onError)
{
sendRequest(QStringLiteral("GET"), endpoint, QByteArray(), onSuccess, onError);
}
if (reply->error() != QNetworkReply::NoError)
{
if (onError)
{
if (reply->error() == QNetworkReply::OperationCanceledError)
onError(QStringLiteral("Ping timed out."));
else
onError(reply->errorString());
}
void LtsRestClient::post(const QString &endpoint, const QJsonDocument &json, SuccessCallback onSuccess, ErrorCallback onError)
{
sendRequest(QStringLiteral("POST"), endpoint, json.toJson(), onSuccess, onError);
}
return;
}
void LtsRestClient::put(const QString &endpoint, const QJsonDocument &json, SuccessCallback onSuccess, ErrorCallback onError)
{
sendRequest(QStringLiteral("PUT"), endpoint, json.toJson(), onSuccess, onError);
}
const int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
void LtsRestClient::del(const QString &endpoint, SuccessCallback onSuccess, ErrorCallback onError)
{
sendRequest(QStringLiteral("DELETE"), endpoint, QByteArray(), onSuccess, onError);
}
if (onSuccess)
onSuccess(statusCode);
});
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;
// 4. Start the timer only after all connections are successfully established
timeoutTimer->start(timeoutMs);
}
connect(reply,
&QNetworkReply::finished,
this,
[reply, onSuccess, onError]()
void LtsRestClient::get(const QString &endpoint, SuccessCallback onSuccess, ErrorCallback onError)
{
reply->deleteLater();
sendRequest(QStringLiteral("GET"), endpoint, QByteArray(), onSuccess, onError);
}
// Handle network errors
if (reply->error() != QNetworkReply::NoError)
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(reply->errorString());
onError(QStringLiteral("Failed to initiate request."));
return;
}
// Handle HTTP errors
const int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (statusCode >= 400)
{
if (onError)
onError(QStringLiteral("HTTP Error %1").arg(statusCode));
connect(reply,
&QNetworkReply::finished,
this,
[reply, onSuccess, onError]()
{
reply->deleteLater();
return;
}
// Handle network errors
if (reply->error() != QNetworkReply::NoError)
{
if (onError)
onError(reply->errorString());
// Parse JSON safely
QJsonParseError parseError;
const QJsonDocument doc = QJsonDocument::fromJson(reply->readAll(), &parseError);
return;
}
if (parseError.error != QJsonParseError::NoError)
{
if (onError)
onError(QStringLiteral("JSON Parse Error: ") + parseError.errorString());
// Handle HTTP errors
const int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (statusCode >= 400)
{
if (onError)
onError(QStringLiteral("HTTP Error %1").arg(statusCode));
return;
}
return;
}
if (onSuccess)
onSuccess(doc);
});
}
// 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
@@ -21,31 +21,31 @@ class QNetworkAccessManager;
namespace LtsCommon
{
class LTSRESTCLIENT_EXPORT LtsRestClient : public QObject
{
Q_OBJECT
class LTSRESTCLIENT_EXPORT LtsRestClient : public QObject
{
Q_OBJECT
public:
explicit LtsRestClient(const QString &baseUrl, QObject *parent = nullptr);
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 &)>;
// 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 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);
// 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);
void sendRequest(const QString &method, const QString &endpoint, const QByteArray &data, SuccessCallback onSuccess, ErrorCallback onError);
QString m_baseUrl;
QNetworkAccessManager *m_manager;
}; // class RestClient
QString m_baseUrl;
QNetworkAccessManager *m_manager;
}; // class RestClient
} // namespace LtsCommon
@@ -7,8 +7,8 @@
namespace LtsSerialPortQuerry
{
LOGGER_T getLogger(const char* name)
{
LOGGER_T getLogger(const char *name)
{
static const char ns[] = "SPQ.";
std::string loggerName;
const size_t len = strlen(name);
@@ -18,13 +18,13 @@ LOGGER_T getLogger(const char* name)
try
{
return NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger(loggerName);
return NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger(loggerName);
}
catch (const std::exception& ex)
catch (const std::exception &ex)
{
fprintf(stderr, "Error retrieving logger: %s", ex.what());
abort();
fprintf(stderr, "Error retrieving logger: %s", ex.what());
abort();
}
}
}
} // namespace LtsSerialPortQuerry
@@ -6,12 +6,12 @@
namespace LtsSerialPortQuerry
{
typedef NGL::INGLLogger& LOGGER_T;
typedef NGL::INGLLogger &LOGGER_T;
LOGGER_T getLogger(const char* name);
LOGGER_T getLogger(const char *name);
inline LOGGER_T getLogger(const QString& loggerName)
{
inline LOGGER_T getLogger(const QString &loggerName)
{
return getLogger(loggerName.toUtf8().constData());
}
}
} // namespace LtsSerialPortQuerry
@@ -9,24 +9,27 @@
namespace LtsSerialPortQuerry
{
class LTSSERIALPORTQUERRY_EXPORT LtsSerialPortQuerry : public QObject
{
class LTSSERIALPORTQUERRY_EXPORT LtsSerialPortQuerry : public QObject
{
Q_OBJECT
public:
explicit LtsSerialPortQuerry(QObject* parent = nullptr);
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 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();
QSerialPort *currentSerialPort();
signals:
void connectionEstablished();
private:
void querrySerialPort(const QSerialPortInfo& info);
void querrySerialPort(const QSerialPortInfo &info);
void closeAndDeleteCurrentPort();
private:
@@ -41,7 +44,7 @@ class LTSSERIALPORTQUERRY_EXPORT LtsSerialPortQuerry : public QObject
QSerialPort::FlowControl m_flowControll;
QSerialPort::Parity m_parity;
QSerialPort::StopBits m_stopBits;
QSerialPort* m_currentSerialPort;
};
QSerialPort *m_currentSerialPort;
};
} // namespace LtsSerialPortQuerry
@@ -5,59 +5,65 @@
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)
{
}
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)
{
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()
{
void LtsSerialPortQuerry::continueQuerry()
{
m_currentQuerry++;
if (m_currentQuerry >= m_serialPortInfos.size())
{
restartQuerry();
return;
restartQuerry();
return;
}
querrySerialPort(m_serialPortInfos.at(m_currentQuerry));
}
}
void LtsSerialPortQuerry::restartQuerry()
{
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));
querrySerialPort(m_serialPortInfos.at(m_currentQuerry));
else
QTimer::singleShot(1000, this, &LtsSerialPortQuerry::restartQuerry);
}
QTimer::singleShot(1000, this, &LtsSerialPortQuerry::restartQuerry);
}
QSerialPort* LtsSerialPortQuerry::currentSerialPort()
{
QSerialPort *LtsSerialPortQuerry::currentSerialPort()
{
return m_currentSerialPort;
}
}
void LtsSerialPortQuerry::querrySerialPort(const QSerialPortInfo& info)
{
void LtsSerialPortQuerry::querrySerialPort(const QSerialPortInfo &info)
{
closeAndDeleteCurrentPort();
m_currentSerialPort = new QSerialPort(info, this);
m_currentSerialPort->setBaudRate(m_baudRate);
@@ -66,75 +72,76 @@ void LtsSerialPortQuerry::querrySerialPort(const QSerialPortInfo& info)
m_currentSerialPort->setStopBits(m_stopBits);
m_currentSerialPort->setFlowControl(m_flowControll);
DEBUG_LOG(m_logger) << "Try opening Comport:" << m_currentSerialPort->portName()
<< " index is: " << m_currentQuerry;
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";
DEBUG_LOG(m_logger) << "Oppening failed query next";
continueQuerry();
continueQuerry();
}
else
{
connect(m_currentSerialPort, &QSerialPort::errorOccurred, this, &LtsSerialPortQuerry::onSerialPortError,
Qt::UniqueConnection);
DEBUG_LOG(m_logger) << "Oppened comport" << m_currentSerialPort->portName();
emit connectionEstablished();
connect(m_currentSerialPort, &QSerialPort::errorOccurred, this, &LtsSerialPortQuerry::onSerialPortError, Qt::UniqueConnection);
DEBUG_LOG(m_logger) << "Oppened comport" << m_currentSerialPort->portName();
emit connectionEstablished();
}
}
}
void LtsSerialPortQuerry::closeAndDeleteCurrentPort()
{
void LtsSerialPortQuerry::closeAndDeleteCurrentPort()
{
if (m_currentSerialPort)
{
m_currentSerialPort->disconnect();
if (m_currentSerialPort->isOpen())
m_currentSerialPort->close();
m_currentSerialPort->deleteLater();
m_currentSerialPort->disconnect();
if (m_currentSerialPort->isOpen())
m_currentSerialPort->close();
m_currentSerialPort->deleteLater();
m_currentSerialPort = nullptr;
m_currentSerialPort = nullptr;
}
}
}
void LtsSerialPortQuerry::onSerialPortError(QSerialPort::SerialPortError serialPortError)
{
void LtsSerialPortQuerry::onSerialPortError(QSerialPort::SerialPortError serialPortError)
{
if (!m_currentSerialPort)
return;
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());
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: {
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();
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();
Q_FALLTHROUGH();
}
case QSerialPort::SerialPortError::UnsupportedOperationError:
{
ERROR_LOG(m_logger) << errStr;
break;
}
default:
{
ERROR_LOG(m_logger) << "Got an Error> " << errStr << "restarting";
continueQuerry();
break;
}
break;
}
}
}
}
} // namespace LtsSerialPortQuerry
@@ -9,18 +9,21 @@
namespace LtsSerialPortQuerry
{
class LTSSERIALPORTQUERRY_EXPORT LtsSerialPortQuerry : public QObject
{
class LTSSERIALPORTQUERRY_EXPORT LtsSerialPortQuerry : public QObject
{
Q_OBJECT
public:
explicit LtsSerialPortQuerry(QObject* parent = nullptr);
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 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();
QSerialPort *currentSerialPort();
public slots:
void continueQuerry();
@@ -29,8 +32,8 @@ class LTSSERIALPORTQUERRY_EXPORT LtsSerialPortQuerry : public QObject
void connectionEstablished();
private:
NGL::INGLLogger& m_logger;
void querrySerialPort(const QSerialPortInfo& info);
NGL::INGLLogger &m_logger;
void querrySerialPort(const QSerialPortInfo &info);
void closeAndDeleteCurrentPort();
void onSerialPortError(QSerialPort::SerialPortError serialPortError);
QList<QSerialPortInfo> m_serialPortInfos;
@@ -41,7 +44,7 @@ class LTSSERIALPORTQUERRY_EXPORT LtsSerialPortQuerry : public QObject
QSerialPort::FlowControl m_flowControll;
QSerialPort::Parity m_parity;
QSerialPort::StopBits m_stopBits;
QSerialPort* m_currentSerialPort;
};
QSerialPort *m_currentSerialPort;
};
} // namespace LtsSerialPortQuerry
@@ -8,7 +8,4 @@
ADD_SUBDIRECTORY(LtsUtilsCore)
IF(NOT RELEASE_BUILD)
ADD_SUBDIRECTORY(LtsUtilsGui)
ENDIF()
ADD_SUBDIRECTORY(LtsUtilsSettings)
@@ -48,22 +48,3 @@ NGL_TARGET_LINK_LIBRARIES(LtsUtilsCore
Qt6::Core
LtsUtilsCoreHeaderOnly
)
#
# --- Tests --------------------------------------------------------------
#
IF(BUILD_RTI AND (BUILD_WS OR BUILD_SV) AND BUILD_TESTING)
ADD_EXECUTABLE(utils_test
UnitTests/utils_test.cpp
UnitTests/utils_test.h
promise_examples.h
promise_examples.cpp
)
TARGET_LINK_LIBRARIES(utils_test
LtsUtilsCore
Qt6::Core
Qt6::Test
ddscore
)
ADD_TEST(NAME utils_test COMMAND $<TARGET_FILE:utils_test>)
ENDIF()
File diff suppressed because it is too large. Load diff
@@ -6,50 +6,50 @@
class LtsUtilsTest : public QObject
{
Q_OBJECT
private Q_SLOTS:
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_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_QPoint3D();
void test_bitArray();
void test_bitArray();
void test_convert();
void test_convert();
void test_connection();
void test_queuedConnection();
void test_signalSignalConnection();
void test_danglingConnection1();
void test_danglingConnection2();
void test_danglingConnection3();
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_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_byteStreamFromSfmMessage();
void test_byteStreamFromSfmMessage2();
void test_byteStreamToSfmMessage();
void test_promise();
void test_promise_example1();
void test_promise_example2();
void test_promise_example3();
void test_promise();
void test_promise_example1();
void test_promise_example2();
void test_promise_example3();
void byteAccess();
void byteAccess();
};
@@ -7,28 +7,25 @@
namespace LtsUtils
{
template <typename Func>
void addConnect(QEventLoop& x, bool& success, const typename QtPrivate::FunctionPointer<Func>::Object* sender,
Func signal, bool isSuccess)
{
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, [&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)
{
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)
{
template <typename... Connect> void await(Connect... connects) noexcept(false)
{
QEventLoop x;
bool success = false;
@@ -39,24 +36,28 @@ template <typename... Connect> void await(Connect... connects) noexcept(false)
if (!success)
{
throw std::runtime_error("Failed.");
throw std::runtime_error("Failed.");
}
}
}
template <typename... Connect> void awaitTimeout(const int timeoutMs, Connect... connects) noexcept(false)
{
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();
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...);
@@ -64,21 +65,23 @@ template <typename... Connect> void awaitTimeout(const int timeoutMs, Connect...
if (timeout)
{
throw std::runtime_error("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)
{
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;
awaitTimeout(timeoutMs, sender1, signal1, true, sender2, signal2, false);
return;
}
await(sender1, signal1, true, sender2, signal2, false);
}
}
} // namespace LtsUtils
@@ -11,36 +11,36 @@
namespace LtsUtils
{
class IConnection
{
class IConnection
{
public:
virtual ~IConnection() = default;
virtual void connect(Qt::ConnectionType = Qt::AutoConnection) = 0;
virtual void disconnect() = 0;
};
};
class DummyConnection : public IConnection
{
class DummyConnection : public IConnection
{
public:
void connect(Qt::ConnectionType = Qt::AutoConnection) override {}
void disconnect() override {}
};
};
namespace detail
{
namespace detail
{
template <class T> struct ExtractClass;
template <class T> struct ExtractClass;
template <class T, class Member> struct ExtractClass<Member T::*>
{
using type = T;
};
template <class T, class Member> struct ExtractClass<Member T::*>
{
using type = T;
};
} // namespace detail
} // namespace detail
template <class Signal, class Slot> class Connection : public IConnection
{
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");
@@ -51,36 +51,39 @@ template <class Signal, class Slot> class Connection : public IConnection
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)
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);
Q_ASSERT(emitter);
Q_ASSERT(signal);
Q_ASSERT(target);
Q_ASSERT(slot);
}
void connect(Qt::ConnectionType connectionType = Qt::AutoConnection) override
{
Q_ASSERT(!m_connected);
Q_ASSERT(!m_connected);
m_connected = true;
m_connected = true;
if (!m_emitter || !m_target)
return;
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);
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);
Q_ASSERT(m_connected);
if (m_conn)
QObject::disconnect(m_conn);
if (m_conn)
QObject::disconnect(m_conn);
m_connected = false;
m_connected = false;
}
private:
@@ -90,13 +93,15 @@ template <class Signal, class Slot> class Connection : public IConnection
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)
{
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
@@ -4,21 +4,26 @@
#include <ostream>
enum class DataModification { eAdded, eModified, eRemoved };
inline std::ostream& operator<<(std::ostream& str, DataModification mod)
enum class DataModification
{
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;
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;
}
@@ -9,82 +9,82 @@
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())
namespace BitArray
{
constexpr inline int bitNumber(int position)
{
if (oob)
*oob = true;
return false;
return 7 - (position % 8);
}
if (oob)
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);
}
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())
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)
const typename T::value_type mask = 1 << bitNumber(position);
if (set)
bitField[byteNum] |= mask;
else
else
bitField[byteNum] &= ~mask;
return true;
}
return true;
}
template <typename T> inline bool clearBit(T& bitField, int position)
{
return setBit(bitField, position, false);
}
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)
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;
ret[byteNum] |= mask;
else
ret[byteNum] &= ~mask;
ret[byteNum] &= ~mask;
}
return ret;
}
return ret;
}
template <typename T> inline QBitArray convert(T& bitField, int realSize)
{
QBitArray ba(realSize);
for (int32_t i = 0; i < realSize; ++i)
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;
}
return ba;
}
#endif
} // namespace BitArray
} // namespace BitArray
} // namespace LtsUtils
@@ -8,30 +8,30 @@
namespace LtsUtils
{
template <typename T, typename S> inline void convert(const S& in, T& out)
{
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)
{
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)
{
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)
{
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
@@ -14,11 +14,11 @@ 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);
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
File diff suppressed because it is too large. Load diff
@@ -3,12 +3,12 @@
namespace LtsUtils
{
LtsUtils::LtsPortRange fromQPoint(const QPoint& point)
{
LtsUtils::LtsPortRange fromQPoint(const QPoint &point)
{
if (point.x() < 1025 || point.y() > 65535 || point.x() > point.y())
return {};
return {};
return {static_cast<quint16>(point.x()), static_cast<quint16>(point.y())};
}
}
} // namespace LtsUtils
@@ -7,7 +7,7 @@
namespace LtsUtils
{
typedef QPair<quint16, quint16> LtsPortRange;
typedef QPair<quint16, quint16> LtsPortRange;
LTSUTILSCORE_EXPORT LtsPortRange fromQPoint(const QPoint& point);
LTSUTILSCORE_EXPORT LtsPortRange fromQPoint(const QPoint &point);
} // namespace LtsUtils
@@ -6,17 +6,17 @@
namespace LtsUtils
{
LtsTranslatableIdentifier::LtsTranslatableIdentifier(const QString& identifier, const QObject* context,
const char* translatableText)
: m_identifier(identifier), m_translationContext(context->metaObject()->className()),
m_translatableText(translatableText)
{
}
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
{
const QString LtsTranslatableIdentifier::translatedText(const char *disambiguation, int n) const
{
if (m_identifier.isEmpty() || m_translationContext == nullptr || m_translatableText == nullptr)
return {};
return {};
return QCoreApplication::translate(m_translationContext, m_translatableText, disambiguation, n);
}
}
} // namespace LtsUtils
@@ -7,29 +7,27 @@
namespace LtsUtils
{
class LTSUTILSCORE_EXPORT LtsTranslatableIdentifier
{
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
LtsTranslatableIdentifier()
: m_translationContext(nullptr)
, m_translatableText("")
{
return m_identifier;
}
const QString translatedText(const char* disambiguation = nullptr, int n = -1) const;
LtsTranslatableIdentifier(const QString &identifier, const QObject *context, const char *translatableText);
const QString _context() const
{
return QString::fromUtf8(m_translationContext);
}
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_translationContext;
const char* m_translatableText;
};
const char *m_translatableText;
};
} // namespace LtsUtils
@@ -18,4 +18,4 @@
#define LTSUTILSCORE_EXPORT Q_DECL_IMPORT
#endif
#endif
#endif
#endif
@@ -6,9 +6,9 @@
namespace LtsUtils
{
inline bool isPositionTimeOutdated(qint64 curTime, qint64 posTime)
{
inline bool isPositionTimeOutdated(qint64 curTime, qint64 posTime)
{
return curTime > posTime + 11 * 60 * 1000;
}
}
} // namespace LtsUtils
@@ -11,141 +11,135 @@
namespace LtsUtils
{
template <typename T> static inline QString convertToPgString(const std::vector<T>& data)
{
template <typename T> static inline QString convertToPgString(const std::vector<T> &data)
{
if (data.size() == 0)
return QLatin1String("{}");
return QLatin1String("{}");
QString ret(QLatin1Char('{'));
for (T i : data)
ret += QString::number(i) + QLatin1Char(',');
ret += QString::number(i) + QLatin1Char(',');
ret.chop(1);
ret += QLatin1Char('}');
return ret;
}
}
template <> LTSUTILSCORE_EXPORT QString IntArray::toPgString() const
{
template <> LTSUTILSCORE_EXPORT QString IntArray::toPgString() const
{
return convertToPgString(m_data);
}
}
template <> LTSUTILSCORE_EXPORT QString BigintArray::toPgString() const
{
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)
{
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);
return T(result);
if (idxStart < 0 && idxEnd < 0)
{
idxStart = -1;
idxEnd = str.length() + 1;
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)
for (const QStringView &s : vec)
{
bool ok = false;
const typename T::Type i = convertFunc(s, &ok);
if (ok)
result.push_back(i);
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 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 <> 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)
{
template <typename T> static inline QString convertToPgString(const std::map<T, T> &data)
{
if (data.size() == 0)
return QLatin1String("{}");
return QLatin1String("{}");
QString ret(QLatin1Char('{'));
for (const auto& it : data)
for (const auto &it : data)
{
ret += QLatin1Char('{') + QString::number(it.first) + QLatin1Char(',') + QString::number(it.second) +
QLatin1String("},");
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
{
template <> LTSUTILSCORE_EXPORT QString IntArray2D::toPgString() const
{
return convertToPgString<IntArray2D::Type>(m_data);
}
}
template <> LTSUTILSCORE_EXPORT QString BigintArray2D::toPgString() const
{
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)
{
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);
return T(ret);
if (idxStart < 0 && idxEnd < 0)
{
idxStart = -1;
idxEnd = str.length() + 1;
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;
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));
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);
idxStart = strRef.indexOf(QLatin1Char('{'), idxEnd + 1);
}
return T(ret);
}
}
template <> LTSUTILSCORE_EXPORT IntArray2D IntArray2D::fromPgString(const QString& str)
{
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)
{
template <> LTSUTILSCORE_EXPORT BigintArray2D BigintArray2D::fromPgString(const QString &str)
{
return convertFromPgString2D<BigintArray2D>(str, [](QStringView val) { return val.toString().toLongLong(); });
}
}
} // namespace LtsUtils
@@ -9,32 +9,32 @@
namespace LtsUtils
{
template <typename T, typename C> class PgArray
{
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
Q_DECL_CONSTEXPR explicit PgArray(const C &data)
: m_data(data)
{
return m_data;
}
Q_DECL_CONSTEXPR C operator()() const { return m_data; }
[[nodiscard]] QString toPgString() const;
static PgArray fromPgString(const QString& str);
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 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>>;
using IntArray2D = PgArray<int, std::map<int, int>>;
using BigintArray2D = PgArray<int64_t, std::map<int64_t, int64_t>>;
} // namespace LtsUtils
@@ -7,74 +7,76 @@
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)
{
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)
{
void Promise::setFunction(const std::function<void(ResultFunction resolve, ResultFunction reject)> &function)
{
if (!function || m_functionAlreadySet)
return;
return;
m_functionAlreadySet = true;
if (m_timeoutSet)
m_timeout->start();
m_timeout->start();
QTimer::singleShot(0, this, [this, function]() {
function([this](const QVariant& value) { resolve(value); }, [this](const QVariant& value) { reject(value); });
});
}
QTimer::singleShot(0, this, [this, function]() { function([this](const QVariant &value) { resolve(value); }, [this](const QVariant &value) { reject(value); }); });
}
void Promise::setTimeout(int interval)
{
void Promise::setTimeout(int interval)
{
m_timeout->stop();
m_timeout->setInterval(interval);
m_timeoutSet = (interval != 0);
if (interval != 0 && m_functionAlreadySet)
m_timeout->start();
}
m_timeout->start();
}
void Promise::slotTimeout()
{
void Promise::slotTimeout()
{
reject(QStringLiteral("timeout"));
}
}
void Promise::resolve(const QVariant& value)
{
void Promise::resolve(const QVariant &value)
{
if (m_resultSet)
return;
return;
m_resultSet = true;
m_timeout->stop();
m_resolveFn(value);
}
}
void Promise::reject(const QVariant& value)
{
void Promise::reject(const QVariant &value)
{
if (m_resultSet)
return;
return;
m_resultSet = true;
m_timeout->stop();
m_rejectFn(value);
}
}
Promise& Promise::resolved(ResultFunction resolveFn)
{
Promise &Promise::resolved(ResultFunction resolveFn)
{
m_resolveFn = resolveFn;
return *this;
}
}
Promise& Promise::rejected(ResultFunction rejectFn)
{
Promise &Promise::rejected(ResultFunction rejectFn)
{
m_rejectFn = rejectFn;
return *this;
}
}
} // namespace LtsUtils
@@ -10,39 +10,38 @@ class QTimer;
namespace LtsUtils
{
typedef std::function<void(const QVariant& value)> RawResultFunction;
typedef const RawResultFunction& ResultFunction;
typedef std::function<void(const QVariant &value)> RawResultFunction;
typedef const RawResultFunction &ResultFunction;
class LTSUTILSCORE_EXPORT Promise : public QObject
{
class LTSUTILSCORE_EXPORT Promise : public QObject
{
Q_OBJECT
public:
Promise(const std::function<void(ResultFunction resolve, ResultFunction reject)>& function,
QObject* parent = nullptr);
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 setFunction(const std::function<void(ResultFunction resolve, ResultFunction reject)> &function);
void resolve(const QVariant& value = QVariant());
void resolve(const QVariant &value = QVariant());
void reject(const QVariant& value = QVariant());
void reject(const QVariant &value = QVariant());
void setTimeout(int interval);
Promise& resolved(ResultFunction resolveFn);
Promise &resolved(ResultFunction resolveFn);
Promise& rejected(ResultFunction rejectFn);
Promise &rejected(ResultFunction rejectFn);
private:
RawResultFunction m_resolveFn;
RawResultFunction m_rejectFn;
bool m_functionAlreadySet;
QTimer* m_timeout;
QTimer *m_timeout;
bool m_resultSet;
bool m_timeoutSet;
private slots:
void slotTimeout();
};
};
} // namespace LtsUtils
@@ -9,57 +9,72 @@
namespace LtsUtils
{
void PromiseExample1_Class::doSomethingAsync1()
{
void PromiseExample1_Class::doSomethingAsync1()
{
QTimer::singleShot(200, this, [this]() { emit signalDone1(true); });
}
}
void PromiseExample1_Class::doSomethingAsync2()
{
void PromiseExample1_Class::doSomethingAsync2()
{
QTimer::singleShot(450, this, [this]() { emit signalDone2(true, 1234); });
}
}
PromiseExample1::PromiseExample1(QObject* parent) : QObject(parent), m_success(false)
{
PromiseExample1::PromiseExample1(QObject *parent)
: QObject(parent)
, m_success(false)
{
auto func = [this](ResultFunction resolve, ResultFunction reject) {
PromiseExample1_Class* c = new PromiseExample1_Class(this);
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)
{
connect(c,
&PromiseExample1_Class::signalDone1,
this,
[this, c, resolve, reject](bool didThisWork)
{
if (!didThisWork)
{
reject(QStringLiteral("First Action did not succeed"));
return;
}
else
{
reject(QStringLiteral("First Action did not succeed"));
return;
}
else
{
connect(c, &PromiseExample1_Class::signalDone2, this,
[resolve, reject](bool didThisWork, int someNumberThatReturns) {
connect(c,
&PromiseExample1_Class::signalDone2,
this,
[resolve, reject](bool didThisWork, int someNumberThatReturns)
{
if (didThisWork)
resolve(someNumberThatReturns);
resolve(someNumberThatReturns);
else
reject(QStringLiteral("Second Action did not succeed"));
});
reject(QStringLiteral("Second Action did not succeed"));
});
c->doSomethingAsync2();
}
});
c->doSomethingAsync2();
}
});
c->doSomethingAsync1();
c->doSomethingAsync1();
};
Promise* p = new Promise(func, this);
Promise *p = new Promise(func, this);
p->resolved([this](const QVariant& value) {
qDebug() << "example1 promise succeeded! 'someNumberThatReturns' was" << value;
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; });
}
m_success = true;
})
.rejected([](const QVariant &value) { qDebug() << "example1 promise failed.." << value; });
}
PromiseExample2::PromiseExample2(QObject* parent) : QObject(parent), m_success(false)
{
PromiseExample2::PromiseExample2(QObject *parent)
: QObject(parent)
, m_success(false)
{
Promise* p = new Promise(
[](ResultFunction, ResultFunction) {
@@ -69,32 +84,39 @@ PromiseExample2::PromiseExample2(QObject* parent) : QObject(parent), m_success(f
p->setTimeout(1000);
p->resolved([](const QVariant&) { QFAIL("This test case's promise should never resolve"); });
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;
});
}
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)
{
PromiseExample3::PromiseExample3(QObject *parent)
: QObject(parent)
, m_success(true)
, m_alreadyRejected(false)
{
Promise* p = new Promise([](ResultFunction, ResultFunction reject) { reject(QString()); }, this);
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->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");
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";
});
}
m_alreadyRejected = true;
qDebug() << "Promise rejected as expected";
});
}
} // namespace LtsUtils
@@ -5,8 +5,8 @@
namespace LtsUtils
{
class PromiseExample1_Class : public QObject
{
class PromiseExample1_Class : public QObject
{
Q_OBJECT
public:
using QObject::QObject;
@@ -17,52 +17,43 @@ class PromiseExample1_Class : public QObject
signals:
void signalDone1(bool didThisWork);
void signalDone2(bool didThisWork, int someNumberThatReturns);
};
};
class PromiseExample1 : public QObject
{
class PromiseExample1 : public QObject
{
Q_OBJECT
public:
explicit PromiseExample1(QObject* parent = nullptr);
explicit PromiseExample1(QObject *parent = nullptr);
[[nodiscard]] bool isSuccess() const
{
return m_success;
}
[[nodiscard]] bool isSuccess() const { return m_success; }
private:
bool m_success;
};
};
class PromiseExample2 : public QObject
{
class PromiseExample2 : public QObject
{
Q_OBJECT
public:
explicit PromiseExample2(QObject* parent = nullptr);
explicit PromiseExample2(QObject *parent = nullptr);
[[nodiscard]] bool isSuccess() const
{
return m_success;
}
[[nodiscard]] bool isSuccess() const { return m_success; }
private:
bool m_success;
};
};
class PromiseExample3 : public QObject
{
class PromiseExample3 : public QObject
{
Q_OBJECT
public:
explicit PromiseExample3(QObject* parent = nullptr);
explicit PromiseExample3(QObject *parent = nullptr);
[[nodiscard]] bool isSuccess() const
{
return m_success;
}
[[nodiscard]] bool isSuccess() const { return m_success; }
private:
bool m_success;
bool m_alreadyRejected;
};
};
} // namespace LtsUtils
@@ -8,8 +8,8 @@
namespace LtsUtils
{
template <typename T> void inline set8Byte(const T in, QByteArray& out)
{
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;
@@ -19,34 +19,35 @@ template <typename T> void inline set8Byte(const T in, QByteArray& out)
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;
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)
{
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;
return false;
const char* data = baData.data() + pos;
const char *data = baData.data() + pos;
if (std::numeric_limits<T>::is_signed)
out |= static_cast<signed long long>(data[0]) << 56;
out |= static_cast<signed long long>(data[0]) << 56;
else
out |= (data[0] & 0xFFULL) << 56;
out |= (data[0] & 0xFFULL) << 56;
out |= (data[1] & 0xFFULL) << 48;
out |= (data[2] & 0xFFULL) << 40;
out |= (data[3] & 0xFFULL) << 32;
@@ -58,59 +59,60 @@ template <typename T> bool inline get8Byte(const QByteArray& baData, size_t& pos
pos += 8;
return true;
}
}
template <> bool inline get8Byte(const QByteArray& baData, size_t& pos, double& out)
{
template <> bool inline get8Byte(const QByteArray &baData, size_t &pos, double &out)
{
out = 0.;
union hack {
double d;
int64_t i;
union hack
{
double d;
int64_t i;
} h;
if (!get8Byte(baData, pos, h.i))
return false;
return false;
out = h.d;
return true;
}
}
template <typename T> bool inline get8Byte(const QByteArray& data, T& out)
{
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)
{
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)
{
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)
{
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;
return false;
const char* data = baData.data() + pos;
const char *data = baData.data() + pos;
if (std::numeric_limits<T>::is_signed)
out |= data[0] << 24;
out |= data[0] << 24;
else
out |= (data[0] & 0xFFU) << 24;
out |= (data[0] & 0xFFU) << 24;
out |= (data[1] & 0xFFU) << 16;
out |= (data[2] & 0xFFU) << 8;
out |= (data[3] & 0xFFU);
@@ -118,124 +120,124 @@ template <typename T> bool inline get4Byte(const QByteArray& baData, size_t& pos
pos += 4;
return true;
}
}
template <> bool inline get4Byte(const QByteArray& baData, size_t& pos, double& out)
{
template <> bool inline get4Byte(const QByteArray &baData, size_t &pos, double &out)
{
out = 0.;
int tmp;
if (!get4Byte(baData, pos, tmp))
return false;
return false;
out = tmp;
return true;
}
}
template <typename T> bool inline get4Byte(const QByteArray& data, T& out)
{
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)
{
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)
{
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;
return false;
const char* data = baData.data() + pos;
const char *data = baData.data() + pos;
if (std::numeric_limits<T>::is_signed)
out |= data[0] << 16;
out |= data[0] << 16;
else
out |= (data[0] & 0xFFU) << 16;
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)
{
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)
{
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)
{
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;
return false;
const char* data = baData.data() + pos;
const char *data = baData.data() + pos;
if (std::numeric_limits<T>::is_signed)
out |= data[0] << 8;
out |= data[0] << 8;
else
out |= (data[0] & 0xFFU) << 8;
out |= (data[0] & 0xFFU) << 8;
out |= data[1] & 0xFFU;
pos += 2;
return true;
}
}
template <typename T> bool inline get2Byte(const QByteArray& data, T& out)
{
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)
{
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)
{
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;
return false;
if (std::numeric_limits<T>::is_signed)
out = (T)(baData.at(pos));
out = (T)(baData.at(pos));
else
out = (T)(baData.at(pos) & 0xFF);
out = (T)(baData.at(pos) & 0xFF);
pos += 1;
return true;
}
}
template <typename T> bool inline get1Byte(const QByteArray& data, T& out)
{
template <typename T> bool inline get1Byte(const QByteArray &data, T &out)
{
size_t pos = 0;
return get1Byte(data, pos, out);
}
}
} // namespace LtsUtils
@@ -5,69 +5,72 @@
namespace LtsUtils
{
QPlane3D::QPlane3D(const QPoint3D& pos, const QPoint3D& vec1, const QPoint3D& vec2)
: m_pos(pos), m_vec1(vec1), m_vec2(vec2)
{
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
{
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();
return inPlane(point) ? point : QPoint3D();
const double distance = distanceTo(point) / std::abs(dotProduct);
return point + distance * direction;
}
}
bool QPlane3D::intersects(const QPoint3D& direction) const
{
bool QPlane3D::intersects(const QPoint3D &direction) const
{
return !isParallel(direction);
}
}
bool QPlane3D::isParallel(const QPoint3D& direction) const
{
bool QPlane3D::isParallel(const QPoint3D &direction) const
{
return qFuzzyIsNull(QPoint3D::dotProduct(m_normal, direction));
}
}
bool QPlane3D::inPlane(const QPoint3D& point) const
{
bool QPlane3D::inPlane(const QPoint3D &point) const
{
if (point == m_pos)
return true;
return true;
return qFuzzyIsNull(QPoint3D::dotProduct(m_normal, point - m_pos));
}
}
double QPlane3D::distanceTo(const QPoint3D& point) const
{
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)
{
}
QPolygon3D::QPolygon3D(const QVector<QPoint3D> &vertices)
: QPlane3D(vertices[0], vertices[1], vertices[2])
, m_vertices(vertices)
{
}
bool QPolygon3D::containsPoint(const QPoint3D& point) const
{
bool QPolygon3D::containsPoint(const QPoint3D &point) const
{
if (!inPlane(point))
return false;
return false;
if (contains(point))
return true;
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;
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);
cosTheta = QPoint3D::dotProduct(first, second) / (first.length() * second.length());
angleSum += acos(cosTheta);
}
return qFuzzyIsNull(M_2_PI - angleSum);
}
}
} // namespace LtsUtils
@@ -11,42 +11,27 @@
namespace LtsUtils
{
class LTSUTILSCORE_EXPORT QPlane3D
{
class LTSUTILSCORE_EXPORT QPlane3D
{
public:
QPlane3D(const QPoint3D& pos, const QPoint3D& vec1, const QPoint3D& vec2);
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;
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 &pos() const { return m_pos; }
const QPoint3D& vec1() const
{
return m_vec1;
}
const QPoint3D &vec1() const { return m_vec1; }
const QPoint3D& vec2() const
{
return m_vec2;
}
const QPoint3D &vec2() const { return m_vec2; }
const QPoint3D& normal() const
{
return m_normal;
}
const QPoint3D &normal() const { return m_normal; }
double planeC() const
{
return m_planeC;
}
double planeC() const { return m_planeC; }
protected:
QPoint3D m_pos;
@@ -54,23 +39,20 @@ class LTSUTILSCORE_EXPORT QPlane3D
QPoint3D m_vec2;
QPoint3D m_normal;
double m_planeC;
};
};
class LTSUTILSCORE_EXPORT QPolygon3D : public QPlane3D
{
class LTSUTILSCORE_EXPORT QPolygon3D : public QPlane3D
{
public:
QPolygon3D(const QVector<QPoint3D>& vertices);
QPolygon3D(const QVector<QPoint3D> &vertices);
bool contains(const QPoint3D& point) const
{
return m_vertices.contains(point);
}
bool contains(const QPoint3D &point) const { return m_vertices.contains(point); }
bool containsPoint(const QPoint3D& point) const;
bool containsPoint(const QPoint3D &point) const;
private:
QVector<QPoint3D> m_vertices;
};
};
} // namespace LtsUtils
@@ -7,14 +7,14 @@
namespace LtsUtils
{
QDataStream& operator<<(QDataStream& s, const QPoint3D& p)
{
QDataStream &operator<<(QDataStream &s, const QPoint3D &p)
{
s << p.x() << p.y() << p.z();
return s;
}
}
QDataStream& operator>>(QDataStream& s, QPoint3D& p)
{
QDataStream &operator>>(QDataStream &s, QPoint3D &p)
{
double x, y, z;
s >> x;
p.rx() = x;
@@ -23,6 +23,6 @@ QDataStream& operator>>(QDataStream& s, QPoint3D& p)
s >> z;
p.rz() = z;
return s;
}
}
} // namespace LtsUtils
@@ -13,15 +13,24 @@
namespace LtsUtils
{
class QPoint3D
{
class QPoint3D
{
public:
enum class Axis { X, Y, Z };
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())
template <typename T>
explicit QPoint3D(const T &data)
: xp(data.offsetX())
, yp(data.offsetY())
, zp(data.offsetZ())
{
}
@@ -34,275 +43,244 @@ class QPoint3D
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 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);
}
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 lengthSquared() const { return (xp * xp) + (yp * yp) + (zp * zp); }
inline double length() const
{
return std::sqrt(lengthSquared());
}
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;
double len = xp * xp + yp * yp + zp * zp;
if (qFuzzyIsNull(len - 1.0f) || qFuzzyIsNull(len))
return;
len = std::sqrt(len);
len = std::sqrt(len);
xp /= len;
yp /= len;
zp /= 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);
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)
inline void rotate(const double &phi, const Axis &axis)
{
const double sin = std::sin(phi);
const double cos = std::cos(phi);
switch (axis)
const double sin = std::sin(phi);
const double cos = std::cos(phi);
switch (axis)
{
case Axis::X:
{
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;
}
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
inline QPoint3D rotated(const double &phi, const Axis &axis) const
{
QPoint3D p(*this);
p.rotate(phi, axis);
return p;
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
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;
}
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)
constexpr inline QPoint3D &operator-=(const QPoint3D &o)
{
return QPoint3D(p1.xp + p2.xp, p1.yp + p2.yp, p1.zp + p2.zp);
xp -= o.xp;
yp -= o.yp;
zp -= o.zp;
return *this;
}
friend constexpr inline QPoint3D operator-(const QPoint3D& p1, const QPoint3D& p2)
constexpr inline QPoint3D &operator*=(double factor)
{
return QPoint3D(p1.xp - p2.xp, p1.yp - p2.yp, p1.zp - p2.zp);
xp *= factor;
yp *= factor;
zp *= factor;
return *this;
}
friend constexpr inline QPoint3D operator*(const QPoint3D& p1, double factor)
constexpr inline QPoint3D &operator/=(double divisor)
{
return QPoint3D(p1.xp * factor, p1.yp * factor, p1.zp * factor);
xp /= divisor;
yp /= divisor;
zp /= divisor;
return *this;
}
friend constexpr inline QPoint3D operator*(double factor, const QPoint3D& p1)
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(p1.xp * factor, p1.yp * factor, p1.zp * factor);
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);
}
friend constexpr inline QPoint3D operator/(const QPoint3D& p1, double factor)
{
return QPoint3D(p1.xp / factor, p1.yp / factor, p1.zp / factor);
}
static inline QPoint3D normal(const QPoint3D &v1, const QPoint3D &v2) { return crossProduct(v1, v2).normalized(); }
constexpr inline QPoint3D& operator+=(const QPoint3D& o)
{
xp += o.xp;
yp += o.yp;
zp += o.zp;
return *this;
}
static inline QPoint3D normal(const QPoint3D &v1, const QPoint3D &v2, const QPoint3D &v3) { return crossProduct((v2 - v1), (v3 - v1)).normalized(); }
constexpr inline QPoint3D& operator-=(const QPoint3D& o)
friend inline bool qFuzzyCompare(const QPoint3D &v1, const QPoint3D &v2)
{
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);
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);
// 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) {}
constexpr inline QPoint3D::QPoint3D(double xpos, double ypos, double zpos)
: xp(xpos)
, yp(ypos)
, zp(zpos)
{
}
inline bool QPoint3D::isNull() const
{
inline bool QPoint3D::isNull() const
{
return qIsNull(xp) && qIsNull(yp) && qIsNull(zp);
}
}
constexpr inline double QPoint3D::x() const
{
constexpr inline double QPoint3D::x() const
{
return xp;
}
}
constexpr inline double QPoint3D::y() const
{
constexpr inline double QPoint3D::y() const
{
return yp;
}
}
constexpr inline double QPoint3D::z() const
{
constexpr inline double QPoint3D::z() const
{
return zp;
}
}
constexpr inline void QPoint3D::setX(double xpos)
{
constexpr inline void QPoint3D::setX(double xpos)
{
xp = xpos;
}
}
constexpr inline void QPoint3D::setY(double ypos)
{
constexpr inline void QPoint3D::setY(double ypos)
{
yp = ypos;
}
}
constexpr inline void QPoint3D::setZ(double zpos)
{
constexpr inline void QPoint3D::setZ(double zpos)
{
zp = zpos;
}
}
constexpr inline double& QPoint3D::rx()
{
constexpr inline double &QPoint3D::rx()
{
return xp;
}
}
constexpr inline double& QPoint3D::ry()
{
constexpr inline double &QPoint3D::ry()
{
return yp;
}
}
constexpr inline double& QPoint3D::rz()
{
constexpr inline double &QPoint3D::rz()
{
return zp;
}
}
constexpr inline QPointF QPoint3D::toPointF() const
{
constexpr inline QPointF QPoint3D::toPointF() const
{
return QPointF(xp, yp);
}
}
constexpr inline bool operator==(const QPoint3D& p1, const QPoint3D& p2)
{
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)
{
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)
{
inline std::ostream &operator<<(std::ostream &stream, const QPoint3D &pos)
{
stream << "(" << pos.x() << "," << pos.y() << "," << pos.z() << ")";
return stream;
}
}
} // namespace LtsUtils
@@ -7,15 +7,16 @@
namespace LtsUtils
{
ScopedConnection::ScopedConnection(IConnection* connection, Qt::ConnectionType connType) : m_conn(connection)
{
ScopedConnection::ScopedConnection(IConnection *connection, Qt::ConnectionType connType)
: m_conn(connection)
{
Q_ASSERT(connection);
m_conn->connect(connType);
}
}
ScopedConnection::~ScopedConnection()
{
ScopedConnection::~ScopedConnection()
{
m_conn->disconnect();
}
}
} // namespace LtsUtils
@@ -9,16 +9,16 @@
namespace LtsUtils
{
class IConnection;
class IConnection;
class LTSUTILSCORE_EXPORT ScopedConnection
{
class LTSUTILSCORE_EXPORT ScopedConnection
{
public:
explicit ScopedConnection(IConnection* connection, Qt::ConnectionType = Qt::AutoConnection);
explicit ScopedConnection(IConnection *connection, Qt::ConnectionType = Qt::AutoConnection);
~ScopedConnection();
private:
IConnection* m_conn;
};
IConnection *m_conn;
};
} // namespace LtsUtils
@@ -5,24 +5,24 @@
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 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 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 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)
{
static SfmMessage getSfmMessage(const QByteArray &p_data)
{
unsigned short id = 0;
id |= (((unsigned short)p_data[0]) & 0x7F) << 8;
@@ -34,10 +34,10 @@ static SfmMessage getSfmMessage(const QByteArray& p_data)
msg.setPayload(p_data.right(p_data.size() - HEADER_SIZE));
return msg;
}
}
static QByteArray getHeader(const SfmMessage& p_msg)
{
static QByteArray getHeader(const SfmMessage &p_msg)
{
QByteArray header(2, Qt::Uninitialized);
header[0] = ((p_msg.id() >> 8) & 0x7f) | (p_msg.rtr() << 7);
@@ -45,184 +45,184 @@ static QByteArray getHeader(const SfmMessage& p_msg)
header[1] = (p_msg.id() >> 0) & 0xff;
return header;
}
}
static inline char getChecksum(const QByteArray& p_data)
{
static inline char getChecksum(const QByteArray &p_data)
{
char sum = 0;
for (const char c : p_data)
sum += c;
sum += c;
return sum ^ 0xff;
}
}
static QByteArray removeChecksum(const QByteArray& p_data)
{
static QByteArray removeChecksum(const QByteArray &p_data)
{
QByteArray withoutChecksum(p_data);
ConversionError error("Checksum error");
if (p_data.size() >= CHECKSUM_SIZE)
{
withoutChecksum.chop(1);
withoutChecksum.chop(1);
if (p_data.at(p_data.size() - 1) != getChecksum(withoutChecksum))
throw error;
if (p_data.at(p_data.size() - 1) != getChecksum(withoutChecksum))
throw error;
}
else
throw error;
throw error;
return withoutChecksum;
}
}
static QByteArray maskData(const QByteArray& p_data)
{
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;
}
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)
{
static bool mustBeMasked(const unsigned char byte)
{
switch (byte)
{
case XON:
case XOFF:
case STX:
case ETX:
case SUBST:
return true;
default:
break;
case XON:
case XOFF:
case STX:
case ETX:
case SUBST:
return true;
default:
break;
}
return false;
}
}
int lenMaskedData(const QByteArray& data)
{
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;
++ret;
if (mustBeMasked(lowerLen))
++ret;
++ret;
for (const unsigned char byte : data)
{
if (mustBeMasked(byte))
++ret;
if (mustBeMasked(byte))
++ret;
}
if (mustBeMasked(getChecksum(data)))
++ret;
++ret;
return ret;
}
}
static QByteArray unmaskData(const QByteArray& p_data)
{
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);
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;
}
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);
}
else
unmaskData.append(byte);
}
return unmaskData;
}
}
static QByteArray addFrame(const QByteArray& p_data)
{
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)
{
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);
return p_data.mid(1, p_data.size() - 2);
}
else
throw ConversionError("Framing Error");
}
throw ConversionError("Framing Error");
}
static void checkLength(const QByteArray& p_data)
{
static void checkLength(const QByteArray &p_data)
{
if (p_data.size() < HEADER_SIZE)
throw ConversionError("Telegram too short");
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");
}
throw ConversionError("Telegram length does not match");
}
QByteArray byteStreamFromSfmMessage(const SfmMessage& message)
{
QByteArray byteStreamFromSfmMessage(const SfmMessage &message)
{
QByteArray byteData(getHeader(message));
byteData.append(message.payload().size());
@@ -230,12 +230,12 @@ QByteArray byteStreamFromSfmMessage(const SfmMessage& message)
byteData.append(getChecksum(byteData));
return addFrame(maskData(byteData));
}
}
SfmMessage byteStreamToSfmMessage(const QByteArray& datastream)
{
SfmMessage byteStreamToSfmMessage(const QByteArray &datastream)
{
if (datastream.size() < MINIMUM_BYTE_SIZE)
throw ConversionError("Can't convert an QByteArray that hasn't the minimum size!");
throw ConversionError("Can't convert an QByteArray that hasn't the minimum size!");
QByteArray checkMsg;
@@ -247,29 +247,29 @@ SfmMessage byteStreamToSfmMessage(const QByteArray& datastream)
checkLength(checkMsg);
return getSfmMessage(checkMsg);
}
}
QByteArray byteStreamFromEscMessage(const QByteArray& message)
{
QByteArray byteStreamFromEscMessage(const QByteArray &message)
{
QByteArray byteData = message;
if (message.size() == 1)
{
byteData.append(message);
byteData.append(message);
}
else
byteData.append(getChecksum(byteData));
byteData.append(getChecksum(byteData));
byteData = maskData(byteData);
byteData = addFrame(byteData);
return byteData;
}
}
QByteArray byteStreamToEscMessage(const QByteArray& datastream)
{
QByteArray byteStreamToEscMessage(const QByteArray &datastream)
{
if (datastream.size() < 2)
return QByteArray("ERROR");
return QByteArray("ERROR");
QByteArray checkMsg;
@@ -278,6 +278,6 @@ QByteArray byteStreamToEscMessage(const QByteArray& datastream)
checkMsg.chop(1);
return checkMsg;
}
}
} // namespace LtsUtils
@@ -9,64 +9,43 @@
namespace LtsUtils
{
class LTSUTILSCORE_EXPORT SfmMessage
{
class LTSUTILSCORE_EXPORT SfmMessage
{
public:
unsigned int id() const
{
return m_id;
}
unsigned int id() const { return m_id; }
void setId(unsigned int id)
{
m_id = id;
}
void setId(unsigned int id) { m_id = id; }
bool rtr() const
{
return m_rtr;
}
bool rtr() const { return m_rtr; }
void setRtr(bool rtr)
{
m_rtr = rtr;
}
void setRtr(bool rtr) { m_rtr = rtr; }
QByteArray payload() const
{
return m_payload;
}
QByteArray payload() const { return m_payload; }
void setPayload(const QByteArray& payload)
{
m_payload = 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());
}
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
{
class ConversionError : public std::runtime_error
{
public:
using std::runtime_error::runtime_error;
};
};
LTSUTILSCORE_EXPORT QByteArray byteStreamFromSfmMessage(const SfmMessage& message);
LTSUTILSCORE_EXPORT QByteArray byteStreamFromSfmMessage(const SfmMessage &message);
LTSUTILSCORE_EXPORT SfmMessage byteStreamToSfmMessage(const QByteArray& datastream);
LTSUTILSCORE_EXPORT SfmMessage byteStreamToSfmMessage(const QByteArray &datastream);
LTSUTILSCORE_EXPORT QByteArray byteStreamFromEscMessage(const QByteArray& message);
LTSUTILSCORE_EXPORT QByteArray byteStreamFromEscMessage(const QByteArray &message);
LTSUTILSCORE_EXPORT QByteArray byteStreamToEscMessage(const QByteArray& datastream);
LTSUTILSCORE_EXPORT QByteArray byteStreamToEscMessage(const QByteArray &datastream);
LTSUTILSCORE_EXPORT int lenMaskedData(const QByteArray& data);
LTSUTILSCORE_EXPORT int lenMaskedData(const QByteArray &data);
} // namespace LtsUtils
@@ -7,31 +7,31 @@
namespace LtsUtils
{
inline bool lessThan(const QVariant& var1, const QVariant& var2)
{
inline bool lessThan(const QVariant &var1, const QVariant &var2)
{
if (var1.canConvert<QString>() && var2.canConvert<QString>())
{
QString str1(var1.toString());
QString str2(var2.toString());
QString str1(var1.toString());
QString str2(var2.toString());
bool k1 = false;
double d1 = str1.toDouble(&k1);
bool k1 = false;
double d1 = str1.toDouble(&k1);
if (!k1)
return str1 < str2;
if (!k1)
return str1 < str2;
bool k2 = false;
double d2 = str2.toDouble(&k2);
bool k2 = false;
double d2 = str2.toDouble(&k2);
if (!k2)
return str1 < str2;
if (!k2)
return str1 < str2;
return d1 < d2;
return d1 < d2;
}
else if (var1.canConvert<double>() && var2.canConvert<double>())
return var1.toDouble() < var2.toDouble();
return var1.toDouble() < var2.toDouble();
return false;
}
}
} // namespace LtsUtils
@@ -8,52 +8,58 @@
namespace LtsUtils
{
int ConnectingDialog::s_waitForHistoricalDataWaitTime = 10000;
int ConnectingDialog::s_waitForHistoricalDataWaitTime = 10000;
void ConnectingDialog::reset()
{
m_ui->label->setText(QStringLiteral("<font color='orange'>%1</font>")
.arg(tr("Connecting to %1 on %2 ...").arg(m_serviceName, m_exerciseName)));
}
void ConnectingDialog::reset()
{
m_ui->label->setText(QStringLiteral("<font color='orange'>%1</font>").arg(tr("Connecting to %1 on %2 ...").arg(m_serviceName, m_exerciseName)));
}
void ConnectingDialog::setup()
{
void ConnectingDialog::setup()
{
m_ui = new Ui::ConnectingDialog;
m_ui->setupUi(this);
reset();
setMinimumSize(sizeHint());
connect(m_ui->pbRetry, &QPushButton::clicked, this, [this]() {
m_ui->pbRetry->setEnabled(false);
m_ui->pbIgnore->setEnabled(false);
connect(m_ui->pbRetry,
&QPushButton::clicked,
this,
[this]()
{
m_ui->pbRetry->setEnabled(false);
m_ui->pbIgnore->setEnabled(false);
reset();
emit signalStopLoop();
});
reset();
emit signalStopLoop();
});
connect(m_ui->pbIgnore, &QPushButton::clicked, this, [this]() {
m_ui->pbIgnore->setEnabled(false);
m_ui->pbRetry->setEnabled(false);
m_ui->pbIgnore->setText(tr("continuing.."));
connect(m_ui->pbIgnore,
&QPushButton::clicked,
this,
[this]()
{
m_ui->pbIgnore->setEnabled(false);
m_ui->pbRetry->setEnabled(false);
m_ui->pbIgnore->setText(tr("continuing.."));
deleteLater();
return;
});
}
deleteLater();
return;
});
}
ConnectingDialog::~ConnectingDialog()
{
ConnectingDialog::~ConnectingDialog()
{
delete m_ui;
}
}
void ConnectingDialog::failed()
{
m_ui->label->setText(QStringLiteral("<font color='red'>%1</font>")
.arg(tr("Could not connect to %1 on %2 !").arg(m_serviceName, m_exerciseName)));
void ConnectingDialog::failed()
{
m_ui->label->setText(QStringLiteral("<font color='red'>%1</font>").arg(tr("Could not connect to %1 on %2 !").arg(m_serviceName, m_exerciseName)));
m_ui->pbRetry->setEnabled(true);
m_ui->pbIgnore->setEnabled(true);
raise();
}
}
} // namespace LtsUtils
@@ -11,47 +11,52 @@
namespace Ui
{
class ConnectingDialog;
class ConnectingDialog;
}
namespace LtsUtils
{
class LTSUTILSGUICONNECTDIALOG_EXPORT ConnectingDialog : public LtsWidgets::LtsFramelessDialog
{
class LTSUTILSGUICONNECTDIALOG_EXPORT ConnectingDialog : public LtsWidgets::LtsFramelessDialog
{
Q_OBJECT
public:
static int s_waitForHistoricalDataWaitTime;
template <typename DtcType, typename WaitForHistoricalDataFunction>
explicit ConnectingDialog(DtcType dtc, WaitForHistoricalDataFunction waitForHistoricalDataFunction,
const QString& serviceName, const QString& exerciseName, QWidget* parent = nullptr)
: LtsWidgets::LtsFramelessDialog(parent, LtsWidgets::Behaviour::Modal), m_serviceName(serviceName),
m_exerciseName(exerciseName), m_ui(nullptr)
explicit ConnectingDialog(DtcType dtc,
WaitForHistoricalDataFunction waitForHistoricalDataFunction,
const QString &serviceName,
const QString &exerciseName,
QWidget *parent = nullptr)
: LtsWidgets::LtsFramelessDialog(parent, LtsWidgets::Behaviour::Modal)
, m_serviceName(serviceName)
, m_exerciseName(exerciseName)
, m_ui(nullptr)
{
setWindowTitle(tr("Connecting .."));
setup();
show();
setWindowTitle(tr("Connecting .."));
setup();
show();
while (true)
while (true)
{
if ((dtc.get()->*waitForHistoricalDataFunction)(s_waitForHistoricalDataWaitTime))
{
if ((dtc.get()->*waitForHistoricalDataFunction)(s_waitForHistoricalDataWaitTime))
{
deleteLater();
return;
}
if (s_waitForHistoricalDataWaitTime >= 999999)
{
deleteLater();
return;
}
else
{
failed();
}
deleteLater();
return;
}
if (s_waitForHistoricalDataWaitTime >= 999999)
{
deleteLater();
return;
}
else
{
failed();
}
}
}
~ConnectingDialog();
@@ -61,13 +66,13 @@ class LTSUTILSGUICONNECTDIALOG_EXPORT ConnectingDialog : public LtsWidgets::LtsF
private:
QString m_serviceName;
QString m_exerciseName;
Ui::ConnectingDialog* m_ui;
Ui::ConnectingDialog *m_ui;
void reset();
void setup();
signals:
void signalStopLoop();
};
};
} // namespace LtsUtils
@@ -12,39 +12,50 @@
namespace LtsUtils
{
ConnectingDialogNT::ConnectingDialogNT(const std::function<bool(int)>& checkFn, const QString& serviceName,
const QString& exerciseName, QWidget* parent)
: LtsWidgets::LtsFramelessDialog(parent, LtsWidgets::Behaviour::Modal), m_serviceName(serviceName),
m_exerciseName(exerciseName), m_checkFn(checkFn), m_go(false), m_autoRetryTimer(new QTimer(this)),
m_ui(new Ui::ConnectingDialog)
{
ConnectingDialogNT::ConnectingDialogNT(const std::function<bool(int)> &checkFn, const QString &serviceName, const QString &exerciseName, QWidget *parent)
: LtsWidgets::LtsFramelessDialog(parent, LtsWidgets::Behaviour::Modal)
, m_serviceName(serviceName)
, m_exerciseName(exerciseName)
, m_checkFn(checkFn)
, m_go(false)
, m_autoRetryTimer(new QTimer(this))
, m_ui(new Ui::ConnectingDialog)
{
m_ui->setupUi(this);
m_autoRetryTimer->setInterval(1000);
connect(m_autoRetryTimer, &QTimer::timeout, this, [this]() {
if (m_autoRetryTick < 1)
{
slotRetry();
return;
}
connect(m_autoRetryTimer,
&QTimer::timeout,
this,
[this]()
{
if (m_autoRetryTick < 1)
{
slotRetry();
return;
}
m_ui->pbRetry->setText(QStringLiteral("%1 [%2]").arg(tr("Retry")).arg(m_autoRetryTick));
m_autoRetryTick--;
});
m_ui->pbRetry->setText(QStringLiteral("%1 [%2]").arg(tr("Retry")).arg(m_autoRetryTick));
m_autoRetryTick--;
});
reset();
setMinimumSize(sizeHint());
connect(m_ui->pbRetry, &QPushButton::clicked, this, &ConnectingDialogNT::slotRetry);
connect(m_ui->pbIgnore, &QPushButton::clicked, this, [this]() {
m_ui->pbIgnore->setEnabled(false);
m_ui->pbRetry->setEnabled(false);
m_ui->pbIgnore->setText(tr("continuing.."));
connect(m_ui->pbIgnore,
&QPushButton::clicked,
this,
[this]()
{
m_ui->pbIgnore->setEnabled(false);
m_ui->pbRetry->setEnabled(false);
m_ui->pbIgnore->setText(tr("continuing.."));
emit signalFailed();
deleteLater();
return;
});
emit signalFailed();
deleteLater();
return;
});
show();
@@ -52,32 +63,32 @@ ConnectingDialogNT::ConnectingDialogNT(const std::function<bool(int)>& checkFn,
m_go = true;
m_ui->pbRetry->setEnabled(false);
}
}
int ConnectingDialogNT::random(int min, int max)
{
int ConnectingDialogNT::random(int min, int max)
{
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
return QRandomGenerator::global()->bounded(min, max);
#else
return (qrand() % (((max + 1) - min) + min));
#endif
}
}
bool ConnectingDialogNT::event(QEvent* event)
{
bool ConnectingDialogNT::event(QEvent *event)
{
bool result = LtsWidgets::LtsFramelessDialog::event(event);
if (event->type() == QEvent::Paint && m_go)
{
m_go = false;
QTimer::singleShot(0, this, &ConnectingDialogNT::signalGo);
m_go = false;
QTimer::singleShot(0, this, &ConnectingDialogNT::signalGo);
}
return result;
}
}
void ConnectingDialogNT::slotRetry()
{
void ConnectingDialogNT::slotRetry()
{
m_autoRetryTimer->stop();
m_ui->pbRetry->setText(tr("Retry"));
@@ -86,36 +97,34 @@ void ConnectingDialogNT::slotRetry()
reset();
QTimer::singleShot(1, this, &ConnectingDialogNT::slotGo);
}
}
void ConnectingDialogNT::slotGo()
{
void ConnectingDialogNT::slotGo()
{
if (m_checkFn(ConnectingDialog::s_waitForHistoricalDataWaitTime))
{
emit signalSuccess();
deleteLater();
return;
emit signalSuccess();
deleteLater();
return;
}
failed();
}
}
void ConnectingDialogNT::reset()
{
m_ui->label->setText(QStringLiteral("<font color='orange'>%1</font>")
.arg(tr("Connecting to %1 on %2 ...").arg(m_serviceName, m_exerciseName)));
}
void ConnectingDialogNT::reset()
{
m_ui->label->setText(QStringLiteral("<font color='orange'>%1</font>").arg(tr("Connecting to %1 on %2 ...").arg(m_serviceName, m_exerciseName)));
}
ConnectingDialogNT::~ConnectingDialogNT()
{
ConnectingDialogNT::~ConnectingDialogNT()
{
delete m_ui;
}
}
void ConnectingDialogNT::failed()
{
m_ui->label->setText(QStringLiteral("<font color='red'>%1</font>")
.arg(tr("Could not connect to %1 on %2 !").arg(m_serviceName, m_exerciseName)));
void ConnectingDialogNT::failed()
{
m_ui->label->setText(QStringLiteral("<font color='red'>%1</font>").arg(tr("Could not connect to %1 on %2 !").arg(m_serviceName, m_exerciseName)));
m_ui->pbRetry->setEnabled(true);
m_ui->pbIgnore->setEnabled(true);
@@ -124,6 +133,6 @@ void ConnectingDialogNT::failed()
m_autoRetryTimer->start();
raise();
}
}
} // namespace LtsUtils
@@ -11,19 +11,18 @@ class QTimer;
namespace Ui
{
class ConnectingDialog;
class ConnectingDialog;
}
namespace LtsUtils
{
class LTSUTILSGUICONNECTDIALOG_EXPORT ConnectingDialogNT : public LtsWidgets::LtsFramelessDialog
{
class LTSUTILSGUICONNECTDIALOG_EXPORT ConnectingDialogNT : public LtsWidgets::LtsFramelessDialog
{
Q_OBJECT
public:
explicit ConnectingDialogNT(const std::function<bool(int)>& checkFn, const QString& serviceName,
const QString& exerciseName, QWidget* parent);
explicit ConnectingDialogNT(const std::function<bool(int)> &checkFn, const QString &serviceName, const QString &exerciseName, QWidget *parent);
~ConnectingDialogNT();
void failed();
@@ -43,14 +42,14 @@ class LTSUTILSGUICONNECTDIALOG_EXPORT ConnectingDialogNT : public LtsWidgets::Lt
std::function<bool(int)> m_checkFn;
bool m_go;
QTimer* m_autoRetryTimer;
QTimer *m_autoRetryTimer;
int m_autoRetryTick{0};
Ui::ConnectingDialog* m_ui;
Ui::ConnectingDialog *m_ui;
int random(int min, int max);
bool event(QEvent* event) override;
bool event(QEvent *event) override;
void reset();
};
};
} // namespace LtsUtils
@@ -45,9 +45,6 @@ if(QT6_GUI_AVAILABLE)
Qt6::Svg
)
endif()
IF(BUILD_RTI)
TARGET_LINK_LIBRARIES(LtsUtilsGuiDds PUBLIC ddscore)
ENDIF(BUILD_RTI)
NGL_TARGET_COMPILE_DEFINITIONS(LtsUtilsGuiDds
PUBLIC
REQUEST_HELPER_WITH_GUI
@@ -66,6 +63,3 @@ NGL_TARGET_LINK_LIBRARIES(LtsUtilsDds
PUBLIC
Qt6::Core
)
IF(BUILD_RTI)
TARGET_LINK_LIBRARIES(LtsUtilsDds PUBLIC ddscore)
ENDIF(BUILD_RTI)
@@ -13,8 +13,8 @@
namespace LtsUtils
{
QIcon iconFromSvg(const QByteArray& svgData, QSize iconSize)
{
QIcon iconFromSvg(const QByteArray &svgData, QSize iconSize)
{
QSvgRenderer renderer(svgData);
QPixmap p(iconSize);
p.fill(Qt::transparent);
@@ -23,60 +23,60 @@ QIcon iconFromSvg(const QByteArray& svgData, QSize iconSize)
painter.end();
return {p};
}
}
QIcon iconFromSvg(const QString& svgFilename, QSize iconSize)
{
QIcon iconFromSvg(const QString &svgFilename, QSize iconSize)
{
QFile f(svgFilename);
if (!f.open(QIODevice::ReadOnly))
return {};
return {};
return iconFromSvg(f.readAll(), iconSize);
}
}
QPixmap pixmapFromIcon(const QIcon& icon, QSize iconSize)
{
QPixmap pixmapFromIcon(const QIcon &icon, QSize iconSize)
{
return icon.pixmap(iconSize).scaled(100, 100, Qt::AspectRatioMode::IgnoreAspectRatio);
}
}
QPixmap pixmapFromSvg(const QString& svgFilename, QSize iconSize)
{
QPixmap pixmapFromSvg(const QString &svgFilename, QSize iconSize)
{
return pixmapFromIcon(iconFromSvg(svgFilename, iconSize), iconSize);
}
}
QPixmap getPixmap(const std::vector<uint8_t>& data)
{
QPixmap getPixmap(const std::vector<uint8_t> &data)
{
if (data.size() == 0)
return QPixmap();
return QPixmap();
return getPixmap(QByteArray(reinterpret_cast<const char*>(&data.at(0)), data.size()));
}
return getPixmap(QByteArray(reinterpret_cast<const char *>(&data.at(0)), data.size()));
}
QPixmap getPixmap(const QByteArray& data)
{
QPixmap getPixmap(const QByteArray &data)
{
return QPixmap::fromImage(QImage::fromData(data));
}
}
QImage getImage(const std::vector<uint8_t>& data)
{
QImage getImage(const std::vector<uint8_t> &data)
{
if (data.size() == 0)
return QImage();
return QImage();
return getImage(QByteArray(reinterpret_cast<const char*>(&data.at(0)), data.size()));
}
return getImage(QByteArray(reinterpret_cast<const char *>(&data.at(0)), data.size()));
}
QImage getImage(const QByteArray& data)
{
QImage getImage(const QByteArray &data)
{
return QImage::fromData(data);
}
}
static inline void setIf(bool* boolPtr, bool val)
{
static inline void setIf(bool *boolPtr, bool val)
{
if (boolPtr)
*boolPtr = val;
}
*boolPtr = val;
}
std::vector<uint8_t> fromPixmap(const QPixmap& pixmap, bool* bIsPng)
{
std::vector<uint8_t> fromPixmap(const QPixmap &pixmap, bool *bIsPng)
{
QBuffer buf;
buf.open(QIODevice::WriteOnly);
pixmap.save(&buf, "PNG");
@@ -87,22 +87,22 @@ std::vector<uint8_t> fromPixmap(const QPixmap& pixmap, bool* bIsPng)
if (ba.size() > 10240 && !pixmap.hasAlpha() && !pixmap.hasAlphaChannel())
{
QBuffer buf2;
buf2.open(QIODevice::WriteOnly);
pixmap.save(&buf2, "JPG");
buf2.close();
if (buf2.buffer().size() < buf.buffer().size())
{
setIf(bIsPng, false);
ba = buf2.buffer();
}
QBuffer buf2;
buf2.open(QIODevice::WriteOnly);
pixmap.save(&buf2, "JPG");
buf2.close();
if (buf2.buffer().size() < buf.buffer().size())
{
setIf(bIsPng, false);
ba = buf2.buffer();
}
}
return convert<std::vector<uint8_t>>(ba);
}
}
std::vector<uint8_t> fromImage(const QImage& image, bool* bIsPng)
{
std::vector<uint8_t> fromImage(const QImage &image, bool *bIsPng)
{
QBuffer buf;
buf.open(QIODevice::WriteOnly);
image.save(&buf, "PNG");
@@ -112,18 +112,18 @@ std::vector<uint8_t> fromImage(const QImage& image, bool* bIsPng)
setIf(bIsPng, true);
if ((ba.size() > 10240 && !image.hasAlphaChannel()) || ba.size() > 1024 * 1024)
{
QBuffer buf2;
buf2.open(QIODevice::WriteOnly);
image.save(&buf2, "JPG");
buf2.close();
if (buf2.buffer().size() < buf.buffer().size())
{
setIf(bIsPng, false);
ba = buf2.buffer();
}
QBuffer buf2;
buf2.open(QIODevice::WriteOnly);
image.save(&buf2, "JPG");
buf2.close();
if (buf2.buffer().size() < buf.buffer().size())
{
setIf(bIsPng, false);
ba = buf2.buffer();
}
}
return convert<std::vector<uint8_t>>(ba);
}
}
} // namespace LtsUtils
@@ -17,15 +17,15 @@ class QIcon;
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 QIcon iconFromSvg(const QByteArray& svgData, QSize iconSize = QSize(100, 100));
LTSUTILSCORE_EXPORT QIcon iconFromSvg(const QString& svgFilename, QSize iconSize = QSize(100, 100));
LTSUTILSCORE_EXPORT QPixmap pixmapFromIcon(const QIcon& icon, QSize iconSize = QSize(100, 100));
LTSUTILSCORE_EXPORT QPixmap pixmapFromSvg(const QString& svgFilename, QSize iconSize = QSize(100, 100));
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);
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 QIcon iconFromSvg(const QByteArray &svgData, QSize iconSize = QSize(100, 100));
LTSUTILSCORE_EXPORT QIcon iconFromSvg(const QString &svgFilename, QSize iconSize = QSize(100, 100));
LTSUTILSCORE_EXPORT QPixmap pixmapFromIcon(const QIcon &icon, QSize iconSize = QSize(100, 100));
LTSUTILSCORE_EXPORT QPixmap pixmapFromSvg(const QString &svgFilename, QSize iconSize = QSize(100, 100));
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
@@ -9,4 +9,4 @@
#define LTSUTILSGUIDDS_EXPORT
#define LTSUTILSGUIDDS_NO_EXPORT
#endif // LTSUTILSDDS_EXPORT_H
#endif // LTSUTILSDDS_EXPORT_H
@@ -18,72 +18,76 @@
namespace LtsUtils
{
bool RequestHelper::s_debug = false;
bool RequestHelper::s_debug = false;
RequestHelper::RequestHelper(QObject* parent, bool quiet,
RequestHelper::RequestHelper(QObject *parent,
bool quiet,
const std::function<void(void)>& success, const std::function<void(void)>& failure)
: QObject(parent), m_failed(false), m_repliedId(-1), m_quiet(quiet), m_blockingCall(true), m_successFn(success),
m_failureFn(failure)
{
const std::function<void(void)> &success,
const std::function<void(void)> &failure)
: QObject(parent)
, m_failed(false)
, m_repliedId(-1)
, m_quiet(quiet)
, m_blockingCall(true)
, m_successFn(success)
, m_failureFn(failure)
{
connect(this, &RequestHelper::signalSuccess, this, m_successFn, Qt::QueuedConnection);
connect(this, &RequestHelper::signalFailed, this, m_failureFn, Qt::QueuedConnection);
if (s_debug)
{
QTimer* t = new QTimer(this);
t->setInterval(2000);
t->setSingleShot(true);
connect(this, &RequestHelper::signalNextRequest, t, static_cast<void (QTimer::*)(void)>(&QTimer::start));
connect(t, &QTimer::timeout, this, &RequestHelper::slotNextRequest, Qt::QueuedConnection);
QTimer *t = new QTimer(this);
t->setInterval(2000);
t->setSingleShot(true);
connect(this, &RequestHelper::signalNextRequest, t, static_cast<void (QTimer::*)(void)>(&QTimer::start));
connect(t, &QTimer::timeout, this, &RequestHelper::slotNextRequest, Qt::QueuedConnection);
}
else
{
connect(this, &RequestHelper::signalNextRequest, this, &RequestHelper::slotNextRequest, Qt::QueuedConnection
connect(this, &RequestHelper::signalNextRequest, this, &RequestHelper::slotNextRequest, Qt::QueuedConnection
);
);
}
}
}
void RequestHelper::addRequest(const std::function<int64_t()>& requestFunction,
const std::function<void(const Core::FunctionReply& baseReply)>& baseReplyHandler)
{
void RequestHelper::addRequest(const std::function<int64_t()> &requestFunction, const std::function<void(const Core::FunctionReply &baseReply)> &baseReplyHandler)
{
m_requestFunctions.append(RequestFunctionContainer(requestFunction, baseReplyHandler));
}
}
bool RequestHelper::requestReply(const Core::FunctionReply& baseReply)
{
bool RequestHelper::requestReply(const Core::FunctionReply &baseReply)
{
// rtiddsgen 7.7 generates plain public members (no getters/setters)
const Core::FunctionReplyObject fro(baseReply.id, baseReply.errorString, baseReply.errorParams);
return _requestReply(fro, &baseReply);
}
}
bool RequestHelper::requestReply(const Core::FunctionReplyObject& replyObject)
{
bool RequestHelper::requestReply(const Core::FunctionReplyObject &replyObject)
{
return _requestReply(replyObject, nullptr);
}
}
bool RequestHelper::_requestReply(const Core::FunctionReplyObject& fro, const Core::FunctionReply* baseReply)
{
bool RequestHelper::_requestReply(const Core::FunctionReplyObject &fro, const Core::FunctionReply *baseReply)
{
m_errorString = fro.translated();
#ifdef REQUEST_HELPER_WITH_GUI
if (fro.error())
{
if (!m_quiet)
if (!m_quiet)
{
if (m_blockingCall)
{
if (m_blockingCall)
{
LtsWidgets::LtsMessageDialog::showMessage(qobject_cast<QWidget*>(parent()), m_errorString,
tr("Request failed"));
}
else
{
new LtsWidgets::LtsMessageDialogNew(qobject_cast<QWidget*>(parent()), m_errorString,
tr("Request failed"));
}
LtsWidgets::LtsMessageDialog::showMessage(qobject_cast<QWidget *>(parent()), m_errorString, tr("Request failed"));
}
else
{
new LtsWidgets::LtsMessageDialogNew(qobject_cast<QWidget *>(parent()), m_errorString, tr("Request failed"));
}
}
}
#endif
@@ -91,67 +95,65 @@ bool RequestHelper::_requestReply(const Core::FunctionReplyObject& fro, const Co
if (m_singleRequestCustomFunctionReply != nullptr)
{
if (baseReply)
m_singleRequestCustomFunctionReply(*baseReply);
else
m_singleRequestCustomFunctionReply(
Core::FunctionReply(fro.id(), fro.str(), fro.args(), fro.additionalInfo()));
if (baseReply)
m_singleRequestCustomFunctionReply(*baseReply);
else
m_singleRequestCustomFunctionReply(Core::FunctionReply(fro.id(), fro.str(), fro.args(), fro.additionalInfo()));
}
if (fro.error())
{
failure();
return false;
failure();
return false;
}
emit signalNextRequest();
return true;
}
}
bool RequestHelper::startSingleRequest(
const std::function<int64_t()>& requestFunction,
const std::function<void(const Core::FunctionReply& baseReply)>& baseReplyHandler)
{
bool RequestHelper::startSingleRequest(const std::function<int64_t()> &requestFunction,
const std::function<void(const Core::FunctionReply &baseReply)> &baseReplyHandler)
{
addRequest(requestFunction, baseReplyHandler);
return startRequests();
}
}
void RequestHelper::failure()
{
void RequestHelper::failure()
{
m_failed = true;
emit signalFailed();
done();
}
}
void RequestHelper::done()
{
void RequestHelper::done()
{
#ifdef REQUEST_HELPER_WITH_GUI
if (!m_quiet)
LtsWidgets::LtsGlobalWaitDialog::getInstance()->done();
LtsWidgets::LtsGlobalWaitDialog::getInstance()->done();
#endif
m_requestFunctions.clear();
m_singleRequestCustomFunctionReply = nullptr;
if (m_blockingCall)
emit signalQuitLoop();
emit signalQuitLoop();
m_blockingCall = true;
if (!m_blockingCall)
deleteLater();
}
deleteLater();
}
void RequestHelper::slotNextRequest()
{
void RequestHelper::slotNextRequest()
{
if (m_requestFunctions.isEmpty())
{
if (!m_blockingCall)
emit signalSuccess();
if (!m_blockingCall)
emit signalSuccess();
done();
done();
return;
return;
}
const RequestFunctionContainer rfc = m_requestFunctions.takeFirst();
@@ -162,59 +164,60 @@ void RequestHelper::slotNextRequest()
if (result == 0)
{
#ifdef REQUEST_HELPER_WITH_GUI
if (!m_quiet)
if (!m_quiet)
{
if (m_blockingCall)
{
if (m_blockingCall)
{
LtsWidgets::LtsMessageDialog::showMessage(qobject_cast<QWidget*>(parent()), tr("Request failed"));
}
else
{
connect(new LtsWidgets::LtsMessageDialogNew(qobject_cast<QWidget*>(parent()), tr("Request failed")),
&LtsWidgets::LtsMessageDialogNew::destroyed, this, [this]() { failure(); });
return;
}
LtsWidgets::LtsMessageDialog::showMessage(qobject_cast<QWidget *>(parent()), tr("Request failed"));
}
#endif
failure();
}
}
else
{
connect(new LtsWidgets::LtsMessageDialogNew(qobject_cast<QWidget *>(parent()), tr("Request failed")),
&LtsWidgets::LtsMessageDialogNew::destroyed,
this,
[this]() { failure(); });
void RequestHelper::startSingleBackgroundRequest(
const std::function<int64_t()>& requestFunction,
const std::function<void(const Core::FunctionReply&)>& baseReplyHandler)
{
return;
}
}
#endif
failure();
}
}
void RequestHelper::startSingleBackgroundRequest(const std::function<int64_t()> &requestFunction,
const std::function<void(const Core::FunctionReply &)> &baseReplyHandler)
{
m_blockingCall = false;
startSingleRequest(requestFunction, baseReplyHandler);
}
}
void RequestHelper::startBackgroundRequests()
{
void RequestHelper::startBackgroundRequests()
{
m_blockingCall = false;
startRequests();
}
}
void RequestHelper::setCustomWaitMessage(const QString& customWaitMessage)
{
void RequestHelper::setCustomWaitMessage(const QString &customWaitMessage)
{
m_customWaitMessage = (customWaitMessage + QStringLiteral(" ..."));
}
}
bool RequestHelper::startRequests()
{
bool RequestHelper::startRequests()
{
if (m_requestFunctions.isEmpty())
{
#ifdef LTS_DEBUG
qWarning("RequestHelper: started request helper without requests!");
qWarning("RequestHelper: started request helper without requests!");
#endif
return true;
return true;
}
m_failed = false;
#ifdef REQUEST_HELPER_WITH_GUI
if (!m_quiet)
LtsWidgets::LtsGlobalWaitDialog::getInstance()->wait(m_customWaitMessage);
LtsWidgets::LtsGlobalWaitDialog::getInstance()->wait(m_customWaitMessage);
m_customWaitMessage.clear();
#endif
@@ -223,25 +226,25 @@ bool RequestHelper::startRequests()
if (s_debug)
{
QTimer* t = new QTimer(this);
t->setInterval(2000);
connect(t, &QTimer::timeout, this, &RequestHelper::slotNextRequest, Qt::QueuedConnection);
connect(t, &QTimer::timeout, t, &QTimer::deleteLater);
t->start();
QTimer *t = new QTimer(this);
t->setInterval(2000);
connect(t, &QTimer::timeout, this, &RequestHelper::slotNextRequest, Qt::QueuedConnection);
connect(t, &QTimer::timeout, t, &QTimer::deleteLater);
t->start();
}
else
{
slotNextRequest();
slotNextRequest();
if (m_blockingCall)
{
QEventLoop loop;
connect(this, &RequestHelper::signalQuitLoop, &loop, &QEventLoop::quit, Qt::QueuedConnection);
loop.exec();
}
if (m_blockingCall)
{
QEventLoop loop;
connect(this, &RequestHelper::signalQuitLoop, &loop, &QEventLoop::quit, Qt::QueuedConnection);
loop.exec();
}
}
return (!m_failed);
}
}
} // namespace LtsUtils
@@ -27,114 +27,113 @@
namespace LtsUtils
{
template<typename T>
dds::core::optional<T> toOptional(T inVal)
{
return inVal != T() ? dds::core::optional<T>(inVal) : dds::core::optional<T>();
}
template <typename T> dds::core::optional<T> toOptional(T inVal)
{
return inVal != T() ? dds::core::optional<T>(inVal) : dds::core::optional<T>();
}
template<typename T>
dds::core::optional<T> optional()
{
return dds::core::optional<T>();
}
template <typename T> dds::core::optional<T> optional()
{
return dds::core::optional<T>();
}
class LTSUTILSGUIDDS_INTERNAL_EXPORT RequestHelper : public QObject // TODO: DOC !!!
{
Q_OBJECT
class LTSUTILSGUIDDS_INTERNAL_EXPORT RequestHelper : public QObject // TODO: DOC !!!
{
Q_OBJECT
public:
static bool s_debug;
public:
static bool s_debug;
explicit RequestHelper(QObject *parent = nullptr, bool quiet = false,
// for non-blocking
const std::function<void (void)> &success = [](){},
const std::function<void (void)> &failure = [](){});
~RequestHelper() = default;
explicit RequestHelper(
QObject *parent = nullptr,
bool quiet = false,
// for non-blocking
const std::function<void(void)> &success = []() {},
const std::function<void(void)> &failure = []() {});
~RequestHelper() = default;
bool quiet() const { return m_quiet; }
void setQuiet(bool quiet) { m_quiet = quiet; }
void addRequest(const std::function<int64_t()> &requestFunction,
const std::function<void(const Core::FunctionReply &baseReply)> &baseReplyHandler = nullptr);
bool startRequests(); // blocks!
bool quiet() const { return m_quiet; }
void setQuiet(bool quiet) { m_quiet = quiet; }
void addRequest(const std::function<int64_t()> &requestFunction, const std::function<void(const Core::FunctionReply &baseReply)> &baseReplyHandler = nullptr);
bool startRequests(); // blocks!
// do not throw a message if this method fails, as this method does this already // blocks!
bool startSingleRequest(const std::function<int64_t(void)> &requestFunction,
const std::function<void(const Core::FunctionReply &baseReply)> &baseReplyHandler = nullptr // for replies that return a custom FunctionReply, which has to be handled >>after successful execution<<
);
// do not throw a message if this method fails, as this method does this already // blocks!
bool startSingleRequest(const std::function<int64_t(void)> &requestFunction,
const std::function<void(const Core::FunctionReply &baseReply)> &baseReplyHandler =
nullptr // for replies that return a custom FunctionReply, which has to be handled >>after successful execution<<
);
// non-blocking !
/**
// non-blocking !
/**
* @brief startSingleBackgroundRequest << you cannot reuse this request helper after using background requests! Only use if your REALLY need it.
* @param requestFunction
* @param baseReplyHandler
*/
void startSingleBackgroundRequest(const std::function<int64_t()> &requestFunction,
const std::function<void(const Core::FunctionReply &baseReply)> &baseReplyHandler = nullptr);
/**
void startSingleBackgroundRequest(const std::function<int64_t()> &requestFunction,
const std::function<void(const Core::FunctionReply &baseReply)> &baseReplyHandler = nullptr);
/**
* @brief startBackgroundRequests << you cannot reuse this request helper after using background requests! Only use if your REALLY need it.
*/
void startBackgroundRequests(); // non-blocking !
void startBackgroundRequests(); // non-blocking !
bool requestReply(const Core::FunctionReply &baseReply); // if you have a custom FunctionReply, pass the base ptr
bool requestReply(const Core::FunctionReplyObject &replyObject);
bool requestReply(const Core::FunctionReply &baseReply); // if you have a custom FunctionReply, pass the base ptr
bool requestReply(const Core::FunctionReplyObject &replyObject);
/**
/**
* @brief hasRequests are requests is added?
* @return True if a request is added, otherwise false
*/
bool hasRequests() const { return !m_requestFunctions.isEmpty(); }
bool hasRequests() const { return !m_requestFunctions.isEmpty(); }
/**
/**
* @brief getRepliedId returns the Return-ID of the ReplyObject you gave to the method 'requestReply' - which is mostly the ID for the new Table Entry (Unique ID)
* @return the Return-ID or -1 on error (not set)
*/
int getRepliedId() const { return m_repliedId; }
int getRepliedId() const { return m_repliedId; }
/**
/**
* @brief getErrorString returns the error string set by an ftc reply
* @return
*/
QString getErrorString() const { return m_errorString; }
QString getErrorString() const { return m_errorString; }
/**
/**
* @brief setCustomWaitMessage changes the default 'Waiting for server reply ...' message with a custom one (NOTE: " ..." is automagically added to the custom text)
* After a request was started, the custom wait message is immediately reset, so that the next call to start a request, shows the default message again
* @param customWaitMessage the wait message to replace the default message with (note that " ..." is added to the text)
*/
void setCustomWaitMessage(const QString &customWaitMessage);
void setCustomWaitMessage(const QString &customWaitMessage);
bool failed() const { return m_failed; }
void failure();
bool failed() const { return m_failed; }
void failure();
private:
using RequestFunctionContainer = QPair<std::function<int64_t()>, std::function<void(const Core::FunctionReply &)>>;
private:
using RequestFunctionContainer = QPair<std::function<int64_t()>, std::function<void(const Core::FunctionReply &)>>;
QVector<RequestFunctionContainer> m_requestFunctions;
bool m_failed;
int m_repliedId;
std::function<void(const Core::FunctionReply &)> m_singleRequestCustomFunctionReply;
bool m_quiet;
bool m_blockingCall;
std::function<void (void)> m_successFn;
std::function<void (void)> m_failureFn;
QString m_errorString;
QString m_customWaitMessage;
QVector<RequestFunctionContainer> m_requestFunctions;
bool m_failed;
int m_repliedId;
std::function<void(const Core::FunctionReply &)> m_singleRequestCustomFunctionReply;
bool m_quiet;
bool m_blockingCall;
std::function<void(void)> m_successFn;
std::function<void(void)> m_failureFn;
QString m_errorString;
QString m_customWaitMessage;
void done();
bool _requestReply(const Core::FunctionReplyObject &fro, const Core::FunctionReply *baseReply);
void done();
bool _requestReply(const Core::FunctionReplyObject &fro, const Core::FunctionReply *baseReply);
signals:
void signalNextRequest();
void signalQuitLoop();
void signalSuccess();
void signalFailed();
signals:
void signalNextRequest();
void signalQuitLoop();
void signalSuccess();
void signalFailed();
private slots:
void slotNextRequest();
};
private slots:
void slotNextRequest();
};
} // namespace LtsUtils
@@ -10,82 +10,79 @@
namespace LtsUtils
{
struct StyleManagerHandler
{
struct StyleManagerHandler
{
StyleManager styleManager;
};
Q_GLOBAL_STATIC(StyleManagerHandler, s_styleManagerHandler)
};
Q_GLOBAL_STATIC(StyleManagerHandler, s_styleManagerHandler)
StyleManager* StyleManager::getInstance()
{
StyleManager *StyleManager::getInstance()
{
return &s_styleManagerHandler->styleManager;
}
}
bool StyleManager::loadStyle(const QString& stylePluginName, bool highDpi)
{
bool StyleManager::loadStyle(const QString &stylePluginName, bool highDpi)
{
if (m_currentStylePluginLoader != nullptr)
{
QObject* pluginInstance = m_currentStylePluginLoader->instance();
StylePlugin::Plugin* sp = qobject_cast<StylePlugin::Plugin*>(pluginInstance);
QObject *pluginInstance = m_currentStylePluginLoader->instance();
StylePlugin::Plugin *sp = qobject_cast<StylePlugin::Plugin *>(pluginInstance);
if (sp == nullptr)
{
qWarning() << "StyleManager::loadStyle: could not unload style plugin - wrong type ("
<< pluginInstance->metaObject()->className() << ") - new style not loaded";
return false;
}
if (sp == nullptr)
{
qWarning() << "StyleManager::loadStyle: could not unload style plugin - wrong type (" << pluginInstance->metaObject()->className() << ") - new style not loaded";
return false;
}
sp->unloadStyle();
sp->unloadStyle();
m_currentStylePluginLoader = nullptr;
m_currentStylePluginLoader = nullptr;
}
LtsPluginManager::LtsPluginLoader* pluginLoader = LtsPluginManager::LtsPluginLoader::getInstance();
LtsPluginManager::LtsPluginLoader *pluginLoader = LtsPluginManager::LtsPluginLoader::getInstance();
QPluginLoader* stylePluginLoader = nullptr;
QPluginLoader *stylePluginLoader = nullptr;
int pluginsLoaded = 0;
std::function<bool(const LtsPluginManager::PluginInstance& pi)> loadPluginFn =
[&stylePluginLoader, &pluginsLoaded](const LtsPluginManager::PluginInstance& pi) {
stylePluginLoader = pi.pluginLoader;
pluginsLoaded++;
return true;
};
std::function<bool(const LtsPluginManager::PluginInstance &pi)> loadPluginFn = [&stylePluginLoader, &pluginsLoaded](const LtsPluginManager::PluginInstance &pi)
{
stylePluginLoader = pi.pluginLoader;
pluginsLoaded++;
return true;
};
if (!pluginLoader->loadPlugins(LtsPluginManager::PluginType::STYLE, loadPluginFn, QStringList() << stylePluginName))
{
qWarning() << "StyleManager::loadStyle: Error loading Style Plugin - using default Qt style";
return false;
qWarning() << "StyleManager::loadStyle: Error loading Style Plugin - using default Qt style";
return false;
}
if (pluginsLoaded == 0)
{
qWarning() << "StyleManager::loadStyle: Could not find Style Plugin" << stylePluginName
<< "- using default Qt style";
return false;
qWarning() << "StyleManager::loadStyle: Could not find Style Plugin" << stylePluginName << "- using default Qt style";
return false;
}
if (pluginsLoaded > 1)
{
qWarning() << "StyleManager::loadStyle: Style Plugin" << stylePluginName
<< " is ambiguous - using default Qt style";
return false;
qWarning() << "StyleManager::loadStyle: Style Plugin" << stylePluginName << " is ambiguous - using default Qt style";
return false;
}
if (stylePluginLoader == nullptr)
{
qWarning() << "StyleManager::loadStyle: No Style Plugin loader available - using default Qt style";
return false;
qWarning() << "StyleManager::loadStyle: No Style Plugin loader available - using default Qt style";
return false;
}
StylePlugin::Plugin* sp = qobject_cast<StylePlugin::Plugin*>(stylePluginLoader->instance());
StylePlugin::Plugin *sp = qobject_cast<StylePlugin::Plugin *>(stylePluginLoader->instance());
if (sp == nullptr)
{
qWarning() << "StyleManager::loadStyle: could not load style plugin - wrong type ("
<< stylePluginLoader->instance()->metaObject()->className() << ") - new style not loaded";
return false;
qWarning() << "StyleManager::loadStyle: could not load style plugin - wrong type (" << stylePluginLoader->instance()->metaObject()->className()
<< ") - new style not loaded";
return false;
}
sp->loadStyle(highDpi);
@@ -95,6 +92,6 @@ bool StyleManager::loadStyle(const QString& stylePluginName, bool highDpi)
emit signalStyleChanged(stylePluginName);
return true;
}
}
} // namespace LtsUtils
@@ -10,29 +10,26 @@ class QPluginLoader;
namespace LtsUtils
{
class LTSUTILSGUISTYLEMANAGER_EXPORT StyleManager : public QObject
{
class LTSUTILSGUISTYLEMANAGER_EXPORT StyleManager : public QObject
{
Q_OBJECT
using QObject::QObject;
~StyleManager() = default;
public:
static StyleManager* getInstance();
static StyleManager *getInstance();
bool loadStyle(const QString& stylePluginName, bool highDpi = false);
bool loadStyle(const QString &stylePluginName, bool highDpi = false);
const QString& currentStyleName() const
{
return m_stylePluginName;
}
const QString &currentStyleName() const { return m_stylePluginName; }
private:
friend struct StyleManagerHandler;
QPluginLoader* m_currentStylePluginLoader = nullptr;
QPluginLoader *m_currentStylePluginLoader = nullptr;
QString m_stylePluginName;
signals:
void signalStyleChanged(const QString& stylePluginName);
};
void signalStyleChanged(const QString &stylePluginName);
};
} // namespace LtsUtils
@@ -16,233 +16,234 @@
namespace LtsUtils
{
enum class SettingType {
enum class SettingType
{
String = 1,
StringList = 2,
Json = 3,
FunctionKeys = 4,
Boolean = 5,
};
};
QString typeToString(SettingType t)
{
QString typeToString(SettingType t)
{
switch (t)
{
case SettingType::String:
return QStringLiteral("String");
case SettingType::StringList:
return QStringLiteral("StringList");
case SettingType::Json:
return QStringLiteral("Json");
case SettingType::FunctionKeys:
return QStringLiteral("FunctionKeys");
case SettingType::Boolean:
return QStringLiteral("Boolean");
case SettingType::String:
return QStringLiteral("String");
case SettingType::StringList:
return QStringLiteral("StringList");
case SettingType::Json:
return QStringLiteral("Json");
case SettingType::FunctionKeys:
return QStringLiteral("FunctionKeys");
case SettingType::Boolean:
return QStringLiteral("Boolean");
}
Q_ASSERT(false);
return QStringLiteral("Unknown SettingType (%1)").arg(int(t));
}
}
SettingType stringToType(const QString& s)
{
SettingType stringToType(const QString &s)
{
if (s == typeToString(SettingType::String))
return SettingType::String;
return SettingType::String;
if (s == typeToString(SettingType::StringList))
return SettingType::StringList;
return SettingType::StringList;
if (s == typeToString(SettingType::Json))
return SettingType::Json;
return SettingType::Json;
if (s == typeToString(SettingType::FunctionKeys))
return SettingType::FunctionKeys;
return SettingType::FunctionKeys;
if (s == typeToString(SettingType::Boolean))
return SettingType::Boolean;
return SettingType::Boolean;
Q_ASSERT(false);
return SettingType::String;
}
}
static QString craftKey(const QString& group, const QString& identifier)
{
static QString craftKey(const QString &group, const QString &identifier)
{
return group + QLatin1Char('.') + identifier;
}
}
static OperatorSettings* s_operatorSettings = nullptr;
static OperatorSettings *s_operatorSettings = nullptr;
static void cleanupOperatorSettings()
{
static void cleanupOperatorSettings()
{
delete s_operatorSettings;
s_operatorSettings = nullptr;
}
}
OperatorSettings* OperatorSettings::getInstance()
{
OperatorSettings *OperatorSettings::getInstance()
{
if (!s_operatorSettings)
{
s_operatorSettings = new OperatorSettings;
qAddPostRoutine(&cleanupOperatorSettings);
s_operatorSettings = new OperatorSettings;
qAddPostRoutine(&cleanupOperatorSettings);
}
return s_operatorSettings;
}
}
static ProjectSettings* s_projectSettings = nullptr;
static ProjectSettings *s_projectSettings = nullptr;
static void cleanupProjectSettings()
{
static void cleanupProjectSettings()
{
delete s_projectSettings;
s_projectSettings = nullptr;
}
}
ProjectSettings* ProjectSettings::getInstance()
{
ProjectSettings *ProjectSettings::getInstance()
{
if (!s_projectSettings)
{
s_projectSettings = new ProjectSettings;
qAddPostRoutine(&cleanupProjectSettings);
s_projectSettings = new ProjectSettings;
qAddPostRoutine(&cleanupProjectSettings);
}
return s_projectSettings;
}
}
bool ProjectSettings::initFromFile(const QString& filename)
{
bool ProjectSettings::initFromFile(const QString &filename)
{
QFile f(filename);
if (!f.open(QIODevice::ReadOnly))
return false;
return false;
QJsonParseError jErr;
const QJsonObject settings = QJsonDocument::fromJson(f.readAll(), &jErr).object();
if (jErr.error != QJsonParseError::NoError)
return false;
return false;
const QJsonObject psObj = settings[QStringLiteral("ProjectSettings")].toObject();
if (psObj.isEmpty())
return false;
return false;
QHash<QString, QVariant> newData;
const QStringList& groupKeys(psObj.keys());
for (const auto& gKey : groupKeys)
const QStringList &groupKeys(psObj.keys());
for (const auto &gKey : groupKeys)
{
const QJsonObject objGroup(psObj[gKey].toObject());
const QStringList& itemKeys(objGroup.keys());
for (const auto& key : itemKeys)
const QJsonObject objGroup(psObj[gKey].toObject());
const QStringList &itemKeys(objGroup.keys());
for (const auto &key : itemKeys)
{
const QJsonObject obj(objGroup[key].toObject());
const auto strType(obj[QStringLiteral("Type")].toString());
const auto type = stringToType(strType);
const QJsonValue jVal(obj[QStringLiteral("Default")]);
QVariant val;
switch (type)
{
const QJsonObject obj(objGroup[key].toObject());
const auto strType(obj[QStringLiteral("Type")].toString());
const auto type = stringToType(strType);
const QJsonValue jVal(obj[QStringLiteral("Default")]);
QVariant val;
switch (type)
{
case SettingType::Json:
val = QJsonDocument(jVal.toObject()).toJson();
break;
case SettingType::StringList: {
const QJsonArray arr(jVal.toArray());
QStringList sl;
sl.reserve(arr.size());
for (const auto& ele : arr)
sl.push_back(ele.toString());
val = sl;
break;
}
case SettingType::FunctionKeys:
val = jVal.toVariant();
break;
case SettingType::String:
val = jVal.toString();
break;
case SettingType::Boolean:
val = jVal.toBool();
break;
}
newData[craftKey(gKey, key)] = val;
case SettingType::Json:
val = QJsonDocument(jVal.toObject()).toJson();
break;
case SettingType::StringList:
{
const QJsonArray arr(jVal.toArray());
QStringList sl;
sl.reserve(arr.size());
for (const auto &ele : arr)
sl.push_back(ele.toString());
val = sl;
break;
}
case SettingType::FunctionKeys:
val = jVal.toVariant();
break;
case SettingType::String:
val = jVal.toString();
break;
case SettingType::Boolean:
val = jVal.toBool();
break;
}
newData[craftKey(gKey, key)] = val;
}
}
getInstance()->m_data = newData;
return true;
}
}
bool ProjectSettings::isFunctionEnabled(const QString& group, const QString& function)
{
const QStringList functionNames =
getInstance()->value(QStringLiteral("Functionalities"), QStringLiteral("IdentifierList")).toStringList();
bool ProjectSettings::isFunctionEnabled(const QString &group, const QString &function)
{
const QStringList functionNames = getInstance()->value(QStringLiteral("Functionalities"), QStringLiteral("IdentifierList")).toStringList();
return functionNames.contains(group + QLatin1Char(':') + function);
}
}
void Settings::init(const QByteArray& settings)
{
void Settings::init(const QByteArray &settings)
{
QByteArray uncompressed;
try
{
uncompressed = qUncompress(settings);
uncompressed = qUncompress(settings);
}
catch (...)
{
}
if (uncompressed.isEmpty())
uncompressed = settings;
uncompressed = settings;
QDataStream stream(uncompressed);
stream >> m_data;
}
}
QByteArray Settings::exportSettings() const
{
QByteArray Settings::exportSettings() const
{
if (m_data.isEmpty())
return QByteArray();
return QByteArray();
QByteArray ba;
QDataStream stream(&ba, QIODevice::WriteOnly);
stream << m_data;
return qCompress(ba);
}
}
void Settings::clear()
{
void Settings::clear()
{
m_data.clear();
}
}
void Settings::dump()
{
void Settings::dump()
{
qWarning() << "Settings::m_data: keys=" << m_data.keys();
QHashIterator<QString, QVariant> it(m_data);
int i = 0;
while (it.hasNext())
{
it.next();
qWarning() << i++ << ":"
<< " - key='" << it.key() << "' value -> '" << it.value() << "'";
it.next();
qWarning() << i++ << ":"
<< " - key='" << it.key() << "' value -> '" << it.value() << "'";
}
qWarning() << "Settings::m_data: ------------------";
}
}
void Settings::setValue(const QString& group, const QString& identifier, const QVariant& value)
{
void Settings::setValue(const QString &group, const QString &identifier, const QVariant &value)
{
m_data.insert(craftKey(group, identifier), value);
emit valueChanged(group, identifier, value);
}
}
void Settings::removeValue(const QString& group, const QString& identifier)
{
void Settings::removeValue(const QString &group, const QString &identifier)
{
if (m_data.remove(craftKey(group, identifier)))
emit valueRemoved(group, identifier);
}
emit valueRemoved(group, identifier);
}
QStringList Settings::identifiers(const QString& group) const
{
QStringList Settings::identifiers(const QString &group) const
{
QStringList result;
for (auto it = m_data.begin(); it != m_data.end(); ++it)
{
const QStringList decrafted = QString(it.key()).split(QLatin1Char('.'));
if (decrafted.size() > 1 && QStringView(group).compare(decrafted.at(0)) == 0)
result.append(decrafted.at(0).mid(1));
const QStringList decrafted = QString(it.key()).split(QLatin1Char('.'));
if (decrafted.size() > 1 && QStringView(group).compare(decrafted.at(0)) == 0)
result.append(decrafted.at(0).mid(1));
}
return result;
}
}
QVariant Settings::value(const QString& group, const QString& identifier, const QVariant& defaultValue) const
{
QVariant Settings::value(const QString &group, const QString &identifier, const QVariant &defaultValue) const
{
return m_data.value(craftKey(group, identifier), defaultValue);
}
}
} // namespace LtsUtils
@@ -12,22 +12,22 @@ class QJsonObject;
namespace LtsUtils
{
class LTSUTILSSETTINGS_EXPORT Settings : public QObject
{
class LTSUTILSSETTINGS_EXPORT Settings : public QObject
{
Q_OBJECT
public:
~Settings() = default;
void setValue(const QString& group, const QString& identifier, const QVariant& value);
void setValue(const QString &group, const QString &identifier, const QVariant &value);
void removeValue(const QString& group, const QString& identifier);
void removeValue(const QString &group, const QString &identifier);
QVariant value(const QString& group, const QString& identifier, const QVariant& defaultValue = QVariant()) const;
QVariant value(const QString &group, const QString &identifier, const QVariant &defaultValue = QVariant()) const;
QStringList identifiers(const QString& group) const;
QStringList identifiers(const QString &group) const;
void init(const QByteArray& settings);
void init(const QByteArray &settings);
QByteArray exportSettings() const;
void clear();
@@ -37,28 +37,28 @@ class LTSUTILSSETTINGS_EXPORT Settings : public QObject
Settings() = default;
signals:
void valueChanged(const QString& group, const QString& identifier, const QVariant& value);
void valueRemoved(const QString& group, const QString& identifier);
void valueChanged(const QString &group, const QString &identifier, const QVariant &value);
void valueRemoved(const QString &group, const QString &identifier);
protected:
QHash<QString, QVariant> m_data;
};
};
class LTSUTILSSETTINGS_EXPORT OperatorSettings : public Settings
{
class LTSUTILSSETTINGS_EXPORT OperatorSettings : public Settings
{
Q_OBJECT
public:
static OperatorSettings* getInstance();
};
static OperatorSettings *getInstance();
};
class LTSUTILSSETTINGS_EXPORT ProjectSettings : public Settings
{
class LTSUTILSSETTINGS_EXPORT ProjectSettings : public Settings
{
Q_OBJECT
public:
static ProjectSettings* getInstance();
static ProjectSettings *getInstance();
static bool initFromFile(const QString& filename);
static bool isFunctionEnabled(const QString& group, const QString& function);
};
static bool initFromFile(const QString &filename);
static bool isFunctionEnabled(const QString &group, const QString &function);
};
} // namespace LtsUtils
@@ -10,80 +10,80 @@
namespace LtsWebSocket
{
ClientConnection::ClientConnection(QWebSocket* socket, QObject* parent)
: QThread(parent), m_logger(getLogger("LtsWebSocket.ClientConnection")), m_socket(socket ? socket : new QWebSocket)
{
}
ClientConnection::ClientConnection(QWebSocket *socket, QObject *parent)
: QThread(parent)
, m_logger(getLogger("LtsWebSocket.ClientConnection"))
, m_socket(socket ? socket : new QWebSocket)
{
}
ClientConnection::~ClientConnection()
{
ClientConnection::~ClientConnection()
{
DEBUG_LOG(m_logger) << "Thread closed" << this;
delete m_socket;
qDeleteAll(m_messageQueue);
}
}
#ifdef QT6_WEBSOCKETS_AVAILABLE
bool ClientConnection::init()
{
bool ClientConnection::init()
{
if (m_socket == nullptr)
{
ERROR_LOG(m_logger) << "Initialisation failed due to an invalid socket";
return false;
ERROR_LOG(m_logger) << "Initialisation failed due to an invalid socket";
return false;
}
DEBUG_LOG(m_logger) << "Started new thread" << this;
connect(m_socket, &QWebSocket::textMessageReceived, this, &ClientConnection::onNewTextMessageFromSocket,
Qt::DirectConnection);
connect(m_socket, &QWebSocket::textMessageReceived, this, &ClientConnection::onNewTextMessageFromSocket, Qt::DirectConnection);
connect(m_socket, &QWebSocket::connected, this, &ClientConnection::sendMessagesFromQueue);
connect(m_socket, &QWebSocket::disconnected, this, &ClientConnection::onSocketDisconnect);
return true;
}
}
void ClientConnection::addReply(ReplyMessage* message)
{
void ClientConnection::addReply(ReplyMessage *message)
{
if (!m_socket || m_socket->state() != QAbstractSocket::ConnectedState)
{
m_messageQueue.enqueue(message);
DEBUG_LOG(m_logger) << "Adding message to queue, size: " << m_messageQueue.size();
return;
m_messageQueue.enqueue(message);
DEBUG_LOG(m_logger) << "Adding message to queue, size: " << m_messageQueue.size();
return;
}
const QString msg(message->toJsonString());
DEBUG_LOG(m_logger) << "Sending message: " << msg;
m_socket->sendTextMessage(msg);
delete message;
}
}
void ClientConnection::onNewTextMessageFromSocket(const QString& message)
{
void ClientConnection::onNewTextMessageFromSocket(const QString &message)
{
DEBUG_LOG(m_logger) << "Recv msg: " << message << this;
emit newTextMessage(this, message);
}
}
void ClientConnection::sendMessagesFromQueue()
{
void ClientConnection::sendMessagesFromQueue()
{
INFO_LOG(m_logger) << "Client connected ip: " << m_socket->peerAddress().toString() << ":" << m_socket->peerPort();
if (m_socket->state() != QAbstractSocket::ConnectedState)
return;
return;
while (!m_messageQueue.isEmpty())
{
ReplyMessage* message = m_messageQueue.dequeue();
const QString msg(message->toJsonString());
TRACE_LOG(m_logger) << "Send msg: " << msg;
m_socket->sendTextMessage(msg);
delete message;
DEBUG_LOG(m_logger) << "Sent message from queue, new size: " << m_messageQueue.size();
ReplyMessage *message = m_messageQueue.dequeue();
const QString msg(message->toJsonString());
TRACE_LOG(m_logger) << "Send msg: " << msg;
m_socket->sendTextMessage(msg);
delete message;
DEBUG_LOG(m_logger) << "Sent message from queue, new size: " << m_messageQueue.size();
}
}
}
void ClientConnection::onSocketDisconnect()
{
DEBUG_LOG(m_logger) << "Client disconnected ip: " << m_socket->peerAddress().toString() << ":"
<< m_socket->peerPort();
void ClientConnection::onSocketDisconnect()
{
DEBUG_LOG(m_logger) << "Client disconnected ip: " << m_socket->peerAddress().toString() << ":" << m_socket->peerPort();
exit(0);
emit disconnected(this);
}
}
#endif
} // namespace LtsWebSocket
@@ -12,68 +12,70 @@
#ifdef QT6_WEBSOCKETS_AVAILABLE
class QWebSocket;
#else
namespace LtsWebSocket { class QWebSocketStub; }
namespace LtsWebSocket
{
class QWebSocketStub;
}
using QWebSocket = LtsWebSocket::QWebSocketStub;
namespace LtsWebSocket
{
class QWebSocketStub
{
class QWebSocketStub
{
public:
QWebSocketStub(QObject* parent = nullptr) { Q_UNUSED(parent); }
QWebSocketStub(QObject *parent = nullptr) { Q_UNUSED(parent); }
virtual ~QWebSocketStub() = default;
void sendTextMessage(const QString& /*message*/) {}
void sendTextMessage(const QString & /*message*/) {}
void close() {}
bool isValid() const { return false; }
QString errorString() const { return QString(); }
};
};
} // namespace LtsWebSocket
#endif
namespace LtsWebSocket
{
class LTSWEBSOCKETSERVER_EXPORT ClientConnection : public QThread, public ReplyHandler
{
class LTSWEBSOCKETSERVER_EXPORT ClientConnection
: public QThread
, public ReplyHandler
{
Q_OBJECT
public:
explicit ClientConnection(QWebSocket* socket, QObject* parent = nullptr);
explicit ClientConnection(QWebSocket *socket, QObject *parent = nullptr);
~ClientConnection();
#ifdef QT6_WEBSOCKETS_AVAILABLE
bool init();
void addReply(ReplyMessage* message) override;
void addReply(ReplyMessage *message) override;
QWebSocket* webSocket()
{
return m_socket;
}
QWebSocket *webSocket() { return m_socket; }
#else
bool init() { return false; }
void addReply(ReplyMessage* /*message*/) override {}
QWebSocket* webSocket() { return nullptr; }
void addReply(ReplyMessage * /*message*/) override {}
QWebSocket *webSocket() { return nullptr; }
#endif
signals:
void newTextMessage(ClientConnection* client, const QString& message);
void newTextMessage(ClientConnection *client, const QString &message);
void disconnected(ClientConnection* client);
void disconnected(ClientConnection *client);
private slots:
#ifdef QT6_WEBSOCKETS_AVAILABLE
void onNewTextMessageFromSocket(const QString& message);
void onNewTextMessageFromSocket(const QString &message);
void sendMessagesFromQueue();
void onSocketDisconnect();
#endif
private:
NGL::INGLLogger& m_logger;
NGL::INGLLogger &m_logger;
#ifdef QT6_WEBSOCKETS_AVAILABLE
void sendMessages();
#endif
QWebSocket* m_socket;
QQueue<ReplyMessage*> m_messageQueue;
};
QWebSocket *m_socket;
QQueue<ReplyMessage *> m_messageQueue;
};
} // namespace LtsWebSocket
@@ -9,13 +9,14 @@
namespace LtsWebSocket
{
InvalidMessage::InvalidMessage(ReplyHandler* client, const QString& uuid, const QString& errorText)
: AbstractClientMessage(client, QString(), 1, uuid), m_errorText(errorText)
{
}
InvalidMessage::InvalidMessage(ReplyHandler *client, const QString &uuid, const QString &errorText)
: AbstractClientMessage(client, QString(), 1, uuid)
, m_errorText(errorText)
{
}
void InvalidMessage::process()
{
void InvalidMessage::process()
{
ErrorMessage::ErrorData errorData;
errorData.errorClass = 1;
@@ -23,12 +24,12 @@ void InvalidMessage::process()
errorData.uuid = m_uuid;
m_client->addReply(new ErrorMessage(errorData));
}
}
bool InvalidMessage::hasValidData() const
{
bool InvalidMessage::hasValidData() const
{
return true;
}
}
} // namespace LtsWebSocket
@@ -11,12 +11,15 @@
namespace LtsWebSocket
{
class LTSWEBSOCKETCOMMON_EXPORT AbstractClientMessage
{
class LTSWEBSOCKETCOMMON_EXPORT AbstractClientMessage
{
public:
AbstractClientMessage(ReplyHandler* client, const QString& type, const int typeId, const QString& uuid,
const QJsonValue& data = QJsonValue())
: m_type(type), m_typeId(typeId), m_uuid(uuid), m_data(data), m_client(client)
AbstractClientMessage(ReplyHandler *client, const QString &type, const int typeId, const QString &uuid, const QJsonValue &data = QJsonValue())
: m_type(type)
, m_typeId(typeId)
, m_uuid(uuid)
, m_data(data)
, m_client(client)
{
}
@@ -26,29 +29,26 @@ class LTSWEBSOCKETCOMMON_EXPORT AbstractClientMessage
virtual bool hasValidData() const = 0;
void reply(ReplyMessage* reply)
{
m_client->addReply(reply);
}
void reply(ReplyMessage *reply) { m_client->addReply(reply); }
protected:
const QString m_type;
const int m_typeId;
const QString m_uuid;
const QJsonValue m_data;
ReplyHandler* m_client;
};
ReplyHandler *m_client;
};
class LTSWEBSOCKETCOMMON_EXPORT InvalidMessage final : public AbstractClientMessage
{
class LTSWEBSOCKETCOMMON_EXPORT InvalidMessage final : public AbstractClientMessage
{
public:
explicit InvalidMessage(ReplyHandler* client, const QString& uuid, const QString& errorText);
explicit InvalidMessage(ReplyHandler *client, const QString &uuid, const QString &errorText);
void process() override;
bool hasValidData() const override;
private:
QString m_errorText;
};
};
} // namespace LtsWebSocket
@@ -10,13 +10,13 @@
namespace LtsWebSocket
{
QJsonParseError AbstractClientMessageFactory::parseMessage(const QString& message)
{
QJsonParseError AbstractClientMessageFactory::parseMessage(const QString &message)
{
QJsonParseError error;
QJsonDocument doc = QJsonDocument::fromJson(message.toUtf8(), &error);
if (error.error != QJsonParseError::NoError)
return error;
return error;
QJsonObject obj = doc.object();
@@ -26,38 +26,37 @@ QJsonParseError AbstractClientMessageFactory::parseMessage(const QString& messag
m_uuid = obj.value(JsonKeys::UUID_()).toString();
return error;
}
}
AbstractClientMessage* AbstractClientMessageFactory::checkAttributes(ReplyHandler* client, const QString& message) const
{
AbstractClientMessage *AbstractClientMessageFactory::checkAttributes(ReplyHandler *client, const QString &message) const
{
if (!m_uuid.isEmpty() && !m_type.isEmpty())
return nullptr;
return nullptr;
if (m_uuid.isEmpty())
{
WARNING_LOG(m_logger) << "Got message without uuid: " << message << "'";
return new LtsWebSocket::InvalidMessage(client, QString(), QStringLiteral("Got message without uuid"));
WARNING_LOG(m_logger) << "Got message without uuid: " << message << "'";
return new LtsWebSocket::InvalidMessage(client, QString(), QStringLiteral("Got message without uuid"));
}
WARNING_LOG(m_logger) << "Got message no type: " << message << "'";
return new LtsWebSocket::InvalidMessage(client, m_uuid, QStringLiteral("Message has no type"));
}
}
AbstractClientMessage* AbstractClientMessageFactory::checkResult(ReplyHandler* client, const QString& message,
AbstractClientMessage* result) const
{
AbstractClientMessage *AbstractClientMessageFactory::checkResult(ReplyHandler *client, const QString &message, AbstractClientMessage *result) const
{
if (result == nullptr)
{
WARNING_LOG(m_logger) << "Could not parse message: " << message;
result = new LtsWebSocket::InvalidMessage(client, m_uuid, QStringLiteral("Invalid type"));
WARNING_LOG(m_logger) << "Could not parse message: " << message;
result = new LtsWebSocket::InvalidMessage(client, m_uuid, QStringLiteral("Invalid type"));
}
if (!result->hasValidData())
{
WARNING_LOG(m_logger) << "Resulting JSon message has invalid data... " << message;
delete result;
result = new LtsWebSocket::InvalidMessage(client, m_uuid, QStringLiteral("Has invalid data part"));
WARNING_LOG(m_logger) << "Resulting JSon message has invalid data... " << message;
delete result;
result = new LtsWebSocket::InvalidMessage(client, m_uuid, QStringLiteral("Has invalid data part"));
}
return result;
}
}
} // namespace LtsWebSocket
@@ -11,58 +11,55 @@
namespace NGL
{
class INGLLogger;
class INGLLogger;
}
namespace LtsWebSocket
{
class LTSWEBSOCKETCOMMON_EXPORT AbstractClientMessageFactory
{
class LTSWEBSOCKETCOMMON_EXPORT AbstractClientMessageFactory
{
public:
explicit AbstractClientMessageFactory(NGL::INGLLogger& logger) : m_logger(logger) {}
explicit AbstractClientMessageFactory(NGL::INGLLogger &logger)
: m_logger(logger)
{
}
virtual ~AbstractClientMessageFactory() {}
QJsonParseError parseMessage(const QString& message);
QJsonParseError parseMessage(const QString &message);
virtual AbstractClientMessage* createMessage(ReplyHandler* client, const QString& message) = 0;
virtual AbstractClientMessage *createMessage(ReplyHandler *client, const QString &message) = 0;
protected:
AbstractClientMessage* checkAttributes(ReplyHandler* client, const QString& message) const;
AbstractClientMessage* checkResult(ReplyHandler* client, const QString& message,
AbstractClientMessage* result) const;
AbstractClientMessage *checkAttributes(ReplyHandler *client, const QString &message) const;
AbstractClientMessage *checkResult(ReplyHandler *client, const QString &message, AbstractClientMessage *result) const;
protected:
NGL::INGLLogger& m_logger;
NGL::INGLLogger &m_logger;
QString m_type;
int m_typeId;
QString m_uuid;
QJsonValue m_data;
};
};
class PongMessage final : public ReplyMessage
{
class PongMessage final : public ReplyMessage
{
public:
static QString strPong()
static QString strPong() { return QStringLiteral("pong"); }
static int idPong() { return 2; }
explicit PongMessage(const QString &payload)
: ReplyMessage(strPong(), idPong(), QString())
, m_payload(payload)
{
return QStringLiteral("pong");
}
static int idPong()
{
return 2;
}
explicit PongMessage(const QString& payload) : ReplyMessage(strPong(), idPong(), QString()), m_payload(payload) {}
QString toJsonString() const override
{
return m_payload.isEmpty() ? strPong() : QStringLiteral("%1 %2").arg(strPong(), m_payload);
}
QString toJsonString() const override { return m_payload.isEmpty() ? strPong() : QStringLiteral("%1 %2").arg(strPong(), m_payload); }
private:
QString m_payload;
};
};
} // namespace LtsWebSocket
@@ -12,84 +12,84 @@
using namespace LtsWebSocket;
ConnectionHandler::ConnectionHandler(QObject* parent)
: QObject(parent), m_logger(getLogger("LtsWebSocket.ConnectionHandler")), m_server(nullptr)
ConnectionHandler::ConnectionHandler(QObject *parent)
: QObject(parent)
, m_logger(getLogger("LtsWebSocket.ConnectionHandler"))
, m_server(nullptr)
{
}
ConnectionHandler::~ConnectionHandler()
{
#ifdef QT6_WEBSOCKETS_AVAILABLE
for (auto connection : std::as_const(m_connections))
connection->disconnect(this);
for (auto connection : std::as_const(m_connections))
connection->disconnect(this);
#endif
}
#ifdef QT6_WEBSOCKETS_AVAILABLE
bool ConnectionHandler::init(const QString& serviceName, unsigned short port)
bool ConnectionHandler::init(const QString &serviceName, unsigned short port)
{
if (m_server != nullptr)
{
m_server->disconnect();
delete m_server;
}
if (m_server != nullptr)
{
m_server->disconnect();
delete m_server;
}
m_server = new QWebSocketServer(QStringLiteral("RME-") + serviceName, QWebSocketServer::NonSecureMode, this);
m_server = new QWebSocketServer(QStringLiteral("RME-") + serviceName, QWebSocketServer::NonSecureMode, this);
connect(m_server, &QWebSocketServer::newConnection, this, &ConnectionHandler::onNewConnection);
connect(m_server, &QWebSocketServer::serverError, this, &ConnectionHandler::onServerError);
connect(m_server, &QWebSocketServer::newConnection, this, &ConnectionHandler::onNewConnection);
connect(m_server, &QWebSocketServer::serverError, this, &ConnectionHandler::onServerError);
DEBUG_LOG(m_logger) << "Trying to listen ";
if (!m_server->listen(QHostAddress::Any, port))
{
ERROR_LOG(m_logger) << "Not possible to listen to port " << port;
return false;
}
DEBUG_LOG(m_logger) << "... ok, port " << m_server->serverPort();
DEBUG_LOG(m_logger) << "Trying to listen ";
if (!m_server->listen(QHostAddress::Any, port))
{
ERROR_LOG(m_logger) << "Not possible to listen to port " << port;
return false;
}
DEBUG_LOG(m_logger) << "... ok, port " << m_server->serverPort();
return true;
return true;
}
void ConnectionHandler::sendToAllClients(ReplyMessage* message)
void ConnectionHandler::sendToAllClients(ReplyMessage *message)
{
for (auto connection : std::as_const(m_connections))
connection->addReply(new ReplyMessage(*message));
for (auto connection : std::as_const(m_connections))
connection->addReply(new ReplyMessage(*message));
delete message;
delete message;
}
void ConnectionHandler::onServerError(QWebSocketProtocol::CloseCode closeCode)
{
ERROR_LOG(m_logger) << "Got server error with close code " << closeCode;
ERROR_LOG(m_logger) << "Got server error with close code " << closeCode;
}
void ConnectionHandler::onNewConnection()
{
while (m_server->hasPendingConnections())
while (m_server->hasPendingConnections())
{
QWebSocket *socket = m_server->nextPendingConnection();
ClientConnection *newConnection = new ClientConnection(socket, this);
connect(newConnection, &ClientConnection::destroyed, this, [this](QObject *o) { m_connections.remove(static_cast<ClientConnection *>(o)); });
if (!newConnection->init())
{
QWebSocket* socket = m_server->nextPendingConnection();
ClientConnection* newConnection = new ClientConnection(socket, this);
connect(newConnection, &ClientConnection::destroyed, this,
[this](QObject* o) { m_connections.remove(static_cast<ClientConnection*>(o)); });
if (!newConnection->init())
{
ERROR_LOG(m_logger) << "Failed to initialise new client";
delete newConnection;
newConnection = nullptr;
continue;
}
newConnection->start();
connect(newConnection, &ClientConnection::newTextMessage, this, &ConnectionHandler::newTextMessageFromClient);
connect(newConnection, &ClientConnection::disconnected, this, &ConnectionHandler::clientDisconnected);
connect(newConnection, &ClientConnection::finished, newConnection, &ClientConnection::deleteLater);
m_connections.insert(newConnection);
emit clientConnected(newConnection);
INFO_LOG(m_logger) << "New client connected ip: " << socket->localAddress().toString() << ":"
<< socket->localPort();
ERROR_LOG(m_logger) << "Failed to initialise new client";
delete newConnection;
newConnection = nullptr;
continue;
}
newConnection->start();
connect(newConnection, &ClientConnection::newTextMessage, this, &ConnectionHandler::newTextMessageFromClient);
connect(newConnection, &ClientConnection::disconnected, this, &ConnectionHandler::clientDisconnected);
connect(newConnection, &ClientConnection::finished, newConnection, &ClientConnection::deleteLater);
m_connections.insert(newConnection);
emit clientConnected(newConnection);
INFO_LOG(m_logger) << "New client connected ip: " << socket->localAddress().toString() << ":" << socket->localPort();
}
}
#endif
Loaded 100 of 745 files, more files were not shown because too many files have changed in this diff. Show more