diff --git a/.clang-format-ignore b/.clang-format-ignore deleted file mode 100644 index 5e71f5bf..00000000 --- a/.clang-format-ignore +++ /dev/null @@ -1 +0,0 @@ -CMakePresets.json diff --git a/.clang-tidy b/.clang-tidy deleted file mode 100644 index 0ca21696..00000000 --- a/.clang-tidy +++ /dev/null @@ -1,19 +0,0 @@ -Checks: - - '-*' - - 'bugprone-*' - - 'clang-analyzer-*' - - 'cppcoreguidelines-*' - - 'misc-*' - - 'modernize-*' - - 'performance-*' - - '-bugprone-easily-swappable-parameters' - - '-cppcoreguidelines-avoid-do-while' - - '-cppcoreguidelines-avoid-non-const-global-variables' - - '-cppcoreguidelines-pro-type-reinterpret-cast' - - '-cppcoreguidelines-pro-type-union-access' - - '-misc-include-cleaner' - - '-misc-non-private-member-variables-in-classes' - - '-misc-use-anonymous-namespace' - - '-modernize-return-braced-init-list' - - '-modernize-use-trailing-return-type' -FormatStyle: 'file' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e3033807..ba82d35a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ on: concurrency: # Cancel in-progress jobs for the same pull request - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + group: ${{ github.head_ref || github.run_id }} cancel-in-progress: true jobs: @@ -20,130 +20,61 @@ jobs: fail-fast: false matrix: include: - - name: windows_msvc2022_x64 + - name: win64_msvc2022 os: windows-2022 build_type: Release env_cc: '' env_cxx: '' compiler: msvc - cppflags: '' - ldflags: '' msvc_arch: x64 msvc_version: 2022 - qt_version: 6.9.2 - qt_arch_aqt: win64_msvc2022_64 - qt_arch_dir: msvc2022_64 + qt_version: 6.7.2 + qt_arch_aqt: win64_msvc2019_64 + qt_arch_dir: msvc2019_64 qt_modules: qtimageformats qtmultimedia qtpositioning qtserialport qt_tools: '' + conan_arch: x86_64 + conan_compiler: Visual Studio + conan_compiler_version: 17 + conan_compiler_runtime: --settings compiler.runtime=MD conan_package_manager: '' - conan_profile: scwx-windows_msvc2022_x64 - appimage_arch: '' artifact_suffix: windows-x64 - - name: linux_gcc_x64 + - name: linux64_gcc os: ubuntu-22.04 build_type: Release env_cc: gcc-11 env_cxx: g++-11 compiler: gcc - cppflags: '' - ldflags: '' - qt_version: 6.9.2 + qt_version: 6.7.2 qt_arch_aqt: linux_gcc_64 qt_arch_dir: gcc_64 qt_modules: qtimageformats qtmultimedia qtpositioning qtserialport qt_tools: '' + conan_arch: x86_64 + conan_compiler: gcc + conan_compiler_version: 11 + conan_compiler_runtime: '' conan_package_manager: --conf tools.system.package_manager:mode=install --conf tools.system.package_manager:sudo=True - conan_profile: scwx-linux_gcc-11 - appimage_arch: x86_64 artifact_suffix: linux-x64 - compiler_packages: '' - - name: linux_clang_x64 - os: ubuntu-24.04 - build_type: Release - env_cc: clang-17 - env_cxx: clang++-17 - compiler: clang - cppflags: '' - ldflags: '' - qt_version: 6.9.2 - qt_arch_aqt: linux_gcc_64 - qt_arch_dir: gcc_64 - qt_modules: qtimageformats qtmultimedia qtpositioning qtserialport - qt_tools: '' - conan_package_manager: --conf tools.system.package_manager:mode=install --conf tools.system.package_manager:sudo=True - conan_profile: scwx-linux_clang-17 - appimage_arch: x86_64 - artifact_suffix: linux-clang-x64 - compiler_packages: clang-17 - - name: linux_gcc_arm64 - os: ubuntu-24.04-arm - build_type: Release - env_cc: gcc-11 - env_cxx: g++-11 - compiler: gcc - cppflags: '' - ldflags: '' - qt_version: 6.9.2 - qt_arch_aqt: linux_gcc_arm64 - qt_arch_dir: gcc_arm64 - qt_modules: qtimageformats qtmultimedia qtpositioning qtserialport - qt_tools: '' - conan_package_manager: --conf tools.system.package_manager:mode=install --conf tools.system.package_manager:sudo=True - conan_profile: scwx-linux_gcc-11_armv8 - appimage_arch: aarch64 - artifact_suffix: linux-arm64 - compiler_packages: g++-11 - - name: macos_clang18_x64 - os: macos-13 - build_type: Release - env_cc: clang - env_cxx: clang++ - compiler: clang - qt_version: 6.9.2 - qt_arch_aqt: clang_64 - qt_arch_dir: macos - qt_modules: qtimageformats qtmultimedia qtpositioning qtserialport - qt_tools: '' - conan_package_manager: '' - conan_profile: scwx-macos_clang-18 - appimage_arch: '' - artifact_suffix: macos-x64 - - name: macos_clang18_arm64 - os: macos-14 - build_type: Release - env_cc: clang - env_cxx: clang++ - compiler: clang - qt_version: 6.9.2 - qt_arch_aqt: clang_64 - qt_arch_dir: macos - qt_modules: qtimageformats qtmultimedia qtpositioning qtserialport - qt_tools: '' - conan_package_manager: '' - conan_profile: scwx-macos_clang-18_armv8 - appimage_arch: '' - artifact_suffix: macos-arm64 name: ${{ matrix.name }} env: CC: ${{ matrix.env_cc }} CXX: ${{ matrix.env_cxx }} - SCWX_VERSION: v0.5.1 + SCWX_VERSION: v0.4.5 runs-on: ${{ matrix.os }} steps: - name: Setup run: git config --global core.longpaths true - + - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v4 with: path: source submodules: recursive - name: Install Qt - uses: jdpurcell/install-qt-action@v5 - env: - AQT_CONFIG: ${{ github.workspace }}/source/tools/aqt-settings.ini + uses: jurplel/install-qt-action@v3 with: version: ${{ matrix.qt_version }} arch: ${{ matrix.qt_arch_aqt }} @@ -158,79 +89,50 @@ jobs: vsversion: ${{ matrix.msvc_version }} - name: Setup Ubuntu Environment - if: ${{ startsWith(matrix.os, 'ubuntu') }} + if: matrix.os == 'ubuntu-22.04' shell: bash run: | sudo apt-get install doxygen \ libfuse2 \ - ninja-build \ - wayland-protocols \ - libwayland-dev \ - libwayland-egl-backend-dev \ - flatpak \ - flatpak-builder \ - ${{ matrix.compiler_packages }} - - - name: Setup macOS Environment - if: ${{ startsWith(matrix.os, 'macos') }} - shell: bash - run: | - brew install llvm@18 - LLVM_PATH=$(brew --prefix llvm@18) - echo "CC=${LLVM_PATH}/bin/clang" >> $GITHUB_ENV - echo "CXX=${LLVM_PATH}/bin/clang++" >> $GITHUB_ENV - echo "CPPFLAGS=-I${LLVM_PATH}/include" >> $GITHUB_ENV - echo "LDFLAGS=-L${LLVM_PATH}/lib -L${LLVM_PATH}/lib/c++" >> $GITHUB_ENV + ninja-build - name: Setup Python Environment shell: pwsh run: | pip install geopandas ` - GitPython ` - conan - - - name: Cache Conan Packages - uses: actions/cache@v4 - with: - path: ~/.conan2 - key: build-${{ matrix.conan_profile }}-${{ hashFiles('./source/conanfile.py', './source/tools/conan/profiles/*') }} + GitPython - name: Install Conan Packages shell: pwsh run: | - conan config install ` - ./source/tools/conan/profiles/${{ matrix.conan_profile }} ` - -tf profiles - mkdir build - cd build - mkdir conan - conan install ../source/ ` + pip install "conan<2.0" + conan profile new default --detect + conan install ./source/ ` --remote conancenter ` --build missing ` - --profile:all ${{ matrix.conan_profile }} ` - --settings:all build_type=${{ matrix.build_type }} ` - --output-folder ./conan/ ` + --settings arch=${{ matrix.conan_arch }} ` + --settings build_type=${{ matrix.build_type }} ` + --settings compiler="${{ matrix.conan_compiler }}" ` + --settings compiler.version=${{ matrix.conan_compiler_version }} ` + ${{ matrix.conan_compiler_runtime }} ` ${{ matrix.conan_package_manager }} - name: Build Supercell Wx shell: pwsh run: | + mkdir build cd build cmake ../source/ ` -G Ninja ` -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" ` - -DCMAKE_PROJECT_TOP_LEVEL_INCLUDES="${{ github.workspace }}/source/external/cmake-conan/conan_provider.cmake" ` - -DCMAKE_INSTALL_PREFIX="${{ github.workspace }}/supercell-wx" ` - -DCONAN_HOST_PROFILE="${{ matrix.conan_profile }}" ` - -DCONAN_BUILD_PROFILE="${{ matrix.conan_profile }}" + -DCMAKE_INSTALL_PREFIX="${{ github.workspace }}/supercell-wx" ninja supercell-wx wxtest - name: Separate Debug Symbols (Linux) - if: ${{ startsWith(matrix.os, 'ubuntu') }} + if: matrix.os == 'ubuntu-22.04' shell: bash run: | cd build/ - cd Release/ cd bin/ objcopy --only-keep-debug supercell-wx supercell-wx.debug objcopy --strip-debug --strip-unneeded supercell-wx @@ -246,7 +148,7 @@ jobs: cmake --install . --component supercell-wx - name: Collect Artifacts - if: ${{ startsWith(matrix.os, 'ubuntu') }} + if: matrix.os == 'ubuntu-22.04' shell: bash run: | pushd supercell-wx/ @@ -259,8 +161,6 @@ jobs: cd plugins/ mkdir -p sqldrivers/ cp "${RUNNER_WORKSPACE}/Qt/${{ matrix.qt_version }}/${{ matrix.qt_arch_dir }}/plugins/sqldrivers/libqsqlite.so" sqldrivers/ - mkdir -p platforms/ - cp ${RUNNER_WORKSPACE}/Qt/${{ matrix.qt_version }}/${{ matrix.qt_arch_dir }}/plugins/platforms/libqwayland* platforms/ cd .. popd tar -czf supercell-wx-${{ matrix.artifact_suffix }}.tar.gz supercell-wx/ @@ -277,23 +177,23 @@ jobs: uses: actions/upload-artifact@v4 with: name: supercell-wx-debug-${{ matrix.artifact_suffix }} - path: ${{ github.workspace }}/build/Release/bin/*.pdb + path: ${{ github.workspace }}/build/bin/*.pdb - name: Upload Artifacts (Linux) - if: ${{ startsWith(matrix.os, 'ubuntu') }} + if: matrix.os == 'ubuntu-22.04' uses: actions/upload-artifact@v4 with: name: supercell-wx-${{ matrix.artifact_suffix }} path: ${{ github.workspace }}/supercell-wx-${{ matrix.artifact_suffix }}.tar.gz - name: Upload Debug Artifacts (Linux) - if: ${{ startsWith(matrix.os, 'ubuntu') }} + if: matrix.os == 'ubuntu-22.04' uses: actions/upload-artifact@v4 with: name: supercell-wx-debug-${{ matrix.artifact_suffix }} path: | - ${{ github.workspace }}/build/Release/bin/*.debug - ${{ github.workspace }}/build/Release/lib/*.debug + ${{ github.workspace }}/build/bin/*.debug + ${{ github.workspace }}/build/lib/*.debug - name: Build Installer (Windows) if: matrix.os == 'windows-2022' @@ -310,90 +210,42 @@ jobs: path: ${{ github.workspace }}/build/supercell-wx-*.msi* - name: Build AppImage (Linux) - if: ${{ startsWith(matrix.os, 'ubuntu') }} + if: matrix.os == 'ubuntu-22.04' env: - INSTALL_DIR: ${{ github.workspace }}/supercell-wx/ - APPIMAGE_DIR: ${{ github.workspace }}/supercell-wx-appimage/ - LDAI_UPDATE_INFORMATION: gh-releases-zsync|dpaulat|supercell-wx|latest|*${{ matrix.appimage_arch }}.AppImage.zsync - LDAI_OUTPUT: supercell-wx-${{ env.SCWX_VERSION }}-${{ matrix.appimage_arch }}.AppImage + APPIMAGE_DIR: ${{ github.workspace }}/supercell-wx/ + LDAI_UPDATE_INFORMATION: gh-releases-zsync|dpaulat|supercell-wx|latest|*x86_64.AppImage.zsync + LDAI_OUTPUT: supercell-wx-${{ env.SCWX_VERSION }}-x86_64.AppImage LINUXDEPLOY_OUTPUT_APP_NAME: supercell-wx LINUXDEPLOY_OUTPUT_VERSION: ${{ env.SCWX_VERSION }} shell: bash run: | - wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-${{ matrix.appimage_arch }}.AppImage - chmod +x linuxdeploy-${{ matrix.appimage_arch }}.AppImage + wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage + chmod +x linuxdeploy-x86_64.AppImage cp "${{ github.workspace }}/source/scwx-qt/res/icons/scwx-256.png" supercell-wx.png cp "${{ github.workspace }}/source/scwx-qt/res/linux/supercell-wx.desktop" . - cp -r "${{ env.INSTALL_DIR }}" "${{ env.APPIMAGE_DIR }}" pushd "${{ env.APPIMAGE_DIR }}" mkdir -p usr/ mv bin/ usr/ mv lib/ usr/ mv plugins/ usr/ popd - ./linuxdeploy-${{ matrix.appimage_arch }}.AppImage --appdir ${{ env.APPIMAGE_DIR }} -i supercell-wx.png -d supercell-wx.desktop - ./linuxdeploy-${{ matrix.appimage_arch }}.AppImage --appdir ${{ env.APPIMAGE_DIR }} --output appimage - rm -f linuxdeploy-${{ matrix.appimage_arch }}.AppImage + ./linuxdeploy-x86_64.AppImage --appdir ${{ env.APPIMAGE_DIR }} -i supercell-wx.png -d supercell-wx.desktop + ./linuxdeploy-x86_64.AppImage --appdir ${{ env.APPIMAGE_DIR }} --output appimage + rm -f linuxdeploy-x86_64.AppImage - name: Upload AppImage (Linux) - if: ${{ startsWith(matrix.os, 'ubuntu') }} + if: matrix.os == 'ubuntu-22.04' uses: actions/upload-artifact@v4 with: - name: supercell-wx-appimage-${{ matrix.artifact_suffix }} - path: ${{ github.workspace }}/*-${{ matrix.appimage_arch }}.AppImage* - - - name: Build FlatPak (Linux) - if: ${{ startsWith(matrix.os, 'ubuntu') }} - env: - INSTALL_DIR: ${{ github.workspace }}/supercell-wx/ - FLATPAK_DIR: ${{ github.workspace }}/supercell-wx-flatpak/ - shell: bash - run: | - cp -r ${{ env.INSTALL_DIR }} ${{ env.FLATPAK_DIR }} - # Copy krb5 libraries to flatpak - cp /usr/lib/*/libkrb5.so* \ - /usr/lib/*/libkrb5support.so* \ - /usr/lib/*/libgssapi_krb5.so* \ - /usr/lib/*/libk5crypto.so* \ - /usr/lib/*/libkeyutils.so* \ - ${{ env.FLATPAK_DIR }}/lib - - flatpak remote-add --if-not-exists --user flathub https://dl.flathub.org/repo/flathub.flatpakrepo - flatpak-builder --force-clean \ - --user \ - --install-deps-from=flathub \ - --repo=flatpak-repo \ - --install flatpak-build \ - ${{ github.workspace }}/source/tools/net.supercellwx.app.yml - flatpak build-bundle flatpak-repo supercell-wx.flatpak net.supercellwx.app - - - name: Upload FlatPak (Linux) - if: ${{ startsWith(matrix.os, 'ubuntu') }} - uses: actions/upload-artifact@v4 - with: - name: supercell-wx-flatpak-${{ matrix.artifact_suffix }} - path: ${{ github.workspace }}/supercell-wx.flatpak - - - name: Build Disk Image (macOS) - if: ${{ startsWith(matrix.os, 'macos') }} - shell: pwsh - run: | - cd build - cpack - - - name: Upload Disk Image (macOS) - if: ${{ startsWith(matrix.os, 'macos') }} - uses: actions/upload-artifact@v4 - with: - name: supercell-wx-${{ matrix.artifact_suffix }} - path: ${{ github.workspace }}/build/supercell-wx-*.dmg* + name: supercell-wx-appimage-x64 + path: ${{ github.workspace }}/*-x86_64.AppImage* - name: Test Supercell Wx working-directory: ${{ github.workspace }}/build env: MAPBOX_API_KEY: ${{ secrets.MAPBOX_API_KEY }} MAPTILER_API_KEY: ${{ secrets.MAPTILER_API_KEY }} - run: ctest -C ${{ matrix.build_type }} --exclude-regex "test_mln.*|NtpClient.*|UpdateManager.*" + run: ctest -C ${{ matrix.build_type }} --exclude-regex test_mln.* - name: Upload Test Logs if: ${{ !cancelled() }} diff --git a/.github/workflows/clang-format-check.yml b/.github/workflows/clang-format-check.yml deleted file mode 100644 index 7eaa1e95..00000000 --- a/.github/workflows/clang-format-check.yml +++ /dev/null @@ -1,42 +0,0 @@ -name: clang-format-check - -on: - workflow_dispatch: - pull_request: - branches: - - 'develop' - -concurrency: - # Cancel in-progress jobs for the same pull request - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -jobs: - format: - runs-on: ubuntu-24.04 - steps: - - - name: Checkout - uses: actions/checkout@v5 - with: - fetch-depth: 0 - submodules: false - - - name: Update References - shell: bash - run: | - git fetch origin develop - - - name: Setup Ubuntu Environment - shell: bash - run: | - sudo apt-get install clang-format-19 - sudo rm -f /usr/bin/clang-format - sudo ln -s /usr/bin/clang-format-19 /usr/bin/clang-format - - - name: Check Formatting - shell: bash - run: | - MERGE_BASE=$(git merge-base origin/develop ${{ github.event.pull_request.head.sha || github.ref }}) - echo "Comparing against ${MERGE_BASE}" - git clang-format-19 --diff --style=file -v ${MERGE_BASE} diff --git a/.github/workflows/clang-tidy-comments.yml b/.github/workflows/clang-tidy-comments.yml deleted file mode 100644 index 9a6df52d..00000000 --- a/.github/workflows/clang-tidy-comments.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: Post clang-tidy Review Comments - -on: - workflow_run: - workflows: ["clang-tidy-review"] - types: - - completed - -jobs: - build: - runs-on: ubuntu-latest - if: ${{ github.event.workflow_run.conclusion != 'cancelled' }} - - steps: - - name: Post Comments - uses: ZedThree/clang-tidy-review/post@v0.21.0 - with: - lgtm_comment_body: '' - annotations: false - max_comments: 25 - num_comments_as_exitcode: false diff --git a/.github/workflows/clang-tidy-review.yml b/.github/workflows/clang-tidy-review.yml deleted file mode 100644 index b3de8edf..00000000 --- a/.github/workflows/clang-tidy-review.yml +++ /dev/null @@ -1,152 +0,0 @@ -name: clang-tidy-review - -on: - pull_request: - branches: - - 'develop' - -concurrency: - # Cancel in-progress jobs for the same pull request - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -jobs: - build: - strategy: - matrix: - include: - - name: linux_clang-tidy_x64 - os: ubuntu-24.04 - build_type: Release - env_cc: clang-18 - env_cxx: clang++-18 - qt_version: 6.9.2 - qt_arch_aqt: linux_gcc_64 - qt_modules: qtimageformats qtmultimedia qtpositioning qtserialport - qt_tools: '' - conan_package_manager: --conf tools.system.package_manager:mode=install --conf tools.system.package_manager:sudo=True - conan_profile: scwx-linux_clang-18 - compiler_packages: clang-18 clang-tidy-18 - clang_tidy_binary: clang-tidy-18 - name: ${{ matrix.name }} - runs-on: ${{ matrix.os }} - env: - CC: ${{ matrix.env_cc }} - CXX: ${{ matrix.env_cxx }} - steps: - - - name: Checkout - uses: actions/checkout@v5 - with: - path: source - submodules: recursive - - - name: Checkout clang-tidy-review Repository - uses: actions/checkout@v5 - with: - repository: ZedThree/clang-tidy-review - ref: v0.20.1 - path: clang-tidy-review - - - name: Install Qt - uses: jdpurcell/install-qt-action@v5 - env: - AQT_CONFIG: ${{ github.workspace }}/source/tools/aqt-settings.ini - with: - version: ${{ matrix.qt_version }} - arch: ${{ matrix.qt_arch_aqt }} - modules: ${{ matrix.qt_modules }} - tools: ${{ matrix.qt_tools }} - - - name: Setup Ubuntu Environment - if: ${{ startsWith(matrix.os, 'ubuntu') }} - shell: bash - run: | - sudo apt-get install doxygen \ - libfuse2 \ - ninja-build \ - wayland-protocols \ - libwayland-dev \ - libwayland-egl-backend-dev \ - ${{ matrix.compiler_packages }} - - - name: Setup Python Environment - shell: pwsh - run: | - pip install geopandas ` - GitPython ` - conan - pip install --break-system-packages clang-tidy-review/post/clang_tidy_review - - - name: Cache Conan Packages - uses: actions/cache@v4 - with: - path: ~/.conan2 - key: build-${{ matrix.conan_profile }}-${{ hashFiles('./source/conanfile.py', './source/tools/conan/profiles/*') }} - - - name: Install Conan Packages - shell: pwsh - run: | - conan config install ` - ./source/tools/conan/profiles/${{ matrix.conan_profile }} ` - -tf profiles - mkdir build - cd build - mkdir conan - conan install ../source/ ` - --remote conancenter ` - --build missing ` - --profile:all ${{ matrix.conan_profile }} ` - --settings:all build_type=${{ matrix.build_type }} ` - --output-folder ./conan/ ` - ${{ matrix.conan_package_manager }} - - - name: Autogenerate - shell: pwsh - run: | - cd build - cmake ../source/ ` - -G Ninja ` - -DCMAKE_BUILD_TYPE="${{ matrix.build_type }}" ` - -DCMAKE_PROJECT_TOP_LEVEL_INCLUDES="${{ github.workspace }}/source/external/cmake-conan/conan_provider.cmake" ` - -DCMAKE_INSTALL_PREFIX="${{ github.workspace }}/supercell-wx" ` - -DCONAN_HOST_PROFILE="${{ matrix.conan_profile }}" ` - -DCONAN_BUILD_PROFILE="${{ matrix.conan_profile }}" ` - -DCMAKE_EXPORT_COMPILE_COMMANDS=on - ninja glad_gl_core_33 ` - scwx-qt_generate_counties_db ` - scwx-qt_generate_versions ` - scwx-qt_autogen - - - name: Code Review - id: review - shell: bash - run: | - cd source - review --clang_tidy_binary=${{ matrix.clang_tidy_binary }} \ - --token=${{ github.token }} \ - --repo='${{ github.repository }}' \ - --pr='${{ github.event.pull_request.number }}' \ - --build_dir='../build' \ - --base_dir='${{ github.workspace }}/source' \ - --clang_tidy_checks='' \ - --config_file='' \ - --include='*.[ch],*.[ch]xx,*.[chi]pp,*.[ch]++,*.cc,*.hh' \ - --exclude='' \ - --apt-packages='' \ - --cmake-command='' \ - --max-comments=25 \ - --lgtm-comment-body='' \ - --split_workflow=true \ - --annotations=false \ - --parallel=0 - rsync -avzh --ignore-missing-args clang-tidy-review-output.json ../ - rsync -avzh --ignore-missing-args clang-tidy-review-metadata.json ../ - rsync -avzh --ignore-missing-args clang_fixes.json ../ - - - name: Upload Review - uses: ZedThree/clang-tidy-review/upload@v0.21.0 - - - name: Status Check - if: steps.review.outputs.total_comments > 0 - run: exit 1 diff --git a/.gitignore b/.gitignore index cb46cec7..9e6da487 100644 --- a/.gitignore +++ b/.gitignore @@ -5,20 +5,9 @@ CMakeLists.txt.user CMakeCache.txt CMakeFiles CMakeScripts -CMakeUserPresets.json Testing cmake_install.cmake install_manifest.txt compile_commands.json CTestTestfile.cmake _deps - -# Editor directories -.idea/ -.vs/ - -# Python Virtual Environment -.venv/ - -# Specific excludes for Supercell Wx -tools/lib/user-setup.sh diff --git a/.gitmodules b/.gitmodules index 5bf3b307..52ede30b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,45 +1,39 @@ -[submodule "data"] - path = data - url = https://github.com/dpaulat/supercell-wx-data -[submodule "external/aws-sdk-cpp"] - path = external/aws-sdk-cpp - url = https://github.com/aws/aws-sdk-cpp.git [submodule "external/cmake-conan"] path = external/cmake-conan url = https://github.com/conan-io/cmake-conan.git -[submodule "external/date"] - path = external/date - url = https://github.com/HowardHinnant/date.git -[submodule "external/glad"] - path = external/glad - url = https://github.com/Dav1dde/glad.git +[submodule "test/data"] + path = test/data + url = https://github.com/dpaulat/supercell-wx-test-data [submodule "external/hsluv-c"] path = external/hsluv-c url = https://github.com/hsluv/hsluv-c.git +[submodule "external/stb"] + path = external/stb + url = https://github.com/nothings/stb.git +[submodule "data"] + path = data + url = https://github.com/dpaulat/supercell-wx-data [submodule "external/imgui"] path = external/imgui url = https://github.com/ocornut/imgui.git [submodule "external/imgui-backend-qt"] path = external/imgui-backend-qt url = https://github.com/dpaulat/imgui-backend-qt -[submodule "external/maplibre-native"] - path = external/maplibre-native - url = https://github.com/dpaulat/maplibre-gl-native.git -[submodule "external/maplibre-native-qt"] - path = external/maplibre-native-qt - url = https://github.com/dpaulat/maplibre-native-qt.git -[submodule "external/qt6ct"] - path = external/qt6ct - url = https://github.com/AdenKoperczak/qt6ct.git -[submodule "external/stb"] - path = external/stb - url = https://github.com/nothings/stb.git -[submodule "external/textflowcpp"] - path = external/textflowcpp - url = https://github.com/catchorg/textflowcpp.git +[submodule "external/aws-sdk-cpp"] + path = external/aws-sdk-cpp + url = https://github.com/aws/aws-sdk-cpp.git +[submodule "external/date"] + path = external/date + url = https://github.com/HowardHinnant/date.git [submodule "external/units"] path = external/units url = https://github.com/nholthaus/units.git -[submodule "test/data"] - path = test/data - url = https://github.com/dpaulat/supercell-wx-test-data +[submodule "external/textflowcpp"] + path = external/textflowcpp + url = https://github.com/catchorg/textflowcpp.git +[submodule "external/maplibre-native-qt"] + path = external/maplibre-native-qt + url = https://github.com/dpaulat/maplibre-native-qt.git +[submodule "external/maplibre-native"] + path = external/maplibre-native + url = https://github.com/dpaulat/maplibre-gl-native.git diff --git a/ACKNOWLEDGEMENTS.md b/ACKNOWLEDGEMENTS.md index 1608b2ae..154d0f6c 100644 --- a/ACKNOWLEDGEMENTS.md +++ b/ACKNOWLEDGEMENTS.md @@ -23,7 +23,7 @@ Supercell Wx uses code from the following dependencies: | [FreeType GL](https://github.com/rougier/freetype-gl) | [BSD 2-Clause with views sentence](https://spdx.org/licenses/BSD-2-Clause-Views.html) | | [GeographicLib](https://geographiclib.sourceforge.io/) | [MIT License](https://spdx.org/licenses/MIT.html) | | [geos](https://libgeos.org/) | [GNU Lesser General Public License v2.1 or later](https://spdx.org/licenses/LGPL-2.1-or-later.html) | -| [GLAD](https://github.com/Dav1dde/glad) | [MIT License](https://spdx.org/licenses/MIT.html) | +| [GLEW](https://www.opengl.org/sdk/libs/GLEW/) | [MIT License](https://spdx.org/licenses/MIT.html) | | [GLM](https://github.com/g-truc/glm) | [MIT License](https://spdx.org/licenses/MIT.html) | | [GoogleTest](https://google.github.io/googletest/) | [BSD 3-Clause "New" or "Revised" License](https://spdx.org/licenses/BSD-3-Clause.html) | | [HSLuv](https://www.hsluv.org/) | [MIT License](https://spdx.org/licenses/MIT.html) | @@ -32,12 +32,9 @@ Supercell Wx uses code from the following dependencies: | [libpng](http://libpng.org/pub/png/libpng.html) | [PNG Reference Library version 2](https://spdx.org/licenses/libpng-2.0.html) | | [libxml2](http://xmlsoft.org/) | [MIT License](https://spdx.org/licenses/MIT.html) | | [MapLibre Native](https://maplibre.org/projects/maplibre-native/) | [BSD 2-Clause "Simplified" License](https://spdx.org/licenses/BSD-2-Clause.html) | -| [Mesa 3D](https://mesa3d.org/) | [MIT License](https://spdx.org/licenses/MIT.html) | | [nunicode](https://bitbucket.org/alekseyt/nunicode/src/master/) | [MIT License](https://spdx.org/licenses/MIT.html) | Modified for MapLibre Native | | [OpenSSL](https://www.openssl.org/) | [OpenSSL License](https://spdx.org/licenses/OpenSSL.html) | | [Qt](https://www.qt.io/) | [GNU Lesser General Public License v3.0 only](https://spdx.org/licenses/LGPL-3.0-only.html) | Qt Core, Qt GUI, Qt Multimedia, Qt Network, Qt OpenGL, Qt Positioning, Qt Serial Port, Qt SQL, Qt SVG, Qt Widgets
Additional Licenses: https://doc.qt.io/qt-6/licenses-used-in-qt.html | -| [qt6ct](https://github.com/trialuser02/qt6ct) | [BSD 2-Clause "Simplified" License](https://spdx.org/licenses/BSD-2-Clause.html) | -| [range-v3](https://github.com/ericniebler/range-v3) | [Boost Software License 1.0](https://spdx.org/licenses/BSL-1.0.html)
[MIT License](https://spdx.org/licenses/MIT.html)
[Stepanov and McJones, "Elements of Programming" license](https://github.com/ericniebler/range-v3/tree/0.12.0?tab=License-1-ov-file)
[SGI C++ Standard Template Library license](https://github.com/ericniebler/range-v3/tree/0.12.0?tab=License-1-ov-file) | | [re2](https://github.com/google/re2) | [BSD 3-Clause "New" or "Revised" License](https://spdx.org/licenses/BSD-3-Clause.html) | | [spdlog](https://github.com/gabime/spdlog) | [MIT License](https://spdx.org/licenses/MIT.html) | | [SQLite](https://www.sqlite.org/) | Public Domain | @@ -70,7 +67,6 @@ Supercell Wx uses assets from the following sources: | [Font Awesome Free](https://fontawesome.com/) | CC BY 4.0 License | | [Inconsolata](https://fonts.google.com/specimen/Inconsolata) | SIL Open Font License | | [NOAA's Weather and Climate Toolkit](https://www.ncdc.noaa.gov/wct/) | Public Domain | Default Color Tables | -| [qt6ct](https://github.com/trialuser02/qt6ct) | [BSD 2-Clause "Simplified" License](https://spdx.org/licenses/BSD-2-Clause.html) | | [Roboto Flex](https://fonts.google.com/specimen/Roboto+Flex) | SIL Open Font License | | [Supercell thunderstorm with dramatic clouds](https://www.shutterstock.com/image-photo/supercell-thunderstorm-dramatic-clouds-1354353521) | Shutterstock Standard License | Photo by John Sirlin diff --git a/CMakeLists.txt b/CMakeLists.txt index e76cb8d1..c06a46e6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,14 +1,7 @@ -cmake_minimum_required(VERSION 3.24) +cmake_minimum_required(VERSION 3.21) set(PROJECT_NAME supercell-wx) - -include(tools/scwx_config.cmake) - -set(CMAKE_OSX_DEPLOYMENT_TARGET 12.0) - -scwx_python_setup() - project(${PROJECT_NAME} - VERSION 0.5.1 + VERSION 0.4.5 DESCRIPTION "Supercell Wx is a free, open source advanced weather radar viewer." HOMEPAGE_URL "https://github.com/dpaulat/supercell-wx" LANGUAGES C CXX) @@ -18,21 +11,40 @@ set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) set(CMAKE_POLICY_DEFAULT_CMP0079 NEW) set(CMAKE_POLICY_DEFAULT_CMP0148 OLD) # aws-sdk-cpp uses FindPythonInterp -scwx_output_dirs_setup() - enable_testing() set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) +include(${PROJECT_SOURCE_DIR}/external/cmake-conan/conan.cmake) + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS conanfile.py) +# Don't use RelWithDebInfo Conan packages +if (${CMAKE_BUILD_TYPE} STREQUAL "RelWithDebInfo") + set(conan_build_type "Release") +else() + set(conan_build_type ${CMAKE_BUILD_TYPE}) +endif() + +conan_cmake_autodetect(settings + BUILD_TYPE ${conan_build_type}) + +conan_cmake_install(PATH_OR_REFERENCE ${PROJECT_SOURCE_DIR} + BUILD missing + REMOTE conancenter + SETTINGS ${settings}) + +include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) +include(${CMAKE_BINARY_DIR}/conan_paths.cmake) +conan_basic_setup(TARGETS) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBOOST_ALL_NO_LIB") set(SCWX_DIR ${PROJECT_SOURCE_DIR}) -set(SCWX_VERSION "0.5.1") +set(SCWX_VERSION "0.4.5") option(SCWX_ADDRESS_SANITIZER "Build with Address Sanitizer" OFF) diff --git a/CMakePresets.json b/CMakePresets.json deleted file mode 100644 index ec997016..00000000 --- a/CMakePresets.json +++ /dev/null @@ -1,383 +0,0 @@ -{ - "version": 5, - "cmakeMinimumRequired": { - "major": 3, - "minor": 24, - "patch": 0 - }, - "configurePresets": [ - { - "name": "base", - "hidden": true, - "generator": "Ninja", - "binaryDir": "${sourceDir}/build/${presetName}", - "cacheVariables": { - "CMAKE_PROJECT_TOP_LEVEL_INCLUDES": "${sourceDir}/external/cmake-conan/conan_provider.cmake", - "SCWX_VIRTUAL_ENV": "${sourceDir}/.venv" - } - }, - { - "name": "windows-base", - "inherits": "base", - "hidden": true, - "generator": "Visual Studio 17 2022", - "condition": { - "type": "equals", - "lhs": "${hostSystemName}", - "rhs": "Windows" - }, - "vendor": { - "microsoft.com/VisualStudioSettings/CMake/1.0": { - "hostOS": [ - "Windows" - ] - } - } - }, - { - "name": "windows-x64-base", - "inherits": "windows-base", - "hidden": true - }, - { - "name": "linux-base", - "inherits": "base", - "hidden": true, - "condition": { - "type": "equals", - "lhs": "${hostSystemName}", - "rhs": "Linux" - } - }, - { - "name": "windows-msvc2022-x64-base", - "inherits": "windows-x64-base", - "hidden": true, - "cacheVariables": { - "CMAKE_PREFIX_PATH": "C:/Qt/6.9.2/msvc2022_64" - } - }, - { - "name": "windows-msvc2022-x64-ninja-base", - "inherits": "windows-msvc2022-x64-base", - "hidden": true, - "generator": "Ninja", - "cacheVariables": { - "CMAKE_PREFIX_PATH": "C:/Qt/6.9.2/msvc2022_64" - } - }, - { - "name": "linux-gcc-base", - "inherits": "linux-base", - "hidden": true, - "cacheVariables": { - "CMAKE_PREFIX_PATH": "/opt/Qt/6.9.2/gcc_64" - }, - "environment": { - "CC": "gcc-11", - "CXX": "g++-11" - } - }, - { - "name": "windows-msvc2022-x64-debug", - "inherits": "windows-msvc2022-x64-base", - "displayName": "Windows MSVC 2022 x64 Debug", - "architecture": { - "value": "x64", - "strategy": "external" - }, - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Debug", - "CONAN_HOST_PROFILE": "scwx-windows_msvc2022_x64-debug", - "CONAN_BUILD_PROFILE": "scwx-windows_msvc2022_x64-debug" - } - }, - { - "name": "windows-msvc2022-x64-release", - "inherits": "windows-msvc2022-x64-base", - "displayName": "Windows MSVC 2022 x64 Release", - "architecture": { - "value": "x64", - "strategy": "external" - }, - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Release", - "CONAN_HOST_PROFILE": "scwx-windows_msvc2022_x64", - "CONAN_BUILD_PROFILE": "scwx-windows_msvc2022_x64" - } - }, - { - "name": "windows-msvc2022-x64-ninja-debug", - "inherits": "windows-msvc2022-x64-ninja-base", - "displayName": "Windows MSVC 2022 x64 Ninja Debug", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Debug", - "CONAN_HOST_PROFILE": "scwx-windows_msvc2022_x64-debug", - "CONAN_BUILD_PROFILE": "scwx-windows_msvc2022_x64-debug" - } - }, - { - "name": "windows-msvc2022-x64-ninja-release", - "inherits": "windows-msvc2022-x64-ninja-base", - "displayName": "Windows MSVC 2022 x64 Ninja Release", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Release", - "CONAN_HOST_PROFILE": "scwx-windows_msvc2022_x64", - "CONAN_BUILD_PROFILE": "scwx-windows_msvc2022_x64" - } - }, - { - "name": "linux-gcc-debug", - "inherits": "linux-gcc-base", - "displayName": "Linux GCC Debug", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Debug", - "CMAKE_INSTALL_PREFIX": "${sourceDir}/build/${presetName}/Debug/supercell-wx", - "CONAN_HOST_PROFILE": "scwx-linux_gcc-11-debug", - "CONAN_BUILD_PROFILE": "scwx-linux_gcc-11-debug" - } - }, - { - "name": "linux-gcc-release", - "inherits": "linux-gcc-base", - "displayName": "Linux GCC Release", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Release", - "CMAKE_INSTALL_PREFIX": "${sourceDir}/build/${presetName}/Release/supercell-wx", - "CONAN_HOST_PROFILE": "scwx-linux_gcc-11", - "CONAN_BUILD_PROFILE": "scwx-linux_gcc-11" - } - }, - { - "name": "linux-gcc-debug-asan", - "inherits": "linux-gcc-base", - "displayName": "Linux GCC Debug Address Sanitizer", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Debug", - "CMAKE_INSTALL_PREFIX": "${sourceDir}/build/${presetName}/Debug/supercell-wx", - "CONAN_HOST_PROFILE": "scwx-linux_gcc-11-debug", - "CONAN_BUILD_PROFILE": "scwx-linux_gcc-11-debug", - "SCWX_ADDRESS_SANITIZER": { - "type": "BOOL", - "value": "ON" - } - } - }, - { - "name": "linux-gcc-release-asan", - "inherits": "linux-gcc-base", - "displayName": "Linux GCC Release Address Sanitizer", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Release", - "CMAKE_INSTALL_PREFIX": "${sourceDir}/build/${presetName}/Release/supercell-wx", - "CONAN_HOST_PROFILE": "scwx-linux_gcc-11", - "CONAN_BUILD_PROFILE": "scwx-linux_gcc-11", - "SCWX_ADDRESS_SANITIZER": { - "type": "BOOL", - "value": "ON" - } - } - }, - { - "name": "ci-linux-gcc14", - "inherits": "linux-gcc-base", - "displayName": "CI Linux GCC 14", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Release", - "CONAN_HOST_PROFILE": "scwx-linux_gcc-14", - "CONAN_BUILD_PROFILE": "scwx-linux_gcc-14" - }, - "environment": { - "CC": "gcc-14", - "CXX": "g++-14" - } - }, - { - "name": "ci-linux-clang17", - "inherits": "linux-gcc-base", - "displayName": "CI Linux Clang 17", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Release", - "CONAN_HOST_PROFILE": "scwx-linux_clang-17", - "CONAN_BUILD_PROFILE": "scwx-linux_clang-17" - }, - "environment": { - "CC": "clang-17", - "CXX": "clang++-17" - } - }, - { - "name": "ci-linux-gcc-arm64", - "inherits": "linux-gcc-base", - "displayName": "CI Linux GCC ARM64", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Release", - "CMAKE_PREFIX_PATH": "/opt/Qt/6.9.2/gcc_arm64", - "CONAN_HOST_PROFILE": "scwx-linux_gcc-11_armv8", - "CONAN_BUILD_PROFILE": "scwx-linux_gcc-11_armv8" - }, - "environment": { - "CC": "gcc-11", - "CXX": "g++-11" - } - }, - { - "name": "macos-base", - "inherits": "base", - "hidden": true, - "cacheVariables": { - "CMAKE_PREFIX_PATH": "$env{HOME}/Qt/6.9.2/macos" - }, - "condition": { - "type": "equals", - "lhs": "${hostSystemName}", - "rhs": "Darwin" - } - }, - { - "name": "macos-clang18-base", - "inherits": "macos-base", - "hidden": true - }, - { - "name": "macos-clang18-x64-base", - "inherits": "macos-clang18-base", - "hidden": true, - "environment": { - "CC": "/usr/local/opt/llvm@18/bin/clang", - "CXX": "/usr/local/opt/llvm@18/bin/clang++", - "PATH": "/usr/local/opt/llvm@18/bin:$penv{PATH}", - "CPPFLAGS": "-I/usr/local/opt/llvm@18/include", - "LDFLAGS": "-L/usr/local/opt/llvm@18/lib -L/usr/local/opt/llvm@18/lib/c++" - } - }, - { - "name": "macos-clang18-arm64-base", - "inherits": "macos-clang18-base", - "hidden": true, - "environment": { - "CC": "/opt/homebrew/opt/llvm@18/bin/clang", - "CXX": "/opt/homebrew/opt/llvm@18/bin/clang++", - "PATH": "/opt/homebrew/opt/llvm@18/bin:$penv{PATH}", - "CPPFLAGS": "-I/opt/homebrew/opt/llvm@18/include", - "LDFLAGS": "-L/opt/homebrew/opt/llvm@18/lib -L/opt/homebrew/opt/llvm@18/lib/c++" - } - }, - { - "name": "macos-clang18-x64-debug", - "inherits": "macos-clang18-x64-base", - "displayName": "macOS Clang 18 x64 Debug", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Debug", - "CONAN_HOST_PROFILE": "scwx-macos_clang-18-debug", - "CONAN_BUILD_PROFILE": "scwx-macos_clang-18-debug" - } - }, - { - "name": "macos-clang18-x64-release", - "inherits": "macos-clang18-x64-base", - "displayName": "macOS Clang 18 x64 Release", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Release", - "CONAN_HOST_PROFILE": "scwx-macos_clang-18", - "CONAN_BUILD_PROFILE": "scwx-macos_clang-18" - } - }, - { - "name": "macos-clang18-arm64-debug", - "inherits": "macos-clang18-arm64-base", - "displayName": "macOS Clang 18 Arm64 Debug", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Debug", - "CONAN_HOST_PROFILE": "scwx-macos_clang-18_armv8-debug", - "CONAN_BUILD_PROFILE": "scwx-macos_clang-18_armv8-debug" - } - }, - { - "name": "macos-clang18-arm64-release", - "inherits": "macos-clang18-arm64-base", - "displayName": "macOS Clang 18 Arm64 Release", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Release", - "CONAN_HOST_PROFILE": "scwx-macos_clang-18_armv8", - "CONAN_BUILD_PROFILE": "scwx-macos_clang-18_armv8" - } - } - ], - "buildPresets": [ - { - "name": "windows-msvc2022-x64-debug", - "configurePreset": "windows-msvc2022-x64-debug", - "displayName": "Windows MSVC 2022 x64 Debug", - "configuration": "Debug" - }, - { - "name": "windows-msvc2022-x64-release", - "configurePreset": "windows-msvc2022-x64-release", - "displayName": "Windows MSVC 2022 x64 Release", - "configuration": "Release" - }, - { - "name": "linux-gcc-debug", - "configurePreset": "linux-gcc-debug", - "displayName": "Linux GCC Debug", - "configuration": "Debug" - }, - { - "name": "linux-gcc-release", - "configurePreset": "linux-gcc-release", - "displayName": "Linux GCC Release", - "configuration": "Release" - }, - { - "name": "macos-clang18-x64-debug", - "configurePreset": "macos-clang18-x64-debug", - "displayName": "macOS Clang 18 x64 Debug", - "configuration": "Debug" - }, - { - "name": "macos-clang18-x64-release", - "configurePreset": "macos-clang18-x64-release", - "displayName": "macOS Clang 18 x64 Release", - "configuration": "Release" - }, - { - "name": "macos-clang18-arm64-debug", - "configurePreset": "macos-clang18-arm64-debug", - "displayName": "macOS Clang 18 Arm64 Debug", - "configuration": "Debug" - }, - { - "name": "macos-clang18-arm64-release", - "configurePreset": "macos-clang18-arm64-release", - "displayName": "macOS Clang 18 Arm64 Release", - "configuration": "Release" - } - ], - "testPresets": [ - { - "name": "windows-msvc2022-x64-debug", - "configurePreset": "windows-msvc2022-x64-debug", - "displayName": "Windows MSVC 2022 x64 Debug", - "configuration": "Debug" - }, - { - "name": "windows-msvc2022-x64-release", - "configurePreset": "windows-msvc2022-x64-release", - "displayName": "Windows MSVC 2022 x64 Release", - "configuration": "Release" - }, - { - "name": "linux-gcc-debug", - "configurePreset": "linux-gcc-debug", - "displayName": "Linux GCC Debug", - "configuration": "Debug" - }, - { - "name": "linux-gcc-release", - "configurePreset": "linux-gcc-release", - "displayName": "Linux GCC Release", - "configuration": "Release" - } - ] -} diff --git a/LICENSE.txt b/LICENSE.txt index 799086a0..8c9c5fbd 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2021-2025 Dan Paulat +Copyright (c) 2021-2024 Dan Paulat Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 81b0e698..321c33f2 100644 --- a/README.md +++ b/README.md @@ -26,36 +26,32 @@ Supercell Wx supports the following 64-bit operating systems: - Fedora Linux 34+ - openSUSE Tumbleweed - Ubuntu 22.04+ - - NixOS 25.05+ - Most distributions supporting the GCC Standard C++ Library 11+ -- macOS - - 13.6+ for Intel-based Macs - - 14.0+ for Apple silicon-based Macs - + ## Linux Dependencies Supercell Wx requires the following Linux dependencies: -- Linux/X11 (Wayland works too) with support for GCC 11, OpenGL 3.3 and OpenGL ES 3.0 +- Linux/X11 (Wayland works too) with support for GCC 11 and OpenGL 3.3 - X11/XCB libraries including xcb-cursor - + ## FAQ Frequently asked questions: - Q: Why is the map black when loading for the first time? - + - A. You must obtain a free API key from either (or both) [MapTiler](https://cloud.maptiler.com/auth/widget?next=https://cloud.maptiler.com/maps/) which currently does not require a credit/debit card, or [Mapbox](https://account.mapbox.com/) which ***does*** require a credit/debit card, but as of writing, you will receive 200K free requests per month, which should be sufficient for an individual user. - Q: Why is it that when I change my color table, API key, grid width/height settings, nothing happens after hitting apply? - A. As of right now, you must restart Supercell Wx in order to apply these changes. In future iterations, this will no longer be an issue. - + - Q. Is it possible to get dark mode? - + - A. In Windows, make sure to set the flag `-style fusion` at the end of the target path of the .exe - Example: `C:\Users\Administrator\Desktop\Supercell-Wx\bin\supercell-wx.exe -style fusion` - A. In Linux, if you're using KDE, Supercell Wx should automatically follow your theme settings. - + - Q: How can I contribute? - A. Head to [Developer Setup](https://supercell-wx.readthedocs.io/en/stable/development/developer-setup.html) and [Contributing](CONTRIBUTING.md) to configure the Supercell Wx development environment for your IDE. Currently Visual Studio and Visual Studio Code are recommended, with other IDEs remaining untested at this time. diff --git a/conanfile.py b/conanfile.py index 6803a56c..b18f2d31 100644 --- a/conanfile.py +++ b/conanfile.py @@ -1,66 +1,37 @@ -from conan import ConanFile -from conan.tools.cmake import CMake -from conan.tools.files import copy -import os +from conans import ConanFile class SupercellWxConan(ConanFile): settings = ("os", "compiler", "build_type", "arch") - requires = ("boost/1.88.0", - "cpr/1.12.0", + requires = ("boost/1.85.0", + "cpr/1.10.5", "fontconfig/2.15.0", "freetype/2.13.2", - "geographiclib/2.4", - "geos/3.13.0", - "glm/1.0.1", - "gtest/1.17.0", - "libcurl/8.12.1", - "libpng/1.6.50", - "libxml2/2.14.5", - "openssl/3.5.0", - "range-v3/0.12.0", - "re2/20250722", - "spdlog/1.15.1", - "sqlite3/3.49.1", - "vulkan-loader/1.3.290.0", + "geographiclib/2.3", + "geos/3.12.2", + "glew/2.2.0", + "glm/cci.20230113", + "gtest/1.15.0", + "libcurl/8.9.1", + "libxml2/2.12.7", + "openssl/3.3.1", + "re2/20240702", + "spdlog/1.14.1", + "sqlite3/3.46.0", + "vulkan-loader/1.3.243.0", "zlib/1.3.1") - generators = ("CMakeDeps") - default_options = {"geos/*:shared" : True, - "libiconv/*:shared" : True} - - def configure(self): - if self.settings.os == "Windows": - self.options["libcurl"].with_ssl = "schannel" - elif self.settings.os == "Linux": - self.options["openssl"].shared = True - self.options["libcurl"].ca_bundle = "none" - self.options["libcurl"].ca_path = "none" - elif self.settings.os == "Macos": - self.options["openssl"].shared = True - self.options["libcurl"].ca_bundle = "none" - self.options["libcurl"].ca_path = "none" + generators = ("cmake", + "cmake_find_package", + "cmake_paths") + default_options = {"geos:shared" : True, + "libiconv:shared" : True, + "openssl:no_module": True, + "openssl:shared" : True} def requirements(self): if self.settings.os == "Linux": - self.requires("mesa-glu/9.0.3") - self.requires("onetbb/2022.2.0") + self.requires("onetbb/2021.12.0") - def generate(self): - build_folder = os.path.join(self.build_folder, - "..", - str(self.settings.build_type), - self.cpp_info.bindirs[0]) - - for dep in self.dependencies.values(): - if dep.cpp_info.bindirs: - copy(self, "*.dll", dep.cpp_info.bindirs[0], build_folder) - if dep.cpp_info.libdirs: - copy(self, "*.dylib", dep.cpp_info.libdirs[0], build_folder) - - def build(self): - cmake = CMake(self) - cmake.configure() - cmake.build() - - def package(self): - cmake = CMake(self) - cmake.install() + def imports(self): + self.copy("*.dll", dst="bin", src="bin") + self.copy("*.dylib", dst="bin", src="lib") + self.copy("license*", dst="licenses", src=".", folder=True, ignore_case=True) diff --git a/data b/data index fd72b32c..8eb89b19 160000 --- a/data +++ b/data @@ -1 +1 @@ -Subproject commit fd72b32cc12419b4a9c9a72487e58ffa04fb2a70 +Subproject commit 8eb89b19fdd1c78e896cc6cb47e07425bb473699 diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index 1039e96e..bbc76c64 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.24) +cmake_minimum_required(VERSION 3.20) set(PROJECT_NAME scwx-external) set_property(DIRECTORY @@ -6,22 +6,18 @@ set_property(DIRECTORY PROPERTY CMAKE_CONFIGURE_DEPENDS aws-sdk-cpp.cmake date.cmake - glad.cmake hsluv-c.cmake imgui.cmake maplibre-native-qt.cmake stb.cmake textflowcpp.cmake - units.cmake - qt6ct.cmake) + units.cmake) include(aws-sdk-cpp.cmake) include(date.cmake) -include(glad.cmake) include(hsluv-c.cmake) include(imgui.cmake) include(maplibre-native-qt.cmake) include(stb.cmake) include(textflowcpp.cmake) include(units.cmake) -include(qt6ct.cmake) diff --git a/external/aws-sdk-cpp b/external/aws-sdk-cpp index 8d31e042..d5eb42fe 160000 --- a/external/aws-sdk-cpp +++ b/external/aws-sdk-cpp @@ -1 +1 @@ -Subproject commit 8d31e042f950fe70924391a205cceaf342ecec00 +Subproject commit d5eb42fe7c632868d4535b454ee2e5ba0e349b7f diff --git a/external/aws-sdk-cpp.cmake b/external/aws-sdk-cpp.cmake index f88df9ca..1ba641db 100644 --- a/external/aws-sdk-cpp.cmake +++ b/external/aws-sdk-cpp.cmake @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.24) +cmake_minimum_required(VERSION 3.20) set(PROJECT_NAME scwx-aws-sdk-cpp) set(AWS_SDK_WARNINGS_ARE_ERRORS OFF) @@ -21,10 +21,6 @@ set(MINIMIZE_SIZE OFF CACHE BOOL "If enabled, the SDK will be built via # Save off ${CMAKE_CXX_FLAGS} before modifying compiler settings set(CMAKE_CXX_FLAGS_PREV "${CMAKE_CXX_FLAGS}") -# Configure OpenSSL crypto library -find_package(OpenSSL) -add_library(crypto ALIAS OpenSSL::Crypto) - # Fix CMake errors for internal variables not set include(aws-sdk-cpp/cmake/compiler_settings.cmake) set_msvc_warnings() diff --git a/external/cmake-conan b/external/cmake-conan index b0e4d1ec..b240c809 160000 --- a/external/cmake-conan +++ b/external/cmake-conan @@ -1 +1 @@ -Subproject commit b0e4d1ec08edb35ef31033938567d621f6643c17 +Subproject commit b240c809b5ea097077fc8222cad71d2329288e48 diff --git a/external/date b/external/date index a5db3aec..cc4685a2 160000 --- a/external/date +++ b/external/date @@ -1 +1 @@ -Subproject commit a5db3aecec580bc78b6c01c118f2628676769b69 +Subproject commit cc4685a21e4a4fdae707ad1233c61bbaff241f93 diff --git a/external/date.cmake b/external/date.cmake index 7fce7ffc..a804f68c 100644 --- a/external/date.cmake +++ b/external/date.cmake @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.24) +cmake_minimum_required(VERSION 3.20) set(PROJECT_NAME scwx-date) set(USE_SYSTEM_TZ_DB ON) diff --git a/external/glad b/external/glad deleted file mode 160000 index 73db193f..00000000 --- a/external/glad +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 73db193f853e2ee079bf3ca8a64aa2eaf6459043 diff --git a/external/glad.cmake b/external/glad.cmake deleted file mode 100644 index 59ceb179..00000000 --- a/external/glad.cmake +++ /dev/null @@ -1,11 +0,0 @@ -cmake_minimum_required(VERSION 3.24) -set(PROJECT_NAME scwx-glad) - -# Path to glad directory -set(GLAD_SOURCES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/glad/") - -# Path to glad CMake files -add_subdirectory("${GLAD_SOURCES_DIR}/cmake" glad_cmake) - -# Specify glad settings -glad_add_library(glad_gl_core_33 LOADER REPRODUCIBLE API gl:core=3.3) diff --git a/external/hsluv-c b/external/hsluv-c index 982217c6..59539e04 160000 --- a/external/hsluv-c +++ b/external/hsluv-c @@ -1 +1 @@ -Subproject commit 982217c65a9ff574302335177d2dc078d9bfa6f5 +Subproject commit 59539e04a6fa648935cbe57c2104041f23136c4a diff --git a/external/hsluv-c.cmake b/external/hsluv-c.cmake index eec8f0f2..0129d39d 100644 --- a/external/hsluv-c.cmake +++ b/external/hsluv-c.cmake @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.24) +cmake_minimum_required(VERSION 3.20) set(PROJECT_NAME scwx-hsluv-c) set(HSLUV_C_TESTS OFF) diff --git a/external/imgui b/external/imgui index 45acd5e0..6ccc561a 160000 --- a/external/imgui +++ b/external/imgui @@ -1 +1 @@ -Subproject commit 45acd5e0e82f4c954432533ae9985ff0e1aad6d5 +Subproject commit 6ccc561a2ab497ad4ae6ee1dbd3b992ffada35cb diff --git a/external/imgui-backend-qt b/external/imgui-backend-qt index 023345ca..0fe974eb 160000 --- a/external/imgui-backend-qt +++ b/external/imgui-backend-qt @@ -1 +1 @@ -Subproject commit 023345ca8abf731fc50568c0197ceebe76bb4324 +Subproject commit 0fe974ebd037844c9f23d6325dbcc128e9973749 diff --git a/external/imgui.cmake b/external/imgui.cmake index 3eba6ee0..443817ef 100644 --- a/external/imgui.cmake +++ b/external/imgui.cmake @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.24) +cmake_minimum_required(VERSION 3.20) set(PROJECT_NAME scwx-imgui) find_package(QT NAMES Qt6 @@ -12,7 +12,7 @@ find_package(Qt${QT_VERSION_MAJOR} find_package(Freetype) -set(IMGUI_SOURCES include/scwx/external/imgui/imconfig.h +set(IMGUI_SOURCES imgui/imconfig.h imgui/imgui.cpp imgui/imgui.h imgui/imgui_demo.cpp @@ -33,9 +33,8 @@ set(IMGUI_SOURCES include/scwx/external/imgui/imconfig.h add_library(imgui STATIC ${IMGUI_SOURCES}) target_include_directories(imgui PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/imgui) -target_include_directories(imgui PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) -target_compile_definitions(imgui PUBLIC IMGUI_USER_CONFIG=) +target_compile_definitions(imgui PRIVATE IMGUI_ENABLE_FREETYPE) target_link_libraries(imgui PRIVATE Qt${QT_VERSION_MAJOR}::Widgets Freetype::Freetype) diff --git a/external/include/scwx/external/imgui/imconfig.h b/external/include/scwx/external/imgui/imconfig.h deleted file mode 100644 index ac954a77..00000000 --- a/external/include/scwx/external/imgui/imconfig.h +++ /dev/null @@ -1,147 +0,0 @@ -// clang-format off -//----------------------------------------------------------------------------- -// DEAR IMGUI COMPILE-TIME OPTIONS -// Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure. -// You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions. -//----------------------------------------------------------------------------- -// A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/rebased branch with your modifications to it) -// B) or '#define IMGUI_USER_CONFIG "my_imgui_config.h"' in your project and then add directives in your own file without touching this template. -//----------------------------------------------------------------------------- -// You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp -// files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures. -// Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts. -// Call IMGUI_CHECKVERSION() from your .cpp file to verify that the data structures your files are using are matching the ones imgui.cpp is using. -//----------------------------------------------------------------------------- - -#pragma once - -//---- Define assertion handler. Defaults to calling assert(). -// If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement. -//#define IM_ASSERT(_EXPR) MyAssert(_EXPR) -//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts - -//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows -// Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility. -// - Windows DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions() -// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details. -//#define IMGUI_API __declspec(dllexport) // MSVC Windows: DLL export -//#define IMGUI_API __declspec(dllimport) // MSVC Windows: DLL import -//#define IMGUI_API __attribute__((visibility("default"))) // GCC/Clang: override visibility when set is hidden - -//---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to clean your code of obsolete function/names. -#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS - -//---- Disable all of Dear ImGui or don't implement standard windows/tools. -// It is very strongly recommended to NOT disable the demo windows and debug tool during development. They are extremely useful in day to day work. Please read comments in imgui_demo.cpp. -//#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty. -//#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty. -//#define IMGUI_DISABLE_DEBUG_TOOLS // Disable metrics/debugger and other debug tools: ShowMetricsWindow(), ShowDebugLogWindow() and ShowIDStackToolWindow() will be empty. - -//---- Don't implement some functions to reduce linkage requirements. -//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a) -//#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with Visual Studio] Implement default IME handler (require imm32.lib/.a, auto-link for Visual Studio, -limm32 on command-line for MinGW) -//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a) -//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, IME). -//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default). -//#define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS // Don't implement default platform_io.Platform_OpenInShellFn() handler (Win32: ShellExecute(), require shell32.lib/.a, Mac/Linux: use system("")). -//#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf) -//#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself. -//#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies) -//#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function. -//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions(). -//#define IMGUI_DISABLE_DEFAULT_FONT // Disable default embedded font (ProggyClean.ttf), remove ~9.5 KB from output binary. AddFontDefault() will assert. -//#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available - -//---- Enable Test Engine / Automation features. -//#define IMGUI_ENABLE_TEST_ENGINE // Enable imgui_test_engine hooks. Generally set automatically by include "imgui_te_config.h", see Test Engine for details. - -//---- Include imgui_user.h at the end of imgui.h as a convenience -// May be convenient for some users to only explicitly include vanilla imgui.h and have extra stuff included. -//#define IMGUI_INCLUDE_IMGUI_USER_H -//#define IMGUI_USER_H_FILENAME "my_folder/my_imgui_user.h" - -//---- Pack vertex colors as BGRA8 instead of RGBA8 (to avoid converting from one to another). Need dedicated backend support. -//#define IMGUI_USE_BGRA_PACKED_COLOR - -//---- Use legacy CRC32-adler tables (used before 1.91.6), in order to preserve old .ini data that you cannot afford to invalidate. -//#define IMGUI_USE_LEGACY_CRC32_ADLER - -//---- Use 32-bit for ImWchar (default is 16-bit) to support Unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...) -//#define IMGUI_USE_WCHAR32 - -//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version -// By default the embedded implementations are declared static and not available outside of Dear ImGui sources files. -//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h" -//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h" -//#define IMGUI_STB_SPRINTF_FILENAME "my_folder/stb_sprintf.h" // only used if IMGUI_USE_STB_SPRINTF is defined. -//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION -//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION -//#define IMGUI_DISABLE_STB_SPRINTF_IMPLEMENTATION // only disabled if IMGUI_USE_STB_SPRINTF is defined. - -//---- Use stb_sprintf.h for a faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined) -// Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by stb_sprintf.h. -//#define IMGUI_USE_STB_SPRINTF - -//---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui) -// Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided). -// On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'. -#define IMGUI_ENABLE_FREETYPE - -//---- Use FreeType + plutosvg or lunasvg to render OpenType SVG fonts (SVGinOT) -// Only works in combination with IMGUI_ENABLE_FREETYPE. -// - plutosvg is currently easier to install, as e.g. it is part of vcpkg. It will support more fonts and may load them faster. See misc/freetype/README for instructions. -// - Both require headers to be available in the include path + program to be linked with the library code (not provided). -// - (note: lunasvg implementation is based on Freetype's rsvg-port.c which is licensed under CeCILL-C Free Software License Agreement) -//#define IMGUI_ENABLE_FREETYPE_PLUTOSVG -//#define IMGUI_ENABLE_FREETYPE_LUNASVG - -//---- Use stb_truetype to build and rasterize the font atlas (default) -// The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend. -//#define IMGUI_ENABLE_STB_TRUETYPE - -//---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4. -// This will be inlined as part of ImVec2 and ImVec4 class declarations. -/* -#define IM_VEC2_CLASS_EXTRA \ - constexpr ImVec2(const MyVec2& f) : x(f.x), y(f.y) {} \ - operator MyVec2() const { return MyVec2(x,y); } - -#define IM_VEC4_CLASS_EXTRA \ - constexpr ImVec4(const MyVec4& f) : x(f.x), y(f.y), z(f.z), w(f.w) {} \ - operator MyVec4() const { return MyVec4(x,y,z,w); } -*/ -//---- ...Or use Dear ImGui's own very basic math operators. -//#define IMGUI_DEFINE_MATH_OPERATORS - -//---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices. -// Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices). -// Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer. -// Read about ImGuiBackendFlags_RendererHasVtxOffset for details. -//#define ImDrawIdx unsigned int - -//---- Override ImDrawCallback signature (will need to modify renderer backends accordingly) -//struct ImDrawList; -//struct ImDrawCmd; -//typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data); -//#define ImDrawCallback MyImDrawCallback - -//---- Debug Tools: Macro to break in Debugger (we provide a default implementation of this in the codebase) -// (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.) -//#define IM_DEBUG_BREAK IM_ASSERT(0) -//#define IM_DEBUG_BREAK __debugbreak() - -//---- Debug Tools: Enable highlight ID conflicts _before_ hovering items. When io.ConfigDebugHighlightIdConflicts is set. -// (THIS WILL SLOW DOWN DEAR IMGUI. Only use occasionally and disable after use) -//#define IMGUI_DEBUG_HIGHLIGHT_ALL_ID_CONFLICTS - -//---- Debug Tools: Enable slower asserts -//#define IMGUI_DEBUG_PARANOID - -//---- Tip: You can add extra functions within the ImGui:: namespace from anywhere (e.g. your own sources/header files) -/* -namespace ImGui -{ - void MyFunction(const char* name, MyMatrix44* mtx); -} -*/ -// clang-format on diff --git a/external/maplibre-native b/external/maplibre-native index 3654f5fa..3d4ca3fd 160000 --- a/external/maplibre-native +++ b/external/maplibre-native @@ -1 +1 @@ -Subproject commit 3654f5fa9f06534d7fd2d95b810049a82e5953ef +Subproject commit 3d4ca3fdf07c50db3002b11bff93c81ec380e493 diff --git a/external/maplibre-native-qt b/external/maplibre-native-qt index 8b406978..805ccf62 160000 --- a/external/maplibre-native-qt +++ b/external/maplibre-native-qt @@ -1 +1 @@ -Subproject commit 8b40697895c19da4479cd037a76608f4c36935e8 +Subproject commit 805ccf6204a546e43fed599631ad5d698f68ae86 diff --git a/external/maplibre-native-qt.cmake b/external/maplibre-native-qt.cmake index 7db42c10..6a508040 100644 --- a/external/maplibre-native-qt.cmake +++ b/external/maplibre-native-qt.cmake @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.24) +cmake_minimum_required(VERSION 3.20) set(PROJECT_NAME scwx-mln) set(gtest_disable_pthreads ON) @@ -19,28 +19,11 @@ if (MSVC) target_link_options(MLNQtCore PRIVATE "$<$:/DEBUG>") target_link_options(MLNQtCore PRIVATE "$<$:/OPT:REF>") target_link_options(MLNQtCore PRIVATE "$<$:/OPT:ICF>") - - # Enable multi-processor compilation - target_compile_options(MLNQtCore PRIVATE "/MP") - target_compile_options(mbgl-core PRIVATE "/MP") - target_compile_options(mbgl-vendor-csscolorparser PRIVATE "/MP") - target_compile_options(mbgl-vendor-nunicode PRIVATE "/MP") - target_compile_options(mbgl-vendor-parsedate PRIVATE "/MP") - - if (TARGET mbgl-vendor-sqlite) - target_compile_options(mbgl-vendor-sqlite PRIVATE "/MP") - endif() else() target_compile_options(mbgl-core PRIVATE "$<$:-g>") target_compile_options(MLNQtCore PRIVATE "$<$:-g>") endif() -if (APPLE) - # Enable GL check error debug - target_compile_definitions(mbgl-core PRIVATE MLN_GL_CHECK_ERRORS=1) - target_compile_definitions(MLNQtCore PRIVATE MLN_GL_CHECK_ERRORS=1) -endif() - set(MLN_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/maplibre-native/include ${CMAKE_CURRENT_SOURCE_DIR}/maplibre-native-qt/src/core/include ${CMAKE_CURRENT_BINARY_DIR}/maplibre-native-qt/src/core/include PARENT_SCOPE) diff --git a/external/qt6ct b/external/qt6ct deleted file mode 160000 index 2c569c6c..00000000 --- a/external/qt6ct +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2c569c6c4776ea5a1299030c079b16f70473c9e6 diff --git a/external/qt6ct.cmake b/external/qt6ct.cmake deleted file mode 100644 index cdae0b25..00000000 --- a/external/qt6ct.cmake +++ /dev/null @@ -1,62 +0,0 @@ -cmake_minimum_required(VERSION 3.16.0) -set(PROJECT_NAME scwx-qt6ct) - -find_package(QT NAMES Qt6 - COMPONENTS Gui Widgets - REQUIRED) -find_package(Qt${QT_VERSION_MAJOR} - COMPONENTS Gui Widgets - REQUIRED) - -#extract version from qt6ct.h -file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/qt6ct/src/qt6ct-common/qt6ct.h" - QT6CT_VERSION_DATA REGEX "^#define[ \t]+QT6CT_VERSION_[A-Z]+[ \t]+[0-9]+.*$") - -if(QT6CT_VERSION_DATA) - foreach(item IN ITEMS MAJOR MINOR) - string(REGEX REPLACE ".*#define[ \t]+QT6CT_VERSION_${item}[ \t]+([0-9]+).*" - "\\1" QT6CT_VERSION_${item} ${QT6CT_VERSION_DATA}) - endforeach() - set(QT6CT_VERSION "${QT6CT_VERSION_MAJOR}.${QT6CT_VERSION_MINOR}") - set(QT6CT_SOVERSION "${QT6CT_VERSION_MAJOR}") - message(STATUS "qt6ct version: ${QT6CT_VERSION}") -else() - message(FATAL_ERROR "invalid header") -endif() - -set(qt6ct-common-source - qt6ct/src/qt6ct-common/qt6ct.cpp -) - -set(qt6ct-widgets-source - qt6ct/src/qt6ct/paletteeditdialog.cpp - qt6ct/src/qt6ct/paletteeditdialog.ui -) - -set(CMAKE_AUTOMOC ON) -set(CMAKE_AUTORCC ON) -set(CMAKE_AUTOUIC ON) - -include_directories(qt6ct/src/qt6ct-common) - -add_library(qt6ct-common STATIC ${qt6ct-common-source}) -set_target_properties(qt6ct-common PROPERTIES VERSION ${QT6CT_VERSION}) -target_link_libraries(qt6ct-common PRIVATE Qt6::Gui) -target_compile_definitions(qt6ct-common PRIVATE QT6CT_LIBRARY) - -add_library(qt6ct-widgets STATIC ${qt6ct-widgets-source}) -set_target_properties(qt6ct-widgets PROPERTIES VERSION ${QT6CT_VERSION}) -target_link_libraries(qt6ct-widgets PRIVATE Qt6::Widgets qt6ct-common) -target_compile_definitions(qt6ct-widgets PRIVATE QT6CT_LIBRARY) - -if (MSVC) - # Produce PDB file for debug - target_compile_options(qt6ct-common PRIVATE "$<$:/Zi>") - target_compile_options(qt6ct-widgets PRIVATE "$<$:/Zi>") -else() - target_compile_options(qt6ct-common PRIVATE "$<$:-g>") - target_compile_options(qt6ct-widgets PRIVATE "$<$:-g>") -endif() - -target_include_directories( qt6ct-common INTERFACE qt6ct/src ) -target_include_directories( qt6ct-widgets INTERFACE qt6ct/src ) diff --git a/external/stb b/external/stb index f58f558c..beebb24b 160000 --- a/external/stb +++ b/external/stb @@ -1 +1 @@ -Subproject commit f58f558c120e9b32c217290b80bad1a0729fbb2c +Subproject commit beebb24b945efdea3b9bba23affb8eb3ba8982e7 diff --git a/external/stb.cmake b/external/stb.cmake index 570af425..c26bedaf 100644 --- a/external/stb.cmake +++ b/external/stb.cmake @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.24) +cmake_minimum_required(VERSION 3.20) set(PROJECT_NAME scwx-stb) set(STB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/stb PARENT_SCOPE) diff --git a/external/textflowcpp.cmake b/external/textflowcpp.cmake index 31020665..1e36da18 100644 --- a/external/textflowcpp.cmake +++ b/external/textflowcpp.cmake @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.24) +cmake_minimum_required(VERSION 3.20) set(PROJECT_NAME scwx-textflowcpp) set(TEXTFLOWCPP_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/textflowcpp PARENT_SCOPE) diff --git a/external/units.cmake b/external/units.cmake index cc70ac1c..d037ae54 100644 --- a/external/units.cmake +++ b/external/units.cmake @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.24) +cmake_minimum_required(VERSION 3.20) set(PROJECT_NAME scwx-units) add_subdirectory(units) diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index afdd2a37..00000000 --- a/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -conan -geopandas -GitPython diff --git a/scwx-qt/CMakeLists.txt b/scwx-qt/CMakeLists.txt index e47bc3fb..f4e636e7 100644 --- a/scwx-qt/CMakeLists.txt +++ b/scwx-qt/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.24) +cmake_minimum_required(VERSION 3.21) set_property(DIRECTORY APPEND diff --git a/scwx-qt/gl/map_color.vert b/scwx-qt/gl/map_color.vert index 609d1c34..6ae98e92 100644 --- a/scwx-qt/gl/map_color.vert +++ b/scwx-qt/gl/map_color.vert @@ -26,9 +26,6 @@ void main() // Always set displayed to true vsOut.displayed = 1; - // Initialize texCoord to default value - vsOut.texCoord = vec3(0.0f, 0.0f, 0.0f); - // Pass the threshold and time range to the geometry shader vsOut.threshold = aThreshold; vsOut.timeRange = aTimeRange; diff --git a/scwx-qt/gl/radar.frag b/scwx-qt/gl/radar.frag index b6491e8b..0c605b8a 100644 --- a/scwx-qt/gl/radar.frag +++ b/scwx-qt/gl/radar.frag @@ -9,14 +9,14 @@ uniform float uDataMomentScale; uniform bool uCFPEnabled; -in float dataMoment; -in float cfpMoment; +flat in uint dataMoment; +flat in uint cfpMoment; layout (location = 0) out vec4 fragColor; void main() { - float texCoord = (dataMoment - float(uDataMomentOffset)) / uDataMomentScale; + float texCoord = float(dataMoment - uDataMomentOffset) / uDataMomentScale; if (uCFPEnabled && cfpMoment > 8u) { diff --git a/scwx-qt/gl/radar.vert b/scwx-qt/gl/radar.vert index 97754b73..b4da9f17 100644 --- a/scwx-qt/gl/radar.vert +++ b/scwx-qt/gl/radar.vert @@ -13,8 +13,8 @@ layout (location = 2) in uint aCfpMoment; uniform mat4 uMVPMatrix; uniform vec2 uMapScreenCoord; -out float dataMoment; -out float cfpMoment; +flat out uint dataMoment; +flat out uint cfpMoment; vec2 latLngToScreenCoordinate(in vec2 latLng) { diff --git a/scwx-qt/gl/threshold.geom b/scwx-qt/gl/threshold.geom index deead87d..677a80cd 100644 --- a/scwx-qt/gl/threshold.geom +++ b/scwx-qt/gl/threshold.geom @@ -21,9 +21,7 @@ smooth out vec4 color; void main() { if (gsIn[0].displayed != 0 && - (gsIn[0].threshold == 0 || // If Threshold: 0 was specified, no threshold - uMapDistance == 0 || // If uMapDistance is zero, threshold is disabled - (gsIn[0].threshold < 0 && -(gsIn[0].threshold) <= uMapDistance) || // If Threshold is negative and below current map distance + (gsIn[0].threshold <= 0 || // If Threshold: 0 was specified, no threshold gsIn[0].threshold >= uMapDistance || // If Threshold is above current map distance gsIn[0].threshold >= 999) && // If Threshold: 999 was specified (or greater), no threshold (gsIn[0].timeRange[0] == 0 || // If there is no start time specified diff --git a/scwx-qt/res/config/radar_sites.json b/scwx-qt/res/config/radar_sites.json index 20d7397c..8f2a1b90 100644 --- a/scwx-qt/res/config/radar_sites.json +++ b/scwx-qt/res/config/radar_sites.json @@ -67,7 +67,7 @@ { "type": "wsr88d", "id": "KLVX", "lat": 37.9753058, "lon": -85.9438455, "country": "USA", "state": "KY", "place": "Louisville", "tz": "America/New_York", "elevation": 833.0 }, { "type": "wsr88d", "id": "KPAH", "lat": 37.068333, "lon": -88.771944, "country": "USA", "state": "KY", "place": "Paducah", "tz": "America/Chicago", "elevation": 506.0 }, { "type": "wsr88d", "id": "KPOE", "lat": 31.1556923, "lon": -92.9762596, "country": "USA", "state": "LA", "place": "Fort Polk", "tz": "America/Chicago", "elevation": 473.0 }, - { "type": "wsr88d", "id": "KHDC", "lat": 30.5196, "lon": -90.4074, "country": "USA", "state": "LA", "place": "New Orleans (Hammond)", "tz": "America/Chicago", "elevation": 43.0 }, + { "type": "wsr88d", "id": "KHDC", "lat": 30.519306, "lon": -90.424028, "country": "USA", "state": "LA", "place": "New Orleans (Hammond)", "tz": "America/Chicago", "elevation": 43.0 }, { "type": "wsr88d", "id": "KLCH", "lat": 30.125306, "lon": -93.215889, "country": "USA", "state": "LA", "place": "Lake Charles", "tz": "America/Chicago", "elevation": 137.0 }, { "type": "wsr88d", "id": "KSHV", "lat": 32.450833, "lon": -93.84125, "country": "USA", "state": "LA", "place": "Shreveport", "tz": "America/Chicago", "elevation": 387.0 }, { "type": "wsr88d", "id": "KLIX", "lat": 30.3367133, "lon": -89.8256618, "country": "USA", "state": "LA", "place": "New Orleans (Slidell)", "tz": "America/Chicago", "elevation": 179.0 }, diff --git a/scwx-qt/res/icons/font-awesome-6/briefcase-solid.svg b/scwx-qt/res/icons/font-awesome-6/briefcase-solid.svg deleted file mode 100644 index b16bc330..00000000 --- a/scwx-qt/res/icons/font-awesome-6/briefcase-solid.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/scwx-qt/res/icons/font-awesome-6/building-columns-solid.svg b/scwx-qt/res/icons/font-awesome-6/building-columns-solid.svg deleted file mode 100644 index cf0df19a..00000000 --- a/scwx-qt/res/icons/font-awesome-6/building-columns-solid.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/scwx-qt/res/icons/font-awesome-6/building-solid.svg b/scwx-qt/res/icons/font-awesome-6/building-solid.svg deleted file mode 100644 index 6f6d3f24..00000000 --- a/scwx-qt/res/icons/font-awesome-6/building-solid.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/scwx-qt/res/icons/font-awesome-6/caravan-solid.svg b/scwx-qt/res/icons/font-awesome-6/caravan-solid.svg deleted file mode 100644 index c341214f..00000000 --- a/scwx-qt/res/icons/font-awesome-6/caravan-solid.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/scwx-qt/res/icons/font-awesome-6/house-solid-white.svg b/scwx-qt/res/icons/font-awesome-6/house-solid-white.svg deleted file mode 100644 index 59f65e1e..00000000 --- a/scwx-qt/res/icons/font-awesome-6/house-solid-white.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/scwx-qt/res/icons/font-awesome-6/location-crosshairs-solid.svg b/scwx-qt/res/icons/font-awesome-6/location-crosshairs-solid.svg deleted file mode 100644 index 5bb1ea5c..00000000 --- a/scwx-qt/res/icons/font-awesome-6/location-crosshairs-solid.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/scwx-qt/res/icons/font-awesome-6/location-pin.svg b/scwx-qt/res/icons/font-awesome-6/location-pin.svg deleted file mode 100644 index 4b6182cd..00000000 --- a/scwx-qt/res/icons/font-awesome-6/location-pin.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/scwx-qt/res/icons/font-awesome-6/star-solid-white.svg b/scwx-qt/res/icons/font-awesome-6/star-solid-white.svg deleted file mode 100644 index 41bcd103..00000000 --- a/scwx-qt/res/icons/font-awesome-6/star-solid-white.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/scwx-qt/res/icons/font-awesome-6/tent-solid.svg b/scwx-qt/res/icons/font-awesome-6/tent-solid.svg deleted file mode 100644 index 9f159d60..00000000 --- a/scwx-qt/res/icons/font-awesome-6/tent-solid.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/scwx-qt/res/icons/scwx.icns b/scwx-qt/res/icons/scwx.icns deleted file mode 100644 index bda4ea32..00000000 Binary files a/scwx-qt/res/icons/scwx.icns and /dev/null differ diff --git a/scwx-qt/res/linux/net.supercellwx.app.desktop b/scwx-qt/res/linux/net.supercellwx.app.desktop deleted file mode 100644 index 8e671522..00000000 --- a/scwx-qt/res/linux/net.supercellwx.app.desktop +++ /dev/null @@ -1,7 +0,0 @@ -[Desktop Entry] -Type=Application -Name=Supercell Wx -Comment=Weather Radar and Data Viewer -Exec=supercell-wx -Icon=net.supercellwx.app.png -Categories=Network;Science; diff --git a/scwx-qt/res/scwx-qt.plist.in b/scwx-qt/res/scwx-qt.plist.in deleted file mode 100644 index f9db57c0..00000000 --- a/scwx-qt/res/scwx-qt.plist.in +++ /dev/null @@ -1,42 +0,0 @@ - - - - - CFBundleInfoDictionaryVersion - 6.0 - CFBundlePackageType - APPL - - CFBundleName - ${MACOSX_BUNDLE_BUNDLE_NAME} - CFBundleIdentifier - ${MACOSX_BUNDLE_GUI_IDENTIFIER} - CFBundleExecutable - ${MACOSX_BUNDLE_EXECUTABLE_NAME} - - CFBundleVersion - ${MACOSX_BUNDLE_BUNDLE_VERSION} - CFBundleShortVersionString - ${MACOSX_BUNDLE_SHORT_VERSION_STRING} - - LSMinimumSystemVersion - ${CMAKE_OSX_DEPLOYMENT_TARGET} - - NSHumanReadableCopyright - ${MACOSX_BUNDLE_COPYRIGHT} - - CFBundleIconFile - ${MACOSX_BUNDLE_ICON_FILE} - - CFBundleDevelopmentRegion - en - CFBundleAllowMixedLocalizations - - - NSPrincipalClass - NSApplication - - NSSupportsAutomaticGraphicsSwitching - - - diff --git a/scwx-qt/res/textures/images/dot.svg b/scwx-qt/res/textures/images/dot.svg deleted file mode 100644 index 8f765035..00000000 --- a/scwx-qt/res/textures/images/dot.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - diff --git a/scwx-qt/res/textures/images/location-marker.svg b/scwx-qt/res/textures/images/location-marker.svg deleted file mode 100644 index 3eef9d9e..00000000 --- a/scwx-qt/res/textures/images/location-marker.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - diff --git a/scwx-qt/scwx-qt.cmake b/scwx-qt/scwx-qt.cmake index ecd26ef9..78d45217 100644 --- a/scwx-qt/scwx-qt.cmake +++ b/scwx-qt/scwx-qt.cmake @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.24) +cmake_minimum_required(VERSION 3.21) project(scwx-qt LANGUAGES CXX) @@ -6,19 +6,17 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) -set(CMAKE_AUTORCC OFF) +set(CMAKE_AUTORCC ON) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) -OPTION(SCWX_DISABLE_CONSOLE "Disables the Windows console in release mode" ON) - find_package(Boost) find_package(Fontconfig) find_package(geographiclib) find_package(geos) +find_package(GLEW) find_package(glm) -find_package(OpenGL) find_package(Python COMPONENTS Interpreter) find_package(SQLite3) @@ -32,9 +30,7 @@ find_package(QT NAMES Qt6 Positioning SerialPort Svg - Widgets - Sql - REQUIRED) + Widgets REQUIRED) find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Gui @@ -53,13 +49,9 @@ find_package(Qt${QT_VERSION_MAJOR} set(SRC_EXE_MAIN source/scwx/qt/main/main.cpp) set(HDR_MAIN source/scwx/qt/main/application.hpp - source/scwx/qt/main/check_privilege.hpp - source/scwx/qt/main/main_window.hpp - source/scwx/qt/main/process_validation.hpp) + source/scwx/qt/main/main_window.hpp) set(SRC_MAIN source/scwx/qt/main/application.cpp - source/scwx/qt/main/check_privilege.cpp - source/scwx/qt/main/main_window.cpp - source/scwx/qt/main/process_validation.cpp) + source/scwx/qt/main/main_window.cpp) set(UI_MAIN source/scwx/qt/main/main_window.ui) set(HDR_CONFIG source/scwx/qt/config/county_database.hpp source/scwx/qt/config/radar_site.hpp) @@ -103,13 +95,11 @@ set(HDR_MANAGER source/scwx/qt/manager/alert_manager.hpp source/scwx/qt/manager/log_manager.hpp source/scwx/qt/manager/media_manager.hpp source/scwx/qt/manager/placefile_manager.hpp - source/scwx/qt/manager/marker_manager.hpp source/scwx/qt/manager/position_manager.hpp source/scwx/qt/manager/radar_product_manager.hpp source/scwx/qt/manager/radar_product_manager_notifier.hpp source/scwx/qt/manager/resource_manager.hpp source/scwx/qt/manager/settings_manager.hpp - source/scwx/qt/manager/task_manager.hpp source/scwx/qt/manager/text_event_manager.hpp source/scwx/qt/manager/thread_manager.hpp source/scwx/qt/manager/timeline_manager.hpp @@ -121,13 +111,11 @@ set(SRC_MANAGER source/scwx/qt/manager/alert_manager.cpp source/scwx/qt/manager/log_manager.cpp source/scwx/qt/manager/media_manager.cpp source/scwx/qt/manager/placefile_manager.cpp - source/scwx/qt/manager/marker_manager.cpp source/scwx/qt/manager/position_manager.cpp source/scwx/qt/manager/radar_product_manager.cpp source/scwx/qt/manager/radar_product_manager_notifier.cpp source/scwx/qt/manager/resource_manager.cpp source/scwx/qt/manager/settings_manager.cpp - source/scwx/qt/manager/task_manager.cpp source/scwx/qt/manager/text_event_manager.cpp source/scwx/qt/manager/thread_manager.cpp source/scwx/qt/manager/timeline_manager.cpp @@ -144,7 +132,6 @@ set(HDR_MAP source/scwx/qt/map/alert_layer.hpp source/scwx/qt/map/overlay_layer.hpp source/scwx/qt/map/overlay_product_layer.hpp source/scwx/qt/map/placefile_layer.hpp - source/scwx/qt/map/marker_layer.hpp source/scwx/qt/map/radar_product_layer.hpp source/scwx/qt/map/radar_range_layer.hpp source/scwx/qt/map/radar_site_layer.hpp) @@ -159,7 +146,6 @@ set(SRC_MAP source/scwx/qt/map/alert_layer.cpp source/scwx/qt/map/overlay_layer.cpp source/scwx/qt/map/overlay_product_layer.cpp source/scwx/qt/map/placefile_layer.cpp - source/scwx/qt/map/marker_layer.cpp source/scwx/qt/map/radar_product_layer.cpp source/scwx/qt/map/radar_range_layer.cpp source/scwx/qt/map/radar_site_layer.cpp) @@ -168,7 +154,6 @@ set(HDR_MODEL source/scwx/qt/model/alert_model.hpp source/scwx/qt/model/imgui_context_model.hpp source/scwx/qt/model/layer_model.hpp source/scwx/qt/model/placefile_model.hpp - source/scwx/qt/model/marker_model.hpp source/scwx/qt/model/radar_site_model.hpp source/scwx/qt/model/tree_item.hpp source/scwx/qt/model/tree_model.hpp) @@ -177,7 +162,6 @@ set(SRC_MODEL source/scwx/qt/model/alert_model.cpp source/scwx/qt/model/imgui_context_model.cpp source/scwx/qt/model/layer_model.cpp source/scwx/qt/model/placefile_model.cpp - source/scwx/qt/model/marker_model.cpp source/scwx/qt/model/radar_site_model.cpp source/scwx/qt/model/tree_item.cpp source/scwx/qt/model/tree_model.cpp) @@ -185,11 +169,9 @@ set(HDR_REQUEST source/scwx/qt/request/download_request.hpp source/scwx/qt/request/nexrad_file_request.hpp) set(SRC_REQUEST source/scwx/qt/request/download_request.cpp source/scwx/qt/request/nexrad_file_request.cpp) -set(HDR_SETTINGS source/scwx/qt/settings/alert_palette_settings.hpp - source/scwx/qt/settings/audio_settings.hpp +set(HDR_SETTINGS source/scwx/qt/settings/audio_settings.hpp source/scwx/qt/settings/general_settings.hpp source/scwx/qt/settings/hotkey_settings.hpp - source/scwx/qt/settings/line_settings.hpp source/scwx/qt/settings/map_settings.hpp source/scwx/qt/settings/palette_settings.hpp source/scwx/qt/settings/product_settings.hpp @@ -203,11 +185,9 @@ set(HDR_SETTINGS source/scwx/qt/settings/alert_palette_settings.hpp source/scwx/qt/settings/text_settings.hpp source/scwx/qt/settings/ui_settings.hpp source/scwx/qt/settings/unit_settings.hpp) -set(SRC_SETTINGS source/scwx/qt/settings/alert_palette_settings.cpp - source/scwx/qt/settings/audio_settings.cpp +set(SRC_SETTINGS source/scwx/qt/settings/audio_settings.cpp source/scwx/qt/settings/general_settings.cpp source/scwx/qt/settings/hotkey_settings.cpp - source/scwx/qt/settings/line_settings.cpp source/scwx/qt/settings/map_settings.cpp source/scwx/qt/settings/palette_settings.cpp source/scwx/qt/settings/product_settings.cpp @@ -230,7 +210,6 @@ set(HDR_TYPES source/scwx/qt/types/alert_types.hpp source/scwx/qt/types/layer_types.hpp source/scwx/qt/types/location_types.hpp source/scwx/qt/types/map_types.hpp - source/scwx/qt/types/marker_types.hpp source/scwx/qt/types/media_types.hpp source/scwx/qt/types/qt_types.hpp source/scwx/qt/types/radar_product_record.hpp @@ -259,13 +238,10 @@ set(HDR_UI source/scwx/qt/ui/about_dialog.hpp source/scwx/qt/ui/alert_dialog.hpp source/scwx/qt/ui/alert_dock_widget.hpp source/scwx/qt/ui/animation_dock_widget.hpp - source/scwx/qt/ui/api_key_edit_widget.hpp source/scwx/qt/ui/collapsible_group.hpp source/scwx/qt/ui/county_dialog.hpp - source/scwx/qt/ui/custom_layer_dialog.hpp + source/scwx/qt/ui/wfo_dialog.hpp source/scwx/qt/ui/download_dialog.hpp - source/scwx/qt/ui/edit_line_dialog.hpp - source/scwx/qt/ui/edit_marker_dialog.hpp source/scwx/qt/ui/flow_layout.hpp source/scwx/qt/ui/gps_info_dialog.hpp source/scwx/qt/ui/hotkey_edit.hpp @@ -276,29 +252,22 @@ set(HDR_UI source/scwx/qt/ui/about_dialog.hpp source/scwx/qt/ui/level2_products_widget.hpp source/scwx/qt/ui/level2_settings_widget.hpp source/scwx/qt/ui/level3_products_widget.hpp - source/scwx/qt/ui/line_label.hpp source/scwx/qt/ui/open_url_dialog.hpp source/scwx/qt/ui/placefile_dialog.hpp source/scwx/qt/ui/placefile_settings_widget.hpp - source/scwx/qt/ui/marker_dialog.hpp - source/scwx/qt/ui/marker_settings_widget.hpp source/scwx/qt/ui/progress_dialog.hpp source/scwx/qt/ui/radar_site_dialog.hpp source/scwx/qt/ui/serial_port_dialog.hpp source/scwx/qt/ui/settings_dialog.hpp - source/scwx/qt/ui/update_dialog.hpp - source/scwx/qt/ui/wfo_dialog.hpp) + source/scwx/qt/ui/update_dialog.hpp) set(SRC_UI source/scwx/qt/ui/about_dialog.cpp source/scwx/qt/ui/alert_dialog.cpp source/scwx/qt/ui/alert_dock_widget.cpp source/scwx/qt/ui/animation_dock_widget.cpp - source/scwx/qt/ui/api_key_edit_widget.cpp source/scwx/qt/ui/collapsible_group.cpp source/scwx/qt/ui/county_dialog.cpp - source/scwx/qt/ui/custom_layer_dialog.cpp + source/scwx/qt/ui/wfo_dialog.cpp source/scwx/qt/ui/download_dialog.cpp - source/scwx/qt/ui/edit_line_dialog.cpp - source/scwx/qt/ui/edit_marker_dialog.cpp source/scwx/qt/ui/flow_layout.cpp source/scwx/qt/ui/gps_info_dialog.cpp source/scwx/qt/ui/hotkey_edit.cpp @@ -309,47 +278,36 @@ set(SRC_UI source/scwx/qt/ui/about_dialog.cpp source/scwx/qt/ui/level2_products_widget.cpp source/scwx/qt/ui/level2_settings_widget.cpp source/scwx/qt/ui/level3_products_widget.cpp - source/scwx/qt/ui/line_label.cpp source/scwx/qt/ui/open_url_dialog.cpp source/scwx/qt/ui/placefile_dialog.cpp source/scwx/qt/ui/placefile_settings_widget.cpp - source/scwx/qt/ui/marker_dialog.cpp - source/scwx/qt/ui/marker_settings_widget.cpp source/scwx/qt/ui/progress_dialog.cpp source/scwx/qt/ui/radar_site_dialog.cpp source/scwx/qt/ui/settings_dialog.cpp source/scwx/qt/ui/serial_port_dialog.cpp - source/scwx/qt/ui/update_dialog.cpp - source/scwx/qt/ui/wfo_dialog.cpp) + source/scwx/qt/ui/update_dialog.cpp) set(UI_UI source/scwx/qt/ui/about_dialog.ui source/scwx/qt/ui/alert_dialog.ui source/scwx/qt/ui/alert_dock_widget.ui source/scwx/qt/ui/animation_dock_widget.ui source/scwx/qt/ui/collapsible_group.ui source/scwx/qt/ui/county_dialog.ui - source/scwx/qt/ui/custom_layer_dialog.ui - source/scwx/qt/ui/edit_line_dialog.ui - source/scwx/qt/ui/edit_marker_dialog.ui + source/scwx/qt/ui/wfo_dialog.ui source/scwx/qt/ui/gps_info_dialog.ui source/scwx/qt/ui/imgui_debug_dialog.ui source/scwx/qt/ui/layer_dialog.ui source/scwx/qt/ui/open_url_dialog.ui source/scwx/qt/ui/placefile_dialog.ui source/scwx/qt/ui/placefile_settings_widget.ui - source/scwx/qt/ui/marker_dialog.ui - source/scwx/qt/ui/marker_settings_widget.ui source/scwx/qt/ui/progress_dialog.ui source/scwx/qt/ui/radar_site_dialog.ui source/scwx/qt/ui/settings_dialog.ui source/scwx/qt/ui/serial_port_dialog.ui - source/scwx/qt/ui/update_dialog.ui - source/scwx/qt/ui/wfo_dialog.ui) -set(HDR_UI_SETTINGS source/scwx/qt/ui/settings/alert_palette_settings_widget.hpp - source/scwx/qt/ui/settings/hotkey_settings_widget.hpp + source/scwx/qt/ui/update_dialog.ui) +set(HDR_UI_SETTINGS source/scwx/qt/ui/settings/hotkey_settings_widget.hpp source/scwx/qt/ui/settings/settings_page_widget.hpp source/scwx/qt/ui/settings/unit_settings_widget.hpp) -set(SRC_UI_SETTINGS source/scwx/qt/ui/settings/alert_palette_settings_widget.cpp - source/scwx/qt/ui/settings/hotkey_settings_widget.cpp +set(SRC_UI_SETTINGS source/scwx/qt/ui/settings/hotkey_settings_widget.cpp source/scwx/qt/ui/settings/settings_page_widget.cpp source/scwx/qt/ui/settings/unit_settings_widget.cpp) set(HDR_UI_SETUP source/scwx/qt/ui/setup/audio_codec_page.hpp @@ -364,9 +322,6 @@ set(SRC_UI_SETUP source/scwx/qt/ui/setup/audio_codec_page.cpp source/scwx/qt/ui/setup/map_provider_page.cpp source/scwx/qt/ui/setup/setup_wizard.cpp source/scwx/qt/ui/setup/welcome_page.cpp) -set(HDR_UI_WIDGETS source/scwx/qt/ui/widgets/focused_combo_box.hpp - source/scwx/qt/ui/widgets/focused_double_spin_box.hpp - source/scwx/qt/ui/widgets/focused_spin_box.hpp) set(HDR_UTIL source/scwx/qt/util/color.hpp source/scwx/qt/util/file.hpp source/scwx/qt/util/geographic_lib.hpp @@ -376,10 +331,8 @@ set(HDR_UTIL source/scwx/qt/util/color.hpp source/scwx/qt/util/network.hpp source/scwx/qt/util/streams.hpp source/scwx/qt/util/texture_atlas.hpp - source/scwx/qt/util/q_color_modulate.hpp source/scwx/qt/util/q_file_buffer.hpp source/scwx/qt/util/q_file_input_stream.hpp - source/scwx/qt/util/queue_counter.hpp source/scwx/qt/util/time.hpp source/scwx/qt/util/tooltip.hpp) set(SRC_UTIL source/scwx/qt/util/color.cpp @@ -390,10 +343,8 @@ set(SRC_UTIL source/scwx/qt/util/color.cpp source/scwx/qt/util/maplibre.cpp source/scwx/qt/util/network.cpp source/scwx/qt/util/texture_atlas.cpp - source/scwx/qt/util/q_color_modulate.cpp source/scwx/qt/util/q_file_buffer.cpp source/scwx/qt/util/q_file_input_stream.cpp - source/scwx/qt/util/queue_counter.cpp source/scwx/qt/util/time.cpp source/scwx/qt/util/tooltip.cpp) set(HDR_VIEW source/scwx/qt/view/level2_product_view.hpp @@ -434,13 +385,13 @@ set(JSON_FILES res/config/radar_sites.json) set(TS_FILES ts/scwx_en_US.ts) set(RADAR_SITES_FILE ${scwx-qt_SOURCE_DIR}/res/config/radar_sites.json) -set(COUNTY_DBF_FILES ${SCWX_DIR}/data/db/c_18mr25.dbf) -set(ZONE_DBF_FILES ${SCWX_DIR}/data/db/fz18mr25.dbf - ${SCWX_DIR}/data/db/mz18mr25.dbf - ${SCWX_DIR}/data/db/oz18mr25.dbf - ${SCWX_DIR}/data/db/z_18mr25.dbf) -set(STATE_DBF_FILES ${SCWX_DIR}/data/db/s_18mr25.dbf) -set(WFO_DBF_FILES ${SCWX_DIR}/data/db/w_18mr25.dbf) +set(COUNTY_DBF_FILES ${SCWX_DIR}/data/db/c_05mr24.dbf) +set(ZONE_DBF_FILES ${SCWX_DIR}/data/db/fz05mr24.dbf + ${SCWX_DIR}/data/db/mz05mr24.dbf + ${SCWX_DIR}/data/db/oz05mr24.dbf + ${SCWX_DIR}/data/db/z_05mr24.dbf) +set(STATE_DBF_FILES ${SCWX_DIR}/data/db/s_05mr24.dbf) +set(WFO_DBF_FILES ${SCWX_DIR}/data/db/w_05mr24.dbf) set(COUNTIES_SQLITE_DB ${scwx-qt_BINARY_DIR}/res/db/counties.db) set(RESOURCE_INPUT ${scwx-qt_SOURCE_DIR}/res/scwx-qt.rc.in) @@ -478,19 +429,17 @@ set(PROJECT_SOURCES ${HDR_MAIN} ${SRC_UI_SETTINGS} ${HDR_UI_SETUP} ${SRC_UI_SETUP} - ${HDR_UI_WIDGETS} ${HDR_UTIL} ${SRC_UTIL} ${HDR_VIEW} ${SRC_VIEW} ${SHADER_FILES} ${JSON_FILES} + ${RESOURCE_FILES} ${TS_FILES} ${CMAKE_FILES}) set(EXECUTABLE_SOURCES ${SRC_EXE_MAIN}) -qt_add_resources(PROJECT_SOURCES ${RESOURCE_FILES}) - source_group("Header Files\\main" FILES ${HDR_MAIN}) source_group("Source Files\\main" FILES ${SRC_MAIN}) source_group("Header Files\\config" FILES ${HDR_CONFIG}) @@ -519,7 +468,6 @@ source_group("Header Files\\ui\\settings" FILES ${HDR_UI_SETTINGS}) source_group("Source Files\\ui\\settings" FILES ${SRC_UI_SETTINGS}) source_group("Header Files\\ui\\setup" FILES ${HDR_UI_SETUP}) source_group("Source Files\\ui\\setup" FILES ${SRC_UI_SETUP}) -source_group("Header Files\\ui\\widgets" FILES ${HDR_UI_WIDGETS}) source_group("UI Files\\ui" FILES ${UI_UI}) source_group("Header Files\\util" FILES ${HDR_UTIL}) source_group("Source Files\\util" FILES ${SRC_UTIL}) @@ -532,7 +480,6 @@ source_group("I18N Files" FILES ${TS_FILES}) add_library(scwx-qt OBJECT ${PROJECT_SOURCES}) set_property(TARGET scwx-qt PROPERTY AUTOMOC ON) -set_property(TARGET scwx-qt PROPERTY AUTOGEN_ORIGIN_DEPENDS OFF) add_custom_command(OUTPUT ${COUNTIES_SQLITE_DB} COMMAND ${Python_EXECUTABLE} @@ -579,8 +526,7 @@ else() -v ${SCWX_VERSION} -c ${VERSIONS_CACHE} -i ${VERSIONS_INPUT} - -o ${VERSIONS_HEADER} - -b ${SCWX_BUILD_NUM}) + -o ${VERSIONS_HEADER}) endif() add_custom_target(scwx-qt_generate_versions ALL @@ -626,29 +572,7 @@ set_target_properties(scwx-qt_update_radar_sites PROPERTIES FOLDER generate) if (WIN32) set(APP_ICON_RESOURCE_WINDOWS ${RESOURCE_OUTPUT}) qt_add_executable(supercell-wx ${EXECUTABLE_SOURCES} ${APP_ICON_RESOURCE_WINDOWS}) - if (SCWX_DISABLE_CONSOLE) - set_target_properties(supercell-wx PROPERTIES WIN32_EXECUTABLE $,TRUE,FALSE>) - endif() -elseif (APPLE) - set(SCWX_ICON "${scwx-qt_SOURCE_DIR}/res/icons/scwx.icns") - - set_source_files_properties(${SCWX_ICON} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources") - - qt_add_executable(supercell-wx ${EXECUTABLE_SOURCES} ${SCWX_ICON}) - - string(TIMESTAMP CURRENT_YEAR "%Y") - - set_target_properties(supercell-wx PROPERTIES - MACOSX_BUNDLE TRUE - MACOSX_BUNDLE_INFO_PLIST "${scwx-qt_SOURCE_DIR}/res/scwx-qt.plist.in" - MACOSX_BUNDLE_GUI_IDENTIFIER "net.supercellwx.app" - MACOSX_BUNDLE_BUNDLE_NAME "Supercell Wx" - MACOSX_BUNDLE_BUNDLE_VERSION "${SCWX_VERSION}" - MACOSX_BUNDLE_SHORT_VERSION_STRING "${SCWX_VERSION}" - MACOSX_BUNDLE_COPYRIGHT "Copyright ${CURRENT_YEAR} Dan Paulat" - MACOSX_BUNDLE_ICON_FILE "scwx.icns" - MACOSX_BUNDLE_INFO_STRING "Free and open source advanced weather radar" - RESOURCE ${SCWX_ICON}) + set_target_properties(supercell-wx PROPERTIES WIN32_EXECUTABLE $,TRUE,FALSE>) else() qt_add_executable(supercell-wx ${EXECUTABLE_SOURCES}) endif() @@ -658,17 +582,12 @@ if (WIN32) target_compile_definitions(supercell-wx PUBLIC WIN32_LEAN_AND_MEAN) endif() -if (LINUX) +if (NOT MSVC) # Qt emit keyword is incompatible with TBB target_compile_definitions(scwx-qt PRIVATE QT_NO_EMIT) target_compile_definitions(supercell-wx PRIVATE QT_NO_EMIT) endif() -if (APPLE) - target_compile_definitions(scwx-qt PRIVATE GL_SILENCE_DEPRECATION) - target_compile_definitions(supercell-wx PRIVATE GL_SILENCE_DEPRECATION) -endif() - target_include_directories(scwx-qt PUBLIC ${scwx-qt_SOURCE_DIR}/source ${FTGL_INCLUDE_DIR} ${IMGUI_INCLUDE_DIRS} @@ -724,25 +643,6 @@ else() target_compile_options(supercell-wx PRIVATE "$<$:-g>") endif() -if (LINUX) - # Add wayland client packages - find_package(QT NAMES Qt6 - COMPONENTS WaylandClient - REQUIRED) - - find_package(Qt${QT_VERSION_MAJOR} - COMPONENTS WaylandClient - REQUIRED) - target_link_libraries(scwx-qt PUBLIC Qt${QT_VERSION_MAJOR}::WaylandClient) -endif() - -if (LINUX) - find_package(mesa-glu REQUIRED) - target_link_libraries(scwx-qt PUBLIC mesa-glu::mesa-glu) -else() - target_link_libraries(scwx-qt PUBLIC OpenGL::GLU) -endif() - target_link_libraries(scwx-qt PUBLIC Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::OpenGLWidgets Qt${QT_VERSION_MAJOR}::Multimedia @@ -751,7 +651,6 @@ target_link_libraries(scwx-qt PUBLIC Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Svg Boost::json Boost::timer - Boost::atomic QMapLibre::Core $<$:opengl32> $<$:SetupAPI> @@ -759,22 +658,18 @@ target_link_libraries(scwx-qt PUBLIC Qt${QT_VERSION_MAJOR}::Widgets GeographicLib::GeographicLib GEOS::geos GEOS::geos_cxx_flags - glad_gl_core_33 + GLEW::GLEW glm::glm imgui - qt6ct-common - qt6ct-widgets SQLite::SQLite3 wxdata) target_link_libraries(supercell-wx PRIVATE scwx-qt wxdata) -if (LINUX) - # Set DT_RUNPATH for Linux targets - set_target_properties(MLNQtCore PROPERTIES INSTALL_RPATH "\$ORIGIN/../lib") # QMapLibre::Core - set_target_properties(supercell-wx PROPERTIES INSTALL_RPATH "\$ORIGIN/../lib") -endif() +# Set DT_RUNPATH for Linux targets +set_target_properties(MLNQtCore PROPERTIES INSTALL_RPATH "\$ORIGIN/../lib") # QMapLibre::Core +set_target_properties(supercell-wx PROPERTIES INSTALL_RPATH "\$ORIGIN/../lib") install(TARGETS supercell-wx MLNQtCore # QMapLibre::Core @@ -784,15 +679,7 @@ install(TARGETS supercell-wx "^(/usr)?/lib/.*\\.so(\\..*)?" RUNTIME COMPONENT supercell-wx - BUNDLE - DESTINATION . - COMPONENT supercell-wx - OPTIONAL LIBRARY - COMPONENT supercell-wx - OPTIONAL - FRAMEWORK - DESTINATION Frameworks COMPONENT supercell-wx OPTIONAL) @@ -814,64 +701,14 @@ install(SCRIPT ${deploy_script_qmaplibre_core} install(SCRIPT ${deploy_script_scwx} COMPONENT supercell-wx) -if (APPLE) - # Install additional script to fix up the bundle - install(CODE [[ - include (BundleUtilities) - - # Define the bundle path - set(BUNDLE_PATH "${CMAKE_INSTALL_PREFIX}/supercell-wx.app") - - file(GLOB_RECURSE PLUGIN_DYLIBS "${BUNDLE_PATH}/Contents/PlugIns/**/*.dylib") - - # Add the correct rpath for plugins to find bundled frameworks - foreach(PLUGIN_DYLIB ${PLUGIN_DYLIBS}) - execute_process( - COMMAND install_name_tool -add_rpath "@loader_path/../../Frameworks" - ${PLUGIN_DYLIB} - ) - endforeach() - - # Fix up the bundle with all dependencies - fixup_bundle( - "${BUNDLE_PATH}" - "" - "${CMAKE_INSTALL_PREFIX}/lib;${CMAKE_INSTALL_PREFIX}/Frameworks" - ) - - # Re-sign the bundle - execute_process( - COMMAND codesign --force --deep --sign - "${BUNDLE_PATH}" - ) - - # Verify the bundle - verify_app("${BUNDLE_PATH}") - - # Rename to "Supercell Wx.app" - file(REMOVE_RECURSE - "${CMAKE_INSTALL_PREFIX}/Supercell Wx.app") - file(RENAME - "${BUNDLE_PATH}" - "${CMAKE_INSTALL_PREFIX}/Supercell Wx.app") - - # Remove extra directories - file(REMOVE_RECURSE - "${CMAKE_INSTALL_PREFIX}/Frameworks") - file(REMOVE_RECURSE - "${CMAKE_INSTALL_PREFIX}/lib") - ]] - COMPONENT supercell-wx) -endif() - -set(CPACK_PACKAGE_NAME "Supercell Wx") -set(CPACK_PACKAGE_VENDOR "Dan Paulat") -set(CPACK_PACKAGE_CHECKSUM SHA256) -set(CPACK_RESOURCE_FILE_LICENSE "${SCWX_DIR}/LICENSE.txt") - if (MSVC) + set(CPACK_PACKAGE_NAME "Supercell Wx") + set(CPACK_PACKAGE_VENDOR "Dan Paulat") set(CPACK_PACKAGE_FILE_NAME "supercell-wx-v${SCWX_VERSION}-windows-x64") set(CPACK_PACKAGE_INSTALL_DIRECTORY "Supercell Wx") set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/res/icons/scwx-256.ico") + set(CPACK_PACKAGE_CHECKSUM SHA256) + set(CPACK_RESOURCE_FILE_LICENSE "${SCWX_DIR}/LICENSE.txt") set(CPACK_GENERATOR WIX) set(CPACK_PACKAGE_EXECUTABLES "supercell-wx;Supercell Wx") set(CPACK_WIX_UPGRADE_GUID 36AD0F51-4D4F-4B5D-AB61-94C6B4E4FE1C) @@ -883,15 +720,5 @@ if (MSVC) set(CPACK_INSTALL_CMAKE_PROJECTS "${CMAKE_CURRENT_BINARY_DIR};${CMAKE_PROJECT_NAME};supercell-wx;/") - include(CPack) -elseif(APPLE) - set(CPACK_PACKAGE_FILE_NAME "supercell-wx-v${SCWX_VERSION}-macos") - set(CPACK_PACKAGE_ICON "${SCWX_ICON}") - set(CPACK_PACKAGE_VERSION "${SCWX_VERSION}") - - set(CPACK_GENERATOR DragNDrop) - - set(CPACK_COMPONENTS_ALL supercell-wx) - include(CPack) endif() diff --git a/scwx-qt/scwx-qt.qrc b/scwx-qt/scwx-qt.qrc index ccb2e42a..c9e00337 100644 --- a/scwx-qt/scwx-qt.qrc +++ b/scwx-qt/scwx-qt.qrc @@ -32,10 +32,6 @@ res/icons/font-awesome-6/angles-up-solid.svg res/icons/font-awesome-6/backward-step-solid.svg res/icons/font-awesome-6/book-solid.svg - res/icons/font-awesome-6/briefcase-solid.svg - res/icons/font-awesome-6/building-columns-solid.svg - res/icons/font-awesome-6/building-solid.svg - res/icons/font-awesome-6/caravan-solid.svg res/icons/font-awesome-6/copy-regular.svg res/icons/font-awesome-6/discord.svg res/icons/font-awesome-6/earth-americas-solid.svg @@ -44,11 +40,8 @@ res/icons/font-awesome-6/gears-solid.svg res/icons/font-awesome-6/github.svg res/icons/font-awesome-6/house-solid.svg - res/icons/font-awesome-6/house-solid-white.svg res/icons/font-awesome-6/keyboard-regular.svg res/icons/font-awesome-6/layer-group-solid.svg - res/icons/font-awesome-6/location-crosshairs-solid.svg - res/icons/font-awesome-6/location-pin.svg res/icons/font-awesome-6/palette-solid.svg res/icons/font-awesome-6/pause-solid.svg res/icons/font-awesome-6/play-solid.svg @@ -60,9 +53,7 @@ res/icons/font-awesome-6/square-minus-regular.svg res/icons/font-awesome-6/square-plus-regular.svg res/icons/font-awesome-6/star-solid.svg - res/icons/font-awesome-6/star-solid-white.svg res/icons/font-awesome-6/stop-solid.svg - res/icons/font-awesome-6/tent-solid.svg res/icons/font-awesome-6/volume-high-solid.svg res/palettes/wct/CC.pal res/palettes/wct/Default16.pal @@ -79,20 +70,11 @@ res/palettes/wct/SW.pal res/palettes/wct/VIL.pal res/palettes/wct/ZDR.pal - ../external/qt6ct/colors/airy.conf - ../external/qt6ct/colors/darker.conf - ../external/qt6ct/colors/dusk.conf - ../external/qt6ct/colors/ia_ora.conf - ../external/qt6ct/colors/sand.conf - ../external/qt6ct/colors/simple.conf - ../external/qt6ct/colors/waves.conf res/textures/lines/default-1x7.png res/textures/lines/test-pattern.png res/textures/images/cursor-17.png res/textures/images/crosshairs-24.png res/textures/images/dot-3.png - res/textures/images/dot.svg - res/textures/images/location-marker.svg res/textures/images/mapbox-logo.svg res/textures/images/maptiler-logo.svg diff --git a/scwx-qt/source/scwx/qt/config/radar_site.cpp b/scwx-qt/source/scwx/qt/config/radar_site.cpp index 69815636..c0cb4636 100644 --- a/scwx-qt/source/scwx/qt/config/radar_site.cpp +++ b/scwx-qt/source/scwx/qt/config/radar_site.cpp @@ -10,7 +10,7 @@ #include -#if (__cpp_lib_chrono < 201907L) +#if !defined(_MSC_VER) # include #endif @@ -51,7 +51,6 @@ public: std::string state_ {}; std::string place_ {}; std::string tzName_ {}; - double altitude_ {0.0}; const scwx::util::time_zone* timeZone_ {nullptr}; }; @@ -143,11 +142,6 @@ const scwx::util::time_zone* RadarSite::time_zone() const return p->timeZone_; } -units::length::feet RadarSite::altitude() const -{ - return units::length::feet(p->altitude_); -} - std::shared_ptr RadarSite::Get(const std::string& id) { std::shared_lock lock(siteMutex_); @@ -245,7 +239,7 @@ size_t RadarSite::ReadConfig(const std::string& path) bool dataValid = true; size_t sitesAdded = 0; - boost::json::value j = util::json::ReadJsonQFile(path); + boost::json::value j = util::json::ReadJsonFile(path); dataValid = j.is_array(); @@ -274,12 +268,10 @@ size_t RadarSite::ReadConfig(const std::string& path) site->p->state_ = boost::json::value_to(o.at("state")); site->p->place_ = boost::json::value_to(o.at("place")); site->p->tzName_ = boost::json::value_to(o.at("tz")); - site->p->altitude_ = - boost::json::value_to(o.at("elevation")); try { -#if (__cpp_lib_chrono >= 201907L) +#if defined(_MSC_VER) using namespace std::chrono; #else using namespace date; diff --git a/scwx-qt/source/scwx/qt/config/radar_site.hpp b/scwx-qt/source/scwx/qt/config/radar_site.hpp index cf622d7a..16f6e710 100644 --- a/scwx-qt/source/scwx/qt/config/radar_site.hpp +++ b/scwx-qt/source/scwx/qt/config/radar_site.hpp @@ -6,9 +6,12 @@ #include #include #include -#include -namespace scwx::qt::config +namespace scwx +{ +namespace qt +{ +namespace config { class RadarSiteImpl; @@ -25,19 +28,18 @@ public: RadarSite(RadarSite&&) noexcept; RadarSite& operator=(RadarSite&&) noexcept; - [[nodiscard]] std::string type() const; - [[nodiscard]] std::string type_name() const; - [[nodiscard]] std::string id() const; - [[nodiscard]] double latitude() const; - [[nodiscard]] double longitude() const; - [[nodiscard]] std::string country() const; - [[nodiscard]] std::string state() const; - [[nodiscard]] std::string place() const; - [[nodiscard]] std::string location_name() const; - [[nodiscard]] std::string tz_name() const; - [[nodiscard]] units::length::feet altitude() const; + std::string type() const; + std::string type_name() const; + std::string id() const; + double latitude() const; + double longitude() const; + std::string country() const; + std::string state() const; + std::string place() const; + std::string location_name() const; + std::string tz_name() const; - [[nodiscard]] const scwx::util::time_zone* time_zone() const; + const scwx::util::time_zone* time_zone() const; static std::shared_ptr Get(const std::string& id); static std::vector> GetAll(); @@ -65,4 +67,6 @@ private: std::string GetRadarIdFromSiteId(const std::string& siteId); -} // namespace scwx::qt::config +} // namespace config +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/gl/draw/draw_item.cpp b/scwx-qt/source/scwx/qt/gl/draw/draw_item.cpp index 0f18e40f..c6737a10 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/draw_item.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/draw_item.cpp @@ -30,11 +30,13 @@ static const std::string logPrefix_ = "scwx::qt::gl::draw::draw_item"; class DrawItem::Impl { public: - explicit Impl() = default; - ~Impl() = default; + explicit Impl(OpenGLFunctions& gl) : gl_ {gl} {} + ~Impl() {} + + OpenGLFunctions& gl_; }; -DrawItem::DrawItem() : p(std::make_unique()) {} +DrawItem::DrawItem(OpenGLFunctions& gl) : p(std::make_unique(gl)) {} DrawItem::~DrawItem() = default; DrawItem::DrawItem(DrawItem&&) noexcept = default; @@ -72,7 +74,7 @@ void DrawItem::UseDefaultProjection( 0.0f, static_cast(params.height)); - glUniformMatrix4fv( + p->gl_.glUniformMatrix4fv( uMVPMatrixLocation, 1, GL_FALSE, glm::value_ptr(projection)); } @@ -89,7 +91,7 @@ void DrawItem::UseRotationProjection( glm::radians(params.bearing), glm::vec3(0.0f, 0.0f, 1.0f)); - glUniformMatrix4fv( + p->gl_.glUniformMatrix4fv( uMVPMatrixLocation, 1, GL_FALSE, glm::value_ptr(projection)); } @@ -98,14 +100,16 @@ void DrawItem::UseMapProjection( GLint uMVPMatrixLocation, GLint uMapScreenCoordLocation) { + OpenGLFunctions& gl = p->gl_; + const glm::mat4 uMVPMatrix = util::maplibre::GetMapMatrix(params); - glUniform2fv(uMapScreenCoordLocation, - 1, - glm::value_ptr(util::maplibre::LatLongToScreenCoordinate( - {params.latitude, params.longitude}))); + gl.glUniform2fv(uMapScreenCoordLocation, + 1, + glm::value_ptr(util::maplibre::LatLongToScreenCoordinate( + {params.latitude, params.longitude}))); - glUniformMatrix4fv( + gl.glUniformMatrix4fv( uMVPMatrixLocation, 1, GL_FALSE, glm::value_ptr(uMVPMatrix)); } diff --git a/scwx-qt/source/scwx/qt/gl/draw/draw_item.hpp b/scwx-qt/source/scwx/qt/gl/draw/draw_item.hpp index 28350190..f7df44c4 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/draw_item.hpp +++ b/scwx-qt/source/scwx/qt/gl/draw/draw_item.hpp @@ -21,8 +21,8 @@ namespace draw class DrawItem { public: - explicit DrawItem(); - virtual ~DrawItem(); + explicit DrawItem(OpenGLFunctions& gl); + ~DrawItem(); DrawItem(const DrawItem&) = delete; DrawItem& operator=(const DrawItem&) = delete; diff --git a/scwx-qt/source/scwx/qt/gl/draw/geo_icons.cpp b/scwx-qt/source/scwx/qt/gl/draw/geo_icons.cpp index 05cc26a5..622718e3 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/geo_icons.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/geo_icons.cpp @@ -4,7 +4,6 @@ #include #include #include -#include #include @@ -39,7 +38,7 @@ static constexpr std::size_t kIntegersPerVertex_ = 4; static constexpr std::size_t kIntegerBufferLength_ = kNumTriangles * kVerticesPerTriangle * kIntegersPerVertex_; -struct GeoIconDrawItem : types::EventHandler +struct GeoIconDrawItem { units::length::nautical_miles threshold_ {}; std::chrono::sys_time startTime_ {}; @@ -145,7 +144,7 @@ public: }; GeoIcons::GeoIcons(const std::shared_ptr& context) : - DrawItem(), p(std::make_unique(context)) + DrawItem(context->gl()), p(std::make_unique(context)) { } GeoIcons::~GeoIcons() = default; @@ -166,6 +165,8 @@ void GeoIcons::set_thresholded(bool thresholded) void GeoIcons::Initialize() { + gl::OpenGLFunctions& gl = p->context_->gl(); + p->shaderProgram_ = p->context_->GetShaderProgram( {{GL_VERTEX_SHADER, ":/gl/geo_texture2d.vert"}, {GL_GEOMETRY_SHADER, ":/gl/threshold.geom"}, @@ -180,95 +181,88 @@ void GeoIcons::Initialize() p->uSelectedTimeLocation_ = p->shaderProgram_->GetUniformLocation("uSelectedTime"); - glGenVertexArrays(1, &p->vao_); - glGenBuffers(static_cast(p->vbo_.size()), p->vbo_.data()); + gl.glGenVertexArrays(1, &p->vao_); + gl.glGenBuffers(static_cast(p->vbo_.size()), p->vbo_.data()); - glBindVertexArray(p->vao_); - glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); - glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); - - // NOLINTBEGIN(modernize-use-nullptr) - // NOLINTBEGIN(performance-no-int-to-ptr) - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) + gl.glBindVertexArray(p->vao_); + gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); + gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); // aLatLong - glVertexAttribPointer(0, - 2, - GL_FLOAT, - GL_FALSE, - kPointsPerVertex * sizeof(float), - static_cast(0)); - glEnableVertexAttribArray(0); + gl.glVertexAttribPointer(0, + 2, + GL_FLOAT, + GL_FALSE, + kPointsPerVertex * sizeof(float), + static_cast(0)); + gl.glEnableVertexAttribArray(0); // aXYOffset - glVertexAttribPointer(1, - 2, - GL_FLOAT, - GL_FALSE, - kPointsPerVertex * sizeof(float), - reinterpret_cast(2 * sizeof(float))); - glEnableVertexAttribArray(1); + gl.glVertexAttribPointer(1, + 2, + GL_FLOAT, + GL_FALSE, + kPointsPerVertex * sizeof(float), + reinterpret_cast(2 * sizeof(float))); + gl.glEnableVertexAttribArray(1); // aModulate - glVertexAttribPointer(3, - 4, - GL_FLOAT, - GL_FALSE, - kPointsPerVertex * sizeof(float), - reinterpret_cast(4 * sizeof(float))); - glEnableVertexAttribArray(3); + gl.glVertexAttribPointer(3, + 4, + GL_FLOAT, + GL_FALSE, + kPointsPerVertex * sizeof(float), + reinterpret_cast(4 * sizeof(float))); + gl.glEnableVertexAttribArray(3); // aAngle - glVertexAttribPointer(4, - 1, - GL_FLOAT, - GL_FALSE, - kPointsPerVertex * sizeof(float), - reinterpret_cast(8 * sizeof(float))); - glEnableVertexAttribArray(4); + gl.glVertexAttribPointer(4, + 1, + GL_FLOAT, + GL_FALSE, + kPointsPerVertex * sizeof(float), + reinterpret_cast(8 * sizeof(float))); + gl.glEnableVertexAttribArray(4); - glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); - glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); + gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); + gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); // aTexCoord - glVertexAttribPointer(2, - 3, - GL_FLOAT, - GL_FALSE, - kPointsPerTexCoord * sizeof(float), - static_cast(0)); - glEnableVertexAttribArray(2); + gl.glVertexAttribPointer(2, + 3, + GL_FLOAT, + GL_FALSE, + kPointsPerTexCoord * sizeof(float), + static_cast(0)); + gl.glEnableVertexAttribArray(2); - glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[2]); - glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); + gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[2]); + gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); // aThreshold - glVertexAttribIPointer(5, // - 1, - GL_INT, - 0, - static_cast(0)); - glEnableVertexAttribArray(5); + gl.glVertexAttribIPointer(5, // + 1, + GL_INT, + 0, + static_cast(0)); + gl.glEnableVertexAttribArray(5); // aTimeRange - glVertexAttribIPointer(6, // - 2, - GL_INT, - kIntegersPerVertex_ * sizeof(GLint), - reinterpret_cast(1 * sizeof(GLint))); - glEnableVertexAttribArray(6); + gl.glVertexAttribIPointer(6, // + 2, + GL_INT, + kIntegersPerVertex_ * sizeof(GLint), + reinterpret_cast(1 * sizeof(GLint))); + gl.glEnableVertexAttribArray(6); // aDisplayed - glVertexAttribIPointer(7, - 1, - GL_INT, - kIntegersPerVertex_ * sizeof(GLint), - reinterpret_cast(3 * sizeof(GLint))); - glEnableVertexAttribArray(7); - - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - // NOLINTEND(performance-no-int-to-ptr) - // NOLINTEND(modernize-use-nullptr) + gl.glVertexAttribPointer(7, + 1, + GL_INT, + GL_FALSE, + kIntegersPerVertex_ * sizeof(GLint), + reinterpret_cast(3 * sizeof(float))); + gl.glEnableVertexAttribArray(7); p->dirty_ = true; } @@ -290,7 +284,9 @@ void GeoIcons::Render(const QMapLibre::CustomLayerRenderParameters& params, if (!p->currentIconList_.empty()) { - glBindVertexArray(p->vao_); + gl::OpenGLFunctions& gl = p->context_->gl(); + + gl.glBindVertexArray(p->vao_); p->Update(textureAtlasChanged); p->shaderProgram_->Use(); @@ -303,38 +299,40 @@ void GeoIcons::Render(const QMapLibre::CustomLayerRenderParameters& params, // If thresholding is enabled, set the map distance units::length::nautical_miles mapDistance = util::maplibre::GetMapDistance(params); - glUniform1f(p->uMapDistanceLocation_, mapDistance.value()); + gl.glUniform1f(p->uMapDistanceLocation_, mapDistance.value()); } else { // If thresholding is disabled, set the map distance to 0 - glUniform1f(p->uMapDistanceLocation_, 0.0f); + gl.glUniform1f(p->uMapDistanceLocation_, 0.0f); } // Selected time std::chrono::system_clock::time_point selectedTime = (p->selectedTime_ == std::chrono::system_clock::time_point {}) ? - scwx::util::time::now() : + std::chrono::system_clock::now() : p->selectedTime_; - glUniform1i( + gl.glUniform1i( p->uSelectedTimeLocation_, static_cast(std::chrono::duration_cast( selectedTime.time_since_epoch()) .count())); // Interpolate texture coordinates - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Draw icons - glDrawArrays(GL_TRIANGLES, 0, p->numVertices_); + gl.glDrawArrays(GL_TRIANGLES, 0, p->numVertices_); } } void GeoIcons::Deinitialize() { - glDeleteVertexArrays(1, &p->vao_); - glDeleteBuffers(static_cast(p->vbo_.size()), p->vbo_.data()); + gl::OpenGLFunctions& gl = p->context_->gl(); + + gl.glDeleteVertexArrays(1, &p->vao_); + gl.glDeleteBuffers(static_cast(p->vbo_.size()), p->vbo_.data()); std::unique_lock lock {p->iconMutex_}; @@ -694,7 +692,7 @@ void GeoIcons::Impl::UpdateSingleBuffer( hoverIcons.end(), [&di](auto& entry) { return entry.di_ == di; }); - if (di->visible_ && (!di->hoverText_.empty() || di->event_ != nullptr)) + if (di->visible_ && !di->hoverText_.empty()) { const units::angle::radians radians = angle; @@ -850,6 +848,8 @@ void GeoIcons::Impl::UpdateModifiedIconBuffers() void GeoIcons::Impl::Update(bool textureAtlasChanged) { + gl::OpenGLFunctions& gl = context_->gl(); + UpdateModifiedIconBuffers(); // If the texture atlas has changed @@ -865,12 +865,11 @@ void GeoIcons::Impl::Update(bool textureAtlasChanged) UpdateTextureBuffer(); // Buffer texture data - glBindBuffer(GL_ARRAY_BUFFER, vbo_[1]); - glBufferData( - GL_ARRAY_BUFFER, - static_cast(sizeof(float) * textureBuffer_.size()), - textureBuffer_.data(), - GL_DYNAMIC_DRAW); + gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[1]); + gl.glBufferData(GL_ARRAY_BUFFER, + sizeof(float) * textureBuffer_.size(), + textureBuffer_.data(), + GL_DYNAMIC_DRAW); lastTextureAtlasChanged_ = false; } @@ -879,20 +878,18 @@ void GeoIcons::Impl::Update(bool textureAtlasChanged) if (dirty_) { // Buffer vertex data - glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]); - glBufferData( - GL_ARRAY_BUFFER, - static_cast(sizeof(float) * currentIconBuffer_.size()), - currentIconBuffer_.data(), - GL_DYNAMIC_DRAW); + gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]); + gl.glBufferData(GL_ARRAY_BUFFER, + sizeof(float) * currentIconBuffer_.size(), + currentIconBuffer_.data(), + GL_DYNAMIC_DRAW); // Buffer threshold data - glBindBuffer(GL_ARRAY_BUFFER, vbo_[2]); - glBufferData( - GL_ARRAY_BUFFER, - static_cast(sizeof(GLint) * currentIntegerBuffer_.size()), - currentIntegerBuffer_.data(), - GL_DYNAMIC_DRAW); + gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[2]); + gl.glBufferData(GL_ARRAY_BUFFER, + sizeof(GLint) * currentIntegerBuffer_.size(), + currentIntegerBuffer_.data(), + GL_DYNAMIC_DRAW); numVertices_ = static_cast(currentIconBuffer_.size() / kPointsPerVertex); @@ -907,7 +904,7 @@ bool GeoIcons::RunMousePicking( const QPointF& mouseGlobalPos, const glm::vec2& mouseCoords, const common::Coordinate& /* mouseGeoCoords */, - std::shared_ptr& eventHandler) + std::shared_ptr& /* eventHandler */) { std::unique_lock lock {p->iconMutex_}; @@ -931,7 +928,7 @@ bool GeoIcons::RunMousePicking( // If no time has been selected, use the current time std::chrono::system_clock::time_point selectedTime = (p->selectedTime_ == std::chrono::system_clock::time_point {}) ? - scwx::util::time::now() : + std::chrono::system_clock::now() : p->selectedTime_; // For each pickable icon @@ -950,10 +947,8 @@ bool GeoIcons::RunMousePicking( units::length::nautical_miles {icon.di_->threshold_} .value())) < 999 && - // Map distance is beyond/within the threshold - icon.di_->threshold_ < mapDistance && - (icon.di_->threshold_.value() >= 0.0 || - -(icon.di_->threshold_) > mapDistance)) || + // Map distance is beyond the threshold + icon.di_->threshold_ < mapDistance) || ( // Geo icon has a start time @@ -997,27 +992,12 @@ bool GeoIcons::RunMousePicking( if (it != p->currentHoverIcons_.crend()) { itemPicked = true; - if (!it->di_->hoverText_.empty()) - { - // Show tooltip - util::tooltip::Show(it->di_->hoverText_, mouseGlobalPos); - } - if (it->di_->event_ != nullptr) - { - eventHandler = it->di_; - } + util::tooltip::Show(it->di_->hoverText_, mouseGlobalPos); } return itemPicked; } -void GeoIcons::RegisterEventHandler( - const std::shared_ptr& di, - const std::function& eventHandler) -{ - di->event_ = eventHandler; -} - } // namespace draw } // namespace gl } // namespace qt diff --git a/scwx-qt/source/scwx/qt/gl/draw/geo_icons.hpp b/scwx-qt/source/scwx/qt/gl/draw/geo_icons.hpp index 073fc118..4d819681 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/geo_icons.hpp +++ b/scwx-qt/source/scwx/qt/gl/draw/geo_icons.hpp @@ -183,16 +183,6 @@ public: */ void FinishIcons(); - /** - * Registers an event handler for an icon. - * - * @param [in] di Icon draw item - * @param [in] eventHandler Event handler function - */ - static void - RegisterEventHandler(const std::shared_ptr& di, - const std::function& eventHandler); - private: class Impl; diff --git a/scwx-qt/source/scwx/qt/gl/draw/geo_lines.cpp b/scwx-qt/source/scwx/qt/gl/draw/geo_lines.cpp index e35cca4f..d9f2c023 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/geo_lines.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/geo_lines.cpp @@ -3,7 +3,6 @@ #include #include #include -#include #include @@ -51,7 +50,6 @@ struct GeoLineDrawItem : types::EventHandler units::angle::degrees angle_ {}; std::string hoverText_ {}; GeoLines::HoverCallback hoverCallback_ {nullptr}; - size_t lineIndex_ {0}; }; class GeoLines::Impl @@ -89,10 +87,10 @@ public: void UpdateBuffers(); void UpdateModifiedLineBuffers(); void UpdateSingleBuffer(const std::shared_ptr& di, + std::size_t lineIndex, std::vector& linesBuffer, - std::vector& integerBuffer, - std::unordered_map, - LineHoverEntry>& hoverLines); + std::vector& integerBuffer, + std::vector& hoverLines); std::shared_ptr context_; @@ -114,10 +112,8 @@ public: std::vector newLinesBuffer_ {}; std::vector newIntegerBuffer_ {}; - std::unordered_map, LineHoverEntry> - currentHoverLines_ {}; - std::unordered_map, LineHoverEntry> - newHoverLines_ {}; + std::vector currentHoverLines_ {}; + std::vector newHoverLines_ {}; std::shared_ptr shaderProgram_; GLint uMVPMatrixLocation_; @@ -131,7 +127,7 @@ public: }; GeoLines::GeoLines(std::shared_ptr context) : - DrawItem(), p(std::make_unique(context)) + DrawItem(context->gl()), p(std::make_unique(context)) { } GeoLines::~GeoLines() = default; @@ -152,6 +148,8 @@ void GeoLines::set_thresholded(bool thresholded) void GeoLines::Initialize() { + gl::OpenGLFunctions& gl = p->context_->gl(); + p->shaderProgram_ = p->context_->GetShaderProgram( {{GL_VERTEX_SHADER, ":/gl/geo_texture2d.vert"}, {GL_GEOMETRY_SHADER, ":/gl/threshold.geom"}, @@ -166,86 +164,79 @@ void GeoLines::Initialize() p->uSelectedTimeLocation_ = p->shaderProgram_->GetUniformLocation("uSelectedTime"); - glGenVertexArrays(1, &p->vao_); - glGenBuffers(static_cast(p->vbo_.size()), p->vbo_.data()); + gl.glGenVertexArrays(1, &p->vao_); + gl.glGenBuffers(static_cast(p->vbo_.size()), p->vbo_.data()); - glBindVertexArray(p->vao_); - glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); - glBufferData(GL_ARRAY_BUFFER, - sizeof(float) * kLineBufferLength_, - nullptr, - GL_DYNAMIC_DRAW); - - // NOLINTBEGIN(modernize-use-nullptr) - // NOLINTBEGIN(performance-no-int-to-ptr) - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) + gl.glBindVertexArray(p->vao_); + gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); + gl.glBufferData(GL_ARRAY_BUFFER, + sizeof(float) * kLineBufferLength_, + nullptr, + GL_DYNAMIC_DRAW); // aLatLong - glVertexAttribPointer(0, - 2, - GL_FLOAT, - GL_FALSE, - kPointsPerVertex * sizeof(float), - static_cast(0)); - glEnableVertexAttribArray(0); + gl.glVertexAttribPointer(0, + 2, + GL_FLOAT, + GL_FALSE, + kPointsPerVertex * sizeof(float), + static_cast(0)); + gl.glEnableVertexAttribArray(0); // aXYOffset - glVertexAttribPointer(1, - 2, - GL_FLOAT, - GL_FALSE, - kPointsPerVertex * sizeof(float), - reinterpret_cast(2 * sizeof(float))); - glEnableVertexAttribArray(1); + gl.glVertexAttribPointer(1, + 2, + GL_FLOAT, + GL_FALSE, + kPointsPerVertex * sizeof(float), + reinterpret_cast(2 * sizeof(float))); + gl.glEnableVertexAttribArray(1); // aModulate - glVertexAttribPointer(3, - 4, - GL_FLOAT, - GL_FALSE, - kPointsPerVertex * sizeof(float), - reinterpret_cast(4 * sizeof(float))); - glEnableVertexAttribArray(3); + gl.glVertexAttribPointer(3, + 4, + GL_FLOAT, + GL_FALSE, + kPointsPerVertex * sizeof(float), + reinterpret_cast(4 * sizeof(float))); + gl.glEnableVertexAttribArray(3); // aAngle - glVertexAttribPointer(4, - 1, - GL_FLOAT, - GL_FALSE, - kPointsPerVertex * sizeof(float), - reinterpret_cast(8 * sizeof(float))); - glEnableVertexAttribArray(4); + gl.glVertexAttribPointer(4, + 1, + GL_FLOAT, + GL_FALSE, + kPointsPerVertex * sizeof(float), + reinterpret_cast(8 * sizeof(float))); + gl.glEnableVertexAttribArray(4); - glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); - glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); + gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); + gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); // aThreshold - glVertexAttribIPointer(5, // - 1, - GL_INT, - kIntegersPerVertex_ * sizeof(GLint), - static_cast(0)); - glEnableVertexAttribArray(5); + gl.glVertexAttribIPointer(5, // + 1, + GL_INT, + kIntegersPerVertex_ * sizeof(GLint), + static_cast(0)); + gl.glEnableVertexAttribArray(5); // aTimeRange - glVertexAttribIPointer(6, // - 2, - GL_INT, - kIntegersPerVertex_ * sizeof(GLint), - reinterpret_cast(1 * sizeof(GLint))); - glEnableVertexAttribArray(6); + gl.glVertexAttribIPointer(6, // + 2, + GL_INT, + kIntegersPerVertex_ * sizeof(GLint), + reinterpret_cast(1 * sizeof(GLint))); + gl.glEnableVertexAttribArray(6); // aDisplayed - glVertexAttribIPointer(7, - 1, - GL_INT, - kIntegersPerVertex_ * sizeof(GLint), - reinterpret_cast(3 * sizeof(GLint))); - glEnableVertexAttribArray(7); - - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - // NOLINTEND(performance-no-int-to-ptr) - // NOLINTEND(modernize-use-nullptr) + gl.glVertexAttribPointer(7, + 1, + GL_INT, + GL_FALSE, + kIntegersPerVertex_ * sizeof(GLint), + reinterpret_cast(3 * sizeof(float))); + gl.glEnableVertexAttribArray(7); p->dirty_ = true; } @@ -261,7 +252,9 @@ void GeoLines::Render(const QMapLibre::CustomLayerRenderParameters& params) if (p->newLineList_.size() > 0) { - glBindVertexArray(p->vao_); + gl::OpenGLFunctions& gl = p->context_->gl(); + + gl.glBindVertexArray(p->vao_); p->Update(); p->shaderProgram_->Use(); @@ -274,37 +267,39 @@ void GeoLines::Render(const QMapLibre::CustomLayerRenderParameters& params) // If thresholding is enabled, set the map distance units::length::nautical_miles mapDistance = util::maplibre::GetMapDistance(params); - glUniform1f(p->uMapDistanceLocation_, mapDistance.value()); + gl.glUniform1f(p->uMapDistanceLocation_, mapDistance.value()); } else { // If thresholding is disabled, set the map distance to 0 - glUniform1f(p->uMapDistanceLocation_, 0.0f); + gl.glUniform1f(p->uMapDistanceLocation_, 0.0f); } // Selected time std::chrono::system_clock::time_point selectedTime = (p->selectedTime_ == std::chrono::system_clock::time_point {}) ? - scwx::util::time::now() : + std::chrono::system_clock::now() : p->selectedTime_; - glUniform1i( + gl.glUniform1i( p->uSelectedTimeLocation_, static_cast(std::chrono::duration_cast( selectedTime.time_since_epoch()) .count())); // Draw icons - glDrawArrays(GL_TRIANGLES, - 0, - static_cast(p->currentLineList_.size() * - kVerticesPerRectangle)); + gl.glDrawArrays(GL_TRIANGLES, + 0, + static_cast(p->currentLineList_.size() * + kVerticesPerRectangle)); } } void GeoLines::Deinitialize() { - glDeleteVertexArrays(1, &p->vao_); - glDeleteBuffers(static_cast(p->vbo_.size()), p->vbo_.data()); + gl::OpenGLFunctions& gl = p->context_->gl(); + + gl.glDeleteVertexArrays(1, &p->vao_); + gl.glDeleteBuffers(static_cast(p->vbo_.size()), p->vbo_.data()); std::unique_lock lock {p->lineMutex_}; @@ -329,9 +324,7 @@ void GeoLines::StartLines() std::shared_ptr GeoLines::AddLine() { - auto& di = p->newLineList_.emplace_back(std::make_shared()); - di->lineIndex_ = p->newLineList_.size() - 1; - return di; + return p->newLineList_.emplace_back(std::make_shared()); } void GeoLines::SetLineLocation(const std::shared_ptr& di, @@ -478,7 +471,7 @@ void GeoLines::Impl::UpdateBuffers() // Update line buffer UpdateSingleBuffer( - di, newLinesBuffer_, newIntegerBuffer_, newHoverLines_); + di, i, newLinesBuffer_, newIntegerBuffer_, newHoverLines_); } // All lines have been updated @@ -496,15 +489,23 @@ void GeoLines::Impl::UpdateModifiedLineBuffers() // Update buffers for modified lines for (auto& di : dirtyLines_) { - // Check if modified line is in the current list - if (di->lineIndex_ >= currentLineList_.size() || - currentLineList_[di->lineIndex_] != di) + // Find modified line in the current list + auto it = + std::find(currentLineList_.cbegin(), currentLineList_.cend(), di); + + // Ignore invalid lines + if (it == currentLineList_.cend()) { continue; } - UpdateSingleBuffer( - di, currentLinesBuffer_, currentIntegerBuffer_, currentHoverLines_); + auto lineIndex = std::distance(currentLineList_.cbegin(), it); + + UpdateSingleBuffer(di, + lineIndex, + currentLinesBuffer_, + currentIntegerBuffer_, + currentHoverLines_); } // Clear list of modified lines @@ -517,10 +518,10 @@ void GeoLines::Impl::UpdateModifiedLineBuffers() void GeoLines::Impl::UpdateSingleBuffer( const std::shared_ptr& di, + std::size_t lineIndex, std::vector& lineBuffer, std::vector& integerBuffer, - std::unordered_map, LineHoverEntry>& - hoverLines) + std::vector& hoverLines) { // Threshold value units::length::nautical_miles threshold = di->threshold_; @@ -588,10 +589,10 @@ void GeoLines::Impl::UpdateSingleBuffer( // Buffer position data auto lineBufferPosition = lineBuffer.end(); - auto lineBufferOffset = di->lineIndex_ * kLineBufferLength_; + auto lineBufferOffset = lineIndex * kLineBufferLength_; auto integerBufferPosition = integerBuffer.end(); - auto integerBufferOffset = di->lineIndex_ * kIntegerBufferLength_; + auto integerBufferOffset = lineIndex * kIntegerBufferLength_; if (lineBufferOffset < lineBuffer.size()) { @@ -620,7 +621,9 @@ void GeoLines::Impl::UpdateSingleBuffer( std::copy(integerData.begin(), integerData.end(), integerBufferPosition); } - auto hoverIt = hoverLines.find(di); + auto hoverIt = std::find_if(hoverLines.begin(), + hoverLines.end(), + [&di](auto& entry) { return entry.di_ == di; }); if (di->visible_ && (!di->hoverText_.empty() || di->hoverCallback_ != nullptr || di->event_ != nullptr)) @@ -642,23 +645,17 @@ void GeoLines::Impl::UpdateSingleBuffer( if (hoverIt == hoverLines.end()) { - hoverLines.emplace(di, - LineHoverEntry {.di_ = di, - .p1_ = sc1, - .p2_ = sc2, - .otl_ = otl, - .otr_ = otr, - .obl_ = obl, - .obr_ = obr}); + hoverLines.emplace_back( + LineHoverEntry {di, sc1, sc2, otl, otr, obl, obr}); } else { - hoverIt->second.p1_ = sc1; - hoverIt->second.p2_ = sc2; - hoverIt->second.otl_ = otl; - hoverIt->second.otr_ = otr; - hoverIt->second.obl_ = obl; - hoverIt->second.obr_ = obr; + hoverIt->p1_ = sc1; + hoverIt->p2_ = sc2; + hoverIt->otl_ = otl; + hoverIt->otr_ = otr; + hoverIt->obl_ = obl; + hoverIt->obr_ = obr; } } else if (hoverIt != hoverLines.end()) @@ -674,21 +671,21 @@ void GeoLines::Impl::Update() // If the lines have been updated if (dirty_) { + gl::OpenGLFunctions& gl = context_->gl(); + // Buffer lines data - glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]); - glBufferData( - GL_ARRAY_BUFFER, - static_cast(sizeof(float) * currentLinesBuffer_.size()), - currentLinesBuffer_.data(), - GL_DYNAMIC_DRAW); + gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]); + gl.glBufferData(GL_ARRAY_BUFFER, + sizeof(float) * currentLinesBuffer_.size(), + currentLinesBuffer_.data(), + GL_DYNAMIC_DRAW); // Buffer threshold data - glBindBuffer(GL_ARRAY_BUFFER, vbo_[1]); - glBufferData( - GL_ARRAY_BUFFER, - static_cast(sizeof(GLint) * currentIntegerBuffer_.size()), - currentIntegerBuffer_.data(), - GL_DYNAMIC_DRAW); + gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[1]); + gl.glBufferData(GL_ARRAY_BUFFER, + sizeof(GLint) * currentIntegerBuffer_.size(), + currentIntegerBuffer_.data(), + GL_DYNAMIC_DRAW); } dirty_ = false; @@ -724,18 +721,16 @@ bool GeoLines::RunMousePicking( // If no time has been selected, use the current time std::chrono::system_clock::time_point selectedTime = (p->selectedTime_ == std::chrono::system_clock::time_point {}) ? - scwx::util::time::now() : + std::chrono::system_clock::now() : p->selectedTime_; // For each pickable line auto it = std::find_if( std::execution::par_unseq, - p->currentHoverLines_.cbegin(), - p->currentHoverLines_.cend(), - [&mapDistance, &selectedTime, &mapMatrix, &mouseCoords]( - const auto& lineIt) + p->currentHoverLines_.rbegin(), + p->currentHoverLines_.rend(), + [&mapDistance, &selectedTime, &mapMatrix, &mouseCoords](const auto& line) { - const auto& line = lineIt.second; if (( // Placefile is thresholded mapDistance > units::length::meters {0.0} && @@ -745,10 +740,8 @@ bool GeoLines::RunMousePicking( units::length::nautical_miles {line.di_->threshold_} .value())) < 999 && - // Map distance is beyond/within the threshold - line.di_->threshold_ < mapDistance && - (line.di_->threshold_.value() >= 0.0 || - -(line.di_->threshold_) > mapDistance)) || + // Map distance is beyond the threshold + line.di_->threshold_ < mapDistance) || ( // Line has a start time @@ -791,24 +784,24 @@ bool GeoLines::RunMousePicking( return util::maplibre::IsPointInPolygon({tl, bl, br, tr}, mouseCoords); }); - if (it != p->currentHoverLines_.cend()) + if (it != p->currentHoverLines_.crend()) { itemPicked = true; - if (!it->second.di_->hoverText_.empty()) + if (!it->di_->hoverText_.empty()) { // Show tooltip - util::tooltip::Show(it->second.di_->hoverText_, mouseGlobalPos); + util::tooltip::Show(it->di_->hoverText_, mouseGlobalPos); } - else if (it->second.di_->hoverCallback_ != nullptr) + else if (it->di_->hoverCallback_ != nullptr) { - it->second.di_->hoverCallback_(it->second.di_, mouseGlobalPos); + it->di_->hoverCallback_(it->di_, mouseGlobalPos); } - if (it->second.di_->event_ != nullptr) + if (it->di_->event_ != nullptr) { // Register event handler - eventHandler = it->second.di_; + eventHandler = it->di_; } } diff --git a/scwx-qt/source/scwx/qt/gl/draw/geo_lines.hpp b/scwx-qt/source/scwx/qt/gl/draw/geo_lines.hpp index d6727110..b7b792d0 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/geo_lines.hpp +++ b/scwx-qt/source/scwx/qt/gl/draw/geo_lines.hpp @@ -19,8 +19,9 @@ struct GeoLineDrawItem; class GeoLines : public DrawItem { public: - using HoverCallback = std::function&, const QPointF&)>; + typedef std::function&, + const QPointF&)> + HoverCallback; explicit GeoLines(std::shared_ptr context); ~GeoLines(); diff --git a/scwx-qt/source/scwx/qt/gl/draw/icons.cpp b/scwx-qt/source/scwx/qt/gl/draw/icons.cpp index b72f4443..473b8a79 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/icons.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/icons.cpp @@ -21,11 +21,12 @@ namespace draw static const std::string logPrefix_ = "scwx::qt::gl::draw::icons"; static const auto logger_ = scwx::util::Logger::Create(logPrefix_); -static constexpr std::size_t kNumRectangles = 1; -static constexpr std::size_t kNumTriangles = kNumRectangles * 2; -static constexpr std::size_t kVerticesPerTriangle = 3; -static constexpr std::size_t kPointsPerVertex = 10; -static constexpr std::size_t kPointsPerTexCoord = 3; +static constexpr std::size_t kNumRectangles = 1; +static constexpr std::size_t kNumTriangles = kNumRectangles * 2; +static constexpr std::size_t kVerticesPerTriangle = 3; +static constexpr std::size_t kVerticesPerRectangle = kVerticesPerTriangle * 2; +static constexpr std::size_t kPointsPerVertex = 10; +static constexpr std::size_t kPointsPerTexCoord = 3; static constexpr std::size_t kIconBufferLength = kNumTriangles * kVerticesPerTriangle * kPointsPerVertex; static constexpr std::size_t kTextureBufferLength = @@ -116,7 +117,7 @@ public: }; Icons::Icons(const std::shared_ptr& context) : - DrawItem(), p(std::make_unique(context)) + DrawItem(context->gl()), p(std::make_unique(context)) { } Icons::~Icons() = default; @@ -126,6 +127,8 @@ Icons& Icons::operator=(Icons&&) noexcept = default; void Icons::Initialize() { + gl::OpenGLFunctions& gl = p->context_->gl(); + p->shaderProgram_ = p->context_->GetShaderProgram( {{GL_VERTEX_SHADER, ":/gl/texture2d_array.vert"}, {GL_GEOMETRY_SHADER, ":/gl/threshold.geom"}, @@ -133,77 +136,69 @@ void Icons::Initialize() p->uMVPMatrixLocation_ = p->shaderProgram_->GetUniformLocation("uMVPMatrix"); - glGenVertexArrays(1, &p->vao_); - glGenBuffers(static_cast(p->vbo_.size()), p->vbo_.data()); + gl.glGenVertexArrays(1, &p->vao_); + gl.glGenBuffers(static_cast(p->vbo_.size()), p->vbo_.data()); - glBindVertexArray(p->vao_); - glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); - glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); - - // NOLINTBEGIN(modernize-use-nullptr) - // NOLINTBEGIN(performance-no-int-to-ptr) - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) + gl.glBindVertexArray(p->vao_); + gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); + gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); // aVertex - glVertexAttribPointer(0, - 2, - GL_FLOAT, - GL_FALSE, - kPointsPerVertex * sizeof(float), - reinterpret_cast(0)); - glEnableVertexAttribArray(0); + gl.glVertexAttribPointer(0, + 2, + GL_FLOAT, + GL_FALSE, + kPointsPerVertex * sizeof(float), + reinterpret_cast(0)); + gl.glEnableVertexAttribArray(0); // aXYOffset - glVertexAttribPointer(1, - 2, - GL_FLOAT, - GL_FALSE, - kPointsPerVertex * sizeof(float), - reinterpret_cast(2 * sizeof(float))); - glEnableVertexAttribArray(1); + gl.glVertexAttribPointer(1, + 2, + GL_FLOAT, + GL_FALSE, + kPointsPerVertex * sizeof(float), + reinterpret_cast(2 * sizeof(float))); + gl.glEnableVertexAttribArray(1); // aModulate - glVertexAttribPointer(3, - 4, - GL_FLOAT, - GL_FALSE, - kPointsPerVertex * sizeof(float), - reinterpret_cast(4 * sizeof(float))); - glEnableVertexAttribArray(3); + gl.glVertexAttribPointer(3, + 4, + GL_FLOAT, + GL_FALSE, + kPointsPerVertex * sizeof(float), + reinterpret_cast(4 * sizeof(float))); + gl.glEnableVertexAttribArray(3); // aAngle - glVertexAttribPointer(4, - 1, - GL_FLOAT, - GL_FALSE, - kPointsPerVertex * sizeof(float), - reinterpret_cast(8 * sizeof(float))); - glEnableVertexAttribArray(4); + gl.glVertexAttribPointer(4, + 1, + GL_FLOAT, + GL_FALSE, + kPointsPerVertex * sizeof(float), + reinterpret_cast(8 * sizeof(float))); + gl.glEnableVertexAttribArray(4); // aDisplayed - glVertexAttribPointer(5, - 1, - GL_FLOAT, - GL_FALSE, - kPointsPerVertex * sizeof(float), - reinterpret_cast(9 * sizeof(float))); - glEnableVertexAttribArray(5); + gl.glVertexAttribPointer(5, + 1, + GL_FLOAT, + GL_FALSE, + kPointsPerVertex * sizeof(float), + reinterpret_cast(9 * sizeof(float))); + gl.glEnableVertexAttribArray(5); - glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); - glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); + gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); + gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); // aTexCoord - glVertexAttribPointer(2, - 3, - GL_FLOAT, - GL_FALSE, - kPointsPerTexCoord * sizeof(float), - static_cast(0)); - glEnableVertexAttribArray(2); - - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - // NOLINTEND(performance-no-int-to-ptr) - // NOLINTEND(modernize-use-nullptr) + gl.glVertexAttribPointer(2, + 3, + GL_FLOAT, + GL_FALSE, + kPointsPerTexCoord * sizeof(float), + static_cast(0)); + gl.glEnableVertexAttribArray(2); p->dirty_ = true; } @@ -225,25 +220,29 @@ void Icons::Render(const QMapLibre::CustomLayerRenderParameters& params, if (!p->currentIconList_.empty()) { - glBindVertexArray(p->vao_); + gl::OpenGLFunctions& gl = p->context_->gl(); + + gl.glBindVertexArray(p->vao_); p->Update(textureAtlasChanged); p->shaderProgram_->Use(); UseDefaultProjection(params, p->uMVPMatrixLocation_); // Interpolate texture coordinates - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Draw icons - glDrawArrays(GL_TRIANGLES, 0, p->numVertices_); + gl.glDrawArrays(GL_TRIANGLES, 0, p->numVertices_); } } void Icons::Deinitialize() { - glDeleteVertexArrays(1, &p->vao_); - glDeleteBuffers(static_cast(p->vbo_.size()), p->vbo_.data()); + gl::OpenGLFunctions& gl = p->context_->gl(); + + gl.glDeleteVertexArrays(1, &p->vao_); + gl.glDeleteBuffers(static_cast(p->vbo_.size()), p->vbo_.data()); std::unique_lock lock {p->iconMutex_}; @@ -681,6 +680,8 @@ void Icons::Impl::UpdateModifiedIconBuffers() void Icons::Impl::Update(bool textureAtlasChanged) { + gl::OpenGLFunctions& gl = context_->gl(); + UpdateModifiedIconBuffers(); // If the texture atlas has changed @@ -696,12 +697,11 @@ void Icons::Impl::Update(bool textureAtlasChanged) UpdateTextureBuffer(); // Buffer texture data - glBindBuffer(GL_ARRAY_BUFFER, vbo_[1]); - glBufferData( - GL_ARRAY_BUFFER, - static_cast(sizeof(float) * textureBuffer_.size()), - textureBuffer_.data(), - GL_DYNAMIC_DRAW); + gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[1]); + gl.glBufferData(GL_ARRAY_BUFFER, + sizeof(float) * textureBuffer_.size(), + textureBuffer_.data(), + GL_DYNAMIC_DRAW); lastTextureAtlasChanged_ = false; } @@ -710,12 +710,11 @@ void Icons::Impl::Update(bool textureAtlasChanged) if (dirty_) { // Buffer vertex data - glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]); - glBufferData( - GL_ARRAY_BUFFER, - static_cast(sizeof(float) * currentIconBuffer_.size()), - currentIconBuffer_.data(), - GL_DYNAMIC_DRAW); + gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]); + gl.glBufferData(GL_ARRAY_BUFFER, + sizeof(float) * currentIconBuffer_.size(), + currentIconBuffer_.data(), + GL_DYNAMIC_DRAW); numVertices_ = static_cast(currentIconBuffer_.size() / kPointsPerVertex); @@ -742,7 +741,7 @@ bool Icons::RunMousePicking( // For each pickable icon auto it = std::find_if( // - std::execution::par, + std::execution::par_unseq, p->currentHoverIcons_.crbegin(), p->currentHoverIcons_.crend(), [&mouseLocalCoords](const auto& icon) diff --git a/scwx-qt/source/scwx/qt/gl/draw/linked_vectors.cpp b/scwx-qt/source/scwx/qt/gl/draw/linked_vectors.cpp index dfc3dd07..3dbab117 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/linked_vectors.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/linked_vectors.cpp @@ -63,12 +63,14 @@ class LinkedVectors::Impl { public: explicit Impl(std::shared_ptr context) : - geoLines_ {std::make_shared(context)} + context_ {context}, geoLines_ {std::make_shared(context)} { } ~Impl() {} + std::shared_ptr context_; + bool borderEnabled_ {true}; bool visible_ {true}; @@ -77,7 +79,7 @@ public: }; LinkedVectors::LinkedVectors(std::shared_ptr context) : - DrawItem(), p(std::make_unique(context)) + DrawItem(context->gl()), p(std::make_unique(context)) { } LinkedVectors::~LinkedVectors() = default; diff --git a/scwx-qt/source/scwx/qt/gl/draw/placefile_icons.cpp b/scwx-qt/source/scwx/qt/gl/draw/placefile_icons.cpp index 21dd25c2..abc852f8 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/placefile_icons.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/placefile_icons.cpp @@ -3,7 +3,6 @@ #include #include #include -#include #include @@ -141,7 +140,7 @@ public: }; PlacefileIcons::PlacefileIcons(const std::shared_ptr& context) : - DrawItem(), p(std::make_unique(context)) + DrawItem(context->gl()), p(std::make_unique(context)) { } PlacefileIcons::~PlacefileIcons() = default; @@ -162,6 +161,9 @@ void PlacefileIcons::set_thresholded(bool thresholded) void PlacefileIcons::Initialize() { + gl::OpenGLFunctions& gl = p->context_->gl(); + auto& gl30 = p->context_->gl30(); + p->shaderProgram_ = p->context_->GetShaderProgram( {{GL_VERTEX_SHADER, ":/gl/geo_texture2d.vert"}, {GL_GEOMETRY_SHADER, ":/gl/threshold.geom"}, @@ -176,90 +178,82 @@ void PlacefileIcons::Initialize() p->uSelectedTimeLocation_ = p->shaderProgram_->GetUniformLocation("uSelectedTime"); - glGenVertexArrays(1, &p->vao_); - glGenBuffers(static_cast(p->vbo_.size()), p->vbo_.data()); + gl.glGenVertexArrays(1, &p->vao_); + gl.glGenBuffers(static_cast(p->vbo_.size()), p->vbo_.data()); - glBindVertexArray(p->vao_); - glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); - glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); - - // NOLINTBEGIN(modernize-use-nullptr) - // NOLINTBEGIN(performance-no-int-to-ptr) - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) + gl.glBindVertexArray(p->vao_); + gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); + gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); // aLatLong - glVertexAttribPointer(0, - 2, - GL_FLOAT, - GL_FALSE, - kPointsPerVertex * sizeof(float), - static_cast(0)); - glEnableVertexAttribArray(0); + gl.glVertexAttribPointer(0, + 2, + GL_FLOAT, + GL_FALSE, + kPointsPerVertex * sizeof(float), + static_cast(0)); + gl.glEnableVertexAttribArray(0); // aXYOffset - glVertexAttribPointer(1, - 2, - GL_FLOAT, - GL_FALSE, - kPointsPerVertex * sizeof(float), - reinterpret_cast(2 * sizeof(float))); - glEnableVertexAttribArray(1); + gl.glVertexAttribPointer(1, + 2, + GL_FLOAT, + GL_FALSE, + kPointsPerVertex * sizeof(float), + reinterpret_cast(2 * sizeof(float))); + gl.glEnableVertexAttribArray(1); // aModulate - glVertexAttribPointer(3, - 4, - GL_FLOAT, - GL_FALSE, - kPointsPerVertex * sizeof(float), - reinterpret_cast(4 * sizeof(float))); - glEnableVertexAttribArray(3); + gl.glVertexAttribPointer(3, + 4, + GL_FLOAT, + GL_FALSE, + kPointsPerVertex * sizeof(float), + reinterpret_cast(4 * sizeof(float))); + gl.glEnableVertexAttribArray(3); // aAngle - glVertexAttribPointer(4, - 1, - GL_FLOAT, - GL_FALSE, - kPointsPerVertex * sizeof(float), - reinterpret_cast(8 * sizeof(float))); - glEnableVertexAttribArray(4); + gl.glVertexAttribPointer(4, + 1, + GL_FLOAT, + GL_FALSE, + kPointsPerVertex * sizeof(float), + reinterpret_cast(8 * sizeof(float))); + gl.glEnableVertexAttribArray(4); - glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); - glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); + gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); + gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); // aTexCoord - glVertexAttribPointer(2, - 3, - GL_FLOAT, - GL_FALSE, - kPointsPerTexCoord * sizeof(float), - static_cast(0)); - glEnableVertexAttribArray(2); + gl.glVertexAttribPointer(2, + 3, + GL_FLOAT, + GL_FALSE, + kPointsPerTexCoord * sizeof(float), + static_cast(0)); + gl.glEnableVertexAttribArray(2); - glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[2]); - glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); + gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[2]); + gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); // aThreshold - glVertexAttribIPointer(5, // - 1, - GL_INT, - 0, - static_cast(0)); - glEnableVertexAttribArray(5); + gl.glVertexAttribIPointer(5, // + 1, + GL_INT, + 0, + static_cast(0)); + gl.glEnableVertexAttribArray(5); // aTimeRange - glVertexAttribIPointer(6, // - 2, - GL_INT, - kIntegersPerVertex_ * sizeof(GLint), - reinterpret_cast(1 * sizeof(GLint))); - glEnableVertexAttribArray(6); + gl.glVertexAttribIPointer(6, // + 2, + GL_INT, + kIntegersPerVertex_ * sizeof(GLint), + reinterpret_cast(1 * sizeof(GLint))); + gl.glEnableVertexAttribArray(6); // aDisplayed - glVertexAttribI1i(7, 1); - - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - // NOLINTEND(performance-no-int-to-ptr) - // NOLINTEND(modernize-use-nullptr) + gl30.glVertexAttribI1i(7, 1); p->dirty_ = true; } @@ -272,7 +266,9 @@ void PlacefileIcons::Render( if (!p->currentIconList_.empty()) { - glBindVertexArray(p->vao_); + gl::OpenGLFunctions& gl = p->context_->gl(); + + gl.glBindVertexArray(p->vao_); p->Update(textureAtlasChanged); p->shaderProgram_->Use(); @@ -285,38 +281,40 @@ void PlacefileIcons::Render( // If thresholding is enabled, set the map distance units::length::nautical_miles mapDistance = util::maplibre::GetMapDistance(params); - glUniform1f(p->uMapDistanceLocation_, mapDistance.value()); + gl.glUniform1f(p->uMapDistanceLocation_, mapDistance.value()); } else { // If thresholding is disabled, set the map distance to 0 - glUniform1f(p->uMapDistanceLocation_, 0.0f); + gl.glUniform1f(p->uMapDistanceLocation_, 0.0f); } // Selected time std::chrono::system_clock::time_point selectedTime = (p->selectedTime_ == std::chrono::system_clock::time_point {}) ? - scwx::util::time::now() : + std::chrono::system_clock::now() : p->selectedTime_; - glUniform1i( + gl.glUniform1i( p->uSelectedTimeLocation_, static_cast(std::chrono::duration_cast( selectedTime.time_since_epoch()) .count())); // Interpolate texture coordinates - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Draw icons - glDrawArrays(GL_TRIANGLES, 0, p->numVertices_); + gl.glDrawArrays(GL_TRIANGLES, 0, p->numVertices_); } } void PlacefileIcons::Deinitialize() { - glDeleteVertexArrays(1, &p->vao_); - glDeleteBuffers(static_cast(p->vbo_.size()), p->vbo_.data()); + gl::OpenGLFunctions& gl = p->context_->gl(); + + gl.glDeleteVertexArrays(1, &p->vao_); + gl.glDeleteBuffers(static_cast(p->vbo_.size()), p->vbo_.data()); std::unique_lock lock {p->iconMutex_}; @@ -644,6 +642,8 @@ void PlacefileIcons::Impl::UpdateTextureBuffer() void PlacefileIcons::Impl::Update(bool textureAtlasChanged) { + gl::OpenGLFunctions& gl = context_->gl(); + // If the texture atlas has changed if (dirty_ || textureAtlasChanged) { @@ -657,32 +657,29 @@ void PlacefileIcons::Impl::Update(bool textureAtlasChanged) UpdateTextureBuffer(); // Buffer texture data - glBindBuffer(GL_ARRAY_BUFFER, vbo_[1]); - glBufferData( - GL_ARRAY_BUFFER, - static_cast(sizeof(float) * textureBuffer_.size()), - textureBuffer_.data(), - GL_DYNAMIC_DRAW); + gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[1]); + gl.glBufferData(GL_ARRAY_BUFFER, + sizeof(float) * textureBuffer_.size(), + textureBuffer_.data(), + GL_DYNAMIC_DRAW); } // If buffers need updating if (dirty_) { // Buffer vertex data - glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]); - glBufferData( - GL_ARRAY_BUFFER, - static_cast(sizeof(float) * currentIconBuffer_.size()), - currentIconBuffer_.data(), - GL_DYNAMIC_DRAW); + gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]); + gl.glBufferData(GL_ARRAY_BUFFER, + sizeof(float) * currentIconBuffer_.size(), + currentIconBuffer_.data(), + GL_DYNAMIC_DRAW); // Buffer threshold data - glBindBuffer(GL_ARRAY_BUFFER, vbo_[2]); - glBufferData( - GL_ARRAY_BUFFER, - static_cast(sizeof(GLint) * currentIntegerBuffer_.size()), - currentIntegerBuffer_.data(), - GL_DYNAMIC_DRAW); + gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[2]); + gl.glBufferData(GL_ARRAY_BUFFER, + sizeof(GLint) * currentIntegerBuffer_.size(), + currentIntegerBuffer_.data(), + GL_DYNAMIC_DRAW); numVertices_ = static_cast(currentIconBuffer_.size() / kPointsPerVertex); @@ -721,7 +718,7 @@ bool PlacefileIcons::RunMousePicking( // If no time has been selected, use the current time std::chrono::system_clock::time_point selectedTime = (p->selectedTime_ == std::chrono::system_clock::time_point {}) ? - scwx::util::time::now() : + std::chrono::system_clock::now() : p->selectedTime_; // For each pickable icon @@ -740,10 +737,8 @@ bool PlacefileIcons::RunMousePicking( units::length::nautical_miles {icon.di_->threshold_} .value())) < 999 && - // Map distance is beyond/within the threshold - icon.di_->threshold_ < mapDistance && - (icon.di_->threshold_.value() >= 0.0 || - -(icon.di_->threshold_) > mapDistance)) || + // Map distance is beyond the threshold + icon.di_->threshold_ < mapDistance) || ( // Line has a start time diff --git a/scwx-qt/source/scwx/qt/gl/draw/placefile_images.cpp b/scwx-qt/source/scwx/qt/gl/draw/placefile_images.cpp index b14a2723..aafaef8d 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/placefile_images.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/placefile_images.cpp @@ -2,7 +2,6 @@ #include #include #include -#include #include #include @@ -118,7 +117,7 @@ public: }; PlacefileImages::PlacefileImages(const std::shared_ptr& context) : - DrawItem(), p(std::make_unique(context)) + DrawItem(context->gl()), p(std::make_unique(context)) { } PlacefileImages::~PlacefileImages() = default; @@ -140,6 +139,9 @@ void PlacefileImages::set_thresholded(bool thresholded) void PlacefileImages::Initialize() { + gl::OpenGLFunctions& gl = p->context_->gl(); + auto& gl30 = p->context_->gl30(); + p->shaderProgram_ = p->context_->GetShaderProgram( {{GL_VERTEX_SHADER, ":/gl/geo_texture2d.vert"}, {GL_GEOMETRY_SHADER, ":/gl/threshold.geom"}, @@ -154,81 +156,73 @@ void PlacefileImages::Initialize() p->uSelectedTimeLocation_ = p->shaderProgram_->GetUniformLocation("uSelectedTime"); - glGenVertexArrays(1, &p->vao_); - glGenBuffers(static_cast(p->vbo_.size()), p->vbo_.data()); + gl.glGenVertexArrays(1, &p->vao_); + gl.glGenBuffers(static_cast(p->vbo_.size()), p->vbo_.data()); - glBindVertexArray(p->vao_); - glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); - glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); - - // NOLINTBEGIN(modernize-use-nullptr) - // NOLINTBEGIN(performance-no-int-to-ptr) - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) + gl.glBindVertexArray(p->vao_); + gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); + gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); // aLatLong - glVertexAttribPointer(0, - 2, - GL_FLOAT, - GL_FALSE, - kPointsPerVertex * sizeof(float), - static_cast(0)); - glEnableVertexAttribArray(0); + gl.glVertexAttribPointer(0, + 2, + GL_FLOAT, + GL_FALSE, + kPointsPerVertex * sizeof(float), + static_cast(0)); + gl.glEnableVertexAttribArray(0); // aXYOffset - glVertexAttribPointer(1, - 2, - GL_FLOAT, - GL_FALSE, - kPointsPerVertex * sizeof(float), - reinterpret_cast(2 * sizeof(float))); - glEnableVertexAttribArray(1); + gl.glVertexAttribPointer(1, + 2, + GL_FLOAT, + GL_FALSE, + kPointsPerVertex * sizeof(float), + reinterpret_cast(2 * sizeof(float))); + gl.glEnableVertexAttribArray(1); // aModulate - glVertexAttribPointer(3, - 4, - GL_FLOAT, - GL_FALSE, - kPointsPerVertex * sizeof(float), - reinterpret_cast(4 * sizeof(float))); - glEnableVertexAttribArray(3); + gl.glVertexAttribPointer(3, + 4, + GL_FLOAT, + GL_FALSE, + kPointsPerVertex * sizeof(float), + reinterpret_cast(4 * sizeof(float))); + gl.glEnableVertexAttribArray(3); - glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); - glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); + gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); + gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); // aTexCoord - glVertexAttribPointer(2, - 3, - GL_FLOAT, - GL_FALSE, - kPointsPerTexCoord * sizeof(float), - static_cast(0)); - glEnableVertexAttribArray(2); + gl.glVertexAttribPointer(2, + 3, + GL_FLOAT, + GL_FALSE, + kPointsPerTexCoord * sizeof(float), + static_cast(0)); + gl.glEnableVertexAttribArray(2); - glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[2]); - glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); + gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[2]); + gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); // aThreshold - glVertexAttribIPointer(5, // - 1, - GL_INT, - kIntegersPerVertex_ * sizeof(GLint), - static_cast(0)); - glEnableVertexAttribArray(5); + gl.glVertexAttribIPointer(5, // + 1, + GL_INT, + kIntegersPerVertex_ * sizeof(GLint), + static_cast(0)); + gl.glEnableVertexAttribArray(5); // aTimeRange - glVertexAttribIPointer(6, // - 2, - GL_INT, - kIntegersPerVertex_ * sizeof(GLint), - reinterpret_cast(1 * sizeof(GLint))); - glEnableVertexAttribArray(6); + gl.glVertexAttribIPointer(6, // + 2, + GL_INT, + kIntegersPerVertex_ * sizeof(GLint), + reinterpret_cast(1 * sizeof(GLint))); + gl.glEnableVertexAttribArray(6); // aDisplayed - glVertexAttribI1i(7, 1); - - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - // NOLINTEND(performance-no-int-to-ptr) - // NOLINTEND(modernize-use-nullptr) + gl30.glVertexAttribI1i(7, 1); p->dirty_ = true; } @@ -241,7 +235,9 @@ void PlacefileImages::Render( if (!p->currentImageList_.empty()) { - glBindVertexArray(p->vao_); + gl::OpenGLFunctions& gl = p->context_->gl(); + + gl.glBindVertexArray(p->vao_); p->Update(textureAtlasChanged); p->shaderProgram_->Use(); @@ -254,38 +250,40 @@ void PlacefileImages::Render( // If thresholding is enabled, set the map distance units::length::nautical_miles mapDistance = util::maplibre::GetMapDistance(params); - glUniform1f(p->uMapDistanceLocation_, mapDistance.value()); + gl.glUniform1f(p->uMapDistanceLocation_, mapDistance.value()); } else { // If thresholding is disabled, set the map distance to 0 - glUniform1f(p->uMapDistanceLocation_, 0.0f); + gl.glUniform1f(p->uMapDistanceLocation_, 0.0f); } // Selected time std::chrono::system_clock::time_point selectedTime = (p->selectedTime_ == std::chrono::system_clock::time_point {}) ? - scwx::util::time::now() : + std::chrono::system_clock::now() : p->selectedTime_; - glUniform1i( + gl.glUniform1i( p->uSelectedTimeLocation_, static_cast(std::chrono::duration_cast( selectedTime.time_since_epoch()) .count())); // Interpolate texture coordinates - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Draw images - glDrawArrays(GL_TRIANGLES, 0, p->numVertices_); + gl.glDrawArrays(GL_TRIANGLES, 0, p->numVertices_); } } void PlacefileImages::Deinitialize() { - glDeleteVertexArrays(1, &p->vao_); - glDeleteBuffers(static_cast(p->vbo_.size()), p->vbo_.data()); + gl::OpenGLFunctions& gl = p->context_->gl(); + + gl.glDeleteVertexArrays(1, &p->vao_); + gl.glDeleteBuffers(static_cast(p->vbo_.size()), p->vbo_.data()); std::unique_lock lock {p->imageMutex_}; @@ -441,6 +439,8 @@ void PlacefileImages::Impl::UpdateTextureBuffer() void PlacefileImages::Impl::Update(bool textureAtlasChanged) { + gl::OpenGLFunctions& gl = context_->gl(); + // If the texture atlas has changed if (dirty_ || textureAtlasChanged) { @@ -454,32 +454,29 @@ void PlacefileImages::Impl::Update(bool textureAtlasChanged) UpdateTextureBuffer(); // Buffer texture data - glBindBuffer(GL_ARRAY_BUFFER, vbo_[1]); - glBufferData( - GL_ARRAY_BUFFER, - static_cast(sizeof(float) * textureBuffer_.size()), - textureBuffer_.data(), - GL_DYNAMIC_DRAW); + gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[1]); + gl.glBufferData(GL_ARRAY_BUFFER, + sizeof(float) * textureBuffer_.size(), + textureBuffer_.data(), + GL_DYNAMIC_DRAW); } // If buffers need updating if (dirty_) { // Buffer vertex data - glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]); - glBufferData( - GL_ARRAY_BUFFER, - static_cast(sizeof(float) * currentImageBuffer_.size()), - currentImageBuffer_.data(), - GL_DYNAMIC_DRAW); + gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]); + gl.glBufferData(GL_ARRAY_BUFFER, + sizeof(float) * currentImageBuffer_.size(), + currentImageBuffer_.data(), + GL_DYNAMIC_DRAW); // Buffer threshold data - glBindBuffer(GL_ARRAY_BUFFER, vbo_[2]); - glBufferData( - GL_ARRAY_BUFFER, - static_cast(sizeof(GLint) * currentIntegerBuffer_.size()), - currentIntegerBuffer_.data(), - GL_DYNAMIC_DRAW); + gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[2]); + gl.glBufferData(GL_ARRAY_BUFFER, + sizeof(GLint) * currentIntegerBuffer_.size(), + currentIntegerBuffer_.data(), + GL_DYNAMIC_DRAW); numVertices_ = static_cast(currentImageBuffer_.size() / kPointsPerVertex); diff --git a/scwx-qt/source/scwx/qt/gl/draw/placefile_lines.cpp b/scwx-qt/source/scwx/qt/gl/draw/placefile_lines.cpp index b908389c..8fdce9f1 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/placefile_lines.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/placefile_lines.cpp @@ -3,7 +3,6 @@ #include #include #include -#include #include @@ -19,9 +18,13 @@ namespace draw static const std::string logPrefix_ = "scwx::qt::gl::draw::placefile_lines"; static const auto logger_ = scwx::util::Logger::Create(logPrefix_); +static constexpr std::size_t kNumRectangles = 1; +static constexpr std::size_t kNumTriangles = kNumRectangles * 2; static constexpr std::size_t kVerticesPerTriangle = 3; static constexpr std::size_t kVerticesPerRectangle = kVerticesPerTriangle * 2; static constexpr std::size_t kPointsPerVertex = 9; +static constexpr std::size_t kBufferLength = + kNumTriangles * kVerticesPerTriangle * kPointsPerVertex; // Threshold, start time, end time static constexpr std::size_t kIntegersPerVertex_ = 3; @@ -107,7 +110,7 @@ public: }; PlacefileLines::PlacefileLines(const std::shared_ptr& context) : - DrawItem(), p(std::make_unique(context)) + DrawItem(context->gl()), p(std::make_unique(context)) { } PlacefileLines::~PlacefileLines() = default; @@ -128,6 +131,9 @@ void PlacefileLines::set_thresholded(bool thresholded) void PlacefileLines::Initialize() { + gl::OpenGLFunctions& gl = p->context_->gl(); + auto& gl30 = p->context_->gl30(); + p->shaderProgram_ = p->context_->GetShaderProgram( {{GL_VERTEX_SHADER, ":/gl/geo_texture2d.vert"}, {GL_GEOMETRY_SHADER, ":/gl/threshold.geom"}, @@ -142,78 +148,70 @@ void PlacefileLines::Initialize() p->uSelectedTimeLocation_ = p->shaderProgram_->GetUniformLocation("uSelectedTime"); - glGenVertexArrays(1, &p->vao_); - glGenBuffers(2, p->vbo_.data()); + gl.glGenVertexArrays(1, &p->vao_); + gl.glGenBuffers(2, p->vbo_.data()); - glBindVertexArray(p->vao_); - glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); - glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); - - // NOLINTBEGIN(modernize-use-nullptr) - // NOLINTBEGIN(performance-no-int-to-ptr) - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) + gl.glBindVertexArray(p->vao_); + gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); + gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); // aLatLong - glVertexAttribPointer(0, - 2, - GL_FLOAT, - GL_FALSE, - kPointsPerVertex * sizeof(float), - static_cast(0)); - glEnableVertexAttribArray(0); + gl.glVertexAttribPointer(0, + 2, + GL_FLOAT, + GL_FALSE, + kPointsPerVertex * sizeof(float), + static_cast(0)); + gl.glEnableVertexAttribArray(0); // aXYOffset - glVertexAttribPointer(1, - 2, - GL_FLOAT, - GL_FALSE, - kPointsPerVertex * sizeof(float), - reinterpret_cast(2 * sizeof(float))); - glEnableVertexAttribArray(1); + gl.glVertexAttribPointer(1, + 2, + GL_FLOAT, + GL_FALSE, + kPointsPerVertex * sizeof(float), + reinterpret_cast(2 * sizeof(float))); + gl.glEnableVertexAttribArray(1); // aModulate - glVertexAttribPointer(3, - 4, - GL_FLOAT, - GL_FALSE, - kPointsPerVertex * sizeof(float), - reinterpret_cast(4 * sizeof(float))); - glEnableVertexAttribArray(3); + gl.glVertexAttribPointer(3, + 4, + GL_FLOAT, + GL_FALSE, + kPointsPerVertex * sizeof(float), + reinterpret_cast(4 * sizeof(float))); + gl.glEnableVertexAttribArray(3); // aAngle - glVertexAttribPointer(4, - 1, - GL_FLOAT, - GL_FALSE, - kPointsPerVertex * sizeof(float), - reinterpret_cast(8 * sizeof(float))); - glEnableVertexAttribArray(4); + gl.glVertexAttribPointer(4, + 1, + GL_FLOAT, + GL_FALSE, + kPointsPerVertex * sizeof(float), + reinterpret_cast(8 * sizeof(float))); + gl.glEnableVertexAttribArray(4); - glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); - glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); + gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); + gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); // aThreshold - glVertexAttribIPointer(5, // - 1, - GL_INT, - kIntegersPerVertex_ * sizeof(GLint), - static_cast(0)); - glEnableVertexAttribArray(5); + gl.glVertexAttribIPointer(5, // + 1, + GL_INT, + kIntegersPerVertex_ * sizeof(GLint), + static_cast(0)); + gl.glEnableVertexAttribArray(5); // aTimeRange - glVertexAttribIPointer(6, // - 2, - GL_INT, - kIntegersPerVertex_ * sizeof(GLint), - reinterpret_cast(1 * sizeof(GLint))); - glEnableVertexAttribArray(6); + gl.glVertexAttribIPointer(6, // + 2, + GL_INT, + kIntegersPerVertex_ * sizeof(GLint), + reinterpret_cast(1 * sizeof(GLint))); + gl.glEnableVertexAttribArray(6); // aDisplayed - glVertexAttribI1i(7, 1); - - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - // NOLINTEND(performance-no-int-to-ptr) - // NOLINTEND(modernize-use-nullptr) + gl30.glVertexAttribI1i(7, 1); p->dirty_ = true; } @@ -225,7 +223,9 @@ void PlacefileLines::Render( if (p->currentNumLines_ > 0) { - glBindVertexArray(p->vao_); + gl::OpenGLFunctions& gl = p->context_->gl(); + + gl.glBindVertexArray(p->vao_); p->Update(); p->shaderProgram_->Use(); @@ -238,34 +238,36 @@ void PlacefileLines::Render( // If thresholding is enabled, set the map distance units::length::nautical_miles mapDistance = util::maplibre::GetMapDistance(params); - glUniform1f(p->uMapDistanceLocation_, mapDistance.value()); + gl.glUniform1f(p->uMapDistanceLocation_, mapDistance.value()); } else { // If thresholding is disabled, set the map distance to 0 - glUniform1f(p->uMapDistanceLocation_, 0.0f); + gl.glUniform1f(p->uMapDistanceLocation_, 0.0f); } // Selected time std::chrono::system_clock::time_point selectedTime = (p->selectedTime_ == std::chrono::system_clock::time_point {}) ? - scwx::util::time::now() : + std::chrono::system_clock::now() : p->selectedTime_; - glUniform1i( + gl.glUniform1i( p->uSelectedTimeLocation_, static_cast(std::chrono::duration_cast( selectedTime.time_since_epoch()) .count())); // Draw icons - glDrawArrays(GL_TRIANGLES, 0, p->numVertices_); + gl.glDrawArrays(GL_TRIANGLES, 0, p->numVertices_); } } void PlacefileLines::Deinitialize() { - glDeleteVertexArrays(1, &p->vao_); - glDeleteBuffers(2, p->vbo_.data()); + gl::OpenGLFunctions& gl = p->context_->gl(); + + gl.glDeleteVertexArrays(1, &p->vao_); + gl.glDeleteBuffers(2, p->vbo_.data()); std::unique_lock lock {p->lineMutex_}; @@ -477,21 +479,21 @@ void PlacefileLines::Impl::Update() // If the placefile has been updated if (dirty_) { + gl::OpenGLFunctions& gl = context_->gl(); + // Buffer lines data - glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]); - glBufferData( - GL_ARRAY_BUFFER, - static_cast(sizeof(float) * currentLinesBuffer_.size()), - currentLinesBuffer_.data(), - GL_DYNAMIC_DRAW); + gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]); + gl.glBufferData(GL_ARRAY_BUFFER, + sizeof(float) * currentLinesBuffer_.size(), + currentLinesBuffer_.data(), + GL_DYNAMIC_DRAW); // Buffer threshold data - glBindBuffer(GL_ARRAY_BUFFER, vbo_[1]); - glBufferData( - GL_ARRAY_BUFFER, - static_cast(sizeof(GLint) * currentIntegerBuffer_.size()), - currentIntegerBuffer_.data(), - GL_DYNAMIC_DRAW); + gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[1]); + gl.glBufferData(GL_ARRAY_BUFFER, + sizeof(GLint) * currentIntegerBuffer_.size(), + currentIntegerBuffer_.data(), + GL_DYNAMIC_DRAW); } dirty_ = false; @@ -527,7 +529,7 @@ bool PlacefileLines::RunMousePicking( // If no time has been selected, use the current time std::chrono::system_clock::time_point selectedTime = (p->selectedTime_ == std::chrono::system_clock::time_point {}) ? - scwx::util::time::now() : + std::chrono::system_clock::now() : p->selectedTime_; // For each pickable line @@ -546,10 +548,8 @@ bool PlacefileLines::RunMousePicking( units::length::nautical_miles {line.di_->threshold_} .value())) < 999 && - // Map distance is beyond/within the threshold - line.di_->threshold_ < mapDistance && - (line.di_->threshold_.value() >= 0.0 || - -(line.di_->threshold_) > mapDistance)) || + // Map distance is beyond the threshold + line.di_->threshold_ < mapDistance) || ( // Line has a start time diff --git a/scwx-qt/source/scwx/qt/gl/draw/placefile_polygons.cpp b/scwx-qt/source/scwx/qt/gl/draw/placefile_polygons.cpp index a30991f9..2944fa20 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/placefile_polygons.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/placefile_polygons.cpp @@ -1,19 +1,13 @@ #include #include #include -#include #include +#include #include -#if !defined(__APPLE__) -# include -#else -# include -#endif - -#if defined(_WIN32) || defined(__APPLE__) +#if defined(_WIN32) typedef void (*_GLUfuncptr)(void); #endif @@ -37,6 +31,7 @@ static constexpr std::size_t kIntegersPerVertex_ = 3; static constexpr std::size_t kTessVertexScreenX_ = 0; static constexpr std::size_t kTessVertexScreenY_ = 1; +static constexpr std::size_t kTessVertexScreenZ_ = 2; static constexpr std::size_t kTessVertexXOffset_ = 3; static constexpr std::size_t kTessVertexYOffset_ = 4; static constexpr std::size_t kTessVertexR_ = 5; @@ -131,7 +126,7 @@ public: PlacefilePolygons::PlacefilePolygons( const std::shared_ptr& context) : - DrawItem(), p(std::make_unique(context)) + DrawItem(context->gl()), p(std::make_unique(context)) { } PlacefilePolygons::~PlacefilePolygons() = default; @@ -153,6 +148,8 @@ void PlacefilePolygons::set_thresholded(bool thresholded) void PlacefilePolygons::Initialize() { + gl::OpenGLFunctions& gl = p->context_->gl(); + p->shaderProgram_ = p->context_->GetShaderProgram( {{GL_VERTEX_SHADER, ":/gl/map_color.vert"}, {GL_GEOMETRY_SHADER, ":/gl/threshold.geom"}, @@ -167,66 +164,58 @@ void PlacefilePolygons::Initialize() p->uSelectedTimeLocation_ = p->shaderProgram_->GetUniformLocation("uSelectedTime"); - glGenVertexArrays(1, &p->vao_); - glGenBuffers(2, p->vbo_.data()); + gl.glGenVertexArrays(1, &p->vao_); + gl.glGenBuffers(2, p->vbo_.data()); - glBindVertexArray(p->vao_); - glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); - glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); - - // NOLINTBEGIN(modernize-use-nullptr) - // NOLINTBEGIN(performance-no-int-to-ptr) - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) + gl.glBindVertexArray(p->vao_); + gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); + gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); // aScreenCoord - glVertexAttribPointer(0, - 2, - GL_FLOAT, - GL_FALSE, - kPointsPerVertex * sizeof(float), - static_cast(0)); - glEnableVertexAttribArray(0); + gl.glVertexAttribPointer(0, + 2, + GL_FLOAT, + GL_FALSE, + kPointsPerVertex * sizeof(float), + static_cast(0)); + gl.glEnableVertexAttribArray(0); // aXYOffset - glVertexAttribPointer(1, - 2, - GL_FLOAT, - GL_FALSE, - kPointsPerVertex * sizeof(float), - reinterpret_cast(2 * sizeof(float))); - glEnableVertexAttribArray(1); + gl.glVertexAttribPointer(1, + 2, + GL_FLOAT, + GL_FALSE, + kPointsPerVertex * sizeof(float), + reinterpret_cast(2 * sizeof(float))); + gl.glEnableVertexAttribArray(1); // aColor - glVertexAttribPointer(2, - 4, - GL_FLOAT, - GL_FALSE, - kPointsPerVertex * sizeof(float), - reinterpret_cast(4 * sizeof(float))); - glEnableVertexAttribArray(2); + gl.glVertexAttribPointer(2, + 4, + GL_FLOAT, + GL_FALSE, + kPointsPerVertex * sizeof(float), + reinterpret_cast(4 * sizeof(float))); + gl.glEnableVertexAttribArray(2); - glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); - glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); + gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); + gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); // aThreshold - glVertexAttribIPointer(3, // - 1, - GL_INT, - kIntegersPerVertex_ * sizeof(GLint), - static_cast(0)); - glEnableVertexAttribArray(3); + gl.glVertexAttribIPointer(3, // + 1, + GL_INT, + kIntegersPerVertex_ * sizeof(GLint), + static_cast(0)); + gl.glEnableVertexAttribArray(3); // aTimeRange - glVertexAttribIPointer(4, // - 2, - GL_INT, - kIntegersPerVertex_ * sizeof(GLint), - reinterpret_cast(1 * sizeof(GLint))); - glEnableVertexAttribArray(4); - - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - // NOLINTEND(performance-no-int-to-ptr) - // NOLINTEND(modernize-use-nullptr) + gl.glVertexAttribIPointer(4, // + 2, + GL_INT, + kIntegersPerVertex_ * sizeof(GLint), + reinterpret_cast(1 * sizeof(GLint))); + gl.glEnableVertexAttribArray(4); p->dirty_ = true; } @@ -236,7 +225,9 @@ void PlacefilePolygons::Render( { if (!p->currentBuffer_.empty()) { - glBindVertexArray(p->vao_); + gl::OpenGLFunctions& gl = p->context_->gl(); + + gl.glBindVertexArray(p->vao_); p->Update(); p->shaderProgram_->Use(); @@ -249,34 +240,36 @@ void PlacefilePolygons::Render( // If thresholding is enabled, set the map distance units::length::nautical_miles mapDistance = util::maplibre::GetMapDistance(params); - glUniform1f(p->uMapDistanceLocation_, mapDistance.value()); + gl.glUniform1f(p->uMapDistanceLocation_, mapDistance.value()); } else { // If thresholding is disabled, set the map distance to 0 - glUniform1f(p->uMapDistanceLocation_, 0.0f); + gl.glUniform1f(p->uMapDistanceLocation_, 0.0f); } // Selected time std::chrono::system_clock::time_point selectedTime = (p->selectedTime_ == std::chrono::system_clock::time_point {}) ? - scwx::util::time::now() : + std::chrono::system_clock::now() : p->selectedTime_; - glUniform1i( + gl.glUniform1i( p->uSelectedTimeLocation_, static_cast(std::chrono::duration_cast( selectedTime.time_since_epoch()) .count())); // Draw icons - glDrawArrays(GL_TRIANGLES, 0, p->numVertices_); + gl.glDrawArrays(GL_TRIANGLES, 0, p->numVertices_); } } void PlacefilePolygons::Deinitialize() { - glDeleteVertexArrays(1, &p->vao_); - glDeleteBuffers(2, p->vbo_.data()); + gl::OpenGLFunctions& gl = p->context_->gl(); + + gl.glDeleteVertexArrays(1, &p->vao_); + gl.glDeleteBuffers(2, p->vbo_.data()); std::unique_lock lock {p->bufferMutex_}; @@ -321,23 +314,23 @@ void PlacefilePolygons::Impl::Update() { if (dirty_) { + gl::OpenGLFunctions& gl = context_->gl(); + std::unique_lock lock {bufferMutex_}; // Buffer vertex data - glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]); - glBufferData( - GL_ARRAY_BUFFER, - static_cast(sizeof(GLfloat) * currentBuffer_.size()), - currentBuffer_.data(), - GL_DYNAMIC_DRAW); + gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]); + gl.glBufferData(GL_ARRAY_BUFFER, + sizeof(GLfloat) * currentBuffer_.size(), + currentBuffer_.data(), + GL_DYNAMIC_DRAW); // Buffer threshold data - glBindBuffer(GL_ARRAY_BUFFER, vbo_[1]); - glBufferData( - GL_ARRAY_BUFFER, - static_cast(sizeof(GLint) * currentIntegerBuffer_.size()), - currentIntegerBuffer_.data(), - GL_DYNAMIC_DRAW); + gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[1]); + gl.glBufferData(GL_ARRAY_BUFFER, + sizeof(GLint) * currentIntegerBuffer_.size(), + currentIntegerBuffer_.data(), + GL_DYNAMIC_DRAW); numVertices_ = static_cast(currentBuffer_.size() / kPointsPerVertex); diff --git a/scwx-qt/source/scwx/qt/gl/draw/placefile_text.cpp b/scwx-qt/source/scwx/qt/gl/draw/placefile_text.cpp index 0ce6ab47..b8faa8f8 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/placefile_text.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/placefile_text.cpp @@ -1,16 +1,22 @@ #include #include +#include #include #include #include #include -#include #include #include #include -namespace scwx::qt::gl::draw +namespace scwx +{ +namespace qt +{ +namespace gl +{ +namespace draw { static const std::string logPrefix_ = "scwx::qt::gl::draw::placefile_text"; @@ -19,16 +25,13 @@ static const auto logger_ = scwx::util::Logger::Create(logPrefix_); class PlacefileText::Impl { public: - explicit Impl(std::string placefileName) : - placefileName_ {std::move(placefileName)} + explicit Impl(const std::shared_ptr& context, + const std::string& placefileName) : + context_ {context}, placefileName_ {placefileName} { } - ~Impl() = default; - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; + ~Impl() {} void RenderTextDrawItem( const QMapLibre::CustomLayerRenderParameters& params, @@ -40,6 +43,8 @@ public: float x, float y); + std::shared_ptr context_; + std::string placefileName_; bool thresholded_ {false}; @@ -61,16 +66,13 @@ public: std::vector> textList_ {}; std::vector> newList_ {}; - std::vector, - units::font_size::pixels>> - fonts_ {}; - std::vector, - units::font_size::pixels>> - newFonts_ {}; + std::vector> fonts_ {}; + std::vector> newFonts_ {}; }; -PlacefileText::PlacefileText(const std::string& placefileName) : - DrawItem(), p(std::make_unique(placefileName)) +PlacefileText::PlacefileText(const std::shared_ptr& context, + const std::string& placefileName) : + DrawItem(context->gl()), p(std::make_unique(context, placefileName)) { } PlacefileText::~PlacefileText() = default; @@ -131,14 +133,10 @@ void PlacefileText::Impl::RenderTextDrawItem( // If no time has been selected, use the current time std::chrono::system_clock::time_point selectedTime = (selectedTime_ == std::chrono::system_clock::time_point {}) ? - scwx::util::time::now() : + std::chrono::system_clock::now() : selectedTime_; - const bool thresholdMet = - !thresholded_ || mapDistance_ <= di->threshold_ || - (di->threshold_.value() < 0.0 && mapDistance_ >= -(di->threshold_)); - - if (thresholdMet && + if ((!thresholded_ || mapDistance_ <= di->threshold_) && (di->startTime_ == std::chrono::system_clock::time_point {} || (di->startTime_ <= selectedTime && selectedTime < di->endTime_))) { @@ -162,8 +160,7 @@ void PlacefileText::Impl::RenderTextDrawItem( std::size_t fontNumber = std::clamp(di->fontNumber_, 0, 8); // Set the font for the drop shadow and text - ImGui::PushFont(fonts_[fontNumber].first->font(), - fonts_[fontNumber].second.value()); + ImGui::PushFont(fonts_[fontNumber]->font()); if (settings::TextSettings::Instance() .placefile_text_drop_shadow_enabled() @@ -265,7 +262,9 @@ void PlacefileText::StartText() p->newList_.clear(); } -void PlacefileText::SetFonts(const manager::PlacefileManager::FontMap& fonts) +void PlacefileText::SetFonts( + const boost::unordered_flat_map>& fonts) { auto defaultFont = manager::FontManager::Instance().GetImGuiFont( types::FontCategory::Default); @@ -307,4 +306,7 @@ void PlacefileText::FinishText() p->newFonts_.clear(); } -} // namespace scwx::qt::gl::draw +} // namespace draw +} // namespace gl +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/gl/draw/placefile_text.hpp b/scwx-qt/source/scwx/qt/gl/draw/placefile_text.hpp index e4e46755..4cbaf0af 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/placefile_text.hpp +++ b/scwx-qt/source/scwx/qt/gl/draw/placefile_text.hpp @@ -2,7 +2,6 @@ #include #include -#include #include #include @@ -20,7 +19,8 @@ namespace draw class PlacefileText : public DrawItem { public: - explicit PlacefileText(const std::string& placefileName); + explicit PlacefileText(const std::shared_ptr& context, + const std::string& placefileName); ~PlacefileText(); PlacefileText(const PlacefileText&) = delete; @@ -55,7 +55,10 @@ public: * * @param [in] fonts A map of ImGui fonts */ - void SetFonts(const manager::PlacefileManager::FontMap& fonts); + void + SetFonts(const boost::unordered_flat_map>& + fonts); /** * Adds placefile text to the internal draw list. diff --git a/scwx-qt/source/scwx/qt/gl/draw/placefile_triangles.cpp b/scwx-qt/source/scwx/qt/gl/draw/placefile_triangles.cpp index 222713ae..0b5f9c30 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/placefile_triangles.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/placefile_triangles.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include @@ -75,7 +74,7 @@ public: PlacefileTriangles::PlacefileTriangles( const std::shared_ptr& context) : - DrawItem(), p(std::make_unique(context)) + DrawItem(context->gl()), p(std::make_unique(context)) { } PlacefileTriangles::~PlacefileTriangles() = default; @@ -97,6 +96,8 @@ void PlacefileTriangles::set_thresholded(bool thresholded) void PlacefileTriangles::Initialize() { + gl::OpenGLFunctions& gl = p->context_->gl(); + p->shaderProgram_ = p->context_->GetShaderProgram( {{GL_VERTEX_SHADER, ":/gl/map_color.vert"}, {GL_GEOMETRY_SHADER, ":/gl/threshold.geom"}, @@ -111,66 +112,58 @@ void PlacefileTriangles::Initialize() p->uSelectedTimeLocation_ = p->shaderProgram_->GetUniformLocation("uSelectedTime"); - glGenVertexArrays(1, &p->vao_); - glGenBuffers(2, p->vbo_.data()); + gl.glGenVertexArrays(1, &p->vao_); + gl.glGenBuffers(2, p->vbo_.data()); - glBindVertexArray(p->vao_); - glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); - glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); - - // NOLINTBEGIN(modernize-use-nullptr) - // NOLINTBEGIN(performance-no-int-to-ptr) - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) + gl.glBindVertexArray(p->vao_); + gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); + gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); // aScreenCoord - glVertexAttribPointer(0, - 2, - GL_FLOAT, - GL_FALSE, - kPointsPerVertex * sizeof(float), - static_cast(0)); - glEnableVertexAttribArray(0); + gl.glVertexAttribPointer(0, + 2, + GL_FLOAT, + GL_FALSE, + kPointsPerVertex * sizeof(float), + static_cast(0)); + gl.glEnableVertexAttribArray(0); // aXYOffset - glVertexAttribPointer(1, - 2, - GL_FLOAT, - GL_FALSE, - kPointsPerVertex * sizeof(float), - reinterpret_cast(2 * sizeof(float))); - glEnableVertexAttribArray(1); + gl.glVertexAttribPointer(1, + 2, + GL_FLOAT, + GL_FALSE, + kPointsPerVertex * sizeof(float), + reinterpret_cast(2 * sizeof(float))); + gl.glEnableVertexAttribArray(1); // aColor - glVertexAttribPointer(2, - 4, - GL_FLOAT, - GL_FALSE, - kPointsPerVertex * sizeof(float), - reinterpret_cast(4 * sizeof(float))); - glEnableVertexAttribArray(2); + gl.glVertexAttribPointer(2, + 4, + GL_FLOAT, + GL_FALSE, + kPointsPerVertex * sizeof(float), + reinterpret_cast(4 * sizeof(float))); + gl.glEnableVertexAttribArray(2); - glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); - glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); + gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); + gl.glBufferData(GL_ARRAY_BUFFER, 0u, nullptr, GL_DYNAMIC_DRAW); // aThreshold - glVertexAttribIPointer(3, // - 1, - GL_INT, - kIntegersPerVertex_ * sizeof(GLint), - static_cast(0)); - glEnableVertexAttribArray(3); + gl.glVertexAttribIPointer(3, // + 1, + GL_INT, + kIntegersPerVertex_ * sizeof(GLint), + static_cast(0)); + gl.glEnableVertexAttribArray(3); // aTimeRange - glVertexAttribIPointer(4, // - 2, - GL_INT, - kIntegersPerVertex_ * sizeof(GLint), - reinterpret_cast(1 * sizeof(GLint))); - glEnableVertexAttribArray(4); - - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - // NOLINTEND(performance-no-int-to-ptr) - // NOLINTEND(modernize-use-nullptr) + gl.glVertexAttribIPointer(4, // + 2, + GL_INT, + kIntegersPerVertex_ * sizeof(GLint), + reinterpret_cast(1 * sizeof(GLint))); + gl.glEnableVertexAttribArray(4); p->dirty_ = true; } @@ -180,7 +173,9 @@ void PlacefileTriangles::Render( { if (!p->currentBuffer_.empty()) { - glBindVertexArray(p->vao_); + gl::OpenGLFunctions& gl = p->context_->gl(); + + gl.glBindVertexArray(p->vao_); p->Update(); p->shaderProgram_->Use(); @@ -193,34 +188,36 @@ void PlacefileTriangles::Render( // If thresholding is enabled, set the map distance units::length::nautical_miles mapDistance = util::maplibre::GetMapDistance(params); - glUniform1f(p->uMapDistanceLocation_, mapDistance.value()); + gl.glUniform1f(p->uMapDistanceLocation_, mapDistance.value()); } else { // If thresholding is disabled, set the map distance to 0 - glUniform1f(p->uMapDistanceLocation_, 0.0f); + gl.glUniform1f(p->uMapDistanceLocation_, 0.0f); } // Selected time std::chrono::system_clock::time_point selectedTime = (p->selectedTime_ == std::chrono::system_clock::time_point {}) ? - scwx::util::time::now() : + std::chrono::system_clock::now() : p->selectedTime_; - glUniform1i( + gl.glUniform1i( p->uSelectedTimeLocation_, static_cast(std::chrono::duration_cast( selectedTime.time_since_epoch()) .count())); // Draw icons - glDrawArrays(GL_TRIANGLES, 0, p->numVertices_); + gl.glDrawArrays(GL_TRIANGLES, 0, p->numVertices_); } } void PlacefileTriangles::Deinitialize() { - glDeleteVertexArrays(1, &p->vao_); - glDeleteBuffers(2, p->vbo_.data()); + gl::OpenGLFunctions& gl = p->context_->gl(); + + gl.glDeleteVertexArrays(1, &p->vao_); + gl.glDeleteBuffers(2, p->vbo_.data()); std::unique_lock lock {p->bufferMutex_}; @@ -323,23 +320,23 @@ void PlacefileTriangles::Impl::Update() { if (dirty_) { + gl::OpenGLFunctions& gl = context_->gl(); + std::unique_lock lock {bufferMutex_}; // Buffer vertex data - glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]); - glBufferData( - GL_ARRAY_BUFFER, - static_cast(sizeof(GLfloat) * currentBuffer_.size()), - currentBuffer_.data(), - GL_DYNAMIC_DRAW); + gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[0]); + gl.glBufferData(GL_ARRAY_BUFFER, + sizeof(GLfloat) * currentBuffer_.size(), + currentBuffer_.data(), + GL_DYNAMIC_DRAW); // Buffer threshold data - glBindBuffer(GL_ARRAY_BUFFER, vbo_[1]); - glBufferData( - GL_ARRAY_BUFFER, - static_cast(sizeof(GLint) * currentIntegerBuffer_.size()), - currentIntegerBuffer_.data(), - GL_DYNAMIC_DRAW); + gl.glBindBuffer(GL_ARRAY_BUFFER, vbo_[1]); + gl.glBufferData(GL_ARRAY_BUFFER, + sizeof(GLint) * currentIntegerBuffer_.size(), + currentIntegerBuffer_.data(), + GL_DYNAMIC_DRAW); numVertices_ = static_cast(currentBuffer_.size() / kPointsPerVertex); diff --git a/scwx-qt/source/scwx/qt/gl/draw/rectangle.cpp b/scwx-qt/source/scwx/qt/gl/draw/rectangle.cpp index d86ba163..800e199f 100644 --- a/scwx-qt/source/scwx/qt/gl/draw/rectangle.cpp +++ b/scwx-qt/source/scwx/qt/gl/draw/rectangle.cpp @@ -3,7 +3,13 @@ #include -namespace scwx::qt::gl::draw +namespace scwx +{ +namespace qt +{ +namespace gl +{ +namespace draw { static const std::string logPrefix_ = "scwx::qt::gl::draw::rectangle"; @@ -21,7 +27,7 @@ class Rectangle::Impl { public: explicit Impl(std::shared_ptr context) : - context_ {std::move(context)}, + context_ {context}, dirty_ {false}, visible_ {true}, x_ {0.0f}, @@ -38,12 +44,8 @@ public: vbo_ {GL_INVALID_INDEX} { } - ~Impl() = default; - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; + ~Impl() {} std::shared_ptr context_; @@ -71,7 +73,7 @@ public: }; Rectangle::Rectangle(std::shared_ptr context) : - DrawItem(), p(std::make_unique(context)) + DrawItem(context->gl()), p(std::make_unique(context)) { } Rectangle::~Rectangle() = default; @@ -81,45 +83,41 @@ Rectangle& Rectangle::operator=(Rectangle&&) noexcept = default; void Rectangle::Initialize() { + gl::OpenGLFunctions& gl = p->context_->gl(); + p->shaderProgram_ = p->context_->GetShaderProgram(":/gl/color.vert", ":/gl/color.frag"); p->uMVPMatrixLocation_ = - glGetUniformLocation(p->shaderProgram_->id(), "uMVPMatrix"); + gl.glGetUniformLocation(p->shaderProgram_->id(), "uMVPMatrix"); if (p->uMVPMatrixLocation_ == -1) { logger_->warn("Could not find uMVPMatrix"); } - glGenVertexArrays(1, &p->vao_); - glGenBuffers(1, &p->vbo_); + gl.glGenVertexArrays(1, &p->vao_); + gl.glGenBuffers(1, &p->vbo_); - glBindVertexArray(p->vao_); - glBindBuffer(GL_ARRAY_BUFFER, p->vbo_); - glBufferData( + gl.glBindVertexArray(p->vao_); + gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_); + gl.glBufferData( GL_ARRAY_BUFFER, sizeof(float) * BUFFER_LENGTH, nullptr, GL_DYNAMIC_DRAW); - // NOLINTBEGIN(modernize-use-nullptr) - // NOLINTBEGIN(performance-no-int-to-ptr) + gl.glVertexAttribPointer(0, + 3, + GL_FLOAT, + GL_FALSE, + POINTS_PER_VERTEX * sizeof(float), + static_cast(0)); + gl.glEnableVertexAttribArray(0); - glVertexAttribPointer(0, - 3, - GL_FLOAT, - GL_FALSE, - POINTS_PER_VERTEX * sizeof(float), - static_cast(0)); - glEnableVertexAttribArray(0); - - glVertexAttribPointer(1, - 4, - GL_FLOAT, - GL_FALSE, - POINTS_PER_VERTEX * sizeof(float), - reinterpret_cast(3 * sizeof(float))); - glEnableVertexAttribArray(1); - - // NOLINTEND(performance-no-int-to-ptr) - // NOLINTEND(modernize-use-nullptr) + gl.glVertexAttribPointer(1, + 4, + GL_FLOAT, + GL_FALSE, + POINTS_PER_VERTEX * sizeof(float), + reinterpret_cast(3 * sizeof(float))); + gl.glEnableVertexAttribArray(1); p->dirty_ = true; } @@ -128,8 +126,10 @@ void Rectangle::Render(const QMapLibre::CustomLayerRenderParameters& params) { if (p->visible_) { - glBindVertexArray(p->vao_); - glBindBuffer(GL_ARRAY_BUFFER, p->vbo_); + gl::OpenGLFunctions& gl = p->context_->gl(); + + gl.glBindVertexArray(p->vao_); + gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_); p->Update(); p->shaderProgram_->Use(); @@ -138,23 +138,23 @@ void Rectangle::Render(const QMapLibre::CustomLayerRenderParameters& params) if (p->fillColor_.has_value()) { // Draw fill - // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) - glDrawArrays(GL_TRIANGLES, 24, 6); + gl.glDrawArrays(GL_TRIANGLES, 24, 6); } if (p->borderWidth_ > 0.0f) { // Draw border - // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) - glDrawArrays(GL_TRIANGLES, 0, 24); + gl.glDrawArrays(GL_TRIANGLES, 0, 24); } } } void Rectangle::Deinitialize() { - glDeleteVertexArrays(1, &p->vao_); - glDeleteBuffers(1, &p->vbo_); + gl::OpenGLFunctions& gl = p->context_->gl(); + + gl.glDeleteVertexArrays(1, &p->vao_); + gl.glDeleteBuffers(1, &p->vbo_); } void Rectangle::SetBorder(float width, boost::gil::rgba8_pixel_t color) @@ -206,6 +206,8 @@ void Rectangle::Impl::Update() { if (dirty_) { + gl::OpenGLFunctions& gl = context_->gl(); + const float lox = x_; const float rox = x_ + width_; const float boy = y_; @@ -287,13 +289,16 @@ void Rectangle::Impl::Update() {lox, toy, z_, fc0, fc1, fc2, fc3} // TL }}; - glBufferData(GL_ARRAY_BUFFER, - sizeof(float) * BUFFER_LENGTH, - static_cast(buffer), - GL_DYNAMIC_DRAW); + gl.glBufferData(GL_ARRAY_BUFFER, + sizeof(float) * BUFFER_LENGTH, + buffer, + GL_DYNAMIC_DRAW); dirty_ = false; } } -} // namespace scwx::qt::gl::draw +} // namespace draw +} // namespace gl +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/gl/gl.hpp b/scwx-qt/source/scwx/qt/gl/gl.hpp index ef5d0053..e87454c8 100644 --- a/scwx-qt/source/scwx/qt/gl/gl.hpp +++ b/scwx-qt/source/scwx/qt/gl/gl.hpp @@ -1,12 +1,25 @@ #pragma once -#include +#include #define SCWX_GL_CHECK_ERROR() \ { \ GLenum err; \ - while ((err = glGetError()) != GL_NO_ERROR) \ + while ((err = gl.glGetError()) != GL_NO_ERROR) \ { \ logger_->error("GL Error: {}, {}: {}", err, __FILE__, __LINE__); \ } \ } + +namespace scwx +{ +namespace qt +{ +namespace gl +{ + +using OpenGLFunctions = QOpenGLFunctions_3_3_Core; + +} +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/gl/gl_context.cpp b/scwx-qt/source/scwx/qt/gl/gl_context.cpp index 8cdd08b4..d927aef3 100644 --- a/scwx-qt/source/scwx/qt/gl/gl_context.cpp +++ b/scwx-qt/source/scwx/qt/gl/gl_context.cpp @@ -3,38 +3,45 @@ #include #include -#include -namespace scwx::qt::gl +namespace scwx +{ +namespace qt +{ +namespace gl { static const std::string logPrefix_ = "scwx::qt::gl::gl_context"; -static const auto logger_ = scwx::util::Logger::Create(logPrefix_); class GlContext::Impl { public: - explicit Impl() = default; - ~Impl() = default; - - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; + explicit Impl() : + gl_ {}, + shaderProgramMap_ {}, + shaderProgramMutex_ {}, + textureAtlas_ {GL_INVALID_INDEX}, + textureMutex_ {} + { + } + ~Impl() {} void InitializeGL(); static std::size_t GetShaderKey(std::initializer_list> shaders); + gl::OpenGLFunctions gl_; + QOpenGLFunctions_3_0 gl30_; + bool glInitialized_ {false}; std::unordered_map> - shaderProgramMap_ {}; - std::mutex shaderProgramMutex_ {}; + shaderProgramMap_; + std::mutex shaderProgramMutex_; - GLuint textureAtlas_ {GL_INVALID_INDEX}; - std::mutex textureMutex_ {}; + GLuint textureAtlas_; + std::mutex textureMutex_; std::uint64_t textureBufferCount_ {}; }; @@ -45,6 +52,16 @@ GlContext::~GlContext() = default; GlContext::GlContext(GlContext&&) noexcept = default; GlContext& GlContext::operator=(GlContext&&) noexcept = default; +gl::OpenGLFunctions& GlContext::gl() +{ + return p->gl_; +} + +QOpenGLFunctions_3_0& GlContext::gl30() +{ + return p->gl30_; +} + std::uint64_t GlContext::texture_buffer_count() const { return p->textureBufferCount_; @@ -57,54 +74,10 @@ void GlContext::Impl::InitializeGL() return; } - const int gladVersion = gladLoaderLoadGL(); - if (!gladVersion) - { - logger_->error("gladLoaderLoadGL failed"); + gl_.initializeOpenGLFunctions(); + gl30_.initializeOpenGLFunctions(); - QMessageBox::critical( - nullptr, "Supercell Wx", "Unable to initialize OpenGL"); - - throw std::runtime_error("Unable to initialize OpenGL"); - } - - logger_->info("GLAD initialization complete: OpenGL {}.{}", - GLAD_VERSION_MAJOR(gladVersion), - GLAD_VERSION_MINOR(gladVersion)); - - auto glVersion = reinterpret_cast(glGetString(GL_VERSION)); - auto glVendor = reinterpret_cast(glGetString(GL_VENDOR)); - auto glRenderer = reinterpret_cast(glGetString(GL_RENDERER)); - - logger_->info("OpenGL Version: {}", glVersion); - logger_->info("OpenGL Vendor: {}", glVendor); - logger_->info("OpenGL Renderer: {}", glRenderer); - - // Get OpenGL version - GLint major = 0; - GLint minor = 0; - glGetIntegerv(GL_MAJOR_VERSION, &major); - glGetIntegerv(GL_MINOR_VERSION, &minor); - - if (major < 3 || (major == 3 && minor < 3) || !GLAD_GL_VERSION_3_3) - { - logger_->error( - "OpenGL 3.3 or greater is required, found {}.{}", major, minor); - - QMessageBox::critical( - nullptr, - "Supercell Wx", - QString("OpenGL 3.3 or greater is required, found %1.%2\n\n%3\n%4\n%5") - .arg(major) - .arg(minor) - .arg(glVersion) - .arg(glVendor) - .arg(glRenderer)); - - throw std::runtime_error("OpenGL version too low"); - } - - glGenTextures(1, &textureAtlas_); + gl_.glGenTextures(1, &textureAtlas_); glInitialized_ = true; } @@ -129,7 +102,7 @@ std::shared_ptr GlContext::GetShaderProgram( if (it == p->shaderProgramMap_.end()) { - shaderProgram = std::make_shared(); + shaderProgram = std::make_shared(p->gl_); shaderProgram->Load(shaders); p->shaderProgramMap_[key] = shaderProgram; } @@ -152,7 +125,7 @@ GLuint GlContext::GetTextureAtlas() if (p->textureBufferCount_ != textureAtlas.BuildCount()) { p->textureBufferCount_ = textureAtlas.BuildCount(); - textureAtlas.BufferAtlas(p->textureAtlas_); + textureAtlas.BufferAtlas(p->gl_, p->textureAtlas_); } return p->textureAtlas_; @@ -165,8 +138,10 @@ void GlContext::Initialize() void GlContext::StartFrame() { - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); + auto& gl = p->gl_; + + gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + gl.glClear(GL_COLOR_BUFFER_BIT); } std::size_t GlContext::Impl::GetShaderKey( @@ -181,4 +156,6 @@ std::size_t GlContext::Impl::GetShaderKey( return seed; } -} // namespace scwx::qt::gl +} // namespace gl +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/gl/gl_context.hpp b/scwx-qt/source/scwx/qt/gl/gl_context.hpp index 1af68b1f..b4a6a866 100644 --- a/scwx-qt/source/scwx/qt/gl/gl_context.hpp +++ b/scwx-qt/source/scwx/qt/gl/gl_context.hpp @@ -3,6 +3,8 @@ #include #include +#include + namespace scwx { namespace qt @@ -22,6 +24,9 @@ public: GlContext(GlContext&&) noexcept; GlContext& operator=(GlContext&&) noexcept; + gl::OpenGLFunctions& gl(); + QOpenGLFunctions_3_0& gl30(); + std::uint64_t texture_buffer_count() const; std::shared_ptr diff --git a/scwx-qt/source/scwx/qt/gl/shader_program.cpp b/scwx-qt/source/scwx/qt/gl/shader_program.cpp index e1b791c0..4da07a32 100644 --- a/scwx-qt/source/scwx/qt/gl/shader_program.cpp +++ b/scwx-qt/source/scwx/qt/gl/shader_program.cpp @@ -2,9 +2,12 @@ #include #include -#include -namespace scwx::qt::gl +namespace scwx +{ +namespace qt +{ +namespace gl { static const std::string logPrefix_ = "scwx::qt::gl::shader_program"; @@ -20,25 +23,29 @@ static const std::unordered_map kShaderNames_ { class ShaderProgram::Impl { public: - explicit Impl() : id_ {glCreateProgram()} {} + explicit Impl(OpenGLFunctions& gl) : gl_(gl), id_ {GL_INVALID_INDEX} + { + // Create shader program + id_ = gl_.glCreateProgram(); + } ~Impl() { // Delete shader program - glDeleteProgram(id_); + gl_.glDeleteProgram(id_); } - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; - static std::string ShaderName(GLenum type); + OpenGLFunctions& gl_; + GLuint id_; }; -ShaderProgram::ShaderProgram() : p(std::make_unique()) {} +ShaderProgram::ShaderProgram(OpenGLFunctions& gl) : + p(std::make_unique(gl)) +{ +} ShaderProgram::~ShaderProgram() = default; ShaderProgram::ShaderProgram(ShaderProgram&&) noexcept = default; @@ -51,7 +58,7 @@ GLuint ShaderProgram::id() const GLint ShaderProgram::GetUniformLocation(const std::string& name) { - const GLint location = glGetUniformLocation(p->id_, name.c_str()); + GLint location = p->gl_.glGetUniformLocation(p->id_, name.c_str()); if (location == -1) { logger_->warn("Could not find {}", name); @@ -81,6 +88,8 @@ bool ShaderProgram::Load( { logger_->debug("Load()"); + OpenGLFunctions& gl = p->gl_; + GLint glSuccess; bool success = true; char infoLog[kInfoLogBufSize]; @@ -111,17 +120,16 @@ bool ShaderProgram::Load( const char* shaderSourceC = shaderSource.c_str(); // Create a shader - const GLuint shaderId = glCreateShader(shader.first); + GLuint shaderId = gl.glCreateShader(shader.first); shaderIds.push_back(shaderId); // Attach the shader source code and compile the shader - glShaderSource(shaderId, 1, &shaderSourceC, nullptr); - glCompileShader(shaderId); + gl.glShaderSource(shaderId, 1, &shaderSourceC, NULL); + gl.glCompileShader(shaderId); // Check for errors - glGetShaderiv(shaderId, GL_COMPILE_STATUS, &glSuccess); - glGetShaderInfoLog( - shaderId, kInfoLogBufSize, &logLength, static_cast(infoLog)); + gl.glGetShaderiv(shaderId, GL_COMPILE_STATUS, &glSuccess); + gl.glGetShaderInfoLog(shaderId, kInfoLogBufSize, &logLength, infoLog); if (!glSuccess) { logger_->error("Shader compilation failed: {}", infoLog); @@ -130,7 +138,7 @@ bool ShaderProgram::Load( } else if (logLength > 0) { - logger_->warn("Shader compiled with warnings: {}", infoLog); + logger_->error("Shader compiled with warnings: {}", infoLog); } } @@ -138,14 +146,13 @@ bool ShaderProgram::Load( { for (auto& shaderId : shaderIds) { - glAttachShader(p->id_, shaderId); + gl.glAttachShader(p->id_, shaderId); } - glLinkProgram(p->id_); + gl.glLinkProgram(p->id_); // Check for errors - glGetProgramiv(p->id_, GL_LINK_STATUS, &glSuccess); - glGetProgramInfoLog( - p->id_, kInfoLogBufSize, &logLength, static_cast(infoLog)); + gl.glGetProgramiv(p->id_, GL_LINK_STATUS, &glSuccess); + gl.glGetProgramInfoLog(p->id_, kInfoLogBufSize, &logLength, infoLog); if (!glSuccess) { logger_->error("Shader program link failed: {}", infoLog); @@ -153,14 +160,14 @@ bool ShaderProgram::Load( } else if (logLength > 0) { - logger_->warn("Shader program linked with warnings: {}", infoLog); + logger_->error("Shader program linked with warnings: {}", infoLog); } } // Delete shaders for (auto& shaderId : shaderIds) { - glDeleteShader(shaderId); + gl.glDeleteShader(shaderId); } return success; @@ -168,7 +175,9 @@ bool ShaderProgram::Load( void ShaderProgram::Use() const { - glUseProgram(p->id_); + p->gl_.glUseProgram(p->id_); } -} // namespace scwx::qt::gl +} // namespace gl +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/gl/shader_program.hpp b/scwx-qt/source/scwx/qt/gl/shader_program.hpp index 13fe043b..a2b887d8 100644 --- a/scwx-qt/source/scwx/qt/gl/shader_program.hpp +++ b/scwx-qt/source/scwx/qt/gl/shader_program.hpp @@ -19,7 +19,7 @@ namespace gl class ShaderProgram { public: - explicit ShaderProgram(); + explicit ShaderProgram(OpenGLFunctions& gl); virtual ~ShaderProgram(); ShaderProgram(const ShaderProgram&) = delete; diff --git a/scwx-qt/source/scwx/qt/main/application.cpp b/scwx-qt/source/scwx/qt/main/application.cpp index 3f62120a..d851c8ec 100644 --- a/scwx-qt/source/scwx/qt/main/application.cpp +++ b/scwx-qt/source/scwx/qt/main/application.cpp @@ -44,14 +44,6 @@ void WaitForInitialization() } } -// Only use for test cases -void ResetInitilization() -{ - logger_->debug("Application initialization reset"); - std::unique_lock lock(initializationMutex_); - initialized_ = false; -} - } // namespace Application } // namespace main } // namespace qt diff --git a/scwx-qt/source/scwx/qt/main/application.hpp b/scwx-qt/source/scwx/qt/main/application.hpp index 0237f13c..9b63ffad 100644 --- a/scwx-qt/source/scwx/qt/main/application.hpp +++ b/scwx-qt/source/scwx/qt/main/application.hpp @@ -11,8 +11,6 @@ namespace Application void FinishInitialization(); void WaitForInitialization(); -// Only use for test cases -void ResetInitilization(); } // namespace Application } // namespace main diff --git a/scwx-qt/source/scwx/qt/main/check_privilege.cpp b/scwx-qt/source/scwx/qt/main/check_privilege.cpp deleted file mode 100644 index e6402af5..00000000 --- a/scwx-qt/source/scwx/qt/main/check_privilege.cpp +++ /dev/null @@ -1,136 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef _WIN32 -# include -#else -# include -#endif - -namespace scwx::qt::main -{ - -bool is_high_privilege() -{ -#if defined(_WIN32) - bool isAdmin = false; - HANDLE token = NULL; - TOKEN_ELEVATION elevation; - DWORD elevationSize = sizeof(TOKEN_ELEVATION); - - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) - { - return false; - } - if (!GetTokenInformation( - token, TokenElevation, &elevation, elevationSize, &elevationSize)) - { - CloseHandle(token); - return false; - } - isAdmin = elevation.TokenIsElevated; - CloseHandle(token); - return isAdmin; -#elif defined(Q_OS_UNIX) - // On UNIX root is always uid 0. On Linux this is enforced by the kernel. - return geteuid() == 0; -#else - return false; -#endif -} - -#if defined(_WIN32) -static const QString message = QObject::tr( - "Supercell Wx has been run with administrator permissions. It is " - "recommended to run it without administrator permissions Do you wish to " - "continue?"); -#elif defined(Q_OS_UNIX) -static const QString message = QObject::tr( - "Supercell Wx has been run as root. It is recommended to run it as a normal " - "user. Do you wish to continue?"); -#else -static const QString message = QObject::tr(""); -#endif - -static const QString title = QObject::tr("Supercell Wx"); -static const QString checkBoxText = - QObject::tr("Do not show this warning again."); - -class PrivilegeChecker::Impl -{ -public: - explicit Impl() : - highPrivilege_ {is_high_privilege()}, - dialog_ {QMessageBox::Icon::Warning, title, message}, - checkBox_(new QCheckBox(checkBoxText, &dialog_)) - { - const std::string appDataPath { - QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) - .toStdString()}; - hasAppData_ = std::filesystem::exists(appDataPath); - - dialog_.setStandardButtons(QMessageBox::Yes | QMessageBox::No); - dialog_.setDefaultButton(QMessageBox::No); - dialog_.setCheckBox(checkBox_); - }; - - bool hasAppData_; - bool firstCheckCheckBoxState_ {true}; - bool highPrivilege_; - - QMessageBox dialog_; - QCheckBox* checkBox_; -}; - -PrivilegeChecker::PrivilegeChecker() : - p(std::make_unique()) -{ -} - -PrivilegeChecker::~PrivilegeChecker() = default; - -bool PrivilegeChecker::pre_settings_check() -{ - if (p->hasAppData_ || !p->highPrivilege_) - { - return false; - } - - const int result = p->dialog_.exec(); - p->firstCheckCheckBoxState_ = p->checkBox_->isChecked(); - - return result != QMessageBox::Yes; -} - -bool PrivilegeChecker::post_settings_check() -{ - auto& highPrivilegeWarningEnabled = - settings::GeneralSettings::Instance().high_privilege_warning_enabled(); - if (!highPrivilegeWarningEnabled.GetValue() || !p->highPrivilege_) - { - return false; - } - else if (!p->hasAppData_) - { - highPrivilegeWarningEnabled.StageValue(!p->firstCheckCheckBoxState_); - return false; - } - - switch (p->dialog_.exec()) - { - case QMessageBox::Yes: - highPrivilegeWarningEnabled.StageValue(!p->checkBox_->isChecked()); - return false; - case QMessageBox::No: - default: - return true; - } -} - -} // namespace scwx::qt::main diff --git a/scwx-qt/source/scwx/qt/main/check_privilege.hpp b/scwx-qt/source/scwx/qt/main/check_privilege.hpp deleted file mode 100644 index 8ec3f8e2..00000000 --- a/scwx-qt/source/scwx/qt/main/check_privilege.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include - -namespace scwx::qt::main -{ - -bool is_high_privilege(); - -class PrivilegeChecker -{ -public: - explicit PrivilegeChecker(); - ~PrivilegeChecker(); - - PrivilegeChecker(const PrivilegeChecker&) = delete; - PrivilegeChecker& operator=(const PrivilegeChecker&) = delete; - PrivilegeChecker(const PrivilegeChecker&&) = delete; - PrivilegeChecker& operator=(const PrivilegeChecker&&) = delete; - - // returning true means check failed. - bool pre_settings_check(); - bool post_settings_check(); - -private: - class Impl; - std::unique_ptr p; -}; - -} // namespace scwx::qt::main diff --git a/scwx-qt/source/scwx/qt/main/main.cpp b/scwx-qt/source/scwx/qt/main/main.cpp index a2416cec..566e9772 100644 --- a/scwx-qt/source/scwx/qt/main/main.cpp +++ b/scwx-qt/source/scwx/qt/main/main.cpp @@ -3,18 +3,15 @@ #include #include #include -#include #include #include #include #include #include -#include #include #include #include #include -#include #include #include #include @@ -28,21 +25,11 @@ #include #include #include -#include -#include #include -#include -#include - -#define QT6CT_LIBRARY -#include -#undef QT6CT_LIBRARY static const std::string logPrefix_ = "scwx::main"; static const auto logger_ = scwx::util::Logger::Create(logPrefix_); -static void ConfigureTheme(const std::vector& args); -static void InitializeOpenGL(); static void OverrideDefaultStyle(const std::vector& args); int main(int argc, char* argv[]) @@ -54,28 +41,19 @@ int main(int argc, char* argv[]) args.push_back(argv[i]); } - if (!scwx::util::GetEnvironment("SCWX_TEST").empty()) - { - QStandardPaths::setTestModeEnabled(true); - } - // Initialize logger auto& logManager = scwx::qt::manager::LogManager::Instance(); logManager.Initialize(); - QCoreApplication::setApplicationName("Supercell Wx"); - - logManager.InitializeLogFile(); - - logger_->info("Supercell Wx v{}.{} ({})", + logger_->info("Supercell Wx v{} ({})", scwx::qt::main::kVersionString_, - scwx::qt::main::kBuildNumber_, scwx::qt::main::kCommitString_); - InitializeOpenGL(); + QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true); QApplication a(argc, argv); + QCoreApplication::setApplicationName("Supercell Wx"); scwx::network::cpr::SetUserAgent( fmt::format("SupercellWx/{}", scwx::qt::main::kVersionString_)); @@ -86,11 +64,9 @@ int main(int argc, char* argv[]) QCoreApplication::installTranslator(&translator); } - // Test to see if scwx was run with high privilege - scwx::qt::main::PrivilegeChecker privilegeChecker; - if (privilegeChecker.pre_settings_check()) + if (!scwx::util::GetEnvironment("SCWX_TEST").empty()) { - return 0; + QStandardPaths::setTestModeEnabled(true); } // Start the io_context main loop @@ -120,54 +96,40 @@ int main(int argc, char* argv[]) Aws::InitAPI(awsSdkOptions); // Initialize application + logManager.InitializeLogFile(); scwx::qt::config::RadarSite::Initialize(); scwx::qt::config::CountyDatabase::Initialize(); - scwx::qt::manager::TaskManager::Initialize(); scwx::qt::manager::SettingsManager::Instance().Initialize(); scwx::qt::manager::ResourceManager::Initialize(); // Theme - ConfigureTheme(args); + auto uiStyle = scwx::qt::types::GetUiStyle( + scwx::qt::settings::GeneralSettings::Instance().theme().GetValue()); - // Check process modules for compatibility - scwx::qt::main::CheckProcessModules(); - - int result = 0; - if (privilegeChecker.post_settings_check()) + if (uiStyle == scwx::qt::types::UiStyle::Default) { - result = 1; + OverrideDefaultStyle(args); } else { - // Run initial setup if required - if (scwx::qt::ui::setup::SetupWizard::IsSetupRequired()) - { - scwx::qt::ui::setup::SetupWizard w; - w.show(); - a.exec(); - } + QApplication::setStyle( + QString::fromStdString(scwx::qt::types::GetUiStyleName(uiStyle))); + } - // Run Qt main loop - { - scwx::qt::main::MainWindow w; + // Run initial setup if required + if (scwx::qt::ui::setup::SetupWizard::IsSetupRequired()) + { + scwx::qt::ui::setup::SetupWizard w; + w.show(); + a.exec(); + } - bool initialized = false; - - try - { - w.show(); - initialized = true; - } - catch (const std::exception& ex) - { - logger_->critical(ex.what()); - } - - if (initialized) - { - result = a.exec(); - } - } + // Run Qt main loop + int result; + { + scwx::qt::main::MainWindow w; + w.show(); + result = a.exec(); } // Deinitialize application @@ -183,7 +145,6 @@ int main(int argc, char* argv[]) // Shutdown application scwx::qt::manager::ResourceManager::Shutdown(); scwx::qt::manager::SettingsManager::Instance().Shutdown(); - scwx::qt::manager::TaskManager::Shutdown(); // Shutdown AWS SDK Aws::ShutdownAPI(awsSdkOptions); @@ -191,73 +152,6 @@ int main(int argc, char* argv[]) return result; } -static void ConfigureTheme(const std::vector& args) -{ - auto& generalSettings = scwx::qt::settings::GeneralSettings::Instance(); - - auto uiStyle = - scwx::qt::types::GetUiStyle(generalSettings.theme().GetValue()); - auto qtColorScheme = scwx::qt::types::GetQtColorScheme(uiStyle); - - if (uiStyle == scwx::qt::types::UiStyle::Default) - { - OverrideDefaultStyle(args); - } - else - { - QApplication::setStyle( - QString::fromStdString(scwx::qt::types::GetQtStyleName(uiStyle))); - } - - QGuiApplication::styleHints()->setColorScheme(qtColorScheme); - - std::optional paletteFile; - if (uiStyle == scwx::qt::types::UiStyle::FusionCustom) - { - paletteFile = generalSettings.theme_file().GetValue(); - } - else - { - paletteFile = scwx::qt::types::GetQtPaletteFile(uiStyle); - } - - if (paletteFile) - { - QPalette defaultPalette = QApplication::style()->standardPalette(); - QPalette palette = Qt6CT::loadColorScheme( - QString::fromStdString(*paletteFile), defaultPalette); - - if (defaultPalette == palette) - { - logger_->warn("Failed to load palette file '{}'", *paletteFile); - } - else - { - logger_->info("Loaded palette file '{}'", *paletteFile); - } - - QApplication::setPalette(palette); - } -} - -static void InitializeOpenGL() -{ - QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true); - - QSurfaceFormat surfaceFormat = QSurfaceFormat::defaultFormat(); - surfaceFormat.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile); - surfaceFormat.setRenderableType(QSurfaceFormat::RenderableType::OpenGL); - -#if defined(__APPLE__) - // For macOS, we must choose between OpenGL 4.1 Core and OpenGL 2.1 - // Compatibility. OpenGL 2.1 does not meet requirements for shaders used by - // Supercell Wx. - surfaceFormat.setVersion(4, 1); -#endif - - QSurfaceFormat::setDefaultFormat(surfaceFormat); -} - static void OverrideDefaultStyle([[maybe_unused]] const std::vector& args) { diff --git a/scwx-qt/source/scwx/qt/main/main_window.cpp b/scwx-qt/source/scwx/qt/main/main_window.cpp index 4fa2f28a..4046e3bd 100644 --- a/scwx-qt/source/scwx/qt/main/main_window.cpp +++ b/scwx-qt/source/scwx/qt/main/main_window.cpp @@ -1,13 +1,11 @@ #include "main_window.hpp" #include "./ui_main_window.h" -#include #include #include #include #include #include -#include #include #include #include @@ -32,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -55,6 +52,10 @@ #include #include +#if !defined(_MSC_VER) +# include +#endif + namespace scwx { namespace qt @@ -89,13 +90,11 @@ public: imGuiDebugDialog_ {nullptr}, layerDialog_ {nullptr}, placefileDialog_ {nullptr}, - markerDialog_ {nullptr}, radarSiteDialog_ {nullptr}, settingsDialog_ {nullptr}, updateDialog_ {nullptr}, alertManager_ {manager::AlertManager::Instance()}, placefileManager_ {manager::PlacefileManager::Instance()}, - markerManager_ {manager::MarkerManager::Instance()}, positionManager_ {manager::PositionManager::Instance()}, textEventManager_ {manager::TextEventManager::Instance()}, timelineManager_ {manager::TimelineManager::Instance()}, @@ -140,9 +139,6 @@ public: } ~MainWindowImpl() { - homeRadarConnection_.disconnect(); - defaultTimeZoneConnection_.disconnect(); - auto& generalSettings = settings::GeneralSettings::Instance(); auto& customStyleUrl = generalSettings.custom_style_url(); @@ -191,8 +187,6 @@ public: map::MapProvider mapProvider_; map::MapWidget* activeMap_; - std::shared_ptr glContext_ {nullptr}; - ui::CollapsibleGroup* mapSettingsGroup_; ui::CollapsibleGroup* level2ProductsGroup_; ui::CollapsibleGroup* level2SettingsGroup_; @@ -213,7 +207,6 @@ public: ui::ImGuiDebugDialog* imGuiDebugDialog_; ui::LayerDialog* layerDialog_; ui::PlacefileDialog* placefileDialog_; - ui::MarkerDialog* markerDialog_; ui::RadarSiteDialog* radarSiteDialog_; ui::SettingsDialog* settingsDialog_; ui::UpdateDialog* updateDialog_; @@ -228,7 +221,6 @@ public: std::shared_ptr hotkeyManager_ { manager::HotkeyManager::Instance()}; std::shared_ptr placefileManager_; - std::shared_ptr markerManager_; std::shared_ptr positionManager_; std::shared_ptr textEventManager_; std::shared_ptr timelineManager_; @@ -245,12 +237,9 @@ public: layerActions_ {}; bool layerActionsInitialized_ {false}; - boost::signals2::scoped_connection homeRadarConnection_ {}; - boost::signals2::scoped_connection defaultTimeZoneConnection_ {}; - std::vector maps_; - std::chrono::system_clock::time_point selectedTime_ {}; + std::chrono::system_clock::time_point volumeTime_ {}; public slots: void UpdateMapParameters(double latitude, @@ -276,7 +265,6 @@ MainWindow::MainWindow(QWidget* parent) : ui->vcpLabel->setVisible(false); ui->vcpValueLabel->setVisible(false); ui->vcpDescriptionLabel->setVisible(false); - ui->saveRadarProductsButton->setVisible(true); p->radarSitePresetsMenu_ = new QMenu(this); ui->radarSitePresetsButton->setMenu(p->radarSitePresetsMenu_); @@ -291,6 +279,7 @@ MainWindow::MainWindow(QWidget* parent) : // Configure Alert Dock p->alertDockWidget_ = new ui::AlertDockWidget(this); + p->alertDockWidget_->setVisible(false); addDockWidget(Qt::BottomDockWidgetArea, p->alertDockWidget_); // GPS Info Dialog @@ -319,25 +308,18 @@ MainWindow::MainWindow(QWidget* parent) : // Placefile Manager Dialog p->placefileDialog_ = new ui::PlacefileDialog(this); - // Marker Manager Dialog - p->markerDialog_ = new ui::MarkerDialog(this); - // Layer Dialog p->layerDialog_ = new ui::LayerDialog(this); // Settings Dialog - p->settingsDialog_ = new ui::SettingsDialog(p->settings_, this); + p->settingsDialog_ = new ui::SettingsDialog(this); // Map Settings p->mapSettingsGroup_ = new ui::CollapsibleGroup(tr("Map Settings"), this); p->mapSettingsGroup_->GetContentsLayout()->addWidget(ui->mapStyleLabel); p->mapSettingsGroup_->GetContentsLayout()->addWidget(ui->mapStyleComboBox); - p->mapSettingsGroup_->GetContentsLayout()->addWidget( - ui->smoothRadarDataCheckBox); p->mapSettingsGroup_->GetContentsLayout()->addWidget( ui->trackLocationCheckBox); - p->mapSettingsGroup_->GetContentsLayout()->addWidget( - ui->saveRadarProductsButton); ui->radarToolboxScrollAreaContents->layout()->replaceWidget( ui->mapSettingsGroupBox, p->mapSettingsGroup_); ui->mapSettingsGroupBox->setVisible(false); @@ -379,7 +361,6 @@ MainWindow::MainWindow(QWidget* parent) : p->animationDockWidget_ = new ui::AnimationDockWidget(this); p->timelineGroup_->GetContentsLayout()->addWidget(p->animationDockWidget_); ui->radarToolboxScrollAreaContents->layout()->addWidget(p->timelineGroup_); - p->animationDockWidget_->UpdateTimeZone(p->activeMap_->GetDefaultTimeZone()); // Reset toolbox spacer at the bottom ui->radarToolboxScrollAreaContents->layout()->removeItem( @@ -463,37 +444,8 @@ void MainWindow::keyReleaseEvent(QKeyEvent* ev) void MainWindow::showEvent(QShowEvent* event) { QMainWindow::showEvent(event); - auto& uiSettings = settings::UiSettings::Instance(); - // restore the geometry state - std::string uiGeometry = uiSettings.main_ui_geometry().GetValue(); - restoreGeometry( - QByteArray::fromBase64(QByteArray::fromStdString(uiGeometry))); - - // restore the UI state - std::string uiState = uiSettings.main_ui_state().GetValue(); - - bool restored = - restoreState(QByteArray::fromBase64(QByteArray::fromStdString(uiState))); - if (!restored) - { - resizeDocks({ui->radarToolboxDock}, {194}, Qt::Horizontal); - } -} - -void MainWindow::closeEvent(QCloseEvent* event) -{ - auto& uiSettings = settings::UiSettings::Instance(); - - // save the UI geometry - QByteArray uiGeometry = saveGeometry().toBase64(); - uiSettings.main_ui_geometry().StageValue(uiGeometry.data()); - - // save the UI state - QByteArray uiState = saveState().toBase64(); - uiSettings.main_ui_state().StageValue(uiState.data()); - - QMainWindow::closeEvent(event); + resizeDocks({ui->radarToolboxDock}, {194}, Qt::Horizontal); } void MainWindow::on_actionOpenNexrad_triggered() @@ -509,11 +461,12 @@ void MainWindow::on_actionOpenNexrad_triggered() map::MapWidget* currentMap = p->activeMap_; // Make sure the parent window properly repaints on close - connect(dialog, - &QFileDialog::finished, - this, - static_cast(&MainWindow::update), - Qt::QueuedConnection); + connect( + dialog, + &QFileDialog::finished, + this, + [this]() { update(); }, + Qt::QueuedConnection); connect( dialog, @@ -574,11 +527,12 @@ void MainWindow::on_actionOpenTextEvent_triggered() dialog->setAttribute(Qt::WA_DeleteOnClose); // Make sure the parent window properly repaints on close - connect(dialog, - &QFileDialog::finished, - this, - static_cast(&MainWindow::update), - Qt::QueuedConnection); + connect( + dialog, + &QFileDialog::finished, + this, + [this]() { update(); }, + Qt::QueuedConnection); connect(dialog, &QFileDialog::fileSelected, @@ -632,11 +586,6 @@ void MainWindow::on_actionPlacefileManager_triggered() p->placefileDialog_->show(); } -void MainWindow::on_actionMarkerManager_triggered() -{ - p->markerDialog_->show(); -} - void MainWindow::on_actionLayerManager_triggered() { p->layerDialog_->show(); @@ -657,11 +606,6 @@ void MainWindow::on_actionDumpRadarProductRecords_triggered() manager::RadarProductManager::DumpRecords(); } -void MainWindow::on_actionRadarWireframe_triggered(bool checked) -{ - p->activeMap_->SetRadarWireframeEnabled(checked); -} - void MainWindow::on_actionUserManual_triggered() { QDesktopServices::openUrl(QUrl {"https://supercell-wx.readthedocs.io/"}); @@ -782,8 +726,6 @@ void MainWindowImpl::ConfigureMapLayout() } }; - glContext_ = std::make_shared(); - for (int64_t y = 0; y < gridHeight; y++) { QSplitter* hs = new QSplitter(vs); @@ -793,9 +735,7 @@ void MainWindowImpl::ConfigureMapLayout() { if (maps_.at(mapIndex) == nullptr) { - // NOLINTNEXTLINE(cppcoreguidelines-owning-memory): Owned by parent - maps_[mapIndex] = - new map::MapWidget(mapIndex, settings_, glContext_); + maps_[mapIndex] = new map::MapWidget(mapIndex, settings_); } hs->addWidget(maps_[mapIndex]); @@ -828,9 +768,9 @@ void MainWindowImpl::ConfigureMapStyles() if ((customStyleAvailable_ && styleName == "Custom") || std::find_if(mapProviderInfo.mapStyles_.cbegin(), mapProviderInfo.mapStyles_.cend(), - [&](const auto& mapStyle) - { return mapStyle.name_ == styleName; }) != - mapProviderInfo.mapStyles_.cend()) + [&](const auto& mapStyle) { + return mapStyle.name_ == styleName; + }) != mapProviderInfo.mapStyles_.cend()) { // Initialize map style from settings maps_.at(i)->SetInitialMapStyle(styleName); @@ -973,28 +913,11 @@ void MainWindowImpl::ConnectMapSignals() } }, Qt::QueuedConnection); - connect( - mapWidget, - &map::MapWidget::IncomingLevel2ElevationChanged, - this, - [this](std::optional) - { level2SettingsWidget_->UpdateSettings(activeMap_); }, - Qt::QueuedConnection); } } void MainWindowImpl::ConnectAnimationSignals() { - defaultTimeZoneConnection_ = settings::GeneralSettings::Instance() - .default_time_zone() - .changed_signal() - .connect( - [this]() - { - animationDockWidget_->UpdateTimeZone( - activeMap_->GetDefaultTimeZone()); - }); - connect(animationDockWidget_, &ui::AnimationDockWidget::DateTimeChanged, timelineManager_.get(), @@ -1038,16 +961,21 @@ void MainWindowImpl::ConnectAnimationSignals() connect(timelineManager_.get(), &manager::TimelineManager::SelectedTimeUpdated, + [this]() + { + for (auto map : maps_) + { + map->update(); + } + }); + connect(timelineManager_.get(), + &manager::TimelineManager::VolumeTimeUpdated, [this](std::chrono::system_clock::time_point dateTime) { - selectedTime_ = dateTime; - + volumeTime_ = dateTime; for (auto map : maps_) { map->SelectTime(dateTime); - textEventManager_->SelectTime(dateTime); - QMetaObject::invokeMethod( - map, static_cast(&QWidget::update)); } }); @@ -1127,29 +1055,10 @@ void MainWindowImpl::ConnectOtherSignals() } } }); - connect( - mainWindow_->ui->smoothRadarDataCheckBox, - &QCheckBox::checkStateChanged, - mainWindow_, - [this](Qt::CheckState state) - { - const bool smoothingEnabled = (state == Qt::CheckState::Checked); - - auto it = std::find(maps_.cbegin(), maps_.cend(), activeMap_); - if (it != maps_.cend()) - { - const std::size_t i = std::distance(maps_.cbegin(), it); - settings::MapSettings::Instance().smoothing_enabled(i).StageValue( - smoothingEnabled); - } - - // Turn on smoothing - activeMap_->SetSmoothingEnabled(smoothingEnabled); - }); connect(mainWindow_->ui->trackLocationCheckBox, - &QCheckBox::checkStateChanged, + &QCheckBox::stateChanged, mainWindow_, - [this](Qt::CheckState state) + [this](int state) { bool trackingEnabled = (state == Qt::CheckState::Checked); @@ -1159,37 +1068,22 @@ void MainWindowImpl::ConnectOtherSignals() // Turn on location tracking positionManager_->TrackLocation(trackingEnabled); }); - connect( - mainWindow_->ui->saveRadarProductsButton, - &QAbstractButton::clicked, - mainWindow_, - [this]() - { - auto& mapSettings = settings::MapSettings::Instance(); - for (std::size_t i = 0; i < maps_.size(); i++) - { - const auto& map = maps_.at(i); - mapSettings.radar_product_group(i).StageValue( - common::GetRadarProductGroupName(map->GetRadarProductGroup())); - mapSettings.radar_product(i).StageValue(map->GetRadarProductName()); - } - }); - connect( - level2ProductsWidget_, - &ui::Level2ProductsWidget::RadarProductSelected, - mainWindow_, - [&](common::RadarProductGroup group, - const std::string& productName, - int16_t productCode) - { SelectRadarProduct(activeMap_, group, productName, productCode); }); - connect( - level3ProductsWidget_, - &ui::Level3ProductsWidget::RadarProductSelected, - mainWindow_, - [&](common::RadarProductGroup group, - const std::string& productName, - int16_t productCode) - { SelectRadarProduct(activeMap_, group, productName, productCode); }); + connect(level2ProductsWidget_, + &ui::Level2ProductsWidget::RadarProductSelected, + mainWindow_, + [&](common::RadarProductGroup group, + const std::string& productName, + int16_t productCode) { + SelectRadarProduct(activeMap_, group, productName, productCode); + }); + connect(level3ProductsWidget_, + &ui::Level3ProductsWidget::RadarProductSelected, + mainWindow_, + [&](common::RadarProductGroup group, + const std::string& productName, + int16_t productCode) { + SelectRadarProduct(activeMap_, group, productName, productCode); + }); connect(level2SettingsWidget_, &ui::Level2SettingsWidget::ElevationSelected, mainWindow_, @@ -1300,33 +1194,11 @@ void MainWindowImpl::ConnectOtherSignals() this, [this]() { - timeLabel_->setText( - QString::fromStdString(util::TimeString(util::time::now()))); + timeLabel_->setText(QString::fromStdString( + util::TimeString(std::chrono::system_clock::now()))); timeLabel_->setVisible(true); }); clockTimer_.start(1000); - - auto& generalSettings = settings::GeneralSettings::Instance(); - homeRadarConnection_ = - generalSettings.default_radar_site().changed_signal().connect( - [this]() - { - const std::shared_ptr radarSite = - activeMap_->GetRadarSite(); - const std::string homeRadarSite = - settings::GeneralSettings::Instance() - .default_radar_site() - .GetValue(); - if (radarSite == nullptr) - { - mainWindow_->ui->saveRadarProductsButton->setVisible(false); - } - else - { - mainWindow_->ui->saveRadarProductsButton->setVisible( - radarSite->id() == homeRadarSite); - } - }); } void MainWindowImpl::InitializeLayerDisplayActions() @@ -1491,8 +1363,7 @@ void MainWindowImpl::SelectRadarProduct(map::MapWidget* mapWidget, UpdateRadarProductSettings(); } - mapWidget->SelectRadarProduct( - group, productName, productCode, selectedTime_); + mapWidget->SelectRadarProduct(group, productName, productCode, volumeTime_); } void MainWindowImpl::SetActiveMap(map::MapWidget* mapWidget) @@ -1562,28 +1433,18 @@ void MainWindowImpl::UpdateRadarProductSettings() { if (activeMap_->GetRadarProductGroup() == common::RadarProductGroup::Level2) { - level2SettingsGroup_->setVisible(true); - // This should be done after setting visible for correct sizing level2SettingsWidget_->UpdateSettings(activeMap_); + level2SettingsGroup_->setVisible(true); } else { level2SettingsGroup_->setVisible(false); } - - mainWindow_->ui->smoothRadarDataCheckBox->setCheckState( - activeMap_->GetSmoothingEnabled() ? Qt::CheckState::Checked : - Qt::CheckState::Unchecked); - - mainWindow_->ui->actionRadarWireframe->setChecked( - activeMap_->GetRadarWireframeEnabled()); } void MainWindowImpl::UpdateRadarSite() { std::shared_ptr radarSite = activeMap_->GetRadarSite(); - const std::string homeRadarSite = - settings::GeneralSettings::Instance().default_radar_site().GetValue(); if (radarSite != nullptr) { @@ -1598,9 +1459,6 @@ void MainWindowImpl::UpdateRadarSite() radarSite->location_name().c_str()); timelineManager_->SetRadarSite(radarSite->id()); - - mainWindow_->ui->saveRadarProductsButton->setVisible(radarSite->id() == - homeRadarSite); } else { @@ -1608,15 +1466,12 @@ void MainWindowImpl::UpdateRadarSite() mainWindow_->ui->radarSiteValueLabel->setVisible(false); mainWindow_->ui->radarLocationLabel->setVisible(false); - mainWindow_->ui->saveRadarProductsButton->setVisible(false); timelineManager_->SetRadarSite("?"); } alertManager_->SetRadarSite(radarSite); placefileManager_->SetRadarSite(radarSite); - - animationDockWidget_->UpdateTimeZone(activeMap_->GetDefaultTimeZone()); } void MainWindowImpl::UpdateVcp() diff --git a/scwx-qt/source/scwx/qt/main/main_window.hpp b/scwx-qt/source/scwx/qt/main/main_window.hpp index 6eb7fee2..33043308 100644 --- a/scwx-qt/source/scwx/qt/main/main_window.hpp +++ b/scwx-qt/source/scwx/qt/main/main_window.hpp @@ -29,7 +29,6 @@ public: void keyPressEvent(QKeyEvent* ev) override final; void keyReleaseEvent(QKeyEvent* ev) override final; void showEvent(QShowEvent* event) override; - void closeEvent(QCloseEvent* event) override; signals: void ActiveMapMoved(double latitude, double longitude); @@ -44,12 +43,10 @@ private slots: void on_actionRadarRange_triggered(bool checked); void on_actionRadarSites_triggered(bool checked); void on_actionPlacefileManager_triggered(); - void on_actionMarkerManager_triggered(); void on_actionLayerManager_triggered(); void on_actionImGuiDebug_triggered(); void on_actionDumpLayerList_triggered(); void on_actionDumpRadarProductRecords_triggered(); - void on_actionRadarWireframe_triggered(bool checked); void on_actionUserManual_triggered(); void on_actionDiscord_triggered(); void on_actionGitHubRepository_triggered(); diff --git a/scwx-qt/source/scwx/qt/main/main_window.ui b/scwx-qt/source/scwx/qt/main/main_window.ui index e760bab2..9fab1adf 100644 --- a/scwx-qt/source/scwx/qt/main/main_window.ui +++ b/scwx-qt/source/scwx/qt/main/main_window.ui @@ -39,7 +39,7 @@ 0 0 1024 - 21 + 33 @@ -97,8 +97,6 @@ - - @@ -106,7 +104,6 @@ - @@ -155,8 +152,8 @@ 0 0 - 191 - 703 + 190 + 686 @@ -174,25 +171,39 @@ + + QFrame::Shape::StyledPanel + + + QFrame::Shadow::Raised + - - + + + + + 0 + 0 + + - 35 + KLSX - - - - Clear Air Mode + + + + + 0 + 0 + + + + Volume Coverage Pattern - - - - - St. Louis, MO + VCP @@ -257,6 +268,34 @@ + + + + Radar Site + + + + + + + St. Louis, MO + + + + + + + 35 + + + + + + + Clear Air Mode + + + @@ -270,42 +309,6 @@ - - - - - 0 - 0 - - - - Volume Coverage Pattern - - - VCP - - - - - - - Radar Site - - - - - - - - 0 - 0 - - - - KLSX - - - @@ -325,13 +328,6 @@ - - - - Smooth Radar Data - - - @@ -339,13 +335,6 @@ - - - - Set As Default Products - - - @@ -498,23 +487,6 @@ &GPS Info - - - - :/res/icons/font-awesome-6/house-solid.svg:/res/icons/font-awesome-6/house-solid.svg - - - Location &Marker Manager - - - - - true - - - Radar &Wireframe - - diff --git a/scwx-qt/source/scwx/qt/main/process_validation.cpp b/scwx-qt/source/scwx/qt/main/process_validation.cpp deleted file mode 100644 index 61f2cb29..00000000 --- a/scwx-qt/source/scwx/qt/main/process_validation.cpp +++ /dev/null @@ -1,109 +0,0 @@ -#include -#include - -#if defined(_WIN32) -# include - -# include -# include - -# include -# include -# include -# include -# include -#endif - -namespace scwx::qt::main -{ - -static const std::string logPrefix_ = "scwx::qt::main::process_validation"; -static const auto logger_ = util::Logger::Create(logPrefix_); - -void CheckProcessModules() -{ -#if defined(_WIN32) - HANDLE process = GetCurrentProcess(); - HMODULE modules[1024]; - DWORD cbNeeded = 0; - - std::vector incompatibleDlls {}; - std::vector descriptions {}; - - auto& processModuleWarningsEnabled = - settings::GeneralSettings::Instance().process_module_warnings_enabled(); - - if (EnumProcessModules(process, modules, sizeof(modules), &cbNeeded)) - { - std::uint32_t numModules = cbNeeded / sizeof(HMODULE); - for (std::uint32_t i = 0; i < numModules; ++i) - { - char modulePath[MAX_PATH]; - if (GetModuleFileNameExA(process, modules[i], modulePath, MAX_PATH)) - { - std::string path = modulePath; - - logger_->trace("DLL Found: {}", path); - - if (boost::algorithm::iends_with(path, "NahimicOSD.dll")) - { - std::string description = - QObject::tr( - "ASUS Sonic Studio injects a Nahimic driver, which causes " - "Supercell Wx to hang. It is suggested to disable the " - "Nahimic service, or to uninstall ASUS Sonic Studio and " - "the Nahimic driver.") - .toStdString(); - - logger_->warn("Incompatible DLL found: {}", path); - logger_->warn("{}", description); - - // Only populate vectors for the message box if warnings are - // enabled - if (processModuleWarningsEnabled.GetValue()) - { - incompatibleDlls.push_back(path); - descriptions.push_back(description); - } - } - } - } - } - - if (!incompatibleDlls.empty()) - { - const std::string header = - QObject::tr( - "The following DLLs have been injected into the Supercell Wx " - "process:") - .toStdString(); - const std::string defaultMessage = - QObject::tr( - "Supercell Wx is known to not run correctly with these DLLs " - "injected. We suggest stopping or uninstalling these services if " - "you experience crashes or unexpected behavior while using " - "Supercell Wx.") - .toStdString(); - - std::string message = fmt::format("{}\n\n{}\n\n{}\n\n{}", - header, - fmt::join(incompatibleDlls, "\n"), - defaultMessage, - fmt::join(descriptions, "\n")); - - QMessageBox dialog(QMessageBox::Icon::Warning, - QObject::tr("Supercell Wx"), - QString::fromStdString(message)); - QCheckBox* checkBox = - new QCheckBox(QObject::tr("Don't show this message again"), &dialog); - dialog.setCheckBox(checkBox); - dialog.exec(); - - // Stage the result of the checkbox. This value will be committed on - // shutdown. - processModuleWarningsEnabled.StageValue(!checkBox->isChecked()); - } -#endif -} - -} // namespace scwx::qt::main diff --git a/scwx-qt/source/scwx/qt/main/process_validation.hpp b/scwx-qt/source/scwx/qt/main/process_validation.hpp deleted file mode 100644 index fb8fabaf..00000000 --- a/scwx-qt/source/scwx/qt/main/process_validation.hpp +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -namespace scwx::qt::main -{ - -void CheckProcessModules(); - -} // namespace scwx::qt::main diff --git a/scwx-qt/source/scwx/qt/main/versions.hpp.in b/scwx-qt/source/scwx/qt/main/versions.hpp.in index bdf9cd62..32a69c59 100644 --- a/scwx-qt/source/scwx/qt/main/versions.hpp.in +++ b/scwx-qt/source/scwx/qt/main/versions.hpp.in @@ -3,12 +3,17 @@ #include #include -namespace scwx::qt::main +namespace scwx +{ +namespace qt +{ +namespace main { -const std::uint32_t kBuildNumber_ {${build_number}u}; const std::string kCommitString_ {"${commit_string}"}; const std::uint16_t kCopyrightYear_ {${copyright_year}u}; const std::string kVersionString_ {"${version_string}"}; -} // namespace scwx::qt::main +} // namespace main +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/manager/alert_manager.cpp b/scwx-qt/source/scwx/qt/manager/alert_manager.cpp index 41e74d7a..757754a9 100644 --- a/scwx-qt/source/scwx/qt/manager/alert_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/alert_manager.cpp @@ -2,13 +2,12 @@ #include #include #include -#include #include -#include #include #include #include -#include +#include +#include #include #include @@ -139,10 +138,8 @@ common::Coordinate AlertManager::Impl::CurrentCoordinate( void AlertManager::Impl::HandleAlert(const types::TextEventKey& key, size_t messageIndex) const { - auto messages = textEventManager_->message_list(key); - // Skip alert if there are more messages to be processed - if (messages.empty() || messageIndex + 1 < messages.size()) + if (messageIndex + 1 < textEventManager_->message_count(key)) { return; } @@ -156,7 +153,7 @@ void AlertManager::Impl::HandleAlert(const types::TextEventKey& key, audioSettings.alert_radius().GetValue()); std::string alertWFO = audioSettings.alert_wfo().GetValue(); - auto message = messages.at(messageIndex); + auto message = textEventManager_->message_list(key).at(messageIndex); for (auto& segment : message->segments()) { @@ -173,7 +170,7 @@ void AlertManager::Impl::HandleAlert(const types::TextEventKey& key, // If the event has ended or is inactive, or if the alert is not enabled, // skip it - if (eventEnd < scwx::util::time::now() || !alertActive || + if (eventEnd < std::chrono::system_clock::now() || !alertActive || !audioSettings.alert_enabled(phenomenon).GetValue()) { continue; diff --git a/scwx-qt/source/scwx/qt/manager/download_manager.cpp b/scwx-qt/source/scwx/qt/manager/download_manager.cpp index 54dd4371..b0585b35 100644 --- a/scwx-qt/source/scwx/qt/manager/download_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/download_manager.cpp @@ -155,7 +155,7 @@ void DownloadManager::Impl::DownloadSync( return !request->IsCanceled(); }), cpr::WriteCallback( - [&](const std::string_view& data, std::intptr_t /* userdata */) + [&](std::string data, std::intptr_t /* userdata */) { // Write file ofs << data; diff --git a/scwx-qt/source/scwx/qt/manager/font_manager.cpp b/scwx-qt/source/scwx/qt/manager/font_manager.cpp index fc645388..20f5f9a6 100644 --- a/scwx-qt/source/scwx/qt/manager/font_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/font_manager.cpp @@ -15,17 +15,19 @@ #include #include #include -#include #include -namespace scwx::qt::manager +namespace scwx +{ +namespace qt +{ +namespace manager { static const std::string logPrefix_ = "scwx::qt::manager::font_manager"; static const auto logger_ = scwx::util::Logger::Create(logPrefix_); static const std::string kFcTrueType_ {"TrueType"}; -static const std::string kFcOpenType_ {"CFF"}; struct FontRecord { @@ -34,13 +36,15 @@ struct FontRecord std::string filename_ {}; }; +typedef std::pair> FontRecordPair; + template struct FontRecordHash; template<> -struct FontRecordHash +struct FontRecordHash { - size_t operator()(const FontRecord& x) const; + size_t operator()(const FontRecordPair& x) const; }; class FontManager::Impl @@ -65,7 +69,6 @@ public: const std::vector& GetRawFontData(const std::string& filename); - static bool CheckFontFormat(const FcChar8* format); static FontRecord MatchFontFile(const std::string& family, const std::vector& styles); @@ -75,20 +78,20 @@ public: std::shared_mutex imguiFontAtlasMutex_ {}; - boost::unordered_flat_map, - FontRecordHash> + FontRecordHash> imguiFonts_ {}; std::shared_mutex imguiFontsMutex_ {}; boost::unordered_flat_map> rawFontData_ {}; std::mutex rawFontDataMutex_ {}; - std::pair, units::font_size::pixels> - defaultFont_ {}; + std::shared_ptr defaultFont_ {}; boost::unordered_flat_map, - units::font_size::pixels>> + std::shared_ptr> fontCategoryImguiFontMap_ {}; boost::unordered_flat_map fontCategoryQFontMap_ {}; @@ -133,22 +136,22 @@ void FontManager::Impl::ConnectSignals() }); } - QObject::connect(&SettingsManager::Instance(), - &SettingsManager::SettingsSaved, - self_, - [this]() - { - const std::scoped_lock lock {dirtyFontsMutex_, - fontCategoryMutex_}; + QObject::connect( + &SettingsManager::Instance(), + &SettingsManager::SettingsSaved, + self_, + [this]() + { + std::scoped_lock lock {dirtyFontsMutex_, fontCategoryMutex_}; - for (auto fontCategory : dirtyFonts_) - { - UpdateImGuiFont(fontCategory); - UpdateQFont(fontCategory); - } + for (auto fontCategory : dirtyFonts_) + { + UpdateImGuiFont(fontCategory); + UpdateQFont(fontCategory); + } - dirtyFonts_.clear(); - }); + dirtyFonts_.clear(); + }); } void FontManager::InitializeFonts() @@ -160,22 +163,6 @@ void FontManager::InitializeFonts() } } -units::font_size::pixels -FontManager::ImFontSize(units::font_size::pixels size) -{ - static constexpr units::font_size::pixels kMinFontSize_ {8}; - static constexpr units::font_size::pixels kMaxFontSize_ {96}; - - // Only allow whole pixels, and clamp to 6-72 pt - const units::font_size::pixels pixels {size}; - const units::font_size::pixels imFontSize { - std::clamp(static_cast(pixels.value()), - kMinFontSize_.value(), - kMaxFontSize_.value())}; - - return imFontSize; -} - void FontManager::Impl::UpdateImGuiFont(types::FontCategory fontCategory) { auto& textSettings = settings::TextSettings::Instance(); @@ -186,8 +173,7 @@ void FontManager::Impl::UpdateImGuiFont(types::FontCategory fontCategory) textSettings.font_point_size(fontCategory).GetValue()}; fontCategoryImguiFontMap_.insert_or_assign( - fontCategory, - std::make_pair(self_->LoadImGuiFont(family, {styles}), ImFontSize(size))); + fontCategory, self_->LoadImGuiFont(family, {styles}, size)); } void FontManager::Impl::UpdateQFont(types::FontCategory fontCategory) @@ -202,13 +188,7 @@ void FontManager::Impl::UpdateQFont(types::FontCategory fontCategory) QFont font = QFontDatabase::font(QString::fromStdString(family), QString::fromStdString(styles), static_cast(size.value())); - -#if !defined(__APPLE__) font.setPointSizeF(size.value()); -#else - const units::font_size::pixels pixelSize {size}; - font.setPixelSize(static_cast(pixelSize.value())); -#endif fontCategoryQFontMap_.insert_or_assign(fontCategory, font); } @@ -218,6 +198,11 @@ std::shared_mutex& FontManager::imgui_font_atlas_mutex() return p->imguiFontAtlasMutex_; } +std::uint64_t FontManager::imgui_fonts_build_count() const +{ + return p->imguiFontsBuildCount_; +} + int FontManager::GetFontId(types::Font font) const { auto it = p->fontIds_.find(font); @@ -228,7 +213,7 @@ int FontManager::GetFontId(types::Font font) const return -1; } -std::pair, units::font_size::pixels> +std::shared_ptr FontManager::GetImGuiFont(types::FontCategory fontCategory) { std::unique_lock lock {p->fontCategoryMutex_}; @@ -256,23 +241,31 @@ QFont FontManager::GetQFont(types::FontCategory fontCategory) } std::shared_ptr -FontManager::LoadImGuiFont(const std::string& family, - const std::vector& styles, - bool loadIfNotFound) +FontManager::LoadImGuiFont(const std::string& family, + const std::vector& styles, + units::font_size::points size, + bool loadIfNotFound) { const std::string styleString = fmt::format("{}", fmt::join(styles, " ")); - const std::string fontString = fmt::format("{}:{}", family, styleString); + const std::string fontString = + fmt::format("{}-{}:{}", family, size.value(), styleString); logger_->debug("LoadFontResource: {}", fontString); FontRecord fontRecord = Impl::MatchFontFile(family, styles); + // Only allow whole pixels, and clamp to 6-72 pt + units::font_size::pixels pixels {size}; + units::font_size::pixels imFontSize { + std::clamp(static_cast(pixels.value()), 8, 96)}; + auto imguiFontKey = std::make_pair(fontRecord, imFontSize); + // Search for a loaded ImGui font { std::shared_lock imguiFontLock {p->imguiFontsMutex_}; // Search for the associated ImGui font - auto it = p->imguiFonts_.find(fontRecord); + auto it = p->imguiFonts_.find(imguiFontKey); if (it != p->imguiFonts_.end()) { return it->second; @@ -297,7 +290,7 @@ FontManager::LoadImGuiFont(const std::string& family, // Search for the associated ImGui font again, to prevent loading the same // font twice - auto it = p->imguiFonts_.find(fontRecord); + auto it = p->imguiFonts_.find(imguiFontKey); if (it != p->imguiFonts_.end()) { return it->second; @@ -308,20 +301,25 @@ FontManager::LoadImGuiFont(const std::string& family, try { fontName = fmt::format( - "{}", std::filesystem::path(fontRecord.filename_).filename().string()); + "{}:{}", + std::filesystem::path(fontRecord.filename_).filename().string(), + imFontSize.value()); } catch (const std::exception& ex) { logger_->warn(ex.what()); - fontName = fmt::format("{}", fontRecord.filename_); + fontName = fmt::format("{}:{}", fontRecord.filename_, imFontSize.value()); } // Create an ImGui font std::shared_ptr imguiFont = - std::make_shared(fontName, rawFontData); + std::make_shared(fontName, rawFontData, imFontSize); // Store the ImGui font - p->imguiFonts_.insert_or_assign(fontRecord, imguiFont); + p->imguiFonts_.insert_or_assign(imguiFontKey, imguiFont); + + // Increment ImGui font build count + ++p->imguiFontsBuildCount_; // Return the ImGui font return imguiFont; @@ -458,13 +456,6 @@ void FontManager::Impl::FinalizeFontconfig() FcFini(); } -bool FontManager::Impl::CheckFontFormat(const FcChar8* format) -{ - const std::string stdFormat = reinterpret_cast(format); - - return stdFormat == kFcTrueType_ || stdFormat == kFcOpenType_; -} - FontRecord FontManager::Impl::MatchFontFile(const std::string& family, const std::vector& styles) @@ -477,7 +468,9 @@ FontManager::Impl::MatchFontFile(const std::string& family, FcPatternAddString( pattern, FC_FAMILY, reinterpret_cast(family.c_str())); - FcPatternAddBool(pattern, FC_SYMBOL, FcFalse); + FcPatternAddString(pattern, + FC_FONTFORMAT, + reinterpret_cast(kFcTrueType_.c_str())); if (!styles.empty()) { @@ -491,55 +484,29 @@ FontManager::Impl::MatchFontFile(const std::string& family, FcDefaultSubstitute(pattern); // Find matching font - FcResult result {}; - FcFontSet* matches = FcFontSort(nullptr, pattern, FcFalse, nullptr, &result); + FcResult result; + FcPattern* match = FcFontMatch(nullptr, pattern, &result); FontRecord record {}; - if (matches != nullptr) + if (match != nullptr) { - for (int i = 0; i < matches->nfont; i++) + FcChar8* fcFamily; + FcChar8* fcStyle; + FcChar8* fcFile; + + // Match was found, get properties + if (FcPatternGetString(match, FC_FAMILY, 0, &fcFamily) == FcResultMatch && + FcPatternGetString(match, FC_STYLE, 0, &fcStyle) == FcResultMatch && + FcPatternGetString(match, FC_FILE, 0, &fcFile) == FcResultMatch) { - FcPattern* match = - // Using C code requires pointer arithmetic - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - FcFontRenderPrepare(nullptr, pattern, matches->fonts[i]); - if (match == nullptr) - { - continue; - } - FcChar8* fcFamily = nullptr; - FcChar8* fcStyle = nullptr; - FcChar8* fcFile = nullptr; - FcChar8* fcFormat = nullptr; - FcBool fcSymbol = FcFalse; + record.family_ = reinterpret_cast(fcFamily); + record.style_ = reinterpret_cast(fcStyle); + record.filename_ = reinterpret_cast(fcFile); - // Match was found, get properties - if (FcPatternGetString(match, FC_FAMILY, 0, &fcFamily) == - FcResultMatch && - FcPatternGetString(match, FC_STYLE, 0, &fcStyle) == - FcResultMatch && - FcPatternGetString(match, FC_FILE, 0, &fcFile) == FcResultMatch && - FcPatternGetBool(match, FC_SYMBOL, 0, &fcSymbol) == - FcResultMatch && - FcPatternGetString(match, FC_FONTFORMAT, 0, &fcFormat) == - FcResultMatch && - fcSymbol == FcFalse /*Must check fcSymbol manually*/ && - CheckFontFormat(fcFormat)) - { - record.family_ = reinterpret_cast(fcFamily); - record.style_ = reinterpret_cast(fcStyle); - record.filename_ = reinterpret_cast(fcFile); - - logger_->debug("Found matching font: {}:{} ({}) {}", - record.family_, - record.style_, - record.filename_, - fcSymbol); - FcPatternDestroy(match); - break; - } - - FcPatternDestroy(match); + logger_->debug("Found matching font: {}:{} ({})", + record.family_, + record.style_, + record.filename_); } } @@ -549,7 +516,7 @@ FontManager::Impl::MatchFontFile(const std::string& family, } // Cleanup - FcFontSetDestroy(matches); + FcPatternDestroy(match); FcPatternDestroy(pattern); return record; @@ -561,12 +528,13 @@ FontManager& FontManager::Instance() return instance_; } -size_t FontRecordHash::operator()(const FontRecord& x) const +size_t FontRecordHash::operator()(const FontRecordPair& x) const { size_t seed = 0; - boost::hash_combine(seed, x.family_); - boost::hash_combine(seed, x.style_); - boost::hash_combine(seed, x.filename_); + boost::hash_combine(seed, x.first.family_); + boost::hash_combine(seed, x.first.style_); + boost::hash_combine(seed, x.first.filename_); + boost::hash_combine(seed, x.second.value()); return seed; } @@ -577,4 +545,6 @@ bool operator==(const FontRecord& lhs, const FontRecord& rhs) lhs.filename_ == rhs.filename_; } -} // namespace scwx::qt::manager +} // namespace manager +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/manager/font_manager.hpp b/scwx-qt/source/scwx/qt/manager/font_manager.hpp index 50e05d9d..e52d0d16 100644 --- a/scwx-qt/source/scwx/qt/manager/font_manager.hpp +++ b/scwx-qt/source/scwx/qt/manager/font_manager.hpp @@ -26,22 +26,21 @@ public: ~FontManager(); std::shared_mutex& imgui_font_atlas_mutex(); + std::uint64_t imgui_fonts_build_count() const; int GetFontId(types::Font font) const; - std::pair, units::font_size::pixels> + std::shared_ptr GetImGuiFont(types::FontCategory fontCategory); QFont GetQFont(types::FontCategory fontCategory); std::shared_ptr - LoadImGuiFont(const std::string& family, - const std::vector& styles, - bool loadIfNotFound = true); + LoadImGuiFont(const std::string& family, + const std::vector& styles, + units::font_size::points size, + bool loadIfNotFound = true); void LoadApplicationFont(types::Font font, const std::string& filename); void InitializeFonts(); - static units::font_size::pixels - ImFontSize(units::font_size::pixels size); - static FontManager& Instance(); private: diff --git a/scwx-qt/source/scwx/qt/manager/log_manager.cpp b/scwx-qt/source/scwx/qt/manager/log_manager.cpp index 34facaa4..457c8d28 100644 --- a/scwx-qt/source/scwx/qt/manager/log_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/log_manager.cpp @@ -1,14 +1,12 @@ #include #include -#include -#include #include #include #include #include -#include +#include #include #include #include @@ -59,14 +57,6 @@ void LogManager::InitializeLogFile() QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) .toStdString(); p->pid_ = boost::this_process::get_id(); - if (p->pid_ == 2) - { - // The pid == 2 means that this is likely a flatpak. We assign a random - // number in this case to avoid overlap, scince it is always 2 in a - // flatpak - std::srand(std::time({})); - p->pid_ = std::rand(); - } p->logFile_ = fmt::format("{}/supercell-wx.{}.log", p->logPath_, p->pid_); // Create log directory if it doesn't exist diff --git a/scwx-qt/source/scwx/qt/manager/marker_manager.cpp b/scwx-qt/source/scwx/qt/manager/marker_manager.cpp deleted file mode 100644 index 8af310ec..00000000 --- a/scwx-qt/source/scwx/qt/manager/marker_manager.cpp +++ /dev/null @@ -1,524 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -namespace scwx -{ -namespace qt -{ -namespace manager -{ - -static const std::string logPrefix_ = "scwx::qt::manager::marker_manager"; -static const auto logger_ = scwx::util::Logger::Create(logPrefix_); - -static const std::string kNameName_ = "name"; -static const std::string kLatitudeName_ = "latitude"; -static const std::string kLongitudeName_ = "longitude"; -static const std::string kIconName_ = "icon"; -static const std::string kIconColorName_ = "icon-color"; - -static const std::string defaultIconName = "images/location-marker"; - -class MarkerManager::Impl -{ -public: - class MarkerRecord; - - explicit Impl(MarkerManager* self) : self_ {self} {} - ~Impl() { threadPool_.join(); } - - std::string markerSettingsPath_ {""}; - std::vector> markerRecords_ {}; - std::unordered_map idToIndex_ {}; - std::unordered_map markerIcons_ {}; - - MarkerManager* self_; - - boost::asio::thread_pool threadPool_ {1u}; - std::shared_mutex markerRecordLock_ {}; - std::shared_mutex markerIconsLock_ {}; - - void InitializeMarkerSettings(); - void ReadMarkerSettings(); - void WriteMarkerSettings(); - std::shared_ptr GetMarkerByName(const std::string& name); - - bool markerFileRead_ {false}; - - void InitalizeIds(); - types::MarkerId NewId(); - types::MarkerId lastId_ {0}; -}; - -class MarkerManager::Impl::MarkerRecord -{ -public: - MarkerRecord(types::MarkerInfo info) : markerInfo_ {std::move(info)} {} - - const types::MarkerInfo& toMarkerInfo() { return markerInfo_; } - - types::MarkerInfo markerInfo_; - - friend void tag_invoke(boost::json::value_from_tag, - boost::json::value& jv, - const std::shared_ptr& record) - { - jv = {{kNameName_, record->markerInfo_.name}, - {kLatitudeName_, record->markerInfo_.latitude}, - {kLongitudeName_, record->markerInfo_.longitude}, - {kIconName_, record->markerInfo_.iconName}, - {kIconColorName_, - util::color::ToArgbString(record->markerInfo_.iconColor)}}; - } - - friend MarkerRecord tag_invoke(boost::json::value_to_tag, - const boost::json::value& jv) - { - static const boost::gil::rgba8_pixel_t defaultIconColor = - util::color::ToRgba8PixelT("#ffff0000"); - - const boost::json::object& jo = jv.as_object(); - - std::string iconName = defaultIconName; - boost::gil::rgba8_pixel_t iconColor = defaultIconColor; - - if (jo.contains(kIconName_) && jo.at(kIconName_).is_string()) - { - iconName = boost::json::value_to(jv.at(kIconName_)); - } - - if (jo.contains(kIconColorName_) && jo.at(kIconName_).is_string()) - { - try - { - iconColor = util::color::ToRgba8PixelT( - boost::json::value_to(jv.at(kIconColorName_))); - } - catch (const std::exception& ex) - { - logger_->warn( - "Could not parse color value in location-markers.json with the " - "following exception: {}", - ex.what()); - } - } - - return {types::MarkerInfo( - boost::json::value_to(jv.at(kNameName_)), - boost::json::value_to(jv.at(kLatitudeName_)), - boost::json::value_to(jv.at(kLongitudeName_)), - iconName, - iconColor)}; - } -}; - -void MarkerManager::Impl::InitalizeIds() -{ - lastId_ = 0; -} - -types::MarkerId MarkerManager::Impl::NewId() -{ - return ++lastId_; -} - -void MarkerManager::Impl::InitializeMarkerSettings() -{ - std::string appDataPath { - QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) - .toStdString()}; - - if (!std::filesystem::exists(appDataPath)) - { - if (!std::filesystem::create_directories(appDataPath)) - { - logger_->error("Unable to create application data directory: \"{}\"", - appDataPath); - } - } - - markerSettingsPath_ = appDataPath + "/location-markers.json"; -} - -void MarkerManager::Impl::ReadMarkerSettings() -{ - logger_->info("Reading location marker settings"); - InitalizeIds(); - - boost::json::value markerJson = nullptr; - { - const std::unique_lock lock(markerRecordLock_); - - // Determine if marker settings exists - if (std::filesystem::exists(markerSettingsPath_)) - { - markerJson = scwx::util::json::ReadJsonFile(markerSettingsPath_); - } - - if (markerJson != nullptr && markerJson.is_array()) - { - // For each marker entry - auto& markerArray = markerJson.as_array(); - markerRecords_.reserve(markerArray.size()); - idToIndex_.reserve(markerArray.size()); - for (auto& markerEntry : markerArray) - { - try - { - auto record = boost::json::value_to(markerEntry); - - const types::MarkerId id = NewId(); - const size_t index = markerRecords_.size(); - record.markerInfo_.id = id; - markerRecords_.emplace_back( - std::make_shared(record.markerInfo_)); - idToIndex_.emplace(id, index); - - self_->add_icon(record.markerInfo_.iconName, true); - } - catch (const std::exception& ex) - { - logger_->warn("Invalid location marker entry: {}", ex.what()); - } - } - - ResourceManager::BuildAtlas(); - - logger_->debug("{} location marker entries", markerRecords_.size()); - } - } - - markerFileRead_ = true; - Q_EMIT self_->MarkersUpdated(); -} - -void MarkerManager::Impl::WriteMarkerSettings() -{ - if (!markerFileRead_) - { - return; - } - logger_->info("Saving location marker settings"); - - const std::shared_lock lock(markerRecordLock_); - auto markerJson = boost::json::value_from(markerRecords_); - scwx::util::json::WriteJsonFile(markerSettingsPath_, markerJson); -} - -std::shared_ptr -MarkerManager::Impl::GetMarkerByName(const std::string& name) -{ - for (auto& markerRecord : markerRecords_) - { - if (markerRecord->markerInfo_.name == name) - { - return markerRecord; - } - } - - return nullptr; -} - -MarkerManager::MarkerManager() : p(std::make_unique(this)) -{ - static const std::vector defaultMarkerIcons_ { - types::MarkerIconInfo(types::ImageTexture::LocationMarker, -1, -1), - types::MarkerIconInfo(types::ImageTexture::LocationPin, 6, 16), - types::MarkerIconInfo(types::ImageTexture::LocationCrosshair, -1, -1), - types::MarkerIconInfo(types::ImageTexture::LocationStar, -1, -1), - types::MarkerIconInfo(types::ImageTexture::LocationBriefcase, -1, -1), - types::MarkerIconInfo( - types::ImageTexture::LocationBuildingColumns, -1, -1), - types::MarkerIconInfo(types::ImageTexture::LocationBuilding, -1, -1), - types::MarkerIconInfo(types::ImageTexture::LocationCaravan, -1, -1), - types::MarkerIconInfo(types::ImageTexture::LocationHouse, -1, -1), - types::MarkerIconInfo(types::ImageTexture::LocationTent, -1, -1), - }; - - p->InitializeMarkerSettings(); - - boost::asio::post(p->threadPool_, - [this]() - { - try - { - // Read Marker settings on startup - main::Application::WaitForInitialization(); - { - const std::unique_lock lock(p->markerIconsLock_); - p->markerIcons_.reserve( - defaultMarkerIcons_.size()); - for (auto& icon : defaultMarkerIcons_) - { - p->markerIcons_.emplace(icon.name, icon); - } - } - p->ReadMarkerSettings(); - - Q_EMIT IconsReady(); - Q_EMIT MarkersInitialized(p->markerRecords_.size()); - } - catch (const std::exception& ex) - { - logger_->error(ex.what()); - } - }); -} - -MarkerManager::~MarkerManager() -{ - p->WriteMarkerSettings(); -} - -size_t MarkerManager::marker_count() -{ - return p->markerRecords_.size(); -} - -std::optional MarkerManager::get_marker(types::MarkerId id) -{ - const std::shared_lock lock(p->markerRecordLock_); - if (!p->idToIndex_.contains(id)) - { - return {}; - } - size_t index = p->idToIndex_[id]; - if (index >= p->markerRecords_.size()) - { - logger_->warn("id in idToIndex_ but out of range!"); - return {}; - } - std::shared_ptr& markerRecord = - p->markerRecords_[index]; - return markerRecord->toMarkerInfo(); -} - -std::optional MarkerManager::get_index(types::MarkerId id) -{ - const std::shared_lock lock(p->markerRecordLock_); - if (!p->idToIndex_.contains(id)) - { - return {}; - } - return p->idToIndex_[id]; -} - -void MarkerManager::set_marker(types::MarkerId id, - const types::MarkerInfo& marker) -{ - { - const std::unique_lock lock(p->markerRecordLock_); - if (!p->idToIndex_.contains(id)) - { - return; - } - size_t index = p->idToIndex_[id]; - if (index >= p->markerRecords_.size()) - { - logger_->warn("id in idToIndex_ but out of range!"); - return; - } - const std::shared_ptr& markerRecord = - p->markerRecords_[index]; - markerRecord->markerInfo_ = marker; - markerRecord->markerInfo_.id = id; - - add_icon(marker.iconName); - } - Q_EMIT MarkerChanged(id); - Q_EMIT MarkersUpdated(); -} - -types::MarkerId MarkerManager::add_marker(const types::MarkerInfo& marker) -{ - types::MarkerId id; - { - const std::unique_lock lock(p->markerRecordLock_); - id = p->NewId(); - size_t index = p->markerRecords_.size(); - p->idToIndex_.emplace(id, index); - p->markerRecords_.emplace_back( - std::make_shared(marker)); - p->markerRecords_[index]->markerInfo_.id = id; - - add_icon(marker.iconName); - } - Q_EMIT MarkerAdded(id); - Q_EMIT MarkersUpdated(); - return id; -} - -void MarkerManager::remove_marker(types::MarkerId id) -{ - { - const std::unique_lock lock(p->markerRecordLock_); - if (!p->idToIndex_.contains(id)) - { - return; - } - size_t index = p->idToIndex_[id]; - if (index >= p->markerRecords_.size()) - { - logger_->warn("id in idToIndex_ but out of range!"); - return; - } - - p->markerRecords_.erase(std::next(p->markerRecords_.begin(), index)); - p->idToIndex_.erase(id); - - for (auto& pair : p->idToIndex_) - { - if (pair.second > index) - { - pair.second -= 1; - } - } - } - - Q_EMIT MarkerRemoved(id); - Q_EMIT MarkersUpdated(); -} - -void MarkerManager::move_marker(size_t from, size_t to) -{ - { - const std::unique_lock lock(p->markerRecordLock_); - if (from >= p->markerRecords_.size() || to >= p->markerRecords_.size()) - { - return; - } - std::shared_ptr& markerRecord = - p->markerRecords_[from]; - - if (from == to) {} - else if (from < to) - { - for (size_t i = from; i < to; i++) - { - p->markerRecords_[i] = p->markerRecords_[i + 1]; - } - p->markerRecords_[to] = markerRecord; - } - else - { - for (size_t i = from; i > to; i--) - { - p->markerRecords_[i] = p->markerRecords_[i - 1]; - } - p->markerRecords_[to] = markerRecord; - } - } - Q_EMIT MarkersUpdated(); -} - -void MarkerManager::for_each(std::function func) -{ - const std::shared_lock lock(p->markerRecordLock_); - for (auto marker : p->markerRecords_) - { - func(marker->markerInfo_); - } -} - -void MarkerManager::add_icon(const std::string& name, bool startup) -{ - { - const std::unique_lock lock(p->markerIconsLock_); - if (p->markerIcons_.contains(name)) - { - return; - } - const std::shared_ptr image = - ResourceManager::LoadImageResource(name); - - if (image) - { - auto icon = types::MarkerIconInfo(name, -1, -1, image); - p->markerIcons_.emplace(name, icon); - } - else - { - // defaultIconName should always be in markerIcons, so at is fine - auto icon = p->markerIcons_.at(defaultIconName); - p->markerIcons_.emplace(name, icon); - } - } - - if (!startup) - { - ResourceManager::BuildAtlas(); - Q_EMIT IconAdded(name); - } -} - -std::optional -MarkerManager::get_icon(const std::string& name) -{ - const std::shared_lock lock(p->markerIconsLock_); - auto it = p->markerIcons_.find(name); - if (it != p->markerIcons_.end()) - { - return it->second; - } - - return {}; -} - -const std::unordered_map -MarkerManager::get_icons() -{ - const std::shared_lock lock(p->markerIconsLock_); - return p->markerIcons_; -} - -// Only use for testing -void MarkerManager::set_marker_settings_path(const std::string& path) -{ - p->markerSettingsPath_ = path; -} - -std::shared_ptr MarkerManager::Instance() -{ - static std::weak_ptr markerManagerReference_ {}; - static std::mutex instanceMutex_ {}; - - const std::unique_lock lock(instanceMutex_); - - std::shared_ptr markerManager = - markerManagerReference_.lock(); - - if (markerManager == nullptr) - { - markerManager = std::make_shared(); - markerManagerReference_ = markerManager; - } - - return markerManager; -} - -const std::string& MarkerManager::getDefaultIconName() -{ - return defaultIconName; -} - -} // namespace manager -} // namespace qt -} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/manager/marker_manager.hpp b/scwx-qt/source/scwx/qt/manager/marker_manager.hpp deleted file mode 100644 index 7004e117..00000000 --- a/scwx-qt/source/scwx/qt/manager/marker_manager.hpp +++ /dev/null @@ -1,61 +0,0 @@ -#pragma once - -#include - -#include -#include - -namespace scwx -{ -namespace qt -{ -namespace manager -{ - -typedef void MarkerForEachFunc(const types::MarkerInfo&); -class MarkerManager : public QObject -{ - Q_OBJECT - -public: - explicit MarkerManager(); - ~MarkerManager(); - - size_t marker_count(); - std::optional get_marker(types::MarkerId id); - std::optional get_index(types::MarkerId id); - void set_marker(types::MarkerId id, const types::MarkerInfo& marker); - types::MarkerId add_marker(const types::MarkerInfo& marker); - void remove_marker(types::MarkerId id); - void move_marker(size_t from, size_t to); - - void add_icon(const std::string& name, bool startup = false); - std::optional get_icon(const std::string& name); - const std::unordered_map get_icons(); - - void for_each(std::function func); - - // Only use for testing - void set_marker_settings_path(const std::string& path); - - static std::shared_ptr Instance(); - static const std::string& getDefaultIconName(); - -signals: - void MarkersInitialized(size_t count); - void MarkersUpdated(); - void MarkerChanged(types::MarkerId id); - void MarkerAdded(types::MarkerId id); - void MarkerRemoved(types::MarkerId id); - - void IconsReady(); - void IconAdded(std::string name); - -private: - class Impl; - std::unique_ptr p; -}; - -} // namespace manager -} // namespace qt -} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/manager/media_manager.cpp b/scwx-qt/source/scwx/qt/manager/media_manager.cpp index 014b9a37..349e73b9 100644 --- a/scwx-qt/source/scwx/qt/manager/media_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/media_manager.cpp @@ -5,10 +5,13 @@ #include #include #include -#include #include -namespace scwx::qt::manager +namespace scwx +{ +namespace qt +{ +namespace manager { static const std::string logPrefix_ = "scwx::qt::manager::media_manager"; @@ -17,80 +20,46 @@ static const auto logger_ = scwx::util::Logger::Create(logPrefix_); class MediaManager::Impl { public: - explicit Impl() + explicit Impl(MediaManager* self) : + self_ {self}, + mediaDevices_ {new QMediaDevices(self)}, + mediaPlayer_ {new QMediaPlayer(self)}, + audioOutput_ {new QAudioOutput(self)} { - mediaParent_ = std::make_unique(); - mediaParent_->moveToThread(&thread_); + logger_->debug("Audio device: {}", + audioOutput_->device().description().toStdString()); - thread_.start(); + mediaPlayer_->setAudioOutput(audioOutput_); - QMetaObject::invokeMethod( - mediaParent_.get(), - [this]() - { - // QObjects are managed by the parent - // NOLINTBEGIN(cppcoreguidelines-owning-memory) - - logger_->debug("Creating QMediaDevices"); - mediaDevices_ = new QMediaDevices(mediaParent_.get()); - logger_->debug("Creating QMediaPlayer"); - mediaPlayer_ = new QMediaPlayer(mediaParent_.get()); - logger_->debug("Creating QAudioOutput"); - audioOutput_ = new QAudioOutput(mediaParent_.get()); - - // NOLINTEND(cppcoreguidelines-owning-memory) - - logger_->debug("Audio device: {}", - audioOutput_->device().description().toStdString()); - - mediaPlayer_->setAudioOutput(audioOutput_); - - ConnectSignals(); - }); + ConnectSignals(); } - ~Impl() - { - // Delete the media parent - mediaParent_.reset(); - - thread_.quit(); - thread_.wait(); - } - - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; + ~Impl() {} void ConnectSignals(); - QThread thread_ {}; + MediaManager* self_; - std::unique_ptr mediaParent_ {nullptr}; - QMediaDevices* mediaDevices_ {nullptr}; - QMediaPlayer* mediaPlayer_ {nullptr}; - QAudioOutput* audioOutput_ {nullptr}; + QMediaDevices* mediaDevices_; + QMediaPlayer* mediaPlayer_; + QAudioOutput* audioOutput_; }; -MediaManager::MediaManager() : p(std::make_unique()) {} +MediaManager::MediaManager() : p(std::make_unique(this)) {} MediaManager::~MediaManager() = default; -MediaManager::MediaManager(MediaManager&&) noexcept = default; -MediaManager& MediaManager::operator=(MediaManager&&) noexcept = default; - void MediaManager::Impl::ConnectSignals() { QObject::connect( mediaDevices_, &QMediaDevices::audioOutputsChanged, - mediaParent_.get(), + self_, [this]() { audioOutput_->setDevice(QMediaDevices::defaultAudioOutput()); }); QObject::connect(audioOutput_, &QAudioOutput::deviceChanged, - mediaParent_.get(), + self_, [this]() { logger_->debug( @@ -100,7 +69,7 @@ void MediaManager::Impl::ConnectSignals() QObject::connect(mediaPlayer_, &QMediaPlayer::errorOccurred, - mediaParent_.get(), + self_, [](QMediaPlayer::Error error, const QString& errorString) { logger_->error("Error {}: {}", @@ -112,46 +81,30 @@ void MediaManager::Impl::ConnectSignals() void MediaManager::Play(types::AudioFile media) { const std::string path = types::GetMediaPath(media); - Play(path); } void MediaManager::Play(const std::string& mediaPath) { logger_->debug("Playing audio: {}", mediaPath); - if (p->mediaPlayer_ == nullptr) - { - logger_->warn("Media player is not yet initialized"); - return; - } - if (mediaPath.starts_with(':')) { - QMetaObject::invokeMethod( - p->mediaPlayer_, - &QMediaPlayer::setSource, + p->mediaPlayer_->setSource( QUrl(QString("qrc%1").arg(QString::fromStdString(mediaPath)))); } else { - QMetaObject::invokeMethod( - p->mediaPlayer_, - &QMediaPlayer::setSource, + p->mediaPlayer_->setSource( QUrl::fromLocalFile(QString::fromStdString(mediaPath))); } - QMetaObject::invokeMethod(p->mediaPlayer_, &QMediaPlayer::setPosition, 0); + p->mediaPlayer_->setPosition(0); + QMetaObject::invokeMethod(p->mediaPlayer_, &QMediaPlayer::play); } void MediaManager::Stop() { - if (p->mediaPlayer_ == nullptr) - { - logger_->warn("Media player is not yet initialized"); - return; - } - QMetaObject::invokeMethod(p->mediaPlayer_, &QMediaPlayer::stop); } @@ -173,4 +126,6 @@ std::shared_ptr MediaManager::Instance() return mediaManager; } -} // namespace scwx::qt::manager +} // namespace manager +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/manager/media_manager.hpp b/scwx-qt/source/scwx/qt/manager/media_manager.hpp index c10dd041..f1d73656 100644 --- a/scwx-qt/source/scwx/qt/manager/media_manager.hpp +++ b/scwx-qt/source/scwx/qt/manager/media_manager.hpp @@ -4,21 +4,24 @@ #include -namespace scwx::qt::manager +#include + +namespace scwx +{ +namespace qt +{ +namespace manager { -class MediaManager +class MediaManager : public QObject { + Q_OBJECT + Q_DISABLE_COPY_MOVE(MediaManager) + public: explicit MediaManager(); ~MediaManager(); - MediaManager(const MediaManager&) = delete; - MediaManager& operator=(const MediaManager&) = delete; - - MediaManager(MediaManager&&) noexcept; - MediaManager& operator=(MediaManager&&) noexcept; - void Play(types::AudioFile media); void Play(const std::string& mediaPath); void Stop(); @@ -30,4 +33,6 @@ private: std::unique_ptr p; }; -} // namespace scwx::qt::manager +} // namespace manager +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/manager/placefile_manager.cpp b/scwx-qt/source/scwx/qt/manager/placefile_manager.cpp index 9685f33f..b324fae3 100644 --- a/scwx-qt/source/scwx/qt/manager/placefile_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/placefile_manager.cpp @@ -2,10 +2,10 @@ #include #include #include +#include #include #include #include -#include #include #include @@ -52,7 +52,8 @@ public: void ReadPlacefileSettings(); void WritePlacefileSettings(); - static FontMap + static boost::unordered_flat_map> LoadFontResources(const std::shared_ptr& placefile); static std::vector> LoadImageResources(const std::shared_ptr& placefile); @@ -69,8 +70,6 @@ public: boost::unordered_flat_map> placefileRecordMap_ {}; std::shared_mutex placefileRecordLock_ {}; - - bool placefileSettingsRead_ {false}; }; class PlacefileManager::Impl::PlacefileRecord @@ -94,7 +93,6 @@ public: { std::unique_lock refreshLock(refreshMutex_); std::unique_lock timerLock(timerMutex_); - enabled_ = false; refreshTimer_.cancel(); timerLock.unlock(); refreshLock.unlock(); @@ -107,8 +105,6 @@ public: void CancelRefresh(); void ScheduleRefresh(); - void ScheduleRefresh( - const std::chrono::system_clock::duration timeUntilNextUpdate); void Update(); void UpdateAsync(); @@ -146,15 +142,14 @@ public: std::mutex refreshMutex_ {}; std::mutex timerMutex_ {}; - FontMap fonts_ {}; + boost::unordered_flat_map> + fonts_ {}; std::mutex fontsMutex_ {}; std::vector> images_ {}; std::string lastRadarSite_ {}; std::chrono::system_clock::time_point lastUpdateTime_ {}; - - std::size_t failureCount_ {}; }; PlacefileManager::PlacefileManager() : p(std::make_unique(this)) @@ -233,7 +228,7 @@ PlacefileManager::placefile(const std::string& name) return nullptr; } -PlacefileManager::FontMap +boost::unordered_flat_map> PlacefileManager::placefile_fonts(const std::string& name) { std::shared_lock lock(p->placefileRecordLock_); @@ -349,8 +344,8 @@ PlacefileManager::Impl::PlacefileRecord::refresh_time() const if (refresh_enabled()) { - // Don't refresh more often than every 1 second - return std::max(placefile_->refresh(), 1s); + // Don't refresh more often than every 15 seconds + return std::max(placefile_->refresh(), 15s); } return -1s; @@ -383,7 +378,7 @@ void PlacefileManager::Impl::ReadPlacefileSettings() // Determine if placefile settings exists if (std::filesystem::exists(placefileSettingsPath_)) { - placefileJson = scwx::util::json::ReadJsonFile(placefileSettingsPath_); + placefileJson = util::json::ReadJsonFile(placefileSettingsPath_); } // If placefile settings was successfully read @@ -413,20 +408,15 @@ void PlacefileManager::Impl::ReadPlacefileSettings() } } } - placefileSettingsRead_ = true; } void PlacefileManager::Impl::WritePlacefileSettings() { - if (!placefileSettingsRead_) - { - return; - } logger_->info("Saving placefile settings"); std::shared_lock lock {placefileRecordLock_}; auto placefileJson = boost::json::value_from(placefileRecords_); - scwx::util::json::WriteJsonFile(placefileSettingsPath_, placefileJson); + util::json::WriteJsonFile(placefileSettingsPath_, placefileJson); } void PlacefileManager::SetRadarSite( @@ -552,11 +542,6 @@ void PlacefileManager::Impl::PlacefileRecord::Update() if (url.isLocalFile()) { updatedPlacefile = gr::Placefile::Load(name); - - if (updatedPlacefile == nullptr) - { - logger_->error("Local placefile not found: {}", name); - } } else { @@ -640,7 +625,6 @@ void PlacefileManager::Impl::PlacefileRecord::Update() placefile_ = updatedPlacefile; title_ = placefile_->title(); lastUpdateTime_ = std::chrono::system_clock::now(); - failureCount_ = 0; // Update font resources { @@ -661,30 +645,10 @@ void PlacefileManager::Impl::PlacefileRecord::Update() // Notify slots of the placefile update Q_EMIT p->self_->PlacefileUpdated(name); } - - // Update refresh timer - ScheduleRefresh(); } - else if (enabled_) - { - using namespace std::chrono_literals; - ++failureCount_; - - // Update refresh timer if the file failed to load, in case it is able to - // be resolved later - if (url.isLocalFile()) - { - ScheduleRefresh(10s); - } - else - { - // Start attempting to refresh at 15 seconds, and start backing off - // until retrying every 60 seconds - ScheduleRefresh( - std::min(15s * failureCount_, 60s)); - } - } + // Update refresh timer + ScheduleRefresh(); } void PlacefileManager::Impl::PlacefileRecord::ScheduleRefresh() @@ -702,12 +666,6 @@ void PlacefileManager::Impl::PlacefileRecord::ScheduleRefresh() auto nextUpdateTime = lastUpdateTime_ + refresh_time(); auto timeUntilNextUpdate = nextUpdateTime - std::chrono::system_clock::now(); - ScheduleRefresh(timeUntilNextUpdate); -} - -void PlacefileManager::Impl::PlacefileRecord::ScheduleRefresh( - const std::chrono::system_clock::duration timeUntilNextUpdate) -{ logger_->debug( "Scheduled refresh in {:%M:%S} ({})", std::chrono::duration_cast(timeUntilNextUpdate), @@ -773,11 +731,13 @@ std::shared_ptr PlacefileManager::Instance() return placefileManager; } -PlacefileManager::FontMap PlacefileManager::Impl::LoadFontResources( +boost::unordered_flat_map> +PlacefileManager::Impl::LoadFontResources( const std::shared_ptr& placefile) { - FontMap imGuiFonts {}; - auto fonts = placefile->fonts(); + boost::unordered_flat_map> + imGuiFonts {}; + auto fonts = placefile->fonts(); for (auto& font : fonts) { @@ -793,11 +753,9 @@ PlacefileManager::FontMap PlacefileManager::Impl::LoadFontResources( styles.push_back("italic"); } - auto imGuiFont = - FontManager::Instance().LoadImGuiFont(font.second->face_, styles); - imGuiFonts.emplace( - font.first, - std::make_pair(std::move(imGuiFont), FontManager::ImFontSize(size))); + auto imGuiFont = FontManager::Instance().LoadImGuiFont( + font.second->face_, styles, size); + imGuiFonts.emplace(font.first, std::move(imGuiFont)); } return imGuiFonts; diff --git a/scwx-qt/source/scwx/qt/manager/placefile_manager.hpp b/scwx-qt/source/scwx/qt/manager/placefile_manager.hpp index 4408fb2f..17b39b2f 100644 --- a/scwx-qt/source/scwx/qt/manager/placefile_manager.hpp +++ b/scwx-qt/source/scwx/qt/manager/placefile_manager.hpp @@ -2,7 +2,6 @@ #include #include -#include #include #include @@ -23,16 +22,12 @@ public: explicit PlacefileManager(); ~PlacefileManager(); - using FontMap = - boost::unordered_flat_map, - units::font_size::pixels>>; - bool placefile_enabled(const std::string& name); bool placefile_thresholded(const std::string& name); std::string placefile_title(const std::string& name); std::shared_ptr placefile(const std::string& name); - FontMap placefile_fonts(const std::string& name); + boost::unordered_flat_map> + placefile_fonts(const std::string& name); void set_placefile_enabled(const std::string& name, bool enabled); void set_placefile_thresholded(const std::string& name, bool thresholded); diff --git a/scwx-qt/source/scwx/qt/manager/radar_product_manager.cpp b/scwx-qt/source/scwx/qt/manager/radar_product_manager.cpp index bda6e232..595cda6d 100644 --- a/scwx-qt/source/scwx/qt/manager/radar_product_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/radar_product_manager.cpp @@ -4,19 +4,17 @@ #include #include #include -#include #include #include #include #include -#include #include +#include #include #include #include #include -#include #if defined(_MSC_VER) # pragma warning(push, 0) @@ -30,7 +28,6 @@ #include #include #include -#include #if defined(_MSC_VER) # pragma warning(pop) @@ -66,12 +63,8 @@ static constexpr uint32_t NUM_COORIDNATES_1_DEGREE = static const std::string kDefaultLevel3Product_ {"N0B"}; -static constexpr std::size_t kTimerPlaces_ {6u}; - static constexpr std::chrono::seconds kFastRetryInterval_ {15}; -static constexpr std::chrono::seconds kFastRetryIntervalChunks_ {3}; static constexpr std::chrono::seconds kSlowRetryInterval_ {120}; -static constexpr std::chrono::seconds kSlowRetryIntervalChunks_ {20}; static std::unordered_map> instanceMap_; @@ -89,25 +82,27 @@ class ProviderManager : public QObject Q_OBJECT public: explicit ProviderManager(RadarProductManager* self, - std::string radarId, + const std::string& radarId, + common::RadarProductGroup group) : + ProviderManager(self, radarId, group, "???") + { + } + explicit ProviderManager(RadarProductManager* self, + const std::string& radarId, common::RadarProductGroup group, - std::string product = "???", - bool isChunks = false) : - radarId_ {std::move(radarId)}, + const std::string& product) : + radarId_ {radarId}, group_ {group}, - product_ {std::move(product)}, - isChunks_ {isChunks} + product_ {product}, + refreshEnabled_ {false}, + refreshTimer_ {threadPool_}, + refreshTimerMutex_ {}, + provider_ {nullptr} { connect(this, &ProviderManager::NewDataAvailable, self, - [this, self](common::RadarProductGroup group, - const std::string& product, - std::chrono::system_clock::time_point latestTime) - { - Q_EMIT self->NewDataAvailable( - group, product, isChunks_, latestTime); - }); + &RadarProductManager::NewDataAvailable); } ~ProviderManager() { threadPool_.join(); }; @@ -120,12 +115,10 @@ public: const std::string radarId_; const common::RadarProductGroup group_; const std::string product_; - const bool isChunks_; - bool refreshEnabled_ {false}; - boost::asio::steady_timer refreshTimer_ {threadPool_}; - std::mutex refreshTimerMutex_ {}; - std::shared_ptr provider_ {nullptr}; - size_t refreshCount_ {0}; + bool refreshEnabled_; + boost::asio::steady_timer refreshTimer_; + std::mutex refreshTimerMutex_; + std::shared_ptr provider_; signals: void NewDataAvailable(common::RadarProductGroup group, @@ -143,10 +136,24 @@ public: initialized_ {false}, level3ProductsInitialized_ {false}, radarSite_ {config::RadarSite::Get(radarId)}, + coordinates0_5Degree_ {}, + coordinates1Degree_ {}, + level2ProductRecords_ {}, + level2ProductRecentRecords_ {}, + level3ProductRecordsMap_ {}, + level3ProductRecentRecordsMap_ {}, + level2ProductRecordMutex_ {}, + level3ProductRecordMutex_ {}, level2ProviderManager_ {std::make_shared( self_, radarId_, common::RadarProductGroup::Level2)}, - level2ChunksProviderManager_ {std::make_shared( - self_, radarId_, common::RadarProductGroup::Level2, "???", true)} + level3ProviderManagerMap_ {}, + level3ProviderManagerMutex_ {}, + initializeMutex_ {}, + level3ProductsInitializeMutex_ {}, + loadLevel2DataMutex_ {}, + loadLevel3DataMutex_ {}, + availableCategoryMap_ {}, + availableCategoryMutex_ {} { if (radarSite_ == nullptr) { @@ -156,27 +163,13 @@ public: level2ProviderManager_->provider_ = provider::NexradDataProviderFactory::CreateLevel2DataProvider(radarId); - level2ChunksProviderManager_->provider_ = - provider::NexradDataProviderFactory::CreateLevel2ChunksDataProvider( - radarId); - - auto level2ChunksProvider = - std::dynamic_pointer_cast( - level2ChunksProviderManager_->provider_); - if (level2ChunksProvider != nullptr) - { - level2ChunksProvider->SetLevel2DataProvider( - std::dynamic_pointer_cast( - level2ProviderManager_->provider_)); - } } ~RadarProductManagerImpl() { level2ProviderManager_->Disable(); - level2ChunksProviderManager_->Disable(); std::shared_lock lock(level3ProviderManagerMutex_); - std::for_each(std::execution::par, + std::for_each(std::execution::par_unseq, level3ProviderManagerMap_.begin(), level3ProviderManagerMap_.end(), [](auto& p) @@ -199,16 +192,15 @@ public: std::shared_ptr GetLevel3ProviderManager(const std::string& product); - void EnableRefresh( - boost::uuids::uuid uuid, - const std::set>& providerManagers, - bool enabled); + void EnableRefresh(boost::uuids::uuid uuid, + std::shared_ptr providerManager, + bool enabled); void RefreshData(std::shared_ptr providerManager); void RefreshDataSync(std::shared_ptr providerManager); - std::map> - GetLevel2ProductRecords(std::chrono::system_clock::time_point time); + std::tuple, + std::chrono::system_clock::time_point> + GetLevel2ProductRecord(std::chrono::system_clock::time_point time); std::tuple, std::chrono::system_clock::time_point> GetLevel3ProductRecord(const std::string& product, @@ -236,13 +228,6 @@ public: void UpdateAvailableProductsSync(); - void - CalculateCoordinates(const boost::integer_range& radialGates, - const units::angle::degrees radialAngle, - const units::angle::degrees angleOffset, - const float gateRangeOffset, - std::vector& outputCoordinates); - static void PopulateProductTimes(std::shared_ptr providerManager, RadarProductRecordMap& productRecordMap, @@ -258,43 +243,37 @@ public: const std::string radarId_; bool initialized_; bool level3ProductsInitialized_; - bool level3AvailabilityReady_ {false}; std::shared_ptr radarSite_; std::size_t cacheLimit_ {6u}; - std::vector coordinates0_5Degree_ {}; - std::vector coordinates0_5DegreeSmooth_ {}; - std::vector coordinates1Degree_ {}; - std::vector coordinates1DegreeSmooth_ {}; + std::vector coordinates0_5Degree_; + std::vector coordinates1Degree_; - RadarProductRecordMap level2ProductRecords_ {}; - RadarProductRecordList level2ProductRecentRecords_ {}; + RadarProductRecordMap level2ProductRecords_; + RadarProductRecordList level2ProductRecentRecords_; std::unordered_map - level3ProductRecordsMap_ {}; + level3ProductRecordsMap_; std::unordered_map - level3ProductRecentRecordsMap_ {}; - std::shared_mutex level2ProductRecordMutex_ {}; - std::shared_mutex level3ProductRecordMutex_ {}; + level3ProductRecentRecordsMap_; + std::shared_mutex level2ProductRecordMutex_; + std::shared_mutex level3ProductRecordMutex_; std::shared_ptr level2ProviderManager_; - std::shared_ptr level2ChunksProviderManager_; std::unordered_map> - level3ProviderManagerMap_ {}; - std::shared_mutex level3ProviderManagerMutex_ {}; + level3ProviderManagerMap_; + std::shared_mutex level3ProviderManagerMutex_; - std::mutex initializeMutex_ {}; - std::mutex level3ProductsInitializeMutex_ {}; - std::mutex loadLevel2DataMutex_ {}; - std::mutex loadLevel3DataMutex_ {}; + std::mutex initializeMutex_; + std::mutex level3ProductsInitializeMutex_; + std::mutex loadLevel2DataMutex_; + std::mutex loadLevel3DataMutex_; - common::Level3ProductCategoryMap availableCategoryMap_ {}; - std::shared_mutex availableCategoryMutex_ {}; - - std::optional incomingLevel2Elevation_ {}; + common::Level3ProductCategoryMap availableCategoryMap_; + std::shared_mutex availableCategoryMutex_; std::unordered_map>, + std::shared_ptr, boost::hash> refreshMap_ {}; std::shared_mutex refreshMapMutex_ {}; @@ -404,29 +383,14 @@ void RadarProductManager::DumpRecords() } const std::vector& -RadarProductManager::coordinates(common::RadialSize radialSize, - bool smoothingEnabled) const +RadarProductManager::coordinates(common::RadialSize radialSize) const { switch (radialSize) { case common::RadialSize::_0_5Degree: - if (smoothingEnabled) - { - return p->coordinates0_5DegreeSmooth_; - } - else - { - return p->coordinates0_5Degree_; - } + return p->coordinates0_5Degree_; case common::RadialSize::_1Degree: - if (smoothingEnabled) - { - return p->coordinates1DegreeSmooth_; - } - else - { - return p->coordinates1Degree_; - } + return p->coordinates1Degree_; default: throw std::invalid_argument("Invalid radial size"); } @@ -449,7 +413,7 @@ const scwx::util::time_zone* RadarProductManager::default_time_zone() const } case types::DefaultTimeZone::Local: -#if (__cpp_lib_chrono >= 201907L) +#if defined(_MSC_VER) return std::chrono::current_zone(); #else return date::current_zone(); @@ -460,21 +424,9 @@ const scwx::util::time_zone* RadarProductManager::default_time_zone() const } } -bool RadarProductManager::is_tdwr() const -{ - return p->radarSite_->type() == "tdwr"; -} - float RadarProductManager::gate_size() const { - // tdwr is 150 meter per gate, wsr88d is 250 meter per gate - // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) - return (is_tdwr()) ? 150.0f : 250.0f; -} - -std::optional RadarProductManager::incoming_level_2_elevation() const -{ - return p->incomingLevel2Elevation_; + return (p->radarSite_->type() == "tdwr") ? 150.0f : 250.0f; } std::string RadarProductManager::radar_id() const @@ -498,59 +450,52 @@ void RadarProductManager::Initialize() logger_->debug("Initialize()"); - if (is_tdwr()) - { - p->initialized_ = true; - return; - } - boost::timer::cpu_timer timer; + const GeographicLib::Geodesic& geodesic( + util::GeographicLib::DefaultGeodesic()); + + const QMapLibre::Coordinate radar(p->radarSite_->latitude(), + p->radarSite_->longitude()); + + const float gateSize = gate_size(); + // Calculate half degree azimuth coordinates timer.start(); std::vector& coordinates0_5Degree = p->coordinates0_5Degree_; coordinates0_5Degree.resize(NUM_COORIDNATES_0_5_DEGREE); - const auto radialGates0_5Degree = + auto radialGates0_5Degree = boost::irange(0, NUM_RADIAL_GATES_0_5_DEGREE); - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers): Values are given - // descriptions - p->CalculateCoordinates( - radialGates0_5Degree, - units::angle::degrees {0.5f}, // Radial angle - units::angle::degrees {0.0f}, // Angle offset - // Far end of the first gate is the gate size distance from the radar site - 1.0f, - coordinates0_5Degree); - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) + std::for_each( + std::execution::par_unseq, + radialGates0_5Degree.begin(), + radialGates0_5Degree.end(), + [&](uint32_t radialGate) + { + const uint16_t gate = + static_cast(radialGate % common::MAX_DATA_MOMENT_GATES); + const uint16_t radial = + static_cast(radialGate / common::MAX_DATA_MOMENT_GATES); + const float angle = radial * 0.5f; // 0.5 degree radial + const float range = (gate + 1) * gateSize; + const size_t offset = radialGate * 2; + + double latitude; + double longitude; + + geodesic.Direct( + radar.first, radar.second, angle, range, latitude, longitude); + + coordinates0_5Degree[offset] = latitude; + coordinates0_5Degree[offset + 1] = longitude; + }); timer.stop(); logger_->debug("Coordinates (0.5 degree) calculated in {}", - timer.format(kTimerPlaces_, "%ws")); - - // Calculate half degree smooth azimuth coordinates - timer.start(); - std::vector& coordinates0_5DegreeSmooth = - p->coordinates0_5DegreeSmooth_; - - coordinates0_5DegreeSmooth.resize(NUM_COORIDNATES_0_5_DEGREE); - - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers): Values are given - // descriptions - p->CalculateCoordinates(radialGates0_5Degree, - units::angle::degrees {0.5f}, // Radial angle - units::angle::degrees {0.25f}, // Angle offset - // Center of the first gate is half the gate size - // distance from the radar site - 0.5f, - coordinates0_5DegreeSmooth); - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - - timer.stop(); - logger_->debug("Coordinates (0.5 degree smooth) calculated in {}", - timer.format(kTimerPlaces_, "%ws")); + timer.format(6, "%ws")); // Calculate 1 degree azimuth coordinates timer.start(); @@ -558,89 +503,38 @@ void RadarProductManager::Initialize() coordinates1Degree.resize(NUM_COORIDNATES_1_DEGREE); - const auto radialGates1Degree = + auto radialGates1Degree = boost::irange(0, NUM_RADIAL_GATES_1_DEGREE); - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers): Values are given - // descriptions - p->CalculateCoordinates( - radialGates1Degree, - units::angle::degrees {1.0f}, // Radial angle - units::angle::degrees {0.0f}, // Angle offset - // Far end of the first gate is the gate size distance from the radar site - 1.0f, - coordinates1Degree); - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - - timer.stop(); - logger_->debug("Coordinates (1 degree) calculated in {}", - timer.format(kTimerPlaces_, "%ws")); - - // Calculate 1 degree smooth azimuth coordinates - timer.start(); - std::vector& coordinates1DegreeSmooth = p->coordinates1DegreeSmooth_; - - coordinates1DegreeSmooth.resize(NUM_COORIDNATES_1_DEGREE); - - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers): Values are given - // descriptions - p->CalculateCoordinates(radialGates1Degree, - units::angle::degrees {1.0f}, // Radial angle - units::angle::degrees {0.5f}, // Angle offset - // Center of the first gate is half the gate size - // distance from the radar site - 0.5f, - coordinates1DegreeSmooth); - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - - timer.stop(); - logger_->debug("Coordinates (1 degree smooth) calculated in {}", - timer.format(kTimerPlaces_, "%ws")); - - p->initialized_ = true; -} - -void RadarProductManagerImpl::CalculateCoordinates( - const boost::integer_range& radialGates, - const units::angle::degrees radialAngle, - const units::angle::degrees angleOffset, - const float gateRangeOffset, - std::vector& outputCoordinates) -{ - const GeographicLib::Geodesic& geodesic( - util::GeographicLib::DefaultGeodesic()); - - const QMapLibre::Coordinate radar(radarSite_->latitude(), - radarSite_->longitude()); - - const float gateSize = self_->gate_size(); - std::for_each( std::execution::par_unseq, - radialGates.begin(), - radialGates.end(), + radialGates1Degree.begin(), + radialGates1Degree.end(), [&](uint32_t radialGate) { - const auto gate = static_cast( - radialGate % common::MAX_DATA_MOMENT_GATES); - const auto radial = static_cast( - radialGate / common::MAX_DATA_MOMENT_GATES); + const uint16_t gate = + static_cast(radialGate % common::MAX_DATA_MOMENT_GATES); + const uint16_t radial = + static_cast(radialGate / common::MAX_DATA_MOMENT_GATES); - const float angle = static_cast(radial) * radialAngle.value() + - angleOffset.value(); - const float range = - (static_cast(gate) + gateRangeOffset) * gateSize; - const std::size_t offset = static_cast(radialGate) * 2; + const float angle = radial * 1.0f; // 1 degree radial + const float range = (gate + 1) * gateSize; + const size_t offset = radialGate * 2; - double latitude = 0.0; - double longitude = 0.0; + double latitude; + double longitude; geodesic.Direct( radar.first, radar.second, angle, range, latitude, longitude); - outputCoordinates[offset] = static_cast(latitude); - outputCoordinates[offset + 1] = static_cast(longitude); + coordinates1Degree[offset] = latitude; + coordinates1Degree[offset + 1] = longitude; }); + timer.stop(); + logger_->debug("Coordinates (1 degree) calculated in {}", + timer.format(6, "%ws")); + + p->initialized_ = true; } std::shared_ptr @@ -673,90 +567,85 @@ void RadarProductManager::EnableRefresh(common::RadarProductGroup group, { if (group == common::RadarProductGroup::Level2) { - p->EnableRefresh( - uuid, - {p->level2ProviderManager_, p->level2ChunksProviderManager_}, - enabled); + p->EnableRefresh(uuid, p->level2ProviderManager_, enabled); } else { - const std::shared_ptr providerManager = + std::shared_ptr providerManager = p->GetLevel3ProviderManager(product); // Only enable refresh on available products - if (enabled) - { - boost::asio::post( - p->threadPool_, - [providerManager, product, uuid, enabled, this]() + boost::asio::post( + p->threadPool_, + [=, this]() + { + try { - try - { - providerManager->provider_->RequestAvailableProducts(); - const auto availableProducts = - providerManager->provider_->GetAvailableProducts(); + providerManager->provider_->RequestAvailableProducts(); + auto availableProducts = + providerManager->provider_->GetAvailableProducts(); - if (std::find(std::execution::par, - availableProducts.cbegin(), - availableProducts.cend(), - product) != availableProducts.cend()) - { - p->EnableRefresh(uuid, {providerManager}, enabled); - } - } - catch (const std::exception& ex) + if (std::find(std::execution::par_unseq, + availableProducts.cbegin(), + availableProducts.cend(), + product) != availableProducts.cend()) { - logger_->error(ex.what()); + p->EnableRefresh(uuid, providerManager, enabled); } - }); - } - else - { - p->EnableRefresh(uuid, {providerManager}, enabled); - } + } + catch (const std::exception& ex) + { + logger_->error(ex.what()); + } + }); } } void RadarProductManagerImpl::EnableRefresh( - boost::uuids::uuid uuid, - const std::set>& providerManagers, - bool enabled) + boost::uuids::uuid uuid, + std::shared_ptr providerManager, + bool enabled) { // Lock the refresh map std::unique_lock lock {refreshMapMutex_}; - auto currentProviderManagers = refreshMap_.find(uuid); - if (currentProviderManagers != refreshMap_.cend()) + auto currentProviderManager = refreshMap_.find(uuid); + if (currentProviderManager != refreshMap_.cend()) { - for (const auto& currentProviderManager : currentProviderManagers->second) + // If the enabling refresh for a different product, or disabling refresh + if (currentProviderManager->second != providerManager || !enabled) { - currentProviderManager->refreshCount_ -= 1; - // If the enabling refresh for a different product, or disabling - // refresh - if (!providerManagers.contains(currentProviderManager) || !enabled) + // Determine number of entries in the map for the current provider + // manager + auto currentProviderManagerCount = std::count_if( + refreshMap_.cbegin(), + refreshMap_.cend(), + [&](const auto& provider) + { return provider.second == currentProviderManager->second; }); + + // If this is the last reference to the provider in the refresh map + if (currentProviderManagerCount == 1) { - // If this is the last reference to the provider in the refresh map - if (currentProviderManager->refreshCount_ == 0) - { - // Disable current provider - currentProviderManager->Disable(); - } + // Disable current provider + currentProviderManager->second->Disable(); + } + + // Dissociate uuid from current provider manager + refreshMap_.erase(currentProviderManager); + + // If we are enabling a new provider manager + if (enabled) + { + // Associate uuid to providerManager + refreshMap_.emplace(uuid, providerManager); } } - - // Dissociate uuid from current provider managers - refreshMap_.erase(currentProviderManagers); } - - if (enabled) + else if (enabled) { - // We are enabling provider managers + // We are enabling a new provider manager // Associate uuid to provider manager - refreshMap_.emplace(uuid, providerManagers); - for (const auto& providerManager : providerManagers) - { - providerManager->refreshCount_ += 1; - } + refreshMap_.emplace(uuid, providerManager); } // Release the refresh map mutex @@ -764,15 +653,13 @@ void RadarProductManagerImpl::EnableRefresh( // We have already handled a disable request by this point. If enabling, and // the provider manager refresh isn't already enabled, enable it. - if (enabled) + if (enabled && providerManager->refreshEnabled_ != enabled) { - for (const auto& providerManager : providerManagers) + providerManager->refreshEnabled_ = enabled; + + if (enabled) { - if (providerManager->refreshEnabled_ != enabled) - { - providerManager->refreshEnabled_ = enabled; - RefreshData(providerManager); - } + RefreshData(providerManager); } } } @@ -780,7 +667,7 @@ void RadarProductManagerImpl::EnableRefresh( void RadarProductManagerImpl::RefreshData( std::shared_ptr providerManager) { - logger_->trace("RefreshData: {}", providerManager->name()); + logger_->debug("RefreshData: {}", providerManager->name()); { std::unique_lock lock(providerManager->refreshTimerMutex_); @@ -808,21 +695,16 @@ void RadarProductManagerImpl::RefreshDataSync( auto [newObjects, totalObjects] = providerManager->provider_->Refresh(); - // Level2 chunked data is updated quickly and uses a faster interval - const std::chrono::milliseconds fastRetryInterval = - providerManager->isChunks_ ? kFastRetryIntervalChunks_ : - kFastRetryInterval_; - const std::chrono::milliseconds slowRetryInterval = - providerManager->isChunks_ ? kSlowRetryIntervalChunks_ : - kSlowRetryInterval_; - std::chrono::milliseconds interval = fastRetryInterval; + std::chrono::milliseconds interval = kFastRetryInterval_; if (totalObjects > 0) { - auto latestTime = providerManager->provider_->FindLatestTime(); + std::string key = providerManager->provider_->FindLatestKey(); + auto latestTime = providerManager->provider_->GetTimePointByKey(key); + auto updatePeriod = providerManager->provider_->update_period(); auto lastModified = providerManager->provider_->last_modified(); - auto sinceLastModified = scwx::util::time::now() - lastModified; + auto sinceLastModified = std::chrono::system_clock::now() - lastModified; // For the default interval, assume products are updated at a // constant rate. Expect the next product at a time based on the @@ -834,12 +716,12 @@ void RadarProductManagerImpl::RefreshDataSync( { // If it has been at least 5 update periods since the file has // been last modified, slow the retry period - interval = slowRetryInterval; + interval = kSlowRetryInterval_; } - else if (interval < std::chrono::milliseconds {fastRetryInterval}) + else if (interval < std::chrono::milliseconds {kFastRetryInterval_}) { // The interval should be no quicker than the fast retry interval - interval = fastRetryInterval; + interval = kFastRetryInterval_; } if (newObjects > 0) @@ -853,14 +735,14 @@ void RadarProductManagerImpl::RefreshDataSync( logger_->info("[{}] No data found", providerManager->name()); // If no data is found, retry at the slow retry interval - interval = slowRetryInterval; + interval = kSlowRetryInterval_; } - std::unique_lock const lock(providerManager->refreshTimerMutex_); - if (providerManager->refreshEnabled_) { - logger_->trace( + std::unique_lock lock(providerManager->refreshTimerMutex_); + + logger_->debug( "[{}] Scheduled refresh in {:%M:%S}", providerManager->name(), std::chrono::duration_cast(interval)); @@ -909,13 +791,10 @@ RadarProductManager::GetActiveVolumeTimes( std::shared_lock refreshLock {p->refreshMapMutex_}; // For each entry in the refresh map (refresh is enabled) - for (auto& refreshSet : p->refreshMap_) + for (auto& refreshEntry : p->refreshMap_) { - for (const auto& refreshEntry : refreshSet.second) - { - // Add the provider for the current entry - providers.insert(refreshEntry->provider_); - } + // Add the provider for the current entry + providers.insert(refreshEntry.second->provider_); } // Unlock the refresh map @@ -928,19 +807,19 @@ RadarProductManager::GetActiveVolumeTimes( // For each provider (in parallel) std::for_each( - std::execution::par, + std::execution::par_unseq, providers.begin(), providers.end(), [&](const std::shared_ptr& provider) { // For yesterday, today and tomorrow (in parallel) - std::for_each(std::execution::par, + std::for_each(std::execution::par_unseq, dates.begin(), dates.end(), [&](const auto& date) { // Don't query for a time point in the future - if (date > scwx::util::time::now()) + if (date > std::chrono::system_clock::now()) { return; } @@ -974,7 +853,7 @@ void RadarProductManagerImpl::LoadProviderData( std::mutex& loadDataMutex, const std::shared_ptr& request) { - logger_->trace("LoadProviderData: {}, {}", + logger_->debug("LoadProviderData: {}, {}", providerManager->name(), scwx::util::TimeString(time)); @@ -994,7 +873,7 @@ void RadarProductManagerImpl::LoadProviderData( if (existingRecord != nullptr) { - logger_->trace( + logger_->debug( "Data previously loaded, loading from data cache"); } } @@ -1002,8 +881,13 @@ void RadarProductManagerImpl::LoadProviderData( if (existingRecord == nullptr) { - nexradFile = providerManager->provider_->LoadObjectByTime(time); - if (nexradFile == nullptr) + std::string key = providerManager->provider_->FindKey(time); + + if (!key.empty()) + { + nexradFile = providerManager->provider_->LoadObjectByKey(key); + } + else { logger_->warn("Attempting to load object without key: {}", scwx::util::TimeString(time)); @@ -1025,7 +909,7 @@ void RadarProductManager::LoadLevel2Data( std::chrono::system_clock::time_point time, const std::shared_ptr& request) { - logger_->trace("LoadLevel2Data: {}", scwx::util::TimeString(time)); + logger_->debug("LoadLevel2Data: {}", scwx::util::TimeString(time)); p->LoadProviderData(time, p->level2ProviderManager_, @@ -1209,10 +1093,6 @@ void RadarProductManagerImpl::PopulateLevel2ProductTimes( level2ProductRecords_, level2ProductRecordMutex_, time); - PopulateProductTimes(level2ChunksProviderManager_, - level2ProductRecords_, - level2ProductRecordMutex_, - time); } void RadarProductManagerImpl::PopulateLevel3ProductTimes( @@ -1254,13 +1134,13 @@ void RadarProductManagerImpl::PopulateProductTimes( std::mutex volumeTimesMutex {}; // For yesterday, today and tomorrow (in parallel) - std::for_each(std::execution::par, + std::for_each(std::execution::par_unseq, dates.begin(), dates.end(), [&](const auto& date) { // Don't query for a time point in the future - if (date > scwx::util::time::now()) + if (date > std::chrono::system_clock::now()) { return; } @@ -1293,91 +1173,60 @@ void RadarProductManagerImpl::PopulateProductTimes( }); } -std::map> -RadarProductManagerImpl::GetLevel2ProductRecords( +std::tuple, + std::chrono::system_clock::time_point> +RadarProductManagerImpl::GetLevel2ProductRecord( std::chrono::system_clock::time_point time) { - std::map> - records {}; - std::vector recordPtrs {}; + std::shared_ptr record {nullptr}; + RadarProductRecordMap::const_pointer recordPtr {nullptr}; + std::chrono::system_clock::time_point recordTime {time}; // Ensure Level 2 product records are updated PopulateLevel2ProductTimes(time); + if (!level2ProductRecords_.empty() && + time == std::chrono::system_clock::time_point {}) { - std::shared_lock lock {level2ProductRecordMutex_}; + // If a default-initialized time point is given, return the latest record + recordPtr = &(*level2ProductRecords_.rbegin()); + } + else + { + recordPtr = + scwx::util::GetBoundedElementPointer(level2ProductRecords_, time); + } - if (!level2ProductRecords_.empty() && - time == std::chrono::system_clock::time_point {}) - { - // If a default-initialized time point is given, return the latest - // record - recordPtrs.push_back(&(*level2ProductRecords_.rbegin())); - } - else - { - // Get the requested record - auto recordIt = - scwx::util::GetBoundedElementIterator(level2ProductRecords_, time); + if (recordPtr != nullptr) + { + // Don't check for an exact time match for level 2 products + recordTime = recordPtr->first; + record = recordPtr->second.lock(); + } - if (recordIt != level2ProductRecords_.cend()) + if (recordPtr != nullptr && record == nullptr && + recordTime != std::chrono::system_clock::time_point {}) + { + // Product is expired, reload it + std::shared_ptr request = + std::make_shared(radarId_); + + QObject::connect( + request.get(), + &request::NexradFileRequest::RequestComplete, + self_, + [this](std::shared_ptr request) { - recordPtrs.push_back(&(*(recordIt))); - - // The requested time may be in the previous record, so get that too - if (recordIt != level2ProductRecords_.cbegin()) + if (request->radar_product_record() != nullptr) { - recordPtrs.push_back(&(*(--recordIt))); + Q_EMIT self_->DataReloaded(request->radar_product_record()); } - } - } + }); + + self_->LoadLevel2Data(recordTime, request); } - // For each record pointer - for (auto& recordPtr : recordPtrs) - { - std::shared_ptr record {nullptr}; - std::chrono::system_clock::time_point recordTime {time}; - - if (recordPtr != nullptr) - { - // Don't check for an exact time match for level 2 products - recordTime = recordPtr->first; - record = recordPtr->second.lock(); - } - - if (recordPtr != nullptr && record == nullptr && - recordTime != std::chrono::system_clock::time_point {}) - { - // Product is expired, reload it - std::shared_ptr request = - std::make_shared(radarId_); - - QObject::connect( - request.get(), - &request::NexradFileRequest::RequestComplete, - self_, - [this](std::shared_ptr request) - { - if (request->radar_product_record() != nullptr) - { - Q_EMIT self_->DataReloaded(request->radar_product_record()); - } - }); - - self_->LoadLevel2Data(recordTime, request); - } - - if (record != nullptr) - { - // Return valid records - records.insert_or_assign(recordTime, record); - } - } - - return records; + return {record, recordTime}; } std::tuple, @@ -1449,7 +1298,7 @@ std::shared_ptr RadarProductManagerImpl::StoreRadarProductRecord( std::shared_ptr record) { - logger_->trace("StoreRadarProductRecord()"); + logger_->debug("StoreRadarProductRecord()"); std::shared_ptr storedRecord = nullptr; @@ -1550,96 +1399,19 @@ RadarProductManager::GetLevel2Data(wsr88d::rda::DataBlockType dataBlockType, { std::shared_ptr radarData = nullptr; float elevationCut = 0.0f; - std::vector elevationCuts {}; - std::chrono::system_clock::time_point foundTime {}; + std::vector elevationCuts; - const bool isEpox = time == std::chrono::system_clock::time_point {}; - bool needArchive = true; - static const auto maxChunkDelay = std::chrono::minutes(10); - const std::chrono::system_clock::time_point firstValidChunkTime = - (isEpox ? scwx::util::time::now() : time) - maxChunkDelay; + std::shared_ptr record; + std::tie(record, time) = p->GetLevel2ProductRecord(time); - // See if we have this one in the chunk provider. - auto chunkFile = std::dynamic_pointer_cast( - p->level2ChunksProviderManager_->provider_->LoadObjectByTime(time)); - if (chunkFile != nullptr) + if (record != nullptr) { std::tie(radarData, elevationCut, elevationCuts) = - chunkFile->GetElevationScan(dataBlockType, elevation, time); - - if (radarData != nullptr) - { - auto& radarData0 = (*radarData)[0]; - foundTime = std::chrono::floor( - scwx::util::TimePoint(radarData0->modified_julian_date(), - radarData0->collection_time())); - - const std::optional incomingElevation = - std::dynamic_pointer_cast( - p->level2ChunksProviderManager_->provider_) - ->GetCurrentElevation(); - if (incomingElevation != p->incomingLevel2Elevation_) - { - p->incomingLevel2Elevation_ = incomingElevation; - Q_EMIT IncomingLevel2ElevationChanged(incomingElevation); - } - - if (foundTime >= firstValidChunkTime) - { - needArchive = false; - } - } + record->level2_file()->GetElevationScan( + dataBlockType, elevation, time); } - // It is not in the chunk provider, so get it from the archive - if (needArchive) - { - auto records = p->GetLevel2ProductRecords(time); - for (auto& recordPair : records) - { - auto& record = recordPair.second; - - if (record != nullptr) - { - std::shared_ptr recordRadarData = - nullptr; - float recordElevationCut = 0.0f; - std::vector recordElevationCuts; - - std::tie(recordRadarData, recordElevationCut, recordElevationCuts) = - record->level2_file()->GetElevationScan( - dataBlockType, elevation, time); - - if (recordRadarData != nullptr) - { - auto& radarData0 = (*recordRadarData)[0]; - auto collectionTime = std::chrono::floor( - scwx::util::TimePoint(radarData0->modified_julian_date(), - radarData0->collection_time())); - - // Find the newest radar data, not newer than the selected time - if (radarData == nullptr || - (collectionTime <= time && foundTime < collectionTime) || - (isEpox && foundTime < collectionTime)) - { - radarData = recordRadarData; - elevationCut = recordElevationCut; - elevationCuts = std::move(recordElevationCuts); - foundTime = collectionTime; - - if (!p->incomingLevel2Elevation_.has_value()) - { - p->incomingLevel2Elevation_ = {}; - Q_EMIT IncomingLevel2ElevationChanged( - p->incomingLevel2Elevation_); - } - } - } - } - } - } - - return {radarData, elevationCut, elevationCuts, foundTime}; + return {radarData, elevationCut, elevationCuts, time}; } std::tuple, @@ -1677,7 +1449,7 @@ std::vector RadarProductManager::GetLevel3Products() void RadarProductManager::SetCacheLimit(size_t cacheLimit) { - p->cacheLimit_ = std::max(cacheLimit, 6u); + p->cacheLimit_ = cacheLimit; } void RadarProductManager::UpdateAvailableProducts() @@ -1686,12 +1458,6 @@ void RadarProductManager::UpdateAvailableProducts() if (p->level3ProductsInitialized_) { - if (p->level3AvailabilityReady_) - { - // Multiple maps may use the same manager, so this ensures that all get - // notified of the change - Q_EMIT Level3ProductsChanged(); - } return; } @@ -1767,7 +1533,6 @@ void RadarProductManagerImpl::UpdateAvailableProductsSync() } } - level3AvailabilityReady_ = true; Q_EMIT self_->Level3ProductsChanged(); } diff --git a/scwx-qt/source/scwx/qt/manager/radar_product_manager.hpp b/scwx-qt/source/scwx/qt/manager/radar_product_manager.hpp index e8c72193..4a3edabf 100644 --- a/scwx-qt/source/scwx/qt/manager/radar_product_manager.hpp +++ b/scwx-qt/source/scwx/qt/manager/radar_product_manager.hpp @@ -41,14 +41,11 @@ public: */ static void DumpRecords(); - [[nodiscard]] const std::vector& - coordinates(common::RadialSize radialSize, bool smoothingEnabled) const; - [[nodiscard]] const scwx::util::time_zone* default_time_zone() const; - [[nodiscard]] float gate_size() const; - [[nodiscard]] std::optional incoming_level_2_elevation() const; - [[nodiscard]] bool is_tdwr() const; - [[nodiscard]] std::string radar_id() const; - [[nodiscard]] std::shared_ptr radar_site() const; + const std::vector& coordinates(common::RadialSize radialSize) const; + const scwx::util::time_zone* default_time_zone() const; + float gate_size() const; + std::string radar_id() const; + std::shared_ptr radar_site() const; void Initialize(); @@ -135,7 +132,6 @@ public: /** * @brief Set the maximum number of products of each type that may be cached. - * The cache limit cannot be set lower than 6. * * @param [in] cacheLimit The maximum number of products of each type */ @@ -148,9 +144,7 @@ signals: void Level3ProductsChanged(); void NewDataAvailable(common::RadarProductGroup group, const std::string& product, - bool isChunks, std::chrono::system_clock::time_point latestTime); - void IncomingLevel2ElevationChanged(std::optional incomingElevation); private: std::unique_ptr p; diff --git a/scwx-qt/source/scwx/qt/manager/resource_manager.cpp b/scwx-qt/source/scwx/qt/manager/resource_manager.cpp index 0c8cecef..443d771b 100644 --- a/scwx-qt/source/scwx/qt/manager/resource_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/resource_manager.cpp @@ -22,9 +22,6 @@ namespace ResourceManager static const std::string logPrefix_ = "scwx::qt::manager::resource_manager"; static const auto logger_ = scwx::util::Logger::Create(logPrefix_); -static const size_t atlasWidth = 2048; -static const size_t atlasHeight = 2048; - static void LoadFonts(); static void LoadTextures(); @@ -43,17 +40,10 @@ void Initialize() void Shutdown() {} std::shared_ptr -LoadImageResource(const std::string& urlString, double scale) +LoadImageResource(const std::string& urlString) { util::TextureAtlas& textureAtlas = util::TextureAtlas::Instance(); - return textureAtlas.CacheTexture(urlString, urlString, scale); -} - -std::shared_ptr LoadImageResource( - const std::string& urlString, const std::string& textureName, double scale) -{ - util::TextureAtlas& textureAtlas = util::TextureAtlas::Instance(); - return textureAtlas.CacheTexture(textureName, urlString, scale); + return textureAtlas.CacheTexture(urlString, urlString); } std::vector> @@ -62,7 +52,7 @@ LoadImageResources(const std::vector& urlStrings) std::mutex m {}; std::vector> images {}; - std::for_each(std::execution::par, + std::for_each(std::execution::par_unseq, urlStrings.begin(), urlStrings.end(), [&](auto& urlString) @@ -78,7 +68,8 @@ LoadImageResources(const std::vector& urlStrings) if (!images.empty()) { - BuildAtlas(); + util::TextureAtlas& textureAtlas = util::TextureAtlas::Instance(); + textureAtlas.BuildAtlas(2048, 2048); } return images; @@ -112,13 +103,7 @@ static void LoadTextures() GetTexturePath(lineTexture)); } - BuildAtlas(); -} - -void BuildAtlas() -{ - util::TextureAtlas& textureAtlas = util::TextureAtlas::Instance(); - textureAtlas.BuildAtlas(atlasWidth, atlasHeight); + textureAtlas.BuildAtlas(2048, 2048); } } // namespace ResourceManager diff --git a/scwx-qt/source/scwx/qt/manager/resource_manager.hpp b/scwx-qt/source/scwx/qt/manager/resource_manager.hpp index cf0aad03..00658891 100644 --- a/scwx-qt/source/scwx/qt/manager/resource_manager.hpp +++ b/scwx-qt/source/scwx/qt/manager/resource_manager.hpp @@ -19,14 +19,9 @@ void Initialize(); void Shutdown(); std::shared_ptr -LoadImageResource(const std::string& urlString, double scale = 1); -std::shared_ptr -LoadImageResource(const std::string& urlString, - const std::string& textureName, - double scale = 1); +LoadImageResource(const std::string& urlString); std::vector> - LoadImageResources(const std::vector& urlStrings); -void BuildAtlas(); +LoadImageResources(const std::vector& urlStrings); } // namespace ResourceManager } // namespace manager diff --git a/scwx-qt/source/scwx/qt/manager/settings_manager.cpp b/scwx-qt/source/scwx/qt/manager/settings_manager.cpp index a47428bb..056799ae 100644 --- a/scwx-qt/source/scwx/qt/manager/settings_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/settings_manager.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include @@ -67,10 +67,9 @@ void SettingsManager::Initialize() } p->settingsPath_ = appDataPath + "/settings.json"; + p->initialized_ = true; ReadSettings(p->settingsPath_); - - p->initialized_ = true; p->ValidateSettings(); } diff --git a/scwx-qt/source/scwx/qt/manager/task_manager.cpp b/scwx-qt/source/scwx/qt/manager/task_manager.cpp deleted file mode 100644 index 66b7285a..00000000 --- a/scwx-qt/source/scwx/qt/manager/task_manager.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include -#include - -namespace scwx::qt::manager::TaskManager -{ - -static const std::string logPrefix_ = "scwx::qt::manager::task_manager"; -static const auto logger_ = scwx::util::Logger::Create(logPrefix_); - -static std::shared_ptr ntpClient_ {}; - -void Initialize() -{ - logger_->debug("Initialize"); - - ntpClient_ = network::NtpClient::Instance(); - - ntpClient_->Start(); - ntpClient_->WaitForInitialOffset(); -} - -void Shutdown() -{ - logger_->debug("Shutdown"); - - ntpClient_->Stop(); -} - -} // namespace scwx::qt::manager::TaskManager diff --git a/scwx-qt/source/scwx/qt/manager/task_manager.hpp b/scwx-qt/source/scwx/qt/manager/task_manager.hpp deleted file mode 100644 index bb50fb3b..00000000 --- a/scwx-qt/source/scwx/qt/manager/task_manager.hpp +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -namespace scwx::qt::manager::TaskManager -{ - -void Initialize(); -void Shutdown(); - -} // namespace scwx::qt::manager::TaskManager diff --git a/scwx-qt/source/scwx/qt/manager/text_event_manager.cpp b/scwx-qt/source/scwx/qt/manager/text_event_manager.cpp index 009f2441..e48ecd48 100644 --- a/scwx-qt/source/scwx/qt/manager/text_event_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/text_event_manager.cpp @@ -2,60 +2,28 @@ #include #include #include -#include #include #include -#include -#include -#include -#include #include #include #include #include #include -#include -#include -#include -#include -#include -#if (__cpp_lib_chrono < 201907L) -# include -#endif - -namespace scwx::qt::manager +namespace scwx +{ +namespace qt +{ +namespace manager { - -using namespace std::chrono_literals; static const std::string logPrefix_ = "scwx::qt::manager::text_event_manager"; static const auto logger_ = scwx::util::Logger::Create(logPrefix_); -static constexpr std::chrono::hours kInitialLoadHistoryDuration_ = - std::chrono::days {3}; -static constexpr std::chrono::hours kDefaultLoadHistoryDuration_ = - std::chrono::hours {1}; - -static const std::array kPils_ = { - "FFS", "FFW", "MWS", "SMW", "SQW", "SVR", "SVS", "TOR"}; - -static const std:: - unordered_map> - kPilLoadWindows_ {{"FFS", {-24h, 1h}}, - {"FFW", {-24h, 1h}}, - {"MWS", {-4h, 1h}}, - {"SMW", {-4h, 1h}}, - {"SQW", {-4h, 1h}}, - {"SVR", {-4h, 1h}}, - {"SVS", {-4h, 1h}}, - {"TOR", {-4h, 1h}}}; - -// Widest load window provided by kPilLoadWindows_ -static const std::pair - kArchiveLoadWindow_ {-24h, 1h}; +static const std::string& kDefaultWarningsProviderUrl { + "https://warnings.allisonhouse.com"}; class TextEventManager::Impl { @@ -74,9 +42,7 @@ public: warningsProviderChangedCallbackUuid_ = generalSettings.warnings_provider().RegisterValueChangedCallback( - [this](const std::string& value) - { - loadHistoryDuration_ = kInitialLoadHistoryDuration_; + [this](const std::string& value) { warningsProvider_ = std::make_shared(value); }); @@ -110,30 +76,11 @@ public: threadPool_.join(); } - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; - - void HandleMessage(const std::shared_ptr& message, - bool archiveEvent = false); - template - requires std::same_as, - std::chrono::sys_days> - void ListArchives(DateRange dates); - void LoadArchives(std::chrono::system_clock::time_point dateTime); - void PruneArchives(); + void HandleMessage(std::shared_ptr message); void RefreshAsync(); void Refresh(); - template - requires std::same_as, - std::chrono::sys_days> - void UpdateArchiveDates(DateRange dates); - // Thread pool sized for: - // - Live Refresh (1x) - // - Archive Loading (1x) - boost::asio::thread_pool threadPool_ {2u}; + boost::asio::thread_pool threadPool_ {1u}; TextEventManager* self_; @@ -148,27 +95,6 @@ public: std::shared_ptr warningsProvider_ {nullptr}; - std::chrono::hours loadHistoryDuration_ {kInitialLoadHistoryDuration_}; - std::chrono::sys_time prevLoadTime_ {}; - std::chrono::sys_days archiveLimit_ {}; - - std::mutex archiveMutex_ {}; - std::list archiveDates_ {}; - - std::mutex archiveEventKeyMutex_ {}; - std::map>> - archiveEventKeys_ {}; - std::unordered_set> - liveEventKeys_ {}; - - std::mutex unloadedProductMapMutex_ {}; - std::map> - unloadedProductMap_; - boost::uuids::uuid warningsProviderChangedCallbackUuid_ {}; }; @@ -238,56 +164,9 @@ void TextEventManager::LoadFile(const std::string& filename) }); } -void TextEventManager::SelectTime( - std::chrono::system_clock::time_point dateTime) -{ - if (dateTime == std::chrono::system_clock::time_point {}) - { - // Ignore a default date/time selection - return; - } - - logger_->trace("Select Time: {}", util::TimeString(dateTime)); - - boost::asio::post( - p->threadPool_, - [dateTime, this]() - { - try - { - const auto today = std::chrono::floor(dateTime); - const auto yesterday = today - std::chrono::days {1}; - const auto tomorrow = today + std::chrono::days {1}; - const auto dateArray = std::array {yesterday, today, tomorrow}; - - const auto dates = - dateArray | - ranges::views::filter( - [this](const auto& date) - { - return p->archiveLimit_ == std::chrono::sys_days {} || - date < p->archiveLimit_; - }); - - const std::unique_lock lock {p->archiveMutex_}; - - p->UpdateArchiveDates(dates); - p->ListArchives(dates); - p->LoadArchives(dateTime); - p->PruneArchives(); - } - catch (const std::exception& ex) - { - logger_->error(ex.what()); - } - }); -} - void TextEventManager::Impl::HandleMessage( - const std::shared_ptr& message, bool archiveEvent) + std::shared_ptr message) { - using namespace std::chrono_literals; - auto segments = message->segments(); // If there are no segments, skip this message @@ -308,49 +187,21 @@ void TextEventManager::Impl::HandleMessage( } } - // Determine year - const std::chrono::year_month_day wmoDate = - std::chrono::floor( - message->wmo_header()->GetDateTime()); - const std::chrono::year wmoYear = wmoDate.year(); - std::unique_lock lock(textEventMutex_); // Find a matching event in the event map auto& vtecString = segments[0]->header_->vtecString_; - types::TextEventKey key {vtecString[0].pVtec_, wmoYear}; + types::TextEventKey key {vtecString[0].pVtec_}; size_t messageIndex = 0; auto it = textEventMap_.find(key); bool updated = false; - if ( - // If there was no matching event - it == textEventMap_.cend() && - // The event is not new - vtecString[0].pVtec_.action() != awips::PVtec::Action::New && - // The message was on January 1 - wmoDate.month() == std::chrono::January && wmoDate.day() == 1d && - // This is at least the 10th ETN of the year - // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers): Readability - vtecString[0].pVtec_.event_tracking_number() > 10) - { - // Attempt to find a matching event from last year - key = {vtecString[0].pVtec_, wmoYear - std::chrono::years {1}}; - it = textEventMap_.find(key); - } - if (it == textEventMap_.cend()) { // If there was no matching event, add the message to a new event textEventMap_.emplace(key, std::vector {message}); messageIndex = 0; updated = true; - - if (!archiveEvent) - { - // Add the Text Event Key to the list of live events to prevent pruning - liveEventKeys_.insert(key); - } } else if (std::find_if(it->second.cbegin(), it->second.cend(), @@ -363,284 +214,16 @@ void TextEventManager::Impl::HandleMessage( // If there was a matching event, and this message has not been stored // (WMO header equivalence check), add the updated message to the existing // event - - // Determine the chronological sequence of the message. Note, if there - // were no time hints given to the WMO header, this will place the message - // at the end of the vector. - auto insertionPoint = std::upper_bound( - it->second.begin(), - it->second.end(), - message, - [](const std::shared_ptr& a, - const std::shared_ptr& b) - { - return a->wmo_header()->GetDateTime() < - b->wmo_header()->GetDateTime(); - }); - - // Insert the message in chronological order - messageIndex = std::distance(it->second.begin(), insertionPoint); - it->second.insert(insertionPoint, message); + messageIndex = it->second.size(); + it->second.push_back(message); updated = true; }; - // If this is an archive event, and the key does not exist in the live events - // Assumption: A live event will always be loaded before a duplicate archive - // event - if (archiveEvent && !liveEventKeys_.contains(key)) - { - // Add the Text Event Key to the current date's archive - const std::unique_lock archiveEventKeyLock {archiveEventKeyMutex_}; - auto& archiveKeys = archiveEventKeys_[wmoDate]; - archiveKeys.insert(key); - } - lock.unlock(); if (updated) { - Q_EMIT self_->AlertUpdated(key, messageIndex, message->uuid()); - } -} - -template - requires std::same_as, - std::chrono::sys_days> -void TextEventManager::Impl::ListArchives(DateRange dates) -{ - // Don't reload data that has already been loaded - auto filteredDates = - dates | - ranges::views::filter([this](const auto& date) - { return !unloadedProductMap_.contains(date); }); - - const auto dv = ranges::to(filteredDates); - - std::for_each( - std::execution::par, - dv.begin(), - dv.end(), - [this](const auto& date) - { - static const auto kEmptyRange_ = - ranges::views::single(std::string_view {}); - static const auto kPilsView_ = - kPils_ | - ranges::views::transform([](const std::string& pil) - { return std::string_view {pil}; }); - - const auto dateArray = std::array {date}; - - auto productEntries = provider::IemApiProvider::ListTextProducts( - dateArray | ranges::views::all, kEmptyRange_, kPilsView_); - - const std::unique_lock lock {unloadedProductMapMutex_}; - - if (productEntries.has_value()) - { - unloadedProductMap_.try_emplace( - date, - boost::container::stable_vector { - std::make_move_iterator(productEntries.value().begin()), - std::make_move_iterator(productEntries.value().end())}); - } - }); -} - -void TextEventManager::Impl::LoadArchives( - std::chrono::system_clock::time_point dateTime) -{ - using namespace std::chrono; - -#if (__cpp_lib_chrono >= 201907L) - namespace df = std; - - static constexpr std::string_view kDateFormat {"{:%Y%m%d%H%M}"}; -#else - using namespace date; - namespace df = date; - -# define kDateFormat "%Y%m%d%H%M" -#endif - - // Search unloaded products in the widest archive load window - const std::chrono::sys_days startDate = - std::chrono::floor(dateTime + - kArchiveLoadWindow_.first); - const std::chrono::sys_days endDate = std::chrono::floor( - dateTime + kArchiveLoadWindow_.second + std::chrono::days {1}); - - // Determine load windows for each PIL - std::unordered_map> - pilLoadWindowStrings; - - for (auto& loadWindow : kPilLoadWindows_) - { - const std::string& pil = loadWindow.first; - - pilLoadWindowStrings.insert_or_assign( - pil, - std::pair { - df::format(kDateFormat, (dateTime + loadWindow.second.first)), - df::format(kDateFormat, (dateTime + loadWindow.second.second))}); - } - - std::vector loadListEntries {}; - - for (auto date = startDate; date < endDate; date += std::chrono::days {1}) - { - auto mapIt = unloadedProductMap_.find(date); - if (mapIt == unloadedProductMap_.cend()) - { - continue; - } - - for (auto it = mapIt->second.begin(); it != mapIt->second.end();) - { - const auto& pil = it->pil_; - - // Check PIL - if (pil.size() >= 3) - { - auto pilPrefix = pil.substr(0, 3); - auto windowIt = pilLoadWindowStrings.find(pilPrefix); - - // Check Window - if (windowIt != pilLoadWindowStrings.cend()) - { - const auto& productId = it->productId_; - const auto& windowStart = windowIt->second.first; - const auto& windowEnd = windowIt->second.second; - - if (windowStart <= productId && productId <= windowEnd) - { - // Product matches, move it to the load list - loadListEntries.emplace_back(std::move(*it)); - it = mapIt->second.erase(it); - continue; - } - } - } - - // Current iterator was not matched - ++it; - } - } - - std::vector> products {}; - - // Load the load list - if (!loadListEntries.empty()) - { - auto loadView = loadListEntries | - ranges::views::transform([](const auto& entry) - { return entry.productId_; }); - products = provider::IemApiProvider::LoadTextProducts(loadView); - } - - // Process loaded products - for (auto& product : products) - { - const auto& messages = product->messages(); - - for (auto& message : messages) - { - HandleMessage(message, true); - } - } -} - -void TextEventManager::Impl::PruneArchives() -{ - static constexpr std::size_t kMaxArchiveDates_ = 5; - - std::unordered_set> - eventKeysToKeep {}; - std::unordered_set> - eventKeysToPrune {}; - - // Remove oldest dates from the archive - while (archiveDates_.size() > kMaxArchiveDates_) - { - archiveDates_.pop_front(); - } - - const std::unique_lock archiveEventKeyLock {archiveEventKeyMutex_}; - - // If there are the same number of dates in archiveEventKeys_, archiveDates_ - // and unloadedProductMap_, there is nothing to prune - if (archiveEventKeys_.size() == archiveDates_.size() && - unloadedProductMap_.size() == archiveDates_.size()) - { - // Nothing to prune - return; - } - - const std::unique_lock unloadedProductMapLock {unloadedProductMapMutex_}; - - for (auto it = archiveEventKeys_.begin(); it != archiveEventKeys_.end();) - { - const auto& date = it->first; - const auto& eventKeys = it->second; - - // If date is not in recent days map - if (std::find(archiveDates_.cbegin(), archiveDates_.cend(), date) == - archiveDates_.cend()) - { - // Prune these keys (unless they are in the eventKeysToKeep set) - eventKeysToPrune.insert(eventKeys.begin(), eventKeys.end()); - - // The date is not in the list of recent dates, remove it - it = archiveEventKeys_.erase(it); - } - else - { - // Make sure these keys don't get pruned - eventKeysToKeep.insert(eventKeys.begin(), eventKeys.end()); - - // The date is recent, keep it - ++it; - } - } - - for (auto it = unloadedProductMap_.begin(); it != unloadedProductMap_.end();) - { - const auto& date = it->first; - - // If date is not in recent days map - if (std::find(archiveDates_.cbegin(), archiveDates_.cend(), date) == - archiveDates_.cend()) - { - // The date is not in the list of recent dates, remove it - it = unloadedProductMap_.erase(it); - } - else - { - // The date is recent, keep it - ++it; - } - } - - // Remove elements from eventKeysToPrune if they are in eventKeysToKeep - for (const auto& eventKey : eventKeysToKeep) - { - eventKeysToPrune.erase(eventKey); - } - - // Remove eventKeysToPrune from textEventMap - for (const auto& eventKey : eventKeysToPrune) - { - textEventMap_.erase(eventKey); - } - - // If event keys were pruned, emit a signal - if (!eventKeysToPrune.empty()) - { - logger_->debug("Pruned {} archive events", eventKeysToPrune.size()); - - Q_EMIT self_->AlertsRemoved(eventKeysToPrune); + Q_EMIT self_->AlertUpdated(key, messageIndex); } } @@ -671,38 +254,21 @@ void TextEventManager::Impl::Refresh() std::shared_ptr warningsProvider = warningsProvider_; - // Load updated files from the warnings provider - // Start time should default to: - // - 3 days of history for the first load - // - 1 hour of history for subsequent loads - // If the time jumps, we should attempt to load from no later than the - // previous load time - auto loadTime = - std::chrono::floor(scwx::util::time::now()); - auto startTime = loadTime - loadHistoryDuration_; + // Update the file listing from the warnings provider + auto [newFiles, totalFiles] = warningsProvider->ListFiles(); - if (prevLoadTime_ != std::chrono::sys_time {}) + if (newFiles > 0) { - startTime = std::min(startTime, prevLoadTime_); - } + // Load new files + auto updatedFiles = warningsProvider->LoadUpdatedFiles(); - if (archiveLimit_ == std::chrono::sys_days {}) - { - archiveLimit_ = std::chrono::ceil(startTime); - } - - auto updatedFiles = warningsProvider->LoadUpdatedFiles(startTime); - - // Store the load time and reset the load history duration - prevLoadTime_ = loadTime; - loadHistoryDuration_ = kDefaultLoadHistoryDuration_; - - // Handle messages - for (auto& file : updatedFiles) - { - for (auto& message : file->messages()) + // Handle messages + for (auto& file : updatedFiles) { - HandleMessage(message); + for (auto& message : file->messages()) + { + HandleMessage(message); + } } } @@ -727,19 +293,6 @@ void TextEventManager::Impl::Refresh() }); } -template - requires std::same_as, - std::chrono::sys_days> -void TextEventManager::Impl::UpdateArchiveDates(DateRange dates) -{ - for (const auto& date : dates) - { - // Remove any existing occurrences of day, and add to the back of the list - archiveDates_.remove(date); - archiveDates_.push_back(date); - } -} - std::shared_ptr TextEventManager::Instance() { static std::weak_ptr textEventManagerReference_ {}; @@ -759,4 +312,6 @@ std::shared_ptr TextEventManager::Instance() return textEventManager; } -} // namespace scwx::qt::manager +} // namespace manager +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/manager/text_event_manager.hpp b/scwx-qt/source/scwx/qt/manager/text_event_manager.hpp index 61affe6c..f97ca223 100644 --- a/scwx-qt/source/scwx/qt/manager/text_event_manager.hpp +++ b/scwx-qt/source/scwx/qt/manager/text_event_manager.hpp @@ -3,12 +3,9 @@ #include #include -#include #include #include -#include -#include #include namespace scwx @@ -31,18 +28,11 @@ public: message_list(const types::TextEventKey& key) const; void LoadFile(const std::string& filename); - void SelectTime(std::chrono::system_clock::time_point dateTime); static std::shared_ptr Instance(); signals: - void AlertsRemoved( - const std::unordered_set>& - keys); - void AlertUpdated(const types::TextEventKey& key, - std::size_t messageIndex, - boost::uuids::uuid uuid); + void AlertUpdated(const types::TextEventKey& key, size_t messageIndex); private: class Impl; diff --git a/scwx-qt/source/scwx/qt/manager/timeline_manager.cpp b/scwx-qt/source/scwx/qt/manager/timeline_manager.cpp index 70c4b2ed..1d48ac9c 100644 --- a/scwx-qt/source/scwx/qt/manager/timeline_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/timeline_manager.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include #include #include @@ -32,8 +31,6 @@ enum class Direction // Wait up to 5 seconds for radar sweeps to update static constexpr std::chrono::seconds kRadarSweepMonitorTimeout_ {5}; -// Only allow for 3 steps to be queued at any time -static constexpr size_t kMaxQueuedSteps_ {3}; class TimelineManager::Impl { @@ -83,8 +80,6 @@ public: boost::asio::thread_pool playThreadPool_ {1}; boost::asio::thread_pool selectThreadPool_ {1}; - util::QueueCounter stepCounter_ {kMaxQueuedSteps_}; - std::size_t mapCount_ {0}; std::string radarSite_ {"?"}; std::string previousRadarSite_ {"?"}; @@ -112,11 +107,6 @@ public: TimelineManager::TimelineManager() : p(std::make_unique(this)) {} TimelineManager::~TimelineManager() = default; -std::chrono::system_clock::time_point TimelineManager::GetSelectedTime() const -{ - return p->selectedTime_; -} - void TimelineManager::SetMapCount(std::size_t mapCount) { p->mapCount_ = mapCount; @@ -218,7 +208,7 @@ void TimelineManager::AnimationStepBegin() p->pinnedTime_ == std::chrono::system_clock::time_point {}) { // If the selected view type is live, select the current products - p->SelectTimeAsync(scwx::util::time::now() - p->loopTime_); + p->SelectTimeAsync(std::chrono::system_clock::now() - p->loopTime_); } else { @@ -266,7 +256,7 @@ void TimelineManager::AnimationStepEnd() if (p->viewType_ == types::MapTime::Live) { // If the selected view type is live, select the current products - p->SelectTimeAsync(); + p->SelectTime(); } else { @@ -346,10 +336,10 @@ void TimelineManager::ReceiveMapWidgetPainted(std::size_t mapIndex) std::unique_lock lock {p->radarSweepMonitorMutex_}; // If the radar sweep has been updated - if (p->radarSweepsUpdated_.contains(mapIndex) && - !p->radarSweepsComplete_.contains(mapIndex)) + if (p->radarSweepsUpdated_.contains(mapIndex)) { // Mark the radar sweep complete + p->radarSweepsUpdated_.erase(mapIndex); p->radarSweepsComplete_.insert(mapIndex); // If all sweeps have completed rendering @@ -385,8 +375,8 @@ TimelineManager::Impl::GetLoopStartAndEndTimes() if (viewType_ == types::MapTime::Live || pinnedTime_ == std::chrono::system_clock::time_point {}) { - endTime = - std::chrono::floor(scwx::util::time::now()); + endTime = std::chrono::floor( + std::chrono::system_clock::now()); } else { @@ -405,9 +395,8 @@ void TimelineManager::Impl::UpdateCacheLimit( { // Calculate the number of volume scans in the loop auto [startTime, endTime] = GetLoopStartAndEndTimes(); - auto startIter = - scwx::util::GetBoundedElementIterator(volumeTimes, startTime); - auto endIter = scwx::util::GetBoundedElementIterator(volumeTimes, endTime); + auto startIter = util::GetBoundedElementIterator(volumeTimes, startTime); + auto endIter = util::GetBoundedElementIterator(volumeTimes, endTime); std::size_t numVolumeScans = std::distance(startIter, endIter) + 1; // Dynamically update maximum cached volume scans to the lesser of @@ -477,12 +466,20 @@ void TimelineManager::Impl::PlaySync() // Select the time auto selectTimeStart = std::chrono::steady_clock::now(); - SelectTime(newTime); + auto [volumeTimeUpdated, selectedTimeUpdated] = SelectTime(newTime); auto selectTimeEnd = std::chrono::steady_clock::now(); auto elapsedTime = selectTimeEnd - selectTimeStart; - // Wait for radar sweeps to update - RadarSweepMonitorWait(radarSweepMonitorLock); + if (volumeTimeUpdated) + { + // Wait for radar sweeps to update + RadarSweepMonitorWait(radarSweepMonitorLock); + } + else + { + // Disable radar sweep monitor + RadarSweepMonitorDisable(); + } // Calculate the interval until the next update, prior to selecting std::chrono::milliseconds interval; @@ -582,8 +579,7 @@ std::pair TimelineManager::Impl::SelectTime( UpdateCacheLimit(radarProductManager, volumeTimes); // Find the best match bounded time - auto elementPtr = - scwx::util::GetBoundedElementPointer(volumeTimes, selectedTime); + auto elementPtr = util::GetBoundedElementPointer(volumeTimes, selectedTime); // The timeline is no longer live Q_EMIT self_->LiveStateUpdated(false); @@ -624,12 +620,6 @@ std::pair TimelineManager::Impl::SelectTime( void TimelineManager::Impl::StepAsync(Direction direction) { - // Prevent too many steps from being added to the queue - if (!stepCounter_.add()) - { - return; - } - boost::asio::post(selectThreadPool_, [=, this]() { @@ -641,7 +631,6 @@ void TimelineManager::Impl::StepAsync(Direction direction) { logger_->error(ex.what()); } - stepCounter_.remove(); }); } @@ -650,63 +639,79 @@ void TimelineManager::Impl::Step(Direction direction) // Take a lock for time selection std::unique_lock lock {selectTimeMutex_}; - std::chrono::system_clock::time_point newTime = selectedTime_; - - if (newTime == std::chrono::system_clock::time_point {}) + // Determine time to get active volume times + std::chrono::system_clock::time_point queryTime = adjustedTime_; + if (queryTime == std::chrono::system_clock::time_point {}) { - if (direction == Direction::Back) - { - newTime = - std::chrono::floor(scwx::util::time::now()); - } - else - { - // Cannot step forward any further - return; - } + queryTime = std::chrono::system_clock::now(); } - // Unlock prior to selecting time - lock.unlock(); + // Request active volume times + auto radarProductManager = + manager::RadarProductManager::Instance(radarSite_); + auto volumeTimes = radarProductManager->GetActiveVolumeTimes(queryTime); - // Lock radar sweep monitor - std::unique_lock radarSweepMonitorLock {radarSweepMonitorMutex_}; - - // Attempt to step forward or backward up to 30 minutes until an update is - // received on at least one map - for (std::size_t i = 0; i < 30; ++i) + if (volumeTimes.empty()) { - using namespace std::chrono_literals; + logger_->debug("No products to step through"); + return; + } - // Increment/decrement selected time by one minute - if (direction == Direction::Back) + // Dynamically update maximum cached volume scans + UpdateCacheLimit(radarProductManager, volumeTimes); + + std::set::const_iterator it; + + if (adjustedTime_ == std::chrono::system_clock::time_point {}) + { + // If the adjusted time is live, get the last element in the set + it = std::prev(volumeTimes.cend()); + } + else + { + // Get the current element in the set + it = scwx::util::GetBoundedElementIterator(volumeTimes, adjustedTime_); + } + + if (it == volumeTimes.cend()) + { + // Should not get here, but protect against an error + logger_->error("No suitable volume time found"); + return; + } + + if (direction == Direction::Back) + { + // Only if we aren't at the beginning of the volume times set + if (it != volumeTimes.cbegin()) { - newTime -= 1min; + // Select the previous time + adjustedTime_ = *(--it); + selectedTime_ = adjustedTime_; + + logger_->debug("Volume time updated: {}", + scwx::util::TimeString(adjustedTime_)); + + Q_EMIT self_->LiveStateUpdated(false); + Q_EMIT self_->VolumeTimeUpdated(adjustedTime_); + Q_EMIT self_->SelectedTimeUpdated(adjustedTime_); } - else + } + else + { + // Only if we aren't at the end of the volume times set + if (it != std::prev(volumeTimes.cend())) { - newTime += 1min; + // Select the next time + adjustedTime_ = *(++it); + selectedTime_ = adjustedTime_; - // If the new time is more than 2 minutes in the future, stop stepping - if (newTime > scwx::util::time::now() + 2min) - { - break; - } - } + logger_->debug("Volume time updated: {}", + scwx::util::TimeString(adjustedTime_)); - // Reset radar sweep monitor in preparation for update - RadarSweepMonitorReset(); - - // Select the time - SelectTime(newTime); - - // Wait for radar sweeps to update - RadarSweepMonitorWait(radarSweepMonitorLock); - - // Check for updates - if (!radarSweepsUpdated_.empty()) - { - break; + Q_EMIT self_->LiveStateUpdated(false); + Q_EMIT self_->VolumeTimeUpdated(adjustedTime_); + Q_EMIT self_->SelectedTimeUpdated(adjustedTime_); } } } diff --git a/scwx-qt/source/scwx/qt/manager/timeline_manager.hpp b/scwx-qt/source/scwx/qt/manager/timeline_manager.hpp index 054a8201..1a4154ac 100644 --- a/scwx-qt/source/scwx/qt/manager/timeline_manager.hpp +++ b/scwx-qt/source/scwx/qt/manager/timeline_manager.hpp @@ -24,8 +24,6 @@ public: static std::shared_ptr Instance(); - [[nodiscard]] std::chrono::system_clock::time_point GetSelectedTime() const; - void SetMapCount(std::size_t mapCount); public slots: diff --git a/scwx-qt/source/scwx/qt/manager/update_manager.cpp b/scwx-qt/source/scwx/qt/manager/update_manager.cpp index 05a9c0d1..d21068cb 100644 --- a/scwx-qt/source/scwx/qt/manager/update_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/update_manager.cpp @@ -1,5 +1,4 @@ #include -#include #include #include @@ -30,7 +29,8 @@ public: ~Impl() {} - static std::string GetVersionString(const std::string& releaseName); + static std::string GetVersionString(const std::string& releaseName); + static boost::json::value ParseResponseText(const std::string& s); size_t PopulateReleases(); size_t AddReleases(const boost::json::value& json); @@ -70,6 +70,28 @@ UpdateManager::Impl::GetVersionString(const std::string& releaseName) return versionString; } +boost::json::value UpdateManager::Impl::ParseResponseText(const std::string& s) +{ + boost::json::stream_parser p; + boost::system::error_code ec; + + p.write(s, ec); + if (ec) + { + logger_->warn("{}", ec.message()); + return nullptr; + } + + p.finish(ec); + if (ec) + { + logger_->warn("{}", ec.message()); + return nullptr; + } + + return p.release(); +} + bool UpdateManager::CheckForUpdates(const std::string& currentVersion) { std::unique_lock lock(p->updateMutex_); @@ -126,7 +148,7 @@ size_t UpdateManager::Impl::PopulateReleases() // Successful REST API query if (r.status_code == 200) { - const boost::json::value json = util::json::ReadJsonString(r.text); + boost::json::value json = Impl::ParseResponseText(r.text); if (json == nullptr) { logger_->warn("Response not JSON: {}", r.header["content-type"]); diff --git a/scwx-qt/source/scwx/qt/map/alert_layer.cpp b/scwx-qt/source/scwx/qt/map/alert_layer.cpp index 7bea5938..cc8bc29b 100644 --- a/scwx-qt/source/scwx/qt/map/alert_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/alert_layer.cpp @@ -6,13 +6,9 @@ #include #include #include -#include #include #include -#include -#include -#include #include #include @@ -22,9 +18,12 @@ #include #include #include -#include -namespace scwx::qt::map +namespace scwx +{ +namespace qt +{ +namespace map { static const std::string logPrefix_ = "scwx::qt::map::alert_layer"; @@ -41,13 +40,9 @@ struct AlertTypeHash> size_t operator()(const std::pair& x) const; }; -static bool IsAlertActive(const std::shared_ptr& segment); - class AlertLayerHandler : public QObject { Q_OBJECT - Q_DISABLE_COPY_MOVE(AlertLayerHandler) - public: struct SegmentRecord { @@ -59,10 +54,10 @@ public: SegmentRecord( const std::shared_ptr& segment, - types::TextEventKey key, + const types::TextEventKey& key, const std::shared_ptr& message) : segment_ {segment}, - key_ {std::move(key)}, + key_ {key}, message_ {message}, segmentBegin_ {segment->event_begin()}, segmentEnd_ {segment->event_end()} @@ -75,11 +70,8 @@ public: connect(textEventManager_.get(), &manager::TextEventManager::AlertUpdated, this, - &AlertLayerHandler::HandleAlert); - connect(textEventManager_.get(), - &manager::TextEventManager::AlertsRemoved, - this, - &AlertLayerHandler::HandleAlertsRemoved); + [this](const types::TextEventKey& key, std::size_t messageIndex) + { HandleAlert(key, messageIndex); }); } ~AlertLayerHandler() { @@ -100,13 +92,7 @@ public: types::TextEventHash> segmentsByKey_ {}; - void HandleAlert(const types::TextEventKey& key, - size_t messageIndex, - boost::uuids::uuid uuid); - void HandleAlertsRemoved( - const std::unordered_set>& - keys); + void HandleAlert(const types::TextEventKey& key, size_t messageIndex); static AlertLayerHandler& Instance(); @@ -119,34 +105,31 @@ signals: void AlertAdded(const std::shared_ptr& segmentRecord, awips::Phenomenon phenomenon); void AlertUpdated(const std::shared_ptr& segmentRecord); - void AlertsRemoved(awips::Phenomenon phenomenon); void AlertsUpdated(awips::Phenomenon phenomenon, bool alertActive); }; class AlertLayer::Impl { public: - struct LineData - { - boost::gil::rgba32f_pixel_t borderColor_ {}; - boost::gil::rgba32f_pixel_t highlightColor_ {}; - boost::gil::rgba32f_pixel_t lineColor_ {}; - - std::size_t borderWidth_ {}; - std::size_t highlightWidth_ {}; - std::size_t lineWidth_ {}; - }; - - explicit Impl(AlertLayer* self, - const std::shared_ptr& glContext, - awips::Phenomenon phenomenon) : + explicit Impl(AlertLayer* self, + std::shared_ptr context, + awips::Phenomenon phenomenon) : self_ {self}, phenomenon_ {phenomenon}, - ibw_ {awips::ibw::GetImpactBasedWarningInfo(phenomenon)}, - geoLines_ {{false, std::make_shared(glContext)}, - {true, std::make_shared(glContext)}} + geoLines_ {{false, std::make_shared(context)}, + {true, std::make_shared(context)}} { - UpdateLineData(); + auto& paletteSettings = settings::PaletteSettings::Instance(); + + for (auto alertActive : {false, true}) + { + lineColor_.emplace( + alertActive, + util::color::ToRgba32fPixelT( + paletteSettings.alert_color(phenomenon_, alertActive) + .GetValue())); + } + ConnectSignals(); ScheduleRefresh(); } @@ -163,51 +146,36 @@ public: std::unique_lock lock(linesMutex_); }; - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; - void AddAlert( const std::shared_ptr& segmentRecord); void UpdateAlert( const std::shared_ptr& segmentRecord); void ConnectAlertHandlerSignals(); void ConnectSignals(); - void HandleGeoLinesEvent(std::weak_ptr& di, - QEvent* ev); - void - HandleGeoLinesHover(const std::shared_ptr& di, - const QPointF& mouseGlobalPos); + void HandleGeoLinesEvent(std::shared_ptr& di, + QEvent* ev); + void HandleGeoLinesHover(std::shared_ptr& di, + const QPointF& mouseGlobalPos); void ScheduleRefresh(); - LineData& GetLineData(const std::shared_ptr& segment, - bool alertActive); - void UpdateLineData(); - void AddLine(std::shared_ptr& geoLines, std::shared_ptr& di, const common::Coordinate& p1, const common::Coordinate& p2, - const boost::gil::rgba32f_pixel_t& color, + boost::gil::rgba32f_pixel_t color, float width, std::chrono::system_clock::time_point startTime, std::chrono::system_clock::time_point endTime, bool enableHover); void AddLines(std::shared_ptr& geoLines, const std::vector& coordinates, - const boost::gil::rgba32f_pixel_t& color, + boost::gil::rgba32f_pixel_t color, float width, std::chrono::system_clock::time_point startTime, std::chrono::system_clock::time_point endTime, bool enableHover, boost::container::stable_vector< std::shared_ptr>& drawItems); - void PopulateLines(bool alertActive); - void RepopulateLines(); - void UpdateLines(); - - static LineData CreateLineData(const settings::LineSettings& lineSettings); boost::asio::thread_pool threadPool_ {1u}; @@ -216,11 +184,9 @@ public: boost::asio::system_timer refreshTimer_ {threadPool_}; std::mutex refreshMutex_; - const awips::Phenomenon phenomenon_; - const awips::ibw::ImpactBasedWarningInfo& ibw_; + const awips::Phenomenon phenomenon_; std::unique_ptr receiver_ {std::make_unique()}; - std::mutex receiverMutex_ {}; std::unordered_map> geoLines_; @@ -233,26 +199,17 @@ public: segmentsByLine_; std::mutex linesMutex_ {}; - std::unordered_map - threatCategoryLineData_; - LineData observedLineData_ {}; - LineData tornadoPossibleLineData_ {}; - LineData inactiveLineData_ {}; + std::unordered_map lineColor_; std::chrono::system_clock::time_point selectedTime_ {}; std::shared_ptr lastHoverDi_ {nullptr}; std::string tooltip_ {}; - - std::vector connections_ {}; }; -AlertLayer::AlertLayer(const std::shared_ptr& glContext, - awips::Phenomenon phenomenon) : - DrawLayer( - glContext, - fmt::format("AlertLayer {}", awips::GetPhenomenonText(phenomenon))), - p(std::make_unique(this, glContext, phenomenon)) +AlertLayer::AlertLayer(std::shared_ptr context, + awips::Phenomenon phenomenon) : + DrawLayer(context), p(std::make_unique(this, context, phenomenon)) { for (auto alertActive : {false, true}) { @@ -276,37 +233,51 @@ void AlertLayer::InitializeHandler() } } -void AlertLayer::Initialize(const std::shared_ptr& mapContext) +void AlertLayer::Initialize() { logger_->debug("Initialize: {}", awips::GetPhenomenonText(p->phenomenon_)); - DrawLayer::Initialize(mapContext); + DrawLayer::Initialize(); auto& alertLayerHandler = AlertLayerHandler::Instance(); - p->selectedTime_ = manager::TimelineManager::Instance()->GetSelectedTime(); - // Take a shared lock to prevent handling additional alerts while populating // initial lists std::shared_lock lock {alertLayerHandler.alertMutex_}; for (auto alertActive : {false, true}) { - p->PopulateLines(alertActive); + auto& geoLines = p->geoLines_.at(alertActive); + + geoLines->StartLines(); + + // Populate initial segments + auto segmentsIt = + alertLayerHandler.segmentsByType_.find({p->phenomenon_, alertActive}); + if (segmentsIt != alertLayerHandler.segmentsByType_.cend()) + { + for (auto& segment : segmentsIt->second) + { + p->AddAlert(segment); + } + } + + geoLines->FinishLines(); } p->ConnectAlertHandlerSignals(); } -void AlertLayer::Render(const std::shared_ptr& mapContext, - const QMapLibre::CustomLayerRenderParameters& params) +void AlertLayer::Render(const QMapLibre::CustomLayerRenderParameters& params) { + gl::OpenGLFunctions& gl = context()->gl(); + for (auto alertActive : {false, true}) { p->geoLines_.at(alertActive)->set_selected_time(p->selectedTime_); } - DrawLayer::Render(mapContext, params); + DrawLayer::Render(params); SCWX_GL_CHECK_ERROR(); } @@ -318,18 +289,8 @@ void AlertLayer::Deinitialize() DrawLayer::Deinitialize(); } -bool IsAlertActive(const std::shared_ptr& segment) -{ - auto& vtec = segment->header_->vtecString_.front(); - auto action = vtec.pVtec_.action(); - bool alertActive = (action != awips::PVtec::Action::Canceled); - - return alertActive; -} - void AlertLayerHandler::HandleAlert(const types::TextEventKey& key, - size_t messageIndex, - boost::uuids::uuid uuid) + size_t messageIndex) { logger_->trace("HandleAlert: {}", key.ToString()); @@ -337,28 +298,7 @@ void AlertLayerHandler::HandleAlert(const types::TextEventKey& key, AlertTypeHash>> alertsUpdated {}; - const auto& messageList = textEventManager_->message_list(key); - - // Find message by UUID instead of index, as the message index could have - // changed between the signal being emitted and the handler being called - auto messageIt = std::find_if(messageList.cbegin(), - messageList.cend(), - [&uuid](const auto& message) - { return uuid == message->uuid(); }); - - if (messageIt == messageList.cend()) - { - logger_->warn( - "Could not find alert uuid: {} ({})", key.ToString(), messageIndex); - return; - } - - auto& message = *messageIt; - auto nextMessageIt = std::next(messageIt); - - // Store the current message index - messageIndex = - static_cast(std::distance(messageList.cbegin(), messageIt)); + auto message = textEventManager_->message_list(key).at(messageIndex); // Determine start time for first segment std::chrono::system_clock::time_point segmentBegin {}; @@ -367,31 +307,14 @@ void AlertLayerHandler::HandleAlert(const types::TextEventKey& key, segmentBegin = message->segment(0)->event_begin(); } - // Determine the start time for the first segment of the next message - std::optional nextMessageBegin {}; - if (nextMessageIt != messageList.cend()) - { - nextMessageBegin = - (*nextMessageIt) - ->wmo_header() - ->GetDateTime((*nextMessageIt)->segment(0)->event_begin()); - } - // Take a unique mutex before modifying segments std::unique_lock lock {alertMutex_}; - // Update any existing earlier segments with new end time + // Update any existing segments with new end time auto& segmentsForKey = segmentsByKey_[key]; for (auto& segmentRecord : segmentsForKey) { - // Determine if the segment is earlier than the current message - auto it = std::find( - messageList.cbegin(), messageList.cend(), segmentRecord->message_); - auto segmentIndex = - static_cast(std::distance(messageList.cbegin(), it)); - - if (segmentIndex < messageIndex && - segmentRecord->segmentEnd_ > segmentBegin) + if (segmentRecord->segmentEnd_ > segmentBegin) { segmentRecord->segmentEnd_ = segmentBegin; @@ -408,9 +331,10 @@ void AlertLayerHandler::HandleAlert(const types::TextEventKey& key, continue; } - auto& vtec = segment->header_->vtecString_.front(); - awips::Phenomenon phenomenon = vtec.pVtec_.phenomenon(); - bool alertActive = IsAlertActive(segment); + auto& vtec = segment->header_->vtecString_.front(); + auto action = vtec.pVtec_.action(); + awips::Phenomenon phenomenon = vtec.pVtec_.phenomenon(); + bool alertActive = (action != awips::PVtec::Action::Canceled); auto& segmentsForType = segmentsByType_[{key.phenomenon_, alertActive}]; @@ -418,14 +342,6 @@ void AlertLayerHandler::HandleAlert(const types::TextEventKey& key, std::shared_ptr segmentRecord = std::make_shared(segment, key, message); - // Update segment end time to be no later than the begin time of the next - // message (if present) - if (nextMessageBegin.has_value() && - segmentRecord->segmentEnd_ > nextMessageBegin) - { - segmentRecord->segmentEnd_ = nextMessageBegin.value(); - } - segmentsForKey.push_back(segmentRecord); segmentsForType.push_back(segmentRecord); @@ -444,63 +360,6 @@ void AlertLayerHandler::HandleAlert(const types::TextEventKey& key, } } -void AlertLayerHandler::HandleAlertsRemoved( - const std::unordered_set>& keys) -{ - logger_->trace("HandleAlertsRemoved: {} keys", keys.size()); - - std::set alertsRemoved {}; - - // Take a unique lock before modifying segments - std::unique_lock lock {alertMutex_}; - - for (const auto& key : keys) - { - // Remove segments associated with the key - auto segmentsIt = segmentsByKey_.find(key); - if (segmentsIt != segmentsByKey_.end()) - { - for (const auto& segmentRecord : segmentsIt->second) - { - auto& segment = segmentRecord->segment_; - const bool alertActive = IsAlertActive(segment); - - // Remove from segmentsByType_ - auto typeIt = segmentsByType_.find({key.phenomenon_, alertActive}); - if (typeIt != segmentsByType_.end()) - { - auto& segmentsForType = typeIt->second; - segmentsForType.erase(std::remove(segmentsForType.begin(), - segmentsForType.end(), - segmentRecord), - segmentsForType.end()); - - // If no segments remain for this type, erase the entry - if (segmentsForType.empty()) - { - segmentsByType_.erase(typeIt); - } - } - - alertsRemoved.emplace(key.phenomenon_); - } - - // Remove the key from segmentsByKey_ - segmentsByKey_.erase(segmentsIt); - } - } - - // Release the lock after completing segment updates - lock.unlock(); - - // Emit signal to notify that alerts have been removed - for (auto& alert : alertsRemoved) - { - Q_EMIT AlertsRemoved(alert); - } -} - void AlertLayer::Impl::ConnectAlertHandlerSignals() { auto& alertLayerHandler = AlertLayerHandler::Instance(); @@ -515,9 +374,6 @@ void AlertLayer::Impl::ConnectAlertHandlerSignals() { if (phenomenon == phenomenon_) { - // Only process one signal at a time - const std::unique_lock lock {receiverMutex_}; - AddAlert(segmentRecord); } }); @@ -530,33 +386,13 @@ void AlertLayer::Impl::ConnectAlertHandlerSignals() { if (segmentRecord->key_.phenomenon_ == phenomenon_) { - // Only process one signal at a time - const std::unique_lock lock {receiverMutex_}; - UpdateAlert(segmentRecord); } }); - QObject::connect(&alertLayerHandler, - &AlertLayerHandler::AlertsRemoved, - receiver_.get(), - [this](awips::Phenomenon phenomenon) - { - if (phenomenon == phenomenon_) - { - // Only process one signal at a time - const std::unique_lock lock {receiverMutex_}; - - // Re-populate the lines if multiple alerts were - // removed - RepopulateLines(); - } - }); } void AlertLayer::Impl::ConnectSignals() { - auto& alertPaletteSettings = - settings::PaletteSettings::Instance().alert_palette(phenomenon_); auto timelineManager = manager::TimelineManager::Instance(); QObject::connect(timelineManager.get(), @@ -564,13 +400,6 @@ void AlertLayer::Impl::ConnectSignals() receiver_.get(), [this](std::chrono::system_clock::time_point dateTime) { selectedTime_ = dateTime; }); - - connections_.push_back(alertPaletteSettings.changed_signal().connect( - [this]() - { - UpdateLineData(); - UpdateLines(); - })); } void AlertLayer::Impl::ScheduleRefresh() @@ -582,7 +411,8 @@ void AlertLayer::Impl::ScheduleRefresh() // Expires at the top of the next minute std::chrono::system_clock::time_point now = - std::chrono::floor(scwx::util::time::now()); + std::chrono::floor( + std::chrono::system_clock::now()); refreshTimer_.expires_at(now + 1min); refreshTimer_.async_wait( @@ -609,12 +439,14 @@ void AlertLayer::Impl::AddAlert( { auto& segment = segmentRecord->segment_; - bool alertActive = IsAlertActive(segment); + auto& vtec = segment->header_->vtecString_.front(); + auto action = vtec.pVtec_.action(); + bool alertActive = (action != awips::PVtec::Action::Canceled); auto& startTime = segmentRecord->segmentBegin_; auto& endTime = segmentRecord->segmentEnd_; - auto& lineData = GetLineData(segment, alertActive); - auto& geoLines = geoLines_.at(alertActive); + auto& lineColor = lineColor_.at(alertActive); + auto& geoLines = geoLines_.at(alertActive); const auto& coordinates = segment->codedLocation_->coordinates(); @@ -630,55 +462,32 @@ void AlertLayer::Impl::AddAlert( // If draw items were added if (drawItems.second) { - const auto borderWidth = static_cast(lineData.borderWidth_); - const auto highlightWidth = static_cast(lineData.highlightWidth_); - const auto lineWidth = static_cast(lineData.lineWidth_); - - const float totalHighlightWidth = lineWidth + (highlightWidth * 2.0f); - const float totalBorderWidth = totalHighlightWidth + (borderWidth * 2.0f); - - constexpr bool borderHover = true; - constexpr bool highlightHover = false; - constexpr bool lineHover = false; - // Add border AddLines(geoLines, coordinates, - lineData.borderColor_, - totalBorderWidth, + kBlack_, + 5.0f, startTime, endTime, - borderHover, + true, drawItems.first->second); - // Add border to segmentsByLine_ + // Add only border to segmentsByLine_ for (auto& di : drawItems.first->second) { segmentsByLine_.insert({di, segmentRecord}); } - // Add highlight - AddLines(geoLines, - coordinates, - lineData.highlightColor_, - totalHighlightWidth, - startTime, - endTime, - highlightHover, - drawItems.first->second); - // Add line AddLines(geoLines, coordinates, - lineData.lineColor_, - lineWidth, + lineColor, + 3.0f, startTime, endTime, - lineHover, + false, drawItems.first->second); } - - Q_EMIT self_->NeedsRendering(); } void AlertLayer::Impl::UpdateAlert( @@ -690,8 +499,11 @@ void AlertLayer::Impl::UpdateAlert( auto it = linesBySegment_.find(segmentRecord); if (it != linesBySegment_.cend()) { - auto& segment = segmentRecord->segment_; - bool alertActive = IsAlertActive(segment); + auto& segment = segmentRecord->segment_; + + auto& vtec = segment->header_->vtecString_.front(); + auto action = vtec.pVtec_.action(); + bool alertActive = (action != awips::PVtec::Action::Canceled); auto& geoLines = geoLines_.at(alertActive); @@ -702,14 +514,12 @@ void AlertLayer::Impl::UpdateAlert( geoLines->SetLineEndTime(line, segmentRecord->segmentEnd_); } } - - Q_EMIT self_->NeedsRendering(); } void AlertLayer::Impl::AddLines( std::shared_ptr& geoLines, const std::vector& coordinates, - const boost::gil::rgba32f_pixel_t& color, + boost::gil::rgba32f_pixel_t color, float width, std::chrono::system_clock::time_point startTime, std::chrono::system_clock::time_point endTime, @@ -749,17 +559,14 @@ void AlertLayer::Impl::AddLine(std::shared_ptr& geoLines, std::shared_ptr& di, const common::Coordinate& p1, const common::Coordinate& p2, - const boost::gil::rgba32f_pixel_t& color, + boost::gil::rgba32f_pixel_t color, float width, std::chrono::system_clock::time_point startTime, std::chrono::system_clock::time_point endTime, bool enableHover) { - geoLines->SetLineLocation(di, - static_cast(p1.latitude_), - static_cast(p1.longitude_), - static_cast(p2.latitude_), - static_cast(p2.longitude_)); + geoLines->SetLineLocation( + di, p1.latitude_, p1.longitude_, p2.latitude_, p2.longitude_); geoLines->SetLineModulate(di, color); geoLines->SetLineWidth(di, width); geoLines->SetLineStartTime(di, startTime); @@ -774,113 +581,18 @@ void AlertLayer::Impl::AddLine(std::shared_ptr& geoLines, std::placeholders::_1, std::placeholders::_2)); - const std::weak_ptr diWeak = di; gl::draw::GeoLines::RegisterEventHandler( di, std::bind(&AlertLayer::Impl::HandleGeoLinesEvent, this, - diWeak, + di, std::placeholders::_1)); } } -void AlertLayer::Impl::PopulateLines(bool alertActive) -{ - auto& alertLayerHandler = AlertLayerHandler::Instance(); - auto& geoLines = geoLines_.at(alertActive); - - geoLines->StartLines(); - - // Populate initial segments - auto segmentsIt = - alertLayerHandler.segmentsByType_.find({phenomenon_, alertActive}); - if (segmentsIt != alertLayerHandler.segmentsByType_.cend()) - { - for (auto& segment : segmentsIt->second) - { - AddAlert(segment); - } - } - - geoLines->FinishLines(); -} - -void AlertLayer::Impl::RepopulateLines() -{ - auto& alertLayerHandler = AlertLayerHandler::Instance(); - - // Take a shared lock to prevent handling additional alerts while populating - // initial lists - const std::shared_lock alertLock {alertLayerHandler.alertMutex_}; - - linesBySegment_.clear(); - segmentsByLine_.clear(); - - for (auto alertActive : {false, true}) - { - PopulateLines(alertActive); - } - - Q_EMIT self_->NeedsRendering(); -} - -void AlertLayer::Impl::UpdateLines() -{ - std::unique_lock lock {linesMutex_}; - - for (auto& segmentLine : linesBySegment_) - { - auto& segmentRecord = segmentLine.first; - auto& geoLineDrawItems = segmentLine.second; - auto& segment = segmentRecord->segment_; - bool alertActive = IsAlertActive(segment); - auto& lineData = GetLineData(segment, alertActive); - auto& geoLines = geoLines_.at(alertActive); - - const auto borderWidth = static_cast(lineData.borderWidth_); - const auto highlightWidth = static_cast(lineData.highlightWidth_); - const auto lineWidth = static_cast(lineData.lineWidth_); - - const float totalHighlightWidth = lineWidth + (highlightWidth * 2.0f); - const float totalBorderWidth = totalHighlightWidth + (borderWidth * 2.0f); - - // Border, highlight and line - std::size_t linesPerType = geoLineDrawItems.size() / 3; - - // Border - for (auto& borderLine : geoLineDrawItems | std::views::take(linesPerType)) - { - geoLines->SetLineModulate(borderLine, lineData.borderColor_); - geoLines->SetLineWidth(borderLine, totalBorderWidth); - } - - // Highlight - for (auto& highlightLine : geoLineDrawItems | - std::views::drop(linesPerType) | - std::views::take(linesPerType)) - { - geoLines->SetLineModulate(highlightLine, lineData.highlightColor_); - geoLines->SetLineWidth(highlightLine, totalHighlightWidth); - } - - // Line - for (auto& line : geoLineDrawItems | std::views::drop(linesPerType * 2)) - { - geoLines->SetLineModulate(line, lineData.lineColor_); - geoLines->SetLineWidth(line, lineWidth); - } - } -} - void AlertLayer::Impl::HandleGeoLinesEvent( - std::weak_ptr& diWeak, QEvent* ev) + std::shared_ptr& di, QEvent* ev) { - const std::shared_ptr di = diWeak.lock(); - if (di == nullptr) - { - return; - } - switch (ev->type()) { case QEvent::Type::MouseButtonPress: @@ -901,8 +613,8 @@ void AlertLayer::Impl::HandleGeoLinesEvent( } void AlertLayer::Impl::HandleGeoLinesHover( - const std::shared_ptr& di, - const QPointF& mouseGlobalPos) + std::shared_ptr& di, + const QPointF& mouseGlobalPos) { if (di != lastHoverDi_) { @@ -926,79 +638,6 @@ void AlertLayer::Impl::HandleGeoLinesHover( } } -AlertLayer::Impl::LineData -AlertLayer::Impl::CreateLineData(const settings::LineSettings& lineSettings) -{ - return LineData { - .borderColor_ {lineSettings.GetBorderColorRgba32f()}, - .highlightColor_ {lineSettings.GetHighlightColorRgba32f()}, - .lineColor_ {lineSettings.GetLineColorRgba32f()}, - .borderWidth_ = - static_cast(lineSettings.border_width().GetValue()), - .highlightWidth_ = - static_cast(lineSettings.highlight_width().GetValue()), - .lineWidth_ = - static_cast(lineSettings.line_width().GetValue())}; -} - -void AlertLayer::Impl::UpdateLineData() -{ - auto& alertPalette = - settings::PaletteSettings().Instance().alert_palette(phenomenon_); - - for (auto threatCategory : ibw_.threatCategories_) - { - auto& palette = alertPalette.threat_category(threatCategory); - threatCategoryLineData_.insert_or_assign(threatCategory, - CreateLineData(palette)); - } - - if (ibw_.hasObservedTag_) - { - observedLineData_ = CreateLineData(alertPalette.observed()); - } - - if (ibw_.hasTornadoPossibleTag_) - { - tornadoPossibleLineData_ = - CreateLineData(alertPalette.tornado_possible()); - } - - inactiveLineData_ = CreateLineData(alertPalette.inactive()); -} - -AlertLayer::Impl::LineData& AlertLayer::Impl::GetLineData( - const std::shared_ptr& segment, bool alertActive) -{ - if (!alertActive) - { - return inactiveLineData_; - } - - for (auto& threatCategory : ibw_.threatCategories_) - { - if (segment->threatCategory_ == threatCategory) - { - if (threatCategory == awips::ibw::ThreatCategory::Base) - { - if (ibw_.hasObservedTag_ && segment->observed_) - { - return observedLineData_; - } - - if (ibw_.hasTornadoPossibleTag_ && segment->tornadoPossible_) - { - return tornadoPossibleLineData_; - } - } - - return threatCategoryLineData_.at(threatCategory); - } - } - - return threatCategoryLineData_.at(awips::ibw::ThreatCategory::Base); -}; - AlertLayerHandler& AlertLayerHandler::Instance() { static AlertLayerHandler alertLayerHandler_ {}; @@ -1014,6 +653,8 @@ size_t AlertTypeHash>::operator()( return seed; } -} // namespace scwx::qt::map +} // namespace map +} // namespace qt +} // namespace scwx #include "alert_layer.moc" diff --git a/scwx-qt/source/scwx/qt/map/alert_layer.hpp b/scwx-qt/source/scwx/qt/map/alert_layer.hpp index 0416ff04..99609210 100644 --- a/scwx-qt/source/scwx/qt/map/alert_layer.hpp +++ b/scwx-qt/source/scwx/qt/map/alert_layer.hpp @@ -1,13 +1,18 @@ #pragma once #include - #include #include #include +#include +#include -namespace scwx::qt::map +namespace scwx +{ +namespace qt +{ +namespace map { class AlertLayer : public DrawLayer @@ -16,14 +21,13 @@ class AlertLayer : public DrawLayer Q_DISABLE_COPY_MOVE(AlertLayer) public: - explicit AlertLayer(const std::shared_ptr& glContext, - scwx::awips::Phenomenon phenomenon); + explicit AlertLayer(std::shared_ptr context, + scwx::awips::Phenomenon phenomenon); ~AlertLayer(); - void Initialize(const std::shared_ptr& mapContext) final; - void Render(const std::shared_ptr& mapContext, - const QMapLibre::CustomLayerRenderParameters&) final; - void Deinitialize() final; + void Initialize() override final; + void Render(const QMapLibre::CustomLayerRenderParameters&) override final; + void Deinitialize() override final; static void InitializeHandler(); @@ -35,4 +39,6 @@ private: std::unique_ptr p; }; -} // namespace scwx::qt::map +} // namespace map +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/map/color_table_layer.cpp b/scwx-qt/source/scwx/qt/map/color_table_layer.cpp index f55bd94a..bdafce3f 100644 --- a/scwx-qt/source/scwx/qt/map/color_table_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/color_table_layer.cpp @@ -14,83 +14,87 @@ # pragma warning(pop) #endif -namespace scwx::qt::map +namespace scwx +{ +namespace qt +{ +namespace map { static const std::string logPrefix_ = "scwx::qt::map::color_table_layer"; static const auto logger_ = scwx::util::Logger::Create(logPrefix_); -class ColorTableLayer::Impl +class ColorTableLayerImpl { public: - explicit Impl() = default; - ~Impl() = default; + explicit ColorTableLayerImpl() : + shaderProgram_(nullptr), + uMVPMatrixLocation_(GL_INVALID_INDEX), + vbo_ {GL_INVALID_INDEX}, + vao_ {GL_INVALID_INDEX}, + texture_ {GL_INVALID_INDEX}, + colorTable_ {}, + colorTableNeedsUpdate_ {true} + { + } + ~ColorTableLayerImpl() = default; - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; + std::shared_ptr shaderProgram_; - std::shared_ptr shaderProgram_ {nullptr}; + GLint uMVPMatrixLocation_; + std::array vbo_; + GLuint vao_; + GLuint texture_; - GLint uMVPMatrixLocation_ {static_cast(GL_INVALID_INDEX)}; - std::array vbo_ {GL_INVALID_INDEX}; - GLuint vao_ {GL_INVALID_INDEX}; - GLuint texture_ {GL_INVALID_INDEX}; + std::vector colorTable_; - std::vector colorTable_ {}; - - bool colorTableNeedsUpdate_ {true}; + bool colorTableNeedsUpdate_; }; -ColorTableLayer::ColorTableLayer(std::shared_ptr glContext) : - GenericLayer(std::move(glContext)), p(std::make_unique()) +ColorTableLayer::ColorTableLayer(std::shared_ptr context) : + GenericLayer(context), p(std::make_unique()) { } ColorTableLayer::~ColorTableLayer() = default; -void ColorTableLayer::Initialize(const std::shared_ptr& mapContext) +void ColorTableLayer::Initialize() { logger_->debug("Initialize()"); - auto glContext = gl_context(); + gl::OpenGLFunctions& gl = context()->gl(); // Load and configure overlay shader p->shaderProgram_ = - glContext->GetShaderProgram(":/gl/texture1d.vert", ":/gl/texture1d.frag"); + context()->GetShaderProgram(":/gl/texture1d.vert", ":/gl/texture1d.frag"); p->uMVPMatrixLocation_ = - glGetUniformLocation(p->shaderProgram_->id(), "uMVPMatrix"); + gl.glGetUniformLocation(p->shaderProgram_->id(), "uMVPMatrix"); if (p->uMVPMatrixLocation_ == -1) { logger_->warn("Could not find uMVPMatrix"); } - glGenTextures(1, &p->texture_); + gl.glGenTextures(1, &p->texture_); p->shaderProgram_->Use(); // Generate a vertex array object - glGenVertexArrays(1, &p->vao_); + gl.glGenVertexArrays(1, &p->vao_); // Generate vertex buffer objects - glGenBuffers(2, p->vbo_.data()); + gl.glGenBuffers(2, p->vbo_.data()); - glBindVertexArray(p->vao_); - - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) - // NOLINTBEGIN(modernize-use-nullptr) + gl.glBindVertexArray(p->vao_); // Bottom panel - glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); - glBufferData( + gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); + gl.glBufferData( GL_ARRAY_BUFFER, sizeof(float) * 6 * 2, nullptr, GL_DYNAMIC_DRAW); - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, static_cast(0)); - glEnableVertexAttribArray(0); + gl.glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, static_cast(0)); + gl.glEnableVertexAttribArray(0); // Color table panel texture coordinates - // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays) const float textureCoords[6][1] = {{0.0f}, // TL {0.0f}, // BL {1.0f}, // TR @@ -98,31 +102,27 @@ void ColorTableLayer::Initialize(const std::shared_ptr& mapContext) {0.0f}, // BL {1.0f}, // TR {1.0f}}; // BR - glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); - glBufferData(GL_ARRAY_BUFFER, - sizeof(textureCoords), - static_cast(textureCoords), - GL_STATIC_DRAW); + gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); + gl.glBufferData( + GL_ARRAY_BUFFER, sizeof(textureCoords), textureCoords, GL_STATIC_DRAW); - glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, 0, static_cast(0)); - glEnableVertexAttribArray(1); + gl.glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, 0, static_cast(0)); + gl.glEnableVertexAttribArray(1); - // NOLINTEND(modernize-use-nullptr) - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - - connect(mapContext->radar_product_view().get(), + connect(context()->radar_product_view().get(), &view::RadarProductView::ColorTableLutUpdated, this, [this]() { p->colorTableNeedsUpdate_ = true; }); } void ColorTableLayer::Render( - const std::shared_ptr& mapContext, const QMapLibre::CustomLayerRenderParameters& params) { - auto radarProductView = mapContext->radar_product_view(); + gl::OpenGLFunctions& gl = context()->gl(); + auto radarProductView = context()->radar_product_view(); - if (radarProductView == nullptr || !radarProductView->IsInitialized()) + if (context()->radar_product_view() == nullptr || + !context()->radar_product_view()->IsInitialized()) { // Defer rendering until view is initialized return; @@ -136,36 +136,33 @@ void ColorTableLayer::Render( p->shaderProgram_->Use(); // Set OpenGL blend mode for transparency - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + gl.glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glUniformMatrix4fv( + gl.glUniformMatrix4fv( p->uMVPMatrixLocation_, 1, GL_FALSE, glm::value_ptr(projection)); if (p->colorTableNeedsUpdate_) { p->colorTable_ = radarProductView->color_table_lut(); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_1D, p->texture_); - glTexImage1D(GL_TEXTURE_1D, - 0, - GL_RGBA, - (GLsizei) p->colorTable_.size(), - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - p->colorTable_.data()); - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glGenerateMipmap(GL_TEXTURE_1D); + gl.glActiveTexture(GL_TEXTURE0); + gl.glBindTexture(GL_TEXTURE_1D, p->texture_); + gl.glTexImage1D(GL_TEXTURE_1D, + 0, + GL_RGBA, + (GLsizei) p->colorTable_.size(), + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + p->colorTable_.data()); + gl.glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + gl.glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + gl.glGenerateMipmap(GL_TEXTURE_1D); } if (p->colorTable_.size() > 0 && radarProductView->sweep_time() != std::chrono::system_clock::time_point()) { - // NOLINTBEGIN(cppcoreguidelines-avoid-c-arrays) - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) - // Color table panel vertices const float vertexLX = 0.0f; const float vertexRX = static_cast(params.width); @@ -180,28 +177,16 @@ void ColorTableLayer::Render( {vertexRX, vertexBY}}; // BR // Draw vertices - glBindVertexArray(p->vao_); - glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); - glBufferSubData(GL_ARRAY_BUFFER, - 0, - sizeof(vertices), - static_cast(vertices)); - glDrawArrays(GL_TRIANGLES, 0, 6); + gl.glBindVertexArray(p->vao_); + gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); + gl.glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); + gl.glDrawArrays(GL_TRIANGLES, 0, 6); - static constexpr int kLeftMargin_ = 0; - static constexpr int kTopMargin_ = 0; - static constexpr int kRightMargin_ = 0; - static constexpr int kBottomMargin_ = 10; - - mapContext->set_color_table_margins( - QMargins {kLeftMargin_, kTopMargin_, kRightMargin_, kBottomMargin_}); - - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - // NOLINTEND(cppcoreguidelines-avoid-c-arrays) + context()->set_color_table_margins(QMargins {0, 0, 0, 10}); } else { - mapContext->set_color_table_margins(QMargins {}); + context()->set_color_table_margins(QMargins {}); } SCWX_GL_CHECK_ERROR(); @@ -211,14 +196,20 @@ void ColorTableLayer::Deinitialize() { logger_->debug("Deinitialize()"); - glDeleteVertexArrays(1, &p->vao_); - glDeleteBuffers(2, p->vbo_.data()); - glDeleteTextures(1, &p->texture_); + gl::OpenGLFunctions& gl = context()->gl(); + + gl.glDeleteVertexArrays(1, &p->vao_); + gl.glDeleteBuffers(2, p->vbo_.data()); + gl.glDeleteTextures(1, &p->texture_); p->uMVPMatrixLocation_ = GL_INVALID_INDEX; p->vao_ = GL_INVALID_INDEX; p->vbo_ = {GL_INVALID_INDEX}; p->texture_ = GL_INVALID_INDEX; + + context()->set_color_table_margins(QMargins {}); } -} // namespace scwx::qt::map +} // namespace map +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/map/color_table_layer.hpp b/scwx-qt/source/scwx/qt/map/color_table_layer.hpp index 17cb505c..c23dc2b8 100644 --- a/scwx-qt/source/scwx/qt/map/color_table_layer.hpp +++ b/scwx-qt/source/scwx/qt/map/color_table_layer.hpp @@ -2,25 +2,29 @@ #include -namespace scwx::qt::map +namespace scwx { +namespace qt +{ +namespace map +{ + +class ColorTableLayerImpl; class ColorTableLayer : public GenericLayer { - Q_DISABLE_COPY_MOVE(ColorTableLayer) - public: - explicit ColorTableLayer(std::shared_ptr glContext); + explicit ColorTableLayer(std::shared_ptr context); ~ColorTableLayer(); - void Initialize(const std::shared_ptr& mapContext) final; - void Render(const std::shared_ptr& mapContext, - const QMapLibre::CustomLayerRenderParameters&) final; - void Deinitialize() final; + void Initialize() override final; + void Render(const QMapLibre::CustomLayerRenderParameters&) override final; + void Deinitialize() override final; private: - class Impl; - std::unique_ptr p; + std::unique_ptr p; }; -} // namespace scwx::qt::map +} // namespace map +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/map/draw_layer.cpp b/scwx-qt/source/scwx/qt/map/draw_layer.cpp index f07cb2ac..7d03d13a 100644 --- a/scwx-qt/source/scwx/qt/map/draw_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/draw_layer.cpp @@ -1,146 +1,65 @@ -#include #include -#include #include #include -#include - -#include -#include -#include -#include -#include - -namespace scwx::qt::map +namespace scwx +{ +namespace qt +{ +namespace map { static const std::string logPrefix_ = "scwx::qt::map::draw_layer"; static const auto logger_ = scwx::util::Logger::Create(logPrefix_); -class DrawLayer::Impl +class DrawLayerImpl { public: - explicit Impl(std::shared_ptr glContext, - const std::string& imGuiContextName) : - glContext_ {std::move(glContext)} + explicit DrawLayerImpl(std::shared_ptr context) : + context_ {context}, drawList_ {}, textureAtlas_ {GL_INVALID_INDEX} { - static size_t currentLayerId_ {0u}; - imGuiContextName_ = - fmt::format("{} {}", imGuiContextName, ++currentLayerId_); - // This must be initialized after the last line - // NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer) - imGuiContext_ = - model::ImGuiContextModel::Instance().CreateContext(imGuiContextName_); - - // Initialize ImGui Qt backend - ImGui_ImplQt_Init(); } - ~Impl() - { - // Set ImGui Context - ImGui::SetCurrentContext(imGuiContext_); + ~DrawLayerImpl() {} - // Shutdown ImGui Context - if (imGuiRendererInitialized_) - { - ImGui_ImplOpenGL3_Shutdown(); - } - ImGui_ImplQt_Shutdown(); - - // Destroy ImGui Context - model::ImGuiContextModel::Instance().DestroyContext(imGuiContextName_); - } - - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; - - std::shared_ptr glContext_; - - std::vector> drawList_ {}; - GLuint textureAtlas_ {GL_INVALID_INDEX}; + std::shared_ptr context_; + std::vector> drawList_; + GLuint textureAtlas_; std::uint64_t textureAtlasBuildCount_ {}; - - std::string imGuiContextName_; - ImGuiContext* imGuiContext_; - bool imGuiRendererInitialized_ {}; }; -DrawLayer::DrawLayer(std::shared_ptr glContext, - const std::string& imGuiContextName) : - GenericLayer(glContext), - p(std::make_unique(std::move(glContext), imGuiContextName)) +DrawLayer::DrawLayer(const std::shared_ptr& context) : + GenericLayer(context), p(std::make_unique(context)) { } DrawLayer::~DrawLayer() = default; -void DrawLayer::Initialize(const std::shared_ptr& mapContext) +void DrawLayer::Initialize() { - p->textureAtlas_ = p->glContext_->GetTextureAtlas(); + p->textureAtlas_ = p->context_->GetTextureAtlas(); for (auto& item : p->drawList_) { item->Initialize(); } - - ImGuiInitialize(mapContext); } -void DrawLayer::ImGuiFrameStart(const std::shared_ptr& mapContext) +void DrawLayer::Render(const QMapLibre::CustomLayerRenderParameters& params) { - auto defaultFont = manager::FontManager::Instance().GetImGuiFont( - types::FontCategory::Default); - - // Setup ImGui Frame - ImGui::SetCurrentContext(p->imGuiContext_); - - // Start ImGui Frame - model::ImGuiContextModel::Instance().NewFrame(); - ImGui_ImplQt_NewFrame(mapContext->widget()); - ImGui_ImplOpenGL3_NewFrame(); - ImGui::NewFrame(); - ImGui::PushFont(defaultFont.first->font(), defaultFont.second.value()); -} - -void DrawLayer::ImGuiFrameEnd() -{ - // Pop default font - ImGui::PopFont(); - - // Render ImGui Frame - ImGui::Render(); - ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); -} - -void DrawLayer::ImGuiInitialize(const std::shared_ptr& mapContext) -{ - ImGui::SetCurrentContext(p->imGuiContext_); - ImGui_ImplQt_RegisterWidget(mapContext->widget()); - ImGui_ImplOpenGL3_Init(); - p->imGuiRendererInitialized_ = true; -} - -void DrawLayer::RenderWithoutImGui( - const QMapLibre::CustomLayerRenderParameters& params) -{ - auto& glContext = p->glContext_; - - p->textureAtlas_ = glContext->GetTextureAtlas(); + gl::OpenGLFunctions& gl = p->context_->gl(); + p->textureAtlas_ = p->context_->GetTextureAtlas(); // Determine if the texture atlas changed since last render - const std::uint64_t newTextureAtlasBuildCount = - glContext->texture_buffer_count(); - const bool textureAtlasChanged = + std::uint64_t newTextureAtlasBuildCount = + p->context_->texture_buffer_count(); + bool textureAtlasChanged = newTextureAtlasBuildCount != p->textureAtlasBuildCount_; // Set OpenGL blend mode for transparency - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + gl.glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D_ARRAY, p->textureAtlas_); + gl.glActiveTexture(GL_TEXTURE0); + gl.glBindTexture(GL_TEXTURE_2D_ARRAY, p->textureAtlas_); for (auto& item : p->drawList_) { @@ -150,19 +69,6 @@ void DrawLayer::RenderWithoutImGui( p->textureAtlasBuildCount_ = newTextureAtlasBuildCount; } -void DrawLayer::ImGuiSelectContext() -{ - ImGui::SetCurrentContext(p->imGuiContext_); -} - -void DrawLayer::Render(const std::shared_ptr& mapContext, - const QMapLibre::CustomLayerRenderParameters& params) -{ - ImGuiFrameStart(mapContext); - RenderWithoutImGui(params); - ImGuiFrameEnd(); -} - void DrawLayer::Deinitialize() { p->textureAtlas_ = GL_INVALID_INDEX; @@ -174,7 +80,6 @@ void DrawLayer::Deinitialize() } bool DrawLayer::RunMousePicking( - const std::shared_ptr& /* mapContext */, const QMapLibre::CustomLayerRenderParameters& params, const QPointF& mouseLocalPos, const QPointF& mouseGlobalPos, @@ -185,15 +90,15 @@ bool DrawLayer::RunMousePicking( bool itemPicked = false; // For each draw item in the draw list in reverse - for (auto& it : std::ranges::reverse_view(p->drawList_)) + for (auto it = p->drawList_.rbegin(); it != p->drawList_.rend(); ++it) { // Run mouse picking on each draw item - if (it->RunMousePicking(params, - mouseLocalPos, - mouseGlobalPos, - mouseCoords, - mouseGeoCoords, - eventHandler)) + if ((*it)->RunMousePicking(params, + mouseLocalPos, + mouseGlobalPos, + mouseCoords, + mouseGeoCoords, + eventHandler)) { // If a draw item was picked, don't process additional items itemPicked = true; @@ -209,4 +114,6 @@ void DrawLayer::AddDrawItem(const std::shared_ptr& drawItem) p->drawList_.push_back(drawItem); } -} // namespace scwx::qt::map +} // namespace map +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/map/draw_layer.hpp b/scwx-qt/source/scwx/qt/map/draw_layer.hpp index f0589eef..22dfa76c 100644 --- a/scwx-qt/source/scwx/qt/map/draw_layer.hpp +++ b/scwx-qt/source/scwx/qt/map/draw_layer.hpp @@ -3,26 +3,27 @@ #include #include -namespace scwx::qt::map +namespace scwx { +namespace qt +{ +namespace map +{ + +class DrawLayerImpl; class DrawLayer : public GenericLayer { - Q_DISABLE_COPY_MOVE(DrawLayer) - public: - explicit DrawLayer(std::shared_ptr glContext, - const std::string& imGuiContextName); + explicit DrawLayer(const std::shared_ptr& context); virtual ~DrawLayer(); - void Initialize(const std::shared_ptr& mapContext) override; - void Render(const std::shared_ptr& mapContext, - const QMapLibre::CustomLayerRenderParameters&) override; - void Deinitialize() override; + virtual void Initialize() override; + virtual void Render(const QMapLibre::CustomLayerRenderParameters&) override; + virtual void Deinitialize() override; - bool - RunMousePicking(const std::shared_ptr& mapContext, - const QMapLibre::CustomLayerRenderParameters& params, + virtual bool + RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params, const QPointF& mouseLocalPos, const QPointF& mouseGlobalPos, const glm::vec2& mouseCoords, @@ -31,16 +32,11 @@ public: protected: void AddDrawItem(const std::shared_ptr& drawItem); - void ImGuiFrameStart(const std::shared_ptr& mapContext); - void ImGuiFrameEnd(); - void ImGuiInitialize(const std::shared_ptr& mapContext); - void - RenderWithoutImGui(const QMapLibre::CustomLayerRenderParameters& params); - void ImGuiSelectContext(); private: - class Impl; - std::unique_ptr p; + std::unique_ptr p; }; -} // namespace scwx::qt::map +} // namespace map +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/map/generic_layer.cpp b/scwx-qt/source/scwx/qt/map/generic_layer.cpp index ec88d1f1..97f22097 100644 --- a/scwx-qt/source/scwx/qt/map/generic_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/generic_layer.cpp @@ -1,34 +1,32 @@ #include -namespace scwx::qt::map +namespace scwx +{ +namespace qt +{ +namespace map { -class GenericLayer::Impl +class GenericLayerImpl { public: - explicit Impl(std::shared_ptr glContext) : - glContext_ {std::move(glContext)} + explicit GenericLayerImpl(std::shared_ptr context) : + context_ {context} { } - ~Impl() = default; + ~GenericLayerImpl() {} - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; - - std::shared_ptr glContext_; + std::shared_ptr context_; }; -GenericLayer::GenericLayer(std::shared_ptr glContext) : - p(std::make_unique(std::move(glContext))) +GenericLayer::GenericLayer(std::shared_ptr context) : + p(std::make_unique(context)) { } GenericLayer::~GenericLayer() = default; bool GenericLayer::RunMousePicking( - const std::shared_ptr& /* mapContext */, const QMapLibre::CustomLayerRenderParameters& /* params */, const QPointF& /* mouseLocalPos */, const QPointF& /* mouseGlobalPos */, @@ -40,9 +38,11 @@ bool GenericLayer::RunMousePicking( return false; } -std::shared_ptr GenericLayer::gl_context() const +std::shared_ptr GenericLayer::context() const { - return p->glContext_; + return p->context_; } -} // namespace scwx::qt::map +} // namespace map +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/map/generic_layer.hpp b/scwx-qt/source/scwx/qt/map/generic_layer.hpp index 2b713c9c..0fee92ab 100644 --- a/scwx-qt/source/scwx/qt/map/generic_layer.hpp +++ b/scwx-qt/source/scwx/qt/map/generic_layer.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include @@ -11,27 +10,30 @@ #include #include -namespace scwx::qt::map +namespace scwx { +namespace qt +{ +namespace map +{ + +class GenericLayerImpl; class GenericLayer : public QObject { Q_OBJECT - Q_DISABLE_COPY_MOVE(GenericLayer) public: - explicit GenericLayer(std::shared_ptr glContext); + explicit GenericLayer(std::shared_ptr context); virtual ~GenericLayer(); - virtual void Initialize(const std::shared_ptr& mapContext) = 0; - virtual void Render(const std::shared_ptr& mapContext, - const QMapLibre::CustomLayerRenderParameters&) = 0; - virtual void Deinitialize() = 0; + virtual void Initialize() = 0; + virtual void Render(const QMapLibre::CustomLayerRenderParameters&) = 0; + virtual void Deinitialize() = 0; /** * @brief Run mouse picking on the layer. * - * @param [in] mapContext Map context * @param [in] params Custom layer render parameters * @param [in] mouseLocalPos Mouse cursor widget position * @param [in] mouseGlobalPos Mouse cursor screen position @@ -42,8 +44,7 @@ public: * @return true if a draw item was picked, otherwise false */ virtual bool - RunMousePicking(const std::shared_ptr& mapContext, - const QMapLibre::CustomLayerRenderParameters& params, + RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params, const QPointF& mouseLocalPos, const QPointF& mouseGlobalPos, const glm::vec2& mouseCoords, @@ -54,11 +55,12 @@ signals: void NeedsRendering(); protected: - [[nodiscard]] std::shared_ptr gl_context() const; + std::shared_ptr context() const; private: - class Impl; - std::unique_ptr p; + std::unique_ptr p; }; -} // namespace scwx::qt::map +} // namespace map +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/map/layer_wrapper.cpp b/scwx-qt/source/scwx/qt/map/layer_wrapper.cpp index 5a60f90b..88fc7df9 100644 --- a/scwx-qt/source/scwx/qt/map/layer_wrapper.cpp +++ b/scwx-qt/source/scwx/qt/map/layer_wrapper.cpp @@ -1,31 +1,27 @@ #include -namespace scwx::qt::map +namespace scwx +{ +namespace qt +{ +namespace map { -class LayerWrapper::Impl +class LayerWrapperImpl { public: - explicit Impl(std::shared_ptr layer, - std::shared_ptr mapContext) : - layer_ {std::move(layer)}, mapContext_ {std::move(mapContext)} + explicit LayerWrapperImpl(std::shared_ptr layer) : + layer_ {layer} { } - ~Impl() = default; - - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; + ~LayerWrapperImpl() {} std::shared_ptr layer_; - std::shared_ptr mapContext_; }; -LayerWrapper::LayerWrapper(std::shared_ptr layer, - std::shared_ptr mapContext) : - p(std::make_unique(std::move(layer), std::move(mapContext))) +LayerWrapper::LayerWrapper(std::shared_ptr layer) : + p(std::make_unique(layer)) { } LayerWrapper::~LayerWrapper() = default; @@ -38,7 +34,7 @@ void LayerWrapper::initialize() auto& layer = p->layer_; if (layer != nullptr) { - layer->Initialize(p->mapContext_); + layer->Initialize(); } } @@ -47,7 +43,7 @@ void LayerWrapper::render(const QMapLibre::CustomLayerRenderParameters& params) auto& layer = p->layer_; if (layer != nullptr) { - layer->Render(p->mapContext_, params); + layer->Render(params); } } @@ -62,4 +58,6 @@ void LayerWrapper::deinitialize() } } -} // namespace scwx::qt::map +} // namespace map +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/map/layer_wrapper.hpp b/scwx-qt/source/scwx/qt/map/layer_wrapper.hpp index ae133c29..6e0e44ee 100644 --- a/scwx-qt/source/scwx/qt/map/layer_wrapper.hpp +++ b/scwx-qt/source/scwx/qt/map/layer_wrapper.hpp @@ -1,16 +1,20 @@ #pragma once #include -#include -namespace scwx::qt::map +namespace scwx { +namespace qt +{ +namespace map +{ + +class LayerWrapperImpl; class LayerWrapper : public QMapLibre::CustomLayerHostInterface { public: - explicit LayerWrapper(std::shared_ptr layer, - std::shared_ptr mapContext); + explicit LayerWrapper(std::shared_ptr layer); ~LayerWrapper(); LayerWrapper(const LayerWrapper&) = delete; @@ -19,13 +23,14 @@ public: LayerWrapper(LayerWrapper&&) noexcept; LayerWrapper& operator=(LayerWrapper&&) noexcept; - void initialize() final; - void render(const QMapLibre::CustomLayerRenderParameters&) final; - void deinitialize() final; + void initialize() override final; + void render(const QMapLibre::CustomLayerRenderParameters&) override final; + void deinitialize() override final; private: - class Impl; - std::unique_ptr p; + std::unique_ptr p; }; -} // namespace scwx::qt::map +} // namespace map +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/map/map_context.cpp b/scwx-qt/source/scwx/qt/map/map_context.cpp index 1d1b5c4d..c659c432 100644 --- a/scwx-qt/source/scwx/qt/map/map_context.cpp +++ b/scwx-qt/source/scwx/qt/map/map_context.cpp @@ -3,7 +3,11 @@ #include #include -namespace scwx::qt::map +namespace scwx +{ +namespace qt +{ +namespace map { class MapContext::Impl @@ -21,9 +25,9 @@ public: float pixelRatio_ {1.0f}; common::RadarProductGroup radarProductGroup_ { common::RadarProductGroup::Unknown}; - std::string radarProduct_ {"???"}; - int16_t radarProductCode_ {0}; - std::shared_ptr radarSite_ {nullptr}; + std::string radarProduct_ {"???"}; + int16_t radarProductCode_ {0}; + QMapLibre::CustomLayerRenderParameters renderParameters_ {}; MapProvider mapProvider_ {MapProvider::Unknown}; std::string mapCopyrights_ {}; @@ -33,8 +37,6 @@ public: std::shared_ptr overlayProductView_ {nullptr}; std::shared_ptr radarProductView_; - - QWidget* widget_; }; MapContext::MapContext( @@ -103,19 +105,14 @@ std::string MapContext::radar_product() const return p->radarProduct_; } -std::shared_ptr MapContext::radar_site() const -{ - return p->radarSite_; -} - int16_t MapContext::radar_product_code() const { return p->radarProductCode_; } -QWidget* MapContext::widget() const +QMapLibre::CustomLayerRenderParameters MapContext::render_parameters() const { - return p->widget_; + return p->renderParameters_; } void MapContext::set_map(const std::shared_ptr& map) @@ -176,14 +173,12 @@ void MapContext::set_radar_product_code(int16_t radarProductCode) p->radarProductCode_ = radarProductCode; } -void MapContext::set_radar_site(const std::shared_ptr& site) +void MapContext::set_render_parameters( + const QMapLibre::CustomLayerRenderParameters& params) { - p->radarSite_ = site; + p->renderParameters_ = params; } -void MapContext::set_widget(QWidget* widget) -{ - p->widget_ = widget; -} - -} // namespace scwx::qt::map +} // namespace map +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/map/map_context.hpp b/scwx-qt/source/scwx/qt/map/map_context.hpp index ba319b95..86f49b8f 100644 --- a/scwx-qt/source/scwx/qt/map/map_context.hpp +++ b/scwx-qt/source/scwx/qt/map/map_context.hpp @@ -1,27 +1,31 @@ #pragma once +#include #include #include #include -#include #include #include -namespace scwx::qt::view +namespace scwx +{ +namespace qt +{ +namespace view { class OverlayProductView; class RadarProductView; -} // namespace scwx::qt::view +} // namespace view -namespace scwx::qt::map +namespace map { struct MapSettings; -class MapContext +class MapContext : public gl::GlContext { public: explicit MapContext( @@ -34,22 +38,19 @@ public: MapContext(MapContext&&) noexcept; MapContext& operator=(MapContext&&) noexcept; - [[nodiscard]] std::weak_ptr map() const; - [[nodiscard]] std::string map_copyrights() const; - [[nodiscard]] MapProvider map_provider() const; - [[nodiscard]] MapSettings& settings(); - [[nodiscard]] QMargins color_table_margins() const; - [[nodiscard]] float pixel_ratio() const; - [[nodiscard]] common::Coordinate mouse_coordinate() const; - [[nodiscard]] std::shared_ptr - overlay_product_view() const; - [[nodiscard]] std::shared_ptr - radar_product_view() const; - [[nodiscard]] common::RadarProductGroup radar_product_group() const; - [[nodiscard]] std::string radar_product() const; - [[nodiscard]] int16_t radar_product_code() const; - [[nodiscard]] std::shared_ptr radar_site() const; - [[nodiscard]] QWidget* widget() const; + std::weak_ptr map() const; + std::string map_copyrights() const; + MapProvider map_provider() const; + MapSettings& settings(); + QMargins color_table_margins() const; + float pixel_ratio() const; + common::Coordinate mouse_coordinate() const; + std::shared_ptr overlay_product_view() const; + std::shared_ptr radar_product_view() const; + common::RadarProductGroup radar_product_group() const; + std::string radar_product() const; + int16_t radar_product_code() const; + QMapLibre::CustomLayerRenderParameters render_parameters() const; void set_map(const std::shared_ptr& map); void set_map_copyrights(const std::string& copyrights); @@ -64,8 +65,8 @@ public: void set_radar_product_group(common::RadarProductGroup radarProductGroup); void set_radar_product(const std::string& radarProduct); void set_radar_product_code(int16_t radarProductCode); - void set_radar_site(const std::shared_ptr& site); - void set_widget(QWidget* widget); + void + set_render_parameters(const QMapLibre::CustomLayerRenderParameters& params); private: class Impl; @@ -73,4 +74,6 @@ private: std::unique_ptr p; }; -} // namespace scwx::qt::map +} // namespace map +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/map/map_provider.cpp b/scwx-qt/source/scwx/qt/map/map_provider.cpp index b1b5979d..586d012c 100644 --- a/scwx-qt/source/scwx/qt/map/map_provider.cpp +++ b/scwx-qt/source/scwx/qt/map/map_provider.cpp @@ -5,7 +5,11 @@ #include -namespace scwx::qt::map +namespace scwx +{ +namespace qt +{ +namespace map { static const std::unordered_map mapProviderName_ { @@ -20,10 +24,10 @@ static const std::vector mapboxDrawBelow_ { static const std::unordered_map mapProviderInfo_ { {MapProvider::Mapbox, MapProviderInfo { - .mapProvider_ = MapProvider::Mapbox, + .mapProvider_ {MapProvider::Mapbox}, .cacheDbName_ {"mbgl-cache.db"}, - .providerTemplate_ = - QMapLibre::Settings::ProviderTemplate::MapboxProvider, + .providerTemplate_ { + QMapLibre::Settings::ProviderTemplate::MapboxProvider}, .mapStyles_ { {.name_ {"Streets"}, .url_ {"mapbox://styles/mapbox/streets-v11"}, @@ -113,10 +117,10 @@ static const std::unordered_map mapProviderInfo_ { .drawBelow_ {mapboxDrawBelow_}}}}}, {MapProvider::MapTiler, MapProviderInfo { - .mapProvider_ = MapProvider::MapTiler, + .mapProvider_ {MapProvider::MapTiler}, .cacheDbName_ {"maptiler-cache.db"}, - .providerTemplate_ = - QMapLibre::Settings::ProviderTemplate::MapTilerProvider, + .providerTemplate_ { + QMapLibre::Settings::ProviderTemplate::MapTilerProvider}, .mapStyles_ { {.name_ {"Satellite"}, .url_ {"https://api.maptiler.com/maps/hybrid/style.json"}, @@ -145,9 +149,6 @@ static const std::unordered_map mapProviderInfo_ { {.name_ {"Landscape"}, .url_ {"https://api.maptiler.com/maps/landscape/style.json"}, .drawBelow_ {"Runway"}}, - {.name_ {"Ocean"}, - .url_ {"https://api.maptiler.com/maps/ocean/style.json"}, - .drawBelow_ {"Landform labels"}}, {.name_ {"Outdoor"}, .url_ {"https://api.maptiler.com/maps/outdoor-v2/style.json"}, .drawBelow_ {"aeroway_runway", "Aeroway"}}, @@ -166,9 +167,6 @@ static const std::unordered_map mapProviderInfo_ { .url_ {"https://api.maptiler.com/maps/ch-swisstopo-lbm-vivid/" "style.json"}, .drawBelow_ {"pattern_landcover_vineyard", "Vineyard pattern"}}, - {.name_ {"Toner"}, - .url_ {"https://api.maptiler.com/maps/toner-v2/style.json"}, - .drawBelow_ {"Bridge"}}, {.name_ {"Topo"}, .url_ {"https://api.maptiler.com/maps/topo-v2/style.json"}, .drawBelow_ {"aeroway_runway", "Runway"}}, @@ -239,4 +237,6 @@ const MapProviderInfo& GetMapProviderInfo(MapProvider mapProvider) return mapProviderInfo_.at(mapProvider); } -} // namespace scwx::qt::map +} // namespace map +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/map/map_provider.hpp b/scwx-qt/source/scwx/qt/map/map_provider.hpp index 1ef6fe80..5bdd67fc 100644 --- a/scwx-qt/source/scwx/qt/map/map_provider.hpp +++ b/scwx-qt/source/scwx/qt/map/map_provider.hpp @@ -6,7 +6,11 @@ #include -namespace scwx::qt::map +namespace scwx +{ +namespace qt +{ +namespace map { enum class MapProvider @@ -15,8 +19,9 @@ enum class MapProvider MapTiler, Unknown }; -using MapProviderIterator = scwx::util:: - Iterator; +typedef scwx::util:: + Iterator + MapProviderIterator; struct MapStyle { @@ -24,7 +29,7 @@ struct MapStyle std::string url_; std::vector drawBelow_; - [[nodiscard]] bool IsValid() const; + bool IsValid() const; }; struct MapProviderInfo @@ -40,4 +45,6 @@ std::string GetMapProviderName(MapProvider mapProvider); std::string GetMapProviderApiKey(MapProvider mapProvider); const MapProviderInfo& GetMapProviderInfo(MapProvider mapProvider); -} // namespace scwx::qt::map +} // namespace map +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/map/map_settings.hpp b/scwx-qt/source/scwx/qt/map/map_settings.hpp index 05a69b42..642c8fa1 100644 --- a/scwx-qt/source/scwx/qt/map/map_settings.hpp +++ b/scwx-qt/source/scwx/qt/map/map_settings.hpp @@ -1,21 +1,26 @@ #pragma once -namespace scwx::qt::map +namespace scwx +{ +namespace qt +{ +namespace map { struct MapSettings { - explicit MapSettings() = default; - ~MapSettings() = default; + explicit MapSettings() : isActive_ {false} {} + ~MapSettings() = default; - MapSettings(const MapSettings&) = delete; + MapSettings(const MapSettings&) = delete; MapSettings& operator=(const MapSettings&) = delete; - MapSettings(MapSettings&&) noexcept = default; + MapSettings(MapSettings&&) noexcept = default; MapSettings& operator=(MapSettings&&) noexcept = default; - bool isActive_ {false}; - bool radarWireframeEnabled_ {false}; + bool isActive_; }; -} // namespace scwx::qt::map +} // namespace map +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/map/map_widget.cpp b/scwx-qt/source/scwx/qt/map/map_widget.cpp index 537318f0..e718bc0e 100644 --- a/scwx-qt/source/scwx/qt/map/map_widget.cpp +++ b/scwx-qt/source/scwx/qt/map/map_widget.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -19,9 +18,7 @@ #include #include #include -#include #include -#include #include #include #include @@ -30,10 +27,7 @@ #include #include -#include -#include #include -#include #include #include @@ -54,11 +48,14 @@ #include #include #include -#include #include #include -namespace scwx::qt::map +namespace scwx +{ +namespace qt +{ +namespace map { static const std::string logPrefix_ = "scwx::qt::map::map_widget"; @@ -69,15 +66,14 @@ class MapWidgetImpl : public QObject Q_OBJECT public: - explicit MapWidgetImpl(MapWidget* widget, - std::size_t id, - QMapLibre::Settings settings, - std::shared_ptr glContext) : + explicit MapWidgetImpl(MapWidget* widget, + std::size_t id, + const QMapLibre::Settings& settings) : id_ {id}, uuid_ {boost::uuids::random_generator()()}, - glContext_ {std::move(glContext)}, + context_ {std::make_shared()}, widget_ {widget}, - settings_(std::move(settings)), + settings_(settings), map_(), layerList_ {}, imGuiRendererInitialized_ {false}, @@ -85,7 +81,6 @@ public: radarProductLayer_ {nullptr}, overlayLayer_ {nullptr}, placefileLayer_ {nullptr}, - markerLayer_ {nullptr}, colorTableLayer_ {nullptr}, autoRefreshEnabled_ {true}, autoUpdateEnabled_ {true}, @@ -97,8 +92,7 @@ public: prevLongitude_ {0.0}, prevZoom_ {0.0}, prevBearing_ {0.0}, - prevPitch_ {0.0}, - tiltsToIndices_ {} + prevPitch_ {0.0} { // Create views auto overlayProductView = std::make_shared(); @@ -109,17 +103,13 @@ public: map::AlertLayer::InitializeHandler(); auto& generalSettings = settings::GeneralSettings::Instance(); - auto& mapSettings = settings::MapSettings::Instance(); // Initialize context context_->set_map_provider( GetMapProvider(generalSettings.map_provider().GetValue())); context_->set_overlay_product_view(overlayProductView); - context_->set_widget(widget); - // Initialize map data SetRadarSite(generalSettings.default_radar_site().GetValue()); - smoothingEnabled_ = mapSettings.smoothing_enabled(id).GetValue(); // Create ImGui Context static size_t currentMapId_ {0u}; @@ -131,13 +121,12 @@ public: ImGui_ImplQt_Init(); InitializeCustomStyles(); + + ConnectSignals(); } ~MapWidgetImpl() { - // Disconnect signals - colorPaletteConnection_.disconnect(); - DeinitializeCustomStyles(); // Set ImGui Context @@ -159,9 +148,9 @@ public: void AddLayer(types::LayerType type, types::LayerDescription description, const std::string& before = {}); - void AddLayer(const std::string& id, - const std::shared_ptr& layer, - const std::string& before = {}); + void AddLayer(const std::string& id, + std::shared_ptr layer, + const std::string& before = {}); void AddLayers(); void AddPlacefileLayer(const std::string& placefileName, const std::string& before); @@ -171,7 +160,7 @@ public: void HandleHotkeyPressed(types::Hotkey hotkey, bool isAutoRepeat); void HandleHotkeyReleased(types::Hotkey hotkey); void HandleHotkeyUpdates(); - void HandlePinchGesture(QPinchGesture* gesture); + void ImGuiCheckFonts(); void InitializeCustomStyles(); void InitializeNewRadarProductView(const std::string& colorPalette); void RadarProductManagerConnect(); @@ -182,12 +171,11 @@ public: void SelectNearestRadarSite(double latitude, double longitude, std::optional type); - void SetRadarSite(const std::string& radarSite, - bool checkProductAvailability = false); - void UpdateColorTable(const std::string& colorPalette); + void SetRadarSite(const std::string& radarSite); void UpdateLoadedStyle(); bool UpdateStoredMapParameters(); - void CheckLevel3Availability(); + + std::string FindMapSymbologyLayer(); common::Level2Product GetLevel2ProductOrDefault(const std::string& productName) const; @@ -199,8 +187,7 @@ public: std::size_t id_; boost::uuids::uuid uuid_; - std::shared_ptr context_ {std::make_shared()}; - std::shared_ptr glContext_; + std::shared_ptr context_; MapWidget* widget_; QMapLibre::Settings settings_; @@ -212,22 +199,20 @@ public: const std::vector emptyStyles_ {}; std::vector customStyles_ { MapStyle {.name_ {"Custom"}, .url_ {}, .drawBelow_ {}}}; - QStringList styleLayers_; + QStringList styleLayers_; + types::LayerVector customLayers_; boost::uuids::uuid customStyleUrlChangedCallbackId_ {}; boost::uuids::uuid customStyleDrawBelowChangedCallbackId_ {}; - boost::signals2::scoped_connection colorPaletteConnection_ {}; - ImGuiContext* imGuiContext_; std::string imGuiContextName_; - bool imGuiRendererInitialized_ {false}; + bool imGuiRendererInitialized_; + std::uint64_t imGuiFontsBuildCount_ {}; std::shared_ptr layerModel_ { model::LayerModel::Instance()}; - ui::EditMarkerDialog* editMarkerDialog_ {nullptr}; - std::shared_ptr hotkeyManager_ { manager::HotkeyManager::Instance()}; std::shared_ptr placefileManager_ { @@ -238,7 +223,6 @@ public: std::shared_ptr overlayLayer_; std::shared_ptr overlayProductLayer_ {nullptr}; std::shared_ptr placefileLayer_; - std::shared_ptr markerLayer_; std::shared_ptr colorTableLayer_; std::shared_ptr radarSiteLayer_ {nullptr}; @@ -246,7 +230,6 @@ public: bool autoRefreshEnabled_; bool autoUpdateEnabled_; - bool smoothingEnabled_ {false}; common::Level2Product selectedLevel2Product_; @@ -275,21 +258,12 @@ public: std::set activeHotkeys_ {}; std::chrono::system_clock::time_point prevHotkeyTime_ {}; - bool productAvailabilityCheckNeeded_ {false}; - bool productAvailabilityUpdated_ {false}; - bool productAvailabilityProductSelected_ {false}; - - std::unordered_map tiltsToIndices_; - size_t currentTiltIndex_ {0}; - public slots: void Update(); }; -MapWidget::MapWidget(std::size_t id, - const QMapLibre::Settings& settings, - std::shared_ptr glContext) : - p(std::make_unique(this, id, settings, std::move(glContext))) +MapWidget::MapWidget(std::size_t id, const QMapLibre::Settings& settings) : + p(std::make_unique(this, id, settings)) { if (settings::GeneralSettings::Instance().anti_aliasing_enabled().GetValue()) { @@ -300,15 +274,7 @@ MapWidget::MapWidget(std::size_t id, setFocusPolicy(Qt::StrongFocus); - grabGesture(Qt::GestureType::PinchGesture); - ImGui_ImplQt_RegisterWidget(this); - - // Qt parent deals with memory management - // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - p->editMarkerDialog_ = new ui::EditMarkerDialog(this); - - p->ConnectSignals(); } MapWidget::~MapWidget() @@ -388,7 +354,7 @@ void MapWidgetImpl::ConnectSignals() connect(placefileManager_.get(), &manager::PlacefileManager::PlacefileUpdated, widget_, - static_cast(&QWidget::update)); + [this]() { widget_->update(); }); // When the layer model changes, update the layers connect(layerModel_.get(), @@ -447,14 +413,6 @@ void MapWidgetImpl::ConnectSignals() &manager::HotkeyManager::HotkeyReleased, this, &MapWidgetImpl::HandleHotkeyReleased); - connect(widget_, - &MapWidget::RadarSiteUpdated, - widget_, - [this](const std::shared_ptr&) - { - productAvailabilityProductSelected_ = true; - CheckLevel3Availability(); - }); } void MapWidgetImpl::HandleHotkeyPressed(types::Hotkey hotkey, bool isAutoRepeat) @@ -463,16 +421,6 @@ void MapWidgetImpl::HandleHotkeyPressed(types::Hotkey hotkey, bool isAutoRepeat) switch (hotkey) { - case types::Hotkey::AddLocationMarker: - if (hasMouse_) - { - auto coordinate = map_->coordinateForPixel(lastPos_); - - editMarkerDialog_->setup(coordinate.first, coordinate.second); - editMarkerDialog_->show(); - } - break; - case types::Hotkey::ChangeMapStyle: if (context_->settings().isActive_) { @@ -612,15 +560,6 @@ void MapWidgetImpl::HandleHotkeyUpdates() } } -void MapWidgetImpl::HandlePinchGesture(QPinchGesture* gesture) -{ - if (gesture->changeFlags() & QPinchGesture::ChangeFlag::ScaleFactorChanged) - { - map_->scaleBy(gesture->scaleFactor(), - widget_->mapFromGlobal(gesture->centerPoint())); - } -} - common::Level3ProductCategoryMap MapWidget::GetAvailableLevel3Categories() { if (p->radarProductManager_ != nullptr) @@ -633,7 +572,7 @@ common::Level3ProductCategoryMap MapWidget::GetAvailableLevel3Categories() } } -std::optional MapWidget::GetElevation() const +float MapWidget::GetElevation() const { auto radarProductView = p->context_->radar_product_view(); @@ -643,7 +582,7 @@ std::optional MapWidget::GetElevation() const } else { - return {}; + return 0.0f; } } @@ -661,11 +600,6 @@ std::vector MapWidget::GetElevationCuts() const } } -std::optional MapWidget::GetIncomingLevel2Elevation() const -{ - return p->radarProductManager_->incoming_level_2_elevation(); -} - common::Level2Product MapWidgetImpl::GetLevel2ProductOrDefault(const std::string& productName) const { @@ -790,40 +724,6 @@ std::uint16_t MapWidget::GetVcp() const } } -bool MapWidget::GetRadarWireframeEnabled() const -{ - return p->context_->settings().radarWireframeEnabled_; -} - -void MapWidget::SetRadarWireframeEnabled(bool wireframeEnabled) -{ - p->context_->settings().radarWireframeEnabled_ = wireframeEnabled; - QMetaObject::invokeMethod( - this, static_cast(&QWidget::update)); -} - -bool MapWidget::GetSmoothingEnabled() const -{ - return p->smoothingEnabled_; -} - -void MapWidget::SetSmoothingEnabled(bool smoothingEnabled) -{ - p->smoothingEnabled_ = smoothingEnabled; - - auto radarProductView = p->context_->radar_product_view(); - if (radarProductView != nullptr) - { - radarProductView->set_smoothing_enabled(smoothingEnabled); - radarProductView->Update(); - } -} - -const scwx::util::time_zone* MapWidget::GetDefaultTimeZone() const -{ - return p->radarProductManager_->default_time_zone(); -} - void MapWidget::SelectElevation(float elevation) { auto radarProductView = p->context_->radar_product_view(); @@ -861,17 +761,6 @@ void MapWidget::SelectRadarProduct(common::RadarProductGroup group, productCode = common::GetLevel3ProductCodeByAwipsId(productName); } - if (group == common::RadarProductGroup::Level3) - { - const auto& tiltIndex = p->tiltsToIndices_.find(productName); - p->currentTiltIndex_ = - tiltIndex != p->tiltsToIndices_.cend() ? tiltIndex->second : 0; - } - else - { - p->currentTiltIndex_ = 0; - } - if (radarProductView == nullptr || radarProductView->GetRadarProductGroup() != group || (radarProductView->GetRadarProductGroup() == @@ -883,7 +772,6 @@ void MapWidget::SelectRadarProduct(common::RadarProductGroup group, radarProductView = view::RadarProductViewFactory::Create( group, productName, productCode, p->radarProductManager_); - radarProductView->set_smoothing_enabled(p->smoothingEnabled_); p->context_->set_radar_product_view(radarProductView); p->RadarProductViewConnect(); @@ -910,13 +798,6 @@ void MapWidget::SelectRadarProduct(common::RadarProductGroup group, (group == common::RadarProductGroup::Level2) ? common::GetLevel2Palette(common::GetLevel2Product(productName)) : common::GetLevel3Palette(productCode); - - auto& paletteSetting = - settings::PaletteSettings::Instance().palette(palette); - - p->colorPaletteConnection_ = paletteSetting.changed_signal().connect( - [this, palette]() { p->UpdateColorTable(palette); }); - p->InitializeNewRadarProductView(palette); } else if (update) @@ -976,13 +857,18 @@ void MapWidget::SelectRadarSite(std::shared_ptr radarSite, p->map_->setCoordinate( {radarSite->latitude(), radarSite->longitude()}); } - p->SetRadarSite(radarSite->id(), true); + p->SetRadarSite(radarSite->id()); p->Update(); // Select products from new site if (radarProductView != nullptr) { radarProductView->set_radar_product_manager(p->radarProductManager_); + SelectRadarProduct(radarProductView->GetRadarProductGroup(), + radarProductView->GetRadarProductName(), + 0, + radarProductView->selected_time(), + false); } p->AddLayers(); @@ -1014,8 +900,7 @@ void MapWidget::SelectTime(std::chrono::system_clock::time_point time) void MapWidget::SetActive(bool isActive) { p->context_->settings().isActive_ = isActive; - QMetaObject::invokeMethod( - this, static_cast(&QWidget::update)); + update(); } void MapWidget::SetAutoRefresh(bool enabled) @@ -1131,18 +1016,14 @@ void MapWidget::UpdateMouseCoordinate(const common::Coordinate& coordinate) { if (p->context_->mouse_coordinate() != coordinate) { - auto& generalSettings = settings::GeneralSettings::Instance(); - p->context_->set_mouse_coordinate(coordinate); auto keyboardModifiers = QGuiApplication::keyboardModifiers(); - if (generalSettings.cursor_icon_always_on().GetValue() || - keyboardModifiers != Qt::KeyboardModifier::NoModifier || + if (keyboardModifiers != Qt::KeyboardModifier::NoModifier || keyboardModifiers != p->lastKeyboardModifiers_) { - QMetaObject::invokeMethod( - this, static_cast(&QWidget::update)); + update(); } p->lastKeyboardModifiers_ = keyboardModifiers; @@ -1189,6 +1070,43 @@ void MapWidget::DumpLayerList() const logger_->info("Layers: {}", p->map_->layerIds().join(", ").toStdString()); } +std::string MapWidgetImpl::FindMapSymbologyLayer() +{ + std::string before = "ferry"; + + for (const QString& qlayer : styleLayers_) + { + const std::string layer = qlayer.toStdString(); + + // Draw below layers defined in map style + auto it = std::find_if(currentStyle_->drawBelow_.cbegin(), + currentStyle_->drawBelow_.cend(), + [&layer](const std::string& styleLayer) -> bool + { + // Perform case-insensitive matching + RE2 re {"(?i)" + styleLayer}; + if (re.ok()) + { + return RE2::FullMatch(layer, re); + } + else + { + // Fall back to basic comparison if RE + // doesn't compile + return layer == styleLayer; + } + }); + + if (it != currentStyle_->drawBelow_.cend()) + { + before = layer; + break; + } + } + + return before; +} + void MapWidgetImpl::AddLayers() { if (styleLayers_.isEmpty()) @@ -1209,23 +1127,22 @@ void MapWidgetImpl::AddLayers() placefileLayers_.clear(); // Update custom layer list from model - types::LayerVector customLayers = model::LayerModel::Instance()->GetLayers(); + customLayers_ = model::LayerModel::Instance()->GetLayers(); // Start by drawing layers before any style-defined layers std::string before = styleLayers_.front().toStdString(); // Loop through each custom layer in reverse order - for (const auto& customLayer : std::ranges::reverse_view(customLayers)) + for (auto it = customLayers_.crbegin(); it != customLayers_.crend(); ++it) { - if (customLayer.type_ == types::LayerType::Map) + if (it->type_ == types::LayerType::Map) { // Style-defined map layers - switch (std::get(customLayer.description_)) + switch (std::get(it->description_)) { // Subsequent layers are drawn underneath the map symbology layer case types::MapLayer::MapUnderlay: - before = util::maplibre::FindMapSymbologyLayer( - styleLayers_, currentStyle_->drawBelow_); + before = FindMapSymbologyLayer(); break; // Subsequent layers are drawn after all style-defined layers @@ -1237,12 +1154,10 @@ void MapWidgetImpl::AddLayers() break; } } - // id_ is always < 4, so this is safe - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-constant-array-index) - else if (customLayer.displayed_[id_]) + else if (it->displayed_[id_]) { // If the layer is displayed for the current map, add it - AddLayer(customLayer.type_, customLayer.description_, before); + AddLayer(it->type_, it->description_, before); } } } @@ -1260,7 +1175,7 @@ void MapWidgetImpl::AddLayer(types::LayerType type, // If there is a radar product view, create the radar product layer if (radarProductView != nullptr) { - radarProductLayer_ = std::make_shared(glContext_); + radarProductLayer_ = std::make_shared(context_); AddLayer(layerName, radarProductLayer_, before); } } @@ -1269,7 +1184,7 @@ void MapWidgetImpl::AddLayer(types::LayerType type, auto phenomenon = std::get(description); std::shared_ptr alertLayer = - std::make_shared(glContext_, phenomenon); + std::make_shared(context_, phenomenon); AddLayer(fmt::format("alert.{}", awips::GetPhenomenonCode(phenomenon)), alertLayer, before); @@ -1293,7 +1208,7 @@ void MapWidgetImpl::AddLayer(types::LayerType type, { // Create the map overlay layer case types::InformationLayer::MapOverlay: - overlayLayer_ = std::make_shared(glContext_); + overlayLayer_ = std::make_shared(context_); AddLayer(layerName, overlayLayer_, before); break; @@ -1301,31 +1216,20 @@ void MapWidgetImpl::AddLayer(types::LayerType type, case types::InformationLayer::ColorTable: if (radarProductView != nullptr) { - colorTableLayer_ = std::make_shared(glContext_); + colorTableLayer_ = std::make_shared(context_); AddLayer(layerName, colorTableLayer_, before); } break; // Create the radar site layer case types::InformationLayer::RadarSite: - radarSiteLayer_ = std::make_shared(glContext_); + radarSiteLayer_ = std::make_shared(context_); AddLayer(layerName, radarSiteLayer_, before); - connect( - radarSiteLayer_.get(), - &RadarSiteLayer::RadarSiteSelected, - this, - [this](const std::string& id) - { - auto& generalSettings = settings::GeneralSettings::Instance(); - widget_->RadarSiteRequested( - id, generalSettings.center_on_radar_selection().GetValue()); - }); - break; - - // Create the location marker layer - case types::InformationLayer::Markers: - markerLayer_ = std::make_shared(glContext_); - AddLayer(layerName, markerLayer_, before); + connect(radarSiteLayer_.get(), + &RadarSiteLayer::RadarSiteSelected, + this, + [this](const std::string& id) + { widget_->RadarSiteRequested(id); }); break; default: @@ -1341,7 +1245,7 @@ void MapWidgetImpl::AddLayer(types::LayerType type, if (radarProductView != nullptr) { overlayProductLayer_ = - std::make_shared(glContext_); + std::make_shared(context_); AddLayer(layerName, overlayProductLayer_, before); } break; @@ -1371,7 +1275,7 @@ void MapWidgetImpl::AddPlacefileLayer(const std::string& placefileName, const std::string& before) { std::shared_ptr placefileLayer = - std::make_shared(glContext_, placefileName); + std::make_shared(context_, placefileName); placefileLayers_.push_back(placefileLayer); AddLayer(GetPlacefileLayerName(placefileName), placefileLayer, before); @@ -1379,7 +1283,7 @@ void MapWidgetImpl::AddPlacefileLayer(const std::string& placefileName, connect(placefileLayer.get(), &PlacefileLayer::DataReloaded, widget_, - static_cast(&QWidget::update)); + [this]() { widget_->update(); }); } std::string @@ -1388,13 +1292,13 @@ MapWidgetImpl::GetPlacefileLayerName(const std::string& placefileName) return types::GetLayerName(types::LayerType::Placefile, placefileName); } -void MapWidgetImpl::AddLayer(const std::string& id, - const std::shared_ptr& layer, - const std::string& before) +void MapWidgetImpl::AddLayer(const std::string& id, + std::shared_ptr layer, + const std::string& before) { // QMapLibre::addCustomLayer will take ownership of the std::unique_ptr std::unique_ptr pHost = - std::make_unique(layer, context_); + std::make_unique(layer); try { @@ -1406,7 +1310,7 @@ void MapWidgetImpl::AddLayer(const std::string& id, connect(layer.get(), &GenericLayer::NeedsRendering, widget_, - static_cast(&QWidget::update)); + [this]() { widget_->update(); }); } catch (const std::exception&) { @@ -1431,18 +1335,6 @@ bool MapWidget::event(QEvent* e) } pickedEventHandler.reset(); - switch (e->type()) - { - case QEvent::Type::Gesture: - // QEvent is always a QGestureEvent - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-static-cast-downcast) - gestureEvent(static_cast(e)); - break; - - default: - break; - } - return QOpenGLWidget::event(e); } @@ -1472,16 +1364,6 @@ void MapWidget::keyReleaseEvent(QKeyEvent* ev) } } -void MapWidget::gestureEvent(QGestureEvent* ev) -{ - if (QGesture* pinch = ev->gesture(Qt::PinchGesture)) - { - // QGesture is always a QPinchGesture - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-static-cast-downcast) - p->HandlePinchGesture(static_cast(pinch)); - } -} - void MapWidget::mousePressEvent(QMouseEvent* ev) { p->lastPos_ = ev->position(); @@ -1562,8 +1444,7 @@ void MapWidget::initializeGL() logger_->debug("initializeGL()"); makeCurrent(); - - p->glContext_->Initialize(); + p->context_->Initialize(); // Lock ImGui font atlas prior to new ImGui frame std::shared_lock imguiFontAtlasLock { @@ -1573,6 +1454,8 @@ void MapWidget::initializeGL() ImGui::SetCurrentContext(p->imGuiContext_); ImGui_ImplQt_RegisterWidget(this); ImGui_ImplOpenGL3_Init(); + p->imGuiFontsBuildCount_ = + manager::FontManager::Instance().imgui_fonts_build_count(); p->imGuiRendererInitialized_ = true; p->map_.reset( @@ -1615,37 +1498,36 @@ void MapWidget::paintGL() p->frameDraws_++; - p->glContext_->StartFrame(); + p->context_->StartFrame(); // Handle hotkey updates p->HandleHotkeyUpdates(); + // Setup ImGui Frame + ImGui::SetCurrentContext(p->imGuiContext_); + // Lock ImGui font atlas prior to new ImGui frame std::shared_lock imguiFontAtlasLock { manager::FontManager::Instance().imgui_font_atlas_mutex()}; + // Start ImGui Frame + ImGui_ImplQt_NewFrame(this); + ImGui_ImplOpenGL3_NewFrame(); + p->ImGuiCheckFonts(); + ImGui::NewFrame(); + + // Set default font + ImGui::PushFont(defaultFont->font()); + // Update pixel ratio p->context_->set_pixel_ratio(pixelRatio()); // Render QMapLibre Map p->map_->resize(size()); - p->map_->setOpenGLFramebufferObject(defaultFramebufferObject(), - size() * pixelRatio()); + p->map_->setFramebufferObject(defaultFramebufferObject(), + size() * pixelRatio()); p->map_->render(); - // ImGui tool tip code - // Setup ImGui Frame - ImGui::SetCurrentContext(p->imGuiContext_); - - // Start ImGui Frame - model::ImGuiContextModel::Instance().NewFrame(); - ImGui_ImplQt_NewFrame(this); - ImGui_ImplOpenGL3_NewFrame(); - ImGui::NewFrame(); - - // Set default font - ImGui::PushFont(defaultFont.first->font(), defaultFont.second.value()); - // Perform mouse picking if (p->hasMouse_) { @@ -1675,17 +1557,26 @@ void MapWidget::paintGL() p->isPainting_ = false; } +void MapWidgetImpl::ImGuiCheckFonts() +{ + // Update ImGui Fonts if required + std::uint64_t currentImGuiFontsBuildCount = + manager::FontManager::Instance().imgui_fonts_build_count(); + + if (imGuiFontsBuildCount_ != currentImGuiFontsBuildCount || + !model::ImGuiContextModel::Instance().font_atlas()->IsBuilt()) + { + ImGui_ImplOpenGL3_DestroyFontsTexture(); + ImGui_ImplOpenGL3_CreateFontsTexture(); + } + + imGuiFontsBuildCount_ = currentImGuiFontsBuildCount; +} + void MapWidgetImpl::RunMousePicking() { - const QMapLibre::CustomLayerRenderParameters params = { - .width = static_cast(widget_->size().width()), - .height = static_cast(widget_->size().height()), - .latitude = map_->coordinate().first, - .longitude = map_->coordinate().second, - .zoom = map_->zoom(), - .bearing = map_->bearing(), - .pitch = map_->pitch(), - .fieldOfView = 0}; + const QMapLibre::CustomLayerRenderParameters params = + context_->render_parameters(); auto coordinate = map_->coordinateForPixel(lastPos_); auto mouseScreenCoordinate = @@ -1697,8 +1588,7 @@ void MapWidgetImpl::RunMousePicking() for (auto it = genericLayers_.rbegin(); it != genericLayers_.rend(); ++it) { // Run mouse picking for each layer - if ((*it)->RunMousePicking(context_, - params, + if ((*it)->RunMousePicking(params, lastPos_, lastGlobalPos_, mouseScreenCoordinate, @@ -1791,41 +1681,10 @@ void MapWidgetImpl::RadarProductManagerConnect() { if (radarProductManager_ != nullptr) { - connect(radarProductManager_.get(), - &manager::RadarProductManager::IncomingLevel2ElevationChanged, - this, - [this](std::optional incomingElevation) - { - Q_EMIT widget_->IncomingLevel2ElevationChanged( - incomingElevation); - }); connect(radarProductManager_.get(), &manager::RadarProductManager::Level3ProductsChanged, this, - [this]() - { - const common::Level3ProductCategoryMap& categoryMap = - widget_->GetAvailableLevel3Categories(); - - tiltsToIndices_.clear(); - for (const auto& category : categoryMap) - { - for (const auto& product : category.second) - { - for (size_t tiltIndex = 0; - tiltIndex < product.second.size(); - tiltIndex++) - { - tiltsToIndices_.emplace(product.second[tiltIndex], - tiltIndex); - } - } - } - - productAvailabilityUpdated_ = true; - CheckLevel3Availability(); - Q_EMIT widget_->Level3ProductsChanged(); - }); + [this]() { Q_EMIT widget_->Level3ProductsChanged(); }); connect( radarProductManager_.get(), @@ -1833,7 +1692,6 @@ void MapWidgetImpl::RadarProductManagerConnect() this, [this](common::RadarProductGroup group, const std::string& product, - bool isChunks, std::chrono::system_clock::time_point latestTime) { if (autoRefreshEnabled_ && @@ -1841,81 +1699,62 @@ void MapWidgetImpl::RadarProductManagerConnect() (group == common::RadarProductGroup::Level2 || context_->radar_product() == product)) { - if (isChunks && autoUpdateEnabled_) + // Create file request + std::shared_ptr request = + std::make_shared( + radarProductManager_->radar_id()); + + // File request callback + if (autoUpdateEnabled_) { - // Level 2 products may have multiple time points, - // ensure the latest is selected - widget_->SelectRadarProduct(group, product); - } - else - { - // Create file request - const std::shared_ptr request = - std::make_shared( - radarProductManager_->radar_id()); - - // File request callback - if (autoUpdateEnabled_) - { - connect( - request.get(), - &request::NexradFileRequest::RequestComplete, - this, - [group, product, this]( - const std::shared_ptr& - request) - { - // Select loaded record - auto record = request->radar_product_record(); - - // Validate record, and verify current map context - // still displays site and product - if (record != nullptr && - radarProductManager_ != nullptr && - radarProductManager_->radar_id() == - request->current_radar_site() && - context_->radar_product_group() == group && - (group == common::RadarProductGroup::Level2 || - context_->radar_product() == product)) - { - if (group == common::RadarProductGroup::Level2) - { - // Level 2 products may have multiple time - // points, ensure the latest is selected - widget_->SelectRadarProduct(group, product); - } - else - { - widget_->SelectRadarProduct(record); - } - } - }); - } - - // Load file - boost::asio::post( - threadPool_, - [group, latestTime, request, product, this]() + connect( + request.get(), + &request::NexradFileRequest::RequestComplete, + this, + [=, + this](std::shared_ptr request) { - try + // Select loaded record + auto record = request->radar_product_record(); + + // Validate record, and verify current map context + // still displays site and product + if (record != nullptr && + radarProductManager_ != nullptr && + radarProductManager_->radar_id() == + request->current_radar_site() && + context_->radar_product_group() == group && + (group == common::RadarProductGroup::Level2 || + context_->radar_product() == product)) { - if (group == common::RadarProductGroup::Level2) - { - radarProductManager_->LoadLevel2Data(latestTime, - request); - } - else - { - radarProductManager_->LoadLevel3Data( - product, latestTime, request); - } - } - catch (const std::exception& ex) - { - logger_->error(ex.what()); + widget_->SelectRadarProduct(record); } }); } + + // Load file + boost::asio::post( + threadPool_, + [=, this]() + { + try + { + if (group == common::RadarProductGroup::Level2) + { + radarProductManager_->LoadLevel2Data(latestTime, + request); + } + else + { + radarProductManager_->LoadLevel3Data( + product, latestTime, request); + } + } + catch (const std::exception& ex) + { + logger_->error(ex.what()); + } + }); } }, Qt::QueuedConnection); @@ -1930,10 +1769,6 @@ void MapWidgetImpl::RadarProductManagerDisconnect() &manager::RadarProductManager::NewDataAvailable, this, nullptr); - disconnect(radarProductManager_.get(), - &manager::RadarProductManager::IncomingLevel2ElevationChanged, - this, - nullptr); } } @@ -1941,12 +1776,27 @@ void MapWidgetImpl::InitializeNewRadarProductView( const std::string& colorPalette) { boost::asio::post(threadPool_, - [colorPalette, this]() + [=, this]() { try { - UpdateColorTable(colorPalette); - context_->radar_product_view()->Initialize(); + auto radarProductView = + context_->radar_product_view(); + + std::string colorTableFile = + settings::PaletteSettings::Instance() + .palette(colorPalette) + .GetValue(); + if (!colorTableFile.empty()) + { + std::unique_ptr colorTableStream = + util::OpenFile(colorTableFile); + std::shared_ptr colorTable = + common::ColorTable::Load(*colorTableStream); + radarProductView->LoadColorTable(colorTable); + } + + radarProductView->Initialize(); } catch (const std::exception& ex) { @@ -1966,11 +1816,12 @@ void MapWidgetImpl::RadarProductViewConnect() if (radarProductView != nullptr) { - connect(radarProductView.get(), - &view::RadarProductView::ColorTableLutUpdated, - widget_, - static_cast(&QWidget::update), - Qt::QueuedConnection); + connect( + radarProductView.get(), + &view::RadarProductView::ColorTableLutUpdated, + this, + [this]() { widget_->update(); }, + Qt::QueuedConnection); connect( radarProductView.get(), &view::RadarProductView::SweepComputed, @@ -1980,14 +1831,10 @@ void MapWidgetImpl::RadarProductViewConnect() std::shared_ptr radarSite = radarProductManager_->radar_site(); - if (map_ != nullptr) - { - RadarRangeLayer::Update( - map_, - radarProductView->range(), - {radarSite->latitude(), radarSite->longitude()}); - } - + RadarRangeLayer::Update( + map_, + radarProductView->range(), + {radarSite->latitude(), radarSite->longitude()}); widget_->update(); Q_EMIT widget_->RadarSweepUpdated(); }, @@ -2007,7 +1854,7 @@ void MapWidgetImpl::RadarProductViewDisconnect() { disconnect(radarProductView.get(), &view::RadarProductView::ColorTableLutUpdated, - widget_, + this, nullptr); disconnect(radarProductView.get(), &view::RadarProductView::SweepComputed, @@ -2032,12 +1879,8 @@ void MapWidgetImpl::SelectNearestRadarSite(double latitude, } } -void MapWidgetImpl::SetRadarSite(const std::string& radarSite, - bool checkProductAvailability) +void MapWidgetImpl::SetRadarSite(const std::string& radarSite) { - // Set the radar site in the context - context_->set_radar_site(config::RadarSite::Get(radarSite)); - // Check if radar site has changed if (radarProductManager_ == nullptr || radarSite != radarProductManager_->radar_site()->id()) @@ -2055,20 +1898,13 @@ void MapWidgetImpl::SetRadarSite(const std::string& radarSite, // Connect signals to new RadarProductManager RadarProductManagerConnect(); - // Once the available products are loaded, check to make sure the current - // one is available - productAvailabilityCheckNeeded_ = checkProductAvailability; - productAvailabilityUpdated_ = false; - productAvailabilityProductSelected_ = false; - radarProductManager_->UpdateAvailableProducts(); } } void MapWidgetImpl::Update() { - QMetaObject::invokeMethod( - widget_, static_cast(&QWidget::update)); + widget_->update(); if (UpdateStoredMapParameters()) { @@ -2077,37 +1913,6 @@ void MapWidgetImpl::Update() } } -void MapWidgetImpl::UpdateColorTable(const std::string& colorPalette) -{ - auto& paletteSetting = - settings::PaletteSettings::Instance().palette(colorPalette); - - std::string colorTableFile = paletteSetting.GetValue(); - if (colorTableFile.empty()) - { - colorTableFile = paletteSetting.GetDefault(); - } - - std::unique_ptr colorTableStream = - util::OpenFile(colorTableFile); - if (colorTableStream->fail()) - { - logger_->warn("Could not open color table {}", colorTableFile); - colorTableStream = util::OpenFile(paletteSetting.GetDefault()); - } - - std::shared_ptr colorTable = - common::ColorTable::Load(*colorTableStream); - if (!colorTable->IsValid()) - { - logger_->warn("Could not load color table {}", colorTableFile); - colorTableStream = util::OpenFile(paletteSetting.GetDefault()); - colorTable = common::ColorTable::Load(*colorTableStream); - } - - context_->radar_product_view()->LoadColorTable(colorTable); -} - bool MapWidgetImpl::UpdateStoredMapParameters() { bool changed = false; @@ -2136,116 +1941,8 @@ bool MapWidgetImpl::UpdateStoredMapParameters() return changed; } -void MapWidgetImpl::CheckLevel3Availability() -{ - /* - * productAvailabilityCheckNeeded_ Only do this when it is indicated that it - * is needed (mostly on radar site change). This is mainly to avoid potential - * recursion with SelectRadarProduct calls. - * - * productAvailabilityUpdated_ Only update once the product availability - * has been updated - * - * productAvailabilityProductSelected_ Only update once the radar site is - * fully selected - */ - if (!(productAvailabilityCheckNeeded_ && productAvailabilityUpdated_ && - productAvailabilityProductSelected_)) - { - return; - } - productAvailabilityCheckNeeded_ = false; - - // Get radar product view for fallback and level2 selection - auto radarProductView = context_->radar_product_view(); - if (radarProductView == nullptr) - { - return; - } - - // Only do this for level3 products - if (widget_->GetRadarProductGroup() != common::RadarProductGroup::Level3) - { - widget_->SelectRadarProduct(radarProductView->GetRadarProductGroup(), - radarProductView->GetRadarProductName(), - 0, - radarProductView->selected_time(), - false); - return; - } - - const common::Level3ProductCategoryMap& categoryMap = - widget_->GetAvailableLevel3Categories(); - - const std::string& productTilt = context_->radar_product(); - const std::string& productName = - common::GetLevel3ProductByAwipsId(productTilt); - const common::Level3ProductCategory productCategory = - common::GetLevel3CategoryByProduct(productName); - if (productCategory == common::Level3ProductCategory::Unknown) - { - // Default to the same as already selected - widget_->SelectRadarProduct(radarProductView->GetRadarProductGroup(), - radarProductView->GetRadarProductName(), - 0, - radarProductView->selected_time(), - false); - return; - } - - const auto& availableProductsIt = categoryMap.find(productCategory); - // Has no products in this category, do not change categories - if (availableProductsIt == categoryMap.cend()) - { - // Default to the same as already selected - widget_->SelectRadarProduct(radarProductView->GetRadarProductGroup(), - radarProductView->GetRadarProductName(), - 0, - radarProductView->selected_time(), - false); - return; - } - - const auto& availableProducts = availableProductsIt->second; - const auto& availableTiltsIt = availableProducts.find(productName); - - const auto& availableTilts = - availableTiltsIt == availableProducts.cend() ? - // Does not have the same product, but has others in the same category. - // Switch to the default product and tilt in this category. - availableProducts.at(common::GetLevel3ProductByAwipsId( - common::GetLevel3CategoryDefaultProduct(productCategory, - categoryMap))) : - // Has the same product - availableTiltsIt->second; - - // Try to match the tilt to the last tilt. - if (currentTiltIndex_ < availableTilts.size()) - { - widget_->SelectRadarProduct(common::RadarProductGroup::Level3, - availableTilts[currentTiltIndex_], - 0, - widget_->GetSelectedTime()); - } - else if (availableTilts.size() > 0) - { - widget_->SelectRadarProduct(common::RadarProductGroup::Level3, - availableTilts[availableTilts.size() - 1], - 0, - widget_->GetSelectedTime()); - } - else - { - // No tilts available in this case, default to the same as already - // selected - widget_->SelectRadarProduct(radarProductView->GetRadarProductGroup(), - radarProductView->GetRadarProductName(), - 0, - radarProductView->selected_time(), - false); - } -} - -} // namespace scwx::qt::map +} // namespace map +} // namespace qt +} // namespace scwx #include "map_widget.moc" diff --git a/scwx-qt/source/scwx/qt/map/map_widget.hpp b/scwx-qt/source/scwx/qt/map/map_widget.hpp index f721044e..40f7df77 100644 --- a/scwx-qt/source/scwx/qt/map/map_widget.hpp +++ b/scwx-qt/source/scwx/qt/map/map_widget.hpp @@ -3,18 +3,15 @@ #include #include #include -#include #include #include #include #include #include -#include #include -#include #include #include #include @@ -23,12 +20,11 @@ class QKeyEvent; class QMouseEvent; class QWheelEvent; -namespace scwx::qt::gl +namespace scwx { -class GlContext; -} - -namespace scwx::qt::map +namespace qt +{ +namespace map { class MapWidgetImpl; @@ -38,28 +34,21 @@ class MapWidget : public QOpenGLWidget Q_OBJECT public: - explicit MapWidget(std::size_t id, - const QMapLibre::Settings&, - std::shared_ptr glContext); + explicit MapWidget(std::size_t id, const QMapLibre::Settings&); ~MapWidget(); void DumpLayerList() const; - [[nodiscard]] common::Level3ProductCategoryMap - GetAvailableLevel3Categories(); - [[nodiscard]] const scwx::util::time_zone* GetDefaultTimeZone() const; - [[nodiscard]] std::optional GetElevation() const; - [[nodiscard]] std::vector GetElevationCuts() const; - [[nodiscard]] std::optional GetIncomingLevel2Elevation() const; - [[nodiscard]] std::vector GetLevel3Products(); - [[nodiscard]] std::string GetMapStyle() const; - [[nodiscard]] common::RadarProductGroup GetRadarProductGroup() const; - [[nodiscard]] std::string GetRadarProductName() const; - [[nodiscard]] std::shared_ptr GetRadarSite() const; - [[nodiscard]] bool GetRadarWireframeEnabled() const; - [[nodiscard]] std::chrono::system_clock::time_point GetSelectedTime() const; - [[nodiscard]] bool GetSmoothingEnabled() const; - [[nodiscard]] std::uint16_t GetVcp() const; + common::Level3ProductCategoryMap GetAvailableLevel3Categories(); + float GetElevation() const; + std::vector GetElevationCuts() const; + std::vector GetLevel3Products(); + std::string GetMapStyle() const; + common::RadarProductGroup GetRadarProductGroup() const; + std::string GetRadarProductName() const; + std::shared_ptr GetRadarSite() const; + std::chrono::system_clock::time_point GetSelectedTime() const; + std::uint16_t GetVcp() const; void SelectElevation(float elevation); @@ -128,8 +117,6 @@ public: double pitch); void SetInitialMapStyle(const std::string& styleName); void SetMapStyle(const std::string& styleName); - void SetRadarWireframeEnabled(bool enabled); - void SetSmoothingEnabled(bool enabled); /** * Updates the coordinates associated with mouse movement from another map. @@ -144,14 +131,13 @@ private: // QWidget implementation. bool event(QEvent* e) override; - void enterEvent(QEnterEvent* ev) final; - void keyPressEvent(QKeyEvent* ev) final; - void keyReleaseEvent(QKeyEvent* ev) final; - void gestureEvent(QGestureEvent* ev); - void leaveEvent(QEvent* ev) final; - void mousePressEvent(QMouseEvent* ev) final; - void mouseMoveEvent(QMouseEvent* ev) final; - void wheelEvent(QWheelEvent* ev) final; + void enterEvent(QEnterEvent* ev) override final; + void keyPressEvent(QKeyEvent* ev) override final; + void keyReleaseEvent(QKeyEvent* ev) override final; + void leaveEvent(QEvent* ev) override final; + void mousePressEvent(QMouseEvent* ev) override final; + void mouseMoveEvent(QMouseEvent* ev) override final; + void wheelEvent(QWheelEvent* ev) override final; // QOpenGLWidget implementation. void initializeGL() override final; @@ -190,7 +176,8 @@ signals: void RadarSweepUpdated(); void RadarSweepNotUpdated(types::NoUpdateReason reason); void WidgetPainted(); - void IncomingLevel2ElevationChanged(std::optional incomingElevation); }; -} // namespace scwx::qt::map +} // namespace map +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/map/marker_layer.cpp b/scwx-qt/source/scwx/qt/map/marker_layer.cpp deleted file mode 100644 index 3e49c1d1..00000000 --- a/scwx-qt/source/scwx/qt/map/marker_layer.cpp +++ /dev/null @@ -1,180 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -namespace scwx::qt::map -{ - -static const std::string logPrefix_ = "scwx::qt::map::marker_layer"; -static const auto logger_ = scwx::util::Logger::Create(logPrefix_); - -class MarkerLayer::Impl -{ -public: - explicit Impl(MarkerLayer* self, - const std::shared_ptr& glContext) : - self_ {self}, - geoIcons_ {std::make_shared(glContext)}, - editMarkerDialog_ {std::make_shared()} - { - ConnectSignals(); - } - ~Impl() = default; - - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; - - void ReloadMarkers(); - void ConnectSignals(); - - std::shared_ptr markerManager_ { - manager::MarkerManager::Instance()}; - - void set_icon_sheets(); - - MarkerLayer* self_; - - std::shared_ptr geoIcons_; - std::shared_ptr editMarkerDialog_; -}; - -void MarkerLayer::Impl::ConnectSignals() -{ - QObject::connect(markerManager_.get(), - &manager::MarkerManager::MarkersUpdated, - self_, - [this]() { ReloadMarkers(); }); - QObject::connect(markerManager_.get(), - &manager::MarkerManager::IconsReady, - self_, - [this]() { set_icon_sheets(); }); - QObject::connect(markerManager_.get(), - &manager::MarkerManager::IconAdded, - self_, - [this]() { set_icon_sheets(); }); -} - -void MarkerLayer::Impl::ReloadMarkers() -{ - logger_->debug("ReloadMarkers()"); - - geoIcons_->StartIcons(); - markerManager_->for_each( - [this](const types::MarkerInfo& marker) - { - // must use local ID, instead of reference to marker in event handler - // callback. - const types::MarkerId id = marker.id; - - const std::shared_ptr icon = - geoIcons_->AddIcon(); - - const std::string latitudeString = - common::GetLatitudeString(marker.latitude); - const std::string longitudeString = - common::GetLongitudeString(marker.longitude); - - const std::string hoverText = - marker.name != "" ? - fmt::format( - "{}\n{}, {}", marker.name, latitudeString, longitudeString) : - fmt::format("{}, {}", latitudeString, longitudeString); - - auto iconInfo = markerManager_->get_icon(marker.iconName); - if (iconInfo) - { - geoIcons_->SetIconTexture(icon, iconInfo->name, 0); - } - else - { - geoIcons_->SetIconTexture(icon, marker.iconName, 0); - } - - geoIcons_->SetIconLocation(icon, marker.latitude, marker.longitude); - geoIcons_->SetIconHoverText(icon, hoverText); - geoIcons_->SetIconModulate(icon, marker.iconColor); - geoIcons_->RegisterEventHandler( - icon, - [this, id](QEvent* ev) - { - switch (ev->type()) - { - case QEvent::Type::MouseButtonPress: - { - auto* mouseEvent = reinterpret_cast(ev); - if (mouseEvent->buttons() == Qt::MouseButton::RightButton) - { - editMarkerDialog_->setup(id); - editMarkerDialog_->show(); - } - } - break; - - default: - break; - } - }); - }); - - geoIcons_->FinishIcons(); - Q_EMIT self_->NeedsRendering(); -} - -MarkerLayer::MarkerLayer(const std::shared_ptr& glContext) : - DrawLayer(glContext, "MarkerLayer"), - p(std::make_unique(this, glContext)) -{ - AddDrawItem(p->geoIcons_); -} - -MarkerLayer::~MarkerLayer() = default; - -void MarkerLayer::Initialize(const std::shared_ptr& mapContext) -{ - logger_->debug("Initialize()"); - DrawLayer::Initialize(mapContext); - - p->set_icon_sheets(); - p->ReloadMarkers(); -} - -void MarkerLayer::Impl::set_icon_sheets() -{ - geoIcons_->StartIconSheets(); - for (auto& markerIcon : markerManager_->get_icons()) - { - geoIcons_->AddIconSheet(markerIcon.second.name, - 0, - 0, - markerIcon.second.hotX, - markerIcon.second.hotY); - } - geoIcons_->FinishIconSheets(); -} - -void MarkerLayer::Render(const std::shared_ptr& mapContext, - const QMapLibre::CustomLayerRenderParameters& params) -{ - DrawLayer::Render(mapContext, params); - - SCWX_GL_CHECK_ERROR(); -} - -void MarkerLayer::Deinitialize() -{ - logger_->debug("Deinitialize()"); - - DrawLayer::Deinitialize(); -} - -} // namespace scwx::qt::map diff --git a/scwx-qt/source/scwx/qt/map/marker_layer.hpp b/scwx-qt/source/scwx/qt/map/marker_layer.hpp deleted file mode 100644 index a5f67d2b..00000000 --- a/scwx-qt/source/scwx/qt/map/marker_layer.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include - -namespace scwx::qt::map -{ - -class MarkerLayer : public DrawLayer -{ - Q_OBJECT - Q_DISABLE_COPY_MOVE(MarkerLayer) - -public: - explicit MarkerLayer(const std::shared_ptr& context); - ~MarkerLayer(); - - void Initialize(const std::shared_ptr& mapContext) final; - void Render(const std::shared_ptr& mapContext, - const QMapLibre::CustomLayerRenderParameters&) final; - void Deinitialize() final; - -private: - class Impl; - std::unique_ptr p; -}; - -} // namespace scwx::qt::map diff --git a/scwx-qt/source/scwx/qt/map/overlay_layer.cpp b/scwx-qt/source/scwx/qt/map/overlay_layer.cpp index 04b0890e..b2fada95 100644 --- a/scwx-qt/source/scwx/qt/map/overlay_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/overlay_layer.cpp @@ -1,18 +1,18 @@ -#include +#include #include #include #include #include #include -#include #include -#include #include #include #include #include #include +#include + #if defined(_MSC_VER) # pragma warning(push, 0) #endif @@ -22,27 +22,34 @@ #include #include +#if !defined(_MSC_VER) +# include +#endif + #if defined(_MSC_VER) # pragma warning(pop) #endif -namespace scwx::qt::map +namespace scwx +{ +namespace qt +{ +namespace map { static const std::string logPrefix_ = "scwx::qt::map::overlay_layer"; static const auto logger_ = scwx::util::Logger::Create(logPrefix_); -class OverlayLayer::Impl +class OverlayLayerImpl { public: - explicit Impl(OverlayLayer* self, - const std::shared_ptr& glContext) : + explicit OverlayLayerImpl(OverlayLayer* self, + std::shared_ptr context) : self_ {self}, - activeBoxOuter_ {std::make_shared(glContext)}, - activeBoxInner_ {std::make_shared(glContext)}, - geoIcons_ {std::make_shared(glContext)}, - icons_ {std::make_shared(glContext)}, - renderMutex_ {} + activeBoxOuter_ {std::make_shared(context)}, + activeBoxInner_ {std::make_shared(context)}, + geoIcons_ {std::make_shared(context)}, + icons_ {std::make_shared(context)} { auto& generalSettings = settings::GeneralSettings::Instance(); @@ -71,7 +78,7 @@ public: [this](const bool&) { Q_EMIT self_->NeedsRendering(); }); } - ~Impl() + ~OverlayLayerImpl() { auto& generalSettings = settings::GeneralSettings::Instance(); @@ -87,14 +94,6 @@ public: showMapLogoCallbackUuid_); } - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; - - void SetupGeoIcons(); - void SetCusorLocation(common::Coordinate coordinate); - OverlayLayer* self_; boost::uuids::uuid clockFormatCallbackUuid_; @@ -122,13 +121,11 @@ public: types::GetTextureName(types::ImageTexture::CardinalPoint24)}; const std::string& compassIconName_ { types::GetTextureName(types::ImageTexture::Compass24)}; - std::string cursorIconName_ { + const std::string& cursorIconName_ { types::GetTextureName(types::ImageTexture::Dot3)}; const std::string& mapCenterIconName_ { types::GetTextureName(types::ImageTexture::Cursor17)}; - std::shared_ptr cursorIconImage_ {nullptr}; - const std::string& mapboxLogoImageName_ { types::GetTextureName(types::ImageTexture::MapboxLogo)}; const std::string& mapTilerLogoImageName_ { @@ -146,19 +143,13 @@ public: float lastFontSize_ {0.0f}; QMargins lastColorTableMargins_ {}; - double cursorScale_ {1}; - boost::signals2::scoped_connection cursorScaleConnection_; - - std::mutex renderMutex_; - std::string sweepTimeString_ {}; bool sweepTimeNeedsUpdate_ {true}; bool sweepTimePicked_ {false}; }; -OverlayLayer::OverlayLayer(const std::shared_ptr& glContext) : - DrawLayer(glContext, "OverlayLayer"), - p(std::make_unique(this, glContext)) +OverlayLayer::OverlayLayer(std::shared_ptr context) : + DrawLayer(context), p(std::make_unique(this, context)) { AddDrawItem(p->activeBoxOuter_); AddDrawItem(p->activeBoxInner_); @@ -168,58 +159,15 @@ OverlayLayer::OverlayLayer(const std::shared_ptr& glContext) : p->activeBoxOuter_->SetPosition(0.0f, 0.0f); } -OverlayLayer::~OverlayLayer() -{ - p->cursorScaleConnection_.disconnect(); -} +OverlayLayer::~OverlayLayer() = default; -void OverlayLayer::Impl::SetCusorLocation(common::Coordinate coordinate) -{ - geoIcons_->SetIconLocation( - cursorIcon_, coordinate.latitude_, coordinate.longitude_); -} - -void OverlayLayer::Impl::SetupGeoIcons() -{ - const std::unique_lock lock {renderMutex_}; - - auto& generalSettings = settings::GeneralSettings::Instance(); - cursorScale_ = generalSettings.cursor_icon_scale().GetValue(); - - const std::string& texturePath = - types::GetTexturePath(types::ImageTexture::Dot3); - cursorIconName_ = fmt::format( - "{}x{}", types::GetTextureName(types::ImageTexture::Dot3), cursorScale_); - cursorIconImage_ = manager::ResourceManager::LoadImageResource( - texturePath, cursorIconName_, cursorScale_); - manager::ResourceManager::BuildAtlas(); - - auto coordinate = currentPosition_.coordinate(); - geoIcons_->StartIconSheets(); - geoIcons_->AddIconSheet(cursorIconName_); - geoIcons_->AddIconSheet(locationIconName_); - geoIcons_->FinishIconSheets(); - - geoIcons_->StartIcons(); - - cursorIcon_ = geoIcons_->AddIcon(); - geoIcons_->SetIconTexture(cursorIcon_, cursorIconName_, 0); - - locationIcon_ = geoIcons_->AddIcon(); - geoIcons_->SetIconTexture(locationIcon_, locationIconName_, 0); - geoIcons_->SetIconLocation( - locationIcon_, coordinate.latitude(), coordinate.longitude()); - - geoIcons_->FinishIcons(); -} - -void OverlayLayer::Initialize(const std::shared_ptr& mapContext) +void OverlayLayer::Initialize() { logger_->debug("Initialize()"); - DrawLayer::Initialize(mapContext); + DrawLayer::Initialize(); - auto radarProductView = mapContext->radar_product_view(); + auto radarProductView = context()->radar_product_view(); if (radarProductView != nullptr) { @@ -230,17 +178,27 @@ void OverlayLayer::Initialize(const std::shared_ptr& mapContext) } p->currentPosition_ = p->positionManager_->position(); + auto coordinate = p->currentPosition_.coordinate(); // Geo Icons - auto& generalSettings = settings::GeneralSettings::Instance(); - p->SetupGeoIcons(); - p->cursorScaleConnection_ = - generalSettings.cursor_icon_scale().changed_signal().connect( - [this]() - { - p->SetupGeoIcons(); - Q_EMIT NeedsRendering(); - }); + p->geoIcons_->StartIconSheets(); + p->geoIcons_->AddIconSheet(p->cursorIconName_); + p->geoIcons_->AddIconSheet(p->locationIconName_); + p->geoIcons_->FinishIconSheets(); + + p->geoIcons_->StartIcons(); + + p->cursorIcon_ = p->geoIcons_->AddIcon(); + p->geoIcons_->SetIconTexture(p->cursorIcon_, p->cursorIconName_, 0); + + p->locationIcon_ = p->geoIcons_->AddIcon(); + p->geoIcons_->SetIconTexture(p->locationIcon_, p->locationIconName_, 0); + p->geoIcons_->SetIconAngle(p->locationIcon_, + units::angle::degrees {45.0}); + p->geoIcons_->SetIconLocation( + p->locationIcon_, coordinate.latitude(), coordinate.longitude()); + + p->geoIcons_->FinishIcons(); // Icons p->icons_->StartIconSheets(); @@ -256,7 +214,7 @@ void OverlayLayer::Initialize(const std::shared_ptr& mapContext) p->icons_->SetIconTexture(p->compassIcon_, p->cardinalPointIconName_, 0); gl::draw::Icons::RegisterEventHandler( p->compassIcon_, - [this, mapContext](QEvent* ev) + [this](QEvent* ev) { switch (ev->type()) { @@ -281,7 +239,7 @@ void OverlayLayer::Initialize(const std::shared_ptr& mapContext) if (mouseEvent->buttons() == Qt::MouseButton::LeftButton && p->lastBearing_ != 0.0) { - auto map = mapContext->map().lock(); + auto map = context()->map().lock(); if (map != nullptr) { map->setBearing(0.0); @@ -300,11 +258,11 @@ void OverlayLayer::Initialize(const std::shared_ptr& mapContext) p->icons_->SetIconTexture(p->mapCenterIcon_, p->mapCenterIconName_, 0); p->mapLogoIcon_ = p->icons_->AddIcon(); - if (mapContext->map_provider() == MapProvider::Mapbox) + if (context()->map_provider() == MapProvider::Mapbox) { p->icons_->SetIconTexture(p->mapLogoIcon_, p->mapboxLogoImageName_, 0); } - else if (mapContext->map_provider() == MapProvider::MapTiler) + else if (context()->map_provider() == MapProvider::MapTiler) { p->icons_->SetIconTexture(p->mapLogoIcon_, p->mapTilerLogoImageName_, 0); } @@ -333,16 +291,14 @@ void OverlayLayer::Initialize(const std::shared_ptr& mapContext) }); } -void OverlayLayer::Render(const std::shared_ptr& mapContext, - const QMapLibre::CustomLayerRenderParameters& params) +void OverlayLayer::Render(const QMapLibre::CustomLayerRenderParameters& params) { - const std::unique_lock lock {p->renderMutex_}; + gl::OpenGLFunctions& gl = context()->gl(); + auto radarProductView = context()->radar_product_view(); + auto& settings = context()->settings(); + const float pixelRatio = context()->pixel_ratio(); - auto radarProductView = mapContext->radar_product_view(); - auto& settings = mapContext->settings(); - const float pixelRatio = mapContext->pixel_ratio(); - - ImGuiFrameStart(mapContext); + context()->set_render_parameters(params); p->sweepTimePicked_ = false; @@ -378,17 +334,15 @@ void OverlayLayer::Render(const std::shared_ptr& mapContext, p->activeBoxInner_->SetBorder(1.0f * pixelRatio, {255, 255, 255, 255}); } - auto& generalSettings = settings::GeneralSettings::Instance(); - // Cursor Icon - bool cursorIconVisible = - generalSettings.cursor_icon_always_on().GetValue() || - (QGuiApplication::keyboardModifiers() & - Qt::KeyboardModifier::ControlModifier); + bool cursorIconVisible = QGuiApplication::keyboardModifiers() & + Qt::KeyboardModifier::ControlModifier; p->geoIcons_->SetIconVisible(p->cursorIcon_, cursorIconVisible); if (cursorIconVisible) { - p->SetCusorLocation(mapContext->mouse_coordinate()); + common::Coordinate mouseCoordinate = context()->mouse_coordinate(); + p->geoIcons_->SetIconLocation( + p->cursorIcon_, mouseCoordinate.latitude_, mouseCoordinate.longitude_); } // Location Icon @@ -428,9 +382,7 @@ void OverlayLayer::Render(const std::shared_ptr& mapContext, if (radarProductView != nullptr) { // Render product name - const std::string productName = radarProductView->GetRadarProductName(); - const std::optional elevation = radarProductView->elevation(); - + std::string productName = radarProductView->GetRadarProductName(); if (productName.length() > 0 && !productName.starts_with('?')) { ImGui::SetNextWindowPos(ImVec2 {0.0f, 0.0f}); @@ -438,21 +390,7 @@ void OverlayLayer::Render(const std::shared_ptr& mapContext, nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize); - - if (elevation.has_value()) - { - const std::string elevationString = - (QString::number(*elevation, 'f', 1) + - common::Characters::DEGREE) - .toStdString(); - ImGui::TextUnformatted( - fmt::format("{} ({})", productName, elevationString).c_str()); - } - else - { - ImGui::TextUnformatted(productName.c_str()); - } - + ImGui::TextUnformatted(productName.c_str()); ImGui::End(); } } @@ -502,6 +440,8 @@ void OverlayLayer::Render(const std::shared_ptr& mapContext, ImGui::End(); } + auto& generalSettings = settings::GeneralSettings::Instance(); + // Map Center Icon if (params.width != p->lastWidth_ || params.height != p->lastHeight_) { @@ -512,7 +452,7 @@ void OverlayLayer::Render(const std::shared_ptr& mapContext, p->icons_->SetIconVisible(p->mapCenterIcon_, generalSettings.show_map_center().GetValue()); - const QMargins colorTableMargins = mapContext->color_table_margins(); + QMargins colorTableMargins = context()->color_table_margins(); if (colorTableMargins != p->lastColorTableMargins_ || p->firstRender_) { // Draw map logo with a 10x10 indent from the bottom left @@ -523,9 +463,9 @@ void OverlayLayer::Render(const std::shared_ptr& mapContext, p->icons_->SetIconVisible(p->mapLogoIcon_, generalSettings.show_map_logo().GetValue()); - DrawLayer::RenderWithoutImGui(params); + DrawLayer::Render(params); - auto mapCopyrights = mapContext->map_copyrights(); + auto mapCopyrights = context()->map_copyrights(); if (mapCopyrights.length() > 0 && generalSettings.show_map_attribution().GetValue()) { @@ -539,8 +479,7 @@ void OverlayLayer::Render(const std::shared_ptr& mapContext, ImVec2 {1.0f, 1.0f}); ImGui::SetNextWindowBgAlpha(0.5f); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2 {3.0f, 2.0f}); - ImGui::PushFont(attributionFont.first->font(), - attributionFont.second.value()); + ImGui::PushFont(attributionFont->font()); ImGui::Begin("Attribution", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | @@ -558,8 +497,6 @@ void OverlayLayer::Render(const std::shared_ptr& mapContext, p->lastFontSize_ = ImGui::GetFontSize(); p->lastColorTableMargins_ = colorTableMargins; - ImGuiFrameEnd(); - SCWX_GL_CHECK_ERROR(); } @@ -569,13 +506,29 @@ void OverlayLayer::Deinitialize() DrawLayer::Deinitialize(); - disconnect(this); + auto radarProductView = context()->radar_product_view(); + + if (radarProductView != nullptr) + { + disconnect(radarProductView.get(), + &view::RadarProductView::SweepComputed, + this, + &OverlayLayer::UpdateSweepTimeNextFrame); + } + + disconnect(p->positionManager_.get(), + &manager::PositionManager::LocationTrackingChanged, + this, + nullptr); + disconnect(p->positionManager_.get(), + &manager::PositionManager::PositionUpdated, + this, + nullptr); p->locationIcon_ = nullptr; } bool OverlayLayer::RunMousePicking( - const std::shared_ptr& mapContext, const QMapLibre::CustomLayerRenderParameters& params, const QPointF& mouseLocalPos, const QPointF& mouseGlobalPos, @@ -589,8 +542,7 @@ bool OverlayLayer::RunMousePicking( return true; } - return DrawLayer::RunMousePicking(mapContext, - params, + return DrawLayer::RunMousePicking(params, mouseLocalPos, mouseGlobalPos, mouseCoords, @@ -603,4 +555,6 @@ void OverlayLayer::UpdateSweepTimeNextFrame() p->sweepTimeNeedsUpdate_ = true; } -} // namespace scwx::qt::map +} // namespace map +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/map/overlay_layer.hpp b/scwx-qt/source/scwx/qt/map/overlay_layer.hpp index 89e49b6b..f842e81b 100644 --- a/scwx-qt/source/scwx/qt/map/overlay_layer.hpp +++ b/scwx-qt/source/scwx/qt/map/overlay_layer.hpp @@ -2,37 +2,42 @@ #include -namespace scwx::qt::map +namespace scwx { +namespace qt +{ +namespace map +{ + +class OverlayLayerImpl; class OverlayLayer : public DrawLayer { Q_DISABLE_COPY_MOVE(OverlayLayer) public: - explicit OverlayLayer(const std::shared_ptr& glContext); + explicit OverlayLayer(std::shared_ptr context); ~OverlayLayer(); - void Initialize(const std::shared_ptr& mapContext) final; - void Render(const std::shared_ptr& mapContext, - const QMapLibre::CustomLayerRenderParameters&) final; - void Deinitialize() final; + void Initialize() override final; + void Render(const QMapLibre::CustomLayerRenderParameters&) override final; + void Deinitialize() override final; - bool - RunMousePicking(const std::shared_ptr& mapContext, - const QMapLibre::CustomLayerRenderParameters& params, - const QPointF& mouseLocalPos, - const QPointF& mouseGlobalPos, - const glm::vec2& mouseCoords, - const common::Coordinate& mouseGeoCoords, - std::shared_ptr& eventHandler) final; + bool RunMousePicking( + const QMapLibre::CustomLayerRenderParameters& params, + const QPointF& mouseLocalPos, + const QPointF& mouseGlobalPos, + const glm::vec2& mouseCoords, + const common::Coordinate& mouseGeoCoords, + std::shared_ptr& eventHandler) override final; public slots: void UpdateSweepTimeNextFrame(); private: - class Impl; - std::unique_ptr p; + std::unique_ptr p; }; -} // namespace scwx::qt::map +} // namespace map +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/map/overlay_product_layer.cpp b/scwx-qt/source/scwx/qt/map/overlay_product_layer.cpp index 457ebccd..64745fd5 100644 --- a/scwx-qt/source/scwx/qt/map/overlay_product_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/overlay_product_layer.cpp @@ -11,7 +11,11 @@ #include #include -namespace scwx::qt::map +namespace scwx +{ +namespace qt +{ +namespace map { static const std::string logPrefix_ = "scwx::qt::map::overlay_product_layer"; @@ -20,10 +24,10 @@ static const auto logger_ = scwx::util::Logger::Create(logPrefix_); class OverlayProductLayer::Impl { public: - explicit Impl(OverlayProductLayer* self, - const std::shared_ptr& glContext) : + explicit Impl(OverlayProductLayer* self, + const std::shared_ptr& context) : self_ {self}, - linkedVectors_ {std::make_shared(glContext)} + linkedVectors_ {std::make_shared(context)} { auto& productSettings = settings::ProductSettings::Instance(); @@ -60,8 +64,7 @@ public: stiPastEnabledCallbackUuid_); } - void UpdateStormTrackingInformation( - const std::shared_ptr& mapContext); + void UpdateStormTrackingInformation(); static void HandleLinkedVectorPacket( const std::shared_ptr& packet, @@ -105,22 +108,10 @@ public: std::shared_ptr linkedVectors_; }; -OverlayProductLayer::OverlayProductLayer( - const std::shared_ptr& glContext) : - DrawLayer(glContext, "OverlayProductLayer"), - p(std::make_unique(this, glContext)) +OverlayProductLayer::OverlayProductLayer(std::shared_ptr context) : + DrawLayer(context), p(std::make_unique(this, context)) { - AddDrawItem(p->linkedVectors_); -} - -OverlayProductLayer::~OverlayProductLayer() = default; - -void OverlayProductLayer::Initialize( - const std::shared_ptr& mapContext) -{ - logger_->debug("Initialize()"); - - auto overlayProductView = mapContext->overlay_product_view(); + auto overlayProductView = context->overlay_product_view(); connect(overlayProductView.get(), &view::OverlayProductView::ProductUpdated, this, @@ -133,21 +124,31 @@ void OverlayProductLayer::Initialize( } }); - p->UpdateStormTrackingInformation(mapContext); + AddDrawItem(p->linkedVectors_); +} - DrawLayer::Initialize(mapContext); +OverlayProductLayer::~OverlayProductLayer() = default; + +void OverlayProductLayer::Initialize() +{ + logger_->debug("Initialize()"); + + p->UpdateStormTrackingInformation(); + + DrawLayer::Initialize(); } void OverlayProductLayer::Render( - const std::shared_ptr& mapContext, const QMapLibre::CustomLayerRenderParameters& params) { + gl::OpenGLFunctions& gl = context()->gl(); + if (p->stiNeedsUpdate_) { - p->UpdateStormTrackingInformation(mapContext); + p->UpdateStormTrackingInformation(); } - DrawLayer::Render(mapContext, params); + DrawLayer::Render(params); SCWX_GL_CHECK_ERROR(); } @@ -156,19 +157,16 @@ void OverlayProductLayer::Deinitialize() { logger_->debug("Deinitialize()"); - disconnect(this); - DrawLayer::Deinitialize(); } -void OverlayProductLayer::Impl::UpdateStormTrackingInformation( - const std::shared_ptr& mapContext) +void OverlayProductLayer::Impl::UpdateStormTrackingInformation() { logger_->debug("Update Storm Tracking Information"); stiNeedsUpdate_ = false; - auto overlayProductView = mapContext->overlay_product_view(); + auto overlayProductView = self_->context()->overlay_product_view(); auto radarProductManager = overlayProductView->radar_product_manager(); auto message = overlayProductView->radar_product_message("NST"); @@ -435,7 +433,6 @@ std::string OverlayProductLayer::Impl::BuildHoverText( } bool OverlayProductLayer::RunMousePicking( - const std::shared_ptr& mapContext, const QMapLibre::CustomLayerRenderParameters& params, const QPointF& mouseLocalPos, const QPointF& mouseGlobalPos, @@ -443,8 +440,7 @@ bool OverlayProductLayer::RunMousePicking( const common::Coordinate& mouseGeoCoords, std::shared_ptr& eventHandler) { - return DrawLayer::RunMousePicking(mapContext, - params, + return DrawLayer::RunMousePicking(params, mouseLocalPos, mouseGlobalPos, mouseCoords, @@ -452,4 +448,6 @@ bool OverlayProductLayer::RunMousePicking( eventHandler); } -} // namespace scwx::qt::map +} // namespace map +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/map/overlay_product_layer.hpp b/scwx-qt/source/scwx/qt/map/overlay_product_layer.hpp index 5c2fd73e..8f65c2d6 100644 --- a/scwx-qt/source/scwx/qt/map/overlay_product_layer.hpp +++ b/scwx-qt/source/scwx/qt/map/overlay_product_layer.hpp @@ -2,35 +2,36 @@ #include -namespace scwx::qt::map +namespace scwx +{ +namespace qt +{ +namespace map { class OverlayProductLayer : public DrawLayer { - Q_DISABLE_COPY_MOVE(OverlayProductLayer) - public: - explicit OverlayProductLayer( - const std::shared_ptr& glContext); + explicit OverlayProductLayer(std::shared_ptr context); ~OverlayProductLayer(); - void Initialize(const std::shared_ptr& mapContext) final; - void Render(const std::shared_ptr& mapContext, - const QMapLibre::CustomLayerRenderParameters&) final; - void Deinitialize() final; + void Initialize() override final; + void Render(const QMapLibre::CustomLayerRenderParameters&) override final; + void Deinitialize() override final; - bool - RunMousePicking(const std::shared_ptr& mapContext, - const QMapLibre::CustomLayerRenderParameters& params, - const QPointF& mouseLocalPos, - const QPointF& mouseGlobalPos, - const glm::vec2& mouseCoords, - const common::Coordinate& mouseGeoCoords, - std::shared_ptr& eventHandler) final; + bool RunMousePicking( + const QMapLibre::CustomLayerRenderParameters& params, + const QPointF& mouseLocalPos, + const QPointF& mouseGlobalPos, + const glm::vec2& mouseCoords, + const common::Coordinate& mouseGeoCoords, + std::shared_ptr& eventHandler) override final; private: class Impl; std::unique_ptr p; }; -} // namespace scwx::qt::map +} // namespace map +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/map/placefile_layer.cpp b/scwx-qt/source/scwx/qt/map/placefile_layer.cpp index a5bcdc58..be2d9a18 100644 --- a/scwx-qt/source/scwx/qt/map/placefile_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/placefile_layer.cpp @@ -12,7 +12,11 @@ #include #include -namespace scwx::qt::map +namespace scwx +{ +namespace qt +{ +namespace map { static const std::string logPrefix_ = "scwx::qt::map::placefile_layer"; @@ -21,30 +25,25 @@ static const auto logger_ = scwx::util::Logger::Create(logPrefix_); class PlacefileLayer::Impl { public: - explicit Impl(PlacefileLayer* self, - const std::shared_ptr& glContext, - const std::string& placefileName) : + explicit Impl(PlacefileLayer* self, + const std::shared_ptr& context, + const std::string& placefileName) : self_ {self}, placefileName_ {placefileName}, - placefileIcons_ {std::make_shared(glContext)}, - placefileImages_ { - std::make_shared(glContext)}, - placefileLines_ {std::make_shared(glContext)}, + placefileIcons_ {std::make_shared(context)}, + placefileImages_ {std::make_shared(context)}, + placefileLines_ {std::make_shared(context)}, placefilePolygons_ { - std::make_shared(glContext)}, + std::make_shared(context)}, placefileTriangles_ { - std::make_shared(glContext)}, - placefileText_ {std::make_shared(placefileName)} + std::make_shared(context)}, + placefileText_ { + std::make_shared(context, placefileName)} { ConnectSignals(); } ~Impl() { threadPool_.join(); } - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; - void ConnectSignals(); void ReloadDataSync(); @@ -65,10 +64,10 @@ public: std::chrono::system_clock::time_point selectedTime_ {}; }; -PlacefileLayer::PlacefileLayer(const std::shared_ptr& glContext, +PlacefileLayer::PlacefileLayer(const std::shared_ptr& context, const std::string& placefileName) : - DrawLayer(glContext, fmt::format("PlacefileLayer {}", placefileName)), - p(std::make_unique(this, glContext, placefileName)) + DrawLayer(context), + p(std::make_unique(this, context, placefileName)) { AddDrawItem(p->placefileImages_); AddDrawItem(p->placefilePolygons_); @@ -118,19 +117,18 @@ void PlacefileLayer::set_placefile_name(const std::string& placefileName) ReloadData(); } -void PlacefileLayer::Initialize(const std::shared_ptr& mapContext) +void PlacefileLayer::Initialize() { logger_->debug("Initialize()"); - DrawLayer::Initialize(mapContext); - - p->selectedTime_ = manager::TimelineManager::Instance()->GetSelectedTime(); + DrawLayer::Initialize(); } void PlacefileLayer::Render( - const std::shared_ptr& mapContext, const QMapLibre::CustomLayerRenderParameters& params) { + gl::OpenGLFunctions& gl = context()->gl(); + std::shared_ptr placefileManager = manager::PlacefileManager::Instance(); @@ -156,7 +154,7 @@ void PlacefileLayer::Render( p->placefileText_->set_selected_time(p->selectedTime_); } - DrawLayer::Render(mapContext, params); + DrawLayer::Render(params); SCWX_GL_CHECK_ERROR(); } @@ -261,4 +259,6 @@ void PlacefileLayer::Impl::ReloadDataSync() Q_EMIT self_->DataReloaded(); } -} // namespace scwx::qt::map +} // namespace map +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/map/placefile_layer.hpp b/scwx-qt/source/scwx/qt/map/placefile_layer.hpp index 35f5a81b..981c3c12 100644 --- a/scwx-qt/source/scwx/qt/map/placefile_layer.hpp +++ b/scwx-qt/source/scwx/qt/map/placefile_layer.hpp @@ -4,27 +4,29 @@ #include -namespace scwx::qt::map +namespace scwx +{ +namespace qt +{ +namespace map { class PlacefileLayer : public DrawLayer { Q_OBJECT - Q_DISABLE_COPY_MOVE(PlacefileLayer) public: - explicit PlacefileLayer(const std::shared_ptr& glContext, - const std::string& placefileName); + explicit PlacefileLayer(const std::shared_ptr& context, + const std::string& placefileName); ~PlacefileLayer(); std::string placefile_name() const; void set_placefile_name(const std::string& placefileName); - void Initialize(const std::shared_ptr& mapContext) final; - void Render(const std::shared_ptr& mapContext, - const QMapLibre::CustomLayerRenderParameters&) final; - void Deinitialize() final; + void Initialize() override final; + void Render(const QMapLibre::CustomLayerRenderParameters&) override final; + void Deinitialize() override final; void ReloadData(); @@ -36,4 +38,6 @@ private: std::unique_ptr p; }; -} // namespace scwx::qt::map +} // namespace map +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/map/radar_product_layer.cpp b/scwx-qt/source/scwx/qt/map/radar_product_layer.cpp index 22b43a87..79d03ce6 100644 --- a/scwx-qt/source/scwx/qt/map/radar_product_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/radar_product_layer.cpp @@ -1,14 +1,12 @@ #include -#include #include -#include -#include -#include #include #include #include #include +#include + #if defined(_MSC_VER) # pragma warning(push, 0) #endif @@ -26,118 +24,63 @@ # pragma warning(pop) #endif -namespace scwx::qt::map +namespace scwx { +namespace qt +{ +namespace map +{ + +static constexpr uint32_t MAX_RADIALS = 720; +static constexpr uint32_t MAX_DATA_MOMENT_GATES = 1840; static const std::string logPrefix_ = "scwx::qt::map::radar_product_layer"; static const auto logger_ = scwx::util::Logger::Create(logPrefix_); -class RadarProductLayer::Impl +class RadarProductLayerImpl { public: - explicit Impl() = default; - ~Impl() = default; + explicit RadarProductLayerImpl() : + shaderProgram_(nullptr), + uMVPMatrixLocation_(GL_INVALID_INDEX), + uMapScreenCoordLocation_(GL_INVALID_INDEX), + uDataMomentOffsetLocation_(GL_INVALID_INDEX), + uDataMomentScaleLocation_(GL_INVALID_INDEX), + uCFPEnabledLocation_(GL_INVALID_INDEX), + vbo_ {GL_INVALID_INDEX}, + vao_ {GL_INVALID_INDEX}, + texture_ {GL_INVALID_INDEX}, + numVertices_ {0}, + cfpEnabled_ {false}, + colorTableNeedsUpdate_ {false}, + sweepNeedsUpdate_ {false} + { + } + ~RadarProductLayerImpl() = default; - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; + std::shared_ptr shaderProgram_; - std::shared_ptr shaderProgram_ {nullptr}; + GLint uMVPMatrixLocation_; + GLint uMapScreenCoordLocation_; + GLint uDataMomentOffsetLocation_; + GLint uDataMomentScaleLocation_; + GLint uCFPEnabledLocation_; + std::array vbo_; + GLuint vao_; + GLuint texture_; - GLint uMVPMatrixLocation_ {static_cast(GL_INVALID_INDEX)}; - GLint uMapScreenCoordLocation_ {static_cast(GL_INVALID_INDEX)}; - GLint uDataMomentOffsetLocation_ {static_cast(GL_INVALID_INDEX)}; - GLint uDataMomentScaleLocation_ {static_cast(GL_INVALID_INDEX)}; - GLint uCFPEnabledLocation_ {static_cast(GL_INVALID_INDEX)}; - std::array vbo_ {GL_INVALID_INDEX}; - GLuint vao_ {GL_INVALID_INDEX}; - GLuint texture_ {GL_INVALID_INDEX}; + GLsizeiptr numVertices_; - GLsizeiptr numVertices_ {0}; + bool cfpEnabled_; - bool cfpEnabled_ {false}; - - std::uint16_t rangeMin_ {0}; - float scale_ {1.0f}; - - bool colorTableNeedsUpdate_ {false}; - bool sweepNeedsUpdate_ {false}; + bool colorTableNeedsUpdate_; + bool sweepNeedsUpdate_; }; -RadarProductLayer::RadarProductLayer(std::shared_ptr glContext) : - GenericLayer(std::move(glContext)), p(std::make_unique()) +RadarProductLayer::RadarProductLayer(std::shared_ptr context) : + GenericLayer(context), p(std::make_unique()) { -} -RadarProductLayer::~RadarProductLayer() = default; - -void RadarProductLayer::Initialize( - const std::shared_ptr& mapContext) -{ - logger_->debug("Initialize()"); - - auto glContext = gl_context(); - - // Load and configure radar shader - p->shaderProgram_ = - glContext->GetShaderProgram(":/gl/radar.vert", ":/gl/radar.frag"); - - p->uMVPMatrixLocation_ = - glGetUniformLocation(p->shaderProgram_->id(), "uMVPMatrix"); - if (p->uMVPMatrixLocation_ == -1) - { - logger_->warn("Could not find uMVPMatrix"); - } - - p->uMapScreenCoordLocation_ = - glGetUniformLocation(p->shaderProgram_->id(), "uMapScreenCoord"); - if (p->uMapScreenCoordLocation_ == -1) - { - logger_->warn("Could not find uMapScreenCoord"); - } - - p->uDataMomentOffsetLocation_ = - glGetUniformLocation(p->shaderProgram_->id(), "uDataMomentOffset"); - if (p->uDataMomentOffsetLocation_ == -1) - { - logger_->warn("Could not find uDataMomentOffset"); - } - - p->uDataMomentScaleLocation_ = - glGetUniformLocation(p->shaderProgram_->id(), "uDataMomentScale"); - if (p->uDataMomentScaleLocation_ == -1) - { - logger_->warn("Could not find uDataMomentScale"); - } - - p->uCFPEnabledLocation_ = - glGetUniformLocation(p->shaderProgram_->id(), "uCFPEnabled"); - if (p->uCFPEnabledLocation_ == -1) - { - logger_->warn("Could not find uCFPEnabled"); - } - - p->shaderProgram_->Use(); - - // Generate a vertex array object - glGenVertexArrays(1, &p->vao_); - - // Generate vertex buffer objects - glGenBuffers(3, p->vbo_.data()); - - // Update radar sweep - p->sweepNeedsUpdate_ = true; - UpdateSweep(mapContext); - - // Create color table - glGenTextures(1, &p->texture_); - p->colorTableNeedsUpdate_ = true; - UpdateColorTable(mapContext); - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - - auto radarProductView = mapContext->radar_product_view(); + auto radarProductView = context->radar_product_view(); connect(radarProductView.get(), &view::RadarProductView::ColorTableLutUpdated, this, @@ -147,46 +90,112 @@ void RadarProductLayer::Initialize( this, [this]() { p->sweepNeedsUpdate_ = true; }); } +RadarProductLayer::~RadarProductLayer() = default; -void RadarProductLayer::UpdateSweep( - const std::shared_ptr& mapContext) +void RadarProductLayer::Initialize() { - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) - // NOLINTBEGIN(modernize-use-nullptr) + logger_->debug("Initialize()"); + + gl::OpenGLFunctions& gl = context()->gl(); + + // Load and configure radar shader + p->shaderProgram_ = + context()->GetShaderProgram(":/gl/radar.vert", ":/gl/radar.frag"); + + p->uMVPMatrixLocation_ = + gl.glGetUniformLocation(p->shaderProgram_->id(), "uMVPMatrix"); + if (p->uMVPMatrixLocation_ == -1) + { + logger_->warn("Could not find uMVPMatrix"); + } + + p->uMapScreenCoordLocation_ = + gl.glGetUniformLocation(p->shaderProgram_->id(), "uMapScreenCoord"); + if (p->uMapScreenCoordLocation_ == -1) + { + logger_->warn("Could not find uMapScreenCoord"); + } + + p->uDataMomentOffsetLocation_ = + gl.glGetUniformLocation(p->shaderProgram_->id(), "uDataMomentOffset"); + if (p->uDataMomentOffsetLocation_ == -1) + { + logger_->warn("Could not find uDataMomentOffset"); + } + + p->uDataMomentScaleLocation_ = + gl.glGetUniformLocation(p->shaderProgram_->id(), "uDataMomentScale"); + if (p->uDataMomentScaleLocation_ == -1) + { + logger_->warn("Could not find uDataMomentScale"); + } + + p->uCFPEnabledLocation_ = + gl.glGetUniformLocation(p->shaderProgram_->id(), "uCFPEnabled"); + if (p->uCFPEnabledLocation_ == -1) + { + logger_->warn("Could not find uCFPEnabled"); + } + + p->shaderProgram_->Use(); + + // Generate a vertex array object + gl.glGenVertexArrays(1, &p->vao_); + + // Generate vertex buffer objects + gl.glGenBuffers(3, p->vbo_.data()); + + // Update radar sweep + p->sweepNeedsUpdate_ = true; + UpdateSweep(); + + // Create color table + gl.glGenTextures(1, &p->texture_); + p->colorTableNeedsUpdate_ = true; + UpdateColorTable(); + gl.glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + gl.glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + gl.glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); +} + +void RadarProductLayer::UpdateSweep() +{ + logger_->debug("UpdateSweep()"); + + gl::OpenGLFunctions& gl = context()->gl(); boost::timer::cpu_timer timer; std::shared_ptr radarProductView = - mapContext->radar_product_view(); + context()->radar_product_view(); std::unique_lock sweepLock(radarProductView->sweep_mutex(), std::try_to_lock); if (!sweepLock.owns_lock()) { - logger_->trace("Sweep locked, deferring update"); + logger_->debug("Sweep locked, deferring update"); return; } - logger_->debug("UpdateSweep()"); p->sweepNeedsUpdate_ = false; const std::vector& vertices = radarProductView->vertices(); // Bind a vertex array object - glBindVertexArray(p->vao_); + gl.glBindVertexArray(p->vao_); // Buffer vertices - glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); + gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[0]); timer.start(); - glBufferData(GL_ARRAY_BUFFER, - static_cast(vertices.size() * sizeof(GLfloat)), - vertices.data(), - GL_STATIC_DRAW); + gl.glBufferData(GL_ARRAY_BUFFER, + vertices.size() * sizeof(GLfloat), + vertices.data(), + GL_STATIC_DRAW); timer.stop(); logger_->debug("Vertices buffered in {}", timer.format(6, "%ws")); - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, static_cast(0)); - glEnableVertexAttribArray(0); + gl.glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, static_cast(0)); + gl.glEnableVertexAttribArray(0); // Buffer data moments const GLvoid* data; @@ -205,14 +214,14 @@ void RadarProductLayer::UpdateSweep( type = GL_UNSIGNED_SHORT; } - glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); + gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[1]); timer.start(); - glBufferData(GL_ARRAY_BUFFER, dataSize, data, GL_STATIC_DRAW); + gl.glBufferData(GL_ARRAY_BUFFER, dataSize, data, GL_STATIC_DRAW); timer.stop(); logger_->debug("Data moments buffered in {}", timer.format(6, "%ws")); - glVertexAttribIPointer(1, 1, type, 0, static_cast(0)); - glEnableVertexAttribArray(1); + gl.glVertexAttribIPointer(1, 1, type, 0, static_cast(0)); + gl.glEnableVertexAttribArray(1); // Buffer CFP data const GLvoid* cfpData; @@ -234,51 +243,41 @@ void RadarProductLayer::UpdateSweep( cfpType = GL_UNSIGNED_SHORT; } - glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[2]); + gl.glBindBuffer(GL_ARRAY_BUFFER, p->vbo_[2]); timer.start(); - glBufferData(GL_ARRAY_BUFFER, cfpDataSize, cfpData, GL_STATIC_DRAW); + gl.glBufferData(GL_ARRAY_BUFFER, cfpDataSize, cfpData, GL_STATIC_DRAW); timer.stop(); logger_->debug("CFP moments buffered in {}", timer.format(6, "%ws")); - glVertexAttribIPointer(2, 1, cfpType, 0, static_cast(0)); - glEnableVertexAttribArray(2); + gl.glVertexAttribIPointer(2, 1, cfpType, 0, static_cast(0)); + gl.glEnableVertexAttribArray(2); } else { - glDisableVertexAttribArray(2); + gl.glDisableVertexAttribArray(2); } - p->numVertices_ = static_cast(vertices.size() / 2); - - // NOLINTEND(modernize-use-nullptr) - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) + p->numVertices_ = vertices.size() / 2; } void RadarProductLayer::Render( - const std::shared_ptr& mapContext, const QMapLibre::CustomLayerRenderParameters& params) { + gl::OpenGLFunctions& gl = context()->gl(); p->shaderProgram_->Use(); // Set OpenGL blend mode for transparency - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - const bool wireframeEnabled = mapContext->settings().radarWireframeEnabled_; - if (wireframeEnabled) - { - // Set polygon mode to draw wireframe - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - } + gl.glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); if (p->colorTableNeedsUpdate_) { - UpdateColorTable(mapContext); + UpdateColorTable(); } if (p->sweepNeedsUpdate_) { - UpdateSweep(mapContext); + UpdateSweep(); } const float scale = std::pow(2.0, params.zoom) * 2.0f * @@ -292,29 +291,20 @@ void RadarProductLayer::Render( glm::radians(params.bearing), glm::vec3(0.0f, 0.0f, 1.0f)); - glUniform2fv(p->uMapScreenCoordLocation_, - 1, - glm::value_ptr(util::maplibre::LatLongToScreenCoordinate( - {params.latitude, params.longitude}))); + gl.glUniform2fv(p->uMapScreenCoordLocation_, + 1, + glm::value_ptr(util::maplibre::LatLongToScreenCoordinate( + {params.latitude, params.longitude}))); - glUniformMatrix4fv( + gl.glUniformMatrix4fv( p->uMVPMatrixLocation_, 1, GL_FALSE, glm::value_ptr(uMVPMatrix)); - glUniform1i(p->uCFPEnabledLocation_, p->cfpEnabled_ ? 1 : 0); + gl.glUniform1i(p->uCFPEnabledLocation_, p->cfpEnabled_ ? 1 : 0); - glUniform1ui(p->uDataMomentOffsetLocation_, p->rangeMin_); - glUniform1f(p->uDataMomentScaleLocation_, p->scale_); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_1D, p->texture_); - glBindVertexArray(p->vao_); - glDrawArrays(GL_TRIANGLES, 0, static_cast(p->numVertices_)); - - if (wireframeEnabled) - { - // Restore polygon mode to default - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - } + gl.glActiveTexture(GL_TEXTURE0); + gl.glBindTexture(GL_TEXTURE_1D, p->texture_); + gl.glBindVertexArray(p->vao_); + gl.glDrawArrays(GL_TRIANGLES, 0, p->numVertices_); SCWX_GL_CHECK_ERROR(); } @@ -323,8 +313,10 @@ void RadarProductLayer::Deinitialize() { logger_->debug("Deinitialize()"); - glDeleteVertexArrays(1, &p->vao_); - glDeleteBuffers(3, p->vbo_.data()); + gl::OpenGLFunctions& gl = context()->gl(); + + gl.glDeleteVertexArrays(1, &p->vao_); + gl.glDeleteBuffers(3, p->vbo_.data()); p->uMVPMatrixLocation_ = GL_INVALID_INDEX; p->uMapScreenCoordLocation_ = GL_INVALID_INDEX; @@ -337,7 +329,6 @@ void RadarProductLayer::Deinitialize() } bool RadarProductLayer::RunMousePicking( - const std::shared_ptr& mapContext, const QMapLibre::CustomLayerRenderParameters& /* params */, const QPointF& /* mouseLocalPos */, const QPointF& mouseGlobalPos, @@ -351,68 +342,13 @@ bool RadarProductLayer::RunMousePicking( Qt::KeyboardModifier::ShiftModifier) { std::shared_ptr radarProductView = - mapContext->radar_product_view(); - - if (mapContext->radar_site() == nullptr) - { - return itemPicked; - } - - // Get distance and altitude of point - const double radarLatitude = mapContext->radar_site()->latitude(); - const double radarLongitude = mapContext->radar_site()->longitude(); - - const auto distanceMeters = - util::GeographicLib::GetDistance(mouseGeoCoords.latitude_, - mouseGeoCoords.longitude_, - radarLatitude, - radarLongitude); - - const std::string distanceUnitName = - settings::UnitSettings::Instance().distance_units().GetValue(); - const types::DistanceUnits distanceUnits = - types::GetDistanceUnitsFromName(distanceUnitName); - const double distanceScale = types::GetDistanceUnitsScale(distanceUnits); - const std::string distanceAbbrev = - types::GetDistanceUnitsAbbreviation(distanceUnits); - - const double distance = distanceMeters.value() * - scwx::common::kKilometersPerMeter * distanceScale; - std::string distanceHeightStr = - fmt::format("{:.2f} {}", distance, distanceAbbrev); + context()->radar_product_view(); if (radarProductView == nullptr) { - util::tooltip::Show(distanceHeightStr, mouseGlobalPos); - itemPicked = true; return itemPicked; } - std::optional elevation = radarProductView->elevation(); - if (elevation.has_value()) - { - const auto altitudeMeters = - util::GeographicLib::GetRadarBeamAltititude( - distanceMeters, - units::angle::degrees(*elevation), - mapContext->radar_site()->altitude()); - - const std::string heightUnitName = - settings::UnitSettings::Instance().echo_tops_units().GetValue(); - const types::EchoTopsUnits heightUnits = - types::GetEchoTopsUnitsFromName(heightUnitName); - const double heightScale = types::GetEchoTopsUnitsScale(heightUnits); - const std::string heightAbbrev = - types::GetEchoTopsUnitsAbbreviation(heightUnits); - - const double altitude = altitudeMeters.value() * - scwx::common::kKilometersPerMeter * - heightScale; - - distanceHeightStr = fmt::format( - "{}\n{:.2f} {}", distanceHeightStr, altitude, heightAbbrev); - } - std::optional binLevel = radarProductView->GetBinLevel(mouseGeoCoords); @@ -438,13 +374,12 @@ bool RadarProductLayer::RunMousePicking( if (codeName != codeShortName && !codeShortName.empty()) { // There is a unique long and short name for the code - hoverText = fmt::format( - "{}: {}\n{}", codeShortName, codeName, distanceHeightStr); + hoverText = fmt::format("{}: {}", codeShortName, codeName); } else { // Otherwise, only use the long name (always present) - hoverText = fmt::format("{}\n{}", codeName, distanceHeightStr); + hoverText = codeName; } // Show the tooltip @@ -495,20 +430,17 @@ bool RadarProductLayer::RunMousePicking( { // Don't display a units value that wasn't intended to be // displayed - hoverText = - fmt::format("{}{}\n{}", f, suffix, distanceHeightStr); + hoverText = fmt::format("{}{}", f, suffix); } else if (std::isalpha(static_cast(units.at(0)))) { // dBZ, Kts, etc. - hoverText = fmt::format( - "{} {}{}\n{}", f, units, suffix, distanceHeightStr); + hoverText = fmt::format("{} {}{}", f, units, suffix); } else { // %, etc. - hoverText = fmt::format( - "{}{}{}\n{}", f, units, suffix, distanceHeightStr); + hoverText = fmt::format("{}{}{}", f, units, suffix); } // Show the tooltip @@ -517,26 +449,20 @@ bool RadarProductLayer::RunMousePicking( itemPicked = true; } } - else - { - // Always show tooltip for distance and altitude - util::tooltip::Show(distanceHeightStr, mouseGlobalPos); - itemPicked = true; - } } return itemPicked; } -void RadarProductLayer::UpdateColorTable( - const std::shared_ptr& mapContext) +void RadarProductLayer::UpdateColorTable() { logger_->debug("UpdateColorTable()"); p->colorTableNeedsUpdate_ = false; + gl::OpenGLFunctions& gl = context()->gl(); std::shared_ptr radarProductView = - mapContext->radar_product_view(); + context()->radar_product_view(); const std::vector& colorTable = radarProductView->color_table_lut(); @@ -545,20 +471,22 @@ void RadarProductLayer::UpdateColorTable( const float scale = rangeMax - rangeMin; - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_1D, p->texture_); - glTexImage1D(GL_TEXTURE_1D, - 0, - GL_RGBA, - (GLsizei) colorTable.size(), - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - colorTable.data()); - glGenerateMipmap(GL_TEXTURE_1D); + gl.glActiveTexture(GL_TEXTURE0); + gl.glBindTexture(GL_TEXTURE_1D, p->texture_); + gl.glTexImage1D(GL_TEXTURE_1D, + 0, + GL_RGBA, + (GLsizei) colorTable.size(), + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + colorTable.data()); + gl.glGenerateMipmap(GL_TEXTURE_1D); - p->rangeMin_ = rangeMin; - p->scale_ = scale; + gl.glUniform1ui(p->uDataMomentOffsetLocation_, rangeMin); + gl.glUniform1f(p->uDataMomentScaleLocation_, scale); } -} // namespace scwx::qt::map +} // namespace map +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/map/radar_product_layer.hpp b/scwx-qt/source/scwx/qt/map/radar_product_layer.hpp index df5adcc9..1e53eba8 100644 --- a/scwx-qt/source/scwx/qt/map/radar_product_layer.hpp +++ b/scwx-qt/source/scwx/qt/map/radar_product_layer.hpp @@ -2,25 +2,27 @@ #include -namespace scwx::qt::map +namespace scwx { +namespace qt +{ +namespace map +{ + +class RadarProductLayerImpl; class RadarProductLayer : public GenericLayer { - Q_DISABLE_COPY_MOVE(RadarProductLayer) - public: - explicit RadarProductLayer(std::shared_ptr glContext); + explicit RadarProductLayer(std::shared_ptr context); ~RadarProductLayer(); - void Initialize(const std::shared_ptr& mapContext) final; - void Render(const std::shared_ptr& mapContext, - const QMapLibre::CustomLayerRenderParameters&) final; - void Deinitialize() final; + void Initialize() override final; + void Render(const QMapLibre::CustomLayerRenderParameters&) override final; + void Deinitialize() override final; - bool - RunMousePicking(const std::shared_ptr& mapContext, - const QMapLibre::CustomLayerRenderParameters& params, + virtual bool + RunMousePicking(const QMapLibre::CustomLayerRenderParameters& params, const QPointF& mouseLocalPos, const QPointF& mouseGlobalPos, const glm::vec2& mouseCoords, @@ -28,12 +30,13 @@ public: std::shared_ptr& eventHandler) override; private: - void UpdateColorTable(const std::shared_ptr& mapContext); - void UpdateSweep(const std::shared_ptr& mapContext); + void UpdateColorTable(); + void UpdateSweep(); private: - class Impl; - std::unique_ptr p; + std::unique_ptr p; }; -} // namespace scwx::qt::map +} // namespace map +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/map/radar_range_layer.cpp b/scwx-qt/source/scwx/qt/map/radar_range_layer.cpp index b23232a3..e660c266 100644 --- a/scwx-qt/source/scwx/qt/map/radar_range_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/radar_range_layer.cpp @@ -5,7 +5,11 @@ #include -namespace scwx::qt::map +namespace scwx +{ +namespace qt +{ +namespace map { static const std::string logPrefix_ = "scwx::qt::map::radar_range_layer"; @@ -94,4 +98,6 @@ GetRangeCircle(float range, QMapLibre::Coordinate center) return rangeCircle; } -} // namespace scwx::qt::map +} // namespace map +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/map/radar_range_layer.hpp b/scwx-qt/source/scwx/qt/map/radar_range_layer.hpp index e11ea6fc..d900f01e 100644 --- a/scwx-qt/source/scwx/qt/map/radar_range_layer.hpp +++ b/scwx-qt/source/scwx/qt/map/radar_range_layer.hpp @@ -2,7 +2,13 @@ #include -namespace scwx::qt::map::RadarRangeLayer +namespace scwx +{ +namespace qt +{ +namespace map +{ +namespace RadarRangeLayer { void Add(std::shared_ptr map, @@ -13,4 +19,7 @@ void Update(std::shared_ptr map, float range, QMapLibre::Coordinate center); -} // namespace scwx::qt::map::RadarRangeLayer +} // namespace RadarRangeLayer +} // namespace map +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/map/radar_site_layer.cpp b/scwx-qt/source/scwx/qt/map/radar_site_layer.cpp index 9f6866b0..33486185 100644 --- a/scwx-qt/source/scwx/qt/map/radar_site_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/radar_site_layer.cpp @@ -1,7 +1,5 @@ #include #include -#include -#include #include #include #include @@ -11,9 +9,11 @@ #include #include -#include - -namespace scwx::qt::map +namespace scwx +{ +namespace qt +{ +namespace map { static const std::string logPrefix_ = "scwx::qt::map::radar_site_layer"; @@ -22,21 +22,11 @@ static const auto logger_ = scwx::util::Logger::Create(logPrefix_); class RadarSiteLayer::Impl { public: - explicit Impl(RadarSiteLayer* self, - const std::shared_ptr& glContext) : - self_ {self}, geoLines_ {std::make_shared(glContext)} - { - } + explicit Impl(RadarSiteLayer* self) : self_ {self} {} ~Impl() = default; - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; - void RenderRadarSite(const QMapLibre::CustomLayerRenderParameters& params, std::shared_ptr& radarSite); - void RenderRadarLine(const std::shared_ptr& mapContext); RadarSiteLayer* self_; @@ -50,62 +40,28 @@ public: float halfHeight_ {}; std::string hoverText_ {}; - - std::shared_ptr geoLines_; - std::array, 2> radarSiteLines_ { - nullptr, nullptr}; }; -RadarSiteLayer::RadarSiteLayer( - const std::shared_ptr& glContext) : - DrawLayer(glContext, "RadarSiteLayer"), - p(std::make_unique(this, glContext)) +RadarSiteLayer::RadarSiteLayer(std::shared_ptr context) : + DrawLayer(context), p(std::make_unique(this)) { } RadarSiteLayer::~RadarSiteLayer() = default; -void RadarSiteLayer::Initialize(const std::shared_ptr& mapContext) +void RadarSiteLayer::Initialize() { logger_->debug("Initialize()"); p->radarSites_ = config::RadarSite::GetAll(); - - p->geoLines_->StartLines(); - p->radarSiteLines_[0] = p->geoLines_->AddLine(); - p->radarSiteLines_[1] = p->geoLines_->AddLine(); - p->geoLines_->FinishLines(); - - static const boost::gil::rgba32f_pixel_t color0 {0.0f, 0.0f, 0.0f, 1.0f}; - static const boost::gil::rgba32f_pixel_t color1 {1.0f, 1.0f, 1.0f, 1.0f}; - static const float width = 1; - p->geoLines_->SetLineModulate(p->radarSiteLines_[0], color0); - p->geoLines_->SetLineWidth(p->radarSiteLines_[0], width + 2); - - p->geoLines_->SetLineModulate(p->radarSiteLines_[1], color1); - p->geoLines_->SetLineWidth(p->radarSiteLines_[1], width); - - AddDrawItem(p->geoLines_); - p->geoLines_->set_thresholded(false); - - DrawLayer::Initialize(mapContext); } void RadarSiteLayer::Render( - const std::shared_ptr& mapContext, const QMapLibre::CustomLayerRenderParameters& params) { - p->hoverText_.clear(); + gl::OpenGLFunctions& gl = context()->gl(); - auto mapDistance = util::maplibre::GetMapDistance(params); - auto threshold = units::length::kilometers( - settings::GeneralSettings::Instance().radar_site_threshold().GetValue()); - - if (!(threshold.value() == 0.0 || mapDistance <= threshold || - (threshold.value() < 0 && mapDistance >= -threshold))) - { - return; - } + context()->set_render_parameters(params); // Update map screen coordinate and scale information p->mapScreenCoordLocation_ = util::maplibre::LatLongToScreenCoordinate( @@ -117,7 +73,8 @@ void RadarSiteLayer::Render( p->halfWidth_ = params.width * 0.5f; p->halfHeight_ = params.height * 0.5f; - ImGuiFrameStart(mapContext); + p->hoverText_.clear(); + // Radar site ImGui windows shouldn't have padding ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2 {0.0f, 0.0f}); @@ -128,11 +85,6 @@ void RadarSiteLayer::Render( ImGui::PopStyleVar(); - p->RenderRadarLine(mapContext); - - DrawLayer::RenderWithoutImGui(params); - - ImGuiFrameEnd(); SCWX_GL_CHECK_ERROR(); } @@ -175,7 +127,6 @@ void RadarSiteLayer::Impl::RenderRadarSite( if (ImGui::Button(radarSite->id().c_str())) { Q_EMIT self_->RadarSiteSelected(radarSite->id()); - self_->ImGuiSelectContext(); } // Store hover text for mouse picking pass @@ -198,38 +149,6 @@ void RadarSiteLayer::Impl::RenderRadarSite( } } -void RadarSiteLayer::Impl::RenderRadarLine( - const std::shared_ptr& mapContext) -{ - if ((QGuiApplication::keyboardModifiers() & - Qt::KeyboardModifier::ShiftModifier) && - mapContext->radar_site() != nullptr) - { - const auto& mouseCoord = mapContext->mouse_coordinate(); - const double radarLatitude = mapContext->radar_site()->latitude(); - const double radarLongitude = mapContext->radar_site()->longitude(); - - geoLines_->SetLineLocation(radarSiteLines_[0], - static_cast(mouseCoord.latitude_), - static_cast(mouseCoord.longitude_), - static_cast(radarLatitude), - static_cast(radarLongitude)); - geoLines_->SetLineVisible(radarSiteLines_[0], true); - - geoLines_->SetLineLocation(radarSiteLines_[1], - static_cast(mouseCoord.latitude_), - static_cast(mouseCoord.longitude_), - static_cast(radarLatitude), - static_cast(radarLongitude)); - geoLines_->SetLineVisible(radarSiteLines_[1], true); - } - else - { - geoLines_->SetLineVisible(radarSiteLines_[0], false); - geoLines_->SetLineVisible(radarSiteLines_[1], false); - } -} - void RadarSiteLayer::Deinitialize() { logger_->debug("Deinitialize()"); @@ -238,7 +157,6 @@ void RadarSiteLayer::Deinitialize() } bool RadarSiteLayer::RunMousePicking( - const std::shared_ptr& /* mapContext */, const QMapLibre::CustomLayerRenderParameters& /* params */, const QPointF& /* mouseLocalPos */, const QPointF& mouseGlobalPos, @@ -255,4 +173,6 @@ bool RadarSiteLayer::RunMousePicking( return false; } -} // namespace scwx::qt::map +} // namespace map +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/map/radar_site_layer.hpp b/scwx-qt/source/scwx/qt/map/radar_site_layer.hpp index 74fc6398..f88786f4 100644 --- a/scwx-qt/source/scwx/qt/map/radar_site_layer.hpp +++ b/scwx-qt/source/scwx/qt/map/radar_site_layer.hpp @@ -2,7 +2,11 @@ #include -namespace scwx::qt::map +namespace scwx +{ +namespace qt +{ +namespace map { class RadarSiteLayer : public DrawLayer @@ -11,22 +15,20 @@ class RadarSiteLayer : public DrawLayer Q_DISABLE_COPY_MOVE(RadarSiteLayer) public: - explicit RadarSiteLayer(const std::shared_ptr& glContext); + explicit RadarSiteLayer(std::shared_ptr context); ~RadarSiteLayer(); - void Initialize(const std::shared_ptr& mapContext) final; - void Render(const std::shared_ptr& mapContext, - const QMapLibre::CustomLayerRenderParameters&) final; - void Deinitialize() final; + void Initialize() override final; + void Render(const QMapLibre::CustomLayerRenderParameters&) override final; + void Deinitialize() override final; - bool - RunMousePicking(const std::shared_ptr& mapContext, - const QMapLibre::CustomLayerRenderParameters& params, - const QPointF& mouseLocalPos, - const QPointF& mouseGlobalPos, - const glm::vec2& mouseCoords, - const common::Coordinate& mouseGeoCoords, - std::shared_ptr& eventHandler) final; + bool RunMousePicking( + const QMapLibre::CustomLayerRenderParameters& params, + const QPointF& mouseLocalPos, + const QPointF& mouseGlobalPos, + const glm::vec2& mouseCoords, + const common::Coordinate& mouseGeoCoords, + std::shared_ptr& eventHandler) override final; signals: void RadarSiteSelected(const std::string& id); @@ -36,4 +38,6 @@ private: std::unique_ptr p; }; -} // namespace scwx::qt::map +} // namespace map +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/model/alert_model.cpp b/scwx-qt/source/scwx/qt/model/alert_model.cpp index 20af05f8..d4bb1111 100644 --- a/scwx-qt/source/scwx/qt/model/alert_model.cpp +++ b/scwx-qt/source/scwx/qt/model/alert_model.cpp @@ -10,10 +10,17 @@ #include #include + +#include + #include #include -namespace scwx::qt::model +namespace scwx +{ +namespace qt +{ +namespace model { static const std::string logPrefix_ = "scwx::qt::model::alert_model"; @@ -30,9 +37,9 @@ public: explicit AlertModelImpl(); ~AlertModelImpl() = default; - bool GetObserved(const types::TextEventKey& key); - awips::ibw::ThreatCategory GetThreatCategory(const types::TextEventKey& key); - bool GetTornadoPossible(const types::TextEventKey& key); + bool GetObserved(const types::TextEventKey& key); + awips::ThreatCategory GetThreatCategory(const types::TextEventKey& key); + bool GetTornadoPossible(const types::TextEventKey& key); static std::string GetCounties(const types::TextEventKey& key); static std::string GetState(const types::TextEventKey& key); @@ -54,7 +61,7 @@ public: types::TextEventHash> observedMap_; std::unordered_map> threatCategoryMap_; std::unordered_map> - distanceMap_; - scwx::common::Coordinate previousPosition_; + distanceMap_; + scwx::common::Coordinate previousPosition_; }; AlertModel::AlertModel(QObject* parent) : @@ -151,7 +158,7 @@ QVariant AlertModel::data(const QModelIndex& index, int role) const case static_cast(Column::ThreatCategory): if (role == Qt::DisplayRole) { - return QString::fromStdString(awips::ibw::GetThreatCategoryName( + return QString::fromStdString(awips::GetThreatCategoryName( p->GetThreatCategory(textEventKey))); } else @@ -323,45 +330,16 @@ AlertModel::headerData(int section, Qt::Orientation orientation, int role) const } void AlertModel::HandleAlert(const types::TextEventKey& alertKey, - std::size_t messageIndex, - boost::uuids::uuid uuid) + size_t messageIndex) { logger_->trace("Handle alert: {}", alertKey.ToString()); double distanceInMeters; - const auto& alertMessages = p->textEventManager_->message_list(alertKey); - - // Find message by UUID instead of index, as the message index could have - // changed between the signal being emitted and the handler being called - auto messageIt = std::find_if(alertMessages.cbegin(), - alertMessages.cend(), - [&uuid](const auto& message) - { return uuid == message->uuid(); }); - - if (messageIt == alertMessages.cend()) - { - logger_->warn("Could not find alert uuid: {} ({})", - alertKey.ToString(), - messageIndex); - return; - } - - auto& message = *messageIt; - - // Store the current message index - messageIndex = static_cast( - std::distance(alertMessages.cbegin(), messageIt)); - - // Skip alert if this is not the most recent message - if (messageIndex + 1 < alertMessages.size()) - { - return; - } - // Get the most recent segment for the event - const std::shared_ptr alertSegment = - message->segments().back(); + auto alertMessages = p->textEventManager_->message_list(alertKey); + std::shared_ptr alertSegment = + alertMessages[messageIndex]->segments().back(); p->observedMap_.insert_or_assign(alertKey, alertSegment->observed_); p->threatCategoryMap_.insert_or_assign(alertKey, @@ -409,36 +387,6 @@ void AlertModel::HandleAlert(const types::TextEventKey& alertKey, } } -void AlertModel::HandleAlertsRemoved( - const std::unordered_set>& - alertKeys) -{ - logger_->trace("Handle alerts removed"); - - for (const auto& alertKey : alertKeys) - { - // Remove from the list of text event keys - auto it = std::find( - p->textEventKeys_.begin(), p->textEventKeys_.end(), alertKey); - if (it != p->textEventKeys_.end()) - { - const int row = - static_cast(std::distance(p->textEventKeys_.begin(), it)); - beginRemoveRows(QModelIndex(), row, row); - p->textEventKeys_.erase(it); - endRemoveRows(); - } - - // Remove from internal maps - p->observedMap_.erase(alertKey); - p->threatCategoryMap_.erase(alertKey); - p->tornadoPossibleMap_.erase(alertKey); - p->centroidMap_.erase(alertKey); - p->distanceMap_.erase(alertKey); - } -} - void AlertModel::HandleMapUpdate(double latitude, double longitude) { logger_->trace("Handle map update: {}, {}", latitude, longitude); @@ -491,10 +439,10 @@ bool AlertModelImpl::GetObserved(const types::TextEventKey& key) return observed; } -awips::ibw::ThreatCategory +awips::ThreatCategory AlertModelImpl::GetThreatCategory(const types::TextEventKey& key) { - awips::ibw::ThreatCategory threatCategory = awips::ibw::ThreatCategory::Base; + awips::ThreatCategory threatCategory = awips::ThreatCategory::Base; auto it = threatCategoryMap_.find(key); if (it != threatCategoryMap_.cend()) @@ -541,8 +489,8 @@ std::string AlertModelImpl::GetCounties(const types::TextEventKey& key) } else { - logger_->trace("GetCounties(): No message associated with key: {}", - key.ToString()); + logger_->warn("GetCounties(): No message associated with key: {}", + key.ToString()); return {}; } } @@ -560,8 +508,8 @@ std::string AlertModelImpl::GetState(const types::TextEventKey& key) } else { - logger_->trace("GetState(): No message associated with key: {}", - key.ToString()); + logger_->warn("GetState(): No message associated with key: {}", + key.ToString()); return {}; } } @@ -578,8 +526,8 @@ AlertModelImpl::GetStartTime(const types::TextEventKey& key) } else { - logger_->trace("GetStartTime(): No message associated with key: {}", - key.ToString()); + logger_->warn("GetStartTime(): No message associated with key: {}", + key.ToString()); return {}; } } @@ -603,8 +551,8 @@ AlertModelImpl::GetEndTime(const types::TextEventKey& key) } else { - logger_->trace("GetEndTime(): No message associated with key: {}", - key.ToString()); + logger_->warn("GetEndTime(): No message associated with key: {}", + key.ToString()); return {}; } } @@ -614,4 +562,6 @@ std::string AlertModelImpl::GetEndTimeString(const types::TextEventKey& key) return scwx::util::TimeString(GetEndTime(key)); } -} // namespace scwx::qt::model +} // namespace model +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/model/alert_model.hpp b/scwx-qt/source/scwx/qt/model/alert_model.hpp index 443ca9bb..df6d561e 100644 --- a/scwx-qt/source/scwx/qt/model/alert_model.hpp +++ b/scwx-qt/source/scwx/qt/model/alert_model.hpp @@ -4,9 +4,7 @@ #include #include -#include -#include #include namespace scwx @@ -52,13 +50,7 @@ public: int role = Qt::DisplayRole) const override; public slots: - void HandleAlert(const types::TextEventKey& alertKey, - std::size_t messageIndex, - boost::uuids::uuid uuid); - void HandleAlertsRemoved( - const std::unordered_set>& - alertKeys); + void HandleAlert(const types::TextEventKey& alertKey, size_t messageIndex); void HandleMapUpdate(double latitude, double longitude); private: diff --git a/scwx-qt/source/scwx/qt/model/alert_proxy_model.cpp b/scwx-qt/source/scwx/qt/model/alert_proxy_model.cpp index 0fa55d96..a2afee55 100644 --- a/scwx-qt/source/scwx/qt/model/alert_proxy_model.cpp +++ b/scwx-qt/source/scwx/qt/model/alert_proxy_model.cpp @@ -3,29 +3,27 @@ #include #include #include -#include #include #include #include -namespace scwx::qt::model +namespace scwx +{ +namespace qt +{ +namespace model { static const std::string logPrefix_ = "scwx::qt::model::alert_proxy_model"; static const auto logger_ = scwx::util::Logger::Create(logPrefix_); -class AlertProxyModel::Impl +class AlertProxyModelImpl { public: - explicit Impl(AlertProxyModel* self); - ~Impl(); - - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; + explicit AlertProxyModelImpl(AlertProxyModel* self); + ~AlertProxyModelImpl(); void UpdateAlerts(); @@ -38,7 +36,8 @@ public: }; AlertProxyModel::AlertProxyModel(QObject* parent) : - QSortFilterProxyModel(parent), p(std::make_unique(this)) + QSortFilterProxyModel(parent), + p(std::make_unique(this)) { } AlertProxyModel::~AlertProxyModel() = default; @@ -68,7 +67,7 @@ bool AlertProxyModel::filterAcceptsRow(int sourceRow, .value(); // Compare end time to current - if (endTime < scwx::util::time::now()) + if (endTime < std::chrono::system_clock::now()) { acceptAlertActiveFilter = false; } @@ -78,7 +77,7 @@ bool AlertProxyModel::filterAcceptsRow(int sourceRow, QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent); } -AlertProxyModel::Impl::Impl(AlertProxyModel* self) : +AlertProxyModelImpl::AlertProxyModelImpl(AlertProxyModel* self) : self_ {self}, alertActiveFilterEnabled_ {false}, alertUpdateTimer_ {scwx::util::io_context()} @@ -87,37 +86,26 @@ AlertProxyModel::Impl::Impl(AlertProxyModel* self) : UpdateAlerts(); } -AlertProxyModel::Impl::~Impl() +AlertProxyModelImpl::~AlertProxyModelImpl() { - try - { - const std::unique_lock lock(alertMutex_); - alertUpdateTimer_.cancel(); - } - catch (const std::exception& ex) - { - logger_->error(ex.what()); - } + std::unique_lock lock(alertMutex_); + alertUpdateTimer_.cancel(); } -void AlertProxyModel::Impl::UpdateAlerts() +void AlertProxyModelImpl::UpdateAlerts() { logger_->trace("UpdateAlerts"); // Take a unique lock before modifying feature lists - const std::unique_lock lock(alertMutex_); + std::unique_lock lock(alertMutex_); // Re-evaluate for expired alerts if (alertActiveFilterEnabled_) { - QMetaObject::invokeMethod(self_, - static_cast( - &QSortFilterProxyModel::invalidate)); + self_->invalidateRowsFilter(); } using namespace std::chrono; - - // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers): Readability alertUpdateTimer_.expires_after(15s); alertUpdateTimer_.async_wait( [this](const boost::system::error_code& e) @@ -144,4 +132,6 @@ void AlertProxyModel::Impl::UpdateAlerts() }); } -} // namespace scwx::qt::model +} // namespace model +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/model/alert_proxy_model.hpp b/scwx-qt/source/scwx/qt/model/alert_proxy_model.hpp index 1ee6a138..ee8b81c1 100644 --- a/scwx-qt/source/scwx/qt/model/alert_proxy_model.hpp +++ b/scwx-qt/source/scwx/qt/model/alert_proxy_model.hpp @@ -4,7 +4,11 @@ #include -namespace scwx::qt::model +namespace scwx +{ +namespace qt +{ +namespace model { class AlertProxyModelImpl; @@ -12,7 +16,7 @@ class AlertProxyModelImpl; class AlertProxyModel : public QSortFilterProxyModel { private: - Q_DISABLE_COPY_MOVE(AlertProxyModel) + Q_DISABLE_COPY(AlertProxyModel) public: explicit AlertProxyModel(QObject* parent = nullptr); @@ -20,13 +24,15 @@ public: void SetAlertActiveFilter(bool enabled); - [[nodiscard]] bool - filterAcceptsRow(int sourceRow, - const QModelIndex& sourceParent) const override; + bool filterAcceptsRow(int sourceRow, + const QModelIndex& sourceParent) const override; private: - class Impl; - std::unique_ptr p; + std::unique_ptr p; + + friend class AlertProxyModelImpl; }; -} // namespace scwx::qt::model +} // namespace model +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/model/imgui_context_model.cpp b/scwx-qt/source/scwx/qt/model/imgui_context_model.cpp index 33cbfe79..37ca523f 100644 --- a/scwx-qt/source/scwx/qt/model/imgui_context_model.cpp +++ b/scwx-qt/source/scwx/qt/model/imgui_context_model.cpp @@ -4,12 +4,11 @@ #include -// Expose required functions from internal API -void ImFontAtlasUpdateNewFrame(ImFontAtlas* atlas, - int frame_count, - bool renderer_has_textures); - -namespace scwx::qt::model +namespace scwx +{ +namespace qt +{ +namespace model { static const std::string logPrefix_ = "scwx::qt::model::imgui_context_model"; @@ -24,8 +23,6 @@ public: std::vector contexts_ {}; ImFontAtlas fontAtlas_ {}; - - int frameCount_ {0}; }; ImGuiContextModel::ImGuiContextModel() : @@ -138,14 +135,6 @@ void ImGuiContextModel::DestroyContext(const std::string& name) } } -void ImGuiContextModel::NewFrame() -{ - static constexpr bool kRendererHasTextures_ = true; - - ImFontAtlasUpdateNewFrame( - &p->fontAtlas_, ++p->frameCount_, kRendererHasTextures_); -} - std::vector ImGuiContextModel::contexts() const { return p->contexts_; @@ -164,4 +153,6 @@ ImGuiContextModel& ImGuiContextModel::Instance() bool ImGuiContextInfo::operator==(const ImGuiContextInfo& o) const = default; -} // namespace scwx::qt::model +} // namespace model +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/model/imgui_context_model.hpp b/scwx-qt/source/scwx/qt/model/imgui_context_model.hpp index 926501fc..894931c5 100644 --- a/scwx-qt/source/scwx/qt/model/imgui_context_model.hpp +++ b/scwx-qt/source/scwx/qt/model/imgui_context_model.hpp @@ -8,7 +8,11 @@ struct ImFontAtlas; struct ImGuiContext; -namespace scwx::qt::model +namespace scwx +{ +namespace qt +{ +namespace model { class ImGuiContextModelImpl; @@ -42,8 +46,6 @@ public: ImGuiContext* CreateContext(const std::string& name); void DestroyContext(const std::string& name); - void NewFrame(); - std::vector contexts() const; ImFontAtlas* font_atlas(); @@ -57,4 +59,6 @@ private: std::unique_ptr p; }; -} // namespace scwx::qt::model +} // namespace model +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/model/layer_model.cpp b/scwx-qt/source/scwx/qt/model/layer_model.cpp index 6be8eb9d..35f188a9 100644 --- a/scwx-qt/source/scwx/qt/model/layer_model.cpp +++ b/scwx-qt/source/scwx/qt/model/layer_model.cpp @@ -1,7 +1,7 @@ #include #include #include -#include +#include #include #include @@ -43,7 +43,6 @@ static const std::vector kDefaultLayers_ { types::InformationLayer::RadarSite, false, {false, false, false, false}}, - {types::LayerType::Information, types::InformationLayer::Markers, true}, {types::LayerType::Data, types::DataLayer::RadarRange, true}, {types::LayerType::Alert, awips::Phenomenon::Tornado, true}, {types::LayerType::Alert, awips::Phenomenon::SnowSquall, true}, @@ -67,6 +66,13 @@ static const std::vector kImmovableLayers_ { {types::LayerType::Map, types::MapLayer::MapUnderlay, false}, }; +static const std::array kAlertPhenomena_ { + awips::Phenomenon::Tornado, + awips::Phenomenon::SnowSquall, + awips::Phenomenon::SevereThunderstorm, + awips::Phenomenon::FlashFlood, + awips::Phenomenon::Marine}; + class LayerModel::Impl { public: @@ -96,8 +102,6 @@ public: manager::PlacefileManager::Instance()}; types::LayerVector layers_ {}; - - bool fileRead_ {false}; }; LayerModel::LayerModel(QObject* parent) : @@ -203,8 +207,6 @@ void LayerModel::Impl::ReadLayerSettings() // Assign read layers layers_.swap(newLayers); } - - fileRead_ = true; } void LayerModel::Impl::ValidateLayerSettings(types::LayerVector& layers) @@ -318,10 +320,6 @@ void LayerModel::Impl::ValidateLayerSettings(types::LayerVector& layers) void LayerModel::Impl::WriteLayerSettings() { - if (!fileRead_) - { - return; - } logger_->info("Saving layer settings"); auto layerJson = boost::json::value_from(layers_); @@ -782,13 +780,6 @@ bool LayerModel::dropMimeData(const QMimeData* data, QDataStream stream(&mimeData, QIODevice::ReadOnly); std::vector sourceRows {}; - // Validate parent row - if (parent.row() < 0 || parent.row() >= static_cast(p->layers_.size())) - { - logger_->warn("Cannot perform drop action, invalid parent row"); - return false; - } - // Read source rows from QMimeData while (!stream.atEnd()) { diff --git a/scwx-qt/source/scwx/qt/model/marker_model.cpp b/scwx-qt/source/scwx/qt/model/marker_model.cpp deleted file mode 100644 index 6c232177..00000000 --- a/scwx-qt/source/scwx/qt/model/marker_model.cpp +++ /dev/null @@ -1,288 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace scwx -{ -namespace qt -{ -namespace model -{ - -static const std::string logPrefix_ = "scwx::qt::model::marker_model"; -static const auto logger_ = scwx::util::Logger::Create(logPrefix_); -static const int iconSize_ = 30; - -static constexpr int kFirstColumn = - static_cast(MarkerModel::Column::Latitude); -static constexpr int kLastColumn = - static_cast(MarkerModel::Column::Name); -static constexpr int kNumColumns = kLastColumn - kFirstColumn + 1; - -class MarkerModel::Impl -{ -public: - explicit Impl() {} - ~Impl() = default; - std::shared_ptr markerManager_ { - manager::MarkerManager::Instance()}; - std::vector markerIds_; -}; - -MarkerModel::MarkerModel(QObject* parent) : - QAbstractTableModel(parent), p(std::make_unique()) -{ - connect(p->markerManager_.get(), - &manager::MarkerManager::MarkersInitialized, - this, - &MarkerModel::HandleMarkersInitialized); - - connect(p->markerManager_.get(), - &manager::MarkerManager::MarkerAdded, - this, - &MarkerModel::HandleMarkerAdded); - - connect(p->markerManager_.get(), - &manager::MarkerManager::MarkerChanged, - this, - &MarkerModel::HandleMarkerChanged); - - connect(p->markerManager_.get(), - &manager::MarkerManager::MarkerRemoved, - this, - &MarkerModel::HandleMarkerRemoved); -} - -MarkerModel::~MarkerModel() = default; - -int MarkerModel::rowCount(const QModelIndex& parent) const -{ - return parent.isValid() ? - 0 : - static_cast(p->markerIds_.size()); -} - -int MarkerModel::columnCount(const QModelIndex& parent) const -{ - return parent.isValid() ? 0 : kNumColumns; -} - -Qt::ItemFlags MarkerModel::flags(const QModelIndex& index) const -{ - Qt::ItemFlags flags = QAbstractTableModel::flags(index); - - return flags; -} - -QVariant MarkerModel::data(const QModelIndex& index, int role) const -{ - if (!index.isValid() || index.row() < 0 || - static_cast(index.row()) >= p->markerIds_.size()) - { - logger_->debug("Failed to get data index {}", index.row()); - return QVariant(); - } - - types::MarkerId id = p->markerIds_[index.row()]; - std::optional markerInfo = - p->markerManager_->get_marker(id); - if (!markerInfo) - { - logger_->debug("Failed to get data index {} id {}", index.row(), id); - return QVariant(); - } - - if (role == Qt::ItemDataRole::UserRole) - { - return qulonglong(id); - } - - switch(index.column()) - { - case static_cast(Column::Name): - if (role == Qt::ItemDataRole::DisplayRole || - role == Qt::ItemDataRole::ToolTipRole) - { - return QString::fromStdString(markerInfo->name); - } - break; - - case static_cast(Column::Latitude): - if (role == Qt::ItemDataRole::DisplayRole || - role == Qt::ItemDataRole::ToolTipRole) - { - return QString::fromStdString( - common::GetLatitudeString(markerInfo->latitude)); - } - break; - - case static_cast(Column::Longitude): - if (role == Qt::ItemDataRole::DisplayRole || - role == Qt::ItemDataRole::ToolTipRole) - { - return QString::fromStdString( - common::GetLongitudeString(markerInfo->longitude)); - } - break; - break; - case static_cast(Column::Icon): - if (role == Qt::ItemDataRole::DisplayRole) - { - std::optional icon = - p->markerManager_->get_icon(markerInfo->iconName); - if (icon) - { - return QString::fromStdString(icon->shortName); - } - else - { - return {}; - } - } - else if (role == Qt::ItemDataRole::DecorationRole) - { - std::optional icon = - p->markerManager_->get_icon(markerInfo->iconName); - if (icon) - { - return util::modulateColors(icon->qIcon, - QSize(iconSize_, iconSize_), - QColor(markerInfo->iconColor[0], - markerInfo->iconColor[1], - markerInfo->iconColor[2], - markerInfo->iconColor[3])); - } - else - { - return {}; - } - } - break; - - default: - break; - } - - return QVariant(); -} - -std::optional MarkerModel::getId(int index) -{ - if (index < 0 || static_cast(index) >= p->markerIds_.size()) - { - return {}; - } - - return p->markerIds_[index]; -} - -QVariant MarkerModel::headerData(int section, - Qt::Orientation orientation, - int role) const -{ - if (role == Qt::ItemDataRole::DisplayRole) - { - if (orientation == Qt::Horizontal) - { - switch (section) - { - case static_cast(Column::Name): - return tr("Name"); - - case static_cast(Column::Latitude): - return tr("Latitude"); - - case static_cast(Column::Longitude): - return tr("Longitude"); - - case static_cast(Column::Icon): - return tr("Icon"); - - default: - break; - } - } - } - - return QVariant(); -} - -bool MarkerModel::setData(const QModelIndex&, const QVariant&, int) -{ - return false; -} - -void MarkerModel::HandleMarkersInitialized(size_t count) -{ - if (count == 0) - { - return; - } - const int index = static_cast(count - 1); - - p->markerIds_.reserve(count); - beginInsertRows(QModelIndex(), 0, index); - p->markerManager_->for_each( - [this](const types::MarkerInfo& info) - { - p->markerIds_.push_back(info.id); - }); - endInsertRows(); -} - -void MarkerModel::HandleMarkerAdded(types::MarkerId id) -{ - std::optional index = p->markerManager_->get_index(id); - if (!index) - { - return; - } - const int newIndex = static_cast(*index); - - beginInsertRows(QModelIndex(), newIndex, newIndex); - auto it = std::next(p->markerIds_.begin(), newIndex); - p->markerIds_.emplace(it, id); - endInsertRows(); -} - -void MarkerModel::HandleMarkerChanged(types::MarkerId id) -{ - auto it = std::find(p->markerIds_.begin(), p->markerIds_.end(), id); - if (it == p->markerIds_.end()) - { - return; - } - const int changedIndex = std::distance(p->markerIds_.begin(), it); - - QModelIndex topLeft = createIndex(changedIndex, kFirstColumn); - QModelIndex bottomRight = createIndex(changedIndex, kLastColumn); - - Q_EMIT dataChanged(topLeft, bottomRight); -} - -void MarkerModel::HandleMarkerRemoved(types::MarkerId id) -{ - auto it = std::find(p->markerIds_.begin(), p->markerIds_.end(), id); - if (it == p->markerIds_.end()) - { - return; - } - - const int removedIndex = std::distance(p->markerIds_.begin(), it); - - beginRemoveRows(QModelIndex(), removedIndex, removedIndex); - p->markerIds_.erase(it); - endRemoveRows(); -} - -} // namespace model -} // namespace qt -} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/model/marker_model.hpp b/scwx-qt/source/scwx/qt/model/marker_model.hpp deleted file mode 100644 index 91c8854f..00000000 --- a/scwx-qt/source/scwx/qt/model/marker_model.hpp +++ /dev/null @@ -1,57 +0,0 @@ -#pragma once - -#include -#include - -namespace scwx -{ -namespace qt -{ -namespace model -{ - -class MarkerModel : public QAbstractTableModel -{ -public: - enum class Column : int - { - Latitude = 0, - Longitude = 1, - Icon = 2, - Name = 3, - }; - - explicit MarkerModel(QObject* parent = nullptr); - ~MarkerModel(); - - int rowCount(const QModelIndex& parent = QModelIndex()) const override; - int columnCount(const QModelIndex& parent = QModelIndex()) const override; - - Qt::ItemFlags flags(const QModelIndex& index) const override; - - QVariant data(const QModelIndex& index, - int role = Qt::DisplayRole) const override; - QVariant headerData(int section, - Qt::Orientation orientation, - int role = Qt::DisplayRole) const override; - - bool setData(const QModelIndex& index, - const QVariant& value, - int role = Qt::EditRole) override; - - std::optional getId(int index); - -public slots: - void HandleMarkersInitialized(size_t count); - void HandleMarkerAdded(types::MarkerId id); - void HandleMarkerChanged(types::MarkerId id); - void HandleMarkerRemoved(types::MarkerId id); - -private: - class Impl; - std::unique_ptr p; -}; - -} // namespace model -} // namespace qt -} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/model/radar_site_model.cpp b/scwx-qt/source/scwx/qt/model/radar_site_model.cpp index f131a1cd..482c9828 100644 --- a/scwx-qt/source/scwx/qt/model/radar_site_model.cpp +++ b/scwx-qt/source/scwx/qt/model/radar_site_model.cpp @@ -4,8 +4,8 @@ #include #include #include +#include #include -#include #include #include @@ -68,8 +68,6 @@ public: scwx::common::Coordinate previousPosition_; QIcon starIcon_ {":/res/icons/font-awesome-6/star-solid.svg"}; - - bool presetsRead_ {false}; }; RadarSiteModel::RadarSiteModel(QObject* parent) : @@ -117,7 +115,7 @@ void RadarSiteModelImpl::ReadPresets() // Determine if presets exists if (std::filesystem::exists(presetsPath_)) { - presetsJson = scwx::util::json::ReadJsonFile(presetsPath_); + presetsJson = util::json::ReadJsonFile(presetsPath_); } // If presets was successfully read @@ -148,19 +146,14 @@ void RadarSiteModelImpl::ReadPresets() } } } - presetsRead_ = true; } void RadarSiteModelImpl::WritePresets() { - if (!presetsRead_) - { - return; - } logger_->info("Saving presets"); auto presetsJson = boost::json::value_from(presets_); - scwx::util::json::WriteJsonFile(presetsPath_, presetsJson); + util::json::WriteJsonFile(presetsPath_, presetsJson); } int RadarSiteModel::rowCount(const QModelIndex& parent) const diff --git a/scwx-qt/source/scwx/qt/settings/alert_palette_settings.cpp b/scwx-qt/source/scwx/qt/settings/alert_palette_settings.cpp deleted file mode 100644 index 1c7aca31..00000000 --- a/scwx-qt/source/scwx/qt/settings/alert_palette_settings.cpp +++ /dev/null @@ -1,240 +0,0 @@ -#include -#include - -#include - -#include -#include -#include - -namespace scwx::qt::settings -{ - -static const std::string logPrefix_ = - "scwx::qt::settings::alert_palette_settings"; - -static const boost::gil::rgba8_pixel_t kColorBlack_ {0, 0, 0, 255}; - -struct LineData -{ - boost::gil::rgba8_pixel_t borderColor_ {kColorBlack_}; - boost::gil::rgba8_pixel_t highlightColor_ {kColorBlack_}; - boost::gil::rgba8_pixel_t lineColor_; - std::int64_t borderWidth_ {1}; - std::int64_t highlightWidth_ {0}; - std::int64_t lineWidth_ {3}; -}; - -typedef boost::unordered_flat_map - ThreatCategoryPalette; - -static const boost::unordered_flat_map - kThreatCategoryPalettes_ // - {{awips::Phenomenon::Marine, - {{awips::ibw::ThreatCategory::Base, {.lineColor_ {255, 127, 0, 255}}}}}, - {awips::Phenomenon::FlashFlood, - {{awips::ibw::ThreatCategory::Base, {.lineColor_ {0, 255, 0, 255}}}, - {awips::ibw::ThreatCategory::Considerable, - {.highlightColor_ {0, 255, 0, 255}, - .lineColor_ {kColorBlack_}, - .highlightWidth_ = 1, - .lineWidth_ = 1}}, - {awips::ibw::ThreatCategory::Catastrophic, - {.highlightColor_ {0, 255, 0, 255}, - .lineColor_ {255, 0, 0, 255}, - .highlightWidth_ = 1, - .lineWidth_ = 1}}}}, - {awips::Phenomenon::SevereThunderstorm, - {{awips::ibw::ThreatCategory::Base, {.lineColor_ {255, 255, 0, 255}}}, - {awips::ibw::ThreatCategory::Considerable, - {.highlightColor_ {255, 255, 0, 255}, - .lineColor_ {255, 0, 0, 255}, - .highlightWidth_ = 1, - .lineWidth_ = 1}}, - {awips::ibw::ThreatCategory::Destructive, - {.highlightColor_ {255, 255, 0, 255}, - .lineColor_ {255, 0, 0, 255}, - .highlightWidth_ = 1, - .lineWidth_ = 2}}}}, - {awips::Phenomenon::SnowSquall, - {{awips::ibw::ThreatCategory::Base, {.lineColor_ {0, 255, 255, 255}}}}}, - {awips::Phenomenon::Tornado, - {{awips::ibw::ThreatCategory::Base, {.lineColor_ {255, 0, 0, 255}}}, - {awips::ibw::ThreatCategory::Considerable, - {.lineColor_ {255, 0, 255, 255}}}, - {awips::ibw::ThreatCategory::Catastrophic, - {.highlightColor_ {255, 0, 255, 255}, - .lineColor_ {kColorBlack_}, - .highlightWidth_ = 1, - .lineWidth_ = 1}}}}}; - -static const boost::unordered_flat_map - kObservedPalettes_ // - {{awips::Phenomenon::Tornado, - {.highlightColor_ {255, 0, 0, 255}, - .lineColor_ {kColorBlack_}, - .highlightWidth_ = 1, - .lineWidth_ = 1}}}; - -static const boost::unordered_flat_map - kTornadoPossiblePalettes_ // - {{awips::Phenomenon::Marine, - {.highlightColor_ {255, 127, 0, 255}, - .lineColor_ {kColorBlack_}, - .highlightWidth_ = 1, - .lineWidth_ = 1}}, - {awips::Phenomenon::SevereThunderstorm, - {.highlightColor_ {255, 255, 0, 255}, - .lineColor_ {kColorBlack_}, - .highlightWidth_ = 1, - .lineWidth_ = 1}}}; - -static const boost::unordered_flat_map - kInactivePalettes_ // - { - {awips::Phenomenon::Marine, {.lineColor_ {127, 63, 0, 255}}}, - {awips::Phenomenon::FlashFlood, {.lineColor_ {0, 127, 0, 255}}}, - {awips::Phenomenon::SevereThunderstorm, {.lineColor_ {127, 127, 0, 255}}}, - {awips::Phenomenon::SnowSquall, {.lineColor_ {0, 127, 127, 255}}}, - {awips::Phenomenon::Tornado, {.lineColor_ {127, 0, 0, 255}}}, - }; - -class AlertPaletteSettings::Impl -{ -public: - explicit Impl(awips::Phenomenon phenomenon) : phenomenon_ {phenomenon} - { - const auto& info = awips::ibw::GetImpactBasedWarningInfo(phenomenon); - - const auto& threatCategoryPalettes = - kThreatCategoryPalettes_.at(phenomenon); - - for (auto& threatCategory : info.threatCategories_) - { - std::string threatCategoryName = - awips::ibw::GetThreatCategoryName(threatCategory); - boost::algorithm::to_lower(threatCategoryName); - auto result = - threatCategoryMap_.emplace(threatCategory, threatCategoryName); - auto& lineSettings = result.first->second; - - SetDefaultLineData(lineSettings, - threatCategoryPalettes.at(threatCategory)); - } - - if (info.hasObservedTag_) - { - SetDefaultLineData(observed_, kObservedPalettes_.at(phenomenon)); - } - - if (info.hasTornadoPossibleTag_) - { - SetDefaultLineData(tornadoPossible_, - kTornadoPossiblePalettes_.at(phenomenon)); - } - - SetDefaultLineData(inactive_, kInactivePalettes_.at(phenomenon)); - } - - ~Impl() = default; - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; - - static void SetDefaultLineData(LineSettings& lineSettings, - const LineData& lineData); - - awips::Phenomenon phenomenon_; - - std::map threatCategoryMap_ {}; - - LineSettings observed_ {"observed"}; - LineSettings tornadoPossible_ {"tornado_possible"}; - LineSettings inactive_ {"inactive"}; -}; - -AlertPaletteSettings::AlertPaletteSettings(awips::Phenomenon phenomenon) : - SettingsCategory(awips::GetPhenomenonCode(phenomenon)), - p(std::make_unique(phenomenon)) -{ - auto& info = awips::ibw::GetImpactBasedWarningInfo(p->phenomenon_); - for (auto& threatCategory : p->threatCategoryMap_) - { - RegisterSubcategory(threatCategory.second); - } - - if (info.hasObservedTag_) - { - RegisterSubcategory(p->observed_); - } - - if (info.hasTornadoPossibleTag_) - { - RegisterSubcategory(p->tornadoPossible_); - } - - RegisterSubcategory(p->inactive_); - - SetDefaults(); -} - -AlertPaletteSettings::~AlertPaletteSettings() = default; - -AlertPaletteSettings::AlertPaletteSettings(AlertPaletteSettings&&) noexcept = - default; -AlertPaletteSettings& -AlertPaletteSettings::operator=(AlertPaletteSettings&&) noexcept = default; - -LineSettings& AlertPaletteSettings::threat_category( - awips::ibw::ThreatCategory threatCategory) const -{ - auto it = p->threatCategoryMap_.find(threatCategory); - if (it != p->threatCategoryMap_.cend()) - { - return it->second; - } - return p->threatCategoryMap_.at(awips::ibw::ThreatCategory::Base); -} - -LineSettings& AlertPaletteSettings::inactive() const -{ - return p->inactive_; -} - -LineSettings& AlertPaletteSettings::observed() const -{ - return p->observed_; -} - -LineSettings& AlertPaletteSettings::tornado_possible() const -{ - return p->tornadoPossible_; -} - -void AlertPaletteSettings::Impl::SetDefaultLineData(LineSettings& lineSettings, - const LineData& lineData) -{ - lineSettings.border_color().SetDefault( - util::color::ToArgbString(lineData.borderColor_)); - lineSettings.highlight_color().SetDefault( - util::color::ToArgbString(lineData.highlightColor_)); - lineSettings.line_color().SetDefault( - util::color::ToArgbString(lineData.lineColor_)); - - lineSettings.border_width().SetDefault(lineData.borderWidth_); - lineSettings.highlight_width().SetDefault(lineData.highlightWidth_); - lineSettings.line_width().SetDefault(lineData.lineWidth_); -} - -bool operator==(const AlertPaletteSettings& lhs, - const AlertPaletteSettings& rhs) -{ - return (lhs.p->phenomenon_ == rhs.p->phenomenon_ && - lhs.p->threatCategoryMap_ == rhs.p->threatCategoryMap_ && - lhs.p->inactive_ == rhs.p->inactive_ && - lhs.p->observed_ == rhs.p->observed_ && - lhs.p->tornadoPossible_ == rhs.p->tornadoPossible_); -} - -} // namespace scwx::qt::settings diff --git a/scwx-qt/source/scwx/qt/settings/alert_palette_settings.hpp b/scwx-qt/source/scwx/qt/settings/alert_palette_settings.hpp deleted file mode 100644 index c4a12e58..00000000 --- a/scwx-qt/source/scwx/qt/settings/alert_palette_settings.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -#include -#include - -namespace scwx::qt::settings -{ - -class AlertPaletteSettings : public SettingsCategory -{ -public: - explicit AlertPaletteSettings(awips::Phenomenon phenomenon); - ~AlertPaletteSettings() override; - - AlertPaletteSettings(const AlertPaletteSettings&) = delete; - AlertPaletteSettings& operator=(const AlertPaletteSettings&) = delete; - - AlertPaletteSettings(AlertPaletteSettings&&) noexcept; - AlertPaletteSettings& operator=(AlertPaletteSettings&&) noexcept; - - [[nodiscard]] LineSettings& - threat_category(awips::ibw::ThreatCategory threatCategory) const; - [[nodiscard]] LineSettings& inactive() const; - [[nodiscard]] LineSettings& observed() const; - [[nodiscard]] LineSettings& tornado_possible() const; - - friend bool operator==(const AlertPaletteSettings& lhs, - const AlertPaletteSettings& rhs); - -private: - class Impl; - std::unique_ptr p; -}; - -} // namespace scwx::qt::settings diff --git a/scwx-qt/source/scwx/qt/settings/audio_settings.cpp b/scwx-qt/source/scwx/qt/settings/audio_settings.cpp index c4b07ff8..a799793b 100644 --- a/scwx-qt/source/scwx/qt/settings/audio_settings.cpp +++ b/scwx-qt/source/scwx/qt/settings/audio_settings.cpp @@ -9,7 +9,11 @@ #include #include -namespace scwx::qt::settings +namespace scwx +{ +namespace qt +{ +namespace settings { static const std::string logPrefix_ = "scwx::qt::settings::audio_settings"; @@ -29,8 +33,6 @@ public: boost::to_lower(defaultAlertLocationMethodValue); - // SetDefault, SetMinimum and SetMaximum are descriptive - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) alertSoundFile_.SetDefault(defaultAlertSoundFileValue); alertLocationMethod_.SetDefault(defaultAlertLocationMethodValue); alertLatitude_.SetDefault(0.0); @@ -46,7 +48,7 @@ public: alertLongitude_.SetMaximum(180.0); alertRadius_.SetMinimum(0.0); alertRadius_.SetMaximum(9999999999); - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) + alertLocationMethod_.SetValidator( SCWX_SETTINGS_ENUM_VALIDATOR(types::LocationMethod, @@ -92,11 +94,7 @@ public: SettingsVariable {"alert_disabled"}); } - ~Impl() = default; - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; + ~Impl() {} SettingsVariable alertSoundFile_ {"alert_sound_file"}; SettingsVariable alertLocationMethod_ {"alert_location_method"}; @@ -210,4 +208,6 @@ bool operator==(const AudioSettings& lhs, const AudioSettings& rhs) lhs.p->alertEnabled_ == rhs.p->alertEnabled_); } -} // namespace scwx::qt::settings +} // namespace settings +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/settings/audio_settings.hpp b/scwx-qt/source/scwx/qt/settings/audio_settings.hpp index 50606001..579d3599 100644 --- a/scwx-qt/source/scwx/qt/settings/audio_settings.hpp +++ b/scwx-qt/source/scwx/qt/settings/audio_settings.hpp @@ -7,14 +7,18 @@ #include #include -namespace scwx::qt::settings +namespace scwx +{ +namespace qt +{ +namespace settings { class AudioSettings : public SettingsCategory { public: explicit AudioSettings(); - ~AudioSettings() override; + ~AudioSettings(); AudioSettings(const AudioSettings&) = delete; AudioSettings& operator=(const AudioSettings&) = delete; @@ -22,17 +26,16 @@ public: AudioSettings(AudioSettings&&) noexcept; AudioSettings& operator=(AudioSettings&&) noexcept; - [[nodiscard]] SettingsVariable& alert_sound_file() const; - [[nodiscard]] SettingsVariable& alert_location_method() const; - [[nodiscard]] SettingsVariable& alert_latitude() const; - [[nodiscard]] SettingsVariable& alert_longitude() const; - [[nodiscard]] SettingsVariable& alert_radius() const; - [[nodiscard]] SettingsVariable& alert_radar_site() const; - [[nodiscard]] SettingsVariable& alert_county() const; - [[nodiscard]] SettingsVariable& alert_wfo() const; - [[nodiscard]] SettingsVariable& - alert_enabled(awips::Phenomenon phenomenon) const; - [[nodiscard]] SettingsVariable& ignore_missing_codecs() const; + SettingsVariable& alert_sound_file() const; + SettingsVariable& alert_location_method() const; + SettingsVariable& alert_latitude() const; + SettingsVariable& alert_longitude() const; + SettingsVariable& alert_radius() const; + SettingsVariable& alert_radar_site() const; + SettingsVariable& alert_county() const; + SettingsVariable& alert_wfo() const; + SettingsVariable& alert_enabled(awips::Phenomenon phenomenon) const; + SettingsVariable& ignore_missing_codecs() const; static AudioSettings& Instance(); @@ -43,4 +46,6 @@ private: std::unique_ptr p; }; -} // namespace scwx::qt::settings +} // namespace settings +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/settings/general_settings.cpp b/scwx-qt/source/scwx/qt/settings/general_settings.cpp index 86ac3d6d..fe3982e2 100644 --- a/scwx-qt/source/scwx/qt/settings/general_settings.cpp +++ b/scwx-qt/source/scwx/qt/settings/general_settings.cpp @@ -8,10 +8,16 @@ #include #include +#include + #include #include -namespace scwx::qt::settings +namespace scwx +{ +namespace qt +{ +namespace settings { static const std::string logPrefix_ = "scwx::qt::settings::general_settings"; @@ -44,10 +50,7 @@ public: boost::to_lower(defaultPositioningPlugin); boost::to_lower(defaultThemeValue); - // SetDefault, SetMinimum, and SetMaximum are descriptive - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) antiAliasingEnabled_.SetDefault(true); - centerOnRadarSelection_.SetDefault(false); clockFormat_.SetDefault(defaultClockFormatValue); customStyleDrawLayer_.SetDefault(".*\\.annotations\\.points"); debugEnabled_.SetDefault(false); @@ -66,22 +69,14 @@ public: nmeaBaudRate_.SetDefault(9600); nmeaSource_.SetDefault(""); positioningPlugin_.SetDefault(defaultPositioningPlugin); - processModuleWarningsEnabled_.SetDefault(true); showMapAttribution_.SetDefault(true); showMapCenter_.SetDefault(false); showMapLogo_.SetDefault(true); theme_.SetDefault(defaultThemeValue); - themeFile_.SetDefault(""); trackLocation_.SetDefault(false); updateNotificationsEnabled_.SetDefault(true); warningsProvider_.SetDefault(defaultWarningsProviderValue); - cursorIconAlwaysOn_.SetDefault(false); - radarSiteThreshold_.SetDefault(0.0); - highPrivilegeWarningEnabled_.SetDefault(true); - cursorIconScale_.SetDefault(1.0); - cursorIconScale_.SetMinimum(1.0); - cursorIconScale_.SetMaximum(5.0); fontSizes_.SetElementMinimum(1); fontSizes_.SetElementMaximum(72); fontSizes_.SetValidator([](const std::vector& value) @@ -95,12 +90,9 @@ public: loopSpeed_.SetMinimum(1.0); loopSpeed_.SetMaximum(99.99); loopTime_.SetMinimum(1); - loopTime_.SetMaximum(2880); + loopTime_.SetMaximum(1440); nmeaBaudRate_.SetMinimum(1); nmeaBaudRate_.SetMaximum(999999999); - radarSiteThreshold_.SetMinimum(-10000); - radarSiteThreshold_.SetMaximum(10000); - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) customStyleDrawLayer_.SetTransform([](const std::string& value) { return boost::trim_copy(value); }); @@ -111,10 +103,6 @@ public: SCWX_SETTINGS_ENUM_VALIDATOR(scwx::util::ClockFormat, scwx::util::ClockFormatIterator(), scwx::util::GetClockFormatName)); - - customStyleUrl_.SetValidator( - [](const std::string& value) - { return value.find("key=") == std::string::npos; }); customStyleDrawLayer_.SetValidator([](const std::string& value) { return !value.empty(); }); defaultAlertAction_.SetValidator( @@ -146,14 +134,9 @@ public: { return QUrl {QString::fromStdString(value)}.isValid(); }); } - ~Impl() = default; - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; + ~Impl() {} - SettingsVariable antiAliasingEnabled_ {"anti_aliasing_enabled"}; - SettingsVariable centerOnRadarSelection_ {"center_on_radar_selection"}; + SettingsVariable antiAliasingEnabled_ {"anti_aliasing_enabled"}; SettingsVariable clockFormat_ {"clock_format"}; SettingsVariable customStyleDrawLayer_ { "custom_style_draw_layer"}; @@ -174,28 +157,19 @@ public: SettingsVariable nmeaBaudRate_ {"nmea_baud_rate"}; SettingsVariable nmeaSource_ {"nmea_source"}; SettingsVariable positioningPlugin_ {"positioning_plugin"}; - SettingsVariable processModuleWarningsEnabled_ { - "process_module_warnings_enabled"}; - SettingsVariable showMapAttribution_ {"show_map_attribution"}; - SettingsVariable showMapCenter_ {"show_map_center"}; - SettingsVariable showMapLogo_ {"show_map_logo"}; - SettingsVariable theme_ {"theme"}; - SettingsVariable themeFile_ {"theme_file"}; - SettingsVariable trackLocation_ {"track_location"}; + SettingsVariable showMapAttribution_ {"show_map_attribution"}; + SettingsVariable showMapCenter_ {"show_map_center"}; + SettingsVariable showMapLogo_ {"show_map_logo"}; + SettingsVariable theme_ {"theme"}; + SettingsVariable trackLocation_ {"track_location"}; SettingsVariable updateNotificationsEnabled_ {"update_notifications"}; SettingsVariable warningsProvider_ {"warnings_provider"}; - SettingsVariable cursorIconAlwaysOn_ {"cursor_icon_always_on"}; - SettingsVariable radarSiteThreshold_ {"radar_site_threshold"}; - SettingsVariable highPrivilegeWarningEnabled_ { - "high_privilege_warning_enabled"}; - SettingsVariable cursorIconScale_ {"cursor_icon_scale"}; }; GeneralSettings::GeneralSettings() : SettingsCategory("general"), p(std::make_unique()) { RegisterVariables({&p->antiAliasingEnabled_, - &p->centerOnRadarSelection_, &p->clockFormat_, &p->customStyleDrawLayer_, &p->customStyleUrl_, @@ -215,19 +189,13 @@ GeneralSettings::GeneralSettings() : &p->nmeaBaudRate_, &p->nmeaSource_, &p->positioningPlugin_, - &p->processModuleWarningsEnabled_, &p->showMapAttribution_, &p->showMapCenter_, &p->showMapLogo_, &p->theme_, - &p->themeFile_, &p->trackLocation_, &p->updateNotificationsEnabled_, - &p->warningsProvider_, - &p->cursorIconAlwaysOn_, - &p->radarSiteThreshold_, - &p->highPrivilegeWarningEnabled_, - &p->cursorIconScale_}); + &p->warningsProvider_}); SetDefaults(); } GeneralSettings::~GeneralSettings() = default; @@ -241,11 +209,6 @@ SettingsVariable& GeneralSettings::anti_aliasing_enabled() const return p->antiAliasingEnabled_; } -SettingsVariable& GeneralSettings::center_on_radar_selection() const -{ - return p->centerOnRadarSelection_; -} - SettingsVariable& GeneralSettings::clock_format() const { return p->clockFormat_; @@ -342,11 +305,6 @@ SettingsVariable& GeneralSettings::positioning_plugin() const return p->positioningPlugin_; } -SettingsVariable& GeneralSettings::process_module_warnings_enabled() const -{ - return p->processModuleWarningsEnabled_; -} - SettingsVariable& GeneralSettings::show_map_attribution() const { return p->showMapAttribution_; @@ -367,11 +325,6 @@ SettingsVariable& GeneralSettings::theme() const return p->theme_; } -SettingsVariable& GeneralSettings::theme_file() const -{ - return p->themeFile_; -} - SettingsVariable& GeneralSettings::track_location() const { return p->trackLocation_; @@ -387,26 +340,6 @@ SettingsVariable& GeneralSettings::warnings_provider() const return p->warningsProvider_; } -SettingsVariable& GeneralSettings::cursor_icon_always_on() const -{ - return p->cursorIconAlwaysOn_; -} - -SettingsVariable& GeneralSettings::radar_site_threshold() const -{ - return p->radarSiteThreshold_; -} - -SettingsVariable& GeneralSettings::high_privilege_warning_enabled() const -{ - return p->highPrivilegeWarningEnabled_; -} - -SettingsVariable& GeneralSettings::cursor_icon_scale() const -{ - return p->cursorIconScale_; -} - bool GeneralSettings::Shutdown() { bool dataChanged = false; @@ -415,9 +348,7 @@ bool GeneralSettings::Shutdown() dataChanged |= p->loopDelay_.Commit(); dataChanged |= p->loopSpeed_.Commit(); dataChanged |= p->loopTime_.Commit(); - dataChanged |= p->processModuleWarningsEnabled_.Commit(); dataChanged |= p->trackLocation_.Commit(); - dataChanged |= p->highPrivilegeWarningEnabled_.Commit(); return dataChanged; } @@ -431,7 +362,6 @@ GeneralSettings& GeneralSettings::Instance() bool operator==(const GeneralSettings& lhs, const GeneralSettings& rhs) { return (lhs.p->antiAliasingEnabled_ == rhs.p->antiAliasingEnabled_ && - lhs.p->centerOnRadarSelection_ == rhs.p->centerOnRadarSelection_ && lhs.p->clockFormat_ == rhs.p->clockFormat_ && lhs.p->customStyleDrawLayer_ == rhs.p->customStyleDrawLayer_ && lhs.p->customStyleUrl_ == rhs.p->customStyleUrl_ && @@ -451,22 +381,16 @@ bool operator==(const GeneralSettings& lhs, const GeneralSettings& rhs) lhs.p->nmeaBaudRate_ == rhs.p->nmeaBaudRate_ && lhs.p->nmeaSource_ == rhs.p->nmeaSource_ && lhs.p->positioningPlugin_ == rhs.p->positioningPlugin_ && - lhs.p->processModuleWarningsEnabled_ == - rhs.p->processModuleWarningsEnabled_ && lhs.p->showMapAttribution_ == rhs.p->showMapAttribution_ && lhs.p->showMapCenter_ == rhs.p->showMapCenter_ && lhs.p->showMapLogo_ == rhs.p->showMapLogo_ && lhs.p->theme_ == rhs.p->theme_ && - lhs.p->themeFile_ == rhs.p->themeFile_ && lhs.p->trackLocation_ == rhs.p->trackLocation_ && lhs.p->updateNotificationsEnabled_ == rhs.p->updateNotificationsEnabled_ && - lhs.p->warningsProvider_ == rhs.p->warningsProvider_ && - lhs.p->cursorIconAlwaysOn_ == rhs.p->cursorIconAlwaysOn_ && - lhs.p->radarSiteThreshold_ == rhs.p->radarSiteThreshold_ && - lhs.p->highPrivilegeWarningEnabled_ == - rhs.p->highPrivilegeWarningEnabled_ && - lhs.p->cursorIconScale_ == rhs.p->cursorIconScale_); + lhs.p->warningsProvider_ == rhs.p->warningsProvider_); } -} // namespace scwx::qt::settings +} // namespace settings +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/settings/general_settings.hpp b/scwx-qt/source/scwx/qt/settings/general_settings.hpp index 59f29275..2628aef1 100644 --- a/scwx-qt/source/scwx/qt/settings/general_settings.hpp +++ b/scwx-qt/source/scwx/qt/settings/general_settings.hpp @@ -6,14 +6,18 @@ #include #include -namespace scwx::qt::settings +namespace scwx +{ +namespace qt +{ +namespace settings { class GeneralSettings : public SettingsCategory { public: explicit GeneralSettings(); - ~GeneralSettings() override; + ~GeneralSettings(); GeneralSettings(const GeneralSettings&) = delete; GeneralSettings& operator=(const GeneralSettings&) = delete; @@ -21,42 +25,33 @@ public: GeneralSettings(GeneralSettings&&) noexcept; GeneralSettings& operator=(GeneralSettings&&) noexcept; - [[nodiscard]] SettingsVariable& anti_aliasing_enabled() const; - [[nodiscard]] SettingsVariable& center_on_radar_selection() const; - [[nodiscard]] SettingsVariable& clock_format() const; - [[nodiscard]] SettingsVariable& custom_style_draw_layer() const; - [[nodiscard]] SettingsVariable& custom_style_url() const; - [[nodiscard]] SettingsVariable& debug_enabled() const; - [[nodiscard]] SettingsVariable& default_alert_action() const; - [[nodiscard]] SettingsVariable& default_radar_site() const; - [[nodiscard]] SettingsVariable& default_time_zone() const; - [[nodiscard]] SettingsContainer>& - font_sizes() const; - [[nodiscard]] SettingsVariable& grid_height() const; - [[nodiscard]] SettingsVariable& grid_width() const; - [[nodiscard]] SettingsVariable& loop_delay() const; - [[nodiscard]] SettingsVariable& loop_speed() const; - [[nodiscard]] SettingsVariable& loop_time() const; - [[nodiscard]] SettingsVariable& map_provider() const; - [[nodiscard]] SettingsVariable& mapbox_api_key() const; - [[nodiscard]] SettingsVariable& maptiler_api_key() const; - [[nodiscard]] SettingsVariable& nmea_baud_rate() const; - [[nodiscard]] SettingsVariable& nmea_source() const; - [[nodiscard]] SettingsVariable& positioning_plugin() const; - [[nodiscard]] SettingsVariable& - process_module_warnings_enabled() const; - [[nodiscard]] SettingsVariable& show_map_attribution() const; - [[nodiscard]] SettingsVariable& show_map_center() const; - [[nodiscard]] SettingsVariable& show_map_logo() const; - [[nodiscard]] SettingsVariable& theme() const; - [[nodiscard]] SettingsVariable& theme_file() const; - [[nodiscard]] SettingsVariable& track_location() const; - [[nodiscard]] SettingsVariable& update_notifications_enabled() const; - [[nodiscard]] SettingsVariable& warnings_provider() const; - [[nodiscard]] SettingsVariable& cursor_icon_always_on() const; - [[nodiscard]] SettingsVariable& radar_site_threshold() const; - [[nodiscard]] SettingsVariable& high_privilege_warning_enabled() const; - [[nodiscard]] SettingsVariable& cursor_icon_scale() const; + SettingsVariable& anti_aliasing_enabled() const; + SettingsVariable& clock_format() const; + SettingsVariable& custom_style_draw_layer() const; + SettingsVariable& custom_style_url() const; + SettingsVariable& debug_enabled() const; + SettingsVariable& default_alert_action() const; + SettingsVariable& default_radar_site() const; + SettingsVariable& default_time_zone() const; + SettingsContainer>& font_sizes() const; + SettingsVariable& grid_height() const; + SettingsVariable& grid_width() const; + SettingsVariable& loop_delay() const; + SettingsVariable& loop_speed() const; + SettingsVariable& loop_time() const; + SettingsVariable& map_provider() const; + SettingsVariable& mapbox_api_key() const; + SettingsVariable& maptiler_api_key() const; + SettingsVariable& nmea_baud_rate() const; + SettingsVariable& nmea_source() const; + SettingsVariable& positioning_plugin() const; + SettingsVariable& show_map_attribution() const; + SettingsVariable& show_map_center() const; + SettingsVariable& show_map_logo() const; + SettingsVariable& theme() const; + SettingsVariable& track_location() const; + SettingsVariable& update_notifications_enabled() const; + SettingsVariable& warnings_provider() const; static GeneralSettings& Instance(); @@ -70,4 +65,6 @@ private: std::unique_ptr p; }; -} // namespace scwx::qt::settings +} // namespace settings +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/settings/hotkey_settings.cpp b/scwx-qt/source/scwx/qt/settings/hotkey_settings.cpp index 39f21379..0edaf840 100644 --- a/scwx-qt/source/scwx/qt/settings/hotkey_settings.cpp +++ b/scwx-qt/source/scwx/qt/settings/hotkey_settings.cpp @@ -2,13 +2,16 @@ #include -namespace scwx::qt::settings +namespace scwx +{ +namespace qt +{ +namespace settings { static const std::string logPrefix_ = "scwx::qt::settings::hotkey_settings"; static const std::unordered_map kDefaultHotkeys_ { - {types::Hotkey::AddLocationMarker, QKeySequence {Qt::Key::Key_M}}, {types::Hotkey::ChangeMapStyle, QKeySequence {Qt::Key::Key_Z}}, {types::Hotkey::CopyCursorCoordinates, QKeySequence {QKeyCombination {Qt::KeyboardModifier::ControlModifier, @@ -25,12 +28,6 @@ static const std::unordered_map kDefaultHotkeys_ { {types::Hotkey::MapRotateCounterclockwise, QKeySequence {Qt::Key::Key_Q}}, {types::Hotkey::MapZoomIn, QKeySequence {Qt::Key::Key_Equal}}, {types::Hotkey::MapZoomOut, QKeySequence {Qt::Key::Key_Minus}}, - {types::Hotkey::ProductCategoryNext, - QKeySequence {QKeyCombination {Qt::KeyboardModifier::ControlModifier, - Qt::Key::Key_BracketRight}}}, - {types::Hotkey::ProductCategoryPrevious, - QKeySequence {QKeyCombination {Qt::KeyboardModifier::ControlModifier, - Qt::Key::Key_BracketLeft}}}, {types::Hotkey::ProductTiltDecrease, QKeySequence {Qt::Key::Key_BracketLeft}}, {types::Hotkey::ProductTiltIncrease, @@ -96,11 +93,7 @@ public: SettingsVariable {"?"}); } - ~Impl() = default; - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; + ~Impl() {} std::unordered_map> hotkey_ {}; std::vector variables_ {}; @@ -148,4 +141,6 @@ static bool IsHotkeyValid(const std::string& value) .toStdString() == value; } -} // namespace scwx::qt::settings +} // namespace settings +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/settings/hotkey_settings.hpp b/scwx-qt/source/scwx/qt/settings/hotkey_settings.hpp index 13e56b7d..9fa56cc4 100644 --- a/scwx-qt/source/scwx/qt/settings/hotkey_settings.hpp +++ b/scwx-qt/source/scwx/qt/settings/hotkey_settings.hpp @@ -7,14 +7,18 @@ #include #include -namespace scwx::qt::settings +namespace scwx +{ +namespace qt +{ +namespace settings { class HotkeySettings : public SettingsCategory { public: explicit HotkeySettings(); - ~HotkeySettings() override; + ~HotkeySettings(); HotkeySettings(const HotkeySettings&) = delete; HotkeySettings& operator=(const HotkeySettings&) = delete; @@ -22,8 +26,7 @@ public: HotkeySettings(HotkeySettings&&) noexcept; HotkeySettings& operator=(HotkeySettings&&) noexcept; - [[nodiscard]] SettingsVariable& - hotkey(scwx::qt::types::Hotkey hotkey) const; + SettingsVariable& hotkey(scwx::qt::types::Hotkey hotkey) const; static HotkeySettings& Instance(); @@ -34,4 +37,6 @@ private: std::unique_ptr p; }; -} // namespace scwx::qt::settings +} // namespace settings +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/settings/line_settings.cpp b/scwx-qt/source/scwx/qt/settings/line_settings.cpp deleted file mode 100644 index 2b013105..00000000 --- a/scwx-qt/source/scwx/qt/settings/line_settings.cpp +++ /dev/null @@ -1,157 +0,0 @@ -#include -#include - -namespace scwx::qt::settings -{ - -static const std::string logPrefix_ = "scwx::qt::settings::line_settings"; - -static const boost::gil::rgba8_pixel_t kTransparentColor_ {0, 0, 0, 0}; -static const std::string kTransparentColorString_ { - util::color::ToArgbString(kTransparentColor_)}; - -static const boost::gil::rgba8_pixel_t kBlackColor_ {0, 0, 0, 255}; -static const std::string kBlackColorString_ { - util::color::ToArgbString(kBlackColor_)}; - -static const boost::gil::rgba8_pixel_t kWhiteColor_ {255, 255, 255, 255}; -static const std::string kWhiteColorString_ { - util::color::ToArgbString(kWhiteColor_)}; - -class LineSettings::Impl -{ -public: - explicit Impl() - { - // SetDefault, SetMinimum, and SetMaximum are descriptive - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) - lineColor_.SetDefault(kWhiteColorString_); - highlightColor_.SetDefault(kTransparentColorString_); - borderColor_.SetDefault(kBlackColorString_); - - lineWidth_.SetDefault(3); - highlightWidth_.SetDefault(0); - borderWidth_.SetDefault(1); - - lineWidth_.SetMinimum(1); - highlightWidth_.SetMinimum(0); - borderWidth_.SetMinimum(0); - - lineWidth_.SetMaximum(9); - highlightWidth_.SetMaximum(9); - borderWidth_.SetMaximum(9); - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - - lineColor_.SetValidator(&util::color::ValidateArgbString); - highlightColor_.SetValidator(&util::color::ValidateArgbString); - borderColor_.SetValidator(&util::color::ValidateArgbString); - } - - ~Impl() = default; - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; - - SettingsVariable lineColor_ {"line_color"}; - SettingsVariable highlightColor_ {"highlight_color"}; - SettingsVariable borderColor_ {"border_color"}; - - SettingsVariable lineWidth_ {"line_width"}; - SettingsVariable highlightWidth_ {"highlight_width"}; - SettingsVariable borderWidth_ {"border_width"}; -}; - -LineSettings::LineSettings(const std::string& name) : - SettingsCategory(name), p(std::make_unique()) -{ - RegisterVariables({&p->lineColor_, - &p->highlightColor_, - &p->borderColor_, - &p->lineWidth_, - &p->highlightWidth_, - &p->borderWidth_}); - SetDefaults(); -} -LineSettings::~LineSettings() = default; - -LineSettings::LineSettings(LineSettings&&) noexcept = default; -LineSettings& LineSettings::operator=(LineSettings&&) noexcept = default; - -SettingsVariable& LineSettings::border_color() const -{ - return p->borderColor_; -} - -SettingsVariable& LineSettings::highlight_color() const -{ - return p->highlightColor_; -} - -SettingsVariable& LineSettings::line_color() const -{ - return p->lineColor_; -} - -SettingsVariable& LineSettings::border_width() const -{ - return p->borderWidth_; -} - -SettingsVariable& LineSettings::highlight_width() const -{ - return p->highlightWidth_; -} - -SettingsVariable& LineSettings::line_width() const -{ - return p->lineWidth_; -} - -boost::gil::rgba32f_pixel_t LineSettings::GetBorderColorRgba32f() const -{ - return util::color::ToRgba32fPixelT(p->borderColor_.GetValue()); -} - -boost::gil::rgba32f_pixel_t LineSettings::GetHighlightColorRgba32f() const -{ - return util::color::ToRgba32fPixelT(p->highlightColor_.GetValue()); -} - -boost::gil::rgba32f_pixel_t LineSettings::GetLineColorRgba32f() const -{ - return util::color::ToRgba32fPixelT(p->lineColor_.GetValue()); -} - -void LineSettings::StageValues(boost::gil::rgba8_pixel_t borderColor, - boost::gil::rgba8_pixel_t highlightColor, - boost::gil::rgba8_pixel_t lineColor, - std::int64_t borderWidth, - std::int64_t highlightWidth, - std::int64_t lineWidth) -{ - set_block_signals(true); - - p->borderColor_.StageValue(util::color::ToArgbString(borderColor)); - p->highlightColor_.StageValue(util::color::ToArgbString(highlightColor)); - p->lineColor_.StageValue(util::color::ToArgbString(lineColor)); - p->borderWidth_.StageValue(borderWidth); - p->highlightWidth_.StageValue(highlightWidth); - p->lineWidth_.StageValue(lineWidth); - - set_block_signals(false); - - staged_signal()(); -} - -bool operator==(const LineSettings& lhs, const LineSettings& rhs) -{ - return (lhs.p->borderColor_ == rhs.p->borderColor_ && - lhs.p->highlightColor_ == rhs.p->highlightColor_ && - lhs.p->lineColor_ == rhs.p->lineColor_ && - lhs.p->borderWidth_ == rhs.p->borderWidth_ && - lhs.p->highlightWidth_ == rhs.p->highlightWidth_ && - lhs.p->lineWidth_ == rhs.p->lineWidth_); -} - -} // namespace scwx::qt::settings diff --git a/scwx-qt/source/scwx/qt/settings/line_settings.hpp b/scwx-qt/source/scwx/qt/settings/line_settings.hpp deleted file mode 100644 index 3f13c601..00000000 --- a/scwx-qt/source/scwx/qt/settings/line_settings.hpp +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once - -#include -#include - -#include -#include - -#include - -namespace scwx::qt::settings -{ - -class LineSettings : public SettingsCategory -{ -public: - explicit LineSettings(const std::string& name); - ~LineSettings() override; - - LineSettings(const LineSettings&) = delete; - LineSettings& operator=(const LineSettings&) = delete; - - LineSettings(LineSettings&&) noexcept; - LineSettings& operator=(LineSettings&&) noexcept; - - [[nodiscard]] SettingsVariable& border_color() const; - [[nodiscard]] SettingsVariable& highlight_color() const; - [[nodiscard]] SettingsVariable& line_color() const; - - [[nodiscard]] SettingsVariable& border_width() const; - [[nodiscard]] SettingsVariable& highlight_width() const; - [[nodiscard]] SettingsVariable& line_width() const; - - [[nodiscard]] boost::gil::rgba32f_pixel_t GetBorderColorRgba32f() const; - [[nodiscard]] boost::gil::rgba32f_pixel_t GetHighlightColorRgba32f() const; - [[nodiscard]] boost::gil::rgba32f_pixel_t GetLineColorRgba32f() const; - - void StageValues(boost::gil::rgba8_pixel_t borderColor, - boost::gil::rgba8_pixel_t highlightColor, - boost::gil::rgba8_pixel_t lineColor, - std::int64_t borderWidth, - std::int64_t highlightWidth, - std::int64_t lineWidth); - - friend bool operator==(const LineSettings& lhs, const LineSettings& rhs); - -private: - class Impl; - std::unique_ptr p; -}; - -} // namespace scwx::qt::settings diff --git a/scwx-qt/source/scwx/qt/settings/map_settings.cpp b/scwx-qt/source/scwx/qt/settings/map_settings.cpp index 76c09d30..2d8e93b0 100644 --- a/scwx-qt/source/scwx/qt/settings/map_settings.cpp +++ b/scwx-qt/source/scwx/qt/settings/map_settings.cpp @@ -6,10 +6,15 @@ #include #include +#include #include -namespace scwx::qt::settings +namespace scwx +{ +namespace qt +{ +namespace settings { static const std::string logPrefix_ = "scwx::qt::settings::map_settings"; @@ -22,15 +27,14 @@ static const std::string kMapStyleName_ {"map_style"}; static const std::string kRadarSiteName_ {"radar_site"}; static const std::string kRadarProductGroupName_ {"radar_product_group"}; static const std::string kRadarProductName_ {"radar_product"}; -static const std::string kSmoothingEnabledName_ {"smoothing_enabled"}; -static const std::string kDefaultMapStyle_ {"?"}; +static const std::string kDefaultMapStyle_ {"?"}; +static constexpr common::RadarProductGroup kDefaultRadarProductGroup_ = + common::RadarProductGroup::Level3; static const std::string kDefaultRadarProductGroupString_ = "L3"; static const std::array kDefaultRadarProduct_ { "N0B", "N0G", "N0C", "N0X"}; -static constexpr bool kDefaultSmoothingEnabled_ {false}; - class MapSettings::Impl { public: @@ -41,28 +45,26 @@ public: SettingsVariable radarProductGroup_ { kRadarProductGroupName_}; SettingsVariable radarProduct_ {kRadarProductName_}; - SettingsVariable smoothingEnabled_ {kSmoothingEnabledName_}; }; explicit Impl() { for (std::size_t i = 0; i < kCount_; i++) { - map_.at(i).mapStyle_.SetDefault(kDefaultMapStyle_); - map_.at(i).radarSite_.SetDefault(kDefaultRadarSite_); - map_.at(i).radarProductGroup_.SetDefault( + map_[i].mapStyle_.SetDefault(kDefaultMapStyle_); + map_[i].radarSite_.SetDefault(kDefaultRadarSite_); + map_[i].radarProductGroup_.SetDefault( kDefaultRadarProductGroupString_); - map_.at(i).radarProduct_.SetDefault(kDefaultRadarProduct_.at(i)); - map_.at(i).smoothingEnabled_.SetDefault(kDefaultSmoothingEnabled_); + map_[i].radarProduct_.SetDefault(kDefaultRadarProduct_[i]); - map_.at(i).radarSite_.SetValidator( + map_[i].radarSite_.SetValidator( [](const std::string& value) { // Radar site must exist return config::RadarSite::Get(value) != nullptr; }); - map_.at(i).radarProductGroup_.SetValidator( + map_[i].radarProductGroup_.SetValidator( [](const std::string& value) { // Radar product group must be valid @@ -71,12 +73,12 @@ public: return radarProductGroup != common::RadarProductGroup::Unknown; }); - map_.at(i).radarProduct_.SetValidator( + map_[i].radarProduct_.SetValidator( [this, i](const std::string& value) { common::RadarProductGroup radarProductGroup = common::GetRadarProductGroup( - map_.at(i).radarProductGroup_.GetStagedOrValue()); + map_[i].radarProductGroup_.GetValue()); if (radarProductGroup == common::RadarProductGroup::Level2) { @@ -92,27 +94,21 @@ public: }); variables_.insert(variables_.cend(), - {&map_.at(i).mapStyle_, - &map_.at(i).radarSite_, - &map_.at(i).radarProductGroup_, - &map_.at(i).radarProduct_, - &map_.at(i).smoothingEnabled_}); + {&map_[i].mapStyle_, + &map_[i].radarSite_, + &map_[i].radarProductGroup_, + &map_[i].radarProduct_}); } } - ~Impl() = default; - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; + ~Impl() {} void SetDefaults(std::size_t i) { - map_.at(i).mapStyle_.SetValueToDefault(); - map_.at(i).radarSite_.SetValueToDefault(); - map_.at(i).radarProductGroup_.SetValueToDefault(); - map_.at(i).radarProduct_.SetValueToDefault(); - map_.at(i).smoothingEnabled_.SetValueToDefault(); + map_[i].mapStyle_.SetValueToDefault(); + map_[i].radarSite_.SetValueToDefault(); + map_[i].radarProductGroup_.SetValueToDefault(); + map_[i].radarProduct_.SetValueToDefault(); } friend void tag_invoke(boost::json::value_from_tag, @@ -122,8 +118,7 @@ public: jv = {{kMapStyleName_, data.mapStyle_.GetValue()}, {kRadarSiteName_, data.radarSite_.GetValue()}, {kRadarProductGroupName_, data.radarProductGroup_.GetValue()}, - {kRadarProductName_, data.radarProduct_.GetValue()}, - {kSmoothingEnabledName_, data.smoothingEnabled_.GetValue()}}; + {kRadarProductName_, data.radarProduct_.GetValue()}}; } friend bool operator==(const MapData& lhs, const MapData& rhs) @@ -131,8 +126,7 @@ public: return (lhs.mapStyle_ == rhs.mapStyle_ && // lhs.radarSite_ == rhs.radarSite_ && lhs.radarProductGroup_ == rhs.radarProductGroup_ && - lhs.radarProduct_ == rhs.radarProduct_ && - lhs.smoothingEnabled_ == rhs.smoothingEnabled_); + lhs.radarProduct_ == rhs.radarProduct_); } std::array map_ {}; @@ -157,29 +151,25 @@ std::size_t MapSettings::count() const return kCount_; } -SettingsVariable& MapSettings::map_style(std::size_t i) +SettingsVariable& MapSettings::map_style(std::size_t i) const { - return p->map_.at(i).mapStyle_; + return p->map_[i].mapStyle_; } -SettingsVariable& MapSettings::radar_site(std::size_t i) +SettingsVariable& MapSettings::radar_site(std::size_t i) const { - return p->map_.at(i).radarSite_; + return p->map_[i].radarSite_; } -SettingsVariable& MapSettings::radar_product_group(std::size_t i) +SettingsVariable& +MapSettings::radar_product_group(std::size_t i) const { - return p->map_.at(i).radarProductGroup_; + return p->map_[i].radarProductGroup_; } -SettingsVariable& MapSettings::radar_product(std::size_t i) +SettingsVariable& MapSettings::radar_product(std::size_t i) const { - return p->map_.at(i).radarProduct_; -} - -SettingsVariable& MapSettings::smoothing_enabled(std::size_t i) -{ - return p->map_.at(i).smoothingEnabled_; + return p->map_[i].radarProduct_; } bool MapSettings::Shutdown() @@ -189,12 +179,9 @@ bool MapSettings::Shutdown() // Commit settings that are managed separate from the settings dialog for (std::size_t i = 0; i < kCount_; ++i) { - Impl::MapData& mapRecordSettings = p->map_.at(i); + Impl::MapData& mapRecordSettings = p->map_[i]; dataChanged |= mapRecordSettings.mapStyle_.Commit(); - dataChanged |= mapRecordSettings.smoothingEnabled_.Commit(); - dataChanged |= mapRecordSettings.radarProductGroup_.Commit(); - dataChanged |= mapRecordSettings.radarProduct_.Commit(); } return dataChanged; @@ -215,15 +202,13 @@ bool MapSettings::ReadJson(const boost::json::object& json) if (i < mapArray.size() && mapArray.at(i).is_object()) { const boost::json::object& mapRecord = mapArray.at(i).as_object(); - Impl::MapData& mapRecordSettings = p->map_.at(i); + Impl::MapData& mapRecordSettings = p->map_[i]; // Load JSON Elements validated &= mapRecordSettings.mapStyle_.ReadValue(mapRecord); validated &= mapRecordSettings.radarSite_.ReadValue(mapRecord); validated &= mapRecordSettings.radarProductGroup_.ReadValue(mapRecord); - validated &= - mapRecordSettings.smoothingEnabled_.ReadValue(mapRecord); bool productValidated = mapRecordSettings.radarProduct_.ReadValue(mapRecord); @@ -278,4 +263,6 @@ bool operator==(const MapSettings& lhs, const MapSettings& rhs) return (lhs.p->map_ == rhs.p->map_); } -} // namespace scwx::qt::settings +} // namespace settings +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/settings/map_settings.hpp b/scwx-qt/source/scwx/qt/settings/map_settings.hpp index 9ffb3540..c8726491 100644 --- a/scwx-qt/source/scwx/qt/settings/map_settings.hpp +++ b/scwx-qt/source/scwx/qt/settings/map_settings.hpp @@ -6,14 +6,18 @@ #include #include -namespace scwx::qt::settings +namespace scwx +{ +namespace qt +{ +namespace settings { class MapSettings : public SettingsCategory { public: explicit MapSettings(); - ~MapSettings() override; + ~MapSettings(); MapSettings(const MapSettings&) = delete; MapSettings& operator=(const MapSettings&) = delete; @@ -21,12 +25,11 @@ public: MapSettings(MapSettings&&) noexcept; MapSettings& operator=(MapSettings&&) noexcept; - [[nodiscard]] std::size_t count() const; - SettingsVariable& map_style(std::size_t i); - SettingsVariable& radar_site(std::size_t i); - SettingsVariable& radar_product_group(std::size_t i); - SettingsVariable& radar_product(std::size_t i); - SettingsVariable& smoothing_enabled(std::size_t i); + std::size_t count() const; + SettingsVariable& map_style(std::size_t i) const; + SettingsVariable& radar_site(std::size_t i) const; + SettingsVariable& radar_product_group(std::size_t i) const; + SettingsVariable& radar_product(std::size_t i) const; bool Shutdown(); @@ -56,4 +59,6 @@ private: std::unique_ptr p; }; -} // namespace scwx::qt::settings +} // namespace settings +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/settings/palette_settings.cpp b/scwx-qt/source/scwx/qt/settings/palette_settings.cpp index 0b88b687..9d9c93fa 100644 --- a/scwx-qt/source/scwx/qt/settings/palette_settings.cpp +++ b/scwx-qt/source/scwx/qt/settings/palette_settings.cpp @@ -2,11 +2,15 @@ #include #include -#include #include #include +#include -namespace scwx::qt::settings +namespace scwx +{ +namespace qt +{ +namespace settings { static const std::string logPrefix_ = "scwx::qt::settings::palette_settings"; @@ -72,24 +76,59 @@ static const awips::Phenomenon kDefaultPhenomenon_ {awips::Phenomenon::Marine}; class PaletteSettings::Impl { public: - explicit Impl(PaletteSettings* self) : self_ {self} + explicit Impl() { - InitializeColorTables(); - InitializeLegacyAlerts(); - InitializeAlerts(); + palette_.reserve(kPaletteKeys_.size()); + + for (const auto& name : kPaletteKeys_) + { + const std::string& defaultValue = kDefaultPalettes_.at(name); + + auto result = + palette_.emplace(name, SettingsVariable {name}); + + SettingsVariable& settingsVariable = result.first->second; + + settingsVariable.SetDefault(defaultValue); + + variables_.push_back(&settingsVariable); + }; + + activeAlertColor_.reserve(kAlertColors_.size()); + inactiveAlertColor_.reserve(kAlertColors_.size()); + + for (auto& alert : kAlertColors_) + { + std::string phenomenonCode = awips::GetPhenomenonCode(alert.first); + std::string activeName = fmt::format("{}-active", phenomenonCode); + std::string inactiveName = fmt::format("{}-inactive", phenomenonCode); + + auto activeResult = activeAlertColor_.emplace( + alert.first, SettingsVariable {activeName}); + auto inactiveResult = inactiveAlertColor_.emplace( + alert.first, SettingsVariable {inactiveName}); + + SettingsVariable& activeVariable = + activeResult.first->second; + SettingsVariable& inactiveVariable = + inactiveResult.first->second; + + activeVariable.SetDefault( + util::color::ToArgbString(alert.second.first)); + inactiveVariable.SetDefault( + util::color::ToArgbString(alert.second.second)); + + activeVariable.SetValidator(&ValidateColor); + inactiveVariable.SetValidator(&ValidateColor); + + variables_.push_back(&activeVariable); + variables_.push_back(&inactiveVariable); + } } - ~Impl() = default; - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; + ~Impl() {} - void InitializeColorTables(); - void InitializeLegacyAlerts(); - void InitializeAlerts(); - - PaletteSettings* self_; + static bool ValidateColor(const std::string& value); std::unordered_map> palette_ {}; std::unordered_map> @@ -97,13 +136,16 @@ public: std::unordered_map> inactiveAlertColor_ {}; std::vector variables_ {}; - - std::unordered_map - alertPaletteMap_ {}; }; +bool PaletteSettings::Impl::ValidateColor(const std::string& value) +{ + static constexpr LazyRE2 re = {"#[0-9A-Fa-f]{8}"}; + return RE2::FullMatch(value, *re); +} + PaletteSettings::PaletteSettings() : - SettingsCategory("palette"), p(std::make_unique(this)) + SettingsCategory("palette"), p(std::make_unique()) { RegisterVariables(p->variables_); SetDefaults(); @@ -116,75 +158,6 @@ PaletteSettings::PaletteSettings(PaletteSettings&&) noexcept = default; PaletteSettings& PaletteSettings::operator=(PaletteSettings&&) noexcept = default; -void PaletteSettings::Impl::InitializeColorTables() -{ - palette_.reserve(kPaletteKeys_.size()); - - for (const auto& name : kPaletteKeys_) - { - const std::string& defaultValue = kDefaultPalettes_.at(name); - - auto result = - palette_.emplace(name, SettingsVariable {name}); - - SettingsVariable& settingsVariable = result.first->second; - - settingsVariable.SetDefault(defaultValue); - - variables_.push_back(&settingsVariable); - }; -} - -void PaletteSettings::Impl::InitializeLegacyAlerts() -{ - activeAlertColor_.reserve(kAlertColors_.size()); - inactiveAlertColor_.reserve(kAlertColors_.size()); - - for (auto& alert : kAlertColors_) - { - std::string phenomenonCode = awips::GetPhenomenonCode(alert.first); - std::string activeName = fmt::format("{}-active", phenomenonCode); - std::string inactiveName = fmt::format("{}-inactive", phenomenonCode); - - auto activeResult = activeAlertColor_.emplace( - alert.first, SettingsVariable {activeName}); - auto inactiveResult = inactiveAlertColor_.emplace( - alert.first, SettingsVariable {inactiveName}); - - SettingsVariable& activeVariable = - activeResult.first->second; - SettingsVariable& inactiveVariable = - inactiveResult.first->second; - - activeVariable.SetDefault(util::color::ToArgbString(alert.second.first)); - inactiveVariable.SetDefault( - util::color::ToArgbString(alert.second.second)); - - activeVariable.SetValidator(&util::color::ValidateArgbString); - inactiveVariable.SetValidator(&util::color::ValidateArgbString); - - variables_.push_back(&activeVariable); - variables_.push_back(&inactiveVariable); - } -} - -void PaletteSettings::Impl::InitializeAlerts() -{ - std::vector alertSettings {}; - - for (auto phenomenon : PaletteSettings::alert_phenomena()) - { - auto result = alertPaletteMap_.emplace(phenomenon, phenomenon); - auto& it = result.first; - AlertPaletteSettings& alertPaletteSettings = it->second; - - // Variable registration - alertSettings.push_back(&alertPaletteSettings); - } - - self_->RegisterSubcategoryArray("alerts", alertSettings); -} - SettingsVariable& PaletteSettings::palette(const std::string& name) const { @@ -221,12 +194,6 @@ PaletteSettings::alert_color(awips::Phenomenon phenomenon, bool active) const } } -AlertPaletteSettings& -PaletteSettings::alert_palette(awips::Phenomenon phenomenon) -{ - return p->alertPaletteMap_.at(phenomenon); -} - const std::vector& PaletteSettings::alert_phenomena() { static const std::vector kAlertPhenomena_ { @@ -252,4 +219,6 @@ bool operator==(const PaletteSettings& lhs, const PaletteSettings& rhs) lhs.p->inactiveAlertColor_ == rhs.p->inactiveAlertColor_); } -} // namespace scwx::qt::settings +} // namespace settings +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/settings/palette_settings.hpp b/scwx-qt/source/scwx/qt/settings/palette_settings.hpp index c7147a30..c0f7985a 100644 --- a/scwx-qt/source/scwx/qt/settings/palette_settings.hpp +++ b/scwx-qt/source/scwx/qt/settings/palette_settings.hpp @@ -1,22 +1,24 @@ #pragma once -#include #include #include -#include #include #include #include -namespace scwx::qt::settings +namespace scwx +{ +namespace qt +{ +namespace settings { class PaletteSettings : public SettingsCategory { public: explicit PaletteSettings(); - ~PaletteSettings() override; + ~PaletteSettings(); PaletteSettings(const PaletteSettings&) = delete; PaletteSettings& operator=(const PaletteSettings&) = delete; @@ -24,11 +26,9 @@ public: PaletteSettings(PaletteSettings&&) noexcept; PaletteSettings& operator=(PaletteSettings&&) noexcept; - [[nodiscard]] SettingsVariable& - palette(const std::string& name) const; - [[nodiscard]] SettingsVariable& - alert_color(awips::Phenomenon phenomenon, bool active) const; - AlertPaletteSettings& alert_palette(awips::Phenomenon); + SettingsVariable& palette(const std::string& name) const; + SettingsVariable& alert_color(awips::Phenomenon phenomenon, + bool active) const; static const std::vector& alert_phenomena(); @@ -42,4 +42,6 @@ private: std::unique_ptr p; }; -} // namespace scwx::qt::settings +} // namespace settings +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/settings/product_settings.cpp b/scwx-qt/source/scwx/qt/settings/product_settings.cpp index 1221d717..3cf47ef7 100644 --- a/scwx-qt/source/scwx/qt/settings/product_settings.cpp +++ b/scwx-qt/source/scwx/qt/settings/product_settings.cpp @@ -1,9 +1,11 @@ #include #include -#include - -namespace scwx::qt::settings +namespace scwx +{ +namespace qt +{ +namespace settings { static const std::string logPrefix_ = "scwx::qt::settings::product_settings"; @@ -13,22 +15,12 @@ class ProductSettings::Impl public: explicit Impl() { - // SetDefault, SetMinimum and SetMaximum are descriptive - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) - showSmoothedRangeFolding_.SetDefault(false); stiForecastEnabled_.SetDefault(true); stiPastEnabled_.SetDefault(true); - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) } - ~Impl() = default; - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; + ~Impl() {} - SettingsVariable showSmoothedRangeFolding_ { - "show_smoothed_range_folding"}; SettingsVariable stiForecastEnabled_ {"sti_forecast_enabled"}; SettingsVariable stiPastEnabled_ {"sti_past_enabled"}; }; @@ -36,9 +28,7 @@ public: ProductSettings::ProductSettings() : SettingsCategory("product"), p(std::make_unique()) { - RegisterVariables({&p->showSmoothedRangeFolding_, - &p->stiForecastEnabled_, - &p->stiPastEnabled_}); + RegisterVariables({&p->stiForecastEnabled_, &p->stiPastEnabled_}); SetDefaults(); } ProductSettings::~ProductSettings() = default; @@ -47,17 +37,12 @@ ProductSettings::ProductSettings(ProductSettings&&) noexcept = default; ProductSettings& ProductSettings::operator=(ProductSettings&&) noexcept = default; -SettingsVariable& ProductSettings::show_smoothed_range_folding() -{ - return p->showSmoothedRangeFolding_; -} - -SettingsVariable& ProductSettings::sti_forecast_enabled() +SettingsVariable& ProductSettings::sti_forecast_enabled() const { return p->stiForecastEnabled_; } -SettingsVariable& ProductSettings::sti_past_enabled() +SettingsVariable& ProductSettings::sti_past_enabled() const { return p->stiPastEnabled_; } @@ -81,10 +66,10 @@ ProductSettings& ProductSettings::Instance() bool operator==(const ProductSettings& lhs, const ProductSettings& rhs) { - return (lhs.p->showSmoothedRangeFolding_ == - rhs.p->showSmoothedRangeFolding_ && - lhs.p->stiForecastEnabled_ == rhs.p->stiForecastEnabled_ && + return (lhs.p->stiForecastEnabled_ == rhs.p->stiForecastEnabled_ && lhs.p->stiPastEnabled_ == rhs.p->stiPastEnabled_); } -} // namespace scwx::qt::settings +} // namespace settings +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/settings/product_settings.hpp b/scwx-qt/source/scwx/qt/settings/product_settings.hpp index d267b127..c7c09dd8 100644 --- a/scwx-qt/source/scwx/qt/settings/product_settings.hpp +++ b/scwx-qt/source/scwx/qt/settings/product_settings.hpp @@ -4,15 +4,20 @@ #include #include +#include -namespace scwx::qt::settings +namespace scwx +{ +namespace qt +{ +namespace settings { class ProductSettings : public SettingsCategory { public: explicit ProductSettings(); - ~ProductSettings() override; + ~ProductSettings(); ProductSettings(const ProductSettings&) = delete; ProductSettings& operator=(const ProductSettings&) = delete; @@ -20,9 +25,8 @@ public: ProductSettings(ProductSettings&&) noexcept; ProductSettings& operator=(ProductSettings&&) noexcept; - SettingsVariable& show_smoothed_range_folding(); - SettingsVariable& sti_forecast_enabled(); - SettingsVariable& sti_past_enabled(); + SettingsVariable& sti_forecast_enabled() const; + SettingsVariable& sti_past_enabled() const; static ProductSettings& Instance(); @@ -36,4 +40,6 @@ private: std::unique_ptr p; }; -} // namespace scwx::qt::settings +} // namespace settings +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/settings/settings_category.cpp b/scwx-qt/source/scwx/qt/settings/settings_category.cpp index b0e1b416..e6c929f8 100644 --- a/scwx-qt/source/scwx/qt/settings/settings_category.cpp +++ b/scwx-qt/source/scwx/qt/settings/settings_category.cpp @@ -4,7 +4,11 @@ #include -namespace scwx::qt::settings +namespace scwx +{ +namespace qt +{ +namespace settings { static const std::string logPrefix_ = "scwx::qt::settings::settings_category"; @@ -15,27 +19,13 @@ class SettingsCategory::Impl public: explicit Impl(const std::string& name) : name_ {name} {} - ~Impl() = default; - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; - - void ConnectSubcategory(SettingsCategory& category); - void ConnectVariable(SettingsVariableBase* variable); + ~Impl() {} const std::string name_; std::vector>> subcategoryArrays_; - std::vector subcategories_; std::vector variables_; - - boost::signals2::signal changedSignal_ {}; - boost::signals2::signal stagedSignal_ {}; - bool blockSignals_ {false}; - - std::vector connections_ {}; }; SettingsCategory::SettingsCategory(const std::string& name) : @@ -48,88 +38,13 @@ SettingsCategory::SettingsCategory(SettingsCategory&&) noexcept = default; SettingsCategory& SettingsCategory::operator=(SettingsCategory&&) noexcept = default; -bool SettingsCategory::IsDefault() const -{ - bool isDefault = true; - - // Get subcategory array defaults - for (auto& subcategoryArray : p->subcategoryArrays_) - { - for (auto& subcategory : subcategoryArray.second) - { - isDefault = isDefault && subcategory->IsDefault(); - } - } - - // Get subcategory defaults - for (auto& subcategory : p->subcategories_) - { - isDefault = isDefault && subcategory->IsDefault(); - } - - // Get variable defaults - for (auto& variable : p->variables_) - { - isDefault = isDefault && variable->IsDefault(); - } - - return isDefault; -} - -bool SettingsCategory::IsDefaultStaged() const -{ - bool isDefaultStaged = true; - - // Get subcategory array defaults - for (auto& subcategoryArray : p->subcategoryArrays_) - { - for (auto& subcategory : subcategoryArray.second) - { - isDefaultStaged = isDefaultStaged && subcategory->IsDefaultStaged(); - } - } - - // Get subcategory defaults - for (auto& subcategory : p->subcategories_) - { - isDefaultStaged = isDefaultStaged && subcategory->IsDefaultStaged(); - } - - // Get variable defaults - for (auto& variable : p->variables_) - { - isDefaultStaged = isDefaultStaged && variable->IsDefaultStaged(); - } - - return isDefaultStaged; -} - std::string SettingsCategory::name() const { return p->name_; } -boost::signals2::signal& SettingsCategory::changed_signal() -{ - return p->changedSignal_; -} - -boost::signals2::signal& SettingsCategory::staged_signal() -{ - return p->stagedSignal_; -} - -void SettingsCategory::set_block_signals(bool blockSignals) -{ - p->blockSignals_ = blockSignals; -} - void SettingsCategory::SetDefaults() { - // Don't allow individual variables to invoke the signal when operating over - // the entire category - p->blockSignals_ = true; - // Set subcategory array defaults for (auto& subcategoryArray : p->subcategoryArrays_) { @@ -139,129 +54,11 @@ void SettingsCategory::SetDefaults() } } - // Set subcategory defaults - for (auto& subcategory : p->subcategories_) - { - subcategory->SetDefaults(); - } - // Set variable defaults for (auto& variable : p->variables_) { variable->SetValueToDefault(); } - - // Unblock signals - p->blockSignals_ = false; - - p->changedSignal_(); - p->stagedSignal_(); -} - -void SettingsCategory::StageDefaults() -{ - // Don't allow individual variables to invoke the signal when operating over - // the entire category - p->blockSignals_ = true; - - // Stage subcategory array defaults - for (auto& subcategoryArray : p->subcategoryArrays_) - { - for (auto& subcategory : subcategoryArray.second) - { - subcategory->StageDefaults(); - } - } - - // Stage subcategory defaults - for (auto& subcategory : p->subcategories_) - { - subcategory->StageDefaults(); - } - - // Stage variable defaults - for (auto& variable : p->variables_) - { - variable->StageDefault(); - } - - // Unblock signals - p->blockSignals_ = false; - - p->stagedSignal_(); -} - -bool SettingsCategory::Commit() -{ - bool committed = false; - - // Don't allow individual variables to invoke the signal when operating over - // the entire category - p->blockSignals_ = true; - - // Commit subcategory arrays - for (auto& subcategoryArray : p->subcategoryArrays_) - { - for (auto& subcategory : subcategoryArray.second) - { - committed |= subcategory->Commit(); - } - } - - // Commit subcategories - for (auto& subcategory : p->subcategories_) - { - committed |= subcategory->Commit(); - } - - // Commit variables - for (auto& variable : p->variables_) - { - committed |= variable->Commit(); - } - - // Unblock signals - p->blockSignals_ = false; - - if (committed) - { - p->changedSignal_(); - } - - return committed; -} - -void SettingsCategory::Reset() -{ - // Don't allow individual variables to invoke the signal when operating over - // the entire category - p->blockSignals_ = true; - - // Reset subcategory arrays - for (auto& subcategoryArray : p->subcategoryArrays_) - { - for (auto& subcategory : subcategoryArray.second) - { - subcategory->Reset(); - } - } - - // Reset subcategories - for (auto& subcategory : p->subcategories_) - { - subcategory->Reset(); - } - - // Reset variables - for (auto& variable : p->variables_) - { - variable->Reset(); - } - - // Unblock signals - p->blockSignals_ = false; - - p->stagedSignal_(); } bool SettingsCategory::ReadJson(const boost::json::object& json) @@ -314,12 +111,6 @@ bool SettingsCategory::ReadJson(const boost::json::object& json) } } - // Read subcategories - for (auto& subcategory : p->subcategories_) - { - validated &= subcategory->ReadJson(object); - } - // Read variables for (auto& variable : p->variables_) { @@ -363,12 +154,6 @@ void SettingsCategory::WriteJson(boost::json::object& json) const object.insert_or_assign(subcategoryArray.first, arrayObject); } - // Write subcategories - for (auto& subcategory : p->subcategories_) - { - subcategory->WriteJson(object); - } - // Write variables for (auto& variable : p->variables_) { @@ -378,12 +163,6 @@ void SettingsCategory::WriteJson(boost::json::object& json) const json.insert_or_assign(p->name_, object); } -void SettingsCategory::RegisterSubcategory(SettingsCategory& subcategory) -{ - p->ConnectSubcategory(subcategory); - p->subcategories_.push_back(&subcategory); -} - void SettingsCategory::RegisterSubcategoryArray( const std::string& name, std::vector& subcategories) { @@ -393,90 +172,22 @@ void SettingsCategory::RegisterSubcategoryArray( std::transform(subcategories.begin(), subcategories.end(), std::back_inserter(newSubcategories.second), - [this](SettingsCategory& subcategory) - { - p->ConnectSubcategory(subcategory); - return &subcategory; - }); -} - -void SettingsCategory::RegisterSubcategoryArray( - const std::string& name, std::vector& subcategories) -{ - auto& newSubcategories = p->subcategoryArrays_.emplace_back( - name, std::vector {}); - - std::transform(subcategories.begin(), - subcategories.end(), - std::back_inserter(newSubcategories.second), - [this](SettingsCategory* subcategory) - { - p->ConnectSubcategory(*subcategory); - return subcategory; - }); + [](SettingsCategory& subcategory) { return &subcategory; }); } void SettingsCategory::RegisterVariables( std::initializer_list variables) { - for (auto& variable : variables) - { - p->ConnectVariable(variable); - } p->variables_.insert(p->variables_.end(), variables); } void SettingsCategory::RegisterVariables( std::vector variables) { - for (auto& variable : variables) - { - p->ConnectVariable(variable); - } p->variables_.insert( p->variables_.end(), variables.cbegin(), variables.cend()); } -void SettingsCategory::Impl::ConnectSubcategory(SettingsCategory& category) -{ - connections_.emplace_back(category.changed_signal().connect( - [this]() - { - if (!blockSignals_) - { - changedSignal_(); - } - })); - - connections_.emplace_back(category.staged_signal().connect( - [this]() - { - if (!blockSignals_) - { - stagedSignal_(); - } - })); -} - -void SettingsCategory::Impl::ConnectVariable(SettingsVariableBase* variable) -{ - connections_.emplace_back(variable->changed_signal().connect( - [this]() - { - if (!blockSignals_) - { - changedSignal_(); - } - })); - - connections_.emplace_back(variable->staged_signal().connect( - [this]() - { - if (!blockSignals_) - { - stagedSignal_(); - } - })); -} - -} // namespace scwx::qt::settings +} // namespace settings +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/settings/settings_category.hpp b/scwx-qt/source/scwx/qt/settings/settings_category.hpp index c47bfdeb..d7c86abd 100644 --- a/scwx-qt/source/scwx/qt/settings/settings_category.hpp +++ b/scwx-qt/source/scwx/qt/settings/settings_category.hpp @@ -6,16 +6,19 @@ #include #include -#include -namespace scwx::qt::settings +namespace scwx +{ +namespace qt +{ +namespace settings { class SettingsCategory { public: explicit SettingsCategory(const std::string& name); - virtual ~SettingsCategory(); + ~SettingsCategory(); SettingsCategory(const SettingsCategory&) = delete; SettingsCategory& operator=(const SettingsCategory&) = delete; @@ -23,63 +26,13 @@ public: SettingsCategory(SettingsCategory&&) noexcept; SettingsCategory& operator=(SettingsCategory&&) noexcept; - [[nodiscard]] std::string name() const; - - /** - * Gets the signal invoked when a variable within the category is changed. - * - * @return Changed signal - */ - boost::signals2::signal& changed_signal(); - - /** - * Gets the signal invoked when a variable within the category is staged. - * - * @return Staged signal - */ - boost::signals2::signal& staged_signal(); - - /** - * Gets whether or not all settings variables are currently set to default - * values. - * - * @return true if all settings variables are currently set to default - * values, otherwise false. - */ - [[nodiscard]] bool IsDefault() const; - - /** - * Gets whether or not all settings variables currently have staged values - * set to default. - * - * @return true if all settings variables currently have staged values set - * to default, otherwise false. - */ - [[nodiscard]] bool IsDefaultStaged() const; + std::string name() const; /** * Set all variables to their defaults. */ void SetDefaults(); - /** - * Stage all variables to their defaults. - */ - void StageDefaults(); - - /** - * Sets the current value of all variables to the staged value. - * - * @return true if any staged value was committed, false if no staged values - * are present. - */ - bool Commit(); - - /** - * Clears the staged value of all variables. - */ - void Reset(); - /** * Reads the variables from the JSON object. * @@ -97,21 +50,17 @@ public: */ virtual void WriteJson(boost::json::object& json) const; - void RegisterSubcategory(SettingsCategory& subcategory); void RegisterSubcategoryArray(const std::string& name, std::vector& subcategories); - void RegisterSubcategoryArray(const std::string& name, - std::vector& subcategories); void RegisterVariables(std::initializer_list variables); void RegisterVariables(std::vector variables); -protected: - void set_block_signals(bool blockSignals); - private: class Impl; std::unique_ptr p; }; -} // namespace scwx::qt::settings +} // namespace settings +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/settings/settings_container.cpp b/scwx-qt/source/scwx/qt/settings/settings_container.cpp index df0d7e41..1eb5b06a 100644 --- a/scwx-qt/source/scwx/qt/settings/settings_container.cpp +++ b/scwx-qt/source/scwx/qt/settings/settings_container.cpp @@ -1,7 +1,13 @@ +#define SETTINGS_CONTAINER_IMPLEMENTATION + #include #include -namespace scwx::qt::settings +namespace scwx +{ +namespace qt +{ +namespace settings { static const std::string logPrefix_ = "scwx::qt::settings::settings_container"; @@ -11,13 +17,9 @@ template class SettingsContainer::Impl { public: - explicit Impl() = default; + explicit Impl() {} - ~Impl() = default; - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; + ~Impl() {} T elementDefault_ {}; std::optional elementMinimum_ {}; @@ -170,6 +172,6 @@ bool SettingsContainer::Equals(const SettingsVariableBase& o) const p->elementMaximum_ == v.p->elementMaximum_; } -template class SettingsContainer>; - -} // namespace scwx::qt::settings +} // namespace settings +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/settings/settings_container.hpp b/scwx-qt/source/scwx/qt/settings/settings_container.hpp index 0e378a81..b35201c6 100644 --- a/scwx-qt/source/scwx/qt/settings/settings_container.hpp +++ b/scwx-qt/source/scwx/qt/settings/settings_container.hpp @@ -2,7 +2,11 @@ #include -namespace scwx::qt::settings +namespace scwx +{ +namespace qt +{ +namespace settings { template @@ -88,12 +92,17 @@ public: void SetElementValidator(std::function validator); protected: - [[nodiscard]] virtual bool - Equals(const SettingsVariableBase& o) const override; + virtual bool Equals(const SettingsVariableBase& o) const override; private: class Impl; std::unique_ptr p; }; -} // namespace scwx::qt::settings +#ifdef SETTINGS_CONTAINER_IMPLEMENTATION +template class SettingsContainer>; +#endif + +} // namespace settings +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/settings/settings_interface.cpp b/scwx-qt/source/scwx/qt/settings/settings_interface.cpp index e2c280b2..9a24c5ae 100644 --- a/scwx-qt/source/scwx/qt/settings/settings_interface.cpp +++ b/scwx-qt/source/scwx/qt/settings/settings_interface.cpp @@ -1,3 +1,5 @@ +#define SETTINGS_INTERFACE_IMPLEMENTATION + #include #include #include @@ -12,17 +14,16 @@ #include #include #include -#include -#include -namespace scwx::qt::settings +namespace scwx +{ +namespace qt +{ +namespace settings { static const std::string logPrefix_ = "scwx::qt::settings::settings_interface"; -static const QString kValidStyleSheet_ = ""; -static const QString kInvalidStyleSheet_ = "border: 2px solid red;"; - template class SettingsInterface::Impl { @@ -32,11 +33,7 @@ public: context_->moveToThread(QCoreApplication::instance()->thread()); } - ~Impl() = default; - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; + ~Impl() {} template void SetWidgetText(U* widget, const T& currentValue); @@ -44,7 +41,6 @@ public: void UpdateEditWidget(); void UpdateResetButton(); void UpdateUnitLabel(); - void UpdateValidityDisplay(); SettingsInterface* self_; @@ -62,10 +58,6 @@ public: double unitScale_ {1}; std::optional unitAbbreviation_ {}; bool unitEnabled_ {false}; - - bool trimmingEnabled_ {false}; - - std::optional invalidTooltip_; }; template @@ -179,13 +171,14 @@ void SettingsInterface::SetEditWidget(QWidget* widget) p->context_.get(), [this](const QKeySequence& sequence) { - const std::string value { + std::string value { sequence.toString().toStdString()}; // Attempt to stage the value p->stagedValid_ = p->variable_->StageValue(value); p->UpdateResetButton(); - p->UpdateValidityDisplay(); + + // TODO: Display invalid status }); } } @@ -200,11 +193,8 @@ void SettingsInterface::SetEditWidget(QWidget* widget) p->context_.get(), [this](const QString& text) { - const QString trimmedText = - p->trimmingEnabled_ ? text.trimmed() : text; - // Map to value if required - std::string value {trimmedText.toStdString()}; + std::string value {text.toStdString()}; if (p->mapToValue_ != nullptr) { value = p->mapToValue_(value); @@ -213,7 +203,8 @@ void SettingsInterface::SetEditWidget(QWidget* widget) // Attempt to stage the value p->stagedValid_ = p->variable_->StageValue(value); p->UpdateResetButton(); - p->UpdateValidityDisplay(); + + // TODO: Display invalid status }); } else if constexpr (std::is_same_v) @@ -226,8 +217,8 @@ void SettingsInterface::SetEditWidget(QWidget* widget) [this](const QString& text) { // Convert to a double - bool ok = false; - const double value = text.toDouble(&ok); + bool ok; + double value = text.toDouble(&ok); if (ok) { // Attempt to stage the value @@ -240,8 +231,6 @@ void SettingsInterface::SetEditWidget(QWidget* widget) p->stagedValid_ = false; p->UpdateResetButton(); } - - p->UpdateValidityDisplay(); }); } else if constexpr (std::is_same_v>) @@ -286,7 +275,8 @@ void SettingsInterface::SetEditWidget(QWidget* widget) // Attempt to stage the value p->stagedValid_ = p->variable_->StageValue(value); p->UpdateResetButton(); - p->UpdateValidityDisplay(); + + // TODO: Display invalid status }); } } @@ -370,8 +360,6 @@ void SettingsInterface::SetEditWidget(QWidget* widget) p->UpdateResetButton(); } // Otherwise, don't process an unchanged value - - p->UpdateValidityDisplay(); }); } } @@ -423,8 +411,6 @@ void SettingsInterface::SetEditWidget(QWidget* widget) p->UpdateResetButton(); } // Otherwise, don't process an unchanged value - - p->UpdateValidityDisplay(); }); } } @@ -504,19 +490,6 @@ void SettingsInterface::SetUnit(const double& scale, p->UpdateUnitLabel(); } -template -void SettingsInterface::EnableTrimming(bool trimmingEnabled) -{ - p->trimmingEnabled_ = trimmingEnabled; -} - -template -void SettingsInterface::SetInvalidTooltip( - const std::optional& tooltip) -{ - p->invalidTooltip_ = std::move(tooltip); -} - template template void SettingsInterface::Impl::SetWidgetText(U* widget, const T& currentValue) @@ -634,15 +607,6 @@ void SettingsInterface::Impl::UpdateUnitLabel() unitLabel_->setText(QString::fromStdString(unitAbbreviation_.value_or(""))); } -template -void SettingsInterface::Impl::UpdateValidityDisplay() -{ - editWidget_->setStyleSheet(stagedValid_ ? kValidStyleSheet_ : - kInvalidStyleSheet_); - editWidget_->setToolTip( - invalidTooltip_ && !stagedValid_ ? invalidTooltip_->c_str() : ""); -} - template void SettingsInterface::Impl::UpdateResetButton() { @@ -652,12 +616,6 @@ void SettingsInterface::Impl::UpdateResetButton() } } -template class SettingsInterface; -template class SettingsInterface; -template class SettingsInterface; -template class SettingsInterface; - -// Containers are not to be used directly -template class SettingsInterface>; - -} // namespace scwx::qt::settings +} // namespace settings +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/settings/settings_interface.hpp b/scwx-qt/source/scwx/qt/settings/settings_interface.hpp index 6bf586a7..b049dcc1 100644 --- a/scwx-qt/source/scwx/qt/settings/settings_interface.hpp +++ b/scwx-qt/source/scwx/qt/settings/settings_interface.hpp @@ -1,15 +1,19 @@ #pragma once -#include #include #include #include #include +#include class QLabel; -namespace scwx::qt::settings +namespace scwx +{ +namespace qt +{ +namespace settings { template @@ -117,30 +121,26 @@ public: /** * Sets the unit to be used by this setting. * - * @param scale The ratio of the current unit to the base unit - * @param abbreviation The abbreviation to be displayed + * @param scale The radio of the current unit to the base unit + * @param abbreviation The abreviation to be displayed */ void SetUnit(const double& scale, const std::string& abbreviation); - /** - * Enables or disables whitespace trimming of text input. - * Removes whitespace ('\t', '\n', '\v', '\f', '\r', and ' ') at the - * beginning and end of the string from a QLineEdit. - * - * @param trimmingEnabled If trimming should be enabled. - */ - void EnableTrimming(bool trimmingEnabled = true); - - /** - * Set a tooltip to be displayed when an invalid input is given. - * - * @param tooltip the tooltip to be displayed - */ - void SetInvalidTooltip(const std::optional& tooltip); - private: class Impl; std::unique_ptr p; }; -} // namespace scwx::qt::settings +#ifdef SETTINGS_INTERFACE_IMPLEMENTATION +template class SettingsInterface; +template class SettingsInterface; +template class SettingsInterface; +template class SettingsInterface; + +// Containers are not to be used directly +template class SettingsInterface>; +#endif + +} // namespace settings +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/settings/settings_interface_base.cpp b/scwx-qt/source/scwx/qt/settings/settings_interface_base.cpp index e7060573..37e1ec25 100644 --- a/scwx-qt/source/scwx/qt/settings/settings_interface_base.cpp +++ b/scwx-qt/source/scwx/qt/settings/settings_interface_base.cpp @@ -2,7 +2,11 @@ #include -namespace scwx::qt::settings +namespace scwx +{ +namespace qt +{ +namespace settings { static const std::string logPrefix_ = @@ -11,12 +15,8 @@ static const std::string logPrefix_ = class SettingsInterfaceBase::Impl { public: - explicit Impl() = default; - ~Impl() = default; - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; + explicit Impl() {} + ~Impl() {} }; SettingsInterfaceBase::SettingsInterfaceBase() : p(std::make_unique()) {} @@ -29,4 +29,6 @@ SettingsInterfaceBase::SettingsInterfaceBase(SettingsInterfaceBase&&) noexcept = SettingsInterfaceBase& SettingsInterfaceBase::operator=(SettingsInterfaceBase&&) noexcept = default; -} // namespace scwx::qt::settings +} // namespace settings +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/settings/settings_interface_base.hpp b/scwx-qt/source/scwx/qt/settings/settings_interface_base.hpp index 16e89469..d0dc2ff2 100644 --- a/scwx-qt/source/scwx/qt/settings/settings_interface_base.hpp +++ b/scwx-qt/source/scwx/qt/settings/settings_interface_base.hpp @@ -5,7 +5,11 @@ class QAbstractButton; class QWidget; -namespace scwx::qt::settings +namespace scwx +{ +namespace qt +{ +namespace settings { class SettingsInterfaceBase @@ -66,4 +70,6 @@ private: std::unique_ptr p; }; -} // namespace scwx::qt::settings +} // namespace settings +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/settings/settings_variable.cpp b/scwx-qt/source/scwx/qt/settings/settings_variable.cpp index 9682cbe4..1a7160f5 100644 --- a/scwx-qt/source/scwx/qt/settings/settings_variable.cpp +++ b/scwx-qt/source/scwx/qt/settings/settings_variable.cpp @@ -1,3 +1,5 @@ +#define SETTINGS_VARIABLE_IMPLEMENTATION + #include #include @@ -5,9 +7,12 @@ #include #include #include -#include -namespace scwx::qt::settings +namespace scwx +{ +namespace qt +{ +namespace settings { static const std::string logPrefix_ = "scwx::qt::settings::settings_variable"; @@ -17,12 +22,8 @@ template class SettingsVariable::Impl { public: - explicit Impl() = default; - ~Impl() = default; - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; + explicit Impl() {} + ~Impl() {} T value_ {}; T default_ {}; @@ -66,18 +67,6 @@ inline auto FormatParameter(const T& value) } } -template -bool SettingsVariable::IsDefault() const -{ - return p->value_ == p->default_; -} - -template -bool SettingsVariable::IsDefaultStaged() const -{ - return p->staged_.value_or(p->value_) == p->default_; -} - template T SettingsVariable::GetValue() const { @@ -94,13 +83,10 @@ bool SettingsVariable::SetValue(const T& value) p->value_ = (p->transform_ != nullptr) ? p->transform_(value) : value; validated = true; - changed_signal()(); for (auto& callback : p->valueChangedCallbackFunctions_) { callback.second(p->value_); } - - staged_signal()(); for (auto& callback : p->valueStagedCallbackFunctions_) { callback.second(p->value_); @@ -145,13 +131,10 @@ bool SettingsVariable::SetValueOrDefault(const T& value) p->value_ = p->default_; } - changed_signal()(); for (auto& callback : p->valueChangedCallbackFunctions_) { callback.second(p->value_); } - - staged_signal()(); for (auto& callback : p->valueStagedCallbackFunctions_) { callback.second(p->value_); @@ -165,13 +148,10 @@ void SettingsVariable::SetValueToDefault() { p->value_ = p->default_; - changed_signal()(); for (auto& callback : p->valueChangedCallbackFunctions_) { callback.second(p->value_); } - - staged_signal()(); for (auto& callback : p->valueStagedCallbackFunctions_) { callback.second(p->value_); @@ -190,7 +170,6 @@ void SettingsVariable::StageDefault() p->staged_.reset(); } - staged_signal()(); for (auto& callback : p->valueStagedCallbackFunctions_) { callback.second(p->default_); @@ -217,7 +196,6 @@ bool SettingsVariable::StageValue(const T& value) validated = true; - staged_signal()(); for (auto& callback : p->valueStagedCallbackFunctions_) { callback.second(transformed); @@ -238,13 +216,10 @@ bool SettingsVariable::Commit() p->staged_.reset(); committed = true; - changed_signal()(); for (auto& callback : p->valueChangedCallbackFunctions_) { callback.second(p->value_); } - - staged_signal()(); for (auto& callback : p->valueStagedCallbackFunctions_) { callback.second(p->value_); @@ -259,7 +234,6 @@ void SettingsVariable::Reset() { p->staged_.reset(); - staged_signal()(); for (auto& callback : p->valueStagedCallbackFunctions_) { callback.second(p->value_); @@ -364,13 +338,10 @@ bool SettingsVariable::ReadValue(const boost::json::object& json) p->value_ = p->default_; } - changed_signal()(); for (auto& callback : p->valueChangedCallbackFunctions_) { callback.second(p->value_); } - - staged_signal()(); for (auto& callback : p->valueStagedCallbackFunctions_) { callback.second(p->value_); @@ -431,12 +402,6 @@ bool SettingsVariable::Equals(const SettingsVariableBase& o) const p->maximum_ == v.p->maximum_; } -template class SettingsVariable; -template class SettingsVariable; -template class SettingsVariable; -template class SettingsVariable; - -// Containers are not to be used directly -template class SettingsVariable>; - -} // namespace scwx::qt::settings +} // namespace settings +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/settings/settings_variable.hpp b/scwx-qt/source/scwx/qt/settings/settings_variable.hpp index 3fc0b81d..581ebcbe 100644 --- a/scwx-qt/source/scwx/qt/settings/settings_variable.hpp +++ b/scwx-qt/source/scwx/qt/settings/settings_variable.hpp @@ -10,7 +10,11 @@ class QAbstractButton; class QWidget; -namespace scwx::qt::settings +namespace scwx +{ +namespace qt +{ +namespace settings { template @@ -25,7 +29,7 @@ public: typedef std::function ValueCallbackFunction; explicit SettingsVariable(const std::string& name); - virtual ~SettingsVariable(); + ~SettingsVariable(); SettingsVariable(const SettingsVariable&) = delete; SettingsVariable& operator=(const SettingsVariable&) = delete; @@ -33,24 +37,6 @@ public: SettingsVariable(SettingsVariable&&) noexcept; SettingsVariable& operator=(SettingsVariable&&) noexcept; - /** - * Gets whether or not the settings variable is currently set to its default - * value. - * - * @return true if the settings variable is currently set to its default - * value, otherwise false. - */ - bool IsDefault() const override; - - /** - * Gets whether or not the settings variable currently has its staged value - * set to default. - * - * @return true if the settings variable currently has its staged value set - * to default, otherwise false. - */ - bool IsDefaultStaged() const override; - /** * Gets the current value of the settings variable. * @@ -105,12 +91,12 @@ public: * @return true if the staged value was committed, false if no staged value * is present. */ - bool Commit() override; + bool Commit(); /** * Clears the staged value of the settings variable. */ - void Reset() override; + void Reset(); /** * Gets the staged value of the settings variable, if defined. @@ -246,12 +232,23 @@ public: void UnregisterValueStagedCallback(boost::uuids::uuid uuid); protected: - [[nodiscard]] virtual bool - Equals(const SettingsVariableBase& o) const override; + virtual bool Equals(const SettingsVariableBase& o) const override; private: class Impl; std::unique_ptr p; }; -} // namespace scwx::qt::settings +#ifdef SETTINGS_VARIABLE_IMPLEMENTATION +template class SettingsVariable; +template class SettingsVariable; +template class SettingsVariable; +template class SettingsVariable; + +// Containers are not to be used directly +template class SettingsVariable>; +#endif + +} // namespace settings +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/settings/settings_variable_base.cpp b/scwx-qt/source/scwx/qt/settings/settings_variable_base.cpp index f2941b9a..55ce72ea 100644 --- a/scwx-qt/source/scwx/qt/settings/settings_variable_base.cpp +++ b/scwx-qt/source/scwx/qt/settings/settings_variable_base.cpp @@ -1,6 +1,10 @@ #include -namespace scwx::qt::settings +namespace scwx +{ +namespace qt +{ +namespace settings { static const std::string logPrefix_ = @@ -11,16 +15,9 @@ class SettingsVariableBase::Impl public: explicit Impl(const std::string& name) : name_ {name} {} - ~Impl() = default; - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; + ~Impl() {} const std::string name_; - - boost::signals2::signal changedSignal_ {}; - boost::signals2::signal stagedSignal_ {}; }; SettingsVariableBase::SettingsVariableBase(const std::string& name) : @@ -41,16 +38,6 @@ std::string SettingsVariableBase::name() const return p->name_; } -boost::signals2::signal& SettingsVariableBase::changed_signal() -{ - return p->changedSignal_; -} - -boost::signals2::signal& SettingsVariableBase::staged_signal() -{ - return p->stagedSignal_; -} - bool SettingsVariableBase::Equals(const SettingsVariableBase& o) const { return p->name_ == o.p->name_; @@ -62,4 +49,6 @@ bool operator==(const SettingsVariableBase& lhs, return typeid(lhs) == typeid(rhs) && lhs.Equals(rhs); } -} // namespace scwx::qt::settings +} // namespace settings +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/settings/settings_variable_base.hpp b/scwx-qt/source/scwx/qt/settings/settings_variable_base.hpp index d613da91..f0444f45 100644 --- a/scwx-qt/source/scwx/qt/settings/settings_variable_base.hpp +++ b/scwx-qt/source/scwx/qt/settings/settings_variable_base.hpp @@ -4,9 +4,12 @@ #include #include -#include -namespace scwx::qt::settings +namespace scwx +{ +namespace qt +{ +namespace settings { /** @@ -16,7 +19,7 @@ class SettingsVariableBase { protected: explicit SettingsVariableBase(const std::string& name); - virtual ~SettingsVariableBase(); + ~SettingsVariableBase(); public: SettingsVariableBase(const SettingsVariableBase&) = delete; @@ -25,39 +28,7 @@ public: SettingsVariableBase(SettingsVariableBase&&) noexcept; SettingsVariableBase& operator=(SettingsVariableBase&&) noexcept; - [[nodiscard]] std::string name() const; - - /** - * Gets the signal invoked when the settings variable is changed. - * - * @return Changed signal - */ - boost::signals2::signal& changed_signal(); - - /** - * Gets the signal invoked when the settings variable is staged. - * - * @return Staged signal - */ - boost::signals2::signal& staged_signal(); - - /** - * Gets whether or not the settings variable is currently set to its default - * value. - * - * @return true if the settings variable is currently set to its default - * value, otherwise false. - */ - [[nodiscard]] virtual bool IsDefault() const = 0; - - /** - * Gets whether or not the settings variable currently has its staged value - * set to default. - * - * @return true if the settings variable currently has its staged value set - * to default, otherwise false. - */ - [[nodiscard]] virtual bool IsDefaultStaged() const = 0; + std::string name() const; /** * Sets the current value of the settings variable to default. @@ -77,11 +48,6 @@ public: */ virtual bool Commit() = 0; - /** - * Clears the staged value of the settings variable. - */ - virtual void Reset() = 0; - /** * Reads the value from the JSON object. If the read value is out of range, * the value is set to the minimum or maximum. If the read value fails @@ -103,7 +69,7 @@ public: protected: friend bool operator==(const SettingsVariableBase& lhs, const SettingsVariableBase& rhs); - [[nodiscard]] virtual bool Equals(const SettingsVariableBase& o) const; + virtual bool Equals(const SettingsVariableBase& o) const; private: class Impl; @@ -113,4 +79,6 @@ private: bool operator==(const SettingsVariableBase& lhs, const SettingsVariableBase& rhs); -} // namespace scwx::qt::settings +} // namespace settings +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/settings/text_settings.cpp b/scwx-qt/source/scwx/qt/settings/text_settings.cpp index b66268e0..942ad4f8 100644 --- a/scwx-qt/source/scwx/qt/settings/text_settings.cpp +++ b/scwx-qt/source/scwx/qt/settings/text_settings.cpp @@ -3,7 +3,11 @@ #include -namespace scwx::qt::settings +namespace scwx +{ +namespace qt +{ +namespace settings { static const std::string logPrefix_ = "scwx::qt::settings::text_settings"; @@ -46,15 +50,12 @@ public: boost::to_lower(defaultTooltipMethodValue); - // SetDefault, SetMinimum and SetMaximum are descriptive - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) hoverTextWrap_.SetDefault(80); hoverTextWrap_.SetMinimum(0); hoverTextWrap_.SetMaximum(999); placefileTextDropShadowEnabled_.SetDefault(true); radarSiteHoverTextEnabled_.SetDefault(true); tooltipMethod_.SetDefault(defaultTooltipMethodValue); - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) tooltipMethod_.SetValidator( [](const std::string& value) @@ -80,11 +81,7 @@ public: InitializeFontVariables(); } - ~Impl() = default; - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; + ~Impl() {} void InitializeFontVariables(); @@ -144,11 +141,8 @@ void TextSettings::Impl::InitializeFontVariables() { return !value.empty(); }); // Font point size must be between 6 and 72 - // SetDefault, SetMinimum and SetMaximum are descriptive - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) font.fontPointSize_.SetMinimum(6.0); font.fontPointSize_.SetMaximum(72.0); - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) // Variable registration auto& settings = fontSettings_.emplace_back( @@ -216,4 +210,6 @@ bool operator==(const TextSettings& lhs, const TextSettings& rhs) lhs.p->tooltipMethod_ == rhs.p->tooltipMethod_); } -} // namespace scwx::qt::settings +} // namespace settings +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/settings/text_settings.hpp b/scwx-qt/source/scwx/qt/settings/text_settings.hpp index 593702fe..2be5ab13 100644 --- a/scwx-qt/source/scwx/qt/settings/text_settings.hpp +++ b/scwx-qt/source/scwx/qt/settings/text_settings.hpp @@ -7,14 +7,18 @@ #include #include -namespace scwx::qt::settings +namespace scwx +{ +namespace qt +{ +namespace settings { class TextSettings : public SettingsCategory { public: explicit TextSettings(); - ~TextSettings() override; + ~TextSettings(); TextSettings(const TextSettings&) = delete; TextSettings& operator=(const TextSettings&) = delete; @@ -22,18 +26,17 @@ public: TextSettings(TextSettings&&) noexcept; TextSettings& operator=(TextSettings&&) noexcept; - [[nodiscard]] SettingsVariable& + SettingsVariable& font_family(types::FontCategory fontCategory) const; - [[nodiscard]] SettingsVariable& + SettingsVariable& font_style(types::FontCategory fontCategory) const; - [[nodiscard]] SettingsVariable& + SettingsVariable& font_point_size(types::FontCategory fontCategory) const; - [[nodiscard]] SettingsVariable& hover_text_wrap() const; - [[nodiscard]] SettingsVariable& - placefile_text_drop_shadow_enabled() const; - [[nodiscard]] SettingsVariable& radar_site_hover_text_enabled() const; - [[nodiscard]] SettingsVariable& tooltip_method() const; + SettingsVariable& hover_text_wrap() const; + SettingsVariable& placefile_text_drop_shadow_enabled() const; + SettingsVariable& radar_site_hover_text_enabled() const; + SettingsVariable& tooltip_method() const; static TextSettings& Instance(); @@ -45,4 +48,6 @@ private: std::unique_ptr p; }; -} // namespace scwx::qt::settings +} // namespace settings +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/settings/ui_settings.cpp b/scwx-qt/source/scwx/qt/settings/ui_settings.cpp index e4689120..dc131d96 100644 --- a/scwx-qt/source/scwx/qt/settings/ui_settings.cpp +++ b/scwx-qt/source/scwx/qt/settings/ui_settings.cpp @@ -1,6 +1,10 @@ #include -namespace scwx::qt::settings +namespace scwx +{ +namespace qt +{ +namespace settings { static const std::string logPrefix_ = "scwx::qt::settings::ui_settings"; @@ -10,31 +14,20 @@ class UiSettingsImpl public: explicit UiSettingsImpl() { - // SetDefault, SetMinimum and SetMaximum are descriptive - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) level2ProductsExpanded_.SetDefault(false); level2SettingsExpanded_.SetDefault(true); level3ProductsExpanded_.SetDefault(true); mapSettingsExpanded_.SetDefault(true); timelineExpanded_.SetDefault(true); - mainUIState_.SetDefault(""); - mainUIGeometry_.SetDefault(""); - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) } - ~UiSettingsImpl() = default; - UiSettingsImpl(const UiSettingsImpl&) = delete; - UiSettingsImpl& operator=(const UiSettingsImpl&) = delete; - UiSettingsImpl(const UiSettingsImpl&&) = delete; - UiSettingsImpl& operator=(const UiSettingsImpl&&) = delete; + ~UiSettingsImpl() {} SettingsVariable level2ProductsExpanded_ {"level2_products_expanded"}; SettingsVariable level2SettingsExpanded_ {"level2_settings_expanded"}; SettingsVariable level3ProductsExpanded_ {"level3_products_expanded"}; SettingsVariable mapSettingsExpanded_ {"map_settings_expanded"}; SettingsVariable timelineExpanded_ {"timeline_expanded"}; - SettingsVariable mainUIState_ {"main_ui_state"}; - SettingsVariable mainUIGeometry_ {"main_ui_geometry"}; }; UiSettings::UiSettings() : @@ -44,9 +37,7 @@ UiSettings::UiSettings() : &p->level2SettingsExpanded_, &p->level3ProductsExpanded_, &p->mapSettingsExpanded_, - &p->timelineExpanded_, - &p->mainUIState_, - &p->mainUIGeometry_}); + &p->timelineExpanded_}); SetDefaults(); } UiSettings::~UiSettings() = default; @@ -79,16 +70,6 @@ SettingsVariable& UiSettings::timeline_expanded() const return p->timelineExpanded_; } -SettingsVariable& UiSettings::main_ui_state() const -{ - return p->mainUIState_; -} - -SettingsVariable& UiSettings::main_ui_geometry() const -{ - return p->mainUIGeometry_; -} - bool UiSettings::Shutdown() { bool dataChanged = false; @@ -99,8 +80,6 @@ bool UiSettings::Shutdown() dataChanged |= p->level3ProductsExpanded_.Commit(); dataChanged |= p->mapSettingsExpanded_.Commit(); dataChanged |= p->timelineExpanded_.Commit(); - dataChanged |= p->mainUIState_.Commit(); - dataChanged |= p->mainUIGeometry_.Commit(); return dataChanged; } @@ -117,9 +96,9 @@ bool operator==(const UiSettings& lhs, const UiSettings& rhs) lhs.p->level2SettingsExpanded_ == rhs.p->level2SettingsExpanded_ && lhs.p->level3ProductsExpanded_ == rhs.p->level3ProductsExpanded_ && lhs.p->mapSettingsExpanded_ == rhs.p->mapSettingsExpanded_ && - lhs.p->timelineExpanded_ == rhs.p->timelineExpanded_ && - lhs.p->mainUIState_ == rhs.p->mainUIState_ && - lhs.p->mainUIGeometry_ == rhs.p->mainUIGeometry_); + lhs.p->timelineExpanded_ == rhs.p->timelineExpanded_); } -} // namespace scwx::qt::settings +} // namespace settings +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/settings/ui_settings.hpp b/scwx-qt/source/scwx/qt/settings/ui_settings.hpp index d8970c73..e3045bcb 100644 --- a/scwx-qt/source/scwx/qt/settings/ui_settings.hpp +++ b/scwx-qt/source/scwx/qt/settings/ui_settings.hpp @@ -6,7 +6,11 @@ #include #include -namespace scwx::qt::settings +namespace scwx +{ +namespace qt +{ +namespace settings { class UiSettingsImpl; @@ -15,7 +19,7 @@ class UiSettings : public SettingsCategory { public: explicit UiSettings(); - ~UiSettings() override; + ~UiSettings(); UiSettings(const UiSettings&) = delete; UiSettings& operator=(const UiSettings&) = delete; @@ -23,13 +27,11 @@ public: UiSettings(UiSettings&&) noexcept; UiSettings& operator=(UiSettings&&) noexcept; - [[nodiscard]] SettingsVariable& level2_products_expanded() const; - [[nodiscard]] SettingsVariable& level2_settings_expanded() const; - [[nodiscard]] SettingsVariable& level3_products_expanded() const; - [[nodiscard]] SettingsVariable& map_settings_expanded() const; - [[nodiscard]] SettingsVariable& timeline_expanded() const; - [[nodiscard]] SettingsVariable& main_ui_state() const; - [[nodiscard]] SettingsVariable& main_ui_geometry() const; + SettingsVariable& level2_products_expanded() const; + SettingsVariable& level2_settings_expanded() const; + SettingsVariable& level3_products_expanded() const; + SettingsVariable& map_settings_expanded() const; + SettingsVariable& timeline_expanded() const; bool Shutdown(); @@ -41,4 +43,6 @@ private: std::unique_ptr p; }; -} // namespace scwx::qt::settings +} // namespace settings +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/settings/unit_settings.cpp b/scwx-qt/source/scwx/qt/settings/unit_settings.cpp index 542ae153..c2cb0f11 100644 --- a/scwx-qt/source/scwx/qt/settings/unit_settings.cpp +++ b/scwx-qt/source/scwx/qt/settings/unit_settings.cpp @@ -4,7 +4,11 @@ #include -namespace scwx::qt::settings +namespace scwx +{ +namespace qt +{ +namespace settings { static const std::string logPrefix_ = "scwx::qt::settings::unit_settings"; @@ -31,14 +35,11 @@ public: boost::to_lower(defaultSpeedUnitsValue); boost::to_lower(defaultDistanceUnitsValue); - // SetDefault, SetMinimum and SetMaximum are descriptive - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) accumulationUnits_.SetDefault(defaultAccumulationUnitsValue); echoTopsUnits_.SetDefault(defaultEchoTopsUnitsValue); otherUnits_.SetDefault(defaultOtherUnitsValue); speedUnits_.SetDefault(defaultSpeedUnitsValue); distanceUnits_.SetDefault(defaultDistanceUnitsValue); - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) accumulationUnits_.SetValidator( SCWX_SETTINGS_ENUM_VALIDATOR(types::AccumulationUnits, @@ -62,11 +63,7 @@ public: types::GetDistanceUnitsName)); } - ~Impl() = default; - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; + ~Impl() {} SettingsVariable accumulationUnits_ {"accumulation_units"}; SettingsVariable echoTopsUnits_ {"echo_tops_units"}; @@ -130,4 +127,6 @@ bool operator==(const UnitSettings& lhs, const UnitSettings& rhs) lhs.p->distanceUnits_ == rhs.p->distanceUnits_); } -} // namespace scwx::qt::settings +} // namespace settings +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/settings/unit_settings.hpp b/scwx-qt/source/scwx/qt/settings/unit_settings.hpp index a7d06eed..15518492 100644 --- a/scwx-qt/source/scwx/qt/settings/unit_settings.hpp +++ b/scwx-qt/source/scwx/qt/settings/unit_settings.hpp @@ -6,14 +6,18 @@ #include #include -namespace scwx::qt::settings +namespace scwx +{ +namespace qt +{ +namespace settings { class UnitSettings : public SettingsCategory { public: explicit UnitSettings(); - ~UnitSettings() override; + ~UnitSettings(); UnitSettings(const UnitSettings&) = delete; UnitSettings& operator=(const UnitSettings&) = delete; @@ -21,11 +25,11 @@ public: UnitSettings(UnitSettings&&) noexcept; UnitSettings& operator=(UnitSettings&&) noexcept; - [[nodiscard]] SettingsVariable& accumulation_units() const; - [[nodiscard]] SettingsVariable& echo_tops_units() const; - [[nodiscard]] SettingsVariable& other_units() const; - [[nodiscard]] SettingsVariable& speed_units() const; - [[nodiscard]] SettingsVariable& distance_units() const; + SettingsVariable& accumulation_units() const; + SettingsVariable& echo_tops_units() const; + SettingsVariable& other_units() const; + SettingsVariable& speed_units() const; + SettingsVariable& distance_units() const; static UnitSettings& Instance(); @@ -36,4 +40,6 @@ private: std::unique_ptr p; }; -} // namespace scwx::qt::settings +} // namespace settings +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/types/hotkey_types.cpp b/scwx-qt/source/scwx/qt/types/hotkey_types.cpp index 7a121079..8a4d0ee5 100644 --- a/scwx-qt/source/scwx/qt/types/hotkey_types.cpp +++ b/scwx-qt/source/scwx/qt/types/hotkey_types.cpp @@ -13,7 +13,6 @@ namespace types { static const std::unordered_map hotkeyShortName_ { - {Hotkey::AddLocationMarker, "add_location_marker"}, {Hotkey::ChangeMapStyle, "change_map_style"}, {Hotkey::CopyCursorCoordinates, "copy_cursor_coordinates"}, {Hotkey::CopyMapCoordinates, "copy_map_coordinates"}, @@ -25,8 +24,6 @@ static const std::unordered_map hotkeyShortName_ { {Hotkey::MapRotateCounterclockwise, "map_rotate_counterclockwise"}, {Hotkey::MapZoomIn, "map_zoom_in"}, {Hotkey::MapZoomOut, "map_zoom_out"}, - {Hotkey::ProductCategoryNext, "product_category_next"}, - {Hotkey::ProductCategoryPrevious, "product_category_last"}, {Hotkey::ProductTiltDecrease, "product_tilt_decrease"}, {Hotkey::ProductTiltIncrease, "product_tilt_increase"}, {Hotkey::SelectLevel2Ref, "select_l2_ref"}, @@ -55,7 +52,6 @@ static const std::unordered_map hotkeyShortName_ { {Hotkey::Unknown, "?"}}; static const std::unordered_map hotkeyLongName_ { - {Hotkey::AddLocationMarker, "Add Location Marker"}, {Hotkey::ChangeMapStyle, "Change Map Style"}, {Hotkey::CopyCursorCoordinates, "Copy Cursor Coordinates"}, {Hotkey::CopyMapCoordinates, "Copy Map Coordinates"}, @@ -67,8 +63,6 @@ static const std::unordered_map hotkeyLongName_ { {Hotkey::MapRotateCounterclockwise, "Map Rotate Counterclockwise"}, {Hotkey::MapZoomIn, "Map Zoom In"}, {Hotkey::MapZoomOut, "Map Zoom Out"}, - {Hotkey::ProductCategoryNext, "Next Product in Category"}, - {Hotkey::ProductCategoryPrevious, "Previous Product in Category"}, {Hotkey::ProductTiltDecrease, "Product Tilt Decrease"}, {Hotkey::ProductTiltIncrease, "Product Tilt Increase"}, {Hotkey::SelectLevel2Ref, "Select L2 REF"}, diff --git a/scwx-qt/source/scwx/qt/types/hotkey_types.hpp b/scwx-qt/source/scwx/qt/types/hotkey_types.hpp index 6e770b67..c2118a4f 100644 --- a/scwx-qt/source/scwx/qt/types/hotkey_types.hpp +++ b/scwx-qt/source/scwx/qt/types/hotkey_types.hpp @@ -13,7 +13,6 @@ namespace types enum class Hotkey { - AddLocationMarker, ChangeMapStyle, CopyCursorCoordinates, CopyMapCoordinates, @@ -25,8 +24,6 @@ enum class Hotkey MapRotateCounterclockwise, MapZoomIn, MapZoomOut, - ProductCategoryPrevious, - ProductCategoryNext, ProductTiltDecrease, ProductTiltIncrease, SelectLevel2Ref, @@ -55,7 +52,7 @@ enum class Hotkey Unknown }; typedef scwx::util:: - Iterator + Iterator HotkeyIterator; Hotkey GetHotkeyFromShortName(const std::string& name); diff --git a/scwx-qt/source/scwx/qt/types/imgui_font.cpp b/scwx-qt/source/scwx/qt/types/imgui_font.cpp index f2cab082..e6f22ad1 100644 --- a/scwx-qt/source/scwx/qt/types/imgui_font.cpp +++ b/scwx-qt/source/scwx/qt/types/imgui_font.cpp @@ -23,8 +23,10 @@ static const auto logger_ = scwx::util::Logger::Create(logPrefix_); class ImGuiFont::Impl { public: - explicit Impl(std::string fontName, const std::vector& fontData) : - fontName_ {std::move(fontName)} + explicit Impl(const std::string& fontName, + const std::vector& fontData, + units::font_size::pixels size) : + fontName_ {fontName}, size_ {size} { CreateImGuiFont(fontData); } @@ -33,14 +35,16 @@ public: void CreateImGuiFont(const std::vector& fontData); - std::string fontName_; + const std::string fontName_; + const units::font_size::pixels size_; ImFont* imFont_ {nullptr}; }; -ImGuiFont::ImGuiFont(const std::string& fontName, - const std::vector& fontData) : - p(std::make_unique(fontName, fontData)) +ImGuiFont::ImGuiFont(const std::string& fontName, + const std::vector& fontData, + units::font_size::pixels size) : + p(std::make_unique(fontName, fontData, size)) { } ImGuiFont::~ImGuiFont() = default; @@ -49,12 +53,11 @@ void ImGuiFont::Impl::CreateImGuiFont(const std::vector& fontData) { logger_->debug("Creating Font: {}", fontName_); - // Default render size, used in debug widget - static constexpr float kSizePixels_ = 16.0f; - ImFontAtlas* fontAtlas = model::ImGuiContextModel::Instance().font_atlas(); ImFontConfig fontConfig {}; + const float sizePixels = static_cast(size_.value()); + // Do not transfer ownership of font data to ImGui, makes const_cast safe fontConfig.FontDataOwnedByAtlas = false; @@ -66,7 +69,7 @@ void ImGuiFont::Impl::CreateImGuiFont(const std::vector& fontData) const_cast(static_cast(fontData.data())), static_cast(std::clamp( fontData.size(), 0, std::numeric_limits::max())), - kSizePixels_, + sizePixels, &fontConfig); } diff --git a/scwx-qt/source/scwx/qt/types/imgui_font.hpp b/scwx-qt/source/scwx/qt/types/imgui_font.hpp index d1c28a0c..ace8ba09 100644 --- a/scwx-qt/source/scwx/qt/types/imgui_font.hpp +++ b/scwx-qt/source/scwx/qt/types/imgui_font.hpp @@ -4,6 +4,8 @@ #include #include +#include + struct ImFont; namespace scwx @@ -16,8 +18,9 @@ namespace types class ImGuiFont { public: - explicit ImGuiFont(const std::string& fontName, - const std::vector& fontData); + explicit ImGuiFont(const std::string& fontName, + const std::vector& fontData, + units::font_size::pixels size); ~ImGuiFont(); ImGuiFont(const ImGuiFont&) = delete; diff --git a/scwx-qt/source/scwx/qt/types/layer_types.cpp b/scwx-qt/source/scwx/qt/types/layer_types.cpp index bd607cc7..6e66c5d1 100644 --- a/scwx-qt/source/scwx/qt/types/layer_types.cpp +++ b/scwx-qt/source/scwx/qt/types/layer_types.cpp @@ -31,7 +31,6 @@ static const std::unordered_map informationLayerName_ {{InformationLayer::MapOverlay, "Map Overlay"}, {InformationLayer::RadarSite, "Radar Sites"}, {InformationLayer::ColorTable, "Color Table"}, - {InformationLayer::Markers, "Location Markers"}, {InformationLayer::Unknown, "?"}}; static const std::unordered_map mapLayerName_ { diff --git a/scwx-qt/source/scwx/qt/types/layer_types.hpp b/scwx-qt/source/scwx/qt/types/layer_types.hpp index bfc10839..f0561a6e 100644 --- a/scwx-qt/source/scwx/qt/types/layer_types.hpp +++ b/scwx-qt/source/scwx/qt/types/layer_types.hpp @@ -44,7 +44,6 @@ enum class InformationLayer MapOverlay, RadarSite, ColorTable, - Markers, Unknown }; diff --git a/scwx-qt/source/scwx/qt/types/marker_types.hpp b/scwx-qt/source/scwx/qt/types/marker_types.hpp deleted file mode 100644 index 661aa207..00000000 --- a/scwx-qt/source/scwx/qt/types/marker_types.hpp +++ /dev/null @@ -1,82 +0,0 @@ -#pragma once - -#include - -#include -#include -#include - -#include -#include -#include - -namespace scwx::qt::types -{ -using MarkerId = std::uint64_t; - -struct MarkerInfo -{ - MarkerInfo(std::string name, - double latitude, - double longitude, - std::string iconName, - const boost::gil::rgba8_pixel_t& iconColor) : - name {std::move(name)}, - latitude {latitude}, - longitude {longitude}, - iconName {std::move(iconName)}, - iconColor {iconColor} - { - } - - MarkerId id {0}; - std::string name; - double latitude; - double longitude; - std::string iconName; - boost::gil::rgba8_pixel_t iconColor; -}; - -struct MarkerIconInfo -{ - // Initializer for default icons (which use a texture) - explicit MarkerIconInfo(types::ImageTexture texture, - std::int32_t hotX, - std::int32_t hotY) : - name {types::GetTextureName(texture)}, - path {types::GetTexturePath(texture)}, - hotX {hotX}, - hotY {hotY}, - qIcon {QIcon(QString::fromStdString(path))}, - image {} - { - auto qName = QString::fromStdString(name); - QStringList parts = qName.split("location-"); - shortName = parts.last().toStdString(); - } - - // Initializer for custom icons (which use a file path) - explicit MarkerIconInfo(const std::string& path, - std::int32_t hotX, - std::int32_t hotY, - std::shared_ptr image) : - name {path}, - path {path}, - shortName {QFileInfo(path.c_str()).fileName().toStdString()}, - hotX {hotX}, - hotY {hotY}, - qIcon {QIcon(QString::fromStdString(path))}, - image {image} - { - } - - std::string name; - std::string path; - std::string shortName; - std::int32_t hotX; - std::int32_t hotY; - QIcon qIcon; - std::optional> image; -}; - -} // namespace scwx::qt::types diff --git a/scwx-qt/source/scwx/qt/types/qt_types.cpp b/scwx-qt/source/scwx/qt/types/qt_types.cpp index 0c10feb2..37717646 100644 --- a/scwx-qt/source/scwx/qt/types/qt_types.cpp +++ b/scwx-qt/source/scwx/qt/types/qt_types.cpp @@ -1,5 +1,4 @@ #include -#include #include @@ -10,76 +9,27 @@ namespace qt namespace types { -static const std::unordered_map qtStyleName_ { - {UiStyle::Default, "Default"}, - {UiStyle::Fusion, "Fusion"}, - {UiStyle::FusionLight, "Fusion"}, - {UiStyle::FusionDark, "Fusion"}, - {UiStyle::FusionAiry, "Fusion"}, - {UiStyle::FusionDarker, "Fusion"}, - {UiStyle::FusionDusk, "Fusion"}, - {UiStyle::FusionIaOra, "Fusion"}, - {UiStyle::FusionSand, "Fusion"}, - {UiStyle::FusionWaves, "Fusion"}, - {UiStyle::FusionCustom, "Fusion"}, - {UiStyle::Unknown, "?"}}; - static const std::unordered_map uiStyleName_ { {UiStyle::Default, "Default"}, {UiStyle::Fusion, "Fusion"}, - {UiStyle::FusionLight, "Fusion Light"}, - {UiStyle::FusionDark, "Fusion Dark"}, - {UiStyle::FusionAiry, "Fusion Airy"}, - {UiStyle::FusionDarker, "Fusion Darker"}, - {UiStyle::FusionDusk, "Fusion Dusk"}, - {UiStyle::FusionIaOra, "Fusion IA Ora"}, - {UiStyle::FusionSand, "Fusion Sand"}, - {UiStyle::FusionWaves, "Fusion Waves"}, - {UiStyle::FusionCustom, "Fusion Custom"}, {UiStyle::Unknown, "?"}}; -static const std::unordered_map qtColorSchemeMap_ { - {UiStyle::Default, Qt::ColorScheme::Unknown}, - {UiStyle::Fusion, Qt::ColorScheme::Unknown}, - {UiStyle::FusionLight, Qt::ColorScheme::Light}, - {UiStyle::FusionDark, Qt::ColorScheme::Dark}, - {UiStyle::FusionAiry, Qt::ColorScheme::Unknown}, - {UiStyle::FusionDarker, Qt::ColorScheme::Unknown}, - {UiStyle::FusionDusk, Qt::ColorScheme::Unknown}, - {UiStyle::FusionIaOra, Qt::ColorScheme::Unknown}, - {UiStyle::FusionSand, Qt::ColorScheme::Unknown}, - {UiStyle::FusionWaves, Qt::ColorScheme::Unknown}, - {UiStyle::FusionCustom, Qt::ColorScheme::Unknown}, - {UiStyle::Unknown, Qt::ColorScheme::Unknown}}; - -static const std::unordered_map paletteFile_ { - {UiStyle::FusionAiry, ":res/qt6ct_colors/airy.conf"}, - {UiStyle::FusionDarker, ":res/qt6ct_colors/darker.conf"}, - {UiStyle::FusionDusk, ":res/qt6ct_colors/dusk.conf"}, - {UiStyle::FusionIaOra, ":res/qt6ct_colors/ia_ora.conf"}, - {UiStyle::FusionSand, ":res/qt6ct_colors/sand.conf"}, - {UiStyle::FusionWaves, ":res/qt6ct_colors/waves.conf"}}; - -SCWX_GET_ENUM(UiStyle, GetUiStyle, uiStyleName_) - -Qt::ColorScheme GetQtColorScheme(UiStyle uiStyle) +UiStyle GetUiStyle(const std::string& name) { - return qtColorSchemeMap_.at(uiStyle); -} + auto result = + std::find_if(uiStyleName_.cbegin(), + uiStyleName_.cend(), + [&](const std::pair& pair) -> bool + { return boost::iequals(pair.second, name); }); -std::string GetQtStyleName(UiStyle uiStyle) -{ - return qtStyleName_.at(uiStyle); -} - -std::optional GetQtPaletteFile(UiStyle uiStyle) -{ - if (paletteFile_.contains(uiStyle)) + if (result != uiStyleName_.cend()) { - return paletteFile_.at(uiStyle); + return result->first; + } + else + { + return UiStyle::Unknown; } - - return std::nullopt; } std::string GetUiStyleName(UiStyle uiStyle) diff --git a/scwx-qt/source/scwx/qt/types/qt_types.hpp b/scwx-qt/source/scwx/qt/types/qt_types.hpp index b5779ff1..26a41c25 100644 --- a/scwx-qt/source/scwx/qt/types/qt_types.hpp +++ b/scwx-qt/source/scwx/qt/types/qt_types.hpp @@ -2,7 +2,6 @@ #include -#include #include #include @@ -21,31 +20,17 @@ enum ItemDataRole RawDataRole }; -enum class UiStyle +enum UiStyle { Default, Fusion, - FusionLight, - FusionDark, - FusionAiry, - FusionDarker, - FusionDusk, - FusionIaOra, - FusionSand, - FusionWaves, - FusionCustom, Unknown }; -typedef scwx::util::Iterator +typedef scwx::util::Iterator UiStyleIterator; -Qt::ColorScheme GetQtColorScheme(UiStyle uiStyle); -std::string GetQtStyleName(UiStyle uiStyle); - -std::optional GetQtPaletteFile(UiStyle uiStyle); - UiStyle GetUiStyle(const std::string& name); -std::string GetUiStyleName(UiStyle uiStyle); +std::string GetUiStyleName(UiStyle alertAction); } // namespace types } // namespace qt diff --git a/scwx-qt/source/scwx/qt/types/text_event_key.cpp b/scwx-qt/source/scwx/qt/types/text_event_key.cpp index be5d0443..bebf6f63 100644 --- a/scwx-qt/source/scwx/qt/types/text_event_key.cpp +++ b/scwx-qt/source/scwx/qt/types/text_event_key.cpp @@ -14,29 +14,26 @@ static const std::string logPrefix_ = "scwx::qt::types::text_event_key"; std::string TextEventKey::ToFullString() const { - return fmt::format("{} {} {} {:04} ({:04})", + return fmt::format("{} {} {} {:04}", officeId_, awips::GetPhenomenonText(phenomenon_), awips::GetSignificanceText(significance_), - etn_, - static_cast(year_)); + etn_); } std::string TextEventKey::ToString() const { - return fmt::format("{}.{}.{}.{:04}.{:04}", + return fmt::format("{}.{}.{}.{:04}", officeId_, awips::GetPhenomenonCode(phenomenon_), awips::GetSignificanceCode(significance_), - etn_, - static_cast(year_)); + etn_); } bool TextEventKey::operator==(const TextEventKey& o) const { return (officeId_ == o.officeId_ && phenomenon_ == o.phenomenon_ && - significance_ == o.significance_ && etn_ == o.etn_ && - year_ == o.year_); + significance_ == o.significance_ && etn_ == o.etn_); } size_t TextEventHash::operator()(const TextEventKey& x) const @@ -46,7 +43,6 @@ size_t TextEventHash::operator()(const TextEventKey& x) const boost::hash_combine(seed, x.phenomenon_); boost::hash_combine(seed, x.significance_); boost::hash_combine(seed, x.etn_); - boost::hash_combine(seed, static_cast(x.year_)); return seed; } diff --git a/scwx-qt/source/scwx/qt/types/text_event_key.hpp b/scwx-qt/source/scwx/qt/types/text_event_key.hpp index 15eec31c..f962bcdf 100644 --- a/scwx-qt/source/scwx/qt/types/text_event_key.hpp +++ b/scwx-qt/source/scwx/qt/types/text_event_key.hpp @@ -1,7 +1,6 @@ #pragma once #include -#include namespace scwx { @@ -13,34 +12,12 @@ namespace types struct TextEventKey { TextEventKey() : TextEventKey(awips::PVtec {}) {} - TextEventKey(const awips::PVtec& pvtec, std::chrono::year yearHint = {}) : + TextEventKey(const awips::PVtec& pvtec) : officeId_ {pvtec.office_id()}, phenomenon_ {pvtec.phenomenon()}, significance_ {pvtec.significance()}, etn_ {pvtec.event_tracking_number()} { - using namespace std::chrono_literals; - - static constexpr std::chrono::year kMinYear_ = 1970y; - - std::chrono::year_month_day ymd = - std::chrono::floor(pvtec.event_begin()); - if (ymd.year() > kMinYear_) - { - // Prefer the year from the event begin - year_ = ymd.year(); - } - else if (yearHint > kMinYear_) - { - // Otherwise, use the year hint - year_ = yearHint; - } - else - { - // If there was no year hint, use the event end - ymd = std::chrono::floor(pvtec.event_end()); - year_ = ymd.year(); - } } std::string ToFullString() const; @@ -50,8 +27,7 @@ struct TextEventKey std::string officeId_; awips::Phenomenon phenomenon_; awips::Significance significance_; - std::int16_t etn_; - std::chrono::year year_ {}; + int16_t etn_; }; template diff --git a/scwx-qt/source/scwx/qt/types/texture_types.cpp b/scwx-qt/source/scwx/qt/types/texture_types.cpp index 2369dc34..5f7da52b 100644 --- a/scwx-qt/source/scwx/qt/types/texture_types.cpp +++ b/scwx-qt/source/scwx/qt/types/texture_types.cpp @@ -24,34 +24,7 @@ static const std::unordered_map imageTextureInfo_ { {"images/crosshairs-24", ":/res/textures/images/crosshairs-24.png"}}, {ImageTexture::Cursor17, {"images/cursor-17", ":/res/textures/images/cursor-17.png"}}, - {ImageTexture::Dot3, {"images/dot-3", ":/res/textures/images/dot.svg"}}, - {ImageTexture::LocationBriefcase, - {"images/location-briefcase", - ":/res/icons/font-awesome-6/briefcase-solid.svg"}}, - {ImageTexture::LocationBuildingColumns, - {"images/location-building-columns", - ":/res/icons/font-awesome-6/building-columns-solid.svg"}}, - {ImageTexture::LocationBuilding, - {"images/location-building", - ":/res/icons/font-awesome-6/building-solid.svg"}}, - {ImageTexture::LocationCaravan, - {"images/location-caravan", - ":/res/icons/font-awesome-6/caravan-solid.svg"}}, - {ImageTexture::LocationCrosshair, - {"images/location-crosshair", - ":/res/icons/font-awesome-6/location-crosshairs-solid.svg"}}, - {ImageTexture::LocationHouse, - {"images/location-house", - ":/res/icons/font-awesome-6/house-solid-white.svg"}}, - {ImageTexture::LocationMarker, - {"images/location-marker", ":/res/textures/images/location-marker.svg"}}, - {ImageTexture::LocationPin, - {"images/location-pin", ":/res/icons/font-awesome-6/location-pin.svg"}}, - {ImageTexture::LocationStar, - {"images/location-star", - ":/res/icons/font-awesome-6/star-solid-white.svg"}}, - {ImageTexture::LocationTent, - {"images/location-tent", ":/res/icons/font-awesome-6/tent-solid.svg"}}, + {ImageTexture::Dot3, {"images/dot-3", ":/res/textures/images/dot-3.png"}}, {ImageTexture::MapboxLogo, {"images/mapbox-logo", ":/res/textures/images/mapbox-logo.svg"}}, {ImageTexture::MapTilerLogo, diff --git a/scwx-qt/source/scwx/qt/types/texture_types.hpp b/scwx-qt/source/scwx/qt/types/texture_types.hpp index d5eabc4a..593d574d 100644 --- a/scwx-qt/source/scwx/qt/types/texture_types.hpp +++ b/scwx-qt/source/scwx/qt/types/texture_types.hpp @@ -18,16 +18,6 @@ enum class ImageTexture Crosshairs24, Cursor17, Dot3, - LocationBriefcase, - LocationBuildingColumns, - LocationBuilding, - LocationCaravan, - LocationCrosshair, - LocationHouse, - LocationMarker, - LocationPin, - LocationStar, - LocationTent, MapboxLogo, MapTilerLogo }; diff --git a/scwx-qt/source/scwx/qt/ui/about_dialog.cpp b/scwx-qt/source/scwx/qt/ui/about_dialog.cpp index 9ae6ce18..42ec4e32 100644 --- a/scwx-qt/source/scwx/qt/ui/about_dialog.cpp +++ b/scwx-qt/source/scwx/qt/ui/about_dialog.cpp @@ -24,19 +24,13 @@ AboutDialog::AboutDialog(QWidget* parent) : p {std::make_unique()}, ui(new Ui::AboutDialog) { -#if !defined(__APPLE__) - static constexpr int titleFontSize = 14; -#else - static constexpr int titleFontSize = 18; -#endif - ui->setupUi(this); - const int titleFontId = + int titleFontId = manager::FontManager::Instance().GetFontId(types::Font::din1451alt_g); - const QString titleFontFamily = + QString titleFontFamily = QFontDatabase::applicationFontFamilies(titleFontId).at(0); - const QFont titleFont(titleFontFamily, titleFontSize); + QFont titleFont(titleFontFamily, 14); ui->titleLabel->setFont(titleFont); QString repositoryUrl = @@ -51,9 +45,7 @@ AboutDialog::AboutDialog(QWidget* parent) : } ui->versionLabel->setText( - tr("Version %1 (Build %2)") - .arg(QString::fromStdString(main::kVersionString_)) - .arg(main::kBuildNumber_)); + tr("Version %1").arg(QString::fromStdString(main::kVersionString_))); ui->revisionLabel->setText( tr("Git Revision %2") .arg(repositoryUrl) diff --git a/scwx-qt/source/scwx/qt/ui/about_dialog.ui b/scwx-qt/source/scwx/qt/ui/about_dialog.ui index f8ef5270..64e8ed46 100644 --- a/scwx-qt/source/scwx/qt/ui/about_dialog.ui +++ b/scwx-qt/source/scwx/qt/ui/about_dialog.ui @@ -16,6 +16,12 @@ + + QFrame::StyledPanel + + + QFrame::Raised + 0 @@ -38,7 +44,7 @@ :/res/icons/scwx-256.png - Qt::AlignmentFlag::AlignCenter + Qt::AlignCenter @@ -48,7 +54,7 @@ Supercell Wx - Qt::AlignmentFlag::AlignCenter + Qt::AlignCenter @@ -58,7 +64,7 @@ Version X.Y.Z - Qt::AlignmentFlag::AlignCenter + Qt::AlignCenter @@ -68,7 +74,7 @@ Git Revision 0000000000 - Qt::AlignmentFlag::AlignCenter + Qt::AlignCenter @@ -78,7 +84,7 @@ Copyright © 2021-YYYY Dan Paulat - Qt::AlignmentFlag::AlignCenter + Qt::AlignCenter @@ -88,10 +94,10 @@ - Qt::Orientation::Horizontal + Qt::Horizontal - QDialogButtonBox::StandardButton::Ok + QDialogButtonBox::Ok diff --git a/scwx-qt/source/scwx/qt/ui/alert_dialog.cpp b/scwx-qt/source/scwx/qt/ui/alert_dialog.cpp index 3d9d1af5..76aa284a 100644 --- a/scwx-qt/source/scwx/qt/ui/alert_dialog.cpp +++ b/scwx-qt/source/scwx/qt/ui/alert_dialog.cpp @@ -54,13 +54,7 @@ AlertDialog::AlertDialog(QWidget* parent) : // Set monospace font for alert view QFont monospaceFont("?"); - monospaceFont.setStyleHint(QFont::StyleHint::TypeWriter); - - if (!monospaceFont.fixedPitch()) - { - monospaceFont.setStyleHint(QFont::StyleHint::Monospace); - } - + monospaceFont.setStyleHint(QFont::TypeWriter); ui->alertText->setFont(monospaceFont); // Add Go button to button box diff --git a/scwx-qt/source/scwx/qt/ui/alert_dialog.ui b/scwx-qt/source/scwx/qt/ui/alert_dialog.ui index f180dc71..55686925 100644 --- a/scwx-qt/source/scwx/qt/ui/alert_dialog.ui +++ b/scwx-qt/source/scwx/qt/ui/alert_dialog.ui @@ -17,12 +17,18 @@ - QTextEdit::LineWrapMode::NoWrap + QTextEdit::NoWrap + + QFrame::StyledPanel + + + QFrame::Raised + 0 @@ -102,7 +108,7 @@ - Qt::Orientation::Horizontal + Qt::Horizontal @@ -115,10 +121,10 @@ - Qt::Orientation::Horizontal + Qt::Horizontal - QDialogButtonBox::StandardButton::Close + QDialogButtonBox::Close diff --git a/scwx-qt/source/scwx/qt/ui/alert_dock_widget.cpp b/scwx-qt/source/scwx/qt/ui/alert_dock_widget.cpp index 5e22071a..61fd160a 100644 --- a/scwx-qt/source/scwx/qt/ui/alert_dock_widget.cpp +++ b/scwx-qt/source/scwx/qt/ui/alert_dock_widget.cpp @@ -131,11 +131,6 @@ void AlertDockWidgetImpl::ConnectSignals() &QAction::toggled, proxyModel_.get(), &model::AlertProxyModel::SetAlertActiveFilter); - connect(textEventManager_.get(), - &manager::TextEventManager::AlertsRemoved, - alertModel_.get(), - &model::AlertModel::HandleAlertsRemoved, - Qt::QueuedConnection); connect(textEventManager_.get(), &manager::TextEventManager::AlertUpdated, alertModel_.get(), diff --git a/scwx-qt/source/scwx/qt/ui/alert_dock_widget.ui b/scwx-qt/source/scwx/qt/ui/alert_dock_widget.ui index 317fc566..96328278 100644 --- a/scwx-qt/source/scwx/qt/ui/alert_dock_widget.ui +++ b/scwx-qt/source/scwx/qt/ui/alert_dock_widget.ui @@ -30,6 +30,12 @@ + + QFrame::StyledPanel + + + QFrame::Raised + 0 @@ -56,7 +62,7 @@ - Qt::Orientation::Horizontal + Qt::Horizontal @@ -79,7 +85,7 @@ :/res/icons/font-awesome-6/sliders-solid.svg:/res/icons/font-awesome-6/sliders-solid.svg - QToolButton::ToolButtonPopupMode::InstantPopup + QToolButton::InstantPopup diff --git a/scwx-qt/source/scwx/qt/ui/animation_dock_widget.cpp b/scwx-qt/source/scwx/qt/ui/animation_dock_widget.cpp index eac16c44..12d94d27 100644 --- a/scwx-qt/source/scwx/qt/ui/animation_dock_widget.cpp +++ b/scwx-qt/source/scwx/qt/ui/animation_dock_widget.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include @@ -19,14 +18,6 @@ namespace ui static const std::string logPrefix_ = "scwx::qt::ui::animation_dock_widget"; static const auto logger_ = scwx::util::Logger::Create(logPrefix_); -#if (__cpp_lib_chrono >= 201907L) -using local_days = std::chrono::local_days; -using zoned_time_ = std::chrono::zoned_time; -#else -using local_days = date::local_days; -using zoned_time_ = date::zoned_time; -#endif - class AnimationDockWidgetImpl { public: @@ -56,14 +47,8 @@ public: types::MapTime viewType_ {types::MapTime::Live}; bool isLive_ {true}; - local_days selectedDate_ {}; - std::chrono::seconds selectedTime_ {}; - - const scwx::util::time_zone* timeZone_ {nullptr}; - - void UpdateTimeZoneLabel(const zoned_time_ zonedTime); - std::chrono::system_clock::time_point GetTimePoint(); - void SetTimePoint(std::chrono::system_clock::time_point time); + std::chrono::sys_days selectedDate_ {}; + std::chrono::seconds selectedTime_ {}; void ConnectSignals(); void UpdateAutoUpdateLabel(); @@ -76,18 +61,19 @@ AnimationDockWidget::AnimationDockWidget(QWidget* parent) : { ui->setupUi(this); -#if (__cpp_lib_chrono >= 201907L) - p->timeZone_ = std::chrono::get_tzdb().locate_zone("UTC"); -#else - p->timeZone_ = date::get_tzdb().locate_zone("UTC"); -#endif - const std::chrono::sys_seconds currentTimePoint = - std::chrono::floor(scwx::util::time::now()); - p->SetTimePoint(currentTimePoint); + // Set current date/time + QDateTime currentDateTime = QDateTime::currentDateTimeUtc(); + QDate currentDate = currentDateTime.date(); + QTime currentTime = currentDateTime.time(); + ui->dateEdit->setDate(currentDate); + ui->timeEdit->setTime(currentTime); + ui->dateEdit->setMaximumDate(currentDateTime.date()); + p->selectedDate_ = util::SysDays(currentDate); + p->selectedTime_ = + std::chrono::seconds(currentTime.msecsSinceStartOfDay() / 1000); // Update maximum date on a timer - // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) Qt Owns this memory - auto* maxDateTimer = new QTimer(this); + QTimer* maxDateTimer = new QTimer(this); connect(maxDateTimer, &QTimer::timeout, this, @@ -120,76 +106,6 @@ AnimationDockWidget::~AnimationDockWidget() delete ui; } -void AnimationDockWidgetImpl::UpdateTimeZoneLabel(const zoned_time_ zonedTime) -{ -#if (__cpp_lib_chrono >= 201907L) - namespace df = std; - static constexpr std::string_view kFormatStringTimezone = "{:%Z}"; -#else - namespace df = date; - static const std::string kFormatStringTimezone = "%Z"; -#endif - const std::string timeZoneStr = df::format(kFormatStringTimezone, zonedTime); - self_->ui->timeZoneLabel->setText(timeZoneStr.c_str()); -} - -std::chrono::system_clock::time_point AnimationDockWidgetImpl::GetTimePoint() -{ -#if (__cpp_lib_chrono >= 201907L) - using namespace std::chrono; -#else - using namespace date; -#endif - - // Convert the local time, to a zoned time, to a system time - const local_time localTime = - selectedDate_ + selectedTime_; - const auto zonedTime = - zoned_time(timeZone_, localTime); - const std::chrono::sys_seconds systemTime = zonedTime.get_sys_time(); - - // This is done to update it when the date changes - UpdateTimeZoneLabel(zonedTime); - - return systemTime; -} - -void AnimationDockWidgetImpl::SetTimePoint( - std::chrono::system_clock::time_point systemTime) -{ -#if (__cpp_lib_chrono >= 201907L) - using namespace std::chrono; -#else - using namespace date; -#endif - // Convert the time to a local time - auto systemTimeSeconds = time_point_cast(systemTime); - auto zonedTime = - zoned_time(timeZone_, systemTimeSeconds); - const local_seconds localTime = zonedTime.get_local_time(); - - // Get the date and time as seperate fields - selectedDate_ = floor(localTime); - selectedTime_ = localTime - selectedDate_; - - // Pull out the local date and time as qt times (with c++20 this could be - // simplified) - auto time = QTime::fromMSecsSinceStartOfDay(static_cast( - duration_cast(selectedTime_).count())); - auto yearMonthDay = year_month_day(selectedDate_); - auto date = QDate(int(yearMonthDay.year()), - // These are always in a small range, so cast is safe - static_cast(unsigned(yearMonthDay.month())), - static_cast(unsigned(yearMonthDay.day()))); - - // Update labels - self_->ui->timeEdit->setTime(time); - self_->ui->dateEdit->setDate(date); - - // Time zone almost certainly just changed, so update it - UpdateTimeZoneLabel(zonedTime); -} - void AnimationDockWidgetImpl::ConnectSignals() { // View type @@ -224,8 +140,8 @@ void AnimationDockWidgetImpl::ConnectSignals() { if (date.isValid()) { - selectedDate_ = util::LocalDays(date); - Q_EMIT self_->DateTimeChanged(GetTimePoint()); + selectedDate_ = util::SysDays(date); + Q_EMIT self_->DateTimeChanged(selectedDate_ + selectedTime_); } }); QObject::connect( @@ -236,9 +152,9 @@ void AnimationDockWidgetImpl::ConnectSignals() { if (time.isValid()) { - selectedTime_ = std::chrono::duration_cast( - std::chrono::milliseconds(time.msecsSinceStartOfDay())); - Q_EMIT self_->DateTimeChanged(GetTimePoint()); + selectedTime_ = + std::chrono::seconds(time.msecsSinceStartOfDay() / 1000); + Q_EMIT self_->DateTimeChanged(selectedDate_ + selectedTime_); } }); @@ -384,27 +300,6 @@ void AnimationDockWidgetImpl::UpdateAutoUpdateLabel() } } -void AnimationDockWidget::UpdateTimeZone(const scwx::util::time_zone* timeZone) -{ - // null timezone is really UTC. This simplifies other code. - if (timeZone == nullptr) - { -#if (__cpp_lib_chrono >= 201907L) - timeZone = std::chrono::get_tzdb().locate_zone("UTC"); -#else - timeZone = date::get_tzdb().locate_zone("UTC"); -#endif - } - - // Get the (UTC relative) time that is selected. We want to preserve this - // across timezone changes. - auto currentTime = p->GetTimePoint(); - p->timeZone_ = timeZone; - // Set the (UTC relative) time that was already selected. This ensures that - // the actual time does not change, only the time zone. - p->SetTimePoint(currentTime); -} - } // namespace ui } // namespace qt } // namespace scwx diff --git a/scwx-qt/source/scwx/qt/ui/animation_dock_widget.hpp b/scwx-qt/source/scwx/qt/ui/animation_dock_widget.hpp index c22b0849..abc79c88 100644 --- a/scwx-qt/source/scwx/qt/ui/animation_dock_widget.hpp +++ b/scwx-qt/source/scwx/qt/ui/animation_dock_widget.hpp @@ -1,7 +1,6 @@ #pragma once #include -#include #include @@ -33,7 +32,6 @@ public slots: void UpdateAnimationState(types::AnimationState state); void UpdateLiveState(bool isLive); void UpdateViewType(types::MapTime viewType); - void UpdateTimeZone(const scwx::util::time_zone* timeZone); signals: void ViewTypeChanged(types::MapTime viewType); diff --git a/scwx-qt/source/scwx/qt/ui/animation_dock_widget.ui b/scwx-qt/source/scwx/qt/ui/animation_dock_widget.ui index dbbed2a7..1c79eb48 100644 --- a/scwx-qt/source/scwx/qt/ui/animation_dock_widget.ui +++ b/scwx-qt/source/scwx/qt/ui/animation_dock_widget.ui @@ -7,9 +7,15 @@ 0 0 189 - 276 + 264 + + QFrame::StyledPanel + + + QFrame::Raised + 0 @@ -50,7 +56,7 @@ - QAbstractSpinBox::CorrectionMode::CorrectToNearestValue + QAbstractSpinBox::CorrectToNearestValue @@ -72,6 +78,12 @@ + + QFrame::StyledPanel + + + QFrame::Raised + 0 @@ -88,7 +100,7 @@ - QAbstractSpinBox::CorrectionMode::CorrectToNearestValue + QAbstractSpinBox::CorrectToNearestValue HH:mm @@ -96,7 +108,7 @@ - + UTC @@ -107,6 +119,12 @@ + + QFrame::StyledPanel + + + QFrame::Raised + 0 @@ -123,7 +141,7 @@ - QAbstractSpinBox::CorrectionMode::CorrectToNearestValue + QAbstractSpinBox::CorrectToNearestValue min @@ -132,7 +150,7 @@ 1 - 2880 + 1440 30 @@ -175,7 +193,7 @@ - QAbstractSpinBox::CorrectionMode::CorrectToNearestValue + QAbstractSpinBox::CorrectToNearestValue x @@ -200,6 +218,12 @@ + + QFrame::StyledPanel + + + QFrame::Raised + 1 diff --git a/scwx-qt/source/scwx/qt/ui/api_key_edit_widget.cpp b/scwx-qt/source/scwx/qt/ui/api_key_edit_widget.cpp deleted file mode 100644 index 73f936b5..00000000 --- a/scwx-qt/source/scwx/qt/ui/api_key_edit_widget.cpp +++ /dev/null @@ -1,107 +0,0 @@ -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace scwx::qt::ui; - -static const std::string logPrefix_ = "scwx::qt::ui::QApiKeyEdit"; -static const auto logger_ = scwx::util::Logger::Create(logPrefix_); - -QApiKeyEdit::QApiKeyEdit(QWidget* parent) : - QLineEdit(parent), networkAccessManager_(new QNetworkAccessManager(this)) -{ - const QIcon icon = - QApplication::style()->standardIcon(QStyle::SP_BrowserReload); - testAction_ = addAction(icon, QLineEdit::TrailingPosition); - testAction_->setIconText(tr("Test Key")); - testAction_->setToolTip(tr("Test the API key for this provider")); - - connect(testAction_, &QAction::triggered, this, &QApiKeyEdit::apiTest); - connect(networkAccessManager_, - &QNetworkAccessManager::finished, - this, - &QApiKeyEdit::apiTestFinished); - - // Reset test icon when text changes - connect(this, - &QLineEdit::textChanged, - this, - [this, icon]() { testAction_->setIcon(icon); }); -} - -void QApiKeyEdit::apiTest() -{ - QNetworkRequest req; - req.setTransferTimeout(5000); - - switch (provider_) - { - case map::MapProvider::Mapbox: - { - QUrl url("https://api.mapbox.com/v4/mapbox.mapbox-streets-v8/1/0/0.mvt"); - logger_->debug("Testing MapProvider::Mapbox API key at {}", - url.toString().toStdString()); - QUrlQuery query; - query.addQueryItem("access_token", text()); - url.setQuery(query); - req.setUrl(url); - break; - } - case map::MapProvider::MapTiler: - { - QUrl url("https://api.maptiler.com/maps/streets-v2/"); - logger_->debug("Testing MapProvider::MapTiler API key at {}", - url.toString().toStdString()); - QUrlQuery query; - query.addQueryItem("key", text()); - url.setQuery(query); - req.setUrl(url); - break; - } - default: - { - logger_->warn("Cannot test MapProvider::Unknown API key"); - break; - } - } - - networkAccessManager_->get(req); -} - -void QApiKeyEdit::apiTestFinished(QNetworkReply* reply) -{ - switch (reply->error()) - { - case QNetworkReply::NoError: - { - logger_->info("QApiKeyEdit: test success"); - QToolTip::showText(mapToGlobal(QPoint()), tr("Key was valid")); - testAction_->setIcon( - QApplication::style()->standardIcon(QStyle::SP_DialogApplyButton)); - Q_EMIT apiTestSucceeded(); - break; - } - default: - { - const char* errStr = - QMetaEnum::fromType().valueToKey( - reply->error()); - logger_->warn("QApiKeyEdit: test failed, got {} from {}", - errStr, - reply->url().host().toStdString()); - QToolTip::showText(mapToGlobal(QPoint()), tr("Invalid key")); - testAction_->setIcon( - QApplication::style()->standardIcon(QStyle::SP_DialogCancelButton)); - Q_EMIT apiTestFailed(reply->error()); - break; - } - } -} diff --git a/scwx-qt/source/scwx/qt/ui/api_key_edit_widget.hpp b/scwx-qt/source/scwx/qt/ui/api_key_edit_widget.hpp deleted file mode 100644 index 074e0b55..00000000 --- a/scwx-qt/source/scwx/qt/ui/api_key_edit_widget.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include -#include -#include - -class QNetworkAccessManager; - -namespace scwx::qt::ui -{ - -class QApiKeyEdit : public QLineEdit -{ - Q_OBJECT - -public: - QApiKeyEdit(QWidget* parent = nullptr); - - map::MapProvider getMapProvider() const { return provider_; } - - void setMapProvider(const map::MapProvider provider) - { - provider_ = provider; - } - -signals: - void apiTestSucceeded(); - void apiTestFailed(QNetworkReply::NetworkError error); - -private slots: - void apiTest(); - void apiTestFinished(QNetworkReply* reply); - -protected: - map::MapProvider provider_ {map::MapProvider::Unknown}; - QNetworkAccessManager* networkAccessManager_ {}; - QAction* testAction_ {}; -}; - -} // namespace scwx::qt::ui diff --git a/scwx-qt/source/scwx/qt/ui/county_dialog.ui b/scwx-qt/source/scwx/qt/ui/county_dialog.ui index 6a9a0257..71741c86 100644 --- a/scwx-qt/source/scwx/qt/ui/county_dialog.ui +++ b/scwx-qt/source/scwx/qt/ui/county_dialog.ui @@ -29,6 +29,12 @@ + + QFrame::StyledPanel + + + QFrame::Raised + 0 @@ -48,10 +54,10 @@ - Qt::Orientation::Horizontal + Qt::Horizontal - QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok + QDialogButtonBox::Cancel|QDialogButtonBox::Ok diff --git a/scwx-qt/source/scwx/qt/ui/custom_layer_dialog.cpp b/scwx-qt/source/scwx/qt/ui/custom_layer_dialog.cpp deleted file mode 100644 index d7c963f6..00000000 --- a/scwx-qt/source/scwx/qt/ui/custom_layer_dialog.cpp +++ /dev/null @@ -1,108 +0,0 @@ -#include "custom_layer_dialog.hpp" -#include "ui_custom_layer_dialog.h" - -#include -#include -#include -#include - -#include - -namespace scwx::qt::ui -{ - -static const std::string logPrefix_ = "scwx::qt::ui::custom_layer_dialog"; -static const auto logger_ = scwx::util::Logger::Create(logPrefix_); - -class CustomLayerDialogImpl -{ -public: - explicit CustomLayerDialogImpl(CustomLayerDialog* self, - QMapLibre::Settings settings) : - self_(self), settings_(std::move(settings)) - { - } - - ~CustomLayerDialogImpl() = default; - CustomLayerDialogImpl(const CustomLayerDialogImpl&) = delete; - CustomLayerDialogImpl(CustomLayerDialogImpl&&) = delete; - CustomLayerDialogImpl& operator=(const CustomLayerDialogImpl&) = delete; - CustomLayerDialogImpl& operator=(CustomLayerDialogImpl&&) = delete; - - void handle_mapChanged(QMapLibre::Map::MapChange change); - - CustomLayerDialog* self_; - - QMapLibre::Settings settings_; - std::shared_ptr map_; -}; - -void CustomLayerDialogImpl::handle_mapChanged(QMapLibre::Map::MapChange change) -{ - if (change == QMapLibre::Map::MapChange::MapChangeDidFinishLoadingStyle) - { - auto& generalSettings = settings::GeneralSettings::Instance(); - const std::string& customStyleDrawLayer = - generalSettings.custom_style_draw_layer().GetStagedOrValue(); - - const QStringList layerIds = map_->layerIds(); - self_->ui->layerListWidget->clear(); - self_->ui->layerListWidget->addItems(layerIds); - - const std::string symbologyLayer = util::maplibre::FindMapSymbologyLayer( - layerIds, {customStyleDrawLayer}); - - const auto& symbologyItems = self_->ui->layerListWidget->findItems( - symbologyLayer.c_str(), Qt::MatchExactly); - if (!symbologyItems.isEmpty()) - { - self_->ui->layerListWidget->setCurrentItem(symbologyItems.first()); - } - } -} - -CustomLayerDialog::CustomLayerDialog(const QMapLibre::Settings& settings, - QWidget* parent) : - QDialog(parent), - p {std::make_unique(this, settings)}, - ui(new Ui::CustomLayerDialog) -{ - ui->setupUi(this); - - auto& generalSettings = settings::GeneralSettings::Instance(); - const auto& customStyleUrl = generalSettings.custom_style_url().GetValue(); - const auto mapProvider = - map::GetMapProvider(generalSettings.map_provider().GetValue()); - - // TODO render the map with a layer to show what they are selecting - p->map_ = std::make_shared( - nullptr, p->settings_, QSize(1, 1), devicePixelRatioF()); - - QString qUrl = QString::fromStdString(customStyleUrl); - - if (mapProvider == map::MapProvider::MapTiler) - { - qUrl.append("?key="); - qUrl.append(map::GetMapProviderApiKey(mapProvider)); - } - - p->map_->setStyleUrl(qUrl); - - QObject::connect(p->map_.get(), - &QMapLibre::Map::mapChanged, - this, - [this](QMapLibre::Map::MapChange change) - { p->handle_mapChanged(change); }); -} - -CustomLayerDialog::~CustomLayerDialog() -{ - delete ui; -} - -std::string CustomLayerDialog::selected_layer() -{ - return ui->layerListWidget->currentItem()->text().toStdString(); -} - -} // namespace scwx::qt::ui diff --git a/scwx-qt/source/scwx/qt/ui/custom_layer_dialog.hpp b/scwx-qt/source/scwx/qt/ui/custom_layer_dialog.hpp deleted file mode 100644 index ad0a2526..00000000 --- a/scwx-qt/source/scwx/qt/ui/custom_layer_dialog.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace Ui -{ -class CustomLayerDialog; -} - -namespace scwx::qt::ui -{ - -class CustomLayerDialogImpl; - -class CustomLayerDialog : public QDialog -{ - Q_OBJECT - Q_DISABLE_COPY_MOVE(CustomLayerDialog) - -public: - explicit CustomLayerDialog(const QMapLibre::Settings& settings, - QWidget* parent = nullptr); - ~CustomLayerDialog() override; - - std::string selected_layer(); - -private: - friend class CustomLayerDialogImpl; - std::unique_ptr p; - Ui::CustomLayerDialog* ui; -}; - -} // namespace scwx::qt::ui diff --git a/scwx-qt/source/scwx/qt/ui/custom_layer_dialog.ui b/scwx-qt/source/scwx/qt/ui/custom_layer_dialog.ui deleted file mode 100644 index 2ce59321..00000000 --- a/scwx-qt/source/scwx/qt/ui/custom_layer_dialog.ui +++ /dev/null @@ -1,96 +0,0 @@ - - - CustomLayerDialog - - - - 0 - 0 - 308 - 300 - - - - - 0 - 0 - - - - Custom Map Style Draw Layer - - - - - - - - - 0 - 0 - - - - QAbstractItemView::EditTrigger::NoEditTriggers - - - true - - - - - - - - - - 0 - 0 - - - - Qt::Orientation::Horizontal - - - QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok - - - - - - - - - buttonBox - accepted() - CustomLayerDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - CustomLayerDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/scwx-qt/source/scwx/qt/ui/edit_line_dialog.cpp b/scwx-qt/source/scwx/qt/ui/edit_line_dialog.cpp deleted file mode 100644 index 5202e732..00000000 --- a/scwx-qt/source/scwx/qt/ui/edit_line_dialog.cpp +++ /dev/null @@ -1,316 +0,0 @@ -#include "edit_line_dialog.hpp" -#include "ui_edit_line_dialog.h" - -#include -#include -#include - -#include -#include - -namespace scwx -{ -namespace qt -{ -namespace ui -{ - -static const std::string logPrefix_ = "scwx::qt::ui::edit_line_dialog"; -static const auto logger_ = scwx::util::Logger::Create(logPrefix_); - -class EditLineDialog::Impl -{ -public: - struct EditComponent - { - void ConnectSignals(EditLineDialog* self) - { - QObject::connect(colorLineEdit_, - &QLineEdit::textEdited, - self, - [=, this](const QString& text) - { - boost::gil::rgba8_pixel_t color = - util::color::ToRgba8PixelT(text.toStdString()); - self->p->set_color(*this, color, false); - }); - - QObject::connect(colorButton_, - &QAbstractButton::clicked, - self, - [=, this]() { self->p->ShowColorDialog(*this); }); - - QObject::connect(widthSpinBox_, - &QSpinBox::valueChanged, - self, - [=, this](int width) - { self->p->set_width(*this, width); }); - } - - boost::gil::rgba8_pixel_t color_; - std::size_t width_; - QFrame* colorFrame_ {nullptr}; - QLineEdit* colorLineEdit_ {nullptr}; - QToolButton* colorButton_ {nullptr}; - QSpinBox* widthSpinBox_ {nullptr}; - }; - - explicit Impl(EditLineDialog* self) : - self_ {self}, lineLabel_ {new LineLabel(self)} - { - } - ~Impl() = default; - - void SetDefaults(); - void ShowColorDialog(EditComponent& component); - void UpdateLineLabel(); - - void set_color(EditComponent& component, - boost::gil::rgba8_pixel_t color, - bool updateLineEdit = true); - void set_width(EditComponent& component, std::size_t width); - - static void SetBackgroundColor(const std::string& value, QFrame* frame); - - EditLineDialog* self_; - - LineLabel* lineLabel_; - - boost::gil::rgba8_pixel_t defaultBorderColor_ {0, 0, 0, 255}; - boost::gil::rgba8_pixel_t defaultHighlightColor_ {0, 0, 0, 0}; - boost::gil::rgba8_pixel_t defaultLineColor_ {255, 255, 255, 255}; - - std::size_t defaultBorderWidth_ {1u}; - std::size_t defaultHighlightWidth_ {0u}; - std::size_t defaultLineWidth_ {3u}; - - EditComponent borderComponent_ {}; - EditComponent highlightComponent_ {}; - EditComponent lineComponent_ {}; -}; - -EditLineDialog::EditLineDialog(QWidget* parent) : - QDialog(parent), - p {std::make_unique(this)}, - ui(new Ui::EditLineDialog) -{ - ui->setupUi(this); - - p->borderComponent_.colorFrame_ = ui->borderColorFrame; - p->borderComponent_.colorLineEdit_ = ui->borderColorLineEdit; - p->borderComponent_.colorButton_ = ui->borderColorButton; - p->borderComponent_.widthSpinBox_ = ui->borderWidthSpinBox; - - p->highlightComponent_.colorFrame_ = ui->highlightColorFrame; - p->highlightComponent_.colorLineEdit_ = ui->highlightColorLineEdit; - p->highlightComponent_.colorButton_ = ui->highlightColorButton; - p->highlightComponent_.widthSpinBox_ = ui->highlightWidthSpinBox; - - p->lineComponent_.colorFrame_ = ui->lineColorFrame; - p->lineComponent_.colorLineEdit_ = ui->lineColorLineEdit; - p->lineComponent_.colorButton_ = ui->lineColorButton; - p->lineComponent_.widthSpinBox_ = ui->lineWidthSpinBox; - - p->SetDefaults(); - - p->lineLabel_->setMinimumWidth(72); - - QHBoxLayout* lineLabelContainerLayout = - static_cast(ui->lineLabelContainer->layout()); - lineLabelContainerLayout->insertWidget(1, p->lineLabel_); - - p->borderComponent_.ConnectSignals(this); - p->highlightComponent_.ConnectSignals(this); - p->lineComponent_.ConnectSignals(this); - - QObject::connect(ui->buttonBox, - &QDialogButtonBox::clicked, - this, - [this](QAbstractButton* button) - { - QDialogButtonBox::ButtonRole role = - ui->buttonBox->buttonRole(button); - - switch (role) - { - case QDialogButtonBox::ButtonRole::ResetRole: // Reset - p->SetDefaults(); - break; - - default: - break; - } - }); -} - -EditLineDialog::~EditLineDialog() -{ - delete ui; -} - -boost::gil::rgba8_pixel_t EditLineDialog::border_color() const -{ - return p->borderComponent_.color_; -} - -boost::gil::rgba8_pixel_t EditLineDialog::highlight_color() const -{ - return p->highlightComponent_.color_; -} - -boost::gil::rgba8_pixel_t EditLineDialog::line_color() const -{ - return p->lineComponent_.color_; -} - -std::size_t EditLineDialog::border_width() const -{ - return p->borderComponent_.width_; -} - -std::size_t EditLineDialog::highlight_width() const -{ - return p->highlightComponent_.width_; -} - -std::size_t EditLineDialog::line_width() const -{ - return p->lineComponent_.width_; -} - -void EditLineDialog::set_border_color(boost::gil::rgba8_pixel_t color) -{ - p->set_color(p->borderComponent_, color); -} - -void EditLineDialog::set_highlight_color(boost::gil::rgba8_pixel_t color) -{ - p->set_color(p->highlightComponent_, color); -} - -void EditLineDialog::set_line_color(boost::gil::rgba8_pixel_t color) -{ - p->set_color(p->lineComponent_, color); -} - -void EditLineDialog::set_border_width(std::size_t width) -{ - p->set_width(p->borderComponent_, width); -} - -void EditLineDialog::set_highlight_width(std::size_t width) -{ - p->set_width(p->highlightComponent_, width); -} - -void EditLineDialog::set_line_width(std::size_t width) -{ - p->set_width(p->lineComponent_, width); -} - -void EditLineDialog::Impl::set_color(EditComponent& component, - boost::gil::rgba8_pixel_t color, - bool updateLineEdit) -{ - const std::string argbString {util::color::ToArgbString(color)}; - - component.color_ = color; - SetBackgroundColor(argbString, component.colorFrame_); - - if (updateLineEdit) - { - component.colorLineEdit_->setText(QString::fromStdString(argbString)); - } - - UpdateLineLabel(); -} - -void EditLineDialog::Impl::set_width(EditComponent& component, - std::size_t width) -{ - component.width_ = width; - component.widthSpinBox_->setValue(static_cast(width)); - - UpdateLineLabel(); -} - -void EditLineDialog::Impl::UpdateLineLabel() -{ - lineLabel_->set_border_color(borderComponent_.color_); - lineLabel_->set_highlight_color(highlightComponent_.color_); - lineLabel_->set_line_color(lineComponent_.color_); - - lineLabel_->set_border_width(borderComponent_.width_); - lineLabel_->set_highlight_width(highlightComponent_.width_); - lineLabel_->set_line_width(lineComponent_.width_); -} - -void EditLineDialog::Initialize(boost::gil::rgba8_pixel_t borderColor, - boost::gil::rgba8_pixel_t highlightColor, - boost::gil::rgba8_pixel_t lineColor, - std::size_t borderWidth, - std::size_t highlightWidth, - std::size_t lineWidth) -{ - p->defaultBorderColor_ = borderColor; - p->defaultHighlightColor_ = highlightColor; - p->defaultLineColor_ = lineColor; - - p->defaultBorderWidth_ = borderWidth; - p->defaultHighlightWidth_ = highlightWidth; - p->defaultLineWidth_ = lineWidth; - - p->SetDefaults(); -} - -void EditLineDialog::Impl::SetDefaults() -{ - self_->set_border_color(defaultBorderColor_); - self_->set_highlight_color(defaultHighlightColor_); - self_->set_line_color(defaultLineColor_); - - self_->set_border_width(defaultBorderWidth_); - self_->set_highlight_width(defaultHighlightWidth_); - self_->set_line_width(defaultLineWidth_); -} - -void EditLineDialog::Impl::ShowColorDialog(EditComponent& component) -{ - QColorDialog* dialog = new QColorDialog(self_); - - dialog->setAttribute(Qt::WA_DeleteOnClose); - dialog->setOption(QColorDialog::ColorDialogOption::ShowAlphaChannel); - - QColor initialColor(component.colorLineEdit_->text()); - if (initialColor.isValid()) - { - dialog->setCurrentColor(initialColor); - } - - QObject::connect( - dialog, - &QColorDialog::colorSelected, - self_, - [this, &component](const QColor& qColor) - { - QString colorName = qColor.name(QColor::NameFormat::HexArgb); - boost::gil::rgba8_pixel_t color = - util::color::ToRgba8PixelT(colorName.toStdString()); - - logger_->info("Selected color: {}", colorName.toStdString()); - set_color(component, color); - }); - - dialog->open(); -} - -void EditLineDialog::Impl::SetBackgroundColor(const std::string& value, - QFrame* frame) -{ - frame->setStyleSheet( - QString::fromStdString(fmt::format("background-color: {}", value))); -} - -} // namespace ui -} // namespace qt -} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/ui/edit_line_dialog.hpp b/scwx-qt/source/scwx/qt/ui/edit_line_dialog.hpp deleted file mode 100644 index 2f8ea3ce..00000000 --- a/scwx-qt/source/scwx/qt/ui/edit_line_dialog.hpp +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once - -#include - -#include - -namespace Ui -{ -class EditLineDialog; -} - -namespace scwx -{ -namespace qt -{ -namespace ui -{ - -class EditLineDialog : public QDialog -{ - Q_OBJECT - Q_DISABLE_COPY_MOVE(EditLineDialog) - -public: - explicit EditLineDialog(QWidget* parent = nullptr); - ~EditLineDialog(); - - boost::gil::rgba8_pixel_t border_color() const; - boost::gil::rgba8_pixel_t highlight_color() const; - boost::gil::rgba8_pixel_t line_color() const; - - std::size_t border_width() const; - std::size_t highlight_width() const; - std::size_t line_width() const; - - void set_border_color(boost::gil::rgba8_pixel_t color); - void set_highlight_color(boost::gil::rgba8_pixel_t color); - void set_line_color(boost::gil::rgba8_pixel_t color); - - void set_border_width(std::size_t width); - void set_highlight_width(std::size_t width); - void set_line_width(std::size_t width); - - void Initialize(boost::gil::rgba8_pixel_t borderColor, - boost::gil::rgba8_pixel_t highlightColor, - boost::gil::rgba8_pixel_t lineColor, - std::size_t borderWidth, - std::size_t highlightWidth, - std::size_t lineWidth); - -private: - class Impl; - std::unique_ptr p; - Ui::EditLineDialog* ui; -}; - -} // namespace ui -} // namespace qt -} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/ui/edit_line_dialog.ui b/scwx-qt/source/scwx/qt/ui/edit_line_dialog.ui deleted file mode 100644 index bc133bf9..00000000 --- a/scwx-qt/source/scwx/qt/ui/edit_line_dialog.ui +++ /dev/null @@ -1,306 +0,0 @@ - - - EditLineDialog - - - - 0 - 0 - 350 - 225 - - - - Edit Line - - - - - - - true - - - - Component - - - - - - - #ff000000 - - - - - - - 0 - - - 9 - - - - - - - ... - - - - :/res/icons/font-awesome-6/palette-solid.svg:/res/icons/font-awesome-6/palette-solid.svg - - - - - - - ... - - - - :/res/icons/font-awesome-6/palette-solid.svg:/res/icons/font-awesome-6/palette-solid.svg - - - - - - - Border - - - - - - - #ff000000 - - - - - - - Line - - - - - - - Qt::Orientation::Horizontal - - - QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok|QDialogButtonBox::StandardButton::Reset - - - - - - - - 24 - 24 - - - - QFrame::Shape::Box - - - QFrame::Shadow::Plain - - - - - - - 0 - - - 9 - - - - - - - Qt::Orientation::Vertical - - - - 20 - 40 - - - - - - - - - 24 - 24 - - - - QFrame::Shape::Box - - - QFrame::Shadow::Plain - - - - - - - - true - - - - Color - - - - - - - #ff000000 - - - - - - - - 24 - 24 - - - - QFrame::Shape::Box - - - QFrame::Shadow::Plain - - - - - - - - true - - - - Width - - - - - - - 1 - - - 9 - - - - - - - Highlight - - - - - - - ... - - - - :/res/icons/font-awesome-6/palette-solid.svg:/res/icons/font-awesome-6/palette-solid.svg - - - - - - - - 0 - 45 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Qt::Orientation::Horizontal - - - - - - - Qt::Orientation::Horizontal - - - - - - - - - - - - - - buttonBox - accepted() - EditLineDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - EditLineDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/scwx-qt/source/scwx/qt/ui/edit_marker_dialog.cpp b/scwx-qt/source/scwx/qt/ui/edit_marker_dialog.cpp deleted file mode 100644 index 4f310488..00000000 --- a/scwx-qt/source/scwx/qt/ui/edit_marker_dialog.cpp +++ /dev/null @@ -1,337 +0,0 @@ -#include "edit_marker_dialog.hpp" -#include "ui_edit_marker_dialog.h" - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include - -namespace scwx::qt::ui -{ - -static const std::string logPrefix_ = "scwx::qt::ui::edit_marker_dialog"; -static const auto logger_ = scwx::util::Logger::Create(logPrefix_); - -static const QString addingTitle_ = QObject::tr("Add Location Marker"); -static const QString editingTitle_ = QObject::tr("Edit Location Marker"); - -class EditMarkerDialog::Impl -{ -public: - explicit Impl(EditMarkerDialog* self) : self_ {self} {} - - void show_color_dialog(); - void show_icon_file_dialog(); - - void set_icon_color(const std::string& color); - void set_adding(bool adding); - - void connect_signals(); - - void handle_accepted(); - void handle_rejected(); - - EditMarkerDialog* self_; - QPushButton* deleteButton_ {nullptr}; - QIcon get_colored_icon(const types::MarkerIconInfo& marker, - const std::string& color); - - std::shared_ptr markerManager_ = - manager::MarkerManager::Instance(); - types::MarkerId editId_ {0}; - bool adding_ {false}; - std::string setIconOnAdded_ {""}; -}; - -QIcon EditMarkerDialog::Impl::get_colored_icon( - const types::MarkerIconInfo& marker, const std::string& color) -{ - return util::modulateColors(marker.qIcon, - self_->ui->iconComboBox->iconSize(), - QColor(QString::fromStdString(color))); -} - -void EditMarkerDialog::Impl::set_adding(bool adding) -{ - if (adding == adding_) - { - return; - } - - if (adding) - { - self_->setWindowTitle(addingTitle_); - } - else - { - self_->setWindowTitle(editingTitle_); - } - adding_ = adding; -} - -EditMarkerDialog::EditMarkerDialog(QWidget* parent) : - QDialog(parent), - p {std::make_unique(this)}, - ui(new Ui::EditMarkerDialog) -{ - ui->setupUi(this); - - for (auto& markerIcon : p->markerManager_->get_icons()) - { - ui->iconComboBox->addItem( - markerIcon.second.qIcon, - QString::fromStdString(markerIcon.second.shortName), - QString::fromStdString(markerIcon.second.name)); - } - p->deleteButton_ = - ui->buttonBox->addButton("Delete", QDialogButtonBox::DestructiveRole); - p->connect_signals(); -} - -EditMarkerDialog::~EditMarkerDialog() -{ - delete ui; -} - -void EditMarkerDialog::setup() -{ - setup(0.0, 0.0); -} - -void EditMarkerDialog::setup(double latitude, double longitude) -{ - // By default use foreground color as marker color, mainly so the icons - // are vissable in the dropdown menu. - const QColor color = QWidget::palette().color(QWidget::foregroundRole()); - p->editId_ = p->markerManager_->add_marker(types::MarkerInfo( - "", - latitude, - longitude, - manager::MarkerManager::getDefaultIconName(), - boost::gil::rgba8_pixel_t {static_cast(color.red()), - static_cast(color.green()), - static_cast(color.blue()), - static_cast(color.alpha())})); - - setup(p->editId_, true); -} - -void EditMarkerDialog::setup(types::MarkerId id, bool adding) -{ - std::optional marker = p->markerManager_->get_marker(id); - if (!marker) - { - return; - } - - p->editId_ = id; - p->set_adding(adding); - - const std::string iconColorStr = - util::color::ToArgbString(marker->iconColor); - p->set_icon_color(iconColorStr); - - int iconIndex = - ui->iconComboBox->findData(QString::fromStdString(marker->iconName)); - if (iconIndex < 0 || marker->iconName == "") - { - iconIndex = 0; - } - - ui->nameLineEdit->setText(QString::fromStdString(marker->name)); - ui->iconComboBox->setCurrentIndex(iconIndex); - ui->latitudeDoubleSpinBox->setValue(marker->latitude); - ui->longitudeDoubleSpinBox->setValue(marker->longitude); - ui->iconColorLineEdit->setText(QString::fromStdString(iconColorStr)); -} - -types::MarkerInfo EditMarkerDialog::get_marker_info() const -{ - const QString colorName = ui->iconColorLineEdit->text(); - const boost::gil::rgba8_pixel_t color = - util::color::ToRgba8PixelT(colorName.toStdString()); - - return types::MarkerInfo( - ui->nameLineEdit->text().toStdString(), - ui->latitudeDoubleSpinBox->value(), - ui->longitudeDoubleSpinBox->value(), - ui->iconComboBox->currentData().toString().toStdString(), - color); -} - -void EditMarkerDialog::Impl::show_color_dialog() -{ - // WA_DeleteOnClose manages memory - // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - auto* dialog = new QColorDialog(self_); - - dialog->setAttribute(Qt::WA_DeleteOnClose); - dialog->setOption(QColorDialog::ColorDialogOption::ShowAlphaChannel); - - const QColor initialColor(self_->ui->iconColorLineEdit->text()); - if (initialColor.isValid()) - { - dialog->setCurrentColor(initialColor); - } - - QObject::connect(dialog, - &QColorDialog::colorSelected, - self_, - [this](const QColor& qColor) - { - const QString colorName = - qColor.name(QColor::NameFormat::HexArgb); - self_->ui->iconColorLineEdit->setText(colorName); - set_icon_color(colorName.toStdString()); - }); - dialog->open(); -} - -void EditMarkerDialog::Impl::show_icon_file_dialog() -{ - auto* dialog = new QFileDialog(self_); - - dialog->setFileMode(QFileDialog::ExistingFile); - dialog->setNameFilters({"Icon (*.png *.svg)", "All Files (*)"}); - dialog->setAttribute(Qt::WA_DeleteOnClose); - - QObject::connect(dialog, - &QFileDialog::fileSelected, - self_, - [this](const QString& file) - { - const std::string path = - QDir::toNativeSeparators(file).toStdString(); - setIconOnAdded_ = path; - markerManager_->add_icon(path); - }); - dialog->open(); -} - -void EditMarkerDialog::Impl::connect_signals() -{ - connect(self_, - &EditMarkerDialog::accepted, - self_, - [this]() { handle_accepted(); }); - - connect(self_, - &EditMarkerDialog::rejected, - self_, - [this]() { handle_rejected(); }); - - connect(deleteButton_, - &QPushButton::clicked, - self_, - [this]() - { - markerManager_->remove_marker(editId_); - self_->done(0); - }); - - connect(self_->ui->iconColorLineEdit, - &QLineEdit::textEdited, - self_, - [this](const QString& text) { set_icon_color(text.toStdString()); }); - - connect(self_->ui->iconColorButton, - &QAbstractButton::clicked, - self_, - [this]() { show_color_dialog(); }); - - connect(self_->ui->iconFileOpenButton, - &QPushButton::clicked, - self_, - [this]() { show_icon_file_dialog(); }); - - connect(markerManager_.get(), - &manager::MarkerManager::IconAdded, - self_, - [this]() - { - const std::string color = - self_->ui->iconColorLineEdit->text().toStdString(); - set_icon_color(color); - - if (setIconOnAdded_ != "") - { - const int i = self_->ui->iconComboBox->findData( - QString::fromStdString(setIconOnAdded_)); - if (i >= 0) - { - self_->ui->iconComboBox->setCurrentIndex(i); - setIconOnAdded_ = ""; - } - } - }); - - connect(self_->ui->buttonBox->button(QDialogButtonBox::Apply), - &QAbstractButton::clicked, - self_, - [this]() { handle_accepted(); }); -} - -void EditMarkerDialog::Impl::set_icon_color(const std::string& color) -{ - self_->ui->iconColorFrame->setStyleSheet( - QString::fromStdString(fmt::format("background-color: {}", color))); - - auto* iconComboBox = self_->ui->iconComboBox; - - const QVariant currentIcon = iconComboBox->currentData(); - - self_->ui->iconComboBox->clear(); - for (auto& markerIcon : markerManager_->get_icons()) - { - const int i = - iconComboBox->findData(QString::fromStdString(markerIcon.second.name)); - const QIcon icon = get_colored_icon(markerIcon.second, color); - if (i < 0) - { - iconComboBox->addItem( - icon, - QString::fromStdString(markerIcon.second.shortName), - QString::fromStdString(markerIcon.second.name)); - } - else - { - self_->ui->iconComboBox->setItemIcon(i, icon); - } - } - - const int i = iconComboBox->findData(currentIcon); - if (i < 0) - { - return; - } - - iconComboBox->setCurrentIndex(i); -} - -void EditMarkerDialog::Impl::handle_accepted() -{ - // switch to editing to that canceling after applying does not delete it - set_adding(false); - markerManager_->set_marker(editId_, self_->get_marker_info()); -} - -void EditMarkerDialog::Impl::handle_rejected() -{ - if (adding_) - { - markerManager_->remove_marker(editId_); - } -} - -} // namespace scwx::qt::ui diff --git a/scwx-qt/source/scwx/qt/ui/edit_marker_dialog.hpp b/scwx-qt/source/scwx/qt/ui/edit_marker_dialog.hpp deleted file mode 100644 index 3990b6c0..00000000 --- a/scwx-qt/source/scwx/qt/ui/edit_marker_dialog.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once -#include - -#include - -namespace Ui -{ -class EditMarkerDialog; -} - -namespace scwx::qt::ui -{ -class EditMarkerDialog : public QDialog -{ - Q_OBJECT - Q_DISABLE_COPY_MOVE(EditMarkerDialog) - -public: - explicit EditMarkerDialog(QWidget* parent = nullptr); - ~EditMarkerDialog() override; - - void setup(); - void setup(double latitude, double longitude); - void setup(types::MarkerId id, bool adding = false); - - [[nodiscard]] types::MarkerInfo get_marker_info() const; - -private: - class Impl; - std::unique_ptr p; - Ui::EditMarkerDialog* ui; -}; - -} // namespace scwx::qt::ui diff --git a/scwx-qt/source/scwx/qt/ui/edit_marker_dialog.ui b/scwx-qt/source/scwx/qt/ui/edit_marker_dialog.ui deleted file mode 100644 index d3d47500..00000000 --- a/scwx-qt/source/scwx/qt/ui/edit_marker_dialog.ui +++ /dev/null @@ -1,210 +0,0 @@ - - - EditMarkerDialog - - - - 0 - 0 - 400 - 249 - - - - Edit Location Marker - - - - - - Qt::Orientation::Vertical - - - - 20 - 40 - - - - - - - - - - - 24 - 24 - - - - QFrame::Shape::Box - - - QFrame::Shadow::Plain - - - - - - - #ffffffff - - - - - - - ... - - - - :/res/icons/font-awesome-6/palette-solid.svg:/res/icons/font-awesome-6/palette-solid.svg - - - - - - - - - QAbstractSpinBox::CorrectionMode::CorrectToNearestValue - - - 5 - - - -90.000000000000000 - - - 90.000000000000000 - - - - - - - Name - - - - - - - Icon - - - - - - - Qt::Orientation::Horizontal - - - QDialogButtonBox::StandardButton::Apply|QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok - - - - - - - Longitude - - - - - - - Icon Color - - - - - - - Latitude - - - - - - - Add Custom Icon - - - ... - - - - - - - QAbstractSpinBox::CorrectionMode::CorrectToNearestValue - - - 5 - - - -180.000000000000000 - - - 180.000000000000000 - - - - - - - - - - - 0 - 0 - - - - true - - - - - - - - - - - buttonBox - accepted() - EditMarkerDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - EditMarkerDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/scwx-qt/source/scwx/qt/ui/imgui_debug_dialog.ui b/scwx-qt/source/scwx/qt/ui/imgui_debug_dialog.ui index 6b371769..5752a7c1 100644 --- a/scwx-qt/source/scwx/qt/ui/imgui_debug_dialog.ui +++ b/scwx-qt/source/scwx/qt/ui/imgui_debug_dialog.ui @@ -16,6 +16,12 @@ + + QFrame::StyledPanel + + + QFrame::Raised + 0 @@ -48,10 +54,10 @@ - Qt::Orientation::Horizontal + Qt::Horizontal - QDialogButtonBox::StandardButton::Close + QDialogButtonBox::Close diff --git a/scwx-qt/source/scwx/qt/ui/imgui_debug_widget.cpp b/scwx-qt/source/scwx/qt/ui/imgui_debug_widget.cpp index 541c8e3e..acb8eda3 100644 --- a/scwx-qt/source/scwx/qt/ui/imgui_debug_widget.cpp +++ b/scwx-qt/source/scwx/qt/ui/imgui_debug_widget.cpp @@ -1,4 +1,5 @@ #include +#include #include #include @@ -9,7 +10,11 @@ #include #include -namespace scwx::qt::ui +namespace scwx +{ +namespace qt +{ +namespace ui { static const std::string logPrefix_ = "scwx::qt::ui::imgui_debug_widget"; @@ -47,14 +52,19 @@ public: model::ImGuiContextModel::Instance().DestroyContext(contextName_); } + void ImGuiCheckFonts(); + ImGuiDebugWidget* self_; ImGuiContext* context_; std::string contextName_; ImGuiContext* currentContext_; + gl::OpenGLFunctions gl_; + std::set renderedSet_ {}; bool imGuiRendererInitialized_ {false}; + std::uint64_t imGuiFontsBuildCount_ {}; }; ImGuiDebugWidget::ImGuiDebugWidget(QWidget* parent) : @@ -96,16 +106,21 @@ void ImGuiDebugWidget::initializeGL() { makeCurrent(); + // Initialize OpenGL Functions + p->gl_.initializeOpenGLFunctions(); + // Initialize ImGui OpenGL3 backend ImGui::SetCurrentContext(p->context_); ImGui_ImplOpenGL3_Init(); + p->imGuiFontsBuildCount_ = + manager::FontManager::Instance().imgui_fonts_build_count(); p->imGuiRendererInitialized_ = true; } void ImGuiDebugWidget::paintGL() { - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); + p->gl_.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + p->gl_.glClear(GL_COLOR_BUFFER_BIT); ImGui::SetCurrentContext(p->currentContext_); @@ -113,9 +128,9 @@ void ImGuiDebugWidget::paintGL() std::shared_lock imguiFontAtlasLock { manager::FontManager::Instance().imgui_font_atlas_mutex()}; - model::ImGuiContextModel::Instance().NewFrame(); ImGui_ImplQt_NewFrame(this); ImGui_ImplOpenGL3_NewFrame(); + p->ImGuiCheckFonts(); ImGui::NewFrame(); if (!p->renderedSet_.contains(p->currentContext_)) @@ -140,4 +155,26 @@ void ImGuiDebugWidget::paintGL() imguiFontAtlasLock.unlock(); } -} // namespace scwx::qt::ui +void ImGuiDebugWidgetImpl::ImGuiCheckFonts() +{ + // Update ImGui Fonts if required + std::uint64_t currentImGuiFontsBuildCount = + manager::FontManager::Instance().imgui_fonts_build_count(); + + if ((context_ == currentContext_ && + imGuiFontsBuildCount_ != currentImGuiFontsBuildCount) || + !model::ImGuiContextModel::Instance().font_atlas()->IsBuilt()) + { + ImGui_ImplOpenGL3_DestroyFontsTexture(); + ImGui_ImplOpenGL3_CreateFontsTexture(); + } + + if (context_ == currentContext_) + { + imGuiFontsBuildCount_ = currentImGuiFontsBuildCount; + } +} + +} // namespace ui +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/ui/imgui_debug_widget.hpp b/scwx-qt/source/scwx/qt/ui/imgui_debug_widget.hpp index 585d2432..695a6be9 100644 --- a/scwx-qt/source/scwx/qt/ui/imgui_debug_widget.hpp +++ b/scwx-qt/source/scwx/qt/ui/imgui_debug_widget.hpp @@ -1,7 +1,5 @@ #pragma once -#include - #include struct ImGuiContext; diff --git a/scwx-qt/source/scwx/qt/ui/layer_dialog.ui b/scwx-qt/source/scwx/qt/ui/layer_dialog.ui index 45f8413e..f9b2a076 100644 --- a/scwx-qt/source/scwx/qt/ui/layer_dialog.ui +++ b/scwx-qt/source/scwx/qt/ui/layer_dialog.ui @@ -16,6 +16,12 @@ + + QFrame::StyledPanel + + + QFrame::Raised + 0 @@ -35,16 +41,16 @@ true - QAbstractItemView::DragDropMode::InternalMove + QAbstractItemView::InternalMove - Qt::DropAction::MoveAction + Qt::MoveAction true - QAbstractItemView::SelectionMode::ExtendedSelection + QAbstractItemView::ExtendedSelection 0 @@ -53,6 +59,12 @@ + + QFrame::StyledPanel + + + QFrame::Raised + 0 @@ -69,7 +81,7 @@ - Qt::Orientation::Vertical + Qt::Vertical @@ -126,7 +138,7 @@ - Qt::Orientation::Vertical + Qt::Vertical @@ -144,6 +156,12 @@ + + QFrame::StyledPanel + + + QFrame::Raised + 0 @@ -170,7 +188,7 @@ - Qt::Orientation::Horizontal + Qt::Horizontal @@ -189,10 +207,10 @@ - Qt::Orientation::Horizontal + Qt::Horizontal - QDialogButtonBox::StandardButton::Close|QDialogButtonBox::StandardButton::Reset + QDialogButtonBox::Close|QDialogButtonBox::Reset diff --git a/scwx-qt/source/scwx/qt/ui/level2_settings_widget.cpp b/scwx-qt/source/scwx/qt/ui/level2_settings_widget.cpp index 3d530733..85b476c9 100644 --- a/scwx-qt/source/scwx/qt/ui/level2_settings_widget.cpp +++ b/scwx-qt/source/scwx/qt/ui/level2_settings_widget.cpp @@ -1,4 +1,3 @@ -#include #include #include #include @@ -30,15 +29,16 @@ public: explicit Level2SettingsWidgetImpl(Level2SettingsWidget* self) : self_ {self}, layout_ {new QVBoxLayout(self)}, + elevationGroupBox_ {}, elevationButtons_ {}, - elevationCuts_ {} + elevationCuts_ {}, + elevationButtonsChanged_ {false}, + resizeElevationButtons_ {false}, + settingsGroupBox_ {}, + declutterCheckBox_ {} { - // NOLINTBEGIN(cppcoreguidelines-owning-memory) Qt takes care of this layout_->setContentsMargins(0, 0, 0, 0); - incomingElevationLabel_ = new QLabel("", self); - layout_->addWidget(incomingElevationLabel_); - elevationGroupBox_ = new QGroupBox(tr("Elevation"), self); new ui::FlowLayout(elevationGroupBox_); layout_->addWidget(elevationGroupBox_); @@ -51,7 +51,6 @@ public: settingsLayout->addWidget(declutterCheckBox_); settingsGroupBox_->setVisible(false); - // NOLINTEND(cppcoreguidelines-owning-memory) Qt takes care of this QObject::connect(hotkeyManager_.get(), &manager::HotkeyManager::HotkeyPressed, @@ -67,15 +66,14 @@ public: Level2SettingsWidget* self_; QLayout* layout_; - QGroupBox* elevationGroupBox_ {}; - QLabel* incomingElevationLabel_ {}; + QGroupBox* elevationGroupBox_; std::list elevationButtons_; std::vector elevationCuts_; - bool elevationButtonsChanged_ {}; - bool resizeElevationButtons_ {}; + bool elevationButtonsChanged_; + bool resizeElevationButtons_; - QGroupBox* settingsGroupBox_ {}; - QCheckBox* declutterCheckBox_ {}; + QGroupBox* settingsGroupBox_; + QCheckBox* declutterCheckBox_; float currentElevation_ {}; QToolButton* currentElevationButton_ {nullptr}; @@ -242,29 +240,10 @@ void Level2SettingsWidget::UpdateElevationSelection(float elevation) p->currentElevationButton_ = newElevationButton; } -void Level2SettingsWidget::UpdateIncomingElevation( - std::optional incomingElevation) -{ - if (incomingElevation.has_value()) - { - p->incomingElevationLabel_->setText( - "Incoming Elevation: " + QString::number(*incomingElevation, 'f', 1) + - common::Characters::DEGREE); - } - else - { - p->incomingElevationLabel_->setText("Incoming Elevation: None"); - } -} - void Level2SettingsWidget::UpdateSettings(map::MapWidget* activeMap) { - std::optional currentElevationOption = activeMap->GetElevation(); - const float currentElevation = - currentElevationOption.has_value() ? *currentElevationOption : 0.0f; - const std::vector elevationCuts = activeMap->GetElevationCuts(); - const std::optional incomingElevation = - activeMap->GetIncomingLevel2Elevation(); + float currentElevation = activeMap->GetElevation(); + std::vector elevationCuts = activeMap->GetElevationCuts(); if (p->elevationCuts_ != elevationCuts) { @@ -298,7 +277,6 @@ void Level2SettingsWidget::UpdateSettings(map::MapWidget* activeMap) } UpdateElevationSelection(currentElevation); - UpdateIncomingElevation(incomingElevation); } } // namespace ui diff --git a/scwx-qt/source/scwx/qt/ui/level2_settings_widget.hpp b/scwx-qt/source/scwx/qt/ui/level2_settings_widget.hpp index 32f788bb..ce2e443f 100644 --- a/scwx-qt/source/scwx/qt/ui/level2_settings_widget.hpp +++ b/scwx-qt/source/scwx/qt/ui/level2_settings_widget.hpp @@ -2,8 +2,6 @@ #include -#include - namespace scwx { namespace qt @@ -25,7 +23,6 @@ public: void showEvent(QShowEvent* event) override; void UpdateElevationSelection(float elevation); - void UpdateIncomingElevation(std::optional incomingElevation); void UpdateSettings(map::MapWidget* activeMap); signals: diff --git a/scwx-qt/source/scwx/qt/ui/level3_products_widget.cpp b/scwx-qt/source/scwx/qt/ui/level3_products_widget.cpp index 5c993b66..ae2c8866 100644 --- a/scwx-qt/source/scwx/qt/ui/level3_products_widget.cpp +++ b/scwx-qt/source/scwx/qt/ui/level3_products_widget.cpp @@ -60,9 +60,7 @@ public: categoryButtons_ {}, productTiltMap_ {}, awipsProductMap_ {}, - awipsProductMutex_ {}, - categoryMap_ {}, - categoryMapMutex_ {} + awipsProductMutex_ {} { layout_->setContentsMargins(0, 0, 0, 0); layout_->addWidget(productsWidget_); @@ -185,9 +183,6 @@ public: std::unordered_map awipsProductMap_; std::shared_mutex awipsProductMutex_; - common::Level3ProductCategoryMap categoryMap_; - std::shared_mutex categoryMapMutex_; - std::string currentAwipsId_ {}; QAction* currentProductTiltAction_ {nullptr}; @@ -216,9 +211,7 @@ void Level3ProductsWidgetImpl::HandleHotkeyPressed(types::Hotkey hotkey, if (productCategoryIt == kHotkeyProductCategoryMap_.cend() && hotkey != types::Hotkey::ProductTiltDecrease && - hotkey != types::Hotkey::ProductTiltIncrease && - hotkey != types::Hotkey::ProductCategoryNext && - hotkey != types::Hotkey::ProductCategoryPrevious) + hotkey != types::Hotkey::ProductTiltIncrease) { // Not handling this hotkey return; @@ -253,69 +246,7 @@ void Level3ProductsWidgetImpl::HandleHotkeyPressed(types::Hotkey hotkey, return; } - if (hotkey == types::Hotkey::ProductCategoryNext || - hotkey == types::Hotkey::ProductCategoryPrevious) - { - const std::shared_lock lock1 {categoryMapMutex_}; - const std::shared_lock lock2 {awipsProductMutex_}; - - const common::Level3ProductCategory category = - common::GetLevel3CategoryByProduct(product); - auto productsIt = categoryMap_.find(category); - if (productsIt == categoryMap_.cend()) - { - logger_->error("Could not find the current category in category map"); - return; - } - auto availableProducts = productsIt->second; - const auto& products = common::GetLevel3ProductsByCategory(category); - - auto productIt = std::find(products.begin(), products.end(), product); - if (productIt == products.end()) - { - logger_->error("Could not find product in category"); - return; - } - - if (hotkey == types::Hotkey::ProductCategoryNext) - { - do - { - productIt = std::next(productIt); - if (productIt == products.cend()) - { - logger_->info("Cannot go past the last product"); - return; - } - } while (!availableProducts.contains(*productIt)); - } - else - { - do - { - if (productIt == products.begin()) - { - logger_->info("Cannot go past the first product"); - return; - } - productIt = std::prev(productIt); - } while (!availableProducts.contains(*productIt)); - } - - auto productTiltsIt = productTiltMap_.find(*productIt); - if (productTiltsIt == productTiltMap_.cend()) - { - logger_->error("Could not find product tilt map: {}", - common::GetLevel3ProductDescription(product)); - return; - } - - // Select the new tilt - productTiltsIt->second.at(0)->trigger(); - return; - } - - const std::shared_lock lock {awipsProductMutex_}; + std::shared_lock lock {awipsProductMutex_}; // Find the current product tilt auto productTiltsIt = productTiltMap_.find(product); @@ -391,11 +322,9 @@ void Level3ProductsWidgetImpl::SelectProductCategory( { UpdateCategorySelection(category); - const std::shared_lock lock {categoryMapMutex_}; - Q_EMIT self_->RadarProductSelected( common::RadarProductGroup::Level3, - common::GetLevel3CategoryDefaultProduct(category, categoryMap_), + common::GetLevel3CategoryDefaultProduct(category), 0); } @@ -404,12 +333,6 @@ void Level3ProductsWidget::UpdateAvailableProducts( { logger_->trace("UpdateAvailableProducts()"); - // Save the category map - { - const std::unique_lock lock {p->categoryMapMutex_}; - p->categoryMap_ = updatedCategoryMap; - } - // Iterate through each category tool button std::for_each( p->categoryButtons_.cbegin(), @@ -497,7 +420,7 @@ void Level3ProductsWidgetImpl::UpdateCategorySelection( std::for_each(categoryButtons_.cbegin(), categoryButtons_.cend(), - [&](auto& toolButton) + [&, this](auto& toolButton) { if (toolButton->text().toStdString() == categoryName) { @@ -521,7 +444,7 @@ void Level3ProductsWidgetImpl::UpdateProductSelection( std::for_each(awipsProductMap_.cbegin(), awipsProductMap_.cend(), - [&](const auto& pair) + [&, this](const auto& pair) { if (pair.second == awipsId) { diff --git a/scwx-qt/source/scwx/qt/ui/line_label.cpp b/scwx-qt/source/scwx/qt/ui/line_label.cpp deleted file mode 100644 index 03dbcaf6..00000000 --- a/scwx-qt/source/scwx/qt/ui/line_label.cpp +++ /dev/null @@ -1,251 +0,0 @@ -#include -#include -#include - -#include -#include - -namespace scwx -{ -namespace qt -{ -namespace ui -{ - -static const std::string logPrefix_ = "scwx::qt::ui::line_label"; -static const auto logger_ = scwx::util::Logger::Create(logPrefix_); - -class LineLabel::Impl -{ -public: - explicit Impl(LineLabel* self) : self_ {self} {}; - ~Impl() = default; - - QImage GenerateImage() const; - void UpdateLineLabel(const settings::LineSettings& lineSettings); - - LineLabel* self_; - - std::size_t borderWidth_ {1}; - std::size_t highlightWidth_ {1}; - std::size_t lineWidth_ {3}; - - boost::gil::rgba8_pixel_t borderColor_ {0, 0, 0, 255}; - boost::gil::rgba8_pixel_t highlightColor_ {255, 255, 0, 255}; - boost::gil::rgba8_pixel_t lineColor_ {0, 0, 255, 255}; - - QPixmap pixmap_ {}; - bool pixmapDirty_ {true}; - - boost::signals2::scoped_connection settingsStaged_ {}; -}; - -LineLabel::LineLabel(QWidget* parent) : - QFrame(parent), p {std::make_unique(this)} -{ -} - -LineLabel::~LineLabel() {} - -boost::gil::rgba8_pixel_t LineLabel::border_color() const -{ - return p->borderColor_; -} - -boost::gil::rgba8_pixel_t LineLabel::highlight_color() const -{ - return p->highlightColor_; -} - -boost::gil::rgba8_pixel_t LineLabel::line_color() const -{ - return p->lineColor_; -} - -std::size_t LineLabel::border_width() const -{ - return p->borderWidth_; -} - -std::size_t LineLabel::highlight_width() const -{ - return p->highlightWidth_; -} - -std::size_t LineLabel::line_width() const -{ - return p->lineWidth_; -} - -void LineLabel::set_border_width(std::size_t width) -{ - p->borderWidth_ = width; - p->pixmapDirty_ = true; - - QMetaObject::invokeMethod(this, &QWidget::updateGeometry); - QMetaObject::invokeMethod( - this, static_cast(&QWidget::update)); -} - -void LineLabel::set_highlight_width(std::size_t width) -{ - p->highlightWidth_ = width; - p->pixmapDirty_ = true; - - QMetaObject::invokeMethod(this, &QWidget::updateGeometry); - QMetaObject::invokeMethod( - this, static_cast(&QWidget::update)); -} - -void LineLabel::set_line_width(std::size_t width) -{ - p->lineWidth_ = width; - p->pixmapDirty_ = true; - - QMetaObject::invokeMethod(this, &QWidget::updateGeometry); - QMetaObject::invokeMethod( - this, static_cast(&QWidget::update)); -} - -void LineLabel::set_border_color(boost::gil::rgba8_pixel_t color) -{ - p->borderColor_ = color; - p->pixmapDirty_ = true; - - QMetaObject::invokeMethod( - this, static_cast(&QWidget::update)); -} - -void LineLabel::set_highlight_color(boost::gil::rgba8_pixel_t color) -{ - p->highlightColor_ = color; - p->pixmapDirty_ = true; - - QMetaObject::invokeMethod( - this, static_cast(&QWidget::update)); -} - -void LineLabel::set_line_color(boost::gil::rgba8_pixel_t color) -{ - p->lineColor_ = color; - p->pixmapDirty_ = true; - - QMetaObject::invokeMethod( - this, static_cast(&QWidget::update)); -} - -void LineLabel::set_line_settings(settings::LineSettings& lineSettings) -{ - p->settingsStaged_ = lineSettings.staged_signal().connect( - [this, &lineSettings]() { p->UpdateLineLabel(lineSettings); }); - - p->UpdateLineLabel(lineSettings); -} - -void LineLabel::Impl::UpdateLineLabel( - const settings::LineSettings& lineSettings) -{ - self_->set_border_color(util::color::ToRgba8PixelT( - lineSettings.border_color().GetStagedOrValue())); - self_->set_highlight_color(util::color::ToRgba8PixelT( - lineSettings.highlight_color().GetStagedOrValue())); - self_->set_line_color( - util::color::ToRgba8PixelT(lineSettings.line_color().GetStagedOrValue())); - - self_->set_border_width(lineSettings.border_width().GetStagedOrValue()); - self_->set_highlight_width( - lineSettings.highlight_width().GetStagedOrValue()); - self_->set_line_width(lineSettings.line_width().GetStagedOrValue()); -} - -QSize LineLabel::minimumSizeHint() const -{ - return sizeHint(); -} - -QSize LineLabel::sizeHint() const -{ - QMargins margins = contentsMargins(); - - const std::size_t width = 1; - const std::size_t height = - (p->borderWidth_ + p->highlightWidth_) * 2 + p->lineWidth_; - - return QSize(static_cast(width) + margins.left() + margins.right(), - static_cast(height) + margins.top() + margins.bottom()); -} - -void LineLabel::paintEvent(QPaintEvent* e) -{ - logger_->trace("paintEvent"); - - QFrame::paintEvent(e); - - if (p->pixmapDirty_) - { - QImage image = p->GenerateImage(); - p->pixmap_ = QPixmap::fromImage(image); - p->pixmapDirty_ = false; - } - - // Don't stretch the line pixmap vertically - QRect rect = contentsRect(); - if (rect.height() > p->pixmap_.height()) - { - int dy = rect.height() - p->pixmap_.height(); - int dy1 = dy / 2; - int dy2 = dy - dy1; - rect.adjust(0, dy1, 0, -dy2); - } - - QPainter painter(this); - painter.drawPixmap(rect, p->pixmap_); -} - -QImage LineLabel::Impl::GenerateImage() const -{ - const QRgb borderRgba = qRgba(static_cast(borderColor_[0]), - static_cast(borderColor_[1]), - static_cast(borderColor_[2]), - static_cast(borderColor_[3])); - const QRgb highlightRgba = qRgba(static_cast(highlightColor_[0]), - static_cast(highlightColor_[1]), - static_cast(highlightColor_[2]), - static_cast(highlightColor_[3])); - const QRgb lineRgba = qRgba(static_cast(lineColor_[0]), - static_cast(lineColor_[1]), - static_cast(lineColor_[2]), - static_cast(lineColor_[3])); - - const std::size_t width = 1; - const std::size_t height = (borderWidth_ + highlightWidth_) * 2 + lineWidth_; - - QImage image(static_cast(width), - static_cast(height), - QImage::Format::Format_ARGB32); - - std::size_t y = 0; - for (std::size_t i = 0; i < borderWidth_; ++i, ++y) - { - image.setPixel(0, static_cast(y), borderRgba); - image.setPixel(0, static_cast(height - 1 - y), borderRgba); - } - - for (std::size_t i = 0; i < highlightWidth_; ++i, ++y) - { - image.setPixel(0, static_cast(y), highlightRgba); - image.setPixel(0, static_cast(height - 1 - y), highlightRgba); - } - - for (std::size_t i = 0; i < lineWidth_; ++i, ++y) - { - image.setPixel(0, static_cast(y), lineRgba); - image.setPixel(0, static_cast(height - 1 - y), lineRgba); - } - - return image; -} - -} // namespace ui -} // namespace qt -} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/ui/line_label.hpp b/scwx-qt/source/scwx/qt/ui/line_label.hpp deleted file mode 100644 index b746a98e..00000000 --- a/scwx-qt/source/scwx/qt/ui/line_label.hpp +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once - -#include - -#include - -#include - -namespace scwx -{ -namespace qt -{ -namespace ui -{ - -class LineLabel : public QFrame -{ - Q_OBJECT - Q_DISABLE_COPY_MOVE(LineLabel) - -public: - explicit LineLabel(QWidget* parent = nullptr); - ~LineLabel(); - - boost::gil::rgba8_pixel_t border_color() const; - boost::gil::rgba8_pixel_t highlight_color() const; - boost::gil::rgba8_pixel_t line_color() const; - - std::size_t border_width() const; - std::size_t highlight_width() const; - std::size_t line_width() const; - - void set_border_color(boost::gil::rgba8_pixel_t color); - void set_highlight_color(boost::gil::rgba8_pixel_t color); - void set_line_color(boost::gil::rgba8_pixel_t color); - - void set_border_width(std::size_t width); - void set_highlight_width(std::size_t width); - void set_line_width(std::size_t width); - - void set_line_settings(settings::LineSettings& lineSettings); - -protected: - QSize minimumSizeHint() const override; - QSize sizeHint() const override; - void paintEvent(QPaintEvent* e) override; - -private: - class Impl; - std::unique_ptr p; -}; - -} // namespace ui -} // namespace qt -} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/ui/marker_dialog.cpp b/scwx-qt/source/scwx/qt/ui/marker_dialog.cpp deleted file mode 100644 index 3db33a06..00000000 --- a/scwx-qt/source/scwx/qt/ui/marker_dialog.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include "marker_dialog.hpp" -#include "ui_marker_dialog.h" - -#include -#include - -namespace scwx -{ -namespace qt -{ -namespace ui -{ - -static const std::string logPrefix_ = "scwx::qt::ui::marker_dialog"; -static const auto logger_ = scwx::util::Logger::Create(logPrefix_); - -class MarkerDialogImpl -{ -public: - explicit MarkerDialogImpl() {} - ~MarkerDialogImpl() = default; - - MarkerSettingsWidget* markerSettingsWidget_ {nullptr}; -}; - -MarkerDialog::MarkerDialog(QWidget* parent) : - QDialog(parent), - p {std::make_unique()}, - ui(new Ui::MarkerDialog) -{ - ui->setupUi(this); - - p->markerSettingsWidget_ = new MarkerSettingsWidget(this); - p->markerSettingsWidget_->layout()->setContentsMargins(0, 0, 0, 0); - ui->contentsFrame->layout()->addWidget(p->markerSettingsWidget_); -} - -MarkerDialog::~MarkerDialog() -{ - delete ui; -} - -} // namespace ui -} // namespace qt -} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/ui/marker_dialog.hpp b/scwx-qt/source/scwx/qt/ui/marker_dialog.hpp deleted file mode 100644 index 4a9503e9..00000000 --- a/scwx-qt/source/scwx/qt/ui/marker_dialog.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include - -namespace Ui -{ -class MarkerDialog; -} - -namespace scwx -{ -namespace qt -{ -namespace ui -{ - -class MarkerDialogImpl; - -class MarkerDialog : public QDialog -{ - Q_OBJECT - -public: - explicit MarkerDialog(QWidget* parent = nullptr); - ~MarkerDialog(); - -private: - friend class MarkerDialogImpl; - std::unique_ptr p; - Ui::MarkerDialog* ui; -}; - -} // namespace ui -} // namespace qt -} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/ui/marker_dialog.ui b/scwx-qt/source/scwx/qt/ui/marker_dialog.ui deleted file mode 100644 index 86e8fad3..00000000 --- a/scwx-qt/source/scwx/qt/ui/marker_dialog.ui +++ /dev/null @@ -1,82 +0,0 @@ - - - MarkerDialog - - - - 0 - 0 - 700 - 600 - - - - Location Marker Manager - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - Qt::Orientation::Horizontal - - - QDialogButtonBox::StandardButton::Close - - - - - - - - - buttonBox - accepted() - MarkerDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - MarkerDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/scwx-qt/source/scwx/qt/ui/marker_settings_widget.cpp b/scwx-qt/source/scwx/qt/ui/marker_settings_widget.cpp deleted file mode 100644 index da1d3809..00000000 --- a/scwx-qt/source/scwx/qt/ui/marker_settings_widget.cpp +++ /dev/null @@ -1,149 +0,0 @@ -#include "marker_settings_widget.hpp" -#include "ui_marker_settings_widget.h" - -#include -#include -#include -#include -#include -#include -#include - -#include - -namespace scwx::qt::ui -{ - -static const std::string logPrefix_ = "scwx::qt::ui::marker_settings_widget"; -static const auto logger_ = scwx::util::Logger::Create(logPrefix_); - -class MarkerSettingsWidgetImpl -{ -public: - explicit MarkerSettingsWidgetImpl(MarkerSettingsWidget* self) : - self_ {self}, - markerModel_ {new model::MarkerModel(self_)}, - proxyModel_ {new QSortFilterProxyModel(self_)} - { - proxyModel_->setSourceModel(markerModel_); - proxyModel_->setSortRole(Qt::DisplayRole); // TODO types::SortRole - proxyModel_->setFilterCaseSensitivity(Qt::CaseInsensitive); - proxyModel_->setFilterKeyColumn(-1); - } - - void ConnectSignals(); - void UpdateHotkeyLabel(); - - MarkerSettingsWidget* self_; - model::MarkerModel* markerModel_; - QSortFilterProxyModel* proxyModel_; - std::shared_ptr markerManager_ { - manager::MarkerManager::Instance()}; - std::shared_ptr editMarkerDialog_ {nullptr}; - boost::signals2::scoped_connection hotkeyConnection_; -}; - -MarkerSettingsWidget::MarkerSettingsWidget(QWidget* parent) : - QFrame(parent), - p {std::make_unique(this)}, - ui(new Ui::MarkerSettingsWidget) -{ - ui->setupUi(this); - - ui->removeButton->setEnabled(false); - ui->markerView->setModel(p->proxyModel_); - p->UpdateHotkeyLabel(); - - p->editMarkerDialog_ = std::make_shared(this); - - p->ConnectSignals(); -} - -MarkerSettingsWidget::~MarkerSettingsWidget() -{ - delete ui; -} - -void MarkerSettingsWidgetImpl::ConnectSignals() -{ - QObject::connect(self_->ui->addButton, - &QPushButton::clicked, - self_, - [this]() - { - editMarkerDialog_->setup(); - editMarkerDialog_->show(); - }); - QObject::connect( - self_->ui->removeButton, - &QPushButton::clicked, - self_, - [this]() - { - auto selectionModel = self_->ui->markerView->selectionModel(); - QModelIndex selected = selectionModel - ->selectedRows(static_cast( - model::MarkerModel::Column::Name)) - .first(); - - QVariant const id = - proxyModel_->data(selected, Qt::ItemDataRole::UserRole); - if (!id.isValid()) - { - return; - } - - markerManager_->remove_marker(id.toULongLong()); - }); - QObject::connect( - self_->ui->markerView->selectionModel(), - &QItemSelectionModel::selectionChanged, - self_, - [this](const QItemSelection& selected, const QItemSelection& deselected) - { - if (selected.size() == 0 && deselected.size() == 0) - { - // Items which stay selected but change their index are not - // included in selected and deselected. Thus, this signal might - // be emitted with both selected and deselected empty, if only - // the indices of selected items change. - return; - } - - const bool itemSelected = selected.size() > 0; - self_->ui->removeButton->setEnabled(itemSelected); - }); - QObject::connect(self_->ui->markerView, - &QAbstractItemView::doubleClicked, - self_, - [this](const QModelIndex& index) - { - QVariant const id = - proxyModel_->data(index, Qt::ItemDataRole::UserRole); - if (!id.isValid()) - { - return; - } - - editMarkerDialog_->setup(id.toULongLong()); - editMarkerDialog_->show(); - }); - hotkeyConnection_ = settings::HotkeySettings::Instance() - .hotkey(types::Hotkey::AddLocationMarker) - .changed_signal() - .connect([this]() { UpdateHotkeyLabel(); }); -} - -void MarkerSettingsWidgetImpl::UpdateHotkeyLabel() -{ - self_->ui->hotkeyLabel->setText( - fmt::format( - "A Location Marker can be placed at the location under the cursor by " - "pressing \"{}\" and edited by right clicking it on the map.", - settings::HotkeySettings::Instance() - .hotkey(types::Hotkey::AddLocationMarker) - .GetValue()) - .c_str()); -} - -} // namespace scwx::qt::ui diff --git a/scwx-qt/source/scwx/qt/ui/marker_settings_widget.hpp b/scwx-qt/source/scwx/qt/ui/marker_settings_widget.hpp deleted file mode 100644 index b784c418..00000000 --- a/scwx-qt/source/scwx/qt/ui/marker_settings_widget.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include - -namespace Ui -{ -class MarkerSettingsWidget; -} - -namespace scwx -{ -namespace qt -{ -namespace ui -{ - -class MarkerSettingsWidgetImpl; - -class MarkerSettingsWidget : public QFrame -{ - Q_OBJECT - -public: - explicit MarkerSettingsWidget(QWidget* parent = nullptr); - ~MarkerSettingsWidget(); - -private: - friend class MarkerSettingsWidgetImpl; - std::unique_ptr p; - Ui::MarkerSettingsWidget* ui; -}; - -} // namespace ui -} // namespace qt -} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/ui/marker_settings_widget.ui b/scwx-qt/source/scwx/qt/ui/marker_settings_widget.ui deleted file mode 100644 index 49b41c8b..00000000 --- a/scwx-qt/source/scwx/qt/ui/marker_settings_widget.ui +++ /dev/null @@ -1,109 +0,0 @@ - - - MarkerSettingsWidget - - - - 0 - 0 - 400 - 300 - - - - Frame - - - - 0 - - - - - - 0 - 0 - - - - - 9 - - - - QFrame::Shape::NoFrame - - - - - - Qt::TextFormat::PlainText - - - - - - - true - - - 0 - - - true - - - - - - - - 0 - - - 6 - - - 0 - - - 0 - - - - - Qt::Orientation::Horizontal - - - - 40 - 20 - - - - - - - - &Add - - - - - - - false - - - R&emove - - - - - - - - - - - diff --git a/scwx-qt/source/scwx/qt/ui/open_url_dialog.ui b/scwx-qt/source/scwx/qt/ui/open_url_dialog.ui index 117d62c1..a796d20d 100644 --- a/scwx-qt/source/scwx/qt/ui/open_url_dialog.ui +++ b/scwx-qt/source/scwx/qt/ui/open_url_dialog.ui @@ -16,6 +16,12 @@ + + QFrame::StyledPanel + + + QFrame::Raised + 0 @@ -52,7 +58,7 @@ - Qt::Orientation::Vertical + Qt::Vertical @@ -65,10 +71,10 @@ - Qt::Orientation::Horizontal + Qt::Horizontal - QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok + QDialogButtonBox::Cancel|QDialogButtonBox::Ok diff --git a/scwx-qt/source/scwx/qt/ui/placefile_dialog.ui b/scwx-qt/source/scwx/qt/ui/placefile_dialog.ui index aa3659bf..8ff045a6 100644 --- a/scwx-qt/source/scwx/qt/ui/placefile_dialog.ui +++ b/scwx-qt/source/scwx/qt/ui/placefile_dialog.ui @@ -16,6 +16,12 @@ + + QFrame::StyledPanel + + + QFrame::Raised + 0 @@ -35,10 +41,10 @@ - Qt::Orientation::Horizontal + Qt::Horizontal - QDialogButtonBox::StandardButton::Close + QDialogButtonBox::Close diff --git a/scwx-qt/source/scwx/qt/ui/placefile_settings_widget.ui b/scwx-qt/source/scwx/qt/ui/placefile_settings_widget.ui index 6355fdc0..b95ab784 100644 --- a/scwx-qt/source/scwx/qt/ui/placefile_settings_widget.ui +++ b/scwx-qt/source/scwx/qt/ui/placefile_settings_widget.ui @@ -29,6 +29,12 @@ + + QFrame::StyledPanel + + + QFrame::Raised + 0 @@ -55,7 +61,7 @@ - Qt::Orientation::Horizontal + Qt::Horizontal diff --git a/scwx-qt/source/scwx/qt/ui/radar_site_dialog.ui b/scwx-qt/source/scwx/qt/ui/radar_site_dialog.ui index bfaf7a5c..74eae33b 100644 --- a/scwx-qt/source/scwx/qt/ui/radar_site_dialog.ui +++ b/scwx-qt/source/scwx/qt/ui/radar_site_dialog.ui @@ -17,7 +17,7 @@ - QAbstractItemView::EditTrigger::CurrentChanged|QAbstractItemView::EditTrigger::DoubleClicked|QAbstractItemView::EditTrigger::EditKeyPressed|QAbstractItemView::EditTrigger::SelectedClicked + QAbstractItemView::CurrentChanged|QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked true @@ -32,6 +32,12 @@ + + QFrame::StyledPanel + + + QFrame::Raised + 0 @@ -58,10 +64,10 @@ - Qt::Orientation::Horizontal + Qt::Horizontal - QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok + QDialogButtonBox::Cancel|QDialogButtonBox::Ok diff --git a/scwx-qt/source/scwx/qt/ui/serial_port_dialog.cpp b/scwx-qt/source/scwx/qt/ui/serial_port_dialog.cpp index ca2daa42..d489c1d6 100644 --- a/scwx-qt/source/scwx/qt/ui/serial_port_dialog.cpp +++ b/scwx-qt/source/scwx/qt/ui/serial_port_dialog.cpp @@ -168,17 +168,7 @@ SerialPortDialog::~SerialPortDialog() std::string SerialPortDialog::serial_port() { - std::string serialPort = p->selectedSerialPort_; - -#if !defined(_WIN32) - auto it = p->portInfoMap_.find(p->selectedSerialPort_); - if (it != p->portInfoMap_.cend()) - { - serialPort = it->second.systemLocation().toStdString(); - } -#endif - - return serialPort; + return p->selectedSerialPort_; } int SerialPortDialog::baud_rate() @@ -235,8 +225,7 @@ void SerialPortDialog::Impl::UpdateModel() static const QStringList headerLabels { tr("Port"), tr("Description"), tr("Device")}; #else - static const QStringList headerLabels { - tr("Port"), tr("Location"), tr("Description")}; + static const QStringList headerLabels {tr("Port"), tr("Description")}; #endif // Clear existing serial ports @@ -271,11 +260,8 @@ void SerialPortDialog::Impl::UpdateModel() new QStandardItem(description), new QStandardItem(device)}); #else - const QString systemLocation = port.second.systemLocation(); - - root->appendRow({new QStandardItem(portName), - new QStandardItem(systemLocation), - new QStandardItem(description)}); + root->appendRow( + {new QStandardItem(portName), new QStandardItem(description)}); #endif } diff --git a/scwx-qt/source/scwx/qt/ui/settings/alert_palette_settings_widget.cpp b/scwx-qt/source/scwx/qt/ui/settings/alert_palette_settings_widget.cpp deleted file mode 100644 index a3ae4642..00000000 --- a/scwx-qt/source/scwx/qt/ui/settings/alert_palette_settings_widget.cpp +++ /dev/null @@ -1,292 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -namespace scwx -{ -namespace qt -{ -namespace ui -{ - -static const std::string logPrefix_ = - "scwx::qt::ui::settings::alert_palette_settings_widget"; - -class AlertPaletteSettingsWidget::Impl -{ -public: - explicit Impl(AlertPaletteSettingsWidget* self) : - self_ {self}, - phenomenonPagesWidget_ {new QStackedWidget(self)}, - phenomenonListView_ {new QListWidget(self)}, - editLineDialog_ {new EditLineDialog(self)} - { - SetupUi(); - ConnectSignals(); - } - ~Impl() {}; - - void AddPhenomenonLine(const std::string& name, - settings::LineSettings& lineSettings, - QGridLayout* layout, - int row); - QWidget* CreateStackedWidgetPage(awips::Phenomenon phenomenon); - void ConnectSignals(); - void SelectPhenomenon(awips::Phenomenon phenomenon); - void SetupUi(); - - AlertPaletteSettingsWidget* self_; - - QStackedWidget* phenomenonPagesWidget_; - QListWidget* phenomenonListView_; - - EditLineDialog* editLineDialog_; - settings::LineSettings* activeLineSettings_ {nullptr}; - - boost::unordered_flat_map phenomenonPages_ {}; - - std::vector connections_ {}; -}; - -AlertPaletteSettingsWidget::AlertPaletteSettingsWidget(QWidget* parent) : - SettingsPageWidget(parent), p {std::make_shared(this)} -{ -} - -AlertPaletteSettingsWidget::~AlertPaletteSettingsWidget() = default; - -void AlertPaletteSettingsWidget::Impl::SetupUi() -{ - // Setup phenomenon index pane - QLabel* phenomenonLabel = new QLabel(tr("Phenomenon:"), self_); - phenomenonPagesWidget_->setSizePolicy(QSizePolicy::Policy::MinimumExpanding, - QSizePolicy::Policy::Preferred); - - // Setup stacked widget - for (auto& phenomenon : settings::PaletteSettings::alert_phenomena()) - { - QWidget* phenomenonWidget = CreateStackedWidgetPage(phenomenon); - phenomenonPagesWidget_->addWidget(phenomenonWidget); - - phenomenonPages_.insert_or_assign(phenomenon, phenomenonWidget); - - phenomenonListView_->addItem( - QString::fromStdString(awips::GetPhenomenonText(phenomenon))); - } - - phenomenonListView_->setCurrentRow(0); - - // Create phenomenon index pane layout - QVBoxLayout* phenomenonIndexLayout = new QVBoxLayout(self_); - phenomenonIndexLayout->addWidget(phenomenonLabel); - phenomenonIndexLayout->addWidget(phenomenonListView_); - - QWidget* phenomenonIndexPane = new QWidget(self_); - phenomenonIndexPane->setLayout(phenomenonIndexLayout); - - // Create primary widget layout - QGridLayout* gridLayout = new QGridLayout(self_); - gridLayout->setContentsMargins(0, 0, 0, 0); - gridLayout->addWidget(phenomenonIndexPane, 0, 0); - gridLayout->addWidget(phenomenonPagesWidget_, 0, 1); - - QSpacerItem* spacer = - new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding); - gridLayout->addItem(spacer, 1, 0); - - self_->setLayout(gridLayout); -} - -void AlertPaletteSettingsWidget::Impl::ConnectSignals() -{ - connect( - phenomenonListView_->selectionModel(), - &QItemSelectionModel::selectionChanged, - self_, - [this](const QItemSelection& selected, const QItemSelection& deselected) - { - if (selected.size() == 0 && deselected.size() == 0) - { - // Items which stay selected but change their index are not - // included in selected and deselected. Thus, this signal might - // be emitted with both selected and deselected empty, if only - // the indices of selected items change. - return; - } - - if (selected.size() > 0) - { - QModelIndex selectedIndex = selected[0].indexes()[0]; - QVariant variantData = - phenomenonListView_->model()->data(selectedIndex); - if (variantData.typeId() == QMetaType::QString) - { - awips::Phenomenon phenomenon = awips::GetPhenomenonFromText( - variantData.toString().toStdString()); - SelectPhenomenon(phenomenon); - } - } - }); - - connect(editLineDialog_, - &EditLineDialog::accepted, - self_, - [this]() - { - // If the active line label was set - if (activeLineSettings_ != nullptr) - { - // Update the active line settings with selected line settings - activeLineSettings_->StageValues( - editLineDialog_->border_color(), - editLineDialog_->highlight_color(), - editLineDialog_->line_color(), - editLineDialog_->border_width(), - editLineDialog_->highlight_width(), - editLineDialog_->line_width()); - - // Reset the active line settings - activeLineSettings_ = nullptr; - } - }); -} - -void AlertPaletteSettingsWidget::Impl::SelectPhenomenon( - awips::Phenomenon phenomenon) -{ - auto it = phenomenonPages_.find(phenomenon); - if (it != phenomenonPages_.cend()) - { - phenomenonPagesWidget_->setCurrentWidget(it->second); - } -} - -QWidget* AlertPaletteSettingsWidget::Impl::CreateStackedWidgetPage( - awips::Phenomenon phenomenon) -{ - QWidget* page = new QWidget(self_); - QGridLayout* gridLayout = new QGridLayout(self_); - page->setLayout(gridLayout); - - const auto& impactBasedWarningInfo = - awips::ibw::GetImpactBasedWarningInfo(phenomenon); - - auto& alertPalette = - settings::PaletteSettings::Instance().alert_palette(phenomenon); - - int row = 0; - - // Add a blank label to align left and right widgets - gridLayout->addWidget(new QLabel(self_), row++, 0); - - AddPhenomenonLine( - "Active", - alertPalette.threat_category(awips::ibw::ThreatCategory::Base), - gridLayout, - row++); - - if (impactBasedWarningInfo.hasObservedTag_) - { - AddPhenomenonLine("Observed", alertPalette.observed(), gridLayout, row++); - } - - if (impactBasedWarningInfo.hasTornadoPossibleTag_) - { - AddPhenomenonLine("Tornado Possible", - alertPalette.tornado_possible(), - gridLayout, - row++); - } - - for (auto& category : impactBasedWarningInfo.threatCategories_) - { - if (category == awips::ibw::ThreatCategory::Base) - { - continue; - } - - AddPhenomenonLine(awips::ibw::GetThreatCategoryName(category), - alertPalette.threat_category(category), - gridLayout, - row++); - } - - AddPhenomenonLine("Inactive", alertPalette.inactive(), gridLayout, row++); - - QSpacerItem* spacer = - new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding); - gridLayout->addItem(spacer, row, 0); - - return page; -} - -void AlertPaletteSettingsWidget::Impl::AddPhenomenonLine( - const std::string& name, - settings::LineSettings& lineSettings, - QGridLayout* layout, - int row) -{ - QToolButton* toolButton = new QToolButton(self_); - toolButton->setText(tr("...")); - - LineLabel* lineLabel = new LineLabel(self_); - lineLabel->set_line_settings(lineSettings); - - QToolButton* resetButton = new QToolButton(self_); - resetButton->setIcon( - QIcon {":/res/icons/font-awesome-6/rotate-left-solid.svg"}); - resetButton->setVisible(!lineSettings.IsDefaultStaged()); - - layout->addWidget(new QLabel(tr(name.c_str()), self_), row, 0); - layout->addWidget(lineLabel, row, 1); - layout->addWidget(toolButton, row, 2); - layout->addWidget(resetButton, row, 3); - - self_->AddSettingsCategory(&lineSettings); - - connect(toolButton, - &QAbstractButton::clicked, - self_, - [this, lineLabel, &lineSettings]() - { - // Set the active line label for when the dialog is finished - activeLineSettings_ = &lineSettings; - - // Initialize dialog with current line settings - editLineDialog_->Initialize(lineLabel->border_color(), - lineLabel->highlight_color(), - lineLabel->line_color(), - lineLabel->border_width(), - lineLabel->highlight_width(), - lineLabel->line_width()); - - // Show the dialog - editLineDialog_->show(); - }); - - connect(resetButton, - &QAbstractButton::clicked, - self_, - [&lineSettings]() { lineSettings.StageDefaults(); }); - - connections_.emplace_back(lineSettings.staged_signal().connect( - [resetButton, &lineSettings]() - { resetButton->setVisible(!lineSettings.IsDefaultStaged()); })); -} - -} // namespace ui -} // namespace qt -} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/ui/settings/alert_palette_settings_widget.hpp b/scwx-qt/source/scwx/qt/ui/settings/alert_palette_settings_widget.hpp deleted file mode 100644 index 45f03e36..00000000 --- a/scwx-qt/source/scwx/qt/ui/settings/alert_palette_settings_widget.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -#include - -namespace scwx -{ -namespace qt -{ -namespace ui -{ - -class AlertPaletteSettingsWidget : public SettingsPageWidget -{ - Q_OBJECT - -public: - explicit AlertPaletteSettingsWidget(QWidget* parent = nullptr); - ~AlertPaletteSettingsWidget(); - -private: - class Impl; - std::shared_ptr p; -}; - -} // namespace ui -} // namespace qt -} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/ui/settings/settings_page_widget.cpp b/scwx-qt/source/scwx/qt/ui/settings/settings_page_widget.cpp index 41c43817..d174fbbd 100644 --- a/scwx-qt/source/scwx/qt/ui/settings/settings_page_widget.cpp +++ b/scwx-qt/source/scwx/qt/ui/settings/settings_page_widget.cpp @@ -19,7 +19,6 @@ public: explicit Impl() {} ~Impl() = default; - std::vector categories_; std::vector settings_; }; @@ -30,12 +29,6 @@ SettingsPageWidget::SettingsPageWidget(QWidget* parent) : SettingsPageWidget::~SettingsPageWidget() = default; -void SettingsPageWidget::AddSettingsCategory( - settings::SettingsCategory* category) -{ - p->categories_.push_back(category); -} - void SettingsPageWidget::AddSettingsInterface( settings::SettingsInterfaceBase* setting) { @@ -46,11 +39,6 @@ bool SettingsPageWidget::CommitChanges() { bool committed = false; - for (auto& category : p->categories_) - { - committed |= category->Commit(); - } - for (auto& setting : p->settings_) { committed |= setting->Commit(); @@ -61,11 +49,6 @@ bool SettingsPageWidget::CommitChanges() void SettingsPageWidget::DiscardChanges() { - for (auto& category : p->categories_) - { - category->Reset(); - } - for (auto& setting : p->settings_) { setting->Reset(); diff --git a/scwx-qt/source/scwx/qt/ui/settings/settings_page_widget.hpp b/scwx-qt/source/scwx/qt/ui/settings/settings_page_widget.hpp index 39d8647a..228badd6 100644 --- a/scwx-qt/source/scwx/qt/ui/settings/settings_page_widget.hpp +++ b/scwx-qt/source/scwx/qt/ui/settings/settings_page_widget.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include @@ -62,15 +61,6 @@ public: protected: void AddSettingsInterface(settings::SettingsInterfaceBase* setting); - /** - * Commits and resets all settings within a category upon page commit or - * reset. The use of SettingsInterface is preferred, as it allows the binding - * of widgets to these actions. - * - * @param [in] category Settings category - */ - void AddSettingsCategory(settings::SettingsCategory* category); - private: class Impl; std::shared_ptr p; diff --git a/scwx-qt/source/scwx/qt/ui/settings/unit_settings_widget.cpp b/scwx-qt/source/scwx/qt/ui/settings/unit_settings_widget.cpp index ea678e65..aff11583 100644 --- a/scwx-qt/source/scwx/qt/ui/settings/unit_settings_widget.cpp +++ b/scwx-qt/source/scwx/qt/ui/settings/unit_settings_widget.cpp @@ -2,17 +2,21 @@ #include #include #include -#include #include #include #include #include +#include #include #include #include -namespace scwx::qt::ui +namespace scwx +{ +namespace qt +{ +namespace ui { static const std::string logPrefix_ = @@ -47,7 +51,7 @@ public: [&row, &self, this]( settings::SettingsInterface& settingsInterface, const std::string& labelName, - QFocusedComboBox* comboBox) + QComboBox* comboBox) { QLabel* label = new QLabel(QObject::tr(labelName.c_str()), self); QToolButton* resetButton = new QToolButton(self); @@ -68,12 +72,9 @@ public: ++row; }; - // Qt manages the memory for these widgets - // NOLINTBEGIN(cppcoreguidelines-owning-memory) - auto* accumulationComboBox = new QFocusedComboBox(self); + QComboBox* accumulationComboBox = new QComboBox(self); accumulationComboBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - accumulationComboBox->setFocusPolicy(Qt::StrongFocus); accumulationUnits_.SetSettingsVariable(unitSettings.accumulation_units()); SCWX_SETTINGS_COMBO_BOX(accumulationUnits_, accumulationComboBox, @@ -81,10 +82,9 @@ public: types::GetAccumulationUnitsName); AddRow(accumulationUnits_, "Accumulation", accumulationComboBox); - auto* echoTopsComboBox = new QFocusedComboBox(self); + QComboBox* echoTopsComboBox = new QComboBox(self); echoTopsComboBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - echoTopsComboBox->setFocusPolicy(Qt::StrongFocus); echoTopsUnits_.SetSettingsVariable(unitSettings.echo_tops_units()); SCWX_SETTINGS_COMBO_BOX(echoTopsUnits_, echoTopsComboBox, @@ -92,10 +92,9 @@ public: types::GetEchoTopsUnitsName); AddRow(echoTopsUnits_, "Echo Tops", echoTopsComboBox); - auto* speedComboBox = new QFocusedComboBox(self); + QComboBox* speedComboBox = new QComboBox(self); speedComboBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - speedComboBox->setFocusPolicy(Qt::StrongFocus); speedUnits_.SetSettingsVariable(unitSettings.speed_units()); SCWX_SETTINGS_COMBO_BOX(speedUnits_, speedComboBox, @@ -103,10 +102,9 @@ public: types::GetSpeedUnitsName); AddRow(speedUnits_, "Speed", speedComboBox); - auto* distanceComboBox = new QFocusedComboBox(self); + QComboBox* distanceComboBox = new QComboBox(self); distanceComboBox->setSizePolicy(QSizePolicy::Expanding, - QSizePolicy::Preferred); - distanceComboBox->setFocusPolicy(Qt::StrongFocus); + QSizePolicy::Preferred); distanceUnits_.SetSettingsVariable(unitSettings.distance_units()); SCWX_SETTINGS_COMBO_BOX(distanceUnits_, distanceComboBox, @@ -114,10 +112,9 @@ public: types::GetDistanceUnitsName); AddRow(distanceUnits_, "Distance", distanceComboBox); - auto* otherComboBox = new QFocusedComboBox(self); + QComboBox* otherComboBox = new QComboBox(self); otherComboBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - otherComboBox->setFocusPolicy(Qt::StrongFocus); otherUnits_.SetSettingsVariable(unitSettings.other_units()); SCWX_SETTINGS_COMBO_BOX(otherUnits_, otherComboBox, @@ -125,19 +122,12 @@ public: types::GetOtherUnitsName); AddRow(otherUnits_, "Other", otherComboBox); - auto* spacer = + QSpacerItem* spacer = new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding); gridLayout_->addItem(spacer, row, 0); - - // NOLINTEND(cppcoreguidelines-owning-memory) } ~Impl() = default; - Impl(const Impl&) = delete; - Impl(Impl&&) = delete; - Impl& operator=(const Impl&) = delete; - Impl& operator=(Impl&&) = delete; - QWidget* contents_; QLayout* layout_; QScrollArea* scrollArea_ {}; @@ -157,4 +147,6 @@ UnitSettingsWidget::UnitSettingsWidget(QWidget* parent) : UnitSettingsWidget::~UnitSettingsWidget() = default; -} // namespace scwx::qt::ui +} // namespace ui +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/ui/settings_dialog.cpp b/scwx-qt/source/scwx/qt/ui/settings_dialog.cpp index 81e3a96d..8159fb69 100644 --- a/scwx-qt/source/scwx/qt/ui/settings_dialog.cpp +++ b/scwx-qt/source/scwx/qt/ui/settings_dialog.cpp @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -24,13 +23,11 @@ #include #include #include -#include +#include #include #include -#include #include #include -#include #include #include #include @@ -43,16 +40,8 @@ #include #include #include -#include #include -#include #include -#include - -#define QT6CT_LIBRARY -#include -#include -#undef QT6CT_LIBRARY namespace scwx { @@ -114,8 +103,7 @@ static const std::unordered_map class SettingsDialogImpl { public: - explicit SettingsDialogImpl(SettingsDialog* self, - QMapLibre::Settings& mapSettings) : + explicit SettingsDialogImpl(SettingsDialog* self) : self_ {self}, radarSiteDialog_ {new RadarSiteDialog(self)}, alertAudioRadarSiteDialog_ {new RadarSiteDialog(self)}, @@ -123,7 +111,6 @@ public: countyDialog_ {new CountyDialog(self)}, wfoDialog_ {new WFODialog(self)}, fontDialog_ {new QFontDialog(self)}, - mapSettings_ {mapSettings}, fontCategoryModel_ {new QStandardItemModel(self)}, settings_ {std::initializer_list { &defaultRadarSite_, @@ -133,7 +120,6 @@ public: &mapboxApiKey_, &mapTilerApiKey_, &theme_, - &themeFile_, &defaultAlertAction_, &clockFormat_, &customStyleDrawLayer_, @@ -143,16 +129,11 @@ public: &nmeaBaudRate_, &nmeaSource_, &warningsProvider_, - &radarSiteThreshold_, &antiAliasingEnabled_, - ¢erOnRadarSelection_, &showMapAttribution_, &showMapCenter_, &showMapLogo_, - &showSmoothedRangeFolding_, &updateNotificationsEnabled_, - &cursorIconAlwaysOn_, - &cursorIconScale_, &debugEnabled_, &alertAudioSoundFile_, &alertAudioLocationMethod_, @@ -200,6 +181,7 @@ public: void SetupTextTab(); void SetupHotkeysTab(); + void ShowColorDialog(QLineEdit* lineEdit, QFrame* frame = nullptr); void UpdateRadarDialogLocation(const std::string& id); void UpdateAlertRadarDialogLocation(const std::string& id); @@ -221,7 +203,8 @@ public: const std::string& value, QLabel* imageLabel); static std::string - RadarSiteLabel(std::shared_ptr& radarSite); + RadarSiteLabel(std::shared_ptr& radarSite); + static void SetBackgroundColor(const std::string& value, QFrame* frame); SettingsDialog* self_; RadarSiteDialog* radarSiteDialog_; @@ -231,8 +214,6 @@ public: WFODialog* wfoDialog_; QFontDialog* fontDialog_; - QMapLibre::Settings& mapSettings_; - QStandardItemModel* fontCategoryModel_; types::FontCategory selectedFontCategory_ {types::FontCategory::Unknown}; @@ -243,7 +224,6 @@ public: manager::PositionManager::Instance()}; std::vector settingsPages_ {}; - AlertPaletteSettingsWidget* alertPaletteSettingsWidget_ {}; HotkeySettingsWidget* hotkeySettingsWidget_ {}; UnitSettingsWidget* unitSettingsWidget_ {}; @@ -262,22 +242,22 @@ public: settings::SettingsInterface nmeaBaudRate_ {}; settings::SettingsInterface nmeaSource_ {}; settings::SettingsInterface theme_ {}; - settings::SettingsInterface themeFile_ {}; settings::SettingsInterface warningsProvider_ {}; - settings::SettingsInterface radarSiteThreshold_ {}; settings::SettingsInterface antiAliasingEnabled_ {}; - settings::SettingsInterface centerOnRadarSelection_ {}; settings::SettingsInterface showMapAttribution_ {}; settings::SettingsInterface showMapCenter_ {}; settings::SettingsInterface showMapLogo_ {}; - settings::SettingsInterface showSmoothedRangeFolding_ {}; settings::SettingsInterface updateNotificationsEnabled_ {}; - settings::SettingsInterface cursorIconAlwaysOn_ {}; - settings::SettingsInterface cursorIconScale_ {}; settings::SettingsInterface debugEnabled_ {}; std::unordered_map> colorTables_ {}; + std::unordered_map> + activeAlertColors_ {}; + std::unordered_map> + inactiveAlertColors_ {}; settings::SettingsInterface alertAudioSoundFile_ {}; settings::SettingsInterface alertAudioLocationMethod_ {}; @@ -308,18 +288,13 @@ public: std::vector settings_; }; -SettingsDialog::SettingsDialog(QMapLibre::Settings& mapSettings, - QWidget* parent) : +SettingsDialog::SettingsDialog(QWidget* parent) : QDialog(parent), - p {std::make_unique(this, mapSettings)}, + p {std::make_unique(this)}, ui(new Ui::SettingsDialog) { ui->setupUi(this); - // Set OK as default - ui->buttonBox->button(QDialogButtonBox::StandardButton::Ok) - ->setDefault(true); - // General p->SetupGeneralTab(); @@ -383,23 +358,24 @@ void SettingsDialogImpl::ConnectSignals() self_, [this]() { alertAudioRadarSiteDialog_->show(); }); - QObject::connect( - alertAudioRadarSiteDialog_, - &RadarSiteDialog::accepted, - self_, - [this]() - { - std::string id = alertAudioRadarSiteDialog_->radar_site(); + QObject::connect(alertAudioRadarSiteDialog_, + &RadarSiteDialog::accepted, + self_, + [this]() + { + std::string id = + alertAudioRadarSiteDialog_->radar_site(); - std::shared_ptr radarSite = - config::RadarSite::Get(id); + std::shared_ptr radarSite = + config::RadarSite::Get(id); - if (radarSite != nullptr) - { - self_->ui->alertAudioRadarSiteComboBox->setCurrentText( - QString::fromStdString(RadarSiteLabel(radarSite))); - } - }); + if (radarSite != nullptr) + { + self_->ui->alertAudioRadarSiteComboBox + ->setCurrentText(QString::fromStdString( + RadarSiteLabel(radarSite))); + } + }); QObject::connect(self_->ui->gpsSourceSelectButton, &QAbstractButton::clicked, @@ -549,22 +525,6 @@ void SettingsDialogImpl::SetupGeneralTab() { settings::GeneralSettings& generalSettings = settings::GeneralSettings::Instance(); - settings::ProductSettings& productSettings = - settings::ProductSettings::Instance(); - - QObject::connect( - self_->ui->themeComboBox, - &QComboBox::currentTextChanged, - self_, - [this](const QString& text) - { - const types::UiStyle style = types::GetUiStyle(text.toStdString()); - const bool themeFileEnabled = style == types::UiStyle::FusionCustom; - - self_->ui->themeFileLineEdit->setEnabled(themeFileEnabled); - self_->ui->themeFileSelectButton->setEnabled(themeFileEnabled); - self_->ui->resetThemeFileButton->setEnabled(themeFileEnabled); - }); theme_.SetSettingsVariable(generalSettings.theme()); SCWX_SETTINGS_COMBO_BOX(theme_, @@ -573,63 +533,6 @@ void SettingsDialogImpl::SetupGeneralTab() types::GetUiStyleName); theme_.SetResetButton(self_->ui->resetThemeButton); - themeFile_.SetSettingsVariable(generalSettings.theme_file()); - themeFile_.SetEditWidget(self_->ui->themeFileLineEdit); - themeFile_.SetResetButton(self_->ui->resetThemeFileButton); - themeFile_.EnableTrimming(); - - QObject::connect( - self_->ui->themeFileSelectButton, - &QAbstractButton::clicked, - self_, - [this]() - { - const settings::GeneralSettings& generalSettings = - settings::GeneralSettings::Instance(); - QString file = generalSettings.theme_file().GetStagedOrValue().c_str(); - - if (file.isEmpty()) - { - const QString appDataPath {QStandardPaths::writableLocation( - QStandardPaths::AppLocalDataLocation)}; - file = appDataPath + "/theme.conf"; - self_->ui->themeFileLineEdit->setText(file); - // setText does not emit the textEdited signal - Q_EMIT self_->ui->themeFileLineEdit->textEdited(file); - } - - const QPalette palette = - Qt6CT::loadColorScheme(file, QApplication::palette()); - QStyle* style = QApplication::style(); - - // WA_DeleteOnClose manages memory - // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - auto* dialog = new PaletteEditDialog(palette, style, self_); - dialog->setAttribute(Qt::WA_DeleteOnClose); - - QObject::connect( - dialog, - &QDialog::accepted, - self_, - [dialog]() - { - const QPalette palette = dialog->selectedPalette(); - const settings::GeneralSettings& generalSettings = - settings::GeneralSettings::Instance(); - const QString file = - generalSettings.theme_file().GetStagedOrValue().c_str(); - Qt6CT::createColorScheme(file, palette); - - auto uiStyle = scwx::qt::types::GetUiStyle( - generalSettings.theme().GetValue()); - if (uiStyle == scwx::qt::types::UiStyle::FusionCustom) - { - QApplication::setPalette(palette); - } - }); - dialog->open(); - }); - auto radarSites = config::RadarSite::GetAll(); // Sort radar sites by ID @@ -674,7 +577,7 @@ void SettingsDialogImpl::SetupGeneralTab() [](const std::string& text) -> std::string { // Find the position of location details - size_t pos = text.find(" ("); + size_t pos = text.rfind(" ("); if (pos == std::string::npos) { @@ -704,55 +607,22 @@ void SettingsDialogImpl::SetupGeneralTab() map::GetMapProviderName); mapProvider_.SetResetButton(self_->ui->resetMapProviderButton); - self_->ui->mapboxApiKeyLineEdit->setMapProvider(map::MapProvider::Mapbox); mapboxApiKey_.SetSettingsVariable(generalSettings.mapbox_api_key()); mapboxApiKey_.SetEditWidget(self_->ui->mapboxApiKeyLineEdit); mapboxApiKey_.SetResetButton(self_->ui->resetMapboxApiKeyButton); - mapboxApiKey_.EnableTrimming(); - self_->ui->mapTilerApiKeyLineEdit->setMapProvider( - map::MapProvider::MapTiler); mapTilerApiKey_.SetSettingsVariable(generalSettings.maptiler_api_key()); mapTilerApiKey_.SetEditWidget(self_->ui->mapTilerApiKeyLineEdit); mapTilerApiKey_.SetResetButton(self_->ui->resetMapTilerApiKeyButton); - mapTilerApiKey_.EnableTrimming(); customStyleUrl_.SetSettingsVariable(generalSettings.custom_style_url()); customStyleUrl_.SetEditWidget(self_->ui->customMapUrlLineEdit); customStyleUrl_.SetResetButton(self_->ui->resetCustomMapUrlButton); - customStyleUrl_.SetInvalidTooltip( - "Remove anything following \"?key=\" in the URL"); - customStyleUrl_.EnableTrimming(); customStyleDrawLayer_.SetSettingsVariable( generalSettings.custom_style_draw_layer()); customStyleDrawLayer_.SetEditWidget(self_->ui->customMapLayerLineEdit); customStyleDrawLayer_.SetResetButton(self_->ui->resetCustomMapLayerButton); - QObject::connect( - self_->ui->customMapLayerToolButton, - &QAbstractButton::clicked, - self_, - [this]() - { - // WA_DeleteOnClose manages memory - // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - auto* customLayerDialog = new ui::CustomLayerDialog(mapSettings_); - customLayerDialog->setAttribute(Qt::WA_DeleteOnClose); - QObject::connect( - customLayerDialog, - &QDialog::accepted, - self_, - [this, customLayerDialog]() - { - auto newLayer = customLayerDialog->selected_layer(); - self_->ui->customMapLayerLineEdit->setText(newLayer.c_str()); - // setText does not emit the textEdited signal - Q_EMIT - self_->ui->customMapLayerLineEdit->textEdited(newLayer.c_str()); - }); - - customLayerDialog->open(); - }); defaultAlertAction_.SetSettingsVariable( generalSettings.default_alert_action()); @@ -809,47 +679,15 @@ void SettingsDialogImpl::SetupGeneralTab() nmeaSource_.SetSettingsVariable(generalSettings.nmea_source()); nmeaSource_.SetEditWidget(self_->ui->nmeaSourceLineEdit); nmeaSource_.SetResetButton(self_->ui->resetNmeaSourceButton); - nmeaSource_.EnableTrimming(); warningsProvider_.SetSettingsVariable(generalSettings.warnings_provider()); warningsProvider_.SetEditWidget(self_->ui->warningsProviderLineEdit); warningsProvider_.SetResetButton(self_->ui->resetWarningsProviderButton); - warningsProvider_.EnableTrimming(); - - radarSiteThreshold_.SetSettingsVariable( - generalSettings.radar_site_threshold()); - radarSiteThreshold_.SetEditWidget(self_->ui->radarSiteThresholdSpinBox); - radarSiteThreshold_.SetResetButton(self_->ui->resetRadarSiteThresholdButton); - radarSiteThreshold_.SetUnitLabel(self_->ui->radarSiteThresholdUnitLabel); - auto radarSiteThresholdUpdateUnits = [this](const std::string& newValue) - { - const types::DistanceUnits radiusUnits = - types::GetDistanceUnitsFromName(newValue); - const double radiusScale = types::GetDistanceUnitsScale(radiusUnits); - const std::string abbreviation = - types::GetDistanceUnitsAbbreviation(radiusUnits); - - radarSiteThreshold_.SetUnit(radiusScale, abbreviation); - }; - settings::UnitSettings::Instance() - .distance_units() - .RegisterValueStagedCallback(radarSiteThresholdUpdateUnits); - radarSiteThresholdUpdateUnits( - settings::UnitSettings::Instance().distance_units().GetValue()); - - cursorIconScale_.SetSettingsVariable(generalSettings.cursor_icon_scale()); - cursorIconScale_.SetEditWidget(self_->ui->cursorIconScaleSpinBox); - cursorIconScale_.SetResetButton(self_->ui->resetCursorIconScaleButton); antiAliasingEnabled_.SetSettingsVariable( generalSettings.anti_aliasing_enabled()); antiAliasingEnabled_.SetEditWidget(self_->ui->antiAliasingEnabledCheckBox); - centerOnRadarSelection_.SetSettingsVariable( - generalSettings.center_on_radar_selection()); - centerOnRadarSelection_.SetEditWidget( - self_->ui->centerOnRadarSelectionCheckBox); - showMapAttribution_.SetSettingsVariable( generalSettings.show_map_attribution()); showMapAttribution_.SetEditWidget(self_->ui->showMapAttributionCheckBox); @@ -860,20 +698,11 @@ void SettingsDialogImpl::SetupGeneralTab() showMapLogo_.SetSettingsVariable(generalSettings.show_map_logo()); showMapLogo_.SetEditWidget(self_->ui->showMapLogoCheckBox); - showSmoothedRangeFolding_.SetSettingsVariable( - productSettings.show_smoothed_range_folding()); - showSmoothedRangeFolding_.SetEditWidget( - self_->ui->showSmoothedRangeFoldingCheckBox); - updateNotificationsEnabled_.SetSettingsVariable( generalSettings.update_notifications_enabled()); updateNotificationsEnabled_.SetEditWidget( self_->ui->enableUpdateNotificationsCheckBox); - cursorIconAlwaysOn_.SetSettingsVariable( - generalSettings.cursor_icon_always_on()); - cursorIconAlwaysOn_.SetEditWidget(self_->ui->cursorIconAlwaysOnCheckBox); - debugEnabled_.SetSettingsVariable(generalSettings.debug_enabled()); debugEnabled_.SetEditWidget(self_->ui->debugEnabledCheckBox); } @@ -928,7 +757,6 @@ void SettingsDialogImpl::SetupPalettesColorTablesTab() colorTable.SetSettingsVariable(colorTableVariable); colorTable.SetEditWidget(lineEdit); colorTable.SetResetButton(resetButton); - colorTable.EnableTrimming(); colorTableVariable.RegisterValueStagedCallback( [colorTableType, imageLabel](const std::string& value) @@ -956,7 +784,7 @@ void SettingsDialogImpl::SetupPalettesColorTablesTab() QObject::connect(dialog, &QFileDialog::fileSelected, self_, - [lineEdit](const QString& file) + [this, lineEdit](const QString& file) { QString path = QDir::toNativeSeparators(file); @@ -975,14 +803,123 @@ void SettingsDialogImpl::SetupPalettesColorTablesTab() void SettingsDialogImpl::SetupPalettesAlertsTab() { + settings::PaletteSettings& paletteSettings = + settings::PaletteSettings::Instance(); + // Palettes > Alerts - QVBoxLayout* layout = new QVBoxLayout(self_->ui->alertsPalette); + QGridLayout* alertsLayout = + reinterpret_cast(self_->ui->alertsFrame->layout()); - alertPaletteSettingsWidget_ = - new AlertPaletteSettingsWidget(self_->ui->hotkeys); - layout->addWidget(alertPaletteSettingsWidget_); + QLabel* phenomenonLabel = new QLabel(QObject::tr("Phenomenon"), self_); + QLabel* activeLabel = new QLabel(QObject::tr("Active"), self_); + QLabel* inactiveLabel = new QLabel(QObject::tr("Inactive"), self_); - settingsPages_.push_back(alertPaletteSettingsWidget_); + QFont boldFont; + boldFont.setBold(true); + phenomenonLabel->setFont(boldFont); + activeLabel->setFont(boldFont); + inactiveLabel->setFont(boldFont); + + alertsLayout->addWidget(phenomenonLabel, 0, 0); + alertsLayout->addWidget(activeLabel, 0, 1, 1, 4); + alertsLayout->addWidget(inactiveLabel, 0, 5, 1, 4); + + auto& alertPhenomena = settings::PaletteSettings::alert_phenomena(); + + activeAlertColors_.reserve(alertPhenomena.size()); + inactiveAlertColors_.reserve(alertPhenomena.size()); + + int alertsRow = 1; + for (auto& phenomenon : alertPhenomena) + { + QFrame* activeFrame = new QFrame(self_); + QFrame* inactiveFrame = new QFrame(self_); + + QLineEdit* activeEdit = new QLineEdit(self_); + QLineEdit* inactiveEdit = new QLineEdit(self_); + + QToolButton* activeButton = new QToolButton(self_); + QToolButton* inactiveButton = new QToolButton(self_); + QToolButton* activeResetButton = new QToolButton(self_); + QToolButton* inactiveResetButton = new QToolButton(self_); + + activeFrame->setMinimumHeight(24); + activeFrame->setMinimumWidth(24); + activeFrame->setFrameShape(QFrame::Shape::Box); + activeFrame->setFrameShadow(QFrame::Shadow::Plain); + inactiveFrame->setMinimumHeight(24); + inactiveFrame->setMinimumWidth(24); + inactiveFrame->setFrameShape(QFrame::Shape::Box); + inactiveFrame->setFrameShadow(QFrame::Shadow::Plain); + + activeButton->setIcon( + QIcon {":/res/icons/font-awesome-6/palette-solid.svg"}); + inactiveButton->setIcon( + QIcon {":/res/icons/font-awesome-6/palette-solid.svg"}); + activeResetButton->setIcon( + QIcon {":/res/icons/font-awesome-6/rotate-left-solid.svg"}); + inactiveResetButton->setIcon( + QIcon {":/res/icons/font-awesome-6/rotate-left-solid.svg"}); + + alertsLayout->addWidget( + new QLabel(QObject::tr(awips::GetPhenomenonText(phenomenon).c_str()), + self_), + alertsRow, + 0); + alertsLayout->addWidget(activeFrame, alertsRow, 1); + alertsLayout->addWidget(activeEdit, alertsRow, 2); + alertsLayout->addWidget(activeButton, alertsRow, 3); + alertsLayout->addWidget(activeResetButton, alertsRow, 4); + alertsLayout->addWidget(inactiveFrame, alertsRow, 5); + alertsLayout->addWidget(inactiveEdit, alertsRow, 6); + alertsLayout->addWidget(inactiveButton, alertsRow, 7); + alertsLayout->addWidget(inactiveResetButton, alertsRow, 8); + ++alertsRow; + + // Create settings interface + auto activeResult = activeAlertColors_.emplace( + phenomenon, settings::SettingsInterface {}); + auto inactiveResult = inactiveAlertColors_.emplace( + phenomenon, settings::SettingsInterface {}); + auto& activeColor = activeResult.first->second; + auto& inactiveColor = inactiveResult.first->second; + + // Add to settings list + settings_.push_back(&activeColor); + settings_.push_back(&inactiveColor); + + auto& activeSetting = paletteSettings.alert_color(phenomenon, true); + auto& inactiveSetting = paletteSettings.alert_color(phenomenon, false); + + activeColor.SetSettingsVariable(activeSetting); + activeColor.SetEditWidget(activeEdit); + activeColor.SetResetButton(activeResetButton); + + inactiveColor.SetSettingsVariable(inactiveSetting); + inactiveColor.SetEditWidget(inactiveEdit); + inactiveColor.SetResetButton(inactiveResetButton); + + SetBackgroundColor(activeSetting.GetValue(), activeFrame); + SetBackgroundColor(inactiveSetting.GetValue(), inactiveFrame); + + activeSetting.RegisterValueStagedCallback( + [activeFrame](const std::string& value) + { SetBackgroundColor(value, activeFrame); }); + inactiveSetting.RegisterValueStagedCallback( + [inactiveFrame](const std::string& value) + { SetBackgroundColor(value, inactiveFrame); }); + + QObject::connect(activeButton, + &QAbstractButton::clicked, + self_, + [=, this]() + { ShowColorDialog(activeEdit, activeFrame); }); + QObject::connect(inactiveButton, + &QAbstractButton::clicked, + self_, + [=, this]() + { ShowColorDialog(inactiveEdit, inactiveFrame); }); + } } void SettingsDialogImpl::SetupUnitsTab() @@ -1016,7 +953,8 @@ void SettingsDialogImpl::SetupAudioTab() locationMethod == types::LocationMethod::RadarSite; bool countyEntryEnabled = locationMethod == types::LocationMethod::County; - bool wfoEntryEnabled = locationMethod == types::LocationMethod::WFO; + bool wfoEntryEnabled = + locationMethod == types::LocationMethod::WFO; self_->ui->alertAudioLatitudeSpinBox->setEnabled( coordinateEntryEnabled); @@ -1034,8 +972,10 @@ void SettingsDialogImpl::SetupAudioTab() self_->ui->resetAlertAudioRadarSiteButton->setEnabled( radarSiteEntryEnable); - self_->ui->alertAudioRadiusSpinBox->setEnabled(radiusEntryEnable); - self_->ui->resetAlertAudioRadiusButton->setEnabled(radiusEntryEnable); + self_->ui->alertAudioRadiusSpinBox->setEnabled( + radiusEntryEnable); + self_->ui->resetAlertAudioRadiusButton->setEnabled( + radiusEntryEnable); self_->ui->alertAudioCountyLineEdit->setEnabled(countyEntryEnabled); self_->ui->alertAudioCountySelectButton->setEnabled( @@ -1052,7 +992,6 @@ void SettingsDialogImpl::SetupAudioTab() alertAudioSoundFile_.SetSettingsVariable(audioSettings.alert_sound_file()); alertAudioSoundFile_.SetEditWidget(self_->ui->alertAudioSoundLineEdit); alertAudioSoundFile_.SetResetButton(self_->ui->resetAlertAudioSoundButton); - alertAudioSoundFile_.EnableTrimming(); QObject::connect( self_->ui->alertAudioSoundSelectButton, @@ -1134,7 +1073,7 @@ void SettingsDialogImpl::SetupAudioTab() [](const std::string& text) -> std::string { // Find the position of location details - size_t pos = text.find(" ("); + size_t pos = text.rfind(" ("); if (pos == std::string::npos) { @@ -1152,14 +1091,15 @@ void SettingsDialogImpl::SetupAudioTab() alertAudioRadius_.SetSettingsVariable(audioSettings.alert_radius()); alertAudioRadius_.SetEditWidget(self_->ui->alertAudioRadiusSpinBox); - alertAudioRadius_.SetResetButton(self_->ui->resetAlertAudioRadiusButton); + alertAudioRadius_.SetResetButton( + self_->ui->resetAlertAudioRadiusButton); alertAudioRadius_.SetUnitLabel(self_->ui->alertAudioRadiusUnitsLabel); auto alertAudioRadiusUpdateUnits = [this](const std::string& newValue) { - const types::DistanceUnits radiusUnits = + types::DistanceUnits radiusUnits = types::GetDistanceUnitsFromName(newValue); - const double radiusScale = types::GetDistanceUnitsScale(radiusUnits); - const std::string abbreviation = + double radiusScale = types::GetDistanceUnitsScale(radiusUnits); + std::string abbreviation = types::GetDistanceUnitsAbbreviation(radiusUnits); alertAudioRadius_.SetUnit(radiusScale, abbreviation); @@ -1265,12 +1205,15 @@ void SettingsDialogImpl::SetupAudioTab() alertAudioCounty_.SetSettingsVariable(audioSettings.alert_county()); alertAudioCounty_.SetEditWidget(self_->ui->alertAudioCountyLineEdit); alertAudioCounty_.SetResetButton(self_->ui->resetAlertAudioCountyButton); - alertAudioCounty_.EnableTrimming(); - QObject::connect(self_->ui->alertAudioWFOSelectButton, - &QAbstractButton::clicked, - self_, - [this]() { wfoDialog_->show(); }); + QObject::connect( + self_->ui->alertAudioWFOSelectButton, + &QAbstractButton::clicked, + self_, + [this]() + { + wfoDialog_->show(); + }); QObject::connect(wfoDialog_, &WFODialog::accepted, self_, @@ -1289,8 +1232,9 @@ void SettingsDialogImpl::SetupAudioTab() self_, [this](const QString& text) { - std::string wfoName = config::CountyDatabase::GetWFOName( - text.toStdString()); + std::string wfoName = + config::CountyDatabase::GetWFOName( + text.toStdString()); self_->ui->alertAudioWFOLabel->setText( QString::fromStdString(wfoName)); }); @@ -1298,7 +1242,7 @@ void SettingsDialogImpl::SetupAudioTab() alertAudioWFO_.SetSettingsVariable(audioSettings.alert_wfo()); alertAudioWFO_.SetEditWidget(self_->ui->alertAudioWFOLineEdit); alertAudioWFO_.SetResetButton(self_->ui->resetAlertAudioWFOButton); - alertAudioWFO_.EnableTrimming(); + } void SettingsDialogImpl::SetupTextTab() @@ -1440,6 +1384,44 @@ void SettingsDialogImpl::LoadColorTablePreview(const std::string& key, }); } +void SettingsDialogImpl::ShowColorDialog(QLineEdit* lineEdit, QFrame* frame) +{ + QColorDialog* dialog = new QColorDialog(self_); + + dialog->setAttribute(Qt::WA_DeleteOnClose); + dialog->setOption(QColorDialog::ColorDialogOption::ShowAlphaChannel); + + QColor initialColor(lineEdit->text()); + if (initialColor.isValid()) + { + dialog->setCurrentColor(initialColor); + } + + QObject::connect( + dialog, + &QColorDialog::colorSelected, + self_, + [this, lineEdit, frame](const QColor& color) + { + QString colorName = color.name(QColor::NameFormat::HexArgb); + + logger_->info("Selected color: {}", colorName.toStdString()); + lineEdit->setText(colorName); + + // setText does not emit the textEdited signal + Q_EMIT lineEdit->textEdited(colorName); + }); + + dialog->open(); +} + +void SettingsDialogImpl::SetBackgroundColor(const std::string& value, + QFrame* frame) +{ + frame->setStyleSheet( + QString::fromStdString(fmt::format("background-color: {}", value))); +} + void SettingsDialogImpl::UpdateRadarDialogLocation(const std::string& id) { std::shared_ptr radarSite = config::RadarSite::Get(id); @@ -1462,6 +1444,8 @@ void SettingsDialogImpl::UpdateAlertRadarDialogLocation(const std::string& id) } } + + QFont SettingsDialogImpl::GetSelectedFont() { std::string fontFamily = fontFamilies_.at(selectedFontCategory_) @@ -1496,12 +1480,6 @@ void SettingsDialogImpl::UpdateFontDisplayData() self_->ui->fontStyleLabel->setText(font.styleName()); self_->ui->fontSizeLabel->setText(QString::number(font.pointSizeF())); -#if defined(__APPLE__) - const units::font_size::points fontSize {font.pointSizeF()}; - const units::font_size::pixels fontPixels {fontSize}; - font.setPixelSize(static_cast(fontPixels.value())); -#endif - self_->ui->fontPreviewLabel->setFont(font); if (selectedFontCategory_ != types::FontCategory::Unknown) diff --git a/scwx-qt/source/scwx/qt/ui/settings_dialog.hpp b/scwx-qt/source/scwx/qt/ui/settings_dialog.hpp index 866e1ea8..82f00905 100644 --- a/scwx-qt/source/scwx/qt/ui/settings_dialog.hpp +++ b/scwx-qt/source/scwx/qt/ui/settings_dialog.hpp @@ -1,7 +1,6 @@ #pragma once #include -#include namespace Ui { @@ -25,8 +24,7 @@ private: Q_DISABLE_COPY(SettingsDialog) public: - explicit SettingsDialog(QMapLibre::Settings& mapSettings, - QWidget* parent = nullptr); + explicit SettingsDialog(QWidget* parent = nullptr); ~SettingsDialog(); private: diff --git a/scwx-qt/source/scwx/qt/ui/settings_dialog.ui b/scwx-qt/source/scwx/qt/ui/settings_dialog.ui index aa12d3b8..88dacbbc 100644 --- a/scwx-qt/source/scwx/qt/ui/settings_dialog.ui +++ b/scwx-qt/source/scwx/qt/ui/settings_dialog.ui @@ -16,6 +16,12 @@ + + QFrame::Shape::StyledPanel + + + QFrame::Shadow::Raised + 0 @@ -116,7 +122,7 @@ - 0 + 3 @@ -130,8 +136,8 @@ 0 0 - 513 - 845 + 274 + 691 @@ -153,69 +159,6 @@ 0 - - - - Qt::FocusPolicy::StrongFocus - - - - - - - Qt::FocusPolicy::StrongFocus - - - - - - - Qt::FocusPolicy::StrongFocus - - - - - - - Radar Site Threshold - - - - - - - Custom Map URL - - - - - - - Warnings Provider - - - - - - - ... - - - - :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg - - - - - - - GPS Source - - - - - - @@ -223,8 +166,8 @@ - - + + ... @@ -234,120 +177,13 @@ - - + + + + + - ... - - - - :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg - - - - - - - ... - - - - :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg - - - - - - - Default Radar Site - - - - - - - Custom Map Layer - - - - - - - Qt::FocusPolicy::StrongFocus - - - - - - - Mapbox API Key - - - - - - - ... - - - - :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg - - - - - - - Clock Format - - - - - - - Qt::FocusPolicy::StrongFocus - - - - - - - Qt::FocusPolicy::StrongFocus - - - - - - - ... - - - - :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg - - - - - - - ... - - - - :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg - - - - - - - Qt::FocusPolicy::StrongFocus - - - 1 - - - 999999999 + Default Time Zone @@ -362,19 +198,8 @@ - - - - Theme File - - - - - - - Grid Width - - + + @@ -387,8 +212,117 @@ - - + + + + Map Provider + + + + + + + + + + ... + + + + :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg + + + + + + + + + + + + + ... + + + + + + + QLineEdit::EchoMode::Password + + + + + + + GPS Plugin + + + + + + + GPS Baud Rate + + + + + + + + + + ... + + + + + + + ... + + + + :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg + + + + + + + Grid Width + + + + + + + + + + + + + + + + GPS Source + + + + + + + + + + Default Radar Site + + + + + ... @@ -405,11 +339,8 @@ - - - - - + + ... @@ -419,65 +350,6 @@ - - - - ... - - - - - - - Default Time Zone - - - - - - - Qt::FocusPolicy::StrongFocus - - - - - - - - - - Qt::FocusPolicy::StrongFocus - - - - - - - ... - - - - - - - Map Provider - - - - - - - QLineEdit::EchoMode::Password - - - - - - - Qt::FocusPolicy::StrongFocus - - - @@ -485,52 +357,40 @@ - - - - - - - - + + - + ... + + + + :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg - - - - - 0 - 0 - - - - Qt::FocusPolicy::StrongFocus - - - Set to 0 to disable - - - - - - 0 - - - -10000.000000000000000 - - - 10000.000000000000000 - - - QAbstractSpinBox::StepType::DefaultStepType + + + + Mapbox API Key - - + + + + Clock Format + + + + + + + QLineEdit::EchoMode::Password + + + + + ... @@ -551,39 +411,23 @@ - - - - QLineEdit::EchoMode::Password + + + + + + + Warnings Provider - - - - ... + + + + 1 - - - :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg - - - - - - - GPS Baud Rate - - - - - - - ... - - - - :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg + + 999999999 @@ -594,52 +438,6 @@ - - - - - - - ... - - - - - - - ... - - - - :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg - - - - - - - ... - - - - :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg - - - - - - - GPS Plugin - - - - - - - ... - - - @@ -651,37 +449,72 @@ - - + + - Multi-Pane Cursor Size + ... + + + + :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg - - - - Qt::FocusPolicy::StrongFocus + + + + ... - - 1 - - - 1.000000000000000 - - - 5.000000000000000 - - - 0.100000000000000 - - - QAbstractSpinBox::StepType::DefaultStepType + + + :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg - - + + + + ... + + + + :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg + + + + + + + + + + + + + Custom Map URL + + + + + + + Custom Map Layer + + + + + + + ... + + + + :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg + + + + + ... @@ -701,26 +534,6 @@ - - - - Center Map on Radar Selection - - - - - - - false - - - - - - Multi-Pane Cursor Marker Always On - - - @@ -742,13 +555,6 @@ - - - - Show Range Folding when Smoothing Radar Data - - - @@ -804,8 +610,8 @@ 0 0 - 505 - 384 + 98 + 28 @@ -828,10 +634,49 @@ - + Alerts + + + + + QFrame::Shape::StyledPanel + + + QFrame::Shadow::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + Qt::Orientation::Vertical + + + + 20 + 239 + + + + + @@ -914,10 +759,7 @@ - - - Qt::FocusPolicy::StrongFocus - + 4 @@ -933,13 +775,7 @@ - - - Qt::FocusPolicy::StrongFocus - - - Set to 0 to disable - + 2 @@ -988,10 +824,7 @@ - - - Qt::FocusPolicy::StrongFocus - + 4 @@ -1088,23 +921,16 @@ - - - Qt::FocusPolicy::StrongFocus - - + - + 0 0 - - Qt::FocusPolicy::StrongFocus - @@ -1191,6 +1017,12 @@ + + QFrame::Shape::StyledPanel + + + QFrame::Shadow::Raised + 0 @@ -1219,6 +1051,12 @@ + + QFrame::Shape::StyledPanel + + + QFrame::Shadow::Raised + 0 @@ -1358,6 +1196,12 @@ + + QFrame::Shape::StyledPanel + + + QFrame::Shadow::Raised + 0 @@ -1397,10 +1241,7 @@ - - - Qt::FocusPolicy::StrongFocus - + 999 @@ -1425,11 +1266,7 @@ - - - Qt::FocusPolicy::StrongFocus - - + @@ -1484,28 +1321,6 @@ - - - scwx::qt::ui::QApiKeyEdit - QLineEdit -
scwx/qt/ui/api_key_edit_widget.hpp
-
- - QFocusedDoubleSpinBox - QDoubleSpinBox -
scwx/qt/ui/widgets/focused_double_spin_box.hpp
-
- - QFocusedSpinBox - QSpinBox -
scwx/qt/ui/widgets/focused_spin_box.hpp
-
- - QFocusedComboBox - QComboBox -
scwx/qt/ui/widgets/focused_combo_box.hpp
-
-
diff --git a/scwx-qt/source/scwx/qt/ui/setup/audio_codec_page.cpp b/scwx-qt/source/scwx/qt/ui/setup/audio_codec_page.cpp index 364c9959..dd86e1f6 100644 --- a/scwx-qt/source/scwx/qt/ui/setup/audio_codec_page.cpp +++ b/scwx-qt/source/scwx/qt/ui/setup/audio_codec_page.cpp @@ -124,9 +124,6 @@ void AudioCodecPage::Impl::SetInstructionsLabelText() self_, [](const QString& link) { QDesktopServices::openUrl(QUrl {link}); }); -#elif defined(__APPLE__) - instructionsLabel_->setText(tr( - "Please see the instructions for your Mac for installing media codecs.")); #else instructionsLabel_->setText( tr("Please see the instructions for your Linux distribution for " diff --git a/scwx-qt/source/scwx/qt/ui/setup/map_provider_page.cpp b/scwx-qt/source/scwx/qt/ui/setup/map_provider_page.cpp index b4d7038a..fc0c9ef1 100644 --- a/scwx-qt/source/scwx/qt/ui/setup/map_provider_page.cpp +++ b/scwx-qt/source/scwx/qt/ui/setup/map_provider_page.cpp @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -19,7 +18,13 @@ #include #include -namespace scwx::qt::ui::setup +namespace scwx +{ +namespace qt +{ +namespace ui +{ +namespace setup { static const std::unordered_map kUrl_ { @@ -28,8 +33,8 @@ static const std::unordered_map kUrl_ { struct MapProviderGroup { - QLabel* apiKeyLabel_ {}; - QApiKeyEdit* apiKeyEdit_ {}; + QLabel* apiKeyLabel_ {}; + QLineEdit* apiKeyEdit_ {}; }; class MapProviderPage::Impl @@ -40,9 +45,7 @@ public: void SelectMapProvider(const QString& text); void SelectMapProvider(map::MapProvider mapProvider); - void SetupMapProviderGroup(const map::MapProvider mapProvider, - MapProviderGroup& group, - int row); + void SetupMapProviderGroup(MapProviderGroup& group, int row); void SetupSettingsInterface(); static void SetGroupVisible(MapProviderGroup& group, bool visible); @@ -119,8 +122,8 @@ MapProviderPage::MapProviderPage(QWidget* parent) : p->buttonLayout_->addItem(p->buttonSpacer_); p->buttonFrame_->setLayout(p->buttonLayout_); - p->SetupMapProviderGroup(map::MapProvider::Mapbox, p->mapboxGroup_, 1); - p->SetupMapProviderGroup(map::MapProvider::MapTiler, p->maptilerGroup_, 2); + p->SetupMapProviderGroup(p->mapboxGroup_, 1); + p->SetupMapProviderGroup(p->maptilerGroup_, 2); // Overall layout p->layout_ = new QVBoxLayout(this); @@ -156,12 +159,11 @@ MapProviderPage::MapProviderPage(QWidget* parent) : MapProviderPage::~MapProviderPage() = default; -void MapProviderPage::Impl::SetupMapProviderGroup( - const map::MapProvider provider, MapProviderGroup& group, int row) +void MapProviderPage::Impl::SetupMapProviderGroup(MapProviderGroup& group, + int row) { group.apiKeyLabel_ = new QLabel(self_); - group.apiKeyEdit_ = new QApiKeyEdit(self_); - group.apiKeyEdit_->setMapProvider(provider); + group.apiKeyEdit_ = new QLineEdit(self_); group.apiKeyLabel_->setText(tr("API Key")); @@ -169,7 +171,7 @@ void MapProviderPage::Impl::SetupMapProviderGroup( mapProviderLayout_->addWidget(group.apiKeyEdit_, row, 1, 1, 1); QObject::connect(group.apiKeyEdit_, - &QApiKeyEdit::textChanged, + &QLineEdit::textChanged, self_, &QWizardPage::completeChanged); } @@ -207,11 +209,9 @@ void MapProviderPage::Impl::SetupSettingsInterface() mapProvider_.SetEditWidget(mapProviderComboBox_); mapboxApiKey_.SetSettingsVariable(generalSettings.mapbox_api_key()); - mapboxApiKey_.EnableTrimming(); mapboxApiKey_.SetEditWidget(mapboxGroup_.apiKeyEdit_); mapTilerApiKey_.SetSettingsVariable(generalSettings.maptiler_api_key()); - mapTilerApiKey_.EnableTrimming(); mapTilerApiKey_.SetEditWidget(maptilerGroup_.apiKeyEdit_); } @@ -290,4 +290,7 @@ bool MapProviderPage::IsRequired() return (mapboxApiKey.size() <= 1 && maptilerApiKey.size() <= 1); } -} // namespace scwx::qt::ui::setup +} // namespace setup +} // namespace ui +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/ui/setup/setup_wizard.cpp b/scwx-qt/source/scwx/qt/ui/setup/setup_wizard.cpp index 9b265bd4..92be250f 100644 --- a/scwx-qt/source/scwx/qt/ui/setup/setup_wizard.cpp +++ b/scwx-qt/source/scwx/qt/ui/setup/setup_wizard.cpp @@ -22,9 +22,6 @@ class SetupWizard::Impl public: explicit Impl() = default; ~Impl() = default; - - bool mapProviderPageIsRequired_ {MapProviderPage::IsRequired()}; - bool audioCodecPageIsRequired_ {AudioCodecPage::IsRequired()}; }; SetupWizard::SetupWizard(QWidget* parent) : @@ -69,14 +66,14 @@ int SetupWizard::nextId() const { case static_cast(Page::MapProvider): case static_cast(Page::MapLayout): - if (p->mapProviderPageIsRequired_) + if (MapProviderPage::IsRequired()) { return nextId; } break; case static_cast(Page::AudioCodec): - if (p->audioCodecPageIsRequired_) + if (AudioCodecPage::IsRequired()) { return nextId; } diff --git a/scwx-qt/source/scwx/qt/ui/update_dialog.cpp b/scwx-qt/source/scwx/qt/ui/update_dialog.cpp index edb0396e..0ca61a18 100644 --- a/scwx-qt/source/scwx/qt/ui/update_dialog.cpp +++ b/scwx-qt/source/scwx/qt/ui/update_dialog.cpp @@ -42,19 +42,13 @@ public: UpdateDialog::UpdateDialog(QWidget* parent) : QDialog(parent), p {std::make_unique(this)}, ui(new Ui::UpdateDialog) { -#if !defined(__APPLE__) - static constexpr int titleFontSize = 12; -#else - static constexpr int titleFontSize = 16; -#endif - ui->setupUi(this); - const int titleFontId = + int titleFontId = manager::FontManager::Instance().GetFontId(types::Font::din1451alt_g); - const QString titleFontFamily = + QString titleFontFamily = QFontDatabase::applicationFontFamilies(titleFontId).at(0); - const QFont titleFont(titleFontFamily, titleFontSize); + QFont titleFont(titleFontFamily, 12); ui->bannerLabel->setFont(titleFont); ui->releaseNotesText->setOpenExternalLinks(true); @@ -91,14 +85,7 @@ void UpdateDialog::UpdateReleaseInfo(const std::string& latestVersion, void UpdateDialog::Impl::HandleAsset(const types::gh::ReleaseAsset& asset) { #if defined(_WIN32) - -# if defined(_M_AMD64) - static constexpr std::string assetSuffix = "-x64.msi"; -# else - static constexpr std::string assetSuffix = "-arm64.msi"; -# endif - - if (asset.name_.ends_with(assetSuffix)) + if (asset.name_.ends_with(".msi")) { self_->ui->installUpdateButton->setVisible(true); installUrl_ = asset.browserDownloadUrl_; diff --git a/scwx-qt/source/scwx/qt/ui/update_dialog.ui b/scwx-qt/source/scwx/qt/ui/update_dialog.ui index 84540fe9..5aa8e054 100644 --- a/scwx-qt/source/scwx/qt/ui/update_dialog.ui +++ b/scwx-qt/source/scwx/qt/ui/update_dialog.ui @@ -16,6 +16,12 @@ + + QFrame::StyledPanel + + + QFrame::Raised + 0 @@ -50,6 +56,12 @@ + + QFrame::StyledPanel + + + QFrame::Raised + 0 @@ -101,6 +113,12 @@ + + QFrame::StyledPanel + + + QFrame::Raised + 0 @@ -131,7 +149,7 @@ - Qt::Orientation::Horizontal + Qt::Horizontal @@ -144,10 +162,10 @@ - Qt::Orientation::Horizontal + Qt::Horizontal - QDialogButtonBox::StandardButton::Ok + QDialogButtonBox::Ok diff --git a/scwx-qt/source/scwx/qt/ui/wfo_dialog.ui b/scwx-qt/source/scwx/qt/ui/wfo_dialog.ui index cfb59664..26623489 100644 --- a/scwx-qt/source/scwx/qt/ui/wfo_dialog.ui +++ b/scwx-qt/source/scwx/qt/ui/wfo_dialog.ui @@ -29,6 +29,12 @@ + + QFrame::Shape::StyledPanel + + + QFrame::Shadow::Raised + 0 diff --git a/scwx-qt/source/scwx/qt/ui/widgets/focused_combo_box.hpp b/scwx-qt/source/scwx/qt/ui/widgets/focused_combo_box.hpp deleted file mode 100644 index 619bcd89..00000000 --- a/scwx-qt/source/scwx/qt/ui/widgets/focused_combo_box.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include -#include - -class QFocusedComboBox : public QComboBox -{ - Q_OBJECT - -public: - using QComboBox::QComboBox; - -protected: - void wheelEvent(QWheelEvent* event) override - { - if (hasFocus()) - { - QComboBox::wheelEvent(event); - } - else - { - event->ignore(); - } - } -}; diff --git a/scwx-qt/source/scwx/qt/ui/widgets/focused_double_spin_box.hpp b/scwx-qt/source/scwx/qt/ui/widgets/focused_double_spin_box.hpp deleted file mode 100644 index f4fe4f9f..00000000 --- a/scwx-qt/source/scwx/qt/ui/widgets/focused_double_spin_box.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include -#include - -class QFocusedDoubleSpinBox : public QDoubleSpinBox -{ - Q_OBJECT - -public: - using QDoubleSpinBox::QDoubleSpinBox; - -protected: - void wheelEvent(QWheelEvent* event) override - { - if (hasFocus()) - { - QDoubleSpinBox::wheelEvent(event); - } - else - { - event->ignore(); - } - } -}; diff --git a/scwx-qt/source/scwx/qt/ui/widgets/focused_spin_box.hpp b/scwx-qt/source/scwx/qt/ui/widgets/focused_spin_box.hpp deleted file mode 100644 index 5d120386..00000000 --- a/scwx-qt/source/scwx/qt/ui/widgets/focused_spin_box.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include -#include - -class QFocusedSpinBox : public QSpinBox -{ - Q_OBJECT - -public: - using QSpinBox::QSpinBox; - -protected: - void wheelEvent(QWheelEvent* event) override - { - if (hasFocus()) - { - QSpinBox::wheelEvent(event); - } - else - { - event->ignore(); - } - } -}; diff --git a/scwx-qt/source/scwx/qt/util/color.cpp b/scwx-qt/source/scwx/qt/util/color.cpp index bdd3f6c2..6e193dc9 100644 --- a/scwx-qt/source/scwx/qt/util/color.cpp +++ b/scwx-qt/source/scwx/qt/util/color.cpp @@ -1,7 +1,6 @@ #include #include -#include #include namespace scwx @@ -13,6 +12,8 @@ namespace util namespace color { +static const std::string logPrefix_ = "scwx::qt::util::color"; + std::string ToArgbString(const boost::gil::rgba8_pixel_t& color) { return fmt::format( @@ -37,12 +38,6 @@ boost::gil::rgba32f_pixel_t ToRgba32fPixelT(const std::string& argbString) rgba8Pixel[3] / 255.0f}; } -bool ValidateArgbString(const std::string& argbString) -{ - static constexpr LazyRE2 re = {"#[0-9A-Fa-f]{8}"}; - return RE2::FullMatch(argbString, *re); -} - } // namespace color } // namespace util } // namespace qt diff --git a/scwx-qt/source/scwx/qt/util/color.hpp b/scwx-qt/source/scwx/qt/util/color.hpp index 6d90fe56..73ca07f1 100644 --- a/scwx-qt/source/scwx/qt/util/color.hpp +++ b/scwx-qt/source/scwx/qt/util/color.hpp @@ -39,15 +39,6 @@ boost::gil::rgba8_pixel_t ToRgba8PixelT(const std::string& argbString); */ boost::gil::rgba32f_pixel_t ToRgba32fPixelT(const std::string& argbString); -/** - * Validates an ARGB string used by Qt libraries. - * - * @param argbString - * - * @return Validity of ARGB string - */ -bool ValidateArgbString(const std::string& argbString); - } // namespace color } // namespace util } // namespace qt diff --git a/scwx-qt/source/scwx/qt/util/file.cpp b/scwx-qt/source/scwx/qt/util/file.cpp index 7e126345..b129e6ce 100644 --- a/scwx-qt/source/scwx/qt/util/file.cpp +++ b/scwx-qt/source/scwx/qt/util/file.cpp @@ -12,6 +12,8 @@ namespace qt namespace util { +static const std::string logPrefix_ = "scwx::qt::util::file"; + std::unique_ptr OpenFile(const std::string& filename, std::ios_base::openmode mode) { diff --git a/scwx-qt/source/scwx/qt/util/geographic_lib.cpp b/scwx-qt/source/scwx/qt/util/geographic_lib.cpp index 1e5fa5e7..bfaf408f 100644 --- a/scwx-qt/source/scwx/qt/util/geographic_lib.cpp +++ b/scwx-qt/source/scwx/qt/util/geographic_lib.cpp @@ -2,7 +2,6 @@ #include #include -#include #include #include @@ -290,25 +289,6 @@ bool AreaInRangeOfPoint(const std::vector& area, return GetDistanceAreaPoint(area, point) <= distance; } -units::length::meters -GetRadarBeamAltititude(units::length::meters range, - units::angle::degrees elevation, - units::length::meters height) -{ - static const units::length::meters earthRadius {6367444 * 4 / 3}; - - height += earthRadius; - - const double elevationRadians = - units::angle::radians(elevation).value(); - const auto altitudeSquared = - (range * range + height * height + - 2 * range * height * std::sin(elevationRadians)); - - return units::length::meters(std::sqrt(altitudeSquared.value())) - - earthRadius; -} - } // namespace GeographicLib } // namespace util } // namespace qt diff --git a/scwx-qt/source/scwx/qt/util/geographic_lib.hpp b/scwx-qt/source/scwx/qt/util/geographic_lib.hpp index d34f2aeb..5038d9a9 100644 --- a/scwx-qt/source/scwx/qt/util/geographic_lib.hpp +++ b/scwx-qt/source/scwx/qt/util/geographic_lib.hpp @@ -121,20 +121,6 @@ bool AreaInRangeOfPoint(const std::vector& area, const common::Coordinate& point, const units::length::meters distance); -/** - * Get the altitude of the radar beam at a given distance, elevation and height - * - * @param [in] range The range to the radar site - * @param [in] elevation The elevation of the radar site - * @param [in] height The height of the radar site - * - * @return The altitude of the radar at that range - */ -units::length::meters -GetRadarBeamAltititude(units::length::meters range, - units::angle::degrees elevation, - units::length::meters height); - } // namespace GeographicLib } // namespace util } // namespace qt diff --git a/scwx-qt/source/scwx/qt/util/imgui.cpp b/scwx-qt/source/scwx/qt/util/imgui.cpp index 1bb8af3c..64076dab 100644 --- a/scwx-qt/source/scwx/qt/util/imgui.cpp +++ b/scwx-qt/source/scwx/qt/util/imgui.cpp @@ -34,7 +34,7 @@ void ImGui::DrawTooltip(const std::string& hoverText) if (::ImGui::BeginTooltip()) { - ::ImGui::PushFont(tooltipFont.first->font(), tooltipFont.second.value()); + ::ImGui::PushFont(tooltipFont->font()); ::ImGui::TextUnformatted(hoverText.c_str()); ::ImGui::PopFont(); ::ImGui::EndTooltip(); diff --git a/scwx-qt/source/scwx/qt/util/json.cpp b/scwx-qt/source/scwx/qt/util/json.cpp index d508a224..7bf0d23a 100644 --- a/scwx-qt/source/scwx/qt/util/json.cpp +++ b/scwx-qt/source/scwx/qt/util/json.cpp @@ -1,19 +1,41 @@ #include -#include #include +#include + +#include +#include #include #include -namespace scwx::qt::util::json +namespace scwx +{ +namespace qt +{ +namespace util +{ +namespace json { static const std::string logPrefix_ = "scwx::qt::util::json"; static const auto logger_ = scwx::util::Logger::Create(logPrefix_); -static boost::json::value ReadJsonFile(QFile& file); +/* Adapted from: + * https://www.boost.org/doc/libs/1_77_0/libs/json/doc/html/json/examples.html#json.examples.pretty + * + * Copyright (c) 2019, 2020 Vinnie Falco + * Copyright (c) 2020 Krystian Stasiowski + * Distributed under the Boost Software License, Version 1.0. (See + * http://www.boost.org/LICENSE_1_0.txt) + */ +static void PrettyPrintJson(std::ostream& os, + boost::json::value const& jv, + std::string* indent = nullptr); -boost::json::value ReadJsonQFile(const std::string& path) +static boost::json::value ReadJsonFile(QFile& file); +static boost::json::value ReadJsonStream(std::istream& is); + +boost::json::value ReadJsonFile(const std::string& path) { boost::json::value json; @@ -24,7 +46,8 @@ boost::json::value ReadJsonQFile(const std::string& path) } else { - json = ::scwx::util::json::ReadJsonFile(path); + std::ifstream ifs {path}; + json = ReadJsonStream(ifs); } return json; @@ -42,7 +65,7 @@ static boost::json::value ReadJsonFile(QFile& file) std::string jsonSource = jsonStream.readAll().toStdString(); std::istringstream is {jsonSource}; - json = ::scwx::util::json::ReadJsonStream(is); + json = ReadJsonStream(is); file.close(); } @@ -55,4 +78,147 @@ static boost::json::value ReadJsonFile(QFile& file) return json; } -} // namespace scwx::qt::util::json +static boost::json::value ReadJsonStream(std::istream& is) +{ + std::string line; + + boost::json::stream_parser p; + boost::system::error_code ec; + + while (std::getline(is, line)) + { + p.write(line, ec); + if (ec) + { + logger_->warn("{}", ec.message()); + return nullptr; + } + } + + p.finish(ec); + if (ec) + { + logger_->warn("{}", ec.message()); + return nullptr; + } + + return p.release(); +} + +void WriteJsonFile(const std::string& path, + const boost::json::value& json, + bool prettyPrint) +{ + std::ofstream ofs {path}; + + if (!ofs.is_open()) + { + logger_->warn("Cannot write JSON file: \"{}\"", path); + } + else + { + if (prettyPrint) + { + PrettyPrintJson(ofs, json); + } + else + { + ofs << json; + } + ofs.close(); + } +} + +static void PrettyPrintJson(std::ostream& os, + boost::json::value const& jv, + std::string* indent) +{ + std::string indent_; + if (!indent) + indent = &indent_; + switch (jv.kind()) + { + case boost::json::kind::object: + { + os << "{\n"; + indent->append(4, ' '); + auto const& obj = jv.get_object(); + if (!obj.empty()) + { + auto it = obj.begin(); + for (;;) + { + os << *indent << boost::json::serialize(it->key()) << " : "; + PrettyPrintJson(os, it->value(), indent); + if (++it == obj.end()) + break; + os << ",\n"; + } + } + os << "\n"; + indent->resize(indent->size() - 4); + os << *indent << "}"; + break; + } + + case boost::json::kind::array: + { + os << "[\n"; + indent->append(4, ' '); + auto const& arr = jv.get_array(); + if (!arr.empty()) + { + auto it = arr.begin(); + for (;;) + { + os << *indent; + PrettyPrintJson(os, *it, indent); + if (++it == arr.end()) + break; + os << ",\n"; + } + } + os << "\n"; + indent->resize(indent->size() - 4); + os << *indent << "]"; + break; + } + + case boost::json::kind::string: + { + os << boost::json::serialize(jv.get_string()); + break; + } + + case boost::json::kind::uint64: + os << jv.get_uint64(); + break; + + case boost::json::kind::int64: + os << jv.get_int64(); + break; + + case boost::json::kind::double_: + os << jv.get_double(); + break; + + case boost::json::kind::bool_: + if (jv.get_bool()) + os << "true"; + else + os << "false"; + break; + + case boost::json::kind::null: + os << "null"; + break; + } + + if (indent->empty()) + os << "\n"; +} + +} // namespace json +} // namespace util +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/util/json.hpp b/scwx-qt/source/scwx/qt/util/json.hpp index 9dd09810..bbf497f4 100644 --- a/scwx-qt/source/scwx/qt/util/json.hpp +++ b/scwx-qt/source/scwx/qt/util/json.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include namespace scwx @@ -11,7 +13,10 @@ namespace util namespace json { -boost::json::value ReadJsonQFile(const std::string& path); +boost::json::value ReadJsonFile(const std::string& path); +void WriteJsonFile(const std::string& path, + const boost::json::value& json, + bool prettyPrint = true); } // namespace json } // namespace util diff --git a/scwx-qt/source/scwx/qt/util/maplibre.cpp b/scwx-qt/source/scwx/qt/util/maplibre.cpp index 6a4c7d55..3414af41 100644 --- a/scwx-qt/source/scwx/qt/util/maplibre.cpp +++ b/scwx-qt/source/scwx/qt/util/maplibre.cpp @@ -1,9 +1,7 @@ #include #include -#include #include -#include namespace scwx { @@ -48,10 +46,7 @@ glm::vec2 GetMapScale(const QMapLibre::CustomLayerRenderParameters& params) bool IsPointInPolygon(const std::vector& vertices, const glm::vec2& point) { - // All members of these unions are floats, so no type safety violation - // NOLINTBEGIN(cppcoreguidelines-pro-type-union-access) bool inPolygon = true; - bool allSame = true; // For each vertex, assume counterclockwise order for (std::size_t i = 0; i < vertices.size(); ++i) @@ -60,8 +55,6 @@ bool IsPointInPolygon(const std::vector& vertices, const auto& p2 = (i == vertices.size() - 1) ? vertices[0] : vertices[i + 1]; - allSame = allSame && p1.x == p2.x && p1.y == p2.y; - // Test which side of edge point lies on const float a = -(p2.y - p1.y); const float b = p2.x - p1.x; @@ -77,14 +70,7 @@ bool IsPointInPolygon(const std::vector& vertices, } } - if (allSame) - { - inPolygon = vertices.size() > 0 && vertices[0].x == point.x && - vertices[0].y == point.y; - } - return inPolygon; - // NOLINTEND(cppcoreguidelines-pro-type-union-access) } glm::vec2 LatLongToScreenCoordinate(const QMapLibre::Coordinate& coordinate) @@ -122,44 +108,6 @@ void SetMapStyleUrl(const std::shared_ptr& mapContext, } } -std::string FindMapSymbologyLayer(const QStringList& styleLayers, - const std::vector& drawBelow) -{ - std::string before = "ferry"; - - for (const QString& qlayer : styleLayers) - { - const std::string layer = qlayer.toStdString(); - - // Draw below layers defined in map style - auto it = - std::ranges::find_if(drawBelow, - [&layer](const std::string& styleLayer) -> bool - { - // Perform case-insensitive matching - const RE2 re {"(?i)" + styleLayer}; - if (re.ok()) - { - return RE2::FullMatch(layer, re); - } - else - { - // Fall back to basic comparison if RE - // doesn't compile - return layer == styleLayer; - } - }); - - if (it != drawBelow.cend()) - { - before = layer; - break; - } - } - - return before; -} - } // namespace maplibre } // namespace util } // namespace qt diff --git a/scwx-qt/source/scwx/qt/util/maplibre.hpp b/scwx-qt/source/scwx/qt/util/maplibre.hpp index c03be113..7c2eb58b 100644 --- a/scwx-qt/source/scwx/qt/util/maplibre.hpp +++ b/scwx-qt/source/scwx/qt/util/maplibre.hpp @@ -37,18 +37,6 @@ glm::vec2 LatLongToScreenCoordinate(const QMapLibre::Coordinate& coordinate); void SetMapStyleUrl(const std::shared_ptr& mapContext, const std::string& url); -/** - * @brief Find the first layer which should be drawn above the radar products - * - * @param [in] styleLayers The layers of the style - * @param [in] drawBelow A list of RE2 compatible regex's describing the layers - * to draw below - * - * @return The first layer to be drawn above the radar products - */ -std::string FindMapSymbologyLayer(const QStringList& styleLayers, - const std::vector& drawBelow); - } // namespace maplibre } // namespace util } // namespace qt diff --git a/scwx-qt/source/scwx/qt/util/network.cpp b/scwx-qt/source/scwx/qt/util/network.cpp index a0a782f8..2e8d442f 100644 --- a/scwx-qt/source/scwx/qt/util/network.cpp +++ b/scwx-qt/source/scwx/qt/util/network.cpp @@ -17,15 +17,14 @@ std::string NormalizeUrl(const std::string& urlString) std::string normalizedUrl; // Normalize URL string - QString trimmedUrlString = QString::fromStdString(urlString).trimmed(); - QUrl url = QUrl::fromUserInput(trimmedUrlString); + QUrl url = QUrl::fromUserInput(QString::fromStdString(urlString)); if (url.isLocalFile()) { normalizedUrl = QDir::toNativeSeparators(url.toLocalFile()).toStdString(); } else { - normalizedUrl = trimmedUrlString.toStdString(); + normalizedUrl = urlString; } return normalizedUrl; diff --git a/scwx-qt/source/scwx/qt/util/q_color_modulate.cpp b/scwx-qt/source/scwx/qt/util/q_color_modulate.cpp deleted file mode 100644 index c205ce88..00000000 --- a/scwx-qt/source/scwx/qt/util/q_color_modulate.cpp +++ /dev/null @@ -1,64 +0,0 @@ -#include - -#include -#include -#include -#include -#include - -namespace scwx::qt::util -{ - -void modulateColors_(QImage& image, const QColor& color) -{ - for (int y = 0; y < image.height(); ++y) - { - QRgb* line = reinterpret_cast(image.scanLine(y)); - for (int x = 0; x < image.width(); ++x) - { - // This is pulled from Qt Documentation - // https://doc.qt.io/qt-6/qimage.html#scanLine - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - QRgb& rgb = line[x]; - /* clang-format off - * NOLINTBEGIN(cppcoreguidelines-narrowing-conversions, bugprone-narrowing-conversions) - * qRed/qGreen/qBlue/qAlpha return values 0-255, handlable by float - * redF/greenF/blueF/alphaF are all 0-1, so output is 0-255 - * Rounding is fine for this. - * clang-format on - */ - const int red = qRed(rgb) * color.redF(); - const int green = qGreen(rgb) * color.greenF(); - const int blue = qBlue(rgb) * color.blueF(); - const int alpha = qAlpha(rgb) * color.alphaF(); - /* clang-format off - * NOLINTEND(cppcoreguidelines-narrowing-conversions, bugprone-narrowing-conversions) - * clang-format on - */ - - rgb = qRgba(red, green, blue, alpha); - } - } -} - -QImage modulateColors(const QImage& image, const QColor& color) -{ - QImage copy = image.copy(); - modulateColors_(copy, color); - return copy; -} - -QPixmap modulateColors(const QPixmap& pixmap, const QColor& color) -{ - QImage image = pixmap.toImage(); - modulateColors_(image, color); - return QPixmap::fromImage(image); -} - -QIcon modulateColors(const QIcon& icon, const QSize& size, const QColor& color) -{ - const QPixmap pixmap = modulateColors(icon.pixmap(size), color); - return QIcon(pixmap); -} - -} // namespace scwx::qt::util diff --git a/scwx-qt/source/scwx/qt/util/q_color_modulate.hpp b/scwx-qt/source/scwx/qt/util/q_color_modulate.hpp deleted file mode 100644 index 35326293..00000000 --- a/scwx-qt/source/scwx/qt/util/q_color_modulate.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -namespace scwx::qt::util -{ - -QImage modulateColors(const QImage& image, const QColor& color); -QPixmap modulateColors(const QPixmap& pixmap, const QColor& color); -QIcon modulateColors(const QIcon& icon, const QSize& size, const QColor& color); - -} // namespace scwx::qt::util diff --git a/scwx-qt/source/scwx/qt/util/q_file_buffer.cpp b/scwx-qt/source/scwx/qt/util/q_file_buffer.cpp index 1808d283..5d55361c 100644 --- a/scwx-qt/source/scwx/qt/util/q_file_buffer.cpp +++ b/scwx-qt/source/scwx/qt/util/q_file_buffer.cpp @@ -224,9 +224,6 @@ QFileBuffer::pos_type QFileBuffer::seekoff(off_type off, break; } - default: - logger_->error("Got invalid seekdir value"); - break; } if (newPos != static_cast(-1)) diff --git a/scwx-qt/source/scwx/qt/util/queue_counter.cpp b/scwx-qt/source/scwx/qt/util/queue_counter.cpp deleted file mode 100644 index 39b9fb9d..00000000 --- a/scwx-qt/source/scwx/qt/util/queue_counter.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include - -#include - -namespace scwx::qt::util -{ - -class QueueCounter::Impl -{ -public: - explicit Impl(size_t maxCount) : maxCount_ {maxCount} {} - - const size_t maxCount_; - boost::atomic count_ {0}; -}; - -QueueCounter::QueueCounter(size_t maxCount) : - p {std::make_unique(maxCount)} -{ -} - -QueueCounter::~QueueCounter() = default; - -bool QueueCounter::add() -{ - const size_t count = p->count_.fetch_add(1); - // Must be >= (not ==) to avoid race conditions - if (count >= p->maxCount_) - { - p->count_.fetch_sub(1); - return false; - } - else - { - return true; - } -} - -void QueueCounter::remove() -{ - p->count_.fetch_sub(1); -} - -bool QueueCounter::is_lock_free() -{ - return p->count_.is_lock_free(); -} - -} // namespace scwx::qt::util diff --git a/scwx-qt/source/scwx/qt/util/queue_counter.hpp b/scwx-qt/source/scwx/qt/util/queue_counter.hpp deleted file mode 100644 index 471bd645..00000000 --- a/scwx-qt/source/scwx/qt/util/queue_counter.hpp +++ /dev/null @@ -1,64 +0,0 @@ -#pragma once - -#include -#include - -namespace scwx::qt::util -{ - -class QueueCounter -{ -public: - /** - * Counts the number of items in a queue, and prevents it from exceeding a - * count in a thread safe manor. This is lock free, assuming - * std::atomic supports lock free fetch_add and fetch_sub. - */ - - /** - * Construct a QueueCounter with a given maximum count - * - * @param maxCount The maximum number of items in the queue - */ - explicit QueueCounter(size_t maxCount); - - ~QueueCounter(); - QueueCounter(const QueueCounter&) = delete; - QueueCounter(QueueCounter&&) = delete; - QueueCounter& operator=(const QueueCounter&) = delete; - QueueCounter& operator=(QueueCounter&&) = delete; - - /** - * Called before adding an item. If it returns true, it is ok to add. If it - * returns false, it should not be added - * - * @return true if it is ok to add, false if the queue is full - */ - bool add(); - - /** - * Called when item is removed from the queue. Should only be called after a - * corresponding and successful call to add. - */ - void remove(); - - /** - * Tells if this instance is lock free - * - * @return true if it is lock free, false otherwise - */ - bool is_lock_free(); - - /** - * Tells if this class is always lock free. True if it is lock free, false - * otherwise - */ - static constexpr bool is_always_lock_free = - boost::atomic::is_always_lock_free; - -private: - class Impl; - std::unique_ptr p; -}; - -} // namespace scwx::qt::util diff --git a/scwx-qt/source/scwx/qt/util/texture_atlas.cpp b/scwx-qt/source/scwx/qt/util/texture_atlas.cpp index 8ed20533..fe2b2a9a 100644 --- a/scwx-qt/source/scwx/qt/util/texture_atlas.cpp +++ b/scwx-qt/source/scwx/qt/util/texture_atlas.cpp @@ -50,12 +50,12 @@ public: ~Impl() {} static std::shared_ptr - LoadImage(const std::string& imagePath, double scale = 1); + LoadImage(const std::string& imagePath); static std::shared_ptr ReadPngFile(const QString& imagePath); static std::shared_ptr - ReadSvgFile(const QString& imagePath, double scale = 1); + ReadSvgFile(const QString& imagePath); std::vector> registeredTextures_ {}; @@ -92,12 +92,12 @@ void TextureAtlas::RegisterTexture(const std::string& name, p->registeredTextures_.emplace_back(std::move(image)); } -std::shared_ptr TextureAtlas::CacheTexture( - const std::string& name, const std::string& path, double scale) +std::shared_ptr +TextureAtlas::CacheTexture(const std::string& name, const std::string& path) { // Attempt to load the image std::shared_ptr image = - TextureAtlas::Impl::LoadImage(path, scale); + TextureAtlas::Impl::LoadImage(path); // If the image is valid if (image != nullptr && image->width() > 0 && image->height() > 0) @@ -314,7 +314,7 @@ void TextureAtlas::BuildAtlas(std::size_t width, std::size_t height) logger_->debug("Texture atlas built in {}", timer.format(6, "%ws")); } -void TextureAtlas::BufferAtlas(GLuint texture) +void TextureAtlas::BufferAtlas(gl::OpenGLFunctions& gl, GLuint texture) { std::shared_lock lock(p->atlasMutex_); @@ -343,23 +343,25 @@ void TextureAtlas::BufferAtlas(GLuint texture) lock.unlock(); - glBindTexture(GL_TEXTURE_2D_ARRAY, texture); + gl.glBindTexture(GL_TEXTURE_2D_ARRAY, texture); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gl.glTexParameteri( + GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + gl.glTexParameteri( + GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + gl.glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage3D(GL_TEXTURE_2D_ARRAY, - 0, - GL_RGBA, - static_cast(width), - static_cast(height), - static_cast(numLayers), - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - pixelData.data()); + gl.glTexImage3D(GL_TEXTURE_2D_ARRAY, + 0, + GL_RGBA, + static_cast(width), + static_cast(height), + static_cast(numLayers), + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + pixelData.data()); } } @@ -378,7 +380,7 @@ TextureAttributes TextureAtlas::GetTextureAttributes(const std::string& name) } std::shared_ptr -TextureAtlas::Impl::LoadImage(const std::string& imagePath, double scale) +TextureAtlas::Impl::LoadImage(const std::string& imagePath) { logger_->debug("Loading image: {}", imagePath); @@ -388,14 +390,15 @@ TextureAtlas::Impl::LoadImage(const std::string& imagePath, double scale) QUrl url = QUrl::fromUserInput(qImagePath); + if (url.isLocalFile()) { - const QString suffix = QFileInfo(qImagePath).suffix().toLower(); - const QString qLocalImagePath = url.toString(QUrl::PreferLocalFile); + QString suffix = QFileInfo(qImagePath).suffix().toLower(); + QString qLocalImagePath = url.toString(QUrl::PreferLocalFile); if (suffix == "svg") { - image = ReadSvgFile(qLocalImagePath, scale); + image = ReadSvgFile(qLocalImagePath); } else { @@ -445,18 +448,18 @@ TextureAtlas::Impl::LoadImage(const std::string& imagePath, double scale) // If no alpha channel, replace black with transparent if (numChannels == 3) { - std::for_each(std::execution::par, - view.begin(), - view.end(), - [](boost::gil::rgba8_pixel_t& pixel) - { - static const boost::gil::rgba8_pixel_t kBlack { - 0, 0, 0, 255}; - if (pixel == kBlack) - { - pixel[3] = 0; - } - }); + std::for_each( + std::execution::par_unseq, + view.begin(), + view.end(), + [](boost::gil::rgba8_pixel_t& pixel) + { + static const boost::gil::rgba8_pixel_t kBlack {0, 0, 0, 255}; + if (pixel == kBlack) + { + pixel[3] = 0; + } + }); } stbi_image_free(pixelData); @@ -506,10 +509,10 @@ TextureAtlas::Impl::ReadPngFile(const QString& imagePath) } std::shared_ptr -TextureAtlas::Impl::ReadSvgFile(const QString& imagePath, double scale) +TextureAtlas::Impl::ReadSvgFile(const QString& imagePath) { QSvgRenderer renderer {imagePath}; - QPixmap pixmap {renderer.defaultSize() * scale}; + QPixmap pixmap {renderer.defaultSize()}; pixmap.fill(Qt::GlobalColor::transparent); QPainter painter {&pixmap}; diff --git a/scwx-qt/source/scwx/qt/util/texture_atlas.hpp b/scwx-qt/source/scwx/qt/util/texture_atlas.hpp index b0214a66..64c5a2d7 100644 --- a/scwx-qt/source/scwx/qt/util/texture_atlas.hpp +++ b/scwx-qt/source/scwx/qt/util/texture_atlas.hpp @@ -74,10 +74,10 @@ public: std::uint64_t BuildCount() const; void RegisterTexture(const std::string& name, const std::string& path); - std::shared_ptr CacheTexture( - const std::string& name, const std::string& path, double scale = 1); + std::shared_ptr + CacheTexture(const std::string& name, const std::string& path); void BuildAtlas(std::size_t width, std::size_t height); - void BufferAtlas(GLuint texture); + void BufferAtlas(gl::OpenGLFunctions& gl, GLuint texture); TextureAttributes GetTextureAttributes(const std::string& name); diff --git a/scwx-qt/source/scwx/qt/util/time.cpp b/scwx-qt/source/scwx/qt/util/time.cpp index 73d7820b..f34c6ea5 100644 --- a/scwx-qt/source/scwx/qt/util/time.cpp +++ b/scwx-qt/source/scwx/qt/util/time.cpp @@ -12,23 +12,13 @@ std::chrono::sys_days SysDays(const QDate& date) using namespace std::chrono; using sys_days = time_point; constexpr auto julianEpoch = sys_days {-4713y / November / 24d}; + constexpr auto unixEpoch = sys_days {1970y / January / 1d}; + constexpr auto offset = std::chrono::days(julianEpoch - unixEpoch); return std::chrono::sys_days(std::chrono::days(date.toJulianDay()) + julianEpoch); } -local_days LocalDays(const QDate& date) -{ -#if (__cpp_lib_chrono >= 201907L) - using namespace std::chrono; -#else - using namespace date; -#endif - auto yearMonthDay = - year_month_day(year(date.year()), month(date.month()), day(date.day())); - return local_days(yearMonthDay); -} - } // namespace util } // namespace qt } // namespace scwx diff --git a/scwx-qt/source/scwx/qt/util/time.hpp b/scwx-qt/source/scwx/qt/util/time.hpp index 34af655e..8f3e7a53 100644 --- a/scwx-qt/source/scwx/qt/util/time.hpp +++ b/scwx-qt/source/scwx/qt/util/time.hpp @@ -2,10 +2,6 @@ #include -#if (__cpp_lib_chrono < 201907L) -# include -#endif - #include namespace scwx @@ -15,12 +11,6 @@ namespace qt namespace util { -#if (__cpp_lib_chrono >= 201907L) -using local_days = std::chrono::local_days; -#else -using local_days = date::local_days; -#endif - /** * @brief Convert QDate to std::chrono::sys_days. * @@ -30,15 +20,6 @@ using local_days = date::local_days; */ std::chrono::sys_days SysDays(const QDate& date); -/** - * @brief Convert QDate to std::chrono::local_days. - * - * @param [in] date Date to convert - * - * @return Days - */ -local_days LocalDays(const QDate& date); - } // namespace util } // namespace qt } // namespace scwx diff --git a/scwx-qt/source/scwx/qt/view/level2_product_view.cpp b/scwx-qt/source/scwx/qt/view/level2_product_view.cpp index 9ead358b..47558d81 100644 --- a/scwx-qt/source/scwx/qt/view/level2_product_view.cpp +++ b/scwx-qt/source/scwx/qt/view/level2_product_view.cpp @@ -25,11 +25,6 @@ static constexpr std::uint32_t kMaxRadialGates_ = common::MAX_0_5_DEGREE_RADIALS * common::MAX_DATA_MOMENT_GATES; static constexpr std::uint32_t kMaxCoordinates_ = kMaxRadialGates_ * 2u; -static constexpr std::uint8_t kDataWordSize8_ = 8u; - -static constexpr std::size_t kVerticesPerGate_ = 6u; -static constexpr std::size_t kVerticesPerOriginGate_ = 3u; - static constexpr uint16_t RANGE_FOLDED = 1u; static constexpr uint32_t VERTICES_PER_BIN = 6u; static constexpr uint32_t VALUES_PER_VERTEX = 2u; @@ -51,9 +46,6 @@ static const std::unordered_map productScale_ { - {common::Level2Product::CorrelationCoefficient, 100.0f}}; - static const std::unordered_map productUnits_ {{common::Level2Product::Reflectivity, "dBZ"}, {common::Level2Product::DifferentialReflectivity, "dB"}, @@ -61,10 +53,11 @@ static const std::unordered_map {common::Level2Product::CorrelationCoefficient, "%"}, {common::Level2Product::ClutterFilterPowerRemoved, "dB"}}; -class Level2ProductView::Impl +class Level2ProductViewImpl { public: - explicit Impl(Level2ProductView* self, common::Level2Product product) : + explicit Level2ProductViewImpl(Level2ProductView* self, + common::Level2Product product) : self_ {self}, product_ {product}, selectedElevation_ {0.0f}, @@ -101,7 +94,7 @@ public: UpdateOtherUnits(unitSettings.other_units().GetValue()); UpdateSpeedUnits(unitSettings.speed_units().GetValue()); } - ~Impl() + ~Level2ProductViewImpl() { auto& unitSettings = settings::UnitSettings::Instance(); @@ -113,36 +106,20 @@ public: threadPool_.join(); }; - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - - Impl(Impl&&) noexcept = delete; - Impl& operator=(Impl&&) noexcept = delete; - - void ComputeCoordinates( - const std::shared_ptr& radarData, - bool smoothingEnabled); + void + ComputeCoordinates(std::shared_ptr radarData); void SetProduct(const std::string& productName); void SetProduct(common::Level2Product product); void UpdateOtherUnits(const std::string& name); void UpdateSpeedUnits(const std::string& name); - void ComputeEdgeValue(); - template - [[nodiscard]] inline T RemapDataMoment(T dataMoment) const; - - static bool IsRadarDataIncomplete( - const std::shared_ptr& radarData); - static units::degrees NormalizeAngle(units::degrees angle); - Level2ProductView* self_; boost::asio::thread_pool threadPool_ {1u}; common::Level2Product product_; - wsr88d::rda::DataBlockType dataBlockType_ { - wsr88d::rda::DataBlockType::Unknown}; + wsr88d::rda::DataBlockType dataBlockType_; float selectedElevation_; @@ -150,17 +127,11 @@ public: std::shared_ptr momentDataBlock0_; - bool lastShowSmoothedRangeFolding_ {false}; - bool lastSmoothingEnabled_ {false}; - std::vector coordinates_ {}; std::vector vertices_ {}; std::vector dataMoments8_ {}; std::vector dataMoments16_ {}; std::vector cfpMoments_ {}; - std::uint16_t edgeValue_ {}; - - bool showSmoothedRangeFolding_ {false}; float latitude_; float longitude_; @@ -190,7 +161,7 @@ Level2ProductView::Level2ProductView( common::Level2Product product, std::shared_ptr radarProductManager) : RadarProductView(radarProductManager), - p(std::make_unique(this, product)) + p(std::make_unique(this, product)) { ConnectRadarProductManager(); } @@ -208,9 +179,12 @@ void Level2ProductView::ConnectRadarProductManager() [this](std::shared_ptr record) { if (record->radar_product_group() == - common::RadarProductGroup::Level2) + common::RadarProductGroup::Level2 && + std::chrono::floor(record->time()) == + selected_time()) { - // If level 2 data associated was reloaded, update the view + // If the data associated with the currently selected time is + // reloaded, update the view Update(); } }); @@ -271,7 +245,7 @@ uint16_t Level2ProductView::color_table_max() const } } -std::optional Level2ProductView::elevation() const +float Level2ProductView::elevation() const { return p->elevationCut_; } @@ -298,15 +272,6 @@ float Level2ProductView::unit_scale() const break; } - if (p->otherUnits_ == types::OtherUnits::Default) - { - auto it = productScale_.find(p->product_); - if (it != productScale_.cend()) - { - return it->second; - } - } - return 1.0f; } @@ -414,12 +379,12 @@ void Level2ProductView::SelectProduct(const std::string& productName) p->SetProduct(productName); } -void Level2ProductView::Impl::SetProduct(const std::string& productName) +void Level2ProductViewImpl::SetProduct(const std::string& productName) { SetProduct(common::GetLevel2Product(productName)); } -void Level2ProductView::Impl::SetProduct(common::Level2Product product) +void Level2ProductViewImpl::SetProduct(common::Level2Product product) { product_ = product; @@ -436,12 +401,12 @@ void Level2ProductView::Impl::SetProduct(common::Level2Product product) } } -void Level2ProductView::Impl::UpdateOtherUnits(const std::string& name) +void Level2ProductViewImpl::UpdateOtherUnits(const std::string& name) { otherUnits_ = types::GetOtherUnitsFromName(name); } -void Level2ProductView::Impl::UpdateSpeedUnits(const std::string& name) +void Level2ProductViewImpl::UpdateSpeedUnits(const std::string& name) { speedUnits_ = types::GetSpeedUnitsFromName(name); } @@ -532,7 +497,7 @@ void Level2ProductView::UpdateColorTableLut() void Level2ProductView::ComputeSweep() { - logger_->trace("ComputeSweep()"); + logger_->debug("ComputeSweep()"); boost::timer::cpu_timer timer; @@ -546,52 +511,34 @@ void Level2ProductView::ComputeSweep() std::shared_ptr radarProductManager = radar_product_manager(); - const bool smoothingEnabled = smoothing_enabled(); - p->showSmoothedRangeFolding_ = show_smoothed_range_folding(); - const bool& showSmoothedRangeFolding = p->showSmoothedRangeFolding_; std::shared_ptr radarData; std::chrono::system_clock::time_point requestedTime {selected_time()}; - std::tie(radarData, p->elevationCut_, p->elevationCuts_, std::ignore) = + std::chrono::system_clock::time_point foundTime; + std::tie(radarData, p->elevationCut_, p->elevationCuts_, foundTime) = radarProductManager->GetLevel2Data( p->dataBlockType_, p->selectedElevation_, requestedTime); + // If a different time was found than what was requested, update it + if (requestedTime != foundTime) + { + SelectTime(foundTime); + } + if (radarData == nullptr) { Q_EMIT SweepNotComputed(types::NoUpdateReason::NotLoaded); return; } - if ((radarData == p->elevationScan_) && - smoothingEnabled == p->lastSmoothingEnabled_ && - (showSmoothedRangeFolding == p->lastShowSmoothedRangeFolding_ || - !smoothingEnabled)) + if (radarData == p->elevationScan_) { Q_EMIT SweepNotComputed(types::NoUpdateReason::NoChange); return; } - p->lastShowSmoothedRangeFolding_ = showSmoothedRangeFolding; - p->lastSmoothingEnabled_ = smoothingEnabled; + const size_t radials = radarData->size(); - logger_->debug("Computing Sweep"); - - std::size_t radials = radarData->crbegin()->first + 1; - std::size_t vertexRadials = radials; - - // When there is missing data, insert another empty vertex radial at the end - // to avoid stretching - const bool isRadarDataIncomplete = Impl::IsRadarDataIncomplete(radarData); - if (isRadarDataIncomplete) - { - ++vertexRadials; - } - - // Limit radials - radials = std::min(radials, common::MAX_0_5_DEGREE_RADIALS); - vertexRadials = - std::min(vertexRadials, common::MAX_0_5_DEGREE_RADIALS); - - p->ComputeCoordinates(radarData, smoothingEnabled); + p->ComputeCoordinates(radarData); const std::vector& coordinates = p->coordinates_; @@ -627,8 +574,7 @@ void Level2ProductView::ComputeSweep() std::vector& vertices = p->vertices_; size_t vIndex = 0; vertices.clear(); - vertices.resize(vertexRadials * gates * VERTICES_PER_BIN * - VALUES_PER_VERTEX); + vertices.resize(radials * gates * VERTICES_PER_BIN * VALUES_PER_VERTEX); // Setup data moment vector std::vector& dataMoments8 = p->dataMoments8_; @@ -670,20 +616,11 @@ void Level2ProductView::ComputeSweep() // Start radial is always 0, as coordinates are calculated for each sweep constexpr std::uint16_t startRadial = 0u; - // For most products other than reflectivity, the edge should not go to the - // bottom of the color table - if (smoothingEnabled) + for (auto& radialPair : *radarData) { - p->ComputeEdgeValue(); - } - - for (auto it = radarData->cbegin(); it != radarData->cend(); ++it) - { - const auto& radialPair = *it; std::uint16_t radial = radialPair.first; - const auto& radialData = radialPair.second; - const std::shared_ptr - momentData = radialData->moment_data_block(p->dataBlockType_); + auto& radialData = radialPair.second; + auto momentData = radialData->moment_data_block(p->dataBlockType_); if (momentData0->data_word_size() != momentData->data_word_size()) { @@ -705,7 +642,7 @@ void Level2ProductView::ComputeSweep() std::max(1, dataMomentInterval / gateSizeMeters); // Compute gate range [startGate, endGate) - std::int32_t startGate = + const std::int32_t startGate = (dataMomentRange - dataMomentIntervalH) / gateSizeMeters; const std::int32_t numberOfDataMomentGates = std::min(momentData->number_of_data_moment_gates(), @@ -714,19 +651,9 @@ void Level2ProductView::ComputeSweep() startGate + numberOfDataMomentGates * gateSize, static_cast(common::MAX_DATA_MOMENT_GATES)); - if (smoothingEnabled) - { - // If smoothing is enabled, the start gate is incremented by one, as we - // are skipping the radar site origin. The end gate is unaffected, as - // we need to draw one less data point. - ++startGate; - } - - const std::uint8_t* dataMomentsArray8 = nullptr; - const std::uint16_t* dataMomentsArray16 = nullptr; - const std::uint8_t* nextDataMomentsArray8 = nullptr; - const std::uint16_t* nextDataMomentsArray16 = nullptr; - const std::uint8_t* cfpMomentsArray = nullptr; + const std::uint8_t* dataMomentsArray8 = nullptr; + const std::uint16_t* dataMomentsArray16 = nullptr; + const std::uint8_t* cfpMomentsArray = nullptr; if (momentData->data_word_size() == 8) { @@ -746,45 +673,6 @@ void Level2ProductView::ComputeSweep() ->data_moments()); } - std::shared_ptr - nextMomentData = nullptr; - std::int32_t numberOfNextDataMomentGates = 0; - if (smoothingEnabled) - { - // Smoothing requires the next radial pair as well - auto nextIt = std::next(it); - if (nextIt == radarData->cend()) - { - nextIt = radarData->cbegin(); - } - - const auto& nextRadialPair = *(nextIt); - const auto& nextRadialData = nextRadialPair.second; - nextMomentData = nextRadialData->moment_data_block(p->dataBlockType_); - - if (momentData->data_word_size() != nextMomentData->data_word_size()) - { - // Data should be consistent between radials - logger_->warn("Invalid data moment size"); - continue; - } - - if (nextMomentData->data_word_size() == kDataWordSize8_) - { - nextDataMomentsArray8 = reinterpret_cast( - nextMomentData->data_moments()); - } - else - { - nextDataMomentsArray16 = reinterpret_cast( - nextMomentData->data_moments()); - } - - numberOfNextDataMomentGates = std::min( - nextMomentData->number_of_data_moment_gates(), - static_cast(gates)); - } - for (std::int32_t gate = startGate, i = 0; gate + gateSize <= endGate; gate += gateSize, ++i) { @@ -793,172 +681,56 @@ void Level2ProductView::ComputeSweep() continue; } - const std::size_t vertexCount = - (gate > 0) ? kVerticesPerGate_ : kVerticesPerOriginGate_; - - // Allow pointer arithmetic here, as bounds have already been checked - // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic) + std::size_t vertexCount = (gate > 0) ? 6 : 3; // Store data moment value if (dataMomentsArray8 != nullptr) { - if (!smoothingEnabled) + std::uint8_t dataValue = dataMomentsArray8[i]; + if (dataValue < snrThreshold && dataValue != RANGE_FOLDED) { - const std::uint8_t& dataValue = dataMomentsArray8[i]; - if (dataValue < snrThreshold && dataValue != RANGE_FOLDED) - { - continue; - } - - for (std::size_t m = 0; m < vertexCount; m++) - { - dataMoments8[mIndex++] = dataValue; - - if (cfpMomentsArray != nullptr) - { - cfpMoments[mIndex - 1] = cfpMomentsArray[i]; - } - } - } - else if (gate > 0) - { - // Validate indices are all in range - if (i + 1 >= numberOfDataMomentGates || - i + 1 >= numberOfNextDataMomentGates) - { - continue; - } - - const std::uint8_t& dm1 = dataMomentsArray8[i]; - const std::uint8_t& dm2 = dataMomentsArray8[i + 1]; - const std::uint8_t& dm3 = nextDataMomentsArray8[i]; - const std::uint8_t& dm4 = nextDataMomentsArray8[i + 1]; - - if ((!showSmoothedRangeFolding && // - (dm1 < snrThreshold || dm1 == RANGE_FOLDED) && - (dm2 < snrThreshold || dm2 == RANGE_FOLDED) && - (dm3 < snrThreshold || dm3 == RANGE_FOLDED) && - (dm4 < snrThreshold || dm4 == RANGE_FOLDED)) || - (showSmoothedRangeFolding && // - dm1 < snrThreshold && dm1 != RANGE_FOLDED && - dm2 < snrThreshold && dm2 != RANGE_FOLDED && - dm3 < snrThreshold && dm3 != RANGE_FOLDED && - dm4 < snrThreshold && dm4 != RANGE_FOLDED)) - { - // Skip only if all data moments are hidden - continue; - } - - // The order must match the store vertices section below - dataMoments8[mIndex++] = p->RemapDataMoment(dm1); - dataMoments8[mIndex++] = p->RemapDataMoment(dm2); - dataMoments8[mIndex++] = p->RemapDataMoment(dm4); - dataMoments8[mIndex++] = p->RemapDataMoment(dm1); - dataMoments8[mIndex++] = p->RemapDataMoment(dm3); - dataMoments8[mIndex++] = p->RemapDataMoment(dm4); - - // cfpMoments is unused, so not populated here - } - else - { - // If smoothing is enabled, gate should never start at zero - // (radar site origin) - logger_->error( - "Smoothing enabled, gate should not start at zero"); continue; } + + for (std::size_t m = 0; m < vertexCount; m++) + { + dataMoments8[mIndex++] = dataMomentsArray8[i]; + + if (cfpMomentsArray != nullptr) + { + cfpMoments[mIndex - 1] = cfpMomentsArray[i]; + } + } } else { - if (!smoothingEnabled) + std::uint16_t dataValue = dataMomentsArray16[i]; + if (dataValue < snrThreshold && dataValue != RANGE_FOLDED) { - const std::uint16_t& dataValue = dataMomentsArray16[i]; - if (dataValue < snrThreshold && dataValue != RANGE_FOLDED) - { - continue; - } - - for (std::size_t m = 0; m < vertexCount; m++) - { - dataMoments16[mIndex++] = dataValue; - } - } - else if (gate > 0) - { - // Validate indices are all in range - if (i + 1 >= numberOfDataMomentGates || - i + 1 >= numberOfNextDataMomentGates) - { - continue; - } - - const std::uint16_t& dm1 = dataMomentsArray16[i]; - const std::uint16_t& dm2 = dataMomentsArray16[i + 1]; - const std::uint16_t& dm3 = nextDataMomentsArray16[i]; - const std::uint16_t& dm4 = nextDataMomentsArray16[i + 1]; - - if ((!showSmoothedRangeFolding && // - (dm1 < snrThreshold || dm1 == RANGE_FOLDED) && - (dm2 < snrThreshold || dm2 == RANGE_FOLDED) && - (dm3 < snrThreshold || dm3 == RANGE_FOLDED) && - (dm4 < snrThreshold || dm4 == RANGE_FOLDED)) || - (showSmoothedRangeFolding && // - dm1 < snrThreshold && dm1 != RANGE_FOLDED && - dm2 < snrThreshold && dm2 != RANGE_FOLDED && - dm3 < snrThreshold && dm3 != RANGE_FOLDED && - dm4 < snrThreshold && dm4 != RANGE_FOLDED)) - { - // Skip only if all data moments are hidden - continue; - } - - // The order must match the store vertices section below - dataMoments16[mIndex++] = p->RemapDataMoment(dm1); - dataMoments16[mIndex++] = p->RemapDataMoment(dm2); - dataMoments16[mIndex++] = p->RemapDataMoment(dm4); - dataMoments16[mIndex++] = p->RemapDataMoment(dm1); - dataMoments16[mIndex++] = p->RemapDataMoment(dm3); - dataMoments16[mIndex++] = p->RemapDataMoment(dm4); - - // cfpMoments is unused, so not populated here - } - else - { - // If smoothing is enabled, gate should never start at zero - // (radar site origin) continue; } - } - // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic) + for (std::size_t m = 0; m < vertexCount; m++) + { + dataMoments16[mIndex++] = dataMomentsArray16[i]; + } + } // Store vertices if (gate > 0) { - // Draw two triangles per gate - // - // 2 +---+ 4 - // | /| - // | / | - // |/ | - // 1 +---+ 3 - const std::uint16_t baseCoord = gate - 1; - const std::size_t offset1 = - ((startRadial + radial) % vertexRadials * - common::MAX_DATA_MOMENT_GATES + - baseCoord) * - 2; - const std::size_t offset2 = - offset1 + static_cast(gateSize) * 2; - const std::size_t offset3 = - (((startRadial + radial + 1) % vertexRadials) * - common::MAX_DATA_MOMENT_GATES + - baseCoord) * - 2; - const std::size_t offset4 = - offset3 + static_cast(gateSize) * 2; + std::size_t offset1 = ((startRadial + radial) % radials * + common::MAX_DATA_MOMENT_GATES + + baseCoord) * + 2; + std::size_t offset2 = offset1 + gateSize * 2; + std::size_t offset3 = (((startRadial + radial + 1) % radials) * + common::MAX_DATA_MOMENT_GATES + + baseCoord) * + 2; + std::size_t offset4 = offset3 + gateSize * 2; vertices[vIndex++] = coordinates[offset1]; vertices[vIndex++] = coordinates[offset1 + 1]; @@ -966,31 +738,32 @@ void Level2ProductView::ComputeSweep() vertices[vIndex++] = coordinates[offset2]; vertices[vIndex++] = coordinates[offset2 + 1]; - vertices[vIndex++] = coordinates[offset4]; - vertices[vIndex++] = coordinates[offset4 + 1]; - - vertices[vIndex++] = coordinates[offset1]; - vertices[vIndex++] = coordinates[offset1 + 1]; + vertices[vIndex++] = coordinates[offset3]; + vertices[vIndex++] = coordinates[offset3 + 1]; vertices[vIndex++] = coordinates[offset3]; vertices[vIndex++] = coordinates[offset3 + 1]; vertices[vIndex++] = coordinates[offset4]; vertices[vIndex++] = coordinates[offset4 + 1]; + + vertices[vIndex++] = coordinates[offset2]; + vertices[vIndex++] = coordinates[offset2 + 1]; + + vertexCount = 6; } else { const std::uint16_t baseCoord = gate; - std::size_t offset1 = ((startRadial + radial) % vertexRadials * + std::size_t offset1 = ((startRadial + radial) % radials * + common::MAX_DATA_MOMENT_GATES + + baseCoord) * + 2; + std::size_t offset2 = (((startRadial + radial + 1) % radials) * common::MAX_DATA_MOMENT_GATES + baseCoord) * 2; - std::size_t offset2 = - (((startRadial + radial + 1) % vertexRadials) * - common::MAX_DATA_MOMENT_GATES + - baseCoord) * - 2; vertices[vIndex++] = p->latitude_; vertices[vIndex++] = p->longitude_; @@ -1000,6 +773,8 @@ void Level2ProductView::ComputeSweep() vertices[vIndex++] = coordinates[offset2]; vertices[vIndex++] = coordinates[offset2 + 1]; + + vertexCount = 3; } } } @@ -1031,50 +806,8 @@ void Level2ProductView::ComputeSweep() Q_EMIT SweepComputed(); } -void Level2ProductView::Impl::ComputeEdgeValue() -{ - const float offset = momentDataBlock0_->offset(); - - switch (dataBlockType_) - { - case wsr88d::rda::DataBlockType::MomentVel: - case wsr88d::rda::DataBlockType::MomentZdr: - edgeValue_ = static_cast(offset); - break; - - case wsr88d::rda::DataBlockType::MomentSw: - case wsr88d::rda::DataBlockType::MomentPhi: - edgeValue_ = 2; - break; - - case wsr88d::rda::DataBlockType::MomentRho: - edgeValue_ = std::numeric_limits::max(); - break; - - case wsr88d::rda::DataBlockType::MomentRef: - default: - edgeValue_ = 0; - break; - } -} - -template -T Level2ProductView::Impl::RemapDataMoment(T dataMoment) const -{ - if (dataMoment != 0 && - (dataMoment != RANGE_FOLDED || showSmoothedRangeFolding_)) - { - return dataMoment; - } - else - { - return edgeValue_; - } -} - -void Level2ProductView::Impl::ComputeCoordinates( - const std::shared_ptr& radarData, - bool smoothingEnabled) +void Level2ProductViewImpl::ComputeCoordinates( + std::shared_ptr radarData) { logger_->debug("ComputeCoordinates()"); @@ -1095,203 +828,52 @@ void Level2ProductView::Impl::ComputeCoordinates( auto& radarData0 = (*radarData)[0]; auto momentData0 = radarData0->moment_data_block(dataBlockType_); - std::uint16_t numRadials = - static_cast(radarData->crbegin()->first + 1); + const std::uint16_t numRadials = + static_cast(radarData->size()); const std::uint16_t numRangeBins = std::max(momentData0->number_of_data_moment_gates() + 1u, common::MAX_DATA_MOMENT_GATES); - // Add an extra radial when incomplete data exists - if (IsRadarDataIncomplete(radarData)) - { - ++numRadials; - } - - // Limit radials - numRadials = - std::min(numRadials, common::MAX_0_5_DEGREE_RADIALS); - auto radials = boost::irange(0u, numRadials); auto gates = boost::irange(0u, numRangeBins); - const float gateRangeOffset = (smoothingEnabled) ? - // Center of the first gate is half the gate - // size distance from the radar site - 0.5f : - // Far end of the first gate is the gate - // size distance from the radar site - 1.0f; + std::for_each(std::execution::par_unseq, + radials.begin(), + radials.end(), + [&](std::uint32_t radial) + { + const units::degrees angle = + (*radarData)[radial]->azimuth_angle(); - std::for_each( - std::execution::par_unseq, - radials.begin(), - radials.end(), - [&](std::uint32_t radial) - { - units::degrees angle {}; + std::for_each(std::execution::par_unseq, + gates.begin(), + gates.end(), + [&](std::uint32_t gate) + { + const std::uint32_t radialGate = + radial * common::MAX_DATA_MOMENT_GATES + + gate; + const float range = (gate + 1) * gateSize; + const std::size_t offset = radialGate * 2; - auto radialData = radarData->find(radial); - if (radialData != radarData->cend() && smoothingEnabled) - { - angle = radialData->second->azimuth_angle(); - } - else - { - auto prevRadial1 = radarData->find( - (radial >= 1) ? radial - 1 : numRadials - (1 - radial)); - auto prevRadial2 = radarData->find( - (radial >= 2) ? radial - 2 : numRadials - (2 - radial)); + double latitude; + double longitude; - if (radialData != radarData->cend() && - prevRadial1 != radarData->cend() && !smoothingEnabled) - { - const units::degrees currentAngle = - radialData->second->azimuth_angle(); - const units::degrees prevAngle = - prevRadial1->second->azimuth_angle(); + geodesic.Direct(radarLatitude, + radarLongitude, + angle.value(), + range, + latitude, + longitude); - // Calculate delta angle - const units::degrees deltaAngle = - NormalizeAngle(currentAngle - prevAngle); - - // Delta scale is half the delta angle to reach the end of the - // bin, because smoothing is not enabled - constexpr float deltaScale = 0.5f; - - angle = currentAngle - deltaAngle * deltaScale; - } - else if (radialData != radarData->cend() && !smoothingEnabled) - { - const units::degrees currentAngle = - radialData->second->azimuth_angle(); - - // Assume a half degree delta if there aren't enough angles - // to determine a delta angle - constexpr units::degrees deltaAngle {0.5f}; - - // Delta scale is half the delta angle to reach the edge of the - // bin, because smoothing is enabled - constexpr float deltaScale = 0.5f; - - angle = currentAngle - deltaAngle * deltaScale; - } - else if (prevRadial1 != radarData->cend() && - prevRadial2 != radarData->cend()) - { - const units::degrees prevAngle1 = - prevRadial1->second->azimuth_angle(); - const units::degrees prevAngle2 = - prevRadial2->second->azimuth_angle(); - - // Calculate delta angle - const units::degrees deltaAngle = - NormalizeAngle(prevAngle1 - prevAngle2); - - const float deltaScale = - (smoothingEnabled) ? - // Delta scale is 1.0x the delta angle to reach the center - // of the next bin, because smoothing is enabled - 1.0f : - // Delta scale is 0.5x the delta angle to reach the edge of - // the next bin - 0.5f; - - angle = prevAngle1 + deltaAngle * deltaScale; - } - else if (prevRadial1 != radarData->cend()) - { - const units::degrees prevAngle1 = - prevRadial1->second->azimuth_angle(); - - // Assume a half degree delta if there aren't enough angles - // to determine a delta angle - constexpr units::degrees deltaAngle {0.5f}; - - const float deltaScale = - (smoothingEnabled) ? - // Delta scale is 1.0x the delta angle to reach the center - // of the next bin, because smoothing is enabled - 1.0f : - // Delta scale is 0.5x the delta angle to reach the edge of - // the next bin - 0.5f; - - angle = prevAngle1 + deltaAngle * deltaScale; - } - else - { - // Not enough angles present to determine an angle - return; - } - } - - std::for_each( - std::execution::par_unseq, - gates.begin(), - gates.end(), - [&](std::uint32_t gate) - { - const std::uint32_t radialGate = - radial * common::MAX_DATA_MOMENT_GATES + gate; - const float range = - (static_cast(gate) + gateRangeOffset) * gateSize; - const std::size_t offset = - static_cast(radialGate) * 2; - - double latitude = 0.0; - double longitude = 0.0; - - geodesic.Direct(radarLatitude, - radarLongitude, - angle.value(), - range, - latitude, - longitude); - - coordinates_[offset] = static_cast(latitude); - coordinates_[offset + 1] = static_cast(longitude); - }); - }); + coordinates_[offset] = latitude; + coordinates_[offset + 1] = longitude; + }); + }); timer.stop(); logger_->debug("Coordinates calculated in {}", timer.format(6, "%ws")); } -bool Level2ProductView::Impl::IsRadarDataIncomplete( - const std::shared_ptr& radarData) -{ - // Assume the data is incomplete when the delta between the first and last - // angles is greater than 2.5 degrees. - constexpr units::degrees kIncompleteDataAngleThreshold_ {2.5}; - - const units::degrees firstAngle = - radarData->cbegin()->second->azimuth_angle(); - const units::degrees lastAngle = - radarData->crbegin()->second->azimuth_angle(); - const units::degrees angleDelta = - common::GetAngleDelta(firstAngle, lastAngle); - - return angleDelta > kIncompleteDataAngleThreshold_; -} - -units::degrees -Level2ProductView::Impl::NormalizeAngle(units::degrees angle) -{ - constexpr auto angleLimit = units::degrees {180.0f}; - constexpr auto fullAngle = units::degrees {360.0f}; - - // Normalize angle to [-180, 180) - while (angle < -angleLimit) - { - angle += fullAngle; - } - while (angle >= angleLimit) - { - angle -= fullAngle; - } - - return angle; -} - std::optional Level2ProductView::GetBinLevel(const common::Coordinate& coordinate) const { @@ -1334,19 +916,8 @@ Level2ProductView::GetBinLevel(const common::Coordinate& coordinate) const } // Find Radial - std::uint16_t numRadials = - static_cast(radarData->crbegin()->first + 1); - - // Add an extra radial when incomplete data exists - if (Impl::IsRadarDataIncomplete(radarData)) - { - ++numRadials; - } - - // Limit radials - numRadials = - std::min(numRadials, common::MAX_0_5_DEGREE_RADIALS); - + const std::uint16_t numRadials = + static_cast(radarData->size()); auto radials = boost::irange(0u, numRadials); auto radial = std::find_if( // @@ -1355,68 +926,25 @@ Level2ProductView::GetBinLevel(const common::Coordinate& coordinate) const radials.end(), [&](std::uint32_t i) { - bool hasNextAngle = false; - bool found = false; + bool found = false; + const units::degrees startAngle = + (*radarData)[i]->azimuth_angle(); + const units::degrees nextAngle = + (*radarData)[(i + 1) % numRadials]->azimuth_angle(); - units::degrees startAngle {}; - units::degrees nextAngle {}; - - auto radialData = radarData->find(i); - if (radialData != radarData->cend()) + if (startAngle < nextAngle) { - startAngle = radialData->second->azimuth_angle(); - - auto nextRadial = radarData->find((i + 1) % numRadials); - if (nextRadial != radarData->cend()) + if (startAngle.value() <= azi1 && azi1 < nextAngle.value()) { - nextAngle = nextRadial->second->azimuth_angle(); - - // Level 2 angles are the center of the bins. - const units::degrees deltaAngle = - common::GetAngleDelta(startAngle, nextAngle); - startAngle -= deltaAngle / 2; - nextAngle -= deltaAngle / 2; - - hasNextAngle = true; - } - else - { - // Next angle is not available, interpolate - auto prevRadial = - radarData->find((i >= 1) ? i - 1 : numRadials - (1 - i)); - - if (prevRadial != radarData->cend()) - { - const units::degrees prevAngle = - prevRadial->second->azimuth_angle(); - - const units::degrees deltaAngle = - common::GetAngleDelta(startAngle, prevAngle); - - // Level 2 angles are the center of the bins. - nextAngle = startAngle + deltaAngle / 2; - startAngle -= deltaAngle / 2; - hasNextAngle = true; - } + found = true; } } - - if (hasNextAngle) + else { - if (startAngle < nextAngle) + // If the bin crosses 0/360 degrees, special handling is needed + if (startAngle.value() <= azi1 || azi1 < nextAngle.value()) { - if (startAngle.value() <= azi1 && azi1 < nextAngle.value()) - { - found = true; - } - } - else - { - // If the bin crosses 0/360 degrees, special handling is needed - if (startAngle.value() <= azi1 || azi1 < nextAngle.value()) - { - found = true; - } + found = true; } } diff --git a/scwx-qt/source/scwx/qt/view/level2_product_view.hpp b/scwx-qt/source/scwx/qt/view/level2_product_view.hpp index 64651bfa..9e25a254 100644 --- a/scwx-qt/source/scwx/qt/view/level2_product_view.hpp +++ b/scwx-qt/source/scwx/qt/view/level2_product_view.hpp @@ -8,8 +8,14 @@ #include #include -namespace scwx::qt::view +namespace scwx { +namespace qt +{ +namespace view +{ + +class Level2ProductViewImpl; class Level2ProductView : public RadarProductView { @@ -19,47 +25,38 @@ public: explicit Level2ProductView( common::Level2Product product, std::shared_ptr radarProductManager); - ~Level2ProductView() override; + ~Level2ProductView(); - Level2ProductView(const Level2ProductView&) = delete; - Level2ProductView(Level2ProductView&&) = delete; - Level2ProductView& operator=(const Level2ProductView&) = delete; - Level2ProductView& operator=(Level2ProductView&&) = delete; - - [[nodiscard]] std::shared_ptr - color_table() const override; - [[nodiscard]] const std::vector& - color_table_lut() const override; - [[nodiscard]] std::uint16_t color_table_min() const override; - [[nodiscard]] std::uint16_t color_table_max() const override; - [[nodiscard]] std::optional elevation() const override; - [[nodiscard]] float range() const override; - [[nodiscard]] std::chrono::system_clock::time_point - sweep_time() const override; - [[nodiscard]] float unit_scale() const override; - [[nodiscard]] std::string units() const override; - [[nodiscard]] std::uint16_t vcp() const override; - [[nodiscard]] const std::vector& vertices() const override; + std::shared_ptr color_table() const override; + const std::vector& + color_table_lut() const override; + std::uint16_t color_table_min() const override; + std::uint16_t color_table_max() const override; + float elevation() const override; + float range() const override; + std::chrono::system_clock::time_point sweep_time() const override; + float unit_scale() const override; + std::string units() const override; + std::uint16_t vcp() const override; + const std::vector& vertices() const override; void LoadColorTable(std::shared_ptr colorTable) override; void SelectElevation(float elevation) override; void SelectProduct(const std::string& productName) override; - [[nodiscard]] common::RadarProductGroup - GetRadarProductGroup() const override; - [[nodiscard]] std::string GetRadarProductName() const override; - [[nodiscard]] std::vector GetElevationCuts() const override; - [[nodiscard]] std::tuple + common::RadarProductGroup GetRadarProductGroup() const override; + std::string GetRadarProductName() const override; + std::vector GetElevationCuts() const override; + std::tuple GetMomentData() const override; - [[nodiscard]] std::tuple + std::tuple GetCfpMomentData() const override; - [[nodiscard]] std::optional + std::optional GetBinLevel(const common::Coordinate& coordinate) const override; - [[nodiscard]] std::optional - GetDataLevelCode(std::uint16_t level) const override; - [[nodiscard]] std::optional - GetDataValue(std::uint16_t level) const override; + std::optional + GetDataLevelCode(std::uint16_t level) const override; + std::optional GetDataValue(std::uint16_t level) const override; static std::shared_ptr Create(common::Level2Product product, @@ -76,8 +73,9 @@ protected slots: void ComputeSweep() override; private: - class Impl; - std::unique_ptr p; + std::unique_ptr p; }; -} // namespace scwx::qt::view +} // namespace view +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/view/level3_product_view.cpp b/scwx-qt/source/scwx/qt/view/level3_product_view.cpp index 97985a39..551d04e4 100644 --- a/scwx-qt/source/scwx/qt/view/level3_product_view.cpp +++ b/scwx-qt/source/scwx/qt/view/level3_product_view.cpp @@ -17,6 +17,10 @@ #include #include +#if !defined(_MSC_VER) +# include +#endif + namespace scwx { namespace qt @@ -29,10 +33,6 @@ static const auto logger_ = util::Logger::Create(logPrefix_); static constexpr uint16_t RANGE_FOLDED = 1u; -static const std::unordered_map - categoryScale_ { - {common::Level3ProductCategory::CorrelationCoefficient, 100.0f}}; - static const std::unordered_map categoryUnits_ { {common::Level3ProductCategory::Reflectivity, "dBZ"}, @@ -221,15 +221,6 @@ float Level3ProductView::unit_scale() const break; } - if (p->otherUnits_ == types::OtherUnits::Default) - { - auto it = categoryScale_.find(p->category_); - if (it != categoryScale_.cend()) - { - return it->second; - } - } - return 1.0f; } @@ -498,52 +489,6 @@ void Level3ProductView::UpdateColorTableLut() Q_EMIT ColorTableLutUpdated(); } -std::uint8_t Level3ProductView::ComputeEdgeValue() const -{ - std::uint8_t edgeValue = 0; - - const std::shared_ptr - descriptionBlock = p->graphicMessage_->description_block(); - - const float offset = descriptionBlock->offset(); - const float scale = descriptionBlock->scale(); - - switch (p->category_) - { - case common::Level3ProductCategory::Velocity: - edgeValue = static_cast((scale > 0.0f) ? (-offset / scale) : - -offset); - break; - - case common::Level3ProductCategory::DifferentialReflectivity: - edgeValue = static_cast(-offset); - break; - - case common::Level3ProductCategory::SpectrumWidth: - case common::Level3ProductCategory::SpecificDifferentialPhase: - edgeValue = 2; - break; - - case common::Level3ProductCategory::CorrelationCoefficient: - edgeValue = static_cast( - std::max(std::numeric_limits::max(), - descriptionBlock->number_of_levels())); - break; - - case common::Level3ProductCategory::Reflectivity: - case common::Level3ProductCategory::StormRelativeVelocity: - case common::Level3ProductCategory::VerticallyIntegratedLiquid: - case common::Level3ProductCategory::EchoTops: - case common::Level3ProductCategory::HydrometeorClassification: - case common::Level3ProductCategory::PrecipitationAccumulation: - default: - edgeValue = 0; - break; - } - - return edgeValue; -} - std::optional Level3ProductView::GetDataLevelCode(std::uint16_t level) const { diff --git a/scwx-qt/source/scwx/qt/view/level3_product_view.hpp b/scwx-qt/source/scwx/qt/view/level3_product_view.hpp index b5e043b3..e836c6e0 100644 --- a/scwx-qt/source/scwx/qt/view/level3_product_view.hpp +++ b/scwx-qt/source/scwx/qt/view/level3_product_view.hpp @@ -58,8 +58,6 @@ protected: void DisconnectRadarProductManager() override; void UpdateColorTableLut() override; - [[nodiscard]] std::uint8_t ComputeEdgeValue() const; - private: class Impl; std::unique_ptr p; diff --git a/scwx-qt/source/scwx/qt/view/level3_radial_view.cpp b/scwx-qt/source/scwx/qt/view/level3_radial_view.cpp index c01e0cd4..5611fdf5 100644 --- a/scwx-qt/source/scwx/qt/view/level3_radial_view.cpp +++ b/scwx-qt/source/scwx/qt/view/level3_radial_view.cpp @@ -39,16 +39,12 @@ public: vcp_ {}, sweepTime_ {} { + coordinates_.resize(kMaxCoordinates_); } ~Impl() { threadPool_.join(); }; void ComputeCoordinates( - const std::shared_ptr& radialData, - bool smoothingEnabled, - float gateSize); - - [[nodiscard]] inline std::uint8_t - RemapDataMoment(std::uint8_t dataMoment) const; + const std::shared_ptr& radialData); Level3RadialView* self_; @@ -57,17 +53,11 @@ public: std::vector coordinates_ {}; std::vector vertices_ {}; std::vector dataMoments8_ {}; - std::uint8_t edgeValue_ {}; - - bool showSmoothedRangeFolding_ {false}; std::shared_ptr lastRadialData_ {}; - bool lastShowSmoothedRangeFolding_ {false}; - bool lastSmoothingEnabled_ {false}; float latitude_; float longitude_; - std::optional elevation_ {}; float range_; std::uint16_t vcp_; @@ -92,11 +82,6 @@ boost::asio::thread_pool& Level3RadialView::thread_pool() return p->threadPool_; } -std::optional Level3RadialView::elevation() const -{ - return p->elevation_; -} - float Level3RadialView::range() const { return p->range_; @@ -132,7 +117,7 @@ std::tuple Level3RadialView::GetMomentData() const void Level3RadialView::ComputeSweep() { - logger_->trace("ComputeSweep()"); + logger_->debug("ComputeSweep()"); boost::timer::cpu_timer timer; @@ -140,9 +125,6 @@ void Level3RadialView::ComputeSweep() std::shared_ptr radarProductManager = radar_product_manager(); - const bool smoothingEnabled = smoothing_enabled(); - p->showSmoothedRangeFolding_ = show_smoothed_range_folding(); - const bool& showSmoothedRangeFolding = p->showSmoothedRangeFolding_; // Retrieve message from Radar Product Manager std::shared_ptr message; @@ -173,10 +155,7 @@ void Level3RadialView::ComputeSweep() Q_EMIT SweepNotComputed(types::NoUpdateReason::InvalidData); return; } - else if (gpm == graphic_product_message() && - smoothingEnabled == p->lastSmoothingEnabled_ && - (showSmoothedRangeFolding == p->lastShowSmoothedRangeFolding_ || - !smoothingEnabled)) + else if (gpm == graphic_product_message()) { // Skip if this is the message we previously processed Q_EMIT SweepNotComputed(types::NoUpdateReason::NoChange); @@ -184,9 +163,6 @@ void Level3RadialView::ComputeSweep() } set_graphic_product_message(gpm); - p->lastShowSmoothedRangeFolding_ = showSmoothedRangeFolding; - p->lastSmoothingEnabled_ = smoothingEnabled; - // A message with radial data should have a Product Description Block and // Product Symbology Block std::shared_ptr descriptionBlock = @@ -209,8 +185,6 @@ void Level3RadialView::ComputeSweep() return; } - logger_->debug("Computing Sweep"); - // A message with radial data should either have a Digital Radial Data // Array Packet, or a Radial Data Array Packet std::shared_ptr @@ -275,34 +249,27 @@ void Level3RadialView::ComputeSweep() } common::RadialSize radialSize; - if (radarProductManager->is_tdwr()) + if (radials == common::MAX_0_5_DEGREE_RADIALS) { - radialSize = common::RadialSize::NonStandard; + radialSize = common::RadialSize::_0_5Degree; + } + else if (radials == common::MAX_1_DEGREE_RADIALS) + { + radialSize = common::RadialSize::_1Degree; } else { - if (radials == common::MAX_0_5_DEGREE_RADIALS) - { - radialSize = common::RadialSize::_0_5Degree; - } - else if (radials == common::MAX_1_DEGREE_RADIALS) - { - radialSize = common::RadialSize::_1Degree; - } - else - { - radialSize = common::RadialSize::NonStandard; - } + radialSize = common::RadialSize::NonStandard; } const std::vector& coordinates = (radialSize == common::RadialSize::NonStandard) ? p->coordinates_ : - radarProductManager->coordinates(radialSize, smoothingEnabled); + radarProductManager->coordinates(radialSize); // There should be a positive number of range bins in radial data - const uint16_t numberOfDataMomentGates = radialData->number_of_range_bins(); - if (numberOfDataMomentGates < 1) + const uint16_t gates = radialData->number_of_range_bins(); + if (gates < 1) { logger_->warn("No range bins in radial data"); Q_EMIT SweepNotComputed(types::NoUpdateReason::InvalidData); @@ -312,10 +279,6 @@ void Level3RadialView::ComputeSweep() p->latitude_ = descriptionBlock->latitude_of_radar(); p->longitude_ = descriptionBlock->longitude_of_radar(); p->range_ = descriptionBlock->range(); - p->elevation_ = - descriptionBlock->has_elevation() ? - static_cast(descriptionBlock->elevation().value()) : - std::optional {}; p->sweepTime_ = scwx::util::TimePoint(descriptionBlock->volume_scan_date(), descriptionBlock->volume_scan_start_time() * 1000); @@ -328,33 +291,22 @@ void Level3RadialView::ComputeSweep() std::vector& vertices = p->vertices_; size_t vIndex = 0; vertices.clear(); - vertices.resize(radials * numberOfDataMomentGates * VERTICES_PER_BIN * - VALUES_PER_VERTEX); + vertices.resize(radials * gates * VERTICES_PER_BIN * VALUES_PER_VERTEX); // Setup data moment vector std::vector& dataMoments8 = p->dataMoments8_; size_t mIndex = 0; - dataMoments8.resize(radials * numberOfDataMomentGates * VERTICES_PER_BIN); + dataMoments8.resize(radials * gates * VERTICES_PER_BIN); // Compute threshold at which to display an individual bin const uint16_t snrThreshold = descriptionBlock->threshold(); - // Compute gate interval - const std::uint16_t dataMomentInterval = - descriptionBlock->x_resolution_raw(); - - // Get the gate length in meters. Use dataMomentInterval for NonStandard to - // avoid generating >1 base gates per bin. - const float gateLength = radialSize == common::RadialSize::NonStandard ? - static_cast(dataMomentInterval) : - radarProductManager->gate_size(); - // Determine which radial to start at std::uint16_t startRadial; if (radialSize == common::RadialSize::NonStandard) { - p->ComputeCoordinates(radialData, smoothingEnabled, gateLength); + p->ComputeCoordinates(radialData); startRadial = 0; } else @@ -364,101 +316,42 @@ void Level3RadialView::ComputeSweep() startRadial = std::lroundf(startAngle * radialMultiplier); } - // Compute gate size (number of base gates per bin) - const std::uint16_t gateSize = std::max( - 1, dataMomentInterval / static_cast(gateLength)); - - // Compute gate range [startGate, endGate) - std::uint16_t startGate = 0; - const std::uint16_t endGate = - std::min(startGate + numberOfDataMomentGates * gateSize, - common::MAX_DATA_MOMENT_GATES); - - if (smoothingEnabled) + for (uint16_t radial = 0; radial < radialData->number_of_radials(); radial++) { - // If smoothing is enabled, the start gate is incremented by one, as we - // are skipping the radar site origin. The end gate is unaffected, as - // we need to draw one less data point. - ++startGate; + const auto dataMomentsArray8 = radialData->level(radial); - // For most products other than reflectivity, the edge should not go to - // the bottom of the color table - p->edgeValue_ = ComputeEdgeValue(); - } + // Compute gate interval + const uint16_t dataMomentInterval = descriptionBlock->x_resolution_raw(); - for (std::uint16_t radial = 0; radial < radialData->number_of_radials(); - ++radial) - { - const auto& dataMomentsArray8 = radialData->level(radial); + // Compute gate size (number of base gates per bin) + const uint16_t gateSize = std::max( + 1, + dataMomentInterval / + static_cast(radarProductManager->gate_size())); - const std::uint16_t nextRadial = - (radial == radialData->number_of_radials() - 1) ? 0 : radial + 1; - const auto& nextDataMomentsArray8 = radialData->level(nextRadial); + // Compute gate range [startGate, endGate) + const uint16_t startGate = 0; + const uint16_t endGate = std::min( + startGate + gates * gateSize, common::MAX_DATA_MOMENT_GATES); - for (std::uint16_t gate = startGate, i = 0; gate + gateSize <= endGate; + for (uint16_t gate = startGate, i = 0; gate + gateSize <= endGate; gate += gateSize, ++i) { size_t vertexCount = (gate > 0) ? 6 : 3; - if (!smoothingEnabled) + // Store data moment value + uint8_t dataValue = + (i < dataMomentsArray8.size()) ? dataMomentsArray8[i] : 0; + if (dataValue < snrThreshold && dataValue != RANGE_FOLDED) { - // Store data moment value - const uint8_t dataValue = - (i < dataMomentsArray8.size()) ? dataMomentsArray8[i] : 0; - if (dataValue < snrThreshold && dataValue != RANGE_FOLDED) - { - continue; - } - - for (size_t m = 0; m < vertexCount; m++) - { - dataMoments8[mIndex++] = dataValue; - } - } - else if (gate > 0) - { - // Validate indices are all in range - if (i + 1 >= numberOfDataMomentGates) - { - continue; - } - - const std::uint8_t& dm1 = dataMomentsArray8[i]; - const std::uint8_t& dm2 = dataMomentsArray8[i + 1]; - const std::uint8_t& dm3 = nextDataMomentsArray8[i]; - const std::uint8_t& dm4 = nextDataMomentsArray8[i + 1]; - - if ((!showSmoothedRangeFolding && // - (dm1 < snrThreshold || dm1 == RANGE_FOLDED) && - (dm2 < snrThreshold || dm2 == RANGE_FOLDED) && - (dm3 < snrThreshold || dm3 == RANGE_FOLDED) && - (dm4 < snrThreshold || dm4 == RANGE_FOLDED)) || - (showSmoothedRangeFolding && // - dm1 < snrThreshold && dm1 != RANGE_FOLDED && - dm2 < snrThreshold && dm2 != RANGE_FOLDED && - dm3 < snrThreshold && dm3 != RANGE_FOLDED && - dm4 < snrThreshold && dm4 != RANGE_FOLDED)) - { - // Skip only if all data moments are hidden - continue; - } - - // The order must match the store vertices section below - dataMoments8[mIndex++] = p->RemapDataMoment(dm1); - dataMoments8[mIndex++] = p->RemapDataMoment(dm2); - dataMoments8[mIndex++] = p->RemapDataMoment(dm4); - dataMoments8[mIndex++] = p->RemapDataMoment(dm1); - dataMoments8[mIndex++] = p->RemapDataMoment(dm3); - dataMoments8[mIndex++] = p->RemapDataMoment(dm4); - } - else - { - // If smoothing is enabled, gate should never start at zero - // (radar site origin) - logger_->error("Smoothing enabled, gate should not start at zero"); continue; } + for (size_t m = 0; m < vertexCount; m++) + { + dataMoments8[mIndex++] = dataValue; + } + // Store vertices if (gate > 0) { @@ -481,17 +374,19 @@ void Level3RadialView::ComputeSweep() vertices[vIndex++] = coordinates[offset2]; vertices[vIndex++] = coordinates[offset2 + 1]; - vertices[vIndex++] = coordinates[offset4]; - vertices[vIndex++] = coordinates[offset4 + 1]; - - vertices[vIndex++] = coordinates[offset1]; - vertices[vIndex++] = coordinates[offset1 + 1]; + vertices[vIndex++] = coordinates[offset3]; + vertices[vIndex++] = coordinates[offset3 + 1]; vertices[vIndex++] = coordinates[offset3]; vertices[vIndex++] = coordinates[offset3 + 1]; vertices[vIndex++] = coordinates[offset4]; vertices[vIndex++] = coordinates[offset4 + 1]; + + vertices[vIndex++] = coordinates[offset2]; + vertices[vIndex++] = coordinates[offset2 + 1]; + + vertexCount = 6; } else { @@ -514,6 +409,8 @@ void Level3RadialView::ComputeSweep() vertices[vIndex++] = coordinates[offset2]; vertices[vIndex++] = coordinates[offset2 + 1]; + + vertexCount = 3; } } } @@ -531,24 +428,8 @@ void Level3RadialView::ComputeSweep() Q_EMIT SweepComputed(); } -std::uint8_t -Level3RadialView::Impl::RemapDataMoment(std::uint8_t dataMoment) const -{ - if (dataMoment != 0 && - (dataMoment != RANGE_FOLDED || showSmoothedRangeFolding_)) - { - return dataMoment; - } - else - { - return edgeValue_; - } -} - void Level3RadialView::Impl::ComputeCoordinates( - const std::shared_ptr& radialData, - bool smoothingEnabled, - float gateSize) + const std::shared_ptr& radialData) { logger_->debug("ComputeCoordinates()"); @@ -559,72 +440,51 @@ void Level3RadialView::Impl::ComputeCoordinates( auto radarProductManager = self_->radar_product_manager(); auto radarSite = radarProductManager->radar_site(); + const float gateSize = radarProductManager->gate_size(); const double radarLatitude = radarSite->latitude(); const double radarLongitude = radarSite->longitude(); // Calculate azimuth coordinates timer.start(); - coordinates_.resize(kMaxCoordinates_); - const std::uint16_t numRadials = radialData->number_of_radials(); const std::uint16_t numRangeBins = radialData->number_of_range_bins(); auto radials = boost::irange(0u, numRadials); auto gates = boost::irange(0u, numRangeBins); - const float gateRangeOffset = (smoothingEnabled) ? - // Center of the first gate is half the gate - // size distance from the radar site - 0.5f : - // Far end of the first gate is the gate - // size distance from the radar site - 1.0f; + std::for_each(std::execution::par_unseq, + radials.begin(), + radials.end(), + [&](std::uint32_t radial) + { + const float angle = radialData->start_angle(radial); - std::for_each( - std::execution::par_unseq, - radials.begin(), - radials.end(), - [&](std::uint32_t radial) - { - float angle = radialData->start_angle(radial); + std::for_each(std::execution::par_unseq, + gates.begin(), + gates.end(), + [&](std::uint32_t gate) + { + const std::uint32_t radialGate = + radial * common::MAX_DATA_MOMENT_GATES + + gate; + const float range = (gate + 1) * gateSize; + const std::size_t offset = radialGate * 2; - if (smoothingEnabled) - { - static constexpr float kDeltaAngleFactor = 0.5f; - angle += radialData->delta_angle(radial) * kDeltaAngleFactor; - } + double latitude; + double longitude; - std::for_each( - std::execution::par_unseq, - gates.begin(), - gates.end(), - [&](std::uint32_t gate) - { - const std::uint32_t radialGate = - radial * common::MAX_DATA_MOMENT_GATES + gate; - const float range = - (static_cast(gate) + gateRangeOffset) * gateSize; - const std::size_t offset = static_cast(radialGate) * 2; - if (offset + 1 >= coordinates_.size()) - { - return; - } + geodesic.Direct(radarLatitude, + radarLongitude, + angle, + range, + latitude, + longitude); - double latitude = 0.0; - double longitude = 0.0; - - geodesic.Direct(radarLatitude, - radarLongitude, - angle, - range, - latitude, - longitude); - - coordinates_[offset] = static_cast(latitude); - coordinates_[offset + 1] = static_cast(longitude); - }); - }); + coordinates_[offset] = latitude; + coordinates_[offset + 1] = longitude; + }); + }); timer.stop(); logger_->debug("Coordinates calculated in {}", timer.format(6, "%ws")); } diff --git a/scwx-qt/source/scwx/qt/view/level3_radial_view.hpp b/scwx-qt/source/scwx/qt/view/level3_radial_view.hpp index 86d550e6..f99f4e63 100644 --- a/scwx-qt/source/scwx/qt/view/level3_radial_view.hpp +++ b/scwx-qt/source/scwx/qt/view/level3_radial_view.hpp @@ -6,7 +6,11 @@ #include #include -namespace scwx::qt::view +namespace scwx +{ +namespace qt +{ +namespace view { class Level3RadialView : public Level3ProductView @@ -17,24 +21,17 @@ public: explicit Level3RadialView( const std::string& product, std::shared_ptr radarProductManager); - ~Level3RadialView() override; + ~Level3RadialView(); - Level3RadialView(const Level3RadialView&) = delete; - Level3RadialView(Level3RadialView&&) = delete; - Level3RadialView& operator=(const Level3RadialView&) = delete; - Level3RadialView& operator=(Level3RadialView&&) = delete; + float range() const override; + std::chrono::system_clock::time_point sweep_time() const override; + std::uint16_t vcp() const override; + const std::vector& vertices() const override; - [[nodiscard]] std::optional elevation() const override; - [[nodiscard]] float range() const override; - [[nodiscard]] std::chrono::system_clock::time_point - sweep_time() const override; - [[nodiscard]] std::uint16_t vcp() const override; - [[nodiscard]] const std::vector& vertices() const override; - - [[nodiscard]] std::tuple + std::tuple GetMomentData() const override; - [[nodiscard]] std::optional + std::optional GetBinLevel(const common::Coordinate& coordinate) const override; static std::shared_ptr @@ -52,4 +49,6 @@ private: std::unique_ptr p; }; -} // namespace scwx::qt::view +} // namespace view +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/view/level3_raster_view.cpp b/scwx-qt/source/scwx/qt/view/level3_raster_view.cpp index 3056cc03..fefeb587 100644 --- a/scwx-qt/source/scwx/qt/view/level3_raster_view.cpp +++ b/scwx-qt/source/scwx/qt/view/level3_raster_view.cpp @@ -33,20 +33,12 @@ public: } ~Level3RasterViewImpl() { threadPool_.join(); }; - [[nodiscard]] inline std::uint8_t - RemapDataMoment(std::uint8_t dataMoment) const; - boost::asio::thread_pool threadPool_ {1u}; - std::vector vertices_ {}; - std::vector dataMoments8_ {}; - std::uint8_t edgeValue_ {}; - - bool showSmoothedRangeFolding_ {false}; + std::vector vertices_; + std::vector dataMoments8_; std::shared_ptr lastRasterData_ {}; - bool lastShowSmoothedRangeFolding_ {false}; - bool lastSmoothingEnabled_ {false}; float latitude_; float longitude_; @@ -109,7 +101,7 @@ std::tuple Level3RasterView::GetMomentData() const void Level3RasterView::ComputeSweep() { - logger_->trace("ComputeSweep()"); + logger_->debug("ComputeSweep()"); boost::timer::cpu_timer timer; @@ -117,9 +109,6 @@ void Level3RasterView::ComputeSweep() std::shared_ptr radarProductManager = radar_product_manager(); - const bool smoothingEnabled = smoothing_enabled(); - p->showSmoothedRangeFolding_ = show_smoothed_range_folding(); - const bool& showSmoothedRangeFolding = p->showSmoothedRangeFolding_; // Retrieve message from Radar Product Manager std::shared_ptr message; @@ -150,10 +139,7 @@ void Level3RasterView::ComputeSweep() Q_EMIT SweepNotComputed(types::NoUpdateReason::InvalidData); return; } - else if (gpm == graphic_product_message() && - smoothingEnabled == p->lastSmoothingEnabled_ && - (showSmoothedRangeFolding == p->lastShowSmoothedRangeFolding_ || - !smoothingEnabled)) + else if (gpm == graphic_product_message()) { // Skip if this is the message we previously processed Q_EMIT SweepNotComputed(types::NoUpdateReason::NoChange); @@ -161,9 +147,6 @@ void Level3RasterView::ComputeSweep() } set_graphic_product_message(gpm); - p->lastShowSmoothedRangeFolding_ = showSmoothedRangeFolding; - p->lastSmoothingEnabled_ = smoothingEnabled; - // A message with radial data should have a Product Description Block and // Product Symbology Block std::shared_ptr descriptionBlock = @@ -186,8 +169,6 @@ void Level3RasterView::ComputeSweep() return; } - logger_->debug("Computing Sweep"); - // A message with raster data should have a Raster Data Packet std::shared_ptr rasterData = nullptr; @@ -248,18 +229,16 @@ void Level3RasterView::ComputeSweep() const GeographicLib::Geodesic& geodesic = util::GeographicLib::DefaultGeodesic(); - const std::uint16_t xResolution = descriptionBlock->x_resolution_raw(); - const std::uint16_t yResolution = descriptionBlock->y_resolution_raw(); - const double iCoordinate = + const uint16_t xResolution = descriptionBlock->x_resolution_raw(); + const uint16_t yResolution = descriptionBlock->y_resolution_raw(); + double iCoordinate = (-rasterData->i_coordinate_start() - 1.0 - p->range_) * 1000.0; - const double jCoordinate = + double jCoordinate = (rasterData->j_coordinate_start() + 1.0 + p->range_) * 1000.0; - const double xOffset = (smoothingEnabled) ? xResolution * 0.5 : 0.0; - const double yOffset = (smoothingEnabled) ? yResolution * 0.5 : 0.0; - const std::size_t numCoordinates = + size_t numCoordinates = static_cast(rows + 1) * static_cast(maxColumns + 1); - const auto coordinateRange = + auto coordinateRange = boost::irange(0, static_cast(numCoordinates)); std::vector coordinates; @@ -279,8 +258,8 @@ void Level3RasterView::ComputeSweep() const uint32_t col = index % (rows + 1); const uint32_t row = index / (rows + 1); - const double i = iCoordinate + xResolution * col + xOffset; - const double j = jCoordinate - yResolution * row - yOffset; + const double i = iCoordinate + xResolution * col; + const double j = jCoordinate - yResolution * row; // Calculate polar coordinates based on i and j const double angle = std::atan2(i, j) * 180.0 / M_PI; @@ -318,83 +297,25 @@ void Level3RasterView::ComputeSweep() // Compute threshold at which to display an individual bin const uint16_t snrThreshold = descriptionBlock->threshold(); - const std::size_t rowCount = (smoothingEnabled) ? - rasterData->number_of_rows() - 1 : - rasterData->number_of_rows(); - - if (smoothingEnabled) + for (size_t row = 0; row < rasterData->number_of_rows(); ++row) { - // For most products other than reflectivity, the edge should not go to - // the bottom of the color table - p->edgeValue_ = ComputeEdgeValue(); - } - - for (std::size_t row = 0; row < rowCount; ++row) - { - const std::size_t nextRow = - (row == static_cast(rasterData->number_of_rows() - 1)) ? - 0 : - row + 1; - - const auto& dataMomentsArray8 = + const auto dataMomentsArray8 = rasterData->level(static_cast(row)); - const auto& nextDataMomentsArray8 = - rasterData->level(static_cast(nextRow)); for (size_t bin = 0; bin < dataMomentsArray8.size(); ++bin) { - if (!smoothingEnabled) + constexpr size_t vertexCount = 6; + + // Store data moment value + uint8_t dataValue = dataMomentsArray8[bin]; + if (dataValue < snrThreshold && dataValue != RANGE_FOLDED) { - static constexpr std::size_t vertexCount = 6; - - // Store data moment value - const std::uint8_t& dataValue = dataMomentsArray8[bin]; - if (dataValue < snrThreshold && dataValue != RANGE_FOLDED) - { - continue; - } - - for (size_t m = 0; m < vertexCount; m++) - { - dataMoments8[mIndex++] = dataValue; - } + continue; } - else + + for (size_t m = 0; m < vertexCount; m++) { - // Validate indices are all in range - if (bin + 1 >= dataMomentsArray8.size() || - bin + 1 >= nextDataMomentsArray8.size()) - { - continue; - } - - const std::uint8_t& dm1 = dataMomentsArray8[bin]; - const std::uint8_t& dm2 = dataMomentsArray8[bin + 1]; - const std::uint8_t& dm3 = nextDataMomentsArray8[bin]; - const std::uint8_t& dm4 = nextDataMomentsArray8[bin + 1]; - - if ((!showSmoothedRangeFolding && // - (dm1 < snrThreshold || dm1 == RANGE_FOLDED) && - (dm2 < snrThreshold || dm2 == RANGE_FOLDED) && - (dm3 < snrThreshold || dm3 == RANGE_FOLDED) && - (dm4 < snrThreshold || dm4 == RANGE_FOLDED)) || - (showSmoothedRangeFolding && // - dm1 < snrThreshold && dm1 != RANGE_FOLDED && - dm2 < snrThreshold && dm2 != RANGE_FOLDED && - dm3 < snrThreshold && dm3 != RANGE_FOLDED && - dm4 < snrThreshold && dm4 != RANGE_FOLDED)) - { - // Skip only if all data moments are hidden - continue; - } - - // The order must match the store vertices section below - dataMoments8[mIndex++] = p->RemapDataMoment(dm1); - dataMoments8[mIndex++] = p->RemapDataMoment(dm2); - dataMoments8[mIndex++] = p->RemapDataMoment(dm4); - dataMoments8[mIndex++] = p->RemapDataMoment(dm1); - dataMoments8[mIndex++] = p->RemapDataMoment(dm3); - dataMoments8[mIndex++] = p->RemapDataMoment(dm4); + dataMoments8[mIndex++] = dataValue; } // Store vertices @@ -409,17 +330,17 @@ void Level3RasterView::ComputeSweep() vertices[vIndex++] = coordinates[offset2]; vertices[vIndex++] = coordinates[offset2 + 1]; - vertices[vIndex++] = coordinates[offset4]; - vertices[vIndex++] = coordinates[offset4 + 1]; - - vertices[vIndex++] = coordinates[offset1]; - vertices[vIndex++] = coordinates[offset1 + 1]; + vertices[vIndex++] = coordinates[offset3]; + vertices[vIndex++] = coordinates[offset3 + 1]; vertices[vIndex++] = coordinates[offset3]; vertices[vIndex++] = coordinates[offset3 + 1]; vertices[vIndex++] = coordinates[offset4]; vertices[vIndex++] = coordinates[offset4 + 1]; + + vertices[vIndex++] = coordinates[offset2]; + vertices[vIndex++] = coordinates[offset2 + 1]; } } vertices.resize(vIndex); @@ -436,20 +357,6 @@ void Level3RasterView::ComputeSweep() Q_EMIT SweepComputed(); } -std::uint8_t -Level3RasterViewImpl::RemapDataMoment(std::uint8_t dataMoment) const -{ - if (dataMoment != 0 && - (dataMoment != RANGE_FOLDED || showSmoothedRangeFolding_)) - { - return dataMoment; - } - else - { - return edgeValue_; - } -} - std::optional Level3RasterView::GetBinLevel(const common::Coordinate& coordinate) const { diff --git a/scwx-qt/source/scwx/qt/view/overlay_product_view.cpp b/scwx-qt/source/scwx/qt/view/overlay_product_view.cpp index ccc41b9d..c33494c2 100644 --- a/scwx-qt/source/scwx/qt/view/overlay_product_view.cpp +++ b/scwx-qt/source/scwx/qt/view/overlay_product_view.cpp @@ -116,9 +116,8 @@ void OverlayProductView::Impl::ConnectRadarProductManager() radarProductManager_.get(), &manager::RadarProductManager::NewDataAvailable, self_, - [this](common::RadarProductGroup group, - const std::string& product, - bool /*isChunks*/, + [this](common::RadarProductGroup group, + const std::string& product, std::chrono::system_clock::time_point latestTime) { if (autoRefreshEnabled_ && @@ -187,7 +186,7 @@ void OverlayProductView::Impl::LoadProduct( header.date_of_message(), header.time_of_message() * 1000); // If the record is from the last 30 minutes - if (productTime + 30min >= scwx::util::time::now() || + if (productTime + 30min >= std::chrono::system_clock::now() || (selectedTime_ != std::chrono::system_clock::time_point {} && productTime + 30min >= selectedTime_)) { diff --git a/scwx-qt/source/scwx/qt/view/radar_product_view.cpp b/scwx-qt/source/scwx/qt/view/radar_product_view.cpp index dc50383c..e2ca6c21 100644 --- a/scwx-qt/source/scwx/qt/view/radar_product_view.cpp +++ b/scwx-qt/source/scwx/qt/view/radar_product_view.cpp @@ -1,5 +1,4 @@ #include -#include #include #include @@ -29,44 +28,26 @@ class RadarProductViewImpl { public: explicit RadarProductViewImpl( - RadarProductView* self, std::shared_ptr radarProductManager) : - self_ {self}, initialized_ {false}, sweepMutex_ {}, selectedTime_ {}, radarProductManager_ {radarProductManager} { - auto& productSettings = settings::ProductSettings::Instance(); - connection_ = productSettings.changed_signal().connect( - [this]() - { - showSmoothedRangeFolding_ = settings::ProductSettings::Instance() - .show_smoothed_range_folding() - .GetValue(); - self_->Update(); - }); - ; } ~RadarProductViewImpl() {} - RadarProductView* self_; - bool initialized_; std::mutex sweepMutex_; std::chrono::system_clock::time_point selectedTime_; - bool showSmoothedRangeFolding_ {false}; - bool smoothingEnabled_ {false}; std::shared_ptr radarProductManager_; - - boost::signals2::scoped_connection connection_; }; RadarProductView::RadarProductView( std::shared_ptr radarProductManager) : - p(std::make_unique(this, radarProductManager)) {}; + p(std::make_unique(radarProductManager)) {}; RadarProductView::~RadarProductView() = default; const std::vector& @@ -85,9 +66,9 @@ std::uint16_t RadarProductView::color_table_max() const return kDefaultColorTableMax_; } -std::optional RadarProductView::elevation() const +float RadarProductView::elevation() const { - return {}; + return 0.0f; } std::shared_ptr @@ -106,16 +87,6 @@ std::chrono::system_clock::time_point RadarProductView::selected_time() const return p->selectedTime_; } -bool RadarProductView::show_smoothed_range_folding() const -{ - return p->showSmoothedRangeFolding_; -} - -bool RadarProductView::smoothing_enabled() const -{ - return p->smoothingEnabled_; -} - std::chrono::system_clock::time_point RadarProductView::sweep_time() const { return {}; @@ -134,11 +105,6 @@ void RadarProductView::set_radar_product_manager( ConnectRadarProductManager(); } -void RadarProductView::set_smoothing_enabled(bool smoothingEnabled) -{ - p->smoothingEnabled_ = smoothingEnabled; -} - void RadarProductView::Initialize() { ComputeSweep(); diff --git a/scwx-qt/source/scwx/qt/view/radar_product_view.hpp b/scwx-qt/source/scwx/qt/view/radar_product_view.hpp index 2801b74e..c695a9e5 100644 --- a/scwx-qt/source/scwx/qt/view/radar_product_view.hpp +++ b/scwx-qt/source/scwx/qt/view/radar_product_view.hpp @@ -16,7 +16,11 @@ #include #include -namespace scwx::qt::view +namespace scwx +{ +namespace qt +{ +namespace view { class RadarProductViewImpl; @@ -28,38 +32,27 @@ class RadarProductView : public QObject public: explicit RadarProductView( std::shared_ptr radarProductManager); - ~RadarProductView() override; + virtual ~RadarProductView(); - RadarProductView(const RadarProductView&) = delete; - RadarProductView(RadarProductView&&) = delete; - RadarProductView& operator=(const RadarProductView&) = delete; - RadarProductView& operator=(RadarProductView&&) = delete; + virtual std::shared_ptr color_table() const = 0; + virtual const std::vector& + color_table_lut() const; + virtual std::uint16_t color_table_min() const; + virtual std::uint16_t color_table_max() const; + virtual float elevation() const; + virtual float range() const; + virtual std::chrono::system_clock::time_point sweep_time() const; + virtual float unit_scale() const = 0; + virtual std::string units() const = 0; + virtual std::uint16_t vcp() const = 0; + virtual const std::vector& vertices() const = 0; - [[nodiscard]] virtual std::shared_ptr - color_table() const = 0; - [[nodiscard]] virtual const std::vector& - color_table_lut() const; - [[nodiscard]] virtual std::uint16_t color_table_min() const; - [[nodiscard]] virtual std::uint16_t color_table_max() const; - [[nodiscard]] virtual std::optional elevation() const; - [[nodiscard]] virtual float range() const; - [[nodiscard]] virtual std::chrono::system_clock::time_point - sweep_time() const; - [[nodiscard]] virtual float unit_scale() const = 0; - [[nodiscard]] virtual std::string units() const = 0; - [[nodiscard]] virtual std::uint16_t vcp() const = 0; - [[nodiscard]] virtual const std::vector& vertices() const = 0; - - [[nodiscard]] std::shared_ptr - radar_product_manager() const; - [[nodiscard]] std::chrono::system_clock::time_point selected_time() const; - [[nodiscard]] bool show_smoothed_range_folding() const; - [[nodiscard]] bool smoothing_enabled() const; - [[nodiscard]] std::mutex& sweep_mutex(); + std::shared_ptr radar_product_manager() const; + std::chrono::system_clock::time_point selected_time() const; + std::mutex& sweep_mutex(); void set_radar_product_manager( std::shared_ptr radarProductManager); - void set_smoothing_enabled(bool smoothingEnabled); void Initialize(); virtual void @@ -69,26 +62,24 @@ public: void SelectTime(std::chrono::system_clock::time_point time); void Update(); - [[nodiscard]] bool IsInitialized() const; + bool IsInitialized() const; - [[nodiscard]] virtual common::RadarProductGroup - GetRadarProductGroup() const = 0; - [[nodiscard]] virtual std::string GetRadarProductName() const = 0; - [[nodiscard]] virtual std::vector GetElevationCuts() const; - [[nodiscard]] virtual std::tuple + virtual common::RadarProductGroup GetRadarProductGroup() const = 0; + virtual std::string GetRadarProductName() const = 0; + virtual std::vector GetElevationCuts() const; + virtual std::tuple GetMomentData() const = 0; - [[nodiscard]] virtual std::tuple + virtual std::tuple GetCfpMomentData() const; - [[nodiscard]] virtual std::optional + virtual std::optional GetBinLevel(const common::Coordinate& coordinate) const = 0; - [[nodiscard]] virtual std::optional - GetDataLevelCode(std::uint16_t level) const = 0; - [[nodiscard]] virtual std::optional - GetDataValue(std::uint16_t level) const = 0; - [[nodiscard]] virtual bool IgnoreUnits() const; + virtual std::optional + GetDataLevelCode(std::uint16_t level) const = 0; + virtual std::optional GetDataValue(std::uint16_t level) const = 0; + virtual bool IgnoreUnits() const; - [[nodiscard]] virtual std::vector> + virtual std::vector> GetDescriptionFields() const; protected: @@ -110,4 +101,6 @@ private: std::unique_ptr p; }; -} // namespace scwx::qt::view +} // namespace view +} // namespace qt +} // namespace scwx diff --git a/setup-debug.bat b/setup-debug.bat new file mode 100644 index 00000000..7ad46d78 --- /dev/null +++ b/setup-debug.bat @@ -0,0 +1,12 @@ +call tools\setup-common.bat + +set build_dir=build-debug +set build_type=Debug +set qt_version=6.7.2 + +mkdir %build_dir% +cmake -B %build_dir% -S . ^ + -DCMAKE_BUILD_TYPE=%build_type% ^ + -DCMAKE_CONFIGURATION_TYPES=%build_type% ^ + -DCMAKE_PREFIX_PATH=C:/Qt/%qt_version%/msvc2019_64 +pause diff --git a/setup-debug.sh b/setup-debug.sh new file mode 100755 index 00000000..87067a3b --- /dev/null +++ b/setup-debug.sh @@ -0,0 +1,15 @@ +#!/bin/bash +./tools/setup-common.sh + +build_dir=${1:-build-debug} +build_type=Debug +qt_version=6.7.2 +script_dir="$(dirname "$(readlink -f "$0")")" + +mkdir -p ${build_dir} +cmake -B ${build_dir} -S . \ + -DCMAKE_BUILD_TYPE=${build_type} \ + -DCMAKE_CONFIGURATION_TYPES=${build_type} \ + -DCMAKE_INSTALL_PREFIX=${build_dir}/${build_type}/supercell-wx \ + -DCMAKE_PREFIX_PATH=/opt/Qt/${qt_version}/gcc_64 \ + -G Ninja diff --git a/setup-release.bat b/setup-release.bat new file mode 100644 index 00000000..3c08d78d --- /dev/null +++ b/setup-release.bat @@ -0,0 +1,12 @@ +call tools\setup-common.bat + +set build_dir=build-release +set build_type=Release +set qt_version=6.7.2 + +mkdir %build_dir% +cmake -B %build_dir% -S . ^ + -DCMAKE_BUILD_TYPE=%build_type% ^ + -DCMAKE_CONFIGURATION_TYPES=%build_type% ^ + -DCMAKE_PREFIX_PATH=C:/Qt/%qt_version%/msvc2019_64 +pause diff --git a/setup-release.sh b/setup-release.sh new file mode 100755 index 00000000..6d81ff8f --- /dev/null +++ b/setup-release.sh @@ -0,0 +1,15 @@ +#!/bin/bash +./tools/setup-common.sh + +build_dir=${1:-build-release} +build_type=Release +qt_version=6.7.2 +script_dir="$(dirname "$(readlink -f "$0")")" + +mkdir -p ${build_dir} +cmake -B ${build_dir} -S . \ + -DCMAKE_BUILD_TYPE=${build_type} \ + -DCMAKE_CONFIGURATION_TYPES=${build_type} \ + -DCMAKE_INSTALL_PREFIX=${build_dir}/${build_type}/supercell-wx \ + -DCMAKE_PREFIX_PATH=/opt/Qt/${qt_version}/gcc_64 \ + -G Ninja diff --git a/test/.clang-tidy b/test/.clang-tidy deleted file mode 100644 index 254b44ad..00000000 --- a/test/.clang-tidy +++ /dev/null @@ -1,20 +0,0 @@ -Checks: - - '-*' - - 'bugprone-*' - - 'clang-analyzer-*' - - 'cppcoreguidelines-*' - - 'misc-*' - - 'modernize-*' - - 'performance-*' - - '-bugprone-easily-swappable-parameters' - - '-cppcoreguidelines-avoid-magic-numbers' - - '-cppcoreguidelines-avoid-do-while' - - '-cppcoreguidelines-avoid-non-const-global-variables' - - '-cppcoreguidelines-pro-type-reinterpret-cast' - - '-cppcoreguidelines-pro-type-union-access' - - '-misc-include-cleaner' - - '-misc-non-private-member-variables-in-classes' - - '-misc-use-anonymous-namespace' - - '-modernize-return-braced-init-list' - - '-modernize-use-trailing-return-type' -FormatStyle: 'file' diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b5428d86..d1db7851 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.24) +cmake_minimum_required(VERSION 3.20) set_property(DIRECTORY APPEND diff --git a/test/data b/test/data index c68bee74..5a91ded6 160000 --- a/test/data +++ b/test/data @@ -1 +1 @@ -Subproject commit c68bee74549963e9a02e0fa998efad0f10f8256b +Subproject commit 5a91ded677d4032b0de9370ed767a16708c0ecff diff --git a/test/source/scwx/awips/wmo_header.test.cpp b/test/source/scwx/awips/wmo_header.test.cpp deleted file mode 100644 index 17cd9706..00000000 --- a/test/source/scwx/awips/wmo_header.test.cpp +++ /dev/null @@ -1,130 +0,0 @@ -#include - -#include - -namespace scwx::awips -{ - -static const std::string logPrefix_ = "scwx::awips::wmo_header.test"; - -static const std::string kWmoHeaderSample_ { - "887\n" - "WFUS54 KOUN 280044\n" - "TOROUN"}; - -TEST(WmoHeader, WmoFields) -{ - std::stringstream ss {kWmoHeaderSample_}; - WmoHeader header; - const bool valid = header.Parse(ss); - - EXPECT_EQ(valid, true); - EXPECT_EQ(header.sequence_number(), "887"); - EXPECT_EQ(header.data_type(), "WF"); - EXPECT_EQ(header.geographic_designator(), "US"); - EXPECT_EQ(header.bulletin_id(), "54"); - EXPECT_EQ(header.icao(), "KOUN"); - EXPECT_EQ(header.date_time(), "280044"); - EXPECT_EQ(header.bbb_indicator(), ""); - EXPECT_EQ(header.product_category(), "TOR"); - EXPECT_EQ(header.product_designator(), "OUN"); - EXPECT_EQ(header.GetDateTime(), - std::chrono::sys_time {}); -} - -TEST(WmoHeader, DateHintBeforeParse) -{ - using namespace std::chrono; - - std::stringstream ss {kWmoHeaderSample_}; - WmoHeader header; - - header.SetDateHint(2022y / October); - const bool valid = header.Parse(ss); - - EXPECT_EQ(valid, true); - EXPECT_EQ(header.GetDateTime(), - sys_days {2022y / October / 28d} + 0h + 44min); -} - -TEST(WmoHeader, DateHintAfterParse) -{ - using namespace std::chrono; - - std::stringstream ss {kWmoHeaderSample_}; - WmoHeader header; - - const bool valid = header.Parse(ss); - header.SetDateHint(2022y / October); - - EXPECT_EQ(valid, true); - EXPECT_EQ(header.GetDateTime(), - sys_days {2022y / October / 28d} + 0h + 44min); -} - -TEST(WmoHeader, EndTimeHintSameMonth) -{ - using namespace std::chrono; - - std::stringstream ss {kWmoHeaderSample_}; - WmoHeader header; - - const bool valid = header.Parse(ss); - - auto endTimeHint = sys_days {2022y / October / 29d} + 0h + 0min + 0s; - - EXPECT_EQ(valid, true); - EXPECT_EQ(header.GetDateTime(endTimeHint), - sys_days {2022y / October / 28d} + 0h + 44min); -} - -TEST(WmoHeader, EndTimeHintPreviousMonth) -{ - using namespace std::chrono; - - std::stringstream ss {kWmoHeaderSample_}; - WmoHeader header; - - const bool valid = header.Parse(ss); - - auto endTimeHint = sys_days {2022y / October / 27d} + 0h + 0min + 0s; - - EXPECT_EQ(valid, true); - EXPECT_EQ(header.GetDateTime(endTimeHint), - sys_days {2022y / September / 28d} + 0h + 44min); -} - -TEST(WmoHeader, EndTimeHintPreviousYear) -{ - using namespace std::chrono; - - std::stringstream ss {kWmoHeaderSample_}; - WmoHeader header; - - const bool valid = header.Parse(ss); - - auto endTimeHint = sys_days {2022y / January / 27d} + 0h + 0min + 0s; - - EXPECT_EQ(valid, true); - EXPECT_EQ(header.GetDateTime(endTimeHint), - sys_days {2021y / December / 28d} + 0h + 44min); -} - -TEST(WmoHeader, EndTimeHintIgnored) -{ - using namespace std::chrono; - - std::stringstream ss {kWmoHeaderSample_}; - WmoHeader header; - - header.SetDateHint(2022y / October); - const bool valid = header.Parse(ss); - - auto endTimeHint = sys_days {2020y / January / 1d} + 0h + 0min + 0s; - - EXPECT_EQ(valid, true); - EXPECT_EQ(header.GetDateTime(endTimeHint), - sys_days {2022y / October / 28d} + 0h + 44min); -} - -} // namespace scwx::awips diff --git a/test/source/scwx/common/products.test.cpp b/test/source/scwx/common/products.test.cpp index bec8a29b..5b945bf3 100644 --- a/test/source/scwx/common/products.test.cpp +++ b/test/source/scwx/common/products.test.cpp @@ -1,7 +1,6 @@ #include #include -#include namespace scwx { diff --git a/test/source/scwx/network/ntp_client.test.cpp b/test/source/scwx/network/ntp_client.test.cpp deleted file mode 100644 index 1450b324..00000000 --- a/test/source/scwx/network/ntp_client.test.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include - -#include - -namespace scwx::network -{ - -TEST(NtpClient, Poll) -{ - NtpClient client {}; - - const std::string firstServer = client.RotateServer(); - std::string currentServer = firstServer; - std::string lastServer = firstServer; - bool error = false; - - do - { - client.RunOnce(); - error = client.error(); - - EXPECT_EQ(error, false); - - // Loop until the current server repeats the first server, or fails to - // rotate - lastServer = currentServer; - currentServer = client.RotateServer(); - } while (currentServer != firstServer && currentServer != lastServer && - !error); -} - -} // namespace scwx::network diff --git a/test/source/scwx/provider/iem_api_provider.test.cpp b/test/source/scwx/provider/iem_api_provider.test.cpp deleted file mode 100644 index e3e25669..00000000 --- a/test/source/scwx/provider/iem_api_provider.test.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include - -#include - -namespace scwx::provider -{ - -TEST(IemApiProviderTest, ListTextProducts) -{ - using namespace std::chrono; - using sys_days = time_point; - - auto date = sys_days {2023y / March / 25d}; - - auto torProducts = IemApiProvider::ListTextProducts(date, {}, "TOR"); - - ASSERT_EQ(torProducts.has_value(), true); - EXPECT_EQ(torProducts.value().size(), 35); - - if (torProducts.value().size() >= 1) - { - EXPECT_EQ(torProducts.value().at(0).productId_, - "202303250016-KMEG-WFUS54-TORMEG"); - } - if (torProducts.value().size() >= 35) - { - EXPECT_EQ(torProducts.value().at(34).productId_, - "202303252015-KFFC-WFUS52-TORFFC"); - } -} - -TEST(IemApiProviderTest, LoadTextProducts) -{ - static const std::vector productIds { - "202303250016-KMEG-WFUS54-TORMEG", - "202303252015-KFFC-WFUS52-TORFFC", - "202303311942-KLZK-WWUS54-SVSLZK"}; - - auto textProducts = IemApiProvider::LoadTextProducts(productIds); - - EXPECT_EQ(textProducts.size(), 3); - - if (textProducts.size() >= 1) - { - EXPECT_EQ(textProducts.at(0)->message_count(), 1); - } - if (textProducts.size() >= 2) - { - EXPECT_EQ(textProducts.at(1)->message_count(), 1); - } - if (textProducts.size() >= 3) - { - EXPECT_EQ(textProducts.at(2)->message_count(), 2); - } -} - -} // namespace scwx::provider diff --git a/test/source/scwx/provider/warnings_provider.test.cpp b/test/source/scwx/provider/warnings_provider.test.cpp index c1c824da..78ef9b95 100644 --- a/test/source/scwx/provider/warnings_provider.test.cpp +++ b/test/source/scwx/provider/warnings_provider.test.cpp @@ -13,27 +13,53 @@ static const std::string& kAlternateUrl {"https://warnings.cod.edu"}; class WarningsProviderTest : public testing::TestWithParam { }; +TEST_P(WarningsProviderTest, ListFiles) +{ + WarningsProvider provider(GetParam()); + + auto [newObjects, totalObjects] = provider.ListFiles(); + + // No objects, skip test + if (totalObjects == 0) + { + GTEST_SKIP(); + } + + EXPECT_GT(newObjects, 0); + EXPECT_GT(totalObjects, 0); + EXPECT_EQ(newObjects, totalObjects); +} TEST_P(WarningsProviderTest, LoadUpdatedFiles) { WarningsProvider provider(GetParam()); - const std::chrono::sys_time now = - std::chrono::floor(std::chrono::system_clock::now()); - const std::chrono::sys_time startTime = - now - std::chrono::days {3}; - - auto updatedFiles = provider.LoadUpdatedFiles(startTime); + auto [newObjects, totalObjects] = provider.ListFiles(); + auto updatedFiles = provider.LoadUpdatedFiles(); // No objects, skip test - if (updatedFiles.empty()) + if (totalObjects == 0) { GTEST_SKIP(); } - EXPECT_GT(updatedFiles.size(), 0); + EXPECT_GT(newObjects, 0); + EXPECT_GT(totalObjects, 0); + EXPECT_EQ(newObjects, totalObjects); + EXPECT_EQ(updatedFiles.size(), newObjects); - auto updatedFiles2 = provider.LoadUpdatedFiles(); + auto [newObjects2, totalObjects2] = provider.ListFiles(); + auto updatedFiles2 = provider.LoadUpdatedFiles(); + + // There should be no more than 2 updated warnings files since the last query + // (assumption that the previous newest file was updated, and a new file was + // created on the hour) + EXPECT_LE(newObjects2, 2); + EXPECT_EQ(updatedFiles2.size(), newObjects2); + + // The total number of objects may have changed, since the oldest file could + // have dropped off the list + EXPECT_GT(totalObjects2, 0); } INSTANTIATE_TEST_SUITE_P(WarningsProvider, diff --git a/test/source/scwx/qt/model/marker_model.test.cpp b/test/source/scwx/qt/model/marker_model.test.cpp deleted file mode 100644 index 74ad28a9..00000000 --- a/test/source/scwx/qt/model/marker_model.test.cpp +++ /dev/null @@ -1,269 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -namespace scwx -{ -namespace qt -{ -namespace model -{ - -static const std::string EMPTY_MARKERS_FILE = - std::string(SCWX_TEST_DATA_DIR) + "/json/markers/markers-empty.json"; -static const std::string TEMP_MARKERS_FILE = - std::string(SCWX_TEST_DATA_DIR) + "/json/markers/markers-temp.json"; -static const std::string ONE_MARKERS_FILE = - std::string(SCWX_TEST_DATA_DIR) + "/json/markers/markers-one.json"; -static const std::string FIVE_MARKERS_FILE = - std::string(SCWX_TEST_DATA_DIR) + "/json/markers/markers-five.json"; -static const std::string PART1_MARKER_FILE = - std::string(SCWX_TEST_DATA_DIR) + "/json/markers/markers-part1.json"; - -static std::mutex initializedMutex {}; -static std::condition_variable initializedCond {}; -static bool initialized; - -static const boost::gil::rgba8_pixel_t defaultIconColor = - util::color::ToRgba8PixelT("#ffff0000"); -static const std::string defaultIconName = "images/location-marker"; - -void CompareFiles(const std::string& file1, const std::string& file2) -{ - std::ifstream ifs1 {file1}; - std::stringstream buffer1; - buffer1 << ifs1.rdbuf(); - - std::ifstream ifs2 {file2}; - std::stringstream buffer2; - buffer2 << ifs2.rdbuf(); - - EXPECT_EQ(buffer1.str(), buffer2.str()); -} - -void CopyFile(const std::string& from, const std::string& to) -{ - std::filesystem::copy_file(from, to); - CompareFiles(from, to); -} - -using TestFunction = void(std::shared_ptr, - MarkerModel&); - -void RunTest(const std::string& filename, TestFunction testFunction) -{ - { - main::Application::ResetInitilization(); - MarkerModel model = MarkerModel(); - std::shared_ptr manager = - manager::MarkerManager::Instance(); - - manager->set_marker_settings_path(TEMP_MARKERS_FILE); - - initialized = false; - QObject::connect(manager.get(), - &manager::MarkerManager::MarkersInitialized, - []() - { - std::unique_lock lock(initializedMutex); - initialized = true; - initializedCond.notify_all(); - }); - - main::Application::FinishInitialization(); - - std::unique_lock lock(initializedMutex); - while (!initialized) - { - initializedCond.wait(lock); - } - // This is not jank - model.HandleMarkersInitialized(manager->marker_count()); - - testFunction(manager, model); - } - - EXPECT_EQ(std::filesystem::exists(TEMP_MARKERS_FILE), true); - - CompareFiles(TEMP_MARKERS_FILE, filename); -} - -TEST(MarkerModelTest, CreateJson) -{ - // Verify file doesn't exist prior to test start - EXPECT_EQ(std::filesystem::exists(TEMP_MARKERS_FILE), false); - - RunTest(EMPTY_MARKERS_FILE, - [](std::shared_ptr, MarkerModel&) {}); - - std::filesystem::remove(TEMP_MARKERS_FILE); - EXPECT_EQ(std::filesystem::exists(TEMP_MARKERS_FILE), false); -} - -TEST(MarkerModelTest, LoadEmpty) -{ - CopyFile(EMPTY_MARKERS_FILE, TEMP_MARKERS_FILE); - - RunTest(EMPTY_MARKERS_FILE, - [](std::shared_ptr, MarkerModel&) {}); - - std::filesystem::remove(TEMP_MARKERS_FILE); - EXPECT_EQ(std::filesystem::exists(TEMP_MARKERS_FILE), false); -} - -TEST(MarkerModelTest, AddRemove) -{ - CopyFile(EMPTY_MARKERS_FILE, TEMP_MARKERS_FILE); - - RunTest(ONE_MARKERS_FILE, - [](std::shared_ptr manager, MarkerModel&) - { - manager->add_marker(types::MarkerInfo( - "Null", 0, 0, defaultIconName, defaultIconColor)); - }); - RunTest( - EMPTY_MARKERS_FILE, - [](std::shared_ptr manager, MarkerModel& model) - { - std::optional id = model.getId(0); - EXPECT_TRUE(id); - if (id) - { - manager->remove_marker(*id); - } - }); - - std::filesystem::remove(TEMP_MARKERS_FILE); - EXPECT_EQ(std::filesystem::exists(TEMP_MARKERS_FILE), false); -} - -TEST(MarkerModelTest, AddFive) -{ - CopyFile(EMPTY_MARKERS_FILE, TEMP_MARKERS_FILE); - - RunTest(FIVE_MARKERS_FILE, - [](std::shared_ptr manager, MarkerModel&) - { - manager->add_marker(types::MarkerInfo( - "Null", 0, 0, defaultIconName, defaultIconColor)); - manager->add_marker(types::MarkerInfo( - "North", 90, 0, defaultIconName, defaultIconColor)); - manager->add_marker(types::MarkerInfo( - "South", -90, 0, defaultIconName, defaultIconColor)); - manager->add_marker(types::MarkerInfo( - "East", 0, 90, defaultIconName, defaultIconColor)); - manager->add_marker(types::MarkerInfo( - "West", 0, -90, defaultIconName, defaultIconColor)); - }); - - std::filesystem::remove(TEMP_MARKERS_FILE); - EXPECT_EQ(std::filesystem::exists(TEMP_MARKERS_FILE), false); -} - -TEST(MarkerModelTest, AddFour) -{ - CopyFile(ONE_MARKERS_FILE, TEMP_MARKERS_FILE); - - RunTest(FIVE_MARKERS_FILE, - [](std::shared_ptr manager, MarkerModel&) - { - manager->add_marker(types::MarkerInfo( - "North", 90, 0, defaultIconName, defaultIconColor)); - manager->add_marker(types::MarkerInfo( - "South", -90, 0, defaultIconName, defaultIconColor)); - manager->add_marker(types::MarkerInfo( - "East", 0, 90, defaultIconName, defaultIconColor)); - manager->add_marker(types::MarkerInfo( - "West", 0, -90, defaultIconName, defaultIconColor)); - }); - - std::filesystem::remove(TEMP_MARKERS_FILE); - EXPECT_EQ(std::filesystem::exists(TEMP_MARKERS_FILE), false); -} - -TEST(MarkerModelTest, RemoveFive) -{ - CopyFile(FIVE_MARKERS_FILE, TEMP_MARKERS_FILE); - - RunTest( - EMPTY_MARKERS_FILE, - [](std::shared_ptr manager, MarkerModel& model) - { - std::optional id; - id = model.getId(4); - EXPECT_TRUE(id); - manager->remove_marker(*id); - - id = model.getId(3); - EXPECT_TRUE(id); - manager->remove_marker(*id); - - id = model.getId(2); - EXPECT_TRUE(id); - manager->remove_marker(*id); - - id = model.getId(1); - EXPECT_TRUE(id); - manager->remove_marker(*id); - - id = model.getId(0); - EXPECT_TRUE(id); - manager->remove_marker(*id); - }); - - std::filesystem::remove(TEMP_MARKERS_FILE); - EXPECT_EQ(std::filesystem::exists(TEMP_MARKERS_FILE), false); -} - -TEST(MarkerModelTest, RemoveFour) -{ - CopyFile(FIVE_MARKERS_FILE, TEMP_MARKERS_FILE); - - RunTest( - ONE_MARKERS_FILE, - [](std::shared_ptr manager, MarkerModel& model) - { - std::optional id; - id = model.getId(4); - EXPECT_TRUE(id); - manager->remove_marker(*id); - - id = model.getId(3); - EXPECT_TRUE(id); - manager->remove_marker(*id); - - id = model.getId(2); - EXPECT_TRUE(id); - manager->remove_marker(*id); - - id = model.getId(1); - EXPECT_TRUE(id); - manager->remove_marker(*id); - }); - - std::filesystem::remove(TEMP_MARKERS_FILE); - EXPECT_EQ(std::filesystem::exists(TEMP_MARKERS_FILE), false); -} - -TEST(MarkerModelTest, UpdateFromPart1) -{ - CopyFile(PART1_MARKER_FILE, TEMP_MARKERS_FILE); - - RunTest(ONE_MARKERS_FILE, - [](std::shared_ptr, MarkerModel&) {}); - - std::filesystem::remove(TEMP_MARKERS_FILE); - EXPECT_EQ(std::filesystem::exists(TEMP_MARKERS_FILE), false); -} - -} // namespace model -} // namespace qt -} // namespace scwx diff --git a/test/source/scwx/qt/util/network.test.cpp b/test/source/scwx/qt/util/network.test.cpp deleted file mode 100644 index 21524d0c..00000000 --- a/test/source/scwx/qt/util/network.test.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#include - -#include - - - -namespace scwx -{ -namespace qt -{ -namespace util -{ - -const std::vector> testUrls = { - {" https://example.com/path/to+a+test/file.txt ", - "https://example.com/path/to+a+test/file.txt"}, - {"\thttps://example.com/path/to+a+test/file.txt\t", - "https://example.com/path/to+a+test/file.txt"}, - {"\nhttps://example.com/path/to+a+test/file.txt\n", - "https://example.com/path/to+a+test/file.txt"}, - {"\rhttps://example.com/path/to+a+test/file.txt\r", - "https://example.com/path/to+a+test/file.txt"}, - {"\r\nhttps://example.com/path/to+a+test/file.txt\r\n", - "https://example.com/path/to+a+test/file.txt"}, - {" https://example.com/path/to+a+test/file.txt ", - "https://example.com/path/to+a+test/file.txt"}, - {" \nhttps://example.com/path/to+a+test/file.txt \n ", - "https://example.com/path/to+a+test/file.txt"}, - - // Only tested for this OS because NormalizeUrl uses native separators -#ifdef _WIN32 - {" C:\\path\\to a test\\file.txt ", "C:\\path\\to a test\\file.txt"}, - {"\tC:\\path\\to a test\\file.txt\t", "C:\\path\\to a test\\file.txt"}, - {"\nC:\\path\\to a test\\file.txt\n", "C:\\path\\to a test\\file.txt"}, - {"\rC:\\path\\to a test\\file.txt\r", "C:\\path\\to a test\\file.txt"}, - {"\r\nC:\\path\\to a test\\file.txt\r\n", "C:\\path\\to a test\\file.txt"}, - {" C:\\path\\to a test\\file.txt ", "C:\\path\\to a test\\file.txt"}, - {" \nC:\\path\\to a test\\file.txt \n ", - "C:\\path\\to a test\\file.txt"}, - - {" C:/path/to a test/file.txt ", "C:\\path\\to a test\\file.txt"}, - {"\tC:/path/to a test/file.txt\t", "C:\\path\\to a test\\file.txt"}, - {"\nC:/path/to a test/file.txt\n", "C:\\path\\to a test\\file.txt"}, - {"\rC:/path/to a test/file.txt\r", "C:\\path\\to a test\\file.txt"}, - {"\r\nC:/path/to a test/file.txt\r\n", "C:\\path\\to a test\\file.txt"}, - {" C:/path/to a test/file.txt ", "C:\\path\\to a test\\file.txt"}, - {" \nC:/path/to a test/file.txt \n ", "C:\\path\\to a test\\file.txt"}, -#else - - {" /path/to a test/file.txt ", "/path/to a test/file.txt"}, - {"\t/path/to a test/file.txt\t", "/path/to a test/file.txt"}, - {"\n/path/to a test/file.txt\n", "/path/to a test/file.txt"}, - {"\r/path/to a test/file.txt\r", "/path/to a test/file.txt"}, - {"\r\n/path/to a test/file.txt\r\n", "/path/to a test/file.txt"}, - {" /path/to a test/file.txt ", "/path/to a test/file.txt"}, - {" \n/path/to a test/file.txt \n ", "/path/to a test/file.txt"}, -#endif -}; - -TEST(network, NormalizeUrl) -{ - for (auto& pair : testUrls) - { - const std::string& preNormalized = pair.first; - const std::string& expNormalized = pair.second; - - std::string normalized = network::NormalizeUrl(preNormalized); - EXPECT_EQ(normalized, expNormalized); - } - -} - - -} // namespace util -} // namespace qt -} // namespace scwx diff --git a/test/test.cmake b/test/test.cmake index 57fbc37e..b3cfedd2 100644 --- a/test/test.cmake +++ b/test/test.cmake @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.24) +cmake_minimum_required(VERSION 3.20) project(scwx-test CXX) include(GoogleTest) @@ -12,29 +12,24 @@ set(SRC_AWIPS_TESTS source/scwx/awips/coded_location.test.cpp source/scwx/awips/coded_time_motion_location.test.cpp source/scwx/awips/pvtec.test.cpp source/scwx/awips/text_product_file.test.cpp - source/scwx/awips/ugc.test.cpp - source/scwx/awips/wmo_header.test.cpp) + source/scwx/awips/ugc.test.cpp) set(SRC_COMMON_TESTS source/scwx/common/color_table.test.cpp source/scwx/common/products.test.cpp) set(SRC_GR_TESTS source/scwx/gr/placefile.test.cpp) -set(SRC_NETWORK_TESTS source/scwx/network/dir_list.test.cpp - source/scwx/network/ntp_client.test.cpp) +set(SRC_NETWORK_TESTS source/scwx/network/dir_list.test.cpp) set(SRC_PROVIDER_TESTS source/scwx/provider/aws_level2_data_provider.test.cpp source/scwx/provider/aws_level3_data_provider.test.cpp - source/scwx/provider/iem_api_provider.test.cpp source/scwx/provider/warnings_provider.test.cpp) set(SRC_QT_CONFIG_TESTS source/scwx/qt/config/county_database.test.cpp source/scwx/qt/config/radar_site.test.cpp) set(SRC_QT_MANAGER_TESTS source/scwx/qt/manager/settings_manager.test.cpp source/scwx/qt/manager/update_manager.test.cpp) set(SRC_QT_MAP_TESTS source/scwx/qt/map/map_provider.test.cpp) -set(SRC_QT_MODEL_TESTS source/scwx/qt/model/imgui_context_model.test.cpp - source/scwx/qt/model/marker_model.test.cpp) +set(SRC_QT_MODEL_TESTS source/scwx/qt/model/imgui_context_model.test.cpp) set(SRC_QT_SETTINGS_TESTS source/scwx/qt/settings/settings_container.test.cpp source/scwx/qt/settings/settings_variable.test.cpp) set(SRC_QT_UTIL_TESTS source/scwx/qt/util/q_file_input_stream.test.cpp - source/scwx/qt/util/geographic_lib.test.cpp - source/scwx/qt/util/network.test.cpp) + source/scwx/qt/util/geographic_lib.test.cpp) set(SRC_UTIL_TESTS source/scwx/util/float.test.cpp source/scwx/util/rangebuf.test.cpp source/scwx/util/streams.test.cpp diff --git a/tools/aqt-settings.ini b/tools/aqt-settings.ini deleted file mode 100644 index 9d20e0a2..00000000 --- a/tools/aqt-settings.ini +++ /dev/null @@ -1,17 +0,0 @@ -[aqt] -# Using this mirror instead of download.qt.io because of timeouts in CI -# Below is the default URL of the mirror -# baseurl: https://download.qt.io -baseurl: https://qt.mirror.constant.com - -[requests] -# Mirrors require sha1 instead of sha256 -hash_algorithm: sha1 - -[mirrors] -trusted_mirrors: - https://qt.mirror.constant.com -fallbacks: - https://qt.mirror.constant.com - https://mirrors.ocf.berkeley.edu - https://download.qt.io diff --git a/tools/conan/profiles/scwx-linux_clang-17 b/tools/conan/profiles/scwx-linux_clang-17 deleted file mode 100644 index 3ce71b57..00000000 --- a/tools/conan/profiles/scwx-linux_clang-17 +++ /dev/null @@ -1,8 +0,0 @@ -[settings] -arch=x86_64 -build_type=Release -compiler=clang -compiler.cppstd=20 -compiler.libcxx=libstdc++11 -compiler.version=17 -os=Linux diff --git a/tools/conan/profiles/scwx-linux_clang-17_armv8 b/tools/conan/profiles/scwx-linux_clang-17_armv8 deleted file mode 100644 index 21ab5248..00000000 --- a/tools/conan/profiles/scwx-linux_clang-17_armv8 +++ /dev/null @@ -1,8 +0,0 @@ -[settings] -arch=armv8 -build_type=Release -compiler=clang -compiler.cppstd=20 -compiler.libcxx=libstdc++11 -compiler.version=17 -os=Linux diff --git a/tools/conan/profiles/scwx-linux_clang-18 b/tools/conan/profiles/scwx-linux_clang-18 deleted file mode 100644 index ea19016b..00000000 --- a/tools/conan/profiles/scwx-linux_clang-18 +++ /dev/null @@ -1,8 +0,0 @@ -[settings] -arch=x86_64 -build_type=Release -compiler=clang -compiler.cppstd=20 -compiler.libcxx=libstdc++11 -compiler.version=18 -os=Linux diff --git a/tools/conan/profiles/scwx-linux_clang-18_armv8 b/tools/conan/profiles/scwx-linux_clang-18_armv8 deleted file mode 100644 index 8c567fd4..00000000 --- a/tools/conan/profiles/scwx-linux_clang-18_armv8 +++ /dev/null @@ -1,8 +0,0 @@ -[settings] -arch=armv8 -build_type=Release -compiler=clang -compiler.cppstd=20 -compiler.libcxx=libstdc++11 -compiler.version=18 -os=Linux diff --git a/tools/conan/profiles/scwx-linux_gcc-11 b/tools/conan/profiles/scwx-linux_gcc-11 deleted file mode 100644 index d0d52fc9..00000000 --- a/tools/conan/profiles/scwx-linux_gcc-11 +++ /dev/null @@ -1,8 +0,0 @@ -[settings] -arch=x86_64 -build_type=Release -compiler=gcc -compiler.cppstd=20 -compiler.libcxx=libstdc++11 -compiler.version=11 -os=Linux diff --git a/tools/conan/profiles/scwx-linux_gcc-11_armv8 b/tools/conan/profiles/scwx-linux_gcc-11_armv8 deleted file mode 100644 index 803d1c8d..00000000 --- a/tools/conan/profiles/scwx-linux_gcc-11_armv8 +++ /dev/null @@ -1,8 +0,0 @@ -[settings] -arch=armv8 -build_type=Release -compiler=gcc -compiler.cppstd=20 -compiler.libcxx=libstdc++11 -compiler.version=11 -os=Linux diff --git a/tools/conan/profiles/scwx-linux_gcc-12 b/tools/conan/profiles/scwx-linux_gcc-12 deleted file mode 100644 index 06f8e0bc..00000000 --- a/tools/conan/profiles/scwx-linux_gcc-12 +++ /dev/null @@ -1,8 +0,0 @@ -[settings] -arch=x86_64 -build_type=Release -compiler=gcc -compiler.cppstd=20 -compiler.libcxx=libstdc++11 -compiler.version=12 -os=Linux diff --git a/tools/conan/profiles/scwx-linux_gcc-12_armv8 b/tools/conan/profiles/scwx-linux_gcc-12_armv8 deleted file mode 100644 index 0a540c20..00000000 --- a/tools/conan/profiles/scwx-linux_gcc-12_armv8 +++ /dev/null @@ -1,8 +0,0 @@ -[settings] -arch=armv8 -build_type=Release -compiler=gcc -compiler.cppstd=20 -compiler.libcxx=libstdc++11 -compiler.version=12 -os=Linux diff --git a/tools/conan/profiles/scwx-linux_gcc-13 b/tools/conan/profiles/scwx-linux_gcc-13 deleted file mode 100644 index 25ad5988..00000000 --- a/tools/conan/profiles/scwx-linux_gcc-13 +++ /dev/null @@ -1,8 +0,0 @@ -[settings] -arch=x86_64 -build_type=Release -compiler=gcc -compiler.cppstd=20 -compiler.libcxx=libstdc++11 -compiler.version=13 -os=Linux diff --git a/tools/conan/profiles/scwx-linux_gcc-13_armv8 b/tools/conan/profiles/scwx-linux_gcc-13_armv8 deleted file mode 100644 index 7e0c0c66..00000000 --- a/tools/conan/profiles/scwx-linux_gcc-13_armv8 +++ /dev/null @@ -1,8 +0,0 @@ -[settings] -arch=armv8 -build_type=Release -compiler=gcc -compiler.cppstd=20 -compiler.libcxx=libstdc++11 -compiler.version=13 -os=Linux diff --git a/tools/conan/profiles/scwx-linux_gcc-14 b/tools/conan/profiles/scwx-linux_gcc-14 deleted file mode 100644 index a315550a..00000000 --- a/tools/conan/profiles/scwx-linux_gcc-14 +++ /dev/null @@ -1,8 +0,0 @@ -[settings] -arch=x86_64 -build_type=Release -compiler=gcc -compiler.cppstd=20 -compiler.libcxx=libstdc++11 -compiler.version=14 -os=Linux diff --git a/tools/conan/profiles/scwx-linux_gcc-14_armv8 b/tools/conan/profiles/scwx-linux_gcc-14_armv8 deleted file mode 100644 index 1b95e2bb..00000000 --- a/tools/conan/profiles/scwx-linux_gcc-14_armv8 +++ /dev/null @@ -1,8 +0,0 @@ -[settings] -arch=armv8 -build_type=Release -compiler=gcc -compiler.cppstd=20 -compiler.libcxx=libstdc++11 -compiler.version=14 -os=Linux diff --git a/tools/conan/profiles/scwx-macos_clang-18 b/tools/conan/profiles/scwx-macos_clang-18 deleted file mode 100644 index f7a5b0ce..00000000 --- a/tools/conan/profiles/scwx-macos_clang-18 +++ /dev/null @@ -1,9 +0,0 @@ -[settings] -arch=x86_64 -build_type=Release -compiler=clang -compiler.cppstd=20 -compiler.libcxx=libc++ -compiler.version=18 -os=Macos -os.version=12.0 diff --git a/tools/conan/profiles/scwx-macos_clang-18_armv8 b/tools/conan/profiles/scwx-macos_clang-18_armv8 deleted file mode 100644 index 65d9afd4..00000000 --- a/tools/conan/profiles/scwx-macos_clang-18_armv8 +++ /dev/null @@ -1,9 +0,0 @@ -[settings] -arch=armv8 -build_type=Release -compiler=clang -compiler.cppstd=20 -compiler.libcxx=libc++ -compiler.version=18 -os=Macos -os.version=12.0 diff --git a/tools/conan/profiles/scwx-windows_msvc2022_x64 b/tools/conan/profiles/scwx-windows_msvc2022_x64 deleted file mode 100644 index 072e4933..00000000 --- a/tools/conan/profiles/scwx-windows_msvc2022_x64 +++ /dev/null @@ -1,8 +0,0 @@ -[settings] -arch=x86_64 -build_type=Release -compiler=msvc -compiler.cppstd=20 -compiler.runtime=dynamic -compiler.version=194 -os=Windows diff --git a/tools/configure-environment.bat b/tools/configure-environment.bat deleted file mode 100644 index bf9118a4..00000000 --- a/tools/configure-environment.bat +++ /dev/null @@ -1,61 +0,0 @@ -@setlocal enabledelayedexpansion - -@set script_dir=%~dp0 -@set venv_path=%script_dir%\..\.venv - -:: Assign user-specified Python Virtual Environment -@if not "%~1"=="" ( - if /i "%~1"=="none" ( - set venv_path= - ) else ( - set venv_path=%~f1 - ) -) - -:: Activate Python Virtual Environment -@if defined venv_path ( - echo Activating Python Virtual Environment: %venv_path% - python -m venv %venv_path% - call %venv_path%\Scripts\activate.bat -) - -:: Install Python packages -python -m pip install --upgrade pip -pip install --upgrade -r "%script_dir%\..\requirements.txt" - -:: Configure default Conan profile -@conan profile detect -e - -:: Conan profiles -@set profile_count=1 -@set /a last_profile=profile_count - 1 -@set conan_profile[0]=scwx-windows_msvc2022_x64 - -:: Install Conan profiles -@for /L %%i in (0,1,!last_profile!) do @( - :: Install the base profile - set "profile_name=!conan_profile[%%i]!" - set "profile_path=%script_dir%\conan\profiles\!profile_name!" - conan config install "!profile_path!" -tf profiles - - :: Create debug profile in temp directory - set "debug_profile_name=!profile_name!-debug" - set "debug_profile_path=%TEMP%\!debug_profile_name!" - copy "!profile_path!" "!debug_profile_path!" >nul - - :: Replace build_type=Release with build_type=Debug - powershell -Command "(Get-Content '!debug_profile_path!') -replace 'build_type=Release', 'build_type=Debug' | Set-Content '!debug_profile_path!'" - - :: Install the debug profile - conan config install "!debug_profile_path!" -tf profiles - - :: Remove temporary debug profile - del "!debug_profile_path!" -) - -:: Deactivate Python Virtual Environment -@if defined venv_path ( - call %venv_path%\Scripts\deactivate.bat -) - -@pause diff --git a/tools/configure-environment.sh b/tools/configure-environment.sh deleted file mode 100755 index f88ef504..00000000 --- a/tools/configure-environment.sh +++ /dev/null @@ -1,98 +0,0 @@ -#!/bin/bash -script_source="${BASH_SOURCE[0]:-$0}" -script_dir="$(cd "$(dirname "${script_source}")" && pwd)" - -# Assign user-specified Python Virtual Environment -if [ "${1:-}" = "none" ]; then - unset venv_path -else - venv_arg="${1:-${script_dir}/../.venv}" - # Portable way to get absolute path without requiring the directory to exist - case "${venv_arg}" in - /*) venv_path="${venv_arg}" ;; - *) venv_path="$(cd "$(dirname "${venv_arg}")" && pwd)/$(basename "${venv_arg}")" ;; - esac - export venv_path -fi - -# Load custom build settings -if [ -f "${script_dir}/lib/user-setup.sh" ]; then - source "${script_dir}/lib/user-setup.sh" -fi - -# Activate Python Virtual Environment -if [ -n "${venv_path:-}" ]; then - python3 -m venv "${venv_path}" - source "${venv_path}/bin/activate" -fi - -# Detect if a Python Virtual Environment was specified above, or elsewhere -IN_VENV=$(python3 -c 'import sys; print(sys.prefix != getattr(sys, "base_prefix", sys.prefix))') - -if [ "${IN_VENV}" = "True" ]; then - # In a virtual environment, don't use --user - PIP_FLAGS="--upgrade" -else - # Not in a virtual environment, use --user - PIP_FLAGS="--upgrade --user" -fi - -# Install Python packages -python3 -m pip install ${PIP_FLAGS} --upgrade pip -python3 -m pip install ${PIP_FLAGS} -r "${script_dir}/../requirements.txt" - -# Configure default Conan profile -conan profile detect -e - -# Conan profiles -if [[ "$(uname)" == "Darwin" ]]; then - # macOS profiles - conan_profiles=( - "scwx-macos_clang-18" - "scwx-macos_clang-18_armv8" - ) -else - # Linux profiles - conan_profiles=( - "scwx-linux_clang-17" - "scwx-linux_clang-17_armv8" - "scwx-linux_clang-18" - "scwx-linux_clang-18_armv8" - "scwx-linux_gcc-11" - "scwx-linux_gcc-11_armv8" - "scwx-linux_gcc-12" - "scwx-linux_gcc-12_armv8" - "scwx-linux_gcc-13" - "scwx-linux_gcc-13_armv8" - "scwx-linux_gcc-14" - "scwx-linux_gcc-14_armv8" - ) -fi - -# Install Conan profiles -for profile_name in "${conan_profiles[@]}"; do - # Install original profile - conan config install "${script_dir}/conan/profiles/${profile_name}" -tf profiles - - # Create debug profile in temp directory - debug_profile="/tmp/${profile_name}-debug" - cp "${script_dir}/conan/profiles/${profile_name}" "${debug_profile}" - - # Replace build_type=Release with build_type=Debug - if [[ "$(uname)" == "Darwin" ]]; then - sed -i '' 's/build_type=Release/build_type=Debug/g' "${debug_profile}" - else - sed -i 's/build_type=Release/build_type=Debug/g' "${debug_profile}" - fi - - # Install the debug profile - conan config install "${debug_profile}" -tf profiles - - # Remove temporary debug profile - rm "${debug_profile}" -done - -# Deactivate Python Virtual Environment -if [ -n "${venv_path:-}" ]; then - deactivate -fi diff --git a/tools/lib/common-paths.bat b/tools/lib/common-paths.bat deleted file mode 100644 index 8cd0cb60..00000000 --- a/tools/lib/common-paths.bat +++ /dev/null @@ -1 +0,0 @@ -@set qt_version=6.9.2 diff --git a/tools/lib/common-paths.sh b/tools/lib/common-paths.sh deleted file mode 100755 index aadbe417..00000000 --- a/tools/lib/common-paths.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -export qt_version=6.9.2 diff --git a/tools/lib/run-cmake-configure.bat b/tools/lib/run-cmake-configure.bat deleted file mode 100644 index 424bcc34..00000000 --- a/tools/lib/run-cmake-configure.bat +++ /dev/null @@ -1,24 +0,0 @@ -@set script_dir=%~dp0 - -@set cmake_args=-B "%build_dir%" -S "%script_dir%\..\.." ^ - -G "%generator%" ^ - -DCMAKE_PREFIX_PATH="%qt_base%/%qt_version%/%qt_arch%" ^ - -DCMAKE_PROJECT_TOP_LEVEL_INCLUDES="%script_dir%\..\..\external\cmake-conan\conan_provider.cmake" ^ - -DCONAN_HOST_PROFILE=%conan_profile% ^ - -DCONAN_BUILD_PROFILE=%conan_profile% ^ - -DSCWX_VIRTUAL_ENV=%venv_path% ^ - -DCMAKE_EXPORT_COMPILE_COMMANDS=on - -@if defined build_type ( - set cmake_args=%cmake_args% ^ - -DCMAKE_BUILD_TYPE=%build_type% ^ - -DCMAKE_CONFIGURATION_TYPES=%build_type% -) else ( - :: CMAKE_BUILD_TYPE isn't used to build, but is required by the Conan CMakeDeps generator - set cmake_args=%cmake_args% ^ - -DCMAKE_BUILD_TYPE=Release ^ - -DCMAKE_CONFIGURATION_TYPES=Debug;Release -) - -@mkdir "%build_dir%" -cmake %cmake_args% diff --git a/tools/lib/run-cmake-configure.sh b/tools/lib/run-cmake-configure.sh deleted file mode 100755 index 03bbcdb1..00000000 --- a/tools/lib/run-cmake-configure.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash -script_source="${BASH_SOURCE[0]:-$0}" -script_dir="$(cd "$(dirname "${script_source}")" && pwd)" - -cmake_args=( - -B "${build_dir}" - -S "${script_dir}/../.." - -G "${generator}" - -DCMAKE_PREFIX_PATH="${qt_base}/${qt_version}/${qt_arch}" - -DCMAKE_PROJECT_TOP_LEVEL_INCLUDES="${script_dir}/../../external/cmake-conan/conan_provider.cmake" - -DCONAN_HOST_PROFILE="${conan_profile}" - -DCONAN_BUILD_PROFILE="${conan_profile}" - -DSCWX_VIRTUAL_ENV="${venv_path}" - -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -) - -if [[ -n "${build_type}" ]]; then - cmake_args+=( - -DCMAKE_BUILD_TYPE="${build_type}" - -DCMAKE_CONFIGURATION_TYPES="${build_type}" - -DCMAKE_INSTALL_PREFIX="${build_dir}/${build_type}/supercell-wx" - ) -else - # CMAKE_BUILD_TYPE isn't used to build, but is required by the Conan CMakeDeps generator - cmake_args+=( - -DCMAKE_BUILD_TYPE="Release" - -DCMAKE_CONFIGURATION_TYPES="Debug;Release" - ) -fi - -# Toggle address sanitizer based on argument -if [ "${address_sanitizer}" != "disabled" ]; then - cmake_args+=( - -DSCWX_ADDRESS_SANITIZER=ON - ) -else - cmake_args+=( - -DSCWX_ADDRESS_SANITIZER=OFF - ) -fi - -mkdir -p "${build_dir}" -cmake "${cmake_args[@]}" diff --git a/tools/lib/setup-common.bat b/tools/lib/setup-common.bat deleted file mode 100644 index 9ba510c2..00000000 --- a/tools/lib/setup-common.bat +++ /dev/null @@ -1,39 +0,0 @@ -@set script_dir=%~dp0 - -:: Import common paths -@call %script_dir%\common-paths.bat - -:: Activate Python Virtual Environment -@if defined venv_path ( - echo Activating Python Virtual Environment: %venv_path% - python -m venv %venv_path% - call %venv_path%\Scripts\activate.bat -) - -:: Install Python packages -python -m pip install --upgrade pip -pip install --upgrade -r "%script_dir%\..\..\requirements.txt" - -@if defined build_type ( - :: Install Conan profile and packages - call %script_dir%\setup-conan.bat -) else ( - :: Install Conan profile and debug packages - set build_type=Debug - call %script_dir%\setup-conan.bat - - :: Install Conan profile and release packages - set build_type=Release - call %script_dir%\setup-conan.bat - - :: Unset build_type - set build_type= -) - -:: Run CMake Configure -@call %script_dir%\run-cmake-configure.bat - -:: Deactivate Python Virtual Environment -@if defined venv_path ( - call %venv_path%\Scripts\deactivate.bat -) diff --git a/tools/lib/setup-common.sh b/tools/lib/setup-common.sh deleted file mode 100755 index b11270e8..00000000 --- a/tools/lib/setup-common.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/bash -script_source="${BASH_SOURCE[0]:-$0}" -script_dir="$(cd "$(dirname "${script_source}")" && pwd)" - -# Import common paths -source "${script_dir}/common-paths.sh" - -# Load custom build settings -if [ -f "${script_dir}/user-setup.sh" ]; then - source "${script_dir}/user-setup.sh" -fi - -# Activate python3 Virtual Environment -if [ -n "${venv_path:-}" ]; then - python3 -m venv "${venv_path}" - source "${venv_path}/bin/activate" -fi - -# Detect if a python3 Virtual Environment was specified above, or elsewhere -IN_VENV=$(python3 -c 'import sys; print(sys.prefix != getattr(sys, "base_prefix", sys.prefix))') - -if [ "${IN_VENV}" = "True" ]; then - # In a virtual environment, don't use --user - PIP_FLAGS="--upgrade" -else - # Not in a virtual environment, use --user - PIP_FLAGS="--upgrade --user" -fi - -# Install python3 packages -python3 -m pip install ${PIP_FLAGS} pip -python3 -m pip install ${PIP_FLAGS} -r "${script_dir}/../../requirements.txt" - -if [[ -n "${build_type}" ]]; then - # Install Conan profile and packages - "${script_dir}/setup-conan.sh" -else - # Install Conan profile and debug packages - export build_type=Debug - "${script_dir}/setup-conan.sh" - - # Install Conan profile and release packages - export build_type=Release - "${script_dir}/setup-conan.sh" - - # Unset build_type - unset build_type -fi - -# Run CMake Configure -"${script_dir}/run-cmake-configure.sh" - -# Deactivate python3 Virtual Environment -if [ -n "${venv_path:-}" ]; then - deactivate -fi diff --git a/tools/lib/setup-conan.bat b/tools/lib/setup-conan.bat deleted file mode 100644 index e3f4f444..00000000 --- a/tools/lib/setup-conan.bat +++ /dev/null @@ -1,15 +0,0 @@ -@set script_dir=%~dp0 - -:: Configure default Conan profile -conan profile detect -e - -:: Install selected Conan profile -conan config install "%script_dir%\..\conan\profiles\%conan_profile%" -tf profiles - -:: Install Conan packages -conan install "%script_dir%\..\.." ^ - --remote conancenter ^ - --build missing ^ - --profile:all %conan_profile% ^ - --settings:all build_type=%build_type% ^ - --output-folder "%build_dir%\conan" diff --git a/tools/lib/setup-conan.sh b/tools/lib/setup-conan.sh deleted file mode 100755 index 0b6c5004..00000000 --- a/tools/lib/setup-conan.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash -script_source="${BASH_SOURCE[0]:-$0}" -script_dir="$(cd "$(dirname "${script_source}")" && pwd)" - -# Configure default Conan profile -conan profile detect -e - -# Install selected Conan profile -conan config install "${script_dir}/../conan/profiles/${conan_profile}" -tf profiles - -# Install Conan packages -conan install "${script_dir}/../.." \ - --remote conancenter \ - --build missing \ - --profile:all ${conan_profile} \ - --settings:all build_type=${build_type} \ - --output-folder "${build_dir}/conan" diff --git a/tools/lib/user-setup.example.sh b/tools/lib/user-setup.example.sh deleted file mode 100644 index 5ea76d24..00000000 --- a/tools/lib/user-setup.example.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -# Example user setup script. Copy as user-setup.sh and modify as required. - -# gcc-13 is not the default gcc version -export CC=/usr/bin/gcc-13 -export CXX=/usr/bin/c++-13 - -# Override conan profile to be gcc-13 -export conan_profile=scwx-linux_gcc-13 diff --git a/tools/net.supercellwx.app.yml b/tools/net.supercellwx.app.yml deleted file mode 100644 index 762edf28..00000000 --- a/tools/net.supercellwx.app.yml +++ /dev/null @@ -1,37 +0,0 @@ -id: net.supercellwx.app -version: '0.5.1' -runtime: "org.freedesktop.Platform" -runtime-version: "23.08" -sdk: "org.freedesktop.Sdk" -command: supercell-wx -modules: - - name: supercell-wx - buildsystem: simple - build-commands: - - install -Dm644 net.supercellwx.app.desktop /app/share/applications/${FLATPAK_ID}.desktop - - install -Dm644 scwx-256.png /app/share/icons/hicolor/256x256/apps/net.supercellwx.app.png - - install -Dm644 scwx-64.png /app/share/icons/hicolor/64x64/apps/net.supercellwx.app.png - - rm net.supercellwx.app.desktop scwx-256.png scwx-64.png - - cp -r * /app/ - sources: - - type: dir - path: ../../supercell-wx-flatpak - - type: file - path: ../scwx-qt/res/linux/net.supercellwx.app.desktop - - type: file - path: ../scwx-qt/res/icons/scwx-256.png - - type: file - path: ../scwx-qt/res/icons/scwx-64.png - -finish-args: - # X11 + XShm access - - --share=ipc - - --socket=fallback-x11 - # Wayland access - - --socket=wayland - # GPU acceleration if needed - - --device=all - # Needs to talk to the network: - - --share=network - # Needs to save files locally - - --filesystem=xdg-documents diff --git a/tools/scwx_config.cmake b/tools/scwx_config.cmake deleted file mode 100644 index 93205f90..00000000 --- a/tools/scwx_config.cmake +++ /dev/null @@ -1,58 +0,0 @@ -macro(scwx_output_dirs_setup) - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin) - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR}/Release/bin) - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/bin) - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_CURRENT_BINARY_DIR}/MinSizeRel/bin) - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR}/Debug/bin) - - set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib) - set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR}/Release/lib) - set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/lib) - set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_CURRENT_BINARY_DIR}/MinSizeRel/lib) - set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR}/Debug/lib) - - set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib) - set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR}/Release/lib) - set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/lib) - set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_CURRENT_BINARY_DIR}/MinSizeRel/lib) - set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR}/Debug/lib) -endmacro() - -macro(scwx_python_setup) - set(SCWX_VIRTUAL_ENV "" CACHE STRING "Python Virtual Environment") - - # Use a Python Virtual Environment - if (SCWX_VIRTUAL_ENV) - set(ENV{VIRTUAL_ENV} "${SCWX_VIRTUAL_ENV}") - - if (WIN32) - set(Python3_EXECUTABLE "$ENV{VIRTUAL_ENV}/Scripts/python.exe") - else() - set(Python3_EXECUTABLE "$ENV{VIRTUAL_ENV}/bin/python") - endif() - - # Add virtual environment to program search paths - set(CMAKE_PROGRAM_PATH "$ENV{VIRTUAL_ENV}/bin" ${CMAKE_PROGRAM_PATH}) - - message(STATUS "Using virtual environment: $ENV{VIRTUAL_ENV}") - else() - message(STATUS "Python virtual environment undefined") - endif() - - # Find Python - find_package(Python3 REQUIRED COMPONENTS Interpreter) - - # Verify we're using the right Python - message(STATUS "Python executable: ${Python3_EXECUTABLE}") - message(STATUS "Python version: ${Python3_VERSION}") - - # Only if we are in an application defined virtual environment - if (SCWX_VIRTUAL_ENV) - # Setup pip - set(PIP_ARGS install --upgrade -r "${CMAKE_SOURCE_DIR}/requirements.txt") - - # Install requirements - execute_process(COMMAND ${Python3_EXECUTABLE} -m pip ${PIP_ARGS} - RESULT_VARIABLE PIP_RESULT) - endif() -endmacro() diff --git a/tools/setup-common.bat b/tools/setup-common.bat new file mode 100644 index 00000000..8362be70 --- /dev/null +++ b/tools/setup-common.bat @@ -0,0 +1,4 @@ +pip install --upgrade "conan<2.0" +pip install --upgrade geopandas +pip install --upgrade GitPython +conan profile new default --detect diff --git a/tools/setup-common.sh b/tools/setup-common.sh new file mode 100755 index 00000000..d2c61d5a --- /dev/null +++ b/tools/setup-common.sh @@ -0,0 +1,5 @@ +#!/bin/bash +pip install --upgrade --user "conan<2.0" +pip install --upgrade --user geopandas +pip install --upgrade --user GitPython +conan profile new default --detect diff --git a/tools/setup-linux-ninja-debug.sh b/tools/setup-linux-ninja-debug.sh deleted file mode 100755 index 9b896d40..00000000 --- a/tools/setup-linux-ninja-debug.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash -script_dir="$(dirname "$(readlink -f "$0")")" - -export build_dir="$(readlink -f "${1:-${script_dir}/../build-debug}")" -export build_type=Debug -export conan_profile=${2:-scwx-linux_gcc-11} -export generator=Ninja -export qt_base=/opt/Qt -export qt_arch=gcc_64 -export address_sanitizer=${4:-disabled} - -# Assign user-specified Python Virtual Environment -[ "${3:-}" = "none" ] && unset venv_path || export venv_path="$(readlink -f "${3:-${script_dir}/../.venv}")" - -# Perform common setup -"${script_dir}/lib/setup-common.sh" diff --git a/tools/setup-linux-ninja-multi.sh b/tools/setup-linux-ninja-multi.sh deleted file mode 100755 index 85bb9a97..00000000 --- a/tools/setup-linux-ninja-multi.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash -script_dir="$(dirname "$(readlink -f "$0")")" - -export build_dir="$(readlink -f "${1:-${script_dir}/../build-multi}")" -export conan_profile=${2:-scwx-linux_gcc-11} -export generator="Ninja Multi-Config" -export qt_base=/opt/Qt -export qt_arch=gcc_64 -export address_sanitizer=${4:-disabled} - -# Assign user-specified Python Virtual Environment -[ "${3:-}" = "none" ] && unset venv_path || export venv_path="$(readlink -f "${3:-${script_dir}/../.venv}")" - -# FIXME: aws-sdk-cpp fails to configure using Ninja Multi-Config -echo "Ninja Multi-Config is not supported in Linux" -read -p "Press Enter to continue..." - -# Perform common setup -# "${script_dir}/lib/setup-common.sh" diff --git a/tools/setup-linux-ninja-release.sh b/tools/setup-linux-ninja-release.sh deleted file mode 100755 index e7e10db0..00000000 --- a/tools/setup-linux-ninja-release.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash -script_dir="$(dirname "$(readlink -f "$0")")" - -export build_dir="$(readlink -f "${1:-${script_dir}/../build-release}")" -export build_type=Release -export conan_profile=${2:-scwx-linux_gcc-11} -export generator=Ninja -export qt_base=/opt/Qt -export qt_arch=gcc_64 -export address_sanitizer=${4:-disabled} - -# Assign user-specified Python Virtual Environment -[ "${3:-}" = "none" ] && unset venv_path || export venv_path="$(readlink -f "${3:-${script_dir}/../.venv}")" - -# Perform common setup -"${script_dir}/lib/setup-common.sh" diff --git a/tools/setup-macos-ninja-debug.sh b/tools/setup-macos-ninja-debug.sh deleted file mode 100755 index ec24dfe2..00000000 --- a/tools/setup-macos-ninja-debug.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash -script_source="${BASH_SOURCE[0]:-$0}" -script_dir="$(cd "$(dirname "${script_source}")" && pwd)" - -export build_dir="$(python3 -c 'import os,sys;print(os.path.realpath(sys.argv[1]))' "${1:-${script_dir}/../build-debug}")" -export build_type=Debug -export conan_profile=${2:-scwx-macos_clang-18_armv8} -export generator=Ninja -export qt_base="/Users/${USER}/Qt" -export qt_arch=macos -export address_sanitizer=${4:-disabled} - -# Set explicit compiler paths -export CC=$(brew --prefix llvm@18)/bin/clang -export CXX=$(brew --prefix llvm@18)/bin/clang++ -export PATH="$(brew --prefix llvm@18)/bin:$PATH" - -export LDFLAGS="-L$(brew --prefix llvm@18)/lib -L$(brew --prefix llvm@18)/lib/c++" -export CPPFLAGS="-I$(brew --prefix llvm@18)/include" - -# Assign user-specified Python Virtual Environment -if [ "${3:-}" = "none" ]; then - unset venv_path -else - # macOS does not have 'readlink -f', use python for realpath - export venv_path="$(python3 -c 'import os,sys;print(os.path.realpath(sys.argv[1]))' "${3:-${script_dir}/../.venv}")" -fi - -# Perform common setup -"${script_dir}/lib/setup-common.sh" diff --git a/tools/setup-macos-ninja-release.sh b/tools/setup-macos-ninja-release.sh deleted file mode 100755 index 870dd841..00000000 --- a/tools/setup-macos-ninja-release.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash -script_source="${BASH_SOURCE[0]:-$0}" -script_dir="$(cd "$(dirname "${script_source}")" && pwd)" - -export build_dir="$(python3 -c 'import os,sys;print(os.path.realpath(sys.argv[1]))' "${1:-${script_dir}/../build-release}")" -export build_type=Release -export conan_profile=${2:-scwx-macos_clang-18_armv8} -export generator=Ninja -export qt_base="/Users/${USER}/Qt" -export qt_arch=macos -export address_sanitizer=${4:-disabled} - -# Set explicit compiler paths -export CC=$(brew --prefix llvm@18)/bin/clang -export CXX=$(brew --prefix llvm@18)/bin/clang++ -export PATH="$(brew --prefix llvm@18)/bin:$PATH" - -export LDFLAGS="-L$(brew --prefix llvm@18)/lib -L$(brew --prefix llvm@18)/lib/c++" -export CPPFLAGS="-I$(brew --prefix llvm@18)/include" - -# Assign user-specified Python Virtual Environment -if [ "${3:-}" = "none" ]; then - unset venv_path -else - # macOS does not have 'readlink -f', use python for realpath - export venv_path="$(python3 -c 'import os,sys;print(os.path.realpath(sys.argv[1]))' "${3:-${script_dir}/../.venv}")" -fi - -# Perform common setup -"${script_dir}/lib/setup-common.sh" diff --git a/tools/setup-macos-xcode-debug.sh b/tools/setup-macos-xcode-debug.sh deleted file mode 100755 index ced08867..00000000 --- a/tools/setup-macos-xcode-debug.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash -script_source="${BASH_SOURCE[0]:-$0}" -script_dir="$(cd "$(dirname "${script_source}")" && pwd)" - -export build_dir="$(python3 -c 'import os,sys;print(os.path.realpath(sys.argv[1]))' "${1:-${script_dir}/../build-xcode-debug}")" -export build_type=Debug -export conan_profile=${2:-scwx-macos_clang-18_armv8} -export generator=Xcode -export qt_base="/Users/${USER}/Qt" -export qt_arch=macos -export address_sanitizer=${4:-disabled} - -# Set explicit compiler paths -export CC=$(brew --prefix llvm@18)/bin/clang -export CXX=$(brew --prefix llvm@18)/bin/clang++ -export PATH="$(brew --prefix llvm@18)/bin:$PATH" - -export LDFLAGS="-L$(brew --prefix llvm@18)/lib -L$(brew --prefix llvm@18)/lib/c++" -export CPPFLAGS="-I$(brew --prefix llvm@18)/include" - -# Assign user-specified Python Virtual Environment -if [ "${3:-}" = "none" ]; then - unset venv_path -else - # macOS does not have 'readlink -f', use python for realpath - export venv_path="$(python3 -c 'import os,sys;print(os.path.realpath(sys.argv[1]))' "${3:-${script_dir}/../.venv}")" -fi - -# FIXME: aws-sdk-cpp fails to configure using Xcode -echo "Xcode is not supported" -read -p "Press Enter to continue..." - -# Perform common setup -# "${script_dir}/lib/setup-common.sh" diff --git a/tools/setup-macos-xcode-multi.sh b/tools/setup-macos-xcode-multi.sh deleted file mode 100755 index f706b072..00000000 --- a/tools/setup-macos-xcode-multi.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash -script_source="${BASH_SOURCE[0]:-$0}" -script_dir="$(cd "$(dirname "${script_source}")" && pwd)" - -export build_dir="$(python3 -c 'import os,sys;print(os.path.realpath(sys.argv[1]))' "${1:-${script_dir}/../build-xcode}")" -export conan_profile=${2:-scwx-macos_clang-18_armv8} -export generator=Xcode -export qt_base=/opt/Qt -export qt_arch=gcc_64 -export address_sanitizer=${4:-disabled} - -# Set explicit compiler paths -export CC=$(brew --prefix llvm@18)/bin/clang -export CXX=$(brew --prefix llvm@18)/bin/clang++ -export PATH="$(brew --prefix llvm@18)/bin:$PATH" - -export LDFLAGS="-L$(brew --prefix llvm@18)/lib -L$(brew --prefix llvm@18)/lib/c++" -export CPPFLAGS="-I$(brew --prefix llvm@18)/include" - -# Assign user-specified Python Virtual Environment -if [ "${3:-}" = "none" ]; then - unset venv_path -else - # macOS does not have 'readlink -f', use python for realpath - export venv_path="$(python3 -c 'import os,sys;print(os.path.realpath(sys.argv[1]))' "${3:-${script_dir}/../.venv}")" -fi - -# FIXME: aws-sdk-cpp fails to configure using Xcode -echo "Xcode is not supported" -read -p "Press Enter to continue..." - -# Perform common setup -# "${script_dir}/lib/setup-common.sh" diff --git a/tools/setup-macos-xcode-release.sh b/tools/setup-macos-xcode-release.sh deleted file mode 100755 index ab788c7e..00000000 --- a/tools/setup-macos-xcode-release.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash -script_source="${BASH_SOURCE[0]:-$0}" -script_dir="$(cd "$(dirname "${script_source}")" && pwd)" - -export build_dir="$(python3 -c 'import os,sys;print(os.path.realpath(sys.argv[1]))' "${1:-${script_dir}/../build-xcode-release}")" -export build_type=Release -export conan_profile=${2:-scwx-macos_clang-18_armv8} -export generator=Xcode -export qt_base="/Users/${USER}/Qt" -export qt_arch=macos -export address_sanitizer=${4:-disabled} - -# Set explicit compiler paths -export CC=$(brew --prefix llvm@18)/bin/clang -export CXX=$(brew --prefix llvm@18)/bin/clang++ -export PATH="$(brew --prefix llvm@18)/bin:$PATH" - -export LDFLAGS="-L$(brew --prefix llvm@18)/lib -L$(brew --prefix llvm@18)/lib/c++" -export CPPFLAGS="-I$(brew --prefix llvm@18)/include" - -# Assign user-specified Python Virtual Environment -if [ "${3:-}" = "none" ]; then - unset venv_path -else - # macOS does not have 'readlink -f', use python for realpath - export venv_path="$(python3 -c 'import os,sys;print(os.path.realpath(sys.argv[1]))' "${3:-${script_dir}/../.venv}")" -fi - -# FIXME: aws-sdk-cpp fails to configure using Xcode -echo "Xcode is not supported" -read -p "Press Enter to continue..." - -# Perform common setup -# "${script_dir}/lib/setup-common.sh" diff --git a/tools/setup-windows-msvc2022-debug.bat b/tools/setup-windows-msvc2022-debug.bat deleted file mode 100644 index 9ef029a3..00000000 --- a/tools/setup-windows-msvc2022-debug.bat +++ /dev/null @@ -1,26 +0,0 @@ -@set script_dir=%~dp0 - -@set build_dir=%script_dir%\..\build-debug-msvc2022 -@set build_type=Debug -@set conan_profile=scwx-windows_msvc2022_x64 -@set generator=Visual Studio 17 2022 -@set qt_base=C:/Qt -@set qt_arch=msvc2022_64 -@set venv_path=%script_dir%\..\.venv - -:: Assign user-specified build directory -@if not "%~1"=="" set build_dir=%~f1 - -:: Assign user-specified Python Virtual Environment -@if not "%~2"=="" ( - if /i "%~2"=="none" ( - set venv_path= - ) else ( - set venv_path=%~f2 - ) -) - -:: Perform common setup -@call %script_dir%\lib\setup-common.bat - -@pause diff --git a/tools/setup-windows-msvc2022-multi.bat b/tools/setup-windows-msvc2022-multi.bat deleted file mode 100644 index 87e19fd3..00000000 --- a/tools/setup-windows-msvc2022-multi.bat +++ /dev/null @@ -1,25 +0,0 @@ -@set script_dir=%~dp0 - -@set build_dir=%script_dir%\..\build-msvc2022 -@set conan_profile=scwx-windows_msvc2022_x64 -@set generator=Visual Studio 17 2022 -@set qt_base=C:/Qt -@set qt_arch=msvc2022_64 -@set venv_path=%script_dir%\..\.venv - -:: Assign user-specified build directory -@if not "%~1"=="" set build_dir=%~f1 - -:: Assign user-specified Python Virtual Environment -@if not "%~2"=="" ( - if /i "%~2"=="none" ( - set venv_path= - ) else ( - set venv_path=%~f2 - ) -) - -:: Perform common setup -@call %script_dir%\lib\setup-common.bat - -@pause diff --git a/tools/setup-windows-msvc2022-release.bat b/tools/setup-windows-msvc2022-release.bat deleted file mode 100644 index a4f805cc..00000000 --- a/tools/setup-windows-msvc2022-release.bat +++ /dev/null @@ -1,26 +0,0 @@ -@set script_dir=%~dp0 - -@set build_dir=%script_dir%\..\build-release-msvc2022 -@set build_type=Release -@set conan_profile=scwx-windows_msvc2022_x64 -@set generator=Visual Studio 17 2022 -@set qt_base=C:/Qt -@set qt_arch=msvc2022_64 -@set venv_path=%script_dir%\..\.venv - -:: Assign user-specified build directory -@if not "%~1"=="" set build_dir=%~f1 - -:: Assign user-specified Python Virtual Environment -@if not "%~2"=="" ( - if /i "%~2"=="none" ( - set venv_path= - ) else ( - set venv_path=%~f2 - ) -) - -:: Perform common setup -@call %script_dir%\lib\setup-common.bat - -@pause diff --git a/tools/setup-windows-ninja-debug.bat b/tools/setup-windows-ninja-debug.bat deleted file mode 100644 index 182c7956..00000000 --- a/tools/setup-windows-ninja-debug.bat +++ /dev/null @@ -1,26 +0,0 @@ -@set script_dir=%~dp0 - -@set build_dir=%script_dir%\..\build-debug-ninja -@set build_type=Debug -@set conan_profile=scwx-windows_msvc2022_x64 -@set generator=Ninja -@set qt_base=C:/Qt -@set qt_arch=msvc2022_64 -@set venv_path=%script_dir%\..\.venv - -:: Assign user-specified build directory -@if not "%~1"=="" set build_dir=%~f1 - -:: Assign user-specified Python Virtual Environment -@if not "%~2"=="" ( - if /i "%~2"=="none" ( - set venv_path= - ) else ( - set venv_path=%~f2 - ) -) - -:: Perform common setup -@call %script_dir%\lib\setup-common.bat - -@pause diff --git a/tools/setup-windows-ninja-multi.bat b/tools/setup-windows-ninja-multi.bat deleted file mode 100644 index 8962fc2b..00000000 --- a/tools/setup-windows-ninja-multi.bat +++ /dev/null @@ -1,25 +0,0 @@ -@set script_dir=%~dp0 - -@set build_dir=%script_dir%\..\build-ninja -@set conan_profile=scwx-windows_msvc2022_x64 -@set generator=Ninja Multi-Config -@set qt_base=C:/Qt -@set qt_arch=msvc2022_64 -@set venv_path=%script_dir%\..\.venv - -:: Assign user-specified build directory -@if not "%~1"=="" set build_dir=%~f1 - -:: Assign user-specified Python Virtual Environment -@if not "%~2"=="" ( - if /i "%~2"=="none" ( - set venv_path= - ) else ( - set venv_path=%~f2 - ) -) - -:: Perform common setup -@call %script_dir%\lib\setup-common.bat - -@pause diff --git a/tools/setup-windows-ninja-release.bat b/tools/setup-windows-ninja-release.bat deleted file mode 100644 index 96ba0e55..00000000 --- a/tools/setup-windows-ninja-release.bat +++ /dev/null @@ -1,26 +0,0 @@ -@set script_dir=%~dp0 - -@set build_dir=%script_dir%\..\build-release-ninja -@set build_type=Release -@set conan_profile=scwx-windows_msvc2022_x64 -@set generator=Ninja -@set qt_base=C:/Qt -@set qt_arch=msvc2022_64 -@set venv_path=%script_dir%\..\.venv - -:: Assign user-specified build directory -@if not "%~1"=="" set build_dir=%~f1 - -:: Assign user-specified Python Virtual Environment -@if not "%~2"=="" ( - if /i "%~2"=="none" ( - set venv_path= - ) else ( - set venv_path=%~f2 - ) -) - -:: Perform common setup -@call %script_dir%\lib\setup-common.bat - -@pause diff --git a/wxdata/CMakeLists.txt b/wxdata/CMakeLists.txt index c5d91595..845ab381 100644 --- a/wxdata/CMakeLists.txt +++ b/wxdata/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.24) +cmake_minimum_required(VERSION 3.20) set_property(DIRECTORY APPEND diff --git a/wxdata/cpp-feature-tests/chrono_feature_test.cpp b/wxdata/cpp-feature-tests/chrono_feature_test.cpp deleted file mode 100644 index c23acffb..00000000 --- a/wxdata/cpp-feature-tests/chrono_feature_test.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include - -int main() -{ -#if (__cpp_lib_chrono < 201907L) -# error("Old chrono version") -#endif -} diff --git a/wxdata/include/scwx/awips/coded_location.hpp b/wxdata/include/scwx/awips/coded_location.hpp index 1f29faa7..0ac03d95 100644 --- a/wxdata/include/scwx/awips/coded_location.hpp +++ b/wxdata/include/scwx/awips/coded_location.hpp @@ -7,18 +7,8 @@ #include #include -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wunused-parameter" -#endif - -#include #include -#if defined(__clang__) -# pragma clang diagnostic pop -#endif - namespace scwx { namespace awips diff --git a/wxdata/include/scwx/awips/coded_time_motion_location.hpp b/wxdata/include/scwx/awips/coded_time_motion_location.hpp index 1d950ee0..6b7b9a19 100644 --- a/wxdata/include/scwx/awips/coded_time_motion_location.hpp +++ b/wxdata/include/scwx/awips/coded_time_motion_location.hpp @@ -8,18 +8,8 @@ #include #include -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wunused-parameter" -#endif - -#include #include -#if defined(__clang__) -# pragma clang diagnostic pop -#endif - namespace scwx { namespace awips diff --git a/wxdata/include/scwx/awips/impact_based_warnings.hpp b/wxdata/include/scwx/awips/impact_based_warnings.hpp index 3d956893..a7b22288 100644 --- a/wxdata/include/scwx/awips/impact_based_warnings.hpp +++ b/wxdata/include/scwx/awips/impact_based_warnings.hpp @@ -1,16 +1,11 @@ #pragma once -#include - #include -#include namespace scwx { namespace awips { -namespace ibw -{ enum class ThreatCategory : int { @@ -22,18 +17,8 @@ enum class ThreatCategory : int Unknown }; -struct ImpactBasedWarningInfo -{ - bool hasObservedTag_ {false}; - bool hasTornadoPossibleTag_ {false}; - std::vector threatCategories_ {ThreatCategory::Base}; -}; - -const ImpactBasedWarningInfo& GetImpactBasedWarningInfo(Phenomenon phenomenon); - ThreatCategory GetThreatCategory(const std::string& name); const std::string& GetThreatCategoryName(ThreatCategory threatCategory); -} // namespace ibw } // namespace awips } // namespace scwx diff --git a/wxdata/include/scwx/awips/message.hpp b/wxdata/include/scwx/awips/message.hpp index 5cd81000..6a386065 100644 --- a/wxdata/include/scwx/awips/message.hpp +++ b/wxdata/include/scwx/awips/message.hpp @@ -1,7 +1,6 @@ #pragma once #include -#include #include #include #include @@ -14,8 +13,12 @@ # include #endif -namespace scwx::awips +namespace scwx { +namespace awips +{ + +class MessageImpl; class Message { @@ -53,165 +56,78 @@ public: static float SwapFloat(float f) { - if constexpr (std::endian::native == std::endian::little) - { - // Variable is initialized by memcpy - // NOLINTNEXTLINE(cppcoreguidelines-init-variables) - std::uint32_t temp; - std::memcpy(&temp, &f, sizeof(std::uint32_t)); - temp = ntohl(temp); - std::memcpy(&f, &temp, sizeof(float)); - } + std::uint32_t temp; + std::memcpy(&temp, &f, sizeof(std::uint32_t)); + temp = ntohl(temp); + std::memcpy(&f, &temp, sizeof(float)); return f; } - static double SwapDouble(double d) + template + static void SwapArray(std::array& arr, + std::size_t size = _Size) { - if constexpr (std::endian::native == std::endian::little) - { - // Variable is initialized by memcpy - // NOLINTNEXTLINE(cppcoreguidelines-init-variables) - std::uint64_t temp; - std::memcpy(&temp, &d, sizeof(std::uint64_t)); - temp = Swap64(temp); - std::memcpy(&d, &temp, sizeof(float)); - } - return d; + std::transform(std::execution::par_unseq, + arr.begin(), + arr.begin() + size, + arr.begin(), + [](float f) { return SwapFloat(f); }); } - static std::uint64_t Swap64(std::uint64_t value) + template + static void SwapArray(std::array& arr, + std::size_t size = _Size) { - if constexpr (std::endian::native == std::endian::little) - { - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) - const std::uint32_t high = - ntohl(static_cast(value >> 32)); - const std::uint32_t low = - ntohl(static_cast(value & 0xFFFFFFFFULL)); - return (static_cast(low) << 32) | high; - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - } - else - { - return value; - } + std::transform(std::execution::par_unseq, + arr.begin(), + arr.begin() + size, + arr.begin(), + [](std::int16_t u) { return ntohs(u); }); } - template - static void SwapArray(std::array& arr, - std::size_t size = kSize) + template + static void SwapArray(std::array& arr, + std::size_t size = _Size) { - if constexpr (std::endian::native == std::endian::little) - { - std::transform(std::execution::par_unseq, - arr.begin(), - arr.begin() + size, - arr.begin(), - [](float f) { return SwapFloat(f); }); - } + std::transform(std::execution::par_unseq, + arr.begin(), + arr.begin() + size, + arr.begin(), + [](std::uint16_t u) { return ntohs(u); }); } - template - static void SwapArray(std::array& arr, - std::size_t size = kSize) + template + static void SwapArray(std::array& arr, + std::size_t size = _Size) { - if constexpr (std::endian::native == std::endian::little) - { - std::transform(std::execution::par_unseq, - arr.begin(), - arr.begin() + size, - arr.begin(), - [](std::int16_t u) { return ntohs(u); }); - } - } - - template - static void SwapArray(std::array& arr, - std::size_t size = kSize) - { - if constexpr (std::endian::native == std::endian::little) - { - std::transform(std::execution::par_unseq, - arr.begin(), - arr.begin() + size, - arr.begin(), - [](std::uint16_t u) { return ntohs(u); }); - } - } - - template - static void SwapArray(std::array& arr, - std::size_t size = kSize) - { - if constexpr (std::endian::native == std::endian::little) - { - std::transform(std::execution::par_unseq, - arr.begin(), - arr.begin() + size, - arr.begin(), - [](std::uint32_t u) { return ntohl(u); }); - } + std::transform(std::execution::par_unseq, + arr.begin(), + arr.begin() + size, + arr.begin(), + [](std::uint32_t u) { return ntohl(u); }); } template static void SwapMap(std::map& m) { - if constexpr (std::endian::native == std::endian::little) - { - std::for_each(std::execution::par_unseq, - m.begin(), - m.end(), - [](auto& p) { p.second = SwapFloat(p.second); }); - } + std::for_each(std::execution::par_unseq, + m.begin(), + m.end(), + [](auto& p) { p.second = SwapFloat(p.second); }); } - template - static void SwapVector(std::vector& v) + static void SwapVector(std::vector& v) { - if constexpr (std::endian::native == std::endian::little) - { - std::transform( - std::execution::par_unseq, - v.begin(), - v.end(), - v.begin(), - [](T u) - { - if constexpr (std::is_same_v || - std::is_same_v) - { - return static_cast(ntohs(u)); - } - else if constexpr (std::is_same_v || - std::is_same_v) - { - return static_cast(ntohl(u)); - } - else if constexpr (std::is_same_v || - std::is_same_v) - { - return static_cast(Swap64(u)); - } - else if constexpr (std::is_same_v) - { - return SwapFloat(u); - } - else if constexpr (std::is_same_v) - { - return SwapDouble(u); - } - else - { - static_assert(std::is_same_v, - "Unsupported type for SwapVector"); - } - }); - } + std::transform(std::execution::par_unseq, + v.begin(), + v.end(), + v.begin(), + [](std::uint16_t u) { return ntohs(u); }); } private: - class Impl; - std::unique_ptr p; + std::unique_ptr p; }; -} // namespace scwx::awips +} // namespace awips +} // namespace scwx diff --git a/wxdata/include/scwx/awips/phenomenon.hpp b/wxdata/include/scwx/awips/phenomenon.hpp index 234e473a..013a9947 100644 --- a/wxdata/include/scwx/awips/phenomenon.hpp +++ b/wxdata/include/scwx/awips/phenomenon.hpp @@ -69,7 +69,6 @@ enum class Phenomenon }; Phenomenon GetPhenomenon(const std::string& code); -Phenomenon GetPhenomenonFromText(const std::string& text); const std::string& GetPhenomenonCode(Phenomenon phenomenon); const std::string& GetPhenomenonText(Phenomenon phenomenon); diff --git a/wxdata/include/scwx/awips/text_product_file.hpp b/wxdata/include/scwx/awips/text_product_file.hpp index b0d1c965..478a93b4 100644 --- a/wxdata/include/scwx/awips/text_product_file.hpp +++ b/wxdata/include/scwx/awips/text_product_file.hpp @@ -5,7 +5,9 @@ #include #include -namespace scwx::awips +namespace scwx +{ +namespace awips { class TextProductFileImpl; @@ -22,17 +24,16 @@ public: TextProductFile(TextProductFile&&) noexcept; TextProductFile& operator=(TextProductFile&&) noexcept; - [[nodiscard]] std::size_t message_count() const; - [[nodiscard]] std::vector> - messages() const; - [[nodiscard]] std::shared_ptr message(size_t i) const; + size_t message_count() const; + std::vector> messages() const; + std::shared_ptr message(size_t i) const; bool LoadFile(const std::string& filename); - bool LoadData(const std::string& filename, std::istream& is); + bool LoadData(std::istream& is); private: - class Impl; - std::unique_ptr p; + std::unique_ptr p; }; -} // namespace scwx::awips +} // namespace awips +} // namespace scwx diff --git a/wxdata/include/scwx/awips/text_product_message.hpp b/wxdata/include/scwx/awips/text_product_message.hpp index 373dc223..d402cfd5 100644 --- a/wxdata/include/scwx/awips/text_product_message.hpp +++ b/wxdata/include/scwx/awips/text_product_message.hpp @@ -13,8 +13,6 @@ #include #include -#include - namespace scwx { namespace awips @@ -66,9 +64,9 @@ struct Segment std::optional codedLocation_ {}; std::optional codedMotion_ {}; - bool observed_ {false}; - ibw::ThreatCategory threatCategory_ {ibw::ThreatCategory::Base}; - bool tornadoPossible_ {false}; + bool observed_ {false}; + ThreatCategory threatCategory_ {ThreatCategory::Base}; + bool tornadoPossible_ {false}; Segment() = default; @@ -96,7 +94,6 @@ public: TextProductMessage(TextProductMessage&&) noexcept; TextProductMessage& operator=(TextProductMessage&&) noexcept; - [[nodiscard]] boost::uuids::uuid uuid() const; std::string message_content() const; std::shared_ptr wmo_header() const; std::vector mnd_header() const; @@ -108,7 +105,7 @@ public: std::chrono::system_clock::time_point segment_event_begin(std::size_t s) const; - std::size_t data_size() const override; + std::size_t data_size() const; bool Parse(std::istream& is) override; diff --git a/wxdata/include/scwx/awips/wmo_header.hpp b/wxdata/include/scwx/awips/wmo_header.hpp index 889c955e..f3487b6d 100644 --- a/wxdata/include/scwx/awips/wmo_header.hpp +++ b/wxdata/include/scwx/awips/wmo_header.hpp @@ -1,11 +1,11 @@ #pragma once -#include #include -#include #include -namespace scwx::awips +namespace scwx +{ +namespace awips { class WmoHeaderImpl; @@ -27,7 +27,7 @@ public: explicit WmoHeader(); ~WmoHeader(); - WmoHeader(const WmoHeader&) = delete; + WmoHeader(const WmoHeader&) = delete; WmoHeader& operator=(const WmoHeader&) = delete; WmoHeader(WmoHeader&&) noexcept; @@ -35,53 +35,21 @@ public: bool operator==(const WmoHeader& o) const; - [[nodiscard]] std::string sequence_number() const; - [[nodiscard]] std::string data_type() const; - [[nodiscard]] std::string geographic_designator() const; - [[nodiscard]] std::string bulletin_id() const; - [[nodiscard]] std::string icao() const; - [[nodiscard]] std::string date_time() const; - [[nodiscard]] std::string bbb_indicator() const; - [[nodiscard]] std::string product_category() const; - [[nodiscard]] std::string product_designator() const; + std::string sequence_number() const; + std::string data_type() const; + std::string geographic_designator() const; + std::string bulletin_id() const; + std::string icao() const; + std::string date_time() const; + std::string bbb_indicator() const; + std::string product_category() const; + std::string product_designator() const; - /** - * @brief Get the WMO date/time - * - * Gets the WMO date/time. Uses the optional date hint provided via - * SetDateHint(std::chrono::year_month). If the date hint has not been - * provided, the endTimeHint parameter is required. - * - * @param [in] endTimeHint The optional end time bounds to provide. This is - * ignored if a date hint has been provided to determine an absolute date. - */ - [[nodiscard]] std::chrono::sys_time GetDateTime( - std::optional endTimeHint = - std::nullopt); - - /** - * @brief Parse a WMO header - * - * @param [in] is The input stream to parse - */ bool Parse(std::istream& is); - /** - * @brief Provide a date hint for the WMO parser - * - * The WMO header contains a date/time in the format DDHHMM. The year and - * month must be derived using another source. The date hint provides the - * additional context required to determine the absolute product time. - * - * This function will update any absolute date/time already calculated, or - * affect the calculation of a subsequent absolute date/time. - * - * @param [in] dateHint The date hint to provide the WMO header parser - */ - void SetDateHint(std::chrono::year_month dateHint); - private: std::unique_ptr p; }; -} // namespace scwx::awips +} // namespace awips +} // namespace scwx diff --git a/wxdata/include/scwx/common/geographic.hpp b/wxdata/include/scwx/common/geographic.hpp index 8b234fd2..8945db17 100644 --- a/wxdata/include/scwx/common/geographic.hpp +++ b/wxdata/include/scwx/common/geographic.hpp @@ -3,8 +3,6 @@ #include #include -#include - namespace scwx { namespace common @@ -48,17 +46,6 @@ enum class DistanceType Miles }; -/** - * Calculate the absolute angle delta between two angles. - * - * @param [in] angle1 First angle - * @param [in] angle2 Second angle - * - * @return Absolute angle delta normalized to [0, 360) - */ -units::degrees GetAngleDelta(units::degrees angle1, - units::degrees angle2); - /** * Calculate the geographic midpoint of a set of coordinates. Uses Method A * described at http://www.geomidpoint.com/calculation.html. diff --git a/wxdata/include/scwx/common/products.hpp b/wxdata/include/scwx/common/products.hpp index 7451aa39..97d9c324 100644 --- a/wxdata/include/scwx/common/products.hpp +++ b/wxdata/include/scwx/common/products.hpp @@ -73,9 +73,8 @@ Level2Product GetLevel2Product(const std::string& name); const std::string& GetLevel3CategoryName(Level3ProductCategory category); const std::string& GetLevel3CategoryDescription(Level3ProductCategory category); -std::string -GetLevel3CategoryDefaultProduct(Level3ProductCategory category, - const Level3ProductCategoryMap& categoryMap); +const std::string& +GetLevel3CategoryDefaultProduct(Level3ProductCategory category); Level3ProductCategory GetLevel3Category(const std::string& categoryName); Level3ProductCategory GetLevel3CategoryByProduct(const std::string& productName); diff --git a/wxdata/include/scwx/network/ntp_client.hpp b/wxdata/include/scwx/network/ntp_client.hpp deleted file mode 100644 index 8be912b3..00000000 --- a/wxdata/include/scwx/network/ntp_client.hpp +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -namespace scwx::network -{ - -/** - * @brief NTP Client - */ -class NtpClient -{ -public: - explicit NtpClient(); - ~NtpClient(); - - NtpClient(const NtpClient&) = delete; - NtpClient& operator=(const NtpClient&) = delete; - - NtpClient(NtpClient&&) noexcept; - NtpClient& operator=(NtpClient&&) noexcept; - - bool error(); - - [[nodiscard]] std::chrono::system_clock::duration time_offset() const; - - void Start(); - void Stop(); - - void Open(std::string_view host, std::string_view service); - void OpenCurrentServer(); - void Poll(); - std::string RotateServer(); - void RunOnce(); - - void WaitForInitialOffset(); - - static std::shared_ptr Instance(); - -private: - class Impl; - std::unique_ptr p; -}; - -} // namespace scwx::network diff --git a/wxdata/include/scwx/provider/aws_level2_chunks_data_provider.hpp b/wxdata/include/scwx/provider/aws_level2_chunks_data_provider.hpp deleted file mode 100644 index abd70787..00000000 --- a/wxdata/include/scwx/provider/aws_level2_chunks_data_provider.hpp +++ /dev/null @@ -1,71 +0,0 @@ -#pragma once - -#include -#include - -#include - -namespace Aws::S3 -{ -class S3Client; -} // namespace Aws::S3 - -namespace scwx::provider -{ - -/** - * @brief AWS Level 2 Data Provider - */ -class AwsLevel2ChunksDataProvider : public NexradDataProvider -{ -public: - explicit AwsLevel2ChunksDataProvider(const std::string& radarSite); - explicit AwsLevel2ChunksDataProvider(const std::string& radarSite, - const std::string& bucketName, - const std::string& region); - ~AwsLevel2ChunksDataProvider() override; - - AwsLevel2ChunksDataProvider(const AwsLevel2ChunksDataProvider&) = delete; - AwsLevel2ChunksDataProvider& - operator=(const AwsLevel2ChunksDataProvider&) = delete; - - AwsLevel2ChunksDataProvider(AwsLevel2ChunksDataProvider&&) noexcept; - AwsLevel2ChunksDataProvider& - operator=(AwsLevel2ChunksDataProvider&&) noexcept; - - [[nodiscard]] std::chrono::system_clock::time_point - GetTimePointByKey(const std::string& key) const override; - - [[nodiscard]] size_t cache_size() const override; - - [[nodiscard]] std::chrono::system_clock::time_point - last_modified() const override; - [[nodiscard]] std::chrono::seconds update_period() const override; - - std::string FindKey(std::chrono::system_clock::time_point time) override; - std::string FindLatestKey() override; - std::chrono::system_clock::time_point FindLatestTime() override; - std::vector - GetTimePointsByDate(std::chrono::system_clock::time_point date) override; - std::tuple - ListObjects(std::chrono::system_clock::time_point date) override; - std::shared_ptr - LoadObjectByKey(const std::string& key) override; - std::shared_ptr - LoadObjectByTime(std::chrono::system_clock::time_point time) override; - std::pair Refresh() override; - - void RequestAvailableProducts() override; - std::vector GetAvailableProducts() override; - - std::optional GetCurrentElevation(); - - void SetLevel2DataProvider( - const std::shared_ptr& provider); - -private: - class Impl; - std::unique_ptr p; -}; - -} // namespace scwx::provider diff --git a/wxdata/include/scwx/provider/aws_nexrad_data_provider.hpp b/wxdata/include/scwx/provider/aws_nexrad_data_provider.hpp index d6ddcd7c..462d293d 100644 --- a/wxdata/include/scwx/provider/aws_nexrad_data_provider.hpp +++ b/wxdata/include/scwx/provider/aws_nexrad_data_provider.hpp @@ -39,15 +39,12 @@ public: std::string FindKey(std::chrono::system_clock::time_point time) override; std::string FindLatestKey() override; - std::chrono::system_clock::time_point FindLatestTime() override; std::vector GetTimePointsByDate(std::chrono::system_clock::time_point date) override; std::tuple ListObjects(std::chrono::system_clock::time_point date) override; std::shared_ptr LoadObjectByKey(const std::string& key) override; - std::shared_ptr - LoadObjectByTime(std::chrono::system_clock::time_point time) override; std::pair Refresh() override; protected: diff --git a/wxdata/include/scwx/provider/iem_api_provider.hpp b/wxdata/include/scwx/provider/iem_api_provider.hpp deleted file mode 100644 index 1aac31b2..00000000 --- a/wxdata/include/scwx/provider/iem_api_provider.hpp +++ /dev/null @@ -1,80 +0,0 @@ -#pragma once - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -#if defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable : 4702) -#endif - -#if defined(_MSC_VER) -# pragma warning(pop) -#endif - -namespace scwx::provider -{ - -/** - * @brief Warnings Provider - */ -class IemApiProvider -{ -public: - explicit IemApiProvider(); - ~IemApiProvider(); - - IemApiProvider(const IemApiProvider&) = delete; - IemApiProvider& operator=(const IemApiProvider&) = delete; - - IemApiProvider(IemApiProvider&&) noexcept; - IemApiProvider& operator=(IemApiProvider&&) noexcept; - - static boost::outcome_v2::result> - ListTextProducts(std::chrono::sys_days date, - std::optional cccc = {}, - std::optional pil = {}); - - template - requires std::same_as, - std::chrono::sys_days> && - std::same_as, - std::string_view> && - std::same_as, std::string_view> - static boost::outcome_v2::result> - ListTextProducts(DateRange dates, CcccRange ccccs, PilRange pils); - - template - requires std::same_as, std::string> - static std::vector> - LoadTextProducts(const Range& textProducts); - -private: - class Impl; - std::unique_ptr p; - - static boost::outcome_v2::result> - ProcessTextProductLists(std::vector& asyncResponses); - static std::vector> - ProcessTextProductFiles( - std::vector>& asyncResponses); - - static const std::shared_ptr logger_; - - static const std::string kBaseUrl_; - static const std::string kListNwsTextProductsEndpoint_; - static const std::string kNwsTextProductEndpoint_; -}; - -} // namespace scwx::provider diff --git a/wxdata/include/scwx/provider/iem_api_provider.ipp b/wxdata/include/scwx/provider/iem_api_provider.ipp deleted file mode 100644 index 25187376..00000000 --- a/wxdata/include/scwx/provider/iem_api_provider.ipp +++ /dev/null @@ -1,111 +0,0 @@ -#pragma once - -#include -#include -#include - -#include -#include -#include -#include -#include - -#if (__cpp_lib_chrono < 201907L) -# include -#endif - -namespace scwx::provider -{ - -template - requires std::same_as, - std::chrono::sys_days> && - std::same_as, std::string_view> && - std::same_as, std::string_view> -boost::outcome_v2::result> -IemApiProvider::ListTextProducts(DateRange dates, - CcccRange ccccs, - PilRange pils) -{ - using namespace std::chrono; - -#if (__cpp_lib_chrono >= 201907L) - namespace df = std; - - static constexpr std::string_view kDateFormat {"{:%Y-%m-%d}"}; -#else - using namespace date; - namespace df = date; - -# define kDateFormat "%Y-%m-%d" -#endif - - auto formattedDates = dates | ranges::views::transform( - [](const std::chrono::sys_days& date) - { return df::format(kDateFormat, date); }); - - logger_->debug("Listing text products for: {}", - boost::algorithm::join(formattedDates, ", ")); - - std::vector asyncResponses {}; - - for (const auto& [date, cccc, pil] : - ranges::views::cartesian_product(dates, ccccs, pils)) - { - auto parameters = - cpr::Parameters {{"date", df::format(kDateFormat, date)}}; - - // WMO Source Code - if (!cccc.empty()) - { - parameters.Add({"cccc", std::string {cccc}}); - } - - // AFOS / AWIPS ID / 3-6 length identifier - if (!pil.empty()) - { - parameters.Add({"pil", std::string {pil}}); - } - - asyncResponses.emplace_back( - cpr::GetAsync(cpr::Url {kBaseUrl_ + kListNwsTextProductsEndpoint_}, - network::cpr::GetHeader(), - parameters)); - } - - return ProcessTextProductLists(asyncResponses); -} - -template - requires std::same_as, std::string> -std::vector> -IemApiProvider::LoadTextProducts(const Range& textProducts) -{ - auto parameters = cpr::Parameters {{"nolimit", "true"}}; - - logger_->debug("Loading {} text products", textProducts.size()); - - std::vector> asyncResponses {}; - asyncResponses.reserve(textProducts.size()); - - const std::string endpointUrl = kBaseUrl_ + kNwsTextProductEndpoint_; - - for (const auto& productId : textProducts) - { - asyncResponses.emplace_back( - productId, - cpr::GetAsync(cpr::Url {endpointUrl + productId}, - network::cpr::GetHeader(), - parameters)); - } - - return ProcessTextProductFiles(asyncResponses); -} - -#ifdef kDateFormat -# undef kDateFormat -#endif - -} // namespace scwx::provider diff --git a/wxdata/include/scwx/provider/nexrad_data_provider.hpp b/wxdata/include/scwx/provider/nexrad_data_provider.hpp index 2a7320d2..14a75815 100644 --- a/wxdata/include/scwx/provider/nexrad_data_provider.hpp +++ b/wxdata/include/scwx/provider/nexrad_data_provider.hpp @@ -59,13 +59,6 @@ public: */ virtual std::string FindLatestKey() = 0; - /** - * Finds the most recent time in the cache. - * - * @return NEXRAD data key - */ - virtual std::chrono::system_clock::time_point FindLatestTime() = 0; - /** * Lists NEXRAD objects for the date supplied, and adds them to the cache. * @@ -88,16 +81,6 @@ public: virtual std::shared_ptr LoadObjectByKey(const std::string& key) = 0; - /** - * Loads a NEXRAD file object at the given time - * - * @param time NEXRAD time - * - * @return NEXRAD data - */ - virtual std::shared_ptr - LoadObjectByTime(std::chrono::system_clock::time_point time) = 0; - /** * Lists NEXRAD objects for the current date, and adds them to the cache. If * no objects have been added to the cache for the current date, the previous diff --git a/wxdata/include/scwx/provider/nexrad_data_provider_factory.hpp b/wxdata/include/scwx/provider/nexrad_data_provider_factory.hpp index 510ee14c..bdd51b9e 100644 --- a/wxdata/include/scwx/provider/nexrad_data_provider_factory.hpp +++ b/wxdata/include/scwx/provider/nexrad_data_provider_factory.hpp @@ -27,9 +27,6 @@ public: static std::shared_ptr CreateLevel2DataProvider(const std::string& radarSite); - static std::shared_ptr - CreateLevel2ChunksDataProvider(const std::string& radarSite); - static std::shared_ptr CreateLevel3DataProvider(const std::string& radarSite, const std::string& product); diff --git a/wxdata/include/scwx/provider/warnings_provider.hpp b/wxdata/include/scwx/provider/warnings_provider.hpp index 0d14d258..e519ec5d 100644 --- a/wxdata/include/scwx/provider/warnings_provider.hpp +++ b/wxdata/include/scwx/provider/warnings_provider.hpp @@ -2,7 +2,9 @@ #include -namespace scwx::provider +namespace scwx +{ +namespace provider { /** @@ -20,12 +22,15 @@ public: WarningsProvider(WarningsProvider&&) noexcept; WarningsProvider& operator=(WarningsProvider&&) noexcept; + std::pair + ListFiles(std::chrono::system_clock::time_point newerThan = {}); std::vector> - LoadUpdatedFiles(std::chrono::sys_time newerThan = {}); + LoadUpdatedFiles(std::chrono::system_clock::time_point newerThan = {}); private: class Impl; std::unique_ptr p; }; -} // namespace scwx::provider +} // namespace provider +} // namespace scwx diff --git a/wxdata/include/scwx/types/iem_types.hpp b/wxdata/include/scwx/types/iem_types.hpp deleted file mode 100644 index ee461c36..00000000 --- a/wxdata/include/scwx/types/iem_types.hpp +++ /dev/null @@ -1,73 +0,0 @@ -#pragma once - -#include -#include - -#include - -namespace scwx::types::iem -{ - -/** - * @brief AFOS Entry object - * - * - */ -struct AfosEntry -{ - std::int64_t index_ {}; - std::string entered_ {}; - std::string pil_ {}; - std::string productId_ {}; - std::string cccc_ {}; - std::int64_t count_ {}; - std::string link_ {}; - std::string textLink_ {}; -}; - -/** - * @brief AFOS List object - * - * - */ -struct AfosList -{ - std::vector data_ {}; -}; - -/** - * @brief Bad Request (400) object - */ -struct BadRequest -{ - std::string detail_ {}; -}; - -/** - * @brief Validation Error (422) object - */ -struct ValidationError -{ - struct Detail - { - std::string type_ {}; - std::vector> loc_ {}; - std::string msg_ {}; - std::string input_ {}; - struct Context - { - std::string error_ {}; - } ctx_; - }; - - std::vector detail_ {}; -}; - -AfosList tag_invoke(boost::json::value_to_tag, - const boost::json::value& jv); -BadRequest tag_invoke(boost::json::value_to_tag, - const boost::json::value& jv); -ValidationError tag_invoke(boost::json::value_to_tag, - const boost::json::value& jv); - -} // namespace scwx::types::iem diff --git a/wxdata/include/scwx/types/ntp_types.hpp b/wxdata/include/scwx/types/ntp_types.hpp deleted file mode 100644 index db1aa61f..00000000 --- a/wxdata/include/scwx/types/ntp_types.hpp +++ /dev/null @@ -1,61 +0,0 @@ -#pragma once - -#include -#include - -namespace scwx::types::ntp -{ - -/* Adapted from: - * https://github.com/lettier/ntpclient/blob/master/source/c/main.c - * - * Copyright (c) 2014 David Lettier - * Copyright (c) 2020 Krystian Stasiowski - * Distributed under the BSD 3-Clause License (See - * https://github.com/lettier/ntpclient/blob/master/LICENSE) - */ - -#pragma pack(push, 1) - -struct NtpPacket -{ - struct LiVnMode - { - std::uint8_t mode : 3; // Client will pick mode 3 for client. - std::uint8_t vn : 3; // Version number of the protocol. - std::uint8_t li : 2; // Leap indicator. - }; - - union - { - std::uint8_t li_vn_mode; - LiVnMode fields; - }; - - std::uint8_t stratum; // Stratum level of the local clock. - std::uint8_t poll; // Maximum interval between successive messages. - std::uint8_t precision; // Precision of the local clock. - - std::uint32_t rootDelay; // Total round trip delay time. - std::uint32_t rootDispersion; // Max error aloud from primary clock source. - std::uint32_t refId; // Reference clock identifier. - - std::uint32_t refTm_s; // Reference time-stamp seconds. - std::uint32_t refTm_f; // Reference time-stamp fraction of a second. - - std::uint32_t origTm_s; // Originate time-stamp seconds. - std::uint32_t origTm_f; // Originate time-stamp fraction of a second. - - std::uint32_t rxTm_s; // Received time-stamp seconds. - std::uint32_t rxTm_f; // Received time-stamp fraction of a second. - - std::uint32_t txTm_s; // Transmit time-stamp seconds. - std::uint32_t txTm_f; // Transmit time-stamp fraction of a second. - - static NtpPacket Parse(const std::span data); -}; -// Total: 48 bytes. - -#pragma pack(pop) - -} // namespace scwx::types::ntp diff --git a/wxdata/include/scwx/util/json.hpp b/wxdata/include/scwx/util/json.hpp deleted file mode 100644 index ab836edc..00000000 --- a/wxdata/include/scwx/util/json.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include - -namespace scwx::util::json -{ - -boost::json::value ReadJsonFile(const std::string& path); -boost::json::value ReadJsonStream(std::istream& is); -boost::json::value ReadJsonString(std::string_view sv); -void WriteJsonFile(const std::string& path, - const boost::json::value& json, - bool prettyPrint = true); - -} // namespace scwx::util::json diff --git a/wxdata/include/scwx/util/time.hpp b/wxdata/include/scwx/util/time.hpp index fe052756..62242589 100644 --- a/wxdata/include/scwx/util/time.hpp +++ b/wxdata/include/scwx/util/time.hpp @@ -6,14 +6,16 @@ #include #include -#if (__cpp_lib_chrono < 201907L) +#if !defined(_MSC_VER) # include #endif -namespace scwx::util::time +namespace scwx +{ +namespace util { -#if (__cpp_lib_chrono >= 201907L) +#if defined(_MSC_VER) typedef std::chrono::time_zone time_zone; #else typedef date::time_zone time_zone; @@ -32,9 +34,6 @@ typedef scwx::util:: ClockFormat GetClockFormat(const std::string& name); const std::string& GetClockFormatName(ClockFormat clockFormat); -template -std::chrono::time_point now(); - std::chrono::system_clock::time_point TimePoint(uint32_t modifiedJulianDate, uint32_t milliseconds); @@ -47,17 +46,5 @@ template std::optional> TryParseDateTime(const std::string& dateTimeFormat, const std::string& str); -} // namespace scwx::util::time - -namespace scwx::util -{ -// Add types and functions to scwx::util for compatibility -using time::ClockFormat; -using time::ClockFormatIterator; -using time::GetClockFormat; -using time::GetClockFormatName; -using time::time_zone; -using time::TimePoint; -using time::TimeString; -using time::TryParseDateTime; -} // namespace scwx::util +} // namespace util +} // namespace scwx diff --git a/wxdata/include/scwx/wsr88d/ar2v_file.hpp b/wxdata/include/scwx/wsr88d/ar2v_file.hpp index 64319283..1f3ab0cc 100644 --- a/wxdata/include/scwx/wsr88d/ar2v_file.hpp +++ b/wxdata/include/scwx/wsr88d/ar2v_file.hpp @@ -32,9 +32,6 @@ public: Ar2vFile(Ar2vFile&&) noexcept; Ar2vFile& operator=(Ar2vFile&&) noexcept; - Ar2vFile(const std::shared_ptr& current, - const std::shared_ptr& last); - std::uint32_t julian_date() const; std::uint32_t milliseconds() const; std::string icao() const; @@ -56,9 +53,6 @@ public: bool LoadFile(const std::string& filename); bool LoadData(std::istream& is); - bool LoadLDMRecords(std::istream& is); - bool IndexFile(); - private: std::unique_ptr p; }; diff --git a/wxdata/include/scwx/wsr88d/rda/digital_radar_data_generic.hpp b/wxdata/include/scwx/wsr88d/rda/digital_radar_data_generic.hpp index 0441f17a..ba911898 100644 --- a/wxdata/include/scwx/wsr88d/rda/digital_radar_data_generic.hpp +++ b/wxdata/include/scwx/wsr88d/rda/digital_radar_data_generic.hpp @@ -2,7 +2,11 @@ #include -namespace scwx::wsr88d::rda +namespace scwx +{ +namespace wsr88d +{ +namespace rda { class DigitalRadarDataGeneric : public GenericRadarData @@ -23,31 +27,30 @@ public: DigitalRadarDataGeneric(DigitalRadarDataGeneric&&) noexcept; DigitalRadarDataGeneric& operator=(DigitalRadarDataGeneric&&) noexcept; - [[nodiscard]] std::string radar_identifier() const; - [[nodiscard]] std::uint32_t collection_time() const override; - [[nodiscard]] std::uint16_t modified_julian_date() const override; - [[nodiscard]] std::uint16_t azimuth_number() const override; - [[nodiscard]] units::degrees azimuth_angle() const override; - [[nodiscard]] std::uint8_t compression_indicator() const; - [[nodiscard]] std::uint16_t radial_length() const; - [[nodiscard]] std::uint8_t azimuth_resolution_spacing() const; - [[nodiscard]] std::uint8_t radial_status() const; - [[nodiscard]] std::uint16_t elevation_number() const override; - [[nodiscard]] std::uint8_t cut_sector_number() const; - [[nodiscard]] units::degrees elevation_angle() const; - [[nodiscard]] std::uint8_t radial_spot_blanking_status() const; - [[nodiscard]] std::uint8_t azimuth_indexing_mode() const; - [[nodiscard]] std::uint16_t data_block_count() const; - [[nodiscard]] std::uint16_t volume_coverage_pattern_number() const override; + std::string radar_identifier() const; + std::uint32_t collection_time() const; + std::uint16_t modified_julian_date() const; + std::uint16_t azimuth_number() const; + units::degrees azimuth_angle() const; + std::uint8_t compression_indicator() const; + std::uint16_t radial_length() const; + std::uint8_t azimuth_resolution_spacing() const; + std::uint8_t radial_status() const; + std::uint16_t elevation_number() const; + std::uint8_t cut_sector_number() const; + units::degrees elevation_angle() const; + std::uint8_t radial_spot_blanking_status() const; + std::uint8_t azimuth_indexing_mode() const; + std::uint16_t data_block_count() const; + std::uint16_t volume_coverage_pattern_number() const; - [[nodiscard]] std::shared_ptr - elevation_data_block() const; - [[nodiscard]] std::shared_ptr radial_data_block() const; - [[nodiscard]] std::shared_ptr volume_data_block() const; - [[nodiscard]] std::shared_ptr - moment_data_block(DataBlockType type) const override; + std::shared_ptr elevation_data_block() const; + std::shared_ptr radial_data_block() const; + std::shared_ptr volume_data_block() const; + std::shared_ptr + moment_data_block(DataBlockType type) const; - bool Parse(std::istream& is) override; + bool Parse(std::istream& is); static std::shared_ptr Create(Level2MessageHeader&& header, std::istream& is); @@ -62,14 +65,11 @@ class DigitalRadarDataGeneric::DataBlock protected: explicit DataBlock(const std::string& dataBlockType, const std::string& dataName); - -public: virtual ~DataBlock(); DataBlock(const DataBlock&) = delete; DataBlock& operator=(const DataBlock&) = delete; -protected: DataBlock(DataBlock&&) noexcept; DataBlock& operator=(DataBlock&&) noexcept; @@ -118,19 +118,17 @@ public: MomentDataBlock(MomentDataBlock&&) noexcept; MomentDataBlock& operator=(MomentDataBlock&&) noexcept; - [[nodiscard]] std::uint16_t number_of_data_moment_gates() const override; - [[nodiscard]] units::kilometers data_moment_range() const override; - [[nodiscard]] std::int16_t data_moment_range_raw() const override; - [[nodiscard]] units::kilometers - data_moment_range_sample_interval() const override; - [[nodiscard]] std::uint16_t - data_moment_range_sample_interval_raw() const override; - [[nodiscard]] float snr_threshold() const; - [[nodiscard]] std::int16_t snr_threshold_raw() const override; - [[nodiscard]] std::uint8_t data_word_size() const override; - [[nodiscard]] float scale() const override; - [[nodiscard]] float offset() const override; - [[nodiscard]] const void* data_moments() const override; + std::uint16_t number_of_data_moment_gates() const; + units::kilometers data_moment_range() const; + std::int16_t data_moment_range_raw() const; + units::kilometers data_moment_range_sample_interval() const; + std::uint16_t data_moment_range_sample_interval_raw() const; + float snr_threshold() const; + std::int16_t snr_threshold_raw() const; + std::uint8_t data_word_size() const; + float scale() const; + float offset() const; + const void* data_moments() const; static std::shared_ptr Create(const std::string& dataBlockType, @@ -157,7 +155,7 @@ public: RadialDataBlock(RadialDataBlock&&) noexcept; RadialDataBlock& operator=(RadialDataBlock&&) noexcept; - [[nodiscard]] float unambiguous_range() const; + float unambiguous_range() const; static std::shared_ptr Create(const std::string& dataBlockType, @@ -184,9 +182,9 @@ public: VolumeDataBlock(VolumeDataBlock&&) noexcept; VolumeDataBlock& operator=(VolumeDataBlock&&) noexcept; - [[nodiscard]] float latitude() const; - [[nodiscard]] float longitude() const; - [[nodiscard]] std::uint16_t volume_coverage_pattern_number() const; + float latitude() const; + float longitude() const; + std::uint16_t volume_coverage_pattern_number() const; static std::shared_ptr Create(const std::string& dataBlockType, @@ -200,4 +198,6 @@ private: bool Parse(std::istream& is); }; -} // namespace scwx::wsr88d::rda +} // namespace rda +} // namespace wsr88d +} // namespace scwx diff --git a/wxdata/include/scwx/wsr88d/rda/level2_message_factory.hpp b/wxdata/include/scwx/wsr88d/rda/level2_message_factory.hpp index ac2b8234..7359e72b 100644 --- a/wxdata/include/scwx/wsr88d/rda/level2_message_factory.hpp +++ b/wxdata/include/scwx/wsr88d/rda/level2_message_factory.hpp @@ -2,19 +2,28 @@ #include -namespace scwx::wsr88d::rda +namespace scwx +{ +namespace wsr88d +{ +namespace rda { struct Level2MessageInfo { - std::shared_ptr message {nullptr}; - bool headerValid {false}; - bool messageValid {false}; + std::shared_ptr message; + bool headerValid; + bool messageValid; + + Level2MessageInfo() : + message(nullptr), headerValid(false), messageValid(false) + { + } }; class Level2MessageFactory { -public: +private: explicit Level2MessageFactory() = delete; ~Level2MessageFactory() = delete; @@ -24,6 +33,7 @@ public: Level2MessageFactory(Level2MessageFactory&&) noexcept = delete; Level2MessageFactory& operator=(Level2MessageFactory&&) noexcept = delete; +public: struct Context; static std::shared_ptr CreateContext(); @@ -31,4 +41,6 @@ public: std::shared_ptr& ctx); }; -} // namespace scwx::wsr88d::rda +} // namespace rda +} // namespace wsr88d +} // namespace scwx diff --git a/wxdata/include/scwx/wsr88d/rda/performance_maintenance_data.hpp b/wxdata/include/scwx/wsr88d/rda/performance_maintenance_data.hpp index c1bf3869..8e1c91ea 100644 --- a/wxdata/include/scwx/wsr88d/rda/performance_maintenance_data.hpp +++ b/wxdata/include/scwx/wsr88d/rda/performance_maintenance_data.hpp @@ -2,8 +2,14 @@ #include -namespace scwx::wsr88d::rda +namespace scwx { +namespace wsr88d +{ +namespace rda +{ + +class PerformanceMaintenanceDataImpl; class PerformanceMaintenanceData : public Level2Message { @@ -18,261 +24,267 @@ public: PerformanceMaintenanceData(PerformanceMaintenanceData&&) noexcept; PerformanceMaintenanceData& operator=(PerformanceMaintenanceData&&) noexcept; - [[nodiscard]] std::uint16_t loop_back_set_status() const; - [[nodiscard]] std::uint32_t t1_output_frames() const; - [[nodiscard]] std::uint32_t t1_input_frames() const; - [[nodiscard]] std::uint32_t router_memory_used() const; - [[nodiscard]] std::uint32_t router_memory_free() const; - [[nodiscard]] std::uint16_t router_memory_utilization() const; - [[nodiscard]] std::uint16_t route_to_rpg() const; - [[nodiscard]] std::uint16_t t1_port_status() const; - [[nodiscard]] std::uint16_t router_dedicated_ethernet_port_status() const; - [[nodiscard]] std::uint16_t router_commercial_ethernet_port_status() const; - [[nodiscard]] std::uint32_t csu_24hr_errored_seconds() const; - [[nodiscard]] std::uint32_t csu_24hr_severely_errored_seconds() const; - [[nodiscard]] std::uint32_t - csu_24hr_severely_errored_framing_seconds() const; - [[nodiscard]] std::uint32_t csu_24hr_unavailable_seconds() const; - [[nodiscard]] std::uint32_t csu_24hr_controlled_slip_seconds() const; - [[nodiscard]] std::uint32_t csu_24hr_path_coding_violations() const; - [[nodiscard]] std::uint32_t csu_24hr_line_errored_seconds() const; - [[nodiscard]] std::uint32_t csu_24hr_bursty_errored_seconds() const; - [[nodiscard]] std::uint32_t csu_24hr_degraded_minutes() const; - [[nodiscard]] std::uint32_t lan_switch_cpu_utilization() const; - [[nodiscard]] std::uint16_t lan_switch_memory_utilization() const; - [[nodiscard]] std::uint16_t ifdr_chasis_temperature() const; - [[nodiscard]] std::uint16_t ifdr_fpga_temperature() const; - [[nodiscard]] std::uint16_t ntp_status() const; - [[nodiscard]] std::uint16_t ipc_status() const; - [[nodiscard]] std::uint16_t commanded_channel_control() const; - [[nodiscard]] std::uint16_t polarization() const; - [[nodiscard]] float ame_internal_temperature() const; - [[nodiscard]] float ame_receiver_module_temperature() const; - [[nodiscard]] float ame_bite_cal_module_temperature() const; - [[nodiscard]] std::uint16_t ame_peltier_pulse_width_modulation() const; - [[nodiscard]] std::uint16_t ame_peltier_status() const; - [[nodiscard]] std::uint16_t ame_a_d_converter_status() const; - [[nodiscard]] std::uint16_t ame_state() const; - [[nodiscard]] float ame_3_3v_ps_voltage() const; - [[nodiscard]] float ame_5v_ps_voltage() const; - [[nodiscard]] float ame_6_5v_ps_voltage() const; - [[nodiscard]] float ame_15v_ps_voltage() const; - [[nodiscard]] float ame_48v_ps_voltage() const; - [[nodiscard]] float ame_stalo_power() const; - [[nodiscard]] float peltier_current() const; - [[nodiscard]] float adc_calibration_reference_voltage() const; - [[nodiscard]] std::uint16_t ame_mode() const; - [[nodiscard]] std::uint16_t ame_peltier_mode() const; - [[nodiscard]] float ame_peltier_inside_fan_current() const; - [[nodiscard]] float ame_peltier_outside_fan_current() const; - [[nodiscard]] float horizontal_tr_limiter_voltage() const; - [[nodiscard]] float vertical_tr_limiter_voltage() const; - [[nodiscard]] float adc_calibration_offset_voltage() const; - [[nodiscard]] float adc_calibration_gain_correction() const; - [[nodiscard]] std::uint16_t rcp_status() const; - [[nodiscard]] std::string rcp_string() const; - [[nodiscard]] std::uint16_t spip_power_buttons() const; - [[nodiscard]] float master_power_administrator_load() const; - [[nodiscard]] float expansion_power_administrator_load() const; - [[nodiscard]] std::uint16_t _5vdc_ps() const; - [[nodiscard]] std::uint16_t _15vdc_ps() const; - [[nodiscard]] std::uint16_t _28vdc_ps() const; - [[nodiscard]] std::uint16_t neg_15vdc_ps() const; - [[nodiscard]] std::uint16_t _45vdc_ps() const; - [[nodiscard]] std::uint16_t filament_ps_voltage() const; - [[nodiscard]] std::uint16_t vacuum_pump_ps_voltage() const; - [[nodiscard]] std::uint16_t focus_coil_ps_voltage() const; - [[nodiscard]] std::uint16_t filament_ps() const; - [[nodiscard]] std::uint16_t klystron_warmup() const; - [[nodiscard]] std::uint16_t transmitter_available() const; - [[nodiscard]] std::uint16_t wg_switch_position() const; - [[nodiscard]] std::uint16_t wg_pfn_transfer_interlock() const; - [[nodiscard]] std::uint16_t maintenance_mode() const; - [[nodiscard]] std::uint16_t maintenance_required() const; - [[nodiscard]] std::uint16_t pfn_switch_position() const; - [[nodiscard]] std::uint16_t modulator_overload() const; - [[nodiscard]] std::uint16_t modulator_inv_current() const; - [[nodiscard]] std::uint16_t modulator_switch_fail() const; - [[nodiscard]] std::uint16_t main_power_voltage() const; - [[nodiscard]] std::uint16_t charging_system_fail() const; - [[nodiscard]] std::uint16_t inverse_diode_current() const; - [[nodiscard]] std::uint16_t trigger_amplifier() const; - [[nodiscard]] std::uint16_t circulator_temperature() const; - [[nodiscard]] std::uint16_t spectrum_filter_pressure() const; - [[nodiscard]] std::uint16_t wg_arc_vswr() const; - [[nodiscard]] std::uint16_t cabinet_interlock() const; - [[nodiscard]] std::uint16_t cabinet_air_temperature() const; - [[nodiscard]] std::uint16_t cabinet_airflow() const; - [[nodiscard]] std::uint16_t klystron_current() const; - [[nodiscard]] std::uint16_t klystron_filament_current() const; - [[nodiscard]] std::uint16_t klystron_vacion_current() const; - [[nodiscard]] std::uint16_t klystron_air_temperature() const; - [[nodiscard]] std::uint16_t klystron_airflow() const; - [[nodiscard]] std::uint16_t modulator_switch_maintenance() const; - [[nodiscard]] std::uint16_t post_charge_regulator_maintenance() const; - [[nodiscard]] std::uint16_t wg_pressure_humidity() const; - [[nodiscard]] std::uint16_t transmitter_overvoltage() const; - [[nodiscard]] std::uint16_t transmitter_overcurrent() const; - [[nodiscard]] std::uint16_t focus_coil_current() const; - [[nodiscard]] std::uint16_t focus_coil_airflow() const; - [[nodiscard]] std::uint16_t oil_temperature() const; - [[nodiscard]] std::uint16_t prf_limit() const; - [[nodiscard]] std::uint16_t transmitter_oil_level() const; - [[nodiscard]] std::uint16_t transmitter_battery_charging() const; - [[nodiscard]] std::uint16_t high_voltage_status() const; - [[nodiscard]] std::uint16_t transmitter_recycling_summary() const; - [[nodiscard]] std::uint16_t transmitter_inoperable() const; - [[nodiscard]] std::uint16_t transmitter_air_filter() const; - [[nodiscard]] std::uint16_t zero_test_bit(unsigned i) const; - [[nodiscard]] std::uint16_t one_test_bit(unsigned i) const; - [[nodiscard]] std::uint16_t xmtr_spip_interface() const; - [[nodiscard]] std::uint16_t transmitter_summary_status() const; - [[nodiscard]] float transmitter_rf_power() const; - [[nodiscard]] float horizontal_xmtr_peak_power() const; - [[nodiscard]] float xmtr_peak_power() const; - [[nodiscard]] float vertical_xmtr_peak_power() const; - [[nodiscard]] float xmtr_rf_avg_power() const; - [[nodiscard]] std::uint32_t xmtr_recycle_count() const; - [[nodiscard]] float receiver_bias() const; - [[nodiscard]] float transmit_imbalance() const; - [[nodiscard]] float xmtr_power_meter_zero() const; - [[nodiscard]] std::uint16_t ac_unit1_compressor_shut_off() const; - [[nodiscard]] std::uint16_t ac_unit2_compressor_shut_off() const; - [[nodiscard]] std::uint16_t generator_maintenance_required() const; - [[nodiscard]] std::uint16_t generator_battery_voltage() const; - [[nodiscard]] std::uint16_t generator_engine() const; - [[nodiscard]] std::uint16_t generator_volt_frequency() const; - [[nodiscard]] std::uint16_t power_source() const; - [[nodiscard]] std::uint16_t transitional_power_source() const; - [[nodiscard]] std::uint16_t generator_auto_run_off_switch() const; - [[nodiscard]] std::uint16_t aircraft_hazard_lighting() const; - [[nodiscard]] std::uint16_t equipment_shelter_fire_detection_system() const; - [[nodiscard]] std::uint16_t equipment_shelter_fire_smoke() const; - [[nodiscard]] std::uint16_t generator_shelter_fire_smoke() const; - [[nodiscard]] std::uint16_t utility_voltage_frequency() const; - [[nodiscard]] std::uint16_t site_security_alarm() const; - [[nodiscard]] std::uint16_t security_equipment() const; - [[nodiscard]] std::uint16_t security_system() const; - [[nodiscard]] std::uint16_t receiver_connected_to_antenna() const; - [[nodiscard]] std::uint16_t radome_hatch() const; - [[nodiscard]] std::uint16_t ac_unit1_filter_dirty() const; - [[nodiscard]] std::uint16_t ac_unit2_filter_dirty() const; - [[nodiscard]] float equipment_shelter_temperature() const; - [[nodiscard]] float outside_ambient_temperature() const; - [[nodiscard]] float transmitter_leaving_air_temp() const; - [[nodiscard]] float ac_unit1_discharge_air_temp() const; - [[nodiscard]] float generator_shelter_temperature() const; - [[nodiscard]] float radome_air_temperature() const; - [[nodiscard]] float ac_unit2_discharge_air_temp() const; - [[nodiscard]] float spip_15v_ps() const; - [[nodiscard]] float spip_neg_15v_ps() const; - [[nodiscard]] std::uint16_t spip_28v_ps_status() const; - [[nodiscard]] float spip_5v_ps() const; - [[nodiscard]] std::uint16_t converted_generator_fuel_level() const; - [[nodiscard]] std::uint16_t elevation_pos_dead_limit() const; - [[nodiscard]] std::uint16_t _150v_overvoltage() const; - [[nodiscard]] std::uint16_t _150v_undervoltage() const; - [[nodiscard]] std::uint16_t elevation_servo_amp_inhibit() const; - [[nodiscard]] std::uint16_t elevation_servo_amp_short_circuit() const; - [[nodiscard]] std::uint16_t elevation_servo_amp_overtemp() const; - [[nodiscard]] std::uint16_t elevation_motor_overtemp() const; - [[nodiscard]] std::uint16_t elevation_stow_pin() const; - [[nodiscard]] std::uint16_t elevation_housing_5v_ps() const; - [[nodiscard]] std::uint16_t elevation_neg_dead_limit() const; - [[nodiscard]] std::uint16_t elevation_pos_normal_limit() const; - [[nodiscard]] std::uint16_t elevation_neg_normal_limit() const; - [[nodiscard]] std::uint16_t elevation_encoder_light() const; - [[nodiscard]] std::uint16_t elevation_gearbox_oil() const; - [[nodiscard]] std::uint16_t elevation_handwheel() const; - [[nodiscard]] std::uint16_t elevation_amp_ps() const; - [[nodiscard]] std::uint16_t azimuth_servo_amp_inhibit() const; - [[nodiscard]] std::uint16_t azimuth_servo_amp_short_circuit() const; - [[nodiscard]] std::uint16_t azimuth_servo_amp_overtemp() const; - [[nodiscard]] std::uint16_t azimuth_motor_overtemp() const; - [[nodiscard]] std::uint16_t azimuth_stow_pin() const; - [[nodiscard]] std::uint16_t azimuth_housing_5v_ps() const; - [[nodiscard]] std::uint16_t azimuth_encoder_light() const; - [[nodiscard]] std::uint16_t azimuth_gearbox_oil() const; - [[nodiscard]] std::uint16_t azimuth_bull_gear_oil() const; - [[nodiscard]] std::uint16_t azimuth_handwheel() const; - [[nodiscard]] std::uint16_t azimuth_servo_amp_ps() const; - [[nodiscard]] std::uint16_t servo() const; - [[nodiscard]] std::uint16_t pedestal_interlock_switch() const; - [[nodiscard]] std::uint16_t coho_clock() const; - [[nodiscard]] std::uint16_t rf_generator_frequency_select_oscillator() const; - [[nodiscard]] std::uint16_t rf_generator_rf_stalo() const; - [[nodiscard]] std::uint16_t rf_generator_phase_shifted_coho() const; - [[nodiscard]] std::uint16_t _9v_receiver_ps() const; - [[nodiscard]] std::uint16_t _5v_receiver_ps() const; - [[nodiscard]] std::uint16_t _18v_receiver_ps() const; - [[nodiscard]] std::uint16_t neg_9v_receiver_ps() const; - [[nodiscard]] std::uint16_t _5v_single_channel_rdaiu_ps() const; - [[nodiscard]] float horizontal_short_pulse_noise() const; - [[nodiscard]] float horizontal_long_pulse_noise() const; - [[nodiscard]] float horizontal_noise_temperature() const; - [[nodiscard]] float vertical_short_pulse_noise() const; - [[nodiscard]] float vertical_long_pulse_noise() const; - [[nodiscard]] float vertical_noise_temperature() const; - [[nodiscard]] float horizontal_linearity() const; - [[nodiscard]] float horizontal_dynamic_range() const; - [[nodiscard]] float horizontal_delta_dbz0() const; - [[nodiscard]] float vertical_delta_dbz0() const; - [[nodiscard]] float kd_peak_measured() const; - [[nodiscard]] float short_pulse_horizontal_dbz0() const; - [[nodiscard]] float long_pulse_horizontal_dbz0() const; - [[nodiscard]] std::uint16_t velocity_processed() const; - [[nodiscard]] std::uint16_t width_processed() const; - [[nodiscard]] std::uint16_t velocity_rf_gen() const; - [[nodiscard]] std::uint16_t width_rf_gen() const; - [[nodiscard]] float horizontal_i0() const; - [[nodiscard]] float vertical_i0() const; - [[nodiscard]] float vertical_dynamic_range() const; - [[nodiscard]] float short_pulse_vertical_dbz0() const; - [[nodiscard]] float long_pulse_vertical_dbz0() const; - [[nodiscard]] float horizontal_power_sense() const; - [[nodiscard]] float vertical_power_sense() const; - [[nodiscard]] float zdr_offset() const; - [[nodiscard]] float clutter_suppression_delta() const; - [[nodiscard]] float clutter_suppression_unfiltered_power() const; - [[nodiscard]] float clutter_suppression_filtered_power() const; - [[nodiscard]] float vertical_linearity() const; - [[nodiscard]] std::uint16_t state_file_read_status() const; - [[nodiscard]] std::uint16_t state_file_write_status() const; - [[nodiscard]] std::uint16_t bypass_map_file_read_status() const; - [[nodiscard]] std::uint16_t bypass_map_file_write_status() const; - [[nodiscard]] std::uint16_t current_adaptation_file_read_status() const; - [[nodiscard]] std::uint16_t current_adaptation_file_write_status() const; - [[nodiscard]] std::uint16_t censor_zone_file_read_status() const; - [[nodiscard]] std::uint16_t censor_zone_file_write_status() const; - [[nodiscard]] std::uint16_t remote_vcp_file_read_status() const; - [[nodiscard]] std::uint16_t remote_vcp_file_write_status() const; - [[nodiscard]] std::uint16_t baseline_adaptation_file_read_status() const; - [[nodiscard]] std::uint16_t read_status_of_prf_sets() const; - [[nodiscard]] std::uint16_t clutter_filter_map_file_read_status() const; - [[nodiscard]] std::uint16_t clutter_filter_map_file_write_status() const; - [[nodiscard]] std::uint16_t general_disk_io_error() const; - [[nodiscard]] std::uint8_t rsp_status() const; - [[nodiscard]] std::uint8_t cpu1_temperature() const; - [[nodiscard]] std::uint8_t cpu2_temperature() const; - [[nodiscard]] std::uint16_t rsp_motherboard_power() const; - [[nodiscard]] std::uint16_t spip_comm_status() const; - [[nodiscard]] std::uint16_t hci_comm_status() const; - [[nodiscard]] std::uint16_t signal_processor_command_status() const; - [[nodiscard]] std::uint16_t ame_communication_status() const; - [[nodiscard]] std::uint16_t rms_link_status() const; - [[nodiscard]] std::uint16_t rpg_link_status() const; - [[nodiscard]] std::uint16_t interpanel_link_status() const; - [[nodiscard]] std::uint32_t performance_check_time() const; - [[nodiscard]] std::uint16_t version() const; + uint16_t loop_back_set_status() const; + uint32_t t1_output_frames() const; + uint32_t t1_input_frames() const; + uint32_t router_memory_used() const; + uint32_t router_memory_free() const; + uint16_t router_memory_utilization() const; + uint16_t route_to_rpg() const; + uint32_t csu_loss_of_signal() const; + uint32_t csu_loss_of_frames() const; + uint32_t csu_yellow_alarms() const; + uint32_t csu_blue_alarms() const; + uint32_t csu_24hr_errored_seconds() const; + uint32_t csu_24hr_severely_errored_seconds() const; + uint32_t csu_24hr_severely_errored_framing_seconds() const; + uint32_t csu_24hr_unavailable_seconds() const; + uint32_t csu_24hr_controlled_slip_seconds() const; + uint32_t csu_24hr_path_coding_violations() const; + uint32_t csu_24hr_line_errored_seconds() const; + uint32_t csu_24hr_bursty_errored_seconds() const; + uint32_t csu_24hr_degraded_minutes() const; + uint32_t lan_switch_cpu_utilization() const; + uint16_t lan_switch_memory_utilization() const; + uint16_t ifdr_chasis_temperature() const; + uint16_t ifdr_fpga_temperature() const; + int32_t gps_satellites() const; + uint16_t ipc_status() const; + uint16_t commanded_channel_control() const; + uint16_t polarization() const; + float ame_internal_temperature() const; + float ame_receiver_module_temperature() const; + float ame_bite_cal_module_temperature() const; + uint16_t ame_peltier_pulse_width_modulation() const; + uint16_t ame_peltier_status() const; + uint16_t ame_a_d_converter_status() const; + uint16_t ame_state() const; + float ame_3_3v_ps_voltage() const; + float ame_5v_ps_voltage() const; + float ame_6_5v_ps_voltage() const; + float ame_15v_ps_voltage() const; + float ame_48v_ps_voltage() const; + float ame_stalo_power() const; + float peltier_current() const; + float adc_calibration_reference_voltage() const; + uint16_t ame_mode() const; + uint16_t ame_peltier_mode() const; + float ame_peltier_inside_fan_current() const; + float ame_peltier_outside_fan_current() const; + float horizontal_tr_limiter_voltage() const; + float vertical_tr_limiter_voltage() const; + float adc_calibration_offset_voltage() const; + float adc_calibration_gain_correction() const; + uint16_t rcp_status() const; + std::string rcp_string() const; + uint16_t spip_power_buttons() const; + float master_power_administrator_load() const; + float expansion_power_administrator_load() const; + uint16_t _5vdc_ps() const; + uint16_t _15vdc_ps() const; + uint16_t _28vdc_ps() const; + uint16_t neg_15vdc_ps() const; + uint16_t _45vdc_ps() const; + uint16_t filament_ps_voltage() const; + uint16_t vacuum_pump_ps_voltage() const; + uint16_t focus_coil_ps_voltage() const; + uint16_t filament_ps() const; + uint16_t klystron_warmup() const; + uint16_t transmitter_available() const; + uint16_t wg_switch_position() const; + uint16_t wg_pfn_transfer_interlock() const; + uint16_t maintenance_mode() const; + uint16_t maintenance_required() const; + uint16_t pfn_switch_position() const; + uint16_t modulator_overload() const; + uint16_t modulator_inv_current() const; + uint16_t modulator_switch_fail() const; + uint16_t main_power_voltage() const; + uint16_t charging_system_fail() const; + uint16_t inverse_diode_current() const; + uint16_t trigger_amplifier() const; + uint16_t circulator_temperature() const; + uint16_t spectrum_filter_pressure() const; + uint16_t wg_arc_vswr() const; + uint16_t cabinet_interlock() const; + uint16_t cabinet_air_temperature() const; + uint16_t cabinet_airflow() const; + uint16_t klystron_current() const; + uint16_t klystron_filament_current() const; + uint16_t klystron_vacion_current() const; + uint16_t klystron_air_temperature() const; + uint16_t klystron_airflow() const; + uint16_t modulator_switch_maintenance() const; + uint16_t post_charge_regulator_maintenance() const; + uint16_t wg_pressure_humidity() const; + uint16_t transmitter_overvoltage() const; + uint16_t transmitter_overcurrent() const; + uint16_t focus_coil_current() const; + uint16_t focus_coil_airflow() const; + uint16_t oil_temperature() const; + uint16_t prf_limit() const; + uint16_t transmitter_oil_level() const; + uint16_t transmitter_battery_charging() const; + uint16_t high_voltage_status() const; + uint16_t transmitter_recycling_summary() const; + uint16_t transmitter_inoperable() const; + uint16_t transmitter_air_filter() const; + uint16_t zero_test_bit(unsigned i) const; + uint16_t one_test_bit(unsigned i) const; + uint16_t xmtr_spip_interface() const; + uint16_t transmitter_summary_status() const; + float transmitter_rf_power() const; + float horizontal_xmtr_peak_power() const; + float xmtr_peak_power() const; + float vertical_xmtr_peak_power() const; + float xmtr_rf_avg_power() const; + uint32_t xmtr_recycle_count() const; + float receiver_bias() const; + float transmit_imbalance() const; + float xmtr_power_meter_zero() const; + uint16_t ac_unit1_compressor_shut_off() const; + uint16_t ac_unit2_compressor_shut_off() const; + uint16_t generator_maintenance_required() const; + uint16_t generator_battery_voltage() const; + uint16_t generator_engine() const; + uint16_t generator_volt_frequency() const; + uint16_t power_source() const; + uint16_t transitional_power_source() const; + uint16_t generator_auto_run_off_switch() const; + uint16_t aircraft_hazard_lighting() const; + uint16_t equipment_shelter_fire_detection_system() const; + uint16_t equipment_shelter_fire_smoke() const; + uint16_t generator_shelter_fire_smoke() const; + uint16_t utility_voltage_frequency() const; + uint16_t site_security_alarm() const; + uint16_t security_equipment() const; + uint16_t security_system() const; + uint16_t receiver_connected_to_antenna() const; + uint16_t radome_hatch() const; + uint16_t ac_unit1_filter_dirty() const; + uint16_t ac_unit2_filter_dirty() const; + float equipment_shelter_temperature() const; + float outside_ambient_temperature() const; + float transmitter_leaving_air_temp() const; + float ac_unit1_discharge_air_temp() const; + float generator_shelter_temperature() const; + float radome_air_temperature() const; + float ac_unit2_discharge_air_temp() const; + float spip_15v_ps() const; + float spip_neg_15v_ps() const; + uint16_t spip_28v_ps_status() const; + float spip_5v_ps() const; + uint16_t converted_generator_fuel_level() const; + uint16_t elevation_pos_dead_limit() const; + uint16_t _150v_overvoltage() const; + uint16_t _150v_undervoltage() const; + uint16_t elevation_servo_amp_inhibit() const; + uint16_t elevation_servo_amp_short_circuit() const; + uint16_t elevation_servo_amp_overtemp() const; + uint16_t elevation_motor_overtemp() const; + uint16_t elevation_stow_pin() const; + uint16_t elevation_housing_5v_ps() const; + uint16_t elevation_neg_dead_limit() const; + uint16_t elevation_pos_normal_limit() const; + uint16_t elevation_neg_normal_limit() const; + uint16_t elevation_encoder_light() const; + uint16_t elevation_gearbox_oil() const; + uint16_t elevation_handwheel() const; + uint16_t elevation_amp_ps() const; + uint16_t azimuth_servo_amp_inhibit() const; + uint16_t azimuth_servo_amp_short_circuit() const; + uint16_t azimuth_servo_amp_overtemp() const; + uint16_t azimuth_motor_overtemp() const; + uint16_t azimuth_stow_pin() const; + uint16_t azimuth_housing_5v_ps() const; + uint16_t azimuth_encoder_light() const; + uint16_t azimuth_gearbox_oil() const; + uint16_t azimuth_bull_gear_oil() const; + uint16_t azimuth_handwheel() const; + uint16_t azimuth_servo_amp_ps() const; + uint16_t servo() const; + uint16_t pedestal_interlock_switch() const; + uint16_t coho_clock() const; + uint16_t rf_generator_frequency_select_oscillator() const; + uint16_t rf_generator_rf_stalo() const; + uint16_t rf_generator_phase_shifted_coho() const; + uint16_t _9v_receiver_ps() const; + uint16_t _5v_receiver_ps() const; + uint16_t _18v_receiver_ps() const; + uint16_t neg_9v_receiver_ps() const; + uint16_t _5v_single_channel_rdaiu_ps() const; + float horizontal_short_pulse_noise() const; + float horizontal_long_pulse_noise() const; + float horizontal_noise_temperature() const; + float vertical_short_pulse_noise() const; + float vertical_long_pulse_noise() const; + float vertical_noise_temperature() const; + float horizontal_linearity() const; + float horizontal_dynamic_range() const; + float horizontal_delta_dbz0() const; + float vertical_delta_dbz0() const; + float kd_peak_measured() const; + float short_pulse_horizontal_dbz0() const; + float long_pulse_horizontal_dbz0() const; + uint16_t velocity_processed() const; + uint16_t width_processed() const; + uint16_t velocity_rf_gen() const; + uint16_t width_rf_gen() const; + float horizontal_i0() const; + float vertical_i0() const; + float vertical_dynamic_range() const; + float short_pulse_vertical_dbz0() const; + float long_pulse_vertical_dbz0() const; + float horizontal_power_sense() const; + float vertical_power_sense() const; + float zdr_bias() const; + float clutter_suppression_delta() const; + float clutter_suppression_unfiltered_power() const; + float clutter_suppression_filtered_power() const; + float vertical_linearity() const; + uint16_t state_file_read_status() const; + uint16_t state_file_write_status() const; + uint16_t bypass_map_file_read_status() const; + uint16_t bypass_map_file_write_status() const; + uint16_t current_adaptation_file_read_status() const; + uint16_t current_adaptation_file_write_status() const; + uint16_t censor_zone_file_read_status() const; + uint16_t censor_zone_file_write_status() const; + uint16_t remote_vcp_file_read_status() const; + uint16_t remote_vcp_file_write_status() const; + uint16_t baseline_adaptation_file_read_status() const; + uint16_t read_status_of_prf_sets() const; + uint16_t clutter_filter_map_file_read_status() const; + uint16_t clutter_filter_map_file_write_status() const; + uint16_t generatl_disk_io_error() const; + uint8_t rsp_status() const; + uint8_t motherboard_temperature() const; + uint8_t cpu1_temperature() const; + uint8_t cpu2_temperature() const; + uint16_t cpu1_fan_speed() const; + uint16_t cpu2_fan_speed() const; + uint16_t rsp_fan1_speed() const; + uint16_t rsp_fan2_speed() const; + uint16_t rsp_fan3_speed() const; + uint16_t spip_comm_status() const; + uint16_t hci_comm_status() const; + uint16_t signal_processor_command_status() const; + uint16_t ame_communication_status() const; + uint16_t rms_link_status() const; + uint16_t rpg_link_status() const; + uint16_t interpanel_link_status() const; + uint32_t performance_check_time() const; + uint16_t version() const; - bool Parse(std::istream& is) override; + bool Parse(std::istream& is); static std::shared_ptr Create(Level2MessageHeader&& header, std::istream& is); private: - class Impl; - std::unique_ptr p; + std::unique_ptr p; }; -} // namespace scwx::wsr88d::rda +} // namespace rda +} // namespace wsr88d +} // namespace scwx diff --git a/wxdata/include/scwx/wsr88d/rda/rda_adaptation_data.hpp b/wxdata/include/scwx/wsr88d/rda/rda_adaptation_data.hpp index 60520e83..38d519a1 100644 --- a/wxdata/include/scwx/wsr88d/rda/rda_adaptation_data.hpp +++ b/wxdata/include/scwx/wsr88d/rda/rda_adaptation_data.hpp @@ -2,8 +2,14 @@ #include -namespace scwx::wsr88d::rda +namespace scwx { +namespace wsr88d +{ +namespace rda +{ + +class RdaAdaptationDataImpl; class RdaAdaptationData : public Level2Message { @@ -11,205 +17,199 @@ public: explicit RdaAdaptationData(); ~RdaAdaptationData(); - RdaAdaptationData(const RdaAdaptationData&) = delete; + RdaAdaptationData(const RdaAdaptationData&) = delete; RdaAdaptationData& operator=(const RdaAdaptationData&) = delete; RdaAdaptationData(RdaAdaptationData&&) noexcept; RdaAdaptationData& operator=(RdaAdaptationData&&) noexcept; - [[nodiscard]] std::string adap_file_name() const; - [[nodiscard]] std::string adap_format() const; - [[nodiscard]] std::string adap_revision() const; - [[nodiscard]] std::string adap_date() const; - [[nodiscard]] std::string adap_time() const; - [[nodiscard]] float lower_pre_limit() const; - [[nodiscard]] float az_lat() const; - [[nodiscard]] float upper_pre_limit() const; - [[nodiscard]] float el_lat() const; - [[nodiscard]] float parkaz() const; - [[nodiscard]] float parkel() const; - [[nodiscard]] float a_fuel_conv(unsigned i) const; - [[nodiscard]] float a_min_shelter_temp() const; - [[nodiscard]] float a_max_shelter_temp() const; - [[nodiscard]] float a_min_shelter_ac_temp_diff() const; - [[nodiscard]] float a_max_xmtr_air_temp() const; - [[nodiscard]] float a_max_rad_temp() const; - [[nodiscard]] float a_max_rad_temp_rise() const; - [[nodiscard]] float lower_dead_limit() const; - [[nodiscard]] float upper_dead_limit() const; - [[nodiscard]] float a_min_gen_room_temp() const; - [[nodiscard]] float a_max_gen_room_temp() const; - [[nodiscard]] float spip_5v_reg_lim() const; - [[nodiscard]] float spip_15v_reg_lim() const; - [[nodiscard]] bool rpg_co_located() const; - [[nodiscard]] bool spec_filter_installed() const; - [[nodiscard]] bool tps_installed() const; - [[nodiscard]] bool rms_installed() const; - [[nodiscard]] std::uint32_t a_hvdl_tst_int() const; - [[nodiscard]] std::uint32_t a_rpg_lt_int() const; - [[nodiscard]] std::uint32_t a_min_stab_util_pwr_time() const; - [[nodiscard]] std::uint32_t a_gen_auto_exer_interval() const; - [[nodiscard]] std::uint32_t a_util_pwr_sw_req_interval() const; - [[nodiscard]] float a_low_fuel_level() const; - [[nodiscard]] std::uint32_t config_chan_number() const; - [[nodiscard]] std::uint32_t redundant_chan_config() const; - [[nodiscard]] float atten_table(unsigned i) const; - [[nodiscard]] float path_losses(unsigned i) const; - [[nodiscard]] float h_coupler_xmt_loss() const; - [[nodiscard]] float h_coupler_cw_loss() const; - [[nodiscard]] float v_coupler_xmt_loss() const; - [[nodiscard]] float ame_ts_bias() const; - [[nodiscard]] float v_coupler_cw_loss() const; - [[nodiscard]] float pwr_sense_bias() const; - [[nodiscard]] float ame_v_noise_enr() const; - [[nodiscard]] float chan_cal_diff() const; - [[nodiscard]] float v_ts_cw() const; - [[nodiscard]] float h_rnscale(unsigned i) const; - [[nodiscard]] float atmos(unsigned i) const; - [[nodiscard]] float el_index(unsigned i) const; - [[nodiscard]] std::uint32_t tfreq_mhz() const; - [[nodiscard]] float base_data_tcn() const; - [[nodiscard]] float refl_data_tover() const; - [[nodiscard]] float tar_h_dbz0_lp() const; - [[nodiscard]] float tar_v_dbz0_lp() const; - [[nodiscard]] std::uint32_t init_phi_dp() const; - [[nodiscard]] std::uint32_t norm_init_phi_dp() const; - [[nodiscard]] float lx_lp() const; - [[nodiscard]] float lx_sp() const; - [[nodiscard]] float meteor_param() const; - [[nodiscard]] float antenna_gain() const; - [[nodiscard]] float vel_degrad_limit() const; - [[nodiscard]] float wth_degrad_limit() const; - [[nodiscard]] float h_noisetemp_dgrad_limit() const; - [[nodiscard]] std::uint32_t h_min_noisetemp() const; - [[nodiscard]] float v_noisetemp_dgrad_limit() const; - [[nodiscard]] std::uint32_t v_min_noisetemp() const; - [[nodiscard]] float kly_degrade_limit() const; - [[nodiscard]] float ts_coho() const; - [[nodiscard]] float h_ts_cw() const; - [[nodiscard]] float ts_stalo() const; - [[nodiscard]] float ame_h_noise_enr() const; - [[nodiscard]] float xmtr_peak_pwr_high_limit() const; - [[nodiscard]] float xmtr_peak_pwr_low_limit() const; - [[nodiscard]] float h_dbz0_delta_limit() const; - [[nodiscard]] float threshold1() const; - [[nodiscard]] float threshold2() const; - [[nodiscard]] float clut_supp_dgrad_lim() const; - [[nodiscard]] float range0_value() const; - [[nodiscard]] float xmtr_pwr_mtr_scale() const; - [[nodiscard]] float v_dbz0_delta_limit() const; - [[nodiscard]] float tar_h_dbz0_sp() const; - [[nodiscard]] float tar_v_dbz0_sp() const; - [[nodiscard]] std::uint32_t deltaprf() const; - [[nodiscard]] std::uint32_t tau_sp() const; - [[nodiscard]] std::uint32_t tau_lp() const; - [[nodiscard]] std::uint32_t nc_dead_value() const; - [[nodiscard]] std::uint32_t tau_rf_sp() const; - [[nodiscard]] std::uint32_t tau_rf_lp() const; - [[nodiscard]] float seg1_lim() const; - [[nodiscard]] float slatsec() const; - [[nodiscard]] float slonsec() const; - [[nodiscard]] std::uint32_t slatdeg() const; - [[nodiscard]] std::uint32_t slatmin() const; - [[nodiscard]] std::uint32_t slondeg() const; - [[nodiscard]] std::uint32_t slonmin() const; - [[nodiscard]] char slatdir() const; - [[nodiscard]] char slondir() const; - [[nodiscard]] double dig_rcvr_clock_freq() const; - [[nodiscard]] double coho_freq() const; - [[nodiscard]] float az_correction_factor() const; - [[nodiscard]] float el_correction_factor() const; - [[nodiscard]] std::string site_name() const; - [[nodiscard]] float ant_manual_setup_ielmin() const; - [[nodiscard]] float ant_manual_setup_ielmax() const; - [[nodiscard]] std::uint32_t ant_manual_setup_fazvelmax() const; - [[nodiscard]] std::uint32_t ant_manual_setup_felvelmax() const; - [[nodiscard]] std::int32_t ant_manual_setup_ignd_hgt() const; - [[nodiscard]] std::uint32_t ant_manual_setup_irad_hgt() const; - [[nodiscard]] float az_pos_sustain_drive() const; - [[nodiscard]] float az_neg_sustain_drive() const; - [[nodiscard]] float az_nom_pos_drive_slope() const; - [[nodiscard]] float az_nom_neg_drive_slope() const; - [[nodiscard]] float az_feedback_slope() const; - [[nodiscard]] float el_pos_sustain_drive() const; - [[nodiscard]] float el_neg_sustain_drive() const; - [[nodiscard]] float el_nom_pos_drive_slope() const; - [[nodiscard]] float el_nom_neg_drive_slope() const; - [[nodiscard]] float el_feedback_slope() const; - [[nodiscard]] float el_first_slope() const; - [[nodiscard]] float el_second_slope() const; - [[nodiscard]] float el_third_slope() const; - [[nodiscard]] float el_droop_pos() const; - [[nodiscard]] float el_off_neutral_drive() const; - [[nodiscard]] float az_intertia() const; - [[nodiscard]] float el_inertia() const; - [[nodiscard]] float az_stow_angle() const; - [[nodiscard]] float el_stow_angle() const; - [[nodiscard]] float az_encoder_alignment() const; - [[nodiscard]] float el_encoder_alignment() const; - [[nodiscard]] std::string refined_park() const; - [[nodiscard]] std::uint32_t rvp8nv_iwaveguide_length() const; - [[nodiscard]] float v_rnscale(unsigned i) const; - [[nodiscard]] float vel_data_tover() const; - [[nodiscard]] float width_data_tover() const; - [[nodiscard]] float doppler_range_start() const; - [[nodiscard]] std::uint32_t max_el_index() const; - [[nodiscard]] float seg2_lim() const; - [[nodiscard]] float seg3_lim() const; - [[nodiscard]] float seg4_lim() const; - [[nodiscard]] std::uint32_t nbr_el_segments() const; - [[nodiscard]] float h_noise_long() const; - [[nodiscard]] float ant_noise_temp() const; - [[nodiscard]] float h_noise_short() const; - [[nodiscard]] float h_noise_tolerance() const; - [[nodiscard]] float min_h_dyn_range() const; - [[nodiscard]] bool gen_installed() const; - [[nodiscard]] bool gen_exercise() const; - [[nodiscard]] float v_noise_tolerance() const; - [[nodiscard]] float min_v_dyn_range() const; - [[nodiscard]] float zdr_offset_dgrad_lim() const; - [[nodiscard]] float baseline_zdr_offset() const; - [[nodiscard]] float v_noise_long() const; - [[nodiscard]] float v_noise_short() const; - [[nodiscard]] float zdr_data_tover() const; - [[nodiscard]] float phi_data_tover() const; - [[nodiscard]] float rho_data_tover() const; - [[nodiscard]] float stalo_power_dgrad_limit() const; - [[nodiscard]] float stalo_power_maint_limit() const; - [[nodiscard]] float min_h_pwr_sense() const; - [[nodiscard]] float min_v_pwr_sense() const; - [[nodiscard]] float h_pwr_sense_offset() const; - [[nodiscard]] float v_pwr_sense_offset() const; - [[nodiscard]] float ps_gain_ref() const; - [[nodiscard]] float rf_pallet_broad_loss() const; - [[nodiscard]] float ame_ps_tolerance() const; - [[nodiscard]] float ame_max_temp() const; - [[nodiscard]] float ame_min_temp() const; - [[nodiscard]] float rcvr_mod_max_temp() const; - [[nodiscard]] float rcvr_mod_min_temp() const; - [[nodiscard]] float bite_mod_max_temp() const; - [[nodiscard]] float bite_mod_min_temp() const; - [[nodiscard]] std::uint32_t default_polarization() const; - [[nodiscard]] float tr_limit_dgrad_limit() const; - [[nodiscard]] float tr_limit_fail_limit() const; - [[nodiscard]] bool rfp_stepper_enabled() const; - [[nodiscard]] float ame_current_tolerance() const; - [[nodiscard]] std::uint32_t h_only_polarization() const; - [[nodiscard]] std::uint32_t v_only_polarization() const; - [[nodiscard]] float sun_bias() const; - [[nodiscard]] float a_min_shelter_temp_warn() const; - [[nodiscard]] float power_meter_zero() const; - [[nodiscard]] float txb_baseline() const; - [[nodiscard]] float txb_alarm_thresh() const; + std::string adap_file_name() const; + std::string adap_format() const; + std::string adap_revision() const; + std::string adap_date() const; + std::string adap_time() const; + float lower_pre_limit() const; + float az_lat() const; + float upper_pre_limit() const; + float el_lat() const; + float parkaz() const; + float parkel() const; + float a_fuel_conv(unsigned i) const; + float a_min_shelter_temp() const; + float a_max_shelter_temp() const; + float a_min_shelter_ac_temp_diff() const; + float a_max_xmtr_air_temp() const; + float a_max_rad_temp() const; + float a_max_rad_temp_rise() const; + float lower_dead_limit() const; + float upper_dead_limit() const; + float a_min_gen_room_temp() const; + float a_max_gen_room_temp() const; + float spip_5v_reg_lim() const; + float spip_15v_reg_lim() const; + bool rpg_co_located() const; + bool spec_filter_installed() const; + bool tps_installed() const; + bool rms_installed() const; + uint32_t a_hvdl_tst_int() const; + uint32_t a_rpg_lt_int() const; + uint32_t a_min_stab_util_pwr_time() const; + uint32_t a_gen_auto_exer_interval() const; + uint32_t a_util_pwr_sw_req_interval() const; + float a_low_fuel_level() const; + uint32_t config_chan_number() const; + uint32_t redundant_chan_config() const; + float atten_table(unsigned i) const; + float path_losses(unsigned i) const; + float h_coupler_xmt_loss() const; + float h_coupler_cw_loss() const; + float v_coupler_xmt_loss() const; + float ame_ts_bias() const; + float v_coupler_cw_loss() const; + float pwr_sense_bias() const; + float ame_v_noise_enr() const; + float chan_cal_diff() const; + float v_ts_cw() const; + float h_rnscale(unsigned i) const; + float atmos(unsigned i) const; + float el_index(unsigned i) const; + uint32_t tfreq_mhz() const; + float base_data_tcn() const; + float refl_data_tover() const; + float tar_h_dbz0_lp() const; + float tar_v_dbz0_lp() const; + uint32_t init_phi_dp() const; + uint32_t norm_init_phi_dp() const; + float lx_lp() const; + float lx_sp() const; + float meteor_param() const; + float antenna_gain() const; + float vel_degrad_limit() const; + float wth_degrad_limit() const; + float h_noisetemp_dgrad_limit() const; + uint32_t h_min_noisetemp() const; + float v_noisetemp_dgrad_limit() const; + uint32_t v_min_noisetemp() const; + float kly_degrade_limit() const; + float ts_coho() const; + float h_ts_cw() const; + float ts_stalo() const; + float ame_h_noise_enr() const; + float xmtr_peak_pwr_high_limit() const; + float xmtr_peak_pwr_low_limit() const; + float h_dbz0_delta_limit() const; + float threshold1() const; + float threshold2() const; + float clut_supp_dgrad_lim() const; + float range0_value() const; + float xmtr_pwr_mtr_scale() const; + float v_dbz0_delta_limit() const; + float tar_h_dbz0_sp() const; + float tar_v_dbz0_sp() const; + uint32_t deltaprf() const; + uint32_t tau_sp() const; + uint32_t tau_lp() const; + uint32_t nc_dead_value() const; + uint32_t tau_rf_sp() const; + uint32_t tau_rf_lp() const; + float seg1_lim() const; + float slatsec() const; + float slonsec() const; + uint32_t slatdeg() const; + uint32_t slatmin() const; + uint32_t slondeg() const; + uint32_t slonmin() const; + char slatdir() const; + char slondir() const; + float az_correction_factor() const; + float el_correction_factor() const; + std::string site_name() const; + float ant_manual_setup_ielmin() const; + float ant_manual_setup_ielmax() const; + uint32_t ant_manual_setup_fazvelmax() const; + uint32_t ant_manual_setup_felvelmax() const; + int32_t ant_manual_setup_ignd_hgt() const; + uint32_t ant_manual_setup_irad_hgt() const; + float az_pos_sustain_drive() const; + float az_neg_sustain_drive() const; + float az_nom_pos_drive_slope() const; + float az_nom_neg_drive_slope() const; + float az_feedback_slope() const; + float el_pos_sustain_drive() const; + float el_neg_sustain_drive() const; + float el_nom_pos_drive_slope() const; + float el_nom_neg_drive_slope() const; + float el_feedback_slope() const; + float el_first_slope() const; + float el_second_slope() const; + float el_third_slope() const; + float el_droop_pos() const; + float el_off_neutral_drive() const; + float az_intertia() const; + float el_inertia() const; + uint32_t rvp8nv_iwaveguide_length() const; + float v_rnscale(unsigned i) const; + float vel_data_tover() const; + float width_data_tover() const; + float doppler_range_start() const; + uint32_t max_el_index() const; + float seg2_lim() const; + float seg3_lim() const; + float seg4_lim() const; + uint32_t nbr_el_segments() const; + float h_noise_long() const; + float ant_noise_temp() const; + float h_noise_short() const; + float h_noise_tolerance() const; + float min_h_dyn_range() const; + bool gen_installed() const; + bool gen_exercise() const; + float v_noise_tolerance() const; + float min_v_dyn_range() const; + float zdr_bias_dgrad_lim() const; + float baseline_zdr_bias() const; + float v_noise_long() const; + float v_noise_short() const; + float zdr_data_tover() const; + float phi_data_tover() const; + float rho_data_tover() const; + float stalo_power_dgrad_limit() const; + float stalo_power_maint_limit() const; + float min_h_pwr_sense() const; + float min_v_pwr_sense() const; + float h_pwr_sense_offset() const; + float v_pwr_sense_offset() const; + float ps_gain_ref() const; + float rf_pallet_broad_loss() const; + float ame_ps_tolerance() const; + float ame_max_temp() const; + float ame_min_temp() const; + float rcvr_mod_max_temp() const; + float rcvr_mod_min_temp() const; + float bite_mod_max_temp() const; + float bite_mod_min_temp() const; + uint32_t default_polarization() const; + float tr_limit_dgrad_limit() const; + float tr_limit_fail_limit() const; + bool rfp_stepper_enabled() const; + float ame_current_tolerance() const; + uint32_t h_only_polarization() const; + uint32_t v_only_polarization() const; + float sun_bias() const; + float a_min_shelter_temp_warn() const; + float power_meter_zero() const; + float txb_baseline() const; + float txb_alarm_thresh() const; - bool Parse(std::istream& is) override; + bool Parse(std::istream& is); static std::shared_ptr Create(Level2MessageHeader&& header, std::istream& is); private: - class Impl; - std::unique_ptr p; + std::unique_ptr p; }; -} // namespace scwx::wsr88d::rda +} // namespace rda +} // namespace wsr88d +} // namespace scwx diff --git a/wxdata/include/scwx/wsr88d/rda/rda_prf_data.hpp b/wxdata/include/scwx/wsr88d/rda/rda_prf_data.hpp deleted file mode 100644 index eb42268b..00000000 --- a/wxdata/include/scwx/wsr88d/rda/rda_prf_data.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include - -namespace scwx::wsr88d::rda -{ - -class RdaPrfData : public Level2Message -{ -public: - explicit RdaPrfData(); - ~RdaPrfData() override; - - RdaPrfData(const RdaPrfData&) = delete; - RdaPrfData& operator=(const RdaPrfData&) = delete; - - RdaPrfData(RdaPrfData&&) noexcept; - RdaPrfData& operator=(RdaPrfData&&) noexcept; - - bool Parse(std::istream& is) override; - - static std::shared_ptr Create(Level2MessageHeader&& header, - std::istream& is); - -private: - class Impl; - std::unique_ptr p; -}; - -} // namespace scwx::wsr88d::rda diff --git a/wxdata/include/scwx/wsr88d/rda/rda_status_data.hpp b/wxdata/include/scwx/wsr88d/rda/rda_status_data.hpp index fcd937ec..7dd51edf 100644 --- a/wxdata/include/scwx/wsr88d/rda/rda_status_data.hpp +++ b/wxdata/include/scwx/wsr88d/rda/rda_status_data.hpp @@ -2,8 +2,14 @@ #include -namespace scwx::wsr88d::rda +namespace scwx { +namespace wsr88d +{ +namespace rda +{ + +class RdaStatusDataImpl; class RdaStatusData : public Level2Message { @@ -11,51 +17,51 @@ public: explicit RdaStatusData(); ~RdaStatusData(); - RdaStatusData(const RdaStatusData&) = delete; + RdaStatusData(const RdaStatusData&) = delete; RdaStatusData& operator=(const RdaStatusData&) = delete; RdaStatusData(RdaStatusData&&) noexcept; RdaStatusData& operator=(RdaStatusData&&) noexcept; - [[nodiscard]] std::uint16_t rda_status() const; - [[nodiscard]] std::uint16_t operability_status() const; - [[nodiscard]] std::uint16_t control_status() const; - [[nodiscard]] std::uint16_t auxiliary_power_generator_state() const; - [[nodiscard]] std::uint16_t average_transmitter_power() const; - [[nodiscard]] float horizontal_reflectivity_calibration_correction() const; - [[nodiscard]] std::uint16_t data_transmission_enabled() const; - [[nodiscard]] std::uint16_t volume_coverage_pattern_number() const; - [[nodiscard]] std::uint16_t rda_control_authorization() const; - [[nodiscard]] std::uint16_t rda_build_number() const; - [[nodiscard]] std::uint16_t operational_mode() const; - [[nodiscard]] std::uint16_t super_resolution_status() const; - [[nodiscard]] std::uint16_t clutter_mitigation_decision_status() const; - [[nodiscard]] std::uint16_t rda_scan_and_data_flags() const; - [[nodiscard]] std::uint16_t rda_alarm_summary() const; - [[nodiscard]] std::uint16_t command_acknowledgement() const; - [[nodiscard]] std::uint16_t channel_control_status() const; - [[nodiscard]] std::uint16_t spot_blanking_status() const; - [[nodiscard]] std::uint16_t bypass_map_generation_date() const; - [[nodiscard]] std::uint16_t bypass_map_generation_time() const; - [[nodiscard]] std::uint16_t clutter_filter_map_generation_date() const; - [[nodiscard]] std::uint16_t clutter_filter_map_generation_time() const; - [[nodiscard]] float vertical_reflectivity_calibration_correction() const; - [[nodiscard]] std::uint16_t transition_power_source_status() const; - [[nodiscard]] std::uint16_t rms_control_status() const; - [[nodiscard]] std::uint16_t performance_check_status() const; - [[nodiscard]] std::uint16_t alarm_codes(unsigned i) const; - [[nodiscard]] std::uint16_t signal_processing_options() const; - [[nodiscard]] std::uint16_t downloaded_pattern_number() const; - [[nodiscard]] std::uint16_t status_version() const; + uint16_t rda_status() const; + uint16_t operability_status() const; + uint16_t control_status() const; + uint16_t auxiliary_power_generator_state() const; + uint16_t average_transmitter_power() const; + float horizontal_reflectivity_calibration_correction() const; + uint16_t data_transmission_enabled() const; + uint16_t volume_coverage_pattern_number() const; + uint16_t rda_control_authorization() const; + uint16_t rda_build_number() const; + uint16_t operational_mode() const; + uint16_t super_resolution_status() const; + uint16_t clutter_mitigation_decision_status() const; + uint16_t avset_ebc_rda_log_data_status() const; + uint16_t rda_alarm_summary() const; + uint16_t command_acknowledgement() const; + uint16_t channel_control_status() const; + uint16_t spot_blanking_status() const; + uint16_t bypass_map_generation_date() const; + uint16_t bypass_map_generation_time() const; + uint16_t clutter_filter_map_generation_date() const; + uint16_t clutter_filter_map_generation_time() const; + float vertical_reflectivity_calibration_correction() const; + uint16_t transition_power_source_status() const; + uint16_t rms_control_status() const; + uint16_t performance_check_status() const; + uint16_t alarm_codes(unsigned i) const; + uint16_t signal_processing_options() const; + uint16_t status_version() const; - bool Parse(std::istream& is) override; + bool Parse(std::istream& is); static std::shared_ptr Create(Level2MessageHeader&& header, std::istream& is); private: - class Impl; - std::unique_ptr p; + std::unique_ptr p; }; -} // namespace scwx::wsr88d::rda +} // namespace rda +} // namespace wsr88d +} // namespace scwx diff --git a/wxdata/include/scwx/wsr88d/rpg/digital_radial_data_array_packet.hpp b/wxdata/include/scwx/wsr88d/rpg/digital_radial_data_array_packet.hpp index 135b81ec..9b94ba34 100644 --- a/wxdata/include/scwx/wsr88d/rpg/digital_radial_data_array_packet.hpp +++ b/wxdata/include/scwx/wsr88d/rpg/digital_radial_data_array_packet.hpp @@ -29,16 +29,16 @@ public: operator=(DigitalRadialDataArrayPacket&&) noexcept; uint16_t packet_code() const override; - uint16_t index_of_first_range_bin() const override; - uint16_t number_of_range_bins() const override; - int16_t i_center_of_sweep() const override; - int16_t j_center_of_sweep() const override; + uint16_t index_of_first_range_bin() const; + uint16_t number_of_range_bins() const; + int16_t i_center_of_sweep() const; + int16_t j_center_of_sweep() const; float range_scale_factor() const; - uint16_t number_of_radials() const override; + uint16_t number_of_radials() const; - float start_angle(uint16_t r) const override; - float delta_angle(uint16_t r) const override; - const std::vector& level(uint16_t r) const override; + float start_angle(uint16_t r) const; + float delta_angle(uint16_t r) const; + const std::vector& level(uint16_t r) const; size_t data_size() const override; diff --git a/wxdata/include/scwx/wsr88d/rpg/digital_raster_data_array_packet.hpp b/wxdata/include/scwx/wsr88d/rpg/digital_raster_data_array_packet.hpp deleted file mode 100644 index c0309568..00000000 --- a/wxdata/include/scwx/wsr88d/rpg/digital_raster_data_array_packet.hpp +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -#include - -#include -#include - -namespace scwx::wsr88d::rpg -{ - -class DigitalRasterDataArrayPacket : public Packet -{ -public: - explicit DigitalRasterDataArrayPacket(); - ~DigitalRasterDataArrayPacket() override; - - DigitalRasterDataArrayPacket(const DigitalRasterDataArrayPacket&) = delete; - DigitalRasterDataArrayPacket& - operator=(const DigitalRasterDataArrayPacket&) = delete; - - DigitalRasterDataArrayPacket(DigitalRasterDataArrayPacket&&) noexcept; - DigitalRasterDataArrayPacket& - operator=(DigitalRasterDataArrayPacket&&) noexcept; - - [[nodiscard]] std::uint16_t packet_code() const override; - [[nodiscard]] std::uint16_t i_coordinate_start() const; - [[nodiscard]] std::uint16_t j_coordinate_start() const; - [[nodiscard]] std::uint16_t i_scale_factor() const; - [[nodiscard]] std::uint16_t j_scale_factor() const; - [[nodiscard]] std::uint16_t number_of_cells() const; - [[nodiscard]] std::uint16_t number_of_rows() const; - - [[nodiscard]] std::uint16_t number_of_bytes_in_row(std::uint16_t r) const; - [[nodiscard]] const std::vector& level(std::uint16_t r) const; - - [[nodiscard]] std::size_t data_size() const override; - - bool Parse(std::istream& is) override; - - static std::shared_ptr - Create(std::istream& is); - -private: - class Impl; - std::unique_ptr p; -}; - -} // namespace scwx::wsr88d::rpg diff --git a/wxdata/include/scwx/wsr88d/rpg/graphic_alphanumeric_block.hpp b/wxdata/include/scwx/wsr88d/rpg/graphic_alphanumeric_block.hpp index 5823d66d..9b1f2019 100644 --- a/wxdata/include/scwx/wsr88d/rpg/graphic_alphanumeric_block.hpp +++ b/wxdata/include/scwx/wsr88d/rpg/graphic_alphanumeric_block.hpp @@ -35,7 +35,7 @@ public: const std::vector>>& page_list() const; - bool Parse(std::istream& is) override; + bool Parse(std::istream& is); static constexpr size_t SIZE = 102u; diff --git a/wxdata/include/scwx/wsr88d/rpg/graphic_product_message.hpp b/wxdata/include/scwx/wsr88d/rpg/graphic_product_message.hpp index cf52badd..a14df940 100644 --- a/wxdata/include/scwx/wsr88d/rpg/graphic_product_message.hpp +++ b/wxdata/include/scwx/wsr88d/rpg/graphic_product_message.hpp @@ -30,7 +30,7 @@ public: GraphicProductMessage(GraphicProductMessage&&) noexcept; GraphicProductMessage& operator=(GraphicProductMessage&&) noexcept; - std::shared_ptr description_block() const override; + std::shared_ptr description_block() const; std::shared_ptr symbology_block() const; std::shared_ptr graphic_block() const; std::shared_ptr tabular_block() const; diff --git a/wxdata/include/scwx/wsr88d/rpg/level3_message_factory.hpp b/wxdata/include/scwx/wsr88d/rpg/level3_message_factory.hpp index 2a5e42ca..c2556434 100644 --- a/wxdata/include/scwx/wsr88d/rpg/level3_message_factory.hpp +++ b/wxdata/include/scwx/wsr88d/rpg/level3_message_factory.hpp @@ -2,22 +2,29 @@ #include -namespace scwx::wsr88d::rpg +namespace scwx +{ +namespace wsr88d +{ +namespace rpg { class Level3MessageFactory { -public: +private: explicit Level3MessageFactory() = delete; ~Level3MessageFactory() = delete; - Level3MessageFactory(const Level3MessageFactory&) = delete; + Level3MessageFactory(const Level3MessageFactory&) = delete; Level3MessageFactory& operator=(const Level3MessageFactory&) = delete; - Level3MessageFactory(Level3MessageFactory&&) noexcept = delete; + Level3MessageFactory(Level3MessageFactory&&) noexcept = delete; Level3MessageFactory& operator=(Level3MessageFactory&&) noexcept = delete; +public: static std::shared_ptr Create(std::istream& is); }; -} // namespace scwx::wsr88d::rpg +} // namespace rpg +} // namespace wsr88d +} // namespace scwx diff --git a/wxdata/include/scwx/wsr88d/rpg/packet_factory.hpp b/wxdata/include/scwx/wsr88d/rpg/packet_factory.hpp index 11e794e8..889b8c3d 100644 --- a/wxdata/include/scwx/wsr88d/rpg/packet_factory.hpp +++ b/wxdata/include/scwx/wsr88d/rpg/packet_factory.hpp @@ -2,22 +2,29 @@ #include -namespace scwx::wsr88d::rpg +namespace scwx +{ +namespace wsr88d +{ +namespace rpg { class PacketFactory { -public: +private: explicit PacketFactory() = delete; ~PacketFactory() = delete; - PacketFactory(const PacketFactory&) = delete; + PacketFactory(const PacketFactory&) = delete; PacketFactory& operator=(const PacketFactory&) = delete; - PacketFactory(PacketFactory&&) noexcept = delete; + PacketFactory(PacketFactory&&) noexcept = delete; PacketFactory& operator=(PacketFactory&&) noexcept = delete; +public: static std::shared_ptr Create(std::istream& is); }; -} // namespace scwx::wsr88d::rpg +} // namespace rpg +} // namespace wsr88d +} // namespace scwx diff --git a/wxdata/include/scwx/wsr88d/rpg/product_description_block.hpp b/wxdata/include/scwx/wsr88d/rpg/product_description_block.hpp index a306460e..1182828a 100644 --- a/wxdata/include/scwx/wsr88d/rpg/product_description_block.hpp +++ b/wxdata/include/scwx/wsr88d/rpg/product_description_block.hpp @@ -9,14 +9,20 @@ #include -namespace scwx::wsr88d::rpg +namespace scwx { +namespace wsr88d +{ +namespace rpg +{ + +class ProductDescriptionBlockImpl; class ProductDescriptionBlock : public awips::Message { public: explicit ProductDescriptionBlock(); - ~ProductDescriptionBlock() override; + ~ProductDescriptionBlock(); ProductDescriptionBlock(const ProductDescriptionBlock&) = delete; ProductDescriptionBlock& operator=(const ProductDescriptionBlock&) = delete; @@ -24,67 +30,66 @@ public: ProductDescriptionBlock(ProductDescriptionBlock&&) noexcept; ProductDescriptionBlock& operator=(ProductDescriptionBlock&&) noexcept; - [[nodiscard]] std::int16_t block_divider() const; - [[nodiscard]] float latitude_of_radar() const; - [[nodiscard]] float longitude_of_radar() const; - [[nodiscard]] std::int16_t height_of_radar() const; - [[nodiscard]] std::int16_t product_code() const; - [[nodiscard]] std::uint16_t operational_mode() const; - [[nodiscard]] std::uint16_t volume_coverage_pattern() const; - [[nodiscard]] std::int16_t sequence_number() const; - [[nodiscard]] std::uint16_t volume_scan_number() const; - [[nodiscard]] std::uint16_t volume_scan_date() const; - [[nodiscard]] std::uint32_t volume_scan_start_time() const; - [[nodiscard]] std::uint16_t generation_date_of_product() const; - [[nodiscard]] std::uint32_t generation_time_of_product() const; - [[nodiscard]] std::uint16_t elevation_number() const; - [[nodiscard]] std::uint16_t data_level_threshold(size_t i) const; - [[nodiscard]] std::uint8_t version() const; - [[nodiscard]] std::uint8_t spot_blank() const; - [[nodiscard]] std::uint32_t offset_to_symbology() const; - [[nodiscard]] std::uint32_t offset_to_graphic() const; - [[nodiscard]] std::uint32_t offset_to_tabular() const; + int16_t block_divider() const; + float latitude_of_radar() const; + float longitude_of_radar() const; + int16_t height_of_radar() const; + int16_t product_code() const; + uint16_t operational_mode() const; + uint16_t volume_coverage_pattern() const; + int16_t sequence_number() const; + uint16_t volume_scan_number() const; + uint16_t volume_scan_date() const; + uint32_t volume_scan_start_time() const; + uint16_t generation_date_of_product() const; + uint32_t generation_time_of_product() const; + uint16_t elevation_number() const; + uint16_t data_level_threshold(size_t i) const; + uint8_t version() const; + uint8_t spot_blank() const; + uint32_t offset_to_symbology() const; + uint32_t offset_to_graphic() const; + uint32_t offset_to_tabular() const; - [[nodiscard]] float range() const; - [[nodiscard]] std::uint16_t range_raw() const; - [[nodiscard]] float x_resolution() const; - [[nodiscard]] std::uint16_t x_resolution_raw() const; - [[nodiscard]] float y_resolution() const; - [[nodiscard]] std::uint16_t y_resolution_raw() const; + float range() const; + uint16_t range_raw() const; + float x_resolution() const; + uint16_t x_resolution_raw() const; + float y_resolution() const; + uint16_t y_resolution_raw() const; - [[nodiscard]] std::uint16_t threshold() const; - [[nodiscard]] float offset() const; - [[nodiscard]] float scale() const; - [[nodiscard]] std::uint16_t number_of_levels() const; + uint16_t threshold() const; + float offset() const; + float scale() const; + uint16_t number_of_levels() const; - [[nodiscard]] std::optional - data_level_code(std::uint8_t level) const; - [[nodiscard]] std::optional data_value(std::uint8_t level) const; + std::optional data_level_code(std::uint8_t level) const; + std::optional data_value(std::uint8_t level) const; - [[nodiscard]] std::uint16_t log_start() const; - [[nodiscard]] float log_offset() const; - [[nodiscard]] float log_scale() const; + std::uint16_t log_start() const; + float log_offset() const; + float log_scale() const; - [[nodiscard]] float gr_scale() const; + float gr_scale() const; - [[nodiscard]] std::uint8_t data_mask() const; - [[nodiscard]] std::uint8_t topped_mask() const; + std::uint8_t data_mask() const; + std::uint8_t topped_mask() const; - [[nodiscard]] units::angle::degrees elevation() const; - [[nodiscard]] bool has_elevation() const; + units::angle::degrees elevation() const; - [[nodiscard]] bool IsCompressionEnabled() const; - [[nodiscard]] bool IsDataLevelCoded() const; + bool IsCompressionEnabled() const; + bool IsDataLevelCoded() const; - [[nodiscard]] std::size_t data_size() const override; + size_t data_size() const override; bool Parse(std::istream& is) override; - static constexpr std::size_t SIZE = 102u; + static constexpr size_t SIZE = 102u; private: - class Impl; - std::unique_ptr p; + std::unique_ptr p; }; -} // namespace scwx::wsr88d::rpg +} // namespace rpg +} // namespace wsr88d +} // namespace scwx diff --git a/wxdata/include/scwx/wsr88d/rpg/product_symbology_block.hpp b/wxdata/include/scwx/wsr88d/rpg/product_symbology_block.hpp index 69eac4c6..d597532c 100644 --- a/wxdata/include/scwx/wsr88d/rpg/product_symbology_block.hpp +++ b/wxdata/include/scwx/wsr88d/rpg/product_symbology_block.hpp @@ -34,7 +34,7 @@ public: size_t data_size() const override; - bool Parse(std::istream& is) override; + bool Parse(std::istream& is); static constexpr size_t SIZE = 102u; diff --git a/wxdata/include/scwx/wsr88d/rpg/radar_coded_message.hpp b/wxdata/include/scwx/wsr88d/rpg/radar_coded_message.hpp index 7d7846f0..f1a22b5e 100644 --- a/wxdata/include/scwx/wsr88d/rpg/radar_coded_message.hpp +++ b/wxdata/include/scwx/wsr88d/rpg/radar_coded_message.hpp @@ -27,7 +27,7 @@ public: RadarCodedMessage(RadarCodedMessage&&) noexcept; RadarCodedMessage& operator=(RadarCodedMessage&&) noexcept; - std::shared_ptr description_block() const override; + std::shared_ptr description_block() const; bool Parse(std::istream& is) override; diff --git a/wxdata/include/scwx/wsr88d/rpg/radial_data_packet.hpp b/wxdata/include/scwx/wsr88d/rpg/radial_data_packet.hpp index 34540dc8..dd6e61ec 100644 --- a/wxdata/include/scwx/wsr88d/rpg/radial_data_packet.hpp +++ b/wxdata/include/scwx/wsr88d/rpg/radial_data_packet.hpp @@ -27,16 +27,16 @@ public: RadialDataPacket& operator=(RadialDataPacket&&) noexcept; uint16_t packet_code() const override; - uint16_t index_of_first_range_bin() const override; - uint16_t number_of_range_bins() const override; - int16_t i_center_of_sweep() const override; - int16_t j_center_of_sweep() const override; + uint16_t index_of_first_range_bin() const; + uint16_t number_of_range_bins() const; + int16_t i_center_of_sweep() const; + int16_t j_center_of_sweep() const; float scale_factor() const; - uint16_t number_of_radials() const override; + uint16_t number_of_radials() const; - float start_angle(uint16_t r) const override; - float delta_angle(uint16_t r) const override; - const std::vector& level(uint16_t r) const override; + float start_angle(uint16_t r) const; + float delta_angle(uint16_t r) const; + const std::vector& level(uint16_t r) const; size_t data_size() const override; diff --git a/wxdata/include/scwx/wsr88d/rpg/tabular_alphanumeric_block.hpp b/wxdata/include/scwx/wsr88d/rpg/tabular_alphanumeric_block.hpp index 267bd0e5..0d41fe62 100644 --- a/wxdata/include/scwx/wsr88d/rpg/tabular_alphanumeric_block.hpp +++ b/wxdata/include/scwx/wsr88d/rpg/tabular_alphanumeric_block.hpp @@ -33,7 +33,7 @@ public: const std::vector>& page_list() const; - bool Parse(std::istream& is) override; + bool Parse(std::istream& is); bool Parse(std::istream& is, bool skipHeader); static constexpr size_t SIZE = 102u; diff --git a/wxdata/include/scwx/wsr88d/rpg/tabular_product_message.hpp b/wxdata/include/scwx/wsr88d/rpg/tabular_product_message.hpp index ff9231cc..006d5e82 100644 --- a/wxdata/include/scwx/wsr88d/rpg/tabular_product_message.hpp +++ b/wxdata/include/scwx/wsr88d/rpg/tabular_product_message.hpp @@ -28,7 +28,7 @@ public: TabularProductMessage(TabularProductMessage&&) noexcept; TabularProductMessage& operator=(TabularProductMessage&&) noexcept; - std::shared_ptr description_block() const override; + std::shared_ptr description_block() const; std::shared_ptr tabular_block() const; bool Parse(std::istream& is) override; diff --git a/wxdata/source/scwx/awips/coded_time_motion_location.cpp b/wxdata/source/scwx/awips/coded_time_motion_location.cpp index 569cc513..61e5ba27 100644 --- a/wxdata/source/scwx/awips/coded_time_motion_location.cpp +++ b/wxdata/source/scwx/awips/coded_time_motion_location.cpp @@ -13,7 +13,7 @@ #include -#if (__cpp_lib_chrono < 201907L) +#if !defined(_MSC_VER) # include #endif @@ -107,7 +107,7 @@ bool CodedTimeMotionLocation::Parse(const StringRange& lines, { using namespace std::chrono; -#if (__cpp_lib_chrono < 201907L) +#if !defined(_MSC_VER) using namespace date; #endif diff --git a/wxdata/source/scwx/awips/impact_based_warnings.cpp b/wxdata/source/scwx/awips/impact_based_warnings.cpp index 40a20051..75f04d1e 100644 --- a/wxdata/source/scwx/awips/impact_based_warnings.cpp +++ b/wxdata/source/scwx/awips/impact_based_warnings.cpp @@ -4,40 +4,13 @@ #include #include -#include namespace scwx { namespace awips { -namespace ibw -{ -static const std::string logPrefix_ = "scwx::awips::ibw::impact_based_warnings"; - -static const boost::unordered_flat_map - impactBasedWarningInfo_ { - {Phenomenon::Marine, - ImpactBasedWarningInfo {.hasTornadoPossibleTag_ = true}}, - {Phenomenon::FlashFlood, - ImpactBasedWarningInfo { - .threatCategories_ {ThreatCategory::Base, - ThreatCategory::Considerable, - ThreatCategory::Catastrophic}}}, - {Phenomenon::SevereThunderstorm, - ImpactBasedWarningInfo { - .hasTornadoPossibleTag_ = true, - .threatCategories_ {ThreatCategory::Base, - ThreatCategory::Considerable, - ThreatCategory::Destructive}}}, - {Phenomenon::SnowSquall, ImpactBasedWarningInfo {}}, - {Phenomenon::Tornado, - ImpactBasedWarningInfo { - .hasObservedTag_ = true, - .threatCategories_ {ThreatCategory::Base, - ThreatCategory::Considerable, - ThreatCategory::Catastrophic}}}, - {Phenomenon::Unknown, ImpactBasedWarningInfo {}}}; +static const std::string logPrefix_ = "scwx::awips::impact_based_warnings"; static const std::unordered_map threatCategoryName_ {{ThreatCategory::Base, "Base"}, @@ -47,16 +20,6 @@ static const std::unordered_map {ThreatCategory::Catastrophic, "Catastrophic"}, {ThreatCategory::Unknown, "?"}}; -const ImpactBasedWarningInfo& GetImpactBasedWarningInfo(Phenomenon phenomenon) -{ - auto it = impactBasedWarningInfo_.find(phenomenon); - if (it != impactBasedWarningInfo_.cend()) - { - return it->second; - } - return impactBasedWarningInfo_.at(Phenomenon::Unknown); -} - SCWX_GET_ENUM(ThreatCategory, GetThreatCategory, threatCategoryName_) const std::string& GetThreatCategoryName(ThreatCategory threatCategory) @@ -64,6 +27,5 @@ const std::string& GetThreatCategoryName(ThreatCategory threatCategory) return threatCategoryName_.at(threatCategory); } -} // namespace ibw } // namespace awips } // namespace scwx diff --git a/wxdata/source/scwx/awips/message.cpp b/wxdata/source/scwx/awips/message.cpp index f4dbe9b7..73ae88a2 100644 --- a/wxdata/source/scwx/awips/message.cpp +++ b/wxdata/source/scwx/awips/message.cpp @@ -9,22 +9,17 @@ namespace awips static const std::string logPrefix_ = "scwx::awips::message"; static const auto logger_ = util::Logger::Create(logPrefix_); -class Message::Impl +class MessageImpl { public: - explicit Impl() = default; - ~Impl() = default; - - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; + explicit MessageImpl() {}; + ~MessageImpl() = default; }; -Message::Message() : p(std::make_unique()) {} +Message::Message() : p(std::make_unique()) {} Message::~Message() = default; -Message::Message(Message&&) noexcept = default; +Message::Message(Message&&) noexcept = default; Message& Message::operator=(Message&&) noexcept = default; bool Message::ValidateMessage(std::istream& is, size_t bytesRead) const diff --git a/wxdata/source/scwx/awips/phenomenon.cpp b/wxdata/source/scwx/awips/phenomenon.cpp index c8154509..ee8e549d 100644 --- a/wxdata/source/scwx/awips/phenomenon.cpp +++ b/wxdata/source/scwx/awips/phenomenon.cpp @@ -77,65 +77,64 @@ static const PhenomenonCodesBimap phenomenonCodes_ = (Phenomenon::FreezingSpray, "ZY") // (Phenomenon::Unknown, "??"); -static const PhenomenonCodesBimap phenomenonText_ = - boost::assign::list_of // - (Phenomenon::AshfallLand, "Ashfall (land)") // - (Phenomenon::AirStagnation, "Air Stagnation") // - (Phenomenon::BeachHazard, "Beach Hazard") // - (Phenomenon::BriskWind, "Brisk Wind") // - (Phenomenon::Blizzard, "Blizzard") // - (Phenomenon::CoastalFlood, "Coastal Flood") // - (Phenomenon::DebrisFlow, "Debris Flow") // - (Phenomenon::DustStorm, "Dust Storm") // - (Phenomenon::BlowingDust, "Blowing Dust") // - (Phenomenon::ExtremeCold, "Extreme Cold") // - (Phenomenon::ExcessiveHeat, "Excessive Heat") // - (Phenomenon::ExtremeWind, "Extreme Wind") // - (Phenomenon::Flood, "Flood") // - (Phenomenon::FlashFlood, "Flash Flood") // - (Phenomenon::DenseFogLand, "Dense Fog (land)") // - (Phenomenon::Flood, "Flood (Forecast Points)") // - (Phenomenon::Frost, "Frost") // - (Phenomenon::FireWeather, "Fire Weather") // - (Phenomenon::Freeze, "Freeze") // - (Phenomenon::Gale, "Gale") // - (Phenomenon::HurricaneForceWind, "Hurricane Force Wind") // - (Phenomenon::Heat, "Heat") // - (Phenomenon::Hurricane, "Hurricane") // - (Phenomenon::HighWind, "High Wind") // - (Phenomenon::Hydrologic, "Hydrologic") // - (Phenomenon::HardFreeze, "Hard Freeze") // - (Phenomenon::IceStorm, "Ice Storm") // - (Phenomenon::LakeEffectSnow, "Lake Effect Snow") // - (Phenomenon::LowWater, "Low Water") // - (Phenomenon::LakeshoreFlood, "Lakeshore Flood") // - (Phenomenon::LakeWind, "Lake Wind") // - (Phenomenon::Marine, "Marine") // - (Phenomenon::DenseFogMarine, "Dense Fog (marine)") // - (Phenomenon::AshfallMarine, "Ashfall (marine)") // - (Phenomenon::DenseSmokeMarine, "Dense Smoke (marine)") // - (Phenomenon::RipCurrentRisk, "Rip Current Risk") // - (Phenomenon::SmallCraft, "Small Craft") // - (Phenomenon::HazardousSeas, "Hazardous Seas") // - (Phenomenon::DenseSmokeLand, "Dense Smoke (land)") // - (Phenomenon::Storm, "Storm") // - (Phenomenon::StormSurge, "Storm Surge") // - (Phenomenon::SnowSquall, "Snow Squall") // - (Phenomenon::HighSurf, "High Surf") // - (Phenomenon::SevereThunderstorm, "Severe Thunderstorm") // - (Phenomenon::Tornado, "Tornado") // - (Phenomenon::TropicalStorm, "Tropical Storm") // - (Phenomenon::Tsunami, "Tsunami") // - (Phenomenon::Typhoon, "Typhoon") // - (Phenomenon::HeavyFreezingSpray, "Heavy Freezing Spray") // - (Phenomenon::WindChill, "Wind Chill") // - (Phenomenon::Wind, "Wind") // - (Phenomenon::WinterStorm, "Winter Storm") // - (Phenomenon::WinterWeather, "Winter Weather") // - (Phenomenon::FreezingFog, "Freezing Fog") // - (Phenomenon::FreezingRain, "Freezing Rain") // - (Phenomenon::FreezingSpray, "Freezing Spray") // - (Phenomenon::Unknown, "Unknown"); +static const std::unordered_map phenomenonText_ { + {Phenomenon::AshfallLand, "Ashfall (land)"}, // + {Phenomenon::AirStagnation, "Air Stagnation"}, // + {Phenomenon::BeachHazard, "Beach Hazard"}, // + {Phenomenon::BriskWind, "Brisk Wind"}, // + {Phenomenon::Blizzard, "Blizzard"}, // + {Phenomenon::CoastalFlood, "Coastal Flood"}, // + {Phenomenon::DebrisFlow, "Debris Flow"}, // + {Phenomenon::DustStorm, "Dust Storm"}, // + {Phenomenon::BlowingDust, "Blowing Dust"}, // + {Phenomenon::ExtremeCold, "Extreme Cold"}, // + {Phenomenon::ExcessiveHeat, "Excessive Heat"}, // + {Phenomenon::ExtremeWind, "Extreme Wind"}, // + {Phenomenon::Flood, "Flood"}, // + {Phenomenon::FlashFlood, "Flash Flood"}, // + {Phenomenon::DenseFogLand, "Dense Fog (land)"}, // + {Phenomenon::Flood, "Flood (Forecast Points)"}, // + {Phenomenon::Frost, "Frost"}, // + {Phenomenon::FireWeather, "Fire Weather"}, // + {Phenomenon::Freeze, "Freeze"}, // + {Phenomenon::Gale, "Gale"}, // + {Phenomenon::HurricaneForceWind, "Hurricane Force Wind"}, // + {Phenomenon::Heat, "Heat"}, // + {Phenomenon::Hurricane, "Hurricane"}, // + {Phenomenon::HighWind, "High Wind"}, // + {Phenomenon::Hydrologic, "Hydrologic"}, // + {Phenomenon::HardFreeze, "Hard Freeze"}, // + {Phenomenon::IceStorm, "Ice Storm"}, // + {Phenomenon::LakeEffectSnow, "Lake Effect Snow"}, // + {Phenomenon::LowWater, "Low Water"}, // + {Phenomenon::LakeshoreFlood, "Lakeshore Flood"}, // + {Phenomenon::LakeWind, "Lake Wind"}, // + {Phenomenon::Marine, "Marine"}, // + {Phenomenon::DenseFogMarine, "Dense Fog (marine)"}, // + {Phenomenon::AshfallMarine, "Ashfall (marine)"}, // + {Phenomenon::DenseSmokeMarine, "Dense Smoke (marine)"}, // + {Phenomenon::RipCurrentRisk, "Rip Current Risk"}, // + {Phenomenon::SmallCraft, "Small Craft"}, // + {Phenomenon::HazardousSeas, "Hazardous Seas"}, // + {Phenomenon::DenseSmokeLand, "Dense Smoke (land)"}, // + {Phenomenon::Storm, "Storm"}, // + {Phenomenon::StormSurge, "Storm Surge"}, // + {Phenomenon::SnowSquall, "Snow Squall"}, // + {Phenomenon::HighSurf, "High Surf"}, // + {Phenomenon::SevereThunderstorm, "Severe Thunderstorm"}, // + {Phenomenon::Tornado, "Tornado"}, // + {Phenomenon::TropicalStorm, "Tropical Storm"}, // + {Phenomenon::Tsunami, "Tsunami"}, // + {Phenomenon::Typhoon, "Typhoon"}, // + {Phenomenon::HeavyFreezingSpray, "Heavy Freezing Spray"}, // + {Phenomenon::WindChill, "Wind Chill"}, // + {Phenomenon::Wind, "Wind"}, // + {Phenomenon::WinterStorm, "Winter Storm"}, // + {Phenomenon::WinterWeather, "Winter Weather"}, // + {Phenomenon::FreezingFog, "Freezing Fog"}, // + {Phenomenon::FreezingRain, "Freezing Rain"}, // + {Phenomenon::FreezingSpray, "Freezing Spray"}, // + {Phenomenon::Unknown, "Unknown"}}; Phenomenon GetPhenomenon(const std::string& code) { @@ -155,24 +154,6 @@ Phenomenon GetPhenomenon(const std::string& code) return phenomenon; } -Phenomenon GetPhenomenonFromText(const std::string& text) -{ - Phenomenon phenomenon; - - if (phenomenonText_.right.find(text) != phenomenonText_.right.end()) - { - phenomenon = phenomenonText_.right.at(text); - } - else - { - phenomenon = Phenomenon::Unknown; - - logger_->debug("Unrecognized code: \"{}\"", text); - } - - return phenomenon; -} - const std::string& GetPhenomenonCode(Phenomenon phenomenon) { return phenomenonCodes_.left.at(phenomenon); @@ -180,7 +161,7 @@ const std::string& GetPhenomenonCode(Phenomenon phenomenon) const std::string& GetPhenomenonText(Phenomenon phenomenon) { - return phenomenonText_.left.at(phenomenon); + return phenomenonText_.at(phenomenon); } } // namespace awips diff --git a/wxdata/source/scwx/awips/pvtec.cpp b/wxdata/source/scwx/awips/pvtec.cpp index b93d2be0..a661a037 100644 --- a/wxdata/source/scwx/awips/pvtec.cpp +++ b/wxdata/source/scwx/awips/pvtec.cpp @@ -17,7 +17,7 @@ #include #include -#if (__cpp_lib_chrono < 201907L) +#if !defined(_MSC_VER) # include #endif @@ -143,7 +143,7 @@ bool PVtec::Parse(const std::string& s) { using namespace std::chrono; -#if (__cpp_lib_chrono < 201907L) +#if !defined(_MSC_VER) using namespace date; #endif diff --git a/wxdata/source/scwx/awips/text_product_file.cpp b/wxdata/source/scwx/awips/text_product_file.cpp index 96d5503f..3edc7b2d 100644 --- a/wxdata/source/scwx/awips/text_product_file.cpp +++ b/wxdata/source/scwx/awips/text_product_file.cpp @@ -3,31 +3,24 @@ #include -#include - -namespace scwx::awips +namespace scwx +{ +namespace awips { static const std::string logPrefix_ = "scwx::awips::text_product_file"; static const auto logger_ = util::Logger::Create(logPrefix_); -class TextProductFile::Impl +class TextProductFileImpl { public: - explicit Impl() : messages_ {} {}; - ~Impl() = default; - - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - - Impl(Impl&&) = delete; - Impl& operator=(Impl&&) = delete; + explicit TextProductFileImpl() : messages_ {} {}; + ~TextProductFileImpl() = default; std::vector> messages_; }; -TextProductFile::TextProductFile() : - p(std::make_unique()) +TextProductFile::TextProductFile() : p(std::make_unique()) { } TextProductFile::~TextProductFile() = default; @@ -66,34 +59,16 @@ bool TextProductFile::LoadFile(const std::string& filename) if (fileValid) { - fileValid = LoadData(filename, f); + fileValid = LoadData(f); } return fileValid; } -bool TextProductFile::LoadData(const std::string& filename, std::istream& is) +bool TextProductFile::LoadData(std::istream& is) { - static constexpr LazyRE2 kDateTimePattern_ = { - R"(((?:19|20)\d{2}))" // Year (YYYY) - R"((0[1-9]|1[0-2]))" // Month (MM) - R"((0[1-9]|[12]\d|3[01]))" // Day (DD) - R"(_?)" // Optional separator (not captured) - R"(([01]\d|2[0-3]))" // Hour (HH) - }; - logger_->trace("Loading Data"); - // Attempt to parse the date from the filename - std::optional yearMonth; - int year {}; - unsigned int month {}; - - if (RE2::PartialMatch(filename, *kDateTimePattern_, &year, &month)) - { - yearMonth = std::chrono::year {year} / std::chrono::month {month}; - } - while (!is.eof()) { std::shared_ptr message = @@ -102,7 +77,7 @@ bool TextProductFile::LoadData(const std::string& filename, std::istream& is) if (message != nullptr) { - for (const auto& m : p->messages_) + for (auto m : p->messages_) { if (*m->wmo_header().get() == *message->wmo_header().get()) { @@ -113,11 +88,6 @@ bool TextProductFile::LoadData(const std::string& filename, std::istream& is) if (!duplicate) { - if (yearMonth.has_value()) - { - message->wmo_header()->SetDateHint(yearMonth.value()); - } - p->messages_.push_back(message); } } @@ -130,4 +100,5 @@ bool TextProductFile::LoadData(const std::string& filename, std::istream& is) return !p->messages_.empty(); } -} // namespace scwx::awips +} // namespace awips +} // namespace scwx diff --git a/wxdata/source/scwx/awips/text_product_message.cpp b/wxdata/source/scwx/awips/text_product_message.cpp index 53ec502d..5128aee8 100644 --- a/wxdata/source/scwx/awips/text_product_message.cpp +++ b/wxdata/source/scwx/awips/text_product_message.cpp @@ -9,10 +9,11 @@ #include #include -#include #include -namespace scwx::awips +namespace scwx +{ +namespace awips { static const std::string logPrefix_ = "scwx::awips::text_product_message"; @@ -26,8 +27,8 @@ static const auto logger_ = scwx::util::Logger::Create(logPrefix_); // Look for hhmm (xM|UTC) to key the date/time string static constexpr LazyRE2 reDateTimeString = {"^[0-9]{3,4} ([AP]M|UTC)"}; -static void ParseCodedInformation(const std::shared_ptr& segment, - const std::string& wfo); +static void ParseCodedInformation(std::shared_ptr segment, + const std::string& wfo); static std::vector ParseProductContent(std::istream& is); static void SkipBlankLines(std::istream& is); static bool TryParseEndOfProduct(std::istream& is); @@ -49,13 +50,6 @@ public: } ~TextProductMessageImpl() = default; - TextProductMessageImpl(const TextProductMessageImpl&) = delete; - TextProductMessageImpl& operator=(const TextProductMessageImpl&) = delete; - TextProductMessageImpl(const TextProductMessageImpl&&) = delete; - TextProductMessageImpl& operator=(const TextProductMessageImpl&&) = delete; - - boost::uuids::uuid uuid_ {boost::uuids::random_generator()()}; - std::string messageContent_; std::shared_ptr wmoHeader_; std::vector mndHeader_; @@ -73,11 +67,6 @@ TextProductMessage::TextProductMessage(TextProductMessage&&) noexcept = default; TextProductMessage& TextProductMessage::operator=(TextProductMessage&&) noexcept = default; -boost::uuids::uuid TextProductMessage::uuid() const -{ - return p->uuid_; -} - std::string TextProductMessage::message_content() const { return p->messageContent_; @@ -127,11 +116,71 @@ std::chrono::system_clock::time_point Segment::event_begin() const // If event begin is 000000T0000Z if (eventBegin == std::chrono::system_clock::time_point {}) { + using namespace std::chrono; + // Determine event end from P-VTEC string - std::chrono::system_clock::time_point eventEnd = + system_clock::time_point eventEnd = header_->vtecString_[0].pVtec_.event_end(); - eventBegin = wmoHeader_->GetDateTime(eventEnd); + auto endDays = floor(eventEnd); + year_month_day endDate {endDays}; + + // Determine WMO date/time + std::string wmoDateTime = wmoHeader_->date_time(); + + bool wmoDateTimeValid = false; + unsigned int dayOfMonth = 0; + unsigned long beginHour = 0; + unsigned long beginMinute = 0; + + try + { + // WMO date time is in the format DDHHMM + dayOfMonth = + static_cast(std::stoul(wmoDateTime.substr(0, 2))); + beginHour = std::stoul(wmoDateTime.substr(2, 2)); + beginMinute = std::stoul(wmoDateTime.substr(4, 2)); + wmoDateTimeValid = true; + } + catch (const std::exception&) + { + logger_->warn("Malformed WMO date/time: {}", wmoDateTime); + } + + if (wmoDateTimeValid) + { + // Combine end date year and month with WMO date time + eventBegin = + sys_days {endDate.year() / endDate.month() / day {dayOfMonth}} + + hours {beginHour} + minutes {beginMinute}; + + // If the begin date is after the end date, assume the start time + // was the previous month (give a 1 day grace period for expiring + // events in the past) + if (eventBegin > eventEnd + 24h) + { + // If the current end month is January + if (endDate.month() == January) + { + // The begin month must be December of last year + eventBegin = + sys_days { + year {static_cast((endDate.year() - 1y).count())} / + December / day {dayOfMonth}} + + hours {beginHour} + minutes {beginMinute}; + } + else + { + // Back up one month + eventBegin = + sys_days {endDate.year() / + month {static_cast( + (endDate.month() - month {1}).count())} / + day {dayOfMonth}} + + hours {beginHour} + minutes {beginMinute}; + } + } + } } } @@ -183,7 +232,7 @@ bool TextProductMessage::Parse(std::istream& is) if (i == 0) { - if (is.peek() != '\r' && is.peek() != '\n') + if (is.peek() != '\r') { segment->header_ = TryParseSegmentHeader(is); } @@ -269,8 +318,8 @@ bool TextProductMessage::Parse(std::istream& is) return dataValid; } -void ParseCodedInformation(const std::shared_ptr& segment, - const std::string& wfo) +void ParseCodedInformation(std::shared_ptr segment, + const std::string& wfo) { typedef std::vector::const_iterator StringIterator; @@ -303,8 +352,8 @@ void ParseCodedInformation(const std::shared_ptr& segment, codedLocationEnd = it; } - if (codedMotionBegin == productContent.cend() && - it->starts_with("TIME...MOT...LOC")) + else if (codedMotionBegin == productContent.cend() && + it->starts_with("TIME...MOT...LOC")) { codedMotionBegin = it; } @@ -317,7 +366,8 @@ void ParseCodedInformation(const std::shared_ptr& segment, codedMotionEnd = it; } - if (!segment->observed_ && it->find("...OBSERVED") != std::string::npos) + else if (!segment->observed_ && + it->find("...OBSERVED") != std::string::npos) { segment->observed_ = true; } @@ -328,37 +378,21 @@ void ParseCodedInformation(const std::shared_ptr& segment, segment->tornadoPossible_ = true; } - // Assignment of an iterator permitted - // NOLINTBEGIN(bugprone-assignment-in-if-condition) - else if (segment->threatCategory_ == ibw::ThreatCategory::Base && + else if (segment->threatCategory_ == ThreatCategory::Base && (threatTagIt = std::find_if(kThreatCategoryTags.cbegin(), kThreatCategoryTags.cend(), [&it](const std::string& tag) { return it->starts_with(tag); })) != kThreatCategoryTags.cend() && it->length() > threatTagIt->length()) - // NOLINTEND(bugprone-assignment-in-if-condition) { const std::string threatCategoryName = it->substr(threatTagIt->length()); - ibw::ThreatCategory threatCategory = - ibw::GetThreatCategory(threatCategoryName); - - switch (threatCategory) + ThreatCategory threatCategory = GetThreatCategory(threatCategoryName); + if (threatCategory == ThreatCategory::Unknown) { - case ibw::ThreatCategory::Significant: - // "Significant" is no longer an official tag, and has largely been - // replaced with "Considerable". - threatCategory = ibw::ThreatCategory::Considerable; - break; - - case ibw::ThreatCategory::Unknown: - threatCategory = ibw::ThreatCategory::Base; - break; - - default: - break; + threatCategory = ThreatCategory::Base; } segment->threatCategory_ = threatCategory; @@ -411,7 +445,7 @@ void SkipBlankLines(std::istream& is) { std::string line; - while (is.peek() == '\r' || is.peek() == '\n') + while (is.peek() == '\r') { util::getline(is, line); } @@ -466,7 +500,7 @@ std::vector TryParseMndHeader(std::istream& is) std::string line; std::streampos isBegin = is.tellg(); - while (!is.eof() && is.peek() != '\r' && is.peek() != '\n') + while (!is.eof() && is.peek() != '\r') { util::getline(is, line); mndHeader.push_back(line); @@ -499,7 +533,7 @@ std::vector TryParseOverviewBlock(std::istream& is) if (is.peek() == '.') { - while (!is.eof() && is.peek() != '\r' && is.peek() != '\n') + while (!is.eof() && is.peek() != '\r') { util::getline(is, line); overviewBlock.push_back(line); @@ -529,7 +563,7 @@ std::optional TryParseSegmentHeader(std::istream& is) header->ugcString_.push_back(line); // If UGC is multi-line, continue parsing - while (!is.eof() && is.peek() != '\r' && is.peek() != '\n' && + while (!is.eof() && is.peek() != '\r' && !RE2::PartialMatch(line, *reUgcExpiration)) { util::getline(is, line); @@ -548,7 +582,7 @@ std::optional TryParseSegmentHeader(std::istream& is) header->vtecString_.push_back(std::move(*vtec)); } - while (!is.eof() && is.peek() != '\r' && is.peek() != '\n') + while (!is.eof() && is.peek() != '\r') { util::getline(is, line); if (!RE2::PartialMatch(line, *reDateTimeString)) @@ -593,8 +627,10 @@ std::optional TryParseVtecString(std::istream& is) if (RE2::PartialMatch(line, *rePVtecString)) { - vtec = Vtec(); - const bool vtecValid = vtec->pVtec_.Parse(line); + bool vtecValid; + + vtec = Vtec(); + vtecValid = vtec->pVtec_.Parse(line); isBegin = is.tellg(); @@ -638,4 +674,5 @@ std::shared_ptr TextProductMessage::Create(std::istream& is) return message; } -} // namespace scwx::awips +} // namespace awips +} // namespace scwx diff --git a/wxdata/source/scwx/awips/wmo_header.cpp b/wxdata/source/scwx/awips/wmo_header.cpp index f89db609..eb4501e7 100644 --- a/wxdata/source/scwx/awips/wmo_header.cpp +++ b/wxdata/source/scwx/awips/wmo_header.cpp @@ -12,19 +12,14 @@ # include #endif -namespace scwx::awips +namespace scwx +{ +namespace awips { static const std::string logPrefix_ = "scwx::awips::wmo_header"; static const auto logger_ = util::Logger::Create(logPrefix_); -static constexpr std::size_t kWmoHeaderMinLineLength_ = 18; -static constexpr std::size_t kWmoIdentifierLengthMin_ = 5; -static constexpr std::size_t kWmoIdentifierLengthMax_ = 6; -static constexpr std::size_t kIcaoLength_ = 4; -static constexpr std::size_t kDateTimeLength_ = 6; -static constexpr std::size_t kAwipsIdentifierLineLength_ = 6; - class WmoHeaderImpl { public: @@ -42,31 +37,17 @@ public: } ~WmoHeaderImpl() = default; - WmoHeaderImpl(const WmoHeaderImpl&) = delete; - WmoHeaderImpl& operator=(const WmoHeaderImpl&) = delete; - WmoHeaderImpl(const WmoHeaderImpl&&) = delete; - WmoHeaderImpl& operator=(const WmoHeaderImpl&&) = delete; - - void CalculateAbsoluteDateTime(); - bool ParseDateTime(unsigned int& dayOfMonth, - unsigned long& hour, - unsigned long& minute); - bool operator==(const WmoHeaderImpl& o) const; - std::string sequenceNumber_ {}; - std::string dataType_ {}; - std::string geographicDesignator_ {}; - std::string bulletinId_ {}; - std::string icao_ {}; - std::string dateTime_ {}; - std::string bbbIndicator_ {}; - std::string productCategory_ {}; - std::string productDesignator_ {}; - - std::optional dateHint_ {}; - std::optional> - absoluteDateTime_ {}; + std::string sequenceNumber_; + std::string dataType_; + std::string geographicDesignator_; + std::string bulletinId_; + std::string icao_; + std::string dateTime_; + std::string bbbIndicator_; + std::string productCategory_; + std::string productDesignator_; }; WmoHeader::WmoHeader() : p(std::make_unique()) {} @@ -138,71 +119,6 @@ std::string WmoHeader::product_designator() const return p->productDesignator_; } -std::chrono::sys_time WmoHeader::GetDateTime( - std::optional endTimeHint) -{ - std::chrono::sys_time wmoDateTime {}; - - const auto absoluteDateTime = p->absoluteDateTime_; - - if (absoluteDateTime.has_value()) - { - wmoDateTime = absoluteDateTime.value(); - } - else if (endTimeHint.has_value()) - { - bool dateTimeValid = false; - unsigned int dayOfMonth = 0; - unsigned long hour = 0; - unsigned long minute = 0; - - dateTimeValid = p->ParseDateTime(dayOfMonth, hour, minute); - - if (dateTimeValid) - { - using namespace std::chrono; - - const auto endDays = floor(endTimeHint.value()); - const year_month_day endDate {endDays}; - - // Combine end date year and month with WMO date time - wmoDateTime = - sys_days {endDate.year() / endDate.month() / day {dayOfMonth}} + - hours {hour} + minutes {minute}; - - // If the begin date is after the end date, assume the start time - // was the previous month (give a 1 day grace period for expiring - // events in the past) - // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) - if (wmoDateTime > endTimeHint.value() + 24h) - { - // If the current end month is January - if (endDate.month() == January) - { - // The begin month must be December of last year - wmoDateTime = - sys_days { - year {static_cast((endDate.year() - 1y).count())} / - December / day {dayOfMonth}} + - hours {hour} + minutes {minute}; - } - else - { - // Back up one month - wmoDateTime = - sys_days {endDate.year() / - month {static_cast( - (endDate.month() - month {1}).count())} / - day {dayOfMonth}} + - hours {hour} + minutes {minute}; - } - } - } - } - - return wmoDateTime; -} - bool WmoHeader::Parse(std::istream& is) { bool headerValid = true; @@ -216,21 +132,9 @@ bool WmoHeader::Parse(std::istream& is) { util::getline(is, sohLine); util::getline(is, sequenceLine); - util::getline(is, wmoLine); - } - else - { - // The next line could be the WMO line or the sequence line - util::getline(is, wmoLine); - if (wmoLine.length() < kWmoHeaderMinLineLength_) - { - // This is likely the sequence line instead - sequenceLine.swap(wmoLine); - util::getline(is, wmoLine); - } } - auto awipsLinePos = is.tellg(); + util::getline(is, wmoLine); util::getline(is, awipsLine); if (is.eof()) @@ -275,18 +179,17 @@ bool WmoHeader::Parse(std::istream& is) logger_->warn("Invalid number of WMO tokens"); headerValid = false; } - else if (wmoTokenList[0].size() < kWmoIdentifierLengthMin_ || - wmoTokenList[0].size() > kWmoIdentifierLengthMax_) + else if (wmoTokenList[0].size() != 6) { logger_->warn("WMO identifier malformed"); headerValid = false; } - else if (wmoTokenList[1].size() != kIcaoLength_) + else if (wmoTokenList[1].size() != 4) { logger_->warn("ICAO malformed"); headerValid = false; } - else if (wmoTokenList[2].size() != kDateTimeLength_) + else if (wmoTokenList[2].size() != 6) { logger_->warn("Date/time malformed"); headerValid = false; @@ -301,11 +204,9 @@ bool WmoHeader::Parse(std::istream& is) { p->dataType_ = wmoTokenList[0].substr(0, 2); p->geographicDesignator_ = wmoTokenList[0].substr(2, 2); - p->bulletinId_ = wmoTokenList[0].substr(4, wmoTokenList[0].size() - 4); - p->icao_ = wmoTokenList[1]; - p->dateTime_ = wmoTokenList[2]; - - p->CalculateAbsoluteDateTime(); + p->bulletinId_ = wmoTokenList[0].substr(4, 2); + p->icao_ = wmoTokenList[1]; + p->dateTime_ = wmoTokenList[2]; if (wmoTokenList.size() == 4) { @@ -323,14 +224,10 @@ bool WmoHeader::Parse(std::istream& is) if (headerValid) { - if (awipsLine.size() != kAwipsIdentifierLineLength_) + if (awipsLine.size() != 6) { - // Older products may be missing an AWIPS Identifier Line - logger_->trace("AWIPS Identifier Line bad size"); - - is.seekg(awipsLinePos); - p->productCategory_ = ""; - p->productDesignator_ = ""; + logger_->warn("AWIPS Identifier Line bad size"); + headerValid = false; } else { @@ -342,60 +239,5 @@ bool WmoHeader::Parse(std::istream& is) return headerValid; } -void WmoHeader::SetDateHint(std::chrono::year_month dateHint) -{ - p->dateHint_ = dateHint; - p->CalculateAbsoluteDateTime(); -} - -bool WmoHeaderImpl::ParseDateTime(unsigned int& dayOfMonth, - unsigned long& hour, - unsigned long& minute) -{ - bool dateTimeValid = false; - - try - { - // WMO date time is in the format DDHHMM - dayOfMonth = - static_cast(std::stoul(dateTime_.substr(0, 2))); - hour = std::stoul(dateTime_.substr(2, 2)); - minute = std::stoul(dateTime_.substr(4, 2)); - dateTimeValid = true; - } - catch (const std::exception&) - { - logger_->warn("Malformed WMO date/time: {}", dateTime_); - } - - return dateTimeValid; -} - -void WmoHeaderImpl::CalculateAbsoluteDateTime() -{ - bool dateTimeValid = false; - - if (dateHint_.has_value() && !dateTime_.empty()) - { - unsigned int dayOfMonth = 0; - unsigned long hour = 0; - unsigned long minute = 0; - - dateTimeValid = ParseDateTime(dayOfMonth, hour, minute); - - if (dateTimeValid) - { - using namespace std::chrono; - absoluteDateTime_ = sys_days {dateHint_->year() / dateHint_->month() / - day {dayOfMonth}} + - hours {hour} + minutes {minute}; - } - } - - if (!dateTimeValid) - { - absoluteDateTime_.reset(); - } -} - -} // namespace scwx::awips +} // namespace awips +} // namespace scwx diff --git a/wxdata/source/scwx/common/color_table.cpp b/wxdata/source/scwx/common/color_table.cpp index 32a4684f..aff48f3d 100644 --- a/wxdata/source/scwx/common/color_table.cpp +++ b/wxdata/source/scwx/common/color_table.cpp @@ -10,18 +10,8 @@ #include #include - -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wunused-parameter" -#endif - #include -#if defined(__clang__) -# pragma clang diagnostic pop -#endif - #include namespace scwx diff --git a/wxdata/source/scwx/common/geographic.cpp b/wxdata/source/scwx/common/geographic.cpp index e9a494d3..bf7d1a2c 100644 --- a/wxdata/source/scwx/common/geographic.cpp +++ b/wxdata/source/scwx/common/geographic.cpp @@ -14,34 +14,6 @@ static std::string GetDegreeString(double degrees, DegreeStringType type, const std::string& suffix); -units::degrees GetAngleDelta(units::degrees angle1, - units::degrees angle2) -{ - // Normalize angles to [0, 360) - while (angle1.value() < 0.0f) - { - angle1 += units::degrees {360.0f}; - } - while (angle2.value() < 0.0f) - { - angle2 += units::degrees {360.0f}; - } - angle1 = units::degrees {std::fmod(angle1.value(), 360.f)}; - angle2 = units::degrees {std::fmod(angle2.value(), 360.f)}; - - // Calculate the absolute difference - auto delta = angle1 - angle2; - if (delta < units::degrees {0.0f}) - { - delta *= -1.0f; - } - - // Account for wrapping - delta = std::min(delta, units::degrees {360.0f} - delta); - - return delta; -} - Coordinate GetCentroid(const std::vector& coordinates) { double x = 0.0; diff --git a/wxdata/source/scwx/common/products.cpp b/wxdata/source/scwx/common/products.cpp index 48969e13..f3ecd1e8 100644 --- a/wxdata/source/scwx/common/products.cpp +++ b/wxdata/source/scwx/common/products.cpp @@ -49,7 +49,7 @@ static const std::unordered_map level3ProductCodeMap_ { {153, "SDR"}, {154, "SDV"}, {159, "DZD"}, {161, "DCC"}, {163, "DKD"}, {165, "DHC"}, {166, "ML"}, {169, "OHA"}, {170, "DAA"}, {172, "DTA"}, {173, "DUA"}, {174, "DOD"}, {175, "DSD"}, {177, "HHC"}, {180, "TDR"}, - {182, "TDV"}, {186, "TZL"}}; + {182, "TDV"}}; static const std::unordered_map level3ProductDescription_ { @@ -84,7 +84,6 @@ static const std::unordered_map {"HHC", "Hybrid Hydrometeor Classification"}, {"TDR", "Digital Reflectivity"}, {"TDV", "Digital Velocity"}, - {"TZL", "Long Range Reflectivity"}, {"?", "Unknown"}}; static const std::unordered_map> @@ -92,7 +91,6 @@ static const std::unordered_map> // Reflectivity {"SDR", {"NXB", "NYB", "NZB", "N0B", "NAB", "N1B", "NBB", "N2B", "N3B"}}, {"DR", {"NXQ", "NYQ", "NZQ", "N0Q", "NAQ", "N1Q", "NBQ", "N2Q", "N3Q"}}, - {"TZL", {"TZL"}}, {"TDR", {"TZ0", "TZ1", "TZ2"}}, {"NCR", {"NCR"}}, @@ -186,7 +184,7 @@ static const std::unordered_map static const std::unordered_map> level3CategoryProductList_ { - {Level3ProductCategory::Reflectivity, {"SDR", "DR", "TZL", "TDR", "NCR"}}, + {Level3ProductCategory::Reflectivity, {"SDR", "DR", "TDR", "NCR"}}, {Level3ProductCategory::Velocity, {"SDV", "DV", "TDV"}}, {Level3ProductCategory::StormRelativeVelocity, {"SRM"}}, {Level3ProductCategory::SpectrumWidth, {"SW"}}, @@ -298,27 +296,9 @@ const std::string& GetLevel3CategoryDescription(Level3ProductCategory category) return level3CategoryDescription_.at(category); } -std::string -GetLevel3CategoryDefaultProduct(Level3ProductCategory category, - const Level3ProductCategoryMap& categoryMap) +const std::string& +GetLevel3CategoryDefaultProduct(Level3ProductCategory category) { - const auto& productsIt = categoryMap.find(category); - if (productsIt == categoryMap.cend()) - { - return level3CategoryDefaultAwipsId_.at(category); - } - - const auto& productsSiteHas = productsIt->second; - const auto& productList = level3CategoryProductList_.at(category); - for (auto& product : productList) - { - const auto& tiltsIt = productsSiteHas.find(product); - if (tiltsIt != productsSiteHas.cend() && tiltsIt->second.size() > 0) - { - return tiltsIt->second[0]; - } - } - return level3CategoryDefaultAwipsId_.at(category); } diff --git a/wxdata/source/scwx/gr/placefile.cpp b/wxdata/source/scwx/gr/placefile.cpp index 808ce19c..1806cdfe 100644 --- a/wxdata/source/scwx/gr/placefile.cpp +++ b/wxdata/source/scwx/gr/placefile.cpp @@ -20,7 +20,7 @@ #include -#if (__cpp_lib_chrono < 201907L) +#if !defined(_MSC_VER) # include #endif @@ -154,17 +154,9 @@ std::shared_ptr Placefile::font(std::size_t i) std::shared_ptr Placefile::Load(const std::string& filename) { - std::shared_ptr placefile = nullptr; - logger_->debug("Loading placefile: {}", filename); std::ifstream f(filename, std::ios_base::in); - - if (f.is_open()) - { - placefile = Load(filename, f); - } - - return placefile; + return Load(filename, f); } std::shared_ptr Placefile::Load(const std::string& name, @@ -292,7 +284,7 @@ void Placefile::Impl::ProcessLine(const std::string& line) { using namespace std::chrono; -#if (__cpp_lib_chrono < 201907L) +#if !defined(_MSC_VER) using namespace date; #endif diff --git a/wxdata/source/scwx/network/cpr.cpp b/wxdata/source/scwx/network/cpr.cpp index 0f8fb956..81dea5ad 100644 --- a/wxdata/source/scwx/network/cpr.cpp +++ b/wxdata/source/scwx/network/cpr.cpp @@ -7,6 +7,8 @@ namespace network namespace cpr { +static const std::string logPrefix_ = "scwx::network::cpr"; + static ::cpr::Header header_ {}; ::cpr::Header GetHeader() diff --git a/wxdata/source/scwx/network/dir_list.cpp b/wxdata/source/scwx/network/dir_list.cpp index f1be20b9..3c6dabd4 100644 --- a/wxdata/source/scwx/network/dir_list.cpp +++ b/wxdata/source/scwx/network/dir_list.cpp @@ -11,7 +11,7 @@ #include #include -#if (__cpp_lib_chrono < 201907L) +#if !defined(_MSC_VER) # include #endif @@ -200,7 +200,7 @@ void DirListSAXHandler::Characters(void* userData, const xmlChar* ch, int len) { using namespace std::chrono; -#if (__cpp_lib_chrono < 201907L) +#if !defined(_MSC_VER) using namespace date; #endif diff --git a/wxdata/source/scwx/network/ntp_client.cpp b/wxdata/source/scwx/network/ntp_client.cpp deleted file mode 100644 index 494aadde..00000000 --- a/wxdata/source/scwx/network/ntp_client.cpp +++ /dev/null @@ -1,571 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -namespace scwx::network -{ - -static const std::string logPrefix_ = "scwx::network::ntp_client"; -static const auto logger_ = scwx::util::Logger::Create(logPrefix_); - -static constexpr std::size_t kReceiveBufferSize_ {48u}; - -// Reasonable min/max values for polling intervals. We don't want to poll too -// quickly and upset the server, but we don't want to poll too slowly in the -// event of a time jump. -static constexpr std::uint32_t kMinPollInterval_ = 6u; // 2^6 = 64 seconds -static constexpr std::uint32_t kMaxPollInterval_ = 9u; // 2^9 = 512 seconds - -class NtpTimestamp -{ -public: - // NTP epoch: January 1, 1900 - // Unix epoch: January 1, 1970 - // Difference = 70 years = 2,208,988,800 seconds - static constexpr std::uint32_t kNtpToUnixOffset_ = 2208988800UL; - - // NTP fractional part represents 1/2^32 of a second - static constexpr std::uint64_t kFractionalMultiplier_ = 0x100000000ULL; - - static constexpr std::uint64_t _1e9 = 1000000000ULL; - - std::uint32_t seconds_ {0}; - std::uint32_t fraction_ {0}; - - explicit NtpTimestamp() = default; - explicit NtpTimestamp(std::uint32_t seconds, std::uint32_t fraction) : - seconds_ {seconds}, fraction_ {fraction} - { - } - ~NtpTimestamp() = default; - - NtpTimestamp(const NtpTimestamp&) = default; - NtpTimestamp& operator=(const NtpTimestamp&) = default; - NtpTimestamp(NtpTimestamp&&) = default; - NtpTimestamp& operator=(NtpTimestamp&&) = default; - - template - [[nodiscard]] std::chrono::time_point ToTimePoint() const - { - // Convert NTP seconds to Unix seconds - // Don't cast to a larger type to account for rollover, and this should - // work until 2106 - const std::uint32_t unixSeconds = seconds_ - kNtpToUnixOffset_; - - // Convert NTP fraction to nanoseconds - const auto nanoseconds = - static_cast(fraction_) * _1e9 / kFractionalMultiplier_; - - return std::chrono::time_point( - std::chrono::duration_cast( - std::chrono::seconds {unixSeconds} + - std::chrono::nanoseconds {nanoseconds})); - } - - template - static NtpTimestamp FromTimePoint(std::chrono::time_point timePoint) - { - // Convert to duration since Unix epoch - const auto unixDuration = timePoint.time_since_epoch(); - - // Extract seconds and nanoseconds - const auto unixSeconds = - std::chrono::duration_cast(unixDuration); - const auto nanoseconds = - std::chrono::duration_cast(unixDuration - - unixSeconds); - - // Convert Unix seconds to NTP seconds - const auto ntpSeconds = - static_cast(unixSeconds.count() + kNtpToUnixOffset_); - - // Convert nanoseconds to NTP fractional seconds - const auto ntpFraction = static_cast( - nanoseconds.count() * kFractionalMultiplier_ / _1e9); - - return NtpTimestamp(ntpSeconds, ntpFraction); - } -}; - -class NtpClient::Impl -{ -public: - explicit Impl(); - ~Impl(); - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(Impl&&) = delete; - Impl& operator=(Impl&&) = delete; - - void Open(std::string_view host, std::string_view service); - void OpenCurrentServer(); - void Poll(); - void ReceivePacket(std::size_t length); - std::string RotateServer(); - void Run(); - void RunOnce(); - - void FinishInitialization(); - - boost::asio::thread_pool threadPool_ {2u}; - - boost::asio::steady_timer pollTimer_ {threadPool_}; - std::uint32_t pollInterval_ {kMinPollInterval_}; - - bool enabled_ {true}; - bool error_ {false}; - bool disableServer_ {false}; - bool rotateServer_ {false}; - - std::mutex initializationMutex_ {}; - std::condition_variable initializationCondition_ {}; - std::atomic initialized_ {false}; - - types::ntp::NtpPacket transmitPacket_ {}; - - boost::asio::ip::udp::socket socket_ {threadPool_}; - std::optional serverEndpoint_ {}; - std::array receiveBuffer_ {}; - - std::chrono::system_clock::duration timeOffset_ {}; - - const std::vector serverList_ {"time.nist.gov", - "time.cloudflare.com", - "pool.ntp.org", - "time.aws.com", - "time.windows.com", - "time.apple.com"}; - std::vector disabledServers_ {}; - - std::vector::const_iterator currentServer_ = - serverList_.begin(); -}; - -NtpClient::NtpClient() : p(std::make_unique()) {} -NtpClient::~NtpClient() = default; - -NtpClient::NtpClient(NtpClient&&) noexcept = default; -NtpClient& NtpClient::operator=(NtpClient&&) noexcept = default; - -NtpClient::Impl::Impl() -{ - using namespace std::chrono_literals; - - const auto now = - std::chrono::floor(std::chrono::system_clock::now()); - - // The NTP timestamp will overflow in 2036. Overflow is handled in such a way - // that dates prior to 1970 result in a Unix timestamp after 2036. Additional - // handling for the year 2106 and subsequent eras is required. - static constexpr auto kMaxYear_ = 2106y; - - enabled_ = now < kMaxYear_ / 1 / 1; - - transmitPacket_.fields.vn = 3; // Version - transmitPacket_.fields.mode = 3; // Client (3) - - // If the NTP client is enabled, wait until the first refresh to consider - // "initialized". Otherwise, mark as initialized immediately to prevent a - // deadlock. - if (!enabled_) - { - initialized_ = true; - } -} - -NtpClient::Impl::~Impl() -{ - threadPool_.join(); -} - -bool NtpClient::error() -{ - const bool returnValue = p->error_; - p->error_ = false; - return returnValue; -} - -std::chrono::system_clock::duration NtpClient::time_offset() const -{ - return p->timeOffset_; -} - -void NtpClient::Start() -{ - if (p->enabled_) - { - boost::asio::post(p->threadPool_, [this]() { p->Run(); }); - } -} - -void NtpClient::Stop() -{ - p->enabled_ = false; - p->socket_.cancel(); - p->pollTimer_.cancel(); - p->threadPool_.join(); -} - -void NtpClient::Open(std::string_view host, std::string_view service) -{ - p->Open(host, service); -} - -void NtpClient::OpenCurrentServer() -{ - p->OpenCurrentServer(); -} - -void NtpClient::Poll() -{ - p->Poll(); -} - -std::string NtpClient::RotateServer() -{ - return p->RotateServer(); -} - -void NtpClient::RunOnce() -{ - p->RunOnce(); -} - -void NtpClient::Impl::Open(std::string_view host, std::string_view service) -{ - boost::asio::ip::udp::resolver resolver(threadPool_); - boost::system::error_code ec; - - auto results = resolver.resolve(host, service, ec); - if (ec.value() == boost::system::errc::success && !results.empty()) - { - logger_->info("Using NTP server: {}", host); - serverEndpoint_ = *results.begin(); - socket_.open(serverEndpoint_->protocol()); - } - else - { - serverEndpoint_ = std::nullopt; - logger_->warn("Could not resolve host {}: {}", host, ec.message()); - rotateServer_ = true; - } -} - -void NtpClient::Impl::OpenCurrentServer() -{ - Open(*currentServer_, "123"); -} - -void NtpClient::Impl::Poll() -{ - using namespace std::chrono_literals; - - static constexpr auto kTimeout_ = 5s; - - if (!serverEndpoint_.has_value()) - { - logger_->error("Server endpoint not set"); - error_ = true; - return; - } - - try - { - const auto originTimestamp = - NtpTimestamp::FromTimePoint(std::chrono::system_clock::now()); - transmitPacket_.txTm_s = ntohl(originTimestamp.seconds_); - transmitPacket_.txTm_f = ntohl(originTimestamp.fraction_); - - const std::size_t transmitPacketSize = sizeof(transmitPacket_); - // Send NTP request - socket_.send_to(boost::asio::buffer(&transmitPacket_, transmitPacketSize), - *serverEndpoint_); - - // Receive NTP response - auto future = - socket_.async_receive_from(boost::asio::buffer(receiveBuffer_), - *serverEndpoint_, - boost::asio::use_future); - std::size_t bytesReceived = 0; - - switch (future.wait_for(kTimeout_)) - { - case std::future_status::ready: - bytesReceived = future.get(); - ReceivePacket(bytesReceived); - break; - - case std::future_status::timeout: - case std::future_status::deferred: - logger_->warn("Timeout waiting for NTP response"); - socket_.cancel(); - error_ = true; - break; - } - } - catch (const std::exception& ex) - { - logger_->error("Error polling: {}", ex.what()); - error_ = true; - } -} - -void NtpClient::Impl::ReceivePacket(std::size_t length) -{ - if (length >= sizeof(types::ntp::NtpPacket)) - { - const auto destinationTime = std::chrono::system_clock::now(); - - const auto packet = types::ntp::NtpPacket::Parse(receiveBuffer_); - - if (packet.stratum == 0) - { - const std::uint32_t refId = ntohl(packet.refId); - const std::string kod = - std::string(reinterpret_cast(&refId), 4); - - logger_->warn("KoD packet received: {}", kod); - - if (kod == "DENY" || kod == "RSTR") - { - // The client MUST demobilize any associations to that server and - // stop sending packets to that server - disableServer_ = true; - } - else if (kod == "RATE") - { - // The client MUST immediately reduce its polling interval to that - // server and continue to reduce it each time it receives a RATE - // kiss code - if (pollInterval_ < kMaxPollInterval_) - { - ++pollInterval_; - } - else - { - // The server wants us to reduce the polling interval lower than - // what we deem useful. Move to the next server. - rotateServer_ = true; - } - } - - // Consider a KoD packet an error - error_ = true; - } - else - { - const auto originTimestamp = - NtpTimestamp(packet.origTm_s, packet.origTm_f); - const auto receiveTimestamp = - NtpTimestamp(packet.rxTm_s, packet.rxTm_f); - const auto transmitTimestamp = - NtpTimestamp(packet.txTm_s, packet.txTm_f); - - const auto originTime = originTimestamp.ToTimePoint(); - const auto receiveTime = receiveTimestamp.ToTimePoint(); - const auto transmitTime = transmitTimestamp.ToTimePoint(); - - const auto& t0 = originTime; - const auto& t1 = receiveTime; - const auto& t2 = transmitTime; - const auto& t3 = destinationTime; - - // Update time offset - timeOffset_ = ((t1 - t0) + (t2 - t3)) / 2; - - logger_->debug("Time offset updated: {:%jd %T}", timeOffset_); - } - } - else - { - logger_->warn("Received too few bytes: {}", length); - error_ = true; - } -} - -std::string NtpClient::Impl::RotateServer() -{ - socket_.close(); - - bool newServerFound = false; - - // Save the current server - const auto oldServer = currentServer_; - - while (!newServerFound) - { - // Increment the current server - ++currentServer_; - - // If we are at the end of the list, start over at the beginning - if (currentServer_ == serverList_.end()) - { - currentServer_ = serverList_.begin(); - } - - // If we have reached the end of the list, give up - if (currentServer_ == oldServer) - { - enabled_ = false; - break; - } - - // If the current server is disabled, continue searching - while (std::find(disabledServers_.cbegin(), - disabledServers_.cend(), - *currentServer_) != disabledServers_.cend()) - { - continue; - } - - // A new server has been found - newServerFound = true; - } - - pollInterval_ = kMinPollInterval_; - rotateServer_ = false; - - return *currentServer_; -} - -void NtpClient::Impl::Run() -{ - RunOnce(); - - if (enabled_) - { - const std::chrono::seconds pollIntervalSeconds {1u << pollInterval_}; - pollTimer_.expires_after(pollIntervalSeconds); - pollTimer_.async_wait( - [this](const boost::system::error_code& e) - { - if (e == boost::asio::error::operation_aborted) - { - logger_->debug("Poll timer cancelled"); - } - else if (e != boost::system::errc::success) - { - logger_->warn("Poll timer error: {}", e.message()); - } - else - { - try - { - Run(); - } - catch (const std::exception& ex) - { - logger_->error(ex.what()); - } - } - }); - } -} - -void NtpClient::Impl::RunOnce() -{ - if (disableServer_) - { - // Disable the current server - disabledServers_.push_back(*currentServer_); - - // Disable the NTP client if all servers are disabled - enabled_ = disabledServers_.size() == serverList_.size(); - - if (!enabled_) - { - error_ = true; - } - - disableServer_ = false; - rotateServer_ = enabled_; - } - - if (!enabled_ && socket_.is_open()) - { - // Sockets should be closed if the client is disabled - socket_.close(); - } - - if (rotateServer_) - { - // Rotate the server if requested - RotateServer(); - } - - if (enabled_ && !socket_.is_open()) - { - // Open the current server if it is not open - OpenCurrentServer(); - } - - if (socket_.is_open()) - { - // Send an NTP message to determine the current time offset - Poll(); - } - else if (enabled_) - { - // Did not poll this frame - error_ = true; - } - - FinishInitialization(); -} - -void NtpClient::Impl::FinishInitialization() -{ - if (!initialized_) - { - // Set initialized to true - std::unique_lock lock(initializationMutex_); - initialized_ = true; - lock.unlock(); - - // Notify any threads waiting for initialization - initializationCondition_.notify_all(); - } -} - -void NtpClient::WaitForInitialOffset() -{ - std::unique_lock lock(p->initializationMutex_); - - // While not yet initialized - while (!p->initialized_) - { - // Wait for initialization - p->initializationCondition_.wait(lock); - } -} - -std::shared_ptr NtpClient::Instance() -{ - static std::weak_ptr ntpClientReference_ {}; - static std::mutex instanceMutex_ {}; - - const std::unique_lock lock(instanceMutex_); - - std::shared_ptr ntpClient = ntpClientReference_.lock(); - - if (ntpClient == nullptr) - { - ntpClient = std::make_shared(); - ntpClientReference_ = ntpClient; - } - - return ntpClient; -} - -} // namespace scwx::network diff --git a/wxdata/source/scwx/provider/aws_level2_chunks_data_provider.cpp b/wxdata/source/scwx/provider/aws_level2_chunks_data_provider.cpp deleted file mode 100644 index f7de36ca..00000000 --- a/wxdata/source/scwx/provider/aws_level2_chunks_data_provider.cpp +++ /dev/null @@ -1,782 +0,0 @@ -#include "scwx/wsr88d/rda/digital_radar_data.hpp" -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - -// Avoid circular refrence errors in boost -// NOLINTBEGIN(misc-header-include-cycle) -#if defined(_MSC_VER) -# pragma warning(push, 0) -#endif - -#include -#include -#include - -#if defined(_MSC_VER) -# pragma warning(pop) -#endif -// NOLINTEND(misc-header-include-cycle) - -#if (__cpp_lib_chrono < 201907L) -# include -#endif - -namespace scwx::provider -{ -static const std::string logPrefix_ = - "scwx::provider::aws_level2_chunks_data_provider"; -static const auto logger_ = util::Logger::Create(logPrefix_); - -static const std::string kDefaultBucketName_ = "unidata-nexrad-level2-chunks"; -static const std::string kDefaultRegion_ = "us-east-1"; - -class AwsLevel2ChunksDataProvider::Impl -{ -public: - struct ScanRecord - { - explicit ScanRecord(std::string prefix, bool valid = true) : - valid_ {valid}, - prefix_ {std::move(prefix)}, - nexradFile_ {}, - lastModified_ {}, - lastKey_ {""} - { - } - ~ScanRecord() = default; - ScanRecord(const ScanRecord&) = default; - ScanRecord(ScanRecord&&) = default; - ScanRecord& operator=(const ScanRecord&) = default; - ScanRecord& operator=(ScanRecord&&) = default; - - bool valid_; - std::string prefix_; - std::shared_ptr nexradFile_; - std::chrono::system_clock::time_point time_; - std::chrono::system_clock::time_point lastModified_; - std::chrono::system_clock::time_point secondLastModified_; - std::string lastKey_; - int nextFile_ {1}; - bool hasAllFiles_ {false}; - }; - - explicit Impl(AwsLevel2ChunksDataProvider* self, - std::string radarSite, - std::string bucketName, - std::string region) : - radarSite_ {std::move(radarSite)}, - bucketName_ {std::move(bucketName)}, - region_ {std::move(region)}, - client_ {nullptr}, - scanTimes_ {}, - lastScan_ {"", false}, - currentScan_ {"", false}, - scansMutex_ {}, - lastTimeListed_ {}, - // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) about average - updatePeriod_ {7}, - level2DataProvider_ {}, - self_ {self} - { - // Disable HTTP request for region - util::SetEnvironment("AWS_EC2_METADATA_DISABLED", "true"); - - // Use anonymous credentials - const Aws::Auth::AWSCredentials credentials {}; - - Aws::Client::ClientConfiguration config; - config.region = region_; - // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) arbitrary - config.connectTimeoutMs = 10000; - - client_ = std::make_shared( - credentials, - Aws::MakeShared( - Aws::S3::S3Client::GetAllocationTag()), - config); - } - ~Impl() = default; - Impl(const Impl&) = delete; - Impl(Impl&&) = delete; - Impl& operator=(const Impl&) = delete; - Impl& operator=(Impl&&) = delete; - - std::chrono::system_clock::time_point GetScanTime(const std::string& prefix); - int GetScanNumber(const std::string& prefix); - - bool LoadScan(Impl::ScanRecord& scanRecord); - std::tuple ListObjects(); - - std::string radarSite_; - std::string bucketName_; - std::string region_; - std::shared_ptr client_; - - std::mutex refreshMutex_; - - std::unordered_map - scanTimes_; - ScanRecord lastScan_; - ScanRecord currentScan_; - std::shared_mutex scansMutex_; - std::chrono::system_clock::time_point lastTimeListed_; - - std::chrono::seconds updatePeriod_; - - std::weak_ptr level2DataProvider_; - - AwsLevel2ChunksDataProvider* self_; -}; - -AwsLevel2ChunksDataProvider::AwsLevel2ChunksDataProvider( - const std::string& radarSite) : - AwsLevel2ChunksDataProvider(radarSite, kDefaultBucketName_, kDefaultRegion_) -{ -} - -AwsLevel2ChunksDataProvider::AwsLevel2ChunksDataProvider( - const std::string& radarSite, - const std::string& bucketName, - const std::string& region) : - p(std::make_unique(this, radarSite, bucketName, region)) -{ -} - -AwsLevel2ChunksDataProvider::~AwsLevel2ChunksDataProvider() = default; - -std::chrono::system_clock::time_point -AwsLevel2ChunksDataProvider::GetTimePointByKey(const std::string& key) const -{ - std::chrono::system_clock::time_point time {}; - - const size_t lastSeparator = key.rfind('/'); - const size_t offset = - (lastSeparator == std::string::npos) ? 0 : lastSeparator + 1; - - // Filename format is YYYYMMDD-TTTTTT-AAA-B - static const size_t formatSize = std::string("YYYYMMDD-TTTTTT").size(); - - if (key.size() >= offset + formatSize) - { - using namespace std::chrono; - -#if (__cpp_lib_chrono < 201907L) - using namespace date; -#endif - - static const std::string timeFormat {"%Y%m%d-%H%M%S"}; - - std::string timeStr {key.substr(offset, formatSize)}; - std::istringstream in {timeStr}; - in >> parse(timeFormat, time); - - if (in.fail()) - { - logger_->warn("Invalid time: \"{}\"", timeStr); - } - } - else - { - logger_->warn("Time not parsable from key: \"{}\"", key); - } - - return time; -} - -size_t AwsLevel2ChunksDataProvider::cache_size() const -{ - return 2; -} - -std::chrono::system_clock::time_point -AwsLevel2ChunksDataProvider::last_modified() const -{ - // There is a slight delay between the "modified time" and when it is - // actually available. Radar product manager uses this as available time - static const auto extra = std::chrono::seconds(2); - - const std::shared_lock lock(p->scansMutex_); - if (p->currentScan_.valid_ && p->currentScan_.lastModified_ != - std::chrono::system_clock::time_point {}) - { - return p->currentScan_.lastModified_ + extra; - } - else if (p->lastScan_.valid_ && p->lastScan_.lastModified_ != - std::chrono::system_clock::time_point {}) - { - return p->lastScan_.lastModified_ + extra; - } - else - { - return {}; - } -} -std::chrono::seconds AwsLevel2ChunksDataProvider::update_period() const -{ - const std::shared_lock lock(p->scansMutex_); - // get update period from time between chunks - if (p->currentScan_.valid_ && p->currentScan_.nextFile_ > 2) - { - auto delta = - p->currentScan_.lastModified_ - p->currentScan_.secondLastModified_; - return std::chrono::duration_cast(delta); - } - else if (p->lastScan_.valid_ && p->lastScan_.nextFile_ > 2) - { - auto delta = - p->lastScan_.lastModified_ - p->lastScan_.secondLastModified_; - return std::chrono::duration_cast(delta); - } - - // default to a set update period - return p->updatePeriod_; -} - -std::string -AwsLevel2ChunksDataProvider::FindKey(std::chrono::system_clock::time_point time) -{ - logger_->debug("FindKey: {}", util::TimeString(time)); - - const std::shared_lock lock(p->scansMutex_); - if (p->currentScan_.valid_ && time >= p->currentScan_.time_) - { - return p->currentScan_.prefix_; - } - else if (p->lastScan_.valid_ && time >= p->lastScan_.time_) - { - return p->lastScan_.prefix_; - } - - return {}; -} - -std::string AwsLevel2ChunksDataProvider::FindLatestKey() -{ - const std::shared_lock lock(p->scansMutex_); - if (!p->currentScan_.valid_) - { - return ""; - } - - return p->currentScan_.prefix_; -} - -std::chrono::system_clock::time_point -AwsLevel2ChunksDataProvider::FindLatestTime() -{ - const std::shared_lock lock(p->scansMutex_); - if (!p->currentScan_.valid_) - { - return {}; - } - - return p->currentScan_.time_; -} - -std::vector -AwsLevel2ChunksDataProvider::GetTimePointsByDate( - std::chrono::system_clock::time_point /*date*/) -{ - return {}; -} - -std::chrono::system_clock::time_point -AwsLevel2ChunksDataProvider::Impl::GetScanTime(const std::string& prefix) -{ - using namespace std::chrono; - const auto& scanTimeIt = scanTimes_.find(prefix); // O(log(n)) - if (scanTimeIt != scanTimes_.cend()) - { - // If the time is greater than 2 hours ago, it may be a new scan - auto replaceBy = util::time::now() - hours {2}; - if (scanTimeIt->second > replaceBy) - { - return scanTimeIt->second; - } - } - - Aws::S3::Model::ListObjectsV2Request request; - request.SetBucket(bucketName_); - request.SetPrefix(prefix); - request.SetDelimiter("/"); - request.SetMaxKeys(1); - - auto outcome = client_->ListObjectsV2(request); - if (outcome.IsSuccess()) - { - auto timePoint = self_->GetTimePointByKey( - outcome.GetResult().GetContents().at(0).GetKey()); - scanTimes_.insert_or_assign(prefix, timePoint); - return timePoint; - } - - return {}; -} - -std::tuple -AwsLevel2ChunksDataProvider::Impl::ListObjects() -{ - size_t newObjects = 0; - const size_t totalObjects = 0; - - const std::chrono::system_clock::time_point now = util::time::now(); - - if (currentScan_.valid_ && !currentScan_.hasAllFiles_ && - lastTimeListed_ + std::chrono::minutes(2) > now) - { - return {true, newObjects, totalObjects}; - } - logger_->trace("ListObjects"); - lastTimeListed_ = now; - - const std::string prefix = radarSite_ + "/"; - - Aws::S3::Model::ListObjectsV2Request request; - request.SetBucket(bucketName_); - request.SetPrefix(prefix); - request.SetDelimiter("/"); - - auto outcome = client_->ListObjectsV2(request); - - if (outcome.IsSuccess()) - { - auto& scans = outcome.GetResult().GetCommonPrefixes(); - logger_->trace("Found {} scans", scans.size()); - - if (scans.size() > 0) - { - // find latest scan - auto scanNumberMap = std::map(); - - for (auto& scan : scans) // O(n log(n)) n <= 999 - { - const std::string& scanPrefix = scan.GetPrefix(); - scanNumberMap.insert_or_assign(GetScanNumber(scanPrefix), - scanPrefix); - } - - // Start with last scan - int previousScanNumber = scanNumberMap.crbegin()->first; - const int firstScanNumber = scanNumberMap.cbegin()->first; - - // Look for a gap in scan numbers. This indicates that is the latest - // scan. - - auto possibleLastNumbers = std::unordered_set(); - // This indicates that highest number scan may be the last scan - // (including if there is only 1 scan) - // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) - if (previousScanNumber != 999 || firstScanNumber != 1) - { - possibleLastNumbers.emplace(previousScanNumber); - } - // Have already checked scan with highest number, so skip first - previousScanNumber = firstScanNumber; - bool first = true; - for (const auto& scan : scanNumberMap) - { - if (first) - { - first = false; - continue; - } - if (scan.first != previousScanNumber + 1) - { - possibleLastNumbers.emplace(previousScanNumber); - } - previousScanNumber = scan.first; - } - - if (possibleLastNumbers.empty()) - { - logger_->warn("Could not find last scan"); - return {false, 0, 0}; - } - - int lastScanNumber = -1; - std::chrono::system_clock::time_point lastScanTime = {}; - std::string lastScanPrefix; - - for (const int scanNumber : possibleLastNumbers) - { - const std::string& scanPrefix = scanNumberMap.at(scanNumber); - auto scanTime = GetScanTime(scanPrefix); - if (scanTime > lastScanTime) - { - lastScanTime = scanTime; - lastScanPrefix = scanPrefix; - lastScanNumber = scanNumber; - } - } - - const int secondLastScanNumber = - // 999 is the last file possible - // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) - lastScanNumber == 1 ? 999 : lastScanNumber - 1; - - const auto& secondLastScanPrefix = - scanNumberMap.find(secondLastScanNumber); - - if (!currentScan_.valid_ || currentScan_.prefix_ != lastScanPrefix) - { - if (currentScan_.valid_ && - (secondLastScanPrefix == scanNumberMap.cend() || - currentScan_.prefix_ == secondLastScanPrefix->second)) - { - lastScan_ = currentScan_; - } - else if (secondLastScanPrefix != scanNumberMap.cend()) - { - lastScan_.valid_ = true; - lastScan_.prefix_ = secondLastScanPrefix->second; - lastScan_.nexradFile_ = nullptr; - lastScan_.time_ = GetScanTime(secondLastScanPrefix->second); - lastScan_.lastModified_ = {}; - lastScan_.secondLastModified_ = {}; - lastScan_.lastKey_ = ""; - lastScan_.nextFile_ = 1; - lastScan_.hasAllFiles_ = false; - newObjects += 1; - } - - currentScan_.valid_ = true; - currentScan_.prefix_ = lastScanPrefix; - currentScan_.nexradFile_ = nullptr; - currentScan_.time_ = lastScanTime; - currentScan_.lastModified_ = {}; - currentScan_.secondLastModified_ = {}; - currentScan_.lastKey_ = ""; - currentScan_.nextFile_ = 1; - currentScan_.hasAllFiles_ = false; - newObjects += 1; - } - } - } - - return {true, newObjects, totalObjects}; -} - -std::tuple -AwsLevel2ChunksDataProvider::ListObjects(std::chrono::system_clock::time_point) -{ - return {true, 0, 0}; -} - -std::shared_ptr -AwsLevel2ChunksDataProvider::LoadObjectByKey(const std::string& /*prefix*/) -{ - return nullptr; -} - -bool AwsLevel2ChunksDataProvider::Impl::LoadScan(Impl::ScanRecord& scanRecord) -{ - if (!scanRecord.valid_) - { - logger_->warn("Tried to load scan which was not listed yet"); - return false; - } - else if (scanRecord.hasAllFiles_) - { - return false; - } - - Aws::S3::Model::ListObjectsV2Request listRequest; - listRequest.SetBucket(bucketName_); - listRequest.SetPrefix(scanRecord.prefix_); - listRequest.SetDelimiter("/"); - if (!scanRecord.lastKey_.empty()) - { - listRequest.SetStartAfter(scanRecord.lastKey_); - } - - auto listOutcome = client_->ListObjectsV2(listRequest); - if (!listOutcome.IsSuccess()) - { - logger_->warn("Could not find scan at {}", scanRecord.prefix_); - return false; - } - - bool hasNew = false; - auto& chunks = listOutcome.GetResult().GetContents(); - logger_->trace("Found {} new chunks.", chunks.size()); - for (const auto& chunk : chunks) - { - const std::string& key = chunk.GetKey(); - - // KIND/585/20250324-134727-001-S - // KIND/5/20250324-134727-001-S - static const size_t firstSlash = std::string("KIND/").size(); - const size_t secondSlash = key.find('/', firstSlash); - static const size_t startNumberPosOffset = - std::string("/20250324-134727-").size(); - const size_t startNumberPos = secondSlash + startNumberPosOffset; - const std::string& keyNumberStr = key.substr(startNumberPos, 3); - const int keyNumber = std::stoi(keyNumberStr); - // As far as order goes, only the first one matters. This may cause some - // issues if keys come in out of order, but usually they just skip chunks - if (scanRecord.nextFile_ == 1 && keyNumber != scanRecord.nextFile_) - { - logger_->warn("Chunk found that was not in order {} {}", - scanRecord.lastKey_, - key); - continue; - } - - // Now we want the ending char - // KIND/585/20250324-134727-001-S - static const size_t charPos = std::string("/20250324-134727-001-").size(); - if (secondSlash + charPos >= key.size()) - { - logger_->warn("Chunk key was not long enough"); - continue; - } - const char keyChar = key[secondSlash + charPos]; - - Aws::S3::Model::GetObjectRequest objectRequest; - objectRequest.SetBucket(bucketName_); - objectRequest.SetKey(key); - - auto outcome = client_->GetObject(objectRequest); - - if (!outcome.IsSuccess()) - { - logger_->warn("Could not get object: {}", - outcome.GetError().GetMessage()); - return hasNew; - } - - auto& body = outcome.GetResultWithOwnership().GetBody(); - - switch (keyChar) - { - case 'S': - { // First chunk - scanRecord.nexradFile_ = std::make_shared(); - if (!scanRecord.nexradFile_->LoadData(body)) - { - logger_->warn("Failed to load first chunk"); - return hasNew; - } - break; - } - case 'I': - { // Middle chunk - if (!scanRecord.nexradFile_->LoadLDMRecords(body)) - { - logger_->warn("Failed to load middle chunk"); - return hasNew; - } - break; - } - case 'E': - { // Last chunk - if (!scanRecord.nexradFile_->LoadLDMRecords(body)) - { - logger_->warn("Failed to load last chunk"); - return hasNew; - } - scanRecord.hasAllFiles_ = true; - break; - } - default: - logger_->warn("Could not load chunk with unknown char"); - return hasNew; - } - hasNew = true; - - const std::chrono::seconds lastModifiedSeconds { - outcome.GetResult().GetLastModified().Seconds()}; - const std::chrono::system_clock::time_point lastModified { - lastModifiedSeconds}; - - scanRecord.secondLastModified_ = scanRecord.lastModified_; - scanRecord.lastModified_ = lastModified; - - scanRecord.nextFile_ = keyNumber + 1; - scanRecord.lastKey_ = key; - } - - if (scanRecord.nexradFile_ == nullptr) - { - logger_->warn("Could not load file"); - } - else if (hasNew) - { - scanRecord.nexradFile_->IndexFile(); - } - - return hasNew; -} - -std::shared_ptr -AwsLevel2ChunksDataProvider::LoadObjectByTime( - std::chrono::system_clock::time_point time) -{ - const std::unique_lock lock(p->scansMutex_); - static const std::chrono::system_clock::time_point epoch {}; - - if (p->currentScan_.valid_ && - (time == epoch || time >= p->currentScan_.time_)) - { - return std::make_shared(p->currentScan_.nexradFile_, - p->lastScan_.nexradFile_); - } - else if (p->lastScan_.valid_ && time >= p->lastScan_.time_) - { - return p->lastScan_.nexradFile_; - } - else - { - return nullptr; - } -} - -int AwsLevel2ChunksDataProvider::Impl::GetScanNumber(const std::string& prefix) -{ - // KIND/585/20250324-134727-001-S - static const size_t firstSlash = std::string("KIND/").size(); - const std::string& prefixNumberStr = prefix.substr(firstSlash, 3); - return std::stoi(prefixNumberStr); -} - -std::pair AwsLevel2ChunksDataProvider::Refresh() -{ - using namespace std::chrono; - - boost::timer::cpu_timer timer {}; - timer.start(); - - const std::unique_lock lock(p->refreshMutex_); - const std::unique_lock scanLock(p->scansMutex_); - - auto [success, newObjects, totalObjects] = p->ListObjects(); - - auto threadPool = boost::asio::thread_pool(3); - bool newCurrent = false; - bool newLast = false; - if (p->currentScan_.valid_) - { - boost::asio::post(threadPool, - [this, &newCurrent]() - { newCurrent = p->LoadScan(p->currentScan_); }); - totalObjects += 1; - } - - if (p->lastScan_.valid_) - { - totalObjects += 1; - boost::asio::post( - threadPool, - [this, &newLast]() - { - if (!p->lastScan_.hasAllFiles_) - { - // If we have chunks, use chunks - if (p->lastScan_.nextFile_ != 1) - { - newLast = p->LoadScan(p->lastScan_); - } - else - { - auto level2DataProvider = p->level2DataProvider_.lock(); - if (level2DataProvider != nullptr) - { - level2DataProvider->ListObjects(p->lastScan_.time_); - p->lastScan_.nexradFile_ = - std::dynamic_pointer_cast( - level2DataProvider->LoadObjectByTime( - p->lastScan_.time_)); - if (p->lastScan_.nexradFile_ != nullptr) - { - p->lastScan_.hasAllFiles_ = true; - } - } - // Fall back to chunks if files did not load - newLast = p->lastScan_.nexradFile_ != nullptr || - p->LoadScan(p->lastScan_); - } - } - }); - } - - threadPool.join(); - if (newCurrent) - { - newObjects += 1; - } - if (newLast) - { - newObjects += 1; - } - - timer.stop(); - // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) format to 6 digits - logger_->debug("Refresh() in {}", timer.format(6, "%ws")); - return std::make_pair(newObjects, totalObjects); -} - -void AwsLevel2ChunksDataProvider::RequestAvailableProducts() {} -std::vector AwsLevel2ChunksDataProvider::GetAvailableProducts() -{ - return {}; -} - -AwsLevel2ChunksDataProvider::AwsLevel2ChunksDataProvider( - AwsLevel2ChunksDataProvider&&) noexcept = default; -AwsLevel2ChunksDataProvider& AwsLevel2ChunksDataProvider::operator=( - AwsLevel2ChunksDataProvider&&) noexcept = default; - -std::optional AwsLevel2ChunksDataProvider::GetCurrentElevation() -{ - if (!p->currentScan_.valid_ || p->currentScan_.nexradFile_ == nullptr) - { - // Does not have any scan elevation. - return {}; - } - - auto vcpData = p->currentScan_.nexradFile_->vcp_data(); - auto radarData = p->currentScan_.nexradFile_->radar_data(); - if (radarData.size() == 0) - { - // Does not have any scan elevation. - return {}; - } - - const auto& lastElevation = radarData.crbegin(); - const std::shared_ptr digitalRadarData0 = - std::dynamic_pointer_cast( - lastElevation->second->cbegin()->second); - - if (vcpData != nullptr) - { - return static_cast(vcpData->elevation_angle(lastElevation->first)); - } - else if (digitalRadarData0 != nullptr) - { - return digitalRadarData0->elevation_angle().value(); - } - - return {}; -} - -void AwsLevel2ChunksDataProvider::SetLevel2DataProvider( - const std::shared_ptr& provider) -{ - p->level2DataProvider_ = provider; -} - -} // namespace scwx::provider diff --git a/wxdata/source/scwx/provider/aws_level2_data_provider.cpp b/wxdata/source/scwx/provider/aws_level2_data_provider.cpp index c2910773..6ac939c0 100644 --- a/wxdata/source/scwx/provider/aws_level2_data_provider.cpp +++ b/wxdata/source/scwx/provider/aws_level2_data_provider.cpp @@ -5,7 +5,7 @@ #include #include -#if (__cpp_lib_chrono < 201907L) +#if !defined(_MSC_VER) # include #endif @@ -82,7 +82,7 @@ AwsLevel2DataProvider::GetTimePointFromKey(const std::string& key) { using namespace std::chrono; -#if (__cpp_lib_chrono < 201907L) +#if !defined(_MSC_VER) using namespace date; #endif diff --git a/wxdata/source/scwx/provider/aws_level3_data_provider.cpp b/wxdata/source/scwx/provider/aws_level3_data_provider.cpp index 5bae6843..901eb41d 100644 --- a/wxdata/source/scwx/provider/aws_level3_data_provider.cpp +++ b/wxdata/source/scwx/provider/aws_level3_data_provider.cpp @@ -12,7 +12,7 @@ #include #include -#if (__cpp_lib_chrono < 201907L) +#if !defined(_MSC_VER) # include #endif @@ -110,7 +110,7 @@ AwsLevel3DataProvider::GetTimePointFromKey(const std::string& key) { using namespace std::chrono; -#if (__cpp_lib_chrono < 201907L) +#if !defined(_MSC_VER) using namespace date; #endif diff --git a/wxdata/source/scwx/provider/aws_nexrad_data_provider.cpp b/wxdata/source/scwx/provider/aws_nexrad_data_provider.cpp index 97528a9e..4e139bac 100644 --- a/wxdata/source/scwx/provider/aws_nexrad_data_provider.cpp +++ b/wxdata/source/scwx/provider/aws_nexrad_data_provider.cpp @@ -170,11 +170,6 @@ std::string AwsNexradDataProvider::FindLatestKey() return key; } -std::chrono::system_clock::time_point AwsNexradDataProvider::FindLatestTime() -{ - return GetTimePointByKey(FindLatestKey()); -} - std::vector AwsNexradDataProvider::GetTimePointsByDate( std::chrono::system_clock::time_point date) @@ -188,7 +183,6 @@ AwsNexradDataProvider::GetTimePointsByDate( std::shared_lock lock(p->objectsMutex_); // Is the date present in the date list? - bool currentDatePresent; auto currentDateIterator = std::find(p->objectDates_.cbegin(), p->objectDates_.cend(), day); if (currentDateIterator == p->objectDates_.cend()) @@ -205,12 +199,6 @@ AwsNexradDataProvider::GetTimePointsByDate( // Re-lock mutex lock.lock(); - - currentDatePresent = false; - } - else - { - currentDatePresent = true; } // Determine objects to retrieve @@ -228,7 +216,7 @@ AwsNexradDataProvider::GetTimePointsByDate( // If we haven't updated the most recently queried dates yet, because the // date was already cached, update - if (currentDatePresent) + if (currentDateIterator != p->objectDates_.cend()) { p->UpdateObjectDates(date); } @@ -332,27 +320,13 @@ AwsNexradDataProvider::LoadObjectByKey(const std::string& key) return nexradFile; } -std::shared_ptr AwsNexradDataProvider::LoadObjectByTime( - std::chrono::system_clock::time_point time) -{ - const std::string key = FindKey(time); - if (key.empty()) - { - return nullptr; - } - else - { - return LoadObjectByKey(key); - } -} - std::pair AwsNexradDataProvider::Refresh() { using namespace std::chrono; logger_->debug("Refresh()"); - auto today = floor(util::time::now()); + auto today = floor(system_clock::now()); auto yesterday = today - days {1}; std::unique_lock lock(p->refreshMutex_); @@ -388,7 +362,7 @@ void AwsNexradDataProvider::Impl::PruneObjects() { using namespace std::chrono; - auto today = floor(util::time::now()); + auto today = floor(system_clock::now()); auto yesterday = today - days {1}; std::unique_lock lock(objectsMutex_); diff --git a/wxdata/source/scwx/provider/iem_api_provider.cpp b/wxdata/source/scwx/provider/iem_api_provider.cpp deleted file mode 100644 index ef0576e7..00000000 --- a/wxdata/source/scwx/provider/iem_api_provider.cpp +++ /dev/null @@ -1,185 +0,0 @@ -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#if (__cpp_lib_chrono < 201907L) -# include -#endif - -namespace scwx::provider -{ - -static const std::string logPrefix_ = "scwx::provider::iem_api_provider"; - -const std::shared_ptr IemApiProvider::logger_ = - util::Logger::Create(logPrefix_); - -const std::string IemApiProvider::kBaseUrl_ = - "https://mesonet.agron.iastate.edu/api/1"; - -const std::string IemApiProvider::kListNwsTextProductsEndpoint_ = - "/nws/afos/list.json"; -const std::string IemApiProvider::kNwsTextProductEndpoint_ = "/nwstext/"; - -class IemApiProvider::Impl -{ -public: - explicit Impl() = default; - ~Impl() = default; - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; -}; - -IemApiProvider::IemApiProvider() : p(std::make_unique()) {} -IemApiProvider::~IemApiProvider() = default; - -IemApiProvider::IemApiProvider(IemApiProvider&&) noexcept = default; -IemApiProvider& IemApiProvider::operator=(IemApiProvider&&) noexcept = default; - -boost::outcome_v2::result> -IemApiProvider::ListTextProducts(std::chrono::sys_days date, - std::optional optionalCccc, - std::optional optionalPil) -{ - const std::string_view cccc = - optionalCccc.has_value() ? optionalCccc.value() : std::string_view {}; - const std::string_view pil = - optionalPil.has_value() ? optionalPil.value() : std::string_view {}; - - const auto dateArray = std::array {date}; - const auto ccccArray = std::array {cccc}; - const auto pilArray = std::array {pil}; - - return ListTextProducts(dateArray, ccccArray, pilArray); -} - -boost::outcome_v2::result> -IemApiProvider::ProcessTextProductLists( - std::vector& asyncResponses) -{ - std::vector textProducts {}; - - for (auto& asyncResponse : asyncResponses) - { - auto response = asyncResponse.get(); - - const boost::json::value json = util::json::ReadJsonString(response.text); - - if (response.status_code == cpr::status::HTTP_OK) - { - try - { - // Get AFOS list from response - auto entries = boost::json::value_to(json); - textProducts.insert(textProducts.end(), - std::make_move_iterator(entries.data_.begin()), - std::make_move_iterator(entries.data_.end())); - } - catch (const std::exception& ex) - { - // Unexpected bad response - logger_->warn("Error parsing JSON: {}", ex.what()); - return boost::system::errc::make_error_code( - boost::system::errc::bad_message); - } - } - else if (response.status_code == cpr::status::HTTP_BAD_REQUEST && - json != nullptr) - { - try - { - // Log bad request details - auto badRequest = - boost::json::value_to(json); - logger_->warn("ListTextProducts bad request: {}", - badRequest.detail_); - } - catch (const std::exception& ex) - { - // Unexpected bad response - logger_->warn("Error parsing bad response: {}", ex.what()); - } - - return boost::system::errc::make_error_code( - boost::system::errc::invalid_argument); - } - else if (response.status_code == cpr::status::HTTP_UNPROCESSABLE_ENTITY && - json != nullptr) - { - try - { - // Log validation error details - auto error = - boost::json::value_to(json); - logger_->warn("ListTextProducts validation error: {}", - error.detail_.at(0).msg_); - } - catch (const std::exception& ex) - { - // Unexpected bad response - logger_->warn("Error parsing validation error: {}", ex.what()); - } - - return boost::system::errc::make_error_code( - boost::system::errc::no_message_available); - } - else - { - logger_->warn("Could not list text products: {}", - response.status_line); - - return boost::system::errc::make_error_code( - boost::system::errc::no_message); - } - } - - logger_->debug("Found {} products", textProducts.size()); - - return textProducts; -} - -std::vector> -IemApiProvider::ProcessTextProductFiles( - std::vector>& asyncResponses) -{ - std::vector> textProductFiles; - - for (auto& asyncResponse : asyncResponses) - { - auto response = asyncResponse.second.get(); - - if (response.status_code == cpr::status::HTTP_OK) - { - // Load file - auto& productId = asyncResponse.first; - const std::shared_ptr textProductFile { - std::make_shared()}; - std::istringstream responseBody {response.text}; - if (textProductFile->LoadData(productId, responseBody)) - { - textProductFiles.push_back(textProductFile); - } - } - else - { - logger_->warn("Could not load text product: {} ({})", - asyncResponse.first, - response.status_line); - } - } - - logger_->debug("Loaded {} text products", textProductFiles.size()); - - return textProductFiles; -} - -} // namespace scwx::provider diff --git a/wxdata/source/scwx/provider/nexrad_data_provider_factory.cpp b/wxdata/source/scwx/provider/nexrad_data_provider_factory.cpp index dcaf7c9f..5e75fd96 100644 --- a/wxdata/source/scwx/provider/nexrad_data_provider_factory.cpp +++ b/wxdata/source/scwx/provider/nexrad_data_provider_factory.cpp @@ -1,6 +1,5 @@ #include #include -#include #include namespace scwx @@ -18,13 +17,6 @@ NexradDataProviderFactory::CreateLevel2DataProvider( return std::make_unique(radarSite); } -std::shared_ptr -NexradDataProviderFactory::CreateLevel2ChunksDataProvider( - const std::string& radarSite) -{ - return std::make_unique(radarSite); -} - std::shared_ptr NexradDataProviderFactory::CreateLevel3DataProvider( const std::string& radarSite, const std::string& product) diff --git a/wxdata/source/scwx/provider/warnings_provider.cpp b/wxdata/source/scwx/provider/warnings_provider.cpp index a762cd99..d187763a 100644 --- a/wxdata/source/scwx/provider/warnings_provider.cpp +++ b/wxdata/source/scwx/provider/warnings_provider.cpp @@ -1,19 +1,9 @@ -// Prevent redefinition of __cpp_lib_format -#if defined(_MSC_VER) -# include -#endif - -// Enable chrono formatters -#ifndef __cpp_lib_format -// NOLINTNEXTLINE(bugprone-reserved-identifier, cppcoreguidelines-macro-usage) -# define __cpp_lib_format 202110L -#endif - #include +#include #include -#include -#include +#include +#include #if defined(_MSC_VER) # pragma warning(push, 0) @@ -21,8 +11,10 @@ #define LIBXML_HTML_ENABLED #include +#include +#include -#if (__cpp_lib_chrono < 201907L) +#if !defined(_MSC_VER) # include #endif @@ -30,47 +22,40 @@ # pragma warning(pop) #endif -namespace scwx::provider +namespace scwx +{ +namespace provider { static const std::string logPrefix_ = "scwx::provider::warnings_provider"; static const auto logger_ = util::Logger::Create(logPrefix_); +static constexpr std::chrono::seconds kUpdatePeriod_ {15}; + class WarningsProvider::Impl { public: struct FileInfoRecord { - FileInfoRecord(std::string contentLength, std::string lastModified) : - contentLengthStr_ {std::move(contentLength)}, - lastModifiedStr_ {std::move(lastModified)} - { - } - - std::string contentLengthStr_ {}; - std::string lastModifiedStr_ {}; + std::chrono::system_clock::time_point startTime_ {}; + std::chrono::system_clock::time_point lastModified_ {}; + size_t size_ {}; + bool updated_ {}; }; - using WarningFileMap = std::map; + typedef std::map WarningFileMap; - explicit Impl(std::string baseUrl) : - baseUrl_ {std::move(baseUrl)}, files_ {}, filesMutex_ {} + explicit Impl(const std::string& baseUrl) : + baseUrl_ {baseUrl}, files_ {}, filesMutex_ {} { } - ~Impl() = default; - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; - - bool UpdateFileRecord(const cpr::Response& response, - const std::string& filename); + ~Impl() {} std::string baseUrl_; - WarningFileMap files_; - std::mutex filesMutex_; + WarningFileMap files_; + std::shared_mutex filesMutex_; }; WarningsProvider::WarningsProvider(const std::string& baseUrl) : @@ -83,177 +68,145 @@ WarningsProvider::WarningsProvider(WarningsProvider&&) noexcept = default; WarningsProvider& WarningsProvider::operator=(WarningsProvider&&) noexcept = default; -std::vector> -WarningsProvider::LoadUpdatedFiles( - std::chrono::sys_time startTime) +std::pair +WarningsProvider::ListFiles(std::chrono::system_clock::time_point newerThan) { using namespace std::chrono; -#if (__cpp_lib_chrono >= 201907L) - namespace df = std; - - static constexpr std::string_view kDateTimeFormat { - "warnings_{:%Y%m%d_%H}.txt"}; -#else +#if !defined(_MSC_VER) using namespace date; - namespace df = date; - -# define kDateTimeFormat "warnings_%Y%m%d_%H.txt" #endif - std::vector< - std::pair, false>>> - asyncCallbacks; - std::vector> updatedFiles; + static constexpr LazyRE2 reWarningsFilename = { + "warnings_[0-9]{8}_[0-9]{2}.txt"}; + static const std::string dateTimeFormat {"warnings_%Y%m%d_%H.txt"}; - const std::chrono::sys_time now = - std::chrono::floor(util::time::now()); - std::chrono::sys_time currentHour = - (startTime != std::chrono::sys_time {}) ? - startTime : - now - std::chrono::hours {1}; + logger_->trace("Listing files"); - logger_->trace("Querying files newer than: {}", util::TimeString(startTime)); + size_t updatedObjects = 0; + size_t totalObjects = 0; - while (currentHour <= now) + // Perform a directory listing + auto records = network::DirList(p->baseUrl_); + + // Sort records by filename + std::sort(records.begin(), + records.end(), + [](auto& a, auto& b) { return a.filename_ < b.filename_; }); + + // Filter warning records + auto warningRecords = + records | + std::views::filter( + [](auto& record) + { + return record.type_ == std::filesystem::file_type::regular && + RE2::FullMatch(record.filename_, *reWarningsFilename); + }); + + std::unique_lock lock(p->filesMutex_); + + Impl::WarningFileMap warningFileMap; + + // Store records + for (auto& record : warningRecords) { - const std::string filename = df::format(kDateTimeFormat, currentHour); - const std::string url = p->baseUrl_ + "/" + filename; + // Determine start time + std::chrono::sys_time startTime; + std::istringstream ssFilename {record.filename_}; - logger_->trace("HEAD request for file: {}", filename); + ssFilename >> parse(dateTimeFormat, startTime); - asyncCallbacks.emplace_back( - filename, - cpr::HeadCallback( - [url, filename, this]( - cpr::Response headResponse) -> std::optional + // If start time is valid + if (!ssFilename.fail()) + { + // Determine if the record should be marked updated + bool updated = true; + auto it = p->files_.find(record.filename_); + if (it != p->files_.cend()) + { + auto& existingRecord = it->second; + + updated = existingRecord.updated_ || + record.size_ != existingRecord.size_ || + record.mtime_ != existingRecord.lastModified_; + } + + // Update object counts, but only if newer than threshold + if (newerThan < startTime) + { + if (updated) { - if (headResponse.status_code == cpr::status::HTTP_OK) - { - const bool updated = - p->UpdateFileRecord(headResponse, filename); + ++updatedObjects; + } + ++totalObjects; + } - if (updated) - { - logger_->trace("GET request for file: {}", filename); - return cpr::GetAsync(cpr::Url {url}); - } - } - else if (headResponse.status_code != cpr::status::HTTP_NOT_FOUND) - { - logger_->warn("HEAD request for file failed: {} ({})", - url, - headResponse.status_line); - } - - return std::nullopt; - }, - cpr::Url {url})); - - // Query the next hour - currentHour += 1h; + // Store record + warningFileMap.emplace( + std::piecewise_construct, + std::forward_as_tuple(record.filename_), + std::forward_as_tuple( + startTime, record.mtime_, record.size_, updated)); + } } - for (auto& asyncCallback : asyncCallbacks) + p->files_ = std::move(warningFileMap); + + return std::make_pair(updatedObjects, totalObjects); +} + +std::vector> +WarningsProvider::LoadUpdatedFiles( + std::chrono::system_clock::time_point newerThan) +{ + logger_->debug("Loading updated files"); + + std::vector> updatedFiles; + + std::vector> asyncResponses; + + std::unique_lock lock(p->filesMutex_); + + // For each warning file + for (auto& record : p->files_) { - auto& filename = asyncCallback.first; - auto& callback = asyncCallback.second; - - if (callback.valid()) + // If file is updated, and time is later than the threshold + if (record.second.updated_ && newerThan < record.second.startTime_) { - // Wait for futures to complete - callback.wait(); - auto asyncResponse = callback.get(); + // Retrieve warning file + asyncResponses.emplace_back( + record.first, + cpr::GetAsync(cpr::Url {p->baseUrl_ + "/" + record.first})); - if (asyncResponse.has_value()) - { - auto response = asyncResponse.value().get(); - - if (response.status_code == cpr::status::HTTP_OK) - { - logger_->debug("Loading file: {}", filename); - - // Load file - const std::shared_ptr textProductFile { - std::make_shared()}; - std::istringstream responseBody {response.text}; - if (textProductFile->LoadData(filename, responseBody)) - { - updatedFiles.push_back(textProductFile); - } - } - else - { - logger_->warn("Could not load file: {} ({})", - filename, - response.status_line); - } - } + // Clear updated flag + record.second.updated_ = false; } - else + } + + lock.unlock(); + + // Wait for warning files to load + for (auto& asyncResponse : asyncResponses) + { + cpr::Response response = asyncResponse.second.get(); + if (response.status_code == cpr::status::HTTP_OK) { - logger_->error("Invalid future state"); + logger_->debug("Loading file: {}", asyncResponse.first); + + // Load file + std::shared_ptr textProductFile { + std::make_shared()}; + std::istringstream responseBody {response.text}; + if (textProductFile->LoadData(responseBody)) + { + updatedFiles.push_back(textProductFile); + } } } return updatedFiles; } -bool WarningsProvider::Impl::UpdateFileRecord(const cpr::Response& response, - const std::string& filename) -{ - bool updated = false; - - auto contentLengthIt = response.header.find("Content-Length"); - auto lastModifiedIt = response.header.find("Last-Modified"); - - std::string contentLength {}; - std::string lastModified {}; - - if (contentLengthIt != response.header.cend()) - { - contentLength = contentLengthIt->second; - } - if (lastModifiedIt != response.header.cend()) - { - lastModified = lastModifiedIt->second; - } - - const std::unique_lock lock(filesMutex_); - - auto it = files_.find(filename); - if (it != files_.cend()) - { - auto& existingRecord = it->second; - - // If the size or last modified changes, request an update - - if (!contentLength.empty() && - contentLength != existingRecord.contentLengthStr_) - { - // Size changed - existingRecord.contentLengthStr_ = contentLengthIt->second; - updated = true; - } - else if (!lastModified.empty() && - lastModified != existingRecord.lastModifiedStr_) - { - // Last modified changed - existingRecord.lastModifiedStr_ = lastModifiedIt->second; - updated = true; - } - } - else - { - // File not found - files_.emplace(std::piecewise_construct, - std::forward_as_tuple(filename), - std::forward_as_tuple(contentLength, lastModified)); - updated = true; - } - - return updated; -} - -} // namespace scwx::provider +} // namespace provider +} // namespace scwx diff --git a/wxdata/source/scwx/types/iem_types.cpp b/wxdata/source/scwx/types/iem_types.cpp deleted file mode 100644 index ed3884d3..00000000 --- a/wxdata/source/scwx/types/iem_types.cpp +++ /dev/null @@ -1,111 +0,0 @@ -#include - -#include - -namespace scwx::types::iem -{ - -AfosEntry tag_invoke(boost::json::value_to_tag, - const boost::json::value& jv) -{ - auto& jo = jv.as_object(); - - AfosEntry entry {}; - - // Required parameters - entry.index_ = jo.at("index").as_int64(); - entry.entered_ = jo.at("entered").as_string(); - entry.pil_ = jo.at("pil").as_string(); - entry.productId_ = jo.at("product_id").as_string(); - entry.cccc_ = jo.at("cccc").as_string(); - entry.count_ = jo.at("count").as_int64(); - entry.link_ = jo.at("link").as_string(); - entry.textLink_ = jo.at("text_link").as_string(); - - return entry; -} - -AfosList tag_invoke(boost::json::value_to_tag, - const boost::json::value& jv) -{ - auto& jo = jv.as_object(); - - AfosList list {}; - - // Required parameters - list.data_ = boost::json::value_to>(jo.at("data")); - - return list; -} - -BadRequest tag_invoke(boost::json::value_to_tag, - const boost::json::value& jv) -{ - auto& jo = jv.as_object(); - - BadRequest badRequest {}; - - // Required parameters - badRequest.detail_ = jo.at("detail").as_string(); - - return badRequest; -} - -ValidationError::Detail::Context -tag_invoke(boost::json::value_to_tag, - const boost::json::value& jv) -{ - auto& jo = jv.as_object(); - - ValidationError::Detail::Context ctx {}; - - // Required parameters - ctx.error_ = jo.at("error").as_string(); - - return ctx; -} - -ValidationError::Detail -tag_invoke(boost::json::value_to_tag, - const boost::json::value& jv) -{ - auto& jo = jv.as_object(); - - ValidationError::Detail detail {}; - - // Required parameters - detail.type_ = jo.at("type").as_string(); - detail.loc_ = boost::json::value_to< - std::vector>>(jo.at("loc")); - detail.msg_ = jo.at("msg").as_string(); - - // Optional parameters - if (jo.contains("input")) - { - detail.input_ = jo.at("input").as_string(); - } - - if (jo.contains("ctx")) - { - detail.ctx_ = - boost::json::value_to(jo.at("ctx")); - } - - return detail; -} - -ValidationError tag_invoke(boost::json::value_to_tag, - const boost::json::value& jv) -{ - auto& jo = jv.as_object(); - - ValidationError error {}; - - // Required parameters - error.detail_ = boost::json::value_to>( - jo.at("detail")); - - return error; -} - -} // namespace scwx::types::iem diff --git a/wxdata/source/scwx/types/ntp_types.cpp b/wxdata/source/scwx/types/ntp_types.cpp deleted file mode 100644 index daf5d46b..00000000 --- a/wxdata/source/scwx/types/ntp_types.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include - -#include -#include - -#ifdef _WIN32 -# include -#else -# include -#endif - -namespace scwx::types::ntp -{ - -NtpPacket NtpPacket::Parse(const std::span data) -{ - NtpPacket packet {}; - - assert(data.size() >= sizeof(NtpPacket)); - - packet = *reinterpret_cast(data.data()); - - packet.rootDelay = ntohl(packet.rootDelay); - packet.rootDispersion = ntohl(packet.rootDispersion); - packet.refId = ntohl(packet.refId); - - packet.refTm_s = ntohl(packet.refTm_s); - packet.refTm_f = ntohl(packet.refTm_f); - - packet.origTm_s = ntohl(packet.origTm_s); - packet.origTm_f = ntohl(packet.origTm_f); - - packet.rxTm_s = ntohl(packet.rxTm_s); - packet.rxTm_f = ntohl(packet.rxTm_f); - - packet.txTm_s = ntohl(packet.txTm_s); - packet.txTm_f = ntohl(packet.txTm_f); - - return packet; -} - -} // namespace scwx::types::ntp diff --git a/wxdata/source/scwx/util/json.cpp b/wxdata/source/scwx/util/json.cpp deleted file mode 100644 index d5873758..00000000 --- a/wxdata/source/scwx/util/json.cpp +++ /dev/null @@ -1,201 +0,0 @@ -#include -#include - -#include - -#include -#include - -namespace scwx::util::json -{ - -static const std::string logPrefix_ = "scwx::util::json"; -static const auto logger_ = scwx::util::Logger::Create(logPrefix_); - -/* Adapted from: - * https://www.boost.org/doc/libs/1_77_0/libs/json/doc/html/json/examples.html#json.examples.pretty - * - * Copyright (c) 2019, 2020 Vinnie Falco - * Copyright (c) 2020 Krystian Stasiowski - * Distributed under the Boost Software License, Version 1.0. (See - * http://www.boost.org/LICENSE_1_0.txt) - */ -static void PrettyPrintJson(std::ostream& os, - boost::json::value const& jv, - std::string* indent = nullptr); - -boost::json::value ReadJsonFile(const std::string& path) -{ - boost::json::value json; - - std::ifstream ifs {path}; - json = ReadJsonStream(ifs); - - return json; -} - -boost::json::value ReadJsonStream(std::istream& is) -{ - std::string line; - - boost::json::stream_parser p; - boost::system::error_code ec; - - while (std::getline(is, line)) - { - p.write(line, ec); - if (ec) - { - logger_->warn("{}", ec.message()); - return nullptr; - } - } - - p.finish(ec); - if (ec) - { - logger_->warn("{}", ec.message()); - return nullptr; - } - - return p.release(); -} - -boost::json::value ReadJsonString(std::string_view sv) -{ - boost::json::stream_parser p; - boost::system::error_code ec; - - p.write(sv, ec); - if (ec) - { - logger_->warn("{}", ec.message()); - return nullptr; - } - - p.finish(ec); - if (ec) - { - logger_->warn("{}", ec.message()); - return nullptr; - } - - return p.release(); -} - -void WriteJsonFile(const std::string& path, - const boost::json::value& json, - bool prettyPrint) -{ - std::ofstream ofs {path}; - - if (!ofs.is_open()) - { - logger_->warn("Cannot write JSON file: \"{}\"", path); - } - else - { - if (prettyPrint) - { - PrettyPrintJson(ofs, json); - } - else - { - ofs << json; - } - ofs.close(); - } -} - -// Allow recursion within the pretty print function -// NOLINTNEXTLINE(misc-no-recursion) -static void PrettyPrintJson(std::ostream& os, - boost::json::value const& jv, - std::string* indent) -{ - std::string indent_; - if (!indent) - indent = &indent_; - switch (jv.kind()) - { - case boost::json::kind::object: - { - os << "{\n"; - indent->append(4, ' '); - auto const& obj = jv.get_object(); - if (!obj.empty()) - { - auto it = obj.begin(); - for (;;) - { - os << *indent << boost::json::serialize(it->key()) << " : "; - PrettyPrintJson(os, it->value(), indent); - if (++it == obj.end()) - break; - os << ",\n"; - } - } - os << "\n"; - indent->resize(indent->size() - 4); - os << *indent << "}"; - break; - } - - case boost::json::kind::array: - { - os << "[\n"; - indent->append(4, ' '); - auto const& arr = jv.get_array(); - if (!arr.empty()) - { - auto it = arr.begin(); - for (;;) - { - os << *indent; - PrettyPrintJson(os, *it, indent); - if (++it == arr.end()) - break; - os << ",\n"; - } - } - os << "\n"; - indent->resize(indent->size() - 4); - os << *indent << "]"; - break; - } - - case boost::json::kind::string: - { - os << boost::json::serialize(jv.get_string()); - break; - } - - case boost::json::kind::uint64: - os << jv.get_uint64(); - break; - - case boost::json::kind::int64: - os << jv.get_int64(); - break; - - case boost::json::kind::double_: - os << jv.get_double(); - break; - - case boost::json::kind::bool_: - if (jv.get_bool()) - os << "true"; - else - os << "false"; - break; - - case boost::json::kind::null: - os << "null"; - break; - } - - if (indent->empty()) - os << "\n"; -} - -} // namespace scwx::util::json diff --git a/wxdata/source/scwx/util/logger.cpp b/wxdata/source/scwx/util/logger.cpp index 407ce354..8a97d80e 100644 --- a/wxdata/source/scwx/util/logger.cpp +++ b/wxdata/source/scwx/util/logger.cpp @@ -20,12 +20,6 @@ static std::vector> extraSinks_ {}; void Initialize() { spdlog::set_pattern(logPattern_); - - // Periodically flush every 3 seconds - spdlog::flush_every(std::chrono::seconds(3)); - - // Flush whenever logging info or higher - spdlog::flush_on(spdlog::level::level_enum::info); } void AddFileSink(const std::string& baseFilename) diff --git a/wxdata/source/scwx/util/streams.cpp b/wxdata/source/scwx/util/streams.cpp index 6374ed35..9e094f9b 100644 --- a/wxdata/source/scwx/util/streams.cpp +++ b/wxdata/source/scwx/util/streams.cpp @@ -1,7 +1,8 @@ #include -#include -namespace scwx::util +namespace scwx +{ +namespace util { std::istream& getline(std::istream& is, std::string& t) @@ -16,8 +17,7 @@ std::istream& getline(std::istream& is, std::string& t) int c = sb->sbumpc(); switch (c) { - case '\n': - return is; + case '\n': return is; case '\r': while (sb->sgetc() == '\r') @@ -30,10 +30,6 @@ std::istream& getline(std::istream& is, std::string& t) } return is; - case common::Characters::ETX: - sb->sungetc(); - return is; - case std::streambuf::traits_type::eof(): if (t.empty()) { @@ -41,10 +37,10 @@ std::istream& getline(std::istream& is, std::string& t) } return is; - default: - t += static_cast(c); + default: t += static_cast(c); } } } -} // namespace scwx::util +} // namespace util +} // namespace scwx diff --git a/wxdata/source/scwx/util/time.cpp b/wxdata/source/scwx/util/time.cpp index 1a687d32..5cf091fe 100644 --- a/wxdata/source/scwx/util/time.cpp +++ b/wxdata/source/scwx/util/time.cpp @@ -8,7 +8,6 @@ # define __cpp_lib_format 202110L #endif -#include #include #include #include @@ -18,11 +17,13 @@ #include -#if (__cpp_lib_chrono < 201907L) +#if !defined(_MSC_VER) # include #endif -namespace scwx::util::time +namespace scwx +{ +namespace util { static const std::string logPrefix_ = "scwx::util::time"; @@ -33,8 +34,6 @@ static const std::unordered_map clockFormatName_ { {ClockFormat::_24Hour, "24-hour"}, {ClockFormat::Unknown, "?"}}; -static std::shared_ptr ntpClient_ {nullptr}; - SCWX_GET_ENUM(ClockFormat, GetClockFormat, clockFormatName_) const std::string& GetClockFormatName(ClockFormat clockFormat) @@ -42,26 +41,6 @@ const std::string& GetClockFormatName(ClockFormat clockFormat) return clockFormatName_.at(clockFormat); } -template -std::chrono::time_point now() -{ - if (ntpClient_ == nullptr) - { - ntpClient_ = network::NtpClient::Instance(); - } - - if (ntpClient_ != nullptr) - { - return Clock::now() + ntpClient_->time_offset(); - } - else - { - return Clock::now(); - } -} - -template std::chrono::time_point now(); - std::chrono::system_clock::time_point TimePoint(uint32_t modifiedJulianDate, uint32_t milliseconds) { @@ -69,7 +48,6 @@ std::chrono::system_clock::time_point TimePoint(uint32_t modifiedJulianDate, using sys_days = time_point; constexpr auto epoch = sys_days {1969y / December / 31d}; - // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers): literals are used return epoch + (modifiedJulianDate * 24h) + std::chrono::milliseconds {milliseconds}; } @@ -81,20 +59,16 @@ std::string TimeString(std::chrono::system_clock::time_point time, { using namespace std::chrono; -#if (__cpp_lib_chrono >= 201907L) +#if defined(_MSC_VER) +# define FORMAT_STRING_24_HOUR "{:%Y-%m-%d %H:%M:%S %Z}" +# define FORMAT_STRING_12_HOUR "{:%Y-%m-%d %I:%M:%S %p %Z}" namespace date = std::chrono; namespace df = std; - - static constexpr std::string_view kFormatString24Hour = - "{:%Y-%m-%d %H:%M:%S %Z}"; - static constexpr std::string_view kFormatString12Hour = - "{:%Y-%m-%d %I:%M:%S %p %Z}"; #else +# define FORMAT_STRING_24_HOUR "%Y-%m-%d %H:%M:%S %Z" +# define FORMAT_STRING_12_HOUR "%Y-%m-%d %I:%M:%S %p %Z" using namespace date; namespace df = date; - -# define kFormatString24Hour "%Y-%m-%d %H:%M:%S %Z" -# define kFormatString12Hour "%Y-%m-%d %I:%M:%S %p %Z" #endif auto timeInSeconds = time_point_cast(time); @@ -110,11 +84,11 @@ std::string TimeString(std::chrono::system_clock::time_point time, if (clockFormat == ClockFormat::_24Hour) { - os << df::format(kFormatString24Hour, zt); + os << df::format(FORMAT_STRING_24_HOUR, zt); } else { - os << df::format(kFormatString12Hour, zt); + os << df::format(FORMAT_STRING_12_HOUR, zt); } } catch (const std::exception& ex) @@ -136,11 +110,11 @@ std::string TimeString(std::chrono::system_clock::time_point time, { if (clockFormat == ClockFormat::_24Hour) { - os << df::format(kFormatString24Hour, timeInSeconds); + os << df::format(FORMAT_STRING_24_HOUR, timeInSeconds); } else { - os << df::format(kFormatString12Hour, timeInSeconds); + os << df::format(FORMAT_STRING_12_HOUR, timeInSeconds); } } } @@ -154,7 +128,7 @@ TryParseDateTime(const std::string& dateTimeFormat, const std::string& str) { using namespace std::chrono; -#if (__cpp_lib_chrono < 201907L) +#if !defined(_MSC_VER) using namespace date; #endif @@ -176,4 +150,5 @@ template std::optional> TryParseDateTime(const std::string& dateTimeFormat, const std::string& str); -} // namespace scwx::util::time +} // namespace util +} // namespace scwx diff --git a/wxdata/source/scwx/wsr88d/ar2v_file.cpp b/wxdata/source/scwx/wsr88d/ar2v_file.cpp index f4a71c15..6d951d6c 100644 --- a/wxdata/source/scwx/wsr88d/ar2v_file.cpp +++ b/wxdata/source/scwx/wsr88d/ar2v_file.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include @@ -24,7 +23,6 @@ #include #include #include -#include #if defined(__GNUC__) # pragma GCC diagnostic pop @@ -67,9 +65,7 @@ public: std::map> radarData_ {}; std::map>>> + std::map>> index_ {}; std::list rawRecords_ {}; @@ -134,60 +130,58 @@ std::shared_ptr Ar2vFile::vcp_data() const } std::tuple, float, std::vector> -Ar2vFile::GetElevationScan(rda::DataBlockType dataBlockType, - float elevation, - std::chrono::system_clock::time_point time) const +Ar2vFile::GetElevationScan(rda::DataBlockType dataBlockType, + float elevation, + std::chrono::system_clock::time_point /*time*/) const { - logger_->trace("GetElevationScan: {} degrees", elevation); + logger_->debug("GetElevationScan: {} degrees", elevation); + + constexpr float scaleFactor = 8.0f / 0.043945f; std::shared_ptr elevationScan = nullptr; float elevationCut = 0.0f; std::vector elevationCuts; + std::uint16_t codedElevation = + static_cast(std::lroundf(elevation * scaleFactor)); + if (p->index_.contains(dataBlockType)) { auto& scans = p->index_.at(dataBlockType); - float lowerBound = scans.cbegin()->first; - float upperBound = scans.crbegin()->first; + std::uint16_t lowerBound = scans.cbegin()->first; + std::uint16_t upperBound = scans.crbegin()->first; - // Find closest elevation match for (auto& scan : scans) { - if (scan.first > lowerBound && scan.first <= elevation) + if (scan.first > lowerBound && scan.first <= codedElevation) { lowerBound = scan.first; } - if (scan.first < upperBound && scan.first >= elevation) + if (scan.first < upperBound && scan.first >= codedElevation) { upperBound = scan.first; } - elevationCuts.push_back(scan.first); + elevationCuts.push_back(scan.first / scaleFactor); } - const float lowerDelta = std::abs(elevation - lowerBound); - const float upperDelta = std::abs(elevation - upperBound); + std::int32_t lowerDelta = + std::abs(static_cast(codedElevation) - + static_cast(lowerBound)); + std::int32_t upperDelta = + std::abs(static_cast(codedElevation) - + static_cast(upperBound)); - // Select closest elevation match - elevationCut = (lowerDelta < upperDelta) ? lowerBound : upperBound; - - // Select closest time match, not newer than the selected time - std::chrono::system_clock::time_point foundTime {}; - auto& elevationScans = scans.at(elevationCut); - - for (auto& scan : elevationScans) + if (lowerDelta < upperDelta) { - auto scanTime = std::chrono::floor(scan.first); - - if (elevationScan == nullptr || - ((scanTime <= time || - time == std::chrono::system_clock::time_point {}) && - scanTime > foundTime)) - { - elevationScan = scan.second; - foundTime = scanTime; - } + elevationScan = scans.at(lowerBound); + elevationCut = lowerBound / scaleFactor; + } + else + { + elevationScan = scans.at(upperBound); + elevationCut = upperBound / scaleFactor; } } @@ -246,13 +240,10 @@ bool Ar2vFile::LoadData(std::istream& is) if (dataValid) { - auto timePoint = util::TimePoint(p->julianDate_, p->milliseconds_); - logger_->debug("Filename: {}", p->tapeFilename_); logger_->debug("Extension: {}", p->extensionNumber_); - logger_->debug("Date: {} ({:%Y-%m-%d})", p->julianDate_, timePoint); - logger_->debug( - "Time: {} ({:%H:%M:%S})", p->milliseconds_, timePoint); + logger_->debug("Date: {}", p->julianDate_); + logger_->debug("Time: {}", p->milliseconds_); logger_->debug("ICAO: {}", p->icao_); size_t decompressedRecords = p->DecompressLDMRecords(is); @@ -273,7 +264,7 @@ bool Ar2vFile::LoadData(std::istream& is) std::size_t Ar2vFileImpl::DecompressLDMRecords(std::istream& is) { - logger_->trace("Decompressing LDM Records"); + logger_->debug("Decompressing LDM Records"); std::size_t numRecords = 0; @@ -321,14 +312,14 @@ std::size_t Ar2vFileImpl::DecompressLDMRecords(std::istream& is) ++numRecords; } - logger_->trace("Decompressed {} LDM Records", numRecords); + logger_->debug("Decompressed {} LDM Records", numRecords); return numRecords; } void Ar2vFileImpl::ParseLDMRecords() { - logger_->trace("Parsing LDM Records"); + logger_->debug("Parsing LDM Records"); std::size_t count = 0; @@ -445,11 +436,11 @@ void Ar2vFileImpl::ProcessRadarData( void Ar2vFileImpl::IndexFile() { - logger_->trace("Indexing file"); + logger_->debug("Indexing file"); for (auto& elevationCut : radarData_) { - float elevationAngle {}; + std::uint16_t elevationAngle {}; rda::WaveformType waveformType = rda::WaveformType::Unknown; std::shared_ptr& radial0 = @@ -465,15 +456,14 @@ void Ar2vFileImpl::IndexFile() if (vcpData_ != nullptr) { - elevationAngle = - static_cast(vcpData_->elevation_angle(elevationCut.first)); - waveformType = vcpData_->waveform_type(elevationCut.first); + elevationAngle = vcpData_->elevation_angle_raw(elevationCut.first); + waveformType = vcpData_->waveform_type(elevationCut.first); } else if ((digitalRadarData0 = - std::dynamic_pointer_cast(radial0)) != - nullptr) + std::dynamic_pointer_cast( + (*elevationCut.second)[0])) != nullptr) { - elevationAngle = digitalRadarData0->elevation_angle().value(); + elevationAngle = digitalRadarData0->elevation_angle_raw(); } else { @@ -498,239 +488,8 @@ void Ar2vFileImpl::IndexFile() if (momentData != nullptr) { - auto time = util::TimePoint(radial0->modified_julian_date(), - radial0->collection_time()); - - index_[dataBlockType][elevationAngle][time] = elevationCut.second; - } - } - } -} - -bool Ar2vFile::LoadLDMRecords(std::istream& is) -{ - const size_t decompressedRecords = p->DecompressLDMRecords(is); - if (decompressedRecords == 0) - { - p->ParseLDMRecord(is); - } - else - { - p->ParseLDMRecords(); - } - - return true; -} - -bool Ar2vFile::IndexFile() -{ - p->IndexFile(); - return true; -} - -// NOLINTNEXTLINE -bool IsRadarDataIncomplete( - const std::shared_ptr& radarData) -{ - // Assume the data is incomplete when the delta between the first and last - // angles is greater than 2.5 degrees. - constexpr units::degrees kIncompleteDataAngleThreshold_ {2.5}; - - const units::degrees firstAngle = - radarData->cbegin()->second->azimuth_angle(); - const units::degrees lastAngle = - radarData->crbegin()->second->azimuth_angle(); - const units::degrees angleDelta = - common::GetAngleDelta(firstAngle, lastAngle); - - return angleDelta > kIncompleteDataAngleThreshold_; -} - -Ar2vFile::Ar2vFile(const std::shared_ptr& current, - const std::shared_ptr& last) : - Ar2vFile() -{ - // This is only used to index right now, so not a huge deal - p->vcpData_ = nullptr; - - // Reconstruct index from the other's indexes - if (current != nullptr) - { - for (const auto& type : current->p->index_) - { - for (const auto& elevation : type.second) - { - // Get the most recent scan - const auto& mostRecent = elevation.second.crbegin(); - if (mostRecent == elevation.second.crend()) - { - continue; - } - - // Add previous scans for stepping back in time - for (auto scan = ++(elevation.second.rbegin()); - scan != elevation.second.rend(); - ++scan) - { - p->index_[type.first][elevation.first][scan->first] = - scan->second; - } - - // Merge this scan with the last one if it is incomplete - if (IsRadarDataIncomplete(mostRecent->second)) - { - std::shared_ptr secondMostRecent = nullptr; - - // check if this volume scan has an earlier elevation scan - auto possibleSecondMostRecent = elevation.second.rbegin(); - ++possibleSecondMostRecent; - - if (possibleSecondMostRecent == elevation.second.rend()) - { - if (last == nullptr) - { - // Nothing to merge with - p->index_[type.first][elevation.first][mostRecent->first] = - mostRecent->second; - continue; - } - - // get the scan from the last scan - auto elevationScan = - std::get>( - last->GetElevationScan( - type.first, elevation.first, {})); - if (elevationScan == nullptr) - { - // Nothing to merge with - p->index_[type.first][elevation.first][mostRecent->first] = - mostRecent->second; - continue; - } - - secondMostRecent = elevationScan; - } - else - { - secondMostRecent = possibleSecondMostRecent->second; - } - - // Make the new scan - auto newScan = std::make_shared(); - - // Copy over the new radials - for (const auto& radial : *(mostRecent->second)) - { - (*newScan)[radial.first] = radial.second; - } - - /* Correctly order the old radials. The radials need to be in - * order for the rendering to work, and the index needs to start - * at 0 and increase by one from there. Since the new radial - * should have index 0, the old radial needs to be reshaped to - * match the new radials indexing. - */ - - const double lowestAzm = - mostRecent->second->cbegin()->second->azimuth_angle().value(); - const double heighestAzm = mostRecent->second->crbegin() - ->second->azimuth_angle() - .value(); - std::uint16_t index = mostRecent->second->crbegin()->first + 1; - - // Sort by the azimuth. Makes the rest of this way easier - auto secondMostRecentAzmMap = - std::map>(); - for (const auto& radial : *secondMostRecent) - { - secondMostRecentAzmMap[radial.second->azimuth_angle() - .value()] = radial.second; - } - - if (lowestAzm <= heighestAzm) // New scan does not contain 0/360 - { - // Get the radials following the new radials - for (const auto& radial : secondMostRecentAzmMap) - { - if (radial.first > heighestAzm) - { - (*newScan)[index] = radial.second; - ++index; - } - } - // Get the radials before the new radials - for (const auto& radial : secondMostRecentAzmMap) - { - if (radial.first < lowestAzm) - { - (*newScan)[index] = radial.second; - ++index; - } - else - { - break; - } - } - } - else // New scan includes 0/360 - { - // The radials will already be in the right order - for (const auto& radial : secondMostRecentAzmMap) - { - if (radial.first > heighestAzm && radial.first < lowestAzm) - { - (*newScan)[index] = radial.second; - ++index; - } - } - } - - p->index_[type.first][elevation.first][mostRecent->first] = - newScan; - } - else - { - p->index_[type.first][elevation.first][mostRecent->first] = - mostRecent->second; - } - } - } - } - - // Go though last, adding other elevations - if (last != nullptr) - { - for (const auto& type : last->p->index_) - { - // Find the highest elevation this type has for the current scan - // Start below any reasonable elevation - // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) - float highestCurrentElevation = -90; - const auto& elevationScans = p->index_.find(type.first); - if (elevationScans != p->index_.cend()) - { - const auto& highestElevation = elevationScans->second.crbegin(); - if (highestElevation != elevationScans->second.crend()) - { - // Add a slight offset to ensure good floating point compare. - // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) - highestCurrentElevation = highestElevation->first + 0.01f; - } - } - - for (const auto& elevation : type.second) - { - // Only add elevations above the current scan's elevation - if (elevation.first > highestCurrentElevation) - { - const auto& mostRecent = elevation.second.crbegin(); - if (mostRecent == elevation.second.crend()) - { - continue; - } - p->index_[type.first][elevation.first][mostRecent->first] = - mostRecent->second; - } + // TODO: Handle multiple elevation scans + index_[dataBlockType][elevationAngle] = elevationCut.second; } } } diff --git a/wxdata/source/scwx/wsr88d/rda/digital_radar_data.cpp b/wxdata/source/scwx/wsr88d/rda/digital_radar_data.cpp index 8f2643af..ebadf4f5 100644 --- a/wxdata/source/scwx/wsr88d/rda/digital_radar_data.cpp +++ b/wxdata/source/scwx/wsr88d/rda/digital_radar_data.cpp @@ -154,18 +154,7 @@ std::uint16_t DigitalRadarData::elevation_angle_raw() const units::degrees DigitalRadarData::elevation_angle() const { - // NOLINTNEXTLINE This conversion is accurate - float elevationAngleConverted = p->elevationAngle_ * kAngleDataScale; - // Any elevation above 90 degrees should be interpreted as a - // negative angle - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) - if (elevationAngleConverted > 90) - { - elevationAngleConverted -= 360; - } - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - - return units::degrees {elevationAngleConverted}; + return units::degrees {p->elevationAngle_ * kAngleDataScale}; } std::uint16_t DigitalRadarData::elevation_number() const diff --git a/wxdata/source/scwx/wsr88d/rda/digital_radar_data_generic.cpp b/wxdata/source/scwx/wsr88d/rda/digital_radar_data_generic.cpp index 4004fd07..4870c1c3 100644 --- a/wxdata/source/scwx/wsr88d/rda/digital_radar_data_generic.cpp +++ b/wxdata/source/scwx/wsr88d/rda/digital_radar_data_generic.cpp @@ -1,7 +1,11 @@ #include #include -namespace scwx::wsr88d::rda +namespace scwx +{ +namespace wsr88d +{ +namespace rda { static const std::string logPrefix_ = @@ -23,9 +27,9 @@ static const std::unordered_map strToDataBlock_ { class DigitalRadarDataGeneric::DataBlock::Impl { public: - explicit Impl(std::string dataBlockType, std::string dataName) : - dataBlockType_ {std::move(dataBlockType)}, - dataName_ {std::move(dataName)} + explicit Impl(const std::string& dataBlockType, + const std::string& dataName) : + dataBlockType_ {dataBlockType}, dataName_ {dataName} { } @@ -47,13 +51,7 @@ DigitalRadarDataGeneric::DataBlock::operator=(DataBlock&&) noexcept = default; class DigitalRadarDataGeneric::MomentDataBlock::Impl { public: - explicit Impl() = default; - ~Impl() = default; - - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; + explicit Impl() {} std::uint16_t numberOfDataMomentGates_ {0}; std::int16_t dataMomentRange_ {0}; @@ -91,9 +89,7 @@ DigitalRadarDataGeneric::MomentDataBlock::number_of_data_moment_gates() const units::kilometers DigitalRadarDataGeneric::MomentDataBlock::data_moment_range() const { - static constexpr float kScale_ = 0.001f; - return units::kilometers {static_cast(p->dataMomentRange_) * - kScale_}; + return units::kilometers {p->dataMomentRange_ * 0.001f}; } std::int16_t @@ -106,9 +102,7 @@ units::kilometers DigitalRadarDataGeneric::MomentDataBlock::data_moment_range_sample_interval() const { - static constexpr float kScale_ = 0.001f; - return units::kilometers { - static_cast(p->dataMomentRangeSampleInterval_) * kScale_}; + return units::kilometers {p->dataMomentRangeSampleInterval_ * 0.001f}; } std::uint16_t DigitalRadarDataGeneric::MomentDataBlock:: @@ -119,8 +113,7 @@ std::uint16_t DigitalRadarDataGeneric::MomentDataBlock:: float DigitalRadarDataGeneric::MomentDataBlock::snr_threshold() const { - static constexpr float kScale_ = 0.1f; - return static_cast(p->snrThreshold_) * kScale_; + return p->snrThreshold_ * 0.1f; } std::int16_t DigitalRadarDataGeneric::MomentDataBlock::snr_threshold_raw() const @@ -145,14 +138,14 @@ float DigitalRadarDataGeneric::MomentDataBlock::offset() const const void* DigitalRadarDataGeneric::MomentDataBlock::data_moments() const { - const void* dataMoments = nullptr; + const void* dataMoments; switch (p->dataWordSize_) { - case 8: // NOLINT(cppcoreguidelines-avoid-magic-numbers) + case 8: dataMoments = p->momentGates8_.data(); break; - case 16: // NOLINT(cppcoreguidelines-avoid-magic-numbers) + case 16: dataMoments = p->momentGates16_.data(); break; default: @@ -196,15 +189,13 @@ bool DigitalRadarDataGeneric::MomentDataBlock::Parse(std::istream& is) is.read(reinterpret_cast(&p->scale_), 4); // 20-23 is.read(reinterpret_cast(&p->offset_), 4); // 24-27 - p->numberOfDataMomentGates_ = ntohs(p->numberOfDataMomentGates_); - p->dataMomentRange_ = static_cast(ntohs(p->dataMomentRange_)); + p->numberOfDataMomentGates_ = ntohs(p->numberOfDataMomentGates_); + p->dataMomentRange_ = ntohs(p->dataMomentRange_); p->dataMomentRangeSampleInterval_ = ntohs(p->dataMomentRangeSampleInterval_); p->tover_ = ntohs(p->tover_); - p->snrThreshold_ = static_cast(ntohs(p->snrThreshold_)); - p->scale_ = awips::Message::SwapFloat(p->scale_); - p->offset_ = awips::Message::SwapFloat(p->offset_); - - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) + p->snrThreshold_ = ntohs(p->snrThreshold_); + p->scale_ = awips::Message::SwapFloat(p->scale_); + p->offset_ = awips::Message::SwapFloat(p->offset_); if (p->numberOfDataMomentGates_ <= 1840) { @@ -218,7 +209,7 @@ bool DigitalRadarDataGeneric::MomentDataBlock::Parse(std::istream& is) { p->momentGates16_.resize(p->numberOfDataMomentGates_); is.read(reinterpret_cast(p->momentGates16_.data()), - static_cast(p->numberOfDataMomentGates_) * 2); + p->numberOfDataMomentGates_ * 2); awips::Message::SwapVector(p->momentGates16_); } else @@ -234,21 +225,13 @@ bool DigitalRadarDataGeneric::MomentDataBlock::Parse(std::istream& is) dataBlockValid = false; } - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - return dataBlockValid; } class DigitalRadarDataGeneric::VolumeDataBlock::Impl { public: - explicit Impl() = default; - ~Impl() = default; - - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; + explicit Impl() {} std::uint16_t lrtup_ {0}; std::uint8_t versionNumberMajor_ {0}; @@ -264,7 +247,6 @@ public: float initialSystemDifferentialPhase_ {0.0f}; std::uint16_t volumeCoveragePatternNumber_ {0}; std::uint16_t processingStatus_ {0}; - std::uint16_t zdrBiasEstimateWeightedMean_ {0}; }; DigitalRadarDataGeneric::VolumeDataBlock::VolumeDataBlock( @@ -338,7 +320,7 @@ bool DigitalRadarDataGeneric::VolumeDataBlock::Parse(std::istream& is) p->lrtup_ = ntohs(p->lrtup_); p->latitude_ = awips::Message::SwapFloat(p->latitude_); p->longitude_ = awips::Message::SwapFloat(p->longitude_); - p->siteHeight_ = static_cast(ntohs(p->siteHeight_)); + p->siteHeight_ = ntohs(p->siteHeight_); p->feedhornHeight_ = ntohs(p->feedhornHeight_); p->calibrationConstant_ = awips::Message::SwapFloat(p->calibrationConstant_); p->horizontaShvTxPower_ = awips::Message::SwapFloat(p->horizontaShvTxPower_); @@ -350,35 +332,13 @@ bool DigitalRadarDataGeneric::VolumeDataBlock::Parse(std::istream& is) p->volumeCoveragePatternNumber_ = ntohs(p->volumeCoveragePatternNumber_); p->processingStatus_ = ntohs(p->processingStatus_); - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) - - if (p->lrtup_ >= 46) - { - is.read(reinterpret_cast(&p->zdrBiasEstimateWeightedMean_), - 2); // 44-45 - p->zdrBiasEstimateWeightedMean_ = ntohs(p->zdrBiasEstimateWeightedMean_); - } - - if (p->lrtup_ >= 52) - { - is.seekg(6, std::ios_base::cur); // 46-51 - } - - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - return dataBlockValid; } class DigitalRadarDataGeneric::ElevationDataBlock::Impl { public: - explicit Impl() = default; - ~Impl() = default; - - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; + explicit Impl() {} std::uint16_t lrtup_ {0}; std::int16_t atmos_ {0}; @@ -424,7 +384,7 @@ bool DigitalRadarDataGeneric::ElevationDataBlock::Parse(std::istream& is) is.read(reinterpret_cast(&p->calibrationConstant_), 4); // 8-11 p->lrtup_ = ntohs(p->lrtup_); - p->atmos_ = static_cast(ntohs(p->atmos_)); + p->atmos_ = ntohs(p->atmos_); p->calibrationConstant_ = awips::Message::SwapFloat(p->calibrationConstant_); return dataBlockValid; @@ -433,13 +393,7 @@ bool DigitalRadarDataGeneric::ElevationDataBlock::Parse(std::istream& is) class DigitalRadarDataGeneric::RadialDataBlock::Impl { public: - explicit Impl() = default; - ~Impl() = default; - - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; + explicit Impl() {} std::uint16_t lrtup_ {0}; std::uint16_t unambigiousRange_ {0}; @@ -466,8 +420,7 @@ DigitalRadarDataGeneric::RadialDataBlock::operator=( float DigitalRadarDataGeneric::RadialDataBlock::unambiguous_range() const { - static constexpr float kScale_ = 0.1f; - return static_cast(p->unambigiousRange_) * kScale_; + return p->unambigiousRange_ / 10.0f; } std::shared_ptr @@ -520,31 +473,24 @@ bool DigitalRadarDataGeneric::RadialDataBlock::Parse(std::istream& is) class DigitalRadarDataGeneric::Impl { public: - explicit Impl() = default; - ~Impl() = default; + explicit Impl() {}; + ~Impl() = default; - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; - - std::string radarIdentifier_ {}; - std::uint32_t collectionTime_ {0}; - std::uint16_t modifiedJulianDate_ {0}; - std::uint16_t azimuthNumber_ {0}; - float azimuthAngle_ {0.0f}; - std::uint8_t compressionIndicator_ {0}; - std::uint16_t radialLength_ {0}; - std::uint8_t azimuthResolutionSpacing_ {0}; - std::uint8_t radialStatus_ {0}; - std::uint8_t elevationNumber_ {0}; - std::uint8_t cutSectorNumber_ {0}; - float elevationAngle_ {0.0f}; - std::uint8_t radialSpotBlankingStatus_ {0}; - std::uint8_t azimuthIndexingMode_ {0}; - std::uint16_t dataBlockCount_ {0}; - - // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) + std::string radarIdentifier_ {}; + std::uint32_t collectionTime_ {0}; + std::uint16_t modifiedJulianDate_ {0}; + std::uint16_t azimuthNumber_ {0}; + float azimuthAngle_ {0.0f}; + std::uint8_t compressionIndicator_ {0}; + std::uint16_t radialLength_ {0}; + std::uint8_t azimuthResolutionSpacing_ {0}; + std::uint8_t radialStatus_ {0}; + std::uint8_t elevationNumber_ {0}; + std::uint8_t cutSectorNumber_ {0}; + float elevationAngle_ {0.0f}; + std::uint8_t radialSpotBlankingStatus_ {0}; + std::uint8_t azimuthIndexingMode_ {0}; + std::uint16_t dataBlockCount_ {0}; std::array dataBlockPointer_ {0}; std::shared_ptr volumeDataBlock_ {nullptr}; @@ -720,8 +666,6 @@ bool DigitalRadarDataGeneric::Parse(std::istream& is) p->elevationAngle_ = SwapFloat(p->elevationAngle_); p->dataBlockCount_ = ntohs(p->dataBlockCount_); - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) - if (p->azimuthNumber_ < 1 || p->azimuthNumber_ > 720) { logger_->warn("Invalid azimuth number: {}", p->azimuthNumber_); @@ -743,22 +687,18 @@ bool DigitalRadarDataGeneric::Parse(std::istream& is) messageValid = false; } - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - if (!messageValid) { p->dataBlockCount_ = 0; } is.read(reinterpret_cast(&p->dataBlockPointer_), - static_cast(p->dataBlockCount_) * 4); + p->dataBlockCount_ * 4); SwapArray(p->dataBlockPointer_, p->dataBlockCount_); for (uint16_t b = 0; b < p->dataBlockCount_; ++b) { - // Index already has bounds check - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-constant-array-index) is.seekg(isBegin + std::streamoff(p->dataBlockPointer_[b]), std::ios_base::beg); @@ -781,15 +721,15 @@ bool DigitalRadarDataGeneric::Parse(std::istream& is) { case DataBlockType::Volume: p->volumeDataBlock_ = - VolumeDataBlock::Create(dataBlockType, dataName, is); + std::move(VolumeDataBlock::Create(dataBlockType, dataName, is)); break; case DataBlockType::Elevation: p->elevationDataBlock_ = - ElevationDataBlock::Create(dataBlockType, dataName, is); + std::move(ElevationDataBlock::Create(dataBlockType, dataName, is)); break; case DataBlockType::Radial: p->radialDataBlock_ = - RadialDataBlock::Create(dataBlockType, dataName, is); + std::move(RadialDataBlock::Create(dataBlockType, dataName, is)); break; case DataBlockType::MomentRef: case DataBlockType::MomentVel: @@ -799,7 +739,7 @@ bool DigitalRadarDataGeneric::Parse(std::istream& is) case DataBlockType::MomentRho: case DataBlockType::MomentCfp: p->momentDataBlock_[dataBlock] = - MomentDataBlock::Create(dataBlockType, dataName, is); + std::move(MomentDataBlock::Create(dataBlockType, dataName, is)); break; default: logger_->warn("Unknown data name: {}", dataName); @@ -831,4 +771,6 @@ DigitalRadarDataGeneric::Create(Level2MessageHeader&& header, std::istream& is) return message; } -} // namespace scwx::wsr88d::rda +} // namespace rda +} // namespace wsr88d +} // namespace scwx diff --git a/wxdata/source/scwx/wsr88d/rda/level2_message_factory.cpp b/wxdata/source/scwx/wsr88d/rda/level2_message_factory.cpp index 7fe5b77e..2a478a2f 100644 --- a/wxdata/source/scwx/wsr88d/rda/level2_message_factory.cpp +++ b/wxdata/source/scwx/wsr88d/rda/level2_message_factory.cpp @@ -8,23 +8,26 @@ #include #include #include -#include #include #include #include #include -namespace scwx::wsr88d::rda +namespace scwx +{ +namespace wsr88d +{ +namespace rda { static const std::string logPrefix_ = "scwx::wsr88d::rda::level2_message_factory"; static const auto logger_ = util::Logger::Create(logPrefix_); -using CreateLevel2MessageFunction = - std::function(Level2MessageHeader&&, - std::istream&)>; +typedef std::function(Level2MessageHeader&&, + std::istream&)> + CreateLevel2MessageFunction; static const std::unordered_map create_ {{1, DigitalRadarData::Create}, @@ -34,18 +37,20 @@ static const std::unordered_map {13, ClutterFilterBypassMap::Create}, {15, ClutterFilterMap::Create}, {18, RdaAdaptationData::Create}, - {31, DigitalRadarDataGeneric::Create}, - {32, RdaPrfData::Create}}; + {31, DigitalRadarDataGeneric::Create}}; struct Level2MessageFactory::Context { Context() : - messageBuffer_ {messageData_}, messageBufferStream_ {&messageBuffer_} + messageData_ {}, + bufferedSize_ {}, + messageBuffer_ {messageData_}, + messageBufferStream_ {&messageBuffer_} { } - std::vector messageData_ {}; - std::size_t bufferedSize_ {}; + std::vector messageData_; + size_t bufferedSize_; util::vectorbuf messageBuffer_; std::istream messageBufferStream_; bool bufferingData_ {false}; @@ -71,16 +76,13 @@ Level2MessageInfo Level2MessageFactory::Create(std::istream& is, if (info.headerValid) { - if (header.message_size() == std::numeric_limits::max()) + if (header.message_size() == 65535) { - // A message size of 65535 indicates a message with a single segment. - // The size is specified in the bytes normally reserved for the segment - // number and total number of segments. segment = 1; totalSegments = 1; dataSize = (static_cast(header.number_of_message_segments()) - << 16) + // NOLINT(cppcoreguidelines-avoid-magic-numbers) + << 16) + header.message_segment_number(); } else @@ -141,16 +143,14 @@ Level2MessageInfo Level2MessageFactory::Create(std::istream& is, logger_->debug("Bad size estimate, increasing size"); // Estimate remaining size - static const std::uint16_t kMinRemainingSegments_ = 100u; - const std::uint16_t remainingSegments = std::max( - totalSegments - segment + 1, kMinRemainingSegments_); - const std::size_t remainingSize = remainingSegments * dataSize; + uint16_t remainingSegments = + std::max(totalSegments - segment + 1, 100u); + size_t remainingSize = remainingSegments * dataSize; ctx->messageData_.resize(ctx->bufferedSize_ + remainingSize); } - is.read(&ctx->messageData_[ctx->bufferedSize_], - static_cast(dataSize)); + is.read(ctx->messageData_.data() + ctx->bufferedSize_, dataSize); ctx->bufferedSize_ += dataSize; if (is.eof()) @@ -164,7 +164,7 @@ Level2MessageInfo Level2MessageFactory::Create(std::istream& is, else if (segment == totalSegments) { ctx->messageBuffer_.update_read_pointers(ctx->bufferedSize_); - header.set_message_size(static_cast( + header.set_message_size(static_cast( ctx->bufferedSize_ / 2 + Level2MessageHeader::SIZE)); messageStream = &ctx->messageBufferStream_; @@ -186,7 +186,7 @@ Level2MessageInfo Level2MessageFactory::Create(std::istream& is, else if (info.headerValid) { // Seek to the end of the current message - is.seekg(static_cast(dataSize), std::ios_base::cur); + is.seekg(dataSize, std::ios_base::cur); } if (info.message == nullptr) @@ -197,4 +197,6 @@ Level2MessageInfo Level2MessageFactory::Create(std::istream& is, return info; } -} // namespace scwx::wsr88d::rda +} // namespace rda +} // namespace wsr88d +} // namespace scwx diff --git a/wxdata/source/scwx/wsr88d/rda/performance_maintenance_data.cpp b/wxdata/source/scwx/wsr88d/rda/performance_maintenance_data.cpp index 647221e6..662ab506 100644 --- a/wxdata/source/scwx/wsr88d/rda/performance_maintenance_data.cpp +++ b/wxdata/source/scwx/wsr88d/rda/performance_maintenance_data.cpp @@ -3,447 +3,700 @@ #include -namespace scwx::wsr88d::rda +namespace scwx +{ +namespace wsr88d +{ +namespace rda { static const std::string logPrefix_ = "scwx::wsr88d::rda::performance_maintenance_data"; static const auto logger_ = util::Logger::Create(logPrefix_); -class PerformanceMaintenanceData::Impl +class PerformanceMaintenanceDataImpl { public: - explicit Impl() = default; - ~Impl() = default; - - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; + explicit PerformanceMaintenanceDataImpl() : + loopBackSetStatus_ {0}, + t1OutputFrames_ {0}, + t1InputFrames_ {0}, + routerMemoryUsed_ {0}, + routerMemoryFree_ {0}, + routerMemoryUtilization_ {0}, + routeToRpg_ {0}, + csuLossOfSignal_ {0}, + csuLossOfFrames_ {0}, + csuYellowAlarms_ {0}, + csuBlueAlarms_ {0}, + csu24HrErroredSeconds_ {0}, + csu24HrSeverelyErroredSeconds_ {0}, + csu24HrSeverelyErroredFramingSeconds_ {0}, + csu24HrUnavailableSeconds_ {0}, + csu24HrControlledSlipSeconds_ {0}, + csu24HrPathCodingViolations_ {0}, + csu24HrLineErroredSeconds_ {0}, + csu24HrBurstyErroredSeconds_ {0}, + csu24HrDegradedMinutes_ {0}, + lanSwitchCpuUtilization_ {0}, + lanSwitchMemoryUtilization_ {0}, + ifdrChasisTemperature_ {0}, + ifdrFpgaTemperature_ {0}, + gpsSatellites_ {0}, + ipcStatus_ {0}, + commandedChannelControl_ {0}, + polarization_ {0}, + ameInternalTemperature_ {0.0f}, + ameReceiverModuleTemperature_ {0.0f}, + ameBiteCalModuleTemperature_ {0.0f}, + amePeltierPulseWidthModulation_ {0}, + amePeltierStatus_ {0}, + ameADConverterStatus_ {0}, + ameState_ {0}, + ame3_3VPsVoltage_ {0.0f}, + ame5VPsVoltage_ {0.0f}, + ame6_5VPsVoltage_ {0.0f}, + ame15VPsVoltage_ {0.0f}, + ame48VPsVoltage_ {0.0f}, + ameStaloPower_ {0.0f}, + peltierCurrent_ {0.0f}, + adcCalibrationReferenceVoltage_ {0.0f}, + ameMode_ {0}, + amePeltierMode_ {0}, + amePeltierInsideFanCurrent_ {0.0f}, + amePeltierOutsideFanCurrent_ {0.0f}, + horizontalTrLimiterVoltage_ {0.0f}, + verticalTrLimiterVoltage_ {0.0f}, + adcCalibrationOffsetVoltage_ {0.0f}, + adcCalibrationGainCorrection_ {0.0f}, + rcpStatus_ {0}, + rcpString_ {}, + spipPowerButtons_ {0}, + masterPowerAdministratorLoad_ {0.0f}, + expansionPowerAdministratorLoad_ {0.0f}, + _5VdcPs_ {0}, + _15VdcPs_ {0}, + _28VdcPs_ {0}, + neg15VdcPs_ {0}, + _45VdcPs_ {0}, + filamentPsVoltage_ {0}, + vacuumPumpPsVoltage_ {0}, + focusCoilPsVoltage_ {0}, + filamentPs_ {0}, + klystronWarmup_ {0}, + transmitterAvailable_ {0}, + wgSwitchPosition_ {0}, + wgPfnTransferInterlock_ {0}, + maintenanceMode_ {0}, + maintenanceRequired_ {0}, + pfnSwitchPosition_ {0}, + modulatorOverload_ {0}, + modulatorInvCurrent_ {0}, + modulatorSwitchFail_ {0}, + mainPowerVoltage_ {0}, + chargingSystemFail_ {0}, + inverseDiodeCurrent_ {0}, + triggerAmplifier_ {0}, + circulatorTemperature_ {0}, + spectrumFilterPressure_ {0}, + wgArcVswr_ {0}, + cabinetInterlock_ {0}, + cabinetAirTemperature_ {0}, + cabinetAirflow_ {0}, + klystronCurrent_ {0}, + klystronFilamentCurrent_ {0}, + klystronVacionCurrent_ {0}, + klystronAirTemperature_ {0}, + klystronAirflow_ {0}, + modulatorSwitchMaintenance_ {0}, + postChargeRegulatorMaintenance_ {0}, + wgPressureHumidity_ {0}, + transmitterOvervoltage_ {0}, + transmitterOvercurrent_ {0}, + focusCoilCurrent_ {0}, + focusCoilAirflow_ {0}, + oilTemperature_ {0}, + prfLimit_ {0}, + transmitterOilLevel_ {0}, + transmitterBatteryCharging_ {0}, + highVoltageStatus_ {0}, + transmitterRecyclingSummary_ {0}, + transmitterInoperable_ {0}, + transmitterAirFilter_ {0}, + zeroTestBit_ {0}, + oneTestBit_ {0}, + xmtrSpipInterface_ {0}, + transmitterSummaryStatus_ {0}, + transmitterRfPower_ {0.0f}, + horizontalXmtrPeakPower_ {0.0f}, + xmtrPeakPower_ {0.0f}, + verticalXmtrPeakPower_ {0.0f}, + xmtrRfAvgPower_ {0.0f}, + xmtrRecycleCount_ {0}, + receiverBias_ {0.0f}, + transmitImbalance_ {0.0f}, + xmtrPowerMeterZero_ {0.0f}, + acUnit1CompressorShutOff_ {0}, + acUnit2CompressorShutOff_ {0}, + generatorMaintenanceRequired_ {0}, + generatorBatteryVoltage_ {0}, + generatorEngine_ {0}, + generatorVoltFrequency_ {0}, + powerSource_ {0}, + transitionalPowerSource_ {0}, + generatorAutoRunOffSwitch_ {0}, + aircraftHazardLighting_ {0}, + equipmentShelterFireDetectionSystem_ {0}, + equipmentShelterFireSmoke_ {0}, + generatorShelterFireSmoke_ {0}, + utilityVoltageFrequency_ {0}, + siteSecurityAlarm_ {0}, + securityEquipment_ {0}, + securitySystem_ {0}, + receiverConnectedToAntenna_ {0}, + radomeHatch_ {0}, + acUnit1FilterDirty_ {0}, + acUnit2FilterDirty_ {0}, + equipmentShelterTemperature_ {0.0f}, + outsideAmbientTemperature_ {0.0f}, + transmitterLeavingAirTemp_ {0.0f}, + acUnit1DischargeAirTemp_ {0.0f}, + generatorShelterTemperature_ {0.0f}, + radomeAirTemperature_ {0.0f}, + acUnit2DischargeAirTemp_ {0.0f}, + spip15VPs_ {0.0f}, + spipNeg15VPs_ {0.0f}, + spip28VPsStatus_ {0}, + spip5VPs_ {0.0f}, + convertedGeneratorFuelLevel_ {0}, + elevationPosDeadLimit_ {0}, + _150VOvervoltage_ {0}, + _150VUndervoltage_ {0}, + elevationServoAmpInhibit_ {0}, + elevationServoAmpShortCircuit_ {0}, + elevationServoAmpOvertemp_ {0}, + elevationMotorOvertemp_ {0}, + elevationStowPin_ {0}, + elevationHousing5VPs_ {0}, + elevationNegDeadLimit_ {0}, + elevationPosNormalLimit_ {0}, + elevationNegNormalLimit_ {0}, + elevationEncoderLight_ {0}, + elevationGearboxOil_ {0}, + elevationHandwheel_ {0}, + elevationAmpPs_ {0}, + azimuthServoAmpInhibit_ {0}, + azimuthServoAmpShortCircuit_ {0}, + azimuthServoAmpOvertemp_ {0}, + azimuthMotorOvertemp_ {0}, + azimuthStowPin_ {0}, + azimuthHousing5VPs_ {0}, + azimuthEncoderLight_ {0}, + azimuthGearboxOil_ {0}, + azimuthBullGearOil_ {0}, + azimuthHandwheel_ {0}, + azimuthServoAmpPs_ {0}, + servo_ {0}, + pedestalInterlockSwitch_ {0}, + cohoClock_ {0}, + rfGeneratorFrequencySelectOscillator_ {0}, + rfGeneratorRfStalo_ {0}, + rfGeneratorPhaseShiftedCoho_ {0}, + _9VReceiverPs_ {0}, + _5VReceiverPs_ {0}, + _18VReceiverPs_ {0}, + neg9VReceiverPs_ {0}, + _5VSingleChannelRdaiuPs_ {0}, + horizontalShortPulseNoise_ {0.0f}, + horizontalLongPulseNoise_ {0.0f}, + horizontalNoiseTemperature_ {0.0f}, + verticalShortPulseNoise_ {0.0f}, + verticalLongPulseNoise_ {0.0f}, + verticalNoiseTemperature_ {0.0f}, + horizontalLinearity_ {0.0f}, + horizontalDynamicRange_ {0.0f}, + horizontalDeltaDbz0_ {0.0f}, + verticalDeltaDbz0_ {0.0f}, + kdPeakMeasured_ {0.0f}, + shortPulseHorizontalDbz0_ {0.0f}, + longPulseHorizontalDbz0_ {0.0f}, + velocityProcessed_ {0}, + widthProcessed_ {0}, + velocityRfGen_ {0}, + widthRfGen_ {0}, + horizontalI0_ {0.0f}, + verticalI0_ {0.0f}, + verticalDynamicRange_ {0.0f}, + shortPulseVerticalDbz0_ {0.0f}, + longPulseVerticalDbz0_ {0.0f}, + horizontalPowerSense_ {0.0f}, + verticalPowerSense_ {0.0f}, + zdrBias_ {0.0f}, + clutterSuppressionDelta_ {0.0f}, + clutterSuppressionUnfilteredPower_ {0.0f}, + clutterSuppressionFilteredPower_ {0.0f}, + verticalLinearity_ {0.0f}, + stateFileReadStatus_ {0}, + stateFileWriteStatus_ {0}, + bypassMapFileReadStatus_ {0}, + bypassMapFileWriteStatus_ {0}, + currentAdaptationFileReadStatus_ {0}, + currentAdaptationFileWriteStatus_ {0}, + censorZoneFileReadStatus_ {0}, + censorZoneFileWriteStatus_ {0}, + remoteVcpFileReadStatus_ {0}, + remoteVcpFileWriteStatus_ {0}, + baselineAdaptationFileReadStatus_ {0}, + readStatusOfPrfSets_ {0}, + clutterFilterMapFileReadStatus_ {0}, + clutterFilterMapFileWriteStatus_ {0}, + generatlDiskIoError_ {0}, + rspStatus_ {0}, + motherboardTemperature_ {0}, + cpu1Temperature_ {0}, + cpu2Temperature_ {0}, + cpu1FanSpeed_ {0}, + cpu2FanSpeed_ {0}, + rspFan1Speed_ {0}, + rspFan2Speed_ {0}, + rspFan3Speed_ {0}, + spipCommStatus_ {0}, + hciCommStatus_ {0}, + signalProcessorCommandStatus_ {0}, + ameCommunicationStatus_ {0}, + rmsLinkStatus_ {0}, + rpgLinkStatus_ {0}, + interpanelLinkStatus_ {0}, + performanceCheckTime_ {0}, + version_ {0} + { + } + ~PerformanceMaintenanceDataImpl() = default; // Communications - std::uint16_t loopBackSetStatus_ {0}; - std::uint32_t t1OutputFrames_ {0}; - std::uint32_t t1InputFrames_ {0}; - std::uint32_t routerMemoryUsed_ {0}; - std::uint32_t routerMemoryFree_ {0}; - std::uint16_t routerMemoryUtilization_ {0}; - std::uint16_t routeToRpg_ {0}; - std::uint16_t t1PortStatus_ {0}; - std::uint16_t routerDedicatedEthernetPortStatus_ {0}; - std::uint16_t routerCommercialEthernetPortStatus_ {0}; - std::uint32_t csu24HrErroredSeconds_ {0}; - std::uint32_t csu24HrSeverelyErroredSeconds_ {0}; - std::uint32_t csu24HrSeverelyErroredFramingSeconds_ {0}; - std::uint32_t csu24HrUnavailableSeconds_ {0}; - std::uint32_t csu24HrControlledSlipSeconds_ {0}; - std::uint32_t csu24HrPathCodingViolations_ {0}; - std::uint32_t csu24HrLineErroredSeconds_ {0}; - std::uint32_t csu24HrBurstyErroredSeconds_ {0}; - std::uint32_t csu24HrDegradedMinutes_ {0}; - std::uint32_t lanSwitchCpuUtilization_ {0}; - std::uint16_t lanSwitchMemoryUtilization_ {0}; - std::uint16_t ifdrChasisTemperature_ {0}; - std::uint16_t ifdrFpgaTemperature_ {0}; - std::uint16_t ntpStatus_ {0}; - std::uint16_t ipcStatus_ {0}; - std::uint16_t commandedChannelControl_ {0}; + uint16_t loopBackSetStatus_; + uint32_t t1OutputFrames_; + uint32_t t1InputFrames_; + uint32_t routerMemoryUsed_; + uint32_t routerMemoryFree_; + uint16_t routerMemoryUtilization_; + uint16_t routeToRpg_; + uint32_t csuLossOfSignal_; + uint32_t csuLossOfFrames_; + uint32_t csuYellowAlarms_; + uint32_t csuBlueAlarms_; + uint32_t csu24HrErroredSeconds_; + uint32_t csu24HrSeverelyErroredSeconds_; + uint32_t csu24HrSeverelyErroredFramingSeconds_; + uint32_t csu24HrUnavailableSeconds_; + uint32_t csu24HrControlledSlipSeconds_; + uint32_t csu24HrPathCodingViolations_; + uint32_t csu24HrLineErroredSeconds_; + uint32_t csu24HrBurstyErroredSeconds_; + uint32_t csu24HrDegradedMinutes_; + uint32_t lanSwitchCpuUtilization_; + uint16_t lanSwitchMemoryUtilization_; + uint16_t ifdrChasisTemperature_; + uint16_t ifdrFpgaTemperature_; + int32_t gpsSatellites_; + uint16_t ipcStatus_; + uint16_t commandedChannelControl_; // AME - std::uint16_t polarization_ {0}; - float ameInternalTemperature_ {0.0f}; - float ameReceiverModuleTemperature_ {0.0f}; - float ameBiteCalModuleTemperature_ {0.0f}; - std::uint16_t amePeltierPulseWidthModulation_ {0}; - std::uint16_t amePeltierStatus_ {0}; - std::uint16_t ameADConverterStatus_ {0}; - std::uint16_t ameState_ {0}; - float ame3_3VPsVoltage_ {0.0f}; - float ame5VPsVoltage_ {0.0f}; - float ame6_5VPsVoltage_ {0.0f}; - float ame15VPsVoltage_ {0.0f}; - float ame48VPsVoltage_ {0.0f}; - float ameStaloPower_ {0.0f}; - float peltierCurrent_ {0.0f}; - float adcCalibrationReferenceVoltage_ {0.0f}; - std::uint16_t ameMode_ {0}; - std::uint16_t amePeltierMode_ {0}; - float amePeltierInsideFanCurrent_ {0.0f}; - float amePeltierOutsideFanCurrent_ {0.0f}; - float horizontalTrLimiterVoltage_ {0.0f}; - float verticalTrLimiterVoltage_ {0.0f}; - float adcCalibrationOffsetVoltage_ {0.0f}; - float adcCalibrationGainCorrection_ {0.0f}; + uint16_t polarization_; + float ameInternalTemperature_; + float ameReceiverModuleTemperature_; + float ameBiteCalModuleTemperature_; + uint16_t amePeltierPulseWidthModulation_; + uint16_t amePeltierStatus_; + uint16_t ameADConverterStatus_; + uint16_t ameState_; + float ame3_3VPsVoltage_; + float ame5VPsVoltage_; + float ame6_5VPsVoltage_; + float ame15VPsVoltage_; + float ame48VPsVoltage_; + float ameStaloPower_; + float peltierCurrent_; + float adcCalibrationReferenceVoltage_; + uint16_t ameMode_; + uint16_t amePeltierMode_; + float amePeltierInsideFanCurrent_; + float amePeltierOutsideFanCurrent_; + float horizontalTrLimiterVoltage_; + float verticalTrLimiterVoltage_; + float adcCalibrationOffsetVoltage_; + float adcCalibrationGainCorrection_; // RCP/SPIP Power Button Status - std::uint16_t rcpStatus_ {0}; - std::string rcpString_ {}; - std::uint16_t spipPowerButtons_ {0}; + uint16_t rcpStatus_; + std::string rcpString_; + uint16_t spipPowerButtons_; // Power - float masterPowerAdministratorLoad_ {0.0f}; - float expansionPowerAdministratorLoad_ {0.0f}; + float masterPowerAdministratorLoad_; + float expansionPowerAdministratorLoad_; // Transmitter - std::uint16_t _5VdcPs_ {0}; - std::uint16_t _15VdcPs_ {0}; - std::uint16_t _28VdcPs_ {0}; - std::uint16_t neg15VdcPs_ {0}; - std::uint16_t _45VdcPs_ {0}; - std::uint16_t filamentPsVoltage_ {0}; - std::uint16_t vacuumPumpPsVoltage_ {0}; - std::uint16_t focusCoilPsVoltage_ {0}; - std::uint16_t filamentPs_ {0}; - std::uint16_t klystronWarmup_ {0}; - std::uint16_t transmitterAvailable_ {0}; - std::uint16_t wgSwitchPosition_ {0}; - std::uint16_t wgPfnTransferInterlock_ {0}; - std::uint16_t maintenanceMode_ {0}; - std::uint16_t maintenanceRequired_ {0}; - std::uint16_t pfnSwitchPosition_ {0}; - std::uint16_t modulatorOverload_ {0}; - std::uint16_t modulatorInvCurrent_ {0}; - std::uint16_t modulatorSwitchFail_ {0}; - std::uint16_t mainPowerVoltage_ {0}; - std::uint16_t chargingSystemFail_ {0}; - std::uint16_t inverseDiodeCurrent_ {0}; - std::uint16_t triggerAmplifier_ {0}; - std::uint16_t circulatorTemperature_ {0}; - std::uint16_t spectrumFilterPressure_ {0}; - std::uint16_t wgArcVswr_ {0}; - std::uint16_t cabinetInterlock_ {0}; - std::uint16_t cabinetAirTemperature_ {0}; - std::uint16_t cabinetAirflow_ {0}; - std::uint16_t klystronCurrent_ {0}; - std::uint16_t klystronFilamentCurrent_ {0}; - std::uint16_t klystronVacionCurrent_ {0}; - std::uint16_t klystronAirTemperature_ {0}; - std::uint16_t klystronAirflow_ {0}; - std::uint16_t modulatorSwitchMaintenance_ {0}; - std::uint16_t postChargeRegulatorMaintenance_ {0}; - std::uint16_t wgPressureHumidity_ {0}; - std::uint16_t transmitterOvervoltage_ {0}; - std::uint16_t transmitterOvercurrent_ {0}; - std::uint16_t focusCoilCurrent_ {0}; - std::uint16_t focusCoilAirflow_ {0}; - std::uint16_t oilTemperature_ {0}; - std::uint16_t prfLimit_ {0}; - std::uint16_t transmitterOilLevel_ {0}; - std::uint16_t transmitterBatteryCharging_ {0}; - std::uint16_t highVoltageStatus_ {0}; - std::uint16_t transmitterRecyclingSummary_ {0}; - std::uint16_t transmitterInoperable_ {0}; - std::uint16_t transmitterAirFilter_ {0}; - - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) - std::array zeroTestBit_ {0}; - std::array oneTestBit_ {0}; - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - - std::uint16_t xmtrSpipInterface_ {0}; - std::uint16_t transmitterSummaryStatus_ {0}; - float transmitterRfPower_ {0.0f}; - float horizontalXmtrPeakPower_ {0.0f}; - float xmtrPeakPower_ {0.0f}; - float verticalXmtrPeakPower_ {0.0f}; - float xmtrRfAvgPower_ {0.0f}; - std::uint32_t xmtrRecycleCount_ {0}; - float receiverBias_ {0.0f}; - float transmitImbalance_ {0.0f}; - float xmtrPowerMeterZero_ {0.0f}; + uint16_t _5VdcPs_; + uint16_t _15VdcPs_; + uint16_t _28VdcPs_; + uint16_t neg15VdcPs_; + uint16_t _45VdcPs_; + uint16_t filamentPsVoltage_; + uint16_t vacuumPumpPsVoltage_; + uint16_t focusCoilPsVoltage_; + uint16_t filamentPs_; + uint16_t klystronWarmup_; + uint16_t transmitterAvailable_; + uint16_t wgSwitchPosition_; + uint16_t wgPfnTransferInterlock_; + uint16_t maintenanceMode_; + uint16_t maintenanceRequired_; + uint16_t pfnSwitchPosition_; + uint16_t modulatorOverload_; + uint16_t modulatorInvCurrent_; + uint16_t modulatorSwitchFail_; + uint16_t mainPowerVoltage_; + uint16_t chargingSystemFail_; + uint16_t inverseDiodeCurrent_; + uint16_t triggerAmplifier_; + uint16_t circulatorTemperature_; + uint16_t spectrumFilterPressure_; + uint16_t wgArcVswr_; + uint16_t cabinetInterlock_; + uint16_t cabinetAirTemperature_; + uint16_t cabinetAirflow_; + uint16_t klystronCurrent_; + uint16_t klystronFilamentCurrent_; + uint16_t klystronVacionCurrent_; + uint16_t klystronAirTemperature_; + uint16_t klystronAirflow_; + uint16_t modulatorSwitchMaintenance_; + uint16_t postChargeRegulatorMaintenance_; + uint16_t wgPressureHumidity_; + uint16_t transmitterOvervoltage_; + uint16_t transmitterOvercurrent_; + uint16_t focusCoilCurrent_; + uint16_t focusCoilAirflow_; + uint16_t oilTemperature_; + uint16_t prfLimit_; + uint16_t transmitterOilLevel_; + uint16_t transmitterBatteryCharging_; + uint16_t highVoltageStatus_; + uint16_t transmitterRecyclingSummary_; + uint16_t transmitterInoperable_; + uint16_t transmitterAirFilter_; + std::array zeroTestBit_; + std::array oneTestBit_; + uint16_t xmtrSpipInterface_; + uint16_t transmitterSummaryStatus_; + float transmitterRfPower_; + float horizontalXmtrPeakPower_; + float xmtrPeakPower_; + float verticalXmtrPeakPower_; + float xmtrRfAvgPower_; + uint32_t xmtrRecycleCount_; + float receiverBias_; + float transmitImbalance_; + float xmtrPowerMeterZero_; // Tower/Utilities - std::uint16_t acUnit1CompressorShutOff_ {0}; - std::uint16_t acUnit2CompressorShutOff_ {0}; - std::uint16_t generatorMaintenanceRequired_ {0}; - std::uint16_t generatorBatteryVoltage_ {0}; - std::uint16_t generatorEngine_ {0}; - std::uint16_t generatorVoltFrequency_ {0}; - std::uint16_t powerSource_ {0}; - std::uint16_t transitionalPowerSource_ {0}; - std::uint16_t generatorAutoRunOffSwitch_ {0}; - std::uint16_t aircraftHazardLighting_ {0}; + uint16_t acUnit1CompressorShutOff_; + uint16_t acUnit2CompressorShutOff_; + uint16_t generatorMaintenanceRequired_; + uint16_t generatorBatteryVoltage_; + uint16_t generatorEngine_; + uint16_t generatorVoltFrequency_; + uint16_t powerSource_; + uint16_t transitionalPowerSource_; + uint16_t generatorAutoRunOffSwitch_; + uint16_t aircraftHazardLighting_; // Equipment Shelter - std::uint16_t equipmentShelterFireDetectionSystem_ {0}; - std::uint16_t equipmentShelterFireSmoke_ {0}; - std::uint16_t generatorShelterFireSmoke_ {0}; - std::uint16_t utilityVoltageFrequency_ {0}; - std::uint16_t siteSecurityAlarm_ {0}; - std::uint16_t securityEquipment_ {0}; - std::uint16_t securitySystem_ {0}; - std::uint16_t receiverConnectedToAntenna_ {0}; - std::uint16_t radomeHatch_ {0}; - std::uint16_t acUnit1FilterDirty_ {0}; - std::uint16_t acUnit2FilterDirty_ {0}; - float equipmentShelterTemperature_ {0.0f}; - float outsideAmbientTemperature_ {0.0f}; - float transmitterLeavingAirTemp_ {0.0f}; - float acUnit1DischargeAirTemp_ {0.0f}; - float generatorShelterTemperature_ {0.0f}; - float radomeAirTemperature_ {0.0f}; - float acUnit2DischargeAirTemp_ {0.0f}; - float spip15VPs_ {0.0f}; - float spipNeg15VPs_ {0.0f}; - std::uint16_t spip28VPsStatus_ {0}; - float spip5VPs_ {0.0f}; - std::uint16_t convertedGeneratorFuelLevel_ {0}; + uint16_t equipmentShelterFireDetectionSystem_; + uint16_t equipmentShelterFireSmoke_; + uint16_t generatorShelterFireSmoke_; + uint16_t utilityVoltageFrequency_; + uint16_t siteSecurityAlarm_; + uint16_t securityEquipment_; + uint16_t securitySystem_; + uint16_t receiverConnectedToAntenna_; + uint16_t radomeHatch_; + uint16_t acUnit1FilterDirty_; + uint16_t acUnit2FilterDirty_; + float equipmentShelterTemperature_; + float outsideAmbientTemperature_; + float transmitterLeavingAirTemp_; + float acUnit1DischargeAirTemp_; + float generatorShelterTemperature_; + float radomeAirTemperature_; + float acUnit2DischargeAirTemp_; + float spip15VPs_; + float spipNeg15VPs_; + uint16_t spip28VPsStatus_; + float spip5VPs_; + uint16_t convertedGeneratorFuelLevel_; // Antenna/Pedestal - std::uint16_t elevationPosDeadLimit_ {0}; - std::uint16_t _150VOvervoltage_ {0}; - std::uint16_t _150VUndervoltage_ {0}; - std::uint16_t elevationServoAmpInhibit_ {0}; - std::uint16_t elevationServoAmpShortCircuit_ {0}; - std::uint16_t elevationServoAmpOvertemp_ {0}; - std::uint16_t elevationMotorOvertemp_ {0}; - std::uint16_t elevationStowPin_ {0}; - std::uint16_t elevationHousing5VPs_ {0}; - std::uint16_t elevationNegDeadLimit_ {0}; - std::uint16_t elevationPosNormalLimit_ {0}; - std::uint16_t elevationNegNormalLimit_ {0}; - std::uint16_t elevationEncoderLight_ {0}; - std::uint16_t elevationGearboxOil_ {0}; - std::uint16_t elevationHandwheel_ {0}; - std::uint16_t elevationAmpPs_ {0}; - std::uint16_t azimuthServoAmpInhibit_ {0}; - std::uint16_t azimuthServoAmpShortCircuit_ {0}; - std::uint16_t azimuthServoAmpOvertemp_ {0}; - std::uint16_t azimuthMotorOvertemp_ {0}; - std::uint16_t azimuthStowPin_ {0}; - std::uint16_t azimuthHousing5VPs_ {0}; - std::uint16_t azimuthEncoderLight_ {0}; - std::uint16_t azimuthGearboxOil_ {0}; - std::uint16_t azimuthBullGearOil_ {0}; - std::uint16_t azimuthHandwheel_ {0}; - std::uint16_t azimuthServoAmpPs_ {0}; - std::uint16_t servo_ {0}; - std::uint16_t pedestalInterlockSwitch_ {0}; + uint16_t elevationPosDeadLimit_; + uint16_t _150VOvervoltage_; + uint16_t _150VUndervoltage_; + uint16_t elevationServoAmpInhibit_; + uint16_t elevationServoAmpShortCircuit_; + uint16_t elevationServoAmpOvertemp_; + uint16_t elevationMotorOvertemp_; + uint16_t elevationStowPin_; + uint16_t elevationHousing5VPs_; + uint16_t elevationNegDeadLimit_; + uint16_t elevationPosNormalLimit_; + uint16_t elevationNegNormalLimit_; + uint16_t elevationEncoderLight_; + uint16_t elevationGearboxOil_; + uint16_t elevationHandwheel_; + uint16_t elevationAmpPs_; + uint16_t azimuthServoAmpInhibit_; + uint16_t azimuthServoAmpShortCircuit_; + uint16_t azimuthServoAmpOvertemp_; + uint16_t azimuthMotorOvertemp_; + uint16_t azimuthStowPin_; + uint16_t azimuthHousing5VPs_; + uint16_t azimuthEncoderLight_; + uint16_t azimuthGearboxOil_; + uint16_t azimuthBullGearOil_; + uint16_t azimuthHandwheel_; + uint16_t azimuthServoAmpPs_; + uint16_t servo_; + uint16_t pedestalInterlockSwitch_; // RF Generator/Receiver - std::uint16_t cohoClock_ {0}; - std::uint16_t rfGeneratorFrequencySelectOscillator_ {0}; - std::uint16_t rfGeneratorRfStalo_ {0}; - std::uint16_t rfGeneratorPhaseShiftedCoho_ {0}; - std::uint16_t _9VReceiverPs_ {0}; - std::uint16_t _5VReceiverPs_ {0}; - std::uint16_t _18VReceiverPs_ {0}; - std::uint16_t neg9VReceiverPs_ {0}; - std::uint16_t _5VSingleChannelRdaiuPs_ {0}; - float horizontalShortPulseNoise_ {0.0f}; - float horizontalLongPulseNoise_ {0.0f}; - float horizontalNoiseTemperature_ {0.0f}; - float verticalShortPulseNoise_ {0.0f}; - float verticalLongPulseNoise_ {0.0f}; - float verticalNoiseTemperature_ {0.0f}; + uint16_t cohoClock_; + uint16_t rfGeneratorFrequencySelectOscillator_; + uint16_t rfGeneratorRfStalo_; + uint16_t rfGeneratorPhaseShiftedCoho_; + uint16_t _9VReceiverPs_; + uint16_t _5VReceiverPs_; + uint16_t _18VReceiverPs_; + uint16_t neg9VReceiverPs_; + uint16_t _5VSingleChannelRdaiuPs_; + float horizontalShortPulseNoise_; + float horizontalLongPulseNoise_; + float horizontalNoiseTemperature_; + float verticalShortPulseNoise_; + float verticalLongPulseNoise_; + float verticalNoiseTemperature_; // Calibration - float horizontalLinearity_ {0.0f}; - float horizontalDynamicRange_ {0.0f}; - float horizontalDeltaDbz0_ {0.0f}; - float verticalDeltaDbz0_ {0.0f}; - float kdPeakMeasured_ {0.0f}; - float shortPulseHorizontalDbz0_ {0.0f}; - float longPulseHorizontalDbz0_ {0.0f}; - std::uint16_t velocityProcessed_ {0}; - std::uint16_t widthProcessed_ {0}; - std::uint16_t velocityRfGen_ {0}; - std::uint16_t widthRfGen_ {0}; - float horizontalI0_ {0.0f}; - float verticalI0_ {0.0f}; - float verticalDynamicRange_ {0.0f}; - float shortPulseVerticalDbz0_ {0.0f}; - float longPulseVerticalDbz0_ {0.0f}; - float horizontalPowerSense_ {0.0f}; - float verticalPowerSense_ {0.0f}; - float zdrOffset_ {0.0f}; - float clutterSuppressionDelta_ {0.0f}; - float clutterSuppressionUnfilteredPower_ {0.0f}; - float clutterSuppressionFilteredPower_ {0.0f}; - float verticalLinearity_ {0.0f}; + float horizontalLinearity_; + float horizontalDynamicRange_; + float horizontalDeltaDbz0_; + float verticalDeltaDbz0_; + float kdPeakMeasured_; + float shortPulseHorizontalDbz0_; + float longPulseHorizontalDbz0_; + uint16_t velocityProcessed_; + uint16_t widthProcessed_; + uint16_t velocityRfGen_; + uint16_t widthRfGen_; + float horizontalI0_; + float verticalI0_; + float verticalDynamicRange_; + float shortPulseVerticalDbz0_; + float longPulseVerticalDbz0_; + float horizontalPowerSense_; + float verticalPowerSense_; + float zdrBias_; + float clutterSuppressionDelta_; + float clutterSuppressionUnfilteredPower_; + float clutterSuppressionFilteredPower_; + float verticalLinearity_; // File Status - std::uint16_t stateFileReadStatus_ {0}; - std::uint16_t stateFileWriteStatus_ {0}; - std::uint16_t bypassMapFileReadStatus_ {0}; - std::uint16_t bypassMapFileWriteStatus_ {0}; - std::uint16_t currentAdaptationFileReadStatus_ {0}; - std::uint16_t currentAdaptationFileWriteStatus_ {0}; - std::uint16_t censorZoneFileReadStatus_ {0}; - std::uint16_t censorZoneFileWriteStatus_ {0}; - std::uint16_t remoteVcpFileReadStatus_ {0}; - std::uint16_t remoteVcpFileWriteStatus_ {0}; - std::uint16_t baselineAdaptationFileReadStatus_ {0}; - std::uint16_t readStatusOfPrfSets_ {0}; - std::uint16_t clutterFilterMapFileReadStatus_ {0}; - std::uint16_t clutterFilterMapFileWriteStatus_ {0}; - std::uint16_t generalDiskIoError_ {0}; - std::uint8_t rspStatus_ {0}; - std::uint8_t cpu1Temperature_ {0}; - std::uint8_t cpu2Temperature_ {0}; - std::uint16_t rspMotherboardPower_ {0}; + uint16_t stateFileReadStatus_; + uint16_t stateFileWriteStatus_; + uint16_t bypassMapFileReadStatus_; + uint16_t bypassMapFileWriteStatus_; + uint16_t currentAdaptationFileReadStatus_; + uint16_t currentAdaptationFileWriteStatus_; + uint16_t censorZoneFileReadStatus_; + uint16_t censorZoneFileWriteStatus_; + uint16_t remoteVcpFileReadStatus_; + uint16_t remoteVcpFileWriteStatus_; + uint16_t baselineAdaptationFileReadStatus_; + uint16_t readStatusOfPrfSets_; + uint16_t clutterFilterMapFileReadStatus_; + uint16_t clutterFilterMapFileWriteStatus_; + uint16_t generatlDiskIoError_; + uint8_t rspStatus_; + uint8_t motherboardTemperature_; + uint8_t cpu1Temperature_; + uint8_t cpu2Temperature_; + uint16_t cpu1FanSpeed_; + uint16_t cpu2FanSpeed_; + uint16_t rspFan1Speed_; + uint16_t rspFan2Speed_; + uint16_t rspFan3Speed_; // Device Status - std::uint16_t spipCommStatus_ {0}; - std::uint16_t hciCommStatus_ {0}; - std::uint16_t signalProcessorCommandStatus_ {0}; - std::uint16_t ameCommunicationStatus_ {0}; - std::uint16_t rmsLinkStatus_ {0}; - std::uint16_t rpgLinkStatus_ {0}; - std::uint16_t interpanelLinkStatus_ {0}; - std::uint32_t performanceCheckTime_ {0}; - std::uint16_t version_ {0}; + uint16_t spipCommStatus_; + uint16_t hciCommStatus_; + uint16_t signalProcessorCommandStatus_; + uint16_t ameCommunicationStatus_; + uint16_t rmsLinkStatus_; + uint16_t rpgLinkStatus_; + uint16_t interpanelLinkStatus_; + uint32_t performanceCheckTime_; + uint16_t version_; }; PerformanceMaintenanceData::PerformanceMaintenanceData() : - Level2Message(), p(std::make_unique()) + Level2Message(), p(std::make_unique()) { } PerformanceMaintenanceData::~PerformanceMaintenanceData() = default; PerformanceMaintenanceData::PerformanceMaintenanceData( - PerformanceMaintenanceData&&) noexcept = default; + PerformanceMaintenanceData&&) noexcept = default; PerformanceMaintenanceData& PerformanceMaintenanceData::operator=( PerformanceMaintenanceData&&) noexcept = default; -std::uint16_t PerformanceMaintenanceData::loop_back_set_status() const +uint16_t PerformanceMaintenanceData::loop_back_set_status() const { return p->loopBackSetStatus_; } -std::uint32_t PerformanceMaintenanceData::t1_output_frames() const +uint32_t PerformanceMaintenanceData::t1_output_frames() const { return p->t1OutputFrames_; } -std::uint32_t PerformanceMaintenanceData::t1_input_frames() const +uint32_t PerformanceMaintenanceData::t1_input_frames() const { return p->t1InputFrames_; } -std::uint32_t PerformanceMaintenanceData::router_memory_used() const +uint32_t PerformanceMaintenanceData::router_memory_used() const { return p->routerMemoryUsed_; } -std::uint32_t PerformanceMaintenanceData::router_memory_free() const +uint32_t PerformanceMaintenanceData::router_memory_free() const { return p->routerMemoryFree_; } -std::uint16_t PerformanceMaintenanceData::router_memory_utilization() const +uint16_t PerformanceMaintenanceData::router_memory_utilization() const { return p->routerMemoryUtilization_; } -std::uint16_t PerformanceMaintenanceData::route_to_rpg() const +uint16_t PerformanceMaintenanceData::route_to_rpg() const { return p->routeToRpg_; } -std::uint16_t PerformanceMaintenanceData::t1_port_status() const +uint32_t PerformanceMaintenanceData::csu_loss_of_signal() const { - return p->t1PortStatus_; + return p->csuLossOfSignal_; } -std::uint16_t -PerformanceMaintenanceData::router_dedicated_ethernet_port_status() const +uint32_t PerformanceMaintenanceData::csu_loss_of_frames() const { - return p->routerDedicatedEthernetPortStatus_; + return p->csuLossOfFrames_; } -std::uint16_t -PerformanceMaintenanceData::router_commercial_ethernet_port_status() const +uint32_t PerformanceMaintenanceData::csu_yellow_alarms() const { - return p->routerCommercialEthernetPortStatus_; + return p->csuYellowAlarms_; } -std::uint32_t PerformanceMaintenanceData::csu_24hr_errored_seconds() const +uint32_t PerformanceMaintenanceData::csu_blue_alarms() const +{ + return p->csuBlueAlarms_; +} + +uint32_t PerformanceMaintenanceData::csu_24hr_errored_seconds() const { return p->csu24HrErroredSeconds_; } -std::uint32_t -PerformanceMaintenanceData::csu_24hr_severely_errored_seconds() const +uint32_t PerformanceMaintenanceData::csu_24hr_severely_errored_seconds() const { return p->csu24HrSeverelyErroredSeconds_; } -std::uint32_t +uint32_t PerformanceMaintenanceData::csu_24hr_severely_errored_framing_seconds() const { return p->csu24HrSeverelyErroredFramingSeconds_; } -std::uint32_t PerformanceMaintenanceData::csu_24hr_unavailable_seconds() const +uint32_t PerformanceMaintenanceData::csu_24hr_unavailable_seconds() const { return p->csu24HrUnavailableSeconds_; } -std::uint32_t -PerformanceMaintenanceData::csu_24hr_controlled_slip_seconds() const +uint32_t PerformanceMaintenanceData::csu_24hr_controlled_slip_seconds() const { return p->csu24HrControlledSlipSeconds_; } -std::uint32_t -PerformanceMaintenanceData::csu_24hr_path_coding_violations() const +uint32_t PerformanceMaintenanceData::csu_24hr_path_coding_violations() const { return p->csu24HrPathCodingViolations_; } -std::uint32_t PerformanceMaintenanceData::csu_24hr_line_errored_seconds() const +uint32_t PerformanceMaintenanceData::csu_24hr_line_errored_seconds() const { return p->csu24HrLineErroredSeconds_; } -std::uint32_t -PerformanceMaintenanceData::csu_24hr_bursty_errored_seconds() const +uint32_t PerformanceMaintenanceData::csu_24hr_bursty_errored_seconds() const { return p->csu24HrBurstyErroredSeconds_; } -std::uint32_t PerformanceMaintenanceData::csu_24hr_degraded_minutes() const +uint32_t PerformanceMaintenanceData::csu_24hr_degraded_minutes() const { return p->csu24HrDegradedMinutes_; } -std::uint32_t PerformanceMaintenanceData::lan_switch_cpu_utilization() const +uint32_t PerformanceMaintenanceData::lan_switch_cpu_utilization() const { return p->lanSwitchCpuUtilization_; } -std::uint16_t PerformanceMaintenanceData::lan_switch_memory_utilization() const +uint16_t PerformanceMaintenanceData::lan_switch_memory_utilization() const { return p->lanSwitchMemoryUtilization_; } -std::uint16_t PerformanceMaintenanceData::ifdr_chasis_temperature() const +uint16_t PerformanceMaintenanceData::ifdr_chasis_temperature() const { return p->ifdrChasisTemperature_; } -std::uint16_t PerformanceMaintenanceData::ifdr_fpga_temperature() const +uint16_t PerformanceMaintenanceData::ifdr_fpga_temperature() const { return p->ifdrFpgaTemperature_; } -std::uint16_t PerformanceMaintenanceData::ntp_status() const +int32_t PerformanceMaintenanceData::gps_satellites() const { - return p->ntpStatus_; + return p->gpsSatellites_; } -std::uint16_t PerformanceMaintenanceData::ipc_status() const +uint16_t PerformanceMaintenanceData::ipc_status() const { return p->ipcStatus_; } -std::uint16_t PerformanceMaintenanceData::commanded_channel_control() const +uint16_t PerformanceMaintenanceData::commanded_channel_control() const { return p->commandedChannelControl_; } -std::uint16_t PerformanceMaintenanceData::polarization() const +uint16_t PerformanceMaintenanceData::polarization() const { return p->polarization_; } @@ -463,23 +716,22 @@ float PerformanceMaintenanceData::ame_bite_cal_module_temperature() const return p->ameBiteCalModuleTemperature_; } -std::uint16_t -PerformanceMaintenanceData::ame_peltier_pulse_width_modulation() const +uint16_t PerformanceMaintenanceData::ame_peltier_pulse_width_modulation() const { return p->amePeltierPulseWidthModulation_; } -std::uint16_t PerformanceMaintenanceData::ame_peltier_status() const +uint16_t PerformanceMaintenanceData::ame_peltier_status() const { return p->amePeltierStatus_; } -std::uint16_t PerformanceMaintenanceData::ame_a_d_converter_status() const +uint16_t PerformanceMaintenanceData::ame_a_d_converter_status() const { return p->ameADConverterStatus_; } -std::uint16_t PerformanceMaintenanceData::ame_state() const +uint16_t PerformanceMaintenanceData::ame_state() const { return p->ameState_; } @@ -524,12 +776,12 @@ float PerformanceMaintenanceData::adc_calibration_reference_voltage() const return p->adcCalibrationReferenceVoltage_; } -std::uint16_t PerformanceMaintenanceData::ame_mode() const +uint16_t PerformanceMaintenanceData::ame_mode() const { return p->ameMode_; } -std::uint16_t PerformanceMaintenanceData::ame_peltier_mode() const +uint16_t PerformanceMaintenanceData::ame_peltier_mode() const { return p->amePeltierMode_; } @@ -564,7 +816,7 @@ float PerformanceMaintenanceData::adc_calibration_gain_correction() const return p->adcCalibrationGainCorrection_; } -std::uint16_t PerformanceMaintenanceData::rcp_status() const +uint16_t PerformanceMaintenanceData::rcp_status() const { return p->rcpStatus_; } @@ -574,7 +826,7 @@ std::string PerformanceMaintenanceData::rcp_string() const return p->rcpString_; } -std::uint16_t PerformanceMaintenanceData::spip_power_buttons() const +uint16_t PerformanceMaintenanceData::spip_power_buttons() const { return p->spipPowerButtons_; } @@ -589,268 +841,267 @@ float PerformanceMaintenanceData::expansion_power_administrator_load() const return p->expansionPowerAdministratorLoad_; } -std::uint16_t PerformanceMaintenanceData::_5vdc_ps() const +uint16_t PerformanceMaintenanceData::_5vdc_ps() const { return p->_5VdcPs_; } -std::uint16_t PerformanceMaintenanceData::_15vdc_ps() const +uint16_t PerformanceMaintenanceData::_15vdc_ps() const { return p->_15VdcPs_; } -std::uint16_t PerformanceMaintenanceData::_28vdc_ps() const +uint16_t PerformanceMaintenanceData::_28vdc_ps() const { return p->_28VdcPs_; } -std::uint16_t PerformanceMaintenanceData::neg_15vdc_ps() const +uint16_t PerformanceMaintenanceData::neg_15vdc_ps() const { return p->neg15VdcPs_; } -std::uint16_t PerformanceMaintenanceData::_45vdc_ps() const +uint16_t PerformanceMaintenanceData::_45vdc_ps() const { return p->_45VdcPs_; } -std::uint16_t PerformanceMaintenanceData::filament_ps_voltage() const +uint16_t PerformanceMaintenanceData::filament_ps_voltage() const { return p->filamentPsVoltage_; } -std::uint16_t PerformanceMaintenanceData::vacuum_pump_ps_voltage() const +uint16_t PerformanceMaintenanceData::vacuum_pump_ps_voltage() const { return p->vacuumPumpPsVoltage_; } -std::uint16_t PerformanceMaintenanceData::focus_coil_ps_voltage() const +uint16_t PerformanceMaintenanceData::focus_coil_ps_voltage() const { return p->focusCoilPsVoltage_; } -std::uint16_t PerformanceMaintenanceData::filament_ps() const +uint16_t PerformanceMaintenanceData::filament_ps() const { return p->filamentPs_; } -std::uint16_t PerformanceMaintenanceData::klystron_warmup() const +uint16_t PerformanceMaintenanceData::klystron_warmup() const { return p->klystronWarmup_; } -std::uint16_t PerformanceMaintenanceData::transmitter_available() const +uint16_t PerformanceMaintenanceData::transmitter_available() const { return p->transmitterAvailable_; } -std::uint16_t PerformanceMaintenanceData::wg_switch_position() const +uint16_t PerformanceMaintenanceData::wg_switch_position() const { return p->wgSwitchPosition_; } -std::uint16_t PerformanceMaintenanceData::wg_pfn_transfer_interlock() const +uint16_t PerformanceMaintenanceData::wg_pfn_transfer_interlock() const { return p->wgPfnTransferInterlock_; } -std::uint16_t PerformanceMaintenanceData::maintenance_mode() const +uint16_t PerformanceMaintenanceData::maintenance_mode() const { return p->maintenanceMode_; } -std::uint16_t PerformanceMaintenanceData::maintenance_required() const +uint16_t PerformanceMaintenanceData::maintenance_required() const { return p->maintenanceRequired_; } -std::uint16_t PerformanceMaintenanceData::pfn_switch_position() const +uint16_t PerformanceMaintenanceData::pfn_switch_position() const { return p->pfnSwitchPosition_; } -std::uint16_t PerformanceMaintenanceData::modulator_overload() const +uint16_t PerformanceMaintenanceData::modulator_overload() const { return p->modulatorOverload_; } -std::uint16_t PerformanceMaintenanceData::modulator_inv_current() const +uint16_t PerformanceMaintenanceData::modulator_inv_current() const { return p->modulatorInvCurrent_; } -std::uint16_t PerformanceMaintenanceData::modulator_switch_fail() const +uint16_t PerformanceMaintenanceData::modulator_switch_fail() const { return p->modulatorSwitchFail_; } -std::uint16_t PerformanceMaintenanceData::main_power_voltage() const +uint16_t PerformanceMaintenanceData::main_power_voltage() const { return p->mainPowerVoltage_; } -std::uint16_t PerformanceMaintenanceData::charging_system_fail() const +uint16_t PerformanceMaintenanceData::charging_system_fail() const { return p->chargingSystemFail_; } -std::uint16_t PerformanceMaintenanceData::inverse_diode_current() const +uint16_t PerformanceMaintenanceData::inverse_diode_current() const { return p->inverseDiodeCurrent_; } -std::uint16_t PerformanceMaintenanceData::trigger_amplifier() const +uint16_t PerformanceMaintenanceData::trigger_amplifier() const { return p->triggerAmplifier_; } -std::uint16_t PerformanceMaintenanceData::circulator_temperature() const +uint16_t PerformanceMaintenanceData::circulator_temperature() const { return p->circulatorTemperature_; } -std::uint16_t PerformanceMaintenanceData::spectrum_filter_pressure() const +uint16_t PerformanceMaintenanceData::spectrum_filter_pressure() const { return p->spectrumFilterPressure_; } -std::uint16_t PerformanceMaintenanceData::wg_arc_vswr() const +uint16_t PerformanceMaintenanceData::wg_arc_vswr() const { return p->wgArcVswr_; } -std::uint16_t PerformanceMaintenanceData::cabinet_interlock() const +uint16_t PerformanceMaintenanceData::cabinet_interlock() const { return p->cabinetInterlock_; } -std::uint16_t PerformanceMaintenanceData::cabinet_air_temperature() const +uint16_t PerformanceMaintenanceData::cabinet_air_temperature() const { return p->cabinetAirTemperature_; } -std::uint16_t PerformanceMaintenanceData::cabinet_airflow() const +uint16_t PerformanceMaintenanceData::cabinet_airflow() const { return p->cabinetAirflow_; } -std::uint16_t PerformanceMaintenanceData::klystron_current() const +uint16_t PerformanceMaintenanceData::klystron_current() const { return p->klystronCurrent_; } -std::uint16_t PerformanceMaintenanceData::klystron_filament_current() const +uint16_t PerformanceMaintenanceData::klystron_filament_current() const { return p->klystronFilamentCurrent_; } -std::uint16_t PerformanceMaintenanceData::klystron_vacion_current() const +uint16_t PerformanceMaintenanceData::klystron_vacion_current() const { return p->klystronVacionCurrent_; } -std::uint16_t PerformanceMaintenanceData::klystron_air_temperature() const +uint16_t PerformanceMaintenanceData::klystron_air_temperature() const { return p->klystronAirTemperature_; } -std::uint16_t PerformanceMaintenanceData::klystron_airflow() const +uint16_t PerformanceMaintenanceData::klystron_airflow() const { return p->klystronAirflow_; } -std::uint16_t PerformanceMaintenanceData::modulator_switch_maintenance() const +uint16_t PerformanceMaintenanceData::modulator_switch_maintenance() const { return p->modulatorSwitchMaintenance_; } -std::uint16_t -PerformanceMaintenanceData::post_charge_regulator_maintenance() const +uint16_t PerformanceMaintenanceData::post_charge_regulator_maintenance() const { return p->postChargeRegulatorMaintenance_; } -std::uint16_t PerformanceMaintenanceData::wg_pressure_humidity() const +uint16_t PerformanceMaintenanceData::wg_pressure_humidity() const { return p->wgPressureHumidity_; } -std::uint16_t PerformanceMaintenanceData::transmitter_overvoltage() const +uint16_t PerformanceMaintenanceData::transmitter_overvoltage() const { return p->transmitterOvervoltage_; } -std::uint16_t PerformanceMaintenanceData::transmitter_overcurrent() const +uint16_t PerformanceMaintenanceData::transmitter_overcurrent() const { return p->transmitterOvercurrent_; } -std::uint16_t PerformanceMaintenanceData::focus_coil_current() const +uint16_t PerformanceMaintenanceData::focus_coil_current() const { return p->focusCoilCurrent_; } -std::uint16_t PerformanceMaintenanceData::focus_coil_airflow() const +uint16_t PerformanceMaintenanceData::focus_coil_airflow() const { return p->focusCoilAirflow_; } -std::uint16_t PerformanceMaintenanceData::oil_temperature() const +uint16_t PerformanceMaintenanceData::oil_temperature() const { return p->oilTemperature_; } -std::uint16_t PerformanceMaintenanceData::prf_limit() const +uint16_t PerformanceMaintenanceData::prf_limit() const { return p->prfLimit_; } -std::uint16_t PerformanceMaintenanceData::transmitter_oil_level() const +uint16_t PerformanceMaintenanceData::transmitter_oil_level() const { return p->transmitterOilLevel_; } -std::uint16_t PerformanceMaintenanceData::transmitter_battery_charging() const +uint16_t PerformanceMaintenanceData::transmitter_battery_charging() const { return p->transmitterBatteryCharging_; } -std::uint16_t PerformanceMaintenanceData::high_voltage_status() const +uint16_t PerformanceMaintenanceData::high_voltage_status() const { return p->highVoltageStatus_; } -std::uint16_t PerformanceMaintenanceData::transmitter_recycling_summary() const +uint16_t PerformanceMaintenanceData::transmitter_recycling_summary() const { return p->transmitterRecyclingSummary_; } -std::uint16_t PerformanceMaintenanceData::transmitter_inoperable() const +uint16_t PerformanceMaintenanceData::transmitter_inoperable() const { return p->transmitterInoperable_; } -std::uint16_t PerformanceMaintenanceData::transmitter_air_filter() const +uint16_t PerformanceMaintenanceData::transmitter_air_filter() const { return p->transmitterAirFilter_; } -std::uint16_t PerformanceMaintenanceData::zero_test_bit(unsigned i) const +uint16_t PerformanceMaintenanceData::zero_test_bit(unsigned i) const { - return p->zeroTestBit_.at(i); + return p->zeroTestBit_[i]; } -std::uint16_t PerformanceMaintenanceData::one_test_bit(unsigned i) const +uint16_t PerformanceMaintenanceData::one_test_bit(unsigned i) const { - return p->oneTestBit_.at(i); + return p->oneTestBit_[i]; } -std::uint16_t PerformanceMaintenanceData::xmtr_spip_interface() const +uint16_t PerformanceMaintenanceData::xmtr_spip_interface() const { return p->xmtrSpipInterface_; } -std::uint16_t PerformanceMaintenanceData::transmitter_summary_status() const +uint16_t PerformanceMaintenanceData::transmitter_summary_status() const { return p->transmitterSummaryStatus_; } @@ -880,7 +1131,7 @@ float PerformanceMaintenanceData::xmtr_rf_avg_power() const return p->xmtrRfAvgPower_; } -std::uint32_t PerformanceMaintenanceData::xmtr_recycle_count() const +uint32_t PerformanceMaintenanceData::xmtr_recycle_count() const { return p->xmtrRecycleCount_; } @@ -900,108 +1151,108 @@ float PerformanceMaintenanceData::xmtr_power_meter_zero() const return p->xmtrPowerMeterZero_; } -std::uint16_t PerformanceMaintenanceData::ac_unit1_compressor_shut_off() const +uint16_t PerformanceMaintenanceData::ac_unit1_compressor_shut_off() const { return p->acUnit1CompressorShutOff_; } -std::uint16_t PerformanceMaintenanceData::ac_unit2_compressor_shut_off() const +uint16_t PerformanceMaintenanceData::ac_unit2_compressor_shut_off() const { return p->acUnit2CompressorShutOff_; } -std::uint16_t PerformanceMaintenanceData::generator_maintenance_required() const +uint16_t PerformanceMaintenanceData::generator_maintenance_required() const { return p->generatorMaintenanceRequired_; } -std::uint16_t PerformanceMaintenanceData::generator_battery_voltage() const +uint16_t PerformanceMaintenanceData::generator_battery_voltage() const { return p->generatorBatteryVoltage_; } -std::uint16_t PerformanceMaintenanceData::generator_engine() const +uint16_t PerformanceMaintenanceData::generator_engine() const { return p->generatorEngine_; } -std::uint16_t PerformanceMaintenanceData::generator_volt_frequency() const +uint16_t PerformanceMaintenanceData::generator_volt_frequency() const { return p->generatorVoltFrequency_; } -std::uint16_t PerformanceMaintenanceData::power_source() const +uint16_t PerformanceMaintenanceData::power_source() const { return p->powerSource_; } -std::uint16_t PerformanceMaintenanceData::transitional_power_source() const +uint16_t PerformanceMaintenanceData::transitional_power_source() const { return p->transitionalPowerSource_; } -std::uint16_t PerformanceMaintenanceData::generator_auto_run_off_switch() const +uint16_t PerformanceMaintenanceData::generator_auto_run_off_switch() const { return p->generatorAutoRunOffSwitch_; } -std::uint16_t PerformanceMaintenanceData::aircraft_hazard_lighting() const +uint16_t PerformanceMaintenanceData::aircraft_hazard_lighting() const { return p->aircraftHazardLighting_; } -std::uint16_t +uint16_t PerformanceMaintenanceData::equipment_shelter_fire_detection_system() const { return p->equipmentShelterFireDetectionSystem_; } -std::uint16_t PerformanceMaintenanceData::equipment_shelter_fire_smoke() const +uint16_t PerformanceMaintenanceData::equipment_shelter_fire_smoke() const { return p->equipmentShelterFireSmoke_; } -std::uint16_t PerformanceMaintenanceData::generator_shelter_fire_smoke() const +uint16_t PerformanceMaintenanceData::generator_shelter_fire_smoke() const { return p->generatorShelterFireSmoke_; } -std::uint16_t PerformanceMaintenanceData::utility_voltage_frequency() const +uint16_t PerformanceMaintenanceData::utility_voltage_frequency() const { return p->utilityVoltageFrequency_; } -std::uint16_t PerformanceMaintenanceData::site_security_alarm() const +uint16_t PerformanceMaintenanceData::site_security_alarm() const { return p->siteSecurityAlarm_; } -std::uint16_t PerformanceMaintenanceData::security_equipment() const +uint16_t PerformanceMaintenanceData::security_equipment() const { return p->securityEquipment_; } -std::uint16_t PerformanceMaintenanceData::security_system() const +uint16_t PerformanceMaintenanceData::security_system() const { return p->securitySystem_; } -std::uint16_t PerformanceMaintenanceData::receiver_connected_to_antenna() const +uint16_t PerformanceMaintenanceData::receiver_connected_to_antenna() const { return p->receiverConnectedToAntenna_; } -std::uint16_t PerformanceMaintenanceData::radome_hatch() const +uint16_t PerformanceMaintenanceData::radome_hatch() const { return p->radomeHatch_; } -std::uint16_t PerformanceMaintenanceData::ac_unit1_filter_dirty() const +uint16_t PerformanceMaintenanceData::ac_unit1_filter_dirty() const { return p->acUnit1FilterDirty_; } -std::uint16_t PerformanceMaintenanceData::ac_unit2_filter_dirty() const +uint16_t PerformanceMaintenanceData::ac_unit2_filter_dirty() const { return p->acUnit2FilterDirty_; } @@ -1051,7 +1302,7 @@ float PerformanceMaintenanceData::spip_neg_15v_ps() const return p->spipNeg15VPs_; } -std::uint16_t PerformanceMaintenanceData::spip_28v_ps_status() const +uint16_t PerformanceMaintenanceData::spip_28v_ps_status() const { return p->spip28VPsStatus_; } @@ -1061,201 +1312,198 @@ float PerformanceMaintenanceData::spip_5v_ps() const return p->spip5VPs_; } -std::uint16_t PerformanceMaintenanceData::converted_generator_fuel_level() const +uint16_t PerformanceMaintenanceData::converted_generator_fuel_level() const { return p->convertedGeneratorFuelLevel_; } -std::uint16_t PerformanceMaintenanceData::elevation_pos_dead_limit() const +uint16_t PerformanceMaintenanceData::elevation_pos_dead_limit() const { return p->elevationPosDeadLimit_; } -std::uint16_t PerformanceMaintenanceData::_150v_overvoltage() const +uint16_t PerformanceMaintenanceData::_150v_overvoltage() const { return p->_150VOvervoltage_; } -std::uint16_t PerformanceMaintenanceData::_150v_undervoltage() const +uint16_t PerformanceMaintenanceData::_150v_undervoltage() const { return p->_150VUndervoltage_; } -std::uint16_t PerformanceMaintenanceData::elevation_servo_amp_inhibit() const +uint16_t PerformanceMaintenanceData::elevation_servo_amp_inhibit() const { return p->elevationServoAmpInhibit_; } -std::uint16_t -PerformanceMaintenanceData::elevation_servo_amp_short_circuit() const +uint16_t PerformanceMaintenanceData::elevation_servo_amp_short_circuit() const { return p->elevationServoAmpShortCircuit_; } -std::uint16_t PerformanceMaintenanceData::elevation_servo_amp_overtemp() const +uint16_t PerformanceMaintenanceData::elevation_servo_amp_overtemp() const { return p->elevationServoAmpOvertemp_; } -std::uint16_t PerformanceMaintenanceData::elevation_motor_overtemp() const +uint16_t PerformanceMaintenanceData::elevation_motor_overtemp() const { return p->elevationMotorOvertemp_; } -std::uint16_t PerformanceMaintenanceData::elevation_stow_pin() const +uint16_t PerformanceMaintenanceData::elevation_stow_pin() const { return p->elevationStowPin_; } -std::uint16_t PerformanceMaintenanceData::elevation_housing_5v_ps() const +uint16_t PerformanceMaintenanceData::elevation_housing_5v_ps() const { return p->elevationHousing5VPs_; } -std::uint16_t PerformanceMaintenanceData::elevation_neg_dead_limit() const +uint16_t PerformanceMaintenanceData::elevation_neg_dead_limit() const { return p->elevationNegDeadLimit_; } -std::uint16_t PerformanceMaintenanceData::elevation_pos_normal_limit() const +uint16_t PerformanceMaintenanceData::elevation_pos_normal_limit() const { return p->elevationPosNormalLimit_; } -std::uint16_t PerformanceMaintenanceData::elevation_neg_normal_limit() const +uint16_t PerformanceMaintenanceData::elevation_neg_normal_limit() const { return p->elevationNegNormalLimit_; } -std::uint16_t PerformanceMaintenanceData::elevation_encoder_light() const +uint16_t PerformanceMaintenanceData::elevation_encoder_light() const { return p->elevationEncoderLight_; } -std::uint16_t PerformanceMaintenanceData::elevation_gearbox_oil() const +uint16_t PerformanceMaintenanceData::elevation_gearbox_oil() const { return p->elevationGearboxOil_; } -std::uint16_t PerformanceMaintenanceData::elevation_handwheel() const +uint16_t PerformanceMaintenanceData::elevation_handwheel() const { return p->elevationHandwheel_; } -std::uint16_t PerformanceMaintenanceData::elevation_amp_ps() const +uint16_t PerformanceMaintenanceData::elevation_amp_ps() const { return p->elevationAmpPs_; } -std::uint16_t PerformanceMaintenanceData::azimuth_servo_amp_inhibit() const +uint16_t PerformanceMaintenanceData::azimuth_servo_amp_inhibit() const { return p->azimuthServoAmpInhibit_; } -std::uint16_t -PerformanceMaintenanceData::azimuth_servo_amp_short_circuit() const +uint16_t PerformanceMaintenanceData::azimuth_servo_amp_short_circuit() const { return p->azimuthServoAmpShortCircuit_; } -std::uint16_t PerformanceMaintenanceData::azimuth_servo_amp_overtemp() const +uint16_t PerformanceMaintenanceData::azimuth_servo_amp_overtemp() const { return p->azimuthServoAmpOvertemp_; } -std::uint16_t PerformanceMaintenanceData::azimuth_motor_overtemp() const +uint16_t PerformanceMaintenanceData::azimuth_motor_overtemp() const { return p->azimuthMotorOvertemp_; } -std::uint16_t PerformanceMaintenanceData::azimuth_stow_pin() const +uint16_t PerformanceMaintenanceData::azimuth_stow_pin() const { return p->azimuthStowPin_; } -std::uint16_t PerformanceMaintenanceData::azimuth_housing_5v_ps() const +uint16_t PerformanceMaintenanceData::azimuth_housing_5v_ps() const { return p->azimuthHousing5VPs_; } -std::uint16_t PerformanceMaintenanceData::azimuth_encoder_light() const +uint16_t PerformanceMaintenanceData::azimuth_encoder_light() const { return p->azimuthEncoderLight_; } -std::uint16_t PerformanceMaintenanceData::azimuth_gearbox_oil() const +uint16_t PerformanceMaintenanceData::azimuth_gearbox_oil() const { return p->azimuthGearboxOil_; } -std::uint16_t PerformanceMaintenanceData::azimuth_bull_gear_oil() const +uint16_t PerformanceMaintenanceData::azimuth_bull_gear_oil() const { return p->azimuthBullGearOil_; } -std::uint16_t PerformanceMaintenanceData::azimuth_handwheel() const +uint16_t PerformanceMaintenanceData::azimuth_handwheel() const { return p->azimuthHandwheel_; } -std::uint16_t PerformanceMaintenanceData::azimuth_servo_amp_ps() const +uint16_t PerformanceMaintenanceData::azimuth_servo_amp_ps() const { return p->azimuthServoAmpPs_; } -std::uint16_t PerformanceMaintenanceData::servo() const +uint16_t PerformanceMaintenanceData::servo() const { return p->servo_; } -std::uint16_t PerformanceMaintenanceData::pedestal_interlock_switch() const +uint16_t PerformanceMaintenanceData::pedestal_interlock_switch() const { return p->pedestalInterlockSwitch_; } -std::uint16_t PerformanceMaintenanceData::coho_clock() const +uint16_t PerformanceMaintenanceData::coho_clock() const { return p->cohoClock_; } -std::uint16_t +uint16_t PerformanceMaintenanceData::rf_generator_frequency_select_oscillator() const { return p->rfGeneratorFrequencySelectOscillator_; } -std::uint16_t PerformanceMaintenanceData::rf_generator_rf_stalo() const +uint16_t PerformanceMaintenanceData::rf_generator_rf_stalo() const { return p->rfGeneratorRfStalo_; } -std::uint16_t -PerformanceMaintenanceData::rf_generator_phase_shifted_coho() const +uint16_t PerformanceMaintenanceData::rf_generator_phase_shifted_coho() const { return p->rfGeneratorPhaseShiftedCoho_; } -std::uint16_t PerformanceMaintenanceData::_9v_receiver_ps() const +uint16_t PerformanceMaintenanceData::_9v_receiver_ps() const { return p->_9VReceiverPs_; } -std::uint16_t PerformanceMaintenanceData::_5v_receiver_ps() const +uint16_t PerformanceMaintenanceData::_5v_receiver_ps() const { return p->_5VReceiverPs_; } -std::uint16_t PerformanceMaintenanceData::_18v_receiver_ps() const +uint16_t PerformanceMaintenanceData::_18v_receiver_ps() const { return p->_18VReceiverPs_; } -std::uint16_t PerformanceMaintenanceData::neg_9v_receiver_ps() const +uint16_t PerformanceMaintenanceData::neg_9v_receiver_ps() const { return p->neg9VReceiverPs_; } -std::uint16_t PerformanceMaintenanceData::_5v_single_channel_rdaiu_ps() const +uint16_t PerformanceMaintenanceData::_5v_single_channel_rdaiu_ps() const { return p->_5VSingleChannelRdaiuPs_; } @@ -1325,22 +1573,22 @@ float PerformanceMaintenanceData::long_pulse_horizontal_dbz0() const return p->longPulseHorizontalDbz0_; } -std::uint16_t PerformanceMaintenanceData::velocity_processed() const +uint16_t PerformanceMaintenanceData::velocity_processed() const { return p->velocityProcessed_; } -std::uint16_t PerformanceMaintenanceData::width_processed() const +uint16_t PerformanceMaintenanceData::width_processed() const { return p->widthProcessed_; } -std::uint16_t PerformanceMaintenanceData::velocity_rf_gen() const +uint16_t PerformanceMaintenanceData::velocity_rf_gen() const { return p->velocityRfGen_; } -std::uint16_t PerformanceMaintenanceData::width_rf_gen() const +uint16_t PerformanceMaintenanceData::width_rf_gen() const { return p->widthRfGen_; } @@ -1380,9 +1628,9 @@ float PerformanceMaintenanceData::vertical_power_sense() const return p->verticalPowerSense_; } -float PerformanceMaintenanceData::zdr_offset() const +float PerformanceMaintenanceData::zdr_bias() const { - return p->zdrOffset_; + return p->zdrBias_; } float PerformanceMaintenanceData::clutter_suppression_delta() const @@ -1405,148 +1653,170 @@ float PerformanceMaintenanceData::vertical_linearity() const return p->verticalLinearity_; } -std::uint16_t PerformanceMaintenanceData::state_file_read_status() const +uint16_t PerformanceMaintenanceData::state_file_read_status() const { return p->stateFileReadStatus_; } -std::uint16_t PerformanceMaintenanceData::state_file_write_status() const +uint16_t PerformanceMaintenanceData::state_file_write_status() const { return p->stateFileWriteStatus_; } -std::uint16_t PerformanceMaintenanceData::bypass_map_file_read_status() const +uint16_t PerformanceMaintenanceData::bypass_map_file_read_status() const { return p->bypassMapFileReadStatus_; } -std::uint16_t PerformanceMaintenanceData::bypass_map_file_write_status() const +uint16_t PerformanceMaintenanceData::bypass_map_file_write_status() const { return p->bypassMapFileWriteStatus_; } -std::uint16_t -PerformanceMaintenanceData::current_adaptation_file_read_status() const +uint16_t PerformanceMaintenanceData::current_adaptation_file_read_status() const { return p->currentAdaptationFileReadStatus_; } -std::uint16_t +uint16_t PerformanceMaintenanceData::current_adaptation_file_write_status() const { return p->currentAdaptationFileWriteStatus_; } -std::uint16_t PerformanceMaintenanceData::censor_zone_file_read_status() const +uint16_t PerformanceMaintenanceData::censor_zone_file_read_status() const { return p->censorZoneFileReadStatus_; } -std::uint16_t PerformanceMaintenanceData::censor_zone_file_write_status() const +uint16_t PerformanceMaintenanceData::censor_zone_file_write_status() const { return p->censorZoneFileWriteStatus_; } -std::uint16_t PerformanceMaintenanceData::remote_vcp_file_read_status() const +uint16_t PerformanceMaintenanceData::remote_vcp_file_read_status() const { return p->remoteVcpFileReadStatus_; } -std::uint16_t PerformanceMaintenanceData::remote_vcp_file_write_status() const +uint16_t PerformanceMaintenanceData::remote_vcp_file_write_status() const { return p->remoteVcpFileWriteStatus_; } -std::uint16_t +uint16_t PerformanceMaintenanceData::baseline_adaptation_file_read_status() const { return p->baselineAdaptationFileReadStatus_; } -std::uint16_t PerformanceMaintenanceData::read_status_of_prf_sets() const +uint16_t PerformanceMaintenanceData::read_status_of_prf_sets() const { return p->readStatusOfPrfSets_; } -std::uint16_t -PerformanceMaintenanceData::clutter_filter_map_file_read_status() const +uint16_t PerformanceMaintenanceData::clutter_filter_map_file_read_status() const { return p->clutterFilterMapFileReadStatus_; } -std::uint16_t +uint16_t PerformanceMaintenanceData::clutter_filter_map_file_write_status() const { return p->clutterFilterMapFileWriteStatus_; } -std::uint16_t PerformanceMaintenanceData::general_disk_io_error() const +uint16_t PerformanceMaintenanceData::generatl_disk_io_error() const { - return p->generalDiskIoError_; + return p->generatlDiskIoError_; } -std::uint8_t PerformanceMaintenanceData::rsp_status() const +uint8_t PerformanceMaintenanceData::rsp_status() const { return p->rspStatus_; } -std::uint8_t PerformanceMaintenanceData::cpu1_temperature() const +uint8_t PerformanceMaintenanceData::motherboard_temperature() const +{ + return p->motherboardTemperature_; +} + +uint8_t PerformanceMaintenanceData::cpu1_temperature() const { return p->cpu1Temperature_; } -std::uint8_t PerformanceMaintenanceData::cpu2_temperature() const +uint8_t PerformanceMaintenanceData::cpu2_temperature() const { return p->cpu2Temperature_; } -std::uint16_t PerformanceMaintenanceData::rsp_motherboard_power() const +uint16_t PerformanceMaintenanceData::cpu1_fan_speed() const { - return p->rspMotherboardPower_; + return p->cpu1FanSpeed_; } -std::uint16_t PerformanceMaintenanceData::spip_comm_status() const +uint16_t PerformanceMaintenanceData::cpu2_fan_speed() const +{ + return p->cpu2FanSpeed_; +} + +uint16_t PerformanceMaintenanceData::rsp_fan1_speed() const +{ + return p->rspFan1Speed_; +} + +uint16_t PerformanceMaintenanceData::rsp_fan2_speed() const +{ + return p->rspFan2Speed_; +} + +uint16_t PerformanceMaintenanceData::rsp_fan3_speed() const +{ + return p->rspFan3Speed_; +} + +uint16_t PerformanceMaintenanceData::spip_comm_status() const { return p->spipCommStatus_; } -std::uint16_t PerformanceMaintenanceData::hci_comm_status() const +uint16_t PerformanceMaintenanceData::hci_comm_status() const { return p->hciCommStatus_; } -std::uint16_t -PerformanceMaintenanceData::signal_processor_command_status() const +uint16_t PerformanceMaintenanceData::signal_processor_command_status() const { return p->signalProcessorCommandStatus_; } -std::uint16_t PerformanceMaintenanceData::ame_communication_status() const +uint16_t PerformanceMaintenanceData::ame_communication_status() const { return p->ameCommunicationStatus_; } -std::uint16_t PerformanceMaintenanceData::rms_link_status() const +uint16_t PerformanceMaintenanceData::rms_link_status() const { return p->rmsLinkStatus_; } -std::uint16_t PerformanceMaintenanceData::rpg_link_status() const +uint16_t PerformanceMaintenanceData::rpg_link_status() const { return p->rpgLinkStatus_; } -std::uint16_t PerformanceMaintenanceData::interpanel_link_status() const +uint16_t PerformanceMaintenanceData::interpanel_link_status() const { return p->interpanelLinkStatus_; } -std::uint32_t PerformanceMaintenanceData::performance_check_time() const +uint32_t PerformanceMaintenanceData::performance_check_time() const { return p->performanceCheckTime_; } -std::uint16_t PerformanceMaintenanceData::version() const +uint16_t PerformanceMaintenanceData::version() const { return p->version_; } @@ -1555,10 +1825,9 @@ bool PerformanceMaintenanceData::Parse(std::istream& is) { logger_->trace("Parsing Performance/Maintenance Data (Message Type 3)"); - bool messageValid = true; - std::size_t bytesRead = 0; + bool messageValid = true; + size_t bytesRead = 0; - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers): Readability p->rcpString_.resize(16); // Communications @@ -1570,13 +1839,11 @@ bool PerformanceMaintenanceData::Parse(std::istream& is) is.read(reinterpret_cast(&p->routerMemoryFree_), 4); // 9-10 is.read(reinterpret_cast(&p->routerMemoryUtilization_), 2); // 11 is.read(reinterpret_cast(&p->routeToRpg_), 2); // 12 - is.read(reinterpret_cast(&p->t1PortStatus_), 2); // 13 - is.read(reinterpret_cast(&p->routerDedicatedEthernetPortStatus_), - 2); // 14 - is.read(reinterpret_cast(&p->routerCommercialEthernetPortStatus_), - 2); // 15 - is.seekg(10, std::ios_base::cur); // 16-20 - is.read(reinterpret_cast(&p->csu24HrErroredSeconds_), 4); // 21-22 + is.read(reinterpret_cast(&p->csuLossOfSignal_), 4); // 13-14 + is.read(reinterpret_cast(&p->csuLossOfFrames_), 4); // 15-16 + is.read(reinterpret_cast(&p->csuYellowAlarms_), 4); // 17-18 + is.read(reinterpret_cast(&p->csuBlueAlarms_), 4); // 19-20 + is.read(reinterpret_cast(&p->csu24HrErroredSeconds_), 4); // 21-22 is.read(reinterpret_cast(&p->csu24HrSeverelyErroredSeconds_), 4); // 23-24 is.read(reinterpret_cast(&p->csu24HrSeverelyErroredFramingSeconds_), @@ -1596,8 +1863,9 @@ bool PerformanceMaintenanceData::Parse(std::istream& is) is.seekg(2, std::ios_base::cur); // 44 is.read(reinterpret_cast(&p->ifdrChasisTemperature_), 2); // 45 is.read(reinterpret_cast(&p->ifdrFpgaTemperature_), 2); // 46 - is.read(reinterpret_cast(&p->ntpStatus_), 2); // 47 - is.seekg(10, std::ios_base::cur); // 48-52 + is.seekg(4, std::ios_base::cur); // 47-48 + is.read(reinterpret_cast(&p->gpsSatellites_), 4); // 49-50 + is.seekg(4, std::ios_base::cur); // 51-52 is.read(reinterpret_cast(&p->ipcStatus_), 2); // 53 is.read(reinterpret_cast(&p->commandedChannelControl_), 2); // 54 is.seekg(6, std::ios_base::cur); // 55-57 @@ -1702,10 +1970,10 @@ bool PerformanceMaintenanceData::Parse(std::istream& is) is.read(reinterpret_cast(&p->transmitterInoperable_), 2); // 184 is.read(reinterpret_cast(&p->transmitterAirFilter_), 2); // 185 is.read(reinterpret_cast(&p->zeroTestBit_[0]), - static_cast(p->zeroTestBit_.size() * 2)); // 186-193 + p->zeroTestBit_.size() * 2); // 186-193 is.read(reinterpret_cast(&p->oneTestBit_[0]), - static_cast(p->oneTestBit_.size() * 2)); // 194-201 - is.read(reinterpret_cast(&p->xmtrSpipInterface_), 2); // 202 + p->oneTestBit_.size() * 2); // 194-201 + is.read(reinterpret_cast(&p->xmtrSpipInterface_), 2); // 202 is.read(reinterpret_cast(&p->transmitterSummaryStatus_), 2); // 203 is.seekg(2, std::ios_base::cur); // 204 is.read(reinterpret_cast(&p->transmitterRfPower_), 4); // 205-206 @@ -1844,7 +2112,7 @@ bool PerformanceMaintenanceData::Parse(std::istream& is) is.seekg(8, std::ios_base::cur); // 393-396 is.read(reinterpret_cast(&p->horizontalPowerSense_), 4); // 397-398 is.read(reinterpret_cast(&p->verticalPowerSense_), 4); // 399-400 - is.read(reinterpret_cast(&p->zdrOffset_), 4); // 401-402 + is.read(reinterpret_cast(&p->zdrBias_), 4); // 401-402 is.seekg(12, std::ios_base::cur); // 403-408 is.read(reinterpret_cast(&p->clutterSuppressionDelta_), 4); // 409-410 is.read(reinterpret_cast(&p->clutterSuppressionUnfilteredPower_), @@ -1875,14 +2143,18 @@ bool PerformanceMaintenanceData::Parse(std::istream& is) is.read(reinterpret_cast(&p->clutterFilterMapFileReadStatus_), 2); // 445 is.read(reinterpret_cast(&p->clutterFilterMapFileWriteStatus_), - 2); // 446 - is.read(reinterpret_cast(&p->generalDiskIoError_), 2); // 447 - is.read(reinterpret_cast(&p->rspStatus_), 1); // 448 - is.seekg(1, std::ios_base::cur); // 448 - is.read(reinterpret_cast(&p->cpu1Temperature_), 1); // 449 - is.read(reinterpret_cast(&p->cpu2Temperature_), 1); // 449 - is.read(reinterpret_cast(&p->rspMotherboardPower_), 2); // 450 - is.seekg(20, std::ios_base::cur); // 451-460 + 2); // 446 + is.read(reinterpret_cast(&p->generatlDiskIoError_), 2); // 447 + is.read(reinterpret_cast(&p->rspStatus_), 1); // 448 + is.read(reinterpret_cast(&p->motherboardTemperature_), 1); // 448 + is.read(reinterpret_cast(&p->cpu1Temperature_), 1); // 449 + is.read(reinterpret_cast(&p->cpu2Temperature_), 1); // 449 + is.read(reinterpret_cast(&p->cpu1FanSpeed_), 2); // 450 + is.read(reinterpret_cast(&p->cpu2FanSpeed_), 2); // 451 + is.read(reinterpret_cast(&p->rspFan1Speed_), 2); // 452 + is.read(reinterpret_cast(&p->rspFan2Speed_), 2); // 453 + is.read(reinterpret_cast(&p->rspFan3Speed_), 2); // 454 + is.seekg(12, std::ios_base::cur); // 455-460 // Device Status is.read(reinterpret_cast(&p->spipCommStatus_), 2); // 461 @@ -1900,21 +2172,18 @@ bool PerformanceMaintenanceData::Parse(std::istream& is) bytesRead += 960; - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - // Communications - p->loopBackSetStatus_ = ntohs(p->loopBackSetStatus_); - p->t1OutputFrames_ = ntohl(p->t1OutputFrames_); - p->t1InputFrames_ = ntohl(p->t1InputFrames_); - p->routerMemoryUsed_ = ntohl(p->routerMemoryUsed_); - p->routerMemoryFree_ = ntohl(p->routerMemoryFree_); - p->routerMemoryUtilization_ = ntohs(p->routerMemoryUtilization_); - p->routeToRpg_ = ntohs(p->routeToRpg_); - p->t1PortStatus_ = ntohs(p->t1PortStatus_); - p->routerDedicatedEthernetPortStatus_ = - ntohs(p->routerDedicatedEthernetPortStatus_); - p->routerCommercialEthernetPortStatus_ = - ntohs(p->routerCommercialEthernetPortStatus_); + p->loopBackSetStatus_ = ntohs(p->loopBackSetStatus_); + p->t1OutputFrames_ = ntohl(p->t1OutputFrames_); + p->t1InputFrames_ = ntohl(p->t1InputFrames_); + p->routerMemoryUsed_ = ntohl(p->routerMemoryUsed_); + p->routerMemoryFree_ = ntohl(p->routerMemoryFree_); + p->routerMemoryUtilization_ = ntohs(p->routerMemoryUtilization_); + p->routeToRpg_ = ntohs(p->routeToRpg_); + p->csuLossOfSignal_ = ntohl(p->csuLossOfSignal_); + p->csuLossOfFrames_ = ntohl(p->csuLossOfFrames_); + p->csuYellowAlarms_ = ntohl(p->csuYellowAlarms_); + p->csuBlueAlarms_ = ntohl(p->csuBlueAlarms_); p->csu24HrErroredSeconds_ = ntohl(p->csu24HrErroredSeconds_); p->csu24HrSeverelyErroredSeconds_ = ntohl(p->csu24HrSeverelyErroredSeconds_); p->csu24HrSeverelyErroredFramingSeconds_ = @@ -1929,7 +2198,7 @@ bool PerformanceMaintenanceData::Parse(std::istream& is) p->lanSwitchMemoryUtilization_ = ntohs(p->lanSwitchMemoryUtilization_); p->ifdrChasisTemperature_ = ntohs(p->ifdrChasisTemperature_); p->ifdrFpgaTemperature_ = ntohs(p->ifdrFpgaTemperature_); - p->ntpStatus_ = ntohs(p->ntpStatus_); + p->gpsSatellites_ = ntohl(p->gpsSatellites_); p->ipcStatus_ = ntohs(p->ipcStatus_); p->commandedChannelControl_ = ntohs(p->commandedChannelControl_); @@ -2144,7 +2413,7 @@ bool PerformanceMaintenanceData::Parse(std::istream& is) p->longPulseVerticalDbz0_ = SwapFloat(p->longPulseVerticalDbz0_); p->horizontalPowerSense_ = SwapFloat(p->horizontalPowerSense_); p->verticalPowerSense_ = SwapFloat(p->verticalPowerSense_); - p->zdrOffset_ = SwapFloat(p->zdrOffset_); + p->zdrBias_ = SwapFloat(p->zdrBias_); p->clutterSuppressionDelta_ = SwapFloat(p->clutterSuppressionDelta_); p->clutterSuppressionUnfilteredPower_ = SwapFloat(p->clutterSuppressionUnfilteredPower_); @@ -2172,8 +2441,12 @@ bool PerformanceMaintenanceData::Parse(std::istream& is) ntohs(p->clutterFilterMapFileReadStatus_); p->clutterFilterMapFileWriteStatus_ = ntohs(p->clutterFilterMapFileWriteStatus_); - p->generalDiskIoError_ = ntohs(p->generalDiskIoError_); - p->rspMotherboardPower_ = ntohs(p->rspMotherboardPower_); + p->generatlDiskIoError_ = ntohs(p->generatlDiskIoError_); + p->cpu1FanSpeed_ = ntohs(p->cpu1FanSpeed_); + p->cpu2FanSpeed_ = ntohs(p->cpu2FanSpeed_); + p->rspFan1Speed_ = ntohs(p->rspFan1Speed_); + p->rspFan2Speed_ = ntohs(p->rspFan2Speed_); + p->rspFan3Speed_ = ntohs(p->rspFan3Speed_); // Device Status p->spipCommStatus_ = ntohs(p->spipCommStatus_); @@ -2210,4 +2483,6 @@ PerformanceMaintenanceData::Create(Level2MessageHeader&& header, return message; } -} // namespace scwx::wsr88d::rda +} // namespace rda +} // namespace wsr88d +} // namespace scwx diff --git a/wxdata/source/scwx/wsr88d/rda/rda_adaptation_data.cpp b/wxdata/source/scwx/wsr88d/rda/rda_adaptation_data.cpp index 7ccd5863..94a96283 100644 --- a/wxdata/source/scwx/wsr88d/rda/rda_adaptation_data.cpp +++ b/wxdata/source/scwx/wsr88d/rda/rda_adaptation_data.cpp @@ -1,7 +1,11 @@ #include #include -namespace scwx::wsr88d::rda +namespace scwx +{ +namespace wsr88d +{ +namespace rda { static const std::string logPrefix_ = "scwx::wsr88d::rda::rda_adaptation_data"; @@ -9,202 +13,362 @@ static const auto logger_ = util::Logger::Create(logPrefix_); struct AntManualSetup { - std::int32_t ielmin_ {0}; - std::int32_t ielmax_ {0}; - std::uint32_t fazvelmax_ {0}; - std::uint32_t felvelmax_ {0}; - std::int32_t igndHgt_ {0}; - std::uint32_t iradHgt_ {0}; + int32_t ielmin_; + int32_t ielmax_; + uint32_t fazvelmax_; + uint32_t felvelmax_; + int32_t igndHgt_; + uint32_t iradHgt_; + + AntManualSetup() : + ielmin_ {0}, + ielmax_ {0}, + fazvelmax_ {0}, + felvelmax_ {0}, + igndHgt_ {0}, + iradHgt_ {0} + { + } }; -class RdaAdaptationData::Impl +class RdaAdaptationDataImpl { public: - explicit Impl() = default; - ~Impl() = default; + explicit RdaAdaptationDataImpl() : + adapFileName_ {}, + adapFormat_ {}, + adapRevision_ {}, + adapDate_ {}, + adapTime_ {}, + lowerPreLimit_ {0.0f}, + azLat_ {0.0f}, + upperPreLimit_ {0.0f}, + elLat_ {0.0f}, + parkaz_ {0.0f}, + parkel_ {0.0f}, + aFuelConv_ {0.0f}, + aMinShelterTemp_ {0.0f}, + aMaxShelterTemp_ {0.0f}, + aMinShelterAcTempDiff_ {0.0f}, + aMaxXmtrAirTemp_ {0.0f}, + aMaxRadTemp_ {0.0f}, + aMaxRadTempRise_ {0.0f}, + lowerDeadLimit_ {0.0f}, + upperDeadLimit_ {0.0f}, + aMinGenRoomTemp_ {0.0f}, + aMaxGenRoomTemp_ {0.0f}, + spip5VRegLim_ {0.0f}, + spip15VRegLim_ {0.0f}, + rpgCoLocated_ {false}, + specFilterInstalled_ {false}, + tpsInstalled_ {false}, + rmsInstalled_ {false}, + aHvdlTstInt_ {0}, + aRpgLtInt_ {0}, + aMinStabUtilPwrTime_ {0}, + aGenAutoExerInterval_ {0}, + aUtilPwrSwReqInterval_ {0}, + aLowFuelLevel_ {0.0f}, + configChanNumber_ {0}, + redundantChanConfig_ {0}, + attenTable_ {0.0f}, + pathLosses_ {}, + vTsCw_ {0.0f}, + hRnscale_ {0.0f}, + atmos_ {0.0f}, + elIndex_ {0.0f}, + tfreqMhz_ {0}, + baseDataTcn_ {0.0f}, + reflDataTover_ {0.0f}, + tarHDbz0Lp_ {0.0f}, + tarVDbz0Lp_ {0.0f}, + initPhiDp_ {0}, + normInitPhiDp_ {0}, + lxLp_ {0.0f}, + lxSp_ {0.0f}, + meteorParam_ {0.0f}, + antennaGain_ {0.0f}, + velDegradLimit_ {0.0f}, + wthDegradLimit_ {0.0f}, + hNoisetempDgradLimit_ {0.0f}, + hMinNoisetemp_ {0}, + vNoisetempDgradLimit_ {0.0f}, + vMinNoisetemp_ {0}, + klyDegradeLimit_ {0.0f}, + tsCoho_ {0.0f}, + hTsCw_ {0.0f}, + tsStalo_ {0.0f}, + ameHNoiseEnr_ {0.0f}, + xmtrPeakPwrHighLimit_ {0.0f}, + xmtrPeakPwrLowLimit_ {0.0f}, + hDbz0DeltaLimit_ {0.0f}, + threshold1_ {0.0f}, + threshold2_ {0.0f}, + clutSuppDgradLim_ {0.0f}, + range0Value_ {0.0f}, + xmtrPwrMtrScale_ {0.0f}, + vDbz0DeltaLimit_ {0.0f}, + tarHDbz0Sp_ {0.0f}, + tarVDbz0Sp_ {0.0f}, + deltaprf_ {0}, + tauSp_ {0}, + tauLp_ {0}, + ncDeadValue_ {0}, + tauRfSp_ {0}, + tauRfLp_ {0}, + seg1Lim_ {0.0f}, + slatsec_ {0.0f}, + slonsec_ {0.0f}, + slatdeg_ {0}, + slatmin_ {0}, + slondeg_ {0}, + slonmin_ {0}, + slatdir_ {0}, + slondir_ {0}, + azCorrectionFactor_ {0.0f}, + elCorrectionFactor_ {0.0f}, + siteName_ {}, + antManualSetup_(), + azPosSustainDrive_ {0.0f}, + azNegSustainDrive_ {0.0f}, + azNomPosDriveSlope_ {0.0f}, + azNomNegDriveSlope_ {0.0f}, + azFeedbackSlope_ {0.0f}, + elPosSustainDrive_ {0.0f}, + elNegSustainDrive_ {0.0f}, + elNomPosDriveSlope_ {0.0f}, + elNomNegDriveSlope_ {0.0f}, + elFeedbackSlope_ {0.0f}, + elFirstSlope_ {0.0f}, + elSecondSlope_ {0.0f}, + elThirdSlope_ {0.0f}, + elDroopPos_ {0.0f}, + elOffNeutralDrive_ {0.0f}, + azIntertia_ {0.0f}, + elInertia_ {0.0f}, + rvp8nvIwaveguideLength_ {0}, + vRnscale_ {0.0f}, + velDataTover_ {0.0f}, + widthDataTover_ {0.0f}, + dopplerRangeStart_ {0.0f}, + maxElIndex_ {0}, + seg2Lim_ {0.0f}, + seg3Lim_ {0.0f}, + seg4Lim_ {0.0f}, + nbrElSegments_ {0}, + hNoiseLong_ {0.0f}, + antNoiseTemp_ {0.0f}, + hNoiseShort_ {0.0f}, + hNoiseTolerance_ {0.0f}, + minHDynRange_ {0.0f}, + genInstalled_ {false}, + genExercise_ {false}, + vNoiseTolerance_ {0.0f}, + minVDynRange_ {0.0f}, + zdrBiasDgradLim_ {0.0f}, + baselineZdrBias_ {0.0f}, + vNoiseLong_ {0.0f}, + vNoiseShort_ {0.0f}, + zdrDataTover_ {0.0f}, + phiDataTover_ {0.0f}, + rhoDataTover_ {0.0f}, + staloPowerDgradLimit_ {0.0f}, + staloPowerMaintLimit_ {0.0f}, + minHPwrSense_ {0.0f}, + minVPwrSense_ {0.0f}, + hPwrSenseOffset_ {0.0f}, + vPwrSenseOffset_ {0.0f}, + psGainRef_ {0.0f}, + rfPalletBroadLoss_ {0.0f}, + amePsTolerance_ {0.0f}, + ameMaxTemp_ {0.0f}, + ameMinTemp_ {0.0f}, + rcvrModMaxTemp_ {0.0f}, + rcvrModMinTemp_ {0.0f}, + biteModMaxTemp_ {0.0f}, + biteModMinTemp_ {0.0f}, + defaultPolarization_ {0}, + trLimitDgradLimit_ {0.0f}, + trLimitFailLimit_ {0.0f}, + rfpStepperEnabled_ {false}, + ameCurrentTolerance_ {0.0f}, + hOnlyPolarization_ {0}, + vOnlyPolarization_ {0}, + sunBias_ {0.0f}, + aMinShelterTempWarn_ {0.0f}, + powerMeterZero_ {0.0f}, + txbBaseline_ {0.0f}, + txbAlarmThresh_ {0.0f} {}; + ~RdaAdaptationDataImpl() = default; - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; - - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) - std::string adapFileName_ {}; - std::string adapFormat_ {}; - std::string adapRevision_ {}; - std::string adapDate_ {}; - std::string adapTime_ {}; - float lowerPreLimit_ {0.0f}; - float azLat_ {0.0f}; - float upperPreLimit_ {0.0f}; - float elLat_ {0.0f}; - float parkaz_ {0.0f}; - float parkel_ {0.0f}; - std::array aFuelConv_ {0.0f}; - float aMinShelterTemp_ {0.0f}; - float aMaxShelterTemp_ {0.0f}; - float aMinShelterAcTempDiff_ {0.0f}; - float aMaxXmtrAirTemp_ {0.0f}; - float aMaxRadTemp_ {0.0f}; - float aMaxRadTempRise_ {0.0f}; - float lowerDeadLimit_ {0.0f}; - float upperDeadLimit_ {0.0f}; - float aMinGenRoomTemp_ {0.0f}; - float aMaxGenRoomTemp_ {0.0f}; - float spip5VRegLim_ {0.0f}; - float spip15VRegLim_ {0.0f}; - bool rpgCoLocated_ {false}; - bool specFilterInstalled_ {false}; - bool tpsInstalled_ {false}; - bool rmsInstalled_ {false}; - std::uint32_t aHvdlTstInt_ {0}; - std::uint32_t aRpgLtInt_ {0}; - std::uint32_t aMinStabUtilPwrTime_ {0}; - std::uint32_t aGenAutoExerInterval_ {0}; - std::uint32_t aUtilPwrSwReqInterval_ {0}; - float aLowFuelLevel_ {0.0f}; - std::uint32_t configChanNumber_ {0}; - std::uint32_t redundantChanConfig_ {0}; - std::array attenTable_ {0.0f}; - std::map pathLosses_ {}; - float vTsCw_ {0.0f}; - std::array hRnscale_ {0.0f}; - std::array atmos_ {0.0f}; - std::array elIndex_ {0.0f}; - std::uint32_t tfreqMhz_ {0}; - float baseDataTcn_ {0.0f}; - float reflDataTover_ {0.0f}; - float tarHDbz0Lp_ {0.0f}; - float tarVDbz0Lp_ {0.0f}; - std::uint32_t initPhiDp_ {0}; - std::uint32_t normInitPhiDp_ {0}; - float lxLp_ {0.0f}; - float lxSp_ {0.0f}; - float meteorParam_ {0.0f}; - float antennaGain_ {0.0f}; - float velDegradLimit_ {0.0f}; - float wthDegradLimit_ {0.0f}; - float hNoisetempDgradLimit_ {0.0f}; - std::uint32_t hMinNoisetemp_ {0}; - float vNoisetempDgradLimit_ {0.0f}; - std::uint32_t vMinNoisetemp_ {0}; - float klyDegradeLimit_ {0.0f}; - float tsCoho_ {0.0f}; - float hTsCw_ {0.0f}; - float tsStalo_ {0.0f}; - float ameHNoiseEnr_ {0.0f}; - float xmtrPeakPwrHighLimit_ {0.0f}; - float xmtrPeakPwrLowLimit_ {0.0f}; - float hDbz0DeltaLimit_ {0.0f}; - float threshold1_ {0.0f}; - float threshold2_ {0.0f}; - float clutSuppDgradLim_ {0.0f}; - float range0Value_ {0.0f}; - float xmtrPwrMtrScale_ {0.0f}; - float vDbz0DeltaLimit_ {0.0f}; - float tarHDbz0Sp_ {0.0f}; - float tarVDbz0Sp_ {0.0f}; - std::uint32_t deltaprf_ {0}; - std::uint32_t tauSp_ {0}; - std::uint32_t tauLp_ {0}; - std::uint32_t ncDeadValue_ {0}; - std::uint32_t tauRfSp_ {0}; - std::uint32_t tauRfLp_ {0}; - float seg1Lim_ {0.0f}; - float slatsec_ {0.0f}; - float slonsec_ {0.0f}; - std::uint32_t slatdeg_ {0}; - std::uint32_t slatmin_ {0}; - std::uint32_t slondeg_ {0}; - std::uint32_t slonmin_ {0}; - char slatdir_ {0}; - char slondir_ {0}; - double digRcvrClockFreq_ {0.0}; - double cohoFreq_ {0.0}; - float azCorrectionFactor_ {0.0f}; - float elCorrectionFactor_ {0.0f}; - std::string siteName_ {}; - AntManualSetup antManualSetup_ {}; - float azPosSustainDrive_ {0.0f}; - float azNegSustainDrive_ {0.0f}; - float azNomPosDriveSlope_ {0.0f}; - float azNomNegDriveSlope_ {0.0f}; - float azFeedbackSlope_ {0.0f}; - float elPosSustainDrive_ {0.0f}; - float elNegSustainDrive_ {0.0f}; - float elNomPosDriveSlope_ {0.0f}; - float elNomNegDriveSlope_ {0.0f}; - float elFeedbackSlope_ {0.0f}; - float elFirstSlope_ {0.0f}; - float elSecondSlope_ {0.0f}; - float elThirdSlope_ {0.0f}; - float elDroopPos_ {0.0f}; - float elOffNeutralDrive_ {0.0f}; - float azIntertia_ {0.0f}; - float elInertia_ {0.0f}; - float azStowAngle_ {0.0f}; - float elStowAngle_ {0.0f}; - float azEncoderAlignment_ {0.0f}; - float elEncoderAlignment_ {0.0f}; - std::string refinedPark_ {}; - std::uint32_t rvp8nvIwaveguideLength_ {0}; - std::array vRnscale_ {0.0f}; - float velDataTover_ {0.0f}; - float widthDataTover_ {0.0f}; - float dopplerRangeStart_ {0.0f}; - std::uint32_t maxElIndex_ {0}; - float seg2Lim_ {0.0f}; - float seg3Lim_ {0.0f}; - float seg4Lim_ {0.0f}; - std::uint32_t nbrElSegments_ {0}; - float hNoiseLong_ {0.0f}; - float antNoiseTemp_ {0.0f}; - float hNoiseShort_ {0.0f}; - float hNoiseTolerance_ {0.0f}; - float minHDynRange_ {0.0f}; - bool genInstalled_ {false}; - bool genExercise_ {false}; - float vNoiseTolerance_ {0.0f}; - float minVDynRange_ {0.0f}; - float zdrOffsetDgradLim_ {0.0f}; - float baselineZdrOffset_ {0.0f}; - float vNoiseLong_ {0.0f}; - float vNoiseShort_ {0.0f}; - float zdrDataTover_ {0.0f}; - float phiDataTover_ {0.0f}; - float rhoDataTover_ {0.0f}; - float staloPowerDgradLimit_ {0.0f}; - float staloPowerMaintLimit_ {0.0f}; - float minHPwrSense_ {0.0f}; - float minVPwrSense_ {0.0f}; - float hPwrSenseOffset_ {0.0f}; - float vPwrSenseOffset_ {0.0f}; - float psGainRef_ {0.0f}; - float rfPalletBroadLoss_ {0.0f}; - float amePsTolerance_ {0.0f}; - float ameMaxTemp_ {0.0f}; - float ameMinTemp_ {0.0f}; - float rcvrModMaxTemp_ {0.0f}; - float rcvrModMinTemp_ {0.0f}; - float biteModMaxTemp_ {0.0f}; - float biteModMinTemp_ {0.0f}; - std::uint32_t defaultPolarization_ {0}; - float trLimitDgradLimit_ {0.0f}; - float trLimitFailLimit_ {0.0f}; - bool rfpStepperEnabled_ {false}; - float ameCurrentTolerance_ {0.0f}; - std::uint32_t hOnlyPolarization_ {0}; - std::uint32_t vOnlyPolarization_ {0}; - float sunBias_ {0.0f}; - float aMinShelterTempWarn_ {0.0f}; - float powerMeterZero_ {0.0f}; - float txbBaseline_ {0.0f}; - float txbAlarmThresh_ {0.0f}; - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) + std::string adapFileName_; + std::string adapFormat_; + std::string adapRevision_; + std::string adapDate_; + std::string adapTime_; + float lowerPreLimit_; + float azLat_; + float upperPreLimit_; + float elLat_; + float parkaz_; + float parkel_; + std::array aFuelConv_; + float aMinShelterTemp_; + float aMaxShelterTemp_; + float aMinShelterAcTempDiff_; + float aMaxXmtrAirTemp_; + float aMaxRadTemp_; + float aMaxRadTempRise_; + float lowerDeadLimit_; + float upperDeadLimit_; + float aMinGenRoomTemp_; + float aMaxGenRoomTemp_; + float spip5VRegLim_; + float spip15VRegLim_; + bool rpgCoLocated_; + bool specFilterInstalled_; + bool tpsInstalled_; + bool rmsInstalled_; + uint32_t aHvdlTstInt_; + uint32_t aRpgLtInt_; + uint32_t aMinStabUtilPwrTime_; + uint32_t aGenAutoExerInterval_; + uint32_t aUtilPwrSwReqInterval_; + float aLowFuelLevel_; + uint32_t configChanNumber_; + uint32_t redundantChanConfig_; + std::array attenTable_; + std::map pathLosses_; + float vTsCw_; + std::array hRnscale_; + std::array atmos_; + std::array elIndex_; + uint32_t tfreqMhz_; + float baseDataTcn_; + float reflDataTover_; + float tarHDbz0Lp_; + float tarVDbz0Lp_; + uint32_t initPhiDp_; + uint32_t normInitPhiDp_; + float lxLp_; + float lxSp_; + float meteorParam_; + float antennaGain_; + float velDegradLimit_; + float wthDegradLimit_; + float hNoisetempDgradLimit_; + uint32_t hMinNoisetemp_; + float vNoisetempDgradLimit_; + uint32_t vMinNoisetemp_; + float klyDegradeLimit_; + float tsCoho_; + float hTsCw_; + float tsStalo_; + float ameHNoiseEnr_; + float xmtrPeakPwrHighLimit_; + float xmtrPeakPwrLowLimit_; + float hDbz0DeltaLimit_; + float threshold1_; + float threshold2_; + float clutSuppDgradLim_; + float range0Value_; + float xmtrPwrMtrScale_; + float vDbz0DeltaLimit_; + float tarHDbz0Sp_; + float tarVDbz0Sp_; + uint32_t deltaprf_; + uint32_t tauSp_; + uint32_t tauLp_; + uint32_t ncDeadValue_; + uint32_t tauRfSp_; + uint32_t tauRfLp_; + float seg1Lim_; + float slatsec_; + float slonsec_; + uint32_t slatdeg_; + uint32_t slatmin_; + uint32_t slondeg_; + uint32_t slonmin_; + char slatdir_; + char slondir_; + float azCorrectionFactor_; + float elCorrectionFactor_; + std::string siteName_; + AntManualSetup antManualSetup_; + float azPosSustainDrive_; + float azNegSustainDrive_; + float azNomPosDriveSlope_; + float azNomNegDriveSlope_; + float azFeedbackSlope_; + float elPosSustainDrive_; + float elNegSustainDrive_; + float elNomPosDriveSlope_; + float elNomNegDriveSlope_; + float elFeedbackSlope_; + float elFirstSlope_; + float elSecondSlope_; + float elThirdSlope_; + float elDroopPos_; + float elOffNeutralDrive_; + float azIntertia_; + float elInertia_; + uint32_t rvp8nvIwaveguideLength_; + std::array vRnscale_; + float velDataTover_; + float widthDataTover_; + float dopplerRangeStart_; + uint32_t maxElIndex_; + float seg2Lim_; + float seg3Lim_; + float seg4Lim_; + uint32_t nbrElSegments_; + float hNoiseLong_; + float antNoiseTemp_; + float hNoiseShort_; + float hNoiseTolerance_; + float minHDynRange_; + bool genInstalled_; + bool genExercise_; + float vNoiseTolerance_; + float minVDynRange_; + float zdrBiasDgradLim_; + float baselineZdrBias_; + float vNoiseLong_; + float vNoiseShort_; + float zdrDataTover_; + float phiDataTover_; + float rhoDataTover_; + float staloPowerDgradLimit_; + float staloPowerMaintLimit_; + float minHPwrSense_; + float minVPwrSense_; + float hPwrSenseOffset_; + float vPwrSenseOffset_; + float psGainRef_; + float rfPalletBroadLoss_; + float amePsTolerance_; + float ameMaxTemp_; + float ameMinTemp_; + float rcvrModMaxTemp_; + float rcvrModMinTemp_; + float biteModMaxTemp_; + float biteModMinTemp_; + uint32_t defaultPolarization_; + float trLimitDgradLimit_; + float trLimitFailLimit_; + bool rfpStepperEnabled_; + float ameCurrentTolerance_; + uint32_t hOnlyPolarization_; + uint32_t vOnlyPolarization_; + float sunBias_; + float aMinShelterTempWarn_; + float powerMeterZero_; + float txbBaseline_; + float txbAlarmThresh_; }; RdaAdaptationData::RdaAdaptationData() : - Level2Message(), p(std::make_unique()) + Level2Message(), p(std::make_unique()) { } RdaAdaptationData::~RdaAdaptationData() = default; @@ -270,7 +434,7 @@ float RdaAdaptationData::parkel() const float RdaAdaptationData::a_fuel_conv(unsigned i) const { - return p->aFuelConv_.at(i); + return p->aFuelConv_[i]; } float RdaAdaptationData::a_min_shelter_temp() const @@ -353,27 +517,27 @@ bool RdaAdaptationData::rms_installed() const return p->rmsInstalled_; } -std::uint32_t RdaAdaptationData::a_hvdl_tst_int() const +uint32_t RdaAdaptationData::a_hvdl_tst_int() const { return p->aHvdlTstInt_; } -std::uint32_t RdaAdaptationData::a_rpg_lt_int() const +uint32_t RdaAdaptationData::a_rpg_lt_int() const { return p->aRpgLtInt_; } -std::uint32_t RdaAdaptationData::a_min_stab_util_pwr_time() const +uint32_t RdaAdaptationData::a_min_stab_util_pwr_time() const { return p->aMinStabUtilPwrTime_; } -std::uint32_t RdaAdaptationData::a_gen_auto_exer_interval() const +uint32_t RdaAdaptationData::a_gen_auto_exer_interval() const { return p->aGenAutoExerInterval_; } -std::uint32_t RdaAdaptationData::a_util_pwr_sw_req_interval() const +uint32_t RdaAdaptationData::a_util_pwr_sw_req_interval() const { return p->aUtilPwrSwReqInterval_; } @@ -383,19 +547,19 @@ float RdaAdaptationData::a_low_fuel_level() const return p->aLowFuelLevel_; } -std::uint32_t RdaAdaptationData::config_chan_number() const +uint32_t RdaAdaptationData::config_chan_number() const { return p->configChanNumber_; } -std::uint32_t RdaAdaptationData::redundant_chan_config() const +uint32_t RdaAdaptationData::redundant_chan_config() const { return p->redundantChanConfig_; } float RdaAdaptationData::atten_table(unsigned i) const { - return p->attenTable_.at(i); + return p->attenTable_[i]; } float RdaAdaptationData::path_losses(unsigned i) const @@ -405,49 +569,41 @@ float RdaAdaptationData::path_losses(unsigned i) const float RdaAdaptationData::h_coupler_xmt_loss() const { - // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) return path_losses(29); } float RdaAdaptationData::h_coupler_cw_loss() const { - // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) return path_losses(48); } float RdaAdaptationData::v_coupler_xmt_loss() const { - // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) return path_losses(49); } float RdaAdaptationData::ame_ts_bias() const { - // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) return path_losses(51); } float RdaAdaptationData::v_coupler_cw_loss() const { - // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) return path_losses(53); } float RdaAdaptationData::pwr_sense_bias() const { - // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) return path_losses(56); } float RdaAdaptationData::ame_v_noise_enr() const { - // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) return path_losses(57); } float RdaAdaptationData::chan_cal_diff() const { - // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) return path_losses(70); } @@ -458,20 +614,20 @@ float RdaAdaptationData::v_ts_cw() const float RdaAdaptationData::h_rnscale(unsigned i) const { - return p->hRnscale_.at(i); + return p->hRnscale_[i]; } float RdaAdaptationData::atmos(unsigned i) const { - return p->atmos_.at(i); + return p->atmos_[i]; } float RdaAdaptationData::el_index(unsigned i) const { - return p->elIndex_.at(i); + return p->elIndex_[i]; } -std::uint32_t RdaAdaptationData::tfreq_mhz() const +uint32_t RdaAdaptationData::tfreq_mhz() const { return p->tfreqMhz_; } @@ -496,12 +652,12 @@ float RdaAdaptationData::tar_v_dbz0_lp() const return p->tarVDbz0Lp_; } -std::uint32_t RdaAdaptationData::init_phi_dp() const +uint32_t RdaAdaptationData::init_phi_dp() const { return p->initPhiDp_; } -std::uint32_t RdaAdaptationData::norm_init_phi_dp() const +uint32_t RdaAdaptationData::norm_init_phi_dp() const { return p->normInitPhiDp_; } @@ -541,7 +697,7 @@ float RdaAdaptationData::h_noisetemp_dgrad_limit() const return p->hNoisetempDgradLimit_; } -std::uint32_t RdaAdaptationData::h_min_noisetemp() const +uint32_t RdaAdaptationData::h_min_noisetemp() const { return p->hMinNoisetemp_; } @@ -551,7 +707,7 @@ float RdaAdaptationData::v_noisetemp_dgrad_limit() const return p->vNoisetempDgradLimit_; } -std::uint32_t RdaAdaptationData::v_min_noisetemp() const +uint32_t RdaAdaptationData::v_min_noisetemp() const { return p->vMinNoisetemp_; } @@ -636,32 +792,32 @@ float RdaAdaptationData::tar_v_dbz0_sp() const return p->tarVDbz0Sp_; } -std::uint32_t RdaAdaptationData::deltaprf() const +uint32_t RdaAdaptationData::deltaprf() const { return p->deltaprf_; } -std::uint32_t RdaAdaptationData::tau_sp() const +uint32_t RdaAdaptationData::tau_sp() const { return p->tauSp_; } -std::uint32_t RdaAdaptationData::tau_lp() const +uint32_t RdaAdaptationData::tau_lp() const { return p->tauLp_; } -std::uint32_t RdaAdaptationData::nc_dead_value() const +uint32_t RdaAdaptationData::nc_dead_value() const { return p->ncDeadValue_; } -std::uint32_t RdaAdaptationData::tau_rf_sp() const +uint32_t RdaAdaptationData::tau_rf_sp() const { return p->tauRfSp_; } -std::uint32_t RdaAdaptationData::tau_rf_lp() const +uint32_t RdaAdaptationData::tau_rf_lp() const { return p->tauRfLp_; } @@ -681,22 +837,22 @@ float RdaAdaptationData::slonsec() const return p->slonsec_; } -std::uint32_t RdaAdaptationData::slatdeg() const +uint32_t RdaAdaptationData::slatdeg() const { return p->slatdeg_; } -std::uint32_t RdaAdaptationData::slatmin() const +uint32_t RdaAdaptationData::slatmin() const { return p->slatmin_; } -std::uint32_t RdaAdaptationData::slondeg() const +uint32_t RdaAdaptationData::slondeg() const { return p->slondeg_; } -std::uint32_t RdaAdaptationData::slonmin() const +uint32_t RdaAdaptationData::slonmin() const { return p->slonmin_; } @@ -711,16 +867,6 @@ char RdaAdaptationData::slondir() const return p->slondir_; } -double RdaAdaptationData::dig_rcvr_clock_freq() const -{ - return p->digRcvrClockFreq_; -} - -double RdaAdaptationData::coho_freq() const -{ - return p->cohoFreq_; -} - float RdaAdaptationData::az_correction_factor() const { return p->azCorrectionFactor_; @@ -739,31 +885,31 @@ std::string RdaAdaptationData::site_name() const float RdaAdaptationData::ant_manual_setup_ielmin() const { constexpr float SCALE = 360.0f / 65536.0f; - return static_cast(p->antManualSetup_.ielmin_) * SCALE; + return p->antManualSetup_.ielmin_ * SCALE; } float RdaAdaptationData::ant_manual_setup_ielmax() const { constexpr float SCALE = 360.0f / 65536.0f; - return static_cast(p->antManualSetup_.ielmax_) * SCALE; + return p->antManualSetup_.ielmax_ * SCALE; } -std::uint32_t RdaAdaptationData::ant_manual_setup_fazvelmax() const +uint32_t RdaAdaptationData::ant_manual_setup_fazvelmax() const { return p->antManualSetup_.fazvelmax_; } -std::uint32_t RdaAdaptationData::ant_manual_setup_felvelmax() const +uint32_t RdaAdaptationData::ant_manual_setup_felvelmax() const { return p->antManualSetup_.felvelmax_; } -std::int32_t RdaAdaptationData::ant_manual_setup_ignd_hgt() const +int32_t RdaAdaptationData::ant_manual_setup_ignd_hgt() const { return p->antManualSetup_.igndHgt_; } -std::uint32_t RdaAdaptationData::ant_manual_setup_irad_hgt() const +uint32_t RdaAdaptationData::ant_manual_setup_irad_hgt() const { return p->antManualSetup_.iradHgt_; } @@ -853,39 +999,14 @@ float RdaAdaptationData::el_inertia() const return p->elInertia_; } -float RdaAdaptationData::az_stow_angle() const -{ - return p->azStowAngle_; -} - -float RdaAdaptationData::el_stow_angle() const -{ - return p->elStowAngle_; -} - -float RdaAdaptationData::az_encoder_alignment() const -{ - return p->azEncoderAlignment_; -} - -float RdaAdaptationData::el_encoder_alignment() const -{ - return p->elEncoderAlignment_; -} - -std::string RdaAdaptationData::refined_park() const -{ - return p->refinedPark_; -} - -std::uint32_t RdaAdaptationData::rvp8nv_iwaveguide_length() const +uint32_t RdaAdaptationData::rvp8nv_iwaveguide_length() const { return p->rvp8nvIwaveguideLength_; } float RdaAdaptationData::v_rnscale(unsigned i) const { - return p->vRnscale_.at(i); + return p->vRnscale_[i]; } float RdaAdaptationData::vel_data_tover() const @@ -903,7 +1024,7 @@ float RdaAdaptationData::doppler_range_start() const return p->dopplerRangeStart_; } -std::uint32_t RdaAdaptationData::max_el_index() const +uint32_t RdaAdaptationData::max_el_index() const { return p->maxElIndex_; } @@ -923,7 +1044,7 @@ float RdaAdaptationData::seg4_lim() const return p->seg4Lim_; } -std::uint32_t RdaAdaptationData::nbr_el_segments() const +uint32_t RdaAdaptationData::nbr_el_segments() const { return p->nbrElSegments_; } @@ -973,14 +1094,14 @@ float RdaAdaptationData::min_v_dyn_range() const return p->minVDynRange_; } -float RdaAdaptationData::zdr_offset_dgrad_lim() const +float RdaAdaptationData::zdr_bias_dgrad_lim() const { - return p->zdrOffsetDgradLim_; + return p->zdrBiasDgradLim_; } -float RdaAdaptationData::baseline_zdr_offset() const +float RdaAdaptationData::baseline_zdr_bias() const { - return p->baselineZdrOffset_; + return p->baselineZdrBias_; } float RdaAdaptationData::v_noise_long() const @@ -1083,7 +1204,7 @@ float RdaAdaptationData::bite_mod_min_temp() const return p->biteModMinTemp_; } -std::uint32_t RdaAdaptationData::default_polarization() const +uint32_t RdaAdaptationData::default_polarization() const { return p->defaultPolarization_; } @@ -1108,12 +1229,12 @@ float RdaAdaptationData::ame_current_tolerance() const return p->ameCurrentTolerance_; } -std::uint32_t RdaAdaptationData::h_only_polarization() const +uint32_t RdaAdaptationData::h_only_polarization() const { return p->hOnlyPolarization_; } -std::uint32_t RdaAdaptationData::v_only_polarization() const +uint32_t RdaAdaptationData::v_only_polarization() const { return p->vOnlyPolarization_; } @@ -1147,17 +1268,15 @@ bool RdaAdaptationData::Parse(std::istream& is) { logger_->trace("Parsing RDA Adaptation Data (Message Type 18)"); - bool messageValid = true; - std::size_t bytesRead = 0; + bool messageValid = true; + size_t bytesRead = 0; - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers): Readability p->adapFileName_.resize(12); p->adapFormat_.resize(4); p->adapRevision_.resize(4); p->adapDate_.resize(12); p->adapTime_.resize(12); p->siteName_.resize(4); - p->refinedPark_.resize(4); is.read(&p->adapFileName_[0], 12); // 0-11 is.read(&p->adapFormat_[0], 4); // 12-15 @@ -1173,7 +1292,7 @@ bool RdaAdaptationData::Parse(std::istream& is) is.read(reinterpret_cast(&p->parkel_), 4); // 64-67 is.read(reinterpret_cast(&p->aFuelConv_[0]), - static_cast(p->aFuelConv_.size() * 4)); // 68-111 + p->aFuelConv_.size() * 4); // 68-111 is.read(reinterpret_cast(&p->aMinShelterTemp_), 4); // 112-115 is.read(reinterpret_cast(&p->aMaxShelterTemp_), 4); // 116-119 @@ -1211,7 +1330,7 @@ bool RdaAdaptationData::Parse(std::istream& is) is.read(reinterpret_cast(&p->redundantChanConfig_), 4); // 224-227 is.read(reinterpret_cast(&p->attenTable_[0]), - static_cast(p->attenTable_.size() * 4)); // 228-643 + p->attenTable_.size() * 4); // 228-643 is.seekg(24, std::ios_base::cur); // 644-667 is.read(reinterpret_cast(&p->pathLosses_[7]), 4); // 668-671 @@ -1264,13 +1383,13 @@ bool RdaAdaptationData::Parse(std::istream& is) is.read(reinterpret_cast(&p->vTsCw_), 4); // 936-939 is.read(reinterpret_cast(&p->hRnscale_[0]), - static_cast(p->hRnscale_.size() * 4)); // 940-991 + p->hRnscale_.size() * 4); // 940-991 is.read(reinterpret_cast(&p->atmos_[0]), - static_cast(p->atmos_.size() * 4)); // 992-1043 + p->atmos_.size() * 4); // 992-1043 is.read(reinterpret_cast(&p->elIndex_[0]), - static_cast(p->elIndex_.size() * 4)); // 1044-1091 + p->elIndex_.size() * 4); // 1044-1091 is.read(reinterpret_cast(&p->tfreqMhz_), 4); // 1092-1095 is.read(reinterpret_cast(&p->baseDataTcn_), 4); // 1096-1099 @@ -1339,12 +1458,7 @@ bool RdaAdaptationData::Parse(std::istream& is) ReadChar(is, p->slatdir_); // 1316-1319 ReadChar(is, p->slondir_); // 1320-1323 - is.seekg(1176, std::ios_base::cur); // 1324-2499 - - is.read(reinterpret_cast(&p->digRcvrClockFreq_), 8); // 2500-2507 - is.read(reinterpret_cast(&p->cohoFreq_), 8); // 2508-2515 - - is.seekg(5844, std::ios_base::cur); // 2516-8359 + is.seekg(7036, std::ios_base::cur); // 1324-8359 is.read(reinterpret_cast(&p->azCorrectionFactor_), 4); // 8360-8363 is.read(reinterpret_cast(&p->elCorrectionFactor_), 4); // 8364-8367 @@ -1379,29 +1493,17 @@ bool RdaAdaptationData::Parse(std::istream& is) is.read(reinterpret_cast(&p->azIntertia_), 4); // 8456-8459 is.read(reinterpret_cast(&p->elInertia_), 4); // 8460-8463 - is.seekg(32, std::ios_base::cur); // 8464-8495 - - is.read(reinterpret_cast(&p->azStowAngle_), 4); // 8496-8499 - is.read(reinterpret_cast(&p->elStowAngle_), 4); // 8500-8503 - is.read(reinterpret_cast(&p->azEncoderAlignment_), 4); // 8504-8507 - is.read(reinterpret_cast(&p->elEncoderAlignment_), 4); // 8508-8511 - - is.seekg(176, std::ios_base::cur); // 8512-8687 - - is.read(&p->refinedPark_[0], 4); // 8688-8691 - - is.seekg(4, std::ios_base::cur); // 8692-8695 + is.seekg(232, std::ios_base::cur); // 8464-8695 is.read(reinterpret_cast(&p->rvp8nvIwaveguideLength_), 4); // 8696-8699 is.read(reinterpret_cast(&p->vRnscale_[0]), - static_cast(11 * 4)); // 8700-8743 + 11 * 4); // 8700-8743 - is.read(reinterpret_cast(&p->velDataTover_), 4); // 8744-8747 - is.read(reinterpret_cast(&p->widthDataTover_), 4); // 8748-8751 - is.read(reinterpret_cast(&p->vRnscale_[11]), - static_cast(2 * 4)); // 8752-8759 + is.read(reinterpret_cast(&p->velDataTover_), 4); // 8744-8747 + is.read(reinterpret_cast(&p->widthDataTover_), 4); // 8748-8751 + is.read(reinterpret_cast(&p->vRnscale_[11]), 2 * 4); // 8752-8759 is.seekg(4, std::ios_base::cur); // 8760-8763 @@ -1420,8 +1522,8 @@ bool RdaAdaptationData::Parse(std::istream& is) ReadBoolean(is, p->genExercise_); // 8812-8815 is.read(reinterpret_cast(&p->vNoiseTolerance_), 4); // 8816-8819 is.read(reinterpret_cast(&p->minVDynRange_), 4); // 8820-8823 - is.read(reinterpret_cast(&p->zdrOffsetDgradLim_), 4); // 8824-8827 - is.read(reinterpret_cast(&p->baselineZdrOffset_), 4); // 8828-8831 + is.read(reinterpret_cast(&p->zdrBiasDgradLim_), 4); // 8824-8827 + is.read(reinterpret_cast(&p->baselineZdrBias_), 4); // 8828-8831 is.seekg(12, std::ios_base::cur); // 8832-8843 @@ -1471,8 +1573,6 @@ bool RdaAdaptationData::Parse(std::istream& is) bytesRead += 9468; - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - p->lowerPreLimit_ = SwapFloat(p->lowerPreLimit_); p->azLat_ = SwapFloat(p->azLat_); p->upperPreLimit_ = SwapFloat(p->upperPreLimit_); @@ -1512,87 +1612,78 @@ bool RdaAdaptationData::Parse(std::istream& is) SwapArray(p->atmos_); SwapArray(p->elIndex_); - p->tfreqMhz_ = ntohl(p->tfreqMhz_); - p->baseDataTcn_ = SwapFloat(p->baseDataTcn_); - p->reflDataTover_ = SwapFloat(p->reflDataTover_); - p->tarHDbz0Lp_ = SwapFloat(p->tarHDbz0Lp_); - p->tarVDbz0Lp_ = SwapFloat(p->tarVDbz0Lp_); - p->initPhiDp_ = ntohl(p->initPhiDp_); - p->normInitPhiDp_ = ntohl(p->normInitPhiDp_); - p->lxLp_ = SwapFloat(p->lxLp_); - p->lxSp_ = SwapFloat(p->lxSp_); - p->meteorParam_ = SwapFloat(p->meteorParam_); - p->antennaGain_ = SwapFloat(p->antennaGain_); - p->velDegradLimit_ = SwapFloat(p->velDegradLimit_); - p->wthDegradLimit_ = SwapFloat(p->wthDegradLimit_); - p->hNoisetempDgradLimit_ = SwapFloat(p->hNoisetempDgradLimit_); - p->hMinNoisetemp_ = ntohl(p->hMinNoisetemp_); - p->vNoisetempDgradLimit_ = SwapFloat(p->vNoisetempDgradLimit_); - p->vMinNoisetemp_ = ntohl(p->vMinNoisetemp_); - p->klyDegradeLimit_ = SwapFloat(p->klyDegradeLimit_); - p->tsCoho_ = SwapFloat(p->tsCoho_); - p->hTsCw_ = SwapFloat(p->hTsCw_); - p->tsStalo_ = SwapFloat(p->tsStalo_); - p->ameHNoiseEnr_ = SwapFloat(p->ameHNoiseEnr_); - p->xmtrPeakPwrHighLimit_ = SwapFloat(p->xmtrPeakPwrHighLimit_); - p->xmtrPeakPwrLowLimit_ = SwapFloat(p->xmtrPeakPwrLowLimit_); - p->hDbz0DeltaLimit_ = SwapFloat(p->hDbz0DeltaLimit_); - p->threshold1_ = SwapFloat(p->threshold1_); - p->threshold2_ = SwapFloat(p->threshold2_); - p->clutSuppDgradLim_ = SwapFloat(p->clutSuppDgradLim_); - p->range0Value_ = SwapFloat(p->range0Value_); - p->xmtrPwrMtrScale_ = SwapFloat(p->xmtrPwrMtrScale_); - p->vDbz0DeltaLimit_ = SwapFloat(p->vDbz0DeltaLimit_); - p->tarHDbz0Sp_ = SwapFloat(p->tarHDbz0Sp_); - p->tarVDbz0Sp_ = SwapFloat(p->tarVDbz0Sp_); - p->deltaprf_ = ntohl(p->deltaprf_); - p->tauSp_ = ntohl(p->tauSp_); - p->tauLp_ = ntohl(p->tauLp_); - p->ncDeadValue_ = ntohl(p->ncDeadValue_); - p->tauRfSp_ = ntohl(p->tauRfSp_); - p->tauRfLp_ = ntohl(p->tauRfLp_); - p->seg1Lim_ = SwapFloat(p->seg1Lim_); - p->slatsec_ = SwapFloat(p->slatsec_); - p->slonsec_ = SwapFloat(p->slonsec_); - p->slatdeg_ = ntohl(p->slatdeg_); - p->slatmin_ = ntohl(p->slatmin_); - p->slondeg_ = ntohl(p->slondeg_); - p->slonmin_ = ntohl(p->slonmin_); - p->digRcvrClockFreq_ = SwapDouble(p->digRcvrClockFreq_); - p->cohoFreq_ = SwapDouble(p->cohoFreq_); - p->azCorrectionFactor_ = SwapFloat(p->azCorrectionFactor_); - p->elCorrectionFactor_ = SwapFloat(p->elCorrectionFactor_); - p->antManualSetup_.ielmin_ = - static_cast(ntohl(p->antManualSetup_.ielmin_)); - p->antManualSetup_.ielmax_ = - static_cast(ntohl(p->antManualSetup_.ielmax_)); + p->tfreqMhz_ = ntohl(p->tfreqMhz_); + p->baseDataTcn_ = SwapFloat(p->baseDataTcn_); + p->reflDataTover_ = SwapFloat(p->reflDataTover_); + p->tarHDbz0Lp_ = SwapFloat(p->tarHDbz0Lp_); + p->tarVDbz0Lp_ = SwapFloat(p->tarVDbz0Lp_); + p->initPhiDp_ = ntohl(p->initPhiDp_); + p->normInitPhiDp_ = ntohl(p->normInitPhiDp_); + p->lxLp_ = SwapFloat(p->lxLp_); + p->lxSp_ = SwapFloat(p->lxSp_); + p->meteorParam_ = SwapFloat(p->meteorParam_); + p->antennaGain_ = SwapFloat(p->antennaGain_); + p->velDegradLimit_ = SwapFloat(p->velDegradLimit_); + p->wthDegradLimit_ = SwapFloat(p->wthDegradLimit_); + p->hNoisetempDgradLimit_ = SwapFloat(p->hNoisetempDgradLimit_); + p->hMinNoisetemp_ = ntohl(p->hMinNoisetemp_); + p->vNoisetempDgradLimit_ = SwapFloat(p->vNoisetempDgradLimit_); + p->vMinNoisetemp_ = ntohl(p->vMinNoisetemp_); + p->klyDegradeLimit_ = SwapFloat(p->klyDegradeLimit_); + p->tsCoho_ = SwapFloat(p->tsCoho_); + p->hTsCw_ = SwapFloat(p->hTsCw_); + p->tsStalo_ = SwapFloat(p->tsStalo_); + p->ameHNoiseEnr_ = SwapFloat(p->ameHNoiseEnr_); + p->xmtrPeakPwrHighLimit_ = SwapFloat(p->xmtrPeakPwrHighLimit_); + p->xmtrPeakPwrLowLimit_ = SwapFloat(p->xmtrPeakPwrLowLimit_); + p->hDbz0DeltaLimit_ = SwapFloat(p->hDbz0DeltaLimit_); + p->threshold1_ = SwapFloat(p->threshold1_); + p->threshold2_ = SwapFloat(p->threshold2_); + p->clutSuppDgradLim_ = SwapFloat(p->clutSuppDgradLim_); + p->range0Value_ = SwapFloat(p->range0Value_); + p->xmtrPwrMtrScale_ = SwapFloat(p->xmtrPwrMtrScale_); + p->vDbz0DeltaLimit_ = SwapFloat(p->vDbz0DeltaLimit_); + p->tarHDbz0Sp_ = SwapFloat(p->tarHDbz0Sp_); + p->tarVDbz0Sp_ = SwapFloat(p->tarVDbz0Sp_); + p->deltaprf_ = ntohl(p->deltaprf_); + p->tauSp_ = ntohl(p->tauSp_); + p->tauLp_ = ntohl(p->tauLp_); + p->ncDeadValue_ = ntohl(p->ncDeadValue_); + p->tauRfSp_ = ntohl(p->tauRfSp_); + p->tauRfLp_ = ntohl(p->tauRfLp_); + p->seg1Lim_ = SwapFloat(p->seg1Lim_); + p->slatsec_ = SwapFloat(p->slatsec_); + p->slonsec_ = SwapFloat(p->slonsec_); + p->slatdeg_ = ntohl(p->slatdeg_); + p->slatmin_ = ntohl(p->slatmin_); + p->slondeg_ = ntohl(p->slondeg_); + p->slonmin_ = ntohl(p->slonmin_); + p->azCorrectionFactor_ = SwapFloat(p->azCorrectionFactor_); + p->elCorrectionFactor_ = SwapFloat(p->elCorrectionFactor_); + p->antManualSetup_.ielmin_ = ntohl(p->antManualSetup_.ielmin_); + p->antManualSetup_.ielmax_ = ntohl(p->antManualSetup_.ielmax_); p->antManualSetup_.fazvelmax_ = ntohl(p->antManualSetup_.fazvelmax_); p->antManualSetup_.felvelmax_ = ntohl(p->antManualSetup_.felvelmax_); - p->antManualSetup_.igndHgt_ = - static_cast(ntohl(p->antManualSetup_.igndHgt_)); - p->antManualSetup_.iradHgt_ = ntohl(p->antManualSetup_.iradHgt_); - p->azPosSustainDrive_ = SwapFloat(p->azPosSustainDrive_); - p->azNegSustainDrive_ = SwapFloat(p->azNegSustainDrive_); - p->azNomPosDriveSlope_ = SwapFloat(p->azNomPosDriveSlope_); - p->azNomNegDriveSlope_ = SwapFloat(p->azNomNegDriveSlope_); - p->azFeedbackSlope_ = SwapFloat(p->azFeedbackSlope_); - p->elPosSustainDrive_ = SwapFloat(p->elPosSustainDrive_); - p->elNegSustainDrive_ = SwapFloat(p->elNegSustainDrive_); - p->elNomPosDriveSlope_ = SwapFloat(p->elNomPosDriveSlope_); - p->elNomNegDriveSlope_ = SwapFloat(p->elNomNegDriveSlope_); - p->elFeedbackSlope_ = SwapFloat(p->elFeedbackSlope_); - p->elFirstSlope_ = SwapFloat(p->elFirstSlope_); - p->elSecondSlope_ = SwapFloat(p->elSecondSlope_); - p->elThirdSlope_ = SwapFloat(p->elThirdSlope_); - p->elDroopPos_ = SwapFloat(p->elDroopPos_); - p->elOffNeutralDrive_ = SwapFloat(p->elOffNeutralDrive_); - p->azIntertia_ = SwapFloat(p->azIntertia_); - p->elInertia_ = SwapFloat(p->elInertia_); - p->azStowAngle_ = SwapFloat(p->azStowAngle_); - p->elStowAngle_ = SwapFloat(p->elStowAngle_); - p->azEncoderAlignment_ = SwapFloat(p->azEncoderAlignment_); - p->elEncoderAlignment_ = SwapFloat(p->elEncoderAlignment_); - p->rvp8nvIwaveguideLength_ = ntohl(p->rvp8nvIwaveguideLength_); + p->antManualSetup_.igndHgt_ = ntohl(p->antManualSetup_.igndHgt_); + p->antManualSetup_.iradHgt_ = ntohl(p->antManualSetup_.iradHgt_); + p->azPosSustainDrive_ = SwapFloat(p->azPosSustainDrive_); + p->azNegSustainDrive_ = SwapFloat(p->azNegSustainDrive_); + p->azNomPosDriveSlope_ = SwapFloat(p->azNomPosDriveSlope_); + p->azNomNegDriveSlope_ = SwapFloat(p->azNomNegDriveSlope_); + p->azFeedbackSlope_ = SwapFloat(p->azFeedbackSlope_); + p->elPosSustainDrive_ = SwapFloat(p->elPosSustainDrive_); + p->elNegSustainDrive_ = SwapFloat(p->elNegSustainDrive_); + p->elNomPosDriveSlope_ = SwapFloat(p->elNomPosDriveSlope_); + p->elNomNegDriveSlope_ = SwapFloat(p->elNomNegDriveSlope_); + p->elFeedbackSlope_ = SwapFloat(p->elFeedbackSlope_); + p->elFirstSlope_ = SwapFloat(p->elFirstSlope_); + p->elSecondSlope_ = SwapFloat(p->elSecondSlope_); + p->elThirdSlope_ = SwapFloat(p->elThirdSlope_); + p->elDroopPos_ = SwapFloat(p->elDroopPos_); + p->elOffNeutralDrive_ = SwapFloat(p->elOffNeutralDrive_); + p->azIntertia_ = SwapFloat(p->azIntertia_); + p->elInertia_ = SwapFloat(p->elInertia_); + p->rvp8nvIwaveguideLength_ = ntohl(p->rvp8nvIwaveguideLength_); SwapArray(p->vRnscale_); @@ -1611,8 +1702,8 @@ bool RdaAdaptationData::Parse(std::istream& is) p->minHDynRange_ = SwapFloat(p->minHDynRange_); p->vNoiseTolerance_ = SwapFloat(p->vNoiseTolerance_); p->minVDynRange_ = SwapFloat(p->minVDynRange_); - p->zdrOffsetDgradLim_ = SwapFloat(p->zdrOffsetDgradLim_); - p->baselineZdrOffset_ = SwapFloat(p->baselineZdrOffset_); + p->zdrBiasDgradLim_ = SwapFloat(p->zdrBiasDgradLim_); + p->baselineZdrBias_ = SwapFloat(p->baselineZdrBias_); p->vNoiseLong_ = SwapFloat(p->vNoiseLong_); p->vNoiseShort_ = SwapFloat(p->vNoiseShort_); p->zdrDataTover_ = SwapFloat(p->zdrDataTover_); @@ -1668,4 +1759,6 @@ RdaAdaptationData::Create(Level2MessageHeader&& header, std::istream& is) return message; } -} // namespace scwx::wsr88d::rda +} // namespace rda +} // namespace wsr88d +} // namespace scwx diff --git a/wxdata/source/scwx/wsr88d/rda/rda_prf_data.cpp b/wxdata/source/scwx/wsr88d/rda/rda_prf_data.cpp deleted file mode 100644 index 147714c7..00000000 --- a/wxdata/source/scwx/wsr88d/rda/rda_prf_data.cpp +++ /dev/null @@ -1,120 +0,0 @@ -#include -#include - -namespace scwx::wsr88d::rda -{ - -static const std::string logPrefix_ = "scwx::wsr88d::rda::rda_prf_data"; -static const auto logger_ = scwx::util::Logger::Create(logPrefix_); - -struct RdaPrfWaveformData -{ - std::uint16_t waveformType_ {0}; - std::uint16_t prfCount_ {0}; - std::vector prfValues_ {}; -}; - -class RdaPrfData::Impl -{ -public: - explicit Impl() = default; - ~Impl() = default; - - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; - - std::uint16_t numberOfWaveforms_ {0}; - std::vector waveformData_ {}; -}; - -RdaPrfData::RdaPrfData() : p(std::make_unique()) {} -RdaPrfData::~RdaPrfData() = default; - -RdaPrfData::RdaPrfData(RdaPrfData&&) noexcept = default; -RdaPrfData& RdaPrfData::operator=(RdaPrfData&&) noexcept = default; - -bool RdaPrfData::Parse(std::istream& is) -{ - logger_->trace("Parsing RDA PRF Data (Message Type 32)"); - - bool messageValid = true; - std::size_t bytesRead = 0; - - const std::streampos isBegin = is.tellg(); - - is.read(reinterpret_cast(&p->numberOfWaveforms_), 2); // 1 - is.seekg(2, std::ios_base::cur); // 2 - - bytesRead += 4; - - p->numberOfWaveforms_ = ntohs(p->numberOfWaveforms_); - - // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers): Readability - if (p->numberOfWaveforms_ < 1 || p->numberOfWaveforms_ > 5) - { - logger_->warn("Invalid number of waveforms: {}", p->numberOfWaveforms_); - p->numberOfWaveforms_ = 0; - messageValid = false; - } - - p->waveformData_.resize(p->numberOfWaveforms_); - - for (std::uint16_t i = 0; i < p->numberOfWaveforms_; ++i) - { - auto& w = p->waveformData_[i]; - - is.read(reinterpret_cast(&w.waveformType_), 2); // P1 - is.read(reinterpret_cast(&w.prfCount_), 2); // P2 - - w.waveformType_ = ntohs(w.waveformType_); - w.prfCount_ = ntohs(w.prfCount_); - - bytesRead += 4; - - // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers): Readability - if (w.prfCount_ > 255) - { - logger_->warn("Invalid PRF count: {} (waveform {})", w.prfCount_, i); - w.prfCount_ = 0; - messageValid = false; - break; - } - - w.prfValues_.resize(w.prfCount_); - - for (std::uint16_t j = 0; j < w.prfCount_; ++j) - { - is.read(reinterpret_cast(&w.prfValues_[j]), 4); - } - - bytesRead += static_cast(w.prfCount_) * 4; - - SwapVector(w.prfValues_); - } - - is.seekg(isBegin, std::ios_base::beg); - if (!ValidateMessage(is, bytesRead)) - { - messageValid = false; - } - - return messageValid; -} - -std::shared_ptr RdaPrfData::Create(Level2MessageHeader&& header, - std::istream& is) -{ - std::shared_ptr message = std::make_shared(); - message->set_header(std::move(header)); - - if (!message->Parse(is)) - { - message.reset(); - } - - return message; -} - -} // namespace scwx::wsr88d::rda diff --git a/wxdata/source/scwx/wsr88d/rda/rda_status_data.cpp b/wxdata/source/scwx/wsr88d/rda/rda_status_data.cpp index 81ff4463..ced8ff59 100644 --- a/wxdata/source/scwx/wsr88d/rda/rda_status_data.cpp +++ b/wxdata/source/scwx/wsr88d/rda/rda_status_data.cpp @@ -1,214 +1,232 @@ #include #include -namespace scwx::wsr88d::rda +namespace scwx +{ +namespace wsr88d +{ +namespace rda { static const std::string logPrefix_ = "scwx::wsr88d::rda::rda_status_data"; static const auto logger_ = util::Logger::Create(logPrefix_); -class RdaStatusData::Impl +class RdaStatusDataImpl { public: - explicit Impl() = default; - ~Impl() = default; + explicit RdaStatusDataImpl() : + rdaStatus_ {0}, + operabilityStatus_ {0}, + controlStatus_ {0}, + auxiliaryPowerGeneratorState_ {0}, + averageTransmitterPower_ {0}, + horizontalReflectivityCalibrationCorrection_ {0}, + dataTransmissionEnabled_ {0}, + volumeCoveragePatternNumber_ {0}, + rdaControlAuthorization_ {0}, + rdaBuildNumber_ {0}, + operationalMode_ {0}, + superResolutionStatus_ {0}, + clutterMitigationDecisionStatus_ {0}, + avsetEbcRdaLogDataStatus_ {0}, + rdaAlarmSummary_ {0}, + commandAcknowledgement_ {0}, + channelControlStatus_ {0}, + spotBlankingStatus_ {0}, + bypassMapGenerationDate_ {0}, + bypassMapGenerationTime_ {0}, + clutterFilterMapGenerationDate_ {0}, + clutterFilterMapGenerationTime_ {0}, + verticalReflectivityCalibrationCorrection_ {0}, + transitionPowerSourceStatus_ {0}, + rmsControlStatus_ {0}, + performanceCheckStatus_ {0}, + alarmCodes_ {0}, + signalProcessingOptions_ {0}, + statusVersion_ {0} {}; + ~RdaStatusDataImpl() = default; - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; - - std::uint16_t rdaStatus_ {0}; - std::uint16_t operabilityStatus_ {0}; - std::uint16_t controlStatus_ {0}; - std::uint16_t auxiliaryPowerGeneratorState_ {0}; - std::uint16_t averageTransmitterPower_ {0}; - std::int16_t horizontalReflectivityCalibrationCorrection_ {0}; - std::uint16_t dataTransmissionEnabled_ {0}; - std::uint16_t volumeCoveragePatternNumber_ {0}; - std::uint16_t rdaControlAuthorization_ {0}; - std::uint16_t rdaBuildNumber_ {0}; - std::uint16_t operationalMode_ {0}; - std::uint16_t superResolutionStatus_ {0}; - std::uint16_t clutterMitigationDecisionStatus_ {0}; - std::uint16_t rdaScanAndDataFlags_ {0}; - std::uint16_t rdaAlarmSummary_ {0}; - std::uint16_t commandAcknowledgement_ {0}; - std::uint16_t channelControlStatus_ {0}; - std::uint16_t spotBlankingStatus_ {0}; - std::uint16_t bypassMapGenerationDate_ {0}; - std::uint16_t bypassMapGenerationTime_ {0}; - std::uint16_t clutterFilterMapGenerationDate_ {0}; - std::uint16_t clutterFilterMapGenerationTime_ {0}; - std::int16_t verticalReflectivityCalibrationCorrection_ {0}; - std::uint16_t transitionPowerSourceStatus_ {0}; - std::uint16_t rmsControlStatus_ {0}; - std::uint16_t performanceCheckStatus_ {0}; - - // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) - std::array alarmCodes_ {0}; - - std::uint16_t signalProcessingOptions_ {0}; - std::uint16_t downloadedPatternNumber_ {0}; - std::uint16_t statusVersion_ {0}; + uint16_t rdaStatus_; + uint16_t operabilityStatus_; + uint16_t controlStatus_; + uint16_t auxiliaryPowerGeneratorState_; + uint16_t averageTransmitterPower_; + int16_t horizontalReflectivityCalibrationCorrection_; + uint16_t dataTransmissionEnabled_; + uint16_t volumeCoveragePatternNumber_; + uint16_t rdaControlAuthorization_; + uint16_t rdaBuildNumber_; + uint16_t operationalMode_; + uint16_t superResolutionStatus_; + uint16_t clutterMitigationDecisionStatus_; + uint16_t avsetEbcRdaLogDataStatus_; + uint16_t rdaAlarmSummary_; + uint16_t commandAcknowledgement_; + uint16_t channelControlStatus_; + uint16_t spotBlankingStatus_; + uint16_t bypassMapGenerationDate_; + uint16_t bypassMapGenerationTime_; + uint16_t clutterFilterMapGenerationDate_; + uint16_t clutterFilterMapGenerationTime_; + int16_t verticalReflectivityCalibrationCorrection_; + uint16_t transitionPowerSourceStatus_; + uint16_t rmsControlStatus_; + uint16_t performanceCheckStatus_; + std::array alarmCodes_; + uint16_t signalProcessingOptions_; + uint16_t statusVersion_; }; -RdaStatusData::RdaStatusData() : Level2Message(), p(std::make_unique()) {} +RdaStatusData::RdaStatusData() : + Level2Message(), p(std::make_unique()) +{ +} RdaStatusData::~RdaStatusData() = default; -RdaStatusData::RdaStatusData(RdaStatusData&&) noexcept = default; +RdaStatusData::RdaStatusData(RdaStatusData&&) noexcept = default; RdaStatusData& RdaStatusData::operator=(RdaStatusData&&) noexcept = default; -std::uint16_t RdaStatusData::rda_status() const +uint16_t RdaStatusData::rda_status() const { return p->rdaStatus_; } -std::uint16_t RdaStatusData::operability_status() const +uint16_t RdaStatusData::operability_status() const { return p->operabilityStatus_; } -std::uint16_t RdaStatusData::control_status() const +uint16_t RdaStatusData::control_status() const { return p->controlStatus_; } -std::uint16_t RdaStatusData::auxiliary_power_generator_state() const +uint16_t RdaStatusData::auxiliary_power_generator_state() const { return p->auxiliaryPowerGeneratorState_; } -std::uint16_t RdaStatusData::average_transmitter_power() const +uint16_t RdaStatusData::average_transmitter_power() const { return p->averageTransmitterPower_; } float RdaStatusData::horizontal_reflectivity_calibration_correction() const { - constexpr float kScale_ = 0.01f; - return static_cast(p->horizontalReflectivityCalibrationCorrection_) * - kScale_; + return p->horizontalReflectivityCalibrationCorrection_ * 0.01f; } -std::uint16_t RdaStatusData::data_transmission_enabled() const +uint16_t RdaStatusData::data_transmission_enabled() const { return p->dataTransmissionEnabled_; } -std::uint16_t RdaStatusData::volume_coverage_pattern_number() const +uint16_t RdaStatusData::volume_coverage_pattern_number() const { return p->volumeCoveragePatternNumber_; } -std::uint16_t RdaStatusData::rda_control_authorization() const +uint16_t RdaStatusData::rda_control_authorization() const { return p->rdaControlAuthorization_; } -std::uint16_t RdaStatusData::rda_build_number() const +uint16_t RdaStatusData::rda_build_number() const { return p->rdaBuildNumber_; } -std::uint16_t RdaStatusData::operational_mode() const +uint16_t RdaStatusData::operational_mode() const { return p->operationalMode_; } -std::uint16_t RdaStatusData::super_resolution_status() const +uint16_t RdaStatusData::super_resolution_status() const { return p->superResolutionStatus_; } -std::uint16_t RdaStatusData::clutter_mitigation_decision_status() const +uint16_t RdaStatusData::clutter_mitigation_decision_status() const { return p->clutterMitigationDecisionStatus_; } -std::uint16_t RdaStatusData::rda_scan_and_data_flags() const +uint16_t RdaStatusData::avset_ebc_rda_log_data_status() const { - return p->rdaScanAndDataFlags_; + return p->avsetEbcRdaLogDataStatus_; } -std::uint16_t RdaStatusData::rda_alarm_summary() const +uint16_t RdaStatusData::rda_alarm_summary() const { return p->rdaAlarmSummary_; } -std::uint16_t RdaStatusData::command_acknowledgement() const +uint16_t RdaStatusData::command_acknowledgement() const { return p->commandAcknowledgement_; } -std::uint16_t RdaStatusData::channel_control_status() const +uint16_t RdaStatusData::channel_control_status() const { return p->channelControlStatus_; } -std::uint16_t RdaStatusData::spot_blanking_status() const +uint16_t RdaStatusData::spot_blanking_status() const { return p->spotBlankingStatus_; } -std::uint16_t RdaStatusData::bypass_map_generation_date() const +uint16_t RdaStatusData::bypass_map_generation_date() const { return p->bypassMapGenerationDate_; } -std::uint16_t RdaStatusData::bypass_map_generation_time() const +uint16_t RdaStatusData::bypass_map_generation_time() const { return p->bypassMapGenerationTime_; } -std::uint16_t RdaStatusData::clutter_filter_map_generation_date() const +uint16_t RdaStatusData::clutter_filter_map_generation_date() const { return p->clutterFilterMapGenerationDate_; } -std::uint16_t RdaStatusData::clutter_filter_map_generation_time() const +uint16_t RdaStatusData::clutter_filter_map_generation_time() const { return p->clutterFilterMapGenerationTime_; } float RdaStatusData::vertical_reflectivity_calibration_correction() const { - constexpr float kScale_ = 0.01f; - return static_cast(p->verticalReflectivityCalibrationCorrection_) * - kScale_; + return p->verticalReflectivityCalibrationCorrection_ * 0.01f; } -std::uint16_t RdaStatusData::transition_power_source_status() const +uint16_t RdaStatusData::transition_power_source_status() const { return p->transitionPowerSourceStatus_; } -std::uint16_t RdaStatusData::rms_control_status() const +uint16_t RdaStatusData::rms_control_status() const { return p->rmsControlStatus_; } -std::uint16_t RdaStatusData::performance_check_status() const +uint16_t RdaStatusData::performance_check_status() const { return p->performanceCheckStatus_; } -std::uint16_t RdaStatusData::alarm_codes(unsigned i) const +uint16_t RdaStatusData::alarm_codes(unsigned i) const { - return p->alarmCodes_.at(i); + return p->alarmCodes_[i]; } -std::uint16_t RdaStatusData::signal_processing_options() const +uint16_t RdaStatusData::signal_processing_options() const { return p->signalProcessingOptions_; } -std::uint16_t RdaStatusData::downloaded_pattern_number() const -{ - return p->downloadedPatternNumber_; -} - -std::uint16_t RdaStatusData::status_version() const +uint16_t RdaStatusData::status_version() const { return p->statusVersion_; } @@ -220,7 +238,6 @@ bool RdaStatusData::Parse(std::istream& is) bool messageValid = true; size_t bytesRead = 0; - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers): Readability is.read(reinterpret_cast(&p->rdaStatus_), 2); // 1 is.read(reinterpret_cast(&p->operabilityStatus_), 2); // 2 is.read(reinterpret_cast(&p->controlStatus_), 2); // 3 @@ -236,14 +253,14 @@ bool RdaStatusData::Parse(std::istream& is) is.read(reinterpret_cast(&p->operationalMode_), 2); // 11 is.read(reinterpret_cast(&p->superResolutionStatus_), 2); // 12 is.read(reinterpret_cast(&p->clutterMitigationDecisionStatus_), - 2); // 13 - is.read(reinterpret_cast(&p->rdaScanAndDataFlags_), 2); // 14 - is.read(reinterpret_cast(&p->rdaAlarmSummary_), 2); // 15 - is.read(reinterpret_cast(&p->commandAcknowledgement_), 2); // 16 - is.read(reinterpret_cast(&p->channelControlStatus_), 2); // 17 - is.read(reinterpret_cast(&p->spotBlankingStatus_), 2); // 18 - is.read(reinterpret_cast(&p->bypassMapGenerationDate_), 2); // 19 - is.read(reinterpret_cast(&p->bypassMapGenerationTime_), 2); // 20 + 2); // 13 + is.read(reinterpret_cast(&p->avsetEbcRdaLogDataStatus_), 2); // 14 + is.read(reinterpret_cast(&p->rdaAlarmSummary_), 2); // 15 + is.read(reinterpret_cast(&p->commandAcknowledgement_), 2); // 16 + is.read(reinterpret_cast(&p->channelControlStatus_), 2); // 17 + is.read(reinterpret_cast(&p->spotBlankingStatus_), 2); // 18 + is.read(reinterpret_cast(&p->bypassMapGenerationDate_), 2); // 19 + is.read(reinterpret_cast(&p->bypassMapGenerationTime_), 2); // 20 is.read(reinterpret_cast(&p->clutterFilterMapGenerationDate_), 2); // 21 is.read(reinterpret_cast(&p->clutterFilterMapGenerationTime_), @@ -255,7 +272,7 @@ bool RdaStatusData::Parse(std::istream& is) is.read(reinterpret_cast(&p->rmsControlStatus_), 2); // 25 is.read(reinterpret_cast(&p->performanceCheckStatus_), 2); // 26 is.read(reinterpret_cast(&p->alarmCodes_), - static_cast(p->alarmCodes_.size() * 2)); // 27-40 + p->alarmCodes_.size() * 2); // 27-40 bytesRead += 80; p->rdaStatus_ = ntohs(p->rdaStatus_); @@ -263,8 +280,8 @@ bool RdaStatusData::Parse(std::istream& is) p->controlStatus_ = ntohs(p->controlStatus_); p->auxiliaryPowerGeneratorState_ = ntohs(p->auxiliaryPowerGeneratorState_); p->averageTransmitterPower_ = ntohs(p->averageTransmitterPower_); - p->horizontalReflectivityCalibrationCorrection_ = static_cast( - ntohs(p->horizontalReflectivityCalibrationCorrection_)); + p->horizontalReflectivityCalibrationCorrection_ = + ntohs(p->horizontalReflectivityCalibrationCorrection_); p->dataTransmissionEnabled_ = ntohs(p->dataTransmissionEnabled_); p->volumeCoveragePatternNumber_ = ntohs(p->volumeCoveragePatternNumber_); p->rdaControlAuthorization_ = ntohs(p->rdaControlAuthorization_); @@ -273,40 +290,36 @@ bool RdaStatusData::Parse(std::istream& is) p->superResolutionStatus_ = ntohs(p->superResolutionStatus_); p->clutterMitigationDecisionStatus_ = ntohs(p->clutterMitigationDecisionStatus_); - p->rdaScanAndDataFlags_ = ntohs(p->rdaScanAndDataFlags_); - p->rdaAlarmSummary_ = ntohs(p->rdaAlarmSummary_); - p->commandAcknowledgement_ = ntohs(p->commandAcknowledgement_); - p->channelControlStatus_ = ntohs(p->channelControlStatus_); - p->spotBlankingStatus_ = ntohs(p->spotBlankingStatus_); - p->bypassMapGenerationDate_ = ntohs(p->bypassMapGenerationDate_); - p->bypassMapGenerationTime_ = ntohs(p->bypassMapGenerationTime_); + p->avsetEbcRdaLogDataStatus_ = ntohs(p->avsetEbcRdaLogDataStatus_); + p->rdaAlarmSummary_ = ntohs(p->rdaAlarmSummary_); + p->commandAcknowledgement_ = ntohs(p->commandAcknowledgement_); + p->channelControlStatus_ = ntohs(p->channelControlStatus_); + p->spotBlankingStatus_ = ntohs(p->spotBlankingStatus_); + p->bypassMapGenerationDate_ = ntohs(p->bypassMapGenerationDate_); + p->bypassMapGenerationTime_ = ntohs(p->bypassMapGenerationTime_); p->clutterFilterMapGenerationDate_ = ntohs(p->clutterFilterMapGenerationDate_); p->clutterFilterMapGenerationTime_ = ntohs(p->clutterFilterMapGenerationTime_); - p->verticalReflectivityCalibrationCorrection_ = static_cast( - ntohs(p->verticalReflectivityCalibrationCorrection_)); + p->verticalReflectivityCalibrationCorrection_ = + ntohs(p->verticalReflectivityCalibrationCorrection_); p->transitionPowerSourceStatus_ = ntohs(p->transitionPowerSourceStatus_); p->rmsControlStatus_ = ntohs(p->rmsControlStatus_); p->performanceCheckStatus_ = ntohs(p->performanceCheckStatus_); SwapArray(p->alarmCodes_); // RDA Build 18.0 increased the size of the message from 80 to 120 bytes - if (static_cast(header().message_size()) * 2 > - Level2MessageHeader::SIZE + 80) + if (header().message_size() * 2 > Level2MessageHeader::SIZE + 80) { is.read(reinterpret_cast(&p->signalProcessingOptions_), 2); // 41 - is.seekg(34, std::ios_base::cur); // 42-58 - is.read(reinterpret_cast(&p->downloadedPatternNumber_), 2); // 59 - is.read(reinterpret_cast(&p->statusVersion_), 2); // 60 + is.seekg(36, std::ios_base::cur); // 42-59 + is.read(reinterpret_cast(&p->statusVersion_), 2); // 60 bytesRead += 40; p->signalProcessingOptions_ = ntohs(p->signalProcessingOptions_); p->statusVersion_ = ntohs(p->statusVersion_); } - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - if (!ValidateMessage(is, bytesRead)) { messageValid = false; @@ -329,4 +342,6 @@ RdaStatusData::Create(Level2MessageHeader&& header, std::istream& is) return message; } -} // namespace scwx::wsr88d::rda +} // namespace rda +} // namespace wsr88d +} // namespace scwx diff --git a/wxdata/source/scwx/wsr88d/rda/volume_coverage_pattern_data.cpp b/wxdata/source/scwx/wsr88d/rda/volume_coverage_pattern_data.cpp index b2159648..d2f3dec2 100644 --- a/wxdata/source/scwx/wsr88d/rda/volume_coverage_pattern_data.cpp +++ b/wxdata/source/scwx/wsr88d/rda/volume_coverage_pattern_data.cpp @@ -220,19 +220,7 @@ uint16_t VolumeCoveragePatternData::number_of_base_tilts() const double VolumeCoveragePatternData::elevation_angle(uint16_t e) const { - - double elevationAngleConverted = - p->elevationCuts_[e].elevationAngle_ * ANGLE_DATA_SCALE; - // Any elevation above 90 degrees should be interpreted as a - // negative angle - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) - if (elevationAngleConverted > 90) - { - elevationAngleConverted -= 360; - } - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - - return elevationAngleConverted; + return p->elevationCuts_[e].elevationAngle_ * ANGLE_DATA_SCALE; } uint16_t VolumeCoveragePatternData::elevation_angle_raw(uint16_t e) const diff --git a/wxdata/source/scwx/wsr88d/rpg/digital_raster_data_array_packet.cpp b/wxdata/source/scwx/wsr88d/rpg/digital_raster_data_array_packet.cpp deleted file mode 100644 index 2e0ef662..00000000 --- a/wxdata/source/scwx/wsr88d/rpg/digital_raster_data_array_packet.cpp +++ /dev/null @@ -1,225 +0,0 @@ -#include -#include - -#include -#include - -namespace scwx::wsr88d::rpg -{ - -static const std::string logPrefix_ = - "scwx::wsr88d::rpg::digital_raster_data_array_packet"; -static const auto logger_ = util::Logger::Create(logPrefix_); - -class DigitalRasterDataArrayPacket::Impl -{ -public: - struct Row - { - std::uint16_t numberOfBytes_ {0}; - std::vector level_ {}; - }; - - explicit Impl() = default; - ~Impl() = default; - - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; - - std::uint16_t packetCode_ {0}; - std::uint16_t iCoordinateStart_ {0}; - std::uint16_t jCoordinateStart_ {0}; - std::uint16_t iScaleFactor_ {0}; - std::uint16_t jScaleFactor_ {0}; - std::uint16_t numberOfCells_ {0}; - std::uint16_t numberOfRows_ {0}; - std::uint16_t numberOfBytesInRow_ {0}; - - // Repeat for each row - std::vector row_ {}; - - std::size_t dataSize_ {0}; -}; - -DigitalRasterDataArrayPacket::DigitalRasterDataArrayPacket() : - p(std::make_unique()) -{ -} -DigitalRasterDataArrayPacket::~DigitalRasterDataArrayPacket() = default; - -DigitalRasterDataArrayPacket::DigitalRasterDataArrayPacket( - DigitalRasterDataArrayPacket&&) noexcept = default; -DigitalRasterDataArrayPacket& DigitalRasterDataArrayPacket::operator=( - DigitalRasterDataArrayPacket&&) noexcept = default; - -std::uint16_t DigitalRasterDataArrayPacket::packet_code() const -{ - return p->packetCode_; -} - -std::uint16_t DigitalRasterDataArrayPacket::i_coordinate_start() const -{ - return p->iCoordinateStart_; -} - -std::uint16_t DigitalRasterDataArrayPacket::j_coordinate_start() const -{ - return p->jCoordinateStart_; -} - -std::uint16_t DigitalRasterDataArrayPacket::i_scale_factor() const -{ - return p->iScaleFactor_; -} - -std::uint16_t DigitalRasterDataArrayPacket::j_scale_factor() const -{ - return p->jScaleFactor_; -} - -std::uint16_t DigitalRasterDataArrayPacket::number_of_cells() const -{ - return p->numberOfCells_; -} - -std::uint16_t DigitalRasterDataArrayPacket::number_of_rows() const -{ - return p->numberOfRows_; -} - -std::uint16_t -DigitalRasterDataArrayPacket::number_of_bytes_in_row(std::uint16_t r) const -{ - return p->row_[r].numberOfBytes_; -} - -const std::vector& -DigitalRasterDataArrayPacket::level(std::uint16_t r) const -{ - return p->row_[r].level_; -} - -size_t DigitalRasterDataArrayPacket::data_size() const -{ - return p->dataSize_; -} - -bool DigitalRasterDataArrayPacket::Parse(std::istream& is) -{ - bool blockValid = true; - std::size_t bytesRead = 0; - - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) - - is.read(reinterpret_cast(&p->packetCode_), 2); - is.read(reinterpret_cast(&p->iCoordinateStart_), 2); - is.read(reinterpret_cast(&p->jCoordinateStart_), 2); - is.read(reinterpret_cast(&p->iScaleFactor_), 2); - is.read(reinterpret_cast(&p->jScaleFactor_), 2); - is.read(reinterpret_cast(&p->numberOfCells_), 2); - is.read(reinterpret_cast(&p->numberOfRows_), 2); - bytesRead += 14; - - p->packetCode_ = ntohs(p->packetCode_); - p->iCoordinateStart_ = ntohs(p->iCoordinateStart_); - p->jCoordinateStart_ = ntohs(p->jCoordinateStart_); - p->iScaleFactor_ = ntohs(p->iScaleFactor_); - p->jScaleFactor_ = ntohs(p->jScaleFactor_); - p->numberOfCells_ = ntohs(p->numberOfCells_); - p->numberOfRows_ = ntohs(p->numberOfRows_); - - if (is.eof()) - { - logger_->debug("Reached end of file"); - blockValid = false; - } - else - { - if (p->packetCode_ != 33) - { - logger_->warn("Invalid packet code: {}", p->packetCode_); - blockValid = false; - } - if (p->numberOfCells_ < 1 || p->numberOfCells_ > 1840) - { - logger_->warn("Invalid number of cells: {}", p->numberOfCells_); - blockValid = false; - } - if (p->numberOfRows_ < 1 || p->numberOfRows_ > 464) - { - logger_->warn("Invalid number of rows: {}", p->numberOfRows_); - blockValid = false; - } - } - - if (blockValid) - { - p->row_.resize(p->numberOfRows_); - - for (std::uint16_t r = 0; r < p->numberOfRows_; r++) - { - auto& row = p->row_[r]; - - is.read(reinterpret_cast(&row.numberOfBytes_), 2); - bytesRead += 2; - - row.numberOfBytes_ = ntohs(row.numberOfBytes_); - - if (row.numberOfBytes_ < 1 || row.numberOfBytes_ > 1840) - { - logger_->warn( - "Invalid number of bytes: {} (Row {})", row.numberOfBytes_, r); - blockValid = false; - break; - } - else if (row.numberOfBytes_ < p->numberOfCells_) - { - logger_->warn("Number of bytes < number of cells: {} < {} (Row {})", - row.numberOfBytes_, - p->numberOfCells_, - r); - blockValid = false; - break; - } - - // Read raster bins - const std::size_t dataSize = p->numberOfCells_; - row.level_.resize(dataSize); - is.read(reinterpret_cast(row.level_.data()), - static_cast(dataSize)); - - is.seekg(static_cast(row.numberOfBytes_ - dataSize), - std::ios_base::cur); - bytesRead += row.numberOfBytes_; - } - } - - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - - p->dataSize_ = bytesRead; - - if (!ValidateMessage(is, bytesRead)) - { - blockValid = false; - } - - return blockValid; -} - -std::shared_ptr -DigitalRasterDataArrayPacket::Create(std::istream& is) -{ - std::shared_ptr packet = - std::make_shared(); - - if (!packet->Parse(is)) - { - packet.reset(); - } - - return packet; -} - -} // namespace scwx::wsr88d::rpg diff --git a/wxdata/source/scwx/wsr88d/rpg/level3_message_factory.cpp b/wxdata/source/scwx/wsr88d/rpg/level3_message_factory.cpp index 0d9d1725..25675470 100644 --- a/wxdata/source/scwx/wsr88d/rpg/level3_message_factory.cpp +++ b/wxdata/source/scwx/wsr88d/rpg/level3_message_factory.cpp @@ -9,17 +9,22 @@ #include #include +#include -namespace scwx::wsr88d::rpg +namespace scwx +{ +namespace wsr88d +{ +namespace rpg { static const std::string logPrefix_ = "scwx::wsr88d::rpg::level3_message_factory"; static const auto logger_ = util::Logger::Create(logPrefix_); -using CreateLevel3MessageFunction = - std::function(Level3MessageHeader&&, - std::istream&)>; +typedef std::function(Level3MessageHeader&&, + std::istream&)> + CreateLevel3MessageFunction; static const std::unordered_map // create_ {{2, GeneralStatusMessage::Create}, @@ -114,14 +119,9 @@ static const std::unordered_map // {182, GraphicProductMessage::Create}, {184, GraphicProductMessage::Create}, {186, GraphicProductMessage::Create}, - {189, GraphicProductMessage::Create}, - {190, GraphicProductMessage::Create}, - {191, GraphicProductMessage::Create}, - {192, GraphicProductMessage::Create}, {193, GraphicProductMessage::Create}, {195, GraphicProductMessage::Create}, {196, GraphicProductMessage::Create}, - {197, GraphicProductMessage::Create}, {202, GraphicProductMessage::Create}}; std::shared_ptr Level3MessageFactory::Create(std::istream& is) @@ -149,12 +149,13 @@ std::shared_ptr Level3MessageFactory::Create(std::istream& is) else if (headerValid) { // Seek to the end of the current message - is.seekg(static_cast(header.length_of_message()) - - static_cast(Level3MessageHeader::SIZE), + is.seekg(header.length_of_message() - Level3MessageHeader::SIZE, std::ios_base::cur); } return message; } -} // namespace scwx::wsr88d::rpg +} // namespace rpg +} // namespace wsr88d +} // namespace scwx diff --git a/wxdata/source/scwx/wsr88d/rpg/packet_factory.cpp b/wxdata/source/scwx/wsr88d/rpg/packet_factory.cpp index 5458119c..e3cd034b 100644 --- a/wxdata/source/scwx/wsr88d/rpg/packet_factory.cpp +++ b/wxdata/source/scwx/wsr88d/rpg/packet_factory.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include #include @@ -28,14 +27,18 @@ #include -namespace scwx::wsr88d::rpg +namespace scwx +{ +namespace wsr88d +{ +namespace rpg { static const std::string logPrefix_ = "scwx::wsr88d::rpg::packet_factory"; static const auto logger_ = util::Logger::Create(logPrefix_); -using CreateMessageFunction = - std::function(std::istream&)>; +typedef std::function(std::istream&)> + CreateMessageFunction; static const std::unordered_map create_ { {1, TextAndSpecialSymbolPacket::Create}, @@ -66,7 +69,6 @@ static const std::unordered_map create_ { {26, PointGraphicSymbolPacket::Create}, {28, GenericDataPacket::Create}, {29, GenericDataPacket::Create}, - {33, DigitalRasterDataArrayPacket::Create}, {0x0802, SetColorLevelPacket::Create}, {0x0E03, LinkedContourVectorPacket::Create}, {0x3501, UnlinkedContourVectorPacket::Create}, @@ -79,7 +81,7 @@ std::shared_ptr PacketFactory::Create(std::istream& is) std::shared_ptr packet = nullptr; bool packetValid = true; - std::uint16_t packetCode {0}; + uint16_t packetCode; is.read(reinterpret_cast(&packetCode), 2); packetCode = ntohs(packetCode); @@ -106,4 +108,6 @@ std::shared_ptr PacketFactory::Create(std::istream& is) return packet; } -} // namespace scwx::wsr88d::rpg +} // namespace rpg +} // namespace wsr88d +} // namespace scwx diff --git a/wxdata/source/scwx/wsr88d/rpg/product_description_block.cpp b/wxdata/source/scwx/wsr88d/rpg/product_description_block.cpp index 016128f3..1a0effaa 100644 --- a/wxdata/source/scwx/wsr88d/rpg/product_description_block.cpp +++ b/wxdata/source/scwx/wsr88d/rpg/product_description_block.cpp @@ -1,4 +1,3 @@ -#include #include #include #include @@ -22,13 +21,28 @@ static const std::string logPrefix_ = static const auto logger_ = util::Logger::Create(logPrefix_); static const std::set compressedProducts_ = { - 32, 94, 99, 113, 134, 135, 138, 149, 152, 153, 154, 155, 159, - 161, 163, 165, 167, 168, 170, 172, 173, 174, 175, 176, 177, 178, - 179, 180, 182, 186, 189, 190, 191, 192, 193, 195, 197, 202}; + 32, 94, 99, 134, 135, 138, 149, 152, 153, 154, 155, + 159, 161, 163, 165, 167, 168, 170, 172, 173, 174, 175, + 176, 177, 178, 179, 180, 182, 186, 193, 195, 202}; -static const std::set uncodedDataLevelProducts_ = { - 32, 34, 81, 93, 94, 99, 134, 135, 138, 153, 154, 155, - 159, 161, 163, 177, 189, 190, 191, 192, 193, 195, 197}; +static const std::set uncodedDataLevelProducts_ = {32, + 34, + 81, + 93, + 94, + 99, + 134, + 135, + 138, + 153, + 154, + 155, + 159, + 161, + 163, + 177, + 193, + 195}; static const std::unordered_map rangeMap_ { {19, 230}, {20, 460}, {27, 230}, {30, 230}, {31, 230}, {32, 230}, @@ -43,8 +57,7 @@ static const std::unordered_map rangeMap_ { {163, 300}, {165, 300}, {166, 230}, {167, 300}, {168, 300}, {169, 230}, {170, 230}, {171, 230}, {172, 230}, {173, 230}, {174, 230}, {175, 230}, {176, 230}, {177, 230}, {178, 300}, {179, 300}, {180, 89}, {181, 89}, - {182, 89}, {184, 89}, {186, 417}, {193, 460}, {195, 460}, {196, 50}, - {197, 230}}; + {182, 89}, {184, 89}, {186, 412}, {193, 460}, {195, 460}, {196, 50}}; static const std::unordered_map xResolutionMap_ { {19, 1000}, {20, 2000}, {27, 1000}, {30, 1000}, {31, 2000}, {32, 1000}, @@ -58,7 +71,7 @@ static const std::unordered_map xResolutionMap_ { {166, 250}, {167, 250}, {168, 250}, {169, 2000}, {170, 250}, {171, 2000}, {172, 250}, {173, 250}, {174, 250}, {175, 250}, {176, 250}, {177, 250}, {178, 1000}, {179, 1000}, {180, 150}, {181, 150}, {182, 150}, {184, 150}, - {186, 300}, {193, 250}, {195, 1000}, {197, 250}}; + {186, 300}, {193, 250}, {195, 1000}}; static const std::unordered_map yResolutionMap_ {{37, 1000}, {38, 4000}, @@ -73,11 +86,7 @@ static const std::unordered_map yResolutionMap_ {{37, 1000}, {90, 4000}, {97, 1000}, {98, 4000}, - {166, 250}, - {189, 20}, - {190, 20}, - {191, 20}, - {192, 20}}; + {166, 250}}; // GR uses different internal units than defined units in level 3 products static const std::unordered_map grScale_ { @@ -96,57 +105,73 @@ static const std::unordered_map grScale_ { {174, ((units::inches {1} * 0.01f) / units::millimeters {1})}, {175, ((units::inches {1} * 0.01f) / units::millimeters {1})}}; -class ProductDescriptionBlock::Impl +class ProductDescriptionBlockImpl { public: - explicit Impl() = default; - ~Impl() = default; + explicit ProductDescriptionBlockImpl() : + blockDivider_ {0}, + latitudeOfRadar_ {0}, + longitudeOfRadar_ {0}, + heightOfRadar_ {0}, + productCode_ {0}, + operationalMode_ {0}, + volumeCoveragePattern_ {0}, + sequenceNumber_ {0}, + volumeScanNumber_ {0}, + volumeScanDate_ {0}, + volumeScanStartTime_ {0}, + generationDateOfProduct_ {0}, + generationTimeOfProduct_ {0}, + elevationNumber_ {0}, + version_ {0}, + spotBlank_ {0}, + offsetToSymbology_ {0}, + offsetToGraphic_ {0}, + offsetToTabular_ {0}, + parameters_ {0}, + halfwords_ {0} + { + } + ~ProductDescriptionBlockImpl() = default; - Impl(const Impl&) = delete; - Impl& operator=(const Impl&) = delete; - Impl(const Impl&&) = delete; - Impl& operator=(const Impl&&) = delete; + uint16_t halfword(size_t i); - std::uint16_t halfword(std::size_t i); - - std::int16_t blockDivider_ {0}; - std::int32_t latitudeOfRadar_ {0}; - std::int32_t longitudeOfRadar_ {0}; - std::int16_t heightOfRadar_ {0}; - std::int16_t productCode_ {0}; - std::uint16_t operationalMode_ {0}; - std::uint16_t volumeCoveragePattern_ {0}; - std::int16_t sequenceNumber_ {0}; - std::uint16_t volumeScanNumber_ {0}; - std::uint16_t volumeScanDate_ {0}; - std::uint32_t volumeScanStartTime_ {0}; - std::uint16_t generationDateOfProduct_ {0}; - std::uint32_t generationTimeOfProduct_ {0}; + int16_t blockDivider_; + int32_t latitudeOfRadar_; + int32_t longitudeOfRadar_; + int16_t heightOfRadar_; + int16_t productCode_; + uint16_t operationalMode_; + uint16_t volumeCoveragePattern_; + int16_t sequenceNumber_; + uint16_t volumeScanNumber_; + uint16_t volumeScanDate_; + uint32_t volumeScanStartTime_; + uint16_t generationDateOfProduct_; + uint32_t generationTimeOfProduct_; // 27-28: Product dependent parameters 1 and 2 (Table V) - std::uint16_t elevationNumber_ {0}; + uint16_t elevationNumber_; // 30: Product dependent parameter 3 (Table V) // 31-46: Product dependent (Note 1) // 47-53: Product dependent parameters 4-10 (Table V, Note 3) - std::uint8_t version_ {0}; - std::uint8_t spotBlank_ {0}; - std::uint32_t offsetToSymbology_ {0}; - std::uint32_t offsetToGraphic_ {0}; - std::uint32_t offsetToTabular_ {0}; + uint8_t version_; + uint8_t spotBlank_; + uint32_t offsetToSymbology_; + uint32_t offsetToGraphic_; + uint32_t offsetToTabular_; - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) - std::array parameters_ {0}; - std::array halfwords_ {0}; - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) + std::array parameters_; + std::array halfwords_; }; -std::uint16_t ProductDescriptionBlock::Impl::halfword(std::size_t i) +uint16_t ProductDescriptionBlockImpl::halfword(size_t i) { // Halfwords start at halfword 31 - // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) - return halfwords_.at(i - 31); + return halfwords_[i - 31]; } -ProductDescriptionBlock::ProductDescriptionBlock() : p(std::make_unique()) +ProductDescriptionBlock::ProductDescriptionBlock() : + p(std::make_unique()) { } ProductDescriptionBlock::~ProductDescriptionBlock() = default; @@ -156,104 +181,102 @@ ProductDescriptionBlock::ProductDescriptionBlock( ProductDescriptionBlock& ProductDescriptionBlock::operator=( ProductDescriptionBlock&&) noexcept = default; -std::int16_t ProductDescriptionBlock::block_divider() const +int16_t ProductDescriptionBlock::block_divider() const { return p->blockDivider_; } float ProductDescriptionBlock::latitude_of_radar() const { - static constexpr float kScale = 0.001f; - return static_cast(p->latitudeOfRadar_) * kScale; + return p->latitudeOfRadar_ * 0.001f; } float ProductDescriptionBlock::longitude_of_radar() const { - static constexpr float kScale = 0.001f; - return static_cast(p->longitudeOfRadar_) * kScale; + return p->longitudeOfRadar_ * 0.001f; } -std::int16_t ProductDescriptionBlock::height_of_radar() const +int16_t ProductDescriptionBlock::height_of_radar() const { return p->heightOfRadar_; } -std::int16_t ProductDescriptionBlock::product_code() const +int16_t ProductDescriptionBlock::product_code() const { return p->productCode_; } -std::uint16_t ProductDescriptionBlock::operational_mode() const +uint16_t ProductDescriptionBlock::operational_mode() const { return p->operationalMode_; } -std::uint16_t ProductDescriptionBlock::volume_coverage_pattern() const +uint16_t ProductDescriptionBlock::volume_coverage_pattern() const { return p->volumeCoveragePattern_; } -std::int16_t ProductDescriptionBlock::sequence_number() const +int16_t ProductDescriptionBlock::sequence_number() const { return p->sequenceNumber_; } -std::uint16_t ProductDescriptionBlock::volume_scan_number() const +uint16_t ProductDescriptionBlock::volume_scan_number() const { return p->volumeScanNumber_; } -std::uint16_t ProductDescriptionBlock::volume_scan_date() const +uint16_t ProductDescriptionBlock::volume_scan_date() const { return p->volumeScanDate_; } -std::uint32_t ProductDescriptionBlock::volume_scan_start_time() const +uint32_t ProductDescriptionBlock::volume_scan_start_time() const { return p->volumeScanStartTime_; } -std::uint16_t ProductDescriptionBlock::generation_date_of_product() const +uint16_t ProductDescriptionBlock::generation_date_of_product() const { return p->generationDateOfProduct_; } -std::uint32_t ProductDescriptionBlock::generation_time_of_product() const +uint32_t ProductDescriptionBlock::generation_time_of_product() const { return p->generationTimeOfProduct_; } -std::uint16_t ProductDescriptionBlock::elevation_number() const +uint16_t ProductDescriptionBlock::elevation_number() const { return p->elevationNumber_; } -std::uint16_t ProductDescriptionBlock::data_level_threshold(std::size_t i) const +uint16_t ProductDescriptionBlock::data_level_threshold(size_t i) const { - return p->halfwords_.at(i); + return p->halfwords_[i]; } -std::uint8_t ProductDescriptionBlock::version() const +uint8_t ProductDescriptionBlock::version() const { return p->version_; } -std::uint8_t ProductDescriptionBlock::spot_blank() const +uint8_t ProductDescriptionBlock::spot_blank() const { return p->spotBlank_; } -std::uint32_t ProductDescriptionBlock::offset_to_symbology() const +uint32_t ProductDescriptionBlock::offset_to_symbology() const { return p->offsetToSymbology_; } -std::uint32_t ProductDescriptionBlock::offset_to_graphic() const +uint32_t ProductDescriptionBlock::offset_to_graphic() const { return p->offsetToGraphic_; } -std::uint32_t ProductDescriptionBlock::offset_to_tabular() const +uint32_t ProductDescriptionBlock::offset_to_tabular() const { return p->offsetToTabular_; } @@ -263,14 +286,14 @@ float ProductDescriptionBlock::range() const return range_raw(); } -std::uint16_t ProductDescriptionBlock::range_raw() const +uint16_t ProductDescriptionBlock::range_raw() const { - std::uint16_t range = 0; + uint16_t range = 0; auto it = rangeMap_.find(p->productCode_); if (it != rangeMap_.cend()) { - range = static_cast(it->second); + range = static_cast(it->second); } return range; @@ -278,18 +301,17 @@ std::uint16_t ProductDescriptionBlock::range_raw() const float ProductDescriptionBlock::x_resolution() const { - static constexpr float kScale = 0.001f; - return static_cast(x_resolution_raw()) * kScale; + return x_resolution_raw() * 0.001f; } -std::uint16_t ProductDescriptionBlock::x_resolution_raw() const +uint16_t ProductDescriptionBlock::x_resolution_raw() const { - std::uint16_t xResolution = 0; + uint16_t xResolution = 0; auto it = xResolutionMap_.find(p->productCode_); if (it != xResolutionMap_.cend()) { - xResolution = static_cast(it->second); + xResolution = static_cast(it->second); } return xResolution; @@ -297,28 +319,25 @@ std::uint16_t ProductDescriptionBlock::x_resolution_raw() const float ProductDescriptionBlock::y_resolution() const { - static constexpr float kScale = 0.001f; - return static_cast(y_resolution_raw()) * kScale; + return y_resolution_raw() * 0.001f; } -std::uint16_t ProductDescriptionBlock::y_resolution_raw() const +uint16_t ProductDescriptionBlock::y_resolution_raw() const { - std::uint16_t yResolution = 0; + uint16_t yResolution = 0; auto it = yResolutionMap_.find(p->productCode_); if (it != yResolutionMap_.cend()) { - yResolution = static_cast(it->second); + yResolution = static_cast(it->second); } return yResolution; } -std::uint16_t ProductDescriptionBlock::threshold() const +uint16_t ProductDescriptionBlock::threshold() const { - std::uint16_t threshold = 1; - - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) + uint16_t threshold = 1; switch (p->productCode_) { @@ -375,8 +394,6 @@ std::uint16_t ProductDescriptionBlock::threshold() const break; } - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - return threshold; } @@ -384,8 +401,6 @@ float ProductDescriptionBlock::offset() const { float offset = 0.0f; - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) - switch (p->productCode_) { case 32: @@ -401,8 +416,7 @@ float ProductDescriptionBlock::offset() const case 186: case 193: case 195: - offset = - static_cast(static_cast(p->halfword(31))) * 0.1f; + offset = static_cast(p->halfword(31)) * 0.1f; break; case 134: @@ -410,7 +424,7 @@ float ProductDescriptionBlock::offset() const break; case 135: - offset = static_cast(p->halfword(33)); + offset = static_cast(p->halfword(33)); break; case 159: @@ -431,8 +445,6 @@ float ProductDescriptionBlock::offset() const break; } - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - return offset; } @@ -440,8 +452,6 @@ float ProductDescriptionBlock::scale() const { float scale = 1.0f; - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) - switch (p->productCode_) { case 32: @@ -456,11 +466,11 @@ float ProductDescriptionBlock::scale() const case 186: case 193: case 195: - scale = static_cast(p->halfword(32)) * 0.1f; + scale = p->halfword(32) * 0.1f; break; case 81: - scale = static_cast(p->halfword(32)) * 0.001f; + scale = p->halfword(32) * 0.001f; break; case 134: @@ -472,7 +482,7 @@ float ProductDescriptionBlock::scale() const break; case 138: - scale = static_cast(p->halfword(32)) * 0.01f; + scale = p->halfword(32) * 0.01f; break; case 159: @@ -493,16 +503,12 @@ float ProductDescriptionBlock::scale() const break; } - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - return scale; } -std::uint16_t ProductDescriptionBlock::number_of_levels() const +uint16_t ProductDescriptionBlock::number_of_levels() const { - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) - - std::uint16_t numberOfLevels = 16u; + uint16_t numberOfLevels = 16u; switch (p->productCode_) { @@ -574,10 +580,6 @@ std::uint16_t ProductDescriptionBlock::number_of_levels() const break; case 134: - case 189: - case 190: - case 191: - case 192: numberOfLevels = 256; break; @@ -617,8 +619,6 @@ std::uint16_t ProductDescriptionBlock::number_of_levels() const break; } - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - return numberOfLevels; } @@ -626,8 +626,6 @@ std::uint16_t ProductDescriptionBlock::log_start() const { std::uint16_t logStart = std::numeric_limits::max(); - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) - switch (p->productCode_) { case 134: @@ -638,8 +636,6 @@ std::uint16_t ProductDescriptionBlock::log_start() const break; } - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - return logStart; } @@ -647,8 +643,6 @@ float ProductDescriptionBlock::log_offset() const { float logOffset = 0.0f; - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) - switch (p->productCode_) { case 134: @@ -659,8 +653,6 @@ float ProductDescriptionBlock::log_offset() const break; } - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - return logOffset; } @@ -668,8 +660,6 @@ float ProductDescriptionBlock::log_scale() const { float logScale = 1.0f; - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) - switch (p->productCode_) { case 134: @@ -680,8 +670,6 @@ float ProductDescriptionBlock::log_scale() const break; } - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - return logScale; } @@ -700,8 +688,6 @@ float ProductDescriptionBlock::gr_scale() const std::uint8_t ProductDescriptionBlock::data_mask() const { - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) - std::uint8_t dataMask = 0xff; switch (p->productCode_) @@ -714,8 +700,6 @@ std::uint8_t ProductDescriptionBlock::data_mask() const break; } - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - return dataMask; } @@ -723,8 +707,6 @@ std::uint8_t ProductDescriptionBlock::topped_mask() const { std::uint8_t toppedMask = 0x00; - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) - switch (p->productCode_) { case 135: @@ -735,8 +717,6 @@ std::uint8_t ProductDescriptionBlock::topped_mask() const break; } - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - return toppedMask; } @@ -744,34 +724,23 @@ units::angle::degrees ProductDescriptionBlock::elevation() const { double elevation = 0.0; - if (has_elevation()) + if (p->elevationNumber_ > 0) { - // Elevation is given in tenths of a degree - // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) - elevation = static_cast(p->parameters_[2]) * 0.1; + elevation = p->parameters_[2] * 0.1; } return units::angle::degrees {elevation}; } -bool ProductDescriptionBlock::has_elevation() const -{ - return p->elevationNumber_ > 0; -} - bool ProductDescriptionBlock::IsCompressionEnabled() const { bool isCompressed = false; - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) - if (compressedProducts_.contains(p->productCode_)) { isCompressed = (p->parameters_[7] == 1u); } - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - return isCompressed; } @@ -780,7 +749,7 @@ bool ProductDescriptionBlock::IsDataLevelCoded() const return !uncodedDataLevelProducts_.contains(p->productCode_); } -std::size_t ProductDescriptionBlock::data_size() const +size_t ProductDescriptionBlock::data_size() const { return SIZE; } @@ -791,8 +760,6 @@ bool ProductDescriptionBlock::Parse(std::istream& is) const std::streampos blockStart = is.tellg(); - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) - is.read(reinterpret_cast(&p->blockDivider_), 2); // 10 is.read(reinterpret_cast(&p->latitudeOfRadar_), 4); // 11-12 is.read(reinterpret_cast(&p->longitudeOfRadar_), 4); // 13-14 @@ -806,31 +773,27 @@ bool ProductDescriptionBlock::Parse(std::istream& is) is.read(reinterpret_cast(&p->volumeScanStartTime_), 4); // 22-23 is.read(reinterpret_cast(&p->generationDateOfProduct_), 2); // 24 is.read(reinterpret_cast(&p->generationTimeOfProduct_), 4); // 25-26 - is.read(reinterpret_cast(&p->parameters_[0]), - static_cast(2 * 2)); // 27-28 - is.read(reinterpret_cast(&p->elevationNumber_), 2); // 29 - is.read(reinterpret_cast(&p->parameters_[2]), 2); // 30 - is.read(reinterpret_cast(&p->halfwords_[0]), - static_cast(16 * 2)); // 31-46 - is.read(reinterpret_cast(&p->parameters_[3]), - static_cast(7 * 2)); // 47-53 - is.read(reinterpret_cast(&p->version_), 1); // 54 - is.read(reinterpret_cast(&p->spotBlank_), 1); // 54 - is.read(reinterpret_cast(&p->offsetToSymbology_), 4); // 55-56 - is.read(reinterpret_cast(&p->offsetToGraphic_), 4); // 57-58 - is.read(reinterpret_cast(&p->offsetToTabular_), 4); // 59-60 + is.read(reinterpret_cast(&p->parameters_[0]), 2 * 2); // 27-28 + is.read(reinterpret_cast(&p->elevationNumber_), 2); // 29 + is.read(reinterpret_cast(&p->parameters_[2]), 2); // 30 + is.read(reinterpret_cast(&p->halfwords_[0]), 16 * 2); // 31-46 + is.read(reinterpret_cast(&p->parameters_[3]), 7 * 2); // 47-53 + is.read(reinterpret_cast(&p->version_), 1); // 54 + is.read(reinterpret_cast(&p->spotBlank_), 1); // 54 + is.read(reinterpret_cast(&p->offsetToSymbology_), 4); // 55-56 + is.read(reinterpret_cast(&p->offsetToGraphic_), 4); // 57-58 + is.read(reinterpret_cast(&p->offsetToTabular_), 4); // 59-60 - p->blockDivider_ = static_cast(ntohs(p->blockDivider_)); - p->latitudeOfRadar_ = static_cast(ntohl(p->latitudeOfRadar_)); - p->longitudeOfRadar_ = - static_cast(ntohl(p->longitudeOfRadar_)); - p->heightOfRadar_ = static_cast(ntohs(p->heightOfRadar_)); - p->productCode_ = static_cast(ntohs(p->productCode_)); - p->operationalMode_ = ntohs(p->operationalMode_); - p->volumeCoveragePattern_ = ntohs(p->volumeCoveragePattern_); - p->sequenceNumber_ = static_cast(ntohs(p->sequenceNumber_)); - p->volumeScanNumber_ = ntohs(p->volumeScanNumber_); - p->volumeScanDate_ = ntohs(p->volumeScanDate_); + p->blockDivider_ = ntohs(p->blockDivider_); + p->latitudeOfRadar_ = ntohl(p->latitudeOfRadar_); + p->longitudeOfRadar_ = ntohl(p->longitudeOfRadar_); + p->heightOfRadar_ = ntohs(p->heightOfRadar_); + p->productCode_ = ntohs(p->productCode_); + p->operationalMode_ = ntohs(p->operationalMode_); + p->volumeCoveragePattern_ = ntohs(p->volumeCoveragePattern_); + p->sequenceNumber_ = ntohs(p->sequenceNumber_); + p->volumeScanNumber_ = ntohs(p->volumeScanNumber_); + p->volumeScanDate_ = ntohs(p->volumeScanDate_); p->volumeScanStartTime_ = ntohl(p->volumeScanStartTime_); p->generationDateOfProduct_ = ntohs(p->generationDateOfProduct_); p->generationTimeOfProduct_ = ntohl(p->generationTimeOfProduct_); @@ -863,8 +826,6 @@ bool ProductDescriptionBlock::Parse(std::istream& is) } } - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - if (blockValid) { logger_->trace("Product code: {}", p->productCode_); @@ -882,8 +843,6 @@ bool ProductDescriptionBlock::Parse(std::istream& is) std::optional ProductDescriptionBlock::data_level_code(std::uint8_t level) const { - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) - switch (p->productCode_) { case 32: @@ -898,10 +857,6 @@ ProductDescriptionBlock::data_level_code(std::uint8_t level) const case 163: case 167: case 168: - case 189: - case 190: - case 191: - case 192: case 195: switch (level) { @@ -1073,11 +1028,11 @@ ProductDescriptionBlock::data_level_code(std::uint8_t level) const if (number_of_levels() <= 16 && level < 16 && !uncodedDataLevelProducts_.contains(p->productCode_)) { - const std::uint16_t th = data_level_threshold(level); + uint16_t th = data_level_threshold(level); if ((th & 0x8000u)) { // If bit 0 is one, then the LSB is coded - const std::uint16_t lsb = th & 0x00ffu; + uint16_t lsb = th & 0x00ffu; switch (lsb) { @@ -1121,8 +1076,6 @@ ProductDescriptionBlock::data_level_code(std::uint8_t level) const } } - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - return std::nullopt; } @@ -1141,8 +1094,6 @@ ProductDescriptionBlock::data_value(std::uint8_t level) const std::optional f = std::nullopt; - // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) - // Different products use different scale/offset formulas if (numberOfLevels > 16 || uncodedDataLevelProducts_.contains(p->productCode_)) @@ -1160,27 +1111,26 @@ ProductDescriptionBlock::data_value(std::uint8_t level) const case 174: case 175: case 176: - f = (static_cast(level) - dataOffset) / dataScale; + f = (level - dataOffset) / dataScale; break; case 134: if (level < log_start()) { - f = (static_cast(level) - dataOffset) / dataScale; + f = (level - dataOffset) / dataScale; } else { - f = expf((static_cast(level) - log_offset()) / log_scale()); + f = expf((level - log_offset()) / log_scale()); } break; case 135: level = level & data_mask(); - f = static_cast(level) / dataScale - dataOffset; - break; + [[fallthrough]]; default: - f = static_cast(level) * dataScale + dataOffset; + f = level * dataScale + dataOffset; break; } } @@ -1220,8 +1170,6 @@ ProductDescriptionBlock::data_value(std::uint8_t level) const } } - // NOLINTEND(cppcoreguidelines-avoid-magic-numbers) - // Scale for GR compatibility if (f.has_value()) { diff --git a/wxdata/source/scwx/wsr88d/rpg/raster_data_packet.cpp b/wxdata/source/scwx/wsr88d/rpg/raster_data_packet.cpp index 03b00220..c0bf5557 100644 --- a/wxdata/source/scwx/wsr88d/rpg/raster_data_packet.cpp +++ b/wxdata/source/scwx/wsr88d/rpg/raster_data_packet.cpp @@ -2,7 +2,6 @@ #include #include -#include #include namespace scwx diff --git a/wxdata/wxdata.cmake b/wxdata/wxdata.cmake index bc489cb3..47ada181 100644 --- a/wxdata/wxdata.cmake +++ b/wxdata/wxdata.cmake @@ -1,20 +1,14 @@ -cmake_minimum_required(VERSION 3.24) +cmake_minimum_required(VERSION 3.20) project(scwx-data) -include(CheckCXXSymbolExists) - find_package(Boost) find_package(cpr) find_package(LibXml2) -find_package(OpenSSL) -find_package(range-v3) find_package(re2) find_package(spdlog) -check_cxx_symbol_exists(_LIBCPP_VERSION version LIBCPP) - -if (LINUX) +if (NOT MSVC) find_package(TBB) endif() @@ -60,39 +54,27 @@ set(HDR_GR include/scwx/gr/color.hpp set(SRC_GR source/scwx/gr/color.cpp source/scwx/gr/placefile.cpp) set(HDR_NETWORK include/scwx/network/cpr.hpp - include/scwx/network/dir_list.hpp - include/scwx/network/ntp_client.hpp) + include/scwx/network/dir_list.hpp) set(SRC_NETWORK source/scwx/network/cpr.cpp - source/scwx/network/dir_list.cpp - source/scwx/network/ntp_client.cpp) + source/scwx/network/dir_list.cpp) set(HDR_PROVIDER include/scwx/provider/aws_level2_data_provider.hpp - include/scwx/provider/aws_level2_chunks_data_provider.hpp include/scwx/provider/aws_level3_data_provider.hpp include/scwx/provider/aws_nexrad_data_provider.hpp - include/scwx/provider/iem_api_provider.hpp - include/scwx/provider/iem_api_provider.ipp include/scwx/provider/nexrad_data_provider.hpp include/scwx/provider/nexrad_data_provider_factory.hpp include/scwx/provider/warnings_provider.hpp) set(SRC_PROVIDER source/scwx/provider/aws_level2_data_provider.cpp - source/scwx/provider/aws_level2_chunks_data_provider.cpp source/scwx/provider/aws_level3_data_provider.cpp source/scwx/provider/aws_nexrad_data_provider.cpp - source/scwx/provider/iem_api_provider.cpp source/scwx/provider/nexrad_data_provider.cpp source/scwx/provider/nexrad_data_provider_factory.cpp source/scwx/provider/warnings_provider.cpp) -set(HDR_TYPES include/scwx/types/iem_types.hpp - include/scwx/types/ntp_types.hpp) -set(SRC_TYPES source/scwx/types/iem_types.cpp - source/scwx/types/ntp_types.cpp) set(HDR_UTIL include/scwx/util/digest.hpp include/scwx/util/enum.hpp include/scwx/util/environment.hpp include/scwx/util/float.hpp include/scwx/util/hash.hpp include/scwx/util/iterator.hpp - include/scwx/util/json.hpp include/scwx/util/logger.hpp include/scwx/util/map.hpp include/scwx/util/rangebuf.hpp @@ -105,7 +87,6 @@ set(SRC_UTIL source/scwx/util/digest.cpp source/scwx/util/environment.cpp source/scwx/util/float.cpp source/scwx/util/hash.cpp - source/scwx/util/json.cpp source/scwx/util/logger.cpp source/scwx/util/rangebuf.cpp source/scwx/util/streams.cpp @@ -133,7 +114,6 @@ set(HDR_WSR88D_RDA include/scwx/wsr88d/rda/clutter_filter_bypass_map.hpp include/scwx/wsr88d/rda/level2_message_header.hpp include/scwx/wsr88d/rda/performance_maintenance_data.hpp include/scwx/wsr88d/rda/rda_adaptation_data.hpp - include/scwx/wsr88d/rda/rda_prf_data.hpp include/scwx/wsr88d/rda/rda_status_data.hpp include/scwx/wsr88d/rda/rda_types.hpp include/scwx/wsr88d/rda/volume_coverage_pattern_data.hpp) @@ -147,7 +127,6 @@ set(SRC_WSR88D_RDA source/scwx/wsr88d/rda/clutter_filter_bypass_map.cpp source/scwx/wsr88d/rda/level2_message_header.cpp source/scwx/wsr88d/rda/performance_maintenance_data.cpp source/scwx/wsr88d/rda/rda_adaptation_data.cpp - source/scwx/wsr88d/rda/rda_prf_data.cpp source/scwx/wsr88d/rda/rda_status_data.cpp source/scwx/wsr88d/rda/volume_coverage_pattern_data.cpp) set(HDR_WSR88D_RPG include/scwx/wsr88d/rpg/ccb_header.hpp @@ -155,7 +134,6 @@ set(HDR_WSR88D_RPG include/scwx/wsr88d/rpg/ccb_header.hpp include/scwx/wsr88d/rpg/cell_trend_volume_scan_times.hpp include/scwx/wsr88d/rpg/digital_precipitation_data_array_packet.hpp include/scwx/wsr88d/rpg/digital_radial_data_array_packet.hpp - include/scwx/wsr88d/rpg/digital_raster_data_array_packet.hpp include/scwx/wsr88d/rpg/general_status_message.hpp include/scwx/wsr88d/rpg/generic_data_packet.hpp include/scwx/wsr88d/rpg/generic_radial_data_packet.hpp @@ -197,7 +175,6 @@ set(SRC_WSR88D_RPG source/scwx/wsr88d/rpg/ccb_header.cpp source/scwx/wsr88d/rpg/cell_trend_volume_scan_times.cpp source/scwx/wsr88d/rpg/digital_precipitation_data_array_packet.cpp source/scwx/wsr88d/rpg/digital_radial_data_array_packet.cpp - source/scwx/wsr88d/rpg/digital_raster_data_array_packet.cpp source/scwx/wsr88d/rpg/general_status_message.cpp source/scwx/wsr88d/rpg/generic_data_packet.cpp source/scwx/wsr88d/rpg/generic_radial_data_packet.cpp @@ -246,8 +223,6 @@ add_library(wxdata OBJECT ${HDR_AWIPS} ${SRC_NETWORK} ${HDR_PROVIDER} ${SRC_PROVIDER} - ${HDR_TYPES} - ${SRC_TYPES} ${HDR_UTIL} ${SRC_UTIL} ${HDR_WSR88D} @@ -268,8 +243,6 @@ source_group("Header Files\\network" FILES ${HDR_NETWORK}) source_group("Source Files\\network" FILES ${SRC_NETWORK}) source_group("Header Files\\provider" FILES ${HDR_PROVIDER}) source_group("Source Files\\provider" FILES ${SRC_PROVIDER}) -source_group("Header Files\\types" FILES ${HDR_TYPES}) -source_group("Source Files\\types" FILES ${SRC_TYPES}) source_group("Header Files\\util" FILES ${HDR_UTIL}) source_group("Source Files\\util" FILES ${SRC_UTIL}) source_group("Header Files\\wsr88d" FILES ${HDR_WSR88D}) @@ -279,15 +252,6 @@ source_group("Source Files\\wsr88d\\rda" FILES ${SRC_WSR88D_RDA}) source_group("Header Files\\wsr88d\\rpg" FILES ${HDR_WSR88D_RPG}) source_group("Source Files\\wsr88d\\rpg" FILES ${SRC_WSR88D_RPG}) - -try_compile(CHRONO_HAS_TIMEZONES_AND_CALENDERS - ${CMAKE_BINARY_DIR} - ${PROJECT_SOURCE_DIR}/cpp-feature-tests/chrono_feature_test.cpp - CXX_STANDARD 20 - CXX_STANDARD_REQUIRED ON - CXX_EXTENSIONS OFF) -message("CHRONO_HAS_TIMEZONES_AND_CALENDERS: ${CHRONO_HAS_TIMEZONES_AND_CALENDERS}") - target_include_directories(wxdata PRIVATE ${Boost_INCLUDE_DIR} ${HSLUV_C_INCLUDE_DIR} ${scwx-data_SOURCE_DIR}/include @@ -318,8 +282,6 @@ target_link_libraries(wxdata PUBLIC aws-cpp-sdk-core aws-cpp-sdk-s3 cpr::cpr LibXml2::LibXml2 - OpenSSL::Crypto - range-v3::range-v3 re2::re2 spdlog::spdlog units::units) @@ -331,18 +293,9 @@ if (WIN32) target_link_libraries(wxdata INTERFACE Ws2_32) endif() -if (NOT CHRONO_HAS_TIMEZONES_AND_CALENDERS) - target_link_libraries(wxdata PUBLIC date::date-tz) -endif() - -if (LINUX) - target_link_libraries(wxdata PUBLIC TBB::tbb) -endif() - -if (LIBCPP) - # Enable support for parallel algorithms - target_compile_options(wxdata PUBLIC -fexperimental-library) - target_link_libraries(wxdata INTERFACE c++experimental) +if (NOT MSVC) + target_link_libraries(wxdata PUBLIC date::date-tz + TBB::tbb) endif() set_target_properties(wxdata PROPERTIES CXX_STANDARD 20