mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-09-24 10:23:02 -07:00
Compare commits
6 commits
89ef10c862
...
779b4d2c95
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
779b4d2c95 | ||
|
|
0155d2b2bc | ||
|
|
96b331746b | ||
|
|
7d6d625ed4 | ||
|
|
e9e3515628 | ||
|
|
7168802bbf |
641 changed files with 49630 additions and 83492 deletions
|
|
@ -159,7 +159,6 @@ if [[ $PACKAGE_TYPE ]]; then
|
|||
fi
|
||||
if [[ $USE_VCPKG ]]; then
|
||||
flags+=("-DUSE_VCPKG=1")
|
||||
flags+=("-DVCPKG_INSTALL_OPTIONS=--x-abi-tools-use-exact-versions")
|
||||
fi
|
||||
|
||||
# Add cmake --build flags
|
||||
|
|
|
|||
|
|
@ -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 <<EOM
|
||||
|
|
@ -28,10 +36,19 @@ case $err in
|
|||
*** Then commit and push those changes to this branch. ***
|
||||
*** Check our CONTRIBUTING.md file for more details. ***
|
||||
*** ***
|
||||
*** Thank you ❤️ ***
|
||||
*** Thank you ❤️ ***
|
||||
*** ***
|
||||
***********************************************************
|
||||
|
||||
Used version:
|
||||
$used_version
|
||||
|
||||
Affected files:
|
||||
$files_to_edit
|
||||
|
||||
The following changes should be made:
|
||||
$changes_to_make
|
||||
|
||||
Exiting...
|
||||
EOM
|
||||
exit 2
|
||||
|
|
@ -48,6 +65,9 @@ EOM
|
|||
*** ***
|
||||
***********************************************************
|
||||
|
||||
Used version:
|
||||
$used_version
|
||||
|
||||
Exiting...
|
||||
EOM
|
||||
exit 0
|
||||
|
|
|
|||
5
.codacy.yml
Normal file
5
.codacy.yml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
exclude_paths:
|
||||
- '**/translations/*.ts'
|
||||
|
||||
# codacy config documentation: https://support.codacy.com/hc/en-us/articles/115002130625-Codacy-Configuration-File
|
||||
2
.github/CONTRIBUTING.md
vendored
2
.github/CONTRIBUTING.md
vendored
|
|
@ -334,7 +334,7 @@ the tr() call, also you can add an extra string as a hint for translators:
|
|||
QString message = tr("Everyone draws %n cards", "english hint for translators", amount);
|
||||
```
|
||||
See [Qt's wiki on translations](
|
||||
https://doc.qt.io/qt-6/i18n-source-translation.html#handling-plurals)
|
||||
https://doc.qt.io/qt-5/i18n-source-translation.html#handling-plurals)
|
||||
|
||||
If you're about to propose a change that adds or modifies any translatable
|
||||
string in the code, you don't need to take care of adding the new strings to
|
||||
|
|
|
|||
402
.github/workflows/desktop-build.yml
vendored
402
.github/workflows/desktop-build.yml
vendored
|
|
@ -1,10 +1,10 @@
|
|||
name: Build Desktop
|
||||
|
||||
permissions:
|
||||
actions: write # needed to delete entries in GHA cache (update ccache)
|
||||
attestations: write # needed to persist the attestation.
|
||||
contents: write
|
||||
id-token: write # needed for signing certificate in attestation
|
||||
id-token: write
|
||||
attestations: write
|
||||
actions: write # needed for ccache action to be able to delete gha caches
|
||||
|
||||
on:
|
||||
push:
|
||||
|
|
@ -19,7 +19,7 @@ on:
|
|||
- '.github/workflows/desktop-build.yml'
|
||||
- 'CMakeLists.txt'
|
||||
- 'vcpkg.json'
|
||||
- 'vcpkg' # needed to match submodule bumps (gitlink)
|
||||
- 'vcpkg'
|
||||
tags:
|
||||
- '*'
|
||||
pull_request:
|
||||
|
|
@ -32,7 +32,7 @@ on:
|
|||
- '.github/workflows/desktop-build.yml'
|
||||
- 'CMakeLists.txt'
|
||||
- 'vcpkg.json'
|
||||
- 'vcpkg' # needed to match submodule bumps (gitlink)
|
||||
- 'vcpkg'
|
||||
|
||||
# Cancel earlier, unfinished runs of this workflow on the same branch (unless on release)
|
||||
concurrency:
|
||||
|
|
@ -44,217 +44,216 @@ jobs:
|
|||
name: Configure
|
||||
runs-on: ubuntu-slim
|
||||
outputs:
|
||||
tag: ${{ steps.configure.outputs.tag }}
|
||||
sha: ${{ steps.configure.outputs.sha }}
|
||||
tag: ${{steps.configure.outputs.tag}}
|
||||
sha: ${{steps.configure.outputs.sha}}
|
||||
|
||||
steps:
|
||||
- name: "Configure"
|
||||
env:
|
||||
RESOLVED_SHA: ${{ case(github.event_name == 'pull_request', github.event.pull_request.head.sha, github.sha) }}
|
||||
steps:
|
||||
- name: Configure
|
||||
id: configure
|
||||
shell: bash
|
||||
run: |
|
||||
if [[ "$GITHUB_REF_TYPE" == 'tag' ]]; then # release
|
||||
echo "tag=$GITHUB_REF_NAME" >> "$GITHUB_OUTPUT"
|
||||
tag_regex='^refs/tags/'
|
||||
if [[ $GITHUB_EVENT_NAME == pull-request ]]; then # pull request
|
||||
sha="${{github.event.pull_request.head.sha}}"
|
||||
elif [[ $GITHUB_REF =~ $tag_regex ]]; then # release
|
||||
sha="$GITHUB_SHA"
|
||||
tag="${GITHUB_REF/refs\/tags\//}"
|
||||
echo "tag=$tag" >>"$GITHUB_OUTPUT"
|
||||
else # push to branch
|
||||
sha="$GITHUB_SHA"
|
||||
fi
|
||||
echo "sha=$RESOLVED_SHA" >> "$GITHUB_OUTPUT"
|
||||
echo "sha=$sha" >>"$GITHUB_OUTPUT"
|
||||
|
||||
- name: "Checkout"
|
||||
- name: Checkout
|
||||
if: steps.configure.outputs.tag != null
|
||||
uses: actions/checkout@v7
|
||||
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"
|
||||
uses: actions/checkout@v7
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: "Restore compiler cache (ccache)"
|
||||
- name: Restore compiler cache (ccache)
|
||||
id: ccache_restore
|
||||
uses: actions/cache/restore@v6
|
||||
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:
|
||||
CACHE_PRIMARY_KEY: ${{ steps.ccache_restore.outputs.cache-primary-key }}
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
if gh cache delete --repo "$GITHUB_REPOSITORY" "$CACHE_PRIMARY_KEY"; then
|
||||
if gh cache delete --repo ${{ github.repository }} ${{ steps.ccache_restore.outputs.cache-primary-key }}; then
|
||||
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@v6
|
||||
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:
|
||||
BUILD_PATH: ${{ steps.build.outputs.path }}
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: gh attestation verify "$BUILD_PATH" --repo Cockatrice/Cockatrice
|
||||
GH_TOKEN: ${{github.token}}
|
||||
run: gh attestation verify "${{steps.build.outputs.path}}" --repo Cockatrice/Cockatrice
|
||||
|
||||
build-vcpkg:
|
||||
strategy:
|
||||
|
|
@ -264,234 +263,234 @@ 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
|
||||
qt_version: 6.11.0
|
||||
qt_modules: qtimageformats qtmultimedia qtwebsockets
|
||||
soc: Apple
|
||||
type: Debug
|
||||
use_ccache: 1
|
||||
xcode: "16.4"
|
||||
type: Debug
|
||||
qt_version: 6.11.0
|
||||
qt_arch: clang_64
|
||||
qt_modules: qtimageformats qtmultimedia qtwebsockets
|
||||
cmake_generator: Ninja
|
||||
use_ccache: 1
|
||||
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"
|
||||
uses: actions/checkout@v7
|
||||
- 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@v6
|
||||
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"
|
||||
env:
|
||||
QT_VERSION: ${{ matrix.qt_version }}
|
||||
- name: Resolve latest Qt patch version
|
||||
id: resolve_qt_version
|
||||
shell: bash
|
||||
run: .ci/resolve_latest_aqt_qt_version.sh "$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@v6
|
||||
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:
|
||||
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@v6
|
||||
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
|
||||
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:
|
||||
CACHE_PRIMARY_KEY: ${{ steps.ccache_restore.outputs.cache-primary-key }}
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
if gh cache delete --repo "$GITHUB_REPOSITORY" "$CACHE_PRIMARY_KEY"; then
|
||||
if gh cache delete --repo ${{ github.repository }} ${{ steps.ccache_restore.outputs.cache-primary-key }}; then
|
||||
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'
|
||||
uses: actions/cache/save@v6
|
||||
- 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:
|
||||
BUILD_PATH: ${{ steps.build.outputs.path }}
|
||||
MACOS_CERTIFICATE_NAME: ${{ secrets.PROD_MACOS_CERTIFICATE_NAME }}
|
||||
MACOS_CI_KEYCHAIN_PWD: ${{ secrets.PROD_MACOS_CI_KEYCHAIN_PWD }}
|
||||
run: |
|
||||
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 "$BUILD_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:
|
||||
BUILD_PATH: ${{ steps.build.outputs.path }}
|
||||
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
|
||||
|
|
@ -503,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 "$BUILD_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
|
||||
|
|
@ -515,52 +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 "$BUILD_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:
|
||||
BUILD_PATH: ${{ steps.build.outputs.path }}
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: gh attestation verify "$BUILD_PATH" --repo Cockatrice/Cockatrice
|
||||
GH_TOKEN: ${{github.token}}
|
||||
run: gh attestation verify "${{steps.build.outputs.path}}" --repo Cockatrice/Cockatrice
|
||||
|
|
|
|||
15
.github/workflows/desktop-lint.yml
vendored
15
.github/workflows/desktop-lint.yml
vendored
|
|
@ -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"
|
||||
uses: actions/checkout@v7
|
||||
- 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
|
||||
|
|
|
|||
51
.github/workflows/docker-release.yml
vendored
51
.github/workflows/docker-release.yml
vendored
|
|
@ -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,51 +24,54 @@ jobs:
|
|||
name: amd64 & arm64
|
||||
if: ${{ github.repository_owner == 'Cockatrice' }}
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: "Checkout"
|
||||
uses: actions/checkout@v7
|
||||
- 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 (GHCR)"
|
||||
if: github.event_name == 'release' && github.event.release.prerelease == false
|
||||
id: login
|
||||
- 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:
|
||||
context: .
|
||||
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
|
||||
context: .
|
||||
labels: ${{ steps.metadata.outputs.labels }}
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: ${{ steps.login.outcome == 'success' }}
|
||||
tags: ${{ steps.metadata.outputs.tags }}
|
||||
|
|
|
|||
24
.github/workflows/documentation-build.yml
vendored
24
.github/workflows/documentation-build.yml
vendored
|
|
@ -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"
|
||||
uses: actions/checkout@v7
|
||||
- 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/
|
||||
|
|
|
|||
55
.github/workflows/translations-pull.yml
vendored
55
.github/workflows/translations-pull.yml
vendored
|
|
@ -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,20 +19,18 @@ jobs:
|
|||
runs-on: ubuntu-slim
|
||||
|
||||
steps:
|
||||
- name: "Checkout repo"
|
||||
uses: actions/checkout@v7
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: "Pull translated strings from Transifex"
|
||||
# Do not run this step for PR's from forks, they don't have access to the secret
|
||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false
|
||||
- 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
|
||||
|
|
@ -40,32 +38,35 @@ jobs:
|
|||
add-paths: |
|
||||
cockatrice/translations/*.ts
|
||||
oracle/translations/*.ts
|
||||
author: github-actions <github-actions@github.com> # owner of the commit
|
||||
commit-message: Update translation files
|
||||
# author is the owner of the commit
|
||||
author: github-actions <github-actions@github.com>
|
||||
branch: ci-update_translations
|
||||
delete-branch: true
|
||||
title: 'Update translations'
|
||||
body: |
|
||||
Pulled all translated strings from [Transifex][1].
|
||||
|
||||
|
||||
---
|
||||
*This PR is automatically generated and updated by the workflow at `.github/workflows/translations-pull.yml`. Review [action runs][2].*<br>
|
||||
*After merging, all new languages and translations are available in the next build.*
|
||||
|
||||
|
||||
[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:
|
||||
PR_NUMBER: ${{ steps.create_pr.outputs.pull-request-number }}
|
||||
PR_URL: ${{ steps.create_pr.outputs.pull-request-url }}
|
||||
STATUS: ${{ case(steps.create_pr.outputs.pull-request-operation == 'none', 'unchanged', steps.create_pr.outputs.pull-request-operation) }}
|
||||
STATUS: ${{ steps.create_pr.outputs.pull-request-operation }}
|
||||
run: |
|
||||
echo "PR #$PR_NUMBER $STATUS!" >> "$GITHUB_STEP_SUMMARY"
|
||||
echo "URL: $PR_URL" >> "$GITHUB_STEP_SUMMARY"
|
||||
if [[ "$STATUS" == "none" ]]; then
|
||||
echo "PR #${{ steps.create_pr.outputs.pull-request-number }} unchanged!" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "PR #${{ steps.create_pr.outputs.pull-request-number }} $STATUS!" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
echo "URL: ${{ steps.create_pr.outputs.pull-request-url }}" >> $GITHUB_STEP_SUMMARY
|
||||
|
|
|
|||
58
.github/workflows/translations-push.yml
vendored
58
.github/workflows/translations-push.yml
vendored
|
|
@ -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,33 +19,32 @@ jobs:
|
|||
runs-on: ubuntu-slim
|
||||
|
||||
steps:
|
||||
- name: "Checkout repo"
|
||||
uses: actions/checkout@v7
|
||||
- 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"
|
||||
env:
|
||||
FILE: cockatrice/cockatrice_en@source.ts
|
||||
- name: Update Cockatrice translation source
|
||||
id: cockatrice
|
||||
shell: bash
|
||||
run: >
|
||||
DIRS="cockatrice/src $(find . -maxdepth 1 -type d -name 'libcockatrice_*')"
|
||||
.ci/update_translation_source_strings.sh
|
||||
run: |
|
||||
FILE="cockatrice/cockatrice_en@source.ts"
|
||||
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:
|
||||
|
|
@ -55,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
|
||||
|
|
@ -63,24 +62,27 @@ jobs:
|
|||
add-paths: |
|
||||
cockatrice/cockatrice_en@source.ts
|
||||
oracle/oracle_en@source.ts
|
||||
author: github-actions <github-actions@github.com> # 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 <github-actions@github.com>
|
||||
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:
|
||||
PR_NUMBER: ${{ steps.create_pr.outputs.pull-request-number }}
|
||||
PR_URL: ${{ steps.create_pr.outputs.pull-request-url }}
|
||||
STATUS: ${{ case(steps.create_pr.outputs.pull-request-operation == 'none', 'unchanged', steps.create_pr.outputs.pull-request-operation) }}
|
||||
STATUS: ${{ steps.create_pr.outputs.pull-request-operation }}
|
||||
run: |
|
||||
echo "PR #$PR_NUMBER $STATUS!" >> "$GITHUB_STEP_SUMMARY"
|
||||
echo "URL: $PR_URL" >> "$GITHUB_STEP_SUMMARY"
|
||||
if [[ "$STATUS" == "none" ]]; then
|
||||
echo "PR #${{ steps.create_pr.outputs.pull-request-number }} unchanged!" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "PR #${{ steps.create_pr.outputs.pull-request-number }} $STATUS!" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
echo "URL: ${{ steps.create_pr.outputs.pull-request-url }}" >> $GITHUB_STEP_SUMMARY
|
||||
|
|
|
|||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -6,7 +6,6 @@ mysql.cnf
|
|||
.DS_Store
|
||||
.idea/
|
||||
*.aps
|
||||
*.cache
|
||||
cmake-build*
|
||||
preferences
|
||||
compile_commands.json
|
||||
|
|
|
|||
|
|
@ -64,11 +64,10 @@ if(WIN32 OR USE_VCPKG)
|
|||
else()
|
||||
set(QTDIR
|
||||
""
|
||||
CACHE PATH "Path to Qt (e.g. C:/Qt/6.4.2/msvc2019_64)"
|
||||
CACHE PATH "Path to Qt (e.g. C:/Qt/5.7/msvc2015_64)"
|
||||
)
|
||||
message(
|
||||
WARNING
|
||||
"QTDIR variable is missing. Please set this variable to specify path to Qt (e.g. C:/Qt/6.4.2/msvc2019_64)"
|
||||
WARNING "QTDIR variable is missing. Please set this variable to specify path to Qt (e.g. C:/Qt/5.7/msvc2015_64)"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
|
@ -175,7 +174,7 @@ elseif(CMAKE_COMPILER_IS_GNUCXX)
|
|||
-Wno-error=delete-non-virtual-dtor
|
||||
-Wno-error=sign-compare
|
||||
-Wno-error=missing-declarations
|
||||
-Wno-error=sfinae-incomplete # GCC 16+: Qt MOC + protobuf forward decls trigger this
|
||||
-Wno-error=sfinae-incomplete # GCC 16+: Qt MOC + protobuf forward decls trigger this
|
||||
)
|
||||
|
||||
foreach(FLAG ${ADDITIONAL_DEBUG_FLAGS})
|
||||
|
|
@ -281,7 +280,11 @@ if(UNIX)
|
|||
if(CPACK_GENERATOR STREQUAL "RPM")
|
||||
set(CPACK_RPM_PACKAGE_LICENSE "GPLv2")
|
||||
set(CPACK_RPM_MAIN_COMPONENT "cockatrice")
|
||||
set(CPACK_RPM_PACKAGE_REQUIRES "protobuf, qt6-qttools, qt6-qtsvg, qt6-qtmultimedia, qt6-qtimageformats")
|
||||
if(Qt6_FOUND)
|
||||
set(CPACK_RPM_PACKAGE_REQUIRES "protobuf, qt6-qttools, qt6-qtsvg, qt6-qtmultimedia, qt6-qtimageformats")
|
||||
elseif(Qt5_FOUND)
|
||||
set(CPACK_RPM_PACKAGE_REQUIRES "protobuf, qt5-qttools, qt5-qtsvg, qt5-qtmultimedia")
|
||||
endif()
|
||||
set(CPACK_RPM_PACKAGE_GROUP "Amusements/Games")
|
||||
set(CPACK_RPM_PACKAGE_URL "http://github.com/Cockatrice/Cockatrice")
|
||||
# stop directories from making package conflicts
|
||||
|
|
@ -299,8 +302,12 @@ if(UNIX)
|
|||
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
|
||||
set(CPACK_DEBIAN_PACKAGE_SECTION "games")
|
||||
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "http://github.com/Cockatrice/Cockatrice")
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt6multimedia6, libqt6svg6, qt6-qpa-plugins, qt6-image-formats-plugins")
|
||||
set(CPACK_DEBIAN_PACKAGE_RECOMMENDS "libqt6sql6-mysql") # for connecting servatrice to a mysql db
|
||||
if(Qt6_FOUND)
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt6multimedia6, libqt6svg6, qt6-qpa-plugins, qt6-image-formats-plugins")
|
||||
set(CPACK_DEBIAN_PACKAGE_RECOMMENDS "libqt6sql6-mysql") # for connecting servatrice to a mysql db
|
||||
elseif(Qt5_FOUND)
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt5multimedia5-plugins, libqt5svg5")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
elseif(WIN32)
|
||||
|
|
|
|||
8
Doxyfile
8
Doxyfile
|
|
@ -349,7 +349,7 @@ OPTIMIZE_OUTPUT_SLICE = NO
|
|||
#
|
||||
# Note see also the list of default file extension mappings.
|
||||
|
||||
EXTENSION_MAPPING = proto=C++
|
||||
EXTENSION_MAPPING =
|
||||
|
||||
# If the MARKDOWN_SUPPORT tag is enabled then Doxygen pre-processes all comments
|
||||
# according to the Markdown format, which allows for more readable
|
||||
|
|
@ -1086,8 +1086,7 @@ FILE_PATTERNS = *.cc \
|
|||
*.h++ \
|
||||
*.markdown \
|
||||
*.md \
|
||||
*.dox \
|
||||
*.proto
|
||||
*.dox
|
||||
|
||||
# The RECURSIVE tag can be used to specify whether or not subdirectories should
|
||||
# be searched for input files as well.
|
||||
|
|
@ -1104,7 +1103,6 @@ RECURSIVE = YES
|
|||
|
||||
EXCLUDE = build/ \
|
||||
cmake/ \
|
||||
cmake-build-debug/ \
|
||||
doc/doxygen/theme/docs/ \
|
||||
doc/doxygen/theme/include/ \
|
||||
vcpkg/
|
||||
|
|
@ -1197,7 +1195,7 @@ INPUT_FILTER =
|
|||
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
|
||||
# properly processed by Doxygen.
|
||||
|
||||
FILTER_PATTERNS = "*.proto=python doc/doxygen/filters/proto2cpp.py"
|
||||
FILTER_PATTERNS =
|
||||
|
||||
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
|
||||
# INPUT_FILTER) will also be used to filter the input files that are used for
|
||||
|
|
|
|||
|
|
@ -158,6 +158,7 @@ The following flags (with their non-default values) can be passed to `cmake`:
|
|||
| `-DWARNING_AS_ERROR=0` | Don't treat compilation warnings as errors in debug mode |
|
||||
| `-DUPDATE_TRANSLATIONS=1` | Configure `make` to update the translation .ts files for new strings in the source code<br> **Note:** `make clean` will remove the .ts files |
|
||||
| `-DTEST=1` | Enable regression tests<br> **Note:** `make test` to run tests, *googletest* will be downloaded if not available |
|
||||
| `-DFORCE_USE_QT5=1` | Skip looking for Qt6 before trying to find Qt5 |
|
||||
|
||||
|
||||
# Run
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
# Find a compatible Qt version
|
||||
# Inputs: WITH_SERVER, WITH_CLIENT, WITH_ORACLE
|
||||
# Inputs: WITH_SERVER, WITH_CLIENT, WITH_ORACLE, FORCE_USE_QT5
|
||||
# Optional Input: QT6_DIR -- Hint as to where Qt6 lives on the system
|
||||
# Output: COCKATRICE_QT_VERSION_NAME -- Example values: Qt6
|
||||
# Optional Input: QT5_DIR -- Hint as to where Qt5 lives on the system
|
||||
# Output: COCKATRICE_QT_VERSION_NAME -- Example values: Qt5, Qt6
|
||||
# Output: SERVATRICE_QT_MODULES
|
||||
# Output: COCKATRICE_QT_MODULES
|
||||
# Output: ORACLE_QT_MODULES
|
||||
|
|
@ -38,37 +39,69 @@ set(REQUIRED_QT_COMPONENTS ${REQUIRED_QT_COMPONENTS} ${_SERVATRICE_NEEDED} ${_CO
|
|||
)
|
||||
list(REMOVE_DUPLICATES REQUIRED_QT_COMPONENTS)
|
||||
|
||||
# Linguist is now a component in Qt6 instead of an external package
|
||||
find_package(
|
||||
Qt6 6.4.2
|
||||
COMPONENTS ${REQUIRED_QT_COMPONENTS} Linguist
|
||||
QUIET HINTS ${Qt6_DIR}
|
||||
)
|
||||
if(NOT Qt6_FOUND)
|
||||
message(FATAL_ERROR "No suitable version of Qt was found")
|
||||
if(NOT FORCE_USE_QT5)
|
||||
# Linguist is now a component in Qt6 instead of an external package
|
||||
find_package(
|
||||
Qt6 6.4.2
|
||||
COMPONENTS ${REQUIRED_QT_COMPONENTS} Linguist
|
||||
QUIET HINTS ${Qt6_DIR}
|
||||
)
|
||||
endif()
|
||||
set(COCKATRICE_QT_VERSION_NAME Qt6)
|
||||
if(Qt6_FOUND)
|
||||
set(COCKATRICE_QT_VERSION_NAME Qt6)
|
||||
|
||||
list(FIND Qt6LinguistTools_TARGETS Qt6::lrelease QT6_LRELEASE_INDEX)
|
||||
if(QT6_LRELEASE_INDEX EQUAL -1)
|
||||
message(WARNING "Qt6 lrelease not found.")
|
||||
list(FIND Qt6LinguistTools_TARGETS Qt6::lrelease QT6_LRELEASE_INDEX)
|
||||
if(QT6_LRELEASE_INDEX EQUAL -1)
|
||||
message(WARNING "Qt6 lrelease not found.")
|
||||
endif()
|
||||
|
||||
list(FIND Qt6LinguistTools_TARGETS Qt6::lupdate QT6_LUPDATE_INDEX)
|
||||
if(QT6_LUPDATE_INDEX EQUAL -1)
|
||||
message(WARNING "Qt6 lupdate not found.")
|
||||
endif()
|
||||
else()
|
||||
find_package(
|
||||
Qt5 5.15.2
|
||||
COMPONENTS ${REQUIRED_QT_COMPONENTS}
|
||||
QUIET HINTS ${Qt5_DIR}
|
||||
)
|
||||
if(Qt5_FOUND)
|
||||
set(COCKATRICE_QT_VERSION_NAME Qt5)
|
||||
else()
|
||||
message(FATAL_ERROR "No suitable version of Qt was found")
|
||||
endif()
|
||||
|
||||
# Qt5 Linguist is in a separate package
|
||||
find_package(Qt5LinguistTools QUIET)
|
||||
if(Qt5LinguistTools_FOUND)
|
||||
if(NOT Qt5_LRELEASE_EXECUTABLE)
|
||||
message(WARNING "Qt5 lrelease not found.")
|
||||
endif()
|
||||
if(NOT Qt5_LUPDATE_EXECUTABLE)
|
||||
message(WARNING "Qt5 lupdate not found.")
|
||||
endif()
|
||||
else()
|
||||
message(WARNING "Linguist Tools not found, cannot handle translations")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
list(FIND Qt6LinguistTools_TARGETS Qt6::lupdate QT6_LUPDATE_INDEX)
|
||||
if(QT6_LUPDATE_INDEX EQUAL -1)
|
||||
message(WARNING "Qt6 lupdate not found.")
|
||||
if(Qt5_POSITION_INDEPENDENT_CODE OR Qt6_FOUND)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
endif()
|
||||
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
# Establish Qt Plugins directory & Library directories
|
||||
get_target_property(QT_LIBRARY_DIR ${COCKATRICE_QT_VERSION_NAME}::Core LOCATION)
|
||||
get_filename_component(QT_LIBRARY_DIR ${QT_LIBRARY_DIR} DIRECTORY)
|
||||
get_filename_component(QT_PLUGINS_DIR "${Qt6Core_DIR}/../../../${QT6_INSTALL_PLUGINS}" ABSOLUTE)
|
||||
get_filename_component(QT_LIBRARY_DIR "${QT_LIBRARY_DIR}/../../.." ABSOLUTE)
|
||||
if(UNIX AND APPLE)
|
||||
# Mac needs a bit more help finding all necessary components
|
||||
list(APPEND QT_LIBRARY_DIR "/usr/local/lib")
|
||||
if(Qt6_FOUND)
|
||||
get_filename_component(QT_PLUGINS_DIR "${Qt6Core_DIR}/../../../${QT6_INSTALL_PLUGINS}" ABSOLUTE)
|
||||
get_filename_component(QT_LIBRARY_DIR "${QT_LIBRARY_DIR}/../../.." ABSOLUTE)
|
||||
if(UNIX AND APPLE)
|
||||
# Mac needs a bit more help finding all necessary components
|
||||
list(APPEND QT_LIBRARY_DIR "/usr/local/lib")
|
||||
endif()
|
||||
elseif(Qt5_FOUND)
|
||||
get_filename_component(QT_PLUGINS_DIR "${Qt5Core_DIR}/../../../plugins" ABSOLUTE)
|
||||
get_filename_component(QT_LIBRARY_DIR "${QT_LIBRARY_DIR}/.." ABSOLUTE)
|
||||
endif()
|
||||
message(DEBUG "QT_PLUGINS_DIR = ${QT_PLUGINS_DIR}")
|
||||
message(DEBUG "QT_LIBRARY_DIR = ${QT_LIBRARY_DIR}")
|
||||
|
|
|
|||
|
|
@ -1,118 +1,38 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
|
||||
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
|
||||
<!-- ========================= -->
|
||||
<!-- CORE BUNDLE METADATA -->
|
||||
<!-- ========================= -->
|
||||
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
|
||||
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>${MACOSX_BUNDLE_INFO_STRING}</string>
|
||||
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
|
||||
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
|
||||
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
|
||||
<key>CFBundleLongVersionString</key>
|
||||
<string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>
|
||||
|
||||
<key>CFBundleName</key>
|
||||
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
|
||||
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
|
||||
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
|
||||
<key>CFBundleVersion</key>
|
||||
<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
|
||||
|
||||
<key>CSResourcesFileMapped</key>
|
||||
<true/>
|
||||
<key>LSRequiresCarbon</key>
|
||||
<true/>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
|
||||
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<true/>
|
||||
|
||||
<!-- ========================= -->
|
||||
<!-- FILE TYPE (.cod) SUPPORT -->
|
||||
<!-- ========================= -->
|
||||
|
||||
<key>UTExportedTypeDeclarations</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>UTTypeIdentifier</key>
|
||||
<string>org.cockatrice.deck</string>
|
||||
|
||||
<key>UTTypeDescription</key>
|
||||
<string>Cockatrice Deck</string>
|
||||
|
||||
<key>UTTypeConformsTo</key>
|
||||
<array>
|
||||
<string>public.data</string>
|
||||
</array>
|
||||
|
||||
<key>UTTypeTagSpecification</key>
|
||||
<dict>
|
||||
<key>public.filename-extension</key>
|
||||
<array>
|
||||
<string>cod</string>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
</array>
|
||||
|
||||
<key>CFBundleDocumentTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>Cockatrice Deck</string>
|
||||
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
|
||||
<key>LSHandlerRank</key>
|
||||
<string>Default</string>
|
||||
|
||||
<key>LSItemContentTypes</key>
|
||||
<array>
|
||||
<string>org.cockatrice.deck</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
|
||||
<!-- ========================= -->
|
||||
<!-- URL SCHEME (cockatrice://) -->
|
||||
<!-- ========================= -->
|
||||
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>Cockatrice URL Scheme</string>
|
||||
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>cockatrice</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
||||
|
|
|
|||
|
|
@ -56,62 +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/tally_menu.cpp
|
||||
src/game_graphics/player/menu/utility_menu.cpp
|
||||
src/game_graphics/tally/stats_tally.cpp
|
||||
src/game_graphics/tally/subtype_tally.cpp
|
||||
src/game_graphics/tally/tally.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
|
||||
|
|
@ -135,12 +129,6 @@ set(cockatrice_SOURCES
|
|||
src/interface/card_picture_loader/card_picture_loader_worker.cpp
|
||||
src/interface/card_picture_loader/card_picture_loader_worker_work.cpp
|
||||
src/interface/card_picture_loader/card_picture_to_load.cpp
|
||||
src/interface/intents/intent.cpp
|
||||
src/interface/intents/intent.h
|
||||
src/interface/intents/intent_open_local_deck.cpp
|
||||
src/interface/intents/intent_open_local_deck.h
|
||||
src/interface/intents/intent_wait_for_database_load.cpp
|
||||
src/interface/intents/intent_wait_for_database_load.h
|
||||
src/interface/layouts/flow_layout.cpp
|
||||
src/interface/layouts/overlap_layout.cpp
|
||||
src/interface/widgets/utility/line_edit_completer.cpp
|
||||
|
|
@ -193,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
|
||||
|
|
@ -240,9 +227,7 @@ set(cockatrice_SOURCES
|
|||
src/interface/widgets/quick_settings/settings_button_widget.cpp
|
||||
src/interface/widgets/quick_settings/settings_popup_widget.cpp
|
||||
src/interface/widgets/replay/replay_manager.cpp
|
||||
src/interface/widgets/replay/replay_quick_settings_widget.cpp
|
||||
src/interface/widgets/replay/replay_timeline_widget.cpp
|
||||
src/interface/widgets/replay/replay_widget.cpp
|
||||
src/interface/widgets/server/chat_view/chat_view.cpp
|
||||
src/interface/widgets/server/game_filter_configs.cpp
|
||||
src/interface/widgets/server/game_selector.cpp
|
||||
|
|
@ -251,22 +236,15 @@ set(cockatrice_SOURCES
|
|||
src/interface/widgets/server/handle_public_servers.cpp
|
||||
src/interface/widgets/server/remote/remote_decklist_tree_widget.cpp
|
||||
src/interface/widgets/server/remote/remote_replay_list_tree_widget.cpp
|
||||
src/interface/widgets/server/user/user_avatar_provider.cpp
|
||||
src/interface/widgets/server/user/user_card_art_provider.cpp
|
||||
src/interface/widgets/server/user/user_card_settings_dialog.cpp
|
||||
src/interface/widgets/server/user/user_context_menu.cpp
|
||||
src/interface/widgets/server/user/user_info_box.cpp
|
||||
src/interface/widgets/server/user/user_info_connection.cpp
|
||||
src/interface/widgets/server/user/user_list_manager.cpp
|
||||
src/interface/widgets/server/user/user_list_painter.cpp
|
||||
src/interface/widgets/server/user/user_list_widget.cpp
|
||||
src/interface/widgets/settings_page/abstract_settings_page.cpp
|
||||
src/interface/widgets/settings_page/appearance_settings_page.cpp
|
||||
src/interface/widgets/settings_page/deck_editor_settings_page.cpp
|
||||
src/interface/widgets/settings_page/general_settings_page.cpp
|
||||
src/interface/widgets/settings_page/messages_settings_page.cpp
|
||||
src/interface/widgets/settings_page/settings_search_delegate.cpp
|
||||
src/interface/widgets/settings_page/settings_search_model.cpp
|
||||
src/interface/widgets/settings_page/shortcut_settings_page.cpp
|
||||
src/interface/widgets/settings_page/sound_settings_page.cpp
|
||||
src/interface/widgets/settings_page/storage_settings_page.cpp
|
||||
|
|
@ -305,7 +283,6 @@ set(cockatrice_SOURCES
|
|||
src/interface/widgets/visual_deck_storage/visual_deck_storage_widget.cpp
|
||||
src/interface/window_main.cpp
|
||||
src/main.cpp
|
||||
src/single_instance_manager.cpp
|
||||
src/interface/widgets/tabs/abstract_tab_deck_editor.cpp
|
||||
src/interface/widgets/tabs/api/archidekt/tab_archidekt.cpp
|
||||
src/interface/widgets/tabs/api/archidekt/api_response/archidekt_deck_listing_api_response.cpp
|
||||
|
|
@ -321,13 +298,6 @@ set(cockatrice_SOURCES
|
|||
src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_entry_display_widget.cpp
|
||||
src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_listings_display_widget.cpp
|
||||
src/interface/widgets/tabs/api/archidekt/display/archidekt_deck_preview_image_display_widget.cpp
|
||||
src/interface/widgets/tabs/api/commander_spellbook/api_response/card_in_deck_request.cpp
|
||||
src/interface/widgets/tabs/api/commander_spellbook/api_response/commander_spellbook_deck_request.cpp
|
||||
src/interface/widgets/tabs/api/commander_spellbook/api_response/commander_spellbook_card_result.cpp
|
||||
src/interface/widgets/tabs/api/commander_spellbook/api_response/commander_spellbook_variant_result.cpp
|
||||
src/interface/widgets/tabs/api/commander_spellbook/api_response/commander_spellbook_estimate_bracket_result.cpp
|
||||
src/interface/widgets/tabs/api/commander_spellbook/commander_spellbook_bracket_explainer.cpp
|
||||
src/interface/widgets/tabs/api/commander_spellbook/commander_spellbook_api_accessor.cpp
|
||||
src/interface/widgets/tabs/api/edhrec/api_response/archidekt_links/edhrec_api_response_archidekt_links.cpp
|
||||
src/interface/widgets/tabs/api/edhrec/api_response/average_deck/edhrec_average_deck_api_response.cpp
|
||||
src/interface/widgets/tabs/api/edhrec/api_response/average_deck/edhrec_deck_api_response.cpp
|
||||
|
|
@ -357,7 +327,6 @@ set(cockatrice_SOURCES
|
|||
src/interface/widgets/tabs/tab.cpp
|
||||
src/interface/widgets/tabs/tab_account.cpp
|
||||
src/interface/widgets/tabs/tab_admin.cpp
|
||||
src/interface/widgets/tabs/tab_card_art_rules.cpp
|
||||
src/interface/widgets/tabs/tab_deck_editor.cpp
|
||||
src/interface/widgets/tabs/tab_deck_storage.cpp
|
||||
src/interface/widgets/tabs/tab_game.cpp
|
||||
|
|
@ -374,31 +343,12 @@ set(cockatrice_SOURCES
|
|||
src/interface/widgets/tabs/visual_deck_storage/tab_deck_storage_visual.cpp
|
||||
src/interface/key_signals.cpp
|
||||
src/interface/logger.cpp
|
||||
src/interface/widgets/tabs/api/commander_spellbook/commander_bracket_service.cpp
|
||||
src/interface/widgets/tabs/api/commander_spellbook/commander_bracket_widget.cpp
|
||||
src/interface/widgets/tabs/api/commander_spellbook/handle_commander_brackets.cpp
|
||||
src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_bracket_navigation_widget.cpp
|
||||
src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_bracket_navigation_widget.h
|
||||
src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_budget_navigation_widget.cpp
|
||||
src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_budget_navigation_widget.h
|
||||
src/interface/widgets/utility/compact_push_button.cpp
|
||||
src/interface/widgets/utility/compact_push_button.h
|
||||
src/single_instance_manager.h
|
||||
src/client/url_scheme_event_filter.h
|
||||
src/interface/intents/intent_connect_to_server.cpp
|
||||
src/interface/intents/intent_connect_to_server.h
|
||||
src/interface/intents/intent_disconnect_from_server.cpp
|
||||
src/interface/intents/intent_disconnect_from_server.h
|
||||
src/interface/intents/intent_join_server_game.cpp
|
||||
src/interface/intents/intent_join_server_game.h
|
||||
src/interface/intents/intent_join_server_room.cpp
|
||||
src/interface/intents/intent_join_server_room.h
|
||||
src/interface/intents/intent_login.cpp
|
||||
src/interface/intents/intent_login.h
|
||||
src/interface/intents/url_parser.cpp
|
||||
src/interface/intents/url_parser.h
|
||||
src/interface/widgets/server/user/user_info_popup.cpp
|
||||
src/interface/widgets/server/user/user_info_popup.h
|
||||
)
|
||||
|
||||
add_subdirectory(sounds)
|
||||
|
|
@ -440,7 +390,11 @@ if(APPLE)
|
|||
set(cockatrice_SOURCES ${cockatrice_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/resources/appicon.icns)
|
||||
endif(APPLE)
|
||||
|
||||
qt6_add_resources(cockatrice_RESOURCES_RCC ${cockatrice_RESOURCES})
|
||||
if(Qt6_FOUND)
|
||||
qt6_add_resources(cockatrice_RESOURCES_RCC ${cockatrice_RESOURCES})
|
||||
elseif(Qt5_FOUND)
|
||||
qt5_add_resources(cockatrice_RESOURCES_RCC ${cockatrice_RESOURCES})
|
||||
endif()
|
||||
|
||||
# Declare path variables
|
||||
set(ICONDIR
|
||||
|
|
@ -452,37 +406,71 @@ set(DESKTOPDIR
|
|||
CACHE STRING "desktop file destination"
|
||||
)
|
||||
|
||||
set(MIMEDIR
|
||||
share/mime/packages
|
||||
CACHE STRING "mime file destination"
|
||||
)
|
||||
|
||||
set(COCKATRICE_MAC_QM_INSTALL_DIR "cockatrice.app/Contents/Resources/translations")
|
||||
set(COCKATRICE_UNIX_QM_INSTALL_DIR "share/cockatrice/translations")
|
||||
set(COCKATRICE_WIN32_QM_INSTALL_DIR "translations")
|
||||
|
||||
qt6_add_executable(
|
||||
cockatrice
|
||||
WIN32
|
||||
MACOSX_BUNDLE
|
||||
${cockatrice_SOURCES}
|
||||
${cockatrice_RESOURCES_RCC}
|
||||
${cockatrice_MOC_SRCS}
|
||||
MANUAL_FINALIZATION
|
||||
)
|
||||
if(Qt6_FOUND)
|
||||
qt6_add_executable(
|
||||
cockatrice
|
||||
WIN32
|
||||
MACOSX_BUNDLE
|
||||
${cockatrice_SOURCES}
|
||||
${cockatrice_RESOURCES_RCC}
|
||||
${cockatrice_MOC_SRCS}
|
||||
MANUAL_FINALIZATION
|
||||
)
|
||||
elseif(Qt5_FOUND)
|
||||
# Qt5 Translations need to be linked at executable creation time
|
||||
if(Qt5LinguistTools_FOUND)
|
||||
if(UPDATE_TRANSLATIONS)
|
||||
qt5_create_translation(cockatrice_QM ${translate_SRCS} ${cockatrice_TS})
|
||||
else()
|
||||
qt5_add_translation(cockatrice_QM ${cockatrice_TS})
|
||||
endif()
|
||||
endif()
|
||||
add_executable(
|
||||
cockatrice WIN32 MACOSX_BUNDLE ${cockatrice_MOC_SRCS} ${cockatrice_QM} ${cockatrice_RESOURCES_RCC}
|
||||
${cockatrice_SOURCES}
|
||||
)
|
||||
if(UNIX)
|
||||
if(APPLE)
|
||||
install(FILES ${cockatrice_QM} DESTINATION ${COCKATRICE_MAC_QM_INSTALL_DIR})
|
||||
else()
|
||||
install(FILES ${cockatrice_QM} DESTINATION ${COCKATRICE_UNIX_QM_INSTALL_DIR})
|
||||
endif()
|
||||
elseif(WIN32)
|
||||
install(FILES ${cockatrice_QM} DESTINATION ${COCKATRICE_WIN32_QM_INSTALL_DIR})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_link_libraries(
|
||||
cockatrice
|
||||
PUBLIC libcockatrice_card
|
||||
libcockatrice_deck_list
|
||||
libcockatrice_filters
|
||||
libcockatrice_utility
|
||||
libcockatrice_network
|
||||
libcockatrice_models
|
||||
libcockatrice_rng
|
||||
libcockatrice_settings
|
||||
${COCKATRICE_QT_MODULES}
|
||||
)
|
||||
if(Qt5_FOUND)
|
||||
target_link_libraries(
|
||||
cockatrice
|
||||
libcockatrice_card
|
||||
libcockatrice_deck_list
|
||||
libcockatrice_filters
|
||||
libcockatrice_utility
|
||||
libcockatrice_network
|
||||
libcockatrice_models
|
||||
libcockatrice_rng
|
||||
libcockatrice_settings
|
||||
${COCKATRICE_QT_MODULES}
|
||||
)
|
||||
else()
|
||||
target_link_libraries(
|
||||
cockatrice
|
||||
PUBLIC libcockatrice_card
|
||||
libcockatrice_deck_list
|
||||
libcockatrice_filters
|
||||
libcockatrice_utility
|
||||
libcockatrice_network
|
||||
libcockatrice_models
|
||||
libcockatrice_rng
|
||||
libcockatrice_settings
|
||||
${COCKATRICE_QT_MODULES}
|
||||
)
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
if(APPLE)
|
||||
|
|
@ -502,23 +490,6 @@ if(UNIX)
|
|||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/cockatrice.png DESTINATION ${ICONDIR}/hicolor/48x48/apps)
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/cockatrice.svg DESTINATION ${ICONDIR}/hicolor/scalable/apps)
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/cockatrice.desktop DESTINATION ${DESKTOPDIR})
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/cockatrice-cod.xml DESTINATION ${MIMEDIR})
|
||||
|
||||
# Refresh the freedesktop databases so the file associations and scheme
|
||||
# handler register without requiring the user to run them manually. The
|
||||
# tools may be missing on minimal systems; that is fine, packaging systems
|
||||
# usually refresh these databases through their own triggers.
|
||||
find_program(UPDATE_MIME_DATABASE update-mime-database)
|
||||
if(UPDATE_MIME_DATABASE)
|
||||
install(CODE "execute_process(COMMAND \"${UPDATE_MIME_DATABASE}\" \"${CMAKE_INSTALL_PREFIX}/share/mime\")")
|
||||
endif()
|
||||
|
||||
find_program(UPDATE_DESKTOP_DATABASE update-desktop-database)
|
||||
if(UPDATE_DESKTOP_DATABASE)
|
||||
install(
|
||||
CODE "execute_process(COMMAND \"${UPDATE_DESKTOP_DATABASE}\" \"${CMAKE_INSTALL_PREFIX}/share/applications\")"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
elseif(WIN32)
|
||||
install(TARGETS cockatrice RUNTIME DESTINATION ./)
|
||||
|
|
@ -529,7 +500,7 @@ if(APPLE)
|
|||
set(plugin_dest_dir cockatrice.app/Contents/Plugins)
|
||||
set(qtconf_dest_dir cockatrice.app/Contents/Resources)
|
||||
|
||||
# Qt plugins: audio, iconengines, imageformats, multimedia, platforms, printsupport, styles, tls
|
||||
# Qt plugins: audio (Qt5), iconengines, imageformats, multimedia (Qt6), platforms, printsupport (Qt5), styles, tls (Qt6)
|
||||
install(
|
||||
DIRECTORY "${QT_PLUGINS_DIR}/"
|
||||
DESTINATION ${plugin_dest_dir}
|
||||
|
|
@ -596,7 +567,7 @@ if(WIN32)
|
|||
PATTERN "*.ini"
|
||||
)
|
||||
|
||||
# Qt plugins: audio, iconengines, imageformats, multimedia, platforms, printsupport, styles, tls
|
||||
# Qt plugins: audio (Qt5), iconengines, imageformats, multimedia (Qt6) platforms, printsupport (Qt5), styles, tls (Qt6)
|
||||
install(
|
||||
DIRECTORY "${QT_PLUGINS_DIR}/"
|
||||
DESTINATION ${plugin_dest_dir}
|
||||
|
|
@ -652,7 +623,7 @@ Data = Resources\")
|
|||
endif()
|
||||
endif()
|
||||
|
||||
if(Qt6LinguistTools_FOUND)
|
||||
if(Qt6_FOUND AND Qt6LinguistTools_FOUND)
|
||||
#Qt6 Translations happen after the executable is built up
|
||||
if(UPDATE_TRANSLATIONS)
|
||||
qt6_add_translations(
|
||||
|
|
@ -679,4 +650,6 @@ if(Qt6LinguistTools_FOUND)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
qt6_finalize_target(cockatrice)
|
||||
if(Qt6_FOUND)
|
||||
qt6_finalize_target(cockatrice)
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
|
||||
<mime-type type="application/x-cockatrice">
|
||||
<comment>Cockatrice Deck File</comment>
|
||||
<glob pattern="*.cod"/>
|
||||
</mime-type>
|
||||
</mime-info>
|
||||
|
|
@ -3,8 +3,6 @@
|
|||
Version=1.0
|
||||
Type=Application
|
||||
Name=Cockatrice
|
||||
Exec=cockatrice %U
|
||||
Exec=cockatrice
|
||||
Icon=cockatrice
|
||||
Categories=Game;CardGame;
|
||||
MimeType=application/x-cockatrice;
|
||||
X-Scheme-Handler/cockatrice=true
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -14,7 +14,6 @@
|
|||
#include <QThread>
|
||||
#include <libcockatrice/network/client/remote/remote_client.h>
|
||||
#include <libcockatrice/protocol/pb/response.pb.h>
|
||||
#include <libcockatrice/settings/servers_settings.h>
|
||||
|
||||
ConnectionController::ConnectionController(QWidget *dialogParent, QObject *parent)
|
||||
: QObject(parent), dialogParent(dialogParent)
|
||||
|
|
|
|||
|
|
@ -6,12 +6,12 @@
|
|||
#include <QNetworkRequest>
|
||||
#include <QRegularExpression>
|
||||
#include <QUrlQuery>
|
||||
#include <libcockatrice/card/database/card_database_manager.h>
|
||||
#include <libcockatrice/deck_list/deck_list.h>
|
||||
#include <libcockatrice/deck_list/tree/deck_list_card_node.h>
|
||||
#include <version_string.h>
|
||||
|
||||
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());
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#ifndef DECKSTATS_INTERFACE_H
|
||||
#define DECKSTATS_INTERFACE_H
|
||||
|
||||
#include <libcockatrice/card/database/card_database.h>
|
||||
#include <libcockatrice/deck_list/deck_list.h>
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -6,12 +6,12 @@
|
|||
#include <QNetworkRequest>
|
||||
#include <QRegularExpression>
|
||||
#include <QUrlQuery>
|
||||
#include <libcockatrice/card/database/card_database_manager.h>
|
||||
#include <libcockatrice/deck_list/deck_list.h>
|
||||
#include <libcockatrice/deck_list/tree/deck_list_card_node.h>
|
||||
#include <version_string.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@
|
|||
#ifndef TAPPEDOUT_INTERFACE_H
|
||||
#define TAPPEDOUT_INTERFACE_H
|
||||
|
||||
#include <QLoggingCategory>
|
||||
#include <QObject>
|
||||
#include <libcockatrice/card/database/card_database.h>
|
||||
#include <libcockatrice/deck_list/deck_list.h>
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -14,8 +14,6 @@
|
|||
#include <QtConcurrent>
|
||||
#include <libcockatrice/card/database/card_database.h>
|
||||
#include <libcockatrice/card/database/card_database_manager.h>
|
||||
#include <libcockatrice/settings/download_settings.h>
|
||||
#include <libcockatrice/settings/paths_settings.h>
|
||||
#include <version_string.h>
|
||||
|
||||
#define SPOILERS_STATUS_URL "https://raw.githubusercontent.com/Cockatrice/Magic-Spoiler/files/SpoilerSeasonEnabled"
|
||||
|
|
@ -23,7 +21,7 @@
|
|||
|
||||
SpoilerBackgroundUpdater::SpoilerBackgroundUpdater(QObject *apParent) : QObject(apParent), cardUpdateProcess(nullptr)
|
||||
{
|
||||
isSpoilerDownloadEnabled = SettingsCache::instance().downloads().getDownloadSpoilersStatus();
|
||||
isSpoilerDownloadEnabled = SettingsCache::instance().getDownloadSpoilersStatus();
|
||||
if (isSpoilerDownloadEnabled) {
|
||||
// Start the process of checking if we're in spoiler season
|
||||
// File exists means we're in spoiler season
|
||||
|
|
@ -77,7 +75,7 @@ void SpoilerBackgroundUpdater::actDownloadFinishedSpoilersFile()
|
|||
|
||||
bool SpoilerBackgroundUpdater::deleteSpoilerFile()
|
||||
{
|
||||
QString fileName = SettingsCache::instance().paths().getSpoilerCardDatabasePath();
|
||||
QString fileName = SettingsCache::instance().getSpoilerCardDatabasePath();
|
||||
QFileInfo fi(fileName);
|
||||
QDir fileDir(fi.path());
|
||||
QFile file(fileName);
|
||||
|
|
@ -128,7 +126,7 @@ void SpoilerBackgroundUpdater::actCheckIfSpoilerSeasonEnabled()
|
|||
|
||||
bool SpoilerBackgroundUpdater::saveDownloadedFile(QByteArray data)
|
||||
{
|
||||
QString fileName = SettingsCache::instance().paths().getSpoilerCardDatabasePath();
|
||||
QString fileName = SettingsCache::instance().getSpoilerCardDatabasePath();
|
||||
QFileInfo fi(fileName);
|
||||
QDir fileDir(fi.path());
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -5,7 +5,7 @@
|
|||
#include <QtMath>
|
||||
|
||||
CardCounterSettings::CardCounterSettings(const QString &settingsPath, QObject *parent)
|
||||
: SettingsManager(settingsPath + "card_counters.ini", "cards", "counters", parent)
|
||||
: SettingsManager(settingsPath + "global.ini", "cards", "counters", parent)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)},
|
||||
|
|
|
|||
|
|
@ -2,11 +2,12 @@
|
|||
|
||||
#include "settings/cache_settings.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QAudioOutput>
|
||||
#include <QDir>
|
||||
#include <QMediaPlayer>
|
||||
#include <libcockatrice/settings/sound_settings.h>
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
#include <QAudioOutput>
|
||||
#endif
|
||||
|
||||
#define DEFAULT_THEME_NAME "Default"
|
||||
#define TEST_SOUND_FILENAME "player_join"
|
||||
|
|
@ -14,10 +15,8 @@
|
|||
SoundEngine::SoundEngine(QObject *parent) : QObject(parent), audioOutput(nullptr), player(nullptr)
|
||||
{
|
||||
ensureThemeDirectoryExists();
|
||||
connect(&SettingsCache::instance().sound(), &SoundSettings::soundThemeChanged, this,
|
||||
&SoundEngine::themeChangedSlot);
|
||||
connect(&SettingsCache::instance().sound(), &SoundSettings::soundEnabledChanged, this,
|
||||
&SoundEngine::soundEnabledChanged);
|
||||
connect(&SettingsCache::instance(), &SettingsCache::soundThemeChanged, this, &SoundEngine::themeChangedSlot);
|
||||
connect(&SettingsCache::instance(), &SettingsCache::soundEnabledChanged, this, &SoundEngine::soundEnabledChanged);
|
||||
|
||||
soundEnabledChanged();
|
||||
themeChangedSlot();
|
||||
|
|
@ -37,12 +36,14 @@ SoundEngine::~SoundEngine()
|
|||
|
||||
void SoundEngine::soundEnabledChanged()
|
||||
{
|
||||
if (SettingsCache::instance().sound().getSoundEnabled()) {
|
||||
if (SettingsCache::instance().getSoundEnabled()) {
|
||||
qCInfo(SoundEngineLog) << "SoundEngine: enabling sound with" << audioData.size() << "sounds";
|
||||
if (!player) {
|
||||
player = new QMediaPlayer;
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
audioOutput = new QAudioOutput(player);
|
||||
player->setAudioOutput(audioOutput);
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
qCInfo(SoundEngineLog) << "SoundEngine: disabling sound";
|
||||
|
|
@ -69,9 +70,14 @@ void SoundEngine::playSound(const QString &fileName)
|
|||
}
|
||||
|
||||
player->stop();
|
||||
int volumeSliderValue = SettingsCache::instance().sound().getMasterVolume();
|
||||
int volumeSliderValue = SettingsCache::instance().getMasterVolume();
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
player->audioOutput()->setVolume(qreal(volumeSliderValue) / 100);
|
||||
player->setSource(QUrl::fromLocalFile(audioData[fileName]));
|
||||
#else
|
||||
player->setVolume(volumeSliderValue);
|
||||
player->setMedia(QUrl::fromLocalFile(audioData[fileName]));
|
||||
#endif
|
||||
player->play();
|
||||
}
|
||||
|
||||
|
|
@ -82,10 +88,10 @@ void SoundEngine::testSound()
|
|||
|
||||
void SoundEngine::ensureThemeDirectoryExists()
|
||||
{
|
||||
if (SettingsCache::instance().sound().getSoundThemeName().isEmpty() ||
|
||||
!getAvailableThemes().contains(SettingsCache::instance().sound().getSoundThemeName())) {
|
||||
if (SettingsCache::instance().getSoundThemeName().isEmpty() ||
|
||||
!getAvailableThemes().contains(SettingsCache::instance().getSoundThemeName())) {
|
||||
qCInfo(SoundEngineLog) << "Sounds theme name not set, setting default value";
|
||||
SettingsCache::instance().sound().setSoundThemeName(DEFAULT_THEME_NAME);
|
||||
SettingsCache::instance().setSoundThemeName(DEFAULT_THEME_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -126,7 +132,7 @@ QStringMap &SoundEngine::getAvailableThemes()
|
|||
|
||||
void SoundEngine::themeChangedSlot()
|
||||
{
|
||||
QString themeName = SettingsCache::instance().sound().getSoundThemeName();
|
||||
QString themeName = SettingsCache::instance().getSoundThemeName();
|
||||
qCInfo(SoundEngineLog) << "Sound theme changed:" << themeName;
|
||||
|
||||
QDir dir = getAvailableThemes().value(themeName);
|
||||
|
|
|
|||
|
|
@ -1,69 +0,0 @@
|
|||
#ifndef COCKATRICE_URL_SCHEME_EVENT_FILTER_H
|
||||
#define COCKATRICE_URL_SCHEME_EVENT_FILTER_H
|
||||
|
||||
#include <QEvent>
|
||||
#include <QFileOpenEvent>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
|
||||
/**
|
||||
* @brief Event filter that catches QFileOpenEvent URLs matching a scheme and
|
||||
* re-emits them as urlReceived().
|
||||
*
|
||||
* On macOS, when the application is registered as a URL scheme handler, the
|
||||
* OS delivers incoming URLs via QFileOpenEvent on the QApplication object.
|
||||
* Install this filter on QApplication to intercept them:
|
||||
*
|
||||
* @code
|
||||
* UrlSchemeEventFilter filter(QStringList{QStringLiteral("cockatrice")});
|
||||
* QObject::connect(&filter, &UrlSchemeEventFilter::urlReceived,
|
||||
* &mainWindow, &MainWindow::handleUrl);
|
||||
* app.installEventFilter(&filter);
|
||||
* @endcode
|
||||
*
|
||||
* Note: the strings are compared against QUrl::scheme(), so they must be
|
||||
* written without the "://" suffix (e.g. "cockatrice", not "cockatrice://").
|
||||
*/
|
||||
class UrlSchemeEventFilter : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit UrlSchemeEventFilter(const QStringList &schemes, QObject *parent = nullptr)
|
||||
: QObject(parent), prefixes(schemes)
|
||||
{
|
||||
}
|
||||
|
||||
signals:
|
||||
void urlReceived(const QString &url);
|
||||
|
||||
public:
|
||||
bool eventFilter(QObject *watched, QEvent *event) override
|
||||
{
|
||||
if (event->type() == QEvent::FileOpen) {
|
||||
auto *fileEvent = static_cast<QFileOpenEvent *>(event);
|
||||
|
||||
const QUrl url = fileEvent->url();
|
||||
|
||||
for (const auto &prefix : prefixes) {
|
||||
if (url.scheme() == prefix) {
|
||||
emit urlReceived(url.toString());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (url.isLocalFile()) {
|
||||
emit urlReceived(url.toLocalFile());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return QObject::eventFilter(watched, event);
|
||||
}
|
||||
|
||||
private:
|
||||
QStringList prefixes;
|
||||
};
|
||||
|
||||
#endif // COCKATRICE_URL_SCHEME_EVENT_FILTER_H
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
#ifndef SETTINGS_CARD_DATABASE_PATH_PROVIDER_H
|
||||
#define SETTINGS_CARD_DATABASE_PATH_PROVIDER_H
|
||||
|
||||
#include "../../client/settings/cache_settings.h"
|
||||
|
||||
#include <libcockatrice/interfaces/interface_card_database_path_provider.h>
|
||||
#include <libcockatrice/settings/paths_settings.h>
|
||||
|
||||
class SettingsCardDatabasePathProvider : public ICardDatabasePathProvider
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SettingsCardDatabasePathProvider(QObject *parent = nullptr) : ICardDatabasePathProvider(parent)
|
||||
{
|
||||
connect(&SettingsCache::instance().paths(), &PathsSettings::cardDatabasePathChanged, this,
|
||||
&ICardDatabasePathProvider::cardDatabasePathChanged);
|
||||
}
|
||||
|
||||
[[nodiscard]] QString getCardDatabasePath() const override
|
||||
{
|
||||
return SettingsCache::instance().paths().getCardDatabasePath();
|
||||
}
|
||||
|
||||
[[nodiscard]] QString getCustomCardDatabasePath() const override
|
||||
{
|
||||
return SettingsCache::instance().paths().getCustomCardDatabasePath();
|
||||
}
|
||||
|
||||
[[nodiscard]] QString getTokenDatabasePath() const override
|
||||
{
|
||||
return SettingsCache::instance().paths().getTokenDatabasePath();
|
||||
}
|
||||
|
||||
[[nodiscard]] virtual QString getSpoilerCardDatabasePath() const override
|
||||
{
|
||||
return SettingsCache::instance().paths().getSpoilerCardDatabasePath();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SETTINGS_CARD_DATABASE_PATH_PROVIDER_H
|
||||
|
|
@ -3,8 +3,6 @@
|
|||
#include "../../client/settings/cache_settings.h"
|
||||
|
||||
#include <libcockatrice/interfaces/interface_card_preference_provider.h>
|
||||
#include <libcockatrice/settings/card_override_settings.h>
|
||||
#include <libcockatrice/settings/cards_display_settings.h>
|
||||
|
||||
class SettingsCardPreferenceProvider : public ICardPreferenceProvider
|
||||
{
|
||||
|
|
@ -16,7 +14,7 @@ public:
|
|||
|
||||
[[nodiscard]] bool getIncludeRebalancedCards() const override
|
||||
{
|
||||
return SettingsCache::instance().cardsDisplay().getIncludeRebalancedCards();
|
||||
return SettingsCache::instance().getIncludeRebalancedCards();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
@ -31,7 +31,7 @@ AbstractClient *AbstractGame::getClientForPlayer(int playerId) const
|
|||
}
|
||||
}
|
||||
|
||||
void AbstractGame::loadReplay(const GameReplay *replay)
|
||||
void AbstractGame::loadReplay(GameReplay *replay)
|
||||
{
|
||||
gameMetaInfo->setFromProto(replay->game_info());
|
||||
gameMetaInfo->setSpectatorsOmniscient(true);
|
||||
|
|
|
|||
|
|
@ -16,19 +16,26 @@
|
|||
#include <libcockatrice/protocol/pb/game_replay.pb.h>
|
||||
|
||||
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;
|
||||
|
|
@ -53,7 +60,7 @@ public:
|
|||
|
||||
AbstractClient *getClientForPlayer(int playerId) const;
|
||||
|
||||
void loadReplay(const GameReplay *replay);
|
||||
void loadReplay(GameReplay *replay);
|
||||
|
||||
CardItem *getCard(int playerId, const QString &zoneName, int cardId) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,48 +0,0 @@
|
|||
#include "arrow_registry.h"
|
||||
|
||||
#include "../game_graphics/board/arrow_item.h"
|
||||
|
||||
void ArrowRegistry::insert(QSharedPointer<ArrowData> 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<int> ArrowRegistry::idsForPlayer(int playerId) const
|
||||
{
|
||||
return byPlayer.value(playerId);
|
||||
}
|
||||
|
||||
QList<ArrowItem *> ArrowRegistry::all() const
|
||||
{
|
||||
return items.values();
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
#ifndef COCKATRICE_ARROW_REGISTRY_H
|
||||
#define COCKATRICE_ARROW_REGISTRY_H
|
||||
|
||||
#include "board/arrow_data.h"
|
||||
|
||||
#include <QMap>
|
||||
#include <QSet>
|
||||
#include <QSharedPointer>
|
||||
|
||||
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<ArrowData> 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<int> idsForPlayer(int playerId) const;
|
||||
[[nodiscard]] QList<ArrowItem *> all() const;
|
||||
|
||||
private:
|
||||
QMap<ArrowKey, QSharedPointer<ArrowData>> dataStore;
|
||||
QMap<ArrowKey, ArrowItem *> items;
|
||||
QMap<int, QSet<int>> byPlayer;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -7,7 +7,6 @@
|
|||
#include <QDebug>
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
#include <QPainter>
|
||||
#include <libcockatrice/settings/cards_display_settings.h>
|
||||
|
||||
const QColor GHOST_MASK = QColor(255, 255, 255, 50);
|
||||
|
||||
|
|
@ -35,13 +34,12 @@ AbstractCardDragItem::AbstractCardDragItem(AbstractCardItem *_item,
|
|||
|
||||
setCacheMode(DeviceCoordinateCache);
|
||||
|
||||
connect(&SettingsCache::instance().cardsDisplay(), &CardsDisplaySettings::roundCardCornersChanged, this,
|
||||
[this](bool _roundCardCorners) {
|
||||
Q_UNUSED(_roundCardCorners);
|
||||
connect(&SettingsCache::instance(), &SettingsCache::roundCardCornersChanged, this, [this](bool _roundCardCorners) {
|
||||
Q_UNUSED(_roundCardCorners);
|
||||
|
||||
prepareGeometryChange();
|
||||
update();
|
||||
});
|
||||
prepareGeometryChange();
|
||||
update();
|
||||
});
|
||||
|
||||
connect(item, &QObject::destroyed, this, &AbstractCardDragItem::deleteLater);
|
||||
}
|
||||
|
|
@ -49,8 +47,7 @@ AbstractCardDragItem::AbstractCardDragItem(AbstractCardItem *_item,
|
|||
QPainterPath AbstractCardDragItem::shape() const
|
||||
{
|
||||
QPainterPath shape;
|
||||
qreal cardCornerRadius =
|
||||
SettingsCache::instance().cardsDisplay().getRoundCardCorners() ? 0.05 * CardDimensions::WIDTH_F : 0.0;
|
||||
qreal cardCornerRadius = SettingsCache::instance().getRoundCardCorners() ? 0.05 * CardDimensions::WIDTH_F : 0.0;
|
||||
shape.addRoundedRect(boundingRect(), cardCornerRadius, cardCornerRadius);
|
||||
return shape;
|
||||
}
|
||||
|
|
@ -12,9 +12,6 @@
|
|||
#include <algorithm>
|
||||
#include <libcockatrice/card/database/card_database.h>
|
||||
#include <libcockatrice/card/database/card_database_manager.h>
|
||||
#include <libcockatrice/settings/appearance_settings.h>
|
||||
#include <libcockatrice/settings/cards_display_settings.h>
|
||||
#include <libcockatrice/settings/debug_settings.h>
|
||||
|
||||
AbstractCardItem::AbstractCardItem(QGraphicsItem *parent, const CardRef &cardRef, PlayerLogic *_owner, int _id)
|
||||
: ArrowTarget(_owner, parent), id(_id), cardRef(cardRef), tapped(false), facedown(false), tapAngle(0),
|
||||
|
|
@ -24,17 +21,15 @@ AbstractCardItem::AbstractCardItem(QGraphicsItem *parent, const CardRef &cardRef
|
|||
setFlag(ItemIsSelectable);
|
||||
setCacheMode(DeviceCoordinateCache);
|
||||
|
||||
connect(&SettingsCache::instance().cardsDisplay(), &CardsDisplaySettings::displayCardNamesChanged, this,
|
||||
[this] { update(); });
|
||||
connect(&SettingsCache::instance(), &SettingsCache::displayCardNamesChanged, this, [this] { update(); });
|
||||
refreshCardInfo();
|
||||
|
||||
connect(&SettingsCache::instance().cardsDisplay(), &CardsDisplaySettings::roundCardCornersChanged, this,
|
||||
[this](bool _roundCardCorners) {
|
||||
Q_UNUSED(_roundCardCorners);
|
||||
connect(&SettingsCache::instance(), &SettingsCache::roundCardCornersChanged, this, [this](bool _roundCardCorners) {
|
||||
Q_UNUSED(_roundCardCorners);
|
||||
|
||||
prepareGeometryChange();
|
||||
update();
|
||||
});
|
||||
prepareGeometryChange();
|
||||
update();
|
||||
});
|
||||
}
|
||||
|
||||
AbstractCardItem::~AbstractCardItem()
|
||||
|
|
@ -50,8 +45,7 @@ QRectF AbstractCardItem::boundingRect() const
|
|||
QPainterPath AbstractCardItem::shape() const
|
||||
{
|
||||
QPainterPath shape;
|
||||
qreal cardCornerRadius =
|
||||
SettingsCache::instance().cardsDisplay().getRoundCardCorners() ? 0.05 * CardDimensions::WIDTH_F : 0.0;
|
||||
qreal cardCornerRadius = SettingsCache::instance().getRoundCardCorners() ? 0.05 * CardDimensions::WIDTH_F : 0.0;
|
||||
shape.addRoundedRect(boundingRect(), cardCornerRadius, cardCornerRadius);
|
||||
return shape;
|
||||
}
|
||||
|
|
@ -107,7 +101,7 @@ QSizeF AbstractCardItem::getTranslatedSize(QPainter *painter) const
|
|||
|
||||
void AbstractCardItem::transformPainter(QPainter *painter, const QSizeF &translatedSize, int angle)
|
||||
{
|
||||
const int MAX_FONT_SIZE = SettingsCache::instance().appearance().getMaxFontSize();
|
||||
const int MAX_FONT_SIZE = SettingsCache::instance().getMaxFontSize();
|
||||
const int fontSize = std::max(9, MAX_FONT_SIZE);
|
||||
|
||||
QRectF totalBoundingRect = painter->combinedTransform().mapRect(boundingRect());
|
||||
|
|
@ -157,7 +151,7 @@ void AbstractCardItem::paintPicture(QPainter *painter, const QSizeF &translatedS
|
|||
painter->drawPath(shape());
|
||||
}
|
||||
|
||||
if (translatedPixmap.isNull() || SettingsCache::instance().cardsDisplay().getDisplayCardNames() || facedown) {
|
||||
if (translatedPixmap.isNull() || SettingsCache::instance().getDisplayCardNames() || facedown) {
|
||||
painter->save();
|
||||
transformPainter(painter, translatedSize, angle);
|
||||
painter->setPen(Qt::white);
|
||||
|
|
@ -240,7 +234,7 @@ void AbstractCardItem::setHovered(bool _hovered)
|
|||
|
||||
isHovered = _hovered;
|
||||
setZValue(_hovered ? ZValues::HOVERED_CARD : realZValue);
|
||||
setScale(_hovered && SettingsCache::instance().cardsDisplay().getScaleCards() ? 1.1 : 1);
|
||||
setScale(_hovered && SettingsCache::instance().getScaleCards() ? 1.1 : 1);
|
||||
setTransformOriginPoint(_hovered ? CardDimensions::WIDTH_HALF_F : 0, _hovered ? CardDimensions::HEIGHT_HALF_F : 0);
|
||||
update();
|
||||
}
|
||||
|
|
@ -293,7 +287,7 @@ void AbstractCardItem::setTapped(bool _tapped, bool canAnimate)
|
|||
}
|
||||
|
||||
tapped = _tapped;
|
||||
if (SettingsCache::instance().cardsDisplay().getTapAnimation() && canAnimate) {
|
||||
if (SettingsCache::instance().getTapAnimation() && canAnimate) {
|
||||
static_cast<GameScene *>(scene())->registerAnimationItem(this);
|
||||
} else {
|
||||
tapAngle = tapped ? 90 : 0;
|
||||
|
|
@ -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 <libcockatrice/card/printing/exact_card.h>
|
||||
#include <libcockatrice/utility/card_ref.h>
|
||||
|
|
@ -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
|
||||
|
|
@ -1,11 +1,10 @@
|
|||
#include "abstract_counter.h"
|
||||
|
||||
#include "../../client/settings/cache_settings.h"
|
||||
#include "../../client/settings/shortcuts_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 <QAction>
|
||||
#include <QApplication>
|
||||
|
|
@ -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 <QGraphicsItem>
|
||||
#include <QInputDialog>
|
||||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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 <QDebug>
|
||||
|
|
@ -18,12 +18,15 @@
|
|||
#include <libcockatrice/protocol/pb/command_attach_card.pb.h>
|
||||
#include <libcockatrice/protocol/pb/command_create_arrow.pb.h>
|
||||
#include <libcockatrice/protocol/pb/command_delete_arrow.pb.h>
|
||||
#include <libcockatrice/settings/interface_settings.h>
|
||||
#include <libcockatrice/utility/color.h>
|
||||
#include <libcockatrice/utility/zone_names.h>
|
||||
|
||||
ArrowItem::ArrowItem(QSharedPointer<const ArrowData> _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);
|
||||
|
||||
|
|
@ -49,7 +52,7 @@ ArrowItem::ArrowItem(QSharedPointer<const ArrowData> _data, ArrowTarget *_startI
|
|||
|
||||
void ArrowItem::onTargetDestroyed()
|
||||
{
|
||||
emit requestDeletion(data->creatorId, data->id);
|
||||
emit requestDeletion(id);
|
||||
}
|
||||
|
||||
void ArrowItem::delArrow()
|
||||
|
|
@ -127,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 {
|
||||
|
|
@ -139,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;
|
||||
}
|
||||
|
|
@ -153,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<ArrowData>::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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -241,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());
|
||||
|
|
@ -262,7 +259,7 @@ void ArrowDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
|||
if (startZone->getName() == ZoneNames::HAND) {
|
||||
startCard->playCard(false);
|
||||
CardInfoPtr ci = startCard->getCard().getCardPtr();
|
||||
bool playToStack = SettingsCache::instance().userInterface().getPlayToStack();
|
||||
bool playToStack = SettingsCache::instance().getPlayToStack();
|
||||
if (ci && ((!playToStack && ci->getUiAttributes().tableRow == 3) ||
|
||||
(playToStack && ci->getUiAttributes().tableRow != 0 &&
|
||||
startCard->getZone()->getName() != ZoneNames::STACK))) {
|
||||
|
|
@ -287,14 +284,7 @@ void ArrowDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
|||
|
||||
// ArrowAttachItem
|
||||
ArrowAttachItem::ArrowAttachItem(ArrowTarget *_startItem)
|
||||
: ArrowItem(
|
||||
QSharedPointer<ArrowData>::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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -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 <QGraphicsItem>
|
||||
#include <QPointer>
|
||||
#include <QSharedPointer>
|
||||
|
||||
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<const ArrowData> data;
|
||||
PlayerLogic *player;
|
||||
int id;
|
||||
QPointer<ArrowTarget> startItem;
|
||||
QPointer<ArrowTarget> targetItem;
|
||||
bool targetLocked = false;
|
||||
QColor color;
|
||||
bool fullColor = true;
|
||||
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
|
||||
public:
|
||||
ArrowItem(QSharedPointer<const ArrowData> _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<ArrowDragItem *> childArrows;
|
||||
QMetaObject::Connection positionConnection;
|
||||
|
|
@ -92,7 +100,6 @@ class ArrowAttachItem : public ArrowItem
|
|||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
PlayerLogic *player;
|
||||
QList<ArrowAttachItem *> childArrows;
|
||||
QMetaObject::Connection positionConnection;
|
||||
void attachCards(CardItem *startCard, const CardItem *targetCard);
|
||||
|
|
@ -106,4 +113,4 @@ protected:
|
|||
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif // ARROWITEM_H
|
||||
|
|
@ -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)
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
#ifndef ARROWTARGET_H
|
||||
#define ARROWTARGET_H
|
||||
|
||||
#include "abstract_graphics_item.h"
|
||||
#include "../../game_graphics/board/abstract_graphics_item.h"
|
||||
|
||||
#include <QList>
|
||||
|
||||
|
|
@ -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 <QCursor>
|
||||
|
|
@ -1,15 +1,14 @@
|
|||
#include "card_item.h"
|
||||
|
||||
#include "../../client/settings/cache_settings.h"
|
||||
#include "../../client/settings/card_counter_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"
|
||||
|
||||
|
|
@ -20,7 +19,6 @@
|
|||
#include <QPainter>
|
||||
#include <libcockatrice/card/card_info.h>
|
||||
#include <libcockatrice/protocol/pb/serverinfo_card.pb.h>
|
||||
#include <libcockatrice/settings/interface_settings.h>
|
||||
|
||||
CardItem::CardItem(PlayerLogic *_owner,
|
||||
QGraphicsItem *parent,
|
||||
|
|
@ -42,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;
|
||||
|
|
@ -281,7 +279,7 @@ void CardItem::drawArrow(const QColor &arrowColor)
|
|||
auto *game = owner->getGame();
|
||||
PlayerLogic *arrowOwner = game->getPlayerManager()->getActiveLocalPlayer(game->getGameState()->getActivePlayer());
|
||||
int phase = 0; // 0 means to not set the phase
|
||||
if (SettingsCache::instance().userInterface().getDoNotDeleteArrowsInSubPhases()) {
|
||||
if (SettingsCache::instance().getDoNotDeleteArrowsInSubPhases()) {
|
||||
int currentPhase = game->getGameState()->getCurrentPhase();
|
||||
phase = Phases::getLastSubphase(currentPhase) + 1;
|
||||
}
|
||||
|
|
@ -400,12 +398,9 @@ void CardItem::playCard(bool faceDown)
|
|||
if (tz) {
|
||||
emit tz->toggleTapped();
|
||||
} else {
|
||||
if (SettingsCache::instance().userInterface().getClickPlaysAllSelected()) {
|
||||
if (faceDown) {
|
||||
emit playSelectedFaceDown(this);
|
||||
} else {
|
||||
emit playSelected(this);
|
||||
}
|
||||
if (SettingsCache::instance().getClickPlaysAllSelected()) {
|
||||
faceDown ? state->getZone()->getPlayer()->getPlayerActions()->actPlayFacedown()
|
||||
: state->getZone()->getPlayer()->getPlayerActions()->actPlay();
|
||||
} else {
|
||||
state->getZone()->getPlayer()->getPlayerActions()->playCard(this, faceDown);
|
||||
}
|
||||
|
|
@ -464,8 +459,8 @@ static bool isUnwritableRevealZone(CardZoneLogic *zone)
|
|||
void CardItem::handleClickedToPlay(bool shiftHeld)
|
||||
{
|
||||
if (isUnwritableRevealZone(state->getZone())) {
|
||||
if (SettingsCache::instance().userInterface().getClickPlaysAllSelected()) {
|
||||
emit hideSelected(this);
|
||||
if (SettingsCache::instance().getClickPlaysAllSelected()) {
|
||||
state->getZone()->getPlayer()->getPlayerActions()->actHide();
|
||||
} else {
|
||||
state->getZone()->removeCard(this);
|
||||
}
|
||||
|
|
@ -476,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().userInterface().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);
|
||||
|
|
@ -493,7 +494,7 @@ void CardItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
|||
void CardItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
if ((event->modifiers() != Qt::AltModifier) && (event->buttons() == Qt::LeftButton) &&
|
||||
(SettingsCache::instance().userInterface().getDoubleClickToPlay())) {
|
||||
(SettingsCache::instance().getDoubleClickToPlay())) {
|
||||
handleClickedToPlay(event->modifiers().testFlag(Qt::ShiftModifier));
|
||||
}
|
||||
event->accept();
|
||||
|
|
@ -530,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);
|
||||
}
|
||||
}
|
||||
|
|
@ -7,11 +7,12 @@
|
|||
#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 <libcockatrice/network/server/remote/game/server_card.h>
|
||||
#include <libcockatrice/utility/trice_limits.h>
|
||||
|
||||
class CardDatabase;
|
||||
class CardDragItem;
|
||||
|
|
@ -54,10 +55,6 @@ public:
|
|||
CardZoneLogic *_zone = nullptr);
|
||||
|
||||
void retranslateUi();
|
||||
[[nodiscard]] CardState *getState() const
|
||||
{
|
||||
return state;
|
||||
}
|
||||
[[nodiscard]] CardZoneLogic *getZone() const
|
||||
{
|
||||
return state->getZone();
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
#include "card_list.h"
|
||||
|
||||
#include "../../game_graphics/board/card_item.h"
|
||||
#include "card_item.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <algorithm>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ void CardState::setZone(CardZoneLogic *_zone)
|
|||
}
|
||||
|
||||
zone = _zone;
|
||||
emit zoneChanged(this, zone);
|
||||
emit zoneChanged(zone);
|
||||
emit stateChanged();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 <QPainter>
|
||||
|
||||
|
|
@ -11,7 +11,6 @@
|
|||
#include <libcockatrice/card/card_info.h>
|
||||
#include <libcockatrice/deck_list/deck_list.h>
|
||||
#include <libcockatrice/deck_list/tree/deck_list_card_node.h>
|
||||
#include <libcockatrice/settings/cards_display_settings.h>
|
||||
|
||||
DeckViewCardDragItem::DeckViewCardDragItem(DeckViewCard *_item,
|
||||
const QPointF &_hotSpot,
|
||||
|
|
@ -78,12 +77,11 @@ DeckViewCard::DeckViewCard(QGraphicsItem *parent, const CardRef &cardRef, const
|
|||
{
|
||||
setAcceptHoverEvents(true);
|
||||
|
||||
connect(&SettingsCache::instance().cardsDisplay(), &CardsDisplaySettings::roundCardCornersChanged, this,
|
||||
[this](bool _roundCardCorners) {
|
||||
Q_UNUSED(_roundCardCorners);
|
||||
connect(&SettingsCache::instance(), &SettingsCache::roundCardCornersChanged, this, [this](bool _roundCardCorners) {
|
||||
Q_UNUSED(_roundCardCorners);
|
||||
|
||||
update();
|
||||
});
|
||||
update();
|
||||
});
|
||||
}
|
||||
|
||||
DeckViewCard::~DeckViewCard()
|
||||
|
|
@ -101,8 +99,7 @@ void DeckViewCard::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti
|
|||
pen.setJoinStyle(Qt::MiterJoin);
|
||||
pen.setColor(originZone == DECK_ZONE_MAIN ? Qt::green : Qt::red);
|
||||
painter->setPen(pen);
|
||||
qreal cardRadius =
|
||||
SettingsCache::instance().cardsDisplay().getRoundCardCorners() ? 0.05 * (CardDimensions::WIDTH_F - 3) : 0.0;
|
||||
qreal cardRadius = SettingsCache::instance().getRoundCardCorners() ? 0.05 * (CardDimensions::WIDTH_F - 3) : 0.0;
|
||||
painter->drawRoundedRect(QRectF(1.5, 1.5, CardDimensions::WIDTH_F - 3, CardDimensions::HEIGHT_F - 3), cardRadius,
|
||||
cardRadius);
|
||||
painter->restore();
|
||||
|
|
@ -363,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) {
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
#include "deck_view_container.h"
|
||||
|
||||
#include "../../client/settings/cache_settings.h"
|
||||
#include "../../client/settings/shortcuts_settings.h"
|
||||
#include "../../interface/card_picture_loader/card_picture_loader.h"
|
||||
#include "../../interface/deck_loader/deck_loader.h"
|
||||
#include "../../interface/widgets/dialogs/dlg_load_deck.h"
|
||||
|
|
@ -20,8 +19,7 @@
|
|||
#include <libcockatrice/protocol/pb/command_set_sideboard_plan.pb.h>
|
||||
#include <libcockatrice/protocol/pb/response_deck_download.pb.h>
|
||||
#include <libcockatrice/protocol/pending_command.h>
|
||||
#include <libcockatrice/settings/visual_deck_storage_settings.h>
|
||||
#include <libcockatrice/utility/string_limits.h>
|
||||
#include <libcockatrice/utility/trice_limits.h>
|
||||
|
||||
ToggleButton::ToggleButton(QWidget *parent) : QPushButton(parent), state(false)
|
||||
{
|
||||
|
|
@ -97,10 +95,11 @@ DeckViewContainer::DeckViewContainer(int _playerId, TabGame *parent)
|
|||
&DeckViewContainer::refreshShortcuts);
|
||||
refreshShortcuts();
|
||||
|
||||
connect(&SettingsCache::instance().visualDeckStorage(), &VisualDeckStorageSettings::visualDeckStorageInGameChanged,
|
||||
this, &DeckViewContainer::setVisualDeckStorageExists);
|
||||
connect(&SettingsCache::instance(), &SettingsCache::visualDeckStorageInGameChanged, this,
|
||||
&DeckViewContainer::setVisualDeckStorageExists);
|
||||
|
||||
switchToDeckSelectView();
|
||||
generateTutorialSequence();
|
||||
}
|
||||
|
||||
TutorialSequence DeckViewContainer::generateTutorialSequence()
|
||||
|
|
@ -112,7 +111,7 @@ TutorialSequence DeckViewContainer::generateTutorialSequence()
|
|||
{this, tr("There are multiple ways to select a deck:\n\n- From a local file"
|
||||
"\n- From the contents of your clipboard\nFrom an external online service")});
|
||||
|
||||
visualDeckStorageWidget->generateTutorialSequence(deckViewContainerSequence);
|
||||
deckViewContainerSequence = visualDeckStorageWidget->generateTutorialSequence(deckViewContainerSequence);
|
||||
|
||||
return deckViewContainerSequence;
|
||||
}
|
||||
|
|
@ -154,7 +153,7 @@ static void setVisibility(QPushButton *button, bool visible)
|
|||
|
||||
void DeckViewContainer::switchToDeckSelectView()
|
||||
{
|
||||
if (SettingsCache::instance().visualDeckStorage().getVisualDeckStorageInGame()) {
|
||||
if (SettingsCache::instance().getVisualDeckStorageInGame()) {
|
||||
deckView->setHidden(true);
|
||||
|
||||
tryCreateVisualDeckStorageWidget();
|
||||
|
|
@ -225,7 +224,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"));
|
||||
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
#ifndef TABBED_DECK_VIEW_CONTAINER_H
|
||||
#define TABBED_DECK_VIEW_CONTAINER_H
|
||||
#include "../../interface/widgets/general/tutorial/tutorial_controller.h"
|
||||
#include "deck_view_container.h"
|
||||
|
||||
#include <QTabWidget>
|
||||
|
|
@ -20,10 +20,7 @@
|
|||
#include <libcockatrice/deck_list/deck_list.h>
|
||||
#include <libcockatrice/models/database/card_database_model.h>
|
||||
#include <libcockatrice/models/database/token/token_display_model.h>
|
||||
#include <libcockatrice/settings/card_override_settings.h>
|
||||
#include <libcockatrice/settings/interface_settings.h>
|
||||
#include <libcockatrice/settings/layouts_settings.h>
|
||||
#include <libcockatrice/utility/string_limits.h>
|
||||
#include <libcockatrice/utility/trice_limits.h>
|
||||
|
||||
DlgCreateToken::DlgCreateToken(const QStringList &_predefinedTokens, QWidget *parent)
|
||||
: QDialog(parent), predefinedTokens(_predefinedTokens)
|
||||
|
|
@ -189,7 +186,7 @@ void DlgCreateToken::tokenSelectionChanged(const QModelIndex ¤t, const QMo
|
|||
const QChar cardColor = cardInfo->getColorChar();
|
||||
colorEdit->setCurrentIndex(colorEdit->findData(cardColor, Qt::UserRole, Qt::MatchFixedString));
|
||||
ptEdit->setText(cardInfo->getPowTough());
|
||||
if (SettingsCache::instance().userInterface().getAnnotateTokens()) {
|
||||
if (SettingsCache::instance().getAnnotateTokens()) {
|
||||
annotationEdit->setText(cardInfo->getText());
|
||||
}
|
||||
} else {
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
#include <QSpinBox>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
#include <libcockatrice/utility/dice_limits.h>
|
||||
#include <libcockatrice/utility/trice_limits.h>
|
||||
|
||||
DlgRollDice::DlgRollDice(QWidget *parent) : QDialog(parent)
|
||||
{
|
||||
|
|
@ -4,16 +4,16 @@
|
|||
|
||||
#include <libcockatrice/protocol/pb/event_game_joined.pb.h>
|
||||
|
||||
Game::Game(QObject *_parent,
|
||||
bool isLocalGame,
|
||||
Game::Game(TabGame *_tab,
|
||||
QList<AbstractClient *> &_clients,
|
||||
const Event_GameJoined &event,
|
||||
const QMap<int, QString> &_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);
|
||||
|
|
|
|||
|
|
@ -16,8 +16,7 @@ class Game : public AbstractGame
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Game(QObject *parent,
|
||||
bool isLocalGame,
|
||||
Game(TabGame *tab,
|
||||
QList<AbstractClient *> &_clients,
|
||||
const Event_GameJoined &event,
|
||||
const QMap<int, QString> &_roomGameTypes);
|
||||
|
|
|
|||
|
|
@ -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 <libcockatrice/network/client/abstract/abstract_client.h>
|
||||
#include <libcockatrice/protocol/get_pb_extension.h>
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -1,16 +1,8 @@
|
|||
/**
|
||||
* @file game_event_handler.h
|
||||
* @ingroup GameLogic
|
||||
* @brief Game-level command sender and event dispatcher.
|
||||
*
|
||||
* GameEventHandler sends commands initiated by the local client to the server
|
||||
* and processes incoming game-wide events. It bridges the networking layer
|
||||
* (protobuf events received via AbstractClient) with the game model and UI
|
||||
* (GameState, PlayerManager, logging, widgets).
|
||||
*
|
||||
* Player-scoped events are forwarded to PlayerEventHandler instances, while
|
||||
* spectator and global game events are handled directly here.
|
||||
*/
|
||||
//! \todo Document this file.
|
||||
|
||||
#ifndef COCKATRICE_GAME_EVENT_HANDLER_H
|
||||
#define COCKATRICE_GAME_EVENT_HANDLER_H
|
||||
|
|
@ -23,310 +15,91 @@
|
|||
#include <libcockatrice/protocol/pb/serverinfo_player.pb.h>
|
||||
|
||||
class AbstractClient;
|
||||
class AbstractGame;
|
||||
class CommandContainer;
|
||||
class GameCommand;
|
||||
class Response;
|
||||
class GameEventContainer;
|
||||
class GameEventContext;
|
||||
class PendingCommand;
|
||||
class PlayerLogic;
|
||||
class Response;
|
||||
|
||||
class GameCommand;
|
||||
class GameState;
|
||||
class MessageLogWidget;
|
||||
class CommandContainer;
|
||||
class Event_GameJoined;
|
||||
class Event_GameStateChanged;
|
||||
class Event_PlayerPropertiesChanged;
|
||||
class Event_Join;
|
||||
class Event_Leave;
|
||||
class Event_GameHostChanged;
|
||||
class Event_GameClosed;
|
||||
class Event_GameStart;
|
||||
class Event_SetActivePlayer;
|
||||
class Event_SetActivePhase;
|
||||
class Event_Ping;
|
||||
class Event_GameSay;
|
||||
class Event_Kicked;
|
||||
class Event_ReverseTurn;
|
||||
class Event_Ping;
|
||||
class AbstractGame;
|
||||
class PendingCommand;
|
||||
class PlayerLogic;
|
||||
|
||||
inline Q_LOGGING_CATEGORY(GameEventHandlerLog, "game_event_handler");
|
||||
|
||||
/**
|
||||
* @class GameEventHandler
|
||||
* @brief Central dispatcher for game-wide commands and events.
|
||||
*
|
||||
* This class owns no game state itself. Instead, it:
|
||||
* - Sends commands to the server on behalf of local players
|
||||
* - Receives and dispatches server-side game events
|
||||
* - Updates the game model indirectly via Player, GameState, and PlayerManager
|
||||
* - Emits high-level signals for UI updates and logging
|
||||
*/
|
||||
class GameEventHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
/** Pointer to the owning game instance. */
|
||||
AbstractGame *game;
|
||||
|
||||
public:
|
||||
/** @name Construction
|
||||
* Lifecycle and ownership.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Construct a GameEventHandler.
|
||||
*
|
||||
* The handler is owned by the AbstractGame instance and uses it to
|
||||
* access the game state, players, and network clients.
|
||||
*
|
||||
* @param _game Owning game instance (also used as QObject parent).
|
||||
*/
|
||||
explicit GameEventHandler(AbstractGame *_game);
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @name Outgoing game commands
|
||||
* Commands initiated locally and sent to the server.
|
||||
*
|
||||
* These methods construct and send protobuf commands corresponding
|
||||
* to user actions in the UI.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @brief Request advancing the game to the next turn. */
|
||||
void handleNextTurn();
|
||||
|
||||
/** @brief Request reversing the current turn order. */
|
||||
void handleReverseTurn();
|
||||
|
||||
/** @brief Concede the game for the currently active local player. */
|
||||
void handleActiveLocalPlayerConceded();
|
||||
|
||||
/** @brief Undo a previous concede for the active local player. */
|
||||
void handleActiveLocalPlayerUnconceded();
|
||||
|
||||
/**
|
||||
* @brief Set the active phase of the game.
|
||||
*
|
||||
* Typically triggered by the active player selecting a new phase.
|
||||
*
|
||||
* @param phase Phase identifier.
|
||||
*/
|
||||
void handleActivePhaseChanged(int phase);
|
||||
|
||||
/** @brief Leave the current game session. */
|
||||
void handleGameLeft();
|
||||
|
||||
/**
|
||||
* @brief Send a chat message to all players and spectators.
|
||||
*
|
||||
* @param chatMessage Message text.
|
||||
*/
|
||||
void handleChatMessageSent(const QString &chatMessage);
|
||||
void handleArrowDeletion(int arrowId);
|
||||
|
||||
/**
|
||||
* @brief Delete an existing arrow.
|
||||
*
|
||||
* @param arrowId Unique identifier of the arrow to delete.
|
||||
*/
|
||||
void handleArrowDeletion(int creatorId, int arrowId);
|
||||
void handleArrowDeletionFinished(const Response &response, int creatorId, int arrowId);
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @name Incoming event processing
|
||||
* Entry points for server-sent events.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Process a container of game events received from the server.
|
||||
*
|
||||
* This is the main dispatch function for incoming game events.
|
||||
* Events are routed to spectator handlers, game-level handlers,
|
||||
* or forwarded to PlayerEventHandler instances as appropriate.
|
||||
*
|
||||
* @param cont Game event container from the server.
|
||||
* @param client Client that received the container.
|
||||
* @param options Processing flags (e.g. silent, replay).
|
||||
*/
|
||||
void
|
||||
processGameEventContainer(const GameEventContainer &cont, AbstractClient *client, EventProcessingOptions options);
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @name Command preparation helpers
|
||||
* Internal helpers for building command containers.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Wrap a single protobuf command in a PendingCommand.
|
||||
*
|
||||
* @param cmd Protobuf command message.
|
||||
* @return Newly allocated PendingCommand (caller takes ownership).
|
||||
*/
|
||||
PendingCommand *prepareGameCommand(const ::google::protobuf::Message &cmd);
|
||||
|
||||
/**
|
||||
* @brief Wrap multiple protobuf commands in a single PendingCommand.
|
||||
*
|
||||
* Ownership of the messages in cmdList is transferred to the handler.
|
||||
*
|
||||
* @param cmdList List of protobuf command messages.
|
||||
* @return Newly allocated PendingCommand.
|
||||
*/
|
||||
PendingCommand *prepareGameCommand(const QList<const ::google::protobuf::Message *> &cmdList);
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @name Spectator event handlers
|
||||
* Events originating from spectators.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Handle a spectator chat message.
|
||||
*/
|
||||
void eventSpectatorSay(const Event_GameSay &event, int eventPlayerId, const GameEventContext &context);
|
||||
|
||||
/**
|
||||
* @brief Handle a spectator leaving the game.
|
||||
*/
|
||||
void eventSpectatorLeave(const Event_Leave &event, int eventPlayerId, const GameEventContext &context);
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @name Game state event handlers
|
||||
* Events that affect global game state.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Handle a full game state update from the server.
|
||||
*
|
||||
* Used during game startup, reconnection, and resynchronization.
|
||||
*/
|
||||
void eventGameStateChanged(const Event_GameStateChanged &event, int eventPlayerId, const GameEventContext &context);
|
||||
|
||||
/**
|
||||
* @brief Update card attachment relationships for all players.
|
||||
*
|
||||
* Called after a game state update to ensure attachments are resolved
|
||||
* consistently across all zones.
|
||||
*/
|
||||
void processCardAttachmentsForPlayers(const Event_GameStateChanged &event);
|
||||
|
||||
/** @brief Handle a change in game host. */
|
||||
void eventGameHostChanged(const Event_GameHostChanged &event, int eventPlayerId, const GameEventContext &context);
|
||||
|
||||
/** @brief Handle the game being closed by the server. */
|
||||
void eventGameClosed(const Event_GameClosed &event, int eventPlayerId, const GameEventContext &context);
|
||||
|
||||
/** @brief Handle a change of the active player. */
|
||||
void eventSetActivePlayer(const Event_SetActivePlayer &event, int eventPlayerId, const GameEventContext &context);
|
||||
|
||||
/** @brief Handle a change of the active phase. */
|
||||
void eventSetActivePhase(const Event_SetActivePhase &event, int eventPlayerId, const GameEventContext &context);
|
||||
|
||||
/** @brief Handle a turn reversal event. */
|
||||
void eventReverseTurn(const Event_ReverseTurn &event, int eventPlayerId, const GameEventContext &context);
|
||||
|
||||
/** @brief Handle ping / latency updates. */
|
||||
void eventPing(const Event_Ping &event, int eventPlayerId, const GameEventContext &context);
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @name Player lifecycle and property handlers
|
||||
* Events related to players joining, leaving, or changing state.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Handle updates to a player's properties.
|
||||
*
|
||||
* Includes readiness, concede state, deck selection, sideboard lock,
|
||||
* and connection state changes.
|
||||
*/
|
||||
void eventPlayerPropertiesChanged(const Event_PlayerPropertiesChanged &event,
|
||||
int eventPlayerId,
|
||||
const GameEventContext &context);
|
||||
|
||||
/** @brief Handle a player or spectator joining the game. */
|
||||
void eventJoin(const Event_Join &event, int eventPlayerId, const GameEventContext &context);
|
||||
|
||||
/** @brief Handle a player leaving the game. */
|
||||
void eventLeave(const Event_Leave &event, int eventPlayerId, const GameEventContext &context);
|
||||
|
||||
/** @brief Handle the local player being kicked from the game. */
|
||||
void eventKicked(const Event_Kicked &event, int eventPlayerId, const GameEventContext &context);
|
||||
|
||||
/**
|
||||
* @brief Convert a leave reason enum to a human-readable string.
|
||||
*/
|
||||
QString getLeaveReason(Event_Leave::LeaveReason reason);
|
||||
void eventKicked(const Event_Kicked &event, int eventPlayerId, const GameEventContext &context);
|
||||
void eventGameHostChanged(const Event_GameHostChanged &event, int eventPlayerId, const GameEventContext &context);
|
||||
void eventGameClosed(const Event_GameClosed &event, int eventPlayerId, const GameEventContext &context);
|
||||
|
||||
/** @} */
|
||||
void eventSetActivePlayer(const Event_SetActivePlayer &event, int eventPlayerId, const GameEventContext &context);
|
||||
void eventSetActivePhase(const Event_SetActivePhase &event, int eventPlayerId, const GameEventContext &context);
|
||||
void eventPing(const Event_Ping &event, int eventPlayerId, const GameEventContext &context);
|
||||
void eventReverseTurn(const Event_ReverseTurn &event, int eventPlayerId, const GameEventContext & /*context*/);
|
||||
|
||||
public slots:
|
||||
/** @name Command dispatch slots
|
||||
* Low-level command transmission.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Send a prepared PendingCommand.
|
||||
*
|
||||
* @param pend Pending command to send.
|
||||
* @param playerId Player whose client should send the command.
|
||||
*/
|
||||
void sendGameCommand(PendingCommand *pend, int playerId = -1);
|
||||
|
||||
/**
|
||||
* @brief Send a single protobuf command.
|
||||
*
|
||||
* @param command Protobuf command message.
|
||||
* @param playerId Player whose client should send the command.
|
||||
*/
|
||||
void sendGameCommand(const ::google::protobuf::Message &command, int playerId = -1);
|
||||
|
||||
/**
|
||||
* @brief Called when a PendingCommand finishes execution.
|
||||
*
|
||||
* Used to detect server-side errors such as chat flood protection.
|
||||
*/
|
||||
void commandFinished(const Response &response);
|
||||
|
||||
/** @} */
|
||||
void
|
||||
processGameEventContainer(const GameEventContainer &cont, AbstractClient *client, EventProcessingOptions options);
|
||||
PendingCommand *prepareGameCommand(const ::google::protobuf::Message &cmd);
|
||||
PendingCommand *prepareGameCommand(const QList<const ::google::protobuf::Message *> &cmdList);
|
||||
public slots:
|
||||
void sendGameCommand(PendingCommand *pend, int playerId = -1);
|
||||
void sendGameCommand(const ::google::protobuf::Message &command, int playerId = -1);
|
||||
|
||||
signals:
|
||||
/** @name Core state signals
|
||||
* @{
|
||||
*/
|
||||
|
||||
void emitUserEvent();
|
||||
void containerProcessingStarted(GameEventContext context);
|
||||
void containerProcessingDone();
|
||||
void gameFlooded();
|
||||
void setContextJudgeName(QString judgeName);
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @name Player and spectator signals
|
||||
* @{
|
||||
*/
|
||||
|
||||
void addPlayerToAutoCompleteList(QString playerName);
|
||||
void localPlayerDeckSelected(PlayerLogic *localPlayer, int playerId, ServerInfo_Player playerInfo);
|
||||
void remotePlayerDeckSelected(QString deckList, int playerId, QString playerName);
|
||||
void remotePlayersDecksSelected(QVector<QPair<int, QPair<QString, QString>>> opponentDecks);
|
||||
void localPlayerSideboardLocked(int playerId, bool sideboardLocked);
|
||||
void localPlayerReadyStateChanged(int playerId, bool ready);
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @name Game flow signals
|
||||
* @{
|
||||
*/
|
||||
|
||||
void gameStopped();
|
||||
void gameClosed();
|
||||
void playerPropertiesChanged(const ServerInfo_PlayerProperties &prop, int playerId);
|
||||
|
|
@ -335,15 +108,10 @@ signals:
|
|||
void playerKicked();
|
||||
void spectatorJoined(const ServerInfo_PlayerProperties &spectatorInfo);
|
||||
void spectatorLeft(int leavingSpectatorId);
|
||||
void arrowDeleted(int creatorId, int arrowId);
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @name Logging signals
|
||||
* Signals consumed by MessageLogWidget.
|
||||
* @{
|
||||
*/
|
||||
|
||||
void gameFlooded();
|
||||
void containerProcessingStarted(GameEventContext context);
|
||||
void setContextJudgeName(QString judgeName);
|
||||
void containerProcessingDone();
|
||||
void logSpectatorSay(ServerInfo_User userInfo, QString message);
|
||||
void logSpectatorLeave(QString name, QString reason);
|
||||
void logGameStart();
|
||||
|
|
@ -362,8 +130,6 @@ signals:
|
|||
void logActivePhaseChanged(int activePhase);
|
||||
void logConcede(int playerId);
|
||||
void logUnconcede(int playerId);
|
||||
|
||||
/** @} */
|
||||
};
|
||||
|
||||
#endif // COCKATRICE_GAME_EVENT_HANDLER_H
|
||||
|
|
|
|||
|
|
@ -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 <QBasicTimer>
|
||||
#include <QDebug>
|
||||
|
|
@ -19,7 +15,6 @@
|
|||
#include <QGraphicsView>
|
||||
#include <QSet>
|
||||
#include <QtMath>
|
||||
#include <libcockatrice/settings/interface_settings.h>
|
||||
#include <libcockatrice/utility/zone_names.h>
|
||||
#include <numeric>
|
||||
|
||||
|
|
@ -37,7 +32,7 @@ GameScene::GameScene(PhasesToolbar *_phasesToolbar, QObject *parent)
|
|||
{
|
||||
animationTimer = new QBasicTimer;
|
||||
addItem(phasesToolbar);
|
||||
connect(&SettingsCache::instance().userInterface(), &InterfaceSettings::minPlayersForMultiColumnLayoutChanged, this,
|
||||
connect(&SettingsCache::instance(), &SettingsCache::minPlayersForMultiColumnLayoutChanged, this,
|
||||
&GameScene::rearrange);
|
||||
|
||||
rearrange();
|
||||
|
|
@ -47,17 +42,6 @@ GameScene::~GameScene()
|
|||
{
|
||||
delete animationTimer;
|
||||
|
||||
// Delete all ArrowItems before QGraphicsScene's base destructor runs.
|
||||
// QGraphicsScene::~QGraphicsScene() destroys items in arbitrary order.
|
||||
// If a PlayerTarget is destroyed before an ArrowItem pointing to it,
|
||||
// ArrowItem::onTargetDestroyed fires and emits on the partially-destroyed
|
||||
// GameScene, causing a segfault.
|
||||
for (auto *item : items()) {
|
||||
if (auto *arrow = qgraphicsitem_cast<ArrowItem *>(item)) {
|
||||
delete arrow;
|
||||
}
|
||||
}
|
||||
|
||||
// DO NOT call clearViews() here
|
||||
// clearViews calls close() on the zoneViews, which sends signals; sending signals in destructors leads to segfaults
|
||||
// deleteLater() deletes the zoneView without allowing it to send signals
|
||||
|
|
@ -88,80 +72,6 @@ QList<CardItem *> GameScene::selectedCards() const
|
|||
return selectedCards;
|
||||
}
|
||||
|
||||
void GameScene::onCardSelectionChanged(AbstractCardItem *abstractCard, bool selected)
|
||||
{
|
||||
CardItem *card = qobject_cast<CardItem *>(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<CardItem *>(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.
|
||||
|
|
@ -172,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) {
|
||||
|
|
@ -185,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);
|
||||
|
||||
|
|
@ -217,7 +123,6 @@ void GameScene::removePlayer(PlayerLogic *player)
|
|||
}
|
||||
auto *view = playerViews.take(player->getPlayerInfo()->getId());
|
||||
removeItem(view);
|
||||
view->deleteLater();
|
||||
rearrange();
|
||||
}
|
||||
|
||||
|
|
@ -299,7 +204,7 @@ QList<PlayerLogic *> 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()) {
|
||||
|
|
@ -336,7 +241,7 @@ QList<PlayerLogic *> GameScene::rotatePlayers(const QList<PlayerLogic *> &active
|
|||
|
||||
int GameScene::determineColumnCount(int playerCount)
|
||||
{
|
||||
return playerCount < SettingsCache::instance().userInterface().getMinPlayersForMultiColumnLayout() ? 1 : 2;
|
||||
return playerCount < SettingsCache::instance().getMinPlayersForMultiColumnLayout() ? 1 : 2;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -370,12 +275,12 @@ QSizeF GameScene::computeSceneSizeAndPlayerLayout(const QList<PlayerLogic *> &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());
|
||||
}
|
||||
|
|
@ -462,62 +367,62 @@ void GameScene::resizeColumnsAndPlayers(const QList<qreal> &minWidthByColumn, qr
|
|||
}
|
||||
}
|
||||
|
||||
void GameScene::addArrow(QSharedPointer<ArrowData> 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<ArrowItem *> toDelete;
|
||||
for (auto *arrow : arrowRegistry.all()) {
|
||||
for (auto *arrow : arrowRegistry.values()) {
|
||||
if (arrow->getStartItem() == card || arrow->getTargetItem() == card) {
|
||||
if (sameZone) {
|
||||
arrow->updatePath();
|
||||
|
|
@ -527,22 +432,15 @@ 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)) {
|
||||
if (auto *arrow = arrowRegistry.take(playerId, arrowId)) {
|
||||
arrow->delArrow();
|
||||
for (auto *arrow : arrowRegistry.values()) {
|
||||
if (arrow->getPlayer()->getPlayerInfo()->getId() == playerId) {
|
||||
emit requestArrowDeletion(arrow->getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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 <QGraphicsScene>
|
||||
#include <QList>
|
||||
|
|
@ -46,7 +45,7 @@ private:
|
|||
PhasesToolbar *phasesToolbar; ///< Toolbar showing game phases
|
||||
QMap<int, PlayerGraphicsItem *> playerViews; ///< ID lookup for player graphics items
|
||||
QList<QList<PlayerGraphicsItem *>> playersByColumn; ///< Players organized by column
|
||||
ArrowRegistry arrowRegistry; ///< ID registry for arrow graphics items
|
||||
QMap<int, ArrowItem *> arrowRegistry; ///< ID registry for arrow graphics items
|
||||
QList<ZoneViewWidget *> zoneViews; ///< Active zone view widgets
|
||||
QSize viewSize; ///< Current view size
|
||||
QPointer<CardItem> hoveredCard; ///< Currently hovered card
|
||||
|
|
@ -97,16 +96,6 @@ public:
|
|||
*/
|
||||
void removePlayer(PlayerLogic *player);
|
||||
|
||||
QMap<int, PlayerGraphicsItem *> 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<ArrowData> 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
|
||||
188
cockatrice/src/game/game_view.cpp
Normal file
188
cockatrice/src/game/game_view.cpp
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
#include "game_view.h"
|
||||
|
||||
#include "../client/settings/cache_settings.h"
|
||||
#include "game_scene.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QLabel>
|
||||
#include <QResizeEvent>
|
||||
#include <QRubberBand>
|
||||
|
||||
// QRubberBand calls raise() in showEvent() and changeEvent() to stay on top of siblings.
|
||||
// This subclass disables that behavior so dragCountLabel can appear above it.
|
||||
class SelectionRubberBand : public QRubberBand
|
||||
{
|
||||
public:
|
||||
using QRubberBand::QRubberBand;
|
||||
|
||||
protected:
|
||||
void showEvent(QShowEvent *event) override
|
||||
{
|
||||
QWidget::showEvent(event); // Skip QRubberBand's raise()
|
||||
}
|
||||
|
||||
void changeEvent(QEvent *event) override
|
||||
{
|
||||
if (event->type() == QEvent::ZOrderChange) {
|
||||
return; // Skip QRubberBand's raise() on z-order changes
|
||||
}
|
||||
QRubberBand::changeEvent(event);
|
||||
}
|
||||
};
|
||||
|
||||
GameView::GameView(GameScene *scene, QWidget *parent) : QGraphicsView(scene, parent), rubberBand(0)
|
||||
{
|
||||
setBackgroundBrush(QBrush(QColor(0, 0, 0)));
|
||||
setRenderHints(QPainter::TextAntialiasing | QPainter::Antialiasing);
|
||||
setFocusPolicy(Qt::ClickFocus);
|
||||
setViewportUpdateMode(BoundingRectViewportUpdate);
|
||||
|
||||
connect(scene, &GameScene::sceneRectChanged, this, &GameView::updateSceneRect);
|
||||
|
||||
connect(scene, &GameScene::sigStartRubberBand, this, &GameView::startRubberBand);
|
||||
connect(scene, &GameScene::sigResizeRubberBand, this, &GameView::resizeRubberBand);
|
||||
connect(scene, &GameScene::sigStopRubberBand, this, &GameView::stopRubberBand);
|
||||
connect(scene, &QGraphicsScene::selectionChanged, this, [this]() { updateTotalSelectionCount(); });
|
||||
|
||||
aCloseMostRecentZoneView = new QAction(this);
|
||||
|
||||
connect(aCloseMostRecentZoneView, &QAction::triggered, scene, &GameScene::closeMostRecentZoneView);
|
||||
addAction(aCloseMostRecentZoneView);
|
||||
connect(&SettingsCache::instance().shortcuts(), &ShortcutsSettings::shortCutChanged, this,
|
||||
&GameView::refreshShortcuts);
|
||||
refreshShortcuts();
|
||||
rubberBand = new SelectionRubberBand(QRubberBand::Rectangle, this);
|
||||
|
||||
const QString countLabelStyle = "color: white; "
|
||||
"font-size: 14px; "
|
||||
"font-weight: bold; "
|
||||
"background-color: rgba(0, 0, 0, 160); "
|
||||
"border-radius: 3px; "
|
||||
"padding: 1px 2px;";
|
||||
|
||||
dragCountLabel = new QLabel(this);
|
||||
dragCountLabel->setStyleSheet(countLabelStyle);
|
||||
dragCountLabel->hide();
|
||||
dragCountLabel->raise();
|
||||
|
||||
totalCountLabel = new QLabel(this);
|
||||
totalCountLabel->setStyleSheet(countLabelStyle);
|
||||
totalCountLabel->hide();
|
||||
}
|
||||
|
||||
void GameView::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
QGraphicsView::resizeEvent(event);
|
||||
|
||||
GameScene *s = dynamic_cast<GameScene *>(scene());
|
||||
if (s) {
|
||||
s->processViewSizeChange(event->size());
|
||||
}
|
||||
|
||||
updateSceneRect(scene()->sceneRect());
|
||||
updateTotalSelectionCount(event->size());
|
||||
}
|
||||
|
||||
void GameView::updateSceneRect(const QRectF &rect)
|
||||
{
|
||||
fitInView(rect, Qt::KeepAspectRatio);
|
||||
}
|
||||
|
||||
void GameView::startRubberBand(const QPointF &_selectionOrigin)
|
||||
{
|
||||
if (!rubberBand) {
|
||||
return;
|
||||
}
|
||||
|
||||
selectionOrigin = _selectionOrigin;
|
||||
rubberBand->setGeometry(QRect(mapFromScene(selectionOrigin), QSize(0, 0)));
|
||||
rubberBand->show();
|
||||
}
|
||||
|
||||
void GameView::resizeRubberBand(const QPointF &cursorPoint, int selectedCount)
|
||||
{
|
||||
if (!rubberBand) {
|
||||
return;
|
||||
}
|
||||
|
||||
constexpr int kLabelPaddingInPixels = 4;
|
||||
|
||||
QPoint cursor = cursorPoint.toPoint();
|
||||
QRect rect = QRect(mapFromScene(selectionOrigin), cursor).normalized();
|
||||
rubberBand->setGeometry(rect);
|
||||
|
||||
if (!SettingsCache::instance().getShowDragSelectionCount()) {
|
||||
dragCountLabel->hide();
|
||||
return;
|
||||
}
|
||||
|
||||
if (selectedCount > 0) {
|
||||
dragCountLabel->setText(QString::number(selectedCount));
|
||||
dragCountLabel->adjustSize();
|
||||
QSize labelSize = dragCountLabel->size();
|
||||
|
||||
if (rect.width() < labelSize.width() + 2 * kLabelPaddingInPixels ||
|
||||
rect.height() < labelSize.height() + 2 * kLabelPaddingInPixels) {
|
||||
dragCountLabel->hide();
|
||||
return;
|
||||
}
|
||||
|
||||
const int minX = rect.left() + kLabelPaddingInPixels;
|
||||
const int minY = rect.top() + kLabelPaddingInPixels;
|
||||
|
||||
int x = qMax(minX, cursor.x() - labelSize.width() - kLabelPaddingInPixels);
|
||||
int y = qMax(minY, cursor.y() - labelSize.height() - kLabelPaddingInPixels);
|
||||
|
||||
bool isAtTopLeftCorner = (x == minX) && (y == minY);
|
||||
if (isAtTopLeftCorner) {
|
||||
constexpr int kCursorClearanceInPixels = 16;
|
||||
x = qMin(cursor.x() + kCursorClearanceInPixels, rect.right() - labelSize.width() - kLabelPaddingInPixels);
|
||||
}
|
||||
|
||||
dragCountLabel->move(x, y);
|
||||
dragCountLabel->show();
|
||||
} else {
|
||||
dragCountLabel->hide();
|
||||
}
|
||||
}
|
||||
|
||||
void GameView::stopRubberBand()
|
||||
{
|
||||
if (!rubberBand) {
|
||||
return;
|
||||
}
|
||||
|
||||
rubberBand->hide();
|
||||
dragCountLabel->hide();
|
||||
}
|
||||
|
||||
void GameView::refreshShortcuts()
|
||||
{
|
||||
aCloseMostRecentZoneView->setShortcuts(
|
||||
SettingsCache::instance().shortcuts().getShortcut("Player/aCloseMostRecentZoneView"));
|
||||
}
|
||||
|
||||
void GameView::updateTotalSelectionCount(const QSize &viewSize)
|
||||
{
|
||||
if (!SettingsCache::instance().getShowTotalSelectionCount()) {
|
||||
totalCountLabel->hide();
|
||||
return;
|
||||
}
|
||||
|
||||
int count = scene()->selectedItems().count();
|
||||
|
||||
if (count > 1) {
|
||||
totalCountLabel->setText(QString::number(count));
|
||||
totalCountLabel->adjustSize();
|
||||
|
||||
constexpr int kMarginInPixels = 10;
|
||||
int availableWidth = viewSize.isValid() ? viewSize.width() : viewport()->width();
|
||||
int availableHeight = viewSize.isValid() ? viewSize.height() : viewport()->height();
|
||||
int x = availableWidth - totalCountLabel->width() - kMarginInPixels;
|
||||
int y = availableHeight - totalCountLabel->height() - kMarginInPixels;
|
||||
totalCountLabel->move(x, y);
|
||||
totalCountLabel->show();
|
||||
} else {
|
||||
totalCountLabel->hide();
|
||||
}
|
||||
}
|
||||
|
|
@ -7,12 +7,9 @@
|
|||
#ifndef GAMEVIEW_H
|
||||
#define GAMEVIEW_H
|
||||
|
||||
#include "tally/tally.h"
|
||||
|
||||
#include <QGraphicsView>
|
||||
|
||||
class GameScene;
|
||||
class QGridLayout;
|
||||
class QLabel;
|
||||
class QRubberBand;
|
||||
|
||||
|
|
@ -24,13 +21,7 @@ private:
|
|||
QRubberBand *rubberBand;
|
||||
QLabel *dragCountLabel;
|
||||
QLabel *totalCountLabel;
|
||||
QWidget *tallyContainer;
|
||||
QGridLayout *tallyLayout;
|
||||
QPointF selectionOrigin;
|
||||
QList<TallyRow> cachedTallyRows; ///< Cached entries to avoid redundant rebuilds
|
||||
|
||||
QSize rebuildTallyLabels(const QList<TallyRow> &entries);
|
||||
void clearTallyLabels();
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
|
|
@ -40,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);
|
||||
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
#include "hand_counter.h"
|
||||
|
||||
#include "zones/card_zone.h"
|
||||
#include "../game_graphics/zones/card_zone.h"
|
||||
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
#include <QPainter>
|
||||
|
|
@ -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 <QString>
|
||||
|
||||
|
|
@ -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 <libcockatrice/protocol/pb/context_move_card.pb.h>
|
||||
#include <libcockatrice/protocol/pb/context_mulligan.pb.h>
|
||||
#include <libcockatrice/utility/zone_names.h>
|
||||
|
|
@ -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("<font class=\"blue\">" + QString::number(delta) + "</font>")
|
||||
.arg("<font color=\"" + hex + "\">●</font>")
|
||||
.arg(cardCounterSettings.displayName(counterId))
|
||||
.arg(cardLink(std::move(cardName)))
|
||||
.arg(value));
|
||||
|
|
@ -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;
|
||||
|
|
@ -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 <QFrame>
|
||||
#include <QGraphicsObject>
|
||||
|
|
@ -1,124 +1,94 @@
|
|||
#include "card_menu.h"
|
||||
|
||||
#include "../../../client/settings/card_counter_settings.h"
|
||||
#include "../../../client/settings/shortcuts_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 <QPainter>
|
||||
#include <libcockatrice/card/database/card_database_manager.h>
|
||||
#include <libcockatrice/card/relation/card_relation.h>
|
||||
#include <libcockatrice/utility/zone_names.h>
|
||||
|
||||
/**
|
||||
* @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 <typename Slot>
|
||||
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>(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<PlayerLogic *> &players = player->getLogic()->getGame()->getPlayerManager()->getPlayers().values();
|
||||
auto playerActions = player->getPlayerActions();
|
||||
|
||||
const QList<PlayerLogic *> &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();
|
||||
|
|
@ -130,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<ZoneViewZoneLogic *>(card->getZone())) {
|
||||
if (view->getRevealZone()) {
|
||||
if (view->getWriteableRevealZone()) {
|
||||
|
|
@ -314,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);
|
||||
|
|
@ -401,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); });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -463,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);
|
||||
}
|
||||
|
||||
|
|
@ -473,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);
|
||||
}
|
||||
|
|
@ -8,20 +8,15 @@
|
|||
#define COCKATRICE_CARD_MENU_H
|
||||
|
||||
#include <QMenu>
|
||||
#include <libcockatrice/utility/card_ref.h>
|
||||
|
||||
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<QAction *> aAddCounter, aSetCounter, aRemoveCounter;
|
||||
|
||||
private:
|
||||
PlayerGraphicsItem *player;
|
||||
PlayerLogic *player;
|
||||
const CardItem *card;
|
||||
QList<QPair<QString, int>> playersInfo;
|
||||
bool shortcutsActive;
|
||||
|
|
@ -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); });
|
||||
}
|
||||
|
|
@ -11,12 +11,12 @@
|
|||
|
||||
#include <QMenu>
|
||||
|
||||
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);
|
||||
|
|
@ -1,23 +1,21 @@
|
|||
#include "grave_menu.h"
|
||||
|
||||
#include "../../../client/settings/shortcuts_settings.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 <QAction>
|
||||
#include <QMenu>
|
||||
#include <libcockatrice/utility/zone_names.h>
|
||||
|
||||
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);
|
||||
|
|
@ -38,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<QVariant>() << ZoneNames::DECK << 0);
|
||||
|
||||
|
|
@ -62,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);
|
||||
|
|
@ -78,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());
|
||||
|
|
@ -92,7 +90,7 @@ void GraveyardMenu::populateRevealRandomMenuWithActivePlayers()
|
|||
void GraveyardMenu::onRevealRandomTriggered()
|
||||
{
|
||||
if (auto *a = qobject_cast<QAction *>(sender())) {
|
||||
player->getLogic()->getPlayerActions()->actRevealRandomGraveyardCard(a->data().toInt());
|
||||
player->getPlayerActions()->actRevealRandomGraveyardCard(a->data().toInt());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -102,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"));
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
#include <QAction>
|
||||
#include <QMenu>
|
||||
|
||||
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
|
||||
|
|
@ -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 <QAction>
|
||||
#include <QMenu>
|
||||
#include <libcockatrice/utility/zone_names.h>
|
||||
|
||||
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<QVariant>() << 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<QVariant>() << 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);
|
||||
}
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
#include <QAction>
|
||||
#include <QMenu>
|
||||
|
||||
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;
|
||||
|
|
@ -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 <QAction>
|
||||
#include <QGraphicsView>
|
||||
#include <QMenu>
|
||||
|
||||
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<QAction *>(sender())) {
|
||||
player->getLogic()->getPlayerActions()->actRevealLibrary(a->data().toInt());
|
||||
player->getPlayerActions()->actRevealLibrary(a->data().toInt());
|
||||
}
|
||||
}
|
||||
|
||||
void LibraryMenu::onLendLibraryTriggered()
|
||||
{
|
||||
if (auto *a = qobject_cast<QAction *>(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<QAction *>(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;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue