diff --git a/qt6-after/qt6-migrated-legatus/CMakeLists.txt b/qt6-after/qt6-migrated-legatus/CMakeLists.txt index 002ecd75e..3f699e624 100755 --- a/qt6-after/qt6-migrated-legatus/CMakeLists.txt +++ b/qt6-after/qt6-migrated-legatus/CMakeLists.txt @@ -221,9 +221,11 @@ IF(WIN32) 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 + # Use environment variable ARCGIS_ROOT if set, otherwise check relative to source dir, then Docker/host paths IF(DEFINED ENV{ARCGIS_ROOT}) SET(ARCGIS_SDK_DIR "$ENV{ARCGIS_ROOT}" CACHE STRING "ArcGIS Runtime SDK for Qt directory") + ELSEIF(EXISTS "${CMAKE_SOURCE_DIR}/external/ArcGIS/MapsSDK_Qt_300.0.0/ArcGIS_Maps_SDK_Qt_300.0.0/qt300.0.0/sdk") + SET(ARCGIS_SDK_DIR "${CMAKE_SOURCE_DIR}/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") 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() @@ -242,12 +244,6 @@ ENDIF() 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) @@ -621,6 +617,12 @@ endif() MESSAGE(STATUS "Qt version is ${Qt6Core_VERSION}, GUI available: ${QT6_GUI_AVAILABLE}") +# Find ArcGIS SDK after Qt6 is configured +# This creates ArcGIS::ArcGIS target for all modules to use +IF(BUILD_ARCGIS) + FIND_PACKAGE(ArcGIS REQUIRED) +ENDIF() + # # RTI Connext DDS - manuelle Konfiguration da keine CMake Config Files vorhanden # diff --git a/qt6-after/qt6-migrated-legatus/Lts/Common/LtsWidgets/CMakeLists.txt b/qt6-after/qt6-migrated-legatus/Lts/Common/LtsWidgets/CMakeLists.txt index f9df0badd..cdf9a9a80 100755 --- a/qt6-after/qt6-migrated-legatus/Lts/Common/LtsWidgets/CMakeLists.txt +++ b/qt6-after/qt6-migrated-legatus/Lts/Common/LtsWidgets/CMakeLists.txt @@ -161,7 +161,7 @@ NGL_TARGET_INCLUDE_DIRECTORIES(LtsWidgets NGL_TARGET_LINK_LIBRARIES(LtsWidgets PRIVATE Qt6::Network # for QHostInfo - for portability - Qt6::Svg + $,Qt6::Svg,> ngltools ngltranslator NGLLogger diff --git a/qt6-after/qt6-migrated-legatus/Lts/Common/LtsWidgets/lts_base_layout_widget.cpp b/qt6-after/qt6-migrated-legatus/Lts/Common/LtsWidgets/lts_base_layout_widget.cpp index 08a6b2f15..0c26d116a 100644 --- a/qt6-after/qt6-migrated-legatus/Lts/Common/LtsWidgets/lts_base_layout_widget.cpp +++ b/qt6-after/qt6-migrated-legatus/Lts/Common/LtsWidgets/lts_base_layout_widget.cpp @@ -39,7 +39,9 @@ #include #include #include -#include +#ifdef QT_SVG_LIB +#include +#endif #include #include #include @@ -399,6 +401,7 @@ void LtsBaseLayoutWidget::showEvent(QShowEvent *event) { const QSize s(QSize(rendererSizeHint.height(), rendererSizeHint.height()) * dpr); // RDE SPLITTER LEFT +#ifdef QT_SVG_LIB QSvgRenderer svgRenderer; QPixmap pixmap(s); pixmap.fill(Qt::transparent); @@ -410,6 +413,9 @@ void LtsBaseLayoutWidget::showEvent(QShowEvent *event) pixmap.setDevicePixelRatio(dpr); m_ui->lbRdeSplitterLeft->setPixmap(pixmap); +#else + qWarning() << "QSvgRenderer not available - skipping SVG rendering for splitter"; +#endif } { diff --git a/qt6-after/qt6-migrated-legatus/Lts/Common/LtsWidgets/lts_column_filter_proxy_model.cpp b/qt6-after/qt6-migrated-legatus/Lts/Common/LtsWidgets/lts_column_filter_proxy_model.cpp index 56c06401a..a047bbc10 100644 --- a/qt6-after/qt6-migrated-legatus/Lts/Common/LtsWidgets/lts_column_filter_proxy_model.cpp +++ b/qt6-after/qt6-migrated-legatus/Lts/Common/LtsWidgets/lts_column_filter_proxy_model.cpp @@ -63,8 +63,7 @@ void LtsColumnFilterProxyModel::setColumnStringFilter(const QString &newFilterSt it.value() = rx; } } - beginFilterChange(); - endFilterChange(); + invalidateFilter(); } void LtsColumnFilterProxyModel::setColumnDataFilter(const QVariant &newFilterData, int column) @@ -91,8 +90,7 @@ void LtsColumnFilterProxyModel::setColumnDataFilter(const QVariant &newFilterDat it.value() = newFilterData; } } - beginFilterChange(); - endFilterChange(); + invalidateFilter(); } @@ -140,8 +138,7 @@ void LtsColumnFilterProxyModel::setRecursiveFilteringEnabled(bool recursive) if (m_bRecursiveFiltering == recursive) return; m_bRecursiveFiltering = recursive; - beginFilterChange(); - endFilterChange(); + invalidateFilter(); } bool LtsColumnFilterProxyModel::recursiveFilteringEnabled() const diff --git a/qt6-after/qt6-migrated-legatus/Lts/Common/LtsWidgets/lts_dialog.cpp b/qt6-after/qt6-migrated-legatus/Lts/Common/LtsWidgets/lts_dialog.cpp index 1bf897677..2605ae850 100644 --- a/qt6-after/qt6-migrated-legatus/Lts/Common/LtsWidgets/lts_dialog.cpp +++ b/qt6-after/qt6-migrated-legatus/Lts/Common/LtsWidgets/lts_dialog.cpp @@ -389,7 +389,7 @@ void LtsDialog::addConnections(QWidget *widget) if (addChangesMadeSignal(widget, &QLineEdit::textChanged)) return; if (addChangesMadeSignal(widget, &QDateTimeEdit::dateTimeChanged)) return; if (addChangesMadeSignal(widget, &QComboBox::currentTextChanged)) return; - if (addChangesMadeSignal(widget, &QCheckBox::checkStateChanged)) return; + if (addChangesMadeSignal(widget, &QCheckBox::stateChanged)) return; if (addChangesMadeSignal(widget, static_cast(&QSpinBox::valueChanged))) return; if (addChangesMadeSignal(widget, static_cast(&QDoubleSpinBox::valueChanged))) return; if (addChangesMadeSignal(widget, &QSlider::valueChanged)) return; diff --git a/qt6-after/qt6-migrated-legatus/Lts/Common/LtsWidgets/lts_msec_date_time_edit.cpp b/qt6-after/qt6-migrated-legatus/Lts/Common/LtsWidgets/lts_msec_date_time_edit.cpp index b88fa9309..4271c46d8 100644 --- a/qt6-after/qt6-migrated-legatus/Lts/Common/LtsWidgets/lts_msec_date_time_edit.cpp +++ b/qt6-after/qt6-migrated-legatus/Lts/Common/LtsWidgets/lts_msec_date_time_edit.cpp @@ -1,4 +1,5 @@ #include "lts_msec_date_time_edit.h" +#include namespace LtsWidgets diff --git a/qt6-after/qt6-migrated-legatus/Lts/Tools/LogViewer/sortfiltermodel.cpp b/qt6-after/qt6-migrated-legatus/Lts/Tools/LogViewer/sortfiltermodel.cpp index 327115fad..3ae7341f1 100755 --- a/qt6-after/qt6-migrated-legatus/Lts/Tools/LogViewer/sortfiltermodel.cpp +++ b/qt6-after/qt6-migrated-legatus/Lts/Tools/LogViewer/sortfiltermodel.cpp @@ -17,8 +17,7 @@ void SortFilterModel::setStartDateFilter(const QDateTime &start) if (m_start == start) return; m_start = start; - beginFilterChange(); - endFilterChange(); + invalidateFilter(); } @@ -27,8 +26,7 @@ void SortFilterModel::setEndDateFilter(const QDateTime &end) if (m_end == end) return; m_end = end; - beginFilterChange(); - endFilterChange(); + invalidateFilter(); } void SortFilterModel::figureFilterOut() @@ -43,8 +41,7 @@ void SortFilterModel::resetAllFilter() m_start = QDateTime(); m_end = QDateTime(); figureFilterOut(); - beginFilterChange(); - endFilterChange(); + invalidateFilter(); } diff --git a/qt6-after/qt6-migrated-legatus/Lts/Viewer/LtsFileDialog/lts_dialog_model_folder.cpp b/qt6-after/qt6-migrated-legatus/Lts/Viewer/LtsFileDialog/lts_dialog_model_folder.cpp index 116cfeb74..7eb83b0be 100755 --- a/qt6-after/qt6-migrated-legatus/Lts/Viewer/LtsFileDialog/lts_dialog_model_folder.cpp +++ b/qt6-after/qt6-migrated-legatus/Lts/Viewer/LtsFileDialog/lts_dialog_model_folder.cpp @@ -346,7 +346,7 @@ void DialogModelProxyFolder::setOperatorId(int operatorId) return; m_operatorId = operatorId; beginFilterChange(); - endFilterChange(); + endFilterChange(); } } // namespace LtsWidgets diff --git a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/CMakeLists.txt b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/CMakeLists.txt index 60b39164a..af3ed2062 100755 --- a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/CMakeLists.txt +++ b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/CMakeLists.txt @@ -1,36 +1,587 @@ # # $Id$ +# $HeadURL$ # $Author$ # -# Minimal CMakeLists.txt for Qt6 migration - only Symbology subdirectory -# Full migration pending +FIND_PACKAGE(ArcGIS REQUIRED) +ADD_SUBDIRECTORY(ArcGISQt5Hack) -# Only migrate Symbology for now +# During development: (instead top CMakeLists.txt" +IF(NOT MSVC) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wextra") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra") +ENDIF() +OPTION(BUILD_SITMAP_UNIT_TESTS "Build situation map unit tests" ON) + + +SET(GraphicalObjects_SRCS + GraphicalObjects/abstract_graphical_object.cpp + GraphicalObjects/ellipse_parameters.cpp + GraphicalObjects/graphical_object_attributes.h + GraphicalObjects/graphical_object_attributes.cpp + GraphicalObjects/graphical_object_ellipse.cpp + GraphicalObjects/graphical_object_multi_path.cpp + GraphicalObjects/graphical_object_path.cpp + GraphicalObjects/graphical_object_picture_marker.cpp + GraphicalObjects/graphical_object_range.cpp + GraphicalObjects/graphical_object_text.cpp + GraphicalObjects/tactical_appearance.cpp + GraphicalObjects/graphical_object_cube.cpp + + GraphicalObjects/graphical_object_scene_marker.cpp + GraphicalObjects/graphical_object_model_scene_marker.cpp + GraphicalObjects/graphical_object_renderer_attributes.cpp +) +SET(GraphicalObjects_HDRS + GraphicalObjects/abstract_graphical_object.h + GraphicalObjects/ellipse_parameters.h + GraphicalObjects/graphical_object_ellipse.h + GraphicalObjects/graphical_object_multi_path.h + GraphicalObjects/graphical_object_picture_marker.h + GraphicalObjects/graphical_object_path.h + GraphicalObjects/graphical_object_range.h + GraphicalObjects/graphical_object_text.h + GraphicalObjects/stub_graphical_object.h + GraphicalObjects/tactical_appearance.h + GraphicalObjects/graphical_object_cube.h + + GraphicalObjects/graphical_object_scene_marker.h + GraphicalObjects/graphical_object_model_scene_marker.h + GraphicalObjects/graphical_object_renderer_attributes.cpp +) + +QT6_ADD_RESOURCES(GraphicalObjects_SRCS Resources/situation_map.qrc) + +SET(Map_SRCS + Map/bounding_box.cpp + Map/fill_style.cpp + Map/line_style.cpp + Map/map.cpp + Map/map_notifier.cpp + Map/map_settings.cpp + Map/map_initializer.cpp + Map/object_container.cpp + Map/object_factory.cpp + Map/operator_map_settings.cpp +# Map/point3D.cpp + Map/party_id_to_color_functor.cpp +# Map/scene_marker_data.cpp + Map/situation_map_utils.cpp + Map/terrain_profile_parameter.cpp + Map/text_style.cpp + Map/geometry_model_renderer.cpp + Map/viewshed_parameter.cpp +) + +SET(Map_HDRS + Map/situation_map_ahtc.ini + Map/situation_map_defaults.ini + Map/situation_map_guez.ini + Map/situation_map_qatar.ini + Map/situation_map_guez_tablet.ini + Map/situation_map_ahtc_tablet.ini + Map/abstract_effect_simulation.h + Map/abstract_map_object.h + Map/bounding_box.h + Map/camera.h + Map/camera.cpp + Map/coord_translation_functor.h +# Map/drop_event_manager.h + Map/fill_style.h + Map/generic_object_factory.h + Map/grid.h + Map/map.h + Map/map_notifier.h + Map/map_settings.h + Map/map_initializer.h + Map/measurement.h + Map/layer_factory.h + Map/layer_parameter.h + Map/layer_parameter.cpp + Map/location_display.h + Map/line_style.h + Map/object_container.h + Map/object_factory.h + Map/object_indicator.h + Map/operator_map_settings.h + Map/overview_map_handler.h + Map/party_id_to_color_functor.h + Map/pixel_based_textbox_handler.h + Map/point3D.h +# Map/scene_marker_data.cpp + Map/sidc_symbol.h + Map/sight_fan.h + Map/situation_map_utils.h + Map/situation_map_types.h + Map/terrain_profile_parameter.h + Map/terrain_profile.h + Map/text_style.h + Map/viewpoint2D.h + Map/viewpoint2D.cpp + Map/viewshed_parameter.h + Map/viewshed.h + Map/camera.h + Map/camera.cpp + + Map/overlay_handler.h + Map/geometry_model_renderer.h +) + +SET(MapImpl_SRCS + MapImpl/abstract_effect_simulation_impl.cpp + MapImpl/abstract_effect_simulation_impl.h + MapImpl/abstract_map_object_impl.cpp + MapImpl/abstract_map_object_impl.h + MapImpl/coordinate_translation.cpp + MapImpl/coordinate_translation_thread.cpp + MapImpl/grid_impl.cpp + MapImpl/jump_point_model.cpp + MapImpl/jump_point_custom_view.cpp + MapImpl/jump_point_widget.cpp + MapImpl/logical_layer.cpp + MapImpl/layer_factory_impl.cpp + MapImpl/layer_control_widget.cpp + MapImpl/screen_location_elevation_helper_base.cpp + MapImpl/location_display_impl.cpp + MapImpl/location_to_elevation_helper.cpp + MapImpl/location_to_elevation_bulk.cpp + MapImpl/map_impl.cpp + MapImpl/map_layer.cpp + MapImpl/measurement_impl.cpp + MapImpl/object_container_impl.cpp + MapImpl/object_indicator_impl.cpp + MapImpl/overview_map_handler_impl.cpp + MapImpl/pixel_based_textbox_handler_impl.cpp + MapImpl/screen_to_location_helper.cpp + MapImpl/sidc_symbol_impl.cpp + MapImpl/sight_fan_impl.cpp + MapImpl/terrain_profile_impl.cpp + MapImpl/terrain_profile_processor.cpp +# MapImpl/tms_layer.cpp + MapImpl/viewshed_base.cpp + MapImpl/viewshed_analysis.cpp + MapImpl/viewshed_geo_processing.cpp + MapImpl/viewshed_base.cpp + MapImpl/viewshed_impl.cpp + MapImpl/jump_point_namer.cpp + + + MapImpl/geometry_model_renderer_esri.cpp + MapImpl/overlay_handler_impl.cpp +) + +SET(MapImpl_HDRS + MapImpl/abstract_effect_simulation_impl.h + MapImpl/abstract_map_object_impl.h + MapImpl/coordinate_translation.h + MapImpl/coordinate_translation_thread.h + MapImpl/coord_translation_functor_impl.h + MapImpl/geometry_model_renderer_esri.h + MapImpl/grid_impl.cpp + MapImpl/grid_impl.h + MapImpl/jump_point_model.h + MapImpl/jump_point_custom_view.h + MapImpl/jump_point_widget.h + MapImpl/logical_layer.h + MapImpl/layer_control_widget.h + MapImpl/layer_factory_impl.h + MapImpl/screen_location_elevation_helper_base.h + MapImpl/location_display_impl.h + MapImpl/location_to_elevation_helper.h + MapImpl/location_to_elevation_bulk.h + MapImpl/map_impl.h + MapImpl/map_layer.h + MapImpl/measurement_impl.h + MapImpl/object_container_impl.h + MapImpl/object_indicator_impl.h + MapImpl/overview_map_handler_impl.h + MapImpl/overlay_handler_impl.h + MapImpl/pixel_based_textbox_handler_impl.h + MapImpl/screen_to_location_helper.h + MapImpl/sidc_symbol_impl.h + MapImpl/sight_fan_impl.h + MapImpl/terrain_profile_impl.h + MapImpl/terrain_profile_processor.h +# MapImpl/tms_layer.h + MapImpl/viewshed_base.h + MapImpl/viewshed_analysis.h + MapImpl/viewshed_geo_processing.h + MapImpl/viewshed_impl.h + MapImpl/jump_point_namer.h +) + + + +SET(MapObj_SRCS + MapObjects/geometry.cpp +) + +SET(MapObj_HDRS + MapObjects/abstract_multi_point_map_object.h + MapObjects/abstract_single_point_map_object.h + MapObjects/air_support.h + MapObjects/area_fire.h + MapObjects/biological_agent.h + MapObjects/building_outline.h + MapObjects/chemical_agent.h + MapObjects/cube.h + MapObjects/danger_area.h + MapObjects/functional_area.h + MapObjects/geo_image.h + MapObjects/geometry.h + MapObjects/hit_line.h + MapObjects/line_of_sight.h + MapObjects/map_object_attributes.h + MapObjects/map_object_indicator.h + MapObjects/mine.h + MapObjects/mine_field.h + MapObjects/nuclear_agent.h + MapObjects/participant.h + MapObjects/polygon.h + MapObjects/polyline.h + MapObjects/single_fire.h +# MapObjects/single_fire_central.h + MapObjects/sound_area.h + MapObjects/text.h + MapObjects/virtual_mine.h + #situation_map_objects_export.h +) + + +SET (LayerAggregation_SRCS + LayerAggregation/layer_aggregation_widget.cpp + LayerAggregation/participant_aggregation_dialog.cpp +) + +SET (LayerAggregation_HDRS + LayerAggregation/layer_aggregation_widget.h + LayerAggregation/participant_aggregation_dialog.h +) + + +SET(Rubberbands_SRCS + Rubberbands/abstract_event_dispatcher.cpp + Rubberbands/drawable_ellipse.cpp + Rubberbands/drawable_line.cpp + Rubberbands/drawable_painter_path.cpp + Rubberbands/drawable_smooth_path.cpp + Rubberbands/event_delegater.cpp + Rubberbands/event_dispatcher.cpp + Rubberbands/event_mouse_navigator.cpp + Rubberbands/gestures.cpp + Rubberbands/rubberband_base.cpp + Rubberbands/rubberband.cpp + Rubberbands/rubberband_3d.cpp + Rubberbands/rubberband_arrow.cpp + Rubberbands/rubberband_corridor.cpp + Rubberbands/rubberband_drawable.cpp + Rubberbands/rubberband_factory.cpp + Rubberbands/rubberband_frame_handle.cpp + Rubberbands/rubberband_free_hand.cpp + Rubberbands/rubberband_ellipse.cpp + Rubberbands/rubberband_ellipse_handle.cpp + Rubberbands/rubberband_handle.cpp + Rubberbands/rubberband_handle_proxy.cpp + Rubberbands/rubberband_internal.cpp + Rubberbands/rubberband_line_handle.cpp + Rubberbands/rubberband_multi_point_feature.cpp + Rubberbands/rubberband_multi_ellipse_feature.cpp + Rubberbands/rubberband_multi_point_feature_3d.cpp + Rubberbands/rubberband_point_handle.cpp + Rubberbands/rubberband_point_cluster.cpp + Rubberbands/rubberband_point_feature.cpp + Rubberbands/rubberband_point_feature_3d.cpp + Rubberbands/rubberband_polyline_width.cpp + Rubberbands/rubberband_rectangle.cpp + Rubberbands/rubberband_smooth_line.cpp + Rubberbands/rubberband_state_select.cpp + Rubberbands/rubberband_transform.cpp + Rubberbands/rubberband_transform_move.cpp + Rubberbands/rubberband_transform_rotate.cpp + Rubberbands/rubberband_transform_scale.cpp + Rubberbands/transient_tactical_symbol.cpp +) + +SET(Rubberbands_HDRS + Rubberbands/abstract_event_dispatcher.h + Rubberbands/drawable_ellipse.h + Rubberbands/drawable_line.h + Rubberbands/drawable_painter_path.h + Rubberbands/drawable_smooth_path.h + Rubberbands/event_delegater.h + Rubberbands/event_dispatcher.h + Rubberbands/event_mouse_navigator.h + Rubberbands/gestures.h + Rubberbands/rubberband_free_hand.h + Rubberbands/rubberband_base.h + Rubberbands/rubberband_base_internal.h + Rubberbands/rubberband.h + Rubberbands/rubberband_3d.h + Rubberbands/rubberband_arrow.h + Rubberbands/rubberband_corridor.h + Rubberbands/rubberband_drawable.h + Rubberbands/rubberband_ellipse.h + Rubberbands/rubberband_ellipse_handle.h + Rubberbands/rubberband_factory.h + Rubberbands/rubberband_frame_handle.h + Rubberbands/rubberband_handle.h + Rubberbands/rubberband_handle_proxy.h + Rubberbands/rubberband_internal.h + Rubberbands/rubberband_line_handle.h + Rubberbands/rubberband_multi_point_feature.h + Rubberbands/rubberband_multi_ellipse_feature.h + Rubberbands/rubberband_multi_point_feature_3d.h + Rubberbands/rubberband_point_cluster.h + Rubberbands/rubberband_point_feature.h + Rubberbands/rubberband_point_feature_3d.h + Rubberbands/rubberband_point_handle.h + Rubberbands/rubberband_polyline_width.h + Rubberbands/rubberband_rectangle.h + Rubberbands/rubberband_smooth_line.h + Rubberbands/rubberband_state_select.h + Rubberbands/rubberband_transform.h + Rubberbands/rubberband_transform_move.h + Rubberbands/rubberband_transform_rotate.h + Rubberbands/rubberband_transform_scale.h + Rubberbands/transient_tactical_symbol.h +) + +SET(Utils_SRCS + situation_map_export.h + Utils/movement_track.cpp + Utils/movement_track_manager.cpp + Utils/terrain_profile_dialog.cpp +) + +SET(Utils_HDRS + Utils/movement_track.h + Utils/movement_track_manager.h + Utils/terrain_profile_dialog.h +) + + + +SET(MathUtils_SRCS + MathUtils/clipper.cpp + MathUtils/curve.cpp + MathUtils/geometry_engine.cpp + MathUtils/matrix2d.cpp + MathUtils/path_rasterer.cpp + MathUtils/simple_helper.cpp +) + +SET(MathUtils_HDRS + MathUtils/clipper.hpp + MathUtils/curve.h + MathUtils/geometry_engine.h + MathUtils/matrix2d.h + MathUtils/math_const.h + MathUtils/path_rasterer.h + MathUtils/simple_helper.h +) + +NGL_WRAP_UI(Utils_HDRS + MapImpl/jump_point_custom_view.ui + Utils/terrain_profile_dialog.ui +) + +NGL_WRAP_UI(MapImpl_SRCS + MapImpl/jump_point_namer.ui +) + + +SOURCE_GROUP(GraphicalObjects FILES ${GraphicalObjects_SRCS} ${GraphicalObjects_HDRS}) +SOURCE_GROUP(Map FILES ${Map_SRCS} ${Map_HDRS} ${MapImpl_SRCS} ${MapImpl_HDRS}) +SOURCE_GROUP(MapObjects FILES ${MapObj_HDRS}) +SOURCE_GROUP(LayerAggregation FILES ${LayerAggregation_SRCS} ${LayerAggregation_HDRS}) +SOURCE_GROUP(Rubberband FILES ${Rubberbands_SRCS} ${Rubberbands_HDRS}) +SOURCE_GROUP(Utils FILES ${Utils_SRCS} ${Utils_HDRS}) +SOURCE_GROUP(MathUtils FILES ${MathUtils_SRCS} ${MathUtils_HDRS}) +SOURCE_GROUP(SideBar FILES ${SideBar_SRCS} ${SideBar_HDRS}) + + +NGL_ADD_LIBRARY(WS situationMap SHARED +# ${FunctionDialog_SRCS} + ${Map_SRCS} ${Map_HDRS} ${MapImpl_SRCS} + ${MapObj_SRCS} ${MapObj_HDRS} + ${GraphicalObjects_SRCS} ${GraphicalObjects_HDRS} + ${LayerAggregation_SRCS} ${LayerAggregation_HDRS} + ${Rubberbands_SRCS} + ${Utils_SRCS} ${Utils_HDRS} + ${MathUtils_SRCS} ${MathUtils_HDRS} +) + +NGL_TARGET_INCLUDE_DIRECTORIES(situationMap + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/.. +) + + +NGL_TARGET_LINK_LIBRARIES(situationMap + PRIVATE + NGLLogger + ArcGIS::ArcGIS + Qt6::Concurrent + Qt6::Network + Qt6::PrintSupport + LtsCoordTrans + ArcGISQt5Hack + PUBLIC + Qt6::Core + Qt6::Widgets + LtsUtilsCoreHeaderOnly # QPoint3D + LtsWidgets + LtsDataView + situationMapCommon + situationMapElevationMap + situationMapSideBar + advancedSymbology + situationMapGeometryModel + ngltools +) + +# Copy on LIBchanges: +IF(TARGET situationMap) + SET(SYMBOLE_CSV symbole2.csv) + ADD_CUSTOM_COMMAND(TARGET situationMap POST_BUILD + COMMAND ${CMAKE_COMMAND} + ARGS -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/FunctionDialog/${SYMBOLE_CSV} $/${SYMBOLE_CSV} + ) + + + + + # copy ini to build-dir/share/Lts/situation_map/: + SET(INI_DEST_DIR ${CMAKE_BINARY_DIR}/share/Lts/situation_map) + + SET(SITUATIONMAPSETTINGS_INI situation_map_defaults.ini) + SET(SITUATIONMAPSETTINGS_INI_PATH Map/${SITUATIONMAPSETTINGS_INI}) + ADD_CUSTOM_COMMAND(TARGET situationMap POST_BUILD + COMMAND ${CMAKE_COMMAND} + ARGS -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/${SITUATIONMAPSETTINGS_INI_PATH} ${INI_DEST_DIR}/${SITUATIONMAPSETTINGS_INI} + ) + + SET(SITUATIONMAPSETTINGS_INI situation_map_defaults.ini) + SET(SITUATIONMAPSETTINGS_INI_PATH Map/${SITUATIONMAPSETTINGS_INI}) + + #check if we need to change it + IF(BUILD_RPM AND DEFINED _pname) + + IF(UNIX AND "${_pname}" STREQUAL "guez") + MESSAGE("Install situationmap ini for GUEZ") + SET(SITUATIONMAPSETTINGS_INI_PATH Map/situation_map_guez.ini) + + SET(TABLET_SITUATIONMAPSETTINGS_INI_PATH Map/situation_map_guez_tablet.ini) + + ElseIF(UNIX AND "${_pname}" STREQUAL "ahtc") + MESSAGE("Install situationmap ini for AHTC") + SET(SITUATIONMAPSETTINGS_INI_PATH Map/situation_map_ahtc.ini) + + SET(TABLET_SITUATIONMAPSETTINGS_INI_PATH Map/situation_map_ahtc_tablet.ini) + + ElseIF(UNIX AND "${_pname}" STREQUAL "l400p2") + MESSAGE("Install situationmap ini for L400P2") + SET(SITUATIONMAPSETTINGS_INI_PATH Map/situation_map_land400.ini) + + SET(TABLET_SITUATIONMAPSETTINGS_INI_PATH Map/situation_map_l400p2_tablet.ini) + + ElseIF(UNIX AND "${_pname}" STREQUAL "qatar") + MESSAGE("Install situationmap ini for Qatar") + SET(SITUATIONMAPSETTINGS_INI_PATH Map/situation_map_qatar.ini) + + SET(TABLET_SITUATIONMAPSETTINGS_INI_PATH Map/situation_map_qatar_tablet.ini) + + ElseIF(UNIX AND "${_pname}" STREQUAL "qatarmout") + MESSAGE("Install situationmap ini for Qatar Mout") + SET(SITUATIONMAPSETTINGS_INI_PATH Map/situation_map_qatarmout.ini) + + SET(TABLET_SITUATIONMAPSETTINGS_INI_PATH Map/situation_map_qatar_tablet.ini) + + ElseIF(UNIX AND "${_pname}" STREQUAL "commaster") + MESSAGE("Install situationmap ini for ComMaster/Luxemburg") + SET(SITUATIONMAPSETTINGS_INI_PATH Map/situation_map_luxemburg.ini) + + SET(TABLET_SITUATIONMAPSETTINGS_INI_PATH Map/situation_map_luxemburg_tablet.ini) + + + ENDIF() + + + ENDIF() + +#now that we set the situation map ini if neccecsary we install it depending of the tablet build or not +IF(TABLET_MODE) + NGL_INSTALL(WS FILES ${TABLET_SITUATIONMAPSETTINGS_INI_PATH} DESTINATION "./share/Lts/situation_map" RENAME ${SITUATIONMAPSETTINGS_INI}) +ELSE() + NGL_INSTALL(WS FILES ${SITUATIONMAPSETTINGS_INI_PATH} DESTINATION "./share/Lts/situation_map" RENAME ${SITUATIONMAPSETTINGS_INI}) +ENDIF() + +ENDIF() + +IF(BUILD_TESTING AND BUILD_SITMAP_UNIT_TESTS) + + NGL_ADD_LIBRARY(WS NO_TRANSLATION situationMap_static STATIC + ${FunctionDialog_SRCS} + ${Map_SRCS} ${Map_HDRS} ${MapImpl_SRCS} + ${MapObj_SRCS} ${MapObj_HDRS} + ${GraphicalObjects_SRCS} + ${Rubberbands_SRCS} + ${Utils_SRCS} ${Utils_HDRS} + ${MathUtils_SRCS} ${MathUtils_HDRS} + ) + NGL_TARGET_COMPILE_DEFINITIONS(situationMap_static PUBLIC "SITUATIONMAP_EXPORT=") + + NGL_TARGET_INCLUDE_DIRECTORIES(situationMap_static + INTERFACE + ${CMAKE_CURRENT_SOURCE_DIR} + ) + + NGL_TARGET_LINK_LIBRARIES(situationMap_static + PRIVATE + NGLLogger + Qt6::Concurrent + Qt6::Network + Qt6::PrintSupport + LtsCoordTrans + ArcGISQt5Hack + PUBLIC + Qt6::Core + Qt6::Widgets + LtsUtilsCoreHeaderOnly # QPoint3D + LtsWidgets + LtsDataView + situationMapCommon + situationMapElevationMap + situationMapSideBar + advancedSymbology_static + situationMapGeometryModel + ngltools + ) +ENDIF() + +NGL_INSTALL_TARGET(situationMap) + + +# Choose logical order instead of alphabetical. +# UnitTest should be performed BEFORE ModuleTest ADD_SUBDIRECTORY(Common) -ADD_SUBDIRECTORY(SymbologyXML) -ADD_SUBDIRECTORY(Symbology) -# ElevationMapManager compatibility stub (src/ + include/ scaffolding) needed by LtsElevation ADD_SUBDIRECTORY(ElevationMap) +ADD_SUBDIRECTORY(Symbology) +ADD_SUBDIRECTORY(SymbologyGui) +ADD_SUBDIRECTORY(SymbologyXML) +ADD_SUBDIRECTORY(MapObjectsImpl) +#ADD_SUBDIRECTORY(LocalSrv) -# Remaining subdirectories not yet migrated: -# ADD_SUBDIRECTORY(SymbologyGui) -# ADD_SUBDIRECTORY(SymbologyXML) -# ADD_SUBDIRECTORY(MapObjectsImpl) -# ADD_SUBDIRECTORY(SideBar) -# ADD_SUBDIRECTORY(FunctionDialog) -# ADD_SUBDIRECTORY(GeometryModel) -# ADD_SUBDIRECTORY(Portal) -# ADD_SUBDIRECTORY(GraphicalObjects) -# ADD_SUBDIRECTORY(Map) -# ADD_SUBDIRECTORY(MapImpl) -# ADD_SUBDIRECTORY(MapObjects) -# ADD_SUBDIRECTORY(Rubberbands) -# ADD_SUBDIRECTORY(Utils) -# ADD_SUBDIRECTORY(MathUtils) -# ADD_SUBDIRECTORY(LayerAggregation) -# ADD_SUBDIRECTORY(LocalSrv) -# ADD_SUBDIRECTORY(Tests) -# ADD_SUBDIRECTORY(EvalApps) -# ADD_SUBDIRECTORY(UnitTests) -# ADD_SUBDIRECTORY(UnitTestsGeoModel) -# ADD_SUBDIRECTORY(ModuleTests) +ADD_SUBDIRECTORY(SideBar) +ADD_SUBDIRECTORY(FunctionDialog) +ADD_SUBDIRECTORY(GeometryModel) +ADD_SUBDIRECTORY(Portal) + +ADD_SUBDIRECTORY(Tests) + +IF(BUILD_SITMAP_UNIT_TESTS) + ADD_SUBDIRECTORY(EvalApps) + ADD_SUBDIRECTORY(UnitTests) + ADD_SUBDIRECTORY(UnitTestsGeoModel) + ADD_SUBDIRECTORY(ModuleTests) +ENDIF() diff --git a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/ElevationMap/CMakeLists.txt b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/ElevationMap/CMakeLists.txt index d17e3cb0b..6f915233a 100644 --- a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/ElevationMap/CMakeLists.txt +++ b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/ElevationMap/CMakeLists.txt @@ -4,34 +4,34 @@ # $Author$ # -# The GDAL-based ElevationMap module is not yet migrated to Qt6 (see the -# commented-out entries in ../CMakeLists.txt). LtsElevation still needs an -# ElevationMapManager, so build the compatibility stub that lives in the -# src/ + include/ scaffolding (same API as the Qt5 class, no GDAL). -NGL_ADD_LIBRARY(WS AAR HLA SV situationMapElevationMap SHARED - ${CMAKE_SOURCE_DIR}/src/Viewer/SituationMap/ElevationMap/elevation_map_manager.cpp - # The header lives in include/Viewer/SituationMap/ElevationMap, apart from - # the cpp. AUTOMOC only mocs headers that are target sources (or sit next - # to one); MOC_INCLUDES merely feeds moc's own -I flags, not header - # discovery. Listed explicitly, otherwise the vtable/staticMetaObject are - # undefined and the link of libsituationMapElevationMap.so fails. - ${CMAKE_SOURCE_DIR}/include/Viewer/SituationMap/ElevationMap/elevation_map_manager.h +# ElevationMap module - migrated to Qt6 +SET(Elevation_SRCS + elevation_map.cpp + elevation_map.h + elevation_map_manager.cpp + elevation_map_manager.h + line_of_sight_calculation.cpp + line_of_sight_calculation.h + situationmapelevationmap_export.h ) -# The stub's ElevationMapManager is a Q_OBJECT class; without AUTOMOC the -# moc symbols (staticMetaObject/vtable) are missing and the link of -# libsituationMapElevationMap.so fails, cascading to every target that -# links it (same pattern as LtsSessionDataDds). +NGL_ADD_LIBRARY(WS AAR HLA SV situationMapElevationMap SHARED ${Elevation_SRCS}) + set_target_properties(situationMapElevationMap PROPERTIES AUTOMOC ON) NGL_TARGET_INCLUDE_DIRECTORIES(situationMapElevationMap PUBLIC - # The stub cpp does #include "elevation_map_manager.h" - it lives in - # include/Viewer/SituationMap/ElevationMap/, not next to the source. - ${CMAKE_SOURCE_DIR}/include/Viewer/SituationMap/ElevationMap - ${CMAKE_SOURCE_DIR}/include + ${CMAKE_CURRENT_SOURCE_DIR}/../ + ${CMAKE_CURRENT_BINARY_DIR}/../ ) NGL_TARGET_LINK_LIBRARIES(situationMapElevationMap + PRIVATE + Qt6::Concurrent + Qt6::Gui + NGLLogger + LtsCoordTrans PUBLIC Qt6::Core + LtsUtilsCoreHeaderOnly + situationMapCommon ) diff --git a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Map/layer_factory.h b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Map/layer_factory.h index 1254621ac..b485f218c 100755 --- a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Map/layer_factory.h +++ b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Map/layer_factory.h @@ -12,7 +12,6 @@ #include "situation_map_types.h" #include -#include // This file is created by RME, not ESRI // Qt diff --git a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Map/map_initializer.cpp b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Map/map_initializer.cpp index 00ca18673..e46c6672f 100755 --- a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Map/map_initializer.cpp +++ b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Map/map_initializer.cpp @@ -18,7 +18,6 @@ #include #include -#include // This file is created by RME, not ESRI #include #include @@ -464,7 +463,7 @@ bool MapInitializer::setParticipantLayername() // Dynamic RenderMode has known issue related to military symbology at 3D. // recommendation: use static: RenderingMode renderingMode = RenderingMode::Dynamic; // ToDo V100: Dynamic vs. Static - SurfacePlacement surfacePlacement = SurfacePlacement::Draped; + SurfacePlacement surfacePlacement = SurfacePlacement::DrapedFlat; // RenderingMode const QString &rmName = sl[1]; @@ -864,7 +863,7 @@ bool MapInitializer::initializeOperationalLayers() // Dynamic RenderMode has known issue related to military symbology at 3D. // recommendation: use static: const RenderingMode defaultRenderingMode = RenderingMode::Dynamic; // ToDo V100: Dynamic vs. Static - const SurfacePlacement defaultSurfacePlacement = SurfacePlacement::Draped; + const SurfacePlacement defaultSurfacePlacement = SurfacePlacement::DrapedFlat; for (const QString &logicalLayerNameEncoded : operationLayers) { diff --git a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Map/situation_map_types.h b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Map/situation_map_types.h index 7a5ea8710..5fa711a59 100755 --- a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Map/situation_map_types.h +++ b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Map/situation_map_types.h @@ -189,9 +189,11 @@ enum class RenderingMode enum class SurfacePlacement { - Draped, ///< Draped (0) - Absolute, ///< Absolute (1) - Relative ///< Relative (2) + DrapedFlat = 4, ///< DrapedFlat (4) - renamed from Draped in ArcGIS SDK v300 + Absolute = 1, ///< Absolute (1) + Relative = 2, ///< Relative (2) + DrapedBillboarded = 0, ///< DrapedBillboarded (0) - new in ArcGIS SDK v300 + RelativeToScene = 3 ///< RelativeToScene (3) - new in ArcGIS SDK v300 }; @@ -303,15 +305,6 @@ struct SymbolData */ using PositionCont = QVector; -inline PositionCont convert2D3D(const QList &lst) -{ - PositionCont posCont; - posCont.reserve(lst.size()); - for (auto i : std::as_const(lst) ) - posCont.append(Point3D::fromQPointF(i)); - return posCont; -} - inline PositionCont convert2D3D(const QVector &vec) { PositionCont posCont; diff --git a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Map/situation_map_utils.cpp b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Map/situation_map_utils.cpp index 5a5a210d9..5c5bf477f 100755 --- a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Map/situation_map_utils.cpp +++ b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Map/situation_map_utils.cpp @@ -12,13 +12,14 @@ // Esri -#include // for LicenseStatus -#include -#include -#include +#include // for LicenseStatus +#include +#include +#include +#include +#include -#include // This file is created by RME, not ESRI #if ACRGIS_VERSION >= 0x640600 // 100.6.0 / Update 6 #define HAS_SURFACEPLACEMENT_RELATIVETOSCENE @@ -228,12 +229,16 @@ QString toString(SurfacePlacement value) { switch (value) { - case SurfacePlacement::Draped: - return QStringLiteral("Draped"); + case SurfacePlacement::DrapedFlat: + return QStringLiteral("DrapedFlat"); case SurfacePlacement::Absolute: return QStringLiteral("Absolute"); case SurfacePlacement::Relative: return QStringLiteral("Relative"); + case SurfacePlacement::DrapedBillboarded: + return QStringLiteral("DrapedBillboarded"); + case SurfacePlacement::RelativeToScene: + return QStringLiteral("RelativeToScene"); } // switch Q_ASSERT(false); return QStringLiteral("SurfacePlacementERROR"); @@ -241,9 +246,9 @@ QString toString(SurfacePlacement value) bool fromString(SituationMap::SurfacePlacement &surfacePlacement, const QString &str) { - if (str.compare(QStringLiteral("Draped")) == 0) + if (str.compare(QStringLiteral("DrapedFlat")) == 0) { - surfacePlacement = SurfacePlacement::Draped; + surfacePlacement = SurfacePlacement::DrapedFlat; return true; } if (str.compare(QStringLiteral("Absolute")) == 0) @@ -256,6 +261,16 @@ bool fromString(SituationMap::SurfacePlacement &surfacePlacement, const QString surfacePlacement = SurfacePlacement::Relative; return true; } + if (str.compare(QStringLiteral("DrapedBillboarded")) == 0) + { + surfacePlacement = SurfacePlacement::DrapedBillboarded; + return true; + } + if (str.compare(QStringLiteral("RelativeToScene")) == 0) + { + surfacePlacement = SurfacePlacement::RelativeToScene; + return true; + } return false; } @@ -378,7 +393,7 @@ QString toString(const Error &value) { std::ostringstream stream; stream << "Esri::ArcGISRuntime::Error: " - << " code=" << value.code() + << " errorType=" << (int)value.errorType() << ", domain=" << (int)value.domain() << ", extendedErrorType=" << (int)value.extendedErrorType() << ", message='" << value.message() << "'" @@ -496,8 +511,6 @@ QString toString(const Esri::ArcGISRuntime::LayerType value) return QStringLiteral("FeatureLayer"); case Esri::ArcGISRuntime::LayerType::KMLLayer: return QStringLiteral("KMLLayer"); - case Esri::ArcGISRuntime::LayerType::BingMapLayer: - return QStringLiteral("BingMapLayer"); case Esri::ArcGISRuntime::LayerType::RasterLayer: return QStringLiteral("RasterLayer"); case Esri::ArcGISRuntime::LayerType::UnsupportedLayer: @@ -539,9 +552,19 @@ QString toString(const Esri::ArcGISRuntime::LayerType value) #if ACRGIS_VERSION >= 0x640D00 // 100.13.0 case Esri::ArcGISRuntime::LayerType::DimensionLayer: - return QStringLiteral("SubtypeFeatureLayer"); + return QStringLiteral("DimensionLayer"); #endif // ACRGIS_VERSION + // ArcGIS SDK v300 new layer types + case Esri::ArcGISRuntime::LayerType::DynamicEntityLayer: + return QStringLiteral("DynamicEntityLayer"); + case Esri::ArcGISRuntime::LayerType::Ogc3dTilesLayer: + return QStringLiteral("Ogc3dTilesLayer"); + case Esri::ArcGISRuntime::LayerType::BuildingSceneLayer: + return QStringLiteral("BuildingSceneLayer"); + case Esri::ArcGISRuntime::LayerType::OrientedImageryLayer: + return QStringLiteral("OrientedImageryLayer"); + case Esri::ArcGISRuntime::LayerType::UnknownLayer: return QStringLiteral("UnknownLayer"); @@ -643,8 +666,6 @@ QString toString(const Esri::ArcGISRuntime::ViewpointType value) { switch (value) { - case Esri::ArcGISRuntime::ViewpointType::Unknown: - return QStringLiteral("Unknown"); case Esri::ArcGISRuntime::ViewpointType::CenterAndScale: return QStringLiteral("CenterAndScale"); case Esri::ArcGISRuntime::ViewpointType::BoundingGeometry: @@ -696,23 +717,16 @@ QString toString(Esri::ArcGISRuntime::SurfacePlacement value) { switch (value) { - case Esri::ArcGISRuntime::SurfacePlacement::Draped: - return QStringLiteral("Draped"); + case Esri::ArcGISRuntime::SurfacePlacement::DrapedBillboarded: + return QStringLiteral("DrapedBillboarded"); case Esri::ArcGISRuntime::SurfacePlacement::Absolute: return QStringLiteral("Absolute"); case Esri::ArcGISRuntime::SurfacePlacement::Relative: return QStringLiteral("Relative"); - -#ifdef HAS_SURFACEPLACEMENT_RELATIVETOSCENE case Esri::ArcGISRuntime::SurfacePlacement::RelativeToScene: return QStringLiteral("RelativeToScene"); -#endif // HAS_SURFACEPLACEMENT_RELATIVETOSCENE - -#if ACRGIS_VERSION >= 0x640700 // 100.7.0 / Update 7 case Esri::ArcGISRuntime::SurfacePlacement::DrapedFlat: return QStringLiteral("DrapedFlat"); -#endif // ACRGIS_VERSION - }// switch Q_ASSERT(false); return QStringLiteral("Esri-SurfacePlacementERROR"); diff --git a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Map/situation_map_utils.h b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Map/situation_map_utils.h index 174412c6a..2a5ef816b 100755 --- a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Map/situation_map_utils.h +++ b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Map/situation_map_utils.h @@ -13,8 +13,8 @@ // arcgis -#include // SurfacePlacement -#include +#include // SurfacePlacement +#include // Qt diff --git a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Symbology/sidc_builder.cpp b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Symbology/sidc_builder.cpp index fa595e4d1..e8d4f82f2 100755 --- a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Symbology/sidc_builder.cpp +++ b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Symbology/sidc_builder.cpp @@ -75,7 +75,7 @@ void SidcBuilder::setStandardIdentity(const SidcDefinitions::StandardIdentity &s SidcDefinitions::Context SidcBuilder::context() const { - return static_cast(QStringView(m_first10_mil2525D).slice(2, 1).toInt()); + return static_cast(QStringView(m_first10_mil2525D).sliced(2, 1).toInt()); } void SidcBuilder::setContext(SidcDefinitions::Context context) { @@ -83,7 +83,7 @@ void SidcBuilder::setContext(SidcDefinitions::Context context) } SidcDefinitions::Identity SidcBuilder::identity() const { - return static_cast(QStringView(m_first10_mil2525D).slice(3, 1).toInt()); + return static_cast(QStringView(m_first10_mil2525D).sliced(3, 1).toInt()); } void SidcBuilder::setIdentity(SidcDefinitions::Identity identity) @@ -112,7 +112,7 @@ bool SidcBuilder::isIdentityAssumed() const SidcDefinitions::SymbolSet SidcBuilder::symbolSet() const { - SymbolSet sset = static_cast(QStringView(m_first10_mil2525D).slice(4, 2).toString().toInt()); + SymbolSet sset = static_cast(QStringView(m_first10_mil2525D).sliced(4, 2).toString().toInt()); return sset; } void SidcBuilder::setSymbolSet(const SymbolSet &symbolSet) @@ -123,7 +123,7 @@ void SidcBuilder::setSymbolSet(const SymbolSet &symbolSet) SidcDefinitions::Status SidcBuilder::status() const { - Status status = static_cast(QStringView(m_first10_mil2525D).slice(6, 1).toInt()); + Status status = static_cast(QStringView(m_first10_mil2525D).sliced(6, 1).toInt()); return status; } @@ -156,7 +156,7 @@ void SidcBuilder::setSymbolEntityCode(const QString &entityCode) SidcDefinitions::HQTFDummy SidcBuilder::hqTfFd() const { - HQTFDummy hdtffd = static_cast(QStringView(m_first10_mil2525D).slice(7, 1).toInt()); + HQTFDummy hdtffd = static_cast(QStringView(m_first10_mil2525D).sliced(7, 1).toInt()); return hdtffd; } @@ -200,7 +200,7 @@ bool SidcBuilder::feintDummy() const SidcDefinitions::AmplifierGroup SidcBuilder::amplifierGroup() const { - AmplifierGroup amplifierGroup = static_cast(QStringView(m_first10_mil2525D).slice(8, 1).toInt()); + AmplifierGroup amplifierGroup = static_cast(QStringView(m_first10_mil2525D).sliced(8, 1).toInt()); return amplifierGroup; } void SidcBuilder::setAmplifierGroup(const AmplifierGroup &lifierGroup) @@ -210,7 +210,7 @@ void SidcBuilder::setAmplifierGroup(const AmplifierGroup &lifierGroup) unsigned int SidcBuilder::amplifier2ndDigit() const { - return QStringView(m_first10_mil2525D).slice(9, 1).toUInt(); + return QStringView(m_first10_mil2525D).sliced(9, 1).toUInt(); } // unsigned int SidcBuilder::amplifier2ndDigit() const @@ -222,13 +222,13 @@ void SidcBuilder::setAmplifier2ndDigit(unsigned int amplifierSecondDigit) unsigned int SidcBuilder::sectorModifier1Digit() { - return QStringView(m_second10_mil2525D).slice(6, 2).toUInt(); + return QStringView(m_second10_mil2525D).sliced(6, 2).toUInt(); } // unsigned int SidcBuilder::sectorModifier1Digit() unsigned int SidcBuilder::sectorModifier2Digit() { - return QStringView(m_second10_mil2525D).slice(8, 2).toUInt(); + return QStringView(m_second10_mil2525D).sliced(8, 2).toUInt(); } // unsigned int SidcBuilder::sectorModifier2Digit() @@ -313,7 +313,7 @@ bool SidcBuilder::initFromSymbologyType(SymbologyType symbologyType, const QStri } // check version - if (QStringView(rawSidc).slice(0, 2) != QLatin1String("10")) + if (QStringView(rawSidc).sliced(0, 2) != QLatin1String("10")) { ERROR_LOG(m_logger) << LOGFUNCTION << " sidc='" << sidc << "'" @@ -371,7 +371,7 @@ bool SidcBuilder::initFromSymbologyTypeBaseSymbolCode(SymbologyType symbologyTyp init(); // set SymbolSet: - SymbolSet sSet = static_cast(QStringView(rawBaseSymbolCode).slice(0, 2).toInt()); + SymbolSet sSet = static_cast(QStringView(rawBaseSymbolCode).sliced(0, 2).toInt()); this->setSymbolSet(sSet); // set Entity: diff --git a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Symbology/sidc_builder_base.cpp b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Symbology/sidc_builder_base.cpp index a2cb918d1..02c385fcc 100755 --- a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Symbology/sidc_builder_base.cpp +++ b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Symbology/sidc_builder_base.cpp @@ -163,8 +163,8 @@ QString SidcBuilderBase::concreteSidcToBaseSymbolCode(const QString &sidcCodec) return QString(); QString baseSymbolCode( - QStringView(rawSidc).slice(4, 2).toString() + - QStringView(rawSidc).slice(10, 6).toString()); + QStringView(rawSidc).sliced(4, 2).toString() + + QStringView(rawSidc).sliced(10, 6).toString()); return SidcCodec::encodeBaseSymbolCode(symbologyType, baseSymbolCode); } break; diff --git a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Symbology/sidc_codec.cpp b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Symbology/sidc_codec.cpp index 027694c87..044fc16db 100755 --- a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Symbology/sidc_codec.cpp +++ b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Symbology/sidc_codec.cpp @@ -92,9 +92,9 @@ bool SidcCodec::checkSidcSyntax(const QString &encodedSidc) { if (!isEncoded(encodedSidc)) return false; - SidcCodec::SidcType sidcType = SidcCodecHelper::decodeSidc(QStringView(encodedSidc).slice(5, 4)); + SidcCodec::SidcType sidcType = SidcCodecHelper::decodeSidc(QStringView(encodedSidc).sliced(5, 4)); - const QStringView symbologyTypeStr = QStringView(encodedSidc).slice(0, 4); + const QStringView symbologyTypeStr = QStringView(encodedSidc).sliced(0, 4); if (symbologyTypeStr.compare(QLatin1String("NONE")) == 0) return true; else if (symbologyTypeStr.compare(QLatin1String("AP6B")) == 0) return true; @@ -162,12 +162,12 @@ int SidcCodec::decodeCivilXml(const QString &civilSidc) SymbologyType SidcCodec::decodeSymbologyType(const QString &encodedSidc) { - return SidcCodecHelper::decodeSymbology(QStringView(encodedSidc).slice(0, 4)); + return SidcCodecHelper::decodeSymbology(QStringView(encodedSidc).sliced(0, 4)); } SidcCodec::SidcType SidcCodec::decodeSidcType(const QString &encodedSidc) { - return SidcCodecHelper::decodeSidc(QStringView(encodedSidc).slice(5, 4)); + return SidcCodecHelper::decodeSidc(QStringView(encodedSidc).sliced(5, 4)); } QString SidcCodec::decodeRawSidc(const QString &encodedSidc) diff --git a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Symbology/symbol_dictionary.h b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Symbology/symbol_dictionary.h index d6282af9b..70bfbb873 100755 --- a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Symbology/symbol_dictionary.h +++ b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Symbology/symbol_dictionary.h @@ -26,7 +26,6 @@ class QValidator; #ifdef BUILD_ARCGIS -# include // This file is created by RME, not ESRI #if ACRGIS_VERSION >= 0x640600 // 100.6.0 / Update 6 //# define USE_ARCADE_SYMBOLOGY diff --git a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Symbology/symbol_properties.cpp b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Symbology/symbol_properties.cpp index 81eca651d..8607c1334 100755 --- a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Symbology/symbol_properties.cpp +++ b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Symbology/symbol_properties.cpp @@ -119,13 +119,13 @@ QString SymbolProperties::key_SymbolSet() const { if (m_key.size() < 8) return QString(); - return QStringView(m_key).slice(0, 2).toString(); + return QStringView(m_key).sliced(0, 2).toString(); } QString SymbolProperties::key_Entity() const { if (m_key.size() < 8) return QString(); - return QStringView(m_key).slice(2, 6).toString(); + return QStringView(m_key).sliced(2, 6).toString(); } QString SymbolProperties::key_SymbolSetEntity() const diff --git a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Symbology/symbol_result.h b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Symbology/symbol_result.h index 68f463517..97fc7e52e 100755 --- a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Symbology/symbol_result.h +++ b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/Symbology/symbol_result.h @@ -163,7 +163,7 @@ protected: * * \code * AdvancedSymbology::SymbolResultWatcherComboxBox *srwCb; - foreach(auto sidc, sidcs) + for ( auto sidc, sidcs) { // SymbolResultWatcherComboxBox is stored as userData at every item. // The lifetime is limited to the lifetime of the comboBox since it`s the parent. diff --git a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/SymbologyImpl/base_symbol_model.cpp b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/SymbologyImpl/base_symbol_model.cpp index 6cb6e4770..295ffc666 100755 --- a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/SymbologyImpl/base_symbol_model.cpp +++ b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/SymbologyImpl/base_symbol_model.cpp @@ -18,8 +18,9 @@ // arcgis -#include #include +#include +#include // Qt @@ -31,6 +32,7 @@ #include #include #include +#include namespace AdvancedSymbology @@ -159,7 +161,7 @@ QString BaseSymbolItem::symbolSet() { if (m_symbolSet.isEmpty()) { - SidcDefinitions::SymbolSet symbolSet = SidcDefinitions::castToSymbolSet(m_symbolProperties.originalKey().left(2).toUInt() // Qt6: leftRef removed); + SidcDefinitions::SymbolSet symbolSet = SidcDefinitions::castToSymbolSet(m_symbolProperties.originalKey().left(2).toUInt()); // Qt6: leftRef removed m_symbolSet = QString(QStringLiteral("%1 - ")).arg(static_cast(symbolSet)) + AdvancedSymbology::SidcDefinitions::toString(symbolSet); } return m_symbolSet; @@ -167,7 +169,7 @@ QString BaseSymbolItem::symbolSet() int BaseSymbolItem::symbolSetAsInt() { - return static_cast(SidcDefinitions::castToSymbolSet(m_symbolProperties.originalKey().left(2).toUInt() // Qt6: leftRef removed)); + return static_cast(SidcDefinitions::castToSymbolSet(m_symbolProperties.originalKey().left(2).toUInt())); // Qt6: leftRef removed } @@ -215,45 +217,44 @@ QImage BaseSymbolItem::getSearchSwatch() // if (!m_esriSearch.m_esriSymbol) // m_esriSearch.m_esriSymbol = m_esriSearch.m_sssResult.symbol(this); - if (m_esriSearch.m_esriSwatch.isNull() && m_esriSearch.m_esriSymbol && m_esriSearch.m_esriTaskUuid.isNull()) + if (m_esriSearch.m_esriSwatch.isNull() && m_esriSearch.m_esriSymbol && !m_esriSearch.m_swatchFuture.isRunning()) { // ok, create swatch now: // qCritical() << " SEARCH: id=" << m_id << " create swatch now"; // qCritical() << " SEARCH: id=" << m_esriSearch.m_esriSymbol->toJson(); - connect(m_esriSearch.m_esriSymbol, &Esri::ArcGISRuntime::Symbol::createSwatchCompleted, - this, &BaseSymbolItem::onEsriSearchSymbolSwatchCompleted, Qt::UniqueConnection); - - const Esri::ArcGISRuntime::TaskWatcher &tw = m_esriSearch.m_esriSymbol->createSwatch(SWATCH_SIZE, SWATCH_SIZE, 1); - if (tw.isValid()) - m_esriSearch.m_esriTaskUuid = tw.taskId(); - else - qCritical() << " SEARCH: id=" << m_id << " taskId invalid"; + // Qt6: Use QFuture pattern instead of signals + m_esriSearch.m_swatchFuture = m_esriSearch.m_esriSymbol->createSwatchAsync(SWATCH_SIZE, SWATCH_SIZE, 1); + + // Use QtConcurrent to handle completion + QtConcurrent::run([this, future = m_esriSearch.m_swatchFuture]() mutable { + future.waitForFinished(); + if (future.isFinished() && !future.isCanceled()) { + QImage image = future.result(); + QMetaObject::invokeMethod(this, [this, image]() { + onEsriSearchSymbolSwatchCompleted(image); + }, Qt::QueuedConnection); + } + }); } return m_esriSearch.m_esriSwatch; } -void BaseSymbolItem::onEsriSearchSymbolSwatchCompleted(const QUuid &taskId, const QImage &image) +void BaseSymbolItem::onEsriSearchSymbolSwatchCompleted(const QImage &image) { - if (m_esriSearch.m_esriTaskUuid != taskId) - return; - m_esriSearch.m_esriSwatch = image; emit dataChanged(m_id); } -QImage BaseSymbolItem::getFetchSwatch() const +QImage BaseSymbolItem::getFetchSwatch() { if (!m_symbolDictionaryImpl || !m_symbolDictionaryImpl->getEsriSymbolDictionary()) return m_esriFetch.m_esriSwatch; - if (m_esriFetch.m_esriSwatch.isNull() && m_esriFetch.m_esriFetchTaskIdUuid.isNull()) + if (m_esriFetch.m_esriSwatch.isNull() && !m_esriFetch.m_symbolFuture.isRunning()) { - connect(m_esriDictionary, &Esri::ArcGISRuntime::DictionarySymbolStyle::fetchSymbolCompleted, - this, &BaseSymbolItem::onEsriFetchCompleted, Qt::UniqueConnection); - // from key8 to sidc (20 digits) const QString &key8 = m_symbolProperties.key().left(8); @@ -272,39 +273,44 @@ QImage BaseSymbolItem::getFetchSwatch() const const QVariantMap keys({{QStringLiteral("sidc"), m_esriFetch.m_sidc}, // SidcCodec::decodeRawSidc ; set sidc of symbol in case of MIL2525 {QStringLiteral("sic"), m_esriFetch.m_sidc}}); // SidcCodec::decodeRawSidc , set sidc of symbol in case of APP6 - const Esri::ArcGISRuntime::TaskWatcher &tw = m_esriDictionary->fetchSymbol(keys); - if (tw.isValid()) - m_esriFetch.m_esriFetchTaskIdUuid = tw.taskId(); - else - qCritical() << " FETCH: id=" << m_id << " m_esriFetchTaskIdUuid invalid"; + // Qt6: Use QFuture pattern instead of signals + m_esriFetch.m_symbolFuture = m_esriDictionary->fetchSymbolAsync(keys, this); + + QtConcurrent::run([this, future = m_esriFetch.m_symbolFuture]() mutable { + future.waitForFinished(); + if (future.isFinished() && !future.isCanceled()) { + Esri::ArcGISRuntime::Symbol *symbol = future.result(); + QMetaObject::invokeMethod(this, [this, symbol]() { + onEsriFetchCompleted(symbol); + }, Qt::QueuedConnection); + } + }); } return m_esriFetch.m_esriSwatch; } -void BaseSymbolItem::onEsriFetchCompleted(const QUuid &taskId, Esri::ArcGISRuntime::Symbol *symbol) +void BaseSymbolItem::onEsriFetchCompleted(Esri::ArcGISRuntime::Symbol *symbol) { - if (m_esriFetch.m_esriFetchTaskIdUuid != taskId) - return; - // save intermediate result: m_esriFetch.m_esriSymbol = symbol; // start creating swatch of fetched symbol: - connect(m_esriFetch.m_esriSymbol, &Esri::ArcGISRuntime::Symbol::createSwatchCompleted, - this, &BaseSymbolItem::onEsriFetchSymbolSwatchCompleted, Qt::UniqueConnection); - - const Esri::ArcGISRuntime::TaskWatcher &tw = m_esriFetch.m_esriSymbol->createSwatch(SWATCH_SIZE, SWATCH_SIZE, 1); - if (tw.isValid()) - m_esriFetch.m_esriSwatchTaskUuid = tw.taskId(); - else - qCritical() << " FETCH: id=" << m_id << " taskId invalid"; + // Qt6: Use QFuture pattern instead of signals + m_esriFetch.m_swatchFuture = m_esriFetch.m_esriSymbol->createSwatchAsync(SWATCH_SIZE, SWATCH_SIZE, 1); + + QtConcurrent::run([this, future = m_esriFetch.m_swatchFuture]() mutable { + future.waitForFinished(); + if (future.isFinished() && !future.isCanceled()) { + QImage image = future.result(); + QMetaObject::invokeMethod(this, [this, image]() { + onEsriFetchSymbolSwatchCompleted(image); + }, Qt::QueuedConnection); + } + }); } -void BaseSymbolItem::onEsriFetchSymbolSwatchCompleted(const QUuid &taskId, const QImage &image) +void BaseSymbolItem::onEsriFetchSymbolSwatchCompleted(const QImage &image) { - if (m_esriFetch.m_esriSwatchTaskUuid != taskId) - return; - m_esriFetch.m_esriSwatch = image; // qCritical() << " FETCH: id=" << m_id << " image " << image.size(); @@ -426,8 +432,7 @@ void BaseSymbolModel::onLoadStatusChanged(Esri::ArcGISRuntime::LoadStatus loadSt void BaseSymbolModel::onErrorDictionary(const Esri::ArcGISRuntime::Error &error) { FATAL_LOG(m_logger) << LOGFUNCTION << " ---EsriError--- occured: " - << " code=" << error.code() - << ", domain=" << static_cast(error.domain()) + << " domain=" << static_cast(error.domain()) << ", extendedErrorType=" << static_cast(error.extendedErrorType()) << ", message='" << error.message() << "'" << ", additionalMessage='" << error.additionalMessage() << "'"; @@ -455,11 +460,13 @@ void BaseSymbolModel::initModel(SymbolDictionary *symbolDictionary, // spend time to create (expensive) Esri::ArcGISRuntime::Symbol? + // Qt6/ArcGIS SDK v300: symbol() method removed, replaced with fetchSymbolAsync() + // For debug mode, symbol fetching would require async pattern - skipping for now #ifdef LTS_DEBUG - Esri::ArcGISRuntime::Symbol *esriSymbol = nullptr; - const bool showAll = QGuiApplication::keyboardModifiers().testFlag(Qt::KeyboardModifier::ControlModifier); - if (showAll) - esriSymbol = searchResult.symbol(this); // symbol() has to be called from mainThread, is expensive / time consuming + // Qt6: Symbol fetching now requires async pattern via fetchSymbolAsync() + // Debug symbol display would require refactoring to async pattern + Esri::ArcGISRuntime::Symbol *esriSymbol = nullptr; + Q_UNUSED(searchResult) #else // release mode: save time, won´t be visible Esri::ArcGISRuntime::Symbol *esriSymbol = nullptr; @@ -991,8 +998,7 @@ QSet BaseSymbolProxyModel::validBaseSymbolCodes() const void BaseSymbolProxyModel::setValidBaseSymbolCodes(const QSet &validBaseSymbolCodes) { m_validBaseSymbolCodes = validBaseSymbolCodes; - beginFilterChange(); - endFilterChange(); + invalidateFilter(); } void BaseSymbolProxyModel::onFilterPoints(bool on) @@ -1001,8 +1007,7 @@ void BaseSymbolProxyModel::onFilterPoints(bool on) m_geometrySet.insert(AdvancedSymbology::GeometryType::Point); else m_geometrySet.remove(AdvancedSymbology::GeometryType::Point); - beginFilterChange(); - endFilterChange(); + invalidateFilter(); } void BaseSymbolProxyModel::onFilterLines(bool on) { @@ -1010,8 +1015,7 @@ void BaseSymbolProxyModel::onFilterLines(bool on) m_geometrySet.insert(AdvancedSymbology::GeometryType::Polyline); else m_geometrySet.remove(AdvancedSymbology::GeometryType::Polyline); - beginFilterChange(); - endFilterChange(); + invalidateFilter(); } void BaseSymbolProxyModel::onFilterAreas(bool on) { @@ -1019,8 +1023,7 @@ void BaseSymbolProxyModel::onFilterAreas(bool on) m_geometrySet.insert(AdvancedSymbology::GeometryType::Polygon); else m_geometrySet.remove(AdvancedSymbology::GeometryType::Polygon); - beginFilterChange(); - endFilterChange(); + invalidateFilter(); } bool BaseSymbolProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const diff --git a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/SymbologyImpl/base_symbol_model.h b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/SymbologyImpl/base_symbol_model.h index 6ec33d2e9..8fdb66bce 100755 --- a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/SymbologyImpl/base_symbol_model.h +++ b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/SymbologyImpl/base_symbol_model.h @@ -102,7 +102,7 @@ public: struct EsriSearch { mutable Esri::ArcGISRuntime::Symbol *m_esriSymbol = nullptr; - mutable QUuid m_esriTaskUuid; + mutable QFuture m_swatchFuture; mutable QImage m_esriSwatch; }; EsriSearch m_esriSearch; @@ -112,15 +112,15 @@ public: struct EsriFetch { mutable QString m_sidc; - mutable QUuid m_esriFetchTaskIdUuid; + mutable QFuture m_symbolFuture; Esri::ArcGISRuntime::Symbol *m_esriSymbol = nullptr; - mutable QUuid m_esriSwatchTaskUuid; + mutable QFuture m_swatchFuture; mutable QImage m_esriSwatch; mutable QImage m_esriToolTipSwatch; }; EsriFetch m_esriFetch; - QImage getFetchSwatch() const; + QImage getFetchSwatch(); ResultWatcherData *m_findBaseSymbolRWD = nullptr; @@ -141,11 +141,11 @@ Q_SIGNALS: public Q_SLOTS: // SEARCH_ICON: - void onEsriSearchSymbolSwatchCompleted(const QUuid &taskId, const QImage &image); + void onEsriSearchSymbolSwatchCompleted(const QImage &image); // FETCH_ICON: - void onEsriFetchCompleted(const QUuid &taskId, Esri::ArcGISRuntime::Symbol *symbol); - void onEsriFetchSymbolSwatchCompleted(const QUuid &taskId, const QImage &image); + void onEsriFetchCompleted(Esri::ArcGISRuntime::Symbol *symbol); + void onEsriFetchSymbolSwatchCompleted(const QImage &image); }; //------------------------------------------------------------------------------ diff --git a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/SymbologyImpl/esri_dictionary_processor.cpp b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/SymbologyImpl/esri_dictionary_processor.cpp index 60ebe3994..47d90be19 100755 --- a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/SymbologyImpl/esri_dictionary_processor.cpp +++ b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/SymbologyImpl/esri_dictionary_processor.cpp @@ -14,7 +14,7 @@ // ESRI -#include +#include #include #include #include @@ -25,6 +25,7 @@ #include #include #include +#include #define CREATE_ESRI_SYMBOL_ON_DEMAND // save time on startup // REGG-3483 - EsriDictionaryProcessor::syncTableWithinMainThread verzögert Applikations-Start um mehrere Sekunden @@ -94,16 +95,21 @@ void EsriDictionaryProcessor::searchSymbols() // search for all results (and store them in member): // - connect(m_esri_dictionary, &Esri::ArcGISRuntime::DictionarySymbolStyle::searchSymbolsCompleted, - this, &EsriDictionaryProcessor::onSearchSymbolsCompletedPropertyTable, Qt::UniqueConnection); - Esri::ArcGISRuntime::SymbolStyleSearchParameters sssp; - Esri::ArcGISRuntime::TaskWatcher tw = m_esri_dictionary->searchSymbols(sssp); - if (tw.isValid()) - DEBUG_LOG(m_logger) << LOGFUNCTION << " TaskWatcher valid: ssTaskId=" << tw.taskId().toString(); - else - ERROR_LOG(m_logger) << LOGFUNCTION << " TaskWatcher invalid" << " ThreadId=" << QThread::currentThreadId(); + auto searchFuture = m_esri_dictionary->searchSymbolsAsync(sssp); + + // Use QFutureWatcher to handle completion + auto *watcher = new QFutureWatcher(this); + connect(watcher, &QFutureWatcher::finished, + this, [this, watcher]() { + auto *searchResults = watcher->result(); + onSearchSymbolsCompletedPropertyTable(QUuid(), searchResults); + watcher->deleteLater(); + }); + + watcher->setFuture(searchFuture); + DEBUG_LOG(m_logger) << LOGFUNCTION << " searchSymbolsAsync started" << " ThreadId=" << QThread::currentThreadId(); TRACE_LOG(m_logger) << LOGFUNCTION << " END"; @@ -115,12 +121,14 @@ void EsriDictionaryProcessor::startBaseSymbolCodeToPropertyTable() // A-sync: // (slot is a pure virtual method) - m_baseSymbolCodeToSymbolPropertyTableWatcher = QtConcurrent::run(this, &EsriDictionaryProcessor::processBaseSymbolCodeToPropertyTable); + m_baseSymbolCodeToSymbolPropertyTableWatcher = QtConcurrent::run([this]() { + return this->processBaseSymbolCodeToPropertyTable(); + }); // Sync: // processBaseSymbolCodeToPropertyTable(); - TRACE_LOG(m_logger) << LOGFUNCTION << " START"; + TRACE_LOG(m_logger) << LOGFUNCTION << " END"; } void EsriDictionaryProcessor::startModifierTable() @@ -129,7 +137,9 @@ void EsriDictionaryProcessor::startModifierTable() // A-sync: // (slot is a pure virtual method) - m_modifierTableWatcher = QtConcurrent::run(this, &EsriDictionaryProcessor::processModifierTable); + m_modifierTableWatcher = QtConcurrent::run([this]() { + return this->processModifierTable(); + }); // Sync: // processModifierTable(); @@ -196,10 +206,6 @@ void EsriDictionaryProcessor::onSearchSymbolsCompletedPropertyTable(QUuid, Esri: // cleanup: searchResults->deleteLater(); - // disconnect: - disconnect(m_esri_dictionary, &Esri::ArcGISRuntime::DictionarySymbolStyle::searchSymbolsCompleted, - this, &EsriDictionaryProcessor::onSearchSymbolsCompletedPropertyTable); - // method 'symbol' has to be called (created) within mainThread: syncTableWithinMainThread(); @@ -281,6 +287,67 @@ void EsriDictionaryProcessor::onEsriSymbolSwatchCompleted(const QUuid &csTaskId, m_symbolPropertyImage2symbolResult.erase(it); } +void EsriDictionaryProcessor::onSymbolFetched(int taskIndex) +{ + if (taskIndex < 0 || taskIndex >= m_symbolFetchTasks.size()) + { + ERROR_LOG(m_logger) << LOGFUNCTION << " invalid taskIndex=" << taskIndex; + return; + } + + SymbolFetchTask *fetchTask = m_symbolFetchTasks.at(taskIndex); + if (!fetchTask) + { + ERROR_LOG(m_logger) << LOGFUNCTION << " null fetchTask at index=" << taskIndex; + return; + } + + QFuture future = fetchTask->watcher.future(); + Esri::ArcGISRuntime::Symbol *symbol = future.result(); + + if (!symbol) + { + ERROR_LOG(m_logger) << LOGFUNCTION << " symbol fetch failed for key=" << fetchTask->key; + // Cleanup + m_symbolFetchTasks.removeAt(taskIndex); + delete fetchTask; + return; + } + + // Store the fetched symbol in the cache + auto it = m_originalKeyToEsriSymbol.find(fetchTask->key); + if (it == m_originalKeyToEsriSymbol.end()) + { + ERROR_LOG(m_logger) << LOGFUNCTION << " key not found in cache: " << fetchTask->key; + m_symbolFetchTasks.removeAt(taskIndex); + delete fetchTask; + return; + } + + EsriSymbol &eSym = it.value(); + eSym.esriSymbol = symbol; + + DEBUG_LOG(m_logger) << LOGFUNCTION << " symbol fetched successfully, key=" << fetchTask->key; + + // Now start the swatch creation + QSharedPointer symResult = fetchTask->symbolResult.toStrongRef(); + if (!symResult) + { + DEBUG_LOG(m_logger) << LOGFUNCTION << " SymbolResult already deleted, skipping swatch creation"; + m_symbolFetchTasks.removeAt(taskIndex); + delete fetchTask; + return; + } + + // Re-call symbolPropertyImage to create the swatch now that symbol is available + // The symbol is now cached, so it will take the fast path + symbolPropertyImage(symResult, fetchTask->key); + + // Cleanup fetch task + m_symbolFetchTasks.removeAt(taskIndex); + delete fetchTask; +} + void EsriDictionaryProcessor::checkIfAllAreDone() { if (allJobsDone()) @@ -296,14 +363,9 @@ void EsriDictionaryProcessor::syncTableWithinMainThread() { const QString &originalKey = resultItem.key(); - // store esriSymbol for rendering issues: + // store key for on-demand symbol fetching via fetchSymbolAsync() EsriSymbol eSym; -#ifdef CREATE_ESRI_SYMBOL_ON_DEMAND - eSym.m_sssResult =resultItem; -#else - QObject *parent = this; - eSym.esriSymbol = resultItem.symbol(parent); // resultItem.symbol() has to be called from mainThread??? -#endif // CREATE_ESRI_SYMBOL_ON_DEMAND + eSym.key = originalKey; m_originalKeyToEsriSymbol[originalKey] = eSym; } @@ -315,7 +377,7 @@ bool EsriDictionaryProcessor::symbolPropertyImageContains(const QString &origina return m_originalKeyToEsriSymbol.contains(originalKey); } -QSharedPointer EsriDictionaryProcessor::symbolPropertyImage(QSharedPointer symResult, const QString &originalKey) const +QSharedPointer EsriDictionaryProcessor::symbolPropertyImage(QSharedPointer symResult, const QString &originalKey) { TRACE_LOG(m_logger) << LOGFUNCTION << " START"; @@ -330,46 +392,71 @@ QSharedPointer EsriDictionaryProcessor::symbolPropertyImage(QShare if (eSym.swatchImage.isNull()) { -#ifdef CREATE_ESRI_SYMBOL_ON_DEMAND - if (!eSym.esriSymbol) - { - QObject *parent = const_cast(this); // cast const away - eSym.esriSymbol = eSym.m_sssResult.symbol(parent); // resultItem.symbol() has to be called from mainThread??? - } -#endif // CREATE_ESRI_SYMBOL_ON_DEMAND + // Generate a unique task ID for tracking this swatch request + QUuid csTaskId = QUuid::createUuid(); + + // Store mapping for later lookup in completion handler + m_symbolPropertyImage2symbolResult[csTaskId] = symResult.toWeakRef(); - connect(eSym.esriSymbol, &Esri::ArcGISRuntime::Symbol::createSwatchCompleted, - this, &EsriDictionaryProcessor::onEsriSymbolSwatchCompleted, Qt::UniqueConnection); + if (eSym.esriSymbol) + { + // Symbol already fetched, create swatch directly + // Create QFutureWatcher to handle the async result + auto *watcher = new QFutureWatcher(this); + connect(watcher, &QFutureWatcher::finished, + this, [this, watcher, csTaskId]() { + onEsriSymbolSwatchCompleted(csTaskId, watcher->result()); + // Cleanup: remove from tracking list and delete watcher + m_swatchWatchers.removeOne(watcher); + watcher->deleteLater(); + }); #ifdef USE_ARCADE_SYMBOLOGY - Esri::ArcGISRuntime::TaskWatcher tw; - auto it = m_baseSymbolCodeToSymbolPropertyTable.find(originalKey); - if (it != m_baseSymbolCodeToSymbolPropertyTable.end() && (it->geometryType() == GeometryType::Polygon) ) - // area/Polygon -> request rectangle, otherwise quadratic swatch: - tw = eSym.esriSymbol->createSwatch(CREATE_SWATCH_PARAMETER.m_width, CREATE_SWATCH_PARAMETER.m_height, CREATE_SWATCH_PARAMETER.m_screenScale); - else - tw = eSym.esriSymbol->createSwatch(CREATE_SWATCH_PARAMETER.m_height, CREATE_SWATCH_PARAMETER.m_height, CREATE_SWATCH_PARAMETER.m_screenScale); + auto it2 = m_baseSymbolCodeToSymbolPropertyTable.find(originalKey); + if (it2 != m_baseSymbolCodeToSymbolPropertyTable.end() && (it2->geometryType() == GeometryType::Polygon) ) + // area/Polygon -> request rectangle, otherwise quadratic swatch: + watcher->setFuture(eSym.esriSymbol->createSwatchAsync(CREATE_SWATCH_PARAMETER.m_width, CREATE_SWATCH_PARAMETER.m_height, CREATE_SWATCH_PARAMETER.m_screenScale)); + else + watcher->setFuture(eSym.esriSymbol->createSwatchAsync(CREATE_SWATCH_PARAMETER.m_height, CREATE_SWATCH_PARAMETER.m_height, CREATE_SWATCH_PARAMETER.m_screenScale)); #else - Esri::ArcGISRuntime::TaskWatcher tw = eSym.esriSymbol->createSwatch(CREATE_SWATCH_SCREEN_SCALE); + watcher->setFuture(eSym.esriSymbol->createSwatchAsync(CREATE_SWATCH_SCREEN_SCALE)); #endif // USE_ARCADE_SYMBOLOGY - QUuid csTaskId; - if (tw.isValid()) - { - csTaskId = tw.taskId(); - DEBUG_LOG(m_logger) << LOGFUNCTION << " csTaskWatcher valid: csTaskId=" << csTaskId; - } - else - { - ERROR_LOG(m_logger) << LOGFUNCTION << " csTaskWatcher invalid" + + // Track watcher for cleanup + m_swatchWatchers.append(watcher); + + DEBUG_LOG(m_logger) << LOGFUNCTION << " createSwatchAsync started (symbol already cached)" + << " csTaskId=" << csTaskId << " ThreadId=" << QThread::currentThreadId(); } - - if (! csTaskId.isNull()) - m_symbolPropertyImage2symbolResult[csTaskId] = symResult.toWeakRef(); else - ERROR_LOG(m_logger) << LOGFUNCTION << " csTaskWatcher invalid"; - + { + // Symbol not fetched yet - start async fetch first, then create swatch + // Create task to track the symbol fetch + auto *fetchTask = new SymbolFetchTask(); + fetchTask->key = originalKey; + fetchTask->symbolResult = symResult.toWeakRef(); + fetchTask->csTaskId = csTaskId; + + connect(&fetchTask->watcher, &QFutureWatcher::finished, + this, [this, fetchTask]() { + onSymbolFetched(m_symbolFetchTasks.indexOf(fetchTask)); + }); + + // Start async symbol fetch using the key + QVariantMap keys; + keys.insert(QStringLiteral("key"), originalKey); + fetchTask->watcher.setFuture(m_esri_dictionary->fetchSymbolAsync(keys)); + + // Track fetch task + m_symbolFetchTasks.append(fetchTask); + + DEBUG_LOG(m_logger) << LOGFUNCTION << " fetchSymbolAsync started" + << " originalKey=" << originalKey + << " csTaskId=" << csTaskId + << " ThreadId=" << QThread::currentThreadId(); + } } else { diff --git a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/SymbologyImpl/esri_dictionary_processor.h b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/SymbologyImpl/esri_dictionary_processor.h index 3daf4d0ae..e64b98808 100755 --- a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/SymbologyImpl/esri_dictionary_processor.h +++ b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/SymbologyImpl/esri_dictionary_processor.h @@ -17,6 +17,7 @@ // Qt #include #include // QUuid used in slot signatures / map keys (Qt6: no transitive include) +#include // Esri @@ -160,6 +161,7 @@ Q_SIGNALS: protected Q_SLOTS: void onSearchSymbolsCompletedPropertyTable(QUuid /*ssTaskId*/, Esri::ArcGISRuntime::SymbolStyleSearchResultListModel *searchResults); void onEsriSymbolSwatchCompleted(const QUuid &csTaskId, const QImage &image); + void onSymbolFetched(int taskIndex); protected: @@ -180,18 +182,31 @@ protected: // originalKey struct EsriSymbol { - Esri::ArcGISRuntime::SymbolStyleSearchResult m_sssResult; - mutable Esri::ArcGISRuntime::Symbol *esriSymbol = nullptr; - mutable QImage swatchImage; + QString key; // Key to fetch symbol via fetchSymbolAsync() + mutable Esri::ArcGISRuntime::Symbol *esriSymbol = nullptr; + mutable QImage swatchImage; }; QHash m_originalKeyToEsriSymbol; // symbolPropertyImage-Uuid -> SymbolResult mutable QMap> m_symbolPropertyImage2symbolResult; + // Track swatch QFutureWatchers to manage lifecycle + mutable QList*> m_swatchWatchers; + + // Helper struct to track symbol fetch tasks for on-demand symbol creation + struct SymbolFetchTask + { + QFutureWatcher watcher; + QString key; // Original key for lookup + QWeakPointer symbolResult; + QUuid csTaskId; // Swatch task ID (for chaining) + }; + mutable QList m_symbolFetchTasks; + public: bool symbolPropertyImageContains(const QString &originalKey) const; - QSharedPointer symbolPropertyImage(QSharedPointer symResult, const QString &originalKey) const; + QSharedPointer symbolPropertyImage(QSharedPointer symResult, const QString &originalKey); const QList & getSearchResultList() const { return m_searchResultList; } const QList & getSearchResultListValid() const { return m_searchResultListValid; } diff --git a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/SymbologyImpl/esri_dictionary_processor_app6d.cpp b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/SymbologyImpl/esri_dictionary_processor_app6d.cpp index 3b37ee38d..ab71abb78 100755 --- a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/SymbologyImpl/esri_dictionary_processor_app6d.cpp +++ b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/SymbologyImpl/esri_dictionary_processor_app6d.cpp @@ -40,7 +40,6 @@ -#include // This file is created by RME, not ESRI namespace AdvancedSymbology diff --git a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/SymbologyImpl/symbol_dictionary_impl.cpp b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/SymbologyImpl/symbol_dictionary_impl.cpp index 3f2f83548..1c3abc90a 100755 --- a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/SymbologyImpl/symbol_dictionary_impl.cpp +++ b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/SymbologyImpl/symbol_dictionary_impl.cpp @@ -27,18 +27,17 @@ #include // ESRI -#include +#include #include #include #include #include +#include +#include -# include // This file is created by RME, not ESRI - -#if ACRGIS_VERSION >= 0x640100 // 100.1.0 / Update 1 -# define SYM_PROTECTION_AREAS_BECOMES_LINE -#endif +// ArcGIS Maps SDK for Qt 200.x (Qt6) - version is always >= 100.1.0 +#define SYM_PROTECTION_AREAS_BECOMES_LINE // Qt @@ -341,7 +340,7 @@ bool SymbolDictionaryImpl::init(SymbologyType symbologyType, const QString &symb delete m_esri_dictionary; clearEtsSymbols(); - m_createSwatch2findSymbolTaskId.clear(); + m_createSwatch2findSymbolTask.clear(); m_findSymbol2propertyResult.clear(); m_findSymbol2symbolResult.clear(); @@ -393,12 +392,13 @@ bool SymbolDictionaryImpl::init(SymbologyType symbologyType, const QString &symb m_esri_dictionary = Esri::ArcGISRuntime::DictionarySymbolStyle::createFromFile(m_symbologyResourcePath); #else + // Qt6/ArcGIS SDK v300: DictionarySymbolStyle constructor requires PortalItem or use createFromFile() // QString symbologyResourcePath("/usr/share/arcgis/resources/symbols//mil2525d/mil2525d.stylx"); if (symbologyResourcePath.isEmpty()) { - INFO_LOG(m_logger) << LOGFUNCTION << " create EsriDict:" - << " m_specificationType='" << m_specificationType << "'"; - m_esri_dictionary = new Esri::ArcGISRuntime::DictionarySymbolStyle(m_specificationType); + ERROR_LOG(m_logger) << LOGFUNCTION << " symbologyResourcePath is empty - cannot create DictionarySymbolStyle without path"; + Q_ASSERT(false); + return false; } else { @@ -413,7 +413,8 @@ bool SymbolDictionaryImpl::init(SymbologyType symbologyType, const QString &symb NOTICE_LOG(m_logger) << LOGFUNCTION << " create EsriDict:" << " m_specificationType='" << m_specificationType << "'" << " m_symbologyResourcePath='" << m_symbologyResourcePath << "'"; - m_esri_dictionary = new Esri::ArcGISRuntime::DictionarySymbolStyle(m_specificationType, m_symbologyResourcePath); + // Qt6: use static createFromFile() method instead of constructor + m_esri_dictionary = Esri::ArcGISRuntime::DictionarySymbolStyle::createFromFile(m_symbologyResourcePath); } #endif // USE_ARCADE_SYMBOLOGY @@ -485,11 +486,9 @@ bool SymbolDictionaryImpl::init(SymbologyType symbologyType, const QString &symb void SymbolDictionaryImpl::connectSignals() { - if (m_esri_dictionary) - { - connect(m_esri_dictionary, &Esri::ArcGISRuntime::DictionarySymbolStyle::fetchSymbolCompleted, - this, &SymbolDictionaryImpl::onFetchSymbolCompleted); - } + // Qt6/ArcGIS SDK v300: No signals to connect - using QFuture-based async API + // fetchSymbolCompleted signal removed in SDK v300, replaced with QFuture pattern + Q_UNUSED(m_esri_dictionary) } @@ -1350,7 +1349,11 @@ QSharedPointer SymbolDictionaryImpl::fetchSymbol(const SymbolDataT #define FETCH_SYMBOL_ETS_CONCURRENT #ifdef FETCH_SYMBOL_ETS_CONCURRENT // symDataToRender contains flag 'symDataToRender' - symResult->setFuture(QtConcurrent::run(renderExtensions, extraImg, symDataToRender, colorToBeReplaced, symDataToRender.renderJustCoreImage)); + // Qt6: Use lambda to capture by value since renderExtensions takes QImage& + symResult->setFuture(QtConcurrent::run([extraImg, symDataToRender, colorToBeReplaced]() mutable { + QImage img = extraImg; + return renderExtensions(img, symDataToRender, colorToBeReplaced, symDataToRender.renderJustCoreImage); + })); #else QImage imageCopy = extraImg; @@ -1463,37 +1466,29 @@ QSharedPointer SymbolDictionaryImpl::fetchSymbol(const SymbolDataT const QVariantMap keys({{QStringLiteral("sidc"), SidcCodec::decodeRawSidc(sidc)}, // set sidc of symbol in case of MIL2525 {QStringLiteral("sic"), SidcCodec::decodeRawSidc(sidc)}}); // set sidc of symbol in case of APP6 - Esri::ArcGISRuntime::TaskWatcher tw = m_esri_dictionary->fetchSymbol(keys); - QUuid fsTaskId; - if (tw.isValid()) - { - fsTaskId = tw.taskId(); + // Qt6: Use QFutureWatcher instead of TaskWatcher + auto *fetchTask = new SymbolFetchTask; + fetchTask->fsTaskId = QUuid::createUuid(); + fetchTask->symbolResult = symResult.toWeakRef(); + + // store taskId in symResult: + symResult->setTaskId(fetchTask->fsTaskId); - if (doParanoiaChecks()) - if (fsTaskId.isNull()) - abort(); + // and put into map to be able to inform customer if swatch is completed: + m_findSymbol2symbolResult[fetchTask] = symResult.toWeakRef(); + m_activeFetchSymbolTasks.append(fetchTask); - // store taskId in symResult: - symResult->setTaskId(fsTaskId); + // Start async fetch and connect to finished signal + QFuture future = m_esri_dictionary->fetchSymbolAsync(keys); + fetchTask->watcher.setFuture(future); + connect(&fetchTask->watcher, &QFutureWatcher::finished, + this, &SymbolDictionaryImpl::onFetchSymbolCompleted, Qt::QueuedConnection); - // and put into map to be able to inform customer if swatch is completed: - m_findSymbol2symbolResult[fsTaskId] = symResult.toWeakRef(); - - DEBUG_LOG(m_logger) << LOGFUNCTION << " TaskWatcher valid: fsTaskId=" << fsTaskId; - } - else - { - ERROR_LOG(m_logger) << LOGFUNCTION << " TaskWatcher invalid" - << " ThreadId=" << QThread::currentThreadId(); - - if (doParanoiaChecks()) - abort(); - - } + DEBUG_LOG(m_logger) << LOGFUNCTION << " QFutureWatcher created: fsTaskId=" << fetchTask->fsTaskId; TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " symDataToRender=" << symDataToRender.toString() - << " fsTaskId=" << fsTaskId; + << " fsTaskId=" << fetchTask->fsTaskId; return symResult; } } // switch(sidcType) @@ -1708,8 +1703,37 @@ QSharedPointer SymbolDictionaryImpl::findBaseSymbol(const QString -void SymbolDictionaryImpl::onFetchSymbolCompleted(QUuid fsTaskId, Esri::ArcGISRuntime::Symbol *symbol) +void SymbolDictionaryImpl::onFetchSymbolCompleted() { + // Qt6: Use dynamic_cast since QFutureWatcher doesn't have Q_OBJECT macro + auto *watcher = dynamic_cast*>(sender()); + if (!watcher) + { + ERROR_LOG(m_logger) << LOGFUNCTION << " Invalid sender (not a QFutureWatcher)"; + return; + } + + // Find the corresponding task + SymbolFetchTask *fetchTask = nullptr; + for (auto *task : m_activeFetchSymbolTasks) + { + if (&task->watcher == watcher) + { + fetchTask = task; + break; + } + } + + if (!fetchTask) + { + ERROR_LOG(m_logger) << LOGFUNCTION << " Task not found for watcher"; + watcher->deleteLater(); + return; + } + + QUuid fsTaskId = fetchTask->fsTaskId; + Esri::ArcGISRuntime::Symbol *symbol = watcher->result(); + TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " symType= '" << this->symbologyType() << "'" << " fsTaskId= '" << fsTaskId << "'" @@ -1726,10 +1750,15 @@ void SymbolDictionaryImpl::onFetchSymbolCompleted(QUuid fsTaskId, Esri::ArcGISRu if (doParanoiaChecks()) abort(); + // Cleanup + m_activeFetchSymbolTasks.removeAll(fetchTask); + m_findSymbol2symbolResult.remove(fetchTask); + watcher->deleteLater(); + delete fetchTask; return; } - QSharedPointer symResult = m_findSymbol2symbolResult.value(fsTaskId); + QSharedPointer symResult = m_findSymbol2symbolResult.value(fetchTask); if (!symResult) { // it´s legal, that the result does not exist anymore. @@ -1738,6 +1767,12 @@ void SymbolDictionaryImpl::onFetchSymbolCompleted(QUuid fsTaskId, Esri::ArcGISRu // So just a Debug msg: DEBUG_LOG(m_logger) << LOGFUNCTION << " SymbolResult not found or already been deleted" << " fsTaskId= '" << fsTaskId << "'"; + + // Cleanup + m_activeFetchSymbolTasks.removeAll(fetchTask); + m_findSymbol2symbolResult.remove(fetchTask); + watcher->deleteLater(); + delete fetchTask; return; } @@ -1769,55 +1804,72 @@ void SymbolDictionaryImpl::onFetchSymbolCompleted(QUuid fsTaskId, Esri::ArcGISRu // retrieve Image : // { - connect(symbol, &Esri::ArcGISRuntime::Symbol::createSwatchCompleted, - this, &SymbolDictionaryImpl::onSwatchCompleted); + // Qt6: Use QFutureWatcher for createSwatchAsync + auto *swatchTask = new SwatchTask; + swatchTask->fsTaskId = fsTaskId; + swatchTask->csTaskId = QUuid::createUuid(); + m_createSwatch2findSymbolTask[swatchTask] = fetchTask; + m_activeSwatchTasks.append(swatchTask); + QFuture future; #ifdef USE_ARCADE_SYMBOLOGY - Esri::ArcGISRuntime::TaskWatcher tw; if (symResult->geometryType() == GeometryType::Polygon) // area/Polygon -> request rectangle, otherwise quadratic swatch: - tw = symbol->createSwatch(CREATE_SWATCH_PARAMETER.m_width, CREATE_SWATCH_PARAMETER.m_height, CREATE_SWATCH_PARAMETER.m_screenScale); + future = symbol->createSwatchAsync(CREATE_SWATCH_PARAMETER.m_width, CREATE_SWATCH_PARAMETER.m_height, CREATE_SWATCH_PARAMETER.m_screenScale); else - tw = symbol->createSwatch(CREATE_SWATCH_PARAMETER.m_height, CREATE_SWATCH_PARAMETER.m_height, CREATE_SWATCH_PARAMETER.m_screenScale); + future = symbol->createSwatchAsync(CREATE_SWATCH_PARAMETER.m_height, CREATE_SWATCH_PARAMETER.m_height, CREATE_SWATCH_PARAMETER.m_screenScale); #else - Esri::ArcGISRuntime::TaskWatcher tw = symbol->createSwatch(CREATE_SWATCH_SCREEN_SCALE); // CREATE_SWATCH_SCREEN_SCALE + future = symbol->createSwatchAsync(CREATE_SWATCH_SCREEN_SCALE); // CREATE_SWATCH_SCREEN_SCALE #endif // USE_ARCADE_SYMBOLOGY - QUuid csTaskId; - if (tw.isValid()) - { - csTaskId = tw.taskId(); - DEBUG_LOG(m_logger) << LOGFUNCTION << " csTaskWatcher valid: csTaskId=" << csTaskId; - - if (doParanoiaChecks()) - if (csTaskId.isNull()) - abort(); - - } - else - { - ERROR_LOG(m_logger) << LOGFUNCTION << " csTaskWatcher invalid" - << " ThreadId=" << QThread::currentThreadId(); - - if (doParanoiaChecks()) - abort(); - - } - - if (! csTaskId.isNull()) - m_createSwatch2findSymbolTaskId[csTaskId] = fsTaskId; - else - ERROR_LOG(m_logger) << LOGFUNCTION << " csTaskWatcher invalid"; + + swatchTask->watcher.setFuture(future); + connect(&swatchTask->watcher, &QFutureWatcher::finished, + this, &SymbolDictionaryImpl::onSwatchCompleted, Qt::QueuedConnection); + DEBUG_LOG(m_logger) << LOGFUNCTION << " swatchWatcher created: csTaskId=" << swatchTask->csTaskId; } // retrieve Image + // Cleanup fetch task (swatch task will handle final cleanup) + m_activeFetchSymbolTasks.removeAll(fetchTask); + m_findSymbol2symbolResult.remove(fetchTask); + delete fetchTask; + TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " fs-taskId= '" << fsTaskId << "'" -// << " cs-taskId= '" << csTaskId << "'" << " symbol= '" << symbol << "'"; } -void SymbolDictionaryImpl::onSwatchCompleted(const QUuid &csTaskId, const QImage &image) +void SymbolDictionaryImpl::onSwatchCompleted() { + // Qt6: Use dynamic_cast since QFutureWatcher doesn't have Q_OBJECT macro + auto *watcher = dynamic_cast*>(sender()); + if (!watcher) + { + ERROR_LOG(m_logger) << LOGFUNCTION << " Invalid sender (not a QFutureWatcher)"; + return; + } + + // Find the corresponding swatch task + SwatchTask *swatchTask = nullptr; + for (auto *task : m_activeSwatchTasks) + { + if (&task->watcher == watcher) + { + swatchTask = task; + break; + } + } + + if (!swatchTask) + { + ERROR_LOG(m_logger) << LOGFUNCTION << " SwatchTask not found for watcher"; + watcher->deleteLater(); + return; + } + + QUuid csTaskId = swatchTask->csTaskId; + QImage image = watcher->result(); + TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " symType= '" << this->symbologyType() << "'" << " csTaskId= '" << csTaskId << "'" @@ -1826,20 +1878,26 @@ void SymbolDictionaryImpl::onSwatchCompleted(const QUuid &csTaskId, const QImage << " image.colorTable().size()= '" << image.colorTable().size() << "'" << " ThreadId=" << QThread::currentThreadId(); - auto it = m_createSwatch2findSymbolTaskId.find(csTaskId); - if (it == m_createSwatch2findSymbolTaskId.end()) + // map to external (findSymbol) task + SymbolFetchTask *fetchTask = m_createSwatch2findSymbolTask.value(swatchTask); + if (!fetchTask) { - ERROR_LOG(m_logger) << LOGFUNCTION << " no taskIdMapping" + ERROR_LOG(m_logger) << LOGFUNCTION << " no fetchTask mapping" << " csTaskId= '" << csTaskId << "'"; if (doParanoiaChecks()) abort(); + // Cleanup + m_activeSwatchTasks.removeAll(swatchTask); + m_createSwatch2findSymbolTask.remove(swatchTask); + watcher->deleteLater(); + delete swatchTask; return; } // map to external (findSymbol) taskId - const QUuid &fsTaskId = it.value(); + const QUuid &fsTaskId = fetchTask->fsTaskId; DEBUG_LOG(m_logger) << LOGFUNCTION << " START" << " fsTaskId= '" << fsTaskId << "'" << " csTaskId= '" << csTaskId << "'"; @@ -1847,11 +1905,11 @@ void SymbolDictionaryImpl::onSwatchCompleted(const QUuid &csTaskId, const QImage //// emit findSymbolCompleted(fsTaskId, image); - if (m_findSymbol2symbolResult.contains(fsTaskId)) + if (m_findSymbol2symbolResult.contains(fetchTask)) { DEBUG_LOG(m_logger) << LOGFUNCTION << " SymbolResult found..." << " fsTaskId= '" << fsTaskId << "'"; - QSharedPointer symResult = m_findSymbol2symbolResult[fsTaskId]; + QSharedPointer symResult = m_findSymbol2symbolResult[fetchTask]; if (symResult) { DEBUG_LOG(m_logger) << LOGFUNCTION << " SymbolResult found and still valid..." @@ -1873,7 +1931,11 @@ void SymbolDictionaryImpl::onSwatchCompleted(const QUuid &csTaskId, const QImage // start computation like: // QFuture QtConcurrent::run(Function function, arg1, arc2...) // ^^^^^^^^^^ without() - symResult->setFuture(QtConcurrent::run(renderExtensions, image, symToRender, QColor(), symToRender.renderJustCoreImage)); + // Qt6: Use lambda to capture by value since renderExtensions takes QImage& + symResult->setFuture(QtConcurrent::run([image, symToRender]() mutable { + QImage img = image; + return renderExtensions(img, symToRender, QColor(), symToRender.renderJustCoreImage); + })); #else // CONCURRENT @@ -1896,8 +1958,7 @@ void SymbolDictionaryImpl::onSwatchCompleted(const QUuid &csTaskId, const QImage // } // cleanup - m_findSymbol2symbolResult.remove(fsTaskId); - + m_findSymbol2symbolResult.remove(fetchTask); } else { @@ -1911,13 +1972,10 @@ void SymbolDictionaryImpl::onSwatchCompleted(const QUuid &csTaskId, const QImage // cleanup - m_createSwatch2findSymbolTaskId.erase(it); - - // see also: "SymbolDictionary - findSymbolCompleted without taskId" - // https://earlyadopter.esri.com/project/forum/thread.html?cap=FA3A32558952489280FB472D26FA8192&forid={A612A2F3-E344-4BD0-A1EA-0CE2DA5E694E}&topid={432F3A6B-E323-4628-BF39-77DB7BAAC9A1} - Esri::ArcGISRuntime::Symbol *symbol = qobject_cast(sender()); - if (symbol) - symbol->deleteLater(); + m_activeSwatchTasks.removeAll(swatchTask); + m_createSwatch2findSymbolTask.remove(swatchTask); + watcher->deleteLater(); + delete swatchTask; TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " symType= '" << this->symbologyType() << "'" @@ -2130,7 +2188,7 @@ QImage renderExtensions(QImage &coreImage, #endif // USE_ARCADE_SYMBOLOGY // replace honoring the hotSpot by simple scaling : - int hqFdTf = QStringView(sidc).slice(7, 1).toInt(); + int hqFdTf = QStringView(sidc).sliced(7, 1).toInt(); // int amplifierDescriptor = QStringRef(&sidc, 8, 2).toInt(); if (((hqFdTf > 0) && ((hqFdTf < 8)))) // HeadQuarter/FeintDummy/TaskFore have more height then width newSize = fullImage.size(); @@ -2326,7 +2384,7 @@ QString SymbolDictionaryImpl::toString() const str.append(QStringLiteral(" SymbologyType=%1").arg(AdvancedSymbology::toString(m_symbolDictionaryType_own))); str.append(QStringLiteral(" m_symbologyResourcePath='%1'").arg(m_symbologyResourcePath)); - str.append(QStringLiteral(" m_createSwatch2findSymbolTaskId.size=%1").arg(m_createSwatch2findSymbolTaskId.size())); + str.append(QStringLiteral(" m_createSwatch2findSymbolTask.size=%1").arg(m_createSwatch2findSymbolTask.size())); str.append(QStringLiteral(" m_findSymbol2symbolResult.size=%1").arg(m_findSymbol2symbolResult.size())); return str; @@ -2349,8 +2407,7 @@ QStringList SymbolDictionaryImpl::textFieldNamesInternal() const void SymbolDictionaryImpl::onErrorDictionary(const Esri::ArcGISRuntime::Error &error) { FATAL_LOG(m_logger) << LOGFUNCTION << " ---EsriError--- occured: " - << " code=" << error.code() - << ", domain=" << static_cast(error.domain()) + << " domain=" << static_cast(error.domain()) << ", extendedErrorType=" << static_cast(error.extendedErrorType()) << ", message='" << error.message() << "'" << ", additionalMessage='" << error.additionalMessage() << "'"; diff --git a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/SymbologyImpl/symbol_dictionary_impl.h b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/SymbologyImpl/symbol_dictionary_impl.h index 2e270e0e6..e6e3fe463 100755 --- a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/SymbologyImpl/symbol_dictionary_impl.h +++ b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/SymbologyImpl/symbol_dictionary_impl.h @@ -14,9 +14,11 @@ // Qt #include // QUuid used in slot signatures / map keys (Qt6: no transitive include) +#include // Qt6: For async ArcGIS operations // Esri #include +#include // Qt6: ArcGIS Job-based API class QStandardItemModel; @@ -50,6 +52,23 @@ QStringList listOfPlanEditorSidcs_Internal(); */ +// Qt6: Helper struct to store QFutureWatcher and associated task data +// Replaces Qt5 TaskWatcher pattern with QFuture-based async API +struct SymbolFetchTask +{ + QFutureWatcher watcher; + QUuid fsTaskId; // Original task ID for mapping + QWeakPointer symbolResult; +}; + +struct SwatchTask +{ + QFutureWatcher watcher; + QUuid csTaskId; // Original task ID for mapping + QUuid fsTaskId; // Corresponding findSymbol task ID +}; + + /** * @brief The SymbolDictionaryImpl class * @@ -224,9 +243,10 @@ protected Q_SLOTS: void onLoadStatusChanged(Esri::ArcGISRuntime::LoadStatus loadStatus); void onProcessorAllIsDone(); - void onFetchSymbolCompleted(QUuid fsTaskId, Esri::ArcGISRuntime::Symbol *symbol); + // Qt6: Slots called when QFutureWatcher finishes (use sender() to identify task) + void onFetchSymbolCompleted(); - void onSwatchCompleted(const QUuid &csTaskId, const QImage &image); + void onSwatchCompleted(); private: Esri::ArcGISRuntime::DictionarySymbolStyle *m_esri_dictionary = nullptr; @@ -241,15 +261,20 @@ protected: // // OWN data: - // createSwatch-Uuid -> findSymbol-Uuid - QMap m_createSwatch2findSymbolTaskId; + // Qt6: Store QFutureWatcher tasks instead of QUuid-based maps + // createSwatch-task -> findSymbol-task mapping + QMap m_createSwatch2findSymbolTask; - // searchSymbol-Uuid -> propertyResult - mutable QMap> m_findSymbol2propertyResult; + // searchSymbol-task -> propertyResult + mutable QMap> m_findSymbol2propertyResult; - // findSymbol-Uuid -> symbolResult - mutable QMap> m_findSymbol2symbolResult; + // findSymbol-task -> symbolResult + mutable QMap> m_findSymbol2symbolResult; + + // Qt6: Store active QFutureWatcher tasks for cleanup + mutable QList m_activeFetchSymbolTasks; + mutable QList m_activeSwatchTasks; // QStringList m_sidcList; diff --git a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/SymbologyXML/symbol_reader.cpp b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/SymbologyXML/symbol_reader.cpp index b246bd73c..bdba81810 100755 --- a/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/SymbologyXML/symbol_reader.cpp +++ b/qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap/SymbologyXML/symbol_reader.cpp @@ -1050,7 +1050,7 @@ QColor SymbolReader::getAttribColor(const QColor &def) { QColor result = def; QStringView _attrib = attributes().value(QStringLiteral("color")); if ( _attrib.length() == 9 ) { - result = QColor::fromString(_attrib.left(7).toString()); + result = QColor(_attrib.left(7).toString()); // Get Alpha-Channel bool ok; int value = _attrib.right(2).toInt(&ok,16); diff --git a/qt6-after/qt6-migrated-legatus/cmake/FindArcGIS.cmake b/qt6-after/qt6-migrated-legatus/cmake/FindArcGIS.cmake index 258b7ab2b..cfa11f851 100755 --- a/qt6-after/qt6-migrated-legatus/cmake/FindArcGIS.cmake +++ b/qt6-after/qt6-migrated-legatus/cmake/FindArcGIS.cmake @@ -27,12 +27,19 @@ ELSE() INCLUDE(FindPackageHandleStandardArgs) SET(QT_MIN_VERSION 6.0.0) - FIND_PACKAGE(Qt6 COMPONENTS Core Gui Location Network Sensors) - IF (NOT Qt6_FOUND) - MESSAGE(WARNING "Qt6 not found; skipping ArcGIS") - SET(BUILD_ARCGIS OFF CACHE BOOL "Build ArcGIS SDK dependent modules" FORCE) - RETURN() + # Qt6 may already be found by main CMakeLists.txt - check for existing targets first + IF(NOT TARGET Qt6::Core) + FIND_PACKAGE(Qt6 COMPONENTS Core Network) + IF(NOT Qt6_FOUND OR NOT Qt6Core_FOUND OR NOT Qt6Network_FOUND) + MESSAGE(WARNING "Qt6 Core/Network not found; skipping ArcGIS") + SET(BUILD_ARCGIS OFF CACHE BOOL "Build ArcGIS SDK dependent modules" FORCE) + RETURN() + ENDIF() ENDIF() + # Gui is optional - ArcGIS can work without it in some configurations + FIND_PACKAGE(Qt6Gui QUIET) + FIND_PACKAGE(Qt6Location QUIET) + FIND_PACKAGE(Qt6Sensors QUIET) SET(_arcgis_include_hint "${CMAKE_SOURCE_DIR}/external/ArcGIS/MapsSDK_Qt_300.0.0/ArcGIS_Maps_SDK_Qt_300.0.0/qt300.0.0/sdk/include") SET(_arcgis_library_hint "${CMAKE_SOURCE_DIR}/external/ArcGIS/MapsSDK_Qt_300.0.0/ArcGIS_Maps_SDK_Qt_300.0.0/qt300.0.0/sdk/linux/x64/lib") @@ -114,10 +121,20 @@ IF(NOT TARGET ArcGIS::ArcGIS) # ArcGIS-ON GROUP5 path was never validated in this pipeline. SET_PROPERTY(TARGET ArcGIS::ArcGIS APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES $ - $ $ - $ ) + IF(TARGET Qt6::Gui) + SET_PROPERTY(TARGET ArcGIS::ArcGIS APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES + $) + ENDIF() + IF(TARGET Qt6::Location) + SET_PROPERTY(TARGET ArcGIS::ArcGIS APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES + $) + ENDIF() + IF(TARGET Qt6::Sensors) + SET_PROPERTY(TARGET ArcGIS::ArcGIS APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES + $) + ENDIF() IF (UNIX) IF(ARCGIS_COMMON_LIBRARY_RELEASE) diff --git a/qt6-after/qt6-migrated-legatus/install_arcgis.sh b/qt6-after/qt6-migrated-legatus/install_arcgis.sh index 30a7fd976..542198147 100755 --- a/qt6-after/qt6-migrated-legatus/install_arcgis.sh +++ b/qt6-after/qt6-migrated-legatus/install_arcgis.sh @@ -27,9 +27,10 @@ if [ -e "${ARCGIS_DEST}" ]; then rm -rf "${ARCGIS_DEST}" fi -# Create symlink to the SDK -echo "Creating symlink: ${ARCGIS_DEST} -> ${ARCGIS_SRC}" -ln -s "${ARCGIS_SRC}" "${ARCGIS_DEST}" +# Copy the SDK instead of symlinking to allow configure.sh to modify files +# (symlinks to read-only mounts prevent configure.sh from working) +echo "Copying ArcGIS SDK: ${ARCGIS_SRC} -> ${ARCGIS_DEST}" +cp -r "${ARCGIS_SRC}" "${ARCGIS_DEST}" # Verify the SDK structure SDK_PATH="${ARCGIS_DEST}/MapsSDK_Qt_300.0.0/ArcGIS_Maps_SDK_Qt_300.0.0/qt300.0.0/sdk" @@ -57,9 +58,11 @@ if [ -x "${CONFIGURE_SCRIPT}" ]; then # Run configure.sh with -a to accept EULA automatically (headless install) # The -np flag skips postInstall.sh which integrates with Qt Creator # Remove -np if Qt Creator integration is needed - "${CONFIGURE_SCRIPT}" -a -np - - echo "✓ ArcGIS SDK configuration complete" + if "${CONFIGURE_SCRIPT}" -a -np; then + echo "✓ ArcGIS SDK configuration complete" + else + echo "WARNING: configure.sh failed, but continuing with build (SDK may still work)" + fi else echo "WARNING: configure.sh not found or not executable at ${CONFIGURE_SCRIPT}" echo "SDK may not be properly configured for use" diff --git a/qt6-after/qt6-migrated-legatus/new_docker_build.sh b/qt6-after/qt6-migrated-legatus/new_docker_build.sh index 173b70e54..a09bd4149 100755 --- a/qt6-after/qt6-migrated-legatus/new_docker_build.sh +++ b/qt6-after/qt6-migrated-legatus/new_docker_build.sh @@ -901,8 +901,13 @@ if [[ "${BUILD_ARCGIS}" == "ON" ]]; then GROUP5_TARGETS=( # Viewer module with ArcGIS (viewer-only subset) situationMapCommon + ArcGISQt5Hack + situationMapElevationMap + situationMapGeometryModel + situationMapSideBar advancedSymbology advancedSymbologyXML + situationMap LtsDataView LtsDataViewTest ) @@ -910,8 +915,13 @@ if [[ "${BUILD_ARCGIS}" == "ON" ]]; then GROUP5_TARGETS=( # Viewer module with ArcGIS (full build) situationMapCommon + ArcGISQt5Hack + situationMapElevationMap + situationMapGeometryModel + situationMapSideBar advancedSymbology advancedSymbologyXML + situationMap LtsDataView LtsDataViewTest LtsFileDialog @@ -924,7 +934,11 @@ else GROUP5_TARGETS=( # Viewer module without ArcGIS (viewer-only subset, advancedSymbology requires ArcGIS) situationMapCommon + situationMapElevationMap + situationMapGeometryModel + situationMapSideBar advancedSymbologyXML + situationMap LtsDataView LtsDataViewTest ) @@ -932,7 +946,11 @@ else GROUP5_TARGETS=( # Viewer module without ArcGIS (full build) situationMapCommon + situationMapElevationMap + situationMapGeometryModel + situationMapSideBar advancedSymbologyXML + situationMap LtsDataView LtsDataViewTest LtsFileDialog