Files
qt6-migration-pipeline/prompts/migrate-arcgis300-symbology.prompt.md
berrux-dev 6b84e24b59
Qt6 Migration CI / migrate (push) Has been cancelled
added Arcgis300 and Symbology prompt
2026-10-06 19:55:34 +02:00

24 KiB

Strict Qt6 Migration Prompt: ArcGIS 300 Symbology — verify & complete the SituationMap + AdvancedSymbology migration

This prompt is binding task context. Keep changes minimal, scoped, and reproducible. The only allowed outcome is a fully-verified ArcGIS-300 symbology migration in qt6-after/qt6-migrated-legatus in which every migrated symbology file preserves the legacy Qt5 behavior except for the approved Qt5→Qt6 / ArcGIS-Maps-SDK-300 API adaptations. No behavior change is allowed in the ON-variant (validated) build.

ArcGIS version in use: ArcGIS Maps SDK for Qt 300.0.0 (external/ArcGIS/MapsSDK_Qt_300.0.0/ArcGIS_Maps_SDK_Qt_300.0.0/qt300.0.0/sdk).

Required base prompts

Before making changes, read and apply:

  • ./prompts/combined-migration-subfolder-rti-compact.prompt.md
  • ./prompts/commit-policy.prompt.md (repository mapping, pre-commit checks, per-repo commits)

If a base prompt is stricter, follow it. This prompt adds:

  • build variants: ON variants only for BUILD_RTI/BUILD_GRANTLEE; validation uses BUILD_ARCGIS=ON (this is not an RTI/Grantlee OFF variant — the prohibition on OFF RTI/Grantlee does not apply to ArcGIS)
  • scope: the symbology subsystem (SituationMap + AdvancedSymbology), ArcGIS 300.0.0

Task

Verify — and where the migration is incomplete or diverges from legacy, complete — the ArcGIS 300 migration of the symbology subsystem:

  • the SituationMap viewer's military (SIDC) symbology: Symbology/, SymbologyImpl/, SymbologyXML/ (the pure-Qt SIDC codec/builder/dictionary plus the Esri dictionary-symbol processors that parse ArcGIS .style dictionaries)
  • the ArcGIS map layer: SituationMap/Map/ (now on the new ArcGIS Maps SDK for Qt 300.0.0)
  • the AdvancedSymbology plugin: Lts/Plugins/AdvancedSymbology/ (symbol editor, symbol proxy, data plugin, helper renderer)
  • the one remaining ArcGIS-dependent service file: Lts/Services/CentralEffectSimulation/Plugins/Explosions/expand_polygon.cpp

For every file in scope, diff it against the legacy Qt5 tree and prove each hunk is migration-only (or restore it to the legacy semantics with approved adaptations, or report a blocker).

Branches and trees

Working repository (a separate git repo; never commit its changes into the workspace root or the legacy repository):

  • ./qt-migration-legatus

Trees:

  • Legacy Qt5 source tree (read-only reference, never modify): ./qt-migration-legatus/qt5-before/qt5-legatus-legacy
  • Qt6 target tree (the only tree that is modified): ./qt-migration-legatus/qt6-after/qt6-migrated-legatus

Working branch: the dedicated ArcGIS-300 symbology branch the user created for this work (verify its name with git branch --show-current; do not conflate it with the main migration branch).

Before starting:

  1. git fetch origin in ./qt-migration-legatus.
  2. Confirm the working tree state with git status --short. Known state at prompt writing (2026-10-06): the main worktree is on feature/qt6-migration-projects-app-tools-viewer-validation-tetraif at 1e07bf76b ("Add ddsview topic-type-plugin deps to GROUP6") with two uncommitted files — qt6-after/qt6-migrated-legatus/new_docker_build.sh (the ensure_database step) and qt6-after/qt6-migrated-legatus/tests/CMakeLists.txt (10 migration_tests target-guard fixes). Do not lose these: if they are not part of this task, commit or stash them on their own branch first; do not fold unrelated changes into the symbology commit.
  3. Confirm both trees exist and that the ArcGIS SDK 300.0.0 directory exists at the path below. If the working tree has unrelated uncommitted changes that block safe work, report the blocker.

What is already established (verified 2026-10-06 — starting state; re-verify cheaply)

