diff --git a/.ci/lint_cpp.sh b/.ci/lint_cpp.sh index 9786a83fc..cfb1e1f07 100755 --- a/.ci/lint_cpp.sh +++ b/.ci/lint_cpp.sh @@ -13,9 +13,17 @@ fi # Check formatting using format.sh echo "Checking your code using format.sh..." -./format.sh --color-diff --cmake --shell --print-version --branch origin/master +diff="$(./format.sh --diff --cmake --shell --print-version --branch origin/master)" err=$? +sep=" +---------- +" +used_version="${diff%%"$sep"*}" +diff="${diff#*"$sep"}" +changes_to_make="${diff%%"$sep"*}" +files_to_edit="${diff#*"$sep"}" + case $err in 1) cat <>"$GITHUB_OUTPUT" - - name: "Checkout" + - name: Checkout if: steps.configure.outputs.tag != null uses: actions/checkout@v6 with: - fetch-depth: 0 # fetch all history for all branches and tags + fetch-depth: 0 - - name: "Prepare release parameters" + - name: Prepare release parameters id: prepare if: steps.configure.outputs.tag != null shell: bash env: - TAG: ${{ steps.configure.outputs.tag }} + TAG: ${{steps.configure.outputs.tag}} run: .ci/prep_release.sh - - name: "Create release" + - name: Create release if: steps.configure.outputs.tag != null id: create_release shell: bash env: - GH_TOKEN: ${{ github.token }} - tag_name: ${{ steps.configure.outputs.tag }} - target: ${{ steps.configure.outputs.sha }} - release_name: ${{ steps.prepare.outputs.title }} - body_path: ${{ steps.prepare.outputs.body_path }} - prerelease: ${{ steps.prepare.outputs.is_beta }} + GH_TOKEN: ${{github.token}} + tag_name: ${{steps.configure.outputs.tag}} + target: ${{steps.configure.outputs.sha}} + release_name: ${{steps.prepare.outputs.title}} + body_path: ${{steps.prepare.outputs.body_path}} + prerelease: ${{steps.prepare.outputs.is_beta}} run: | - args=() - [[ $prerelease == yes ]] && args+=(--prerelease) - - gh release create "$tag_name" --verify-tag --draft "${args[@]}" \ - --target "$target" \ - --title "$release_name" \ - --notes-file "$body_path" + if [[ $prerelease == yes ]]; then + args="--prerelease" + fi + gh release create "$tag_name" --draft --verify-tag $args \ + --target "$target" --title "$release_name" \ + --notes-file "$body_path" build-linux: strategy: fail-fast: false matrix: - # The files in ".ci/$distro$version" correspond to the values given here + # These names correspond to the files in ".ci/$distro$version" include: - distro: Arch - - allow-failure: yes package: skip # We are packaged in Arch already + allow-failure: yes - distro: Servatrice_Debian version: 12 - package: DEB - server_only: yes test: skip + server_only: yes - distro: Debian version: 12 - package: DEB test: skip # Running tests on all distros is superfluous - distro: Debian version: 13 - package: DEB - distro: Fedora version: 43 - package: RPM test: skip # Running tests on all distros is superfluous - distro: Fedora version: 44 - package: RPM - distro: Ubuntu version: 24.04 - package: DEB test: skip # Running tests on all distros is superfluous - distro: Ubuntu version: 26.04 - package: DEB - name: ${{ matrix.distro }} ${{ matrix.version }} + name: ${{matrix.distro}} ${{matrix.version}} needs: configure runs-on: ubuntu-latest - continue-on-error: ${{ matrix.allow-failure == 'yes' }} + continue-on-error: ${{matrix.allow-failure == 'yes'}} timeout-minutes: 70 env: - CACHE: ${{ github.workspace }}/.cache/${{ matrix.distro }}${{ matrix.version }} # directory for caching docker image and ccache + NAME: ${{matrix.distro}}${{matrix.version}} + CACHE: ${{github.workspace}}/.cache/${{matrix.distro}}${{matrix.version}} # directory for caching docker image and ccache + # Cache size over the entire repo is 10Gi: + # https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#usage-limits-and-eviction-policy + CCACHE_SIZE: 550M CCACHE_EVICTION_AGE: 7d - CCACHE_SIZE: 550M # space of all repo is 10Gi: https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#usage-limits-and-eviction-policy CMAKE_GENERATOR: 'Ninja' - NAME: ${{ matrix.distro }}${{ matrix.version }} steps: - - name: "Checkout" + - name: Checkout uses: actions/checkout@v6 - - name: "Restore compiler cache (ccache)" + - name: Restore compiler cache (ccache) id: ccache_restore uses: actions/cache/restore@v5 env: BRANCH_NAME: ${{ github.head_ref || github.ref_name }} with: - key: ccache-${{ matrix.distro }}${{ matrix.version }}-${{ env.BRANCH_NAME }} - path: ${{ env.CACHE }} - restore-keys: ccache-${{ matrix.distro }}${{ matrix.version }}- + path: ${{env.CACHE}} + key: ccache-${{matrix.distro}}${{matrix.version}}-${{env.BRANCH_NAME}} + restore-keys: ccache-${{matrix.distro}}${{matrix.version}}- - - name: "Build ${{ matrix.distro }} ${{ matrix.version }} Docker image" + - name: Build ${{matrix.distro}} ${{matrix.version}} Docker image shell: bash run: source .ci/docker.sh --build - - name: "Build debug and test" + - name: Build debug and test if: matrix.test != 'skip' shell: bash run: | source .ci/docker.sh RUN --server --debug --test --ccache "$CCACHE_SIZE" \ - --cmake-generator "$CMAKE_GENERATOR" + --cmake-generator "$CMAKE_GENERATOR" - - name: "Build release package" + - name: Build release package id: build if: matrix.package != 'skip' shell: bash env: - SUFFIX: '-${{ matrix.distro }}${{ matrix.version }}' - package: '${{ matrix.package }}' - server_only: '${{ matrix.server_only }}' + SUFFIX: '-${{matrix.distro}}${{matrix.version}}' + package: '${{matrix.package}}' + server_only: '${{matrix.server_only}}' run: | source .ci/docker.sh args=() - [[ $server_only == yes ]] && args+=(--no-client) - [[ $GITHUB_REF == "refs/heads/master" ]] && args+=(--evict-ccache "$CCACHE_EVICTION_AGE") + if [[ $server_only == yes ]]; then + args+=(--no-client) + fi + if [[ $GITHUB_REF == "refs/heads/master" ]]; then + args+=(--evict-ccache "$CCACHE_EVICTION_AGE") + fi args+=(--ccache "$CCACHE_SIZE") args+=(--cmake-generator "$CMAKE_GENERATOR") args+=(--suffix "$SUFFIX") - RUN --server --release --package "$package" "${args[@]}" # Delete used cache to emulate a ccache update. See https://github.com/actions/cache/issues/342 - - name: "Delete remote compiler cache (ccache)" + - name: Delete remote compiler cache (ccache) if: github.ref == 'refs/heads/master' && steps.ccache_restore.outputs.cache-hit continue-on-error: true env: @@ -217,47 +213,47 @@ jobs: echo "Cache deleted successfully" fi - - name: "Save updated compiler cache (ccache)" + - name: Save updated compiler cache (ccache) if: github.ref == 'refs/heads/master' uses: actions/cache/save@v5 with: + path: ${{env.CACHE}} key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - path: ${{ env.CACHE }} - - name: "Upload artifact" + - name: Upload artifact id: upload_artifact if: matrix.package != 'skip' uses: actions/upload-artifact@v7 with: + path: ${{steps.build.outputs.path}} archive: false if-no-files-found: error - path: ${{ steps.build.outputs.path }} - - name: "Upload to release" + - name: Upload to release id: upload_release if: matrix.package != 'skip' && needs.configure.outputs.tag != null shell: bash env: - asset_name: ${{ steps.build.outputs.fullname }} - asset_path: ${{ steps.build.outputs.path }} - GH_TOKEN: ${{ github.token }} - tag_name: ${{ needs.configure.outputs.tag }} + GH_TOKEN: ${{github.token}} + tag_name: ${{needs.configure.outputs.tag}} + asset_name: ${{steps.build.outputs.fullname}} + asset_path: ${{steps.build.outputs.path}} run: gh release upload "$tag_name" "$asset_path#$asset_name" - - name: "Attest binary provenance" + - name: Attest binary provenance id: attestation if: steps.upload_release.outcome == 'success' uses: actions/attest@v4 with: + subject-path: ${{steps.build.outputs.path}} show-summary: false - subject-path: ${{ steps.build.outputs.path }} - - name: "Verify binary attestation" + - name: Verify binary attestation if: steps.attestation.outcome == 'success' shell: bash env: - GH_TOKEN: ${{ github.token }} - run: gh attestation verify "${{ steps.build.outputs.path }}" --repo Cockatrice/Cockatrice + GH_TOKEN: ${{github.token}} + run: gh attestation verify "${{steps.build.outputs.path}}" --repo Cockatrice/Cockatrice build-vcpkg: strategy: @@ -267,202 +263,200 @@ jobs: - os: macOS target: 13 runner: macos-15-intel - - ccache_eviction_age: 7d - cmake_generator: Ninja - make_package: 1 + soc: Intel + xcode: "16.4" + type: Release override_target: 13 + make_package: 1 package_suffix: "-macOS13_Intel" qt_version: 6.11.0 qt_arch: clang_64 qt_modules: qtimageformats qtmultimedia qtwebsockets - soc: Intel - type: Release + cmake_generator: Ninja use_ccache: 1 - xcode: "16.4" + ccache_eviction_age: 7d - os: macOS target: 14 runner: macos-14 - - ccache_eviction_age: 7d - cmake_generator: Ninja + soc: Apple + xcode: "15.4" + type: Release make_package: 1 package_suffix: "-macOS14" qt_version: 6.11.0 qt_arch: clang_64 qt_modules: qtimageformats qtmultimedia qtwebsockets - soc: Apple - type: Release + cmake_generator: Ninja use_ccache: 1 - xcode: "15.4" + ccache_eviction_age: 7d - os: macOS target: 15 runner: macos-15 - - ccache_eviction_age: 7d - cmake_generator: Ninja + soc: Apple + xcode: "16.4" + type: Release make_package: 1 package_suffix: "-macOS15" qt_version: 6.11.0 qt_arch: clang_64 qt_modules: qtimageformats qtmultimedia qtwebsockets - soc: Apple - type: Release + cmake_generator: Ninja use_ccache: 1 - xcode: "16.4" + ccache_eviction_age: 7d - os: macOS target: 15 runner: macos-15 - - ccache_eviction_age: 7d - cmake_generator: Ninja + soc: Apple + xcode: "16.4" + type: Debug qt_version: 6.11.0 qt_arch: clang_64 qt_modules: qtimageformats qtmultimedia qtwebsockets - soc: Apple - type: Debug + cmake_generator: Ninja use_ccache: 1 - xcode: "16.4" + ccache_eviction_age: 7d - os: Windows target: 10 runner: windows-2025 - - cmake_generator: "Visual Studio 18 2026" - cmake_generator_platform: x64 + type: Release make_package: 1 package_suffix: "-Win10" qt_version: 6.11.0 qt_arch: win64_msvc2022_64 qt_modules: qtimageformats qtmultimedia qtwebsockets - type: Release + cmake_generator: "Visual Studio 17 2022" + cmake_generator_platform: x64 - name: ${{ matrix.os }} ${{ matrix.target }}${{ matrix.soc == 'Intel' && ' Intel' || '' }}${{ matrix.type == 'Debug' && ' Debug' || '' }} + name: ${{matrix.os}} ${{matrix.target}}${{ matrix.soc == 'Intel' && ' Intel' || '' }}${{ matrix.type == 'Debug' && ' Debug' || '' }} needs: configure - runs-on: ${{ matrix.runner }} + runs-on: ${{matrix.runner}} timeout-minutes: 100 env: - CCACHE_DIR: ${{ github.workspace }}/.cache/ - CCACHE_SIZE: 550M # space of all repo is 10Gi: https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#usage-limits-and-eviction-policy + CCACHE_DIR: ${{github.workspace}}/.cache/ + # Cache size over the entire repo is 10Gi: + # https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#usage-limits-and-eviction-policy + CCACHE_SIZE: 550M steps: - - name: "Checkout" + - name: Checkout uses: actions/checkout@v6 with: submodules: recursive - - name: "[Windows] Add msbuild to PATH" + - name: Add msbuild to PATH if: matrix.os == 'Windows' id: add-msbuild uses: microsoft/setup-msbuild@v3 with: msbuild-architecture: x64 - - name: "[macOS] Setup ccache" - if: matrix.os == 'macOS' && matrix.use_ccache == 1 + - name: Setup ccache + if: matrix.use_ccache == 1 && matrix.os == 'macOS' run: brew install ccache - - name: "[macOS] Restore compiler cache (ccache)" - if: matrix.os == 'macOS' && matrix.use_ccache == 1 + - name: Restore compiler cache (ccache) + if: matrix.use_ccache == 1 id: ccache_restore uses: actions/cache/restore@v5 env: BRANCH_NAME: ${{ github.head_ref || github.ref_name }} with: - key: ccache-${{ matrix.runner }}-${{ matrix.soc }}-${{ matrix.type }}-${{ env.BRANCH_NAME }} - path: ${{ env.CCACHE_DIR }} - restore-keys: ccache-${{ matrix.runner }}-${{ matrix.soc }}-${{ matrix.type }}- + path: ${{env.CCACHE_DIR}} + key: ccache-${{matrix.runner}}-${{matrix.soc}}-${{matrix.type}}-${{env.BRANCH_NAME}} + restore-keys: ccache-${{matrix.runner}}-${{matrix.soc}}-${{matrix.type}}- - - name: "Install aqtinstall" + - name: Install aqtinstall run: pipx install aqtinstall # Resolve given wildcard versions (e.g. Qt 6.6.*) to latest version via aqtinstall to avoid stale caches on new releases - - name: "Resolve latest Qt patch version" + - name: Resolve latest Qt patch version id: resolve_qt_version shell: bash - run: .ci/resolve_latest_aqt_qt_version.sh "${{ matrix.qt_version }}" + run: .ci/resolve_latest_aqt_qt_version.sh "${{matrix.qt_version}}" - - name: "[macOS] Restore thin Qt ${{ steps.resolve_qt_version.outputs.version }} libraries" + - name: Restore thin Qt ${{ steps.resolve_qt_version.outputs.version }} libraries (${{ matrix.soc }} macOS) if: matrix.os == 'macOS' id: restore_qt uses: actions/cache/restore@v5 with: - key: thin-qt-macos-${{ matrix.soc }}-${{ steps.resolve_qt_version.outputs.version }} path: ${{ github.workspace }}/Qt + key: thin-qt-macos-${{ matrix.soc }}-${{ steps.resolve_qt_version.outputs.version }} # Using jurplel/install-qt-action to install Qt without using brew - # Qt build using vcpkg either just fails or takes too long to build - - name: "[macOS] Install fat Qt ${{ steps.resolve_qt_version.outputs.version }}" + # qt build using vcpkg either just fails or takes too long to build + - name: Install fat Qt ${{ steps.resolve_qt_version.outputs.version }} (${{ matrix.soc }} macOS) if: matrix.os == 'macOS' && steps.restore_qt.outputs.cache-hit != 'true' uses: jurplel/install-qt-action@v4 with: - arch: ${{ matrix.qt_arch }} - cache: false - dir: ${{ github.workspace }} - modules: ${{ matrix.qt_modules }} version: ${{ steps.resolve_qt_version.outputs.version }} + arch: ${{matrix.qt_arch}} + modules: ${{matrix.qt_modules}} + cache: false + dir: ${{github.workspace}} - - name: "[macOS] Create thin Qt libraries" + - name: Thin Qt libraries (${{ matrix.soc }} macOS) if: matrix.os == 'macOS' && steps.restore_qt.outputs.cache-hit != 'true' run: .ci/thin_macos_qtlib.sh - - name: "[macOS] Cache thin Qt libraries" + - name: Cache thin Qt libraries (${{ matrix.soc }} macOS) if: matrix.os == 'macOS' && steps.restore_qt.outputs.cache-hit != 'true' uses: actions/cache/save@v5 with: - key: thin-qt-macos-${{ matrix.soc }}-${{ steps.resolve_qt_version.outputs.version }} path: ${{ github.workspace }}/Qt + key: thin-qt-macos-${{ matrix.soc }}-${{ steps.resolve_qt_version.outputs.version }} - - name: "[Windows] Install Qt ${{ matrix.qt_version }}" + - name: Install Qt ${{matrix.qt_version}} (Windows) if: matrix.os == 'Windows' uses: jurplel/install-qt-action@v4 with: - # Qt 6.11.0 only works with aqtinstall directly from git until aqtinstall 3.4 is released + # qt 6.11.0 only works with aqtinstall directly from git until aqtinstall 3.4 is released aqtsource: git+https://github.com/miurahr/aqtinstall.git - arch: ${{ matrix.qt_arch }} - cache: true - modules: ${{ matrix.qt_modules }} version: ${{ steps.resolve_qt_version.outputs.version }} + arch: ${{matrix.qt_arch}} + modules: ${{matrix.qt_modules}} + cache: true - - name: "[Windows] Install NSIS" + - name: Install NSIS if: matrix.os == 'Windows' shell: bash run: choco install nsis - - name: "Setup vcpkg cache" + - name: Setup vcpkg cache id: vcpkg-cache uses: TAServers/vcpkg-cache@v3 with: token: ${{ secrets.GITHUB_TOKEN }} - # Uses environment variables, see compile.sh for more details - - name: "Build Cockatrice" + # uses environment variables, see compile.sh for more details + - name: Build Cockatrice id: build shell: bash env: - BUILDTYPE: '${{ matrix.type }}' - CCACHE_EVICTION_AGE: ${{ matrix.ccache_eviction_age }} - CMAKE_GENERATOR: ${{ matrix.cmake_generator }} - CMAKE_GENERATOR_PLATFORM: ${{ matrix.cmake_generator_platform }} - DEVELOPER_DIR: '/Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer' - MACOS_CERTIFICATE: ${{ secrets.PROD_MACOS_CERTIFICATE }} - MACOS_CERTIFICATE_NAME: ${{ secrets.PROD_MACOS_CERTIFICATE_NAME }} - MACOS_CERTIFICATE_PWD: ${{ secrets.PROD_MACOS_CERTIFICATE_PWD }} - MACOS_CI_KEYCHAIN_PWD: ${{ secrets.PROD_MACOS_CI_KEYCHAIN_PWD }} - MAKE_PACKAGE: '${{ matrix.make_package }}' - PACKAGE_SUFFIX: '${{ matrix.package_suffix }}' - TARGET_MACOS_VERSION: ${{ matrix.override_target }} - USE_CCACHE: ${{ matrix.use_ccache }} - VCPKG_BINARY_SOURCES: 'clear;files,${{ steps.vcpkg-cache.outputs.path }},readwrite' + BUILDTYPE: '${{matrix.type}}' + MAKE_PACKAGE: '${{matrix.make_package}}' + PACKAGE_SUFFIX: '${{matrix.package_suffix}}' + CMAKE_GENERATOR: ${{matrix.cmake_generator}} + CMAKE_GENERATOR_PLATFORM: ${{matrix.cmake_generator_platform}} + USE_CCACHE: ${{matrix.use_ccache}} VCPKG_DISABLE_METRICS: 1 + VCPKG_BINARY_SOURCES: 'clear;files,${{ steps.vcpkg-cache.outputs.path }},readwrite' + # macOS-specific environment variables, will be ignored on Windows + MACOS_CERTIFICATE: ${{ secrets.PROD_MACOS_CERTIFICATE }} + MACOS_CERTIFICATE_PWD: ${{ secrets.PROD_MACOS_CERTIFICATE_PWD }} + MACOS_CERTIFICATE_NAME: ${{ secrets.PROD_MACOS_CERTIFICATE_NAME }} + MACOS_CI_KEYCHAIN_PWD: ${{ secrets.PROD_MACOS_CI_KEYCHAIN_PWD }} + DEVELOPER_DIR: '/Applications/Xcode_${{matrix.xcode}}.app/Contents/Developer' + TARGET_MACOS_VERSION: ${{ matrix.override_target }} + CCACHE_EVICTION_AGE: ${{ matrix.ccache_eviction_age }} run: .ci/compile.sh --server --test --vcpkg # Delete used cache to emulate a ccache update. See https://github.com/actions/cache/issues/342 - - name: "[macOS] Delete remote compiler cache (ccache)" - if: matrix.os == 'macOS' && matrix.use_ccache == 1 && github.ref == 'refs/heads/master' && steps.ccache_restore.outputs.cache-hit + - name: Delete remote compiler cache (ccache) + if: github.ref == 'refs/heads/master' && matrix.use_ccache == 1 && steps.ccache_restore.outputs.cache-hit continue-on-error: true env: GH_TOKEN: ${{ github.token }} @@ -471,14 +465,14 @@ jobs: echo "Cache deleted successfully" fi - - name: "[macOS] Save updated compiler cache (ccache)" - if: matrix.os == 'macOS' && matrix.use_ccache == 1 && github.ref == 'refs/heads/master' + - name: Save updated compiler cache (ccache) + if: github.ref == 'refs/heads/master' && matrix.use_ccache == 1 uses: actions/cache/save@v5 with: + path: ${{env.CCACHE_DIR}} key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - path: ${{ env.CCACHE_DIR }} - - name: "[macOS] Sign app bundle" + - name: Sign app bundle if: matrix.os == 'macOS' && matrix.make_package && needs.configure.outputs.tag != null id: sign_macos env: @@ -488,15 +482,15 @@ jobs: if [[ -n "$MACOS_CERTIFICATE_NAME" ]] then security unlock-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain - /usr/bin/codesign --sign="$MACOS_CERTIFICATE_NAME" --entitlements=".ci/macos.entitlements" --options=runtime --force --deep --timestamp --verbose "${{ steps.build.outputs.path }}" + /usr/bin/codesign --sign="$MACOS_CERTIFICATE_NAME" --entitlements=".ci/macos.entitlements" --options=runtime --force --deep --timestamp --verbose "${{steps.build.outputs.path}}" fi - - name: "[macOS] Notarize app bundle" - if: matrix.os == 'macOS' && steps.sign_macos.outcome == 'success' + - name: Notarize app bundle + if: steps.sign_macos.outcome == 'success' env: MACOS_NOTARIZATION_APPLE_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_APPLE_ID }} - MACOS_NOTARIZATION_PWD: ${{ secrets.PROD_MACOS_NOTARIZATION_PWD }} MACOS_NOTARIZATION_TEAM_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_TEAM_ID }} + MACOS_NOTARIZATION_PWD: ${{ secrets.PROD_MACOS_NOTARIZATION_PWD }} run: | if [[ -n "$MACOS_NOTARIZATION_APPLE_ID" ]] then @@ -508,7 +502,7 @@ jobs: # Therefore, we create a zip file containing our app bundle, so that we can send it to the # notarization service echo "Creating temp notarization archive" - ditto -c -k --keepParent "${{ steps.build.outputs.path }}" "notarization.zip" + ditto -c -k --keepParent "${{steps.build.outputs.path}}" "notarization.zip" # Here we send the notarization request to the Apple's Notarization service, waiting for the result. # This typically takes a few seconds inside a CI environment, but it might take more depending on the App @@ -520,51 +514,51 @@ jobs: # Finally, we need to "attach the staple" to our executable, which will allow our app to be # validated by macOS even when an internet connection is not available. echo "Attach staple" - xcrun stapler staple "${{ steps.build.outputs.path }}" + xcrun stapler staple "${{steps.build.outputs.path}}" fi - - name: "Upload artifact" + - name: Upload artifact if: matrix.make_package id: upload_artifact uses: actions/upload-artifact@v7 with: + path: ${{steps.build.outputs.path}} archive: false if-no-files-found: error - path: ${{ steps.build.outputs.path }} - - name: "[Windows] Upload PDBs (Program Databases)" + - name: Upload PDBs (Program Databases) if: matrix.os == 'Windows' && github.ref_type != 'tag' uses: actions/upload-artifact@v7 with: - if-no-files-found: error - name: ${{ steps.build.outputs.name }}-PDBs + name: ${{steps.build.outputs.name}}-PDBs path: | build/cockatrice/Release/*.pdb build/oracle/Release/*.pdb build/servatrice/Release/*.pdb + if-no-files-found: error - - name: "Upload to release" + - name: Upload to release if: needs.configure.outputs.tag != null && matrix.make_package == '1' id: upload_release shell: bash env: - asset_name: ${{ steps.build.outputs.fullname }} - asset_path: ${{ steps.build.outputs.path }} - GH_TOKEN: ${{ github.token }} - tag_name: ${{ needs.configure.outputs.tag }} + GH_TOKEN: ${{github.token}} + tag_name: ${{needs.configure.outputs.tag}} + asset_name: ${{steps.build.outputs.fullname}} + asset_path: ${{steps.build.outputs.path}} run: gh release upload "$tag_name" "$asset_path#$asset_name" - - name: "Attest binary provenance" + - name: Attest binary provenance if: steps.upload_release.outcome == 'success' id: attestation uses: actions/attest@v4 with: + subject-path: ${{steps.build.outputs.path}} show-summary: false - subject-path: ${{ steps.build.outputs.path }} - - name: "Verify binary attestation" + - name: Verify binary attestation if: steps.attestation.outcome == 'success' shell: bash env: - GH_TOKEN: ${{ github.token }} - run: gh attestation verify "${{ steps.build.outputs.path }}" --repo Cockatrice/Cockatrice + GH_TOKEN: ${{github.token}} + run: gh attestation verify "${{steps.build.outputs.path}}" --repo Cockatrice/Cockatrice diff --git a/.github/workflows/desktop-lint.yml b/.github/workflows/desktop-lint.yml index 54931933c..df8b9f89e 100644 --- a/.github/workflows/desktop-lint.yml +++ b/.github/workflows/desktop-lint.yml @@ -1,7 +1,7 @@ name: Code Style (C++) on: - # Push trigger not needed for linting, we do not allow direct pushes to master + # push trigger not needed for linting, we do not allow direct pushes to master pull_request: paths: - '*/**' # matches all files not in root @@ -21,20 +21,17 @@ jobs: runs-on: ubuntu-slim steps: - - name: "Checkout" + - name: Checkout uses: actions/checkout@v6 with: fetch-depth: 20 # should be enough to find merge base - - name: "Install dependencies" + - name: Install dependencies shell: bash run: | sudo apt-get update - sudo apt-get install -y --no-install-recommends \ - clang-format \ - cmake-format \ - shellcheck + sudo apt-get install -y --no-install-recommends clang-format cmake-format shellcheck - - name: "Check code formatting" + - name: Check code formatting shell: bash run: ./.ci/lint_cpp.sh diff --git a/.github/workflows/docker-release.yml b/.github/workflows/docker-release.yml index d9ff06282..b869d1fa9 100644 --- a/.github/workflows/docker-release.yml +++ b/.github/workflows/docker-release.yml @@ -1,10 +1,9 @@ name: Build Docker Image -permissions: - contents: read - packages: write - on: + release: + types: + - released # publishing of stable releases push: branches: - master @@ -14,9 +13,6 @@ on: paths: - '.github/workflows/docker-release.yml' - 'Dockerfile' - release: - types: - - released # publishing of stable releases # Cancel earlier, unfinished runs of this workflow on the same branch (unless on release) concurrency: @@ -28,50 +24,54 @@ jobs: name: amd64 & arm64 if: ${{ github.repository_owner == 'Cockatrice' }} runs-on: ubuntu-latest + + permissions: + contents: read + packages: write steps: - - name: "Checkout" + - name: Checkout uses: actions/checkout@v6 - - name: "Docker metadata" + - name: Docker metadata id: metadata uses: docker/metadata-action@v6 env: DOCKER_METADATA_ANNOTATIONS_LEVELS: index # needed for GHCR with: - annotations: | - org.opencontainers.image.title=Servatrice - org.opencontainers.image.url=https://cockatrice.github.io/ - org.opencontainers.image.description=Server for Cockatrice, a cross-platform virtual tabletop for multiplayer card games images: | ghcr.io/cockatrice/servatrice labels: | org.opencontainers.image.title=Servatrice org.opencontainers.image.url=https://cockatrice.github.io/ org.opencontainers.image.description=Server for Cockatrice, a cross-platform virtual tabletop for multiplayer card games + annotations: | + org.opencontainers.image.title=Servatrice + org.opencontainers.image.url=https://cockatrice.github.io/ + org.opencontainers.image.description=Server for Cockatrice, a cross-platform virtual tabletop for multiplayer card games - - name: "Set up QEMU" + - name: Set up QEMU uses: docker/setup-qemu-action@v4 - - name: "Set up Docker buildx" + - name: Set up Docker buildx uses: docker/setup-buildx-action@v4 - - name: "Login to GitHub Container Registry" + - name: Login to GitHub Container Registry if: contains(github.event.release.tag_name, 'Release') && github.event.release.target_commitish == 'master' uses: docker/login-action@v4 with: - password: ${{ github.token }} registry: ghcr.io username: ${{ github.actor }} + password: ${{ github.token }} - - name: "Build and push Docker image" + - name: Build and push Docker image uses: docker/build-push-action@v7 with: - annotations: ${{ steps.metadata.outputs.annotations }} - cache-from: type=gha,scope=servatrice - cache-to: type=gha,mode=max,scope=servatrice context: . - labels: ${{ steps.metadata.outputs.labels }} platforms: linux/amd64,linux/arm64 push: ${{ github.ref_type == 'tag' }} tags: ${{ steps.metadata.outputs.tags }} + labels: ${{ steps.metadata.outputs.labels }} + annotations: ${{ steps.metadata.outputs.annotations }} + cache-from: type=gha,scope=servatrice + cache-to: type=gha,mode=max,scope=servatrice diff --git a/.github/workflows/documentation-build.yml b/.github/workflows/documentation-build.yml index 717999d5a..b0093d6b1 100644 --- a/.github/workflows/documentation-build.yml +++ b/.github/workflows/documentation-build.yml @@ -1,18 +1,18 @@ name: Generate Docs on: + release: + types: + - published # publishing of stable releases and pre-releases pull_request: paths: - 'doc/doxygen/**' - '.github/workflows/documentation-build.yml' - 'Doxyfile' - release: - types: - - published # publishing of stable releases and pre-releases workflow_dispatch: env: - COCKATRICE_REF: ${{ github.ref_name }} # tag name if the commit is tagged, otherwise branch name + COCKATRICE_REF: ${{ github.ref_name }} # Tag name if the commit is tagged, otherwise branch name jobs: docs: @@ -20,22 +20,22 @@ jobs: runs-on: ubuntu-latest steps: - - name: "Checkout code" + - name: Checkout code uses: actions/checkout@v6 with: submodules: recursive - - name: "Install Graphviz" + - name: Install Graphviz run: | sudo apt-get install -y graphviz dot -V - - name: "Install Doxygen" + - name: Install Doxygen uses: ssciwr/doxygen-install@v2 with: version: "1.16.1" - - name: "Update Doxygen Configuration" + - name: Update Doxygen Configuration run: | git diff Doxyfile doxygen -u Doxyfile @@ -48,16 +48,16 @@ jobs: exit 1 fi - - name: "Generate Documentation" + - name: Generate Documentation if: always() run: doxygen Doxyfile - - name: "Deploy to cockatrice.github.io" + - name: Deploy to cockatrice.github.io if: github.event_name == 'release' || github.event_name == 'workflow_dispatch' uses: peaceiris/actions-gh-pages@v4 with: deploy_key: ${{ secrets.DOCS_DEPLOY_KEY }} - destination_dir: docs # docs will be available at https://cockatrice.github.io/docs/ external_repository: Cockatrice/cockatrice.github.io publish_branch: master publish_dir: ./docs/html + destination_dir: docs # Docs will live under https://cockatrice.github.io/docs/ diff --git a/.github/workflows/translations-pull.yml b/.github/workflows/translations-pull.yml index 057381f8a..8f673fce9 100644 --- a/.github/workflows/translations-pull.yml +++ b/.github/workflows/translations-pull.yml @@ -1,14 +1,14 @@ name: Update Translations on: + workflow_dispatch: + schedule: + # runs in the middle of each month starting a quarter (UTC) = two weeks after new strings are built + - cron: '0 0 15 1,4,7,10 *' pull_request: paths: - '.tx/**' - '.github/workflows/translations-pull.yml' - schedule: - # Runs in the middle of each month starting a quarter (UTC) = two weeks after new strings are built - - cron: '0 0 15 1,4,7,10 *' - workflow_dispatch: jobs: translations: @@ -19,18 +19,18 @@ jobs: runs-on: ubuntu-slim steps: - - name: "Checkout repo" + - name: Checkout repo uses: actions/checkout@v6 - - name: "Pull translated strings from Transifex" + - name: Pull translated strings from Transifex uses: transifex/cli-action@v2 with: - # Used config file: https://github.com/Cockatrice/Cockatrice/blob/master/.tx/config - # Docs: https://github.com/transifex/cli#pulling-files-from-transifex - args: pull --force --all + # used config file: https://github.com/Cockatrice/Cockatrice/blob/master/.tx/config + # https://github.com/transifex/cli#pulling-files-from-transifex token: ${{ secrets.TX_TOKEN }} + args: pull --force --all - - name: "Create pull request" + - name: Create pull request if: github.event_name != 'pull_request' id: create_pr uses: peter-evans/create-pull-request@v8 @@ -38,7 +38,12 @@ jobs: add-paths: | cockatrice/translations/*.ts oracle/translations/*.ts - author: github-actions # owner of the commit + commit-message: Update translation files + # author is the owner of the commit + author: github-actions + branch: ci-update_translations + delete-branch: true + title: 'Update translations' body: | Pulled all translated strings from [Transifex][1]. @@ -48,16 +53,12 @@ jobs: [1]: https://explore.transifex.com/cockatrice/cockatrice/ [2]: https://github.com/Cockatrice/Cockatrice/actions/workflows/translations-pull.yml?query=branch%3Amaster - branch: ci-update_translations - commit-message: Update translation files - delete-branch: true - draft: false labels: | CI Translation - title: 'Update translations' + draft: false - - name: "PR Status" + - name: PR Status if: github.event_name != 'pull_request' shell: bash env: diff --git a/.github/workflows/translations-push.yml b/.github/workflows/translations-push.yml index 4adcaf4a4..e926a58ed 100644 --- a/.github/workflows/translations-push.yml +++ b/.github/workflows/translations-push.yml @@ -1,14 +1,14 @@ name: Update Translation Source on: + workflow_dispatch: + schedule: + # runs at the start of each quarter (UTC) + - cron: '0 0 1 1,4,7,10 *' pull_request: paths: - '.ci/update_translation_source_strings.sh' - '.github/workflows/translations-push.yml' - schedule: - # Runs at the start of each quarter (UTC) - - cron: '0 0 1 1,4,7,10 *' - workflow_dispatch: jobs: translations: @@ -19,16 +19,16 @@ jobs: runs-on: ubuntu-slim steps: - - name: "Checkout repo" + - name: Checkout repo uses: actions/checkout@v6 - - name: "Install lupdate" + - name: Install lupdate shell: bash run: | sudo apt-get update sudo apt-get install -y --no-install-recommends qttools5-dev-tools - - name: "Update Cockatrice translation source" + - name: Update Cockatrice translation source id: cockatrice shell: bash run: | @@ -36,15 +36,15 @@ jobs: export DIRS="cockatrice/src $(find . -maxdepth 1 -type d -name 'libcockatrice_*')" FILE="$FILE" DIRS="$DIRS" .ci/update_translation_source_strings.sh - - name: "Update Oracle translation source" + - name: Update Oracle translation source id: oracle shell: bash env: - DIRS: 'oracle/src' FILE: 'oracle/oracle_en@source.ts' + DIRS: 'oracle/src' run: .ci/update_translation_source_strings.sh - - name: "Render template" + - name: Render template id: template uses: chuhlomin/render-template/binary@v1 with: @@ -54,7 +54,7 @@ jobs: oracle_output: ${{ steps.oracle.outputs.output }} commit: ${{ github.sha }} - - name: "Create pull request" + - name: Create pull request if: github.event_name != 'pull_request' id: create_pr uses: peter-evans/create-pull-request@v8 @@ -62,18 +62,19 @@ jobs: add-paths: | cockatrice/cockatrice_en@source.ts oracle/oracle_en@source.ts - author: github-actions # owner of the commit - body: ${{ steps.template.outputs.result }} - branch: ci-update_translation_source commit-message: Update translation source strings + # author is the owner of the commit + author: github-actions + branch: ci-update_translation_source delete-branch: true - draft: false + title: 'Update source strings' + body: ${{ steps.template.outputs.result }} labels: | CI Translation - title: 'Update source strings' + draft: false - - name: "PR Status" + - name: PR Status if: github.event_name != 'pull_request' shell: bash env: diff --git a/cmake/NSIS.template.in b/cmake/NSIS.template.in index 5af116470..7b52b7bcc 100644 --- a/cmake/NSIS.template.in +++ b/cmake/NSIS.template.in @@ -117,22 +117,21 @@ ${If} $InstDir == "" ; we need to set a default based on the install mode StrCpy $InstDir $0 ${EndIf} +Call SetModeDestinationFromInstdir -; --- Detect portable install when using /R (must come BEFORE SetModeDestinationFromInstdir) --- +; --- Detect portable install when using /R --- ${If} $ReinstallMode = 1 IfFileExists "$InstDir\portable.dat" 0 not_portable StrCpy $PortableMode 1 Goto portable_done + not_portable: StrCpy $PortableMode 0 + portable_done: ${EndIf} -; Now that $PortableMode reflects reality, commit InstDir into the correct slot -Call SetModeDestinationFromInstdir - ${If} $ReinstallMode = 1 -${AndIf} $PortableMode = 0 Call AutoUninstallIfNeeded ${EndIf} diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index bd99d08bf..0b2192399 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -56,58 +56,56 @@ set(cockatrice_SOURCES src/filters/filter_tree_model.cpp src/filters/syntax_help.cpp src/game/abstract_game.cpp - src/game/arrow_registry.cpp - src/game_graphics/board/abstract_card_drag_item.cpp - src/game_graphics/board/abstract_card_item.cpp - src/game_graphics/board/abstract_counter.cpp + src/game/board/abstract_card_drag_item.cpp + src/game/board/abstract_card_item.cpp + src/game/board/abstract_counter.cpp src/game/board/arrow_data.cpp - src/game_graphics/board/arrow_item.cpp - src/game_graphics/board/arrow_target.cpp - src/game_graphics/board/card_drag_item.cpp - src/game_graphics/board/card_item.cpp + src/game/board/arrow_item.cpp + src/game/board/arrow_target.cpp + src/game/board/card_drag_item.cpp + src/game/board/card_item.cpp src/game/board/card_list.cpp src/game/board/card_state.cpp - src/game_graphics/board/counter_general.cpp + src/game/board/counter_general.cpp src/game/board/counter_state.cpp - src/game_graphics/board/translate_counter_name.cpp - src/game_graphics/deckview/deck_view.cpp - src/game_graphics/deckview/deck_view_container.cpp - src/game_graphics/deckview/tabbed_deck_view_container.cpp - src/game_graphics/dialogs/dlg_create_token.cpp - src/game_graphics/dialogs/dlg_move_top_cards_until.cpp - src/game_graphics/dialogs/dlg_roll_dice.cpp + src/game/board/translate_counter_name.cpp + src/game/deckview/deck_view.cpp + src/game/deckview/deck_view_container.cpp + src/game/deckview/tabbed_deck_view_container.cpp + src/game/dialogs/dlg_create_token.cpp + src/game/dialogs/dlg_move_top_cards_until.cpp + src/game/dialogs/dlg_roll_dice.cpp src/game/game.cpp src/game/game_event_handler.cpp src/game/game_meta_info.cpp - src/game_graphics/game_scene.cpp + src/game/game_scene.cpp src/game/game_state.cpp - src/game_graphics/game_view.cpp - src/game_graphics/hand_counter.cpp - src/game_graphics/log/message_log_widget.cpp + src/game/game_view.cpp + src/game/hand_counter.cpp + src/game/log/message_log_widget.cpp src/game/phase.cpp - src/game_graphics/phases_toolbar.cpp - src/game_graphics/player/menu/card_menu.cpp - src/game_graphics/player/menu/custom_zone_menu.cpp - src/game_graphics/player/menu/grave_menu.cpp - src/game_graphics/player/menu/hand_menu.cpp - src/game_graphics/player/menu/library_menu.cpp - src/game_graphics/player/menu/move_menu.cpp - src/game_graphics/player/menu/player_menu.cpp - src/game_graphics/player/menu/pt_menu.cpp - src/game_graphics/player/menu/rfg_menu.cpp - src/game_graphics/player/menu/say_menu.cpp - src/game_graphics/player/menu/sideboard_menu.cpp - src/game_graphics/player/menu/utility_menu.cpp + src/game/phases_toolbar.cpp + src/game/player/menu/card_menu.cpp + src/game/player/menu/custom_zone_menu.cpp + src/game/player/menu/grave_menu.cpp + src/game/player/menu/hand_menu.cpp + src/game/player/menu/library_menu.cpp + src/game/player/menu/move_menu.cpp + src/game/player/menu/player_menu.cpp + src/game/player/menu/pt_menu.cpp + src/game/player/menu/rfg_menu.cpp + src/game/player/menu/say_menu.cpp + src/game/player/menu/sideboard_menu.cpp + src/game/player/menu/utility_menu.cpp src/game/player/player_actions.cpp - src/game_graphics/player/player_area.cpp - src/game_graphics/player/player_dialogs.cpp + src/game/player/player_area.cpp src/game/player/player_event_handler.cpp - src/game_graphics/player/player_graphics_item.cpp + src/game/player/player_graphics_item.cpp src/game/player/player_info.cpp - src/game_graphics/player/player_list_widget.cpp + src/game/player/player_list_widget.cpp src/game/player/player_logic.cpp src/game/player/player_manager.cpp - src/game_graphics/player/player_target.cpp + src/game/player/player_target.cpp src/game/replay.cpp src/game/zones/card_zone_logic.cpp src/game/zones/hand_zone_logic.cpp @@ -183,7 +181,6 @@ set(cockatrice_SOURCES src/interface/widgets/deck_analytics/analyzer_modules/mana_distribution/mana_distribution_single_display_widget.cpp src/interface/widgets/deck_analytics/analyzer_modules/mana_curve/mana_curve_total_widget.cpp src/interface/widgets/deck_analytics/analyzer_modules/mana_curve/mana_curve_category_widget.cpp - src/interface/widgets/deck_editor/card_database_view.cpp src/interface/widgets/deck_editor/deck_list_history_manager_widget.cpp src/interface/widgets/deck_editor/deck_editor_card_database_dock_widget.cpp src/interface/widgets/deck_editor/deck_editor_card_info_dock_widget.cpp diff --git a/cockatrice/src/client/network/interfaces/deck_stats_interface.cpp b/cockatrice/src/client/network/interfaces/deck_stats_interface.cpp index 8689a19e9..0298daa6b 100644 --- a/cockatrice/src/client/network/interfaces/deck_stats_interface.cpp +++ b/cockatrice/src/client/network/interfaces/deck_stats_interface.cpp @@ -6,12 +6,12 @@ #include #include #include -#include #include #include #include -DeckStatsInterface::DeckStatsInterface(QObject *parent) : QObject(parent) +DeckStatsInterface::DeckStatsInterface(CardDatabase &_cardDatabase, QObject *parent) + : QObject(parent), cardDatabase(_cardDatabase) { manager = new QNetworkAccessManager(this); connect(manager, &QNetworkAccessManager::finished, this, &DeckStatsInterface::queryFinished); @@ -70,8 +70,8 @@ void DeckStatsInterface::analyzeDeck(const DeckList &deck) void DeckStatsInterface::copyDeckWithoutTokens(const DeckList &source, DeckList &destination) { - auto copyIfNotAToken = [&destination](const auto node, const auto card) { - CardInfoPtr dbCard = CardDatabaseManager::query()->getCardInfo(card->getName()); + auto copyIfNotAToken = [this, &destination](const auto node, const auto card) { + CardInfoPtr dbCard = cardDatabase.query()->getCardInfo(card->getName()); if (dbCard && !dbCard->getIsToken()) { DecklistCardNode *addedCard = destination.addCard(card->getName(), node->getName(), -1); addedCard->setNumber(card->getNumber()); diff --git a/cockatrice/src/client/network/interfaces/deck_stats_interface.h b/cockatrice/src/client/network/interfaces/deck_stats_interface.h index 09bf998de..2ec67a5a7 100644 --- a/cockatrice/src/client/network/interfaces/deck_stats_interface.h +++ b/cockatrice/src/client/network/interfaces/deck_stats_interface.h @@ -7,6 +7,7 @@ #ifndef DECKSTATS_INTERFACE_H #define DECKSTATS_INTERFACE_H +#include #include class QByteArray; @@ -20,6 +21,8 @@ class DeckStatsInterface : public QObject private: QNetworkAccessManager *manager; + CardDatabase &cardDatabase; + /** * Deckstats doesn't recognize token cards, and instead tries to find the * closest non-token card instead. So we construct a new deck which has no @@ -32,7 +35,7 @@ private slots: void getAnalyzeRequestData(const DeckList &deck, QByteArray &data); public: - explicit DeckStatsInterface(QObject *parent = nullptr); + explicit DeckStatsInterface(CardDatabase &_cardDatabase, QObject *parent = nullptr); void analyzeDeck(const DeckList &deck); }; diff --git a/cockatrice/src/client/network/interfaces/tapped_out_interface.cpp b/cockatrice/src/client/network/interfaces/tapped_out_interface.cpp index 5dc77fa2c..cd39ea251 100644 --- a/cockatrice/src/client/network/interfaces/tapped_out_interface.cpp +++ b/cockatrice/src/client/network/interfaces/tapped_out_interface.cpp @@ -6,12 +6,12 @@ #include #include #include -#include #include #include #include -TappedOutInterface::TappedOutInterface(QObject *parent) : QObject(parent) +TappedOutInterface::TappedOutInterface(CardDatabase &_cardDatabase, QObject *parent) + : QObject(parent), cardDatabase(_cardDatabase) { manager = new QNetworkAccessManager(this); connect(manager, &QNetworkAccessManager::finished, this, &TappedOutInterface::queryFinished); @@ -97,8 +97,8 @@ void TappedOutInterface::analyzeDeck(const DeckList &deck) void TappedOutInterface::copyDeckSplitMainAndSide(const DeckList &source, DeckList &mainboard, DeckList &sideboard) { - auto copyMainOrSide = [&mainboard, &sideboard](const auto node, const auto card) { - CardInfoPtr dbCard = CardDatabaseManager::query()->getCardInfo(card->getName()); + auto copyMainOrSide = [this, &mainboard, &sideboard](const auto node, const auto card) { + CardInfoPtr dbCard = cardDatabase.query()->getCardInfo(card->getName()); if (!dbCard || dbCard->getIsToken()) { return; } diff --git a/cockatrice/src/client/network/interfaces/tapped_out_interface.h b/cockatrice/src/client/network/interfaces/tapped_out_interface.h index 32f9369d5..f1cc1cbeb 100644 --- a/cockatrice/src/client/network/interfaces/tapped_out_interface.h +++ b/cockatrice/src/client/network/interfaces/tapped_out_interface.h @@ -7,8 +7,8 @@ #ifndef TAPPEDOUT_INTERFACE_H #define TAPPEDOUT_INTERFACE_H -#include -#include +#include +#include inline Q_LOGGING_CATEGORY(TappedOutInterfaceLog, "tapped_out_interface"); @@ -29,13 +29,14 @@ class TappedOutInterface : public QObject private: QNetworkAccessManager *manager; + CardDatabase &cardDatabase; void copyDeckSplitMainAndSide(const DeckList &source, DeckList &mainboard, DeckList &sideboard); private slots: void queryFinished(QNetworkReply *reply); void getAnalyzeRequestData(const DeckList &deck, QByteArray &data); public: - explicit TappedOutInterface(QObject *parent = nullptr); + explicit TappedOutInterface(CardDatabase &_cardDatabase, QObject *parent = nullptr); void analyzeDeck(const DeckList &deck); }; diff --git a/cockatrice/src/client/settings/cache_settings.cpp b/cockatrice/src/client/settings/cache_settings.cpp index cc34e1707..64416e5ee 100644 --- a/cockatrice/src/client/settings/cache_settings.cpp +++ b/cockatrice/src/client/settings/cache_settings.cpp @@ -309,7 +309,6 @@ SettingsCache::SettingsCache() cardViewExpandedRowsMax = settings->value("interface/cardViewExpandedRowsMax", 20).toInt(); closeEmptyCardView = settings->value("interface/closeEmptyCardView", true).toBool(); focusCardViewSearchBar = settings->value("interface/focusCardViewSearchBar", true).toBool(); - keepGameChatFocus = settings->value("interface/keepGameChatFocus", false).toBool(); showDragSelectionCount = settings->value("interface/showlassoselectioncount", true).toBool(); showTotalSelectionCount = settings->value("interface/showpersistentselectioncount", true).toBool(); @@ -389,7 +388,6 @@ SettingsCache::SettingsCache() ignoreUnregisteredUsers = settings->value("chat/ignore_unregistered", false).toBool(); ignoreUnregisteredUserMessages = settings->value("chat/ignore_unregistered_messages", false).toBool(); - ignoreNonBuddyUserMessages = settings->value("chat/ignore_nonbuddy_messages", false).toBool(); scaleCards = settings->value("cards/scaleCards", true).toBool(); verticalCardOverlapPercent = settings->value("cards/verticalCardOverlapPercent", 33).toInt(); @@ -458,13 +456,6 @@ void SettingsCache::setFocusCardViewSearchBar(QT_STATE_CHANGED_T value) settings->setValue("interface/focusCardViewSearchBar", focusCardViewSearchBar); } -void SettingsCache::setKeepGameChatFocus(QT_STATE_CHANGED_T value) -{ - keepGameChatFocus = value; - settings->setValue("interface/keepGameChatFocus", keepGameChatFocus); - emit keepGameChatFocusChanged(keepGameChatFocus); -} - void SettingsCache::setKnownMissingFeatures(const QString &_knownMissingFeatures) { knownMissingFeatures = _knownMissingFeatures; @@ -1126,12 +1117,6 @@ void SettingsCache::setIgnoreUnregisteredUserMessages(QT_STATE_CHANGED_T _ignore settings->setValue("chat/ignore_unregistered_messages", ignoreUnregisteredUserMessages); } -void SettingsCache::setIgnoreNonBuddyUserMessages(QT_STATE_CHANGED_T _ignoreNonBuddyUserMessages) -{ - ignoreNonBuddyUserMessages = static_cast(_ignoreNonBuddyUserMessages); - settings->setValue("chat/ignore_nonbuddy_messages", ignoreNonBuddyUserMessages); -} - void SettingsCache::setPixmapCacheSize(const int _pixmapCacheSize) { pixmapCacheSize = _pixmapCacheSize; diff --git a/cockatrice/src/client/settings/cache_settings.h b/cockatrice/src/client/settings/cache_settings.h index a166917c1..b1197e267 100644 --- a/cockatrice/src/client/settings/cache_settings.h +++ b/cockatrice/src/client/settings/cache_settings.h @@ -183,7 +183,6 @@ signals: void soundThemeChanged(); void ignoreUnregisteredUsersChanged(); void ignoreUnregisteredUserMessagesChanged(); - void ignoreNonBuddyUserMessagesChanged(); void pixmapCacheSizeChanged(int newSizeInMBs); void networkCacheSizeChanged(int newSizeInMBs); void redirectCacheTtlChanged(int newTtl); @@ -195,7 +194,6 @@ signals: void downloadSpoilerStatusChanged(); void useTearOffMenusChanged(bool state); void roundCardCornersChanged(bool roundCardCorners); - void keepGameChatFocusChanged(bool value); private: QSettings *settings; @@ -296,7 +294,6 @@ private: QString soundThemeName; bool ignoreUnregisteredUsers; bool ignoreUnregisteredUserMessages; - bool ignoreNonBuddyUserMessages; QString picUrl; QString picUrlFallback; QString clientID; @@ -307,7 +304,6 @@ private: int cardViewExpandedRowsMax; bool closeEmptyCardView; bool focusCardViewSearchBar; - bool keepGameChatFocus; int pixmapCacheSize; int networkCacheSize; int redirectCacheTtl; @@ -792,10 +788,6 @@ public: { return ignoreUnregisteredUserMessages; } - [[nodiscard]] bool getIgnoreNonBuddyUserMessages() const - { - return ignoreNonBuddyUserMessages; - } [[nodiscard]] int getPixmapCacheSize() const { return pixmapCacheSize; @@ -937,7 +929,6 @@ public: void setCardViewExpandedRowsMax(int value); void setCloseEmptyCardView(QT_STATE_CHANGED_T value); void setFocusCardViewSearchBar(QT_STATE_CHANGED_T value); - void setKeepGameChatFocus(QT_STATE_CHANGED_T value); QString getClientID() override { return clientID; @@ -970,10 +961,6 @@ public: { return focusCardViewSearchBar; } - [[nodiscard]] bool getKeepGameChatFocus() const - { - return keepGameChatFocus; - } [[nodiscard]] ShortcutsSettings &shortcuts() const { return *shortcutsSettings; @@ -1124,7 +1111,6 @@ public slots: void setSoundThemeName(const QString &_soundThemeName); void setIgnoreUnregisteredUsers(QT_STATE_CHANGED_T _ignoreUnregisteredUsers); void setIgnoreUnregisteredUserMessages(QT_STATE_CHANGED_T _ignoreUnregisteredUserMessages); - void setIgnoreNonBuddyUserMessages(QT_STATE_CHANGED_T _ignoreNonBuddyUserMessages); void setPixmapCacheSize(const int _pixmapCacheSize); void setCardImageCacheMethod(CardPictureLoaderCacheMethod::CacheMethod _cardImageCachingMethod); void setNetworkCacheSizeInMB(const int _networkCacheSize); diff --git a/cockatrice/src/client/settings/shortcuts_settings.h b/cockatrice/src/client/settings/shortcuts_settings.h index 95155b8d1..45e2c4fca 100644 --- a/cockatrice/src/client/settings/shortcuts_settings.h +++ b/cockatrice/src/client/settings/shortcuts_settings.h @@ -223,10 +223,6 @@ private: {"TabDeckEditor/aLoadDeck", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Load Deck..."), parseSequenceString("Ctrl+O"), ShortcutGroup::Deck_Editor)}, - {"TabDeckEditor/aLoadDeckFromWebsite", - ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Load deck from online service..."), - parseSequenceString("Ctrl+Shift+O"), - ShortcutGroup::Deck_Editor)}, {"TabDeckEditor/aLoadDeckFromClipboard", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Load Deck from Clipboard..."), parseSequenceString("Ctrl+Shift+V"), @@ -287,10 +283,6 @@ private: ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Load Deck from Clipboard..."), parseSequenceString("Ctrl+Shift+V"), ShortcutGroup::Game_Lobby)}, - {"DeckViewContainer/loadFromWebsiteButton", - ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Load from website..."), - parseSequenceString("Ctrl+Shift+O"), - ShortcutGroup::Game_Lobby)}, {"DeckViewContainer/unloadDeckButton", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Unload Deck"), parseSequenceString("Ctrl+Alt+U"), ShortcutGroup::Game_Lobby)}, diff --git a/cockatrice/src/game/abstract_game.cpp b/cockatrice/src/game/abstract_game.cpp index c20003ece..5b1b4bff2 100644 --- a/cockatrice/src/game/abstract_game.cpp +++ b/cockatrice/src/game/abstract_game.cpp @@ -3,7 +3,7 @@ #include "../interface/widgets/tabs/tab_game.h" #include "player/player_logic.h" -AbstractGame::AbstractGame(QObject *_parent) : QObject(_parent) +AbstractGame::AbstractGame(TabGame *_tab) : QObject(_tab), tab(_tab) { gameMetaInfo = new GameMetaInfo(this); gameEventHandler = new GameEventHandler(this); diff --git a/cockatrice/src/game/abstract_game.h b/cockatrice/src/game/abstract_game.h index 5115ed5ca..2441bac2d 100644 --- a/cockatrice/src/game/abstract_game.h +++ b/cockatrice/src/game/abstract_game.h @@ -16,19 +16,26 @@ #include class CardItem; +class TabGame; class AbstractGame : public QObject { Q_OBJECT public: - explicit AbstractGame(QObject *parent); + explicit AbstractGame(TabGame *tab); + TabGame *tab; GameMetaInfo *gameMetaInfo; GameState *gameState; GameEventHandler *gameEventHandler; PlayerManager *playerManager; CardItem *activeCard; + TabGame *getTab() const + { + return tab; + } + GameMetaInfo *getGameMetaInfo() { return gameMetaInfo; diff --git a/cockatrice/src/game/arrow_registry.cpp b/cockatrice/src/game/arrow_registry.cpp deleted file mode 100644 index 286764b3b..000000000 --- a/cockatrice/src/game/arrow_registry.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "arrow_registry.h" - -#include "../game_graphics/board/arrow_item.h" - -void ArrowRegistry::insert(QSharedPointer data, ArrowItem *arrow) -{ - const ArrowKey key{data->creatorId, data->id}; - - if (auto *existing = take(data->creatorId, data->id)) { - existing->delArrow(); - } - - dataStore.insert(key, data); - items.insert(key, arrow); - byPlayer[data->creatorId].insert(data->id); -} - -ArrowItem *ArrowRegistry::take(int creatorId, int arrowId) -{ - const ArrowKey key{creatorId, arrowId}; - dataStore.remove(key); - auto &playerSet = byPlayer[creatorId]; - playerSet.remove(arrowId); - if (playerSet.isEmpty()) { - byPlayer.remove(creatorId); - } - return items.take(key); -} - -ArrowItem *ArrowRegistry::get(int creatorId, int arrowId) const -{ - return items.value(ArrowKey{creatorId, arrowId}, nullptr); -} - -bool ArrowRegistry::contains(int creatorId, int arrowId) const -{ - return items.contains(ArrowKey{creatorId, arrowId}); -} - -QSet ArrowRegistry::idsForPlayer(int playerId) const -{ - return byPlayer.value(playerId); -} - -QList ArrowRegistry::all() const -{ - return items.values(); -} \ No newline at end of file diff --git a/cockatrice/src/game/arrow_registry.h b/cockatrice/src/game/arrow_registry.h deleted file mode 100644 index ef98229a2..000000000 --- a/cockatrice/src/game/arrow_registry.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef COCKATRICE_ARROW_REGISTRY_H -#define COCKATRICE_ARROW_REGISTRY_H - -#include "board/arrow_data.h" - -#include -#include -#include - -class ArrowItem; - -struct ArrowKey -{ - int creatorId; - int arrowId; - - bool operator<(const ArrowKey &other) const - { - if (creatorId != other.creatorId) { - return creatorId < other.creatorId; - } - return arrowId < other.arrowId; - } -}; - -class ArrowRegistry -{ -public: - void insert(QSharedPointer data, ArrowItem *arrow); - ArrowItem *take(int creatorId, int arrowId); - - [[nodiscard]] ArrowItem *get(int creatorId, int arrowId) const; - [[nodiscard]] bool contains(int creatorId, int arrowId) const; - [[nodiscard]] QSet idsForPlayer(int playerId) const; - [[nodiscard]] QList all() const; - -private: - QMap> dataStore; - QMap items; - QMap> byPlayer; -}; - -#endif \ No newline at end of file diff --git a/cockatrice/src/game_graphics/board/abstract_card_drag_item.cpp b/cockatrice/src/game/board/abstract_card_drag_item.cpp similarity index 100% rename from cockatrice/src/game_graphics/board/abstract_card_drag_item.cpp rename to cockatrice/src/game/board/abstract_card_drag_item.cpp diff --git a/cockatrice/src/game_graphics/board/abstract_card_drag_item.h b/cockatrice/src/game/board/abstract_card_drag_item.h similarity index 100% rename from cockatrice/src/game_graphics/board/abstract_card_drag_item.h rename to cockatrice/src/game/board/abstract_card_drag_item.h diff --git a/cockatrice/src/game_graphics/board/abstract_card_item.cpp b/cockatrice/src/game/board/abstract_card_item.cpp similarity index 100% rename from cockatrice/src/game_graphics/board/abstract_card_item.cpp rename to cockatrice/src/game/board/abstract_card_item.cpp diff --git a/cockatrice/src/game_graphics/board/abstract_card_item.h b/cockatrice/src/game/board/abstract_card_item.h similarity index 91% rename from cockatrice/src/game_graphics/board/abstract_card_item.h rename to cockatrice/src/game/board/abstract_card_item.h index bdb5f7cf1..ed545e1ab 100644 --- a/cockatrice/src/game_graphics/board/abstract_card_item.h +++ b/cockatrice/src/game/board/abstract_card_item.h @@ -7,9 +7,9 @@ #ifndef ABSTRACTCARDITEM_H #define ABSTRACTCARDITEM_H +#include "../../game_graphics/board/graphics_item_type.h" #include "../card_dimensions.h" #include "arrow_target.h" -#include "graphics_item_type.h" #include #include @@ -44,11 +44,6 @@ signals: void deleteCardInfoPopup(QString cardName); void sigPixmapUpdated(); void cardShiftClicked(QString cardName); - void rightClicked(AbstractCardItem *card, QPoint screenPos); - void playSelected(AbstractCardItem *card); - void playSelectedFaceDown(AbstractCardItem *card); - void hideSelected(AbstractCardItem *card); - void selectionChanged(AbstractCardItem *card, bool selected); public: enum diff --git a/cockatrice/src/game_graphics/board/abstract_counter.cpp b/cockatrice/src/game/board/abstract_counter.cpp similarity index 97% rename from cockatrice/src/game_graphics/board/abstract_counter.cpp rename to cockatrice/src/game/board/abstract_counter.cpp index 219dd456e..18787a0bc 100644 --- a/cockatrice/src/game_graphics/board/abstract_counter.cpp +++ b/cockatrice/src/game/board/abstract_counter.cpp @@ -1,10 +1,10 @@ #include "abstract_counter.h" #include "../../client/settings/cache_settings.h" -#include "../../game/player/player_actions.h" -#include "../../game/player/player_logic.h" -#include "../../game_graphics/board/translate_counter_name.h" #include "../../interface/widgets/tabs/tab_game.h" +#include "../player/player_actions.h" +#include "../player/player_logic.h" +#include "translate_counter_name.h" #include #include diff --git a/cockatrice/src/game_graphics/board/abstract_counter.h b/cockatrice/src/game/board/abstract_counter.h similarity index 98% rename from cockatrice/src/game_graphics/board/abstract_counter.h rename to cockatrice/src/game/board/abstract_counter.h index b319a722d..b31bd1aa3 100644 --- a/cockatrice/src/game_graphics/board/abstract_counter.h +++ b/cockatrice/src/game/board/abstract_counter.h @@ -7,9 +7,9 @@ #ifndef COUNTER_H #define COUNTER_H -#include "../../game/board/counter_state.h" #include "../../interface/widgets/menus/tearoff_menu.h" #include "../player/menu/abstract_player_component.h" +#include "counter_state.h" #include #include diff --git a/cockatrice/src/game/board/arrow_data.cpp b/cockatrice/src/game/board/arrow_data.cpp index 9e89deed0..bbb70f474 100644 --- a/cockatrice/src/game/board/arrow_data.cpp +++ b/cockatrice/src/game/board/arrow_data.cpp @@ -1,10 +1,8 @@ #include "arrow_data.h" -ArrowData ArrowData::fromProto(const ServerInfo_Arrow &arrow, int creatorId, bool isLocalCreator) +ArrowData ArrowData::fromProto(const ServerInfo_Arrow &arrow) { ArrowData data; - data.creatorId = creatorId; - data.isLocalCreator = isLocalCreator; data.id = arrow.id(); data.startPlayerId = arrow.start_player_id(); data.startZone = QString::fromStdString(arrow.start_zone()); diff --git a/cockatrice/src/game/board/arrow_data.h b/cockatrice/src/game/board/arrow_data.h index 2752f97e3..a8b35dad6 100644 --- a/cockatrice/src/game/board/arrow_data.h +++ b/cockatrice/src/game/board/arrow_data.h @@ -8,18 +8,16 @@ struct ArrowData { - int creatorId = -1; - bool isLocalCreator = false; - int id = -1; - int startPlayerId = -1; - QString startZone = ""; - int startCardId = -1; - int targetPlayerId = -1; - QString targetZone = ""; - int targetCardId = -1; - QColor color = ""; + int id; + int startPlayerId; + QString startZone; + int startCardId; + int targetPlayerId; + QString targetZone; // empty = targeting a player + int targetCardId = -1; // -1 = targeting a player + QColor color; - static ArrowData fromProto(const ServerInfo_Arrow &arrow, int creatorId, bool isLocalCreator); + static ArrowData fromProto(const ServerInfo_Arrow &arrow); bool isPlayerTargeted() const { diff --git a/cockatrice/src/game_graphics/board/arrow_item.cpp b/cockatrice/src/game/board/arrow_item.cpp similarity index 89% rename from cockatrice/src/game_graphics/board/arrow_item.cpp rename to cockatrice/src/game/board/arrow_item.cpp index af6a6bf36..430477d76 100644 --- a/cockatrice/src/game_graphics/board/arrow_item.cpp +++ b/cockatrice/src/game/board/arrow_item.cpp @@ -2,11 +2,11 @@ #include "arrow_item.h" #include "../../client/settings/cache_settings.h" -#include "../../game/player/player_actions.h" -#include "../../game/player/player_logic.h" +#include "../../game_graphics/zones/card_zone.h" +#include "../player/player_actions.h" +#include "../player/player_logic.h" #include "../player/player_target.h" #include "../z_values.h" -#include "../zones/card_zone.h" #include "card_item.h" #include @@ -21,8 +21,12 @@ #include #include -ArrowItem::ArrowItem(QSharedPointer _data, ArrowTarget *_startItem, ArrowTarget *_targetItem) - : data(std::move(_data)), startItem(_startItem), targetItem(_targetItem) +ArrowItem::ArrowItem(PlayerLogic *_player, + int _id, + ArrowTarget *_startItem, + ArrowTarget *_targetItem, + const QColor &_color) + : player(_player), id(_id), startItem(_startItem), targetItem(_targetItem), color(_color) { setZValue(ZValues::ARROWS); @@ -48,7 +52,7 @@ ArrowItem::ArrowItem(QSharedPointer _data, ArrowTarget *_startI void ArrowItem::onTargetDestroyed() { - emit requestDeletion(data->creatorId, data->id); + emit requestDeletion(id); } void ArrowItem::delArrow() @@ -126,7 +130,7 @@ void ArrowItem::updatePath(const QPointF &endPoint) void ArrowItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/) { - QColor paintColor(data->color); + QColor paintColor(color); if (fullColor) { paintColor.setAlpha(200); } else { @@ -138,7 +142,7 @@ void ArrowItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*opti void ArrowItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { - if (!data->isLocalCreator) { + if (!player->getPlayerInfo()->getLocal()) { event->ignore(); return; } @@ -152,20 +156,14 @@ void ArrowItem::mousePressEvent(QGraphicsSceneMouseEvent *event) event->accept(); if (event->button() == Qt::RightButton) { - emit requestDeletion(data->creatorId, data->id); + emit requestDeletion(id); } } // ArrowDragItem ArrowDragItem::ArrowDragItem(PlayerLogic *_owner, ArrowTarget *_startItem, const QColor &_color, int _deleteInPhase) - : ArrowItem(QSharedPointer::create(ArrowData{.creatorId = _owner->getPlayerInfo()->getId(), - .isLocalCreator = true, - .id = -1, - .color = _color}), - _startItem, - nullptr), - player(_owner), deleteInPhase(_deleteInPhase) + : ArrowItem(_owner, -1, _startItem, nullptr, _color), deleteInPhase(_deleteInPhase) { } @@ -240,7 +238,7 @@ void ArrowDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) CardZoneLogic *startZone = startCard->getZone(); Command_CreateArrow cmd; - cmd.mutable_arrow_color()->CopyFrom(convertQColorToColor(data->color)); + cmd.mutable_arrow_color()->CopyFrom(convertQColorToColor(color)); cmd.set_start_player_id(startZone->getPlayer()->getPlayerInfo()->getId()); cmd.set_start_zone(startZone->getName().toStdString()); cmd.set_start_card_id(startCard->getId()); @@ -286,14 +284,7 @@ void ArrowDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) // ArrowAttachItem ArrowAttachItem::ArrowAttachItem(ArrowTarget *_startItem) - : ArrowItem( - QSharedPointer::create(ArrowData{.creatorId = _startItem->getOwner()->getPlayerInfo()->getId(), - .isLocalCreator = true, - .id = -1, - .color = Qt::green}), - _startItem, - nullptr), - player(_startItem->getOwner()) + : ArrowItem(_startItem->getOwner(), -1, _startItem, nullptr, Qt::green) { } diff --git a/cockatrice/src/game_graphics/board/arrow_item.h b/cockatrice/src/game/board/arrow_item.h similarity index 85% rename from cockatrice/src/game_graphics/board/arrow_item.h rename to cockatrice/src/game/board/arrow_item.h index 1c306e065..7dc0f9477 100644 --- a/cockatrice/src/game_graphics/board/arrow_item.h +++ b/cockatrice/src/game/board/arrow_item.h @@ -1,15 +1,20 @@ +/** + * @file arrow_item.h + * @ingroup GameGraphics + */ +//! \todo Document this file. + #ifndef ARROWITEM_H #define ARROWITEM_H -#include "../../game/board/arrow_data.h" #include "arrow_target.h" #include #include -#include class CardItem; class QGraphicsSceneMouseEvent; +class QMenu; class PlayerLogic; class ArrowItem : public QObject, public QGraphicsItem @@ -17,27 +22,25 @@ class ArrowItem : public QObject, public QGraphicsItem Q_OBJECT Q_INTERFACES(QGraphicsItem) signals: - void requestDeletion(int creatorId, int id); + void requestDeletion(int id); private: QPainterPath path; protected: - QSharedPointer data; + PlayerLogic *player; + int id; QPointer startItem; QPointer targetItem; bool targetLocked = false; + QColor color; bool fullColor = true; void mousePressEvent(QGraphicsSceneMouseEvent *event) override; public: - ArrowItem(QSharedPointer _data, ArrowTarget *_startItem, ArrowTarget *_targetItem); - + ArrowItem(PlayerLogic *_player, int _id, ArrowTarget *_startItem, ArrowTarget *_targetItem, const QColor &_color); void onTargetDestroyed(); - void delArrow(); - void updatePath(); - void updatePath(const QPointF &endPoint); void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; [[nodiscard]] QRectF boundingRect() const override @@ -48,13 +51,17 @@ public: { return path; } + + void updatePath(); + void updatePath(const QPointF &endPoint); + [[nodiscard]] int getId() const { - return data->id; + return id; } - [[nodiscard]] int getCreatorId() const + [[nodiscard]] PlayerLogic *getPlayer() const { - return data->creatorId; + return player; } [[nodiscard]] ArrowTarget *getStartItem() const { @@ -68,13 +75,14 @@ public: { targetLocked = _targetLocked; } + + void delArrow(); }; class ArrowDragItem : public ArrowItem { Q_OBJECT private: - PlayerLogic *player; int deleteInPhase; QList childArrows; QMetaObject::Connection positionConnection; @@ -92,7 +100,6 @@ class ArrowAttachItem : public ArrowItem { Q_OBJECT private: - PlayerLogic *player; QList childArrows; QMetaObject::Connection positionConnection; void attachCards(CardItem *startCard, const CardItem *targetCard); @@ -106,4 +113,4 @@ protected: void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override; }; -#endif \ No newline at end of file +#endif // ARROWITEM_H diff --git a/cockatrice/src/game_graphics/board/arrow_target.cpp b/cockatrice/src/game/board/arrow_target.cpp similarity index 92% rename from cockatrice/src/game_graphics/board/arrow_target.cpp rename to cockatrice/src/game/board/arrow_target.cpp index 79b21d921..edf526e4e 100644 --- a/cockatrice/src/game_graphics/board/arrow_target.cpp +++ b/cockatrice/src/game/board/arrow_target.cpp @@ -1,6 +1,6 @@ #include "arrow_target.h" -#include "../../game/player/player_logic.h" +#include "../player/player_logic.h" #include "arrow_item.h" ArrowTarget::ArrowTarget(PlayerLogic *_owner, QGraphicsItem *parent) : AbstractGraphicsItem(parent), owner(_owner) diff --git a/cockatrice/src/game_graphics/board/arrow_target.h b/cockatrice/src/game/board/arrow_target.h similarity index 93% rename from cockatrice/src/game_graphics/board/arrow_target.h rename to cockatrice/src/game/board/arrow_target.h index bf89c5456..664572705 100644 --- a/cockatrice/src/game_graphics/board/arrow_target.h +++ b/cockatrice/src/game/board/arrow_target.h @@ -7,7 +7,7 @@ #ifndef ARROWTARGET_H #define ARROWTARGET_H -#include "abstract_graphics_item.h" +#include "../../game_graphics/board/abstract_graphics_item.h" #include diff --git a/cockatrice/src/game_graphics/board/card_drag_item.cpp b/cockatrice/src/game/board/card_drag_item.cpp similarity index 96% rename from cockatrice/src/game_graphics/board/card_drag_item.cpp rename to cockatrice/src/game/board/card_drag_item.cpp index 49467c5c9..39fb9a390 100644 --- a/cockatrice/src/game_graphics/board/card_drag_item.cpp +++ b/cockatrice/src/game/board/card_drag_item.cpp @@ -1,9 +1,9 @@ #include "card_drag_item.h" +#include "../../game_graphics/zones/card_zone.h" +#include "../../game_graphics/zones/table_zone.h" +#include "../../game_graphics/zones/view_zone.h" #include "../game_scene.h" -#include "../zones/card_zone.h" -#include "../zones/table_zone.h" -#include "../zones/view_zone.h" #include "card_item.h" #include diff --git a/cockatrice/src/game_graphics/board/card_drag_item.h b/cockatrice/src/game/board/card_drag_item.h similarity index 100% rename from cockatrice/src/game_graphics/board/card_drag_item.h rename to cockatrice/src/game/board/card_drag_item.h diff --git a/cockatrice/src/game_graphics/board/card_item.cpp b/cockatrice/src/game/board/card_item.cpp similarity index 92% rename from cockatrice/src/game_graphics/board/card_item.cpp rename to cockatrice/src/game/board/card_item.cpp index cabe988c2..a08194540 100644 --- a/cockatrice/src/game_graphics/board/card_item.cpp +++ b/cockatrice/src/game/board/card_item.cpp @@ -1,14 +1,14 @@ #include "card_item.h" #include "../../client/settings/cache_settings.h" -#include "../../game/phase.h" -#include "../../game/player/player_actions.h" -#include "../../game/player/player_logic.h" -#include "../../game/zones/view_zone_logic.h" +#include "../../game_graphics/zones/table_zone.h" +#include "../../game_graphics/zones/view_zone.h" #include "../../interface/widgets/tabs/tab_game.h" #include "../game_scene.h" -#include "../zones/table_zone.h" -#include "../zones/view_zone.h" +#include "../phase.h" +#include "../player/player_actions.h" +#include "../player/player_logic.h" +#include "../zones/view_zone_logic.h" #include "arrow_item.h" #include "card_drag_item.h" @@ -40,7 +40,7 @@ void CardItem::prepareDelete() { if (owner != nullptr) { if (owner->getGame()->getActiveCard() == this) { - emit owner->requestCardMenuUpdate(nullptr); + owner->getPlayerMenu()->updateCardMenu(nullptr); owner->getGame()->setActiveCard(nullptr); } owner = nullptr; @@ -399,11 +399,8 @@ void CardItem::playCard(bool faceDown) emit tz->toggleTapped(); } else { if (SettingsCache::instance().getClickPlaysAllSelected()) { - if (faceDown) { - emit playSelectedFaceDown(this); - } else { - emit playSelected(this); - } + faceDown ? state->getZone()->getPlayer()->getPlayerActions()->actPlayFacedown() + : state->getZone()->getPlayer()->getPlayerActions()->actPlay(); } else { state->getZone()->getPlayer()->getPlayerActions()->playCard(this, faceDown); } @@ -463,7 +460,7 @@ void CardItem::handleClickedToPlay(bool shiftHeld) { if (isUnwritableRevealZone(state->getZone())) { if (SettingsCache::instance().getClickPlaysAllSelected()) { - emit hideSelected(this); + state->getZone()->getPlayer()->getPlayerActions()->actHide(); } else { state->getZone()->removeCard(this); } @@ -474,15 +471,21 @@ void CardItem::handleClickedToPlay(bool shiftHeld) void CardItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { - if (event->button() == Qt::RightButton && owner != nullptr) { - emit rightClicked(this, event->screenPos()); - return; - } - if ((event->modifiers() != Qt::AltModifier) && (event->button() == Qt::LeftButton) && - (!SettingsCache::instance().getDoubleClickToPlay())) { + if (event->button() == Qt::RightButton) { + + if (owner != nullptr) { + owner->getGame()->setActiveCard(this); + if (QMenu *cardMenu = owner->getPlayerMenu()->updateCardMenu(this)) { + cardMenu->popup(event->screenPos()); + return; + } + } + } else if ((event->modifiers() != Qt::AltModifier) && (event->button() == Qt::LeftButton) && + (!SettingsCache::instance().getDoubleClickToPlay())) { handleClickedToPlay(event->modifiers().testFlag(Qt::ShiftModifier)); } - if (owner != nullptr) { + + if (owner != nullptr) { // cards without owner will be deleted setCursor(Qt::OpenHandCursor); } AbstractCardItem::mouseReleaseEvent(event); @@ -528,14 +531,14 @@ bool CardItem::animationEvent() QVariant CardItem::itemChange(GraphicsItemChange change, const QVariant &value) { if ((change == ItemSelectedHasChanged) && owner != nullptr) { - bool selected = value.toBool(); - - if (selected) { + if (value == true) { owner->getGame()->setActiveCard(this); + owner->getPlayerMenu()->updateCardMenu(this); + } else if (owner->getGameScene()->selectedItems().isEmpty()) { + + owner->getGame()->setActiveCard(nullptr); + owner->getPlayerMenu()->updateCardMenu(nullptr); } - - emit selectionChanged(this, selected); } - return AbstractCardItem::itemChange(change, value); -} \ No newline at end of file +} diff --git a/cockatrice/src/game_graphics/board/card_item.h b/cockatrice/src/game/board/card_item.h similarity index 96% rename from cockatrice/src/game_graphics/board/card_item.h rename to cockatrice/src/game/board/card_item.h index 8efcd085d..451fed0c6 100644 --- a/cockatrice/src/game_graphics/board/card_item.h +++ b/cockatrice/src/game/board/card_item.h @@ -7,9 +7,9 @@ #ifndef CARDITEM_H #define CARDITEM_H -#include "../../game/board/card_state.h" -#include "../../game/zones/card_zone_logic.h" +#include "../zones/card_zone_logic.h" #include "abstract_card_item.h" +#include "card_state.h" #include #include @@ -55,10 +55,6 @@ public: CardZoneLogic *_zone = nullptr); void retranslateUi(); - [[nodiscard]] CardState *getState() const - { - return state; - } [[nodiscard]] CardZoneLogic *getZone() const { return state->getZone(); diff --git a/cockatrice/src/game/board/card_list.cpp b/cockatrice/src/game/board/card_list.cpp index 0080b5ae6..c324ca10a 100644 --- a/cockatrice/src/game/board/card_list.cpp +++ b/cockatrice/src/game/board/card_list.cpp @@ -1,6 +1,6 @@ #include "card_list.h" -#include "../../game_graphics/board/card_item.h" +#include "card_item.h" #include #include diff --git a/cockatrice/src/game/board/card_state.cpp b/cockatrice/src/game/board/card_state.cpp index 4319400d7..fe1aa9b73 100644 --- a/cockatrice/src/game/board/card_state.cpp +++ b/cockatrice/src/game/board/card_state.cpp @@ -18,7 +18,7 @@ void CardState::setZone(CardZoneLogic *_zone) } zone = _zone; - emit zoneChanged(this, zone); + emit zoneChanged(zone); emit stateChanged(); } diff --git a/cockatrice/src/game/board/card_state.h b/cockatrice/src/game/board/card_state.h index 0498b1aa2..ef17f408c 100644 --- a/cockatrice/src/game/board/card_state.h +++ b/cockatrice/src/game/board/card_state.h @@ -31,7 +31,7 @@ signals: void doesntUntapChanged(bool newValue); void destroyOnZoneChangeChanged(bool newValue); void attachedToChanged(CardItem *newAttachedTo); - void zoneChanged(CardState *changedCard, CardZoneLogic *newZone); + void zoneChanged(CardZoneLogic *newZone); public: explicit CardState(QObject *parent, CardZoneLogic *_zone) : QObject(parent), zone(_zone) diff --git a/cockatrice/src/game_graphics/board/counter_general.cpp b/cockatrice/src/game/board/counter_general.cpp similarity index 95% rename from cockatrice/src/game_graphics/board/counter_general.cpp rename to cockatrice/src/game/board/counter_general.cpp index 379c6f837..5147ede6b 100644 --- a/cockatrice/src/game_graphics/board/counter_general.cpp +++ b/cockatrice/src/game/board/counter_general.cpp @@ -1,7 +1,7 @@ #include "counter_general.h" +#include "../../game_graphics/board/abstract_graphics_item.h" #include "../../interface/pixel_map_generator.h" -#include "abstract_graphics_item.h" #include diff --git a/cockatrice/src/game_graphics/board/counter_general.h b/cockatrice/src/game/board/counter_general.h similarity index 100% rename from cockatrice/src/game_graphics/board/counter_general.h rename to cockatrice/src/game/board/counter_general.h diff --git a/cockatrice/src/game_graphics/board/translate_counter_name.cpp b/cockatrice/src/game/board/translate_counter_name.cpp similarity index 100% rename from cockatrice/src/game_graphics/board/translate_counter_name.cpp rename to cockatrice/src/game/board/translate_counter_name.cpp diff --git a/cockatrice/src/game_graphics/board/translate_counter_name.h b/cockatrice/src/game/board/translate_counter_name.h similarity index 100% rename from cockatrice/src/game_graphics/board/translate_counter_name.h rename to cockatrice/src/game/board/translate_counter_name.h diff --git a/cockatrice/src/game_graphics/card_dimensions.h b/cockatrice/src/game/card_dimensions.h similarity index 100% rename from cockatrice/src/game_graphics/card_dimensions.h rename to cockatrice/src/game/card_dimensions.h diff --git a/cockatrice/src/game_graphics/deckview/deck_view.cpp b/cockatrice/src/game/deckview/deck_view.cpp similarity index 98% rename from cockatrice/src/game_graphics/deckview/deck_view.cpp rename to cockatrice/src/game/deckview/deck_view.cpp index a5d0fa3bc..ced02c8db 100644 --- a/cockatrice/src/game_graphics/deckview/deck_view.cpp +++ b/cockatrice/src/game/deckview/deck_view.cpp @@ -360,16 +360,6 @@ void DeckViewScene::rebuildTree() return; } - QStringList requiredZones = {DECK_ZONE_MAIN, DECK_ZONE_SIDE}; - - for (const QString &zoneName : requiredZones) { - if (!cardContainers.contains(zoneName)) { - auto *container = new DeckViewCardContainer(zoneName); - cardContainers.insert(zoneName, container); - addItem(container); - } - } - for (auto *currentZone : deck->getZoneNodes()) { DeckViewCardContainer *container = cardContainers.value(currentZone->getName(), 0); if (!container) { diff --git a/cockatrice/src/game_graphics/deckview/deck_view.h b/cockatrice/src/game/deckview/deck_view.h similarity index 100% rename from cockatrice/src/game_graphics/deckview/deck_view.h rename to cockatrice/src/game/deckview/deck_view.h diff --git a/cockatrice/src/game_graphics/deckview/deck_view_container.cpp b/cockatrice/src/game/deckview/deck_view_container.cpp similarity index 99% rename from cockatrice/src/game_graphics/deckview/deck_view_container.cpp rename to cockatrice/src/game/deckview/deck_view_container.cpp index 21284c517..cbd6c2bad 100644 --- a/cockatrice/src/game_graphics/deckview/deck_view_container.cpp +++ b/cockatrice/src/game/deckview/deck_view_container.cpp @@ -209,7 +209,6 @@ void DeckViewContainer::refreshShortcuts() loadLocalButton->setShortcut(shortcuts.getSingleShortcut("DeckViewContainer/loadLocalButton")); loadRemoteButton->setShortcut(shortcuts.getSingleShortcut("DeckViewContainer/loadRemoteButton")); loadFromClipboardButton->setShortcut(shortcuts.getSingleShortcut("DeckViewContainer/loadFromClipboardButton")); - loadFromWebsiteButton->setShortcut(shortcuts.getSingleShortcut("DeckViewContainer/loadFromWebsiteButton")); unloadDeckButton->setShortcut(shortcuts.getSingleShortcut("DeckViewContainer/unloadDeckButton")); readyStartButton->setShortcut(shortcuts.getSingleShortcut("DeckViewContainer/readyStartButton")); sideboardLockButton->setShortcut(shortcuts.getSingleShortcut("DeckViewContainer/sideboardLockButton")); diff --git a/cockatrice/src/game_graphics/deckview/deck_view_container.h b/cockatrice/src/game/deckview/deck_view_container.h similarity index 100% rename from cockatrice/src/game_graphics/deckview/deck_view_container.h rename to cockatrice/src/game/deckview/deck_view_container.h diff --git a/cockatrice/src/game_graphics/deckview/tabbed_deck_view_container.cpp b/cockatrice/src/game/deckview/tabbed_deck_view_container.cpp similarity index 100% rename from cockatrice/src/game_graphics/deckview/tabbed_deck_view_container.cpp rename to cockatrice/src/game/deckview/tabbed_deck_view_container.cpp diff --git a/cockatrice/src/game_graphics/deckview/tabbed_deck_view_container.h b/cockatrice/src/game/deckview/tabbed_deck_view_container.h similarity index 100% rename from cockatrice/src/game_graphics/deckview/tabbed_deck_view_container.h rename to cockatrice/src/game/deckview/tabbed_deck_view_container.h diff --git a/cockatrice/src/game_graphics/dialogs/dlg_create_token.cpp b/cockatrice/src/game/dialogs/dlg_create_token.cpp similarity index 100% rename from cockatrice/src/game_graphics/dialogs/dlg_create_token.cpp rename to cockatrice/src/game/dialogs/dlg_create_token.cpp diff --git a/cockatrice/src/game_graphics/dialogs/dlg_create_token.h b/cockatrice/src/game/dialogs/dlg_create_token.h similarity index 100% rename from cockatrice/src/game_graphics/dialogs/dlg_create_token.h rename to cockatrice/src/game/dialogs/dlg_create_token.h diff --git a/cockatrice/src/game_graphics/dialogs/dlg_move_top_cards_until.cpp b/cockatrice/src/game/dialogs/dlg_move_top_cards_until.cpp similarity index 100% rename from cockatrice/src/game_graphics/dialogs/dlg_move_top_cards_until.cpp rename to cockatrice/src/game/dialogs/dlg_move_top_cards_until.cpp diff --git a/cockatrice/src/game_graphics/dialogs/dlg_move_top_cards_until.h b/cockatrice/src/game/dialogs/dlg_move_top_cards_until.h similarity index 100% rename from cockatrice/src/game_graphics/dialogs/dlg_move_top_cards_until.h rename to cockatrice/src/game/dialogs/dlg_move_top_cards_until.h diff --git a/cockatrice/src/game_graphics/dialogs/dlg_roll_dice.cpp b/cockatrice/src/game/dialogs/dlg_roll_dice.cpp similarity index 100% rename from cockatrice/src/game_graphics/dialogs/dlg_roll_dice.cpp rename to cockatrice/src/game/dialogs/dlg_roll_dice.cpp diff --git a/cockatrice/src/game_graphics/dialogs/dlg_roll_dice.h b/cockatrice/src/game/dialogs/dlg_roll_dice.h similarity index 100% rename from cockatrice/src/game_graphics/dialogs/dlg_roll_dice.h rename to cockatrice/src/game/dialogs/dlg_roll_dice.h diff --git a/cockatrice/src/game/game.cpp b/cockatrice/src/game/game.cpp index 4c8b109c2..38477f7f7 100644 --- a/cockatrice/src/game/game.cpp +++ b/cockatrice/src/game/game.cpp @@ -4,16 +4,16 @@ #include -Game::Game(QObject *_parent, - bool isLocalGame, +Game::Game(TabGame *_tab, QList &_clients, const Event_GameJoined &event, const QMap &_roomGameTypes) - : AbstractGame(_parent) + : AbstractGame(_tab) { gameMetaInfo->setFromProto(event.game_info()); gameMetaInfo->setRoomGameTypes(_roomGameTypes); - gameState = new GameState(this, 0, event.host_id(), isLocalGame, _clients, false, event.resuming(), -1, false); + gameState = new GameState(this, 0, event.host_id(), tab->getTabSupervisor()->getIsLocalGame(), _clients, false, + event.resuming(), -1, false); connect(gameMetaInfo, &GameMetaInfo::startedChanged, gameState, &GameState::onStartedChanged); playerManager = new PlayerManager(this, event.player_id(), event.judge(), event.spectator()); gameMetaInfo->setStarted(false); diff --git a/cockatrice/src/game/game.h b/cockatrice/src/game/game.h index 4f912664c..ccdb679df 100644 --- a/cockatrice/src/game/game.h +++ b/cockatrice/src/game/game.h @@ -16,8 +16,7 @@ class Game : public AbstractGame Q_OBJECT public: - Game(QObject *parent, - bool isLocalGame, + Game(TabGame *tab, QList &_clients, const Event_GameJoined &event, const QMap &_roomGameTypes); diff --git a/cockatrice/src/game/game_event_handler.cpp b/cockatrice/src/game/game_event_handler.cpp index 4a96eebdb..b338deaea 100644 --- a/cockatrice/src/game/game_event_handler.cpp +++ b/cockatrice/src/game/game_event_handler.cpp @@ -1,8 +1,8 @@ #include "game_event_handler.h" -#include "../game_graphics/log/message_log_widget.h" #include "../interface/widgets/tabs/tab_game.h" #include "abstract_game.h" +#include "log/message_log_widget.h" #include #include @@ -213,25 +213,11 @@ void GameEventHandler::handleChatMessageSent(const QString &chatMessage) sendGameCommand(cmd); } -void GameEventHandler::handleArrowDeletion(int creatorId, int arrowId) +void GameEventHandler::handleArrowDeletion(int arrowId) { Command_DeleteArrow cmd; cmd.set_arrow_id(arrowId); - - auto preparedCommand = prepareGameCommand(cmd); - - connect(preparedCommand, &PendingCommand::finished, this, [creatorId, arrowId, this](const Response &response) { - handleArrowDeletionFinished(response, creatorId, arrowId); - }); - - sendGameCommand(preparedCommand); -} - -void GameEventHandler::handleArrowDeletionFinished(const Response &response, int creatorId, int arrowId) -{ - if (response.response_code() == Response::RespNameNotFound) { - emit arrowDeleted(creatorId, arrowId); - } + sendGameCommand(cmd); } void GameEventHandler::eventSpectatorSay(const Event_GameSay &event, diff --git a/cockatrice/src/game/game_event_handler.h b/cockatrice/src/game/game_event_handler.h index f47116949..7587ab46d 100644 --- a/cockatrice/src/game/game_event_handler.h +++ b/cockatrice/src/game/game_event_handler.h @@ -60,8 +60,7 @@ public: void handleActivePhaseChanged(int phase); void handleGameLeft(); void handleChatMessageSent(const QString &chatMessage); - void handleArrowDeletion(int creatorId, int arrowId); - void handleArrowDeletionFinished(const Response &response, int creatorId, int arrowId); + void handleArrowDeletion(int arrowId); void eventSpectatorSay(const Event_GameSay &event, int eventPlayerId, const GameEventContext &context); void eventSpectatorLeave(const Event_Leave &event, int eventPlayerId, const GameEventContext &context); @@ -113,7 +112,6 @@ signals: void containerProcessingStarted(GameEventContext context); void setContextJudgeName(QString judgeName); void containerProcessingDone(); - void arrowDeleted(int creatorId, int arrowId); void logSpectatorSay(ServerInfo_User userInfo, QString message); void logSpectatorLeave(QString name, QString reason); void logGameStart(); diff --git a/cockatrice/src/game_graphics/game_scene.cpp b/cockatrice/src/game/game_scene.cpp similarity index 81% rename from cockatrice/src/game_graphics/game_scene.cpp rename to cockatrice/src/game/game_scene.cpp index b9816a602..500c1cbe0 100644 --- a/cockatrice/src/game_graphics/game_scene.cpp +++ b/cockatrice/src/game/game_scene.cpp @@ -1,17 +1,13 @@ #include "game_scene.h" #include "../client/settings/cache_settings.h" -#include "../game/abstract_game.h" -#include "../game/player/player_actions.h" -#include "../game/player/player_logic.h" -#include "../game_graphics/player/player_graphics_item.h" +#include "../game_graphics/zones/select_zone.h" +#include "../game_graphics/zones/view_zone.h" +#include "../game_graphics/zones/view_zone_widget.h" #include "board/card_item.h" #include "phases_toolbar.h" -#include "player/menu/player_menu.h" #include "player/player_graphics_item.h" -#include "zones/select_zone.h" -#include "zones/view_zone.h" -#include "zones/view_zone_widget.h" +#include "player/player_logic.h" #include #include @@ -76,80 +72,6 @@ QList GameScene::selectedCards() const return selectedCards; } -void GameScene::onCardSelectionChanged(AbstractCardItem *abstractCard, bool selected) -{ - CardItem *card = qobject_cast(abstractCard); - if (!card || !card->getOwner()) { - return; - } - - auto *owner = card->getOwner(); - - if (selected) { - owner->requestCardMenuUpdate(card); - return; - } - - if (selectedItems().isEmpty()) { - owner->getGame()->setActiveCard(nullptr); - owner->requestCardMenuUpdate(nullptr); - } -} - -void GameScene::onCardRightClicked(AbstractCardItem *abstractCard, QPoint screenPos) -{ - auto *card = qobject_cast(abstractCard); - if (!card) { - return; - } - if (!card->getOwner()) { - return; - } - auto *view = playerViews.value(card->getOwner()->getPlayerInfo()->getId()); - if (!view) { - return; - } - - card->getOwner()->getGame()->setActiveCard(card); - - if (auto *menu = view->getPlayerMenu()->updateCardMenu(card)) { - menu->popup(screenPos); - } -} - -void GameScene::playSelected(AbstractCardItem *card) -{ - if (!card) { - return; - } - if (!card->getOwner()) { - return; - } - card->getOwner()->getPlayerActions()->actPlay(selectedCards()); -} - -void GameScene::playSelectedFaceDown(AbstractCardItem *card) -{ - if (!card) { - return; - } - if (!card->getOwner()) { - return; - } - card->getOwner()->getPlayerActions()->actPlayFacedown(selectedCards()); -} - -void GameScene::hideSelected(AbstractCardItem *card) -{ - if (!card) { - return; - } - if (!card->getOwner()) { - return; - } - card->getOwner()->getPlayerActions()->actHide(selectedCards()); -} - /** * @brief Adds a player to the scene and stores their graphics item. * @param player Player to add. @@ -160,11 +82,9 @@ void GameScene::addPlayer(PlayerLogic *player) { qCInfo(GameScenePlayerAdditionRemovalLog) << "GameScene::addPlayer name=" << player->getPlayerInfo()->getName(); - auto *view = new PlayerGraphicsItem(player); - - playerViews.insert(player->getPlayerInfo()->getId(), view); - addItem(view); - connect(view, &PlayerGraphicsItem::sizeChanged, this, &GameScene::rearrange); + playerViews.insert(player->getPlayerInfo()->getId(), player->getGraphicsItem()); + addItem(player->getGraphicsItem()); + connect(player->getGraphicsItem(), &PlayerGraphicsItem::sizeChanged, this, &GameScene::rearrange); connect(player, &PlayerLogic::concededChanged, this, [this](int id, bool conceded) { if (conceded) { @@ -173,13 +93,11 @@ void GameScene::addPlayer(PlayerLogic *player) rearrange(); }); - connect(player, &PlayerLogic::requestZoneViewToggle, this, &GameScene::toggleZoneView); - connect(player, &PlayerLogic::requestRevealedZoneView, this, &GameScene::addRevealedZoneView); - connect(player, &PlayerLogic::arrowDeleted, this, &GameScene::deleteArrow); - connect(player, &PlayerLogic::arrowCreateRequested, this, &GameScene::addArrow); - connect(player, &PlayerLogic::arrowDeleteRequested, this, &GameScene::requestArrowDeletion); - connect(player, &PlayerLogic::arrowsClearedLocally, this, - [this, id = player->getPlayerInfo()->getId()]() { clearArrowsForPlayerLocally(id); }); + connect(player, &PlayerLogic::arrowDeleted, this, &GameScene::onArrowDeleted); + connect(player, &PlayerLogic::arrowCreateRequested, this, &GameScene::onArrowCreateRequested); + connect(player, &PlayerLogic::arrowDeleteRequested, this, &GameScene::onArrowDeleteRequested); + connect(player, &PlayerLogic::arrowsCleared, this, + [this, id = player->getPlayerInfo()->getId()]() { clearArrowsForPlayer(id); }); connect(player->getPlayerEventHandler(), &PlayerEventHandler::cardZoneChanged, this, &GameScene::onCardZoneChanged); @@ -205,7 +123,6 @@ void GameScene::removePlayer(PlayerLogic *player) } auto *view = playerViews.take(player->getPlayerInfo()->getId()); removeItem(view); - view->deleteLater(); rearrange(); } @@ -287,7 +204,7 @@ QList GameScene::collectActivePlayers(int &firstPlayerIndex) cons bool firstPlayerFound = false; for (auto *pgItem : playerViews.values()) { - PlayerLogic *p = pgItem->getLogic(); + PlayerLogic *p = pgItem->getPlayer(); if (p && !p->getConceded()) { activePlayers.append(p); if (!firstPlayerFound && p->getPlayerInfo()->getLocal()) { @@ -358,12 +275,12 @@ QSizeF GameScene::computeSceneSizeAndPlayerLayout(const QList &pl for (int j = 0; j < rowsInColumn; ++j) { PlayerLogic *player = playersIter.next(); if (col == 0) { - playersByColumn[col].prepend(playerViews.value(player->getPlayerInfo()->getId())); + playersByColumn[col].prepend(player->getGraphicsItem()); } else { - playersByColumn[col].append(playerViews.value(player->getPlayerInfo()->getId())); + playersByColumn[col].append(player->getGraphicsItem()); } - auto *pgItem = playerViews.value(player->getPlayerInfo()->getId()); + auto *pgItem = player->getGraphicsItem(); thisColumnHeight += pgItem->boundingRect().height() + playerAreaSpacing; columnWidth[col] = std::max(columnWidth[col], (int)pgItem->boundingRect().width()); } @@ -450,62 +367,62 @@ void GameScene::resizeColumnsAndPlayers(const QList &minWidthByColumn, qr } } -void GameScene::addArrow(QSharedPointer data) +void GameScene::onArrowCreateRequested(const ArrowData &data) { - auto *startView = playerViews.value(data->startPlayerId); - auto *targetView = playerViews.value(data->targetPlayerId); + auto *startView = playerViews.value(data.startPlayerId); + auto *targetView = playerViews.value(data.targetPlayerId); if (!startView || !targetView) { return; } - PlayerLogic *startLogic = startView->getLogic(); - auto *startZone = startLogic->getZones().value(data->startZone); + PlayerLogic *startLogic = startView->getPlayer(); + auto *startZone = startLogic->getZones().value(data.startZone); if (!startZone) { return; } - CardItem *startCard = startZone->getCard(data->startCardId); + CardItem *startCard = startZone->getCard(data.startCardId); if (!startCard) { return; } ArrowTarget *targetItem = nullptr; - if (data->isPlayerTargeted()) { + if (data.isPlayerTargeted()) { targetItem = targetView->getPlayerTarget(); } else { - auto *zone = targetView->getLogic()->getZones().value(data->targetZone); + auto *zone = targetView->getPlayer()->getZones().value(data.targetZone); if (zone) { - targetItem = zone->getCard(data->targetCardId); + targetItem = zone->getCard(data.targetCardId); } } if (!targetItem) { return; } - auto *arrow = new ArrowItem(data, startCard, targetItem); + auto *arrow = new ArrowItem(startView->getPlayer(), data.id, startCard, targetItem, data.color); addItem(arrow); - arrowRegistry.insert(data, arrow); - connect(arrow, &ArrowItem::requestDeletion, this, &GameScene::requestArrowDeletion); + arrowRegistry.insert(data.id, arrow); + connect(arrow, &ArrowItem::requestDeletion, this, &GameScene::onArrowDeleteRequested); } -void GameScene::deleteArrow(int playerId, int arrowId) +void GameScene::onArrowDeleted(int arrowId) { - if (auto *arrow = arrowRegistry.take(playerId, arrowId)) { - arrow->delArrow(); + if (arrowRegistry.contains(arrowId)) { + arrowRegistry.take(arrowId)->delArrow(); } } -void GameScene::requestArrowDeletion(int playerId, int arrowId) +void GameScene::onArrowDeleteRequested(int arrowId) { - if (arrowRegistry.contains(playerId, arrowId)) { - emit arrowDeletionRequested(playerId, arrowId); + if (arrowRegistry.contains(arrowId)) { + emit requestArrowDeletion(arrowId); } } void GameScene::onCardZoneChanged(CardItem *card, bool sameZone) { QList toDelete; - for (auto *arrow : arrowRegistry.all()) { + for (auto *arrow : arrowRegistry.values()) { if (arrow->getStartItem() == card || arrow->getTargetItem() == card) { if (sameZone) { arrow->updatePath(); @@ -515,21 +432,16 @@ void GameScene::onCardZoneChanged(CardItem *card, bool sameZone) } } for (auto *arrow : toDelete) { - deleteArrow(arrow->getCreatorId(), arrow->getId()); + emit requestArrowDeletion(arrow->getId()); } } void GameScene::clearArrowsForPlayer(int playerId) { - for (int arrowId : arrowRegistry.idsForPlayer(playerId)) { - emit requestArrowDeletion(playerId, arrowId); - } -} - -void GameScene::clearArrowsForPlayerLocally(int playerId) -{ - for (int arrowId : arrowRegistry.idsForPlayer(playerId)) { - arrowRegistry.take(playerId, arrowId)->delArrow(); + for (auto *arrow : arrowRegistry.values()) { + if (arrow->getPlayer()->getPlayerInfo()->getId() == playerId) { + emit requestArrowDeletion(arrow->getId()); + } } } diff --git a/cockatrice/src/game_graphics/game_scene.h b/cockatrice/src/game/game_scene.h similarity index 88% rename from cockatrice/src/game_graphics/game_scene.h rename to cockatrice/src/game/game_scene.h index 74e979556..235ce6550 100644 --- a/cockatrice/src/game_graphics/game_scene.h +++ b/cockatrice/src/game/game_scene.h @@ -1,10 +1,9 @@ #ifndef GAMESCENE_H #define GAMESCENE_H -#include "../game/arrow_registry.h" -#include "../game/board/arrow_data.h" -#include "../game/zones/card_zone_logic.h" +#include "board/arrow_data.h" #include "board/arrow_item.h" +#include "zones/card_zone_logic.h" #include #include @@ -46,7 +45,7 @@ private: PhasesToolbar *phasesToolbar; ///< Toolbar showing game phases QMap playerViews; ///< ID lookup for player graphics items QList> playersByColumn; ///< Players organized by column - ArrowRegistry arrowRegistry; ///< ID registry for arrow graphics items + QMap arrowRegistry; ///< ID registry for arrow graphics items QList zoneViews; ///< Active zone view widgets QSize viewSize; ///< Current view size QPointer hoveredCard; ///< Currently hovered card @@ -97,16 +96,6 @@ public: */ void removePlayer(PlayerLogic *player); - QMap getPlayers() const - { - return playerViews; - } - - PlayerGraphicsItem *viewForPlayer(int playerId) - { - return playerViews.value(playerId); - } - /** * @brief Adjusts the global rotation offset for player layout. * @param rotationAdjustment Number of positions to rotate. @@ -192,11 +181,6 @@ public: void stopRubberBand(); public slots: - void onCardSelectionChanged(AbstractCardItem *card, bool selected); - void onCardRightClicked(AbstractCardItem *card, QPoint screenPos); - void playSelected(AbstractCardItem *card); - void playSelectedFaceDown(AbstractCardItem *card); - void hideSelected(AbstractCardItem *card); /** @brief Toggles a zone view for a player. */ void toggleZoneView(PlayerLogic *player, const QString &zoneName, int numberCards, bool isReversed = false); @@ -217,16 +201,11 @@ public slots: QTransform getViewTransform() const; QTransform getViewportTransform() const; - /// Directly modifies the scene - void addArrow(QSharedPointer data); - void deleteArrow(int playerId, int arrowId); - void clearArrowsForPlayer(int playerId); - void clearArrowsForPlayerLocally(int playerId); - - /// Queues up arrow deletion but doesn't directly modify the scene - void requestArrowDeletion(int playerId, int arrowId); - + void onArrowCreateRequested(const ArrowData &data); + void onArrowDeleted(int arrowId); + void onArrowDeleteRequested(int arrowId); void onCardZoneChanged(CardItem *card, bool sameZone); + void clearArrowsForPlayer(int playerId); protected: /** @brief Handles hover updates. */ @@ -239,7 +218,7 @@ signals: void sigStartRubberBand(const QPointF &selectionOrigin); void sigResizeRubberBand(const QPointF &cursorPoint, int selectedCount); void sigStopRubberBand(); - void arrowDeletionRequested(int creatorId, int arrowId); + void requestArrowDeletion(int arrowId); }; #endif diff --git a/cockatrice/src/game_graphics/game_view.cpp b/cockatrice/src/game/game_view.cpp similarity index 92% rename from cockatrice/src/game_graphics/game_view.cpp rename to cockatrice/src/game/game_view.cpp index 41befd9a4..4ba41cffb 100644 --- a/cockatrice/src/game_graphics/game_view.cpp +++ b/cockatrice/src/game/game_view.cpp @@ -34,6 +34,7 @@ GameView::GameView(GameScene *scene, QWidget *parent) : QGraphicsView(scene, par { setBackgroundBrush(QBrush(QColor(0, 0, 0))); setRenderHints(QPainter::TextAntialiasing | QPainter::Antialiasing); + setFocusPolicy(Qt::ClickFocus); setViewportUpdateMode(BoundingRectViewportUpdate); connect(scene, &GameScene::sceneRectChanged, this, &GameView::updateSceneRect); @@ -43,9 +44,6 @@ GameView::GameView(GameScene *scene, QWidget *parent) : QGraphicsView(scene, par connect(scene, &GameScene::sigStopRubberBand, this, &GameView::stopRubberBand); connect(scene, &QGraphicsScene::selectionChanged, this, [this]() { updateTotalSelectionCount(); }); - setFocusDisabled(SettingsCache::instance().getKeepGameChatFocus()); - connect(&SettingsCache::instance(), &SettingsCache::keepGameChatFocusChanged, this, &GameView::setFocusDisabled); - aCloseMostRecentZoneView = new QAction(this); connect(aCloseMostRecentZoneView, &QAction::triggered, scene, &GameScene::closeMostRecentZoneView); @@ -188,12 +186,3 @@ void GameView::updateTotalSelectionCount(const QSize &viewSize) totalCountLabel->hide(); } } - -/** - * Disabling focus on the game view will allow chat to maintain the autofocusing behavior of pre 2.10.3, - * at the cost of disabling the zone view search bar. - */ -void GameView::setFocusDisabled(bool disabled) -{ - setFocusPolicy(disabled ? Qt::NoFocus : Qt::ClickFocus); -} diff --git a/cockatrice/src/game_graphics/game_view.h b/cockatrice/src/game/game_view.h similarity index 95% rename from cockatrice/src/game_graphics/game_view.h rename to cockatrice/src/game/game_view.h index 80e8e96b5..15abad9af 100644 --- a/cockatrice/src/game_graphics/game_view.h +++ b/cockatrice/src/game/game_view.h @@ -31,7 +31,6 @@ private slots: void stopRubberBand(); void refreshShortcuts(); void updateTotalSelectionCount(const QSize &viewSize = QSize()); - void setFocusDisabled(bool disabled); public slots: void updateSceneRect(const QRectF &rect); diff --git a/cockatrice/src/game_graphics/hand_counter.cpp b/cockatrice/src/game/hand_counter.cpp similarity index 96% rename from cockatrice/src/game_graphics/hand_counter.cpp rename to cockatrice/src/game/hand_counter.cpp index 35989ff38..a853ae2de 100644 --- a/cockatrice/src/game_graphics/hand_counter.cpp +++ b/cockatrice/src/game/hand_counter.cpp @@ -1,6 +1,6 @@ #include "hand_counter.h" -#include "zones/card_zone.h" +#include "../game_graphics/zones/card_zone.h" #include #include diff --git a/cockatrice/src/game_graphics/hand_counter.h b/cockatrice/src/game/hand_counter.h similarity index 87% rename from cockatrice/src/game_graphics/hand_counter.h rename to cockatrice/src/game/hand_counter.h index 9aa65d514..41ab3b5b2 100644 --- a/cockatrice/src/game_graphics/hand_counter.h +++ b/cockatrice/src/game/hand_counter.h @@ -7,8 +7,8 @@ #ifndef HANDCOUNTER_H #define HANDCOUNTER_H -#include "board/abstract_graphics_item.h" -#include "board/graphics_item_type.h" +#include "../game_graphics/board/abstract_graphics_item.h" +#include "../game_graphics/board/graphics_item_type.h" #include diff --git a/cockatrice/src/game_graphics/log/message_log_widget.cpp b/cockatrice/src/game/log/message_log_widget.cpp similarity index 98% rename from cockatrice/src/game_graphics/log/message_log_widget.cpp rename to cockatrice/src/game/log/message_log_widget.cpp index ccd903b04..fe564b531 100644 --- a/cockatrice/src/game_graphics/log/message_log_widget.cpp +++ b/cockatrice/src/game/log/message_log_widget.cpp @@ -1,13 +1,13 @@ #include "message_log_widget.h" -#include "../../client/settings/card_counter_settings.h" #include "../../client/sound_engine.h" -#include "../../game/phase.h" -#include "../../game/player/player_logic.h" #include "../../interface/widgets/tabs/tab_game.h" #include "../board/card_item.h" #include "../board/translate_counter_name.h" +#include "../phase.h" +#include "../player/player_logic.h" +#include <../../client/settings/card_counter_settings.h> #include #include #include @@ -650,16 +650,14 @@ void MessageLogWidget::logSetCardCounter(PlayerLogic *player, QString cardName, QString finalStr; int delta = abs(oldValue - value); if (value > oldValue) { - finalStr = tr("%1 places %2 %3%4 counter(s) on %5 (now %6).", "", delta); + finalStr = tr("%1 places %2 \"%3\" counter(s) on %4 (now %5).", "", delta); } else { - finalStr = tr("%1 removes %2 %3%4 counter(s) from %5 (now %6).", "", delta); + finalStr = tr("%1 removes %2 \"%3\" counter(s) from %4 (now %5).", "", delta); } auto &cardCounterSettings = SettingsCache::instance().cardCounters(); - QString hex = cardCounterSettings.color(counterId).name(); appendHtmlServerMessage(finalStr.arg(sanitizeHtml(player->getPlayerInfo()->getName())) .arg("" + QString::number(delta) + "") - .arg("") .arg(cardCounterSettings.displayName(counterId)) .arg(cardLink(std::move(cardName))) .arg(value)); diff --git a/cockatrice/src/game_graphics/log/message_log_widget.h b/cockatrice/src/game/log/message_log_widget.h similarity index 99% rename from cockatrice/src/game_graphics/log/message_log_widget.h rename to cockatrice/src/game/log/message_log_widget.h index a145d358d..9f1990ac4 100644 --- a/cockatrice/src/game_graphics/log/message_log_widget.h +++ b/cockatrice/src/game/log/message_log_widget.h @@ -7,8 +7,8 @@ #ifndef MESSAGELOGWIDGET_H #define MESSAGELOGWIDGET_H -#include "../../game/zones/card_zone_logic.h" #include "../../interface/widgets/server/chat_view/chat_view.h" +#include "../zones/card_zone_logic.h" class AbstractGame; class CardItem; diff --git a/cockatrice/src/game_graphics/phases_toolbar.cpp b/cockatrice/src/game/phases_toolbar.cpp similarity index 100% rename from cockatrice/src/game_graphics/phases_toolbar.cpp rename to cockatrice/src/game/phases_toolbar.cpp diff --git a/cockatrice/src/game_graphics/phases_toolbar.h b/cockatrice/src/game/phases_toolbar.h similarity index 97% rename from cockatrice/src/game_graphics/phases_toolbar.h rename to cockatrice/src/game/phases_toolbar.h index 39884ef75..6f0931d61 100644 --- a/cockatrice/src/game_graphics/phases_toolbar.h +++ b/cockatrice/src/game/phases_toolbar.h @@ -8,7 +8,7 @@ #ifndef PHASESTOOLBAR_H #define PHASESTOOLBAR_H -#include "board/abstract_graphics_item.h" +#include "../game_graphics/board/abstract_graphics_item.h" #include #include diff --git a/cockatrice/src/game_graphics/player/card_menu_action_type.h b/cockatrice/src/game/player/card_menu_action_type.h similarity index 100% rename from cockatrice/src/game_graphics/player/card_menu_action_type.h rename to cockatrice/src/game/player/card_menu_action_type.h diff --git a/cockatrice/src/game_graphics/player/menu/abstract_player_component.h b/cockatrice/src/game/player/menu/abstract_player_component.h similarity index 100% rename from cockatrice/src/game_graphics/player/menu/abstract_player_component.h rename to cockatrice/src/game/player/menu/abstract_player_component.h diff --git a/cockatrice/src/game_graphics/player/menu/card_menu.cpp b/cockatrice/src/game/player/menu/card_menu.cpp similarity index 76% rename from cockatrice/src/game_graphics/player/menu/card_menu.cpp rename to cockatrice/src/game/player/menu/card_menu.cpp index aa94c3be7..933f4094c 100644 --- a/cockatrice/src/game_graphics/player/menu/card_menu.cpp +++ b/cockatrice/src/game/player/menu/card_menu.cpp @@ -3,121 +3,92 @@ #include "../../../client/settings/card_counter_settings.h" #include "../../../interface/widgets/tabs/tab_game.h" #include "../../board/card_item.h" -#include "../../game/player/player_actions.h" -#include "../../game/player/player_logic.h" -#include "../../game/zones/view_zone_logic.h" +#include "../../zones/view_zone_logic.h" #include "../card_menu_action_type.h" -#include "../player_graphics_item.h" +#include "../player_actions.h" +#include "../player_logic.h" #include "move_menu.h" #include "pt_menu.h" -#include #include #include #include -/** - * @brief Creates a circular icon filled with the specified color. - */ -static QIcon createCircleIcon(const QColor &color) -{ - QPixmap pixmap(32, 32); - pixmap.fill(Qt::transparent); - QPainter painter(&pixmap); - painter.setRenderHint(QPainter::Antialiasing); - painter.setPen(Qt::NoPen); - painter.setBrush(color); - painter.drawEllipse(pixmap.rect()); - - return QIcon(pixmap); -} - -template -static QAction *makeAction(QObject *parent, Slot &&slot, bool checkable = false, bool checked = false) -{ - auto *a = new QAction(parent); - a->setCheckable(checkable); - if (checkable) { - a->setChecked(checked); - } - QObject::connect(a, &QAction::triggered, parent, std::forward(slot)); - return a; -} - -CardMenu::CardMenu(PlayerGraphicsItem *_player, const CardItem *_card, bool _shortcutsActive) +CardMenu::CardMenu(PlayerLogic *_player, const CardItem *_card, bool _shortcutsActive) : player(_player), card(_card), shortcutsActive(_shortcutsActive) { - const QList &players = player->getLogic()->getGame()->getPlayerManager()->getPlayers().values(); + auto playerActions = player->getPlayerActions(); + + const QList &players = player->getGame()->getPlayerManager()->getPlayers().values(); for (auto playerToAdd : players) { - if (playerToAdd == player->getLogic()) { + if (playerToAdd == player) { continue; } playersInfo.append(qMakePair(playerToAdd->getPlayerInfo()->getName(), playerToAdd->getPlayerInfo()->getId())); } - connect(player->getLogic()->getGame()->getPlayerManager(), &PlayerManager::playerRemoved, this, - &CardMenu::removePlayer); + connect(player->getGame()->getPlayerManager(), &PlayerManager::playerRemoved, this, &CardMenu::removePlayer); - auto *actions = player->getLogic()->getPlayerActions(); - auto *gameScene = player->getGameScene(); - - // Single selection resolver used by all lambdas — called at trigger time - auto sel = [gameScene]() { return gameScene->selectedCards(); }; - - // Unified dispatcher for card menu actions - auto invoke = [actions, sel](CardMenuActionType type) { - return [actions, sel, type]() { actions->cardMenuAction(sel(), type); }; - }; - - // Actions using invoke (type dispatch, need selection) - aTap = makeAction(this, invoke(cmTap)); - aDoesntUntap = makeAction(this, invoke(cmDoesntUntap), /*checkable=*/true, card && card->getDoesntUntap()); - aFlip = makeAction(this, invoke(cmFlip)); - aPeek = makeAction(this, invoke(cmPeek)); - aClone = makeAction(this, invoke(cmClone)); - - // Actions using selection directly - aUnattach = makeAction(this, [actions, sel]() { actions->actUnattach(sel()); }); - aSetAnnotation = makeAction(this, [actions, sel]() { actions->actRequestSetAnnotationDialog(sel()); }); - aPlay = makeAction(this, [actions, sel]() { actions->actPlay(sel()); }); - aPlayFacedown = makeAction(this, [actions, sel]() { actions->actPlayFacedown(sel()); }); - aHide = makeAction(this, [actions, sel]() { actions->actHide(sel()); }); - aReduceLifeByPower = makeAction(this, [actions, sel]() { actions->actReduceLifeByPower(sel()); }); - - // Actions that use activeCard, not selection — direct connection + aTap = new QAction(this); + aTap->setData(cmTap); + connect(aTap, &QAction::triggered, playerActions, &PlayerActions::cardMenuAction); + aDoesntUntap = new QAction(this); + aDoesntUntap->setData(cmDoesntUntap); + aDoesntUntap->setCheckable(true); + aDoesntUntap->setChecked(card != nullptr && card->getDoesntUntap()); + connect(aDoesntUntap, &QAction::triggered, playerActions, &PlayerActions::cardMenuAction); aAttach = new QAction(this); + connect(aAttach, &QAction::triggered, playerActions, &PlayerActions::actAttach); + aUnattach = new QAction(this); + connect(aUnattach, &QAction::triggered, playerActions, &PlayerActions::actUnattach); aDrawArrow = new QAction(this); + connect(aDrawArrow, &QAction::triggered, playerActions, &PlayerActions::actDrawArrow); + aSetAnnotation = new QAction(this); + connect(aSetAnnotation, &QAction::triggered, playerActions, &PlayerActions::actSetAnnotation); + aFlip = new QAction(this); + aFlip->setData(cmFlip); + connect(aFlip, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction); + aPeek = new QAction(this); + aPeek->setData(cmPeek); + connect(aPeek, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction); + aClone = new QAction(this); + aClone->setData(cmClone); + connect(aClone, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction); aSelectAll = new QAction(this); + connect(aSelectAll, &QAction::triggered, playerActions, &PlayerActions::actSelectAll); aSelectRow = new QAction(this); + connect(aSelectRow, &QAction::triggered, playerActions, &PlayerActions::actSelectRow); aSelectColumn = new QAction(this); + connect(aSelectColumn, &QAction::triggered, playerActions, &PlayerActions::actSelectColumn); - connect(aAttach, &QAction::triggered, actions, &PlayerActions::actAttach); - connect(aDrawArrow, &QAction::triggered, actions, &PlayerActions::actDrawArrow); - connect(aSelectAll, &QAction::triggered, actions, &PlayerActions::actSelectAll); - connect(aSelectRow, &QAction::triggered, actions, &PlayerActions::actSelectRow); - connect(aSelectColumn, &QAction::triggered, actions, &PlayerActions::actSelectColumn); + aReduceLifeByPower = new QAction(this); + connect(aReduceLifeByPower, &QAction::triggered, playerActions, &PlayerActions::actReduceLifeByPower); + + aPlay = new QAction(this); + connect(aPlay, &QAction::triggered, playerActions, &PlayerActions::actPlay); + aHide = new QAction(this); + connect(aHide, &QAction::triggered, playerActions, &PlayerActions::actHide); + aPlayFacedown = new QAction(this); + connect(aPlayFacedown, &QAction::triggered, playerActions, &PlayerActions::actPlayFacedown); aRevealToAll = new QAction(this); mCardCounters = new QMenu; - // Card counters for (int i = 0; i < 6; ++i) { - QColor color = SettingsCache::instance().cardCounters().color(i); - QIcon circleIcon = createCircleIcon(color); - - auto *addAction = makeAction(this, [actions, sel, i]() { actions->actAddCardCounter(sel(), i); }); - addAction->setIcon(circleIcon); - aAddCounter.append(addAction); - - auto *removeAction = makeAction(this, [actions, sel, i]() { actions->actRemoveCardCounter(sel(), i); }); - removeAction->setIcon(circleIcon); - aRemoveCounter.append(removeAction); - - auto *setAction = makeAction(this, [actions, sel, i]() { actions->actRequestSetCardCounterDialog(sel(), i); }); - setAction->setIcon(circleIcon); - aSetCounter.append(setAction); + auto *tempAddCounter = new QAction(this); + auto *tempRemoveCounter = new QAction(this); + auto *tempSetCounter = new QAction(this); + aAddCounter.append(tempAddCounter); + aRemoveCounter.append(tempRemoveCounter); + aSetCounter.append(tempSetCounter); + connect(tempAddCounter, &QAction::triggered, playerActions, + [playerActions, i] { playerActions->actAddCardCounter(i); }); + connect(tempRemoveCounter, &QAction::triggered, playerActions, + [playerActions, i] { playerActions->actRemoveCardCounter(i); }); + connect(tempSetCounter, &QAction::triggered, playerActions, + [playerActions, i] { playerActions->actSetCardCounter(i); }); } setShortcutsActive(); @@ -129,7 +100,7 @@ CardMenu::CardMenu(PlayerGraphicsItem *_player, const CardItem *_card, bool _sho } bool revealedCard = false; - bool writeableCard = player->getLogic()->getPlayerInfo()->getLocalOrJudge(); + bool writeableCard = player->getPlayerInfo()->getLocalOrJudge(); if (auto *view = qobject_cast(card->getZone())) { if (view->getRevealZone()) { if (view->getWriteableRevealZone()) { @@ -313,9 +284,7 @@ void CardMenu::createHandOrCustomZoneMenu(bool canModifyCard) initContextualPlayersMenu(revealMenu, aRevealToAll); - connect(revealMenu, &QMenu::triggered, this, [this](QAction *action) { - player->getLogic()->getPlayerActions()->actReveal(player->getGameScene()->selectedCards(), action); - }); + connect(revealMenu, &QMenu::triggered, player->getPlayerActions(), &PlayerActions::actReveal); addSeparator(); addAction(aClone); @@ -400,7 +369,8 @@ void CardMenu::addRelatedCardView() QAction *viewCard = viewRelatedCards->addAction(relatedCardName); Q_UNUSED(viewCard); - connect(viewCard, &QAction::triggered, this, [this, cardRef] { emit cardInfoRequested(cardRef); }); + connect(viewCard, &QAction::triggered, player->getGame(), + [this, cardRef] { player->getGame()->getTab()->viewCardInfo(cardRef); }); } } @@ -462,8 +432,7 @@ void CardMenu::addRelatedCardActions() auto *createRelated = new QAction(text, this); createRelated->setData(QVariant(index++)); - connect(createRelated, &QAction::triggered, player->getLogic()->getPlayerActions(), - &PlayerActions::actCreateRelatedCard); + connect(createRelated, &QAction::triggered, player->getPlayerActions(), &PlayerActions::actCreateRelatedCard); addAction(createRelated); } @@ -472,7 +441,7 @@ void CardMenu::addRelatedCardActions() createRelatedCards->setShortcuts( SettingsCache::instance().shortcuts().getShortcut("Player/aCreateRelatedTokens")); } - connect(createRelatedCards, &QAction::triggered, player->getLogic()->getPlayerActions(), + connect(createRelatedCards, &QAction::triggered, player->getPlayerActions(), &PlayerActions::actCreateAllRelatedCards); addAction(createRelatedCards); } diff --git a/cockatrice/src/game_graphics/player/menu/card_menu.h b/cockatrice/src/game/player/menu/card_menu.h similarity index 83% rename from cockatrice/src/game_graphics/player/menu/card_menu.h rename to cockatrice/src/game/player/menu/card_menu.h index d67ef3876..ad3962caf 100644 --- a/cockatrice/src/game_graphics/player/menu/card_menu.h +++ b/cockatrice/src/game/player/menu/card_menu.h @@ -8,20 +8,15 @@ #define COCKATRICE_CARD_MENU_H #include -#include class CardItem; -class PlayerGraphicsItem; class PlayerLogic; class CardMenu : public QMenu { Q_OBJECT -signals: - void cardInfoRequested(const CardRef &cardRef); - public: - explicit CardMenu(PlayerGraphicsItem *player, const CardItem *card, bool shortcutsActive); + explicit CardMenu(PlayerLogic *player, const CardItem *card, bool shortcutsActive); void removePlayer(PlayerLogic *playerToRemove); void createTableMenu(bool canModifyCard); void createStackMenu(bool canModifyCard); @@ -46,7 +41,7 @@ public: QList aAddCounter, aSetCounter, aRemoveCounter; private: - PlayerGraphicsItem *player; + PlayerLogic *player; const CardItem *card; QList> playersInfo; bool shortcutsActive; diff --git a/cockatrice/src/game_graphics/player/menu/custom_zone_menu.cpp b/cockatrice/src/game/player/menu/custom_zone_menu.cpp similarity index 63% rename from cockatrice/src/game_graphics/player/menu/custom_zone_menu.cpp rename to cockatrice/src/game/player/menu/custom_zone_menu.cpp index 743746cc8..88b7f3710 100644 --- a/cockatrice/src/game_graphics/player/menu/custom_zone_menu.cpp +++ b/cockatrice/src/game/player/menu/custom_zone_menu.cpp @@ -1,14 +1,13 @@ #include "custom_zone_menu.h" -#include "../../game/player/player_logic.h" -#include "../player_graphics_item.h" +#include "../player_logic.h" -CustomZoneMenu::CustomZoneMenu(PlayerGraphicsItem *_player) : player(_player) +CustomZoneMenu::CustomZoneMenu(PlayerLogic *_player) : player(_player) { menuAction()->setVisible(false); - connect(player->getLogic(), &PlayerLogic::clearCustomZonesMenu, this, &CustomZoneMenu::clearCustomZonesMenu); - connect(player->getLogic(), &PlayerLogic::addViewCustomZoneActionToCustomZoneMenu, this, + connect(player, &PlayerLogic::clearCustomZonesMenu, this, &CustomZoneMenu::clearCustomZonesMenu); + connect(player, &PlayerLogic::addViewCustomZoneActionToCustomZoneMenu, this, &CustomZoneMenu::addViewCustomZoneActionToCustomZoneMenu); retranslateUi(); @@ -18,7 +17,7 @@ void CustomZoneMenu::retranslateUi() { setTitle(tr("C&ustom Zones")); - if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) { + if (player->getPlayerInfo()->getLocalOrJudge()) { for (auto aViewZone : actions()) { aViewZone->setText(tr("View custom zone '%1'").arg(aViewZone->data().toString())); @@ -38,5 +37,5 @@ void CustomZoneMenu::addViewCustomZoneActionToCustomZoneMenu(QString zoneName) QAction *aViewZone = addAction(tr("View custom zone '%1'").arg(zoneName)); aViewZone->setData(zoneName); connect(aViewZone, &QAction::triggered, this, - [zoneName, this]() { player->getGameScene()->toggleZoneView(player->getLogic(), zoneName, -1); }); + [zoneName, this]() { player->getGameScene()->toggleZoneView(player, zoneName, -1); }); } \ No newline at end of file diff --git a/cockatrice/src/game_graphics/player/menu/custom_zone_menu.h b/cockatrice/src/game/player/menu/custom_zone_menu.h similarity index 84% rename from cockatrice/src/game_graphics/player/menu/custom_zone_menu.h rename to cockatrice/src/game/player/menu/custom_zone_menu.h index 46dd58db6..e10f6a4f0 100644 --- a/cockatrice/src/game_graphics/player/menu/custom_zone_menu.h +++ b/cockatrice/src/game/player/menu/custom_zone_menu.h @@ -11,12 +11,12 @@ #include -class PlayerGraphicsItem; +class PlayerLogic; class CustomZoneMenu : public QMenu, public AbstractPlayerComponent { Q_OBJECT public: - explicit CustomZoneMenu(PlayerGraphicsItem *player); + explicit CustomZoneMenu(PlayerLogic *player); void retranslateUi() override; void setShortcutsActive() override { @@ -26,7 +26,7 @@ public: } private: - PlayerGraphicsItem *player; + PlayerLogic *player; private slots: void clearCustomZonesMenu(); void addViewCustomZoneActionToCustomZoneMenu(QString zoneName); diff --git a/cockatrice/src/game_graphics/player/menu/grave_menu.cpp b/cockatrice/src/game/player/menu/grave_menu.cpp similarity index 79% rename from cockatrice/src/game_graphics/player/menu/grave_menu.cpp rename to cockatrice/src/game/player/menu/grave_menu.cpp index 698481f7a..16a5858ca 100644 --- a/cockatrice/src/game_graphics/player/menu/grave_menu.cpp +++ b/cockatrice/src/game/player/menu/grave_menu.cpp @@ -1,22 +1,21 @@ #include "grave_menu.h" -#include "../../game/abstract_game.h" -#include "../../game/player/player_actions.h" -#include "../../game/player/player_logic.h" -#include "../player_graphics_item.h" +#include "../../abstract_game.h" +#include "../player_actions.h" +#include "../player_logic.h" #include #include #include -GraveyardMenu::GraveyardMenu(PlayerGraphicsItem *_player, QWidget *parent) : TearOffMenu(parent), player(_player) +GraveyardMenu::GraveyardMenu(PlayerLogic *_player, QWidget *parent) : TearOffMenu(parent), player(_player) { createMoveActions(); createViewActions(); addAction(aViewGraveyard); - if (player->getLogic()->getPlayerInfo()->local || player->getLogic()->getPlayerInfo()->judge) { + if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) { mRevealRandomGraveyardCard = addMenu(QString()); connect(mRevealRandomGraveyardCard, &QMenu::aboutToShow, this, &GraveyardMenu::populateRevealRandomMenuWithActivePlayers); @@ -37,9 +36,9 @@ GraveyardMenu::GraveyardMenu(PlayerGraphicsItem *_player, QWidget *parent) : Tea void GraveyardMenu::createMoveActions() { - auto grave = player->getLogic()->getGraveZone(); + auto grave = player->getGraveZone(); - if (player->getLogic()->getPlayerInfo()->local || player->getLogic()->getPlayerInfo()->judge) { + if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) { aMoveGraveToTopLibrary = new QAction(this); aMoveGraveToTopLibrary->setData(QList() << ZoneNames::DECK << 0); @@ -61,7 +60,7 @@ void GraveyardMenu::createMoveActions() void GraveyardMenu::createViewActions() { - PlayerActions *playerActions = player->getLogic()->getPlayerActions(); + PlayerActions *playerActions = player->getPlayerActions(); aViewGraveyard = new QAction(this); connect(aViewGraveyard, &QAction::triggered, playerActions, &PlayerActions::actViewGraveyard); @@ -77,9 +76,9 @@ void GraveyardMenu::populateRevealRandomMenuWithActivePlayers() mRevealRandomGraveyardCard->addSeparator(); - const auto &players = player->getLogic()->getGame()->getPlayerManager()->getPlayers().values(); + const auto &players = player->getGame()->getPlayerManager()->getPlayers().values(); for (auto *other : players) { - if (other == player->getLogic()) { + if (other == player) { continue; } QAction *a = mRevealRandomGraveyardCard->addAction(other->getPlayerInfo()->getName()); @@ -91,7 +90,7 @@ void GraveyardMenu::populateRevealRandomMenuWithActivePlayers() void GraveyardMenu::onRevealRandomTriggered() { if (auto *a = qobject_cast(sender())) { - player->getLogic()->getPlayerActions()->actRevealRandomGraveyardCard(a->data().toInt()); + player->getPlayerActions()->actRevealRandomGraveyardCard(a->data().toInt()); } } @@ -101,7 +100,7 @@ void GraveyardMenu::retranslateUi() aViewGraveyard->setText(tr("&View graveyard")); - if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) { + if (player->getPlayerInfo()->getLocalOrJudge()) { moveGraveMenu->setTitle(tr("&Move graveyard to...")); aMoveGraveToTopLibrary->setText(tr("&Top of library")); aMoveGraveToBottomLibrary->setText(tr("&Bottom of library")); diff --git a/cockatrice/src/game_graphics/player/menu/grave_menu.h b/cockatrice/src/game/player/menu/grave_menu.h similarity index 88% rename from cockatrice/src/game_graphics/player/menu/grave_menu.h rename to cockatrice/src/game/player/menu/grave_menu.h index 116261e9b..d3d98802d 100644 --- a/cockatrice/src/game_graphics/player/menu/grave_menu.h +++ b/cockatrice/src/game/player/menu/grave_menu.h @@ -13,7 +13,7 @@ #include #include -class PlayerGraphicsItem; +class PlayerLogic; class GraveyardMenu : public TearOffMenu, public AbstractPlayerComponent { Q_OBJECT @@ -21,7 +21,7 @@ signals: void newPlayerActionCreated(QAction *action); public: - explicit GraveyardMenu(PlayerGraphicsItem *player, QWidget *parent = nullptr); + explicit GraveyardMenu(PlayerLogic *player, QWidget *parent = nullptr); void createMoveActions(); void createViewActions(); void populateRevealRandomMenuWithActivePlayers(); @@ -40,7 +40,7 @@ public: QAction *aMoveGraveToRfg = nullptr; private: - PlayerGraphicsItem *player; + PlayerLogic *player; }; #endif // COCKATRICE_GRAVE_MENU_H diff --git a/cockatrice/src/game_graphics/player/menu/hand_menu.cpp b/cockatrice/src/game/player/menu/hand_menu.cpp similarity index 87% rename from cockatrice/src/game_graphics/player/menu/hand_menu.cpp rename to cockatrice/src/game/player/menu/hand_menu.cpp index ba0702f07..6ff177655 100644 --- a/cockatrice/src/game_graphics/player/menu/hand_menu.cpp +++ b/cockatrice/src/game/player/menu/hand_menu.cpp @@ -3,22 +3,18 @@ #include "../../../client/settings/cache_settings.h" #include "../../../client/settings/shortcuts_settings.h" #include "../../../game_graphics/zones/hand_zone.h" -#include "../../game/abstract_game.h" -#include "../../game/player/player_actions.h" -#include "../../game/player/player_logic.h" -#include "../player_graphics_item.h" +#include "../../abstract_game.h" +#include "../player_actions.h" +#include "../player_logic.h" #include #include #include -HandMenu::HandMenu(PlayerGraphicsItem *_player, QWidget *parent) : TearOffMenu(parent), player(_player) +HandMenu::HandMenu(PlayerLogic *_player, PlayerActions *actions, QWidget *parent) : TearOffMenu(parent), player(_player) { - auto *actions = player->getLogic()->getPlayerActions(); - - if (player->getLogic()->getPlayerInfo()->local || player->getLogic()->getPlayerInfo()->judge) { + if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) { aViewHand = new QAction(this); - connect(aViewHand, &QAction::triggered, actions, &PlayerActions::actViewHand); addAction(aViewHand); @@ -62,7 +58,7 @@ HandMenu::HandMenu(PlayerGraphicsItem *_player, QWidget *parent) : TearOffMenu(p addSeparator(); aMulligan = new QAction(this); - connect(aMulligan, &QAction::triggered, actions, &PlayerActions::actRequestMulliganDialog); + connect(aMulligan, &QAction::triggered, actions, &PlayerActions::actMulligan); addAction(aMulligan); // Mulligan same size @@ -79,7 +75,7 @@ HandMenu::HandMenu(PlayerGraphicsItem *_player, QWidget *parent) : TearOffMenu(p mMoveHandMenu = addTearOffMenu(QString()); - if (player->getLogic()->getPlayerInfo()->local || player->getLogic()->getPlayerInfo()->judge) { + if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) { aMoveHandToTopLibrary = new QAction(this); aMoveHandToTopLibrary->setData(QList() << ZoneNames::DECK << 0); aMoveHandToBottomLibrary = new QAction(this); @@ -89,7 +85,7 @@ HandMenu::HandMenu(PlayerGraphicsItem *_player, QWidget *parent) : TearOffMenu(p aMoveHandToRfg = new QAction(this); aMoveHandToRfg->setData(QList() << ZoneNames::EXILE << 0); - auto hand = player->getLogic()->getHandZone(); + auto hand = player->getHandZone(); connect(aMoveHandToTopLibrary, &QAction::triggered, hand, &HandZoneLogic::moveAllToZone); connect(aMoveHandToBottomLibrary, &QAction::triggered, hand, &HandZoneLogic::moveAllToZone); @@ -111,7 +107,7 @@ void HandMenu::retranslateUi() { setTitle(tr("&Hand")); - if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) { + if (player->getPlayerInfo()->getLocalOrJudge()) { aViewHand->setText(tr("&View hand")); mSortHand->setTitle(tr("Sort hand by...")); @@ -170,9 +166,9 @@ void HandMenu::populateRevealHandMenuWithActivePlayers() mRevealHand->addSeparator(); - const auto &players = player->getLogic()->getGame()->getPlayerManager()->getPlayers().values(); + const auto &players = player->getGame()->getPlayerManager()->getPlayers().values(); for (auto *other : players) { - if (other == player->getLogic()) { + if (other == player) { continue; } QAction *a = mRevealHand->addAction(other->getPlayerInfo()->getName()); @@ -189,9 +185,9 @@ void HandMenu::populateRevealRandomHandCardMenuWithActivePlayers() mRevealRandomHandCard->addSeparator(); - const auto &players = player->getLogic()->getGame()->getPlayerManager()->getPlayers().values(); + const auto &players = player->getGame()->getPlayerManager()->getPlayers().values(); for (auto *other : players) { - if (other == player->getLogic()) { + if (other == player) { continue; } QAction *a = mRevealRandomHandCard->addAction(other->getPlayerInfo()->getName()); @@ -208,7 +204,7 @@ void HandMenu::onRevealHandTriggered() } const int targetId = action->data().toInt(); - player->getLogic()->getPlayerActions()->actRevealHand(targetId); + player->getPlayerActions()->actRevealHand(targetId); } void HandMenu::onRevealRandomHandCardTriggered() @@ -219,5 +215,5 @@ void HandMenu::onRevealRandomHandCardTriggered() } const int targetId = action->data().toInt(); - player->getLogic()->getPlayerActions()->actRevealRandomHandCard(targetId); + player->getPlayerActions()->actRevealRandomHandCard(targetId); } diff --git a/cockatrice/src/game_graphics/player/menu/hand_menu.h b/cockatrice/src/game/player/menu/hand_menu.h similarity index 92% rename from cockatrice/src/game_graphics/player/menu/hand_menu.h rename to cockatrice/src/game/player/menu/hand_menu.h index d5204612b..1e2ddd95a 100644 --- a/cockatrice/src/game_graphics/player/menu/hand_menu.h +++ b/cockatrice/src/game/player/menu/hand_menu.h @@ -13,7 +13,7 @@ #include #include -class PlayerGraphicsItem; +class PlayerLogic; class PlayerActions; class HandMenu : public TearOffMenu, public AbstractPlayerComponent @@ -21,7 +21,7 @@ class HandMenu : public TearOffMenu, public AbstractPlayerComponent Q_OBJECT public: - HandMenu(PlayerGraphicsItem *player, QWidget *parent = nullptr); + HandMenu(PlayerLogic *player, PlayerActions *actions, QWidget *parent = nullptr); QMenu *revealHandMenu() const { @@ -43,7 +43,7 @@ private slots: void onRevealRandomHandCardTriggered(); private: - PlayerGraphicsItem *player; + PlayerLogic *player; QAction *aViewHand = nullptr; QAction *aMulligan = nullptr; diff --git a/cockatrice/src/game_graphics/player/menu/library_menu.cpp b/cockatrice/src/game/player/menu/library_menu.cpp similarity index 87% rename from cockatrice/src/game_graphics/player/menu/library_menu.cpp rename to cockatrice/src/game/player/menu/library_menu.cpp index 4c15e09ec..8449af05a 100644 --- a/cockatrice/src/game_graphics/player/menu/library_menu.cpp +++ b/cockatrice/src/game/player/menu/library_menu.cpp @@ -3,16 +3,14 @@ #include "../../../client/settings/cache_settings.h" #include "../../../client/settings/shortcuts_settings.h" #include "../../../interface/widgets/tabs/tab_game.h" -#include "../../game/abstract_game.h" -#include "../../game/player/player_actions.h" -#include "../../game/player/player_logic.h" -#include "../player_graphics_item.h" +#include "../../abstract_game.h" +#include "../player_actions.h" +#include "../player_logic.h" #include -#include #include -LibraryMenu::LibraryMenu(PlayerGraphicsItem *_player, QWidget *parent) : TearOffMenu(parent), player(_player) +LibraryMenu::LibraryMenu(PlayerLogic *_player, QWidget *parent) : TearOffMenu(parent), player(_player) { createDrawActions(); createShuffleActions(); @@ -77,8 +75,8 @@ LibraryMenu::LibraryMenu(PlayerGraphicsItem *_player, QWidget *parent) : TearOff bottomLibraryMenu->addSeparator(); bottomLibraryMenu->addAction(aShuffleBottomCards); - connect(player->getLogic(), &PlayerLogic::resetTopCardMenuActions, this, &LibraryMenu::resetTopCardMenuActions); - connect(player->getLogic(), &PlayerLogic::deckChanged, this, &LibraryMenu::enableOpenInDeckEditorAction); + connect(player, &PlayerLogic::resetTopCardMenuActions, this, &LibraryMenu::resetTopCardMenuActions); + connect(player, &PlayerLogic::deckChanged, this, &LibraryMenu::enableOpenInDeckEditorAction); retranslateUi(); } @@ -96,41 +94,41 @@ void LibraryMenu::resetTopCardMenuActions() void LibraryMenu::createDrawActions() { - PlayerActions *playerActions = player->getLogic()->getPlayerActions(); + PlayerActions *playerActions = player->getPlayerActions(); - if (player->getLogic()->getPlayerInfo()->local || player->getLogic()->getPlayerInfo()->judge) { + if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) { aDrawCard = new QAction(this); connect(aDrawCard, &QAction::triggered, playerActions, &PlayerActions::actDrawCard); aDrawCards = new QAction(this); - connect(aDrawCards, &QAction::triggered, playerActions, &PlayerActions::actRequestDrawCardsDialog); + connect(aDrawCards, &QAction::triggered, playerActions, &PlayerActions::actDrawCards); aUndoDraw = new QAction(this); connect(aUndoDraw, &QAction::triggered, playerActions, &PlayerActions::actUndoDraw); aDrawBottomCard = new QAction(this); connect(aDrawBottomCard, &QAction::triggered, playerActions, &PlayerActions::actDrawBottomCard); aDrawBottomCards = new QAction(this); - connect(aDrawBottomCards, &QAction::triggered, playerActions, &PlayerActions::actRequestDrawBottomCardsDialog); + connect(aDrawBottomCards, &QAction::triggered, playerActions, &PlayerActions::actDrawBottomCards); } } void LibraryMenu::createShuffleActions() { - PlayerActions *playerActions = player->getLogic()->getPlayerActions(); + PlayerActions *playerActions = player->getPlayerActions(); - if (player->getLogic()->getPlayerInfo()->local || player->getLogic()->getPlayerInfo()->judge) { + if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) { aShuffle = new QAction(this); connect(aShuffle, &QAction::triggered, playerActions, &PlayerActions::actShuffle); aShuffleTopCards = new QAction(this); - connect(aShuffleTopCards, &QAction::triggered, playerActions, &PlayerActions::actRequestShuffleTopDialog); + connect(aShuffleTopCards, &QAction::triggered, playerActions, &PlayerActions::actShuffleTop); aShuffleBottomCards = new QAction(this); - connect(aShuffleBottomCards, &QAction::triggered, playerActions, &PlayerActions::actRequestShuffleBottomDialog); + connect(aShuffleBottomCards, &QAction::triggered, playerActions, &PlayerActions::actShuffleBottom); } } void LibraryMenu::createMoveActions() { - PlayerActions *playerActions = player->getLogic()->getPlayerActions(); + PlayerActions *playerActions = player->getPlayerActions(); - if (player->getLogic()->getPlayerInfo()->local || player->getLogic()->getPlayerInfo()->judge) { + if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) { aMoveTopToPlay = new QAction(this); connect(aMoveTopToPlay, &QAction::triggered, playerActions, &PlayerActions::actMoveTopCardToPlay); aMoveTopToPlayFaceDown = new QAction(this); @@ -151,8 +149,7 @@ void LibraryMenu::createMoveActions() connect(aMoveTopCardsToExileFaceDown, &QAction::triggered, playerActions, &PlayerActions::actMoveTopCardsToExileFaceDown); aMoveTopCardsUntil = new QAction(this); - connect(aMoveTopCardsUntil, &QAction::triggered, playerActions, - &PlayerActions::actRequestMoveTopCardsUntilDialog); + connect(aMoveTopCardsUntil, &QAction::triggered, playerActions, &PlayerActions::actMoveTopCardsUntil); aMoveTopCardToBottom = new QAction(this); connect(aMoveTopCardToBottom, &QAction::triggered, playerActions, &PlayerActions::actMoveTopCardToBottom); @@ -184,16 +181,16 @@ void LibraryMenu::createMoveActions() void LibraryMenu::createViewActions() { - PlayerActions *playerActions = player->getLogic()->getPlayerActions(); + PlayerActions *playerActions = player->getPlayerActions(); - if (player->getLogic()->getPlayerInfo()->local || player->getLogic()->getPlayerInfo()->judge) { + if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) { aViewLibrary = new QAction(this); connect(aViewLibrary, &QAction::triggered, playerActions, &PlayerActions::actViewLibrary); aViewTopCards = new QAction(this); - connect(aViewTopCards, &QAction::triggered, playerActions, &PlayerActions::actRequestViewTopCardsDialog); + connect(aViewTopCards, &QAction::triggered, playerActions, &PlayerActions::actViewTopCards); aViewBottomCards = new QAction(this); - connect(aViewBottomCards, &QAction::triggered, playerActions, &PlayerActions::actRequestViewBottomCardsDialog); + connect(aViewBottomCards, &QAction::triggered, playerActions, &PlayerActions::actViewBottomCards); aAlwaysRevealTopCard = new QAction(this); aAlwaysRevealTopCard->setCheckable(true); connect(aAlwaysRevealTopCard, &QAction::triggered, playerActions, &PlayerActions::actAlwaysRevealTopCard); @@ -210,7 +207,7 @@ void LibraryMenu::retranslateUi() { setTitle(tr("&Library")); - if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) { + if (player->getPlayerInfo()->getLocalOrJudge()) { aViewLibrary->setText(tr("&View library")); aViewTopCards->setText(tr("View &top cards of library...")); aViewBottomCards->setText(tr("View bottom cards of library...")); @@ -266,9 +263,9 @@ void LibraryMenu::populateRevealLibraryMenuWithActivePlayers() mRevealLibrary->addSeparator(); - const auto &players = player->getLogic()->getGame()->getPlayerManager()->getPlayers().values(); + const auto &players = player->getGame()->getPlayerManager()->getPlayers().values(); for (auto *other : players) { - if (other == player->getLogic()) { + if (other == player) { continue; } QAction *a = mRevealLibrary->addAction(other->getPlayerInfo()->getName()); @@ -281,9 +278,9 @@ void LibraryMenu::populateLendLibraryMenuWithActivePlayers() { mLendLibrary->clear(); - const auto &players = player->getLogic()->getGame()->getPlayerManager()->getPlayers().values(); + const auto &players = player->getGame()->getPlayerManager()->getPlayers().values(); for (auto *other : players) { - if (other == player->getLogic()) { + if (other == player) { continue; } QAction *a = mLendLibrary->addAction(other->getPlayerInfo()->getName()); @@ -302,9 +299,9 @@ void LibraryMenu::populateRevealTopCardMenuWithActivePlayers() mRevealTopCard->addSeparator(); - const auto &players = player->getLogic()->getGame()->getPlayerManager()->getPlayers().values(); + const auto &players = player->getGame()->getPlayerManager()->getPlayers().values(); for (auto *other : players) { - if (other == player->getLogic()) { + if (other == player) { continue; } QAction *a = mRevealTopCard->addAction(other->getPlayerInfo()->getName()); @@ -316,33 +313,27 @@ void LibraryMenu::populateRevealTopCardMenuWithActivePlayers() void LibraryMenu::onRevealLibraryTriggered() { if (auto *a = qobject_cast(sender())) { - player->getLogic()->getPlayerActions()->actRevealLibrary(a->data().toInt()); + player->getPlayerActions()->actRevealLibrary(a->data().toInt()); } } void LibraryMenu::onLendLibraryTriggered() { if (auto *a = qobject_cast(sender())) { - player->getLogic()->getPlayerActions()->actLendLibrary(a->data().toInt()); + player->getPlayerActions()->actLendLibrary(a->data().toInt()); } } void LibraryMenu::onRevealTopCardTriggered() { - QWidget *parent = nullptr; - if (auto *view = player->scene() ? player->scene()->views().value(0) : nullptr) { - parent = view->window(); - } if (auto *a = qobject_cast(sender())) { - - int deckSize = player->getLogic()->getDeckZone()->getCards().size(); - bool ok = true; - int number = QInputDialog::getInt(parent, tr("Reveal top cards of library"), + int deckSize = player->getDeckZone()->getCards().size(); + bool ok; + int number = QInputDialog::getInt(player->getGame()->getTab(), tr("Reveal top cards of library"), tr("Number of cards: (max. %1)").arg(deckSize), defaultNumberTopCards, 1, deckSize, 1, &ok); - if (ok) { - player->getLogic()->getPlayerActions()->actRevealTopCards(a->data().toInt(), number); + player->getPlayerActions()->actRevealTopCards(a->data().toInt(), number); defaultNumberTopCards = number; } } diff --git a/cockatrice/src/game_graphics/player/menu/library_menu.h b/cockatrice/src/game/player/menu/library_menu.h similarity index 96% rename from cockatrice/src/game_graphics/player/menu/library_menu.h rename to cockatrice/src/game/player/menu/library_menu.h index bc0e6fb8e..a941c54b1 100644 --- a/cockatrice/src/game_graphics/player/menu/library_menu.h +++ b/cockatrice/src/game/player/menu/library_menu.h @@ -13,7 +13,6 @@ #include #include -class PlayerGraphicsItem; class PlayerLogic; class PlayerActions; @@ -25,7 +24,7 @@ public slots: void resetTopCardMenuActions(); public: - LibraryMenu(PlayerGraphicsItem *player, QWidget *parent = nullptr); + LibraryMenu(PlayerLogic *player, QWidget *parent = nullptr); void createDrawActions(); void createShuffleActions(); void createMoveActions(); @@ -112,7 +111,7 @@ public: int defaultNumberTopCards = 1; private: - PlayerGraphicsItem *player; + PlayerLogic *player; }; #endif // COCKATRICE_LIBRARY_MENU_H diff --git a/cockatrice/src/game_graphics/player/menu/move_menu.cpp b/cockatrice/src/game/player/menu/move_menu.cpp similarity index 64% rename from cockatrice/src/game_graphics/player/menu/move_menu.cpp rename to cockatrice/src/game/player/menu/move_menu.cpp index 5b7209a9f..3a5ad4da3 100644 --- a/cockatrice/src/game_graphics/player/menu/move_menu.cpp +++ b/cockatrice/src/game/player/menu/move_menu.cpp @@ -1,11 +1,10 @@ #include "move_menu.h" -#include "../../game/player/player_actions.h" -#include "../../game/player/player_logic.h" #include "../card_menu_action_type.h" -#include "../player_graphics_item.h" +#include "../player_actions.h" +#include "../player_logic.h" -MoveMenu::MoveMenu(PlayerGraphicsItem *player) : QMenu(tr("Move to")) +MoveMenu::MoveMenu(PlayerLogic *player) : QMenu(tr("Move to")) { aMoveToTopLibrary = new QAction(this); aMoveToTopLibrary->setData(cmMoveToTopLibrary); @@ -21,22 +20,14 @@ MoveMenu::MoveMenu(PlayerGraphicsItem *player) : QMenu(tr("Move to")) aMoveToExile = new QAction(this); aMoveToExile->setData(cmMoveToExile); - auto *actions = player->getLogic()->getPlayerActions(); - - auto invoke = [player](CardMenuActionType type) { - return [type, player]() { - player->getLogic()->getPlayerActions()->cardMenuAction(player->getGameScene()->selectedCards(), type); - }; - }; - - connect(aMoveToTopLibrary, &QAction::triggered, actions, invoke(cmMoveToTopLibrary)); - connect(aMoveToBottomLibrary, &QAction::triggered, actions, invoke(cmMoveToBottomLibrary)); - connect(aMoveToXfromTopOfLibrary, &QAction::triggered, actions, - &PlayerActions::actRequestMoveCardXCardsFromTopDialog); - connect(aMoveToTable, &QAction::triggered, actions, invoke(cmMoveToTable)); - connect(aMoveToHand, &QAction::triggered, actions, invoke(cmMoveToHand)); - connect(aMoveToGraveyard, &QAction::triggered, actions, invoke(cmMoveToGraveyard)); - connect(aMoveToExile, &QAction::triggered, actions, invoke(cmMoveToExile)); + connect(aMoveToTopLibrary, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction); + connect(aMoveToBottomLibrary, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction); + connect(aMoveToXfromTopOfLibrary, &QAction::triggered, player->getPlayerActions(), + &PlayerActions::actMoveCardXCardsFromTop); + connect(aMoveToTable, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction); + connect(aMoveToHand, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction); + connect(aMoveToGraveyard, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction); + connect(aMoveToExile, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction); addAction(aMoveToTopLibrary); addAction(aMoveToXfromTopOfLibrary); diff --git a/cockatrice/src/game_graphics/player/menu/move_menu.h b/cockatrice/src/game/player/menu/move_menu.h similarity index 88% rename from cockatrice/src/game_graphics/player/menu/move_menu.h rename to cockatrice/src/game/player/menu/move_menu.h index 150bdbd3c..4e257b7fb 100644 --- a/cockatrice/src/game_graphics/player/menu/move_menu.h +++ b/cockatrice/src/game/player/menu/move_menu.h @@ -8,13 +8,13 @@ #define COCKATRICE_MOVE_MENU_H #include -class PlayerGraphicsItem; +class PlayerLogic; class MoveMenu : public QMenu { Q_OBJECT public: - explicit MoveMenu(PlayerGraphicsItem *player); + explicit MoveMenu(PlayerLogic *player); void setShortcutsActive(); void retranslateUi(); diff --git a/cockatrice/src/game_graphics/player/menu/player_menu.cpp b/cockatrice/src/game/player/menu/player_menu.cpp similarity index 62% rename from cockatrice/src/game_graphics/player/menu/player_menu.cpp rename to cockatrice/src/game/player/menu/player_menu.cpp index 17b791222..9e7b91923 100644 --- a/cockatrice/src/game_graphics/player/menu/player_menu.cpp +++ b/cockatrice/src/game/player/menu/player_menu.cpp @@ -5,21 +5,17 @@ #include "../../../game_graphics/zones/table_zone.h" #include "../../../interface/widgets/tabs/tab_game.h" #include "../../board/card_item.h" -#include "../player_graphics_item.h" #include "card_menu.h" #include "hand_menu.h" #include -PlayerMenu::PlayerMenu(PlayerGraphicsItem *_player) : QObject(_player), player(_player) +PlayerMenu::PlayerMenu(PlayerLogic *_player) : QObject(_player), player(_player) { - connect(player->getLogic(), &PlayerLogic::requestCardMenuUpdate, this, &PlayerMenu::updateCardMenu); - connect(this, &PlayerMenu::cardInfoRequested, player, &PlayerGraphicsItem::cardInfoRequested); - playerMenu = new TearOffMenu(); - if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) { - handMenu = addManagedMenu(player, playerMenu); + if (player->getPlayerInfo()->getLocalOrJudge()) { + handMenu = addManagedMenu(player, player->getPlayerActions(), playerMenu); libraryMenu = addManagedMenu(player, playerMenu); } else { handMenu = nullptr; @@ -29,7 +25,7 @@ PlayerMenu::PlayerMenu(PlayerGraphicsItem *_player) : QObject(_player), player(_ graveMenu = addManagedMenu(player, playerMenu); rfgMenu = addManagedMenu(player, playerMenu); - if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) { + if (player->getPlayerInfo()->getLocalOrJudge()) { sideboardMenu = addManagedMenu(player, playerMenu); customZonesMenu = addManagedMenu(player); playerMenu->addSeparator(); @@ -44,7 +40,7 @@ PlayerMenu::PlayerMenu(PlayerGraphicsItem *_player) : QObject(_player), player(_ utilityMenu = nullptr; } - if (player->getLogic()->getPlayerInfo()->getLocal()) { + if (player->getPlayerInfo()->getLocal()) { sayMenu = addManagedMenu(player); } else { sayMenu = nullptr; @@ -59,13 +55,13 @@ PlayerMenu::PlayerMenu(PlayerGraphicsItem *_player) : QObject(_player), player(_ void PlayerMenu::setMenusForGraphicItems() { - player->getTableZoneGraphicsItem()->setMenu(playerMenu); - player->getGraveyardZoneGraphicsItem()->setMenu(graveMenu, graveMenu->aViewGraveyard); - player->getRfgZoneGraphicsItem()->setMenu(rfgMenu, rfgMenu->aViewRfg); - if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) { - player->getHandZoneGraphicsItem()->setMenu(handMenu); - player->getDeckZoneGraphicsItem()->setMenu(libraryMenu, libraryMenu->aDrawCard); - player->getSideboardZoneGraphicsItem()->setMenu(sideboardMenu); + player->getGraphicsItem()->getTableZoneGraphicsItem()->setMenu(playerMenu); + player->getGraphicsItem()->getGraveyardZoneGraphicsItem()->setMenu(graveMenu, graveMenu->aViewGraveyard); + player->getGraphicsItem()->getRfgZoneGraphicsItem()->setMenu(rfgMenu, rfgMenu->aViewRfg); + if (player->getPlayerInfo()->getLocalOrJudge()) { + player->getGraphicsItem()->getHandZoneGraphicsItem()->setMenu(handMenu); + player->getGraphicsItem()->getDeckZoneGraphicsItem()->setMenu(libraryMenu, libraryMenu->aDrawCard); + player->getGraphicsItem()->getSideboardZoneGraphicsItem()->setMenu(sideboardMenu); } } @@ -78,14 +74,12 @@ QMenu *PlayerMenu::updateCardMenu(const CardItem *card) // If is spectator (as spectators don't need card menus), return // only update the menu if the card is actually selected - if ((player->getLogic()->getGame()->getPlayerManager()->isSpectator() && - !player->getLogic()->getGame()->getPlayerManager()->isJudge()) || - player->getLogic()->getGame()->getActiveCard() != card) { + if ((player->getGame()->getPlayerManager()->isSpectator() && !player->getGame()->getPlayerManager()->isJudge()) || + player->getGame()->getActiveCard() != card) { return nullptr; } - CardMenu *menu = new CardMenu(player, card, shortcutsActive); - connect(menu, &CardMenu::cardInfoRequested, this, &PlayerMenu::cardInfoRequested); + QMenu *menu = new CardMenu(player, card, shortcutsActive); emit cardMenuUpdated(menu); return menu; @@ -93,7 +87,7 @@ QMenu *PlayerMenu::updateCardMenu(const CardItem *card) void PlayerMenu::retranslateUi() { - playerMenu->setTitle(tr("Player \"%1\"").arg(player->getLogic()->getPlayerInfo()->getName())); + playerMenu->setTitle(tr("Player \"%1\"").arg(player->getPlayerInfo()->getName())); for (auto *component : managedComponents) { component->retranslateUi(); @@ -110,8 +104,7 @@ void PlayerMenu::refreshShortcuts() { if (shortcutsActive) { // Judges get access to every player's menus but only want shortcuts to be set for their own. - if (player->getLogic()->getPlayerInfo()->getLocalOrJudge() && - !player->getLogic()->getPlayerInfo()->getLocal()) { + if (player->getPlayerInfo()->getLocalOrJudge() && !player->getPlayerInfo()->getLocal()) { setShortcutsInactive(); } else { setShortcutsActive(); diff --git a/cockatrice/src/game_graphics/player/menu/player_menu.h b/cockatrice/src/game/player/menu/player_menu.h similarity index 92% rename from cockatrice/src/game_graphics/player/menu/player_menu.h rename to cockatrice/src/game/player/menu/player_menu.h index 62ba66df7..d5c19df58 100644 --- a/cockatrice/src/game_graphics/player/menu/player_menu.h +++ b/cockatrice/src/game/player/menu/player_menu.h @@ -8,6 +8,7 @@ #define COCKATRICE_PLAYER_MENU_H #include "../../../interface/widgets/menus/tearoff_menu.h" +#include "../player_logic.h" #include "custom_zone_menu.h" #include "grave_menu.h" #include "hand_menu.h" @@ -22,31 +23,29 @@ #include class CardItem; -class CardMenu; -class PlayerGraphicsItem; class PlayerMenu : public QObject { Q_OBJECT signals: - void cardMenuUpdated(CardMenu *cardMenu); - void cardInfoRequested(const CardRef &cardRef); + void cardMenuUpdated(QMenu *cardMenu); void shortcutsActivated(); void shortcutsDeactivated(); void retranslateRequested(); public slots: void setMenusForGraphicItems(); - QMenu *updateCardMenu(const CardItem *card); private slots: void refreshShortcuts(); public: - explicit PlayerMenu(PlayerGraphicsItem *player); + explicit PlayerMenu(PlayerLogic *player); /** @brief Retranslate all user-visible strings. Called on language change. */ void retranslateUi(); + QMenu *updateCardMenu(const CardItem *card); + [[nodiscard]] QMenu *getPlayerMenu() const { return playerMenu; @@ -78,7 +77,7 @@ public: void setShortcutsInactive(); private: - PlayerGraphicsItem *player; + PlayerLogic *player; TearOffMenu *playerMenu; QMenu *countersMenu; HandMenu *handMenu; diff --git a/cockatrice/src/game_graphics/player/menu/pt_menu.cpp b/cockatrice/src/game/player/menu/pt_menu.cpp similarity index 51% rename from cockatrice/src/game_graphics/player/menu/pt_menu.cpp rename to cockatrice/src/game/player/menu/pt_menu.cpp index a01be9424..7dc3035c1 100644 --- a/cockatrice/src/game_graphics/player/menu/pt_menu.cpp +++ b/cockatrice/src/game/player/menu/pt_menu.cpp @@ -1,43 +1,32 @@ #include "pt_menu.h" -#include "../../game/player/player_actions.h" -#include "../../game/player/player_logic.h" -#include "../player_graphics_item.h" +#include "../player_actions.h" +#include "../player_logic.h" -PtMenu::PtMenu(PlayerGraphicsItem *player) : QMenu(tr("Power / toughness")) +PtMenu::PtMenu(PlayerLogic *player) : QMenu(tr("Power / toughness")) { - PlayerActions *playerActions = player->getLogic()->getPlayerActions(); + PlayerActions *playerActions = player->getPlayerActions(); aIncP = new QAction(this); - connect(aIncP, &QAction::triggered, playerActions, - [player, playerActions] { playerActions->actIncP(player->getGameScene()->selectedCards()); }); + connect(aIncP, &QAction::triggered, playerActions, &PlayerActions::actIncP); aDecP = new QAction(this); - connect(aDecP, &QAction::triggered, playerActions, - [player, playerActions] { playerActions->actDecP(player->getGameScene()->selectedCards()); }); + connect(aDecP, &QAction::triggered, playerActions, &PlayerActions::actDecP); aIncT = new QAction(this); - connect(aIncT, &QAction::triggered, playerActions, - [player, playerActions] { playerActions->actIncT(player->getGameScene()->selectedCards()); }); + connect(aIncT, &QAction::triggered, playerActions, &PlayerActions::actIncT); aDecT = new QAction(this); - connect(aDecT, &QAction::triggered, playerActions, - [player, playerActions] { playerActions->actDecT(player->getGameScene()->selectedCards()); }); + connect(aDecT, &QAction::triggered, playerActions, &PlayerActions::actDecT); aIncPT = new QAction(this); - connect(aIncPT, &QAction::triggered, playerActions, - [player, playerActions] { playerActions->actIncPT(player->getGameScene()->selectedCards()); }); + connect(aIncPT, &QAction::triggered, playerActions, [playerActions] { playerActions->actIncPT(); }); aDecPT = new QAction(this); - connect(aDecPT, &QAction::triggered, playerActions, - [player, playerActions] { playerActions->actDecPT(player->getGameScene()->selectedCards()); }); + connect(aDecPT, &QAction::triggered, playerActions, &PlayerActions::actDecPT); aFlowP = new QAction(this); - connect(aFlowP, &QAction::triggered, playerActions, - [player, playerActions] { playerActions->actFlowP(player->getGameScene()->selectedCards()); }); + connect(aFlowP, &QAction::triggered, playerActions, &PlayerActions::actFlowP); aFlowT = new QAction(this); - connect(aFlowT, &QAction::triggered, playerActions, - [player, playerActions] { playerActions->actFlowT(player->getGameScene()->selectedCards()); }); + connect(aFlowT, &QAction::triggered, playerActions, &PlayerActions::actFlowT); aSetPT = new QAction(this); - connect(aSetPT, &QAction::triggered, playerActions, - [player, playerActions] { playerActions->actRequestSetPTDialog(player->getGameScene()->selectedCards()); }); + connect(aSetPT, &QAction::triggered, playerActions, &PlayerActions::actSetPT); aResetPT = new QAction(this); - connect(aResetPT, &QAction::triggered, playerActions, - [player, playerActions] { playerActions->actResetPT(player->getGameScene()->selectedCards()); }); + connect(aResetPT, &QAction::triggered, playerActions, &PlayerActions::actResetPT); addAction(aIncP); addAction(aDecP); diff --git a/cockatrice/src/game_graphics/player/menu/pt_menu.h b/cockatrice/src/game/player/menu/pt_menu.h similarity index 89% rename from cockatrice/src/game_graphics/player/menu/pt_menu.h rename to cockatrice/src/game/player/menu/pt_menu.h index 72f828801..645449586 100644 --- a/cockatrice/src/game_graphics/player/menu/pt_menu.h +++ b/cockatrice/src/game/player/menu/pt_menu.h @@ -8,14 +8,14 @@ #define COCKATRICE_PT_MENU_H #include -class PlayerGraphicsItem; +class PlayerLogic; class PtMenu : public QMenu { Q_OBJECT public: - explicit PtMenu(PlayerGraphicsItem *player); + explicit PtMenu(PlayerLogic *player); void retranslateUi(); void setShortcutsActive(); diff --git a/cockatrice/src/game_graphics/player/menu/rfg_menu.cpp b/cockatrice/src/game/player/menu/rfg_menu.cpp similarity index 78% rename from cockatrice/src/game_graphics/player/menu/rfg_menu.cpp rename to cockatrice/src/game/player/menu/rfg_menu.cpp index 45abadbf7..e8aca00cb 100644 --- a/cockatrice/src/game_graphics/player/menu/rfg_menu.cpp +++ b/cockatrice/src/game/player/menu/rfg_menu.cpp @@ -1,19 +1,18 @@ #include "rfg_menu.h" -#include "../../game/player/player_actions.h" -#include "../../game/player/player_logic.h" -#include "../player_graphics_item.h" +#include "../player_actions.h" +#include "../player_logic.h" #include -RfgMenu::RfgMenu(PlayerGraphicsItem *_player, QWidget *parent) : TearOffMenu(parent), player(_player) +RfgMenu::RfgMenu(PlayerLogic *_player, QWidget *parent) : TearOffMenu(parent), player(_player) { createMoveActions(); createViewActions(); addAction(aViewRfg); - if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) { + if (player->getPlayerInfo()->getLocalOrJudge()) { addSeparator(); moveRfgMenu = addTearOffMenu(QString()); moveRfgMenu->addAction(aMoveRfgToTopLibrary); @@ -29,8 +28,8 @@ RfgMenu::RfgMenu(PlayerGraphicsItem *_player, QWidget *parent) : TearOffMenu(par void RfgMenu::createMoveActions() { - if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) { - auto rfg = player->getLogic()->getRfgZone(); + if (player->getPlayerInfo()->getLocalOrJudge()) { + auto rfg = player->getRfgZone(); aMoveRfgToTopLibrary = new QAction(this); aMoveRfgToTopLibrary->setData(QList() << ZoneNames::DECK << 0); @@ -50,7 +49,7 @@ void RfgMenu::createMoveActions() void RfgMenu::createViewActions() { - PlayerActions *playerActions = player->getLogic()->getPlayerActions(); + PlayerActions *playerActions = player->getPlayerActions(); aViewRfg = new QAction(this); connect(aViewRfg, &QAction::triggered, playerActions, &PlayerActions::actViewRfg); @@ -62,7 +61,7 @@ void RfgMenu::retranslateUi() aViewRfg->setText(tr("&View exile")); - if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) { + if (player->getPlayerInfo()->getLocalOrJudge()) { moveRfgMenu->setTitle(tr("&Move exile to...")); aMoveRfgToTopLibrary->setText(tr("&Top of library")); aMoveRfgToBottomLibrary->setText(tr("&Bottom of library")); diff --git a/cockatrice/src/game_graphics/player/menu/rfg_menu.h b/cockatrice/src/game/player/menu/rfg_menu.h similarity index 86% rename from cockatrice/src/game_graphics/player/menu/rfg_menu.h rename to cockatrice/src/game/player/menu/rfg_menu.h index f5dd888e4..9e179f8fd 100644 --- a/cockatrice/src/game_graphics/player/menu/rfg_menu.h +++ b/cockatrice/src/game/player/menu/rfg_menu.h @@ -13,12 +13,12 @@ #include #include -class PlayerGraphicsItem; +class PlayerLogic; class RfgMenu : public TearOffMenu, public AbstractPlayerComponent { Q_OBJECT public: - explicit RfgMenu(PlayerGraphicsItem *player, QWidget *parent = nullptr); + explicit RfgMenu(PlayerLogic *player, QWidget *parent = nullptr); void createMoveActions(); void createViewActions(); void retranslateUi() override; @@ -38,7 +38,7 @@ public: QAction *aMoveRfgToGrave = nullptr; private: - PlayerGraphicsItem *player; + PlayerLogic *player; }; #endif // COCKATRICE_RFG_MENU_H diff --git a/cockatrice/src/game_graphics/player/menu/say_menu.cpp b/cockatrice/src/game/player/menu/say_menu.cpp similarity index 78% rename from cockatrice/src/game_graphics/player/menu/say_menu.cpp rename to cockatrice/src/game/player/menu/say_menu.cpp index 336b70f0d..a2d5ab982 100644 --- a/cockatrice/src/game_graphics/player/menu/say_menu.cpp +++ b/cockatrice/src/game/player/menu/say_menu.cpp @@ -1,11 +1,10 @@ #include "say_menu.h" #include "../../../client/settings/cache_settings.h" -#include "../../game/player/player_actions.h" -#include "../../game/player/player_logic.h" -#include "../player_graphics_item.h" +#include "../player_actions.h" +#include "../player_logic.h" -SayMenu::SayMenu(PlayerGraphicsItem *_player) : player(_player) +SayMenu::SayMenu(PlayerLogic *_player) : player(_player) { connect(&SettingsCache::instance().messages(), &MessageSettings::messageMacrosChanged, this, &SayMenu::initSayMenu); initSayMenu(); @@ -45,7 +44,7 @@ void SayMenu::initSayMenu() for (int i = 0; i < count; ++i) { auto *newAction = new QAction(SettingsCache::instance().messages().getMessageAt(i), this); - connect(newAction, &QAction::triggered, player->getLogic()->getPlayerActions(), &PlayerActions::actSayMessage); + connect(newAction, &QAction::triggered, player->getPlayerActions(), &PlayerActions::actSayMessage); addAction(newAction); } diff --git a/cockatrice/src/game_graphics/player/menu/say_menu.h b/cockatrice/src/game/player/menu/say_menu.h similarity index 83% rename from cockatrice/src/game_graphics/player/menu/say_menu.h rename to cockatrice/src/game/player/menu/say_menu.h index 3ff160d05..3de70e85c 100644 --- a/cockatrice/src/game_graphics/player/menu/say_menu.h +++ b/cockatrice/src/game/player/menu/say_menu.h @@ -11,12 +11,12 @@ #include -class PlayerGraphicsItem; +class PlayerLogic; class SayMenu : public QMenu, public AbstractPlayerComponent { Q_OBJECT public: - explicit SayMenu(PlayerGraphicsItem *player); + explicit SayMenu(PlayerLogic *player); void retranslateUi() override; void setShortcutsActive() override; @@ -26,7 +26,7 @@ private slots: void initSayMenu(); private: - PlayerGraphicsItem *player; + PlayerLogic *player; bool shortcutsActive = false; }; diff --git a/cockatrice/src/game_graphics/player/menu/sideboard_menu.cpp b/cockatrice/src/game/player/menu/sideboard_menu.cpp similarity index 56% rename from cockatrice/src/game_graphics/player/menu/sideboard_menu.cpp rename to cockatrice/src/game/player/menu/sideboard_menu.cpp index 0dd7894d2..f88625a1f 100644 --- a/cockatrice/src/game_graphics/player/menu/sideboard_menu.cpp +++ b/cockatrice/src/game/player/menu/sideboard_menu.cpp @@ -1,16 +1,14 @@ #include "sideboard_menu.h" -#include "../../game/player/player_actions.h" -#include "../../game/player/player_logic.h" -#include "../player_graphics_item.h" +#include "../player_actions.h" +#include "../player_logic.h" -SideboardMenu::SideboardMenu(PlayerGraphicsItem *player, QMenu *playerMenu) : QMenu(playerMenu) +SideboardMenu::SideboardMenu(PlayerLogic *player, QMenu *playerMenu) : QMenu(playerMenu) { aViewSideboard = new QAction(this); - connect(aViewSideboard, &QAction::triggered, player->getLogic()->getPlayerActions(), - &PlayerActions::actViewSideboard); + connect(aViewSideboard, &QAction::triggered, player->getPlayerActions(), &PlayerActions::actViewSideboard); - if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) { + if (player->getPlayerInfo()->getLocalOrJudge()) { addAction(aViewSideboard); } diff --git a/cockatrice/src/game_graphics/player/menu/sideboard_menu.h b/cockatrice/src/game/player/menu/sideboard_menu.h similarity index 79% rename from cockatrice/src/game_graphics/player/menu/sideboard_menu.h rename to cockatrice/src/game/player/menu/sideboard_menu.h index b3b547291..20a206782 100644 --- a/cockatrice/src/game_graphics/player/menu/sideboard_menu.h +++ b/cockatrice/src/game/player/menu/sideboard_menu.h @@ -11,19 +11,19 @@ #include -class PlayerGraphicsItem; +class PlayerLogic; class SideboardMenu : public QMenu, public AbstractPlayerComponent { Q_OBJECT public: - explicit SideboardMenu(PlayerGraphicsItem *player, QMenu *playerMenu); + explicit SideboardMenu(PlayerLogic *player, QMenu *playerMenu); void retranslateUi() override; void setShortcutsActive() override; void setShortcutsInactive() override; private: - PlayerGraphicsItem *player; + PlayerLogic *player; QAction *aViewSideboard; }; diff --git a/cockatrice/src/game_graphics/player/menu/utility_menu.cpp b/cockatrice/src/game/player/menu/utility_menu.cpp similarity index 70% rename from cockatrice/src/game_graphics/player/menu/utility_menu.cpp rename to cockatrice/src/game/player/menu/utility_menu.cpp index 61a822b21..6b33d7bde 100644 --- a/cockatrice/src/game_graphics/player/menu/utility_menu.cpp +++ b/cockatrice/src/game/player/menu/utility_menu.cpp @@ -1,49 +1,41 @@ #include "utility_menu.h" #include "../../../interface/deck_loader/deck_loader.h" -#include "../../game/player/player_actions.h" -#include "../../game/player/player_logic.h" -#include "../player_graphics_item.h" +#include "../player_actions.h" +#include "../player_logic.h" #include "player_menu.h" #include #include -UtilityMenu::UtilityMenu(PlayerGraphicsItem *_player, QMenu *playerMenu) : QMenu(playerMenu), player(_player) +UtilityMenu::UtilityMenu(PlayerLogic *_player, QMenu *playerMenu) : QMenu(playerMenu), player(_player) { - PlayerActions *playerActions = player->getLogic()->getPlayerActions(); - connect(playerActions, &PlayerActions::requestEnableAndSetCreateAnotherTokenAction, this, - &UtilityMenu::setAndEnableCreateAnotherTokenAction); - connect(playerActions, &PlayerActions::requestSetLastToken, this, &UtilityMenu::setLastToken); + PlayerActions *playerActions = player->getPlayerActions(); - if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) { + if (player->getPlayerInfo()->getLocalOrJudge()) { aUntapAll = new QAction(this); connect(aUntapAll, &QAction::triggered, playerActions, &PlayerActions::actUntapAll); aRollDie = new QAction(this); - connect(aRollDie, &QAction::triggered, playerActions, &PlayerActions::actRequestRollDieDialog); + connect(aRollDie, &QAction::triggered, playerActions, &PlayerActions::actRollDie); aFlipCoin = new QAction(this); connect(aFlipCoin, &QAction::triggered, playerActions, &PlayerActions::actFlipCoin); aCreateToken = new QAction(this); - connect(aCreateToken, &QAction::triggered, playerActions, [this]() { - player->getLogic()->getPlayerActions()->actRequestCreateTokenDialog(getPredefinedTokens()); - }); + connect(aCreateToken, &QAction::triggered, playerActions, &PlayerActions::actCreateToken); aCreateAnotherToken = new QAction(this); connect(aCreateAnotherToken, &QAction::triggered, playerActions, &PlayerActions::actCreateAnotherToken); aCreateAnotherToken->setEnabled(false); aIncrementAllCardCounters = new QAction(this); - connect(aIncrementAllCardCounters, &QAction::triggered, playerActions, [this]() { - player->getLogic()->getPlayerActions()->actIncrementAllCardCounters( - player->getGameScene()->selectedCards()); - }); + connect(aIncrementAllCardCounters, &QAction::triggered, playerActions, + &PlayerActions::actIncrementAllCardCounters); createPredefinedTokenMenu = new QMenu(QString()); createPredefinedTokenMenu->setEnabled(false); - connect(player->getLogic(), &PlayerLogic::deckChanged, this, &UtilityMenu::populatePredefinedTokensMenu); + connect(player, &PlayerLogic::deckChanged, this, &UtilityMenu::populatePredefinedTokensMenu); playerMenu->addAction(aIncrementAllCardCounters); playerMenu->addSeparator(); @@ -74,7 +66,7 @@ void UtilityMenu::populatePredefinedTokensMenu() clear(); setEnabled(false); predefinedTokens.clear(); - const DeckList &deckList = player->getLogic()->getDeck(); + const DeckList &deckList = player->getDeck(); if (deckList.isEmpty()) { return; @@ -92,24 +84,14 @@ void UtilityMenu::populatePredefinedTokensMenu() if (i < 10) { a->setShortcut(QKeySequence("Alt+" + QString::number((i + 1) % 10))); } - connect(a, &QAction::triggered, player->getLogic()->getPlayerActions(), - &PlayerActions::actCreatePredefinedToken); + connect(a, &QAction::triggered, player->getPlayerActions(), &PlayerActions::actCreatePredefinedToken); } } } -void UtilityMenu::setLastToken(CardInfoPtr lastToken) -{ - if (!createAnotherTokenActionExists()) { - return; - } - - player->getLogic()->getPlayerActions()->setLastTokenInfo(lastToken); -} - void UtilityMenu::retranslateUi() { - if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) { + if (player->getPlayerInfo()->getLocalOrJudge()) { aIncrementAllCardCounters->setText(tr("Increment all card counters")); aUntapAll->setText(tr("&Untap all permanents")); aRollDie->setText(tr("R&oll die...")); @@ -124,7 +106,7 @@ void UtilityMenu::setShortcutsActive() { ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts(); - if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) { + if (player->getPlayerInfo()->getLocalOrJudge()) { aIncrementAllCardCounters->setShortcuts(shortcuts.getShortcut("Player/aIncrementAllCardCounters")); aUntapAll->setShortcuts(shortcuts.getShortcut("Player/aUntapAll")); aRollDie->setShortcuts(shortcuts.getShortcut("Player/aRollDie")); @@ -136,7 +118,7 @@ void UtilityMenu::setShortcutsActive() void UtilityMenu::setShortcutsInactive() { - if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) { + if (player->getPlayerInfo()->getLocalOrJudge()) { aUntapAll->setShortcut(QKeySequence()); aRollDie->setShortcut(QKeySequence()); aFlipCoin->setShortcut(QKeySequence()); diff --git a/cockatrice/src/game_graphics/player/menu/utility_menu.h b/cockatrice/src/game/player/menu/utility_menu.h similarity index 78% rename from cockatrice/src/game_graphics/player/menu/utility_menu.h rename to cockatrice/src/game/player/menu/utility_menu.h index bdc2a81a5..fab3211ca 100644 --- a/cockatrice/src/game_graphics/player/menu/utility_menu.h +++ b/cockatrice/src/game/player/menu/utility_menu.h @@ -10,21 +10,19 @@ #include "abstract_player_component.h" #include -#include -class PlayerGraphicsItem; +class PlayerLogic; class UtilityMenu : public QMenu, public AbstractPlayerComponent { Q_OBJECT public slots: void populatePredefinedTokensMenu(); - void setLastToken(CardInfoPtr lastToken); void retranslateUi() override; void setShortcutsActive() override; void setShortcutsInactive() override; public: - explicit UtilityMenu(PlayerGraphicsItem *player, QMenu *playerMenu); + explicit UtilityMenu(PlayerLogic *player, QMenu *playerMenu); [[nodiscard]] bool createAnotherTokenActionExists() const { @@ -33,7 +31,7 @@ public: void setAndEnableCreateAnotherTokenAction(QString text) { - aCreateAnotherToken->setText(tr("C&reate another %1 token").arg(text)); + aCreateAnotherToken->setText(text); aCreateAnotherToken->setEnabled(true); } @@ -43,7 +41,7 @@ public: } private: - PlayerGraphicsItem *player; + PlayerLogic *player; QStringList predefinedTokens; QMenu *createPredefinedTokenMenu; diff --git a/cockatrice/src/game/player/player_actions.cpp b/cockatrice/src/game/player/player_actions.cpp index fffd23ccf..1706c44dc 100644 --- a/cockatrice/src/game/player/player_actions.cpp +++ b/cockatrice/src/game/player/player_actions.cpp @@ -1,13 +1,15 @@ #include "player_actions.h" -#include "../../game_graphics/dialogs/dlg_move_top_cards_until.h" -#include "../../game_graphics/dialogs/dlg_roll_dice.h" -#include "../../game_graphics/player/card_menu_action_type.h" #include "../../game_graphics/zones/hand_zone.h" #include "../../game_graphics/zones/table_zone.h" #include "../../interface/widgets/tabs/tab_game.h" #include "../../interface/widgets/utility/get_text_with_max.h" +#include "../board/card_item.h" +#include "../client/settings/card_counter_settings.h" +#include "../dialogs/dlg_move_top_cards_until.h" +#include "../dialogs/dlg_roll_dice.h" #include "../zones/view_zone_logic.h" +#include "card_menu_action_type.h" #include #include @@ -37,8 +39,6 @@ static constexpr int MOVE_TOP_CARD_UNTIL_INTERVAL = 100; PlayerActions::PlayerActions(PlayerLogic *_player) : QObject(_player), player(_player), lastTokenTableRow(0), movingCardsUntil(false) { - connect(this, &PlayerActions::requestZoneViewToggle, player, &PlayerLogic::onRequestZoneViewToggle); - moveTopCardTimer = new QTimer(this); moveTopCardTimer->setInterval(MOVE_TOP_CARD_UNTIL_INTERVAL); moveTopCardTimer->setSingleShot(true); @@ -133,12 +133,12 @@ void PlayerActions::playCardToTable(const CardItem *card, bool faceDown) void PlayerActions::actViewLibrary() { - emit requestZoneViewToggle(ZoneNames::DECK, -1); + player->getGameScene()->toggleZoneView(player, ZoneNames::DECK, -1); } void PlayerActions::actViewHand() { - emit requestZoneViewToggle(ZoneNames::HAND, -1); + player->getGameScene()->toggleZoneView(player, ZoneNames::HAND, -1); } /** @@ -170,45 +170,49 @@ void PlayerActions::actSortHand() static QList defaultOptions = {CardList::SortByName, CardList::SortByPrinting}; - emit requestSortHand(sortOptions + defaultOptions); + player->getGraphicsItem()->getHandZoneGraphicsItem()->sortHand(sortOptions + defaultOptions); } -void PlayerActions::actRequestViewTopCardsDialog() +void PlayerActions::actViewTopCards() { - emit requestViewTopCardsDialog(defaultNumberTopCards, player->getDeckZone()->getCards().size()); + int deckSize = player->getDeckZone()->getCards().size(); + bool ok; + int number = QInputDialog::getInt(player->getGame()->getTab(), tr("View top cards of library"), + tr("Number of cards: (max. %1)").arg(deckSize), defaultNumberTopCards, 1, + deckSize, 1, &ok); + if (ok) { + defaultNumberTopCards = number; + player->getGameScene()->toggleZoneView(player, ZoneNames::DECK, number); + } } -void PlayerActions::actViewTopCards(int number) +void PlayerActions::actViewBottomCards() { - defaultNumberTopCards = number; - emit requestZoneViewToggle(ZoneNames::DECK, number); + int deckSize = player->getDeckZone()->getCards().size(); + bool ok; + int number = QInputDialog::getInt(player->getGame()->getTab(), tr("View bottom cards of library"), + tr("Number of cards: (max. %1)").arg(deckSize), defaultNumberBottomCards, 1, + deckSize, 1, &ok); + if (ok) { + defaultNumberBottomCards = number; + player->getGameScene()->toggleZoneView(player, ZoneNames::DECK, number, true); + } } -void PlayerActions::actRequestViewBottomCardsDialog() -{ - emit requestViewBottomCardsDialog(defaultNumberBottomCards, player->getDeckZone()->getCards().size()); -} - -void PlayerActions::actViewBottomCards(int number) -{ - defaultNumberBottomCards = number; - emit requestZoneViewToggle(ZoneNames::DECK, number, true); -} - -void PlayerActions::actAlwaysRevealTopCard(bool alwaysRevealTopCard) +void PlayerActions::actAlwaysRevealTopCard() { Command_ChangeZoneProperties cmd; cmd.set_zone_name(ZoneNames::DECK); - cmd.set_always_reveal_top_card(alwaysRevealTopCard); + cmd.set_always_reveal_top_card(player->getPlayerMenu()->getLibraryMenu()->isAlwaysRevealTopCardChecked()); sendGameCommand(cmd); } -void PlayerActions::actAlwaysLookAtTopCard(bool alwaysRevealTopCard) +void PlayerActions::actAlwaysLookAtTopCard() { Command_ChangeZoneProperties cmd; cmd.set_zone_name(ZoneNames::DECK); - cmd.set_always_look_at_top_card(alwaysRevealTopCard); + cmd.set_always_look_at_top_card(player->getPlayerMenu()->getLibraryMenu()->isAlwaysLookAtTopCardChecked()); sendGameCommand(cmd); } @@ -220,17 +224,17 @@ void PlayerActions::actOpenDeckInDeckEditor() void PlayerActions::actViewGraveyard() { - emit requestZoneViewToggle(ZoneNames::GRAVE, -1); + player->getGameScene()->toggleZoneView(player, ZoneNames::GRAVE, -1); } void PlayerActions::actViewRfg() { - emit requestZoneViewToggle(ZoneNames::EXILE, -1); + player->getGameScene()->toggleZoneView(player, ZoneNames::EXILE, -1); } void PlayerActions::actViewSideboard() { - emit requestZoneViewToggle(ZoneNames::SIDEBOARD, -1); + player->getGameScene()->toggleZoneView(player, ZoneNames::SIDEBOARD, -1); } void PlayerActions::actShuffle() @@ -238,20 +242,18 @@ void PlayerActions::actShuffle() sendGameCommand(Command_Shuffle()); } -void PlayerActions::actRequestShuffleTopDialog() +void PlayerActions::actShuffleTop() { const int maxCards = player->getDeckZone()->getCards().size(); if (maxCards == 0) { return; } - emit requestShuffleTopDialog(defaultNumberTopCards, maxCards); -} - -void PlayerActions::actShuffleTop(int number) -{ - const int maxCards = player->getDeckZone()->getCards().size(); - if (maxCards == 0) { + bool ok; + int number = QInputDialog::getInt(player->getGame()->getTab(), tr("Shuffle top cards of library"), + tr("Number of cards: (max. %1)").arg(maxCards), defaultNumberTopCards, 1, + maxCards, 1, &ok); + if (!ok) { return; } @@ -269,20 +271,18 @@ void PlayerActions::actShuffleTop(int number) sendGameCommand(cmd); } -void PlayerActions::actRequestShuffleBottomDialog() +void PlayerActions::actShuffleBottom() { const int maxCards = player->getDeckZone()->getCards().size(); if (maxCards == 0) { return; } - emit requestShuffleBottomDialog(defaultNumberBottomCards, maxCards); -} - -void PlayerActions::actShuffleBottom(int number) -{ - const int maxCards = player->getDeckZone()->getCards().size(); - if (maxCards == 0) { + bool ok; + int number = QInputDialog::getInt(player->getGame()->getTab(), tr("Shuffle bottom cards of library"), + tr("Number of cards: (max. %1)").arg(maxCards), defaultNumberBottomCards, 1, + maxCards, 1, &ok); + if (!ok) { return; } @@ -307,18 +307,21 @@ void PlayerActions::actDrawCard() sendGameCommand(cmd); } -void PlayerActions::actRequestMulliganDialog() +void PlayerActions::actMulligan() { int startSize = SettingsCache::instance().getStartingHandSize(); int handSize = player->getHandZone()->getCards().size(); int deckSize = player->getDeckZone()->getCards().size() + handSize; - emit requestMulliganDialog(startSize, handSize, deckSize); -} + bool ok; + int number = QInputDialog::getInt(player->getGame()->getTab(), tr("Draw hand"), + tr("Number of cards: (max. %1)").arg(deckSize) + '\n' + + tr("0 and lower are in comparison to current hand size"), + startSize, -handSize, deckSize, 1, &ok); -void PlayerActions::actMulligan(int number) -{ - int handSize = player->getHandZone()->getCards().size(); + if (!ok) { + return; + } if (number < 1) { number = handSize + number; @@ -352,19 +355,19 @@ void PlayerActions::doMulligan(int number) sendGameCommand(cmd); } -void PlayerActions::actRequestDrawCardsDialog() +void PlayerActions::actDrawCards() { int deckSize = player->getDeckZone()->getCards().size(); - - emit requestDrawCardsDialog(defaultNumberTopCards, deckSize); -} - -void PlayerActions::actDrawCards(int number) -{ - defaultNumberTopCards = number; - Command_DrawCards cmd; - cmd.set_number(static_cast(number)); - sendGameCommand(cmd); + bool ok; + int number = QInputDialog::getInt(player->getGame()->getTab(), tr("Draw cards"), + tr("Number of cards: (max. %1)").arg(deckSize), defaultNumberTopCards, 1, + deckSize, 1, &ok); + if (ok) { + defaultNumberTopCards = number; + Command_DrawCards cmd; + cmd.set_number(static_cast(number)); + sendGameCommand(cmd); + } } void PlayerActions::actUndoDraw() @@ -422,40 +425,36 @@ void PlayerActions::actMoveTopCardToExile() void PlayerActions::actMoveTopCardsToGrave() { - actRequestMoveTopCardsToDialog(ZoneNames::GRAVE, tr("grave"), false); + moveTopCardsTo(ZoneNames::GRAVE, tr("grave"), false); } void PlayerActions::actMoveTopCardsToGraveFaceDown() { - actRequestMoveTopCardsToDialog(ZoneNames::GRAVE, tr("grave"), true); + moveTopCardsTo(ZoneNames::GRAVE, tr("grave"), true); } void PlayerActions::actMoveTopCardsToExile() { - actRequestMoveTopCardsToDialog(ZoneNames::EXILE, tr("exile"), false); + moveTopCardsTo(ZoneNames::EXILE, tr("exile"), false); } void PlayerActions::actMoveTopCardsToExileFaceDown() { - actRequestMoveTopCardsToDialog(ZoneNames::EXILE, tr("exile"), true); + moveTopCardsTo(ZoneNames::EXILE, tr("exile"), true); } -void PlayerActions::actRequestMoveTopCardsToDialog(const QString &targetZone, - const QString &zoneDisplayName, - bool faceDown) +void PlayerActions::moveTopCardsTo(const QString &targetZone, const QString &zoneDisplayName, bool faceDown) { const int maxCards = player->getDeckZone()->getCards().size(); if (maxCards == 0) { return; } - emit requestMoveTopCardsToDialog(defaultNumberTopCards, maxCards, targetZone, zoneDisplayName, faceDown); -} - -void PlayerActions::moveTopCardsTo(int number, const QString &targetZone, bool faceDown) -{ - const int maxCards = player->getDeckZone()->getCards().size(); - if (maxCards == 0) { + bool ok; + int number = QInputDialog::getInt(player->getGame()->getTab(), tr("Move top cards to %1").arg(zoneDisplayName), + tr("Number of cards: (max. %1)").arg(maxCards), defaultNumberTopCards, 1, + maxCards, 1, &ok); + if (!ok) { return; } @@ -482,16 +481,17 @@ void PlayerActions::moveTopCardsTo(int number, const QString &targetZone, bool f sendGameCommand(cmd); } -void PlayerActions::actRequestMoveTopCardsUntilDialog() +void PlayerActions::actMoveTopCardsUntil() { stopMoveTopCardsUntil(); - emit requestMoveTopCardsUntilDialog(movingCardsUntilOptions); -} + DlgMoveTopCardsUntil dlg(player->getGame()->getTab(), movingCardsUntilOptions); + if (!dlg.exec()) { + return; + } -void PlayerActions::moveTopCardsUntil(const QString &expr, MoveTopCardsUntilOptions options) -{ - movingCardsUntilOptions = options; + auto expr = dlg.getExpr(); + movingCardsUntilOptions = dlg.getOptions(); if (player->getDeckZone()->getCards().empty()) { stopMoveTopCardsUntil(); @@ -620,40 +620,36 @@ void PlayerActions::actMoveBottomCardToExile() void PlayerActions::actMoveBottomCardsToGrave() { - actRequestMoveBottomCardsToDialog(ZoneNames::GRAVE, tr("grave"), false); + moveBottomCardsTo(ZoneNames::GRAVE, tr("grave"), false); } void PlayerActions::actMoveBottomCardsToGraveFaceDown() { - actRequestMoveBottomCardsToDialog(ZoneNames::GRAVE, tr("grave"), true); + moveBottomCardsTo(ZoneNames::GRAVE, tr("grave"), true); } void PlayerActions::actMoveBottomCardsToExile() { - actRequestMoveBottomCardsToDialog(ZoneNames::EXILE, tr("exile"), false); + moveBottomCardsTo(ZoneNames::EXILE, tr("exile"), false); } void PlayerActions::actMoveBottomCardsToExileFaceDown() { - actRequestMoveBottomCardsToDialog(ZoneNames::EXILE, tr("exile"), true); + moveBottomCardsTo(ZoneNames::EXILE, tr("exile"), true); } -void PlayerActions::actRequestMoveBottomCardsToDialog(const QString &targetZone, - const QString &zoneDisplayName, - bool faceDown) +void PlayerActions::moveBottomCardsTo(const QString &targetZone, const QString &zoneDisplayName, bool faceDown) { const int maxCards = player->getDeckZone()->getCards().size(); if (maxCards == 0) { return; } - emit requestMoveBottomCardsToDialog(defaultNumberBottomCards, maxCards, targetZone, zoneDisplayName, faceDown); -} - -void PlayerActions::moveBottomCardsTo(int number, const QString &targetZone, bool faceDown) -{ - const int maxCards = player->getDeckZone()->getCards().size(); - if (maxCards == 0) { + bool ok; + int number = QInputDialog::getInt(player->getGame()->getTab(), tr("Move bottom cards to %1").arg(zoneDisplayName), + tr("Number of cards: (max. %1)").arg(maxCards), defaultNumberBottomCards, 1, + maxCards, 1, &ok); + if (!ok) { return; } @@ -765,24 +761,20 @@ void PlayerActions::actDrawBottomCard() sendGameCommand(cmd); } -void PlayerActions::actRequestDrawBottomCardsDialog() +void PlayerActions::actDrawBottomCards() { const int maxCards = player->getDeckZone()->getCards().size(); if (maxCards == 0) { return; } - emit requestDrawBottomCardsDialog(defaultNumberBottomCards, maxCards); -} - -void PlayerActions::actDrawBottomCards(int number) -{ - const int maxCards = player->getDeckZone()->getCards().size(); - if (maxCards == 0) { + bool ok; + int number = QInputDialog::getInt(player->getGame()->getTab(), tr("Draw bottom cards"), + tr("Number of cards: (max. %1)").arg(maxCards), defaultNumberBottomCards, 1, + maxCards, 1, &ok); + if (!ok) { return; - } - - if (number > maxCards) { + } else if (number > maxCards) { number = maxCards; } defaultNumberBottomCards = number; @@ -849,16 +841,16 @@ void PlayerActions::actUntapAll() sendGameCommand(cmd); } -void PlayerActions::actRequestRollDieDialog() +void PlayerActions::actRollDie() { - emit requestRollDieDialog(); -} + DlgRollDice dlg(player->getGame()->getTab()); + if (!dlg.exec()) { + return; + } -void PlayerActions::actRollDie(int sides, int count) -{ Command_RollDie cmd; - cmd.set_sides(sides); - cmd.set_count(count); + cmd.set_sides(dlg.getDieSideCount()); + cmd.set_count(dlg.getDiceToRollCount()); sendGameCommand(cmd); } @@ -870,26 +862,26 @@ void PlayerActions::actFlipCoin() sendGameCommand(cmd); } -void PlayerActions::actRequestCreateTokenDialog(const QStringList &predefinedTokens) +void PlayerActions::actCreateToken() { - emit requestCreateTokenDialog(predefinedTokens); -} + DlgCreateToken dlg(player->getPlayerMenu()->getUtilityMenu()->getPredefinedTokens(), player->getGame()->getTab()); + if (!dlg.exec()) { + return; + } -void PlayerActions::actCreateToken(TokenInfo tokenToCreate) -{ - lastTokenInfo = tokenToCreate; + lastTokenInfo = dlg.getTokenInfo(); ExactCard correctedCard = CardDatabaseManager::query()->guessCard({lastTokenInfo.name, lastTokenInfo.providerId}); if (correctedCard) { lastTokenInfo.name = correctedCard.getName(); - int tableRow = lastTokenInfo.faceDown ? 2 : correctedCard.getInfo().getUiAttributes().tableRow; - lastTokenTableRow = TableZone::tableRowToGridY(tableRow); + lastTokenTableRow = TableZone::tableRowToGridY(correctedCard.getInfo().getUiAttributes().tableRow); if (lastTokenInfo.pt.isEmpty()) { lastTokenInfo.pt = correctedCard.getInfo().getPowTough(); } } - emit requestEnableAndSetCreateAnotherTokenAction(lastTokenInfo.name); + player->getPlayerMenu()->getUtilityMenu()->setAndEnableCreateAnotherTokenAction( + tr("C&reate another %1 token").arg(lastTokenInfo.name)); actCreateAnotherToken(); } @@ -920,12 +912,8 @@ void PlayerActions::setLastToken(CardInfoPtr cardInfo) return; } - emit requestSetLastToken(cardInfo); -} - -void PlayerActions::setLastTokenInfo(CardInfoPtr cardInfo) -{ - if (cardInfo == nullptr) { + UtilityMenu *utilityMenu = player->getPlayerMenu()->getUtilityMenu(); + if (utilityMenu == nullptr || !utilityMenu->createAnotherTokenActionExists()) { return; } @@ -939,7 +927,7 @@ void PlayerActions::setLastTokenInfo(CardInfoPtr cardInfo) lastTokenTableRow = TableZone::tableRowToGridY(cardInfo->getUiAttributes().tableRow); - emit requestEnableAndSetCreateAnotherTokenAction(lastTokenInfo.name); + utilityMenu->setAndEnableCreateAnotherTokenAction(tr("C&reate another %1 token").arg(lastTokenInfo.name)); } void PlayerActions::actCreatePredefinedToken() @@ -958,17 +946,23 @@ void PlayerActions::actCreatePredefinedToken() void PlayerActions::actCreateRelatedCard() { const CardItem *sourceCard = player->getGame()->getActiveCard(); - if (!sourceCard) { return; } - auto *action = static_cast(sender()); // If there is a better way of passing a CardRelation through a QAction, please add it here. auto relatedCards = sourceCard->getCardInfo().getAllRelatedCards(); - CardRelation *cardRelation = relatedCards.at(action->data().toInt()); - actRequestCreateRelatedFromRelationDialog(sourceCard, cardRelation); + + /* + * If we make a token via "Token: TokenName" + * then let's allow it to be created via "create another token" + */ + if (createRelatedFromRelation(sourceCard, cardRelation) && cardRelation->getCanCreateAnother()) { + ExactCard relatedCard = CardDatabaseManager::query()->getCardFromSameSet(cardRelation->getName(), + sourceCard->getCard().getPrinting()); + setLastToken(relatedCard.getCardPtr()); + } } void PlayerActions::actCreateAllRelatedCards() @@ -988,9 +982,7 @@ void PlayerActions::actCreateAllRelatedCards() if (relatedCards.length() == 1) { cardRelation = relatedCards.at(0); - lastRelatedCreationSucceeded = false; // reset before emit - actRequestCreateRelatedFromRelationDialog(sourceCard, cardRelation); - if (lastRelatedCreationSucceeded) { + if (createRelatedFromRelation(sourceCard, cardRelation)) { ++tokensTypesCreated; } } else { @@ -1002,18 +994,15 @@ void PlayerActions::actCreateAllRelatedCards() } } switch (nonExcludedRelatedCards.length()) { - case 1: + case 1: // if nonExcludedRelatedCards == 1 cardRelation = nonExcludedRelatedCards.at(0); - lastRelatedCreationSucceeded = false; // reset before emit - actRequestCreateRelatedFromRelationDialog(sourceCard, cardRelation); - if (lastRelatedCreationSucceeded) { + if (createRelatedFromRelation(sourceCard, cardRelation)) { ++tokensTypesCreated; } break; - // If all are marked "Exclude", then treat the situation as if none of them are. // We won't accept "garbage in, garbage out", here. - case 0: + case 0: // else if nonExcludedRelatedCards == 0 for (CardRelation *cardRelationAll : relatedCards) { if (!cardRelationAll->getDoesAttach() && !cardRelationAll->getIsVariable()) { dbName = cardRelationAll->getName(); @@ -1028,8 +1017,7 @@ void PlayerActions::actCreateAllRelatedCards() } } break; - - default: + default: // else for (CardRelation *cardRelationNotExcluded : nonExcludedRelatedCards) { if (!cardRelationNotExcluded->getDoesAttach() && !cardRelationNotExcluded->getIsVariable()) { dbName = cardRelationNotExcluded->getName(); @@ -1057,83 +1045,50 @@ void PlayerActions::actCreateAllRelatedCards() } } -void PlayerActions::actRequestCreateRelatedFromRelationDialog(const CardItem *sourceCard, - const CardRelation *cardRelation) -{ - emit requestCreateRelatedFromRelationDialog(sourceCard, cardRelation); -} - -bool PlayerActions::createRelatedFromRelation(const CardItem *sourceCard, - const CardRelation *cardRelation, - int variableCount) +bool PlayerActions::createRelatedFromRelation(const CardItem *sourceCard, const CardRelation *cardRelation) { if (sourceCard == nullptr || cardRelation == nullptr) { return false; } - - const QString dbName = cardRelation->getName(); - const bool persistent = cardRelation->getIsPersistent(); - - // Variable relations always use DoesNotAttach, regardless of the count the user - // entered. + QString dbName = cardRelation->getName(); + bool persistent = cardRelation->getIsPersistent(); if (cardRelation->getIsVariable()) { - if (variableCount <= 0) { + bool ok; + player->setDialogSemaphore(true); + int count = QInputDialog::getInt(player->getGame()->getTab(), tr("Create tokens"), tr("Number:"), + cardRelation->getDefaultCount(), 1, MAX_TOKENS_PER_DIALOG, 1, &ok); + player->setDialogSemaphore(false); + if (!ok) { return false; } - for (int i = 0; i < variableCount; ++i) { - createCard(sourceCard, dbName, CardRelationType::DoesNotAttach, persistent); - } - return true; - } - - const int count = cardRelation->getDefaultCount(); - - if (count > 1) { for (int i = 0; i < count; ++i) { createCard(sourceCard, dbName, CardRelationType::DoesNotAttach, persistent); } - return true; - } - - CardRelationType attachType; - // do not attempt to attach to another player's cards, this causes the card to attempt to attach to the same - // cardid on the local player's field instead, which is an entirely different card! - if (player->getPlayerInfo()->getLocalOrJudge()) { - attachType = cardRelation->getAttachType(); + } else if (cardRelation->getDefaultCount() > 1) { + for (int i = 0; i < cardRelation->getDefaultCount(); ++i) { + createCard(sourceCard, dbName, CardRelationType::DoesNotAttach, persistent); + } } else { - attachType = CardRelationType::DoesNotAttach; - } + CardRelationType attachType; + // do not attempt to attach to another player's cards, this causes the card to attempt to attach to the same + // cardid on the local player's field instead, which is an entirely different card! + if (player->getPlayerInfo()->getLocalOrJudge()) { + attachType = cardRelation->getAttachType(); + } else { + attachType = CardRelationType::DoesNotAttach; + } - // move card onto table first if attaching from some other zone - // we only do this for AttachTo because cross-zone TransformInto is already handled server-side - if (attachType == CardRelationType::AttachTo && sourceCard->getZone()->getName() != ZoneNames::TABLE) { - playCardToTable(sourceCard, false); - } + // move card onto table first if attaching from some other zone + // we only do this for AttachTo because cross-zone TransformInto is already handled server-side + if (attachType == CardRelationType::AttachTo && sourceCard->getZone()->getName() != ZoneNames::TABLE) { + playCardToTable(sourceCard, false); + } - createCard(sourceCard, dbName, attachType, persistent); + createCard(sourceCard, dbName, attachType, persistent); + } return true; } -void PlayerActions::onRelatedCardCreated(const CardItem *sourceCard, const CardRelation *cardRelation) -{ - if (sourceCard == nullptr || cardRelation == nullptr) { - return; - } - - /* - * If we make a token via "Token: TokenName" - * then let's allow it to be created via "create another token" - */ - if (!cardRelation->getCanCreateAnother()) { - return; - } - - ExactCard relatedCard = - CardDatabaseManager::query()->getCardFromSameSet(cardRelation->getName(), sourceCard->getCard().getPrinting()); - - setLastToken(relatedCard.getCardPtr()); -} - void PlayerActions::createCard(const CardItem *sourceCard, const QString &dbCardName, CardRelationType attachType, @@ -1211,29 +1166,35 @@ void PlayerActions::actSayMessage() sendGameCommand(cmd); } -void PlayerActions::actRequestMoveCardXCardsFromTopDialog() +void PlayerActions::actMoveCardXCardsFromTop() { int deckSize = player->getDeckZone()->getCards().size() + 1; // add the card to move to the deck + bool ok; + int number = + QInputDialog::getInt(player->getGame()->getTab(), tr("Place card X cards from top of library"), + tr("Which position should this card be placed:") + "\n" + tr("(max. %1)").arg(deckSize), + defaultNumberTopCardsToPlaceBelow, 1, deckSize, 1, &ok); + number -= 1; // indexes start at 0 - emit requestMoveCardXCardsFromTopDialog(defaultNumberTopCardsToPlaceBelow, deckSize); -} + if (!ok) { + return; + } -void PlayerActions::actMoveCardXCardsFromTop(QList selectedCards, int number) -{ defaultNumberTopCardsToPlaceBelow = number; - if (selectedCards.isEmpty()) { + QList cardList = player->getGameScene()->selectedCards(); + if (cardList.isEmpty()) { return; } QList commandList; ListOfCardsToMove idList; - for (const auto &i : selectedCards) { + for (const auto &i : cardList) { idList.add_card()->set_card_id(i->getId()); } - int startPlayerId = selectedCards[0]->getZone()->getPlayer()->getPlayerInfo()->getId(); - QString startZone = selectedCards[0]->getZone()->getName(); + int startPlayerId = cardList[0]->getZone()->getPlayer()->getPlayerInfo()->getId(); + QString startZone = cardList[0]->getZone()->getName(); auto *cmd = new Command_MoveCard; cmd->set_start_player_id(startPlayerId); @@ -1252,12 +1213,12 @@ void PlayerActions::actMoveCardXCardsFromTop(QList selectedCards, in } } -void PlayerActions::actIncPT(QList selectedCards, int deltaP, int deltaT) +void PlayerActions::actIncPT(int deltaP, int deltaT) { int playerid = player->getPlayerInfo()->getId(); QList commandList; - for (auto card : selectedCards) { + for (auto card : player->getGameScene()->selectedCards()) { QString pt = card->getPT(); const auto ptList = CardItem::parsePT(pt); QString newpt; @@ -1285,11 +1246,11 @@ void PlayerActions::actIncPT(QList selectedCards, int deltaP, int de player->getGame()->getGameEventHandler()->sendGameCommand(prepareGameCommand(commandList), playerid); } -void PlayerActions::actResetPT(QList selectedCards) +void PlayerActions::actResetPT() { int playerid = player->getPlayerInfo()->getId(); QList commandList; - for (auto card : selectedCards) { + for (auto card : player->getGameScene()->selectedCards()) { QString ptString; if (!card->getFaceDown()) { // leave the pt empty if the card is face down ExactCard ec = card->getCard(); @@ -1318,28 +1279,31 @@ void PlayerActions::actResetPT(QList selectedCards) } } -void PlayerActions::actRequestSetPTDialog(QList selectedCards) +void PlayerActions::actSetPT() { QString oldPT; + int playerid = player->getPlayerInfo()->getId(); - for (auto card : selectedCards) { + auto cards = player->getGameScene()->selectedCards(); + for (auto card : cards) { if (!card->getPT().isEmpty()) { oldPT = card->getPT(); } } - - emit requestSetPTDialog(oldPT); -} - -void PlayerActions::actSetPT(QList selectedCards, const QString &pt) -{ - int playerid = player->getPlayerInfo()->getId(); + bool ok; + player->setDialogSemaphore(true); + QString pt = getTextWithMax(player->getGame()->getTab(), tr("Change power/toughness"), tr("Change stats to:"), + QLineEdit::Normal, oldPT, &ok); + player->setDialogSemaphore(false); + if (player->clearCardsToDelete() || !ok) { + return; + } const auto ptList = CardItem::parsePT(pt); bool empty = ptList.isEmpty(); QList commandList; - for (auto card : selectedCards) { + for (auto card : cards) { auto *cmd = new Command_SetCardAttr; QString newpt = QString(); if (!empty) { @@ -1383,47 +1347,47 @@ void PlayerActions::actDrawArrow() } } -void PlayerActions::actIncP(QList selectedCards) +void PlayerActions::actIncP() { - actIncPT(selectedCards, 1, 0); + actIncPT(1, 0); } -void PlayerActions::actDecP(QList selectedCards) +void PlayerActions::actDecP() { - actIncPT(selectedCards, -1, 0); + actIncPT(-1, 0); } -void PlayerActions::actIncT(QList selectedCards) +void PlayerActions::actIncT() { - actIncPT(selectedCards, 0, 1); + actIncPT(0, 1); } -void PlayerActions::actDecT(QList selectedCards) +void PlayerActions::actDecT() { - actIncPT(selectedCards, 0, -1); + actIncPT(0, -1); } -void PlayerActions::actIncPT(QList selectedCards) +void PlayerActions::actIncPT() { - actIncPT(selectedCards, 1, 1); + actIncPT(1, 1); } -void PlayerActions::actDecPT(QList selectedCards) +void PlayerActions::actDecPT() { - actIncPT(selectedCards, -1, -1); + actIncPT(-1, -1); } -void PlayerActions::actFlowP(QList selectedCards) +void PlayerActions::actFlowP() { - actIncPT(selectedCards, 1, -1); + actIncPT(1, -1); } -void PlayerActions::actFlowT(QList selectedCards) +void PlayerActions::actFlowT() { - actIncPT(selectedCards, -1, 1); + actIncPT(-1, 1); } -void PlayerActions::actReduceLifeByPower(QList selectedCards) +void PlayerActions::actReduceLifeByPower() { // find life counter auto lifeCounter = player->getLifeCounter(); @@ -1431,9 +1395,10 @@ void PlayerActions::actReduceLifeByPower(QList selectedCards) return; } - // calculate total power; + // calculate total power + auto cards = player->getGameScene()->selectedCards(); int total = 0; - for (auto card : selectedCards) { + for (auto card : cards) { QVariantList parsed = CardItem::parsePT(card->getPT()); if (!parsed.isEmpty()) { int power = parsed.first().toInt(); // toInt will default to 0 if it's not an int @@ -1458,22 +1423,31 @@ void AnnotationDialog::keyPressEvent(QKeyEvent *event) QInputDialog::keyPressEvent(event); } -void PlayerActions::actRequestSetAnnotationDialog(QList selectedCards) +void PlayerActions::actSetAnnotation() { QString oldAnnotation; - for (auto card : selectedCards) { + auto cards = player->getGameScene()->selectedCards(); + for (auto card : cards) { if (!card->getAnnotation().isEmpty()) { oldAnnotation = card->getAnnotation(); } } - emit requestSetAnnotationDialog(oldAnnotation); -} + player->setDialogSemaphore(true); + AnnotationDialog *dialog = new AnnotationDialog(player->getGame()->getTab()); + dialog->setOptions(QInputDialog::UsePlainTextEditForTextInput); + dialog->setWindowTitle(tr("Set annotation")); + dialog->setLabelText(tr("Please enter the new annotation:")); + dialog->setTextValue(oldAnnotation); + bool ok = dialog->exec(); + player->setDialogSemaphore(false); + if (player->clearCardsToDelete() || !ok) { + return; + } + QString annotation = dialog->textValue().left(MAX_NAME_LENGTH); -void PlayerActions::actSetAnnotation(QList selectedCards, const QString &annotation) -{ QList commandList; - for (auto card : selectedCards) { + for (auto card : cards) { auto *cmd = new Command_SetCardAttr; cmd->set_zone(card->getZone()->getName().toStdString()); cmd->set_card_id(card->getId()); @@ -1494,10 +1468,10 @@ void PlayerActions::actAttach() card->drawAttachArrow(); } -void PlayerActions::actUnattach(QList selectedCards) +void PlayerActions::actUnattach() { QList commandList; - for (auto card : selectedCards) { + for (auto card : player->getGameScene()->selectedCards()) { if (!card->getAttachedTo()) { continue; } @@ -1510,20 +1484,20 @@ void PlayerActions::actUnattach(QList selectedCards) sendGameCommand(prepareGameCommand(commandList)); } -void PlayerActions::actAddCardCounter(QList selectedCards, int counterId) +void PlayerActions::actAddCardCounter(int counterId) { - offsetCardCounter(selectedCards, counterId, 1); + offsetCardCounter(counterId, 1); } -void PlayerActions::actRemoveCardCounter(QList selectedCards, int counterId) +void PlayerActions::actRemoveCardCounter(int counterId) { - offsetCardCounter(selectedCards, counterId, -1); + offsetCardCounter(counterId, -1); } -void PlayerActions::offsetCardCounter(QList selectedCards, int counterId, int offset) +void PlayerActions::offsetCardCounter(int counterId, int offset) { QList commandList; - for (auto card : selectedCards) { + for (auto card : player->getGameScene()->selectedCards()) { int oldValue = card->getCounters().value(counterId, 0); int newValue = oldValue + offset; @@ -1543,25 +1517,34 @@ void PlayerActions::offsetCardCounter(QList selectedCards, int count sendGameCommand(prepareGameCommand(commandList)); } -void PlayerActions::actRequestSetCardCounterDialog(QList selectedCards, int counterId) +void PlayerActions::actSetCardCounter(int counterId) { + player->setDialogSemaphore(true); + // If a single card is selected, we show the old value in the dialog. Otherwise, we show "x" + QList sel = player->getGameScene()->selectedCards(); QString oldValueForDlg = "x"; - if (selectedCards.size() == 1) { - auto *card = selectedCards.first(); + if (sel.size() == 1) { + auto *card = sel.first(); oldValueForDlg = QString::number(card->getCounters().value(counterId, 0)); } - emit requestSetCardCounterDialog(counterId, oldValueForDlg); -} + auto &cardCounterSettings = SettingsCache::instance().cardCounters(); + QString counterName = cardCounterSettings.displayName(counterId); + + AbstractCounterDialog dialog(counterName, oldValueForDlg, player->getGame()->getTab()); + int ok = dialog.exec(); + + player->setDialogSemaphore(false); + if (player->clearCardsToDelete() || !ok) { + return; + } -void PlayerActions::actSetCardCounter(QList selectedCards, int counterId, const QString &counterValue) -{ QList commandList; - for (auto card : selectedCards) { + for (auto card : sel) { int oldValue = card->getCounters().value(counterId, 0); Expression exp(oldValue); - double parsed = exp.parse(counterValue); + double parsed = exp.parse(dialog.textValue()); // Clamp in double precision first to avoid UB, then cast int number = static_cast(qBound(0.0, parsed, static_cast(MAX_COUNTERS_ON_CARD))); @@ -1576,8 +1559,9 @@ void PlayerActions::actSetCardCounter(QList selectedCards, int count sendGameCommand(prepareGameCommand(commandList)); } -void PlayerActions::actIncrementAllCardCounters(QList cardsToUpdate) +void PlayerActions::actIncrementAllCardCounters() { + auto cardsToUpdate = player->getGameScene()->selectedCards(); if (cardsToUpdate.isEmpty()) { // If no cards selected, update all cards on table cardsToUpdate = static_cast>(player->getTableZone()->getCards()); @@ -1623,8 +1607,10 @@ static bool isUnwritableRevealZone(CardZoneLogic *zone) return false; } -void PlayerActions::playSelectedCards(QList selectedCards, const bool faceDown) +void PlayerActions::playSelectedCards(const bool faceDown) { + QList selectedCards = player->getGameScene()->selectedCards(); + // CardIds will get shuffled downwards when cards leave the deck. // We need to iterate through the cards in reverse order so cardIds don't get changed out from under us as we play // out the cards one-by-one. @@ -1638,19 +1624,19 @@ void PlayerActions::playSelectedCards(QList selectedCards, const boo } } -void PlayerActions::actPlay(QList selectedCards) +void PlayerActions::actPlay() { - playSelectedCards(selectedCards, false); + playSelectedCards(false); } -void PlayerActions::actPlayFacedown(QList selectedCards) +void PlayerActions::actPlayFacedown() { - playSelectedCards(selectedCards, true); + playSelectedCards(true); } -void PlayerActions::actHide(QList selectedCards) +void PlayerActions::actHide() { - for (const auto &item : selectedCards) { + for (const auto &item : player->getGameScene()->selectedCards()) { auto *card = static_cast(item); if (card && isUnwritableRevealZone(card->getZone())) { card->getZone()->removeCard(card); @@ -1658,7 +1644,7 @@ void PlayerActions::actHide(QList selectedCards) } } -void PlayerActions::actReveal(QList selectedCards, QAction *action) +void PlayerActions::actReveal(QAction *action) { const int otherPlayerId = action->data().toInt(); @@ -1667,7 +1653,7 @@ void PlayerActions::actReveal(QList selectedCards, QAction *action) cmd.set_player_id(otherPlayerId); } - for (auto card : selectedCards) { + for (auto card : player->getGameScene()->selectedCards()) { if (!cmd.has_zone_name()) { cmd.set_zone_name(card->getZone()->getName().toStdString()); } @@ -1749,14 +1735,15 @@ void PlayerActions::actRevealRandomGraveyardCard(int revealToPlayerId) sendGameCommand(cmd); } -void PlayerActions::cardMenuAction(QList selectedCards, CardMenuActionType type) +void PlayerActions::cardMenuAction() { - QList cardList = selectedCards; + auto *a = dynamic_cast(sender()); + QList cardList = player->getGameScene()->selectedCards(); QList commandList; - if (type <= cmClone) { + if (a->data().toInt() <= (int)cmClone) { for (const auto &card : cardList) { - switch (type) { + switch (static_cast(a->data().toInt())) { // Leaving both for compatibility with server case cmUntap: // fallthrough @@ -1837,7 +1824,7 @@ void PlayerActions::cardMenuAction(QList selectedCards, CardMenuActi idList.add_card()->set_card_id(i->getId()); } - switch (type) { + switch (static_cast(a->data().toInt())) { case cmMoveToTopLibrary: { auto *cmd = new Command_MoveCard; cmd->set_start_player_id(startPlayerId); diff --git a/cockatrice/src/game/player/player_actions.h b/cockatrice/src/game/player/player_actions.h index 3f1960892..3b822b61a 100644 --- a/cockatrice/src/game/player/player_actions.h +++ b/cockatrice/src/game/player/player_actions.h @@ -7,11 +7,8 @@ #ifndef COCKATRICE_PLAYER_ACTIONS_H #define COCKATRICE_PLAYER_ACTIONS_H - -#include "../../game_graphics/board/card_item.h" -#include "../../game_graphics/dialogs/dlg_create_token.h" -#include "../../game_graphics/dialogs/dlg_move_top_cards_until.h" -#include "../../game_graphics/player/card_menu_action_type.h" +#include "../dialogs/dlg_create_token.h" +#include "../dialogs/dlg_move_top_cards_until.h" #include "event_processing_options.h" #include "player_logic.h" @@ -28,6 +25,7 @@ class Message; } } // namespace google +class CardItem; class Command_MoveCard; class GameEventContext; class PendingCommand; @@ -58,75 +56,30 @@ public: return movingCardsUntil; } -signals: - void requestViewTopCardsDialog(int defaultNumberTopCards, int deckSize); - void requestViewBottomCardsDialog(int defaultNumberBottomCards, int deckSize); - void requestShuffleTopDialog(int defaultNumberTopCards, int maxCards); - void requestShuffleBottomDialog(int defaultNumberBottomCards, int maxCards); - void requestMulliganDialog(int startSize, int handSize, int deckSize); - void requestDrawCardsDialog(int defaultNumberTopCards, int deckSize); - void requestMoveTopCardsToDialog(int defaultNumberTopCards, - int maxCards, - const QString &targetZone, - const QString &zoneDisplayName, - bool faceDown); - void requestMoveTopCardsUntilDialog(MoveTopCardsUntilOptions options); - void requestMoveBottomCardsToDialog(int defaultNumberBottomCards, - int maxCards, - const QString &targetZone, - const QString &zoneDisplayName, - bool faceDown); - void requestDrawBottomCardsDialog(int defaultNumberBottomCards, int maxCards); - void requestRollDieDialog(); - void requestCreateTokenDialog(const QStringList &predefinedTokens); - void requestCreateRelatedFromRelationDialog(const CardItem *sourceCard, const CardRelation *cardRelation); - void requestMoveCardXCardsFromTopDialog(int defaultNumberTopCardsToPlaceBelow, int deckSize); - void requestSetPTDialog(const QString &oldPT); - void requestSetAnnotationDialog(const QString &oldAnnotation); - void requestSetCardCounterDialog(int counterId, const QString &oldValueForDlg); - void requestZoneViewToggle(const QString &zoneName, int numberCards, bool isReversed = false); - void requestSortHand(const QList &options); - void requestEnableAndSetCreateAnotherTokenAction(const QString &lastTokenName); - void requestSetLastToken(CardInfoPtr lastToken); - public slots: void setLastToken(CardInfoPtr cardInfo); - void setLastTokenInfo(CardInfoPtr cardInfo); void playCard(CardItem *c, bool faceDown); void playCardToTable(const CardItem *c, bool faceDown); void actUntapAll(); - void actRequestRollDieDialog(); - void actRollDie(int sides, int count); + void actRollDie(); void actFlipCoin(); - void actRequestCreateTokenDialog(const QStringList &predefinedTokens); - void actCreateToken(TokenInfo tokenToCreate); + void actCreateToken(); void actCreateAnotherToken(); - void actRequestCreateRelatedFromRelationDialog(const CardItem *sourceCard, const CardRelation *cardRelation); - bool createRelatedFromRelation(const CardItem *sourceCard, const CardRelation *cardRelation, int variableCount); - void onRelatedCardCreated(const CardItem *sourceCard, const CardRelation *cardRelation); - void setLastRelatedCreationSucceeded(bool succeeded) - { - lastRelatedCreationSucceeded = succeeded; - } void actShuffle(); - void actRequestShuffleTopDialog(); - void actShuffleTop(int number); - void actRequestShuffleBottomDialog(); - void actShuffleBottom(int number); + void actShuffleTop(); + void actShuffleBottom(); void actDrawCard(); - void actRequestDrawCardsDialog(); - void actDrawCards(int number); + void actDrawCards(); void actUndoDraw(); - void actRequestMulliganDialog(); - void actMulligan(int number); + void actMulligan(); void actMulliganSameSize(); void actMulliganMinusOne(); void doMulligan(int number); - void actPlay(QList selectedCards); - void actPlayFacedown(QList selectedCards); - void actHide(QList selectedCards); + void actPlay(); + void actPlayFacedown(); + void actHide(); void actMoveTopCardToPlay(); void actMoveTopCardToPlayFaceDown(); @@ -136,14 +89,10 @@ public slots: void actMoveTopCardsToGraveFaceDown(); void actMoveTopCardsToExile(); void actMoveTopCardsToExileFaceDown(); - void actRequestMoveTopCardsUntilDialog(); - void moveTopCardsUntil(const QString &expr, MoveTopCardsUntilOptions options); + void actMoveTopCardsUntil(); void actMoveTopCardToBottom(); - void actRequestMoveTopCardsToDialog(const QString &targetZone, const QString &zoneDisplayName, bool faceDown); - void moveTopCardsTo(int number, const QString &targetZone, bool faceDown); void actDrawBottomCard(); - void actRequestDrawBottomCardsDialog(); - void actDrawBottomCards(int number); + void actDrawBottomCards(); void actMoveBottomCardToPlay(); void actMoveBottomCardToPlayFaceDown(); void actMoveBottomCardToGrave(); @@ -153,8 +102,6 @@ public slots: void actMoveBottomCardsToExile(); void actMoveBottomCardsToExileFaceDown(); void actMoveBottomCardToTop(); - void actRequestMoveBottomCardsToDialog(const QString &targetZone, const QString &zoneDisplayName, bool faceDown); - void moveBottomCardsTo(int number, const QString &targetZone, bool faceDown); void actSelectAll(); void actSelectRow(); @@ -162,12 +109,10 @@ public slots: void actViewLibrary(); void actViewHand(); - void actRequestViewTopCardsDialog(); - void actViewTopCards(int number); - void actRequestViewBottomCardsDialog(); - void actViewBottomCards(int number); - void actAlwaysRevealTopCard(bool alwaysRevealTopCard); - void actAlwaysLookAtTopCard(bool alwaysRevealTopCard); + void actViewTopCards(); + void actViewBottomCards(); + void actAlwaysRevealTopCard(); + void actAlwaysLookAtTopCard(); void actViewGraveyard(); void actLendLibrary(int lendToPlayerId); void actRevealTopCards(int revealToPlayerId, int amount); @@ -182,41 +127,37 @@ public slots: void actCreateRelatedCard(); void actCreateAllRelatedCards(); - void actRequestMoveCardXCardsFromTopDialog(); - void actMoveCardXCardsFromTop(QList selectedCards, int number); - void actRemoveCardCounter(QList selectedCards, int counterId); - void actAddCardCounter(QList selectedCards, int counterId); - void actRequestSetCardCounterDialog(QList selectedCards, int counterId); - void actSetCardCounter(QList selectedCards, int counterId, const QString &counterValue); - void actIncrementAllCardCounters(QList cardsToUpdate); + void actMoveCardXCardsFromTop(); + void actRemoveCardCounter(int counterId); + void actAddCardCounter(int counterId); + void actSetCardCounter(int counterId); + void actIncrementAllCardCounters(); void actAttach(); - void actUnattach(QList selectedCards); + void actUnattach(); void actDrawArrow(); - void actIncPT(QList selectedCards, int deltaP, int deltaT); - void actResetPT(QList selectedCards); - void actRequestSetPTDialog(QList selectedCards); - void actSetPT(QList selectedCards, const QString &pt); - void actIncP(QList selectedCards); - void actDecP(QList selectedCards); - void actIncT(QList selectedCards); - void actDecT(QList selectedCards); - void actIncPT(QList selectedCards); - void actDecPT(QList selectedCards); - void actFlowP(QList selectedCards); - void actFlowT(QList selectedCards); + void actIncPT(int deltaP, int deltaT); + void actResetPT(); + void actSetPT(); + void actIncP(); + void actDecP(); + void actIncT(); + void actDecT(); + void actIncPT(); + void actDecPT(); + void actFlowP(); + void actFlowT(); - void actReduceLifeByPower(QList selectedCards); + void actReduceLifeByPower(); - void actRequestSetAnnotationDialog(QList selectedCards); - void actSetAnnotation(QList selectedCards, const QString &annotation); - void actReveal(QList selectedCards, QAction *action); + void actSetAnnotation(); + void actReveal(QAction *action); void actRevealHand(int revealToPlayerId); void actRevealRandomHandCard(int revealToPlayerId); void actRevealLibrary(int revealToPlayerId); void actSortHand(); - void cardMenuAction(QList selectedCards, CardMenuActionType type); + void cardMenuAction(); private: PlayerLogic *player; @@ -235,19 +176,21 @@ private: int movingCardsUntilCounter = 0; MoveTopCardsUntilOptions movingCardsUntilOptions; - bool lastRelatedCreationSucceeded = false; + void moveTopCardsTo(const QString &targetZone, const QString &zoneDisplayName, bool faceDown); + void moveBottomCardsTo(const QString &targetZone, const QString &zoneDisplayName, bool faceDown); void createCard(const CardItem *sourceCard, const QString &dbCardName, CardRelationType attach = CardRelationType::DoesNotAttach, bool persistent = false); + bool createRelatedFromRelation(const CardItem *sourceCard, const CardRelation *cardRelation); - void playSelectedCards(QList selectedCards, bool faceDown = false); + void playSelectedCards(bool faceDown = false); void cmdSetTopCard(Command_MoveCard &cmd); void cmdSetBottomCard(Command_MoveCard &cmd); - void offsetCardCounter(QList selectedCards, int counterId, int offset); + void offsetCardCounter(int counterId, int offset); }; #endif // COCKATRICE_PLAYER_ACTIONS_H diff --git a/cockatrice/src/game_graphics/player/player_area.cpp b/cockatrice/src/game/player/player_area.cpp similarity index 100% rename from cockatrice/src/game_graphics/player/player_area.cpp rename to cockatrice/src/game/player/player_area.cpp diff --git a/cockatrice/src/game_graphics/player/player_area.h b/cockatrice/src/game/player/player_area.h similarity index 94% rename from cockatrice/src/game_graphics/player/player_area.h rename to cockatrice/src/game/player/player_area.h index d73547f81..6ffaf4958 100644 --- a/cockatrice/src/game_graphics/player/player_area.h +++ b/cockatrice/src/game/player/player_area.h @@ -7,7 +7,7 @@ #ifndef COCKATRICE_PLAYER_AREA_H #define COCKATRICE_PLAYER_AREA_H -#include "../board/graphics_item_type.h" +#include "../../game_graphics/board/graphics_item_type.h" #include "QGraphicsItem" /** diff --git a/cockatrice/src/game/player/player_event_handler.cpp b/cockatrice/src/game/player/player_event_handler.cpp index bc48298f7..3a7d0345b 100644 --- a/cockatrice/src/game/player/player_event_handler.cpp +++ b/cockatrice/src/game/player/player_event_handler.cpp @@ -1,11 +1,12 @@ #include "player_event_handler.h" -#include "../../game_graphics/board/arrow_item.h" -#include "../../game_graphics/board/card_item.h" #include "../../game_graphics/zones/view_zone.h" #include "../../interface/widgets/tabs/tab_game.h" #include "../board/arrow_data.h" +#include "../board/arrow_item.h" +#include "../board/card_item.h" #include "../board/card_list.h" +#include "libcockatrice/utility/color.h" #include "player_actions.h" #include "player_logic.h" @@ -32,12 +33,10 @@ #include #include #include -#include #include PlayerEventHandler::PlayerEventHandler(PlayerLogic *_player) : QObject(_player), player(_player) { - connect(this, &PlayerEventHandler::requestCardMenuUpdate, player, &PlayerLogic::requestCardMenuUpdate); } void PlayerEventHandler::eventGameSay(const Event_GameSay &event) @@ -93,24 +92,26 @@ void PlayerEventHandler::eventRollDie(const Event_RollDie &event) void PlayerEventHandler::eventCreateArrow(const Event_CreateArrow &event) { - auto data = QSharedPointer::create(ArrowData::fromProto( - event.arrow_info(), player->getPlayerInfo()->getId(), player->getPlayerInfo()->getLocal())); + const ArrowData data = ArrowData::fromProto(event.arrow_info()); + // Resolve names for logging const auto &playerList = player->getGame()->getPlayerManager()->getPlayers(); - PlayerLogic *startPlayer = playerList.value(data->startPlayerId); - PlayerLogic *targetPlayer = playerList.value(data->targetPlayerId); + PlayerLogic *startPlayer = playerList.value(data.startPlayerId); + PlayerLogic *targetPlayer = playerList.value(data.targetPlayerId); QString startCardName, targetCardName; if (startPlayer) { - if (auto *zone = startPlayer->getZones().value(data->startZone)) { - if (auto *card = zone->getCard(data->startCardId)) { + auto *zone = startPlayer->getZones().value(data.startZone); + if (zone) { + if (auto *card = zone->getCard(data.startCardId)) { startCardName = card->getName(); } } } - if (!data->isPlayerTargeted() && targetPlayer) { - if (auto *zone = targetPlayer->getZones().value(data->targetZone)) { - if (auto *card = zone->getCard(data->targetCardId)) { + if (!data.isPlayerTargeted() && targetPlayer) { + auto *zone = targetPlayer->getZones().value(data.targetZone); + if (zone) { + if (auto *card = zone->getCard(data.targetCardId)) { targetCardName = card->getName(); } } @@ -118,15 +119,16 @@ void PlayerEventHandler::eventCreateArrow(const Event_CreateArrow &event) emit player->arrowCreateRequested(data); - if (startPlayer && targetPlayer && !startCardName.isEmpty() && - (data->isPlayerTargeted() || !targetCardName.isEmpty())) { - emit logCreateArrow(player, startPlayer, startCardName, targetPlayer, targetCardName, data->isPlayerTargeted()); + const bool validForLogging = !startCardName.isEmpty() && (data.isPlayerTargeted() || !targetCardName.isEmpty()); + + if (startPlayer && targetPlayer && validForLogging) { + emit logCreateArrow(player, startPlayer, startCardName, targetPlayer, targetCardName, data.isPlayerTargeted()); } } void PlayerEventHandler::eventDeleteArrow(const Event_DeleteArrow &event) { - emit player->arrowDeleted(player->getPlayerInfo()->getId(), event.arrow_id()); + emit player->arrowDeleted(event.arrow_id()); } void PlayerEventHandler::eventCreateToken(const Event_CreateToken &event) @@ -253,7 +255,7 @@ void PlayerEventHandler::eventSetCardCounter(const Event_SetCardCounter &event) int oldValue = card->getCounters().value(event.counter_id(), 0); card->setCounter(event.counter_id(), event.counter_value()); - emit requestCardMenuUpdate(card); + player->getPlayerMenu()->updateCardMenu(card); emit logSetCardCounter(player, card->getName(), event.counter_id(), event.counter_value(), oldValue); } @@ -371,7 +373,7 @@ void PlayerEventHandler::eventMoveCard(const Event_MoveCard &event, const GameEv targetZone->addCard(card, true, x, y); emit cardZoneChanged(card, startZone == targetZone); - emit requestCardMenuUpdate(card); + player->getPlayerMenu()->updateCardMenu(card); if (player->getPlayerActions()->isMovingCardsUntil() && startZoneString == ZoneNames::DECK && targetZone->getName() == ZoneNames::STACK) { @@ -398,7 +400,7 @@ void PlayerEventHandler::eventFlipCard(const Event_FlipCard &event) emit logFlipCard(player, card->getName(), event.face_down()); card->setFaceDown(event.face_down()); - emit requestCardMenuUpdate(card); + player->getPlayerMenu()->updateCardMenu(card); } void PlayerEventHandler::eventDestroyCard(const Event_DestroyCard &event) @@ -467,7 +469,7 @@ void PlayerEventHandler::eventAttachCard(const Event_AttachCard &event) } else { emit logUnattachCard(player, startCard->getName()); } - emit requestCardMenuUpdate(startCard); + player->getPlayerMenu()->updateCardMenu(startCard); } void PlayerEventHandler::eventDrawCards(const Event_DrawCards &event) @@ -553,7 +555,7 @@ void PlayerEventHandler::eventRevealCards(const Event_RevealCards &event, EventP } if (!options.testFlag(SKIP_REVEAL_WINDOW) && showZoneView && !cardList.isEmpty()) { - emit player->requestRevealedZoneView(player, zone, cardList, event.grant_write_access()); + player->getGameScene()->addRevealedZoneView(player, zone, cardList, event.grant_write_access()); } emit logRevealCards(player, zone, cardId, cardName, otherPlayer, false, diff --git a/cockatrice/src/game/player/player_event_handler.h b/cockatrice/src/game/player/player_event_handler.h index cfd82933f..958dee16b 100644 --- a/cockatrice/src/game/player/player_event_handler.h +++ b/cockatrice/src/game/player/player_event_handler.h @@ -83,7 +83,6 @@ signals: void logAlwaysRevealTopCard(PlayerLogic *player, CardZoneLogic *zone, bool reveal); void logAlwaysLookAtTopCard(PlayerLogic *player, CardZoneLogic *zone, bool reveal); void cardZoneChanged(CardItem *card, bool sameZone); - void requestCardMenuUpdate(const CardItem *card); public: PlayerEventHandler(PlayerLogic *player); diff --git a/cockatrice/src/game_graphics/player/player_graphics_item.cpp b/cockatrice/src/game/player/player_graphics_item.cpp similarity index 78% rename from cockatrice/src/game_graphics/player/player_graphics_item.cpp rename to cockatrice/src/game/player/player_graphics_item.cpp index e0194abda..0d4f8c3ed 100644 --- a/cockatrice/src/game_graphics/player/player_graphics_item.cpp +++ b/cockatrice/src/game/player/player_graphics_item.cpp @@ -1,18 +1,13 @@ #include "player_graphics_item.h" -#include "../../game/player/player_actions.h" +#include "../../game_graphics/zones/hand_zone.h" +#include "../../game_graphics/zones/pile_zone.h" +#include "../../game_graphics/zones/stack_zone.h" +#include "../../game_graphics/zones/table_zone.h" #include "../../interface/widgets/tabs/tab_game.h" #include "../board/abstract_card_item.h" #include "../board/counter_general.h" #include "../hand_counter.h" -#include "../zones/hand_zone.h" -#include "../zones/pile_zone.h" -#include "../zones/stack_zone.h" -#include "../zones/table_zone.h" -#include "menu/player_menu.h" -#include "player_dialogs.h" - -#include PlayerGraphicsItem::PlayerGraphicsItem(PlayerLogic *_player) : player(_player) { @@ -21,35 +16,28 @@ PlayerGraphicsItem::PlayerGraphicsItem(PlayerLogic *_player) : player(_player) connect(&SettingsCache::instance(), &SettingsCache::handJustificationChanged, this, &PlayerGraphicsItem::rearrangeZones); connect(player, &PlayerLogic::rearrangeCounters, this, &PlayerGraphicsItem::rearrangeCounters); - connect(player, &PlayerLogic::activeChanged, this, &PlayerGraphicsItem::onPlayerActiveChanged); connect(player, &PlayerLogic::concededChanged, this, [this](int, bool c) { setVisible(!c); }); connect(player, &PlayerLogic::zoneIdChanged, this, [this](int id) { playerArea->setPlayerZoneId(id); }); connect(player, &PlayerLogic::counterAdded, this, &PlayerGraphicsItem::onCounterAdded); connect(player, &PlayerLogic::counterRemoved, this, &PlayerGraphicsItem::onCounterRemoved); - playerMenu = new PlayerMenu(this); - - connect(playerMenu, &PlayerMenu::shortcutsActivated, this, [this]() { + connect(player->getPlayerMenu(), &PlayerMenu::shortcutsActivated, this, [this]() { for (auto *ctr : counterWidgets) { ctr->setShortcutsActive(); } }); - connect(playerMenu, &PlayerMenu::shortcutsDeactivated, this, [this]() { + connect(player->getPlayerMenu(), &PlayerMenu::shortcutsDeactivated, this, [this]() { for (auto *ctr : counterWidgets) { ctr->setShortcutsInactive(); } }); - connect(playerMenu, &PlayerMenu::retranslateRequested, this, [this]() { + connect(player->getPlayerMenu(), &PlayerMenu::retranslateRequested, this, [this]() { for (auto *ctr : counterWidgets) { ctr->retranslateUi(); } }); - playerDialogs = new PlayerDialogs(this, player->getPlayerActions()); - - connect(playerDialogs, &PlayerDialogs::requestDialogSemaphore, player, &PlayerLogic::setDialogSemaphore); - playerArea = new PlayerArea(this); playerTarget = new PlayerTarget(player, playerArea); @@ -59,11 +47,6 @@ PlayerGraphicsItem::PlayerGraphicsItem(PlayerLogic *_player) : player(_player) initializeZones(); - connect(player, &PlayerLogic::addViewCustomZoneActionToCustomZoneMenu, this, - &PlayerGraphicsItem::onCustomZoneAdded); - - playerMenu->setMenusForGraphicItems(); - connect(tableZoneGraphicsItem, &TableZone::sizeChanged, this, &PlayerGraphicsItem::updateBoundingRect); updateBoundingRect(); @@ -74,7 +57,7 @@ PlayerGraphicsItem::PlayerGraphicsItem(PlayerLogic *_player) : player(_player) void PlayerGraphicsItem::retranslateUi() { - playerMenu->retranslateUi(); + player->getPlayerMenu()->retranslateUi(); QMapIterator zoneIterator(player->getZones()); while (zoneIterator.hasNext()) { @@ -110,33 +93,18 @@ void PlayerGraphicsItem::initializeZones() rfgZoneGraphicsItem = new PileZone(player->getRfgZone(), this); rfgZoneGraphicsItem->setPos(base + QPointF(0, 2 * h + h2 + 10)); - tableZoneGraphicsItem = new TableZone(player->getTableZone(), mirrored, this); + tableZoneGraphicsItem = new TableZone(player->getTableZone(), this); connect(tableZoneGraphicsItem, &TableZone::sizeChanged, this, &PlayerGraphicsItem::updateBoundingRect); - connect(this, &PlayerGraphicsItem::mirroredChanged, tableZoneGraphicsItem, &TableZone::setMirrored); stackZoneGraphicsItem = new StackZone(player->getStackZone(), static_cast(tableZoneGraphicsItem->boundingRect().height()), this); handZoneGraphicsItem = new HandZone(player->getHandZone(), static_cast(tableZoneGraphicsItem->boundingRect().height()), this); - connect(player->getPlayerActions(), &PlayerActions::requestSortHand, handZoneGraphicsItem, &HandZone::sortHand); connect(handZoneGraphicsItem->getLogic(), &HandZoneLogic::cardCountChanged, handCounter, &HandCounter::updateNumber); connect(handCounter, &HandCounter::showContextMenu, handZoneGraphicsItem, &HandZone::showContextMenu); - - zoneGraphicsItems.insert(player->getDeckZone()->getName(), deckZoneGraphicsItem); - zoneGraphicsItems.insert(player->getGraveZone()->getName(), graveyardZoneGraphicsItem); - zoneGraphicsItems.insert(player->getRfgZone()->getName(), rfgZoneGraphicsItem); - zoneGraphicsItems.insert(player->getSideboardZone()->getName(), sideboardGraphicsItem); - zoneGraphicsItems.insert(player->getTableZone()->getName(), tableZoneGraphicsItem); - zoneGraphicsItems.insert(player->getStackZone()->getName(), stackZoneGraphicsItem); - zoneGraphicsItems.insert(player->getHandZone()->getName(), handZoneGraphicsItem); -} - -void PlayerGraphicsItem::onCustomZoneAdded(QString customZoneName) -{ - zoneGraphicsItems.insert(customZoneName, nullptr); // Custom zone view goes here, if we ever implement it. } QRectF PlayerGraphicsItem::boundingRect() const @@ -177,7 +145,6 @@ void PlayerGraphicsItem::setMirrored(bool _mirrored) { if (mirrored != _mirrored) { mirrored = _mirrored; - emit mirroredChanged(mirrored); rearrangeZones(); } } @@ -192,11 +159,11 @@ void PlayerGraphicsItem::onCounterAdded(CounterState *state) } counterWidgets.insert(state->getId(), widget); - if (playerMenu->getCountersMenu() && widget->getMenu()) { - playerMenu->getCountersMenu()->addMenu(widget->getMenu()); + if (player->getPlayerMenu()->getCountersMenu() && widget->getMenu()) { + player->getPlayerMenu()->getCountersMenu()->addMenu(widget->getMenu()); } - if (playerMenu->getShortcutsActive()) { + if (player->getPlayerMenu()->getShortcutsActive()) { widget->setShortcutsActive(); } @@ -209,8 +176,8 @@ void PlayerGraphicsItem::onCounterRemoved(int counterId) if (!widget) { return; } - if (playerMenu->getCountersMenu() && widget->getMenu()) { - playerMenu->getCountersMenu()->removeAction(widget->getMenu()->menuAction()); + if (player->getPlayerMenu()->getCountersMenu() && widget->getMenu()) { + player->getPlayerMenu()->getCountersMenu()->removeAction(widget->getMenu()->menuAction()); } widget->delCounter(); rearrangeCounters(); diff --git a/cockatrice/src/game_graphics/player/player_graphics_item.h b/cockatrice/src/game/player/player_graphics_item.h similarity index 83% rename from cockatrice/src/game_graphics/player/player_graphics_item.h rename to cockatrice/src/game/player/player_graphics_item.h index d02234ded..e37fe7290 100644 --- a/cockatrice/src/game_graphics/player/player_graphics_item.h +++ b/cockatrice/src/game/player/player_graphics_item.h @@ -6,16 +6,14 @@ #ifndef COCKATRICE_PLAYER_GRAPHICS_ITEM_H #define COCKATRICE_PLAYER_GRAPHICS_ITEM_H -#include "../../game/player/player_logic.h" #include "../board/abstract_counter.h" #include "../game_scene.h" +#include "player_logic.h" #include class HandZone; class PileZone; -class PlayerDialogs; -class PlayerMenu; class PlayerTarget; class StackZone; class TableZone; @@ -57,16 +55,11 @@ public: return static_cast(scene()); } - PlayerLogic *getLogic() const + PlayerLogic *getPlayer() const { return player; } - [[nodiscard]] PlayerMenu *getPlayerMenu() const - { - return playerMenu; - } - PlayerArea *getPlayerArea() const { return playerArea; @@ -77,11 +70,6 @@ public: return playerTarget; } - CardZone *getZoneGraphicsItem(const QString &name) const - { - return zoneGraphicsItems.value(name, nullptr); - } - [[nodiscard]] PileZone *getDeckZoneGraphicsItem() const { return deckZoneGraphicsItem; @@ -115,7 +103,6 @@ public: public slots: void onPlayerActiveChanged(bool _active); - void onCustomZoneAdded(QString customZoneName); void onCounterAdded(CounterState *state); void onCounterRemoved(int counterId); void rearrangeCounters(); @@ -124,17 +111,12 @@ public slots: signals: void sizeChanged(); void playerCountChanged(); - void mirroredChanged(bool isMirrored); - void cardInfoRequested(const CardRef &cardRef); private: PlayerLogic *player; - PlayerMenu *playerMenu; - PlayerDialogs *playerDialogs; PlayerArea *playerArea; PlayerTarget *playerTarget; QMap counterWidgets; - QMap zoneGraphicsItems; PileZone *deckZoneGraphicsItem; PileZone *sideboardGraphicsItem; PileZone *graveyardZoneGraphicsItem; diff --git a/cockatrice/src/game/player/player_info.h b/cockatrice/src/game/player/player_info.h index 4ec39edbd..e67131ceb 100644 --- a/cockatrice/src/game/player/player_info.h +++ b/cockatrice/src/game/player/player_info.h @@ -7,7 +7,7 @@ #ifndef COCKATRICE_PLAYER_INFO_H #define COCKATRICE_PLAYER_INFO_H -#include "../../game_graphics/player/player_target.h" +#include "player_target.h" #include #include diff --git a/cockatrice/src/game_graphics/player/player_list_widget.cpp b/cockatrice/src/game/player/player_list_widget.cpp similarity index 100% rename from cockatrice/src/game_graphics/player/player_list_widget.cpp rename to cockatrice/src/game/player/player_list_widget.cpp diff --git a/cockatrice/src/game_graphics/player/player_list_widget.h b/cockatrice/src/game/player/player_list_widget.h similarity index 97% rename from cockatrice/src/game_graphics/player/player_list_widget.h rename to cockatrice/src/game/player/player_list_widget.h index a53cfa989..842c45873 100644 --- a/cockatrice/src/game_graphics/player/player_list_widget.h +++ b/cockatrice/src/game/player/player_list_widget.h @@ -7,7 +7,7 @@ #ifndef PLAYERLISTWIDGET_H #define PLAYERLISTWIDGET_H -#include "../../game/player/player_logic.h" +#include "player_logic.h" #include #include diff --git a/cockatrice/src/game/player/player_logic.cpp b/cockatrice/src/game/player/player_logic.cpp index 485e2fc5c..67c6e9519 100644 --- a/cockatrice/src/game/player/player_logic.cpp +++ b/cockatrice/src/game/player/player_logic.cpp @@ -1,18 +1,18 @@ #include "player_logic.h" -#include "../../game_graphics/board/arrow_item.h" -#include "../../game_graphics/board/card_item.h" -#include "../../game_graphics/board/counter_general.h" -#include "../../game_graphics/game_scene.h" -#include "../../game_graphics/player/player_target.h" #include "../../game_graphics/zones/hand_zone.h" #include "../../game_graphics/zones/pile_zone.h" #include "../../game_graphics/zones/stack_zone.h" #include "../../game_graphics/zones/table_zone.h" #include "../../interface/theme_manager.h" #include "../../interface/widgets/tabs/tab_game.h" +#include "../board/arrow_item.h" +#include "../board/card_item.h" #include "../board/card_list.h" +#include "../board/counter_general.h" +#include "../game_scene.h" #include "player_actions.h" +#include "player_target.h" #include #include @@ -35,6 +35,14 @@ PlayerLogic::PlayerLogic(const ServerInfo_User &info, int _id, bool _local, bool conceded(false), zoneId(0), dialogSemaphore(false) { initializeZones(); + + playerMenu = new PlayerMenu(this); + graphicsItem = new PlayerGraphicsItem(this); + playerMenu->setMenusForGraphicItems(); + + connect(this, &PlayerLogic::activeChanged, graphicsItem, &PlayerGraphicsItem::onPlayerActiveChanged); + + connect(this, &PlayerLogic::openDeckEditor, game->getTab(), &TabGame::openDeckEditor); } void PlayerLogic::initializeZones() @@ -60,12 +68,13 @@ PlayerLogic::~PlayerLogic() } zones.clear(); + delete playerMenu; delete getPlayerInfo()->userInfo; } void PlayerLogic::clear() { - emit arrowsClearedLocally(); + emit arrowsCleared(); QMapIterator i(zones); while (i.hasNext()) { @@ -106,7 +115,7 @@ void PlayerLogic::processPlayerInfo(const ServerInfo_Player &info) /* HandZone */ ZoneNames::HAND}; clearCounters(); - emit arrowsClearedLocally(); + emit arrowsCleared(); QMutableMapIterator zoneIt(zones); while (zoneIt.hasNext()) { @@ -222,8 +231,7 @@ void PlayerLogic::processCardAttachment(const ServerInfo_Player &info) const int arrowListSize = info.arrow_list_size(); for (int i = 0; i < arrowListSize; ++i) { - emit arrowCreateRequested(QSharedPointer::create( - ArrowData::fromProto(info.arrow_list(i), getPlayerInfo()->getId(), getPlayerInfo()->getLocal()))); + emit arrowCreateRequested(ArrowData::fromProto(info.arrow_list(i))); } } @@ -317,16 +325,22 @@ void PlayerLogic::setActive(bool _active) active = _active; emit activeChanged(active); } -void PlayerLogic::onRequestZoneViewToggle(const QString &zoneName, int numberCards, bool isReversed) -{ - emit requestZoneViewToggle(this, zoneName, numberCards, isReversed); -} void PlayerLogic::updateZones() { getTableZone()->reorganizeCards(); } +PlayerGraphicsItem *PlayerLogic::getGraphicsItem() +{ + return graphicsItem; +} + +GameScene *PlayerLogic::getGameScene() +{ + return getGraphicsItem()->getGameScene(); +} + void PlayerLogic::setGameStarted() { if (playerInfo->local) { diff --git a/cockatrice/src/game/player/player_logic.h b/cockatrice/src/game/player/player_logic.h index a89cb6eed..20d7597b4 100644 --- a/cockatrice/src/game/player/player_logic.h +++ b/cockatrice/src/game/player/player_logic.h @@ -7,7 +7,6 @@ #ifndef PLAYER_H #define PLAYER_H -#include "../../game_graphics/player/player_area.h" #include "../../interface/widgets/menus/tearoff_menu.h" #include "../board/arrow_data.h" #include "../interface/deck_loader/loaded_deck.h" @@ -15,7 +14,10 @@ #include "../zones/pile_zone_logic.h" #include "../zones/stack_zone_logic.h" #include "../zones/table_zone_logic.h" +#include "menu/player_menu.h" +#include "player_area.h" #include "player_event_handler.h" +#include "player_graphics_item.h" #include "player_info.h" #include @@ -52,7 +54,6 @@ class PlayerMenu; class QAction; class QMenu; class ServerInfo_Arrow; -class ServerInfo_Card; class ServerInfo_Counter; class ServerInfo_Player; class ServerInfo_User; @@ -66,14 +67,8 @@ class PlayerLogic : public QObject signals: void openDeckEditor(const LoadedDeck &deck); - void requestZoneViewToggle(PlayerLogic *player, const QString &zoneName, int numberCards, bool isReversed); - void requestRevealedZoneView(PlayerLogic *player, - CardZoneLogic *zone, - const QList &cardList, - bool withWritePermission); void deckChanged(); void newCardAdded(AbstractCardItem *card); - void requestCardMenuUpdate(const CardItem *card); void counterAdded(CounterState *state); void counterRemoved(int counterId); void rearrangeCounters(); @@ -83,14 +78,13 @@ signals: void clearCustomZonesMenu(); void addViewCustomZoneActionToCustomZoneMenu(QString zoneName); void resetTopCardMenuActions(); - void arrowCreateRequested(QSharedPointer data); - void arrowDeleteRequested(int creatorId, int arrowId); - void arrowDeleted(int creatorId, int arrowId); - void arrowsClearedLocally(); // fires on clear() and processPlayerInfo + void arrowCreateRequested(ArrowData data); + void arrowDeleteRequested(int arrowId); + void arrowDeleted(int arrowId); + void arrowsCleared(); // fires on clear() and processPlayerInfo public slots: void setActive(bool _active); - void onRequestZoneViewToggle(const QString &zoneName, int numberCards, bool isReversed); public: PlayerLogic(const ServerInfo_User &info, int _id, bool _local, bool _judge, AbstractGame *_parent); @@ -118,6 +112,10 @@ public: return game; } + GameScene *getGameScene(); + + [[nodiscard]] PlayerGraphicsItem *getGraphicsItem(); + [[nodiscard]] PlayerActions *getPlayerActions() const { return playerActions; @@ -133,6 +131,11 @@ public: return playerInfo; } + [[nodiscard]] PlayerMenu *getPlayerMenu() const + { + return playerMenu; + } + void setDeck(const DeckList &_deck); [[nodiscard]] const DeckList &getDeck() const @@ -231,6 +234,8 @@ private: PlayerInfo *playerInfo; PlayerEventHandler *playerEventHandler; PlayerActions *playerActions; + PlayerMenu *playerMenu; + PlayerGraphicsItem *graphicsItem; bool active; bool conceded; diff --git a/cockatrice/src/game_graphics/player/player_target.cpp b/cockatrice/src/game/player/player_target.cpp similarity index 99% rename from cockatrice/src/game_graphics/player/player_target.cpp rename to cockatrice/src/game/player/player_target.cpp index 567f3d44d..97fd51998 100644 --- a/cockatrice/src/game_graphics/player/player_target.cpp +++ b/cockatrice/src/game/player/player_target.cpp @@ -1,7 +1,7 @@ #include "player_target.h" -#include "../../game/player/player_logic.h" #include "../../interface/pixel_map_generator.h" +#include "player_logic.h" #include #include diff --git a/cockatrice/src/game_graphics/player/player_target.h b/cockatrice/src/game/player/player_target.h similarity index 95% rename from cockatrice/src/game_graphics/player/player_target.h rename to cockatrice/src/game/player/player_target.h index 67e155660..d3facc60d 100644 --- a/cockatrice/src/game_graphics/player/player_target.h +++ b/cockatrice/src/game/player/player_target.h @@ -7,9 +7,9 @@ #ifndef PLAYERTARGET_H #define PLAYERTARGET_H +#include "../../game_graphics/board/graphics_item_type.h" #include "../board/abstract_counter.h" #include "../board/arrow_target.h" -#include "../board/graphics_item_type.h" #include diff --git a/cockatrice/src/game/replay.cpp b/cockatrice/src/game/replay.cpp index 69f9d8b20..6886f817a 100644 --- a/cockatrice/src/game/replay.cpp +++ b/cockatrice/src/game/replay.cpp @@ -2,9 +2,9 @@ #include "../interface/widgets/tabs/tab_game.h" -Replay::Replay(QObject *_parent, GameReplay *_replay, bool isLocalGame) : AbstractGame(_parent) +Replay::Replay(TabGame *_tab, GameReplay *_replay) : AbstractGame(_tab) { - gameState = new GameState(this, 0, -1, isLocalGame, {}, false, false, -1, false); + gameState = new GameState(this, 0, -1, tab->getTabSupervisor()->getIsLocalGame(), {}, false, false, -1, false); connect(gameMetaInfo, &GameMetaInfo::startedChanged, gameState, &GameState::onStartedChanged); playerManager = new PlayerManager(this, -1, false, true); loadReplay(_replay); diff --git a/cockatrice/src/game/replay.h b/cockatrice/src/game/replay.h index ecb3a10d0..b837e4b8c 100644 --- a/cockatrice/src/game/replay.h +++ b/cockatrice/src/game/replay.h @@ -15,7 +15,7 @@ class Replay : public AbstractGame Q_OBJECT public: - explicit Replay(QObject *_parent, GameReplay *_replay, bool isLocalGame); + explicit Replay(TabGame *_tab, GameReplay *_replay); }; #endif // COCKATRICE_REPLAY_H diff --git a/cockatrice/src/game_graphics/z_value_layer_manager.h b/cockatrice/src/game/z_value_layer_manager.h similarity index 100% rename from cockatrice/src/game_graphics/z_value_layer_manager.h rename to cockatrice/src/game/z_value_layer_manager.h diff --git a/cockatrice/src/game_graphics/z_values.h b/cockatrice/src/game/z_values.h similarity index 100% rename from cockatrice/src/game_graphics/z_values.h rename to cockatrice/src/game/z_values.h diff --git a/cockatrice/src/game/zones/card_zone_logic.cpp b/cockatrice/src/game/zones/card_zone_logic.cpp index 7e0585f4e..aace7097e 100644 --- a/cockatrice/src/game/zones/card_zone_logic.cpp +++ b/cockatrice/src/game/zones/card_zone_logic.cpp @@ -1,7 +1,7 @@ #include "card_zone_logic.h" -#include "../../game_graphics/board/card_item.h" #include "../../game_graphics/zones/view_zone.h" +#include "../board/card_item.h" #include "../player/player_actions.h" #include "../player/player_logic.h" #include "view_zone_logic.h" diff --git a/cockatrice/src/game/zones/hand_zone_logic.cpp b/cockatrice/src/game/zones/hand_zone_logic.cpp index 3bdd15902..36af11131 100644 --- a/cockatrice/src/game/zones/hand_zone_logic.cpp +++ b/cockatrice/src/game/zones/hand_zone_logic.cpp @@ -1,6 +1,6 @@ #include "hand_zone_logic.h" -#include "../../game_graphics/board/card_item.h" +#include "../board/card_item.h" #include "card_zone_algorithms.h" HandZoneLogic::HandZoneLogic(PlayerLogic *_player, diff --git a/cockatrice/src/game/zones/pile_zone_logic.cpp b/cockatrice/src/game/zones/pile_zone_logic.cpp index 0f374fb84..66edde4b7 100644 --- a/cockatrice/src/game/zones/pile_zone_logic.cpp +++ b/cockatrice/src/game/zones/pile_zone_logic.cpp @@ -1,6 +1,6 @@ #include "pile_zone_logic.h" -#include "../../game_graphics/board/card_item.h" +#include "../board/card_item.h" PileZoneLogic::PileZoneLogic(PlayerLogic *_player, const QString &_name, diff --git a/cockatrice/src/game/zones/stack_zone_logic.cpp b/cockatrice/src/game/zones/stack_zone_logic.cpp index 341d4b0e4..2120b9a1d 100644 --- a/cockatrice/src/game/zones/stack_zone_logic.cpp +++ b/cockatrice/src/game/zones/stack_zone_logic.cpp @@ -1,6 +1,6 @@ #include "stack_zone_logic.h" -#include "../../game_graphics/board/card_item.h" +#include "../board/card_item.h" #include "card_zone_algorithms.h" StackZoneLogic::StackZoneLogic(PlayerLogic *_player, diff --git a/cockatrice/src/game/zones/table_zone_logic.cpp b/cockatrice/src/game/zones/table_zone_logic.cpp index a4f033819..3d7ac4297 100644 --- a/cockatrice/src/game/zones/table_zone_logic.cpp +++ b/cockatrice/src/game/zones/table_zone_logic.cpp @@ -1,6 +1,6 @@ #include "table_zone_logic.h" -#include "../../game_graphics/board/card_item.h" +#include "../board/card_item.h" TableZoneLogic::TableZoneLogic(PlayerLogic *_player, const QString &_name, diff --git a/cockatrice/src/game/zones/view_zone_logic.cpp b/cockatrice/src/game/zones/view_zone_logic.cpp index 8782a1762..fa4a73d38 100644 --- a/cockatrice/src/game/zones/view_zone_logic.cpp +++ b/cockatrice/src/game/zones/view_zone_logic.cpp @@ -1,7 +1,7 @@ #include "view_zone_logic.h" #include "../../client/settings/cache_settings.h" -#include "../../game_graphics/board/card_item.h" +#include "../board/card_item.h" /** * @param _player the player that the cards are revealed to. diff --git a/cockatrice/src/game_graphics/player/player_dialogs.cpp b/cockatrice/src/game_graphics/player/player_dialogs.cpp deleted file mode 100644 index 3c26ae1fe..000000000 --- a/cockatrice/src/game_graphics/player/player_dialogs.cpp +++ /dev/null @@ -1,298 +0,0 @@ -#include "player_dialogs.h" - -#include "../../client/settings/card_counter_settings.h" -#include "../../interface/widgets/utility/get_text_with_max.h" -#include "../board/card_item.h" -#include "../dialogs/dlg_roll_dice.h" -#include "../player/player_graphics_item.h" - -#include -#include - -PlayerDialogs::PlayerDialogs(PlayerGraphicsItem *_player, PlayerActions *_playerActions) - : QObject(_player), player(_player), playerActions(_playerActions) -{ - connect(playerActions, &PlayerActions::requestViewTopCardsDialog, this, - &PlayerDialogs::onViewTopCardsDialogRequested); - - connect(playerActions, &PlayerActions::requestViewBottomCardsDialog, this, - &PlayerDialogs::onViewBottomCardsDialogRequested); - - connect(playerActions, &PlayerActions::requestShuffleTopDialog, this, &PlayerDialogs::onShuffleTopDialogRequested); - - connect(playerActions, &PlayerActions::requestShuffleBottomDialog, this, - &PlayerDialogs::onShuffleBottomDialogRequested); - - connect(playerActions, &PlayerActions::requestMulliganDialog, this, &PlayerDialogs::onMulliganDialogRequested); - - connect(playerActions, &PlayerActions::requestDrawCardsDialog, this, &PlayerDialogs::onDrawCardsDialogRequested); - - connect(playerActions, &PlayerActions::requestMoveTopCardsToDialog, this, - &PlayerDialogs::onMoveTopCardsToDialogRequested); - - connect(playerActions, &PlayerActions::requestMoveTopCardsUntilDialog, this, - &PlayerDialogs::onMoveTopCardsUntilDialogRequested); - - connect(playerActions, &PlayerActions::requestMoveBottomCardsToDialog, this, - &PlayerDialogs::onMoveBottomCardsToDialogRequested); - - connect(playerActions, &PlayerActions::requestDrawBottomCardsDialog, this, - &PlayerDialogs::onDrawBottomCardsDialogRequested); - - connect(playerActions, &PlayerActions::requestRollDieDialog, this, &PlayerDialogs::onRollDieDialogRequested); - - connect(playerActions, &PlayerActions::requestCreateTokenDialog, this, - &PlayerDialogs::onCreateTokenDialogRequested); - - connect(playerActions, &PlayerActions::requestCreateRelatedFromRelationDialog, this, - &PlayerDialogs::onCreateRelatedFromRelationDialogRequested); - - connect(playerActions, &PlayerActions::requestMoveCardXCardsFromTopDialog, this, - &PlayerDialogs::onMoveCardXCardsFromTopDialogRequested); - - connect(playerActions, &PlayerActions::requestSetPTDialog, this, &PlayerDialogs::onSetPTDialogRequested); - - connect(playerActions, &PlayerActions::requestSetAnnotationDialog, this, - &PlayerDialogs::onSetAnnotationDialogRequested); - - connect(playerActions, &PlayerActions::requestSetCardCounterDialog, this, - &PlayerDialogs::onSetCardCounterDialogRequested); -} - -void PlayerDialogs::onViewTopCardsDialogRequested(int defaultNumberTopCards, int deckSize) -{ - bool ok; - int number = QInputDialog::getInt(dialogParent(), tr("View top cards of library"), - tr("Number of cards: (max. %1)").arg(deckSize), defaultNumberTopCards, 1, - deckSize, 1, &ok); - if (ok) { - playerActions->actViewTopCards(number); - } -} - -void PlayerDialogs::onViewBottomCardsDialogRequested(int defaultNumberBottomCards, int deckSize) -{ - bool ok; - int number = QInputDialog::getInt(dialogParent(), tr("View bottom cards of library"), - tr("Number of cards: (max. %1)").arg(deckSize), defaultNumberBottomCards, 1, - deckSize, 1, &ok); - if (ok) { - playerActions->actViewBottomCards(number); - } -} - -void PlayerDialogs::onShuffleTopDialogRequested(int defaultNumberTopCards, int maxCards) -{ - bool ok; - int number = QInputDialog::getInt(dialogParent(), tr("Shuffle top cards of library"), - tr("Number of cards: (max. %1)").arg(maxCards), defaultNumberTopCards, 1, - maxCards, 1, &ok); - if (ok) { - playerActions->actShuffleTop(number); - } -} - -void PlayerDialogs::onShuffleBottomDialogRequested(int defaultNumberBottomCards, int maxCards) -{ - bool ok; - int number = QInputDialog::getInt(dialogParent(), tr("Shuffle bottom cards of library"), - tr("Number of cards: (max. %1)").arg(maxCards), defaultNumberBottomCards, 1, - maxCards, 1, &ok); - if (ok) { - playerActions->actShuffleBottom(number); - } -} - -void PlayerDialogs::onMulliganDialogRequested(int startSize, int handSize, int deckSize) -{ - bool ok; - int number = QInputDialog::getInt(dialogParent(), tr("Draw hand"), - tr("Number of cards: (max. %1)").arg(deckSize) + '\n' + - tr("0 and lower are in comparison to current hand size"), - startSize, -handSize, deckSize, 1, &ok); - - if (ok) { - playerActions->actMulligan(number); - } -} - -void PlayerDialogs::onDrawCardsDialogRequested(int defaultNumberTopCards, int deckSize) -{ - bool ok; - int number = QInputDialog::getInt(dialogParent(), tr("Draw cards"), tr("Number of cards: (max. %1)").arg(deckSize), - defaultNumberTopCards, 1, deckSize, 1, &ok); - - if (ok) { - playerActions->actDrawCards(number); - } -} - -void PlayerDialogs::onMoveTopCardsToDialogRequested(int defaultNumberTopCards, - int maxCards, - const QString &targetZone, - const QString &zoneDisplayName, - bool faceDown) -{ - bool ok; - int number = QInputDialog::getInt(dialogParent(), tr("Move top cards to %1").arg(zoneDisplayName), - tr("Number of cards: (max. %1)").arg(maxCards), defaultNumberTopCards, 1, - maxCards, 1, &ok); - if (ok) { - playerActions->moveTopCardsTo(number, targetZone, faceDown); - } -} - -void PlayerDialogs::onMoveTopCardsUntilDialogRequested(MoveTopCardsUntilOptions options) -{ - DlgMoveTopCardsUntil dlg(dialogParent(), options); - if (!dlg.exec()) { - return; - } - playerActions->moveTopCardsUntil(dlg.getExpr(), dlg.getOptions()); -} - -void PlayerDialogs::onMoveBottomCardsToDialogRequested(int defaultNumberBottomCards, - int maxCards, - const QString &targetZone, - const QString &zoneDisplayName, - bool faceDown) -{ - bool ok; - int number = QInputDialog::getInt(dialogParent(), tr("Move bottom cards to %1").arg(zoneDisplayName), - tr("Number of cards: (max. %1)").arg(maxCards), defaultNumberBottomCards, 1, - maxCards, 1, &ok); - if (ok) { - playerActions->moveBottomCardsTo(number, targetZone, faceDown); - } -} - -void PlayerDialogs::onDrawBottomCardsDialogRequested(int defaultNumberBottomCards, int maxCards) -{ - bool ok; - int number = - QInputDialog::getInt(dialogParent(), tr("Draw bottom cards"), tr("Number of cards: (max. %1)").arg(maxCards), - defaultNumberBottomCards, 1, maxCards, 1, &ok); - if (ok) { - playerActions->actDrawBottomCards(number); - } -} - -void PlayerDialogs::onRollDieDialogRequested() -{ - DlgRollDice dlg(dialogParent()); - if (!dlg.exec()) { - return; - } - playerActions->actRollDie(dlg.getDieSideCount(), dlg.getDiceToRollCount()); -} - -void PlayerDialogs::onCreateRelatedFromRelationDialogRequested(const CardItem *sourceCard, - const CardRelation *cardRelation) -{ - if (sourceCard == nullptr || cardRelation == nullptr) { - playerActions->setLastRelatedCreationSucceeded(false); - return; - } - - int variableCount = cardRelation->getDefaultCount(); - - if (cardRelation->getIsVariable()) { - bool ok; - - emit requestDialogSemaphore(true); - - variableCount = QInputDialog::getInt(dialogParent(), tr("Create tokens"), tr("Number:"), - cardRelation->getDefaultCount(), 1, MAX_TOKENS_PER_DIALOG, 1, &ok); - - emit requestDialogSemaphore(false); - - if (!ok) { - playerActions->setLastRelatedCreationSucceeded(false); // cancelled - return; - } - } - - const bool succeeded = playerActions->createRelatedFromRelation(sourceCard, cardRelation, variableCount); - - playerActions->setLastRelatedCreationSucceeded(succeeded); - - if (succeeded) { - playerActions->onRelatedCardCreated(sourceCard, cardRelation); // only on confirmed success - } -} - -void PlayerDialogs::onCreateTokenDialogRequested(const QStringList &predefinedTokens) -{ - DlgCreateToken dlg(predefinedTokens, dialogParent()); - if (!dlg.exec()) { - return; - } - - playerActions->actCreateToken(dlg.getTokenInfo()); -} - -void PlayerDialogs::onMoveCardXCardsFromTopDialogRequested(int defaultNumberTopCardsToPlaceBelow, int deckSize) -{ - bool ok; - int number = - QInputDialog::getInt(dialogParent(), tr("Place card X cards from top of library"), - tr("Which position should this card be placed:") + "\n" + tr("(max. %1)").arg(deckSize), - defaultNumberTopCardsToPlaceBelow, 1, deckSize, 1, &ok); - number -= 1; // indexes start at 0 - - if (ok) { - playerActions->actMoveCardXCardsFromTop(player->getGameScene()->selectedCards(), number); - } -} - -void PlayerDialogs::onSetPTDialogRequested(const QString &oldPT) -{ - bool ok; - auto cards = player->getGameScene()->selectedCards(); - emit requestDialogSemaphore(true); - QString pt = getTextWithMax(dialogParent(), tr("Change power/toughness"), tr("Change stats to:"), QLineEdit::Normal, - oldPT, &ok); - emit requestDialogSemaphore(false); - - if (!ok || player->getLogic()->clearCardsToDelete()) { - return; - } - - playerActions->actSetPT(cards, pt); -} - -void PlayerDialogs::onSetAnnotationDialogRequested(const QString &oldAnnotation) -{ - auto cards = player->getGameScene()->selectedCards(); - emit requestDialogSemaphore(true); - AnnotationDialog *dialog = new AnnotationDialog(dialogParent()); - dialog->setOptions(QInputDialog::UsePlainTextEditForTextInput); - dialog->setWindowTitle(tr("Set annotation")); - dialog->setLabelText(tr("Please enter the new annotation:")); - dialog->setTextValue(oldAnnotation); - bool ok = dialog->exec(); - emit requestDialogSemaphore(false); - if (!ok || player->getLogic()->clearCardsToDelete()) { - return; - } - QString annotation = dialog->textValue().left(MAX_NAME_LENGTH); - playerActions->actSetAnnotation(cards, annotation); -} - -void PlayerDialogs::onSetCardCounterDialogRequested(int counterId, const QString &oldValueForDlg) -{ - auto cards = player->getGameScene()->selectedCards(); - emit requestDialogSemaphore(true); - - auto &cardCounterSettings = SettingsCache::instance().cardCounters(); - QString counterName = cardCounterSettings.displayName(counterId); - - AbstractCounterDialog dialog(counterName, oldValueForDlg, dialogParent()); - int ok = dialog.exec(); - - emit requestDialogSemaphore(false); - if (!ok || player->getLogic()->clearCardsToDelete()) { - return; - } - playerActions->actSetCardCounter(cards, counterId, dialog.textValue()); -} \ No newline at end of file diff --git a/cockatrice/src/game_graphics/player/player_dialogs.h b/cockatrice/src/game_graphics/player/player_dialogs.h deleted file mode 100644 index f87704f2d..000000000 --- a/cockatrice/src/game_graphics/player/player_dialogs.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef COCKATRICE_PLAYER_DIALOGS_H -#define COCKATRICE_PLAYER_DIALOGS_H -#include "../../game/player/player_actions.h" -#include "player_graphics_item.h" - -#include -#include - -class PlayerGraphicsItem; -class PlayerDialogs : public QObject -{ - - Q_OBJECT - -public: - explicit PlayerDialogs(PlayerGraphicsItem *player, PlayerActions *playerActions); - -signals: - void requestDialogSemaphore(bool active); - -public slots: - void onViewTopCardsDialogRequested(int defaultNumberTopCards, int deckSize); - void onViewBottomCardsDialogRequested(int defaultNumberBottomCards, int deckSize); - void onShuffleTopDialogRequested(int defaultNumberTopCards, int maxCards); - void onShuffleBottomDialogRequested(int defaultNumberBottomCards, int maxCards); - void onMulliganDialogRequested(int startSize, int handSize, int deckSize); - void onDrawCardsDialogRequested(int defaultNumberTopCards, int deckSize); - void onMoveTopCardsToDialogRequested(int defaultNumberTopCards, - int maxCards, - const QString &targetZone, - const QString &zoneDisplayName, - bool faceDown); - void onMoveTopCardsUntilDialogRequested(MoveTopCardsUntilOptions options); - void onMoveBottomCardsToDialogRequested(int defaultNumberBottomCards, - int maxCards, - const QString &targetZone, - const QString &zoneDisplayName, - bool faceDown); - void onDrawBottomCardsDialogRequested(int defaultNumberBottomCards, int maxCards); - void onRollDieDialogRequested(); - void onCreateRelatedFromRelationDialogRequested(const CardItem *sourceCard, const CardRelation *cardRelation); - void onCreateTokenDialogRequested(const QStringList &predefinedTokens); - void onMoveCardXCardsFromTopDialogRequested(int defaultNumberTopCardsToPlaceBelow, int deckSize); - void onSetPTDialogRequested(const QString &oldPT); - void onSetAnnotationDialogRequested(const QString &oldAnnotation); - void onSetCardCounterDialogRequested(int counterId, const QString &oldValueForDlg); - -private: - PlayerGraphicsItem *player; - PlayerActions *playerActions; - - QWidget *dialogParent() const - { - if (auto *s = player->scene()) { - if (auto *v = s->views().value(0)) { - return v->window(); - } - } - return nullptr; - } -}; - -#endif // COCKATRICE_PLAYER_DIALOGS_H diff --git a/cockatrice/src/game_graphics/zones/card_zone.cpp b/cockatrice/src/game_graphics/zones/card_zone.cpp index 3457b681e..6ba8abe42 100644 --- a/cockatrice/src/game_graphics/zones/card_zone.cpp +++ b/cockatrice/src/game_graphics/zones/card_zone.cpp @@ -1,6 +1,6 @@ #include "card_zone.h" -#include "../board/card_item.h" +#include "../../game/board/card_item.h" #include "view_zone.h" #include diff --git a/cockatrice/src/game_graphics/zones/hand_zone.cpp b/cockatrice/src/game_graphics/zones/hand_zone.cpp index 5885e3630..09e9a5091 100644 --- a/cockatrice/src/game_graphics/zones/hand_zone.cpp +++ b/cockatrice/src/game_graphics/zones/hand_zone.cpp @@ -1,11 +1,11 @@ #include "hand_zone.h" #include "../../client/settings/cache_settings.h" +#include "../../game/board/card_drag_item.h" +#include "../../game/board/card_item.h" #include "../../game/player/player_actions.h" #include "../../game/player/player_logic.h" #include "../../interface/theme_manager.h" -#include "../board/card_drag_item.h" -#include "../board/card_item.h" #include #include diff --git a/cockatrice/src/game_graphics/zones/pile_zone.cpp b/cockatrice/src/game_graphics/zones/pile_zone.cpp index 7bb0e695a..302b983d8 100644 --- a/cockatrice/src/game_graphics/zones/pile_zone.cpp +++ b/cockatrice/src/game_graphics/zones/pile_zone.cpp @@ -1,10 +1,10 @@ #include "pile_zone.h" +#include "../../game/board/card_drag_item.h" +#include "../../game/board/card_item.h" #include "../../game/player/player_actions.h" #include "../../game/player/player_logic.h" #include "../../game/zones/pile_zone_logic.h" -#include "../board/card_drag_item.h" -#include "../board/card_item.h" #include "view_zone.h" #include diff --git a/cockatrice/src/game_graphics/zones/select_zone.cpp b/cockatrice/src/game_graphics/zones/select_zone.cpp index f2e720686..90d53b464 100644 --- a/cockatrice/src/game_graphics/zones/select_zone.cpp +++ b/cockatrice/src/game_graphics/zones/select_zone.cpp @@ -1,8 +1,8 @@ #include "select_zone.h" #include "../../client/settings/cache_settings.h" -#include "../board/card_item.h" -#include "../game_scene.h" +#include "../../game/board/card_item.h" +#include "../../game/game_scene.h" #include #include diff --git a/cockatrice/src/game_graphics/zones/stack_zone.cpp b/cockatrice/src/game_graphics/zones/stack_zone.cpp index 46ff099ab..9b0545b1d 100644 --- a/cockatrice/src/game_graphics/zones/stack_zone.cpp +++ b/cockatrice/src/game_graphics/zones/stack_zone.cpp @@ -1,12 +1,12 @@ #include "stack_zone.h" +#include "../../game/board/card_drag_item.h" +#include "../../game/board/card_item.h" +#include "../../game/card_dimensions.h" #include "../../game/player/player_actions.h" #include "../../game/player/player_logic.h" #include "../../game/zones/stack_zone_logic.h" #include "../../interface/theme_manager.h" -#include "../board/card_drag_item.h" -#include "../board/card_item.h" -#include "../card_dimensions.h" #include #include diff --git a/cockatrice/src/game_graphics/zones/table_zone.cpp b/cockatrice/src/game_graphics/zones/table_zone.cpp index e886f62e9..ffb4adf5c 100644 --- a/cockatrice/src/game_graphics/zones/table_zone.cpp +++ b/cockatrice/src/game_graphics/zones/table_zone.cpp @@ -1,14 +1,14 @@ #include "table_zone.h" #include "../../client/settings/cache_settings.h" +#include "../../game/board/arrow_item.h" +#include "../../game/board/card_drag_item.h" +#include "../../game/board/card_item.h" #include "../../game/player/player_actions.h" #include "../../game/player/player_logic.h" +#include "../../game/z_values.h" #include "../../game/zones/table_zone_logic.h" #include "../../interface/theme_manager.h" -#include "../board/arrow_item.h" -#include "../board/card_drag_item.h" -#include "../board/card_item.h" -#include "../z_values.h" #include #include @@ -22,8 +22,7 @@ const QColor TableZone::FADE_MASK = QColor(0, 0, 0, 80); const QColor TableZone::GRADIENT_COLOR = QColor(255, 255, 255, 150); const QColor TableZone::GRADIENT_COLORLESS = QColor(255, 255, 255, 0); -TableZone::TableZone(TableZoneLogic *_logic, bool _mirrored, QGraphicsItem *parent) - : SelectZone(_logic, parent), active(false), mirrored(_mirrored) +TableZone::TableZone(TableZoneLogic *_logic, QGraphicsItem *parent) : SelectZone(_logic, parent), active(false) { connect(_logic, &TableZoneLogic::contentSizeChanged, this, &TableZone::resizeToContents); connect(_logic, &TableZoneLogic::toggleTapped, this, &TableZone::toggleTapped); @@ -51,16 +50,12 @@ QRectF TableZone::boundingRect() const return QRectF(0, 0, width, height); } -void TableZone::setMirrored(bool isMirrored) -{ - mirrored = isMirrored; - update(); -} - bool TableZone::isInverted() const { - return ((mirrored && !SettingsCache::instance().getInvertVerticalCoordinate()) || - (!mirrored && SettingsCache::instance().getInvertVerticalCoordinate())); + return ((getLogic()->getPlayer()->getGraphicsItem()->getMirrored() && + !SettingsCache::instance().getInvertVerticalCoordinate()) || + (!getLogic()->getPlayer()->getGraphicsItem()->getMirrored() && + SettingsCache::instance().getInvertVerticalCoordinate())); } void TableZone::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/) diff --git a/cockatrice/src/game_graphics/zones/table_zone.h b/cockatrice/src/game_graphics/zones/table_zone.h index 0d7e58206..f46531520 100644 --- a/cockatrice/src/game_graphics/zones/table_zone.h +++ b/cockatrice/src/game_graphics/zones/table_zone.h @@ -7,8 +7,8 @@ #ifndef TABLEZONE_H #define TABLEZONE_H +#include "../../game/board/abstract_card_item.h" #include "../../game/zones/table_zone_logic.h" -#include "../board/abstract_card_item.h" #include "select_zone.h" /** @@ -82,7 +82,6 @@ private: If this TableZone is currently active */ bool active = false; - bool mirrored = false; [[nodiscard]] bool isInverted() const; @@ -97,7 +96,6 @@ public slots: Reorganizes CardItems in the TableZone */ void reorganizeCards() override; - void setMirrored(bool isMirrored); public: /** @@ -106,7 +104,7 @@ public: @param _p the Player @param parent defaults to null */ - explicit TableZone(TableZoneLogic *_logic, bool mirrored, QGraphicsItem *parent = nullptr); + explicit TableZone(TableZoneLogic *_logic, QGraphicsItem *parent = nullptr); /** @return a QRectF of the TableZone bounding box. diff --git a/cockatrice/src/game_graphics/zones/view_zone.cpp b/cockatrice/src/game_graphics/zones/view_zone.cpp index baf7b8b30..805c60638 100644 --- a/cockatrice/src/game_graphics/zones/view_zone.cpp +++ b/cockatrice/src/game_graphics/zones/view_zone.cpp @@ -1,10 +1,10 @@ #include "view_zone.h" +#include "../../game/board/card_drag_item.h" +#include "../../game/board/card_item.h" #include "../../game/player/player_actions.h" #include "../../game/player/player_logic.h" #include "../../game/zones/view_zone_logic.h" -#include "../board/card_drag_item.h" -#include "../board/card_item.h" #include #include diff --git a/cockatrice/src/game_graphics/zones/view_zone_widget.cpp b/cockatrice/src/game_graphics/zones/view_zone_widget.cpp index 14537a826..03c6d8925 100644 --- a/cockatrice/src/game_graphics/zones/view_zone_widget.cpp +++ b/cockatrice/src/game_graphics/zones/view_zone_widget.cpp @@ -2,12 +2,12 @@ #include "../../client/settings/cache_settings.h" #include "../../filters/syntax_help.h" +#include "../../game/board/card_item.h" +#include "../../game/game_scene.h" #include "../../game/player/player_actions.h" #include "../../game/player/player_logic.h" +#include "../../game/z_values.h" #include "../../interface/pixel_map_generator.h" -#include "../board/card_item.h" -#include "../game_scene.h" -#include "../z_values.h" #include "view_zone.h" #include @@ -75,11 +75,6 @@ ZoneViewWidget::ZoneViewWidget(PlayerLogic *_player, searchEditProxy->setZValue(ZValues::DRAG_ITEM); vbox->addItem(searchEditProxy); - // hide search bar if chat autofocus setting is enabled, since typing into it will no longer work anyway - searchEditProxy->setVisible(!SettingsCache::instance().getKeepGameChatFocus()); - connect(&SettingsCache::instance(), &SettingsCache::keepGameChatFocusChanged, searchEditProxy, - [searchEditProxy](bool keepFocus) { searchEditProxy->setVisible(!keepFocus); }); - // top row QGraphicsLinearLayout *hTopRow = new QGraphicsLinearLayout(Qt::Horizontal); diff --git a/cockatrice/src/interface/card_picture_loader/card_picture_loader_local_schemes.h b/cockatrice/src/interface/card_picture_loader/card_picture_loader_local_schemes.h index d51d646e6..cad7d2d5f 100644 --- a/cockatrice/src/interface/card_picture_loader/card_picture_loader_local_schemes.h +++ b/cockatrice/src/interface/card_picture_loader/card_picture_loader_local_schemes.h @@ -61,30 +61,24 @@ inline QString expandPattern(const QString &pattern, QString result = pattern; auto replaceIfPresent = [&](const QString &token, const QString &value) -> bool { - if (!result.contains(token)) { + if (!result.contains(token)) return true; - } - if (value.isEmpty()) { + if (value.isEmpty()) return false; - } result.replace(token, value); return true; }; - if (!replaceIfPresent("{name}", name)) { + if (!replaceIfPresent("{name}", name)) return {}; - } - if (!replaceIfPresent("{set}", set)) { + if (!replaceIfPresent("{set}", set)) return {}; - } - if (!replaceIfPresent("{collector}", collector)) { + if (!replaceIfPresent("{collector}", collector)) return {}; - } - if (!replaceIfPresent("{providerId}", providerId)) { + if (!replaceIfPresent("{providerId}", providerId)) return {}; - } return result; } @@ -102,9 +96,8 @@ generateImportVariants(const QString &name, const QString &set, const QString &c pattern.replace("_", sep); QString v = expandPattern(pattern, name, set, collector, providerId); - if (!v.isEmpty()) { + if (!v.isEmpty()) variants << v; - } } } diff --git a/cockatrice/src/interface/card_picture_loader/card_picture_loader_worker.cpp b/cockatrice/src/interface/card_picture_loader/card_picture_loader_worker.cpp index 2f51ba986..a0f000139 100644 --- a/cockatrice/src/interface/card_picture_loader/card_picture_loader_worker.cpp +++ b/cockatrice/src/interface/card_picture_loader/card_picture_loader_worker.cpp @@ -28,9 +28,8 @@ CardPictureLoaderWorker::CardPictureLoaderWorker() static_cast(SettingsCache::instance().getNetworkCacheSizeInMB())); connect(&SettingsCache::instance(), &SettingsCache::networkCacheSizeChanged, cache, [this](int newSizeInMB) { - if (cache) { + if (cache) cache->setMaximumCacheSize(1024L * 1024L * static_cast(newSizeInMB)); - } }); networkManager->setCache(cache); diff --git a/cockatrice/src/interface/deck_loader/deck_loader.cpp b/cockatrice/src/interface/deck_loader/deck_loader.cpp index 39a0c1071..e616c5eb5 100644 --- a/cockatrice/src/interface/deck_loader/deck_loader.cpp +++ b/cockatrice/src/interface/deck_loader/deck_loader.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -130,10 +129,7 @@ std::optional DeckLoader::loadFromRemote(const QString &nativeString std::optional DeckLoader::saveToFile(const DeckList &deck, const QString &fileName, DeckFileFormat::Format fmt) { - // Use QSaveFile so that a failed write (e.g. a full disk) leaves the existing deck untouched - // instead of truncating it to a 0-byte file. The target is only replaced once every byte has - // been flushed successfully in commit(). - QSaveFile file(fileName); + QFile file(fileName); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { qCWarning(DeckLoaderLog) << "Could not create or open file:" << fileName; return std::nullopt; @@ -149,19 +145,15 @@ DeckLoader::saveToFile(const DeckList &deck, const QString &fileName, DeckFileFo break; } + file.flush(); + file.close(); + + qCInfo(DeckLoaderLog) << "Saved deck to " << fileName << "with format" << fmt << "-" << success; + if (!success) { - file.cancelWriting(); - qCWarning(DeckLoaderLog) << "Failed to serialize deck for file:" << fileName; return std::nullopt; } - if (!file.commit()) { - qCWarning(DeckLoaderLog) << "Failed to save deck to " << fileName << ":" << file.errorString(); - return std::nullopt; - } - - qCInfo(DeckLoaderLog) << "Saved deck to " << fileName << "with format" << fmt; - LoadedDeck::LoadInfo lastLoadInfo = {fileName, fmt}; return lastLoadInfo; } @@ -204,44 +196,38 @@ bool DeckLoader::updateLastLoadedTimestamp(LoadedDeck &deck) QDateTime originalTimestamp = fileInfo.lastModified(); - // Use QSaveFile so that a failed write (e.g. a full disk) cannot truncate an existing deck to a - // 0-byte file while merely bumping its timestamp. - QSaveFile file(fileName); + // Open the file for writing + QFile file(fileName); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { qCWarning(DeckLoaderLog) << "Failed to open file for writing:" << fileName; return false; } + bool result = false; + // Perform file modifications deck.deckList.setLastLoadedTimestamp(QDateTime::currentDateTime().toString()); + result = deck.deckList.saveToFile_Native(&file); - if (!deck.deckList.saveToFile_Native(&file)) { - file.cancelWriting(); - qCWarning(DeckLoaderLog) << "Failed to serialize deck for file:" << fileName; - return false; + file.close(); // Close the file to ensure changes are flushed + + if (result) { + // Re-open the file and set the original timestamp + if (!file.open(QIODevice::ReadWrite)) { + qCWarning(DeckLoaderLog) << "Failed to re-open file to set timestamp:" << fileName; + return false; + } + + if (!file.setFileTime(originalTimestamp, QFileDevice::FileModificationTime)) { + qCWarning(DeckLoaderLog) << "Failed to set modification time for file:" << fileName; + file.close(); + return false; + } + + file.close(); } - if (!file.commit()) { - qCWarning(DeckLoaderLog) << "Failed to update timestamp for file:" << fileName << ":" << file.errorString(); - return false; - } - - // Re-open the file and restore the original timestamp, so that updating the lastLoadedTimestamp - // does not change the file's modification time. - QFile timestampFile(fileName); - if (!timestampFile.open(QIODevice::ReadWrite)) { - qCWarning(DeckLoaderLog) << "Failed to re-open file to set timestamp:" << fileName; - return false; - } - - if (!timestampFile.setFileTime(originalTimestamp, QFileDevice::FileModificationTime)) { - qCWarning(DeckLoaderLog) << "Failed to set modification time for file:" << fileName; - timestampFile.close(); - return false; - } - - timestampFile.close(); - return true; + return result; } static QString getDomainForWebsite(DeckLoader::DecklistWebsite website) @@ -458,54 +444,51 @@ bool DeckLoader::convertToCockatriceFormat(LoadedDeck &deck) return false; } - // Determine the format before touching any file, so an already-converted or - // unsupported deck never truncates or deletes anything. - switch (DeckFileFormat::getFormatFromName(fileName)) { - case DeckFileFormat::PlainText: - break; - case DeckFileFormat::Cockatrice: - qCInfo(DeckLoaderLog) << "File is already in Cockatrice format. No conversion needed."; - return true; - default: - qCWarning(DeckLoaderLog) << "Unsupported file format for conversion:" << fileName; - return false; - } - // Change the file extension to .cod QFileInfo fileInfo(fileName); QString newFileName = QDir::toNativeSeparators(fileInfo.path() + "/" + fileInfo.completeBaseName() + ".cod"); - // Use QSaveFile so a failed write (e.g. a full disk) cannot leave a 0-byte .cod - // behind and then delete the original deck. - QSaveFile file(newFileName); + // Open the new file for writing + QFile file(newFileName); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { qCWarning(DeckLoaderLog) << "Failed to open file for writing:" << newFileName; return false; } - if (!deck.deckList.saveToFile_Native(&file)) { - file.cancelWriting(); - qCWarning(DeckLoaderLog) << "Failed to serialize deck for file:" << newFileName; - return false; + bool result = false; + + // Perform file modifications based on the detected format + switch (DeckFileFormat::getFormatFromName(fileName)) { + case DeckFileFormat::PlainText: + // Save in Cockatrice's native format + result = deck.deckList.saveToFile_Native(&file); + break; + case DeckFileFormat::Cockatrice: + qCInfo(DeckLoaderLog) << "File is already in Cockatrice format. No conversion needed."; + result = true; + break; + default: + qCWarning(DeckLoaderLog) << "Unsupported file format for conversion:" << fileName; + result = false; + break; } - if (!file.commit()) { - qCWarning(DeckLoaderLog) << "Failed to convert deck to " << newFileName << ":" << file.errorString(); - return false; + file.close(); + + // Delete the old file if conversion was successful + if (result) { + if (!QFile::remove(fileName)) { + qCWarning(DeckLoaderLog) << "Failed to delete original file:" << fileName; + } else { + qCInfo(DeckLoaderLog) << "Original file deleted successfully:" << fileName; + } + deck.lastLoadInfo = { + .fileName = newFileName, + .fileFormat = DeckFileFormat::Cockatrice, + }; } - // Conversion succeeded: delete the original file. - if (!QFile::remove(fileName)) { - qCWarning(DeckLoaderLog) << "Failed to delete original file:" << fileName; - } else { - qCInfo(DeckLoaderLog) << "Original file deleted successfully:" << fileName; - } - deck.lastLoadInfo = { - .fileName = newFileName, - .fileFormat = DeckFileFormat::Cockatrice, - }; - - return true; + return result; } void DeckLoader::printDeckListNode(QTextCursor *cursor, const InnerDecklistNode *node) diff --git a/cockatrice/src/interface/layouts/flow_layout.cpp b/cockatrice/src/interface/layouts/flow_layout.cpp index 0d03b7789..36edd2c21 100644 --- a/cockatrice/src/interface/layouts/flow_layout.cpp +++ b/cockatrice/src/interface/layouts/flow_layout.cpp @@ -70,9 +70,8 @@ bool FlowLayout::hasHeightForWidth() const */ int FlowLayout::heightForWidth(const int width) const { - if (flowDirection != Qt::Horizontal) { + if (flowDirection != Qt::Horizontal) return -1; - } int totalHeight = 0; int rowUsedWidth = 0; @@ -182,9 +181,8 @@ int FlowLayout::layoutAllRows(const int originX, const int originY, const int av */ void FlowLayout::layoutSingleRow(const QVector &rowItems, int x, const int y, const int availableWidth) { - if (rowItems.isEmpty()) { + if (rowItems.isEmpty()) return; - } // ── Pass 1: measure fixed width and count expanding items ──────────────── int fixedWidth = 0; @@ -213,14 +211,12 @@ void FlowLayout::layoutSingleRow(const QVector &rowItems, int x, // ── Pass 2: place items ────────────────────────────────────────────────── for (QLayoutItem *item : rowItems) { - if (!item || item->isEmpty()) { + if (!item || item->isEmpty()) continue; - } QWidget *widget = item->widget(); - if (!widget) { + if (!widget) continue; - } const QSizePolicy::Policy hPolicy = widget->sizePolicy().horizontalPolicy(); const QSize maxSize = widget->maximumSize(); diff --git a/cockatrice/src/interface/widgets/cards/card_group_display_widgets/card_group_display_widget.cpp b/cockatrice/src/interface/widgets/cards/card_group_display_widgets/card_group_display_widget.cpp index 3f36e559c..5fb0cb343 100644 --- a/cockatrice/src/interface/widgets/cards/card_group_display_widgets/card_group_display_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/card_group_display_widgets/card_group_display_widget.cpp @@ -58,6 +58,16 @@ void CardGroupDisplayWidget::mousePressEvent(QMouseEvent *event) } } +void CardGroupDisplayWidget::onClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *card) +{ + emit cardClicked(event, card); +} + +void CardGroupDisplayWidget::onHover(const ExactCard &card) +{ + emit cardHovered(card); +} + void CardGroupDisplayWidget::onSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected) { auto proxyModel = qobject_cast(selectionModel->model()); @@ -144,8 +154,8 @@ QWidget *CardGroupDisplayWidget::constructWidgetForIndex(QPersistentModelIndex i widget->setScaleFactor(cardSizeWidget->getSlider()->value()); widget->setCard(CardDatabaseManager::query()->getCard({cardName, cardProviderId})); - connect(widget, &CardInfoPictureWithTextOverlayWidget::cardClicked, this, &CardGroupDisplayWidget::cardClicked); - connect(widget, &CardInfoPictureWithTextOverlayWidget::hoveredOnCard, this, &CardGroupDisplayWidget::cardHovered); + connect(widget, &CardInfoPictureWithTextOverlayWidget::imageClicked, this, &CardGroupDisplayWidget::onClick); + connect(widget, &CardInfoPictureWithTextOverlayWidget::hoveredOnCard, this, &CardGroupDisplayWidget::onHover); connect(cardSizeWidget->getSlider(), &QSlider::valueChanged, widget, &CardInfoPictureWidget::setScaleFactor); indexToWidgetMap[index].append(widget); diff --git a/cockatrice/src/interface/widgets/cards/card_group_display_widgets/card_group_display_widget.h b/cockatrice/src/interface/widgets/cards/card_group_display_widgets/card_group_display_widget.h index 2308ccf8d..848bebb7e 100644 --- a/cockatrice/src/interface/widgets/cards/card_group_display_widgets/card_group_display_widget.h +++ b/cockatrice/src/interface/widgets/cards/card_group_display_widgets/card_group_display_widget.h @@ -48,6 +48,8 @@ public: public slots: void mousePressEvent(QMouseEvent *event) override; + void onClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *card); + void onHover(const ExactCard &card); virtual QWidget *constructWidgetForIndex(QPersistentModelIndex index); virtual void updateCardDisplays(); virtual void onCardAddition(const QModelIndex &parent, int first, int last); @@ -57,7 +59,7 @@ public slots: void resizeEvent(QResizeEvent *event) override; signals: - void cardClicked(QMouseEvent *event, const ExactCard &card); + void cardClicked(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *card); void cardHovered(const ExactCard &card); void cleanupRequested(CardGroupDisplayWidget *cardGroupDisplayWidget); diff --git a/cockatrice/src/interface/widgets/cards/card_info_display_widget.cpp b/cockatrice/src/interface/widgets/cards/card_info_display_widget.cpp index 577dafe0a..509a2d92f 100644 --- a/cockatrice/src/interface/widgets/cards/card_info_display_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/card_info_display_widget.cpp @@ -1,6 +1,6 @@ #include "card_info_display_widget.h" -#include "../../../game_graphics/board/card_item.h" +#include "../../../game/board/card_item.h" #include "card_info_picture_widget.h" #include "card_info_text_widget.h" diff --git a/cockatrice/src/interface/widgets/cards/card_info_frame_widget.cpp b/cockatrice/src/interface/widgets/cards/card_info_frame_widget.cpp index 2e7c62461..21bee8f54 100644 --- a/cockatrice/src/interface/widgets/cards/card_info_frame_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/card_info_frame_widget.cpp @@ -1,7 +1,7 @@ #include "card_info_frame_widget.h" #include "../../../client/settings/cache_settings.h" -#include "../../../game_graphics/board/card_item.h" +#include "../../../game/board/card_item.h" #include "card_info_display_widget.h" #include "card_info_picture_widget.h" #include "card_info_text_widget.h" diff --git a/cockatrice/src/interface/widgets/cards/card_info_picture_widget.cpp b/cockatrice/src/interface/widgets/cards/card_info_picture_widget.cpp index 3bfd9ce7d..555d69381 100644 --- a/cockatrice/src/interface/widgets/cards/card_info_picture_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/card_info_picture_widget.cpp @@ -1,7 +1,7 @@ #include "card_info_picture_widget.h" #include "../../../client/settings/cache_settings.h" -#include "../../../game_graphics/board/card_item.h" +#include "../../../game/board/card_item.h" #include "../../../interface/card_picture_loader/card_picture_loader.h" #include "../../../interface/widgets/tabs/tab_supervisor.h" #include "../../window_main.h" @@ -345,7 +345,7 @@ void CardInfoPictureWidget::mousePressEvent(QMouseEvent *event) createRightClickMenu()->popup(QCursor::pos()); } - emit cardClicked(event, exactCard); + emit cardClicked(event); } void CardInfoPictureWidget::hideEvent(QHideEvent *event) @@ -431,13 +431,13 @@ QMenu *CardInfoPictureWidget::createAddToOpenDeckMenu() QAction *addCard = addCardMenu->addAction(tr("Mainboard")); connect(addCard, &QAction::triggered, this, [this, deckEditorTab] { deckEditorTab->updateCard(exactCard); - deckEditorTab->addCard(exactCard, DECK_ZONE_MAIN); + deckEditorTab->actAddCard(exactCard); }); QAction *addCardSideboard = addCardMenu->addAction(tr("Sideboard")); connect(addCardSideboard, &QAction::triggered, this, [this, deckEditorTab] { deckEditorTab->updateCard(exactCard); - deckEditorTab->addCard(exactCard, DECK_ZONE_SIDE); + deckEditorTab->actAddCardToSideboard(exactCard); }); } diff --git a/cockatrice/src/interface/widgets/cards/card_info_picture_widget.h b/cockatrice/src/interface/widgets/cards/card_info_picture_widget.h index 1f065eed9..bfa6584b1 100644 --- a/cockatrice/src/interface/widgets/cards/card_info_picture_widget.h +++ b/cockatrice/src/interface/widgets/cards/card_info_picture_widget.h @@ -43,7 +43,7 @@ signals: void hoveredOnCard(const ExactCard &hoveredCard); void cardScaleFactorChanged(int _scale); void cardChanged(const ExactCard &card); - void cardClicked(QMouseEvent *event, const ExactCard &card); + void cardClicked(QMouseEvent *event); protected: void resizeEvent(QResizeEvent *event) override; diff --git a/cockatrice/src/interface/widgets/cards/card_info_picture_with_text_overlay_widget.cpp b/cockatrice/src/interface/widgets/cards/card_info_picture_with_text_overlay_widget.cpp index c5cb59b3b..2f0aeccfd 100644 --- a/cockatrice/src/interface/widgets/cards/card_info_picture_with_text_overlay_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/card_info_picture_with_text_overlay_widget.cpp @@ -93,7 +93,7 @@ void CardInfoPictureWithTextOverlayWidget::setHighlighted(bool _highlighted) void CardInfoPictureWithTextOverlayWidget::mousePressEvent(QMouseEvent *event) { - emit cardClicked(event, getCard()); + emit imageClicked(event, this); } /** diff --git a/cockatrice/src/interface/widgets/cards/card_info_picture_with_text_overlay_widget.h b/cockatrice/src/interface/widgets/cards/card_info_picture_with_text_overlay_widget.h index ba978498d..0cc7e501c 100644 --- a/cockatrice/src/interface/widgets/cards/card_info_picture_with_text_overlay_widget.h +++ b/cockatrice/src/interface/widgets/cards/card_info_picture_with_text_overlay_widget.h @@ -35,6 +35,8 @@ public: void setHighlighted(bool _highlighted); [[nodiscard]] QSize sizeHint() const override; +signals: + void imageClicked(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance); protected: void paintEvent(QPaintEvent *event) override; diff --git a/cockatrice/src/interface/widgets/cards/card_info_text_widget.cpp b/cockatrice/src/interface/widgets/cards/card_info_text_widget.cpp index c6af5320b..345eb9909 100644 --- a/cockatrice/src/interface/widgets/cards/card_info_text_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/card_info_text_widget.cpp @@ -1,6 +1,6 @@ #include "card_info_text_widget.h" -#include "../../../game_graphics/board/card_item.h" +#include "../../../game/board/card_item.h" #include #include diff --git a/cockatrice/src/interface/widgets/cards/deck_card_zone_display_widget.cpp b/cockatrice/src/interface/widgets/cards/deck_card_zone_display_widget.cpp index eaf3a67b0..a8a97a4ca 100644 --- a/cockatrice/src/interface/widgets/cards/deck_card_zone_display_widget.cpp +++ b/cockatrice/src/interface/widgets/cards/deck_card_zone_display_widget.cpp @@ -51,7 +51,7 @@ DeckCardZoneDisplayWidget::DeckCardZoneDisplayWidget(QWidget *parent, // User Interaction // ===================================================================================================================== -void DeckCardZoneDisplayWidget::onClick(QMouseEvent *event, const ExactCard &card) +void DeckCardZoneDisplayWidget::onClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *card) { emit cardClicked(event, card, zoneName); } diff --git a/cockatrice/src/interface/widgets/cards/deck_card_zone_display_widget.h b/cockatrice/src/interface/widgets/cards/deck_card_zone_display_widget.h index b426fca30..074a77e53 100644 --- a/cockatrice/src/interface/widgets/cards/deck_card_zone_display_widget.h +++ b/cockatrice/src/interface/widgets/cards/deck_card_zone_display_widget.h @@ -42,7 +42,7 @@ public: void addCardsToOverlapWidget(); public slots: - void onClick(QMouseEvent *event, const ExactCard &card); + void onClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *card); void onHover(const ExactCard &card); void cleanupInvalidCardGroup(CardGroupDisplayWidget *displayWidget); void constructAppropriateWidget(QPersistentModelIndex index); @@ -55,7 +55,7 @@ public slots: void onCategoryRemoval(const QModelIndex &parent, int first, int last); signals: - void cardClicked(QMouseEvent *event, const ExactCard &card, const QString &zoneName); + void cardClicked(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *card, QString zoneName); void cardHovered(const ExactCard &card); void activeSortCriteriaChanged(QStringList activeSortCriteria); void requestCleanup(DeckCardZoneDisplayWidget *displayWidget); diff --git a/cockatrice/src/interface/widgets/deck_editor/card_database_view.cpp b/cockatrice/src/interface/widgets/deck_editor/card_database_view.cpp deleted file mode 100644 index a1c29e241..000000000 --- a/cockatrice/src/interface/widgets/deck_editor/card_database_view.cpp +++ /dev/null @@ -1,167 +0,0 @@ -#include "card_database_view.h" - -#include "../../../client/settings/cache_settings.h" -#include "card_database_display_model.h" -#include "card_database_model.h" - -#include -#include -#include -#include -#include -#include -#include - -static bool canBeCommander(const CardInfo &cardInfo) -{ - return (cardInfo.getCardType().contains("Legendary", Qt::CaseInsensitive) && - cardInfo.getCardType().contains("Creature", Qt::CaseInsensitive)) || - cardInfo.getText().contains("can be your commander", Qt::CaseInsensitive); -} - -CardDatabaseView::CardDatabaseView(QWidget *parent, CardDatabaseDisplayModel *model) - : QTreeView(parent), databaseDisplayModel(model) -{ - // set up object - setUniformRowHeights(true); - setRootIsDecorated(false); - setAlternatingRowColors(true); - setSortingEnabled(true); - sortByColumn(0, Qt::AscendingOrder); - QTreeView::setModel(databaseDisplayModel); - setContextMenuPolicy(Qt::CustomContextMenu); - - connect(databaseDisplayModel, &CardDatabaseDisplayModel::modelDirty, this, - &CardDatabaseView::resetSelectionIfEmpty); - - connect(this, &QTreeView::customContextMenuRequested, this, &CardDatabaseView::openCustomMenu); - connect(selectionModel(), &QItemSelectionModel::currentRowChanged, this, &CardDatabaseView::updateCard); - connect(this, &QTreeView::doubleClicked, this, &CardDatabaseView::actDoubleClick); - - // layout settings - QByteArray dbHeaderState = SettingsCache::instance().layouts().getDeckEditorDbHeaderState(); - if (dbHeaderState.isNull()) { - // first run - setColumnWidth(0, 200); - } else { - header()->restoreState(dbHeaderState); - } - connect(header(), &QHeaderView::geometriesChanged, this, &CardDatabaseView::saveDbHeaderState); - - // create key filters - searchKeySignals.setObjectName("searchKeySignals"); - connect(&searchKeySignals, &KeySignals::onEnter, this, [this] { addCard(DECK_ZONE_MAIN); }); - connect(&searchKeySignals, &KeySignals::onCtrlAltEqual, this, [this] { addCard(DECK_ZONE_MAIN); }); - connect(&searchKeySignals, &KeySignals::onCtrlAltRBracket, this, [this] { addCard(DECK_ZONE_SIDE); }); - connect(&searchKeySignals, &KeySignals::onCtrlAltMinus, this, [this] { decrementCard(DECK_ZONE_MAIN); }); - connect(&searchKeySignals, &KeySignals::onCtrlAltLBracket, this, [this] { decrementCard(DECK_ZONE_SIDE); }); - connect(&searchKeySignals, &KeySignals::onCtrlAltEnter, this, [this] { addCard(DECK_ZONE_SIDE); }); - connect(&searchKeySignals, &KeySignals::onCtrlEnter, this, [this] { addCard(DECK_ZONE_SIDE); }); - connect(&searchKeySignals, &KeySignals::onCtrlC, this, &CardDatabaseView::copyDatabaseCellContents); -} - -QString CardDatabaseView::currentCardName() const -{ - const QModelIndex currentIndex = selectionModel()->currentIndex(); - if (!currentIndex.isValid()) { - return {}; - } - - return currentIndex.siblingAtColumn(CardDatabaseModel::NameColumn).data().toString(); -} - -void CardDatabaseView::actDoubleClick() -{ - if (QApplication::keyboardModifiers() & Qt::ControlModifier) { - addCard(DECK_ZONE_SIDE); - } else { - addCard(DECK_ZONE_MAIN); - } -} - -void CardDatabaseView::addCard(const QString &zoneName) -{ - emit cardAdded(currentCardName(), zoneName); -} - -void CardDatabaseView::decrementCard(const QString &zoneName) -{ - emit cardDecremented(currentCardName(), zoneName); -} - -void CardDatabaseView::updateCard(const QModelIndex ¤t, const QModelIndex & /*previous*/) -{ - if (!current.isValid()) { - return; - } - - const QString cardName = current.siblingAtColumn(CardDatabaseModel::NameColumn).data().toString(); - - if (!current.model()->hasChildren(current.siblingAtColumn(CardDatabaseModel::NameColumn))) { - emit cardChanged(cardName); - } -} - -void CardDatabaseView::resetSelectionIfEmpty() -{ - QModelIndexList sel = selectionModel()->selectedRows(); - if (sel.isEmpty() && databaseDisplayModel->rowCount() > 0) { - selectionModel()->setCurrentIndex(databaseDisplayModel->index(0, 0), - QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); - } -} - -void CardDatabaseView::copyDatabaseCellContents() const -{ - auto _data = selectionModel()->currentIndex().data(); - QApplication::clipboard()->setText(_data.toString()); -} - -void CardDatabaseView::saveDbHeaderState() -{ - SettingsCache::instance().layouts().setDeckEditorDbHeaderState(header()->saveState()); -} - -void CardDatabaseView::openCustomMenu(QPoint point) -{ - CardInfoPtr card = CardDatabaseManager::query()->getCardInfo(currentCardName()); - - if (!card) { - return; - } - - QMenu menu; - // add to deck and sideboard options - QAction *addToDeck = menu.addAction(tr("Add to Deck")); - QAction *addToSideboard = menu.addAction(tr("Add to Sideboard")); - QAction *selectPrinting = menu.addAction(tr("Select Printing")); - - connect(addToDeck, &QAction::triggered, this, [this, card] { emit cardAdded(card->getName(), DECK_ZONE_MAIN); }); - connect(addToSideboard, &QAction::triggered, this, - [this, card] { emit cardAdded(card->getName(), DECK_ZONE_SIDE); }); - connect(selectPrinting, &QAction::triggered, this, &CardDatabaseView::selectPrintingClicked); - - if (canBeCommander(*card)) { - QAction *edhRecCommander = menu.addAction(tr("Show on EDHRec (Commander)")); - connect(edhRecCommander, &QAction::triggered, this, [this, card] { emit edhrecClicked(card, true); }); - } - QAction *edhRecCard = menu.addAction(tr("Show on EDHRec (Card)")); - connect(edhRecCard, &QAction::triggered, this, [this, card] { emit edhrecClicked(card, false); }); - - // filling out the related cards submenu - auto *relatedMenu = new QMenu(tr("Show Related cards")); - menu.addMenu(relatedMenu); - auto relatedCards = card->getAllRelatedCards(); - if (relatedCards.isEmpty()) { - relatedMenu->setDisabled(true); - } else { - for (const CardRelation *rel : relatedCards) { - const QString &relatedCardName = rel->getName(); - QAction *relatedCard = relatedMenu->addAction(relatedCardName); - connect(relatedCard, &QAction::triggered, this, - [this, relatedCardName] { emit relatedCardClicked(relatedCardName); }); - } - } - - menu.exec(mapToGlobal(point)); -} diff --git a/cockatrice/src/interface/widgets/deck_editor/card_database_view.h b/cockatrice/src/interface/widgets/deck_editor/card_database_view.h deleted file mode 100644 index 175ec12b9..000000000 --- a/cockatrice/src/interface/widgets/deck_editor/card_database_view.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef COCKATRICE_CARD_DATABASE_VIEW_H -#define COCKATRICE_CARD_DATABASE_VIEW_H - -#include "../../key_signals.h" - -#include -#include - -class CardDatabaseModel; -class CardDatabaseDisplayModel; - -/** - * @brief The card database table. - */ -class CardDatabaseView : public QTreeView -{ - Q_OBJECT - - KeySignals searchKeySignals; - CardDatabaseDisplayModel *databaseDisplayModel; - -public: - explicit CardDatabaseView(QWidget *parent, CardDatabaseDisplayModel *model); - - QString currentCardName() const; - - /** - * @brief Get the KeySignals that are connected to this view. - * You can install the KeySignals as an eventFilter to capture keyboard shortcuts for adding and decrementing cards. - */ - KeySignals *getKeySignals() - { - return &searchKeySignals; - } - -signals: - void cardChanged(const QString &cardName); - - void cardAdded(const QString &cardName, const QString &zoneName); - void cardDecremented(const QString &cardName, const QString &zoneName); - - void edhrecClicked(const CardInfoPtr &cardInfo, bool isCommander); - void selectPrintingClicked(); - void relatedCardClicked(const QString &relatedCard); - -private slots: - void actDoubleClick(); - - void addCard(const QString &zoneName); - void decrementCard(const QString &zoneName); - void updateCard(const QModelIndex ¤t, const QModelIndex &); - - void resetSelectionIfEmpty(); - void copyDatabaseCellContents() const; - void saveDbHeaderState(); - void openCustomMenu(QPoint point); -}; - -#endif // COCKATRICE_CARD_DATABASE_VIEW_H diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_editor_card_database_dock_widget.cpp b/cockatrice/src/interface/widgets/deck_editor/deck_editor_card_database_dock_widget.cpp index 2a491de4f..f2a2ab4ea 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_editor_card_database_dock_widget.cpp +++ b/cockatrice/src/interface/widgets/deck_editor/deck_editor_card_database_dock_widget.cpp @@ -13,7 +13,7 @@ DeckEditorCardDatabaseDockWidget::DeckEditorCardDatabaseDockWidget(AbstractTabDe void DeckEditorCardDatabaseDockWidget::createDatabaseDisplayDock(AbstractTabDeckEditor *deckEditor) { - databaseDisplayWidget = new DeckEditorDatabaseDisplayWidget(this, deckEditor->databaseModel); + databaseDisplayWidget = new DeckEditorDatabaseDisplayWidget(this, deckEditor); auto *frame = new QVBoxLayout; frame->setObjectName("databaseDisplayFrame"); @@ -29,16 +29,19 @@ void DeckEditorCardDatabaseDockWidget::createDatabaseDisplayDock(AbstractTabDeck // connect signals connect(databaseDisplayWidget, &DeckEditorDatabaseDisplayWidget::cardChanged, deckEditor, &AbstractTabDeckEditor::updateCard); - connect(databaseDisplayWidget, &DeckEditorDatabaseDisplayWidget::cardAdded, deckEditor, - &AbstractTabDeckEditor::addCard); - connect(databaseDisplayWidget, &DeckEditorDatabaseDisplayWidget::cardDecremented, deckEditor, - &AbstractTabDeckEditor::decrementCard); - connect(databaseDisplayWidget, &DeckEditorDatabaseDisplayWidget::edhrecRequested, deckEditor, - &AbstractTabDeckEditor::openEdhrecTab); - connect(databaseDisplayWidget, &DeckEditorDatabaseDisplayWidget::printingSelectorRequested, deckEditor, - &AbstractTabDeckEditor::showPrintingSelector); - connect(databaseDisplayWidget, &DeckEditorDatabaseDisplayWidget::cardInfoRequested, deckEditor, - &AbstractTabDeckEditor::updateCardInfo); + connect(databaseDisplayWidget, &DeckEditorDatabaseDisplayWidget::addCardToMainDeck, deckEditor, + &AbstractTabDeckEditor::actAddCard); + connect(databaseDisplayWidget, &DeckEditorDatabaseDisplayWidget::addCardToSideboard, deckEditor, + &AbstractTabDeckEditor::actAddCardToSideboard); + connect(databaseDisplayWidget, &DeckEditorDatabaseDisplayWidget::decrementCardFromMainDeck, deckEditor, + &AbstractTabDeckEditor::actDecrementCard); + connect(databaseDisplayWidget, &DeckEditorDatabaseDisplayWidget::decrementCardFromSideboard, deckEditor, + &AbstractTabDeckEditor::actDecrementCardFromSideboard); +} + +CardDatabase *DeckEditorCardDatabaseDockWidget::getDatabase() const +{ + return databaseDisplayWidget->databaseModel->getDatabase(); } void DeckEditorCardDatabaseDockWidget::retranslateUi() diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_editor_card_database_dock_widget.h b/cockatrice/src/interface/widgets/deck_editor/deck_editor_card_database_dock_widget.h index 6af2e4432..bff9ee36f 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_editor_card_database_dock_widget.h +++ b/cockatrice/src/interface/widgets/deck_editor/deck_editor_card_database_dock_widget.h @@ -17,6 +17,7 @@ public: DeckEditorDatabaseDisplayWidget *databaseDisplayWidget; + CardDatabase *getDatabase() const; void setFilterTree(FilterTree *filterTree); public slots: diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.cpp b/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.cpp index 9da821813..580db67f4 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.cpp +++ b/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.cpp @@ -5,17 +5,24 @@ #include "../../../interface/widgets/tabs/abstract_tab_deck_editor.h" #include "../../../interface/widgets/tabs/tab_supervisor.h" #include "../../pixel_map_generator.h" -#include "card_database_view.h" #include #include +#include #include #include #include #include -DeckEditorDatabaseDisplayWidget::DeckEditorDatabaseDisplayWidget(QWidget *parent, CardDatabaseModel *databaseModel) - : QWidget(parent) +static bool canBeCommander(const CardInfo &cardInfo) +{ + return (cardInfo.getCardType().contains("Legendary", Qt::CaseInsensitive) && + cardInfo.getCardType().contains("Creature", Qt::CaseInsensitive)) || + cardInfo.getText().contains("can be your commander", Qt::CaseInsensitive); +} + +DeckEditorDatabaseDisplayWidget::DeckEditorDatabaseDisplayWidget(QWidget *parent, AbstractTabDeckEditor *deckEditor) + : QWidget(parent), deckEditor(deckEditor) { setObjectName("databaseDisplayWidget"); @@ -29,34 +36,62 @@ DeckEditorDatabaseDisplayWidget::DeckEditorDatabaseDisplayWidget(QWidget *parent searchEdit->setClearButtonEnabled(true); searchEdit->addAction(loadColorAdjustedPixmap("theme:icons/search"), QLineEdit::LeadingPosition); auto help = searchEdit->addAction(QPixmap("theme:icons/info"), QLineEdit::TrailingPosition); + searchEdit->installEventFilter(&searchKeySignals); setFocusProxy(searchEdit); setFocusPolicy(Qt::ClickFocus); + searchKeySignals.setObjectName("searchKeySignals"); + connect(searchEdit, &SearchLineEdit::textChanged, this, &DeckEditorDatabaseDisplayWidget::updateSearch); + connect(&searchKeySignals, &KeySignals::onEnter, this, &DeckEditorDatabaseDisplayWidget::actAddCardToMainDeck); + connect(&searchKeySignals, &KeySignals::onCtrlAltEqual, this, + &DeckEditorDatabaseDisplayWidget::actAddCardToMainDeck); + connect(&searchKeySignals, &KeySignals::onCtrlAltRBracket, this, + &DeckEditorDatabaseDisplayWidget::actAddCardToSideboard); + connect(&searchKeySignals, &KeySignals::onCtrlAltMinus, this, + &DeckEditorDatabaseDisplayWidget::actDecrementCardFromMainDeck); + connect(&searchKeySignals, &KeySignals::onCtrlAltLBracket, this, + &DeckEditorDatabaseDisplayWidget::actDecrementCardFromSideboard); + connect(&searchKeySignals, &KeySignals::onCtrlAltEnter, this, + &DeckEditorDatabaseDisplayWidget::actAddCardToSideboard); + connect(&searchKeySignals, &KeySignals::onCtrlEnter, this, &DeckEditorDatabaseDisplayWidget::actAddCardToSideboard); + connect(&searchKeySignals, &KeySignals::onCtrlC, this, &DeckEditorDatabaseDisplayWidget::copyDatabaseCellContents); connect(help, &QAction::triggered, this, [this] { createSearchSyntaxHelpWindow(searchEdit); }); + databaseModel = new CardDatabaseModel(CardDatabaseManager::getInstance(), true, this); + databaseModel->setObjectName("databaseModel"); databaseDisplayModel = new CardDatabaseDisplayModel(this); databaseDisplayModel->setObjectName("databaseDisplayModel"); databaseDisplayModel->setSourceModel(databaseModel); databaseDisplayModel->setFilterKeyColumn(0); - databaseView = new CardDatabaseView(this, databaseDisplayModel); + databaseView = new QTreeView(this); databaseView->setObjectName("databaseView"); databaseView->setFocusProxy(searchEdit); + databaseView->setUniformRowHeights(true); + databaseView->setRootIsDecorated(false); + databaseView->setAlternatingRowColors(true); + databaseView->setSortingEnabled(true); + databaseView->sortByColumn(0, Qt::AscendingOrder); + databaseView->setModel(databaseDisplayModel); + databaseView->setContextMenuPolicy(Qt::CustomContextMenu); + connect(databaseView, &QTreeView::customContextMenuRequested, this, + &DeckEditorDatabaseDisplayWidget::databaseCustomMenu); + connect(databaseView->selectionModel(), &QItemSelectionModel::currentRowChanged, this, + &DeckEditorDatabaseDisplayWidget::updateCard); + connect(databaseView, &QTreeView::doubleClicked, this, &DeckEditorDatabaseDisplayWidget::actAddCardToMainDeck); + + QByteArray dbHeaderState = SettingsCache::instance().layouts().getDeckEditorDbHeaderState(); + if (dbHeaderState.isNull()) { + // first run + databaseView->setColumnWidth(0, 200); + } else { + databaseView->header()->restoreState(dbHeaderState); + } + connect(databaseView->header(), &QHeaderView::geometriesChanged, this, + &DeckEditorDatabaseDisplayWidget::saveDbHeaderState); searchEdit->setTreeView(databaseView); - searchEdit->installEventFilter(databaseView->getKeySignals()); - - connect(searchEdit, &SearchLineEdit::textChanged, databaseDisplayModel, &CardDatabaseDisplayModel::setStringFilter); - connect(databaseView, &CardDatabaseView::cardAdded, this, &DeckEditorDatabaseDisplayWidget::addCard); - connect(databaseView, &CardDatabaseView::cardDecremented, this, &DeckEditorDatabaseDisplayWidget::decrementCard); - connect(databaseView, &CardDatabaseView::cardChanged, this, &DeckEditorDatabaseDisplayWidget::updateCard); - - connect(databaseView, &CardDatabaseView::edhrecClicked, this, &DeckEditorDatabaseDisplayWidget::edhrecRequested); - connect(databaseView, &CardDatabaseView::selectPrintingClicked, this, - &DeckEditorDatabaseDisplayWidget::printingSelectorRequested); - connect(databaseView, &CardDatabaseView::relatedCardClicked, this, - &DeckEditorDatabaseDisplayWidget::onRelatedCardClicked); aAddCard = new QAction(QString(), this); aAddCard->setIcon(QPixmap("theme:icons/arrow_right_green")); @@ -82,39 +117,121 @@ DeckEditorDatabaseDisplayWidget::DeckEditorDatabaseDisplayWidget(QWidget *parent retranslateUi(); } +void DeckEditorDatabaseDisplayWidget::updateSearch(const QString &search) +{ + databaseDisplayModel->setStringFilter(search); + QModelIndexList sel = databaseView->selectionModel()->selectedRows(); + if (sel.isEmpty() && databaseDisplayModel->rowCount()) { + databaseView->selectionModel()->setCurrentIndex(databaseDisplayModel->index(0, 0), + QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); + } +} + void DeckEditorDatabaseDisplayWidget::clearAllDatabaseFilters() { databaseDisplayModel->clearFilterAll(); searchEdit->setText(""); } +void DeckEditorDatabaseDisplayWidget::updateCard(const QModelIndex ¤t, const QModelIndex & /*previous*/) +{ + if (!current.isValid()) { + return; + } + + const QString cardName = current.siblingAtColumn(CardDatabaseModel::NameColumn).data().toString(); + + if (!current.model()->hasChildren(current.siblingAtColumn(CardDatabaseModel::NameColumn))) { + emit cardChanged(CardDatabaseManager::query()->getPreferredCard(cardName)); + } +} + void DeckEditorDatabaseDisplayWidget::actAddCardToMainDeck() { - addCard(databaseView->currentCardName(), DECK_ZONE_MAIN); + highlightAllSearchEdit(); + emit addCardToMainDeck(currentCard()); } void DeckEditorDatabaseDisplayWidget::actAddCardToSideboard() -{ - addCard(databaseView->currentCardName(), DECK_ZONE_SIDE); -} - -void DeckEditorDatabaseDisplayWidget::addCard(const QString &cardName, const QString &zoneName) { highlightAllSearchEdit(); - ExactCard exactCard = CardDatabaseManager::query()->getPreferredCard(cardName); - emit cardAdded(exactCard, zoneName); + emit addCardToSideboard(currentCard()); } -void DeckEditorDatabaseDisplayWidget::decrementCard(const QString &cardName, const QString &zoneName) +void DeckEditorDatabaseDisplayWidget::actDecrementCardFromMainDeck() { - ExactCard exactCard = CardDatabaseManager::query()->getPreferredCard(cardName); - emit cardDecremented(exactCard, zoneName); + emit decrementCardFromMainDeck(currentCard()); } -void DeckEditorDatabaseDisplayWidget::updateCard(const QString &cardName) +void DeckEditorDatabaseDisplayWidget::actDecrementCardFromSideboard() { - ExactCard exactCard = CardDatabaseManager::query()->getPreferredCard(cardName); - emit cardChanged(exactCard); + emit decrementCardFromSideboard(currentCard()); +} + +ExactCard DeckEditorDatabaseDisplayWidget::currentCard() const +{ + const QModelIndex currentIndex = databaseView->selectionModel()->currentIndex(); + if (!currentIndex.isValid()) { + return {}; + } + + const QString cardName = currentIndex.siblingAtColumn(CardDatabaseModel::NameColumn).data().toString(); + + return CardDatabaseManager::query()->getPreferredCard(cardName); +} + +void DeckEditorDatabaseDisplayWidget::databaseCustomMenu(QPoint point) +{ + QMenu menu; + ExactCard card = currentCard(); + + if (card) { + // add to deck and sideboard options + QAction *addToDeck, *addToSideboard, *selectPrinting, *edhRecCommander, *edhRecCard; + addToDeck = menu.addAction(tr("Add to Deck")); + addToSideboard = menu.addAction(tr("Add to Sideboard")); + selectPrinting = menu.addAction(tr("Select Printing")); + connect(selectPrinting, &QAction::triggered, this, [this, card] { deckEditor->showPrintingSelector(); }); + if (canBeCommander(card.getInfo())) { + edhRecCommander = menu.addAction(tr("Show on EDHRec (Commander)")); + connect(edhRecCommander, &QAction::triggered, this, + [this, card] { deckEditor->getTabSupervisor()->addEdhrecTab(card.getCardPtr(), true); }); + } + edhRecCard = menu.addAction(tr("Show on EDHRec (Card)")); + + connect(addToDeck, &QAction::triggered, this, &DeckEditorDatabaseDisplayWidget::actAddCardToMainDeck); + connect(addToSideboard, &QAction::triggered, this, &DeckEditorDatabaseDisplayWidget::actAddCardToSideboard); + connect(edhRecCard, &QAction::triggered, this, + [this, card] { deckEditor->getTabSupervisor()->addEdhrecTab(card.getCardPtr()); }); + + // filling out the related cards submenu + auto *relatedMenu = new QMenu(tr("Show Related cards")); + menu.addMenu(relatedMenu); + auto relatedCards = card.getInfo().getAllRelatedCards(); + if (relatedCards.isEmpty()) { + relatedMenu->setDisabled(true); + } else { + for (const CardRelation *rel : relatedCards) { + const QString &relatedCardName = rel->getName(); + QAction *relatedCard = relatedMenu->addAction(relatedCardName); + connect( + relatedCard, &QAction::triggered, deckEditor->cardInfoDockWidget->cardInfo, + [this, relatedCardName] { deckEditor->cardInfoDockWidget->cardInfo->setCard(relatedCardName); }); + } + } + menu.exec(databaseView->mapToGlobal(point)); + } +} + +void DeckEditorDatabaseDisplayWidget::copyDatabaseCellContents() +{ + auto _data = databaseView->selectionModel()->currentIndex().data(); + QApplication::clipboard()->setText(_data.toString()); +} + +void DeckEditorDatabaseDisplayWidget::saveDbHeaderState() +{ + SettingsCache::instance().layouts().setDeckEditorDbHeaderState(databaseView->header()->saveState()); } void DeckEditorDatabaseDisplayWidget::setFilterTree(FilterTree *filterTree) @@ -131,10 +248,4 @@ void DeckEditorDatabaseDisplayWidget::retranslateUi() void DeckEditorDatabaseDisplayWidget::highlightAllSearchEdit() { searchEdit->setSelection(0, searchEdit->text().length()); -} - -void DeckEditorDatabaseDisplayWidget::onRelatedCardClicked(const QString &relatedCard) -{ - ExactCard exactCard = CardDatabaseManager::query()->guessCard({relatedCard}); - emit cardInfoRequested(exactCard); } \ No newline at end of file diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.h b/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.h index 5de4d211d..0f62998ef 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.h +++ b/cockatrice/src/interface/widgets/deck_editor/deck_editor_database_display_widget.h @@ -9,6 +9,7 @@ #define DECK_EDITOR_DATABASE_DISPLAY_WIDGET_H #include "../../../interface/widgets/tabs/abstract_tab_deck_editor.h" +#include "../../key_signals.h" #include "../utility/custom_line_edit.h" #include @@ -16,44 +17,45 @@ #include #include -class CardDatabaseView; class AbstractTabDeckEditor; - class DeckEditorDatabaseDisplayWidget : public QWidget { Q_OBJECT public: - explicit DeckEditorDatabaseDisplayWidget(QWidget *parent, CardDatabaseModel *databaseModel); + explicit DeckEditorDatabaseDisplayWidget(QWidget *parent, AbstractTabDeckEditor *deckEditor); + AbstractTabDeckEditor *deckEditor; + CardDatabaseModel *databaseModel; + CardDatabaseDisplayModel *databaseDisplayModel; - CardDatabaseView *getDatabaseView() const + QTreeView *getDatabaseView() { return databaseView; } public slots: + ExactCard currentCard() const; void setFilterTree(FilterTree *filterTree); void clearAllDatabaseFilters(); - + void updateSearch(const QString &search); + void updateCard(const QModelIndex ¤t, const QModelIndex &); void actAddCardToMainDeck(); void actAddCardToSideboard(); - - void addCard(const QString &cardName, const QString &zoneName); - void decrementCard(const QString &cardName, const QString &zoneName); - void updateCard(const QString &cardName); + void actDecrementCardFromMainDeck(); + void actDecrementCardFromSideboard(); + void databaseCustomMenu(QPoint point); + void copyDatabaseCellContents(); signals: - void cardAdded(const ExactCard &card, const QString &zoneName); - void cardDecremented(const ExactCard &card, const QString &zoneName); + void addCardToMainDeck(const ExactCard &card); + void addCardToSideboard(const ExactCard &card); + void decrementCardFromMainDeck(const ExactCard &card); + void decrementCardFromSideboard(const ExactCard &card); void cardChanged(const ExactCard &_card); - void edhrecRequested(const CardInfoPtr &cardInfo, bool isCommander); - void printingSelectorRequested(); - void cardInfoRequested(const ExactCard &card); - private: - CardDatabaseDisplayModel *databaseDisplayModel; - CardDatabaseView *databaseView; + KeySignals searchKeySignals; + QTreeView *databaseView; QHBoxLayout *searchLayout; SearchLineEdit *searchEdit; QAction *aAddCard, *aAddCardToSideboard; @@ -64,8 +66,7 @@ private: private slots: void retranslateUi(); - - void onRelatedCardClicked(const QString &relatedCard); + void saveDbHeaderState(); }; #endif // DECK_EDITOR_DATABASE_DISPLAY_WIDGET_H diff --git a/cockatrice/src/interface/widgets/deck_editor/deck_state_manager.cpp b/cockatrice/src/interface/widgets/deck_editor/deck_state_manager.cpp index f8fb450ce..6db8e5623 100644 --- a/cockatrice/src/interface/widgets/deck_editor/deck_state_manager.cpp +++ b/cockatrice/src/interface/widgets/deck_editor/deck_state_manager.cpp @@ -255,10 +255,6 @@ bool DeckStateManager::swapCardAtIndex(const QModelIndex &idx) } QString zoneName = gparent.siblingAtColumn(DeckListModelColumns::CARD_NAME).data(Qt::EditRole).toString(); - // tokens have no swap target - if (zoneName == DECK_ZONE_TOKENS) { - return false; - } QString otherZoneName = zoneName == DECK_ZONE_MAIN ? DECK_ZONE_SIDE : DECK_ZONE_MAIN; QString reason = tr("Moved to %1 1 × \"%2\" (%3)") // diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_update.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_update.cpp index ee2149309..15735168f 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_update.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_update.cpp @@ -219,25 +219,10 @@ void DlgUpdate::downloadError(const QString &errorString) void DlgUpdate::downloadSuccessful(const QUrl &filepath) { setLabel(tr("Installing...")); - - QString installerPath = filepath.toLocalFile(); - - QString appDir = QDir::toNativeSeparators(QCoreApplication::applicationDirPath()); - QProcess process; - process.setProgram(installerPath); - - // NSIS needs the /D= argument to be an UNQUOTED string, even if it contains spaces. Qt likes to quote arguments if - // they contain spaces, so we use the windows exclusive QProcess::setNativeArguments in the only case where this is - // relevant, which preserves the argument unquoted. -#ifdef Q_OS_WIN - process.setNativeArguments(QString("/R /D=%1").arg(appDir)); -#else - // Linux/macOS: normal argument passing (not relevant since they update differently.) - process.setArguments({"/R", QString("/D=%1").arg(appDir)}); -#endif - // Try to open the installer. If it opens, quit Cockatrice - if (process.startDetached()) { + if (QProcess::startDetached(filepath.toLocalFile(), + QStringList() + << "/R" << QString("/D=%1").arg(QCoreApplication::applicationDirPath()))) { QMetaObject::invokeMethod(static_cast(parent()), "close", Qt::QueuedConnection); qCInfo(DlgUpdateLog) << "Opened downloaded update file successfully - closing Cockatrice"; close(); diff --git a/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.cpp b/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.cpp index 025f457bd..59c657724 100644 --- a/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.cpp +++ b/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.cpp @@ -108,9 +108,8 @@ void FlowWidget::clearLayout() if (flowLayout) { QLayoutItem *item; while ((item = flowLayout->takeAt(0))) { - if (item->widget()) { + if (item->widget()) item->widget()->deleteLater(); - } delete item; } } else { diff --git a/cockatrice/src/interface/widgets/menus/deck_editor_menu.cpp b/cockatrice/src/interface/widgets/menus/deck_editor_menu.cpp index d6df694df..23d19abbb 100644 --- a/cockatrice/src/interface/widgets/menus/deck_editor_menu.cpp +++ b/cockatrice/src/interface/widgets/menus/deck_editor_menu.cpp @@ -193,8 +193,6 @@ void DeckEditorMenu::refreshShortcuts() aEditDeckInClipboardRaw->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aEditDeckInClipboardRaw")); aPrintDeck->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aPrintDeck")); - aLoadDeckFromWebsite->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aLoadDeckFromWebsite")); - aExportDeckDecklist->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aExportDeckDecklist")); aExportDeckDecklistXyz->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aExportDeckDecklistXyz")); aAnalyzeDeckDeckstats->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aAnalyzeDeck")); diff --git a/cockatrice/src/interface/widgets/printing_selector/all_zones_card_amount_widget.cpp b/cockatrice/src/interface/widgets/printing_selector/all_zones_card_amount_widget.cpp index 05e269174..36bccbcc3 100644 --- a/cockatrice/src/interface/widgets/printing_selector/all_zones_card_amount_widget.cpp +++ b/cockatrice/src/interface/widgets/printing_selector/all_zones_card_amount_widget.cpp @@ -8,7 +8,7 @@ * @brief Constructor for the AllZonesCardAmountWidget class. * * Initializes the widget with its layout and sets up the connections and necessary - * UI elements for managing card counts in all the mainboard, tokensboard and sideboard zones. + * UI elements for managing card counts in both the mainboard and sideboard zones. * * @param parent The parent widget. * @param deckStateManager Pointer to the DeckStateManager @@ -31,28 +31,13 @@ AllZonesCardAmountWidget::AllZonesCardAmountWidget(QWidget *parent, buttonBoxMainboard = new CardAmountWidget(this, deckStateManager, cardSizeSlider, rootCard, DECK_ZONE_MAIN); zoneLabelSideboard = new ShadowBackgroundLabel(this, tr("Sideboard")); buttonBoxSideboard = new CardAmountWidget(this, deckStateManager, cardSizeSlider, rootCard, DECK_ZONE_SIDE); - zoneLabelTokensboard = new ShadowBackgroundLabel(this, tr("Tokens")); - buttonBoxTokensboard = new CardAmountWidget(this, deckStateManager, cardSizeSlider, rootCard, DECK_ZONE_TOKENS); layout->addWidget(zoneLabelMainboard, 0, Qt::AlignHCenter | Qt::AlignBottom); layout->addWidget(buttonBoxMainboard, 0, Qt::AlignHCenter | Qt::AlignTop); - layout->addSpacing(12); - layout->addWidget(zoneLabelTokensboard, 0, Qt::AlignHCenter | Qt::AlignBottom); - layout->addWidget(buttonBoxTokensboard, 0, Qt::AlignHCenter | Qt::AlignTop); - layout->addSpacing(13); + layout->addSpacing(25); layout->addWidget(zoneLabelSideboard, 0, Qt::AlignHCenter | Qt::AlignBottom); layout->addWidget(buttonBoxSideboard, 0, Qt::AlignHCenter | Qt::AlignTop); - // Show Tokens buttons for token cards, Mainboard/Sideboard for non-token cards - bool isToken = rootCard.getInfo().getIsToken(); - - zoneLabelMainboard->setVisible(!isToken); - buttonBoxMainboard->setVisible(!isToken); - zoneLabelTokensboard->setVisible(isToken); - buttonBoxTokensboard->setVisible(isToken); - zoneLabelSideboard->setVisible(!isToken); - buttonBoxSideboard->setVisible(!isToken); - connect(cardSizeSlider, &QSlider::valueChanged, this, &AllZonesCardAmountWidget::adjustFontSize); QTimer::singleShot(10, this, [this]() { adjustFontSize(this->cardSizeSlider->value()); }); @@ -82,17 +67,15 @@ void AllZonesCardAmountWidget::adjustFontSize(int scalePercentage) zoneLabelFont.setPointSize(newFontSize); zoneLabelMainboard->setFont(zoneLabelFont); zoneLabelSideboard->setFont(zoneLabelFont); - zoneLabelTokensboard->setFont(zoneLabelFont); // Repaint the widget (if necessary) repaint(); } -void AllZonesCardAmountWidget::setAmounts(int mainboardAmount, int sideboardAmount, int tokensboardAmount) +void AllZonesCardAmountWidget::setAmounts(int mainboardAmount, int sideboardAmount) { buttonBoxMainboard->setAmount(mainboardAmount); buttonBoxSideboard->setAmount(sideboardAmount); - buttonBoxTokensboard->setAmount(tokensboardAmount); } /** @@ -116,21 +99,11 @@ int AllZonesCardAmountWidget::getSideboardAmount() } /** - * @brief Gets the card count in the tokensboard zone. - * - * @return The number of cards in the tokensboard. - */ -int AllZonesCardAmountWidget::getTokensboardAmount() -{ - return buttonBoxTokensboard->getAmount(); -} - -/** - * @brief Checks if the amount is at least one in either the mainboard or sideboard or tokensboard. + * @brief Checks if the amount is at least one in either the mainboard or sideboard. */ bool AllZonesCardAmountWidget::isNonZero() { - return getMainboardAmount() > 0 || getSideboardAmount() > 0 || getTokensboardAmount() > 0; + return getMainboardAmount() > 0 || getSideboardAmount() > 0; } /** diff --git a/cockatrice/src/interface/widgets/printing_selector/all_zones_card_amount_widget.h b/cockatrice/src/interface/widgets/printing_selector/all_zones_card_amount_widget.h index de4a984be..05047d94f 100644 --- a/cockatrice/src/interface/widgets/printing_selector/all_zones_card_amount_widget.h +++ b/cockatrice/src/interface/widgets/printing_selector/all_zones_card_amount_widget.h @@ -23,7 +23,6 @@ public: const ExactCard &rootCard); int getMainboardAmount(); int getSideboardAmount(); - int getTokensboardAmount(); bool isNonZero(); #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) @@ -34,7 +33,7 @@ public: public slots: void adjustFontSize(int scalePercentage); - void setAmounts(int mainboardAmount, int sideboardAmount, int tokensboardAmount); + void setAmounts(int mainboardAmount, int sideboardAmount); private: QVBoxLayout *layout; @@ -43,8 +42,6 @@ private: CardAmountWidget *buttonBoxMainboard; QLabel *zoneLabelSideboard; CardAmountWidget *buttonBoxSideboard; - QLabel *zoneLabelTokensboard; - CardAmountWidget *buttonBoxTokensboard; }; #endif // ALL_ZONES_CARD_AMOUNT_WIDGET_H diff --git a/cockatrice/src/interface/widgets/printing_selector/card_amount_widget.cpp b/cockatrice/src/interface/widgets/printing_selector/card_amount_widget.cpp index ff47e7b9c..25222f437 100644 --- a/cockatrice/src/interface/widgets/printing_selector/card_amount_widget.cpp +++ b/cockatrice/src/interface/widgets/printing_selector/card_amount_widget.cpp @@ -11,7 +11,7 @@ * @param parent The parent widget. * @param cardSizeSlider Pointer to the QSlider for adjusting font size. * @param rootCard The root card to manage within the widget. - * @param zoneName The zone name (e.g., DECK_ZONE_MAIN , DECK_ZONE_SIDE, or DECK_ZONE_TOKENS). + * @param zoneName The zone name (e.g., DECK_ZONE_MAIN or DECK_ZONE_SIDE). */ CardAmountWidget::CardAmountWidget(QWidget *parent, DeckStateManager *deckStateManager, @@ -36,16 +36,13 @@ CardAmountWidget::CardAmountWidget(QWidget *parent, incrementButton->setFixedSize(parentWidget()->size().width() / 3, parentWidget()->size().height() / 9); decrementButton->setFixedSize(parentWidget()->size().width() / 3, parentWidget()->size().height() / 9); - // Set up connections based on the zone (Mainboard, Sideboard, or Tokensboard) + // Set up connections based on the zone (Mainboard or Sideboard) if (zoneName == DECK_ZONE_MAIN) { connect(incrementButton, &QPushButton::clicked, this, &CardAmountWidget::addPrintingMainboard); connect(decrementButton, &QPushButton::clicked, this, &CardAmountWidget::removePrintingMainboard); } else if (zoneName == DECK_ZONE_SIDE) { connect(incrementButton, &QPushButton::clicked, this, &CardAmountWidget::addPrintingSideboard); connect(decrementButton, &QPushButton::clicked, this, &CardAmountWidget::removePrintingSideboard); - } else if (zoneName == DECK_ZONE_TOKENS) { - connect(incrementButton, &QPushButton::clicked, this, &CardAmountWidget::addPrintingTokensboard); - connect(decrementButton, &QPushButton::clicked, this, &CardAmountWidget::removePrintingTokensboard); } cardCountInZone = new QLabel(QString::number(amount), this); @@ -140,19 +137,6 @@ void CardAmountWidget::updateCardCount() layout->activate(); } -static QString zoneLogName(const QString &zone) -{ - if (zone == DECK_ZONE_MAIN) { - return "mainboard"; - } else if (zone == DECK_ZONE_SIDE) { - return "sideboard"; - } else if (zone == DECK_ZONE_TOKENS) { - return "tokens"; - } else { - return "unknown"; - } -} - static QModelIndex addAndReplacePrintings(DeckListModel *model, const QModelIndex &existing, const ExactCard &rootCard, @@ -177,9 +161,9 @@ static QModelIndex addAndReplacePrintings(DeckListModel *model, } /** - * @brief Adds a printing of the card to the specified zone (Mainboard, Sideboard, or Tokensboard). + * @brief Adds a printing of the card to the specified zone (Mainboard or Sideboard). * - * @param zone The zone to add the card to (DECK_ZONE_MAIN, DECK_ZONE_SIDE, or DECK_ZONE_TOKENS). + * @param zone The zone to add the card to (DECK_ZONE_MAIN or DECK_ZONE_SIDE). */ void CardAmountWidget::addPrinting(const QString &zone) { @@ -199,13 +183,12 @@ void CardAmountWidget::addPrinting(const QString &zone) } } - QString zoneName = zoneLogName(zone); QString reason = QString("Added %1 copies of '%2 (%3) %4' to %5 [ProviderID: %6]%7") .arg(1 + extraCopies) .arg(rootCard.getName()) .arg(rootCard.getPrinting().getSet()->getShortName()) .arg(rootCard.getPrinting().getProperty("num")) - .arg(zoneName) + .arg(zone == DECK_ZONE_MAIN ? "mainboard" : "sideboard") .arg(rootCard.getPrinting().getUuid()) .arg(replacingProviderless ? " (replaced providerless printings)" : ""); @@ -235,14 +218,6 @@ void CardAmountWidget::addPrintingSideboard() addPrinting(DECK_ZONE_SIDE); } -/** - * @brief Adds a printing to the tokens zone. - */ -void CardAmountWidget::addPrintingTokensboard() -{ - addPrinting(DECK_ZONE_TOKENS); -} - /** * @brief Removes a printing from the mainboard zone. */ @@ -259,27 +234,18 @@ void CardAmountWidget::removePrintingSideboard() decrementCardHelper(DECK_ZONE_SIDE); } -/** - * @brief Removes a printing from the tokens zone. - */ -void CardAmountWidget::removePrintingTokensboard() -{ - decrementCardHelper(DECK_ZONE_TOKENS); -} - /** * @brief Helper function to decrement the card count for a given zone. * - * @param zone The zone from which to remove the card (DECK_ZONE_MAIN, DECK_ZONE_SIDE, or DECK_ZONE_TOKENS). + * @param zone The zone from which to remove the card (DECK_ZONE_MAIN or DECK_ZONE_SIDE). */ void CardAmountWidget::decrementCardHelper(const QString &zone) { - QString zoneName = zoneLogName(zone); QString reason = QString("Removed 1 copy of '%1 (%2) %3' from %4 [ProviderID: %5]") .arg(rootCard.getName()) .arg(rootCard.getPrinting().getSet()->getShortName()) .arg(rootCard.getPrinting().getProperty("num")) - .arg(zoneName) + .arg(zone == DECK_ZONE_MAIN ? "mainboard" : "sideboard") .arg(rootCard.getPrinting().getUuid()); deckStateManager->modifyDeck(reason, [this, &zone](auto model) { diff --git a/cockatrice/src/interface/widgets/printing_selector/card_amount_widget.h b/cockatrice/src/interface/widgets/printing_selector/card_amount_widget.h index 2780e3ad2..f0f2128f0 100644 --- a/cockatrice/src/interface/widgets/printing_selector/card_amount_widget.h +++ b/cockatrice/src/interface/widgets/printing_selector/card_amount_widget.h @@ -60,10 +60,8 @@ private: private slots: void addPrintingMainboard(); void addPrintingSideboard(); - void addPrintingTokensboard(); void removePrintingMainboard(); void removePrintingSideboard(); - void removePrintingTokensboard(); void adjustFontSize(int scalePercentage); }; diff --git a/cockatrice/src/interface/widgets/printing_selector/printing_selector.cpp b/cockatrice/src/interface/widgets/printing_selector/printing_selector.cpp index 76a416587..71b93b297 100644 --- a/cockatrice/src/interface/widgets/printing_selector/printing_selector.cpp +++ b/cockatrice/src/interface/widgets/printing_selector/printing_selector.cpp @@ -105,30 +105,23 @@ void PrintingSelector::printingsInDeckChanged() } /** - * @return A map of uuid to amounts (main, side, tokens). + * @return A map of uuid to amounts (main, side). */ -static QMap tallyUuidCounts(const DeckListModel *model, const QString &cardName) +static QMap> tallyUuidCounts(const DeckListModel *model, const QString &cardName) { - QMap map; + QMap> map; auto mainNodes = model->getCardNodesForZone(DECK_ZONE_MAIN); for (auto &node : mainNodes) { if (node->getName() == cardName) { - map[node->getCardProviderId()].mainboard += node->getNumber(); + map[node->getCardProviderId()].first += node->getNumber(); } } auto sideNodes = model->getCardNodesForZone(DECK_ZONE_SIDE); for (auto &node : sideNodes) { if (node->getName() == cardName) { - map[node->getCardProviderId()].sideboard += node->getNumber(); - } - } - - auto tokensNodes = model->getCardNodesForZone(DECK_ZONE_TOKENS); - for (auto &node : tokensNodes) { - if (node->getName() == cardName) { - map[node->getCardProviderId()].tokensboard += node->getNumber(); + map[node->getCardProviderId()].second += node->getNumber(); } } diff --git a/cockatrice/src/interface/widgets/printing_selector/printing_selector.h b/cockatrice/src/interface/widgets/printing_selector/printing_selector.h index 14d73f836..b9e6723f2 100644 --- a/cockatrice/src/interface/widgets/printing_selector/printing_selector.h +++ b/cockatrice/src/interface/widgets/printing_selector/printing_selector.h @@ -22,13 +22,6 @@ #define BATCH_SIZE 10 -struct ZoneCounts -{ - int mainboard = 0; - int sideboard = 0; - int tokensboard = 0; -}; - class DeckStateManager; class PrintingSelectorCardSearchWidget; class PrintingSelectorCardSelectionWidget; @@ -66,9 +59,9 @@ signals: /** * The amounts of the printings in the deck has changed - * @param uuidToAmounts Map of uuids to the amounts (maindeck, sideboard, tokensboard) in the deck + * @param uuidToAmounts Map of uuids to the amounts (maindeck, sideboard) in the deck */ - void cardAmountsChanged(const QMap &uuidToAmounts); + void cardAmountsChanged(const QMap> &uuidToAmounts); private: QVBoxLayout *layout; diff --git a/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_display_widget.cpp b/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_display_widget.cpp index edeba86d1..7d0b4882f 100644 --- a/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_display_widget.cpp +++ b/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_display_widget.cpp @@ -67,10 +67,10 @@ void PrintingSelectorCardDisplayWidget::clampSetNameToPicture() update(); } -void PrintingSelectorCardDisplayWidget::updateCardAmounts(const QMap &uuidToAmounts) +void PrintingSelectorCardDisplayWidget::updateCardAmounts(const QMap> &uuidToAmounts) { - auto counts = uuidToAmounts.value(rootCard.getPrinting().getUuid()); - overlayWidget->updateCardAmounts(counts.mainboard, counts.sideboard, counts.tokensboard); + auto [main, side] = uuidToAmounts.value(rootCard.getPrinting().getUuid()); + overlayWidget->updateCardAmounts(main, side); } void PrintingSelectorCardDisplayWidget::resizeEvent(QResizeEvent *event) diff --git a/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_display_widget.h b/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_display_widget.h index 4de561f4f..b708bd973 100644 --- a/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_display_widget.h +++ b/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_display_widget.h @@ -27,7 +27,7 @@ public: public slots: void clampSetNameToPicture(); - void updateCardAmounts(const QMap &uuidToAmounts); + void updateCardAmounts(const QMap> &uuidToAmounts); void resizeEvent(QResizeEvent *event) override; diff --git a/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_overlay_widget.cpp b/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_overlay_widget.cpp index dd5f6dd7f..69334d6f3 100644 --- a/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_overlay_widget.cpp +++ b/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_overlay_widget.cpp @@ -116,11 +116,9 @@ void PrintingSelectorCardOverlayWidget::enterEvent(QEvent *event) updateVisibility(); } -void PrintingSelectorCardOverlayWidget::updateCardAmounts(int mainboardAmount, - int sideboardAmount, - int tokensboardAmount) +void PrintingSelectorCardOverlayWidget::updateCardAmounts(int mainboardAmount, int sideboardAmount) { - allZonesCardAmountWidget->setAmounts(mainboardAmount, sideboardAmount, tokensboardAmount); + allZonesCardAmountWidget->setAmounts(mainboardAmount, sideboardAmount); updateVisibility(); } @@ -175,8 +173,8 @@ void PrintingSelectorCardOverlayWidget::updatePinBadgeVisibility() /** * @brief Handles the mouse leave event when the cursor leaves the overlay widget area. * - * When the cursor leaves the widget, the card amount widget is hidden if all of the mainboard, sideboard, and - * tokensboard amounts are zero. + * When the cursor leaves the widget, the card amount widget is hidden if both the mainboard and sideboard + * amounts are zero. * * @param event The event triggered when the mouse leaves the widget. */ diff --git a/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_overlay_widget.h b/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_overlay_widget.h index 52a43d220..2fdf5ab74 100644 --- a/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_overlay_widget.h +++ b/cockatrice/src/interface/widgets/printing_selector/printing_selector_card_overlay_widget.h @@ -39,7 +39,7 @@ signals: void cardPreferenceChanged(); public slots: - void updateCardAmounts(int mainboardAmount, int sideboardAmount, int tokensboardAmount); + void updateCardAmounts(int mainboardAmount, int sideboardAmount); private slots: void updateVisibility(); diff --git a/cockatrice/src/interface/widgets/replay/replay_manager.cpp b/cockatrice/src/interface/widgets/replay/replay_manager.cpp index a1330a82d..525b703db 100644 --- a/cockatrice/src/interface/widgets/replay/replay_manager.cpp +++ b/cockatrice/src/interface/widgets/replay/replay_manager.cpp @@ -98,7 +98,8 @@ ReplayManager::ReplayManager(TabGame *parent, GameReplay *_replay) void ReplayManager::replayNextEvent(EventProcessingOptions options) { - emit eventReplayed(replay->event_list(timelineWidget->getCurrentEvent()), options); + game->getGame()->getGameEventHandler()->processGameEventContainer( + replay->event_list(timelineWidget->getCurrentEvent()), nullptr, options); } void ReplayManager::replayFinished() diff --git a/cockatrice/src/interface/widgets/replay/replay_manager.h b/cockatrice/src/interface/widgets/replay/replay_manager.h index a3e0126c7..d67ae5a90 100644 --- a/cockatrice/src/interface/widgets/replay/replay_manager.h +++ b/cockatrice/src/interface/widgets/replay/replay_manager.h @@ -27,7 +27,6 @@ public: signals: void requestChatAndPhaseReset(); - void eventReplayed(const GameEventContainer &cont, EventProcessingOptions options); private: // Replay related members diff --git a/cockatrice/src/interface/widgets/server/user/user_context_menu.cpp b/cockatrice/src/interface/widgets/server/user/user_context_menu.cpp index faa96fa1f..195b1cc8d 100644 --- a/cockatrice/src/interface/widgets/server/user/user_context_menu.cpp +++ b/cockatrice/src/interface/widgets/server/user/user_context_menu.cpp @@ -476,15 +476,10 @@ void UserContextMenu::showContextMenu(const QPoint &pos, client->sendCommand(client->prepareSessionCommand(cmd)); } else if (actionClicked == aKick) { - auto result = QMessageBox::question(static_cast(parent()), tr("Kick Player"), - tr("Are you sure you want to kick this player from the game?"), - QMessageBox::Yes | QMessageBox::No, QMessageBox::No); - if (result == QMessageBox::Yes) { - Command_KickFromGame cmd; - cmd.set_player_id(playerId); + Command_KickFromGame cmd; + cmd.set_player_id(playerId); - game->getGameEventHandler()->sendGameCommand(cmd); - } + game->getGameEventHandler()->sendGameCommand(cmd); } else if (actionClicked == aBan) { Command_GetUserInfo cmd; cmd.set_user_name(userName.toStdString()); diff --git a/cockatrice/src/interface/widgets/server/user/user_info_box.cpp b/cockatrice/src/interface/widgets/server/user/user_info_box.cpp index e41ae6e75..a9955ff3d 100644 --- a/cockatrice/src/interface/widgets/server/user/user_info_box.cpp +++ b/cockatrice/src/interface/widgets/server/user/user_info_box.cpp @@ -85,15 +85,24 @@ void UserInfoBox::retranslateUi() avatarButton.setText(tr("Change avatar")); } +/** + * Creates the default profile pic that is used when the user doesn't have a custom pic + */ +static QPixmap createDefaultAvatar(int height, const ServerInfo_User &user) +{ + return UserLevelPixmapGenerator::generatePixmap(height, UserLevelFlags(user.user_level()), user.pawn_colors(), + false, QString::fromStdString(user.privlevel())); +} + void UserInfoBox::updateInfo(const ServerInfo_User &user) { - userLevel = UserLevelFlags(user.user_level()); - pawnColors = user.pawn_colors(); - privLevel = QString::fromStdString(user.privlevel()); + currentUserInfo = &user; + + const UserLevelFlags userLevel(user.user_level()); const std::string &bmp = user.avatar_bmp(); if (!avatarPixmap.loadFromData((const uchar *)bmp.data(), static_cast(bmp.size()))) { - avatarPixmap = UserLevelPixmapGenerator::generatePixmap(64, userLevel, pawnColors, false, privLevel); + avatarPixmap = createDefaultAvatar(64, user); hasAvatar = false; } else { hasAvatar = true; @@ -111,7 +120,8 @@ void UserInfoBox::updateInfo(const ServerInfo_User &user) countryLabel3.setText(""); } - userLevelIcon.setPixmap(UserLevelPixmapGenerator::generatePixmap(15, userLevel, pawnColors, false, privLevel)); + userLevelIcon.setPixmap(UserLevelPixmapGenerator::generatePixmap(15, userLevel, user.pawn_colors(), false, + QString::fromStdString(user.privlevel()))); QString userLevelText; if (userLevel.testFlag(ServerInfo_User::IsAdmin)) { userLevelText = tr("Administrator"); @@ -363,7 +373,7 @@ void UserInfoBox::processAvatarResponse(const Response &r) break; case Response::RespInternalError: default: - QMessageBox::critical(this, tr("Error"), tr("An error occured while trying to update your avatar.")); + QMessageBox::critical(this, tr("Error"), tr("An error occured while trying to updater your avatar.")); break; } } @@ -375,7 +385,7 @@ void UserInfoBox::resizeEvent(QResizeEvent *event) resizedPixmap = avatarPixmap.scaled(avatarPic.size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); } else { int height = qMin(avatarPic.size().width(), avatarPic.size().height()); - resizedPixmap = UserLevelPixmapGenerator::generatePixmap(height, userLevel, pawnColors, false, privLevel); + resizedPixmap = createDefaultAvatar(height, *currentUserInfo); } avatarPic.setPixmap(resizedPixmap); diff --git a/cockatrice/src/interface/widgets/server/user/user_info_box.h b/cockatrice/src/interface/widgets/server/user/user_info_box.h index 055ac0096..299deed2f 100644 --- a/cockatrice/src/interface/widgets/server/user/user_info_box.h +++ b/cockatrice/src/interface/widgets/server/user/user_info_box.h @@ -11,9 +11,8 @@ #include #include #include -#include -#include +class ServerInfo_User; class AbstractClient; class Response; @@ -28,15 +27,20 @@ private: QPushButton editButton, passwordButton, avatarButton; QPixmap avatarPixmap; bool hasAvatar; - UserLevelFlags userLevel; - ServerInfo_User::PawnColorsOverride pawnColors; - QString privLevel; + const ServerInfo_User *currentUserInfo; static QString getAgeString(int ageSeconds); public: UserInfoBox(AbstractClient *_client, bool editable, QWidget *parent = nullptr, Qt::WindowFlags flags = {}); void retranslateUi(); + + inline static QPair getDaysAndYearsBetween(const QDate &then, const QDate &now) + { + int years = now.addDays(1 - then.dayOfYear()).year() - then.year(); // there is no yearsTo + int days = then.addYears(years).daysTo(now); + return {days, years}; + } private slots: void processResponse(const Response &r); void processEditResponse(const Response &r); diff --git a/cockatrice/src/interface/widgets/settings_page/messages_settings_page.cpp b/cockatrice/src/interface/widgets/settings_page/messages_settings_page.cpp index 1e6f99245..f64398fe5 100644 --- a/cockatrice/src/interface/widgets/settings_page/messages_settings_page.cpp +++ b/cockatrice/src/interface/widgets/settings_page/messages_settings_page.cpp @@ -22,14 +22,10 @@ MessagesSettingsPage::MessagesSettingsPage() ignoreUnregUsersMainChat.setChecked(SettingsCache::instance().getIgnoreUnregisteredUsers()); ignoreUnregUserMessages.setChecked(SettingsCache::instance().getIgnoreUnregisteredUserMessages()); - ignoreNonBuddyUserMessages.setChecked(SettingsCache::instance().getIgnoreNonBuddyUserMessages()); - connect(&ignoreUnregUsersMainChat, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), &SettingsCache::setIgnoreUnregisteredUsers); connect(&ignoreUnregUserMessages, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), &SettingsCache::setIgnoreUnregisteredUserMessages); - connect(&ignoreNonBuddyUserMessages, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), - &SettingsCache::setIgnoreNonBuddyUserMessages); invertMentionForeground.setChecked(SettingsCache::instance().getChatMentionForeground()); connect(&invertMentionForeground, &QCheckBox::QT_STATE_CHANGED, this, &MessagesSettingsPage::updateTextColor); @@ -66,10 +62,9 @@ MessagesSettingsPage::MessagesSettingsPage() chatGrid->addWidget(&ignoreUnregUsersMainChat, 2, 0); chatGrid->addWidget(&hexLabel, 1, 2); chatGrid->addWidget(&ignoreUnregUserMessages, 3, 0); - chatGrid->addWidget(&ignoreNonBuddyUserMessages, 4, 0); - chatGrid->addWidget(&messagePopups, 5, 0); - chatGrid->addWidget(&mentionPopups, 6, 0); - chatGrid->addWidget(&roomHistory, 7, 0); + chatGrid->addWidget(&messagePopups, 4, 0); + chatGrid->addWidget(&mentionPopups, 5, 0); + chatGrid->addWidget(&roomHistory, 6, 0); chatGroupBox = new QGroupBox; chatGroupBox->setLayout(chatGrid); @@ -242,7 +237,6 @@ void MessagesSettingsPage::retranslateUi() QString("%2").arg(WIKI_CUSTOM_SHORTCUTS).arg(tr("How to use in-game message macros"))); ignoreUnregUsersMainChat.setText(tr("Ignore chat room messages sent by unregistered users")); ignoreUnregUserMessages.setText(tr("Ignore private messages sent by unregistered users")); - ignoreNonBuddyUserMessages.setText(tr("Ignore private messages sent by non-buddy users")); invertMentionForeground.setText(tr("Invert text color")); invertHighlightForeground.setText(tr("Invert text color")); messagePopups.setText(tr("Enable desktop notifications for private messages")); diff --git a/cockatrice/src/interface/widgets/settings_page/messages_settings_page.h b/cockatrice/src/interface/widgets/settings_page/messages_settings_page.h index e98ae0592..e8a4a8aa4 100644 --- a/cockatrice/src/interface/widgets/settings_page/messages_settings_page.h +++ b/cockatrice/src/interface/widgets/settings_page/messages_settings_page.h @@ -36,7 +36,6 @@ private: QCheckBox invertHighlightForeground; QCheckBox ignoreUnregUsersMainChat; QCheckBox ignoreUnregUserMessages; - QCheckBox ignoreNonBuddyUserMessages; QCheckBox messagePopups; QCheckBox mentionPopups; QCheckBox roomHistory; diff --git a/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.cpp b/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.cpp index 6039e3758..dfa736a1a 100644 --- a/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.cpp +++ b/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.cpp @@ -72,10 +72,6 @@ UserInterfaceSettingsPage::UserInterfaceSettingsPage() connect(&useTearOffMenusCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), [](const QT_STATE_CHANGED_T state) { SettingsCache::instance().setUseTearOffMenus(state == Qt::Checked); }); - keepGameChatFocusCheckBox.setChecked(SettingsCache::instance().getKeepGameChatFocus()); - connect(&keepGameChatFocusCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), - &SettingsCache::setKeepGameChatFocus); - auto *generalGrid = new QGridLayout; generalGrid->addWidget(&doubleClickToPlayCheckBox, 0, 0); generalGrid->addWidget(&clickPlaysAllSelectedCheckBox, 1, 0); @@ -87,7 +83,6 @@ UserInterfaceSettingsPage::UserInterfaceSettingsPage() generalGrid->addWidget(&showDragSelectionCountCheckBox, 7, 0); generalGrid->addWidget(&showTotalSelectionCountCheckBox, 8, 0); generalGrid->addWidget(&useTearOffMenusCheckBox, 9, 0); - generalGrid->addWidget(&keepGameChatFocusCheckBox, 10, 0); generalGroupBox = new QGroupBox; generalGroupBox->setLayout(generalGrid); @@ -212,9 +207,6 @@ void UserInterfaceSettingsPage::retranslateUi() showDragSelectionCountCheckBox.setText(tr("Show selection counter during drag selection")); showTotalSelectionCountCheckBox.setText(tr("Show total selection counter")); useTearOffMenusCheckBox.setText(tr("Use tear-off menus, allowing right click menus to persist on screen")); - keepGameChatFocusCheckBox.setText( - tr("Keep game chat focused when clicking in game (Note: disables card view search bar)")); - notificationsGroupBox->setTitle(tr("Notifications settings")); notificationsEnabledCheckBox.setText(tr("Enable notifications in taskbar")); specNotificationsEnabledCheckBox.setText(tr("Notify in the taskbar for game events while you are spectating")); diff --git a/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.h b/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.h index e10ed2a06..6dd43ceae 100644 --- a/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.h +++ b/cockatrice/src/interface/widgets/settings_page/user_interface_settings_page.h @@ -30,7 +30,6 @@ private: QCheckBox showDragSelectionCountCheckBox; QCheckBox showTotalSelectionCountCheckBox; QCheckBox useTearOffMenusCheckBox; - QCheckBox keepGameChatFocusCheckBox; QCheckBox tapAnimationCheckBox; QCheckBox openDeckInNewTabCheckBox; QLabel visualDeckStoragePromptForConversionLabel; diff --git a/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.cpp b/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.cpp index a8cc4cee6..66609456e 100644 --- a/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.cpp +++ b/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.cpp @@ -56,9 +56,6 @@ AbstractTabDeckEditor::AbstractTabDeckEditor(TabSupervisor *_tabSupervisor) : Ta deckStateManager = new DeckStateManager(this); - databaseModel = new CardDatabaseModel(CardDatabaseManager::getInstance(), true, this); - databaseModel->setObjectName("databaseModel"); - cardDatabaseDockWidget = new DeckEditorCardDatabaseDockWidget(this); deckDockWidget = new DeckEditorDeckDockWidget(this); cardInfoDockWidget = new DeckEditorCardInfoDockWidget(this); @@ -108,17 +105,16 @@ void AbstractTabDeckEditor::registerDockWidget(QMenu *_viewMenu, QDockWidget *wi dockToActions.insert(widget, {menu, aVisible, aFloating, defaultSize}); } +/** + * @brief Updates the card info dock and printing selector. + * @param card The card to display. + */ void AbstractTabDeckEditor::updateCard(const ExactCard &card) { cardInfoDockWidget->updateCard(card); printingSelectorDockWidget->printingSelector->setCard(card.getCardPtr()); } -void AbstractTabDeckEditor::updateCardInfo(const ExactCard &card) -{ - cardInfoDockWidget->updateCard(card); -} - /** @brief Placeholder: called when the deck changes. */ void AbstractTabDeckEditor::onDeckChanged() { @@ -133,14 +129,47 @@ void AbstractTabDeckEditor::onDeckModified() emit tabTextChanged(this, getTabText()); } -void AbstractTabDeckEditor::addCard(const ExactCard &card, const QString &zoneName) +/** + * @brief Helper for adding a card to a deck zone. + * @param card Card to add. + * @param zoneName Zone to add the card to. + */ +void AbstractTabDeckEditor::addCardHelper(const ExactCard &card, const QString &zoneName) { deckStateManager->addCard(card, zoneName); } -void AbstractTabDeckEditor::decrementCard(const ExactCard &card, const QString &zoneName) +/** + * @brief Adds a card to the main deck or sideboard depending on Ctrl key. + */ +void AbstractTabDeckEditor::actAddCard(const ExactCard &card) { - deckStateManager->decrementCard(card, zoneName); + if (QApplication::keyboardModifiers() & Qt::ControlModifier) { + actAddCardToSideboard(card); + } else { + addCardHelper(card, DECK_ZONE_MAIN); + } + + deckMenu->setSaveStatus(true); +} + +/** @brief Adds a card to the sideboard explicitly. */ +void AbstractTabDeckEditor::actAddCardToSideboard(const ExactCard &card) +{ + addCardHelper(card, DECK_ZONE_SIDE); + deckMenu->setSaveStatus(true); +} + +/** @brief Decrements a card from the main deck. */ +void AbstractTabDeckEditor::actDecrementCard(const ExactCard &card) +{ + deckStateManager->decrementCard(card, DECK_ZONE_MAIN); +} + +/** @brief Decrements a card from the sideboard. */ +void AbstractTabDeckEditor::actDecrementCardFromSideboard(const ExactCard &card) +{ + deckStateManager->decrementCard(card, DECK_ZONE_SIDE); } /** @@ -542,14 +571,14 @@ void AbstractTabDeckEditor::actExportDeckDecklistXyz() /** @brief Analyzes the deck using DeckStats. */ void AbstractTabDeckEditor::actAnalyzeDeckDeckstats() { - auto *interface = new DeckStatsInterface(this); + auto *interface = new DeckStatsInterface(*cardDatabaseDockWidget->getDatabase(), this); interface->analyzeDeck(deckStateManager->getDeckList()); } /** @brief Analyzes the deck using TappedOut. */ void AbstractTabDeckEditor::actAnalyzeDeckTappedout() { - auto *interface = new TappedOutInterface(this); + auto *interface = new TappedOutInterface(*cardDatabaseDockWidget->getDatabase(), this); interface->analyzeDeck(deckStateManager->getDeckList()); } @@ -592,15 +621,3 @@ bool AbstractTabDeckEditor::closeRequest() } return close(); } - -void AbstractTabDeckEditor::showPrintingSelector() -{ - printingSelectorDockWidget->printingSelector->setCard(cardInfoDockWidget->cardInfo->getCard().getCardPtr()); - printingSelectorDockWidget->printingSelector->updateDisplay(); - printingSelectorDockWidget->setVisible(true); -} - -void AbstractTabDeckEditor::openEdhrecTab(const CardInfoPtr &info, bool isCommander) -{ - getTabSupervisor()->addEdhrecTab(info, isCommander); -} diff --git a/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.h b/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.h index 34c585597..477c3f973 100644 --- a/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.h +++ b/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.h @@ -77,8 +77,8 @@ class QAction; * * **Key Methods:** * - * - addCard(const ExactCard &card, const QString &zoneName) — Adds a card to the deck. - * - decrementCard(const ExactCard &card, const QString &zoneName) — Removes a single instance of a card from the deck. + * - actAddCard(const ExactCard &card) — Adds a card to the deck. + * - actDecrementCard(const ExactCard &card) — Removes a single instance of a card from the deck. * - actRemoveCard() — Removes the currently selected card from the deck. * - actSaveDeckAs() — Performs a "Save As" action for the deck. * - updateCard(const ExactCard &card) — Updates the currently displayed card info in the dock. @@ -126,7 +126,6 @@ public: // UI Elements DeckStateManager *deckStateManager; - CardDatabaseModel *databaseModel; ///< Card database DeckEditorMenu *deckMenu; ///< Menu for deck operations DeckEditorCardDatabaseDockWidget *cardDatabaseDockWidget; ///< Database dock DeckEditorCardInfoDockWidget *cardInfoDockWidget; ///< Card info dock @@ -141,35 +140,22 @@ public slots: /** @brief Called when the deck is modified. */ virtual void onDeckModified(); - /** - * @brief Updates the card info dock and printing selector. - * @param card The card to display. + /** @brief Updates the card info panel. + * @param card The card to display. */ void updateCard(const ExactCard &card); - /** - * @brief Updates just the card info dock - * @param card The card to display - */ - void updateCardInfo(const ExactCard &card); + /** @brief Adds a card to the main deck or sideboard based on Ctrl key. */ + void actAddCard(const ExactCard &card); - /** - * @brief Adds a card to the given zone - * @param card Card to add. - * @param zoneName Zone to add the card to. - */ - void addCard(const ExactCard &card, const QString &zoneName); + /** @brief Adds a card to the sideboard explicitly. */ + void actAddCardToSideboard(const ExactCard &card); - /** - * @brief Decrements a card from the given zone - * - * Use an ExactCard with empty PrintingInfo if you want to remove a card by name regardless of printing. - * Otherwise, it won't remove anything unless there's an exact printing match. - * - * @param card Card to decrement. - * @param zoneName Zone to decrement from. - */ - void decrementCard(const ExactCard &card, const QString &zoneName); + /** @brief Decrements a card from the main deck. */ + void actDecrementCard(const ExactCard &card); + + /** @brief Decrements a card from the sideboard. */ + void actDecrementCardFromSideboard(const ExactCard &card); /** @brief Opens a recently opened deck file. */ void actOpenRecent(const QString &fileName); @@ -180,15 +166,8 @@ public slots: /** @brief Requests closing the tab. */ bool closeRequest() override; - /** @brief Shows the printing selector dock and updates it with the current card. */ - void showPrintingSelector(); - - /** - * @brief Opens an EDHRec tab for the given card - * @param info The card - * @param isCommander The type of search - */ - void openEdhrecTab(const CardInfoPtr &info, bool isCommander); + /** @brief Shows the printing selector dock. Pure virtual. */ + virtual void showPrintingSelector() = 0; signals: /** @brief Emitted when a deck should be opened in a new editor tab. */ @@ -314,6 +293,9 @@ protected: */ QMessageBox *createSaveConfirmationWindow(); + /** @brief Helper function to add a card to a specific deck zone. */ + void addCardHelper(const ExactCard &card, const QString &zoneName); + /** @brief Opens a deck from a file. */ virtual void openDeckFromFile(const QString &fileName, DeckOpenLocation deckOpenLocation); diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card.h b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card.h index 559580da2..265498228 100644 --- a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card.h +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card.h @@ -24,7 +24,7 @@ public: QJsonObject getOracleCard() const { return oracleCard; - } + }; QString getCollectorNumber() const { diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card_entry.h b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card_entry.h index 118cf5b13..f3961dc6f 100644 --- a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card_entry.h +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card_entry.h @@ -33,7 +33,7 @@ public: ArchidektApiResponseCard getCard() const { return card; - } + }; QList getCategories() const { diff --git a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck.h b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck.h index b539d9dd1..fce437751 100644 --- a/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck.h +++ b/cockatrice/src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck.h @@ -27,7 +27,7 @@ public: QVector getCards() const { return cards; - } + }; QVector getCategories() const { @@ -37,7 +37,7 @@ public: QString getDeckName() const { return name; - } + }; int getDeckFormat() const { diff --git a/cockatrice/src/interface/widgets/tabs/tab_deck_editor.cpp b/cockatrice/src/interface/widgets/tabs/tab_deck_editor.cpp index 4e7cbfecf..77dfddb4a 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_deck_editor.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_deck_editor.cpp @@ -120,6 +120,16 @@ void TabDeckEditor::refreshShortcuts() aResetLayout->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aResetLayout")); } +/** + * @brief Displays the printing selector dock with the current card. + */ +void TabDeckEditor::showPrintingSelector() +{ + printingSelectorDockWidget->printingSelector->setCard(cardInfoDockWidget->cardInfo->getCard().getCardPtr()); + printingSelectorDockWidget->printingSelector->updateDisplay(); + printingSelectorDockWidget->setVisible(true); +} + /** * @brief Loads deck editor layout from settings or resets to default. */ diff --git a/cockatrice/src/interface/widgets/tabs/tab_deck_editor.h b/cockatrice/src/interface/widgets/tabs/tab_deck_editor.h index 14be59cd7..ab7a0bfc5 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_deck_editor.h +++ b/cockatrice/src/interface/widgets/tabs/tab_deck_editor.h @@ -83,6 +83,10 @@ public: /** @brief Creates menus for deck editing and view options. */ void createMenus() override; + +public slots: + /** @brief Shows the printing selector dock and updates it with current card. */ + void showPrintingSelector() override; }; #endif diff --git a/cockatrice/src/interface/widgets/tabs/tab_game.cpp b/cockatrice/src/interface/widgets/tabs/tab_game.cpp index a81161e83..6b7b3539c 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_game.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_game.cpp @@ -1,21 +1,18 @@ #include "tab_game.h" #include "../../../client/settings/cache_settings.h" +#include "../game/board/arrow_item.h" +#include "../game/board/card_item.h" +#include "../game/deckview/deck_view_container.h" +#include "../game/deckview/tabbed_deck_view_container.h" #include "../game/game.h" +#include "../game/game_scene.h" +#include "../game/game_view.h" +#include "../game/log/message_log_widget.h" +#include "../game/phases_toolbar.h" +#include "../game/player/player_list_widget.h" #include "../game/player/player_logic.h" #include "../game/replay.h" -#include "../game_graphics/board/arrow_item.h" -#include "../game_graphics/board/card_item.h" -#include "../game_graphics/deckview/deck_view_container.h" -#include "../game_graphics/deckview/tabbed_deck_view_container.h" -#include "../game_graphics/game_scene.h" -#include "../game_graphics/game_view.h" -#include "../game_graphics/log/message_log_widget.h" -#include "../game_graphics/phases_toolbar.h" -#include "../game_graphics/player/menu/card_menu.h" -#include "../game_graphics/player/menu/player_menu.h" -#include "../game_graphics/player/player_graphics_item.h" -#include "../game_graphics/player/player_list_widget.h" #include "../interface/card_picture_loader/card_picture_loader.h" #include "../interface/widgets/cards/card_info_frame_widget.h" #include "../interface/widgets/dialogs/dlg_create_game.h" @@ -50,7 +47,7 @@ TabGame::TabGame(TabSupervisor *_tabSupervisor, GameReplay *_replay) : Tab(_tabSupervisor), sayLabel(nullptr), sayEdit(nullptr) { // THIS CTOR IS USED ON REPLAY - game = new Replay(this, _replay, tabSupervisor->getIsLocalGame()); + game = new Replay(this, _replay); createCardInfoDock(true); createPlayerListDock(true); @@ -94,7 +91,7 @@ TabGame::TabGame(TabSupervisor *_tabSupervisor, : Tab(_tabSupervisor), userListProxy(_tabSupervisor->getUserListManager()) { // THIS CTOR IS USED ON GAMES - game = new Game(this, tabSupervisor->getIsLocalGame(), _clients, event, _roomGameTypes); + game = new Game(this, _clients, event, _roomGameTypes); createCardInfoDock(); createPlayerListDock(); @@ -366,10 +363,11 @@ void TabGame::retranslateUi() cardInfoFrameWidget->retranslateUi(); - for (auto playerView : scene->getPlayers().values()) { - playerView->retranslateUi(); - } + QMapIterator i(game->getPlayerManager()->getPlayers()); + while (i.hasNext()) { + i.next().value()->getGraphicsItem()->retranslateUi(); + } QMapIterator j(deckViewContainers); while (j.hasNext()) { j.next().value()->playerDeckView->retranslateUi(); @@ -656,12 +654,8 @@ PlayerLogic *TabGame::addPlayer(PlayerLogic *newPlayer) scene->addPlayer(newPlayer); - auto *view = scene->viewForPlayer(newPlayer->getPlayerInfo()->getId()); - connect(newPlayer, &PlayerLogic::newCardAdded, this, &TabGame::newCardAdded); - connect(newPlayer, &PlayerLogic::openDeckEditor, this, &TabGame::openDeckEditor); - connect(view->getPlayerMenu(), &PlayerMenu::cardMenuUpdated, this, &TabGame::setCardMenu); - connect(view, &PlayerGraphicsItem::cardInfoRequested, this, &TabGame::viewCardInfo); + connect(newPlayer->getPlayerMenu(), &PlayerMenu::cardMenuUpdated, this, &TabGame::setCardMenu); messageLog->connectToPlayerEventHandler(newPlayer->getPlayerEventHandler()); @@ -674,7 +668,7 @@ PlayerLogic *TabGame::addPlayer(PlayerLogic *newPlayer) addLocalPlayer(newPlayer, newPlayer->getPlayerInfo()->getId()); } - gameMenu->insertMenu(playersSeparator, view->getPlayerMenu()->getPlayerMenu()); + gameMenu->insertMenu(playersSeparator, newPlayer->getPlayerMenu()->getPlayerMenu()); createZoneForPlayer(newPlayer, newPlayer->getPlayerInfo()->getId()); @@ -684,7 +678,7 @@ PlayerLogic *TabGame::addPlayer(PlayerLogic *newPlayer) void TabGame::addLocalPlayer(PlayerLogic *newPlayer, int playerId) { if (game->getGameState()->getClients().size() == 1) { - scene->viewForPlayer(playerId)->getPlayerMenu()->setShortcutsActive(); + newPlayer->getPlayerMenu()->setShortcutsActive(); } auto *deckView = new TabbedDeckViewContainer(playerId, this); @@ -704,24 +698,27 @@ void TabGame::addLocalPlayer(PlayerLogic *newPlayer, int playerId) void TabGame::processPlayerLeave(PlayerLogic *leavingPlayer) { - removePlayerFromAutoCompleteList("@" + leavingPlayer->getPlayerInfo()->getName()); + QString playerName = "@" + leavingPlayer->getPlayerInfo()->getName(); + removePlayerFromAutoCompleteList(playerName); + + scene->removePlayer(leavingPlayer); // When we inserted the playerMenu into the gameMenu earlier, Qt wrapped the playerMenu into a QAction*, which lives // independently and does not get cleaned up when the source menu gets destroyed. We have to manually clean here. - auto *view = scene->viewForPlayer(leavingPlayer->getPlayerInfo()->getId()); - if (view) { - // Find and remove the QAction pointing to this menu - QMenu *menu = view->getPlayerMenu()->getPlayerMenu(); - for (QAction *act : gameMenu->actions()) { - if (act->menu() == menu) { - gameMenu->removeAction(act); - delete act; - break; + if (leavingPlayer->getPlayerMenu()) { + QMenu *menu = leavingPlayer->getPlayerMenu()->getPlayerMenu(); + if (menu) { + // Find and remove the QAction pointing to this menu + QList actions = gameMenu->actions(); + for (QAction *act : actions) { + if (act->menu() == menu) { + gameMenu->removeAction(act); + delete act; // deletes the QAction wrapper around the submenu + break; + } } } } - - scene->removePlayer(leavingPlayer); } void TabGame::processRemotePlayerDeckSelect(QString deckList, int playerId, QString playerName) @@ -872,12 +869,12 @@ PlayerLogic *TabGame::setActivePlayer(int id) if (i.value() == player) { i.value()->setActive(true); if (game->getGameState()->getClients().size() > 1) { - scene->viewForPlayer(i.value()->getPlayerInfo()->getId())->getPlayerMenu()->setShortcutsActive(); + i.value()->getPlayerMenu()->setShortcutsActive(); } } else { i.value()->setActive(false); if (game->getGameState()->getClients().size() > 1) { - scene->viewForPlayer(i.value()->getPlayerInfo()->getId())->getPlayerMenu()->setShortcutsInactive(); + i.value()->getPlayerMenu()->setShortcutsInactive(); } } } @@ -893,13 +890,8 @@ void TabGame::setActivePhase(int phase) void TabGame::newCardAdded(AbstractCardItem *card) { - connect(card, &AbstractCardItem::rightClicked, scene, &GameScene::onCardRightClicked); - connect(card, &AbstractCardItem::playSelected, scene, &GameScene::playSelected); - connect(card, &AbstractCardItem::playSelectedFaceDown, scene, &GameScene::playSelectedFaceDown); - connect(card, &AbstractCardItem::hideSelected, scene, &GameScene::hideSelected); connect(card, &AbstractCardItem::hovered, cardInfoFrameWidget, qOverload(&CardInfoFrameWidget::setCard)); - connect(card, &AbstractCardItem::selectionChanged, scene, &GameScene::onCardSelectionChanged); connect(card, &AbstractCardItem::showCardInfoPopup, this, &TabGame::showCardInfoPopup); connect(card, SIGNAL(deleteCardInfoPopup(QString)), this, SLOT(deleteCardInfoPopup(QString))); connect(card, &AbstractCardItem::cardShiftClicked, this, &TabGame::linkCardToChat); @@ -943,7 +935,7 @@ QString TabGame::getTabText() const /** * @param menu The menu to set. Pass in nullptr to set the menu to empty. */ -void TabGame::setCardMenu(CardMenu *menu) +void TabGame::setCardMenu(QMenu *menu) { if (!aCardMenu) { return; @@ -1153,9 +1145,8 @@ void TabGame::createPlayAreaWidget(bool bReplay) scene = new GameScene(phasesToolbar, this); connect(game->getPlayerManager(), &PlayerManager::playerConceded, scene, &GameScene::rearrange); connect(game->getPlayerManager(), &PlayerManager::playerCountChanged, scene, &GameScene::rearrange); - connect(scene, &GameScene::arrowDeletionRequested, game->getGameEventHandler(), + connect(scene, &GameScene::requestArrowDeletion, game->getGameEventHandler(), &GameEventHandler::handleArrowDeletion); - connect(game->getGameEventHandler(), &GameEventHandler::arrowDeleted, scene, &GameScene::deleteArrow); gameView = new GameView(scene); auto gamePlayAreaVBox = new QVBoxLayout; @@ -1177,11 +1168,6 @@ void TabGame::createReplayDock(GameReplay *replay) QDockWidget::DockWidgetMovable); replayDock->setWidget(replayManager); replayDock->setFloating(false); - - connect(replayManager, &ReplayManager::eventReplayed, game->getGameEventHandler(), - [this](const auto &event, auto options) { - game->getGameEventHandler()->processGameEventContainer(event, nullptr, options); - }); } void TabGame::createDeckViewContainerWidget(bool bReplay) diff --git a/cockatrice/src/interface/widgets/tabs/tab_game.h b/cockatrice/src/interface/widgets/tabs/tab_game.h index b9289432d..7f9392034 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_game.h +++ b/cockatrice/src/interface/widgets/tabs/tab_game.h @@ -10,8 +10,8 @@ #define TAB_GAME_H #include "../game/abstract_game.h" +#include "../game/log/message_log_widget.h" #include "../game/player/player_logic.h" -#include "../game_graphics/log/message_log_widget.h" #include "../interface/widgets/menus/tearoff_menu.h" #include "../interface/widgets/replay/replay_manager.h" #include "tab.h" @@ -20,7 +20,6 @@ #include #include -class CardMenu; class ServerInfo_PlayerProperties; class TabbedDeckViewContainer; inline Q_LOGGING_CATEGORY(TabGameLog, "tab_game"); @@ -142,7 +141,7 @@ signals: private slots: void adminLockChanged(bool lock); void newCardAdded(AbstractCardItem *card); - void setCardMenu(CardMenu *menu); + void setCardMenu(QMenu *menu); void actGameInfo(); void actConcede(); diff --git a/cockatrice/src/interface/widgets/tabs/tab_supervisor.cpp b/cockatrice/src/interface/widgets/tabs/tab_supervisor.cpp index e7075f78f..3566d6939 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_supervisor.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_supervisor.cpp @@ -1019,12 +1019,6 @@ void TabSupervisor::processUserMessageEvent(const Event_UserMessage &event) !userLevel.testFlag(ServerInfo_User::IsRegistered)) { // Flags are additive, so reg/mod/admin are all IsRegistered return; - } else if (SettingsCache::instance().getIgnoreNonBuddyUserMessages() && - !userListManager->isUserBuddy(senderName) && !userLevel.testFlag(ServerInfo_User::IsModerator) && - !userLevel.testFlag(ServerInfo_User::IsAdmin)) { - // Ignore private messages from non-buddies - // Moderator/Admin messages are exempt to ensure warnings reach users - return; } } tab = addMessageTab(QString::fromStdString(event.sender_name()), false); diff --git a/cockatrice/src/interface/widgets/tabs/tab_visual_database_display.cpp b/cockatrice/src/interface/widgets/tabs/tab_visual_database_display.cpp index 3112e7ada..5e8fb8670 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_visual_database_display.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_visual_database_display.cpp @@ -1,19 +1,14 @@ #include "tab_visual_database_display.h" #include "tab_deck_editor.h" -#include "tab_supervisor.h" - -#include TabVisualDatabaseDisplay::TabVisualDatabaseDisplay(TabSupervisor *_tabSupervisor) : Tab(_tabSupervisor) { - auto databaseModel = new CardDatabaseModel(CardDatabaseManager::getInstance(), true, this); - databaseModel->setObjectName("databaseModel"); - - visualDatabaseDisplayWidget = new VisualDatabaseDisplayWidget(this, databaseModel); - - connect(visualDatabaseDisplayWidget, &VisualDatabaseDisplayWidget::edhrecRequested, this, - &TabVisualDatabaseDisplay::openEdhrecTab); + deckEditor = new TabDeckEditor(_tabSupervisor); + deckEditor->setHidden(true); + visualDatabaseDisplayWidget = new VisualDatabaseDisplayWidget( + this, deckEditor, deckEditor->cardDatabaseDockWidget->databaseDisplayWidget->databaseModel, + deckEditor->cardDatabaseDockWidget->databaseDisplayWidget->databaseDisplayModel); setCentralWidget(visualDatabaseDisplayWidget); @@ -23,8 +18,3 @@ TabVisualDatabaseDisplay::TabVisualDatabaseDisplay(TabSupervisor *_tabSupervisor void TabVisualDatabaseDisplay::retranslateUi() { } - -void TabVisualDatabaseDisplay::openEdhrecTab(const CardInfoPtr &info, bool isCommander) const -{ - getTabSupervisor()->addEdhrecTab(info, isCommander); -} \ No newline at end of file diff --git a/cockatrice/src/interface/widgets/tabs/tab_visual_database_display.h b/cockatrice/src/interface/widgets/tabs/tab_visual_database_display.h index 3a4bcd6ea..f5aef6d9b 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_visual_database_display.h +++ b/cockatrice/src/interface/widgets/tabs/tab_visual_database_display.h @@ -15,11 +15,9 @@ class TabVisualDatabaseDisplay : public Tab Q_OBJECT private: + TabDeckEditor *deckEditor; VisualDatabaseDisplayWidget *visualDatabaseDisplayWidget; -private slots: - void openEdhrecTab(const CardInfoPtr &info, bool isCommander) const; - public: TabVisualDatabaseDisplay(TabSupervisor *_tabSupervisor); void retranslateUi() override; diff --git a/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual.cpp b/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual.cpp index fd465ec21..3cdad91fc 100644 --- a/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual.cpp +++ b/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual.cpp @@ -1,7 +1,6 @@ #include "tab_deck_editor_visual.h" #include "../../../../client/settings/cache_settings.h" -#include "../../cards/card_info_display_widget.h" #include "../../deck_editor/deck_state_manager.h" #include "../../filters/filter_builder.h" #include "../../interface/pixel_map_generator.h" @@ -26,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -65,10 +63,9 @@ void TabDeckEditorVisual::createCentralFrame() centralFrame = new QVBoxLayout; centralWidget->setLayout(centralFrame); - auto databaseModel = new CardDatabaseModel(CardDatabaseManager::getInstance(), true, this); - databaseModel->setObjectName("databaseModel"); - - tabContainer = new TabDeckEditorVisualTabWidget(centralWidget, this, deckStateManager->getModel(), databaseModel); + tabContainer = new TabDeckEditorVisualTabWidget( + centralWidget, this, deckStateManager->getModel(), cardDatabaseDockWidget->databaseDisplayWidget->databaseModel, + cardDatabaseDockWidget->databaseDisplayWidget->databaseDisplayModel); connect(tabContainer, &TabDeckEditorVisualTabWidget::cardChanged, this, &TabDeckEditorVisual::changeModelIndexAndCardInfo); @@ -77,14 +74,7 @@ void TabDeckEditorVisual::createCentralFrame() connect(tabContainer, &TabDeckEditorVisualTabWidget::cardClicked, this, &TabDeckEditorVisual::processMainboardCardClick); connect(tabContainer, &TabDeckEditorVisualTabWidget::cardClickedDatabaseDisplay, this, - &TabDeckEditorVisual::processDatabaseCardClick); - - connect(tabContainer, &TabDeckEditorVisualTabWidget::cardAdded, this, &TabDeckEditorVisual::addCard); - connect(tabContainer, &TabDeckEditorVisualTabWidget::cardDecremented, this, &TabDeckEditorVisual::decrementCard); - connect(tabContainer, &TabDeckEditorVisualTabWidget::edhrecRequested, this, &TabDeckEditorVisual::openEdhrecTab); - connect(tabContainer, &TabDeckEditorVisualTabWidget::printingSelectorRequested, this, - &TabDeckEditorVisual::showPrintingSelector); - connect(tabContainer, &TabDeckEditorVisualTabWidget::cardInfoRequested, this, &TabDeckEditorVisual::updateCardInfo); + &TabDeckEditorVisual::processCardClickDatabaseDisplay); centralFrame->addWidget(tabContainer); setCentralWidget(centralWidget); @@ -153,10 +143,12 @@ void TabDeckEditorVisual::changeModelIndexToCard(const ExactCard &activeCard) } } -void TabDeckEditorVisual::processMainboardCardClick(const QMouseEvent *event, - const ExactCard &card, +void TabDeckEditorVisual::processMainboardCardClick(QMouseEvent *event, + CardInfoPictureWithTextOverlayWidget *instance, const QString &zoneName) { + auto card = instance->getCard(); + // Get the model index for the card QModelIndex idx = deckStateManager->getModel()->findCard(card.getName(), zoneName); if (!idx.isValid()) { @@ -176,14 +168,22 @@ void TabDeckEditorVisual::processMainboardCardClick(const QMouseEvent *event, // Alt + Right-click = decrement if (event->button() == Qt::RightButton && event->modifiers().testFlag(Qt::AltModifier)) { - decrementCard(card, zoneName); + if (zoneName == DECK_ZONE_MAIN) { + actDecrementCard(card); + } else { + actDecrementCardFromSideboard(card); + } // Keep selection intact. return; } // Alt + Left click = increment if (event->button() == Qt::LeftButton && event->modifiers().testFlag(Qt::AltModifier)) { - addCard(card, zoneName); + if (zoneName == DECK_ZONE_MAIN) { + actAddCard(card); + } else { + actAddCardToSideboard(card); + } // Keep selection intact. return; } @@ -219,16 +219,13 @@ void TabDeckEditorVisual::processMainboardCardClick(const QMouseEvent *event, } /** @brief Handles clicks on cards in the database display. */ -void TabDeckEditorVisual::processDatabaseCardClick(const QMouseEvent *event, const ExactCard &card) +void TabDeckEditorVisual::processCardClickDatabaseDisplay(QMouseEvent *event, + CardInfoPictureWithTextOverlayWidget *instance) { if (event->button() == Qt::LeftButton) { - if (QApplication::keyboardModifiers() & Qt::ControlModifier) { - addCard(card, DECK_ZONE_SIDE); - } else { - addCard(card, DECK_ZONE_MAIN); - } + actAddCard(instance->getCard()); } else if (event->button() == Qt::RightButton) { - decrementCard(card, DECK_ZONE_MAIN); + actDecrementCard(instance->getCard()); } else if (event->button() == Qt::MiddleButton) { deckDockWidget->actRemoveCard(); } @@ -243,6 +240,14 @@ bool TabDeckEditorVisual::actSaveDeckAs() return result; } +/** @brief Shows the printing selector dock and updates it with the current card. */ +void TabDeckEditorVisual::showPrintingSelector() +{ + printingSelectorDockWidget->printingSelector->setCard(cardInfoDockWidget->cardInfo->getCard().getCardPtr()); + printingSelectorDockWidget->printingSelector->updateDisplay(); + printingSelectorDockWidget->setVisible(true); +} + /** @brief Refreshes keyboard shortcuts for this tab from settings. */ void TabDeckEditorVisual::refreshShortcuts() { diff --git a/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual.h b/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual.h index 7d7a3f3a2..8a0677c9d 100644 --- a/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual.h +++ b/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual.h @@ -41,7 +41,7 @@ * - changeModelIndexAndCardInfo(const ExactCard &card) — Updates deck model selection and card info. * - changeModelIndexToCard(const ExactCard &card) — Selects the card in the deck view. * - processMainboardCardClick(QMouseEvent *event, ...) — Handles clicks on mainboard cards. - * - processDatabaseCardClick(QMouseEvent *event, ...) — Handles clicks on database cards. + * - processCardClickDatabaseDisplay(QMouseEvent *event, ...) — Handles clicks on database cards. * - actSaveDeckAs() — Overrides save action with temporary UI adjustments. * - showPrintingSelector() — Opens the printing selector dock for the current card. * - freeDocksSize() — Frees constraints on dock widget sizes. @@ -144,20 +144,27 @@ public slots: */ void onDeckChanged() override; + /** + * @brief Show the printing selector dock for the currently active card. + */ + void showPrintingSelector() override; + /** * @brief Handle card clicks in the mainboard visual deck. * @param event Mouse event triggering the action. - * @param card The clicked card. + * @param instance Widget representing the clicked card. * @param zoneName Deck zone of the card. */ - void processMainboardCardClick(const QMouseEvent *event, const ExactCard &card, const QString &zoneName); + void processMainboardCardClick(QMouseEvent *event, + CardInfoPictureWithTextOverlayWidget *instance, + const QString &zoneName); /** * @brief Handle card clicks in the database visual display. * @param event Mouse event triggering the action. - * @param card The clicked card. + * @param instance Widget representing the clicked card. */ - void processDatabaseCardClick(const QMouseEvent *event, const ExactCard &card); + void processCardClickDatabaseDisplay(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance); /** * @brief Save the deck under a new name. diff --git a/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.cpp b/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.cpp index 2ee560859..8a4d5903d 100644 --- a/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.cpp +++ b/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.cpp @@ -9,6 +9,7 @@ * @param _deckEditor Pointer to the associated deck editor. * @param _deckModel Pointer to the deck list model. * @param _cardDatabaseModel Pointer to the card database model. + * @param _cardDatabaseDisplayModel Pointer to the card database display model. * * Initializes all sub-widgets (visual deck view, database display, deck analytics, * sample hand) and sets up the tab layout and signal connections. @@ -16,8 +17,10 @@ TabDeckEditorVisualTabWidget::TabDeckEditorVisualTabWidget(QWidget *parent, AbstractTabDeckEditor *_deckEditor, DeckListModel *_deckModel, - CardDatabaseModel *_cardDatabaseModel) - : QTabWidget(parent), deckEditor(_deckEditor), deckModel(_deckModel), cardDatabaseModel(_cardDatabaseModel) + CardDatabaseModel *_cardDatabaseModel, + CardDatabaseDisplayModel *_cardDatabaseDisplayModel) + : QTabWidget(parent), deckEditor(_deckEditor), deckModel(_deckModel), cardDatabaseModel(_cardDatabaseModel), + cardDatabaseDisplayModel(_cardDatabaseDisplayModel) { this->setTabsClosable(true); // Enable tab closing connect(this, &QTabWidget::tabCloseRequested, this, &TabDeckEditorVisualTabWidget::handleTabClose); @@ -31,25 +34,16 @@ TabDeckEditorVisualTabWidget::TabDeckEditorVisualTabWidget(QWidget *parent, &TabDeckEditorVisualTabWidget::onCardChanged); connect(visualDeckView, &VisualDeckEditorWidget::cardClicked, this, &TabDeckEditorVisualTabWidget::onCardClickedDeckEditor); - connect(visualDeckView, &VisualDeckEditorWidget::cardAdditionRequested, this, - &TabDeckEditorVisualTabWidget::actAddCard); + connect(visualDeckView, &VisualDeckEditorWidget::cardAdditionRequested, deckEditor, + &AbstractTabDeckEditor::actAddCard); - visualDatabaseDisplay = new VisualDatabaseDisplayWidget(this, _cardDatabaseModel, deckModel); + visualDatabaseDisplay = + new VisualDatabaseDisplayWidget(this, deckEditor, _cardDatabaseModel, _cardDatabaseDisplayModel); visualDatabaseDisplay->setObjectName("visualDatabaseView"); connect(visualDatabaseDisplay, &VisualDatabaseDisplayWidget::cardHoveredDatabaseDisplay, this, &TabDeckEditorVisualTabWidget::onCardChangedDatabaseDisplay); connect(visualDatabaseDisplay, &VisualDatabaseDisplayWidget::cardClickedDatabaseDisplay, this, &TabDeckEditorVisualTabWidget::onCardClickedDatabaseDisplay); - connect(visualDatabaseDisplay, &VisualDatabaseDisplayWidget::cardAdded, this, - &TabDeckEditorVisualTabWidget::cardAdded); - connect(visualDatabaseDisplay, &VisualDatabaseDisplayWidget::cardDecremented, this, - &TabDeckEditorVisualTabWidget::cardDecremented); - connect(visualDatabaseDisplay, &VisualDatabaseDisplayWidget::edhrecRequested, this, - &TabDeckEditorVisualTabWidget::edhrecRequested); - connect(visualDatabaseDisplay, &VisualDatabaseDisplayWidget::printingSelectorRequested, this, - &TabDeckEditorVisualTabWidget::printingSelectorRequested); - connect(visualDatabaseDisplay, &VisualDatabaseDisplayWidget::cardInfoRequested, this, - &TabDeckEditorVisualTabWidget::cardInfoRequested); statsAnalyzer = new DeckListStatisticsAnalyzer(this, deckModel); statsAnalyzer->analyze(); @@ -88,24 +82,25 @@ void TabDeckEditorVisualTabWidget::onCardChangedDatabaseDisplay(const ExactCard /** * @brief Emits the cardClicked signal when a card is clicked in the visual deck view. * @param event The mouse event. - * @param card The clicked card. + * @param instance The widget instance of the clicked card. * @param zoneName The zone of the deck where the card is located. */ void TabDeckEditorVisualTabWidget::onCardClickedDeckEditor(QMouseEvent *event, - const ExactCard &card, - const QString &zoneName) + CardInfoPictureWithTextOverlayWidget *instance, + QString zoneName) { - emit cardClicked(event, card, zoneName); + emit cardClicked(event, instance, zoneName); } /** * @brief Emits the cardClickedDatabaseDisplay signal when a card is clicked in the database display. * @param event The mouse event. - * @param card The clicked card. + * @param instance The widget instance of the clicked card. */ -void TabDeckEditorVisualTabWidget::onCardClickedDatabaseDisplay(QMouseEvent *event, const ExactCard &card) +void TabDeckEditorVisualTabWidget::onCardClickedDatabaseDisplay(QMouseEvent *event, + CardInfoPictureWithTextOverlayWidget *instance) { - emit cardClickedDatabaseDisplay(event, card); + emit cardClickedDatabaseDisplay(event, instance); } /** @@ -171,15 +166,3 @@ void TabDeckEditorVisualTabWidget::handleTabClose(int index) this->removeTab(index); delete tab; } - -void TabDeckEditorVisualTabWidget::actAddCard(const ExactCard &card) -{ - QString zoneName; - if (QApplication::keyboardModifiers() & Qt::ControlModifier) { - zoneName = DECK_ZONE_SIDE; - } else { - zoneName = DECK_ZONE_MAIN; - } - - deckEditor->addCard(card, zoneName); -} diff --git a/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.h b/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.h index 2aabbb26a..48dd8ea9d 100644 --- a/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.h +++ b/cockatrice/src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.h @@ -55,11 +55,13 @@ public: * @param _deckEditor Pointer to the deck editor instance. * @param _deckModel Deck list model. * @param _cardDatabaseModel Card database model. + * @param _cardDatabaseDisplayModel Database display model. */ explicit TabDeckEditorVisualTabWidget(QWidget *parent, AbstractTabDeckEditor *_deckEditor, DeckListModel *_deckModel, - CardDatabaseModel *_cardDatabaseModel); + CardDatabaseModel *_cardDatabaseModel, + CardDatabaseDisplayModel *_cardDatabaseDisplayModel); /** @brief Add a new tab with a widget and title. */ void addNewTab(QWidget *widget, const QString &title); @@ -99,35 +101,30 @@ public slots: /** * @brief Emitted when a card is clicked in the deck view. * @param event Mouse event. - * @param card The clicked card. + * @param instance Widget representing the clicked card. * @param zoneName Deck zone of the card. */ - void onCardClickedDeckEditor(QMouseEvent *event, const ExactCard &card, const QString &zoneName); + void onCardClickedDeckEditor(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance, QString zoneName); /** * @brief Emitted when a card is clicked in the database display. * @param event Mouse event. - * @param card The clicked card. + * @param instance Widget representing the clicked card. */ - void onCardClickedDatabaseDisplay(QMouseEvent *event, const ExactCard &card); + void onCardClickedDatabaseDisplay(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance); signals: void cardChanged(const ExactCard &activeCard); void cardChangedDatabaseDisplay(const ExactCard &activeCard); - void cardClicked(QMouseEvent *event, const ExactCard &card, const QString &zoneName); - void cardClickedDatabaseDisplay(QMouseEvent *event, const ExactCard &card); - - void cardAdded(const ExactCard &card, const QString &zoneName); - void cardDecremented(const ExactCard &card, const QString &zoneName); - void edhrecRequested(const CardInfoPtr &cardInfo, bool isCommander); - void printingSelectorRequested(); - void cardInfoRequested(const ExactCard &cardName); + void cardClicked(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance, QString zoneName); + void cardClickedDatabaseDisplay(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance); private: - QVBoxLayout *layout; ///< Layout for tabs and controls. - AbstractTabDeckEditor *deckEditor; ///< Reference to the deck editor. - DeckListModel *deckModel; ///< Deck list model. - CardDatabaseModel *cardDatabaseModel; ///< Card database model. + QVBoxLayout *layout; ///< Layout for tabs and controls. + AbstractTabDeckEditor *deckEditor; ///< Reference to the deck editor. + DeckListModel *deckModel; ///< Deck list model. + CardDatabaseModel *cardDatabaseModel; ///< Card database model. + CardDatabaseDisplayModel *cardDatabaseDisplayModel; ///< Card database display model. private slots: /** @@ -135,12 +132,6 @@ private slots: * @param index Index of the tab to close. */ void handleTabClose(int index); - - /** - * @brief Adds card to maindeck or side depending on whether ctrl is held - * @param card - */ - void actAddCard(const ExactCard &card); }; #endif // TAB_DECK_EDITOR_VISUAL_TAB_WIDGET_H \ No newline at end of file diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_toolbar_widget.cpp b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_toolbar_widget.cpp index 62e1bf5ba..885925694 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_toolbar_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_toolbar_widget.cpp @@ -1,14 +1,12 @@ #include "visual_database_display_filter_toolbar_widget.h" -#include "../deck_editor/card_database_view.h" #include "visual_database_display_widget.h" #include -VisualDatabaseDisplayFilterToolbarWidget::VisualDatabaseDisplayFilterToolbarWidget(VisualDatabaseDisplayWidget *_parent, - DeckListModel *deckListModel) +VisualDatabaseDisplayFilterToolbarWidget::VisualDatabaseDisplayFilterToolbarWidget(VisualDatabaseDisplayWidget *_parent) : FlowWidget(_parent, Qt::Horizontal, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAlwaysOff), - visualDatabaseDisplay(_parent), deckListModel(deckListModel) + visualDatabaseDisplay(_parent) { connect(this, &VisualDatabaseDisplayFilterToolbarWidget::searchModelChanged, visualDatabaseDisplay, &VisualDatabaseDisplayWidget::onSearchModelChanged); @@ -99,7 +97,8 @@ void VisualDatabaseDisplayFilterToolbarWidget::initialize() auto filterModel = visualDatabaseDisplay->getFilterModel(); saveLoadWidget = new VisualDatabaseDisplayFilterSaveLoadWidget(this, filterModel); - nameFilterWidget = new VisualDatabaseDisplayNameFilterWidget(this, filterModel, deckListModel); + nameFilterWidget = + new VisualDatabaseDisplayNameFilterWidget(this, visualDatabaseDisplay->getDeckEditor(), filterModel); mainTypeFilterWidget = new VisualDatabaseDisplayMainTypeFilterWidget(this, filterModel); formatLegalityWidget = new VisualDatabaseDisplayFormatLegalityFilterWidget(this, filterModel); subTypeFilterWidget = new VisualDatabaseDisplaySubTypeFilterWidget(this, filterModel); @@ -175,8 +174,7 @@ void VisualDatabaseDisplayFilterToolbarWidget::updateCompactMode(int availableWi }; for (auto *btn : filterButtons) { - if (btn->isCompact() != compact) { // only act on transitions + if (btn->isCompact() != compact) // only act on transitions btn->setCompact(compact); - } } } \ No newline at end of file diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_toolbar_widget.h b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_toolbar_widget.h index 8a3555455..5b55f4ba6 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_toolbar_widget.h +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_filter_toolbar_widget.h @@ -18,14 +18,12 @@ signals: void searchModelChanged(); public: - explicit VisualDatabaseDisplayFilterToolbarWidget(VisualDatabaseDisplayWidget *parent, - DeckListModel *deckListModel = nullptr); + explicit VisualDatabaseDisplayFilterToolbarWidget(VisualDatabaseDisplayWidget *parent); void initialize(); void retranslateUi(); private: VisualDatabaseDisplayWidget *visualDatabaseDisplay; - DeckListModel *deckListModel; QGroupBox *sortGroupBox; QLabel *sortByLabel; diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_name_filter_widget.cpp b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_name_filter_widget.cpp index 3fa1a782a..fd03e17e6 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_name_filter_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_name_filter_widget.cpp @@ -8,9 +8,9 @@ #include VisualDatabaseDisplayNameFilterWidget::VisualDatabaseDisplayNameFilterWidget(QWidget *parent, - FilterTreeModel *_filterModel, - DeckListModel *deckListModel) - : QWidget(parent), filterModel(_filterModel), deckListModel(deckListModel) + AbstractTabDeckEditor *_deckEditor, + FilterTreeModel *_filterModel) + : QWidget(parent), deckEditor(_deckEditor), filterModel(_filterModel) { setMinimumWidth(300); setMaximumHeight(300); @@ -62,6 +62,8 @@ void VisualDatabaseDisplayNameFilterWidget::retranslateUi() void VisualDatabaseDisplayNameFilterWidget::actLoadFromDeck() { + DeckListModel *deckListModel = deckEditor->deckStateManager->getModel(); + if (!deckListModel) { return; } diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_name_filter_widget.h b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_name_filter_widget.h index 0c10408ae..5a8438a05 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_name_filter_widget.h +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_name_filter_widget.h @@ -21,8 +21,8 @@ class VisualDatabaseDisplayNameFilterWidget : public QWidget Q_OBJECT public: explicit VisualDatabaseDisplayNameFilterWidget(QWidget *parent, - FilterTreeModel *filterModel, - DeckListModel *deckListModel = nullptr); + AbstractTabDeckEditor *deckEditor, + FilterTreeModel *filterModel); void createNameFilter(const QString &name); void removeNameFilter(const QString &name); @@ -34,8 +34,8 @@ public slots: void retranslateUi(); private: + AbstractTabDeckEditor *deckEditor; FilterTreeModel *filterModel; - DeckListModel *deckListModel; QVBoxLayout *layout; QLineEdit *searchBox; FlowWidget *flowWidget; diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp index cc4cce496..70218d478 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.cpp @@ -5,7 +5,7 @@ #include "../../../filters/syntax_help.h" #include "../../pixel_map_generator.h" #include "../cards/card_info_picture_with_text_overlay_widget.h" -#include "../deck_editor/card_database_view.h" +#include "../quick_settings/settings_button_widget.h" #include "../utility/custom_line_edit.h" #include "visual_database_display_color_filter_widget.h" #include "visual_database_display_filter_save_load_widget.h" @@ -23,21 +23,17 @@ #include VisualDatabaseDisplayWidget::VisualDatabaseDisplayWidget(QWidget *parent, + AbstractTabDeckEditor *_deckEditor, CardDatabaseModel *database_model, - DeckListModel *deckListModel) - : QWidget(parent) + CardDatabaseDisplayModel *database_display_model) + : QWidget(parent), deckEditor(_deckEditor), databaseModel(database_model), + databaseDisplayModel(database_display_model) { debounceTimer = new QTimer(this); debounceTimer->setSingleShot(true); // Ensure it only fires once after the timeout connect(debounceTimer, &QTimer::timeout, this, &VisualDatabaseDisplayWidget::onSearchModelChanged); - // Create display model - databaseDisplayModel = new CardDatabaseDisplayModel(this); - databaseDisplayModel->setObjectName("databaseDisplayModel"); - databaseDisplayModel->setSourceModel(database_model); - databaseDisplayModel->setFilterKeyColumn(0); - cards = new QList; connect(databaseDisplayModel, &CardDatabaseDisplayModel::modelDirty, this, &VisualDatabaseDisplayWidget::modelDirty); @@ -64,6 +60,7 @@ VisualDatabaseDisplayWidget::VisualDatabaseDisplayWidget(QWidget *parent, searchEdit->addAction(loadColorAdjustedPixmap("theme:icons/search"), QLineEdit::LeadingPosition); auto help = searchEdit->addAction(QPixmap("theme:icons/info"), QLineEdit::TrailingPosition); connect(help, &QAction::triggered, this, [this] { createSearchSyntaxHelpWindow(searchEdit); }); + searchEdit->installEventFilter(&searchKeySignals); setFocusProxy(searchEdit); setFocusPolicy(Qt::ClickFocus); @@ -78,29 +75,43 @@ VisualDatabaseDisplayWidget::VisualDatabaseDisplayWidget(QWidget *parent, filterModel = new FilterTreeModel(); filterModel->setObjectName("filterModel"); - connect(searchEdit, &SearchLineEdit::textChanged, databaseDisplayModel, &CardDatabaseDisplayModel::setStringFilter); + searchKeySignals.setObjectName("searchKeySignals"); + connect(searchEdit, &SearchLineEdit::textChanged, this, &VisualDatabaseDisplayWidget::updateSearch); - databaseView = new CardDatabaseView(this, databaseDisplayModel); - databaseView->setObjectName("databaseView"); + DeckEditorDatabaseDisplayWidget *databaseDisplayWidget = deckEditor->cardDatabaseDockWidget->databaseDisplayWidget; + connect(&searchKeySignals, &KeySignals::onEnter, databaseDisplayWidget, + &DeckEditorDatabaseDisplayWidget::actAddCardToMainDeck); + connect(&searchKeySignals, &KeySignals::onCtrlAltEqual, databaseDisplayWidget, + &DeckEditorDatabaseDisplayWidget::actAddCardToMainDeck); + connect(&searchKeySignals, &KeySignals::onCtrlAltRBracket, databaseDisplayWidget, + &DeckEditorDatabaseDisplayWidget::actAddCardToSideboard); + connect(&searchKeySignals, &KeySignals::onCtrlAltMinus, databaseDisplayWidget, + &DeckEditorDatabaseDisplayWidget::actDecrementCardFromMainDeck); + connect(&searchKeySignals, &KeySignals::onCtrlAltLBracket, databaseDisplayWidget, + &DeckEditorDatabaseDisplayWidget::actDecrementCardFromSideboard); + connect(&searchKeySignals, &KeySignals::onCtrlAltEnter, databaseDisplayWidget, + &DeckEditorDatabaseDisplayWidget::actAddCardToSideboard); + connect(&searchKeySignals, &KeySignals::onCtrlEnter, databaseDisplayWidget, + &DeckEditorDatabaseDisplayWidget::actAddCardToSideboard); + connect(&searchKeySignals, &KeySignals::onCtrlC, databaseDisplayWidget, + &DeckEditorDatabaseDisplayWidget::copyDatabaseCellContents); + connect(help, &QAction::triggered, this, [this] { createSearchSyntaxHelpWindow(searchEdit); }); + + connect(databaseDisplayWidget, &DeckEditorDatabaseDisplayWidget::addCardToMainDeck, this, + &VisualDatabaseDisplayWidget::highlightAllSearchEdit); + connect(databaseDisplayWidget, &DeckEditorDatabaseDisplayWidget::addCardToSideboard, this, + &VisualDatabaseDisplayWidget::highlightAllSearchEdit); + + databaseView = databaseDisplayWidget->getDatabaseView(); databaseView->setFocusProxy(searchEdit); databaseView->setItemDelegate(nullptr); databaseView->setVisible(false); searchEdit->setTreeView(databaseView); - searchEdit->installEventFilter(databaseView->getKeySignals()); - - connect(databaseView, &CardDatabaseView::cardChanged, this, &VisualDatabaseDisplayWidget::onSelectedCardChanged); - connect(databaseView, &CardDatabaseView::cardAdded, this, &VisualDatabaseDisplayWidget::actAddCard); - connect(databaseView, &CardDatabaseView::cardDecremented, this, &VisualDatabaseDisplayWidget::actDecrementCard); - connect(databaseView, &CardDatabaseView::edhrecClicked, this, &VisualDatabaseDisplayWidget::edhrecRequested); - connect(databaseView, &CardDatabaseView::selectPrintingClicked, this, - &VisualDatabaseDisplayWidget::printingSelectorRequested); - connect(databaseView, &CardDatabaseView::relatedCardClicked, this, - &VisualDatabaseDisplayWidget::onRelatedCardClicked); colorFilterWidget = new VisualDatabaseDisplayColorFilterWidget(this, filterModel); - filterContainer = new VisualDatabaseDisplayFilterToolbarWidget(this, deckListModel); + filterContainer = new VisualDatabaseDisplayFilterToolbarWidget(this); clearFilterWidget = new QToolButton(); clearFilterWidget->setFixedSize(32, 32); @@ -205,9 +216,9 @@ void VisualDatabaseDisplayWidget::onDisplayModeChanged(bool checked) } } -void VisualDatabaseDisplayWidget::onClick(QMouseEvent *event, const ExactCard &card) +void VisualDatabaseDisplayWidget::onClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance) { - emit cardClickedDatabaseDisplay(event, card); + emit cardClickedDatabaseDisplay(event, instance); } void VisualDatabaseDisplayWidget::onHover(const ExactCard &hoveredCard) @@ -215,18 +226,28 @@ void VisualDatabaseDisplayWidget::onHover(const ExactCard &hoveredCard) emit cardHoveredDatabaseDisplay(hoveredCard); } -void VisualDatabaseDisplayWidget::addCardToDisplay(const ExactCard &cardToAdd) +void VisualDatabaseDisplayWidget::addCard(const ExactCard &cardToAdd) { cards->append(cardToAdd); auto *display = new CardInfoPictureWithTextOverlayWidget(flowWidget, false); display->setScaleFactor(cardSizeWidget->getSlider()->value()); display->setCard(cardToAdd); flowWidget->addWidget(display); - connect(display, &CardInfoPictureWithTextOverlayWidget::cardClicked, this, &VisualDatabaseDisplayWidget::onClick); + connect(display, &CardInfoPictureWithTextOverlayWidget::imageClicked, this, &VisualDatabaseDisplayWidget::onClick); connect(display, &CardInfoPictureWithTextOverlayWidget::hoveredOnCard, this, &VisualDatabaseDisplayWidget::onHover); connect(cardSizeWidget->getSlider(), &QSlider::valueChanged, display, &CardInfoPictureWidget::setScaleFactor); } +void VisualDatabaseDisplayWidget::updateSearch(const QString &search) const +{ + databaseDisplayModel->setStringFilter(search); + QModelIndexList sel = databaseView->selectionModel()->selectedRows(); + if (sel.isEmpty() && databaseDisplayModel->rowCount()) { + databaseView->selectionModel()->setCurrentIndex(databaseDisplayModel->index(0, 0), + QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); + } +} + bool VisualDatabaseDisplayWidget::isVisualDisplayMode() const { return !displayModeButton->isChecked(); @@ -248,30 +269,6 @@ void VisualDatabaseDisplayWidget::onSearchModelChanged() } } -void VisualDatabaseDisplayWidget::onSelectedCardChanged(const QString &cardName) -{ - emit cardHoveredDatabaseDisplay(CardDatabaseManager::query()->getPreferredCard(cardName)); -} - -void VisualDatabaseDisplayWidget::actAddCard(const QString &cardName, const QString &zoneName) -{ - highlightAllSearchEdit(); - ExactCard exactCard = CardDatabaseManager::query()->getPreferredCard(cardName); - emit cardAdded(exactCard, zoneName); -} - -void VisualDatabaseDisplayWidget::actDecrementCard(const QString &cardName, const QString &zoneName) -{ - ExactCard exactCard = CardDatabaseManager::query()->getPreferredCard(cardName); - emit cardDecremented(exactCard, zoneName); -} - -void VisualDatabaseDisplayWidget::onRelatedCardClicked(const QString &relatedCard) -{ - ExactCard exactCard = CardDatabaseManager::query()->guessCard({relatedCard}); - emit cardInfoRequested(exactCard); -} - bool VisualDatabaseDisplayWidget::nearEndOfPage() const { if (!flowWidget->isVisible()) { @@ -338,12 +335,12 @@ void VisualDatabaseDisplayWidget::loadPage(int start, int end) for (const CardFilter *setFilter : setFilters) { if (setMap.contains(setFilter->term())) { for (PrintingInfo printing : setMap[setFilter->term()]) { - addCardToDisplay(ExactCard(info, printing)); + addCard(ExactCard(info, printing)); } } } } else { - addCardToDisplay(CardDatabaseManager::query()->getPreferredCard(info)); + addCard(CardDatabaseManager::query()->getPreferredCard(info)); } } else { qCDebug(VisualDatabaseDisplayLog) << "Card not found in database!"; diff --git a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h index a383e8ead..48a026d11 100644 --- a/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h +++ b/cockatrice/src/interface/widgets/visual_database_display/visual_database_display_widget.h @@ -34,8 +34,9 @@ class VisualDatabaseDisplayWidget : public QWidget public: explicit VisualDatabaseDisplayWidget(QWidget *parent, + AbstractTabDeckEditor *deckEditor, CardDatabaseModel *database_model, - DeckListModel *deckListModel = nullptr); + CardDatabaseDisplayModel *database_display_model); void retranslateUi(); void adjustCardsPerPage(); @@ -46,12 +47,17 @@ public: void sortCardList(const QStringList &properties, Qt::SortOrder order) const; void setDeckList(const DeckList &new_deck_list_model); + AbstractTabDeckEditor *getDeckEditor() + { + return deckEditor; + } + CardDatabaseDisplayModel *getDatabaseDisplayModel() { return databaseDisplayModel; } - CardDatabaseView *getDatabaseView() + QTreeView *getDatabaseView() { return databaseView; } @@ -70,29 +76,19 @@ public slots: void onSearchModelChanged(); signals: - void cardClickedDatabaseDisplay(QMouseEvent *event, const ExactCard &card); + void cardClickedDatabaseDisplay(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance); void cardHoveredDatabaseDisplay(const ExactCard &hoveredCard); - void cardAdded(const ExactCard &card, const QString &zoneName); - void cardDecremented(const ExactCard &card, const QString &zoneName); - void edhrecRequested(const CardInfoPtr &cardInfo, bool isCommander); - void printingSelectorRequested(); - void cardInfoRequested(const ExactCard &cardName); - protected slots: void initialize(); - void onClick(QMouseEvent *event, const ExactCard &card); + void onClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance); void onHover(const ExactCard &hoveredCard); - void addCardToDisplay(const ExactCard &cardToAdd); + void addCard(const ExactCard &cardToAdd); void databaseDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); void modelDirty() const; + void updateSearch(const QString &search) const; void onDisplayModeChanged(bool checked); - void onSelectedCardChanged(const QString &cardName); - void actAddCard(const QString &cardName, const QString &zoneName); - void actDecrementCard(const QString &cardName, const QString &zoneName); - void onRelatedCardClicked(const QString &relatedCard); - private: FlowWidget *searchContainer; SearchLineEdit *searchEdit; @@ -104,8 +100,11 @@ private: QToolButton *clearFilterWidget; VisualDatabaseDisplayFilterToolbarWidget *filterContainer; + KeySignals searchKeySignals; + AbstractTabDeckEditor *deckEditor; + CardDatabaseModel *databaseModel; CardDatabaseDisplayModel *databaseDisplayModel; - CardDatabaseView *databaseView; + QTreeView *databaseView; QList *cards; QVBoxLayout *mainLayout; QScrollArea *scrollArea; diff --git a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.cpp b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.cpp index 815892f4c..4a67edcd1 100644 --- a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.cpp +++ b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.cpp @@ -281,7 +281,7 @@ void VisualDeckEditorWidget::constructZoneWidgetForIndex(QPersistentModelIndex p displayOptionsWidget->getActiveGroupCriteria(), displayOptionsWidget->getActiveSortCriteria(), displayOptionsWidget->getDisplayType(), 20, 10, cardSizeWidget); connect(zoneDisplayWidget, &DeckCardZoneDisplayWidget::cardHovered, this, &VisualDeckEditorWidget::onHover); - connect(zoneDisplayWidget, &DeckCardZoneDisplayWidget::cardClicked, this, &VisualDeckEditorWidget::cardClicked); + connect(zoneDisplayWidget, &DeckCardZoneDisplayWidget::cardClicked, this, &VisualDeckEditorWidget::onCardClick); connect(zoneDisplayWidget, &DeckCardZoneDisplayWidget::requestCleanup, this, &VisualDeckEditorWidget::cleanupInvalidZones); connect(this, &VisualDeckEditorWidget::activeSortCriteriaChanged, zoneDisplayWidget, @@ -401,6 +401,13 @@ void VisualDeckEditorWidget::decklistDataChanged(QModelIndex topLeft, QModelInde // User Interaction // ===================================================================================================================== +void VisualDeckEditorWidget::onCardClick(QMouseEvent *event, + CardInfoPictureWithTextOverlayWidget *instance, + QString zoneName) +{ + emit cardClicked(event, instance, zoneName); +} + void VisualDeckEditorWidget::onHover(const ExactCard &hoveredCard) { // If user has any card selected, ignore hover diff --git a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.h b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.h index da02b5c1f..1af565b29 100644 --- a/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.h +++ b/cockatrice/src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.h @@ -69,7 +69,7 @@ signals: void activeCardChanged(const ExactCard &activeCard); void activeGroupCriteriaChanged(QString activeGroupCriteria); void activeSortCriteriaChanged(QStringList activeSortCriteria); - void cardClicked(QMouseEvent *event, const ExactCard &card, const QString &zoneName); + void cardClicked(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance, QString zoneName); void cardAdditionRequested(const ExactCard &card); void displayTypeChanged(DisplayType displayType); @@ -82,6 +82,7 @@ protected: protected slots: void onHover(const ExactCard &hoveredCard); + void onCardClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance, QString zoneName); void decklistModelReset(); void resizeEvent(QResizeEvent *event) override; diff --git a/format.sh b/format.sh index 83dee9e28..c43f537f5 100755 --- a/format.sh +++ b/format.sh @@ -3,7 +3,7 @@ # This script will run clang-format on all modified, non-3rd-party C++/Header files. # Optionally runs cmake-format on all modified cmake files. # Optionally runs shellcheck on all modified shell files. -# Uses clang-format, cmake-format, git, diff, find and shellcheck +# Uses clang-format cmake-format git diff find shellcheck # Never, ever, should this receive a path with a newline in it. Don't bother proofing it for that. set -o pipefail @@ -103,11 +103,11 @@ OPTIONS: Do not check any source files for clang-format. --print-version - Print the lint tool version being used before continuing. + Print the version of clang-format being used before continuing. --shell - Use shellcheck to lint shell files. - Not available in the default inline mode. + Use shellcheck to lint shell files. Not available in the default inline + mode. -t, --test Do not edit files in place. Set exit code to 1 if changes are required. diff --git a/libcockatrice_card/libcockatrice/card/database/card_database.cpp b/libcockatrice_card/libcockatrice/card/database/card_database.cpp index edad46174..951381aa4 100644 --- a/libcockatrice_card/libcockatrice/card/database/card_database.cpp +++ b/libcockatrice_card/libcockatrice/card/database/card_database.cpp @@ -92,7 +92,7 @@ void CardDatabase::refreshCachedReverseRelatedCards() } } -void CardDatabase::addCard(const CardInfoPtr &card) +void CardDatabase::addCard(CardInfoPtr card) { if (card == nullptr) { qCWarning(CardDatabaseLog) << "CardDatabase::addCard(nullptr)"; @@ -118,7 +118,7 @@ void CardDatabase::addCard(const CardInfoPtr &card) emit cardAdded(card); } -void CardDatabase::removeCard(const CardInfoPtr &card) +void CardDatabase::removeCard(CardInfoPtr card) { if (card.isNull()) { qCWarning(CardDatabaseLog) << "CardDatabase::removeCard(nullptr)"; @@ -143,7 +143,7 @@ void CardDatabase::removeCard(const CardInfoPtr &card) emit cardRemoved(card); } -void CardDatabase::addSet(const CardSetPtr &set) +void CardDatabase::addSet(CardSetPtr set) { sets.insert(set->getShortName(), set); } @@ -215,7 +215,7 @@ void CardDatabase::notifyEnabledSetsChanged() emit cardDatabaseEnabledSetsChanged(); } -void CardDatabase::addFormat(const FormatRulesPtr &format) +void CardDatabase::addFormat(FormatRulesPtr format) { formats.insert(format->formatName.toLower(), format); -} +} \ No newline at end of file diff --git a/libcockatrice_card/libcockatrice/card/database/card_database.h b/libcockatrice_card/libcockatrice/card/database/card_database.h index 44838962d..521be8fbc 100644 --- a/libcockatrice_card/libcockatrice/card/database/card_database.h +++ b/libcockatrice_card/libcockatrice/card/database/card_database.h @@ -88,7 +88,7 @@ public: * @brief Removes a card from the database. * @param card Pointer to the card to remove. */ - void removeCard(const CardInfoPtr &card); + void removeCard(CardInfoPtr card); /** @brief Clears all cards, sets, and internal state. */ void clear(); @@ -140,15 +140,15 @@ public slots: * @brief Adds a card to the database. * @param card CardInfoPtr to add. */ - void addCard(const CardInfoPtr &card); + void addCard(CardInfoPtr card); /** * @brief Adds a set to the database. * @param set Pointer to CardSet to add. */ - void addSet(const CardSetPtr &set); + void addSet(CardSetPtr set); - void addFormat(const FormatRulesPtr &format); + void addFormat(FormatRulesPtr format); /** @brief Loads card databases from configured paths. */ void loadCardDatabases(); diff --git a/libcockatrice_card/libcockatrice/card/database/parser/cockatrice_xml_3.cpp b/libcockatrice_card/libcockatrice/card/database/parser/cockatrice_xml_3.cpp index b6c3afc57..ba27d63c4 100644 --- a/libcockatrice_card/libcockatrice/card/database/parser/cockatrice_xml_3.cpp +++ b/libcockatrice_card/libcockatrice/card/database/parser/cockatrice_xml_3.cpp @@ -217,32 +217,27 @@ void CockatriceXml3Parser::loadCardsFromXml(QXmlStreamReader &xml) // NOTE: attributes must be read before readElementText() QXmlStreamAttributes attrs = xml.attributes(); QString setName = xml.readElementText(QXmlStreamReader::IncludeChildElements); - auto set = internalAddSet(setName); - // Only load printings from sets the user has enabled, matching the v4 loader's - // behaviour. Without this check, disabling a set has no effect on v3 databases. - if (set->getEnabled()) { - PrintingInfo setInfo(set); - if (attrs.hasAttribute("muId")) { - setInfo.setProperty("muid", attrs.value("muId").toString()); - } - - if (attrs.hasAttribute("uuId")) { - setInfo.setProperty("uuid", attrs.value("uuId").toString()); - } - - if (attrs.hasAttribute("picURL")) { - setInfo.setProperty("picurl", attrs.value("picURL").toString()); - } - - if (attrs.hasAttribute("num")) { - setInfo.setProperty("num", attrs.value("num").toString()); - } - - if (attrs.hasAttribute("rarity")) { - setInfo.setProperty("rarity", attrs.value("rarity").toString()); - } - _sets[setName].append(setInfo); + PrintingInfo setInfo(internalAddSet(setName)); + if (attrs.hasAttribute("muId")) { + setInfo.setProperty("muid", attrs.value("muId").toString()); } + + if (attrs.hasAttribute("muId")) { + setInfo.setProperty("uuid", attrs.value("uuId").toString()); + } + + if (attrs.hasAttribute("picURL")) { + setInfo.setProperty("picurl", attrs.value("picURL").toString()); + } + + if (attrs.hasAttribute("num")) { + setInfo.setProperty("num", attrs.value("num").toString()); + } + + if (attrs.hasAttribute("rarity")) { + setInfo.setProperty("rarity", attrs.value("rarity").toString()); + } + _sets[setName].append(setInfo); // related cards } else if (xmlName == "related" || xmlName == "reverse-related") { CardRelationType attach = CardRelationType::DoesNotAttach; diff --git a/libcockatrice_filters/libcockatrice/filters/filter_string.cpp b/libcockatrice_filters/libcockatrice/filters/filter_string.cpp index 25e8e97db..704e8fadb 100644 --- a/libcockatrice_filters/libcockatrice/filters/filter_string.cpp +++ b/libcockatrice_filters/libcockatrice/filters/filter_string.cpp @@ -251,27 +251,20 @@ static void setupParserRules() const auto arg = std::any_cast(sv[1]); const auto op = std::any_cast(sv[0]); - if (op == ">") { + if (op == ">") return [=](const int s) { return s > arg; }; - } - if (op == ">=") { + if (op == ">=") return [=](const int s) { return s >= arg; }; - } - if (op == "<") { + if (op == "<") return [=](const int s) { return s < arg; }; - } - if (op == "<=") { + if (op == "<=") return [=](const int s) { return s <= arg; }; - } - if (op == "=") { + if (op == "=") return [=](const int s) { return s == arg; }; - } - if (op == ":") { + if (op == ":") return [=](const int s) { return s == arg; }; - } - if (op == "!=") { + if (op == "!=") return [=](const int s) { return s != arg; }; - } return [](int) { return false; }; }; @@ -322,9 +315,8 @@ static void setupParserRules() return true; } - if (parts.contains("c") && match.length() == 0) { + if (parts.contains("c") && match.length() == 0) return true; - } auto containsColor = [&parts](const QString &s) { return parts.contains(s); }; return std::any_of(match.begin(), match.end(), containsColor); diff --git a/libcockatrice_filters/libcockatrice/filters/filter_tree.cpp b/libcockatrice_filters/libcockatrice/filters/filter_tree.cpp index 8502db50b..19e8c2d8d 100644 --- a/libcockatrice_filters/libcockatrice/filters/filter_tree.cpp +++ b/libcockatrice_filters/libcockatrice/filters/filter_tree.cpp @@ -205,9 +205,8 @@ bool FilterItem::acceptColor(const CardInfoPtr info) const */ int match_count = 0; for (auto &it : converted_term) { - if (info->getColors().contains(it, Qt::CaseInsensitive)) { + if (info->getColors().contains(it, Qt::CaseInsensitive)) match_count++; - } } return match_count == converted_term.length(); @@ -543,14 +542,12 @@ void FilterTree::removeFilter(const CardFilter *toRemove) { for (int i = childNodes.size() - 1; i >= 0; --i) { auto *logicMap = dynamic_cast(childNodes.at(i)); - if (!logicMap || logicMap->attr != toRemove->attr()) { + if (!logicMap || logicMap->attr != toRemove->attr()) continue; - } FilterItemList *typeList = logicMap->typeList(toRemove->type()); - if (!typeList) { + if (!typeList) continue; - } int termIdx = typeList->termIndex(toRemove->term()); if (termIdx != -1) { diff --git a/libcockatrice_interfaces/libcockatrice/interfaces/interface_card_set_priority_controller.h b/libcockatrice_interfaces/libcockatrice/interfaces/interface_card_set_priority_controller.h index 9559967af..333190015 100644 --- a/libcockatrice_interfaces/libcockatrice/interfaces/interface_card_set_priority_controller.h +++ b/libcockatrice_interfaces/libcockatrice/interfaces/interface_card_set_priority_controller.h @@ -6,8 +6,7 @@ class ICardSetPriorityController { public: - struct SetSaveData - { + struct SetSaveData { QString shortName; unsigned int sortKey; bool enabled; diff --git a/libcockatrice_interfaces/libcockatrice/interfaces/noop_card_set_priority_controller.h b/libcockatrice_interfaces/libcockatrice/interfaces/noop_card_set_priority_controller.h index 188e2ced9..16fc4c19a 100644 --- a/libcockatrice_interfaces/libcockatrice/interfaces/noop_card_set_priority_controller.h +++ b/libcockatrice_interfaces/libcockatrice/interfaces/noop_card_set_priority_controller.h @@ -29,9 +29,8 @@ public: return true; } - void saveSets(const QVector & /* data */) override - { - } + void saveSets(const QVector & /* data */) override { + }; }; #endif // COCKATRICE_NOOP_CARD_SET_PRIORITY_CONTROLLER_H diff --git a/libcockatrice_models/libcockatrice/models/database/card/card_search_model.cpp b/libcockatrice_models/libcockatrice/models/database/card/card_search_model.cpp index d1fbbac2f..6a930c1da 100644 --- a/libcockatrice_models/libcockatrice/models/database/card/card_search_model.cpp +++ b/libcockatrice_models/libcockatrice/models/database/card/card_search_model.cpp @@ -19,9 +19,8 @@ int CardSearchModel::rowCount(const QModelIndex &parent) const QVariant CardSearchModel::data(const QModelIndex &index, int role) const { - if (!index.isValid() || index.row() >= searchResults.size()) { + if (!index.isValid() || index.row() >= searchResults.size()) return QVariant(); - } if (role == Qt::DisplayRole) { return searchResults.at(index.row()).card->getName(); @@ -35,9 +34,8 @@ void CardSearchModel::updateSearchResults(const QString &query) beginResetModel(); searchResults.clear(); - if (query.isEmpty() || !sourceModel) { + if (query.isEmpty() || !sourceModel) return; - } // Set the filter for the display model sourceModel->setCardName(query); @@ -48,15 +46,13 @@ void CardSearchModel::updateSearchResults(const QString &query) QModelIndex sourceIndex = sourceModel->mapToSource(modelIndex); CardDatabaseModel *sourceDbModel = qobject_cast(sourceModel->sourceModel()); - if (!sourceDbModel || !sourceIndex.isValid()) { + if (!sourceDbModel || !sourceIndex.isValid()) return; - } CardInfoPtr card = sourceDbModel->getCard(sourceIndex.row()); - if (!card) { + if (!card) continue; - } int distance = levenshteinDistance(query.toLower(), card->getName().toLower()); searchResults.append({card, distance}); @@ -67,9 +63,8 @@ void CardSearchModel::updateSearchResults(const QString &query) [](const SearchResult &a, const SearchResult &b) { return a.distance < b.distance; }); // Keep only the top 5 results - if (searchResults.size() > 10) { + if (searchResults.size() > 10) searchResults = searchResults.mid(0, 10); - } emit dataChanged(index(0, 0), index(rowCount() - 1, 0)); emit layoutChanged(); diff --git a/libcockatrice_models/libcockatrice/models/database/card_database_display_model.cpp b/libcockatrice_models/libcockatrice/models/database/card_database_display_model.cpp index 724ee61f2..b9c38d3d7 100644 --- a/libcockatrice_models/libcockatrice/models/database/card_database_display_model.cpp +++ b/libcockatrice_models/libcockatrice/models/database/card_database_display_model.cpp @@ -75,14 +75,12 @@ bool CardDatabaseDisplayModel::lessThan(const QModelIndex &left, const QModelInd // test for an exact match: isLeftType && leftString.size() == cardName.size() // or an exclusive start match: isLeftType && !isRightType - if (isLeftType && (!isRightType || leftString.size() == cardName.size())) { + if (isLeftType && (!isRightType || leftString.size() == cardName.size())) return true; - } // same checks for the right string - if (isRightType && (!isLeftType || rightString.size() == cardName.size())) { + if (isRightType && (!isLeftType || rightString.size() == cardName.size())) return false; - } } else if (right.column() == CardDatabaseModel::PTColumn && left.column() == CardDatabaseModel::PTColumn) { QStringList leftList = leftString.split("/"); QStringList rightList = rightString.split("/"); @@ -174,9 +172,8 @@ bool CardDatabaseDisplayModel::filterAcceptsRow(int sourceRow, const QModelIndex { CardInfoPtr info = static_cast(sourceModel())->getCard(sourceRow); - if (((isToken == ShowTrue) && !info->getIsToken()) || ((isToken == ShowFalse) && info->getIsToken())) { + if (((isToken == ShowTrue) && !info->getIsToken()) || ((isToken == ShowFalse) && info->getIsToken())) return false; - } if (filterString != nullptr) { if (filterTree != nullptr && !filterTree->acceptsCard(info)) { @@ -190,17 +187,14 @@ bool CardDatabaseDisplayModel::filterAcceptsRow(int sourceRow, const QModelIndex bool CardDatabaseDisplayModel::rowMatchesCardName(CardInfoPtr info) const { - if (!cardName.isEmpty() && !info->getName().contains(cardName, Qt::CaseInsensitive)) { + if (!cardName.isEmpty() && !info->getName().contains(cardName, Qt::CaseInsensitive)) return false; - } - if (!cardNameSet.isEmpty() && !cardNameSet.contains(info->getName())) { + if (!cardNameSet.isEmpty() && !cardNameSet.contains(info->getName())) return false; - } - if (filterTree != nullptr) { + if (filterTree != nullptr) return filterTree->acceptsCard(info); - } return true; } @@ -214,9 +208,8 @@ void CardDatabaseDisplayModel::clearFilterAll() cardText.clear(); cardTypes.clear(); cardColors.clear(); - if (filterTree != nullptr) { + if (filterTree != nullptr) filterTree->clear(); - } #if (QT_VERSION >= QT_VERSION_CHECK(6, 10, 0)) endFilterChange(QSortFilterProxyModel::Direction::Rows); #else @@ -226,9 +219,8 @@ void CardDatabaseDisplayModel::clearFilterAll() void CardDatabaseDisplayModel::setFilterTree(FilterTree *_filterTree) { - if (this->filterTree != nullptr) { + if (this->filterTree != nullptr) disconnect(this->filterTree, nullptr, this, nullptr); - } this->filterTree = _filterTree; connect(this->filterTree, &FilterTree::changed, this, &CardDatabaseDisplayModel::filterTreeChanged); diff --git a/libcockatrice_models/libcockatrice/models/database/card_database_model.cpp b/libcockatrice_models/libcockatrice/models/database/card_database_model.cpp index 253dcd134..e33156329 100644 --- a/libcockatrice_models/libcockatrice/models/database/card_database_model.cpp +++ b/libcockatrice_models/libcockatrice/models/database/card_database_model.cpp @@ -31,9 +31,8 @@ int CardDatabaseModel::columnCount(const QModelIndex & /*parent*/) const QVariant CardDatabaseModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || index.row() >= cardList.size() || index.column() >= CARDDBMODEL_COLUMNS || - (role != Qt::DisplayRole && role != SortRole)) { + (role != Qt::DisplayRole && role != SortRole)) return QVariant(); - } CardInfoPtr card = cardList.at(index.row()); switch (index.column()) { @@ -57,12 +56,10 @@ QVariant CardDatabaseModel::data(const QModelIndex &index, int role) const QVariant CardDatabaseModel::headerData(int section, Qt::Orientation orientation, int role) const { - if (role != Qt::DisplayRole) { + if (role != Qt::DisplayRole) return QVariant(); - } - if (orientation != Qt::Horizontal) { + if (orientation != Qt::Horizontal) return QVariant(); - } switch (section) { case NameColumn: return QString(tr("Name")); @@ -81,27 +78,24 @@ QVariant CardDatabaseModel::headerData(int section, Qt::Orientation orientation, } } -void CardDatabaseModel::cardInfoChanged(const CardInfoPtr &card) +void CardDatabaseModel::cardInfoChanged(CardInfoPtr card) { const int row = cardList.indexOf(card); - if (row == -1) { + if (row == -1) return; - } emit dataChanged(index(row, 0), index(row, CARDDBMODEL_COLUMNS - 1)); } -bool CardDatabaseModel::checkCardHasAtLeastOneEnabledSet(const CardInfoPtr &card) const +bool CardDatabaseModel::checkCardHasAtLeastOneEnabledSet(CardInfoPtr card) { - if (!showOnlyCardsFromEnabledSets) { + if (!showOnlyCardsFromEnabledSets) return true; - } for (const auto &printings : card->getSets()) { for (const auto &printing : printings) { - if (printing.getSet()->getEnabled()) { + if (printing.getSet()->getEnabled()) return true; - } } } @@ -125,7 +119,7 @@ void CardDatabaseModel::cardDatabaseEnabledSetsChanged() } } -void CardDatabaseModel::cardAdded(const CardInfoPtr &card) +void CardDatabaseModel::cardAdded(CardInfoPtr card) { if (checkCardHasAtLeastOneEnabledSet(card)) { // add the card if it's present in at least one enabled set diff --git a/libcockatrice_models/libcockatrice/models/database/card_database_model.h b/libcockatrice_models/libcockatrice/models/database/card_database_model.h index 8655389d7..218cfff92 100644 --- a/libcockatrice_models/libcockatrice/models/database/card_database_model.h +++ b/libcockatrice_models/libcockatrice/models/database/card_database_model.h @@ -51,11 +51,11 @@ private: CardDatabase *db; bool showOnlyCardsFromEnabledSets; - inline bool checkCardHasAtLeastOneEnabledSet(const CardInfoPtr &card) const; + inline bool checkCardHasAtLeastOneEnabledSet(CardInfoPtr card); private slots: - void cardAdded(const CardInfoPtr &card); + void cardAdded(CardInfoPtr card); void cardRemoved(CardInfoPtr card); - void cardInfoChanged(const CardInfoPtr &card); + void cardInfoChanged(CardInfoPtr card); void cardDatabaseEnabledSetsChanged(); }; diff --git a/libcockatrice_models/libcockatrice/models/database/card_set/card_sets_model.cpp b/libcockatrice_models/libcockatrice/models/database/card_set/card_sets_model.cpp index 5e0cc31d8..c0164ad75 100644 --- a/libcockatrice_models/libcockatrice/models/database/card_set/card_sets_model.cpp +++ b/libcockatrice_models/libcockatrice/models/database/card_set/card_sets_model.cpp @@ -6,9 +6,8 @@ SetsModel::SetsModel(CardDatabase *_db, QObject *parent) : QAbstractTableModel(p { sets.sortByKey(); for (const CardSetPtr &set : sets) { - if (set->getEnabled()) { + if (set->getEnabled()) enabledSets.insert(set); - } } } @@ -16,18 +15,16 @@ SetsModel::~SetsModel() = default; int SetsModel::rowCount(const QModelIndex &parent) const { - if (parent.isValid()) { + if (parent.isValid()) return 0; - } else { + else return sets.size(); - } } QVariant SetsModel::data(const QModelIndex &index, int role) const { - if (!index.isValid() || (index.column() >= NUM_COLS) || (index.row() >= rowCount())) { + if (!index.isValid() || (index.column() >= NUM_COLS) || (index.row() >= rowCount())) return QVariant(); - } CardSetPtr set = sets[index.row()]; @@ -43,9 +40,8 @@ QVariant SetsModel::data(const QModelIndex &index, int role) const } } - if (role != Qt::DisplayRole && role != SortRole) { + if (role != Qt::DisplayRole && role != SortRole) return QVariant(); - } switch (index.column()) { case SortKeyCol: @@ -76,9 +72,8 @@ bool SetsModel::setData(const QModelIndex &index, const QVariant &value, int rol QVariant SetsModel::headerData(int section, Qt::Orientation orientation, int role) const { - if ((role != Qt::DisplayRole) || (orientation != Qt::Horizontal)) { + if ((role != Qt::DisplayRole) || (orientation != Qt::Horizontal)) return QVariant(); - } switch (section) { case SortKeyCol: return QString("Key"); /* no tr() for translations needed, column just used for sorting --> hidden */ @@ -102,15 +97,13 @@ QVariant SetsModel::headerData(int section, Qt::Orientation orientation, int rol Qt::ItemFlags SetsModel::flags(const QModelIndex &index) const { - if (!index.isValid()) { + if (!index.isValid()) return Qt::NoItemFlags; - } Qt::ItemFlags flags = QAbstractTableModel::flags(index) | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; - if (index.column() == EnabledCol) { + if (index.column() == EnabledCol) flags |= Qt::ItemIsUserCheckable; - } return flags; } @@ -122,9 +115,8 @@ Qt::DropActions SetsModel::supportedDropActions() const QMimeData *SetsModel::mimeData(const QModelIndexList &indexes) const { - if (indexes.isEmpty()) { + if (indexes.isEmpty()) return 0; - } SetsMimeData *result = new SetsMimeData(indexes[0].row()); return qobject_cast(result); @@ -136,19 +128,16 @@ bool SetsModel::dropMimeData(const QMimeData *data, int /*column*/, const QModelIndex &parent) { - if (action != Qt::MoveAction) { + if (action != Qt::MoveAction) return false; - } if (row == -1) { - if (!parent.isValid()) { + if (!parent.isValid()) return false; - } row = parent.row(); } int oldRow = qobject_cast(data)->getOldRow(); - if (oldRow < row) { + if (oldRow < row) row--; - } swapRows(oldRow, row); @@ -159,11 +148,10 @@ void SetsModel::toggleRow(int row, bool enable) { CardSetPtr temp = sets.at(row); - if (enable) { + if (enable) enabledSets.insert(temp); - } else { + else enabledSets.remove(temp); - } emit dataChanged(index(row, EnabledCol), index(row, EnabledCol)); } @@ -172,15 +160,13 @@ void SetsModel::toggleRow(int row) { CardSetPtr tmp = sets.at(row); - if (tmp == nullptr) { + if (tmp == nullptr) return; - } - if (enabledSets.contains(tmp)) { + if (enabledSets.contains(tmp)) enabledSets.remove(tmp); - } else { + else enabledSets.insert(tmp); - } emit dataChanged(index(row, EnabledCol), index(row, EnabledCol)); } @@ -189,11 +175,9 @@ void SetsModel::toggleAll(bool enabled) { enabledSets.clear(); - if (enabled) { - for (CardSetPtr set : sets) { + if (enabled) + for (CardSetPtr set : sets) enabledSets.insert(set); - } - } emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1)); } @@ -224,9 +208,8 @@ void SetsModel::sort(int column, Qt::SortOrder order) int numRows = rowCount(); int row; - for (row = 0; row < numRows; ++row) { + for (row = 0; row < numRows; ++row) setMap.insert(index(row, column).data(SetsModel::SortRole).toString(), sets.at(row)); - } QList tmp = setMap.values(); sets.clear(); @@ -270,9 +253,8 @@ void SetsModel::restore(CardDatabase *db) // enabled sets enabledSets.clear(); for (const CardSetPtr &set : sets) { - if (set->getEnabled()) { + if (set->getEnabled()) enabledSets.insert(set); - } } emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1)); diff --git a/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.h b/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.h index 209ec8c42..86d36b7f9 100644 --- a/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.h +++ b/libcockatrice_models/libcockatrice/models/deck_list/deck_list_model.h @@ -89,15 +89,12 @@ static inline QString toString(Type t) static inline Type fromString(const QString &s) { - if (s == "Main Type") { + if (s == "Main Type") return MAIN_TYPE; - } - if (s == "Mana Cost") { + if (s == "Mana Cost") return MANA_COST; - } - if (s == "Colors") { + if (s == "Colors") return COLOR; - } return MAIN_TYPE; // default } } // namespace DeckListModelGroupCriteria @@ -430,9 +427,8 @@ private: template T getNode(const QModelIndex &index) const { - if (!index.isValid()) { + if (!index.isValid()) return dynamic_cast(root); - } return dynamic_cast(static_cast(index.internalPointer())); } diff --git a/libcockatrice_models/libcockatrice/models/deck_list/deck_list_sort_filter_proxy_model.cpp b/libcockatrice_models/libcockatrice/models/deck_list/deck_list_sort_filter_proxy_model.cpp index 3d433153a..0ec159737 100644 --- a/libcockatrice_models/libcockatrice/models/deck_list/deck_list_sort_filter_proxy_model.cpp +++ b/libcockatrice_models/libcockatrice/models/deck_list/deck_list_sort_filter_proxy_model.cpp @@ -29,29 +29,25 @@ bool DeckListSortFilterProxyModel::lessThan(const QModelIndex &left, const QMode QString ln = lNode->getName(); QString rn = rNode->getName(); int cmp = ln.localeAwareCompare(rn); - if (cmp != 0) { + if (cmp != 0) return cmp < 0; - } } else if (crit == "cmc") { int lc = lInfo ? lInfo->getCmc().toInt() : 0; int rc = rInfo ? rInfo->getCmc().toInt() : 0; - if (lc != rc) { + if (lc != rc) return lc < rc; - } } else if (crit == "colors") { QString lr = lInfo ? lInfo->getColors() : QString(); QString rr = rInfo ? rInfo->getColors() : QString(); int cmp = lr.localeAwareCompare(rr); - if (cmp != 0) { + if (cmp != 0) return cmp < 0; - } } else if (crit == "maintype") { QString lr = lInfo ? lInfo->getMainCardType() : QString(); QString rr = rInfo ? rInfo->getMainCardType() : QString(); int cmp = lr.localeAwareCompare(rr); - if (cmp != 0) { + if (cmp != 0) return cmp < 0; - } } } diff --git a/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_player.cpp b/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_player.cpp index 157fa6441..100a4ebc6 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_player.cpp +++ b/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_player.cpp @@ -81,6 +81,17 @@ int Server_AbstractPlayer::newCardId() return nextCardId++; } +int Server_AbstractPlayer::newArrowId() const +{ + int id = 0; + for (Server_Arrow *a : arrows) { + if (a->getId() > id) { + id = a->getId(); + } + } + return id + 1; +} + void Server_AbstractPlayer::setupZones() { nextCardId = 0; @@ -386,9 +397,6 @@ void Server_AbstractPlayer::processMoveCard(GameEventStorage &ges, } } for (int j : arrowsToDelete) { - Event_DeleteArrow event; - event.set_arrow_id(j); - ges.enqueueGameEvent(event, player->getPlayerId()); player->deleteArrow(j); } } @@ -1124,18 +1132,12 @@ Server_AbstractPlayer::cmdCreateToken(const Command_CreateToken &cmd, ResponseCo targetItem = card; } if (sendGameEvent) { - const int oldId = arrow->getId(); - changedArrowIds.append(oldId); - - Event_DeleteArrow deleteEvent; - deleteEvent.set_arrow_id(oldId); - ges.enqueueGameEvent(deleteEvent, player->getPlayerId()); - - Event_CreateArrow createEvent; - ServerInfo_Arrow *arrowInfo = createEvent.mutable_arrow_info(); - const int newId = game->generateArrowId(); - arrow->setId(newId); - arrowInfo->set_id(newId); + Event_CreateArrow _event; + ServerInfo_Arrow *arrowInfo = _event.mutable_arrow_info(); + changedArrowIds.append(arrow->getId()); + int id = player->newArrowId(); + arrow->setId(id); + arrowInfo->set_id(id); arrowInfo->set_start_player_id(player->getPlayerId()); arrowInfo->set_start_zone(startCard->getZone()->getName().toStdString()); arrowInfo->set_start_card_id(startCard->getId()); @@ -1149,7 +1151,7 @@ Server_AbstractPlayer::cmdCreateToken(const Command_CreateToken &cmd, ResponseCo arrowInfo->set_target_card_id(arrowTargetCard->getId()); } arrowInfo->mutable_arrow_color()->CopyFrom(arrow->getColor()); - ges.enqueueGameEvent(createEvent, player->getPlayerId()); + ges.enqueueGameEvent(_event, player->getPlayerId()); } } for (int id : changedArrowIds) { @@ -1256,8 +1258,7 @@ Server_AbstractPlayer::cmdCreateArrow(const Command_CreateArrow &cmd, ResponseCo int currentPhase = game->getActivePhase(); int deletionPhase = cmd.has_delete_in_phase() ? cmd.delete_in_phase() : currentPhase; - auto arrow = new Server_Arrow(game->generateArrowId(), startCard, targetItem, cmd.arrow_color(), currentPhase, - deletionPhase); + auto arrow = new Server_Arrow(newArrowId(), startCard, targetItem, cmd.arrow_color(), currentPhase, deletionPhase); addArrow(arrow); Event_CreateArrow event; diff --git a/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_player.h b/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_player.h index 85fbc0557..9d9809298 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_player.h +++ b/libcockatrice_network/libcockatrice/network/server/remote/game/server_abstract_player.h @@ -74,6 +74,7 @@ public: } int newCardId(); + int newArrowId() const; void addZone(Server_CardZone *zone); void addArrow(Server_Arrow *arrow); diff --git a/libcockatrice_network/libcockatrice/network/server/remote/game/server_game.cpp b/libcockatrice_network/libcockatrice/network/server/remote/game/server_game.cpp index 4761199e5..50fff4812 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/game/server_game.cpp +++ b/libcockatrice_network/libcockatrice/network/server/remote/game/server_game.cpp @@ -697,11 +697,6 @@ void Server_Game::setActivePhase(int newPhase) sendGameEventContainer(prepareGameEvent(event, -1)); } -qint64 Server_Game::generateArrowId() -{ - return nextArrowId++; -} - void Server_Game::removeArrows(int newPhase, bool force) { QMutexLocker locker(&gameMutex); diff --git a/libcockatrice_network/libcockatrice/network/server/remote/game/server_game.h b/libcockatrice_network/libcockatrice/network/server/remote/game/server_game.h index e0e7896b7..1c658f2ba 100644 --- a/libcockatrice_network/libcockatrice/network/server/remote/game/server_game.h +++ b/libcockatrice_network/libcockatrice/network/server/remote/game/server_game.h @@ -49,7 +49,6 @@ class Server_Game : public QObject private: Server_Room *room; int nextPlayerId; - std::atomic nextArrowId = 1; int hostId; ServerInfo_User *creatorInfo; QMap participants; @@ -197,7 +196,6 @@ public: } void setActivePlayer(int newPlayer); void setActivePhase(int newPhase); - qint64 generateArrowId(); void removeArrows(int newPhase, bool force = false); void nextTurn(); int getSecondsElapsed() const diff --git a/libcockatrice_utility/libcockatrice/utility/days_years_between.h b/libcockatrice_utility/libcockatrice/utility/days_years_between.h deleted file mode 100644 index c0f5da23a..000000000 --- a/libcockatrice_utility/libcockatrice/utility/days_years_between.h +++ /dev/null @@ -1,8 +0,0 @@ -#include - -inline static QPair getDaysAndYearsBetween(const QDate &then, const QDate &now) -{ - int years = now.addDays(1 - then.dayOfYear()).year() - then.year(); // there is no yearsTo - int days = then.addYears(years).daysTo(now); - return {days, years}; -} diff --git a/oracle/src/pagetemplates.h b/oracle/src/pagetemplates.h index 6e79c867e..79dcdd632 100644 --- a/oracle/src/pagetemplates.h +++ b/oracle/src/pagetemplates.h @@ -27,7 +27,7 @@ protected: inline OracleWizard *wizard() { return (OracleWizard *)QWizardPage::wizard(); - } + }; }; class SimpleDownloadFilePage : public OracleWizardPage diff --git a/oracle/translations/oracle_es.ts b/oracle/translations/oracle_es.ts index 33dbbdc3a..eeb9f71bd 100644 --- a/oracle/translations/oracle_es.ts +++ b/oracle/translations/oracle_es.ts @@ -63,7 +63,7 @@ Sets file (%1) Sets JSON file (%1) - Archivo de ediciones (%1) + @@ -172,7 +172,7 @@ spoiler - spoiler + @@ -192,7 +192,7 @@ Local file: - Archivo local: + @@ -202,7 +202,7 @@ Choose file... - Elegir archivo... + @@ -230,7 +230,7 @@ tokens - fichas + @@ -250,7 +250,7 @@ Local file: - Archivo local: + @@ -260,7 +260,7 @@ Choose file... - Elegir archivo... + @@ -391,12 +391,12 @@ Load %1 file - Cargar archivo de %1 + %1 file (%1) - archivo de %1 (%1) + @@ -420,12 +420,12 @@ Please choose a file. - Por favor elija un archivo. + Cannot open file '%1'. - No se puede abrir el archivo '%1'. + @@ -602,7 +602,7 @@ Run in no-confirm background mode - Ejecutar en modo del segundo plano sin confirmación + \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 04ac7fcee..00eba288e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -59,9 +59,7 @@ endif() include_directories(${GTEST_INCLUDE_DIRS}) target_link_libraries(dummy_test Threads::Threads ${GTEST_BOTH_LIBRARIES}) target_link_libraries(expression_test libcockatrice_utility Threads::Threads ${GTEST_BOTH_LIBRARIES} ${TEST_QT_MODULES}) -target_link_libraries( - test_age_formatting libcockatrice_utility Threads::Threads ${GTEST_BOTH_LIBRARIES} ${TEST_QT_MODULES} -) +target_link_libraries(test_age_formatting Threads::Threads ${GTEST_BOTH_LIBRARIES} ${TEST_QT_MODULES}) target_link_libraries( password_hash_test libcockatrice_utility Threads::Threads ${GTEST_BOTH_LIBRARIES} ${TEST_QT_MODULES} ) diff --git a/tests/test_age_formatting.cpp b/tests/test_age_formatting.cpp index 6a9d5d4af..e4fc64cf9 100644 --- a/tests/test_age_formatting.cpp +++ b/tests/test_age_formatting.cpp @@ -1,5 +1,6 @@ +#include "../cockatrice/src/interface/widgets/server/user/user_info_box.h" + #include "gtest/gtest.h" -#include namespace { @@ -7,31 +8,31 @@ using dayyear = QPair; TEST(AgeFormatting, Zero) { - auto got = getDaysAndYearsBetween(QDate(2000, 1, 1), QDate(2000, 1, 1)); + auto got = UserInfoBox::getDaysAndYearsBetween(QDate(2000, 1, 1), QDate(2000, 1, 1)); ASSERT_EQ(got, dayyear(0, 0)) << "these are the same day"; } TEST(AgeFormatting, LeapDay) { - auto got = getDaysAndYearsBetween(QDate(2000, 2, 28), QDate(2000, 3, 1)); + auto got = UserInfoBox::getDaysAndYearsBetween(QDate(2000, 2, 28), QDate(2000, 3, 1)); ASSERT_EQ(got, dayyear(2, 0)) << "there is a leap day in between these days"; } TEST(AgeFormatting, LeapYear) { - auto got = getDaysAndYearsBetween(QDate(2000, 1, 1), QDate(2001, 1, 1)); + auto got = UserInfoBox::getDaysAndYearsBetween(QDate(2000, 1, 1), QDate(2001, 1, 1)); ASSERT_EQ(got, dayyear(0, 1)) << "there is a leap day in between these dates, but that's fine"; } TEST(AgeFormatting, LeapDayWithYear) { - auto got = getDaysAndYearsBetween(QDate(2000, 2, 28), QDate(2001, 3, 1)); + auto got = UserInfoBox::getDaysAndYearsBetween(QDate(2000, 2, 28), QDate(2001, 3, 1)); ASSERT_EQ(got, dayyear(1, 1)) << "there is a leap day in between these days but not in the last year"; } TEST(AgeFormatting, LeapDayThisYear) { - auto got = getDaysAndYearsBetween(QDate(2003, 2, 28), QDate(2004, 3, 1)); + auto got = UserInfoBox::getDaysAndYearsBetween(QDate(2003, 2, 28), QDate(2004, 3, 1)); ASSERT_EQ(got, dayyear(2, 1)) << "there is a leap day in between these days this year"; } } // namespace