Treat the following as the verified starting state. Re-run the cheap checks to confirm the current state, but do not re-derive the whole picture.

  • The migration STUBBED almost all ArcGIS. Legacy Lts/Viewer uses the OLD ArcGIS Runtime SDK (100.x) with 399 #include <arcgis/...>. The migrated tree has 11 arcgis includes total, all in:
    • Lts/Viewer/SituationMap/Map/situation_map_utils.h (SceneViewTypes.h, Error.h)
    • Lts/Viewer/SituationMap/Map/situation_map_utils.cpp (CoreTypes.h, MapTypes.h, Viewpoint.h, Camera.h, arcgisversion.h)
    • Lts/Viewer/SituationMap/Map/map_initializer.cpp (arcgisversion.h)
    • Lts/Viewer/SituationMap/Map/layer_factory.h (arcgisversion.h)
    • Lts/Services/CentralEffectSimulation/Plugins/Explosions/expand_polygon.cpp (PolygonBuilder.h, GeometryEngine.h)
  • Lts/Viewer/SituationMap/ElevationMap/ (7 files in legacy) is removed entirely in the migrated tree. Do not restore it unless this task explicitly requires it.
  • The SIDC symbology (Symbology/, SymbologyImpl/, SymbologyXML/) is pure Qt — zero arcgis includes. The ArcGIS dependency is confined to the map layer and the one service file above.
  • The migrated arcgis includes use the new 300.0.0 header names (MapTypes.h, Viewpoint.h, Camera.h, CoreTypes.h, SceneViewTypes.h, PolygonBuilder.h, GeometryEngine.h, arcgisversion.h) and keep the Esri::ArcGISRuntime:: namespace (e.g. Esri::ArcGISRuntime::SymbolStyleSearchResult in SymbologyImpl/esri_dictionary_processor.cpp). The include style is inconsistent: some keep the arcgis/ prefix (#include <arcgis/Viewpoint.h>), some drop it (#include <TaskWatcher.h>). This must be reconciled (see step 6 of the procedure).
  • Audit baseline (2026-10-06, CRLF-ignored diff of files present in both trees):
    • SituationMap: 96 common source files differ, ~1149 changed lines, all migration-only so far.
    • AdvancedSymbology: 37 common source files differ (no added/removed source files).
    • The Esri dictionary processors (esri_dictionary_processor*.cpp) changed only includes (#include <arcgis/X.h> → #include <X.h>, Qt include-path churn, qAsConst→std::as_const); the Esri types and symbol-search logic are unchanged.

Scope (the files to audit)

Audit, diff-vs-legacy, and classify every source file in:

  1. Lts/Viewer/SituationMap/Symbology/ — SIDC codec/builder/dictionary/definitions (sidc_codec.*, sidc_builder*.*, symbol_dictionary*.*, symbol_properties.*, symbol_result.*, sidc_definitions.*, bulk_renderer.*, property_result.*, result_watcher.*, symbol_data_to_render*.*, symbology_type.*, …).
  2. Lts/Viewer/SituationMap/SymbologyImpl/ — esri_dictionary_processor*.cpp/.h (esri_dictionary_processor, ..._app6, ..._app6d, ..._mil2525d), base_symbol_model.*, symbol_dictionary_impl.*, symbol_extension_renderer.*, advanced_symbology_logging.*.
  3. Lts/Viewer/SituationMap/SymbologyXML/ — symbol.*, symbol_reader.*, symbol_writer.*, symbol_exporter.*, symbol_table.*, pixmap_symbol_cache.*, symbol_custom_graphics_item_group.*, attribute_data.h, symbol_types.h, xml_symbol_codec.h, Gui/symbol_dialog.*.
  4. Lts/Viewer/SituationMap/Map/ — the ArcGIS map layer (57 files): map.*, map_initializer.*, layer_factory.h, situation_map_utils.*, camera.*, fill_style.*, line_style.*, geometry_model_renderer.*, object_container.*, object_factory.*, map_settings.*, operator_map_settings.*, map_notifier.*, bounding_box.*, grid.h, measurement.h, … and every sibling present in the dir.
  5. Lts/Plugins/AdvancedSymbology/ (37 files): Data/asb_data_plugin.*, Data/asb_foreign_interface_impl.*, Data/logger.*, Gui/SymbolEditor/*, Gui/SymbolProxy/*, Helper/table_model_symbol_renderer*.*, and the asb_*_interface.h headers.
  6. Lts/Services/CentralEffectSimulation/Plugins/Explosions/expand_polygon.cpp.

Do not touch ElevationMap/ (removed) unless the task requires restoring it.

Expected migration patterns (each must verify as migration-only)

These are the changes seen in the baseline audit. Each is an approved adaptation; when you see one, confirm it is the exact legacy-equivalent transformation and leave it. If a file deviates from the pattern (extra/missing logic), classify it as semantic-change and act.

  • Qt include path churn: #include <QX> → #include <QtCore/QX> (and QtGui/, QtWidgets/, QtMultimedia/, QtNetwork/, QtSql/, QtXml/, QtPrintSupport/).
  • qAsConst(x) → std::as_const(x) (Qt6 removed qAsConst).
  • QRegExp::exactMatch(s) → QRegularExpression::match(s).hasMatch(); QRegExp → QRegularExpression (type + include).
  • QString::count() → QString::size() (count() removed in Qt6).
  • QString::leftRef(n) → QString::left(n) (leftRef removed in Qt6; a // Qt6: leftRef removed note may accompany it).
  • QString::split(...): in Qt6 the QStringView overload is gone and split() returns QStringList. Sites may now use QVector<QStringView> or QStringList — verify the chosen type is behavior-identical (same element order/values, same last()/indexing).
  • New const QStringView & overloads added to the SIDC codec helpers (decodeSymbology, decodeSidc, encodeBaseSymbolCode, encodeComplete, encodeCivilEts, encodeCivilXml) that delegate to the QString overloads (.toString()). Verify the delegate body is an exact pass-through.
  • ArcGIS include path: old <arcgis/X.h> → the SDK-300 layout. Reconcile to ONE consistent form (see procedure step 6) that matches how the CMake sets the SDK include path.
  • const QImage &img = x.image() → const QImage img = x.image() (Qt6 QImage::image() returns by value).

Verify carefully (potential behavior changes — do NOT auto-accept)

These are the non-obvious changes. For each, prove the legacy semantics are preserved in the validated (ON) build, or report a blocker. Files are given so you do not hunt.

  1. ParticipantManagement::Role_def::* → Role::* — file Lts/Viewer/SituationMap/Symbology/symbol_data_to_render_role.h. Legacy references the DDS-generated enumerator set Role_def; migrated references Role. This is a DDS-generated-type rename. VERIFY the enum value mapping is 1:1 — every Role_def::X → Role::X with the same numeric value/meaning (Unknown, Friend, Neutral, Enemy, Pending, AssumedFriend, Suspect, …). If the generated Role enum dropped, added, or reordered any enumerator, flag it (the value→role mapping must be preserved).
  2. #ifdef BUILD_WITH_EXTERNAL_DDS role-conversion stub — files Lts/Viewer/SituationMap/Symbology/symbol_data_to_render_role.h and Lts/Plugins/AdvancedSymbology/Data/asb_foreign_interface_impl.{h,cpp}. When external DDS types are absent, roleToRole(...) returns Role::Unknown (a STUB) instead of the real conversion. This is a runtime behavior change vs legacy. Confirm: (a) the real path (external-DDS available) still matches legacy 1:1; (b) the STUB path is never the one exercised in the validated ON build; (c) the stub is documented as intentional migration scaffolding. Do NOT "fix" the stub to look real, and do NOT let it leak into the validated build.
  3. Logger pattern — files Lts/Viewer/SituationMap/SymbologyImpl/ advanced_symbology_logging.{h,cpp}, symbol_dictionary_impl.cpp, esri_dictionary_processor.cpp, base_symbol_model.cpp. Legacy LOGGER_T m_logger = getLogger("...") (local) → migrated member NGL::INGLLogger &m_logger initialized in the constructor (, m_logger(getLogger(...))). Matches the known export-header/logger migration pattern. VERIFY there is no double-allocation, lifetime, or initialization-order issue, and the logger name string is unchanged.
  4. QAbstractItemModel filter API — file Lts/Viewer/SituationMap/SymbologyImpl/base_symbol_model.cpp. Legacy invalidateFilter() → migrated beginFilterChange() / endFilterChange() (Qt6 removed invalidateFilter()). VERIFY every invalidateFilter() call is correctly wrapped (a beginFilterChange() before the change and an endFilterChange() after), preserving the same filtering semantics.

Mandatory build variants

Only these variants are valid for validation:

  • BUILD_RTI=ON
  • BUILD_GRANTLEE=ON
  • BUILD_ARCGIS=ON

Forbidden: BUILD_RTI=OFF, BUILD_GRANTLEE=OFF. Do not implement, fix, preserve, test, or validate OFF variants of BUILD_RTI/BUILD_GRANTLEE (no CMake logic, tests, stubs, or fallbacks for them). BUILD_ARCGIS must be ON for this task (the ArcGIS map layer is the point). The #ifdef BUILD_ARCGIS / #ifdef BUILD_WITH_EXTERNAL_DDS guards and their STUB fallbacks are accepted migration scaffolding, but the validated build must use the real, legacy-faithful (ON) path.

Preservation rules

  • Migration-only: every change must be justified against the legacy Qt5 source at the same relative path. No behavior change in the ON-variant / validated build.
  • No refactoring, no style cleanup, no warning suppression, no new features, no opportunistic modernization.
  • Do not restore removed modules or the ElevationMap/ directory unless this task explicitly requires it.
  • Never commit generated outputs. No fake/dummy/stub files beyond the accepted BUILD_ARCGIS/BUILD_WITH_EXTERNAL_DDS scaffolding that already exists.
  • Any required existing stub/forward declaration must live only under qt6-after/qt6-migrated-legatus/forward-declarations/ or qt6-after/qt6-migrated-legatus/.forward-declarations/include/; do not leave such files in service/plugin directories.
  • Keep the Esri::ArcGISRuntime::* type names (do not "modernize" them away).
  • Keep the SIDC symbology pure-Qt: do not introduce arcgis includes into Symbology/, SymbologyImpl/, or SymbologyXML/ (they have none today).

Legacy comparison (required validation step)

This step proves the migration did not change code behavior.

Reference audit command (reproduce; CRLF-ignored, only files present in both trees):

cd ./qt-migration-legatus
LEG=qt5-before/qt5-legatus-legacy/Lts/Viewer/SituationMap
MIG=qt6-after/qt6-migrated-legatus/Lts/Viewer/SituationMap
: > /tmp/sym_cr.diff; n_real=0
while IFS= read -r rel; do
  if [[ -f "$LEG/$rel" && -f "$MIG/$rel" ]] && ! diff -q "$LEG/$rel" "$MIG/$rel" >/dev/null 2>&1; then
    if diff -q --strip-trailing-cr "$LEG/$rel" "$MIG/$rel" >/dev/null 2>&1; then :; else
      n_real=$((n_real+1)); diff -u --strip-trailing-cr "$LEG/$rel" "$MIG/$rel" >> /tmp/sym_cr.diff
    fi
  fi
done < <(cd "$LEG" && find . -type f \( -name '*.cpp' -o -name '*.h' -o -name '*.hpp' \) | sed 's#^\./##' | sort)
echo "files with real changes: $n_real"

For every file you edit (and, as a sweep, every in-scope file):

  1. Read the legacy Qt5 source at the same relative path in ./qt-migration-legatus/qt5-before/qt5-legatus-legacy. If the file does not exist there (e.g. a pure-Qt6 scaffolding header), say so and compare against the pre-migration baseline.
  2. Produce the audit diff: migrated result vs legacy (CRLF-ignored).
  3. Classify every hunk of the audit diff into exactly one category:
    • qt6-api: mandatory Qt5→Qt6 API adaptation (the pattern list above)
    • sdk300-api: mandatory ArcGIS old-SDK → Maps-SDK-300 adaptation
    • build: CMake/docker/test-infra change with no runtime semantics
    • stub-scaffolding: an accepted #ifdef BUILD_ARCGIS / BUILD_WITH_EXTERNAL_DDS guard (documented, OFF-path only)
    • semantic-change: anything else
  4. Every semantic-change hunk is a failure of this task unless you can point to the legacy source line that implements the same behavior. Fix it back to the legacy semantics (with approved adaptations) or report it as a blocker. Do not silently accept semantic-change hunks.
  5. Record the per-file hunk classification (counts per category is sufficient; list every semantic-change hunk explicitly) in the final report.

Docker and CI

  • Authoritative validation script: ./qt-migration-legatus/qt6-after/qt6-migrated-legatus/new_docker_build.sh
  • Prebuilt image legatus-qt6-prebuilt:latest (has local PostgreSQL; the DB is auto-provisioned by the ensure_database step — no office DB needed).
  • ArcGIS SDK under /workspace/external/ArcGIS/MapsSDK_Qt_300.0.0/ArcGIS_Maps_SDK_Qt_300.0.0/ qt300.0.0/sdk (mounted from the pipeline root external/); repo root at /workspace.
  • new_docker_build.sh is the single validation script; do not reintroduce a second script.

Required procedure

  1. Read the base prompts. git fetch origin; confirm the working branch and the working- tree state (protect the two uncommitted files from "Branches and trees").
  2. Confirm the ArcGIS SDK 300.0.0 directory exists at the pipeline-root external/ path (and therefore /workspace/external/... in the container).
  3. Re-run the audit command over SituationMap/ and Lts/Plugins/AdvancedSymbology/ (CRLF-ignored); confirm the baseline (SituationMap ~96 files, AdvancedSymbology 37 files, all migration-only). Record any drift.
  4. For each in-scope file, diff vs legacy and classify every hunk (see "Legacy comparison"). Fix any semantic-change back to legacy semantics (with approved adaptations) or report a blocker.
  5. Resolve the four "Verify carefully" items (Role value mapping; the DDS roleToRole stub real-path vs legacy; the logger pattern; the filter API pairing).
  6. Reconcile the ArcGIS include style (the arcgis/ prefix question) across the 11 migrated arcgis includes to ONE consistent form that matches the SDK 300 include path set in CMake. Record which form you chose and why.
  7. Confirm the Esri dictionary processors still parse the same .style / MIL-STD-2525D / App-6 / App-6D dictionaries as legacy (same Esri::ArcGISRuntime::* types, same symbol results; only includes changed).
  8. Build the symbology targets with BUILD_RTI=ON BUILD_GRANTLEE=ON BUILD_ARCGIS=ON (the Viewer/SituationMap targets + the AdvancedSymbology plugin targets + expand_polygon) and confirm they compile and link against the 300.0.0 SDK.
  9. Run the relevant CTest tests.
  10. Create the commit(s) (see "Commits").
  11. Report factual status and write the summary (see "Summary").

Do not push. The result stays local on the working branch until the user says otherwise.

Required validation

Targeted (fast, focused) — from the repo root, in the validation container (repo at /workspace):

cmake -S /workspace/qt-migration-legatus/qt6-after/qt6-migrated-legatus \
  -B /workspace/build-arcgis300-symbology -G Ninja -DCMAKE_BUILD_TYPE=Debug \
  -DBUILD_RTI=ON -DBUILD_GRANTLEE=ON -DBUILD_ARCGIS=ON \
  -DUSE_IPO=ON -DUSE_UNITY_BUILD=ON -DGUEZ_MODE=ON -DBUILD_WLS=ON \
  -DPostgreSQL_TYPE_INCLUDE_DIR=/usr/include/postgresql/
# Discover the exact SituationMap + AdvancedSymbology target names from the
# SituationMap/AdvancedSymbology CMakeLists (or new_docker_build.sh's GROUP5_TARGETS),
# then build only those (faster than the whole tree):
cmake --build /workspace/build-arcgis300-symbology --target <situationmap_target> \
  <asb_symbol_editor> <asb_symbol_proxy> <asb_data_plugin> --parallel
ctest --test-dir /workspace/build-arcgis300-symbology --output-on-failure

End-to-end via the validation script (the Viewer group carries the SituationMap targets; also build the group that owns the AdvancedSymbology plugin targets — identify it from GROUPn_TARGETS in new_docker_build.sh):

cd ./qt-migration-legatus/qt6-after/qt6-migrated-legatus
BUILD_RTI=ON BUILD_GRANTLEE=ON BUILD_ARCGIS=ON ./new_docker_build.sh \
  --use-prebuilt-image --docker-image legatus-qt6-prebuilt:latest --group5

Mandatory positive checks:

  • The SituationMap map layer compiles and links against the ArcGIS Maps SDK 300.0.0 targets (no undefined Esri::ArcGISRuntime::* refs; no Qt5 imported-target links).
  • The Esri dictionary-symbol processors build and the SIDC codec/dictionary tests pass (same symbol results as legacy for the same inputs).
  • The AdvancedSymbology plugin targets build.
  • No ***Failed/***Timeout CTest entries beyond documented base-state failures (record any base-state failures as base state, do not weaken a test to make it pass).
  • No active Qt5 imported-target links (Qt5::, find_package(Qt5, Qt5Core, …) in the touched targets.

Do not run or validate OFF variants of BUILD_RTI/BUILD_GRANTLEE.

Commits

Commits on the working branch:

  • Single author — the user's git identity (berrux-dev berrux.kana@axilinx.com). The user is the only author; do NOT add any co-author, co-authored-by, or bot attribution lines of any kind.
  • Message: maximum 2 lines (one subject line plus at most one short body line), no blank-line separators, no extra metadata. Subject example: Qt6: verify/complete ArcGIS 300 symbology migration (SituationMap + AdvancedSymbology)
  • The repository has commit.gpgsign=false: sign every created commit explicitly (git commit -S). Follow ./prompts/commit-policy.prompt.md for repository mapping and pre-commit checks. If signing is not configured in this repository context, stop and report the exact reason instead of committing unsigned.
  • Keep the two unrelated uncommitted files (new_docker_build.sh DB step, tests/CMakeLists.txt guard fixes) OUT of the symbology commit unless the user says otherwise.
  • If a fix requires an additional commit, the same 2-line / single-author / no-attribution / signed rules apply.

Success criteria

Success requires:

  • every in-scope file diffed vs legacy and every hunk classified; zero unexplained semantic-change hunks (each one either fixed to legacy semantics or reported as a blocker)
  • the four "Verify carefully" items resolved with evidence (Role 1:1 mapping; the DDS roleToRole stub real-path matches legacy and does not leak into the ON build; the logger pattern is sound; the filter API pairing is correct)
  • the 11 migrated arcgis includes reconciled to ONE consistent include style (recorded)
  • the Esri dictionary processors confirmed to parse the same dictionaries as legacy
  • configure, build (link), and CTest pass with BUILD_RTI=ON BUILD_GRANTLEE=ON BUILD_ARCGIS=ON for the symbology targets
  • no active Qt5 imported-target links in the touched targets; generated outputs build-tree only, never committed; no fake/dummy/stub files beyond the accepted scaffolding
  • required stubs/forward declarations only in allowed directories
  • no OFF-variant logic/stubs for BUILD_RTI/BUILD_GRANTLEE introduced
  • the commits are signed (verify Good), single-author, ≤2-line, no bot attribution
  • no push performed

If blocked

Do not fake success. Report:

  • failing command and key error output
  • affected file/branch
  • category: project, path, CMake, Qt API, ArcGIS-SDK-300, DDS-generated-types, codegen, Docker, RTI/license, test, CTest, stub scaffolding, or environment
  • the specific in-scope file and hunk, and which category it was misclassified as
  • what was resolved safely, what remains blocked
  • whether stale artifacts were ruled out
  • whether generated files or the ArcGIS SDK path were involved
  • the legacy comparison status for the unresolved files

Final report

Keep it short. Include:

  • status: validated, partially validated, or blocked
  • the working branch name and the commit hash(es) (signed)
  • the re-run audit baseline (SituationMap / AdvancedSymbology file + changed-line counts) and any drift vs the 2026-10-06 baseline
  • per-scope-area hunk counts by category, and every semantic-change hunk with its justification or fix
  • the four "Verify carefully" resolutions with evidence (Role mapping; DDS stub real-path; logger; filter API)
  • the ArcGIS include-style decision (prefix vs bare) and the reason
  • the Esri dictionary-processor equivalence evidence
  • exact validation commands and results (targeted build + the --group5 docker run + ctest)
  • remaining blockers or risks

Summary

Write a MIGRATION_SUMMARY_ARCGIS300_SYMBOLOGY.md (same style/convention as MIGRATION_SUMMARY_Z_AND_PROXIES.md) documenting: the scope audited, the migration-only pattern classes found, the four verify-carefully resolutions, the ArcGIS 300 include-style reconciliation, the validation commands/results, and the remaining blockers. Place it at the migrated-tree root (qt6-after/qt6-migrated-legatus/) and commit it with the work.