mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2025-12-21 14:50:26 -08:00
Compare commits
1 Commits
2024-06-24
...
zach/fix_o
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
316c9d13a0 |
@@ -9,7 +9,6 @@ RUN pacman --sync --refresh --sysupgrade --needed --noconfirm \
|
||||
mariadb-libs \
|
||||
protobuf \
|
||||
qt6-base \
|
||||
qt6-imageformats \
|
||||
qt6-multimedia \
|
||||
qt6-svg \
|
||||
qt6-tools \
|
||||
|
||||
25
.ci/Debian10/Dockerfile
Normal file
25
.ci/Debian10/Dockerfile
Normal file
@@ -0,0 +1,25 @@
|
||||
FROM debian:10
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
build-essential \
|
||||
ccache \
|
||||
clang-format \
|
||||
cmake \
|
||||
file \
|
||||
g++ \
|
||||
git \
|
||||
liblzma-dev \
|
||||
libmariadb-dev-compat \
|
||||
libprotobuf-dev \
|
||||
libqt5multimedia5-plugins \
|
||||
libqt5sql5-mysql \
|
||||
libqt5svg5-dev \
|
||||
libqt5websockets5-dev \
|
||||
protobuf-compiler \
|
||||
qt5-default \
|
||||
qtbase5-dev \
|
||||
qtmultimedia5-dev \
|
||||
qttools5-dev \
|
||||
qttools5-dev-tools \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
@@ -17,7 +17,6 @@ RUN apt-get update && \
|
||||
libqt5svg5-dev \
|
||||
libqt5websockets5-dev \
|
||||
protobuf-compiler \
|
||||
qt5-image-formats-plugins \
|
||||
qtmultimedia5-dev \
|
||||
qttools5-dev \
|
||||
qttools5-dev-tools \
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
FROM debian:12
|
||||
|
||||
RUN apt-get update && \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||
build-essential \
|
||||
ccache \
|
||||
clang-format \
|
||||
cmake \
|
||||
file \
|
||||
g++ \
|
||||
git \
|
||||
libgl-dev \
|
||||
liblzma-dev \
|
||||
libmariadb-dev-compat \
|
||||
libprotobuf-dev \
|
||||
libqt6multimedia6 \
|
||||
libqt6sql6-mysql \
|
||||
qt6-svg-dev \
|
||||
qt6-websockets-dev \
|
||||
protobuf-compiler \
|
||||
qt6-image-formats-plugins \
|
||||
qt6-l10n-tools \
|
||||
qt6-multimedia-dev \
|
||||
qt6-tools-dev \
|
||||
qt6-tools-dev-tools \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
21
.ci/Fedora35/Dockerfile
Normal file
21
.ci/Fedora35/Dockerfile
Normal file
@@ -0,0 +1,21 @@
|
||||
FROM fedora:35
|
||||
|
||||
RUN dnf install -y \
|
||||
@development-tools \
|
||||
ccache \
|
||||
cmake \
|
||||
desktop-file-utils \
|
||||
file \
|
||||
gcc-c++ \
|
||||
git \
|
||||
hicolor-icon-theme \
|
||||
libappstream-glib \
|
||||
mariadb-devel \
|
||||
protobuf-devel \
|
||||
qt5-{qttools,qtsvg,qtmultimedia,qtwebsockets}-devel \
|
||||
rpm-build \
|
||||
sqlite-devel \
|
||||
wget \
|
||||
xz-devel \
|
||||
zlib-devel \
|
||||
&& dnf clean all
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM fedora:39
|
||||
FROM fedora:36
|
||||
|
||||
RUN dnf install -y \
|
||||
ccache \
|
||||
@@ -8,7 +8,6 @@ RUN dnf install -y \
|
||||
mariadb-devel \
|
||||
protobuf-devel \
|
||||
qt6-{qttools,qtsvg,qtmultimedia,qtwebsockets}-devel \
|
||||
qt6-qtimageformats \
|
||||
rpm-build \
|
||||
xz-devel \
|
||||
zlib-devel \
|
||||
@@ -1,15 +0,0 @@
|
||||
FROM fedora:40
|
||||
|
||||
RUN dnf install -y \
|
||||
ccache \
|
||||
cmake \
|
||||
gcc-c++ \
|
||||
git \
|
||||
mariadb-devel \
|
||||
protobuf-devel \
|
||||
qt6-{qttools,qtsvg,qtmultimedia,qtwebsockets}-devel \
|
||||
qt6-qtimageformats \
|
||||
rpm-build \
|
||||
xz-devel \
|
||||
zlib-devel \
|
||||
&& dnf clean all
|
||||
@@ -17,7 +17,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
libqt5websockets5-dev \
|
||||
protobuf-compiler \
|
||||
qt5-default \
|
||||
qt5-image-formats-plugins \
|
||||
qtmultimedia5-dev \
|
||||
qttools5-dev \
|
||||
qttools5-dev-tools \
|
||||
|
||||
@@ -18,7 +18,6 @@ RUN apt-get update && \
|
||||
libqt5websockets5-dev \
|
||||
protobuf-compiler \
|
||||
qt5-default \
|
||||
qt5-image-formats-plugins \
|
||||
qtmultimedia5-dev \
|
||||
qttools5-dev \
|
||||
qttools5-dev-tools \
|
||||
|
||||
@@ -18,7 +18,6 @@ RUN apt-get update && \
|
||||
libqt6svg6-dev \
|
||||
libqt6websockets6-dev \
|
||||
protobuf-compiler \
|
||||
qt6-image-formats-plugins \
|
||||
qt6-l10n-tools \
|
||||
qt6-multimedia-dev \
|
||||
qt6-tools-dev \
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
FROM ubuntu:noble
|
||||
|
||||
RUN apt-get update && \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||
build-essential \
|
||||
ccache \
|
||||
clang-format \
|
||||
cmake \
|
||||
file \
|
||||
g++ \
|
||||
git \
|
||||
libgl-dev \
|
||||
liblzma-dev \
|
||||
libmariadb-dev-compat \
|
||||
libprotobuf-dev \
|
||||
libqt6multimedia6 \
|
||||
libqt6sql6-mysql \
|
||||
qt6-svg-dev \
|
||||
qt6-websockets-dev \
|
||||
protobuf-compiler \
|
||||
qt6-image-formats-plugins \
|
||||
qt6-l10n-tools \
|
||||
qt6-multimedia-dev \
|
||||
qt6-tools-dev \
|
||||
qt6-tools-dev-tools \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
@@ -127,7 +127,7 @@ fi
|
||||
# Add cmake --build flags
|
||||
buildflags=(--config "$BUILDTYPE")
|
||||
if [[ $PARALLEL_COUNT ]]; then
|
||||
if [[ $(cmake --build /not_a_dir --parallel 2>&1 | head -1) =~ parallel ]]; then
|
||||
if [[ $(cmake --build /not_a_dir --parallel |& head -1) =~ parallel ]]; then
|
||||
# workaround for bionic having an old cmake
|
||||
echo "this version of cmake does not support --parallel, using native build tool -j instead"
|
||||
buildflags+=(-- -j "$PARALLEL_COUNT")
|
||||
@@ -160,13 +160,7 @@ cmake .. "${flags[@]}"
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Build project"
|
||||
if [[ $RUNNER_OS == Windows ]]; then
|
||||
# Enable MTT, see https://devblogs.microsoft.com/cppblog/improved-parallelism-in-msbuild/
|
||||
# and https://devblogs.microsoft.com/cppblog/cpp-build-throughput-investigation-and-tune-up/#multitooltask-mtt
|
||||
cmake --build . "${buildflags[@]}" -- -p:UseMultiToolTask=true -p:EnableClServerMode=true
|
||||
else
|
||||
cmake --build . "${buildflags[@]}"
|
||||
fi
|
||||
cmake --build . "${buildflags[@]}"
|
||||
echo "::endgroup::"
|
||||
|
||||
if [[ $USE_CCACHE ]]; then
|
||||
@@ -177,7 +171,7 @@ fi
|
||||
|
||||
if [[ $MAKE_TEST ]]; then
|
||||
echo "::group::Run tests"
|
||||
ctest -C "$BUILDTYPE" --output-on-failure
|
||||
ctest -C "$BUILDTYPE"
|
||||
echo "::endgroup::"
|
||||
fi
|
||||
|
||||
|
||||
@@ -8,20 +8,21 @@ git push -d origin --REPLACE-WITH-BETA-LIST--
|
||||
include different targets -->
|
||||
<pre>
|
||||
<b>Pre-compiled binaries we serve:</b>
|
||||
- <kbd>Windows 7+</kbd>
|
||||
- <kbd>Windows 10+</kbd>
|
||||
- <kbd>macOS 10.15+</kbd> ("Catalina")
|
||||
- <kbd>macOS 13+</kbd> ("Ventura")
|
||||
- <kbd>Ubuntu 18.04 LTS</kbd> ("Bionic Beaver")
|
||||
- <kbd>Ubuntu 20.04 LTS</kbd> ("Focal Fossa")
|
||||
- <kbd>Ubuntu 22.04 LTS</kbd> ("Jammy Jellyfish")
|
||||
- <kbd>Ubuntu 24.04 LTS</kbd> ("Noble Numbat")
|
||||
- <kbd>Windows 7/8/10/11 (32-bit)</kbd>
|
||||
- <kbd>Windows 7/8 (64-bit)</kbd>
|
||||
- <kbd>Windows 10/11 (64-bit)</kbd>
|
||||
- <kbd>macOS 10.14</kbd> ("Mojave")
|
||||
- <kbd>macOS 10.15</kbd> ("Catalina")
|
||||
- <kbd>macOS 11.0+</kbd> ("Big Sur")
|
||||
- <kbd>Ubuntu 18.04</kbd> ("Bionic Beaver")
|
||||
- <kbd>Ubuntu 20.04</kbd> ("Focal Fossa")
|
||||
- <kbd>Ubuntu 22.04</kbd> ("Jammy Jellyfish")
|
||||
- <kbd>Debian 10</kbd> ("Buster")
|
||||
- <kbd>Debian 11</kbd> ("Bullseye")
|
||||
- <kbd>Debian 12</kbd> ("Bookworm")
|
||||
- <kbd>Fedora 39</kbd>
|
||||
- <kbd>Fedora 40</kbd>
|
||||
- <kbd>Fedora 35</kbd>
|
||||
- <kbd>Fedora 36</kbd>
|
||||
<kbd>We are also packaged in Arch Linux's official community repository, courtesy of @FFY00</kbd></i>
|
||||
<kbd>General Linux support is available via a flatpak package (Flathub)</kbd></i>
|
||||
<kbd>General linux support is available via a flatpak package (Flathub)</kbd></i>
|
||||
</pre>
|
||||
|
||||
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ci script to update translation files
|
||||
# usage:
|
||||
# $0 cockatrice/cockatrice_en@source.ts cockatrice/src common
|
||||
# or
|
||||
# FILE="cockatrice/cockatrice_en@source.ts"
|
||||
# DIRS="cockatrice/src common"
|
||||
# $0
|
||||
# note: directories can't contain spaces
|
||||
|
||||
# check parameters
|
||||
if [[ ! $FILE ]]; then
|
||||
FILE="$1"
|
||||
shift
|
||||
fi
|
||||
if [[ ! $FILE ]]; then
|
||||
echo "no output file selected" >&2
|
||||
exit 2;
|
||||
fi
|
||||
if [[ ! $DIRS ]]; then
|
||||
DIRS="$*"
|
||||
fi
|
||||
if [[ ! $DIRS ]]; then
|
||||
echo "no source directories selected to translate" >&2
|
||||
exit 2;
|
||||
fi
|
||||
if [[ ! -e $FILE ]]; then
|
||||
echo "output file does not exist at: $FILE" >&2
|
||||
exit 3;
|
||||
fi
|
||||
|
||||
# print version
|
||||
if ! lupdate -version; then
|
||||
echo "failed to run lupdate" >&2
|
||||
exit 4;
|
||||
fi
|
||||
|
||||
# run lupdate, duplicating the output in stderr and saving it
|
||||
# for convenience we ignore that $DIRS will be split on spaces
|
||||
# shellcheck disable=SC2086
|
||||
if ! got="$(lupdate $DIRS -ts "$FILE" | tee /dev/stderr)"; then
|
||||
echo "failed to update $FILE with $DIRS" >&2
|
||||
exit 4;
|
||||
fi
|
||||
|
||||
# trim output
|
||||
# the line we are interested in is:
|
||||
# Found xxx source text(s) (x new and xxx already existing)
|
||||
output="${got##* source text(s) (}" # get stuff in between brackets
|
||||
output="${output%%)*}" # trim everything after first )
|
||||
if [[ $output == "$got" ]]; then
|
||||
echo "could not parse generated output" >&2
|
||||
exit 4;
|
||||
fi
|
||||
|
||||
# write output to ci environment file
|
||||
echo "output=$output" >> "$GITHUB_OUTPUT"
|
||||
@@ -1,14 +0,0 @@
|
||||
Updated source strings for translations:
|
||||
- {{ .cockatrice_output }} (Cockatrice)
|
||||
- {{ .oracle_output }} (Oracle)
|
||||
|
||||
<br>
|
||||
|
||||
Last changes are based on commit {{ .commit }}.
|
||||
|
||||
---
|
||||
*This PR is automatically generated and updated by the workflow at `.github/workflows/translations-push.yml`. Review [action runs][2].*<br>
|
||||
*After merging, all changes to the source language are available for translation at [Transifex][1] shortly.*
|
||||
|
||||
[1]: https://app.transifex.com/cockatrice/cockatrice/
|
||||
[2]: https://github.com/Cockatrice/Cockatrice/actions/workflows/translations-push.yml?query=branch%3Amaster
|
||||
73
.github/CONTRIBUTING.md
vendored
73
.github/CONTRIBUTING.md
vendored
@@ -290,21 +290,20 @@ be included in the next release 👍
|
||||
|
||||
Basic workflow for translations:
|
||||
1. Developer adds a `tr("foo")` string in the code;
|
||||
2. CI updates the `*_en@source.ts files` regularly and creates a PR automatically;
|
||||
3. Maintainer verifies and merges the change;
|
||||
4. Transifex picks up the new files from GitHub automatically;
|
||||
5. Translators translate the new untranslated strings on Transifex;
|
||||
6. Before a release, a maintainer fetches the updated translations from Transifex.
|
||||
2. Every few days, a maintainer updates the `*_en@source.ts files` with the new strings;
|
||||
3. Transifex picks up the new files from GitHub every 24 hours;
|
||||
4. Translators translate the new untranslated strings on Transifex;
|
||||
5. Before a release, a maintainer fetches the updated translations from Transifex.
|
||||
|
||||
### Using Translations (for developers) ###
|
||||
|
||||
All user interface strings inside Cockatrice's source code must be written
|
||||
in English (US).
|
||||
All the user-interface strings inside Cockatrice's source code must be written
|
||||
in English(US).
|
||||
Translations to other languages are managed using [Transifex](
|
||||
https://www.transifex.com/projects/p/cockatrice/).
|
||||
|
||||
Adding a new string to translate is as easy as adding the string in the
|
||||
`tr("")` function, the string will be picked up as translatable automatically
|
||||
'tr("")' function, the string will be picked up as translatable automatically
|
||||
and translated as needed.
|
||||
For example, setting the text of a label in the way that the string
|
||||
`"My name is:"` can be translated:
|
||||
@@ -313,7 +312,7 @@ nameLabel.setText(tr("My name is:"));
|
||||
```
|
||||
|
||||
To translate a string that would have plural forms you can add the amount to
|
||||
the tr() call, also you can add an extra string as a hint for translators:
|
||||
the tr call, also you can add an extra string as a hint for translators:
|
||||
```c++
|
||||
QString message = tr("Everyone draws %n cards", "pop up message", amount);
|
||||
```
|
||||
@@ -322,46 +321,20 @@ 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
|
||||
the translation files.<br>
|
||||
We have an automated process to update our language source files on a schedule
|
||||
and provide the translators on Transifex with the new contents.<br>
|
||||
Maintainers can also manually trigger this on demand.
|
||||
the translation files.
|
||||
Every few days, or when a lot of new strings have been added, someone from the
|
||||
development team will take care of extracting all the new strings and adding
|
||||
them to the english translation files and making them available to translators
|
||||
on Transifex.
|
||||
|
||||
### Maintaining Translations (for maintainers) ###
|
||||
|
||||
When new translatable strings have been added to the code, a maintainer has to
|
||||
make them available to translators on Transifex.
|
||||
When new translatable strings have been added to the code, a maintainer should
|
||||
make them available to translators on Transifex. Every few days, or when a lot
|
||||
of new strings have been added, a maintainer should take care of extracting all
|
||||
the new strings and add them to the english translation files.
|
||||
|
||||
To help with that, we have an automated CI workflow, that regularly looks at the
|
||||
code in the master branch, extracts all strings and updates dedicated source string
|
||||
files with any changes. These updates are not commited right away, the CI creates a
|
||||
PR for reviewing instead.<br>
|
||||
After approval, our translation tool automatically picks the changes up and deploys
|
||||
them to our translators. Be mindful when merging only a few changes!
|
||||
|
||||
Once a release is planned, or when a lot of strings have been added or changed, a
|
||||
maintainer can manually trigger a CI run to extract all strings on demand.
|
||||
|
||||
<details>
|
||||
<summary><b>Manually trigger CI run (Workflow Dispatch)</b></summary>
|
||||
|
||||
Maintainers can always request the CI to run on demand if it's required.
|
||||
|
||||
Go to the `Actions` tab and select our dedicated translation workflow:
|
||||
https://github.com/Cockatrice/Cockatrice/actions/workflows/translations.yml
|
||||
|
||||
You see a "This workflow has a workflow_dispatch event trigger." hint at the top of
|
||||
the list.<br>
|
||||
Select `Run workflow` on the right and trigger a run from master branch.
|
||||
|
||||
The CI will now check for changed strings and create a PR if there are any updates.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Manually update source strings locally</b></summary>
|
||||
|
||||
To update the english source files for translation, re-run cmake enabling the appropriate
|
||||
To update the english translation files, re-run cmake enabling the appropriate
|
||||
parameter and then run make:
|
||||
```sh
|
||||
cd cockatrice/build
|
||||
@@ -384,13 +357,11 @@ It is recommended to disable the parameter afterwards using:
|
||||
```sh
|
||||
cmake .. -DUPDATE_TRANSLATIONS=OFF
|
||||
```
|
||||
Now you are ready to commit your changes and open a PR.
|
||||
Now you are ready to propose your change.
|
||||
|
||||
</details>
|
||||
|
||||
Once the changes get merged, Transifex will pick up the modified files
|
||||
automatically (checked every few hours) and update their online editor where
|
||||
translators will be able to translate the new strings right in the browser.
|
||||
Once your change gets merged, Transifex will pick up the modified files
|
||||
automatically (checked every 24 hours) and update the interface where
|
||||
translators will be able to translate the new strings.
|
||||
|
||||
### Releasing Translations (for maintainers) ###
|
||||
|
||||
|
||||
49
.github/dependabot.yml
vendored
49
.github/dependabot.yml
vendored
@@ -1,49 +0,0 @@
|
||||
# Configuration options: https://docs.github.com/en/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
# # Enable version updates for git submodules
|
||||
# Not yet possible to bump only on tags or releases, see:
|
||||
# https://github.com/dependabot/dependabot-core/issues/1639
|
||||
# https://github.com/dependabot/dependabot-core/issues/2192
|
||||
# Alternative: Action that updates submodule and can be manually run on demand (workflow_dispatch)
|
||||
# - package-ecosystem: "gitsubmodule"
|
||||
# # Look for `.gitmodules` in the `root` directory
|
||||
# directory: "/"
|
||||
# # Check for updates once a month
|
||||
# schedule:
|
||||
# interval: "monthly"
|
||||
# # Limit the amout of open PR's (default = 5, disabled = 0, security updates are not impacted)
|
||||
# open-pull-requests-limit: 1
|
||||
|
||||
# # Enable version updates for Docker
|
||||
# Not yet possible to bump from one LTS version to the next and skip others, see:
|
||||
# https://github.com/dependabot/dependabot-core/issues/2247
|
||||
# - package-ecosystem: "docker"
|
||||
# # Look for a `Dockerfile` in the `root` directory
|
||||
# directory: "/"
|
||||
# # Check for updates once a week
|
||||
# schedule:
|
||||
# interval: "weekly"
|
||||
# # Limit the amout of open PR's (default = 5, disabled = 0, security updates are not impacted)
|
||||
# open-pull-requests-limit: 1
|
||||
|
||||
# Enable version updates for GitHub Actions
|
||||
- package-ecosystem: "github-actions"
|
||||
# Directory must be set to "/" to check for workflow files in .github/workflows
|
||||
directory: "/"
|
||||
# Check for updates to GitHub Actions once a week
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
# Limit the amout of open PR's (default = 5, disabled = 0, security updates are not impacted)
|
||||
open-pull-requests-limit: 2
|
||||
|
||||
# # Enable version updates for npm
|
||||
# - package-ecosystem: "npm"
|
||||
# # Look for `package.json` and `lock` files in the `webclient` subdirectory
|
||||
# directory: "/webclient"
|
||||
# # Check the npm registry for updates once a week
|
||||
# schedule:
|
||||
# interval: "weekly"
|
||||
# # Limit the amout of open PR's (default = 5, disabled = 0, security updates are not impacted)
|
||||
# open-pull-requests-limit: 5
|
||||
232
.github/workflows/desktop-build.yml
vendored
232
.github/workflows/desktop-build.yml
vendored
@@ -8,7 +8,6 @@ on:
|
||||
- '**.md'
|
||||
- 'webclient/**'
|
||||
- '.github/workflows/web-*.yml'
|
||||
- '.github/workflows/translations-*.yml'
|
||||
tags:
|
||||
- '*'
|
||||
pull_request:
|
||||
@@ -16,12 +15,6 @@ on:
|
||||
- '**.md'
|
||||
- 'webclient/**'
|
||||
- '.github/workflows/web-*.yml'
|
||||
- '.github/workflows/translations-*.yml'
|
||||
|
||||
# Cancel earlier, unfinished runs of this workflow on the same branch (unless on master)
|
||||
concurrency:
|
||||
group: "${{ github.workflow }} @ ${{ github.ref_name }}"
|
||||
cancel-in-progress: ${{ github.ref_name != 'master' }}
|
||||
|
||||
jobs:
|
||||
configure:
|
||||
@@ -30,8 +23,14 @@ jobs:
|
||||
outputs:
|
||||
tag: ${{steps.configure.outputs.tag}}
|
||||
sha: ${{steps.configure.outputs.sha}}
|
||||
upload_url: ${{steps.create_release.outputs.upload_url}}
|
||||
|
||||
steps:
|
||||
- name: Cancel previous runs
|
||||
uses: styfle/cancel-workflow-action@0.11.0
|
||||
with:
|
||||
access_token: ${{github.token}} # needs other token https://github.com/styfle/cancel-workflow-action/issues/7
|
||||
|
||||
steps:
|
||||
- name: Configure
|
||||
id: configure
|
||||
shell: bash
|
||||
@@ -50,7 +49,7 @@ jobs:
|
||||
|
||||
- name: Checkout
|
||||
if: steps.configure.outputs.tag != null
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -65,21 +64,15 @@ jobs:
|
||||
- name: Create release
|
||||
if: steps.configure.outputs.tag != null
|
||||
id: create_release
|
||||
shell: bash
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GH_TOKEN: ${{github.token}}
|
||||
tag_name: ${{steps.configure.outputs.tag}}
|
||||
target: ${{steps.configure.outputs.sha}}
|
||||
GITHUB_TOKEN: ${{github.token}}
|
||||
with:
|
||||
tag_name: ${{github.ref}}
|
||||
release_name: ${{steps.prepare.outputs.title}}
|
||||
body_path: ${{steps.prepare.outputs.body_path}}
|
||||
prerelease: ${{steps.prepare.outputs.is_beta}}
|
||||
run: |
|
||||
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"
|
||||
draft: true
|
||||
prerelease: ${{steps.prepare.outputs.is_beta == 'yes'}}
|
||||
|
||||
build-linux:
|
||||
strategy:
|
||||
@@ -91,16 +84,18 @@ jobs:
|
||||
package: skip # we are packaged in arch already
|
||||
allow-failure: yes
|
||||
|
||||
- distro: Debian10
|
||||
package: DEB
|
||||
test: skip # running tests on all distros is superfluous
|
||||
|
||||
- distro: Debian11
|
||||
package: DEB
|
||||
|
||||
- distro: Debian12
|
||||
package: DEB
|
||||
|
||||
- distro: Fedora39
|
||||
- distro: Fedora35
|
||||
package: RPM
|
||||
test: skip
|
||||
|
||||
- distro: Fedora40
|
||||
- distro: Fedora36
|
||||
package: RPM
|
||||
|
||||
- distro: UbuntuBionic
|
||||
@@ -112,10 +107,6 @@ jobs:
|
||||
|
||||
- distro: UbuntuJammy
|
||||
package: DEB
|
||||
test: skip # running tests on all distros is superfluous
|
||||
|
||||
- distro: UbuntuNoble
|
||||
package: DEB
|
||||
|
||||
name: ${{matrix.distro}}
|
||||
needs: configure
|
||||
@@ -130,7 +121,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Get cache timestamp
|
||||
id: cache_timestamp
|
||||
@@ -138,7 +129,7 @@ jobs:
|
||||
run: echo "timestamp=$(date -u '+%Y%m%d%H%M%S')" >>"$GITHUB_OUTPUT"
|
||||
|
||||
- name: Restore cache
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
timestamp: ${{steps.cache_timestamp.outputs.timestamp}}
|
||||
with:
|
||||
@@ -158,10 +149,10 @@ jobs:
|
||||
distro: '${{matrix.distro}}'
|
||||
run: |
|
||||
source .ci/docker.sh
|
||||
RUN --server --debug --test --ccache "$CCACHE_SIZE" --parallel 4
|
||||
RUN --server --debug --test --ccache "$CCACHE_SIZE" --parallel 2
|
||||
|
||||
- name: Build release package
|
||||
id: build
|
||||
id: package
|
||||
if: matrix.package != 'skip'
|
||||
shell: bash
|
||||
env:
|
||||
@@ -172,50 +163,73 @@ jobs:
|
||||
run: |
|
||||
source .ci/docker.sh
|
||||
RUN --server --release --package "$type" --dir "$BUILD_DIR" \
|
||||
--ccache "$CCACHE_SIZE" --parallel 4
|
||||
--ccache "$CCACHE_SIZE" --parallel 2
|
||||
.ci/name_build.sh
|
||||
|
||||
- name: Upload artifact
|
||||
if: matrix.package != 'skip'
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{matrix.distro}}-package
|
||||
path: ${{steps.build.outputs.path}}
|
||||
path: ${{steps.package.outputs.path}}
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload to release
|
||||
if: matrix.package != 'skip' && needs.configure.outputs.tag != null
|
||||
shell: bash
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GH_TOKEN: ${{github.token}}
|
||||
tag_name: ${{needs.configure.outputs.tag}}
|
||||
asset_path: ${{steps.build.outputs.path}}
|
||||
asset_name: ${{steps.build.outputs.name}}
|
||||
run: gh release upload "$tag_name" "$asset_path#$asset_name"
|
||||
GITHUB_TOKEN: ${{github.token}}
|
||||
with:
|
||||
upload_url: ${{needs.configure.outputs.upload_url}}
|
||||
asset_path: ${{steps.package.outputs.path}}
|
||||
asset_name: ${{steps.package.outputs.name}}
|
||||
asset_content_type: application/octet-stream
|
||||
|
||||
build-macos:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- target: 12_Monterey_and_13_Ventura
|
||||
os: macos-12
|
||||
xcode: "14.0.1"
|
||||
type: Release
|
||||
make_package: 1
|
||||
|
||||
- target: 14_Sonoma
|
||||
os: macos-14
|
||||
xcode: "15.4"
|
||||
type: Release
|
||||
make_package: 1
|
||||
|
||||
- target: 14_Sonoma_Debug
|
||||
os: macos-14
|
||||
xcode: "15.4"
|
||||
- target: Debug # tests only
|
||||
os: macos-latest
|
||||
xcode: 12.5.1
|
||||
qt_version: 6
|
||||
type: Debug
|
||||
do_tests: 1
|
||||
|
||||
name: macOS${{matrix.target}}
|
||||
- target: 10.14_Mojave
|
||||
os: macos-10.15 # runs on Catalina
|
||||
xcode: 10.3 # allows compatibility with macOS 10.14
|
||||
qt_version: 5
|
||||
type: Release
|
||||
# do_tests: 1 # tests do not work on qt5?
|
||||
make_package: 1
|
||||
|
||||
- target: 10.15_Catalina
|
||||
os: macos-10.15
|
||||
xcode: 12.4
|
||||
qt_version: 6
|
||||
type: Release
|
||||
do_tests: 1
|
||||
make_package: 1
|
||||
|
||||
- target: 11_Big_Sur
|
||||
os: macos-11
|
||||
xcode: 13.2
|
||||
qt_version: 6
|
||||
type: Release
|
||||
do_tests: 1
|
||||
make_package: 1
|
||||
|
||||
# - target: 12_Monterey
|
||||
# os: macos-12
|
||||
# xcode: 13.3
|
||||
# qt_version: 6
|
||||
# type: Release
|
||||
# do_tests: 1
|
||||
# make_package: 1
|
||||
|
||||
name: macOS ${{matrix.target}}
|
||||
needs: configure
|
||||
runs-on: ${{matrix.os}}
|
||||
continue-on-error: ${{matrix.allow-failure == 'yes'}}
|
||||
@@ -225,126 +239,140 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install dependencies using Homebrew
|
||||
- name: Install dependencies using homebrew
|
||||
shell: bash
|
||||
# cmake cannot find the mysql connector
|
||||
# neither of these works: mariadb-connector-c mysql-connector-c++
|
||||
env:
|
||||
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1
|
||||
qt_version: 'qt@${{matrix.qt_version}}'
|
||||
run: |
|
||||
brew update
|
||||
brew install protobuf qt --force-bottle
|
||||
brew install protobuf
|
||||
brew install "$qt_version" --force-bottle
|
||||
|
||||
- name: Build on Xcode ${{matrix.xcode}}
|
||||
shell: bash
|
||||
id: build
|
||||
env:
|
||||
BUILDTYPE: '${{matrix.type}}'
|
||||
MAKE_TEST: 1
|
||||
MAKE_TEST: '${{matrix.do_tests}}'
|
||||
MAKE_PACKAGE: '${{matrix.make_package}}'
|
||||
PACKAGE_SUFFIX: '-macOS-${{matrix.target}}'
|
||||
# macOS runner actually have only 3 cores
|
||||
# See https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources
|
||||
# set QTDIR to find qt5, qt6 can be found without this
|
||||
QTDIR: '/usr/local/opt/qt5'
|
||||
# Mac machines actually have 3 cores
|
||||
run: .ci/compile.sh --server --parallel 3
|
||||
|
||||
- name: Upload artifact
|
||||
if: matrix.make_package
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: macOS-${{matrix.target}}-dmg
|
||||
path: ${{steps.build.outputs.path}}
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload to release
|
||||
if: matrix.package != 'skip' && needs.configure.outputs.tag != null
|
||||
shell: bash
|
||||
if: matrix.make_package && needs.configure.outputs.tag != null
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GH_TOKEN: ${{github.token}}
|
||||
tag_name: ${{needs.configure.outputs.tag}}
|
||||
GITHUB_TOKEN: ${{github.token}}
|
||||
with:
|
||||
upload_url: ${{needs.configure.outputs.upload_url}}
|
||||
asset_path: ${{steps.build.outputs.path}}
|
||||
asset_name: ${{steps.build.outputs.name}}
|
||||
run: gh release upload "$tag_name" "$asset_path#$asset_name"
|
||||
asset_content_type: application/octet-stream
|
||||
|
||||
build-windows:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- target: 7
|
||||
- target: Win-32bit
|
||||
bit: 32
|
||||
arch: x86
|
||||
cmake_generator_platform: Win32
|
||||
qt_version: 5.15.*
|
||||
qt_arch: msvc2019
|
||||
qt_tools: "tools_openssl_x86"
|
||||
|
||||
- target: Win7+-64bit
|
||||
bit: 64
|
||||
arch: x64
|
||||
cmake_generator_platform: x64
|
||||
qt_version: 5.15.*
|
||||
qt_arch: msvc2019_64
|
||||
qt_tools: "tools_opensslv3_x64"
|
||||
qt_tools: "tools_openssl_x64"
|
||||
|
||||
- target: 10
|
||||
qt_version: 6.5.*
|
||||
- target: Win10+-64bit
|
||||
bit: 64
|
||||
arch: x64
|
||||
cmake_generator_platform: x64
|
||||
qt_version: 6.3.*
|
||||
qt_arch: msvc2019_64
|
||||
qt_tools: "tools_opensslv3_x64"
|
||||
qt_tools: "tools_openssl_x64"
|
||||
qt_modules: "qtmultimedia qtwebsockets"
|
||||
|
||||
name: Windows ${{matrix.target}}
|
||||
name: ${{matrix.target}}
|
||||
needs: configure
|
||||
runs-on: windows-2022
|
||||
runs-on: windows-2019
|
||||
env:
|
||||
CMAKE_GENERATOR: 'Visual Studio 17 2022'
|
||||
CMAKE_GENERATOR: 'Visual Studio 16 2019'
|
||||
|
||||
steps:
|
||||
- name: Add msbuild to PATH
|
||||
id: add-msbuild
|
||||
uses: microsoft/setup-msbuild@v2
|
||||
with:
|
||||
msbuild-architecture: x64
|
||||
uses: microsoft/setup-msbuild@v1.1
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Install Qt ${{matrix.qt_version}}
|
||||
- name: Install Qt ${{matrix.qt_version}} for ${{matrix.target}}
|
||||
uses: jurplel/install-qt-action@v3
|
||||
with:
|
||||
cache: true
|
||||
setup-python: false
|
||||
version: ${{matrix.qt_version}}
|
||||
arch: win64_${{matrix.qt_arch}}
|
||||
arch: win${{matrix.bit}}_${{matrix.qt_arch}}
|
||||
tools: ${{matrix.qt_tools}}
|
||||
modules: ${{matrix.qt_modules}}
|
||||
|
||||
- name: Run vcpkg
|
||||
uses: lukka/run-vcpkg@v11
|
||||
uses: lukka/run-vcpkg@v10.6
|
||||
with:
|
||||
runVcpkgInstall: true
|
||||
doNotCache: false
|
||||
appendedCacheKey: ${{matrix.bit}}-bit
|
||||
env:
|
||||
VCPKG_DEFAULT_TRIPLET: 'x64-windows'
|
||||
VCPKG_DEFAULT_TRIPLET: '${{matrix.arch}}-windows'
|
||||
VCPKG_DISABLE_METRICS: 1
|
||||
|
||||
- name: Build Cockatrice
|
||||
id: build
|
||||
shell: bash
|
||||
env:
|
||||
PACKAGE_SUFFIX: '-Win${{matrix.target}}'
|
||||
PACKAGE_SUFFIX: '-${{matrix.target}}'
|
||||
CMAKE_GENERATOR: '${{env.CMAKE_GENERATOR}}'
|
||||
CMAKE_GENERATOR_PLATFORM: 'x64'
|
||||
QTDIR: '${{github.workspace}}\Qt\${{matrix.qt_version}}\win64_${{matrix.qt_arch}}'
|
||||
# No need for --parallel flag, MTT is added in the compile script to let cmake/msbuild manage core count,
|
||||
# project and process parallelism: https://devblogs.microsoft.com/cppblog/improved-parallelism-in-msbuild/
|
||||
run: .ci/compile.sh --server --release --test --package
|
||||
CMAKE_GENERATOR_PLATFORM: '${{matrix.cmake_generator_platform}}'
|
||||
QTDIR: '${{github.workspace}}\Qt\${{matrix.qt_version}}\win${{matrix.bit}}_${{matrix.qt_arch}}'
|
||||
run: .ci/compile.sh --server --release --test --package --parallel 2
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: Windows${{matrix.target}}-installer
|
||||
name: ${{matrix.target}}-installer
|
||||
path: ${{steps.build.outputs.path}}
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload to release
|
||||
if: matrix.package != 'skip' && needs.configure.outputs.tag != null
|
||||
shell: bash
|
||||
if: needs.configure.outputs.tag != null
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GH_TOKEN: ${{github.token}}
|
||||
tag_name: ${{needs.configure.outputs.tag}}
|
||||
GITHUB_TOKEN: ${{github.token}}
|
||||
with:
|
||||
upload_url: ${{needs.configure.outputs.upload_url}}
|
||||
asset_path: ${{steps.build.outputs.path}}
|
||||
asset_name: ${{steps.build.outputs.name}}
|
||||
run: gh release upload "$tag_name" "$asset_path#$asset_name"
|
||||
asset_content_type: application/octet-stream
|
||||
|
||||
3
.github/workflows/desktop-lint.yml
vendored
3
.github/workflows/desktop-lint.yml
vendored
@@ -6,7 +6,6 @@ on:
|
||||
- '**.md'
|
||||
- 'webclient/**'
|
||||
- '.github/workflows/web-*.yml'
|
||||
- '.github/workflows/translations-*.yml'
|
||||
|
||||
jobs:
|
||||
format:
|
||||
@@ -14,7 +13,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 20 # should be enough to find merge base
|
||||
|
||||
|
||||
72
.github/workflows/translations-pull.yml
vendored
72
.github/workflows/translations-pull.yml
vendored
@@ -1,72 +0,0 @@
|
||||
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:
|
||||
- '.github/workflows/translations-pull.yml'
|
||||
|
||||
jobs:
|
||||
translations:
|
||||
# Do not run the scheduled workflow on forks
|
||||
if: github.event_name != 'schedule' || github.repository_owner == 'Cockatrice'
|
||||
|
||||
name: Pull languages
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Pull translated strings from Transifex
|
||||
uses: transifex/cli-action@v2
|
||||
with:
|
||||
# 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
|
||||
if: github.event_name != 'pull_request'
|
||||
id: create_pr
|
||||
uses: peter-evans/create-pull-request@v6
|
||||
with:
|
||||
add-paths: |
|
||||
cockatrice/translations/*.ts
|
||||
oracle/translations/*.ts
|
||||
webclient/public/locales/*/translation.json
|
||||
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://app.transifex.com/cockatrice/cockatrice/
|
||||
[2]: https://github.com/Cockatrice/Cockatrice/actions/workflows/translations-pull.yml?query=branch%3Amaster
|
||||
labels: |
|
||||
CI
|
||||
Translation
|
||||
draft: false
|
||||
|
||||
- name: PR Status
|
||||
if: github.event_name != 'pull_request'
|
||||
shell: bash
|
||||
env:
|
||||
STATUS: ${{ steps.create_pr.outputs.pull-request-operation }}
|
||||
run: |
|
||||
if [[ "$STATUS" == "" ]]; 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
|
||||
87
.github/workflows/translations-push.yml
vendored
87
.github/workflows/translations-push.yml
vendored
@@ -1,87 +0,0 @@
|
||||
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:
|
||||
- '.github/workflows/translations-push.yml'
|
||||
|
||||
jobs:
|
||||
translations:
|
||||
# Do not run the scheduled workflow on forks
|
||||
if: github.event_name != 'schedule' || github.repository_owner == 'Cockatrice'
|
||||
|
||||
name: Push strings
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- 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
|
||||
id: cockatrice
|
||||
shell: bash
|
||||
env:
|
||||
FILE: 'cockatrice/cockatrice_en@source.ts'
|
||||
DIRS: 'cockatrice/src common'
|
||||
run: .ci/update_translation_source_strings.sh
|
||||
|
||||
- name: Update Oracle translation source
|
||||
id: oracle
|
||||
shell: bash
|
||||
env:
|
||||
FILE: 'oracle/oracle_en@source.ts'
|
||||
DIRS: 'oracle/src'
|
||||
run: .ci/update_translation_source_strings.sh
|
||||
|
||||
- name: Render template
|
||||
id: template
|
||||
uses: chuhlomin/render-template@v1
|
||||
with:
|
||||
template: .ci/update_translation_source_strings_template.md
|
||||
vars: |
|
||||
cockatrice_output: ${{ steps.cockatrice.outputs.output }}
|
||||
oracle_output: ${{ steps.oracle.outputs.output }}
|
||||
commit: ${{ github.sha }}
|
||||
|
||||
- name: Create pull request
|
||||
if: github.event_name != 'pull_request'
|
||||
id: create_pr
|
||||
uses: peter-evans/create-pull-request@v6
|
||||
with:
|
||||
add-paths: |
|
||||
cockatrice/cockatrice_en@source.ts
|
||||
oracle/oracle_en@source.ts
|
||||
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
|
||||
title: 'Update source strings'
|
||||
body: ${{ steps.template.outputs.result }}
|
||||
labels: |
|
||||
CI
|
||||
Translation
|
||||
draft: false
|
||||
|
||||
- name: PR Status
|
||||
if: github.event_name != 'pull_request'
|
||||
shell: bash
|
||||
env:
|
||||
STATUS: ${{ steps.create_pr.outputs.pull-request-operation }}
|
||||
run: |
|
||||
if [[ "$STATUS" == "" ]]; 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
|
||||
66
.github/workflows/translations.yml
vendored
Normal file
66
.github/workflows/translations.yml
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
name: Update translation source
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
# runs once per month
|
||||
- cron: '0 0 1 * *'
|
||||
|
||||
jobs:
|
||||
translations:
|
||||
# Do not run the scheduled workflow on forks
|
||||
if: github.event_name != 'schedule' || github.repository_owner == 'Cockatrice'
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Install lupdate
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --no-install-recommends qttools5-dev-tools
|
||||
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Update cockatrice translations
|
||||
shell: bash
|
||||
run: |
|
||||
shopt -s globstar # globstar is needed for recursive **
|
||||
lupdate -version
|
||||
echo "reading the following source files:"
|
||||
# note: there are three strings to translate in common right now
|
||||
echo {cockatrice,common}/**/*.{cpp,h}
|
||||
echo "$(echo {cockatrice,common}/**/*.{cpp,h} | wc -w) files total"
|
||||
lupdate {cockatrice,common}/**/*.{cpp,h} -ts cockatrice/translations/cockatrice_en@source.ts
|
||||
|
||||
- name: Update oracle translations
|
||||
shell: bash
|
||||
run: |
|
||||
shopt -s globstar # globstar is needed for recursive **
|
||||
lupdate -version
|
||||
echo "reading the following source files:"
|
||||
echo oracle/**/*.{cpp,h}
|
||||
echo "$(echo oracle/**/*.{cpp,h} | wc -w) files total"
|
||||
lupdate oracle/**/*.{cpp,h} -ts oracle/translations/oracle_en@source.ts
|
||||
|
||||
- name: Check for updates
|
||||
id: check
|
||||
shell: bash
|
||||
run: |
|
||||
set +e # do not fail, just save the exit state
|
||||
git diff --exit-code
|
||||
echo "deploy=$?" >>"$GITHUB_OUTPUT"
|
||||
|
||||
- name: Commit changes
|
||||
if: steps.check.outputs.deploy == '1'
|
||||
shell: bash
|
||||
working-directory: ${{env.OUTPUT_PATH}}
|
||||
run: |
|
||||
git config user.name github-actions
|
||||
git config user.email github-actions@github.com
|
||||
git add cockatrice/translations/cockatrice_en@source.ts oracle/translations/oracle_en@source.ts
|
||||
git commit -m "Automated translation update ( $GITHUB_SHA )"
|
||||
git push
|
||||
deploy_commit=$(git rev-parse HEAD)
|
||||
echo "Created commit: $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/commit/$deploy_commit"
|
||||
5
.github/workflows/web-build.yml
vendored
5
.github/workflows/web-build.yml
vendored
@@ -33,10 +33,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: ${{matrix.node_version}}
|
||||
cache: 'npm'
|
||||
@@ -50,3 +50,4 @@ jobs:
|
||||
|
||||
- name: Test app
|
||||
run: npm run test
|
||||
|
||||
|
||||
4
.github/workflows/web-lint.yml
vendored
4
.github/workflows/web-lint.yml
vendored
@@ -17,10 +17,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
cache: 'npm'
|
||||
cache-dependency-path: 'webclient/package-lock.json'
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -11,5 +11,3 @@ preferences
|
||||
compile_commands.json
|
||||
.vs/
|
||||
.vscode/
|
||||
.cache
|
||||
.gdb_history
|
||||
|
||||
27
.tx/config
27
.tx/config
@@ -1,26 +1,13 @@
|
||||
[main]
|
||||
host = https://app.transifex.com
|
||||
host = https://www.transifex.com
|
||||
|
||||
[o:cockatrice:p:cockatrice:r:cockatrice-cockatrice-en-source-ts--master]
|
||||
resource_name = Cockatrice
|
||||
source_lang = en
|
||||
source_file = cockatrice/cockatrice_en@source.ts
|
||||
[cockatrice.cockatrice-translations-cockatrice-en-source-ts--master]
|
||||
file_filter = cockatrice/translations/cockatrice_<lang>.ts
|
||||
type = QT
|
||||
minimum_perc = 10
|
||||
|
||||
[o:cockatrice:p:cockatrice:r:oracle-oracle-en-source-ts--master]
|
||||
resource_name = Oracle
|
||||
source_file = cockatrice/translations/cockatrice_en@source.ts
|
||||
source_lang = en
|
||||
source_file = oracle/oracle_en@source.ts
|
||||
|
||||
[cockatrice.oracle-translations-oracle-en-source-ts--master]
|
||||
file_filter = oracle/translations/oracle_<lang>.ts
|
||||
type = QT
|
||||
minimum_perc = 10
|
||||
|
||||
[o:cockatrice:p:cockatrice:r:webclient-src-i18n-default-json--master]
|
||||
resource_name = Webclient
|
||||
source_file = oracle/translations/oracle_en@source.ts
|
||||
source_lang = en
|
||||
source_file = webclient/src/i18n-default.json
|
||||
file_filter = webclient/public/locales/<lang>/translation.json
|
||||
type = KEYVALUEJSON
|
||||
minimum_perc = 10
|
||||
|
||||
|
||||
@@ -74,11 +74,11 @@ endif()
|
||||
|
||||
# A project name is needed for CPack
|
||||
# Version can be overriden by git tags, see cmake/getversion.cmake
|
||||
project("Cockatrice" VERSION 2.9.1)
|
||||
project("Cockatrice" VERSION 2.8.1)
|
||||
|
||||
# Set release name if not provided via env/cmake var
|
||||
if(NOT DEFINED GIT_TAG_RELEASENAME)
|
||||
set(GIT_TAG_RELEASENAME "Rings of the Wild")
|
||||
set(GIT_TAG_RELEASENAME "Prismatic Bridge")
|
||||
endif()
|
||||
|
||||
# Use c++17 for all targets
|
||||
@@ -141,7 +141,7 @@ endif()
|
||||
# Define proper compilation flags
|
||||
if(MSVC)
|
||||
# Visual Studio: Maximum optimization, disable warning C4251, establish C++17 compatibility
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "/Ox /MD /wd4251 /Zc:__cplusplus /std:c++17 /permissive- /W4")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "/Ox /MD /wd4251 /Zc:__cplusplus /std:c++17 /permissive-")
|
||||
# Generate complete debugging information
|
||||
#set(CMAKE_CXX_FLAGS_DEBUG "/Zi")
|
||||
elseif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
@@ -179,7 +179,7 @@ else()
|
||||
# other: osx/llvm, bsd/llvm
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-O2")
|
||||
if(WARNING_AS_ERROR)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -Wall -Wextra -Werror -Wno-unused-parameter")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -Wall -Wextra -Werror")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -Wall -Wextra")
|
||||
endif()
|
||||
@@ -216,26 +216,16 @@ include(FindQtRuntime)
|
||||
set(CMAKE_AUTOMOC TRUE)
|
||||
|
||||
# Find other needed libraries
|
||||
find_package(Protobuf CONFIG)
|
||||
if(NOT Protobuf_FOUND)
|
||||
find_package(Protobuf REQUIRED)
|
||||
endif()
|
||||
|
||||
if(${Protobuf_VERSION} VERSION_LESS "3.21.0.0" AND NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
|
||||
find_package(Protobuf REQUIRED)
|
||||
if(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
|
||||
message(FATAL_ERROR "No protoc command found!")
|
||||
else()
|
||||
message(STATUS "Found Protobuf ${Protobuf_VERSION} at: ${Protobuf_LIBRARIES}")
|
||||
endif()
|
||||
|
||||
#Find OpenSSL
|
||||
if(WIN32)
|
||||
find_package(OpenSSL REQUIRED)
|
||||
if(OPENSSL_FOUND)
|
||||
include_directories(${OPENSSL_INCLUDE_DIRS})
|
||||
else()
|
||||
message(
|
||||
WARNING
|
||||
"Could not find OpenSSL runtime libraries. They are not required for compiling, but needs to be available at runtime."
|
||||
)
|
||||
endif()
|
||||
find_package(Win32SslRuntime)
|
||||
endif()
|
||||
|
||||
#Find VCredist
|
||||
@@ -262,8 +252,6 @@ if(UNIX)
|
||||
set(CPACK_DMG_VOLUME_NAME "${PROJECT_NAME}")
|
||||
set(CPACK_SYSTEM_NAME "OSX")
|
||||
set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/cockatrice/resources/appicon.icns")
|
||||
set(CPACK_DMG_DS_STORE_SETUP_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/cmake/CMakeDMGSetup.script")
|
||||
set(CPACK_DMG_BACKGROUND_IMAGE "${CMAKE_CURRENT_SOURCE_DIR}/cmake/dmgBackground.tif")
|
||||
else()
|
||||
# linux
|
||||
if(CPACK_GENERATOR STREQUAL "RPM")
|
||||
|
||||
10
README.md
10
README.md
@@ -40,7 +40,7 @@ Downloads are available for full releases and the current beta version in develo
|
||||
- To be a Cockatrice Beta Tester, use this version. Find more information [here](https://github.com/Cockatrice/Cockatrice/wiki/Release-Channels)!
|
||||
|
||||
|
||||
# Get Involved [](https://discord.gg/3Z9yzmA)
|
||||
# Get Involved [](https://discord.gg/3Z9yzmA) [](https://gitter.im/Cockatrice/Cockatrice)
|
||||
|
||||
Join our [Discord community](https://discord.gg/3Z9yzmA) to connect with the project or fellow users of the app. The Cockatrice developers are also available on [Gitter](https://gitter.im/Cockatrice/Cockatrice). Come here to talk about the application, features, or just to hang out.<br>
|
||||
For support regarding specific servers, please contact that server's admin or forum for support rather than asking here.<br>
|
||||
@@ -65,9 +65,13 @@ Cockatrice uses the [Google Developer Documentation Style Guide](https://develop
|
||||
- [reddit r/Cockatrice](https://reddit.com/r/cockatrice)
|
||||
|
||||
|
||||
# Translations [](https://transifex.com/cockatrice/cockatrice/)
|
||||
# Translations [](https://www.transifex.com/projects/p/cockatrice/)
|
||||
|
||||
Cockatrice uses Transifex for translations. You can help us bring Cockatrice, Oracle and Webatrice to your language or just adjust single wordings right from within your browser by visiting our [Transifex project page](https://transifex.com/cockatrice/cockatrice/).<br>
|
||||
Cockatrice uses Transifex for translations. You can help us bring Cockatrice and Oracle to your language or just edit single wordings right from within your browser by visiting our [Transifex project page](https://www.transifex.com/projects/p/cockatrice/).<br>
|
||||
|
||||
| Cockatrice | Oracle |
|
||||
|:-:|:-:|
|
||||
| [](https://www.transifex.com/projects/p/cockatrice/) | [](https://www.transifex.com/projects/p/cockatrice/) |
|
||||
|
||||
Check out our [Translator FAQ](https://github.com/Cockatrice/Cockatrice/wiki/Translation-FAQ) for more information about contributing!<br>
|
||||
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
on run argv
|
||||
set image_name to item 1 of argv
|
||||
|
||||
tell application "Finder"
|
||||
tell disk image_name
|
||||
|
||||
-- wait for the image to finish mounting
|
||||
set open_attempts to 0
|
||||
repeat while open_attempts < 4
|
||||
try
|
||||
open
|
||||
delay 1
|
||||
set open_attempts to 5
|
||||
close
|
||||
on error errStr number errorNumber
|
||||
set open_attempts to open_attempts + 1
|
||||
delay 10
|
||||
end try
|
||||
end repeat
|
||||
delay 5
|
||||
|
||||
-- open the image the first time and save a DS_Store with just
|
||||
-- background and icon setup
|
||||
open
|
||||
set current view of container window to icon view
|
||||
set theViewOptions to the icon view options of container window
|
||||
set background picture of theViewOptions to file ".background:background.tif"
|
||||
set arrangement of theViewOptions to not arranged
|
||||
set icon size of theViewOptions to 128
|
||||
delay 5
|
||||
close
|
||||
|
||||
-- next setup the position of the app and Applications symlink
|
||||
-- plus hide all the window decoration
|
||||
open
|
||||
update without registering applications
|
||||
tell container window
|
||||
set sidebar width to 0
|
||||
set statusbar visible to false
|
||||
set toolbar visible to false
|
||||
set the bounds to { 400, 100, 1400, 922 }
|
||||
set position of item "Cockatrice.app" to { 139, 214 }
|
||||
set position of item "Oracle.app" to { 139, 414 }
|
||||
set position of item "Servatrice.app" to { 139, 614 }
|
||||
set position of item "dbconverter.app" to { 1400, 1400 }
|
||||
set position of item "Applications" to { 861, 414 }
|
||||
end tell
|
||||
update without registering applications
|
||||
delay 5
|
||||
close
|
||||
|
||||
end tell
|
||||
delay 1
|
||||
end tell
|
||||
end run
|
||||
@@ -9,8 +9,7 @@ if(WIN32)
|
||||
set(REDIST_ARCH x86)
|
||||
endif()
|
||||
|
||||
# VS 2017 uses vcredist_ARCH.exe, VS 2022 uses vc_redist.ARCH.exe
|
||||
set(REDIST_FILE_NAMES vcredist_${REDIST_ARCH}.exe vcredist.${REDIST_ARCH}.exe vc_redist.${REDIST_ARCH}.exe)
|
||||
set(REDIST_FILE vc_redist.${REDIST_ARCH}.exe)
|
||||
|
||||
set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP TRUE)
|
||||
include(InstallRequiredSystemLibraries)
|
||||
@@ -23,20 +22,18 @@ if(WIN32)
|
||||
get_filename_component(_path ${_path} DIRECTORY)
|
||||
get_filename_component(_path ${_path}/../../ ABSOLUTE)
|
||||
|
||||
foreach(redist_file ${REDIST_FILE_NAMES})
|
||||
if(EXISTS "${_path}/${redist_file}")
|
||||
set(VCREDISTRUNTIME_FOUND "YES")
|
||||
set(VCREDISTRUNTIME_FILE ${_path}/${redist_file})
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
if(EXISTS "${_path}/${REDIST_FILE}") # VS 2017
|
||||
set(VCREDISTRUNTIME_FOUND "YES")
|
||||
set(VCREDISTRUNTIME_FILE ${_path}/${REDIST_FILE})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(VCREDISTRUNTIME_FOUND)
|
||||
message(STATUS "Found VCredist ${VCREDISTRUNTIME_FILE}")
|
||||
else()
|
||||
message(
|
||||
WARNING "Could not find VCredist package. It's not required for compiling, but needs to be available at runtime."
|
||||
WARNING
|
||||
"Could not find VCredist package in \"${_path}/${REDIST_FILE}\". It's not required for compiling, but needs to be available at runtime."
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
81
cmake/FindWin32SslRuntime.cmake
Normal file
81
cmake/FindWin32SslRuntime.cmake
Normal file
@@ -0,0 +1,81 @@
|
||||
# Find the OpenSSL runtime libraries (.dll) for Windows that
|
||||
# will be needed by Qt in order to access https urls.
|
||||
if(NOT DEFINED WIN32 OR NOT ${WIN32})
|
||||
message(STATUS "Non-Windows device trying to execute FindWin32SslRuntime, skipping")
|
||||
return()
|
||||
endif()
|
||||
|
||||
if("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "x64")
|
||||
message(STATUS "Looking for OpenSSL for ${CMAKE_GENERATOR_PLATFORM}")
|
||||
file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _programfiles)
|
||||
set(_OPENSSL_ROOT_PATHS
|
||||
"$ENV{VCPKG_PACKAGES_DIR}/x64-windows/bin"
|
||||
"C:/OpenSSL-Win64/bin"
|
||||
"C:/OpenSSL-Win64"
|
||||
"C:/Tools/vcpkg/installed/x64-windows/bin"
|
||||
"${_programfiles}/OpenSSL-Win64"
|
||||
"D:/a/Cockatrice/Qt/Tools/OpenSSL/Win_x64/bin"
|
||||
expanduser
|
||||
("~/Documents/Development/Qt/Tools/OpenSSL/Win_x64/bin")
|
||||
)
|
||||
unset(_programfiles)
|
||||
elseif("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "Win32")
|
||||
message(STATUS "Looking for OpenSSL for ${CMAKE_GENERATOR_PLATFORM}")
|
||||
file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _programfiles)
|
||||
set(_OPENSSL_ROOT_PATHS
|
||||
"$ENV{VCPKG_PACKAGES_DIR}/x86-windows/bin"
|
||||
"C:/OpenSSL-Win32/bin"
|
||||
"C:/OpenSSL-Win32"
|
||||
"C:/OpenSSL"
|
||||
"C:/Tools/vcpkg/installed/x86-windows/bin"
|
||||
"${_programfiles}/OpenSSL"
|
||||
"${_programfiles}/OpenSSL-Win32"
|
||||
"D:/a/Cockatrice/Qt/Tools/OpenSSL/Win_x86/bin"
|
||||
expanduser
|
||||
("~/Documents/Development/Qt/Tools/OpenSSL/Win_x86/bin")
|
||||
)
|
||||
unset(_programfiles)
|
||||
endif()
|
||||
|
||||
message(STATUS "Looking for OpenSSL @ ${CMAKE_GENERATOR_PLATFORM} in ${_OPENSSL_ROOT_PATHS}")
|
||||
if("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "x64")
|
||||
find_file(
|
||||
WIN32SSLRUNTIME_LIBEAY
|
||||
NAMES libcrypto-1_1-x64.dll libcrypto.dll
|
||||
PATHS ${_OPENSSL_ROOT_PATHS}
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
find_file(
|
||||
WIN32SSLRUNTIME_SSLEAY
|
||||
NAMES libssl-1_1-x64.dll libssl.dll
|
||||
PATHS ${_OPENSSL_ROOT_PATHS}
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
elseif("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "Win32")
|
||||
find_file(
|
||||
WIN32SSLRUNTIME_LIBEAY
|
||||
NAMES libcrypto-1_1.dll libcrypto.dll
|
||||
PATHS ${_OPENSSL_ROOT_PATHS}
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
find_file(
|
||||
WIN32SSLRUNTIME_SSLEAY
|
||||
NAMES libssl-1_1.dll libssl.dll
|
||||
PATHS ${_OPENSSL_ROOT_PATHS}
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WIN32SSLRUNTIME_LIBEAY AND WIN32SSLRUNTIME_SSLEAY)
|
||||
set(WIN32SSLRUNTIME_LIBRARIES "${WIN32SSLRUNTIME_LIBEAY}" "${WIN32SSLRUNTIME_SSLEAY}")
|
||||
set(WIN32SSLRUNTIME_FOUND "YES")
|
||||
message(STATUS "Found OpenSSL ${WIN32SSLRUNTIME_LIBRARIES}")
|
||||
else()
|
||||
set(WIN32SSLRUNTIME_FOUND "NO")
|
||||
message(
|
||||
WARNING
|
||||
"Could not find OpenSSL runtime libraries. They are not required for compiling, but needs to be available at runtime."
|
||||
)
|
||||
endif()
|
||||
|
||||
mark_as_advanced(WIN32SSLRUNTIME_LIBEAY WIN32SSLRUNTIME_SSLEAY)
|
||||
@@ -248,20 +248,20 @@ ${If} $PortableMode = 0
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "VersionMajor" "@CPACK_PACKAGE_VERSION_MAJOR@"
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "VersionMinor" "@CPACK_PACKAGE_VERSION_MINOR@"
|
||||
|
||||
IfFileExists "$INSTDIR\vc_redist.x86.exe" VcRedist86Exists PastVcRedist86Check
|
||||
IfFileExists "$INSTDIR\vcredist_x86.exe" VcRedist86Exists PastVcRedist86Check
|
||||
VcRedist86Exists:
|
||||
ExecWait '"$INSTDIR\vc_redist.x86.exe" /passive /norestart'
|
||||
ExecWait '"$INSTDIR\vcredist_x86.exe" /passive /norestart'
|
||||
DetailPrint "Wait to ensure unlock of vc_redist file after installation..."
|
||||
Sleep 3000
|
||||
Delete "$INSTDIR\vc_redist.x86.exe"
|
||||
Delete "$INSTDIR\vcredist_x86.exe"
|
||||
PastVcRedist86Check:
|
||||
|
||||
IfFileExists "$INSTDIR\vc_redist.x64.exe" VcRedist64Exists PastVcRedist64Check
|
||||
IfFileExists "$INSTDIR\vcredist_x64.exe" VcRedist64Exists PastVcRedist64Check
|
||||
VcRedist64Exists:
|
||||
ExecWait '"$INSTDIR\vc_redist.x64.exe" /passive /norestart'
|
||||
ExecWait '"$INSTDIR\vcredist_x64.exe" /passive /norestart'
|
||||
DetailPrint "Sleep to ensure unlock of vc_redist file after installation..."
|
||||
Sleep 3000
|
||||
Delete "$INSTDIR\vc_redist.x64.exe"
|
||||
Delete "$INSTDIR\vcredist_x64.exe"
|
||||
PastVcRedist64Check:
|
||||
|
||||
${Else}
|
||||
|
||||
Binary file not shown.
19
cmake/expanduser.cmake
Normal file
19
cmake/expanduser.cmake
Normal file
@@ -0,0 +1,19 @@
|
||||
# expands ~ to user home directory
|
||||
#
|
||||
# usage:
|
||||
# expanduser("~/code" x)
|
||||
|
||||
function(expanduser in outvar)
|
||||
|
||||
if(CMAKE_VERSION VERSION_LESS 3.21)
|
||||
get_filename_component(out ${in} ABSOLUTE)
|
||||
else()
|
||||
file(REAL_PATH ${in} out EXPAND_TILDE)
|
||||
endif()
|
||||
|
||||
set(${outvar}
|
||||
${out}
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
endfunction(expanduser)
|
||||
@@ -48,7 +48,6 @@ set(cockatrice_SOURCES
|
||||
src/dlg_load_remote_deck.cpp
|
||||
src/dlg_manage_sets.cpp
|
||||
src/dlg_register.cpp
|
||||
src/dlg_roll_dice.cpp
|
||||
src/dlg_settings.cpp
|
||||
src/dlg_tip_of_the_day.cpp
|
||||
src/dlg_update.cpp
|
||||
@@ -312,9 +311,15 @@ if(WIN32)
|
||||
PATTERN "audio/qtaudio_wasapi.dll"
|
||||
PATTERN "audio/qtaudio_windows.dll"
|
||||
PATTERN "iconengines/qsvgicon.dll"
|
||||
PATTERN "imageformats/*.dll"
|
||||
PATTERN "mediaservice/dsengine.dll"
|
||||
PATTERN "mediaservice/wmfengine.dll"
|
||||
PATTERN "imageformats/qgif.dll"
|
||||
PATTERN "imageformats/qicns.dll"
|
||||
PATTERN "imageformats/qico.dll"
|
||||
PATTERN "imageformats/qjpeg.dll"
|
||||
PATTERN "imageformats/qsvg.dll"
|
||||
PATTERN "imageformats/qtga.dll"
|
||||
PATTERN "imageformats/qtiff.dll"
|
||||
PATTERN "imageformats/qwbmp.dll"
|
||||
PATTERN "imageformats/qwebp.dll"
|
||||
PATTERN "platforms/qdirect2d.dll"
|
||||
PATTERN "platforms/qminimal.dll"
|
||||
PATTERN "platforms/qoffscreen.dll"
|
||||
@@ -350,8 +355,8 @@ Data = Resources\")
|
||||
COMPONENT Runtime
|
||||
)
|
||||
|
||||
if(OPENSSL_FOUND)
|
||||
install(FILES ${OPENSSL_INCLUDE_DIRS} DESTINATION ./)
|
||||
if(WIN32SSLRUNTIME_FOUND)
|
||||
install(FILES ${WIN32SSLRUNTIME_LIBRARIES} DESTINATION ./)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
@@ -351,10 +351,10 @@
|
||||
<file>resources/tips/images/cockatrice_wiki.png</file>
|
||||
<file>resources/tips/images/coin_flip.png</file>
|
||||
<file>resources/tips/images/counter_expression.png</file>
|
||||
<file>resources/tips/images/discord.png</file>
|
||||
<file>resources/tips/images/face_down.png</file>
|
||||
<file>resources/tips/images/filter_games.png</file>
|
||||
<file>resources/tips/images/github_logo.png</file>
|
||||
<file>resources/tips/images/gitter.png</file>
|
||||
<file>resources/tips/images/setpt.png</file>
|
||||
<file>resources/tips/images/shortcuts.png</file>
|
||||
<file>resources/tips/images/themes.png</file>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -1,7 +1,6 @@
|
||||
## Search Syntax Help
|
||||
## Syntax Help
|
||||
-----
|
||||
The search bar recognizes a set of special commands similar to some other card databases.<br>
|
||||
In this list of examples below, each entry has an explanation and can be clicked to test the query. Note that all searches are case insensitive.
|
||||
The search bar recognizes a set of special commands similar to some other card databases. Here is a list with examples. Each entry can be clicked to test the query and has a small explanation. Note that all searches are case insensitive.
|
||||
<dl>
|
||||
<dt>Name:</dt>
|
||||
<dd>[birds of paradise](#birds of paradise) <small>(Any card name containing the words birds, of, and paradise)</small></dd>
|
||||
@@ -47,7 +46,8 @@ In this list of examples below, each entry has an explanation and can be clicked
|
||||
|
||||
<dt><u>E</u>dition:</dt>
|
||||
<dd>[set:lea](#set:lea) <small>(Cards that appear in Alpha, which has the set code LEA)</small></dd>
|
||||
<dd>[e:lea or e:leb](#e:lea or e:leb) <small>(Cards that appear in Alpha or Beta)</small></dd>
|
||||
<dd>[e:lea,leb](#e:lea,leb) <small>(Cards that appear in Alpha or Beta)</small></dd>
|
||||
<dd><a href="#e:lea,leb -(e:lea e:leb)">e:lea,leb -(e:lea e:leb)</a> <small>(Cards that appear in Alpha or Beta but not in both editions)</small></dd>
|
||||
|
||||
<dt>Negate:</dt>
|
||||
<dd>[c:wu -c:m](#c:wu -c:m) <small>(Any card that is white or blue, but not multicolored)</small></dd>
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 30 KiB |
BIN
cockatrice/resources/tips/images/gitter.png
Normal file
BIN
cockatrice/resources/tips/images/gitter.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.9 KiB |
@@ -7,9 +7,9 @@
|
||||
</tip>
|
||||
<tip>
|
||||
<title>Suggesting New Tips</title>
|
||||
<text>You can suggest new Tips of the Day by reaching out to the development team on <a href="https://discord.gg/3Z9yzmA">Discord</a>!</text>
|
||||
<image>discord.png</image>
|
||||
<date>2023-10-18</date>
|
||||
<text>You can suggest new Tips of the Day by reaching out to the development team on <a href="https://gitter.im/cockatrice/cockatrice">Gitter</a>!</text>
|
||||
<image>gitter.png</image>
|
||||
<date>2018-03-01</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>Reporting Bugs</title>
|
||||
|
||||
@@ -20,8 +20,13 @@ AbstractCardDragItem::AbstractCardDragItem(AbstractCardItem *_item,
|
||||
parentDrag->addChildDrag(this);
|
||||
setZValue(2000000007 + hotSpot.x() * 1000000 + hotSpot.y() * 1000 + 1000);
|
||||
} else {
|
||||
hotSpot = QPointF{qBound(0.0, hotSpot.x(), static_cast<qreal>(CARD_WIDTH - 1)),
|
||||
qBound(0.0, hotSpot.y(), static_cast<qreal>(CARD_HEIGHT - 1))};
|
||||
if ((hotSpot.x() < 0) || (hotSpot.y() < 0)) {
|
||||
qDebug() << "CardDragItem: coordinate overflow: x =" << hotSpot.x() << ", y =" << hotSpot.y();
|
||||
hotSpot = QPointF();
|
||||
} else if ((hotSpot.x() > CARD_WIDTH) || (hotSpot.y() > CARD_HEIGHT)) {
|
||||
qDebug() << "CardDragItem: coordinate overflow: x =" << hotSpot.x() << ", y =" << hotSpot.y();
|
||||
hotSpot = QPointF(CARD_WIDTH, CARD_HEIGHT);
|
||||
}
|
||||
setCursor(Qt::ClosedHandCursor);
|
||||
setZValue(2000000007);
|
||||
}
|
||||
@@ -40,19 +45,12 @@ AbstractCardDragItem::~AbstractCardDragItem()
|
||||
delete childDrags[i];
|
||||
}
|
||||
|
||||
QPainterPath AbstractCardDragItem::shape() const
|
||||
{
|
||||
QPainterPath shape;
|
||||
shape.addRoundedRect(boundingRect(), 0.05 * CARD_WIDTH, 0.05 * CARD_WIDTH);
|
||||
return shape;
|
||||
}
|
||||
|
||||
void AbstractCardDragItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||
{
|
||||
item->paint(painter, option, widget);
|
||||
|
||||
// adds a mask to the card so it looks like the card hasnt been placed yet
|
||||
painter->fillPath(shape(), GHOST_MASK);
|
||||
painter->fillRect(boundingRect(), GHOST_MASK);
|
||||
}
|
||||
|
||||
void AbstractCardDragItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
||||
|
||||
@@ -21,18 +21,17 @@ public:
|
||||
{
|
||||
Type = typeCardDrag
|
||||
};
|
||||
int type() const override
|
||||
int type() const
|
||||
{
|
||||
return Type;
|
||||
}
|
||||
AbstractCardDragItem(AbstractCardItem *_item, const QPointF &_hotSpot, AbstractCardDragItem *parentDrag = 0);
|
||||
~AbstractCardDragItem();
|
||||
QRectF boundingRect() const override
|
||||
QRectF boundingRect() const
|
||||
{
|
||||
return QRectF(0, 0, CARD_WIDTH, CARD_HEIGHT);
|
||||
}
|
||||
QPainterPath shape() const override;
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
|
||||
AbstractCardItem *getItem() const
|
||||
{
|
||||
return item;
|
||||
@@ -45,7 +44,7 @@ public:
|
||||
virtual void updatePosition(const QPointF &cursorScenePos) = 0;
|
||||
|
||||
protected:
|
||||
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -34,13 +34,6 @@ QRectF AbstractCardItem::boundingRect() const
|
||||
return QRectF(0, 0, CARD_WIDTH, CARD_HEIGHT);
|
||||
}
|
||||
|
||||
QPainterPath AbstractCardItem::shape() const
|
||||
{
|
||||
QPainterPath shape;
|
||||
shape.addRoundedRect(boundingRect(), 0.05 * CARD_WIDTH, 0.05 * CARD_WIDTH);
|
||||
return shape;
|
||||
}
|
||||
|
||||
void AbstractCardItem::pixmapUpdated()
|
||||
{
|
||||
update();
|
||||
@@ -120,14 +113,24 @@ void AbstractCardItem::paintPicture(QPainter *painter, const QSizeF &translatedS
|
||||
|
||||
if (paintImage) {
|
||||
painter->save();
|
||||
painter->setClipPath(shape());
|
||||
painter->drawPixmap(boundingRect(), translatedPixmap, QRectF({0, 0}, translatedPixmap.size()));
|
||||
transformPainter(painter, translatedSize, angle);
|
||||
painter->drawPixmap(QPointF(1, 1), translatedPixmap);
|
||||
painter->restore();
|
||||
} else {
|
||||
painter->setBrush(bgColor);
|
||||
painter->drawPath(shape());
|
||||
}
|
||||
|
||||
QPen pen(Qt::black);
|
||||
pen.setJoinStyle(Qt::MiterJoin);
|
||||
const int penWidth = 2;
|
||||
pen.setWidth(penWidth);
|
||||
painter->setPen(pen);
|
||||
|
||||
if (!angle)
|
||||
painter->drawRect(QRectF(0, 0, CARD_WIDTH - 1, CARD_HEIGHT - penWidth));
|
||||
else
|
||||
painter->drawRect(QRectF(1, 1, CARD_WIDTH - 2, CARD_HEIGHT - 1.5));
|
||||
|
||||
if (translatedPixmap.isNull() || SettingsCache::instance().getDisplayCardNames() || facedown) {
|
||||
painter->save();
|
||||
transformPainter(painter, translatedSize, angle);
|
||||
@@ -155,7 +158,9 @@ void AbstractCardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *
|
||||
QSizeF translatedSize = getTranslatedSize(painter);
|
||||
paintPicture(painter, translatedSize, tapAngle);
|
||||
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing, false);
|
||||
transformPainter(painter, translatedSize, tapAngle);
|
||||
|
||||
if (isSelected() || isHovered) {
|
||||
QPen pen;
|
||||
@@ -163,12 +168,15 @@ void AbstractCardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *
|
||||
pen.setColor(Qt::yellow);
|
||||
if (isSelected())
|
||||
pen.setColor(Qt::red);
|
||||
pen.setWidth(0); // Cosmetic pen
|
||||
const int penWidth = 1;
|
||||
pen.setWidth(penWidth);
|
||||
painter->setPen(pen);
|
||||
painter->drawPath(shape());
|
||||
painter->drawRect(QRectF(0, 0, translatedSize.width() + penWidth, translatedSize.height() - penWidth));
|
||||
}
|
||||
|
||||
painter->restore();
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
void AbstractCardItem::setName(const QString &_name)
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
{
|
||||
Type = typeCard
|
||||
};
|
||||
int type() const override
|
||||
int type() const
|
||||
{
|
||||
return Type;
|
||||
}
|
||||
@@ -53,11 +53,10 @@ public:
|
||||
int _id = -1,
|
||||
QGraphicsItem *parent = nullptr);
|
||||
~AbstractCardItem();
|
||||
QRectF boundingRect() const override;
|
||||
QPainterPath shape() const override;
|
||||
QRectF boundingRect() const;
|
||||
QSizeF getTranslatedSize(QPainter *painter) const;
|
||||
void paintPicture(QPainter *painter, const QSizeF &translatedSize, int angle);
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
|
||||
CardInfoPtr getInfo() const
|
||||
{
|
||||
return info;
|
||||
@@ -104,9 +103,9 @@ public:
|
||||
|
||||
protected:
|
||||
void transformPainter(QPainter *painter, const QSizeF &translatedSize, int angle);
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) override;
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent *event);
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
|
||||
QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value);
|
||||
void cacheBgColor();
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "abstractclient.h"
|
||||
|
||||
#include "client_metatypes.h"
|
||||
#include "featureset.h"
|
||||
#include "get_pb_extension.h"
|
||||
#include "pb/commands.pb.h"
|
||||
|
||||
@@ -266,14 +266,9 @@ CardInfoPtr CardInfo::newInstance(const QString &_name,
|
||||
|
||||
QString CardInfo::getCorrectedName() const
|
||||
{
|
||||
// remove all the characters reserved in windows file paths,
|
||||
// other oses only disallow a subset of these so it covers all
|
||||
static const QRegularExpression rmrx(R"(( // |[*<>:"\\?\x00-\x08\x10-\x1f]))");
|
||||
static const QRegularExpression spacerx(R"([/\x09-\x0f])");
|
||||
static const QString space(' ');
|
||||
QString result = name;
|
||||
// Fire // Ice, Circle of Protection: Red, "Ach! Hans, Run!", Who/What/When/Where/Why, Question Elemental?
|
||||
return result.remove(rmrx).replace(spacerx, space);
|
||||
return result.remove(" // ").remove(':').remove('"').remove('?').replace('/', ' ');
|
||||
}
|
||||
|
||||
void CardInfo::addToSet(const CardSetPtr &_set, const CardInfoPerSet _info)
|
||||
@@ -592,9 +587,9 @@ void CardDatabase::refreshCachedReverseRelatedCards()
|
||||
continue;
|
||||
}
|
||||
|
||||
auto *newCardRelation = new CardRelation(
|
||||
card->getName(), cardRelation->getAttachType(), cardRelation->getIsCreateAllExclusion(),
|
||||
cardRelation->getIsVariable(), cardRelation->getDefaultCount(), cardRelation->getIsPersistent());
|
||||
auto *newCardRelation = new CardRelation(card->getName(), cardRelation->getDoesAttach(),
|
||||
cardRelation->getIsCreateAllExclusion(),
|
||||
cardRelation->getIsVariable(), cardRelation->getDefaultCount());
|
||||
cards.value(targetCard)->addReverseRelatedCards2Me(newCardRelation);
|
||||
}
|
||||
}
|
||||
@@ -612,22 +607,22 @@ QStringList CardDatabase::getAllMainCardTypes() const
|
||||
|
||||
void CardDatabase::checkUnknownSets()
|
||||
{
|
||||
auto _sets = getSetList();
|
||||
SetList sets = getSetList();
|
||||
|
||||
if (_sets.getEnabledSetsNum()) {
|
||||
if (sets.getEnabledSetsNum()) {
|
||||
// if some sets are first found on this run, ask the user
|
||||
int numUnknownSets = _sets.getUnknownSetsNum();
|
||||
QStringList unknownSetNames = _sets.getUnknownSetsNames();
|
||||
int numUnknownSets = sets.getUnknownSetsNum();
|
||||
QStringList unknownSetNames = sets.getUnknownSetsNames();
|
||||
if (numUnknownSets > 0) {
|
||||
emit cardDatabaseNewSetsFound(numUnknownSets, unknownSetNames);
|
||||
} else {
|
||||
_sets.markAllAsKnown();
|
||||
sets.markAllAsKnown();
|
||||
}
|
||||
} else {
|
||||
// No set enabled. Probably this is the first time running trice
|
||||
_sets.guessSortKeys();
|
||||
_sets.sortByKey();
|
||||
_sets.enableAll();
|
||||
sets.guessSortKeys();
|
||||
sets.sortByKey();
|
||||
sets.enableAll();
|
||||
notifyEnabledSetsChanged();
|
||||
|
||||
emit cardDatabaseAllNewSetsEnabled();
|
||||
@@ -636,14 +631,14 @@ void CardDatabase::checkUnknownSets()
|
||||
|
||||
void CardDatabase::enableAllUnknownSets()
|
||||
{
|
||||
auto _sets = getSetList();
|
||||
_sets.enableAllUnknown();
|
||||
SetList sets = getSetList();
|
||||
sets.enableAllUnknown();
|
||||
}
|
||||
|
||||
void CardDatabase::markAllSetsAsKnown()
|
||||
{
|
||||
auto _sets = getSetList();
|
||||
_sets.markAllAsKnown();
|
||||
SetList sets = getSetList();
|
||||
sets.markAllAsKnown();
|
||||
}
|
||||
|
||||
void CardDatabase::notifyEnabledSetsChanged()
|
||||
@@ -677,12 +672,12 @@ bool CardDatabase::saveCustomTokensToFile()
|
||||
}
|
||||
|
||||
CardRelation::CardRelation(const QString &_name,
|
||||
AttachType _attachType,
|
||||
bool _doesAttach,
|
||||
bool _isCreateAllExclusion,
|
||||
bool _isVariableCount,
|
||||
int _defaultCount,
|
||||
bool _isPersistent)
|
||||
: name(_name), attachType(_attachType), isCreateAllExclusion(_isCreateAllExclusion),
|
||||
: name(_name), doesAttach(_doesAttach), isCreateAllExclusion(_isCreateAllExclusion),
|
||||
isVariableCount(_isVariableCount), defaultCount(_defaultCount), isPersistent(_isPersistent)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -452,17 +452,9 @@ signals:
|
||||
class CardRelation : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum AttachType
|
||||
{
|
||||
DoesNotAttach = 0,
|
||||
AttachTo = 1,
|
||||
TransformInto = 2,
|
||||
};
|
||||
|
||||
private:
|
||||
QString name;
|
||||
AttachType attachType;
|
||||
bool doesAttach;
|
||||
bool isCreateAllExclusion;
|
||||
bool isVariableCount;
|
||||
int defaultCount;
|
||||
@@ -470,7 +462,7 @@ private:
|
||||
|
||||
public:
|
||||
explicit CardRelation(const QString &_name = QString(),
|
||||
AttachType _attachType = DoesNotAttach,
|
||||
bool _doesAttach = false,
|
||||
bool _isCreateAllExclusion = false,
|
||||
bool _isVariableCount = false,
|
||||
int _defaultCount = 1,
|
||||
@@ -480,32 +472,13 @@ public:
|
||||
{
|
||||
return name;
|
||||
}
|
||||
AttachType getAttachType() const
|
||||
{
|
||||
return attachType;
|
||||
}
|
||||
bool getDoesAttach() const
|
||||
{
|
||||
return attachType != DoesNotAttach;
|
||||
}
|
||||
bool getDoesTransform() const
|
||||
{
|
||||
return attachType == TransformInto;
|
||||
}
|
||||
QString getAttachTypeAsString() const
|
||||
{
|
||||
switch (attachType) {
|
||||
case AttachTo:
|
||||
return "attach";
|
||||
case TransformInto:
|
||||
return "transform";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
return doesAttach;
|
||||
}
|
||||
bool getCanCreateAnother() const
|
||||
{
|
||||
return !getDoesAttach();
|
||||
return !doesAttach;
|
||||
}
|
||||
bool getIsCreateAllExclusion() const
|
||||
{
|
||||
|
||||
@@ -326,12 +326,12 @@ void CardDatabaseDisplayModel::clearFilterAll()
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
void CardDatabaseDisplayModel::setFilterTree(FilterTree *_filterTree)
|
||||
void CardDatabaseDisplayModel::setFilterTree(FilterTree *filterTree)
|
||||
{
|
||||
if (this->filterTree != nullptr)
|
||||
disconnect(this->filterTree, nullptr, this, nullptr);
|
||||
|
||||
this->filterTree = _filterTree;
|
||||
this->filterTree = filterTree;
|
||||
connect(this->filterTree, SIGNAL(changed()), this, SLOT(filterTreeChanged()));
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ private:
|
||||
|
||||
public:
|
||||
explicit CardDatabaseDisplayModel(QObject *parent = nullptr);
|
||||
void setFilterTree(FilterTree *_filterTree);
|
||||
void setFilterTree(FilterTree *filterTree);
|
||||
void setIsToken(FilterBool _isToken)
|
||||
{
|
||||
isToken = _isToken;
|
||||
|
||||
@@ -155,7 +155,7 @@ void CockatriceXml3Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
||||
QVariantHash properties = QVariantHash();
|
||||
QString colors = QString("");
|
||||
QList<CardRelation *> relatedCards, reverseRelatedCards;
|
||||
auto _sets = CardInfoPerSetMap();
|
||||
CardInfoPerSetMap sets = CardInfoPerSetMap();
|
||||
int tableRow = 0;
|
||||
bool cipt = false;
|
||||
bool isToken = false;
|
||||
@@ -221,10 +221,10 @@ void CockatriceXml3Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
||||
if (attrs.hasAttribute("rarity")) {
|
||||
setInfo.setProperty("rarity", attrs.value("rarity").toString());
|
||||
}
|
||||
_sets.insert(setName, setInfo);
|
||||
sets.insert(setName, setInfo);
|
||||
// related cards
|
||||
} else if (xmlName == "related" || xmlName == "reverse-related") {
|
||||
CardRelation::AttachType attach = CardRelation::DoesNotAttach;
|
||||
bool attach = false;
|
||||
bool exclude = false;
|
||||
bool variable = false;
|
||||
int count = 1;
|
||||
@@ -246,7 +246,7 @@ void CockatriceXml3Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
||||
}
|
||||
|
||||
if (attrs.hasAttribute("attach")) {
|
||||
attach = CardRelation::AttachTo;
|
||||
attach = true;
|
||||
}
|
||||
|
||||
if (attrs.hasAttribute("exclude")) {
|
||||
@@ -268,7 +268,7 @@ void CockatriceXml3Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
||||
|
||||
properties.insert("colors", colors);
|
||||
CardInfoPtr newCard = CardInfo::newInstance(name, text, isToken, properties, relatedCards,
|
||||
reverseRelatedCards, _sets, cipt, tableRow, upsideDown);
|
||||
reverseRelatedCards, sets, cipt, tableRow, upsideDown);
|
||||
emit addCard(newCard);
|
||||
}
|
||||
}
|
||||
@@ -412,7 +412,7 @@ static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfoPtr &in
|
||||
return xml;
|
||||
}
|
||||
|
||||
bool CockatriceXml3Parser::saveToFile(SetNameMap _sets,
|
||||
bool CockatriceXml3Parser::saveToFile(SetNameMap sets,
|
||||
CardNameMap cards,
|
||||
const QString &fileName,
|
||||
const QString &sourceUrl,
|
||||
@@ -439,9 +439,9 @@ bool CockatriceXml3Parser::saveToFile(SetNameMap _sets,
|
||||
xml.writeTextElement("sourceVersion", sourceVersion);
|
||||
xml.writeEndElement();
|
||||
|
||||
if (_sets.count() > 0) {
|
||||
if (sets.count() > 0) {
|
||||
xml.writeStartElement("sets");
|
||||
for (CardSetPtr set : _sets) {
|
||||
for (CardSetPtr set : sets) {
|
||||
xml << set;
|
||||
}
|
||||
xml.writeEndElement();
|
||||
@@ -459,4 +459,4 @@ bool CockatriceXml3Parser::saveToFile(SetNameMap _sets,
|
||||
xml.writeEndDocument();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ public:
|
||||
~CockatriceXml3Parser() override = default;
|
||||
bool getCanParseFile(const QString &name, QIODevice &device) override;
|
||||
void parseFile(QIODevice &device) override;
|
||||
bool saveToFile(SetNameMap _sets,
|
||||
bool saveToFile(SetNameMap sets,
|
||||
CardNameMap cards,
|
||||
const QString &fileName,
|
||||
const QString &sourceUrl = "unknown",
|
||||
|
||||
@@ -134,7 +134,7 @@ void CockatriceXml4Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
||||
QString text = QString("");
|
||||
QVariantHash properties = QVariantHash();
|
||||
QList<CardRelation *> relatedCards, reverseRelatedCards;
|
||||
auto _sets = CardInfoPerSetMap();
|
||||
CardInfoPerSetMap sets = CardInfoPerSetMap();
|
||||
int tableRow = 0;
|
||||
bool cipt = false;
|
||||
bool isToken = false;
|
||||
@@ -178,11 +178,11 @@ void CockatriceXml4Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
||||
attrName = "picurl";
|
||||
setInfo.setProperty(attrName, attr.value().toString());
|
||||
}
|
||||
_sets.insert(setName, setInfo);
|
||||
sets.insert(setName, setInfo);
|
||||
}
|
||||
// related cards
|
||||
} else if (xmlName == "related" || xmlName == "reverse-related") {
|
||||
CardRelation::AttachType attachType = CardRelation::DoesNotAttach;
|
||||
bool attach = false;
|
||||
bool exclude = false;
|
||||
bool variable = false;
|
||||
bool persistent = false;
|
||||
@@ -205,8 +205,7 @@ void CockatriceXml4Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
||||
}
|
||||
|
||||
if (attrs.hasAttribute("attach")) {
|
||||
attachType = attrs.value("attach").toString() == "transform" ? CardRelation::TransformInto
|
||||
: CardRelation::AttachTo;
|
||||
attach = true;
|
||||
}
|
||||
|
||||
if (attrs.hasAttribute("exclude")) {
|
||||
@@ -217,7 +216,7 @@ void CockatriceXml4Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
||||
persistent = true;
|
||||
}
|
||||
|
||||
auto *relation = new CardRelation(cardName, attachType, exclude, variable, count, persistent);
|
||||
auto *relation = new CardRelation(cardName, attach, exclude, variable, count, persistent);
|
||||
if (xmlName == "reverse-related") {
|
||||
reverseRelatedCards << relation;
|
||||
} else {
|
||||
@@ -231,7 +230,7 @@ void CockatriceXml4Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
||||
}
|
||||
|
||||
CardInfoPtr newCard = CardInfo::newInstance(name, text, isToken, properties, relatedCards,
|
||||
reverseRelatedCards, _sets, cipt, tableRow, upsideDown);
|
||||
reverseRelatedCards, sets, cipt, tableRow, upsideDown);
|
||||
emit addCard(newCard);
|
||||
}
|
||||
}
|
||||
@@ -295,7 +294,7 @@ static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfoPtr &in
|
||||
for (auto i : related) {
|
||||
xml.writeStartElement("related");
|
||||
if (i->getDoesAttach()) {
|
||||
xml.writeAttribute("attach", i->getAttachTypeAsString());
|
||||
xml.writeAttribute("attach", "attach");
|
||||
}
|
||||
if (i->getIsCreateAllExclusion()) {
|
||||
xml.writeAttribute("exclude", "exclude");
|
||||
@@ -319,7 +318,7 @@ static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfoPtr &in
|
||||
for (auto i : reverseRelated) {
|
||||
xml.writeStartElement("reverse-related");
|
||||
if (i->getDoesAttach()) {
|
||||
xml.writeAttribute("attach", i->getAttachTypeAsString());
|
||||
xml.writeAttribute("attach", "attach");
|
||||
}
|
||||
|
||||
if (i->getIsCreateAllExclusion()) {
|
||||
@@ -356,7 +355,7 @@ static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfoPtr &in
|
||||
return xml;
|
||||
}
|
||||
|
||||
bool CockatriceXml4Parser::saveToFile(SetNameMap _sets,
|
||||
bool CockatriceXml4Parser::saveToFile(SetNameMap sets,
|
||||
CardNameMap cards,
|
||||
const QString &fileName,
|
||||
const QString &sourceUrl,
|
||||
@@ -383,9 +382,9 @@ bool CockatriceXml4Parser::saveToFile(SetNameMap _sets,
|
||||
xml.writeTextElement("sourceVersion", sourceVersion);
|
||||
xml.writeEndElement();
|
||||
|
||||
if (_sets.count() > 0) {
|
||||
if (sets.count() > 0) {
|
||||
xml.writeStartElement("sets");
|
||||
for (CardSetPtr set : _sets) {
|
||||
for (CardSetPtr set : sets) {
|
||||
xml << set;
|
||||
}
|
||||
xml.writeEndElement();
|
||||
|
||||
@@ -14,7 +14,7 @@ public:
|
||||
~CockatriceXml4Parser() override = default;
|
||||
bool getCanParseFile(const QString &name, QIODevice &device) override;
|
||||
void parseFile(QIODevice &device) override;
|
||||
bool saveToFile(SetNameMap _sets,
|
||||
bool saveToFile(SetNameMap sets,
|
||||
CardNameMap cards,
|
||||
const QString &fileName,
|
||||
const QString &sourceUrl = "unknown",
|
||||
|
||||
@@ -24,7 +24,7 @@ void CardDragItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti
|
||||
AbstractCardDragItem::paint(painter, option, widget);
|
||||
|
||||
if (occupied)
|
||||
painter->fillPath(shape(), QColor(200, 0, 0, 100));
|
||||
painter->fillRect(boundingRect(), QColor(200, 0, 0, 100));
|
||||
}
|
||||
|
||||
void CardDragItem::updatePosition(const QPointF &cursorScenePos)
|
||||
@@ -53,20 +53,8 @@ void CardDragItem::updatePosition(const QPointF &cursorScenePos)
|
||||
|
||||
QPointF zonePos = currentZone->scenePos();
|
||||
QPointF cursorPosInZone = cursorScenePos - zonePos;
|
||||
|
||||
// If we are on a Table, we center the card around the cursor, because we
|
||||
// snap it into place and no longer see it being dragged.
|
||||
//
|
||||
// For other zones (where we do display the card under the cursor), we use
|
||||
// the hotspot to feel like the card was dragged at the corresponding
|
||||
// position.
|
||||
TableZone *tableZone = qobject_cast<TableZone *>(cursorZone);
|
||||
QPointF closestGridPoint;
|
||||
if (tableZone)
|
||||
closestGridPoint = tableZone->closestGridPoint(cursorPosInZone);
|
||||
else
|
||||
closestGridPoint = cursorPosInZone - hotSpot;
|
||||
|
||||
QPointF cardTopLeft = cursorPosInZone - hotSpot;
|
||||
QPointF closestGridPoint = cursorZone->closestGridPoint(cardTopLeft);
|
||||
QPointF newPos = zonePos + closestGridPoint;
|
||||
|
||||
if (newPos != pos()) {
|
||||
@@ -95,7 +83,7 @@ void CardDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||
|
||||
QList<CardDragItem *> dragItemList;
|
||||
CardZone *startZone = static_cast<CardItem *>(item)->getZone();
|
||||
if (currentZone && !(static_cast<CardItem *>(item)->getAttachedTo() && (startZone == currentZone)) && !occupied) {
|
||||
if (currentZone && !(static_cast<CardItem *>(item)->getAttachedTo() && (startZone == currentZone))) {
|
||||
dragItemList.append(this);
|
||||
for (int i = 0; i < childDrags.size(); i++) {
|
||||
CardDragItem *c = static_cast<CardDragItem *>(childDrags[i]);
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
#include "main.h"
|
||||
#include "pictureloader.h"
|
||||
|
||||
#include <QStylePainter>
|
||||
#include <QPainter>
|
||||
#include <QStyle>
|
||||
#include <QWidget>
|
||||
|
||||
CardInfoPicture::CardInfoPicture(QWidget *parent) : QWidget(parent), info(nullptr), pixmapDirty(true)
|
||||
@@ -54,13 +55,6 @@ void CardInfoPicture::paintEvent(QPaintEvent *)
|
||||
if (pixmapDirty)
|
||||
loadPixmap();
|
||||
|
||||
QSize scaledSize = resizedPixmap.size().scaled(size(), Qt::KeepAspectRatio);
|
||||
QPoint topLeft{(width() - scaledSize.width()) / 2, (height() - scaledSize.height()) / 2};
|
||||
qreal radius = 0.05 * scaledSize.width();
|
||||
|
||||
QStylePainter painter(this);
|
||||
QPainterPath shape;
|
||||
shape.addRoundedRect(QRect(topLeft, scaledSize), radius, radius);
|
||||
painter.setClipPath(shape);
|
||||
painter.drawItemPixmap(QRect(topLeft, scaledSize), Qt::AlignCenter, resizedPixmap);
|
||||
QPainter painter(this);
|
||||
style()->drawItemPixmap(&painter, rect(), Qt::AlignHCenter, resizedPixmap);
|
||||
}
|
||||
|
||||
@@ -97,10 +97,10 @@ void CardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
|
||||
QMapIterator<int, int> counterIterator(counters);
|
||||
while (counterIterator.hasNext()) {
|
||||
counterIterator.next();
|
||||
QColor _color;
|
||||
_color.setHsv(counterIterator.key() * 60, 150, 255);
|
||||
QColor color;
|
||||
color.setHsv(counterIterator.key() * 60, 150, 255);
|
||||
|
||||
paintNumberEllipse(counterIterator.value(), 14, _color, i, counters.size(), painter);
|
||||
paintNumberEllipse(counterIterator.value(), 14, color, i, counters.size(), painter);
|
||||
++i;
|
||||
}
|
||||
|
||||
@@ -141,19 +141,21 @@ void CardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
|
||||
}
|
||||
|
||||
if (getBeingPointedAt()) {
|
||||
painter->fillPath(shape(), QBrush(QColor(255, 0, 0, 100)));
|
||||
painter->fillRect(boundingRect(), QBrush(QColor(255, 0, 0, 100)));
|
||||
}
|
||||
|
||||
if (doesntUntap) {
|
||||
painter->save();
|
||||
|
||||
painter->setRenderHint(QPainter::Antialiasing, false);
|
||||
transformPainter(painter, translatedSize, tapAngle);
|
||||
|
||||
QPen pen;
|
||||
pen.setColor(Qt::magenta);
|
||||
pen.setWidth(0); // Cosmetic pen
|
||||
const int penWidth = 1;
|
||||
pen.setWidth(penWidth);
|
||||
painter->setPen(pen);
|
||||
painter->drawPath(shape());
|
||||
painter->drawRect(QRectF(0, 0, translatedSize.width() + penWidth, translatedSize.height() - penWidth));
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
@@ -233,25 +235,25 @@ void CardItem::resetState()
|
||||
update();
|
||||
}
|
||||
|
||||
void CardItem::processCardInfo(const ServerInfo_Card &_info)
|
||||
void CardItem::processCardInfo(const ServerInfo_Card &info)
|
||||
{
|
||||
counters.clear();
|
||||
const int counterListSize = _info.counter_list_size();
|
||||
const int counterListSize = info.counter_list_size();
|
||||
for (int i = 0; i < counterListSize; ++i) {
|
||||
const ServerInfo_CardCounter &counterInfo = _info.counter_list(i);
|
||||
const ServerInfo_CardCounter &counterInfo = info.counter_list(i);
|
||||
counters.insert(counterInfo.id(), counterInfo.value());
|
||||
}
|
||||
|
||||
setId(_info.id());
|
||||
setName(QString::fromStdString(_info.name()));
|
||||
setAttacking(_info.attacking());
|
||||
setFaceDown(_info.face_down());
|
||||
setPT(QString::fromStdString(_info.pt()));
|
||||
setAnnotation(QString::fromStdString(_info.annotation()));
|
||||
setColor(QString::fromStdString(_info.color()));
|
||||
setTapped(_info.tapped());
|
||||
setDestroyOnZoneChange(_info.destroy_on_zone_change());
|
||||
setDoesntUntap(_info.doesnt_untap());
|
||||
setId(info.id());
|
||||
setName(QString::fromStdString(info.name()));
|
||||
setAttacking(info.attacking());
|
||||
setFaceDown(info.face_down());
|
||||
setPT(QString::fromStdString(info.pt()));
|
||||
setAnnotation(QString::fromStdString(info.annotation()));
|
||||
setColor(QString::fromStdString(info.color()));
|
||||
setTapped(info.tapped());
|
||||
setDestroyOnZoneChange(info.destroy_on_zone_change());
|
||||
setDoesntUntap(info.doesnt_untap());
|
||||
}
|
||||
|
||||
CardDragItem *CardItem::createDragItem(int _id, const QPointF &_pos, const QPointF &_scenePos, bool faceDown)
|
||||
@@ -348,9 +350,7 @@ void CardItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
||||
|
||||
bool forceFaceDown = event->modifiers().testFlag(Qt::ShiftModifier);
|
||||
|
||||
// Use the buttonDownPos to align the hot spot with the position when
|
||||
// the user originally clicked
|
||||
createDragItem(id, event->buttonDownPos(Qt::LeftButton), event->scenePos(), facedown || forceFaceDown);
|
||||
createDragItem(id, event->pos(), event->scenePos(), facedown || forceFaceDown);
|
||||
dragItem->grabMouse();
|
||||
|
||||
int childIndex = 0;
|
||||
|
||||
@@ -138,7 +138,7 @@ public:
|
||||
return attachedCards;
|
||||
}
|
||||
void resetState();
|
||||
void processCardInfo(const ServerInfo_Card &_info);
|
||||
void processCardInfo(const ServerInfo_Card &info);
|
||||
|
||||
QMenu *getCardMenu() const
|
||||
{
|
||||
|
||||
@@ -470,23 +470,15 @@ void ChatView::showSystemPopup(const QString &userName)
|
||||
|
||||
QColor ChatView::getCustomMentionColor()
|
||||
{
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 4, 0))
|
||||
QColor customColor = QColor::fromString("#" + SettingsCache::instance().getChatMentionColor());
|
||||
#else
|
||||
QColor customColor;
|
||||
customColor.setNamedColor("#" + SettingsCache::instance().getChatMentionColor());
|
||||
#endif
|
||||
return customColor.isValid() ? customColor : DEFAULT_MENTION_COLOR;
|
||||
}
|
||||
|
||||
QColor ChatView::getCustomHighlightColor()
|
||||
{
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 4, 0))
|
||||
QColor customColor = QColor::fromString("#" + SettingsCache::instance().getChatMentionColor());
|
||||
#else
|
||||
QColor customColor;
|
||||
customColor.setNamedColor("#" + SettingsCache::instance().getChatMentionColor());
|
||||
#endif
|
||||
customColor.setNamedColor("#" + SettingsCache::instance().getChatHighlightColor());
|
||||
return customColor.isValid() ? customColor : DEFAULT_MENTION_COLOR;
|
||||
}
|
||||
|
||||
|
||||
@@ -65,8 +65,8 @@ private:
|
||||
QTextCursor prepareBlock(bool same = false);
|
||||
void appendCardTag(QTextCursor &cursor, const QString &cardName);
|
||||
void appendUrlTag(QTextCursor &cursor, QString url);
|
||||
static QColor getCustomMentionColor();
|
||||
static QColor getCustomHighlightColor();
|
||||
QColor getCustomMentionColor();
|
||||
QColor getCustomHighlightColor();
|
||||
void showSystemPopup(const QString &userName);
|
||||
bool isModeratorSendingGlobal(QFlags<ServerInfo_User::UserLevelFlag> userLevelFlag, QString message);
|
||||
void checkTag(QTextCursor &cursor, QString &message);
|
||||
|
||||
29
cockatrice/src/client_metatypes.h
Normal file
29
cockatrice/src/client_metatypes.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifndef CLIENT_METATYPES_H
|
||||
#define CLIENT_METATYPES_H
|
||||
|
||||
#include <QMetaType>
|
||||
|
||||
Q_DECLARE_METATYPE(QVariant)
|
||||
Q_DECLARE_METATYPE(CommandContainer)
|
||||
Q_DECLARE_METATYPE(Response)
|
||||
Q_DECLARE_METATYPE(Response::ResponseCode)
|
||||
Q_DECLARE_METATYPE(ClientStatus)
|
||||
Q_DECLARE_METATYPE(RoomEvent)
|
||||
Q_DECLARE_METATYPE(GameEventContainer)
|
||||
Q_DECLARE_METATYPE(Event_ServerIdentification)
|
||||
Q_DECLARE_METATYPE(Event_ConnectionClosed)
|
||||
Q_DECLARE_METATYPE(Event_ServerShutdown)
|
||||
Q_DECLARE_METATYPE(Event_AddToList)
|
||||
Q_DECLARE_METATYPE(Event_RemoveFromList)
|
||||
Q_DECLARE_METATYPE(Event_UserJoined)
|
||||
Q_DECLARE_METATYPE(Event_UserLeft)
|
||||
Q_DECLARE_METATYPE(Event_ServerMessage)
|
||||
Q_DECLARE_METATYPE(Event_ListRooms)
|
||||
Q_DECLARE_METATYPE(Event_GameJoined)
|
||||
Q_DECLARE_METATYPE(Event_UserMessage)
|
||||
Q_DECLARE_METATYPE(ServerInfo_User)
|
||||
Q_DECLARE_METATYPE(QList<ServerInfo_User>)
|
||||
Q_DECLARE_METATYPE(Event_ReplayAdded)
|
||||
Q_DECLARE_METATYPE(QList<QString>)
|
||||
|
||||
#endif
|
||||
@@ -289,7 +289,7 @@ QString DeckLoader::getCardZoneFromName(QString cardName, QString currentZoneNam
|
||||
return currentZoneName;
|
||||
}
|
||||
|
||||
QString DeckLoader::getCompleteCardName(const QString &cardName) const
|
||||
QString DeckLoader::getCompleteCardName(const QString cardName) const
|
||||
{
|
||||
if (db) {
|
||||
CardInfoPtr temp = db->guessCard(cardName);
|
||||
|
||||
@@ -57,8 +57,8 @@ protected:
|
||||
const InnerDecklistNode *zoneNode,
|
||||
QList<DecklistCardNode *> cards,
|
||||
bool addComments = true);
|
||||
[[nodiscard]] QString getCardZoneFromName(QString cardName, QString currentZoneName) override;
|
||||
[[nodiscard]] QString getCompleteCardName(const QString &cardName) const override;
|
||||
virtual QString getCardZoneFromName(QString cardName, QString currentZoneName);
|
||||
virtual QString getCompleteCardName(const QString cardName) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -89,8 +89,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 = 0.05 * (CARD_WIDTH - 3);
|
||||
painter->drawRoundedRect(QRectF(1.5, 1.5, CARD_WIDTH - 3., CARD_HEIGHT - 3.), cardRadius, cardRadius);
|
||||
painter->drawRect(QRectF(1, 1, CARD_WIDTH - 2, CARD_HEIGHT - 2.5));
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "dlg_connect.h"
|
||||
|
||||
#include "settingscache.h"
|
||||
#include "trice_limits.h"
|
||||
#include "stringsizes.h"
|
||||
#include "userconnection_information.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
@@ -245,22 +245,22 @@ void DlgConnect::updateDisplayInfo(const QString &saveName)
|
||||
}
|
||||
|
||||
UserConnection_Information uci;
|
||||
QStringList _data = uci.getServerInfo(saveName);
|
||||
QStringList data = uci.getServerInfo(saveName);
|
||||
|
||||
bool savePasswordStatus = (_data.at(5) == "1");
|
||||
bool savePasswordStatus = (data.at(5) == "1");
|
||||
|
||||
saveEdit->setText(_data.at(0));
|
||||
hostEdit->setText(_data.at(1));
|
||||
portEdit->setText(_data.at(2));
|
||||
playernameEdit->setText(_data.at(3));
|
||||
saveEdit->setText(data.at(0));
|
||||
hostEdit->setText(data.at(1));
|
||||
portEdit->setText(data.at(2));
|
||||
playernameEdit->setText(data.at(3));
|
||||
savePasswordCheckBox->setChecked(savePasswordStatus);
|
||||
|
||||
if (savePasswordStatus) {
|
||||
passwordEdit->setText(_data.at(4));
|
||||
passwordEdit->setText(data.at(4));
|
||||
}
|
||||
|
||||
if (!_data.at(6).isEmpty()) {
|
||||
QString formattedLink = "<a href=\"" + _data.at(6) + "\">" + _data.at(6) + "</a>";
|
||||
if (!data.at(6).isEmpty()) {
|
||||
QString formattedLink = "<a href=\"" + data.at(6) + "\">" + data.at(6) + "</a>";
|
||||
serverContactLabel->setText(tr("Webpage") + ":");
|
||||
serverContactLink->setText(formattedLink);
|
||||
} else {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "decklist.h"
|
||||
#include "main.h"
|
||||
#include "settingscache.h"
|
||||
#include "trice_limits.h"
|
||||
#include "stringsizes.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QCloseEvent>
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
#include "pb/serverinfo_game.pb.h"
|
||||
#include "pending_command.h"
|
||||
#include "settingscache.h"
|
||||
#include "stringsizes.h"
|
||||
#include "tab_room.h"
|
||||
#include "trice_limits.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCheckBox>
|
||||
@@ -235,13 +235,13 @@ void DlgCreateGame::actOK()
|
||||
cmd.set_join_as_judge(QApplication::keyboardModifiers() & Qt::ShiftModifier);
|
||||
cmd.set_join_as_spectator(createGameAsSpectatorCheckBox->isChecked());
|
||||
|
||||
QString _gameTypes = QString();
|
||||
QString gameTypes = QString();
|
||||
QMapIterator<int, QRadioButton *> gameTypeCheckBoxIterator(gameTypeCheckBoxes);
|
||||
while (gameTypeCheckBoxIterator.hasNext()) {
|
||||
gameTypeCheckBoxIterator.next();
|
||||
if (gameTypeCheckBoxIterator.value()->isChecked()) {
|
||||
cmd.add_game_type_ids(gameTypeCheckBoxIterator.key());
|
||||
_gameTypes += gameTypeCheckBoxIterator.value()->text() + ", ";
|
||||
gameTypes += gameTypeCheckBoxIterator.value()->text() + ", ";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,7 +256,7 @@ void DlgCreateGame::actOK()
|
||||
SettingsCache::instance().setSpectatorsCanTalk(spectatorsCanTalkCheckBox->isChecked());
|
||||
SettingsCache::instance().setSpectatorsCanSeeEverything(spectatorsSeeEverythingCheckBox->isChecked());
|
||||
SettingsCache::instance().setCreateGameAsSpectator(createGameAsSpectatorCheckBox->isChecked());
|
||||
SettingsCache::instance().setGameTypes(_gameTypes);
|
||||
SettingsCache::instance().setGameTypes(gameTypes);
|
||||
}
|
||||
PendingCommand *pend = room->prepareRoomCommand(cmd);
|
||||
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(checkResponse(Response)));
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "dlg_edit_avatar.h"
|
||||
|
||||
#include "trice_limits.h"
|
||||
#include "stringsizes.h"
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QDebug>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "dlg_edit_password.h"
|
||||
|
||||
#include "settingscache.h"
|
||||
#include "trice_limits.h"
|
||||
#include "stringsizes.h"
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QGridLayout>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "carddatabasemodel.h"
|
||||
#include "gettextwithmax.h"
|
||||
#include "main.h"
|
||||
#include "trice_limits.h"
|
||||
#include "stringsizes.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QComboBox>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "dlg_edit_user.h"
|
||||
|
||||
#include "settingscache.h"
|
||||
#include "trice_limits.h"
|
||||
#include "stringsizes.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDialogButtonBox>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "dlg_forgotpasswordchallenge.h"
|
||||
|
||||
#include "settingscache.h"
|
||||
#include "trice_limits.h"
|
||||
#include "stringsizes.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QDebug>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "dlg_forgotpasswordrequest.h"
|
||||
|
||||
#include "settingscache.h"
|
||||
#include "trice_limits.h"
|
||||
#include "stringsizes.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QDebug>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "dlg_forgotpasswordreset.h"
|
||||
|
||||
#include "settingscache.h"
|
||||
#include "trice_limits.h"
|
||||
#include "stringsizes.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QDebug>
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include "main.h"
|
||||
#include "pictureloader.h"
|
||||
#include "setsmodel.h"
|
||||
#include "settingscache.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QDebug>
|
||||
@@ -85,6 +84,7 @@ WndSets::WndSets(QWidget *parent) : QMainWindow(parent)
|
||||
displayModel->setDynamicSortFilter(false);
|
||||
view = new QTreeView;
|
||||
view->setModel(displayModel);
|
||||
view->setMinimumSize(QSize(500, 250));
|
||||
|
||||
view->setAlternatingRowColors(true);
|
||||
view->setUniformRowHeights(true);
|
||||
@@ -98,6 +98,10 @@ WndSets::WndSets(QWidget *parent) : QMainWindow(parent)
|
||||
view->setDropIndicatorShown(true);
|
||||
view->setDragDropMode(QAbstractItemView::InternalMove);
|
||||
|
||||
view->header()->setSectionResizeMode(QHeaderView::Stretch);
|
||||
view->header()->setSectionResizeMode(SetsModel::EnabledCol, QHeaderView::ResizeToContents);
|
||||
view->header()->setSectionResizeMode(SetsModel::LongNameCol, QHeaderView::ResizeToContents);
|
||||
|
||||
view->sortByColumn(SetsModel::SortKeyCol, Qt::AscendingOrder);
|
||||
view->setColumnHidden(SetsModel::SortKeyCol, true);
|
||||
view->setColumnHidden(SetsModel::IsKnownCol, true);
|
||||
@@ -166,7 +170,7 @@ WndSets::WndSets(QWidget *parent) : QMainWindow(parent)
|
||||
|
||||
mainLayout = new QGridLayout;
|
||||
mainLayout->addLayout(filterBox, 0, 1, 1, 2);
|
||||
mainLayout->addWidget(setsEditToolBar, 1, 0, 4, 1);
|
||||
mainLayout->addWidget(setsEditToolBar, 1, 0, 2, 1);
|
||||
mainLayout->addWidget(view, 1, 1, 1, 2);
|
||||
mainLayout->addWidget(enableAllButton, 2, 1);
|
||||
mainLayout->addWidget(disableAllButton, 2, 2);
|
||||
@@ -186,35 +190,13 @@ WndSets::WndSets(QWidget *parent) : QMainWindow(parent)
|
||||
setCentralWidget(centralWidget);
|
||||
|
||||
setWindowTitle(tr("Manage sets"));
|
||||
setMinimumSize(800, 500);
|
||||
auto &geometry = SettingsCache::instance().getSetsDialogGeometry();
|
||||
if (!geometry.isEmpty()) {
|
||||
restoreGeometry(geometry);
|
||||
}
|
||||
auto &headerState = SettingsCache::instance().layouts().getSetsDialogHeaderState();
|
||||
if (!headerState.isEmpty()) {
|
||||
view->header()->restoreState(headerState);
|
||||
view->header()->setSortIndicator(SORT_RESET, Qt::DescendingOrder);
|
||||
} else {
|
||||
view->header()->resizeSections(QHeaderView::ResizeToContents);
|
||||
}
|
||||
connect(view->header(), &QHeaderView::geometriesChanged, this, &WndSets::saveHeaderState);
|
||||
resize(800, 500);
|
||||
}
|
||||
|
||||
WndSets::~WndSets()
|
||||
{
|
||||
}
|
||||
|
||||
void WndSets::closeEvent(QCloseEvent * /*ev*/)
|
||||
{
|
||||
SettingsCache::instance().setSetsDialogGeometry(saveGeometry());
|
||||
}
|
||||
|
||||
void WndSets::saveHeaderState()
|
||||
{
|
||||
SettingsCache::instance().layouts().setSetsDialogHeaderState(view->header()->saveState());
|
||||
}
|
||||
|
||||
void WndSets::rebuildMainLayout(int actionToTake)
|
||||
{
|
||||
if (mainLayout == nullptr)
|
||||
|
||||
@@ -40,8 +40,6 @@ private:
|
||||
QHBoxLayout *filterBox;
|
||||
int sortIndex;
|
||||
Qt::SortOrder sortOrder;
|
||||
void closeEvent(QCloseEvent *ev) override;
|
||||
void saveHeaderState();
|
||||
void rebuildMainLayout(int actionToTake);
|
||||
bool setOrderIsSorted;
|
||||
enum
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include "pb/serverinfo_user.pb.h"
|
||||
#include "settingscache.h"
|
||||
#include "trice_limits.h"
|
||||
#include "stringsizes.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QDebug>
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
#include "dlg_roll_dice.h"
|
||||
|
||||
#include "trice_limits.h"
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QLabel>
|
||||
#include <QSpinBox>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
|
||||
DlgRollDice::DlgRollDice(QWidget *parent) : QDialog(parent)
|
||||
{
|
||||
numberOfSidesLabel = new QLabel(tr("Number of sides:"));
|
||||
numberOfSidesEdit = new QSpinBox(this);
|
||||
numberOfSidesEdit->setValue(DEFAULT_NUMBER_SIDES_DIE);
|
||||
numberOfSidesEdit->setRange(MINIMUM_DIE_SIDES, MAXIMUM_DIE_SIDES);
|
||||
numberOfSidesEdit->setFocus();
|
||||
numberOfSidesLabel->setBuddy(numberOfSidesEdit);
|
||||
|
||||
numberOfDiceLabel = new QLabel(tr("Number of dice:"));
|
||||
numberOfDiceEdit = new QSpinBox(this);
|
||||
numberOfDiceEdit->setValue(DEFAULT_NUMBER_DICE_TO_ROLL);
|
||||
numberOfDiceEdit->setRange(MINIMUM_DICE_TO_ROLL, MAXIMUM_DICE_TO_ROLL);
|
||||
numberOfDiceLabel->setBuddy(numberOfDiceEdit);
|
||||
|
||||
auto *grid = new QGridLayout;
|
||||
grid->addWidget(numberOfSidesLabel, 0, 0);
|
||||
grid->addWidget(numberOfSidesEdit, 0, 1);
|
||||
grid->addWidget(numberOfDiceLabel, 1, 0);
|
||||
grid->addWidget(numberOfDiceEdit, 1, 1);
|
||||
|
||||
buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
|
||||
auto *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addItem(grid);
|
||||
mainLayout->addWidget(buttonBox);
|
||||
|
||||
setLayout(mainLayout);
|
||||
setWindowTitle(tr("Roll Dice"));
|
||||
}
|
||||
|
||||
uint DlgRollDice::getDieSideCount() const
|
||||
{
|
||||
return numberOfSidesEdit->text().toUInt();
|
||||
}
|
||||
|
||||
uint DlgRollDice::getDiceToRollCount() const
|
||||
{
|
||||
return numberOfDiceEdit->text().toUInt();
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
#ifndef DLG_ROLL_DICE_H
|
||||
#define DLG_ROLL_DICE_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QLabel>
|
||||
#include <QSpinBox>
|
||||
|
||||
class DlgRollDice : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
static constexpr uint DEFAULT_NUMBER_SIDES_DIE = 20;
|
||||
static constexpr uint DEFAULT_NUMBER_DICE_TO_ROLL = 1;
|
||||
|
||||
QLabel *numberOfSidesLabel, *numberOfDiceLabel;
|
||||
QSpinBox *numberOfSidesEdit, *numberOfDiceEdit;
|
||||
QDialogButtonBox *buttonBox;
|
||||
|
||||
public:
|
||||
explicit DlgRollDice(QWidget *parent = nullptr);
|
||||
[[nodiscard]] uint getDieSideCount() const;
|
||||
[[nodiscard]] uint getDiceToRollCount() const;
|
||||
};
|
||||
|
||||
#endif // DLG_ROLL_DICE_H
|
||||
@@ -3,7 +3,6 @@
|
||||
#include "carddatabase.h"
|
||||
#include "gettextwithmax.h"
|
||||
#include "main.h"
|
||||
#include "pictureloader.h"
|
||||
#include "releasechannel.h"
|
||||
#include "sequenceEdit/sequenceedit.h"
|
||||
#include "settingscache.h"
|
||||
@@ -69,9 +68,18 @@ GeneralSettingsPage::GeneralSettingsPage()
|
||||
updateNotificationCheckBox.setChecked(settings.getNotifyAboutUpdates());
|
||||
newVersionOracleCheckBox.setChecked(settings.getNotifyAboutNewVersion());
|
||||
|
||||
// pixmap cache
|
||||
pixmapCacheEdit.setMinimum(PIXMAPCACHE_SIZE_MIN);
|
||||
// 2047 is the max value to avoid overflowing of QPixmapCache::setCacheLimit(int size)
|
||||
pixmapCacheEdit.setMaximum(PIXMAPCACHE_SIZE_MAX);
|
||||
pixmapCacheEdit.setSingleStep(64);
|
||||
pixmapCacheEdit.setValue(settings.getPixmapCacheSize());
|
||||
pixmapCacheEdit.setSuffix(" MB");
|
||||
|
||||
showTipsOnStartup.setChecked(settings.getShowTipsOnStartup());
|
||||
|
||||
connect(&languageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(languageBoxChanged(int)));
|
||||
connect(&pixmapCacheEdit, SIGNAL(valueChanged(int)), &settings, SLOT(setPixmapCacheSize(int)));
|
||||
connect(&updateReleaseChannelBox, SIGNAL(currentIndexChanged(int)), &settings, SLOT(setUpdateReleaseChannel(int)));
|
||||
connect(&updateNotificationCheckBox, SIGNAL(stateChanged(int)), &settings, SLOT(setNotifyAboutUpdate(int)));
|
||||
connect(&newVersionOracleCheckBox, SIGNAL(stateChanged(int)), &settings, SLOT(setNotifyAboutNewVersion(int)));
|
||||
@@ -82,6 +90,8 @@ GeneralSettingsPage::GeneralSettingsPage()
|
||||
personalGrid->addWidget(&languageBox, 0, 1);
|
||||
personalGrid->addWidget(&updateReleaseChannelLabel, 1, 0);
|
||||
personalGrid->addWidget(&updateReleaseChannelBox, 1, 1);
|
||||
personalGrid->addWidget(&pixmapCacheLabel, 2, 0);
|
||||
personalGrid->addWidget(&pixmapCacheEdit, 2, 1);
|
||||
personalGrid->addWidget(&updateNotificationCheckBox, 3, 0, 1, 2);
|
||||
personalGrid->addWidget(&newVersionOracleCheckBox, 4, 0, 1, 2);
|
||||
personalGrid->addWidget(&showTipsOnStartup, 5, 0, 1, 2);
|
||||
@@ -291,6 +301,7 @@ void GeneralSettingsPage::retranslateUi()
|
||||
cardDatabasePathLabel.setText(tr("Card database:"));
|
||||
customCardDatabasePathLabel.setText(tr("Custom database directory:"));
|
||||
tokenDatabasePathLabel.setText(tr("Token database:"));
|
||||
pixmapCacheLabel.setText(tr("Picture cache size:"));
|
||||
updateReleaseChannelLabel.setText(tr("Update channel"));
|
||||
updateNotificationCheckBox.setText(tr("Notify if a feature supported by the server is missing in my client"));
|
||||
newVersionOracleCheckBox.setText(tr("Automatically run Oracle when running a new version of Cockatrice"));
|
||||
@@ -299,7 +310,6 @@ void GeneralSettingsPage::retranslateUi()
|
||||
|
||||
AppearanceSettingsPage::AppearanceSettingsPage()
|
||||
{
|
||||
SettingsCache &settings = SettingsCache::instance();
|
||||
QString themeName = SettingsCache::instance().getThemeName();
|
||||
|
||||
QStringList themeDirs = themeManager->getAvailableThemes().keys();
|
||||
@@ -320,31 +330,27 @@ AppearanceSettingsPage::AppearanceSettingsPage()
|
||||
themeGroupBox = new QGroupBox;
|
||||
themeGroupBox->setLayout(themeGrid);
|
||||
|
||||
displayCardNamesCheckBox.setChecked(settings.getDisplayCardNames());
|
||||
connect(&displayCardNamesCheckBox, SIGNAL(stateChanged(int)), &settings, SLOT(setDisplayCardNames(int)));
|
||||
displayCardNamesCheckBox.setChecked(SettingsCache::instance().getDisplayCardNames());
|
||||
connect(&displayCardNamesCheckBox, SIGNAL(stateChanged(int)), &SettingsCache::instance(),
|
||||
SLOT(setDisplayCardNames(int)));
|
||||
|
||||
cardScalingCheckBox.setChecked(settings.getScaleCards());
|
||||
connect(&cardScalingCheckBox, SIGNAL(stateChanged(int)), &settings, SLOT(setCardScaling(int)));
|
||||
|
||||
verticalCardOverlapPercentBox.setValue(settings.getStackCardOverlapPercent());
|
||||
verticalCardOverlapPercentBox.setRange(0, 80);
|
||||
connect(&verticalCardOverlapPercentBox, SIGNAL(valueChanged(int)), &settings,
|
||||
SLOT(setStackCardOverlapPercent(int)));
|
||||
cardScalingCheckBox.setChecked(SettingsCache::instance().getScaleCards());
|
||||
connect(&cardScalingCheckBox, SIGNAL(stateChanged(int)), &SettingsCache::instance(), SLOT(setCardScaling(int)));
|
||||
|
||||
auto *cardsGrid = new QGridLayout;
|
||||
cardsGrid->addWidget(&displayCardNamesCheckBox, 0, 0, 1, 2);
|
||||
cardsGrid->addWidget(&cardScalingCheckBox, 1, 0, 1, 2);
|
||||
cardsGrid->addWidget(&verticalCardOverlapPercentLabel, 2, 0, 1, 1);
|
||||
cardsGrid->addWidget(&verticalCardOverlapPercentBox, 2, 1, 1, 1);
|
||||
|
||||
cardsGroupBox = new QGroupBox;
|
||||
cardsGroupBox->setLayout(cardsGrid);
|
||||
|
||||
horizontalHandCheckBox.setChecked(settings.getHorizontalHand());
|
||||
connect(&horizontalHandCheckBox, SIGNAL(stateChanged(int)), &settings, SLOT(setHorizontalHand(int)));
|
||||
horizontalHandCheckBox.setChecked(SettingsCache::instance().getHorizontalHand());
|
||||
connect(&horizontalHandCheckBox, SIGNAL(stateChanged(int)), &SettingsCache::instance(),
|
||||
SLOT(setHorizontalHand(int)));
|
||||
|
||||
leftJustifiedHandCheckBox.setChecked(settings.getLeftJustified());
|
||||
connect(&leftJustifiedHandCheckBox, SIGNAL(stateChanged(int)), &settings, SLOT(setLeftJustified(int)));
|
||||
leftJustifiedHandCheckBox.setChecked(SettingsCache::instance().getLeftJustified());
|
||||
connect(&leftJustifiedHandCheckBox, SIGNAL(stateChanged(int)), &SettingsCache::instance(),
|
||||
SLOT(setLeftJustified(int)));
|
||||
|
||||
auto *handGrid = new QGridLayout;
|
||||
handGrid->addWidget(&horizontalHandCheckBox, 0, 0, 1, 2);
|
||||
@@ -353,18 +359,18 @@ AppearanceSettingsPage::AppearanceSettingsPage()
|
||||
handGroupBox = new QGroupBox;
|
||||
handGroupBox->setLayout(handGrid);
|
||||
|
||||
invertVerticalCoordinateCheckBox.setChecked(settings.getInvertVerticalCoordinate());
|
||||
connect(&invertVerticalCoordinateCheckBox, SIGNAL(stateChanged(int)), &settings,
|
||||
invertVerticalCoordinateCheckBox.setChecked(SettingsCache::instance().getInvertVerticalCoordinate());
|
||||
connect(&invertVerticalCoordinateCheckBox, SIGNAL(stateChanged(int)), &SettingsCache::instance(),
|
||||
SLOT(setInvertVerticalCoordinate(int)));
|
||||
|
||||
minPlayersForMultiColumnLayoutEdit.setMinimum(2);
|
||||
minPlayersForMultiColumnLayoutEdit.setValue(settings.getMinPlayersForMultiColumnLayout());
|
||||
connect(&minPlayersForMultiColumnLayoutEdit, SIGNAL(valueChanged(int)), &settings,
|
||||
minPlayersForMultiColumnLayoutEdit.setValue(SettingsCache::instance().getMinPlayersForMultiColumnLayout());
|
||||
connect(&minPlayersForMultiColumnLayoutEdit, SIGNAL(valueChanged(int)), &SettingsCache::instance(),
|
||||
SLOT(setMinPlayersForMultiColumnLayout(int)));
|
||||
minPlayersForMultiColumnLayoutLabel.setBuddy(&minPlayersForMultiColumnLayoutEdit);
|
||||
|
||||
connect(&maxFontSizeForCardsEdit, SIGNAL(valueChanged(int)), &settings, SLOT(setMaxFontSize(int)));
|
||||
maxFontSizeForCardsEdit.setValue(settings.getMaxFontSize());
|
||||
connect(&maxFontSizeForCardsEdit, SIGNAL(valueChanged(int)), &SettingsCache::instance(), SLOT(setMaxFontSize(int)));
|
||||
maxFontSizeForCardsEdit.setValue(SettingsCache::instance().getMaxFontSize());
|
||||
maxFontSizeForCardsLabel.setBuddy(&maxFontSizeForCardsEdit);
|
||||
maxFontSizeForCardsEdit.setMinimum(9);
|
||||
maxFontSizeForCardsEdit.setMaximum(100);
|
||||
@@ -418,8 +424,6 @@ void AppearanceSettingsPage::retranslateUi()
|
||||
cardsGroupBox->setTitle(tr("Card rendering"));
|
||||
displayCardNamesCheckBox.setText(tr("Display card names on cards having a picture"));
|
||||
cardScalingCheckBox.setText(tr("Scale cards on mouse over"));
|
||||
verticalCardOverlapPercentLabel.setText(
|
||||
tr("Minimum overlap percentage of cards on the stack and in vertical hand"));
|
||||
|
||||
handGroupBox->setTitle(tr("Hand layout"));
|
||||
horizontalHandCheckBox.setText(tr("Display hand horizontally (wastes space)"));
|
||||
@@ -587,38 +591,12 @@ DeckEditorSettingsPage::DeckEditorSettingsPage()
|
||||
messageListLayout->addWidget(messageToolBar);
|
||||
messageListLayout->addWidget(urlList);
|
||||
|
||||
// pixmap cache
|
||||
pixmapCacheEdit.setMinimum(PIXMAPCACHE_SIZE_MIN);
|
||||
// 2047 is the max value to avoid overflowing of QPixmapCache::setCacheLimit(int size)
|
||||
pixmapCacheEdit.setMaximum(PIXMAPCACHE_SIZE_MAX);
|
||||
pixmapCacheEdit.setSingleStep(64);
|
||||
pixmapCacheEdit.setValue(SettingsCache::instance().getPixmapCacheSize());
|
||||
pixmapCacheEdit.setSuffix(" MB");
|
||||
|
||||
networkCacheEdit.setMinimum(NETWORK_CACHE_SIZE_MIN);
|
||||
networkCacheEdit.setMaximum(NETWORK_CACHE_SIZE_MAX);
|
||||
networkCacheEdit.setSingleStep(1);
|
||||
networkCacheEdit.setValue(SettingsCache::instance().getNetworkCacheSizeInMB());
|
||||
networkCacheEdit.setSuffix(" MB");
|
||||
|
||||
auto networkCacheLayout = new QHBoxLayout;
|
||||
networkCacheLayout->addStretch();
|
||||
networkCacheLayout->addWidget(&networkCacheLabel);
|
||||
networkCacheLayout->addWidget(&networkCacheEdit);
|
||||
|
||||
auto pixmapCacheLayout = new QHBoxLayout;
|
||||
pixmapCacheLayout->addStretch();
|
||||
pixmapCacheLayout->addWidget(&pixmapCacheLabel);
|
||||
pixmapCacheLayout->addWidget(&pixmapCacheEdit);
|
||||
|
||||
// Top Layout
|
||||
lpGeneralGrid->addWidget(&picDownloadCheckBox, 0, 0);
|
||||
lpGeneralGrid->addWidget(&resetDownloadURLs, 0, 1);
|
||||
lpGeneralGrid->addLayout(messageListLayout, 1, 0, 1, 2);
|
||||
lpGeneralGrid->addLayout(networkCacheLayout, 2, 0, 1, 2);
|
||||
lpGeneralGrid->addLayout(pixmapCacheLayout, 3, 0, 1, 2);
|
||||
lpGeneralGrid->addWidget(&urlLinkLabel, 4, 0);
|
||||
lpGeneralGrid->addWidget(&clearDownloadedPicsButton, 4, 1);
|
||||
lpGeneralGrid->addWidget(&urlLinkLabel, 2, 0);
|
||||
lpGeneralGrid->addWidget(&clearDownloadedPicsButton, 2, 1);
|
||||
|
||||
// Spoiler Layout
|
||||
lpSpoilerGrid->addWidget(&mcDownloadSpoilersCheckBox, 0, 0);
|
||||
@@ -633,9 +611,6 @@ DeckEditorSettingsPage::DeckEditorSettingsPage()
|
||||
connect(&mcDownloadSpoilersCheckBox, SIGNAL(toggled(bool)), &SettingsCache::instance(),
|
||||
SLOT(setDownloadSpoilerStatus(bool)));
|
||||
connect(&mcDownloadSpoilersCheckBox, SIGNAL(toggled(bool)), this, SLOT(setSpoilersEnabled(bool)));
|
||||
connect(&pixmapCacheEdit, SIGNAL(valueChanged(int)), &SettingsCache::instance(), SLOT(setPixmapCacheSize(int)));
|
||||
connect(&networkCacheEdit, SIGNAL(valueChanged(int)), &SettingsCache::instance(),
|
||||
SLOT(setNetworkCacheSizeInMB(int)));
|
||||
|
||||
mpGeneralGroupBox = new QGroupBox;
|
||||
mpGeneralGroupBox->setLayout(lpGeneralGrid);
|
||||
@@ -660,11 +635,6 @@ void DeckEditorSettingsPage::resetDownloadedURLsButtonClicked()
|
||||
|
||||
void DeckEditorSettingsPage::clearDownloadedPicsButtonClicked()
|
||||
{
|
||||
PictureLoader::clearNetworkCache();
|
||||
|
||||
// These are not used anymore, but we don't delete them automatically, so
|
||||
// we should do it here lest we leave pictures hanging around on users'
|
||||
// machines.
|
||||
QString picsPath = SettingsCache::instance().getPicsPath() + "/downloadedPics/";
|
||||
QStringList dirs = QDir(picsPath).entryList(QDir::AllDirs | QDir::NoDotAndDotDot);
|
||||
bool outerSuccessRemove = true;
|
||||
@@ -692,7 +662,6 @@ void DeckEditorSettingsPage::clearDownloadedPicsButtonClicked()
|
||||
}
|
||||
if (outerSuccessRemove) {
|
||||
QMessageBox::information(this, tr("Success"), tr("Downloaded card pictures have been reset."));
|
||||
QDir(SettingsCache::instance().getPicsPath()).rmdir("downloadedPics");
|
||||
} else {
|
||||
QMessageBox::critical(this, tr("Error"), tr("One or more downloaded card pictures could not be cleared."));
|
||||
}
|
||||
@@ -816,10 +785,6 @@ void DeckEditorSettingsPage::retranslateUi()
|
||||
urlLinkLabel.setText(QString("<a href='%1'>%2</a>").arg(WIKI_CUSTOM_PIC_URL).arg(tr("How to add a custom URL")));
|
||||
clearDownloadedPicsButton.setText(tr("Delete Downloaded Images"));
|
||||
resetDownloadURLs.setText(tr("Reset Download URLs"));
|
||||
networkCacheLabel.setText(tr("Downloaded images directory size:"));
|
||||
networkCacheEdit.setToolTip(tr("On-disk cache for downloaded pictures"));
|
||||
pixmapCacheLabel.setText(tr("Picture cache size:"));
|
||||
pixmapCacheEdit.setToolTip(tr("In-memory cache for pictures not currently on screen"));
|
||||
}
|
||||
|
||||
MessagesSettingsPage::MessagesSettingsPage()
|
||||
@@ -944,12 +909,8 @@ MessagesSettingsPage::MessagesSettingsPage()
|
||||
|
||||
void MessagesSettingsPage::updateColor(const QString &value)
|
||||
{
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 4, 0))
|
||||
QColor colorToSet = QColor::fromString("#" + value);
|
||||
#else
|
||||
QColor colorToSet;
|
||||
colorToSet.setNamedColor("#" + value);
|
||||
#endif
|
||||
if (colorToSet.isValid()) {
|
||||
SettingsCache::instance().setChatMentionColor(value);
|
||||
updateMentionPreview();
|
||||
@@ -958,12 +919,8 @@ void MessagesSettingsPage::updateColor(const QString &value)
|
||||
|
||||
void MessagesSettingsPage::updateHighlightColor(const QString &value)
|
||||
{
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 4, 0))
|
||||
QColor colorToSet = QColor::fromString("#" + value);
|
||||
#else
|
||||
QColor colorToSet;
|
||||
colorToSet.setNamedColor("#" + value);
|
||||
#endif
|
||||
if (colorToSet.isValid()) {
|
||||
SettingsCache::instance().setChatHighlightColor(value);
|
||||
updateHighlightPreview();
|
||||
@@ -1161,28 +1118,28 @@ ShortcutSettingsPage::ShortcutSettingsPage()
|
||||
btnClearAll->setIcon(QPixmap("theme:icons/clearsearch"));
|
||||
|
||||
// layout
|
||||
auto *_editLayout = new QGridLayout;
|
||||
_editLayout->addWidget(currentActionGroupLabel, 0, 0);
|
||||
_editLayout->addWidget(currentActionGroupName, 0, 1);
|
||||
_editLayout->addWidget(currentActionLabel, 1, 0);
|
||||
_editLayout->addWidget(currentActionName, 1, 1);
|
||||
_editLayout->addWidget(currentShortcutLabel, 2, 0);
|
||||
_editLayout->addWidget(editTextBox, 2, 1);
|
||||
auto *editLayout = new QGridLayout;
|
||||
editLayout->addWidget(currentActionGroupLabel, 0, 0);
|
||||
editLayout->addWidget(currentActionGroupName, 0, 1);
|
||||
editLayout->addWidget(currentActionLabel, 1, 0);
|
||||
editLayout->addWidget(currentActionName, 1, 1);
|
||||
editLayout->addWidget(currentShortcutLabel, 2, 0);
|
||||
editLayout->addWidget(editTextBox, 2, 1);
|
||||
|
||||
editShortcutGroupBox = new QGroupBox;
|
||||
editShortcutGroupBox->setLayout(_editLayout);
|
||||
editShortcutGroupBox->setLayout(editLayout);
|
||||
|
||||
auto *_buttonsLayout = new QHBoxLayout;
|
||||
_buttonsLayout->addWidget(faqLabel);
|
||||
_buttonsLayout->addWidget(btnResetAll);
|
||||
_buttonsLayout->addWidget(btnClearAll);
|
||||
auto *buttonsLayout = new QHBoxLayout;
|
||||
buttonsLayout->addWidget(faqLabel);
|
||||
buttonsLayout->addWidget(btnResetAll);
|
||||
buttonsLayout->addWidget(btnClearAll);
|
||||
|
||||
auto *_mainLayout = new QVBoxLayout;
|
||||
_mainLayout->addWidget(shortcutsTable);
|
||||
_mainLayout->addWidget(editShortcutGroupBox);
|
||||
_mainLayout->addLayout(_buttonsLayout);
|
||||
auto *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addWidget(shortcutsTable);
|
||||
mainLayout->addWidget(editShortcutGroupBox);
|
||||
mainLayout->addLayout(buttonsLayout);
|
||||
|
||||
setLayout(_mainLayout);
|
||||
setLayout(mainLayout);
|
||||
|
||||
connect(btnResetAll, SIGNAL(clicked()), this, SLOT(resetShortcuts()));
|
||||
connect(btnClearAll, SIGNAL(clicked()), this, SLOT(clearShortcuts()));
|
||||
@@ -1288,8 +1245,8 @@ void ShortcutSettingsPage::retranslateUi()
|
||||
currentShortcutLabel->setText(tr("Shortcut:"));
|
||||
editTextBox->retranslateUi();
|
||||
faqLabel->setText(QString("<a href='%1'>%2</a>").arg(WIKI_CUSTOM_SHORTCUTS).arg(tr("How to set custom shortcuts")));
|
||||
btnResetAll->setText(tr("Restore all default shortcuts"));
|
||||
btnClearAll->setText(tr("Clear all shortcuts"));
|
||||
btnResetAll->setText("Restore all default shortcuts");
|
||||
btnClearAll->setText("Clear all shortcuts");
|
||||
}
|
||||
|
||||
DlgSettings::DlgSettings(QWidget *parent) : QDialog(parent)
|
||||
|
||||
@@ -58,6 +58,7 @@ private:
|
||||
QLineEdit *tokenDatabasePathEdit;
|
||||
QPushButton *resetAllPathsButton;
|
||||
QLabel *allPathsResetLabel;
|
||||
QSpinBox pixmapCacheEdit;
|
||||
QGroupBox *personalGroupBox;
|
||||
QGroupBox *pathsGroupBox;
|
||||
QComboBox languageBox;
|
||||
@@ -65,6 +66,7 @@ private:
|
||||
QCheckBox newVersionOracleCheckBox;
|
||||
QComboBox updateReleaseChannelBox;
|
||||
QLabel languageLabel;
|
||||
QLabel pixmapCacheLabel;
|
||||
QLabel deckPathLabel;
|
||||
QLabel replaysPathLabel;
|
||||
QLabel picsPathLabel;
|
||||
@@ -90,8 +92,6 @@ private:
|
||||
QLabel maxFontSizeForCardsLabel;
|
||||
QCheckBox displayCardNamesCheckBox;
|
||||
QCheckBox cardScalingCheckBox;
|
||||
QLabel verticalCardOverlapPercentLabel;
|
||||
QSpinBox verticalCardOverlapPercentBox;
|
||||
QCheckBox horizontalHandCheckBox;
|
||||
QCheckBox leftJustifiedHandCheckBox;
|
||||
QCheckBox invertVerticalCoordinateCheckBox;
|
||||
@@ -168,10 +168,6 @@ private:
|
||||
QLabel infoOnSpoilersLabel;
|
||||
QPushButton *mpSpoilerPathButton;
|
||||
QPushButton *updateNowButton;
|
||||
QLabel networkCacheLabel;
|
||||
QSpinBox networkCacheEdit;
|
||||
QSpinBox pixmapCacheEdit;
|
||||
QLabel pixmapCacheLabel;
|
||||
};
|
||||
|
||||
class MessagesSettingsPage : public AbstractSettingsPage
|
||||
|
||||
@@ -154,7 +154,7 @@ void DlgTipOfTheDay::updateTip(int tipId)
|
||||
imageLabel->setPixmap(image->scaled(w, h, Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
||||
}
|
||||
|
||||
date->setText("<i>Tip added on: " + tip.getDate().toString("yyyy-MM-dd") + "</i>");
|
||||
date->setText("<i>Tip added on: " + tip.getDate().toString("yyyy.MM.dd") + "</i>");
|
||||
|
||||
tipNumber->setText("Tip " + QString::number(tipId + 1) + " / " + QString::number(tipDatabase->rowCount()));
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include "../../common/lib/peglib.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QDebug>
|
||||
#include <QString>
|
||||
#include <functional>
|
||||
|
||||
@@ -42,10 +41,9 @@ ColorQuery <- [cC] 'olor'? <[iI]?> <[:!]> ColorEx*
|
||||
|
||||
FieldQuery <- String [:] RegexString / String ws? NumericExpression
|
||||
|
||||
NonDoubleQuoteUnlessEscaped <- !["]. / '\"'.
|
||||
NonSingleQuoteUnlessEscaped <- ![']. / "\'".
|
||||
UnescapedStringListPart <- !['":<>=! ].
|
||||
String <- UnescapedStringListPart+ / ["] <NonDoubleQuoteUnlessEscaped*> ["] / ['] <NonSingleQuoteUnlessEscaped*> [']
|
||||
NonQuote <- !["].
|
||||
UnescapedStringListPart <- ![":<>=! ].
|
||||
String <- UnescapedStringListPart+ / ["] <NonQuote*> ["]
|
||||
StringValue <- String / [(] StringList [)]
|
||||
StringList <- StringListString (ws? [,] ws? StringListString)*
|
||||
StringListString <- UnescapedStringListPart+
|
||||
@@ -57,7 +55,7 @@ CompactStringSet <- StringListString ([,+] StringListString)+
|
||||
|
||||
NumericExpression <- NumericOperator ws? NumericValue
|
||||
NumericOperator <- [=:] / <[><!][=]?>
|
||||
NumericValue <- [0-9]+
|
||||
NumericValue <- [0-9]+
|
||||
|
||||
)");
|
||||
|
||||
@@ -243,12 +241,7 @@ static void setupParserRules()
|
||||
|
||||
search["RegexString"] = [](const peg::SemanticValues &sv) -> StringMatcher {
|
||||
auto target = sv[0].get<QString>();
|
||||
return [=](const QString &s) {
|
||||
auto sanitizedTarget = QString(target);
|
||||
sanitizedTarget.replace("\\\"", "\"");
|
||||
sanitizedTarget.replace("\\'", "'");
|
||||
return s.QString::contains(sanitizedTarget, Qt::CaseInsensitive);
|
||||
};
|
||||
return [=](const QString &s) { return s.QString::contains(target, Qt::CaseInsensitive); };
|
||||
};
|
||||
|
||||
search["OracleQuery"] = [](const peg::SemanticValues &sv) -> Filter {
|
||||
@@ -341,12 +334,6 @@ static void setupParserRules()
|
||||
};
|
||||
}
|
||||
|
||||
FilterString::FilterString()
|
||||
{
|
||||
result = [](CardData) -> bool { return false; };
|
||||
_error = "Not initialized";
|
||||
}
|
||||
|
||||
FilterString::FilterString(const QString &expr)
|
||||
{
|
||||
QByteArray ba = expr.simplified().toUtf8();
|
||||
@@ -365,7 +352,7 @@ FilterString::FilterString(const QString &expr)
|
||||
};
|
||||
|
||||
if (!search.parse(ba.data(), result)) {
|
||||
qDebug() << "Filter string error" << _error;
|
||||
std::cout << "Error!" << _error.toStdString() << std::endl;
|
||||
result = [](CardData) -> bool { return false; };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ typedef AstBase<EmptyType> Ast;
|
||||
class FilterString
|
||||
{
|
||||
public:
|
||||
FilterString();
|
||||
explicit FilterString(const QString &exp);
|
||||
bool check(const CardData &card)
|
||||
{
|
||||
|
||||
@@ -198,19 +198,9 @@ void GameSelector::actCreate()
|
||||
|
||||
void GameSelector::checkResponse(const Response &response)
|
||||
{
|
||||
// NB: We re-enable buttons for the currently selected game, which may not
|
||||
// be the same game as the one for which we are processing a response.
|
||||
// This could lead to situations where we join a game, select a different
|
||||
// game, join the new game, then receive the response for the original
|
||||
// join, which would re-activate the buttons for the second game too soon.
|
||||
// However, that is better than doing things the other ways, because then
|
||||
// the response to the first game could lock us out of join/join as
|
||||
// spectator for the second game!
|
||||
//
|
||||
// Ideally we should have a way to figure out if the current game is the
|
||||
// same as the one we are getting a response for, but it's probably not
|
||||
// worth the trouble.
|
||||
enableButtons();
|
||||
if (createButton)
|
||||
createButton->setEnabled(true);
|
||||
joinButton->setEnabled(true);
|
||||
|
||||
switch (response.response_code()) {
|
||||
case Response::RespNotInRoom:
|
||||
@@ -239,6 +229,9 @@ void GameSelector::checkResponse(const Response &response)
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
|
||||
if (response.response_code() != Response::RespSpectatorsNotAllowed)
|
||||
spectateButton->setEnabled(true);
|
||||
}
|
||||
|
||||
void GameSelector::actJoin()
|
||||
@@ -277,39 +270,12 @@ void GameSelector::actJoin()
|
||||
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(checkResponse(Response)));
|
||||
r->sendRoomCommand(pend);
|
||||
|
||||
disableButtons();
|
||||
}
|
||||
|
||||
void GameSelector::disableButtons()
|
||||
{
|
||||
if (createButton)
|
||||
createButton->setEnabled(false);
|
||||
|
||||
joinButton->setEnabled(false);
|
||||
spectateButton->setEnabled(false);
|
||||
}
|
||||
|
||||
void GameSelector::enableButtons()
|
||||
{
|
||||
if (createButton)
|
||||
createButton->setEnabled(true);
|
||||
|
||||
// Enable buttons for the currently selected game
|
||||
enableButtonsForIndex(gameListView->currentIndex());
|
||||
}
|
||||
|
||||
void GameSelector::enableButtonsForIndex(const QModelIndex ¤t)
|
||||
{
|
||||
if (!current.isValid())
|
||||
return;
|
||||
|
||||
const ServerInfo_Game &game = gameListModel->getGame(current.data(Qt::UserRole).toInt());
|
||||
bool overrideRestrictions = !tabSupervisor->getAdminLocked();
|
||||
|
||||
spectateButton->setEnabled(game.spectators_allowed() || overrideRestrictions);
|
||||
joinButton->setEnabled(game.player_count() < game.max_players() || overrideRestrictions);
|
||||
}
|
||||
|
||||
void GameSelector::retranslateUi()
|
||||
{
|
||||
filterButton->setText(tr("&Filter games"));
|
||||
@@ -330,7 +296,14 @@ void GameSelector::processGameInfo(const ServerInfo_Game &info)
|
||||
|
||||
void GameSelector::actSelectedGameChanged(const QModelIndex ¤t, const QModelIndex & /* previous */)
|
||||
{
|
||||
enableButtonsForIndex(current);
|
||||
if (!current.isValid())
|
||||
return;
|
||||
|
||||
const ServerInfo_Game &game = gameListModel->getGame(current.data(Qt::UserRole).toInt());
|
||||
bool overrideRestrictions = !tabSupervisor->getAdminLocked();
|
||||
|
||||
spectateButton->setEnabled(game.spectators_allowed() || overrideRestrictions);
|
||||
joinButton->setEnabled(game.player_count() < game.max_players() || overrideRestrictions);
|
||||
}
|
||||
|
||||
void GameSelector::updateTitle()
|
||||
|
||||
@@ -49,9 +49,6 @@ private:
|
||||
GameTypeMap gameTypeMap;
|
||||
|
||||
void updateTitle();
|
||||
void disableButtons();
|
||||
void enableButtons();
|
||||
void enableButtonsForIndex(const QModelIndex ¤t);
|
||||
|
||||
public:
|
||||
GameSelector(AbstractClient *_client,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#ifndef GETTEXTWITHMAX_H
|
||||
#define GETTEXTWITHMAX_H
|
||||
|
||||
#include "trice_limits.h"
|
||||
#include "stringsizes.h"
|
||||
|
||||
#include <QInputDialog>
|
||||
|
||||
|
||||
@@ -114,18 +114,23 @@ void HandZone::reorganizeCards()
|
||||
}
|
||||
} else {
|
||||
qreal totalWidth = boundingRect().width();
|
||||
qreal totalHeight = boundingRect().height();
|
||||
qreal cardWidth = cards.at(0)->boundingRect().width();
|
||||
qreal cardHeight = cards.at(0)->boundingRect().height();
|
||||
qreal xspace = 5;
|
||||
qreal x1 = xspace;
|
||||
qreal x2 = totalWidth - xspace - cardWidth;
|
||||
|
||||
for (int i = 0; i < cardCount; i++) {
|
||||
CardItem *card = cards.at(i);
|
||||
CardItem *c = cards.at(i);
|
||||
qreal x = (i % 2) ? x2 : x1;
|
||||
qreal y =
|
||||
divideCardSpaceInZone(i, cardCount, boundingRect().height(), cards.at(0)->boundingRect().height());
|
||||
card->setPos(x, y);
|
||||
card->setRealZValue(i);
|
||||
// If the total height of the cards is smaller than the available height,
|
||||
// the cards do not need to overlap and are displayed in the center of the area.
|
||||
if (cardHeight * cardCount > totalHeight)
|
||||
c->setPos(x, ((qreal)i) * (totalHeight - cardHeight) / (cardCount - 1));
|
||||
else
|
||||
c->setPos(x, ((qreal)i) * cardHeight + (totalHeight - cardCount * cardHeight) / 2);
|
||||
c->setRealZValue(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -481,8 +481,7 @@ void MessageLogWidget::logRevealCards(Player *player,
|
||||
QString cardName,
|
||||
Player *otherPlayer,
|
||||
bool faceDown,
|
||||
int amount,
|
||||
bool isLentToAnotherPlayer)
|
||||
int amount)
|
||||
{
|
||||
// getFromStr uses cardname.empty() to check if it should contain the start zone, it's not actually used
|
||||
QPair<QString, QString> temp = getFromStr(zone, amount == 1 ? cardName : QString::number(amount), cardId, false);
|
||||
@@ -508,17 +507,10 @@ void MessageLogWidget::logRevealCards(Player *player,
|
||||
}
|
||||
if (cardId == -1) {
|
||||
if (otherPlayer) {
|
||||
if (isLentToAnotherPlayer) {
|
||||
appendHtmlServerMessage(tr("%1 lends %2 to %3.")
|
||||
.arg(sanitizeHtml(player->getName()))
|
||||
.arg(zone->getTranslatedName(true, CaseRevealZone))
|
||||
.arg(sanitizeHtml(otherPlayer->getName())));
|
||||
} else {
|
||||
appendHtmlServerMessage(tr("%1 reveals %2 to %3.")
|
||||
.arg(sanitizeHtml(player->getName()))
|
||||
.arg(zone->getTranslatedName(true, CaseRevealZone))
|
||||
.arg(sanitizeHtml(otherPlayer->getName())));
|
||||
}
|
||||
appendHtmlServerMessage(tr("%1 reveals %2 to %3.")
|
||||
.arg(sanitizeHtml(player->getName()))
|
||||
.arg(zone->getTranslatedName(true, CaseRevealZone))
|
||||
.arg(sanitizeHtml(otherPlayer->getName())));
|
||||
} else {
|
||||
appendHtmlServerMessage(tr("%1 reveals %2.")
|
||||
.arg(sanitizeHtml(player->getName()))
|
||||
@@ -566,39 +558,18 @@ void MessageLogWidget::logReverseTurn(Player *player, bool reversed)
|
||||
.arg(reversed ? tr("reversed") : tr("normal")));
|
||||
}
|
||||
|
||||
void MessageLogWidget::logRollDie(Player *player, int sides, const QList<uint> &rolls)
|
||||
void MessageLogWidget::logRollDie(Player *player, int sides, int roll)
|
||||
{
|
||||
if (rolls.length() == 1) {
|
||||
const auto roll = rolls.at(0);
|
||||
if (sides == 2) {
|
||||
QString coinOptions[2] = {tr("Heads") + " (1)", tr("Tails") + " (2)"};
|
||||
appendHtmlServerMessage(tr("%1 flipped a coin. It landed as %2.")
|
||||
.arg(sanitizeHtml(player->getName()))
|
||||
.arg("<font class=\"blue\">" + coinOptions[roll - 1] + "</font>"));
|
||||
} else {
|
||||
appendHtmlServerMessage(tr("%1 rolls a %2 with a %3-sided die.")
|
||||
.arg(sanitizeHtml(player->getName()))
|
||||
.arg("<font class=\"blue\">" + QString::number(roll) + "</font>")
|
||||
.arg("<font class=\"blue\">" + QString::number(sides) + "</font>"));
|
||||
}
|
||||
if (sides == 2) {
|
||||
QString coinOptions[2] = {tr("Heads") + " (1)", tr("Tails") + " (2)"};
|
||||
appendHtmlServerMessage(tr("%1 flipped a coin. It landed as %2.")
|
||||
.arg(sanitizeHtml(player->getName()))
|
||||
.arg("<font class=\"blue\">" + coinOptions[roll - 1] + "</font>"));
|
||||
} else {
|
||||
if (sides == 2) {
|
||||
appendHtmlServerMessage(tr("%1 flips %2 coins. There are %3 heads and %4 tails.")
|
||||
.arg(sanitizeHtml(player->getName()))
|
||||
.arg("<font class=\"blue\">" + QString::number(rolls.length()) + "</font>")
|
||||
.arg("<font class=\"blue\">" + QString::number(rolls.count(1)) + "</font>")
|
||||
.arg("<font class=\"blue\">" + QString::number(rolls.count(2)) + "</font>"));
|
||||
} else {
|
||||
QStringList rollsStrings;
|
||||
for (const auto &roll : rolls) {
|
||||
rollsStrings.append(QString::number(roll));
|
||||
}
|
||||
appendHtmlServerMessage(tr("%1 rolls a %2-sided dice %3 times: %4.")
|
||||
.arg(sanitizeHtml(player->getName()))
|
||||
.arg("<font class=\"blue\">" + QString::number(sides) + "</font>")
|
||||
.arg("<font class=\"blue\">" + QString::number(rolls.length()) + "</font>")
|
||||
.arg("<font class=\"blue\">" + rollsStrings.join(", ") + "</font>"));
|
||||
}
|
||||
appendHtmlServerMessage(tr("%1 rolls a %2 with a %3-sided die.")
|
||||
.arg(sanitizeHtml(player->getName()))
|
||||
.arg("<font class=\"blue\">" + QString::number(roll) + "</font>")
|
||||
.arg("<font class=\"blue\">" + QString::number(sides) + "</font>"));
|
||||
}
|
||||
soundEngine->playSound("roll_dice");
|
||||
}
|
||||
@@ -825,8 +796,7 @@ void MessageLogWidget::connectToPlayer(Player *player)
|
||||
|
||||
connect(player, SIGNAL(logSay(Player *, QString)), this, SLOT(logSay(Player *, QString)));
|
||||
connect(player, &Player::logShuffle, this, &MessageLogWidget::logShuffle);
|
||||
connect(player, SIGNAL(logRollDie(Player *, int, const QList<uint> &)), this,
|
||||
SLOT(logRollDie(Player *, int, const QList<uint> &)));
|
||||
connect(player, SIGNAL(logRollDie(Player *, int, int)), this, SLOT(logRollDie(Player *, int, int)));
|
||||
connect(player, SIGNAL(logCreateArrow(Player *, Player *, QString, Player *, QString, bool)), this,
|
||||
SLOT(logCreateArrow(Player *, Player *, QString, Player *, QString, bool)));
|
||||
connect(player, SIGNAL(logCreateToken(Player *, QString, QString)), this,
|
||||
@@ -853,8 +823,8 @@ void MessageLogWidget::connectToPlayer(Player *player)
|
||||
connect(player, SIGNAL(logDumpZone(Player *, CardZone *, int)), this, SLOT(logDumpZone(Player *, CardZone *, int)));
|
||||
connect(player, SIGNAL(logDrawCards(Player *, int, bool)), this, SLOT(logDrawCards(Player *, int, bool)));
|
||||
connect(player, SIGNAL(logUndoDraw(Player *, QString)), this, SLOT(logUndoDraw(Player *, QString)));
|
||||
connect(player, SIGNAL(logRevealCards(Player *, CardZone *, int, QString, Player *, bool, int, bool)), this,
|
||||
SLOT(logRevealCards(Player *, CardZone *, int, QString, Player *, bool, int, bool)));
|
||||
connect(player, SIGNAL(logRevealCards(Player *, CardZone *, int, QString, Player *, bool, int)), this,
|
||||
SLOT(logRevealCards(Player *, CardZone *, int, QString, Player *, bool, int)));
|
||||
connect(player, SIGNAL(logAlwaysRevealTopCard(Player *, CardZone *, bool)), this,
|
||||
SLOT(logAlwaysRevealTopCard(Player *, CardZone *, bool)));
|
||||
connect(player, SIGNAL(logAlwaysLookAtTopCard(Player *, CardZone *, bool)), this,
|
||||
|
||||
@@ -77,10 +77,9 @@ public slots:
|
||||
QString cardName,
|
||||
Player *otherPlayer,
|
||||
bool faceDown,
|
||||
int amount,
|
||||
bool isLentToAnotherPlayer);
|
||||
int amount);
|
||||
void logReverseTurn(Player *player, bool reversed);
|
||||
void logRollDie(Player *player, int sides, const QList<uint> &rolls);
|
||||
void logRollDie(Player *player, int sides, int roll);
|
||||
void logSay(Player *player, QString message);
|
||||
void logSetActivePhase(int phase);
|
||||
void logSetActivePlayer(Player *player);
|
||||
|
||||
@@ -6,16 +6,13 @@
|
||||
#include "thememanager.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QBuffer>
|
||||
#include <QCryptographicHash>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QDirIterator>
|
||||
#include <QFile>
|
||||
#include <QImageReader>
|
||||
#include <QMovie>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkDiskCache>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkRequest>
|
||||
#include <QPainter>
|
||||
@@ -119,21 +116,6 @@ PictureLoaderWorker::PictureLoaderWorker()
|
||||
connect(&SettingsCache::instance(), SIGNAL(picDownloadChanged()), this, SLOT(picDownloadChanged()));
|
||||
|
||||
networkManager = new QNetworkAccessManager(this);
|
||||
// We need a timeout to ensure requests don't hang indefinitely in case of
|
||||
// cache corruption, see related Qt bug: https://bugreports.qt.io/browse/QTBUG-111397
|
||||
// Use Qt's default timeout (30s, as of 2023-02-22)
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
|
||||
networkManager->setTransferTimeout();
|
||||
#endif
|
||||
auto cache = new QNetworkDiskCache(this);
|
||||
cache->setCacheDirectory(SettingsCache::instance().getNetworkCachePath());
|
||||
// Note: the settings is in MB, but QNetworkDiskCache uses bytes
|
||||
connect(&SettingsCache::instance(), &SettingsCache::networkCacheSizeChanged, cache,
|
||||
[cache](int newSizeInMB) { cache->setMaximumCacheSize(1024L * 1024L * static_cast<qint64>(newSizeInMB)); });
|
||||
networkManager->setCache(cache);
|
||||
// Use a ManualRedirectPolicy since we keep track of redirects in picDownloadFinished
|
||||
// We can't use NoLessSafeRedirectPolicy because it is not applied with AlwaysCache
|
||||
networkManager->setRedirectPolicy(QNetworkRequest::ManualRedirectPolicy);
|
||||
connect(networkManager, SIGNAL(finished(QNetworkReply *)), this, SLOT(picDownloadFinished(QNetworkReply *)));
|
||||
|
||||
pictureLoaderThread = new QThread;
|
||||
@@ -167,19 +149,37 @@ void PictureLoaderWorker::processLoadQueue()
|
||||
QString cardName = cardBeingLoaded.getCard()->getName();
|
||||
QString correctedCardName = cardBeingLoaded.getCard()->getCorrectedName();
|
||||
|
||||
qDebug().nospace() << "PictureLoader: [card: " << cardName << " set: " << setName
|
||||
<< "]: Trying to load picture";
|
||||
qDebug() << "PictureLoader: [card: " << cardName << " set: " << setName << "]: Trying to load picture";
|
||||
|
||||
if (cardImageExistsOnDisk(setName, correctedCardName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
qDebug().nospace() << "PictureLoader: [card: " << cardName << " set: " << setName
|
||||
<< "]: No custom picture, trying to download";
|
||||
cardsToDownload.append(cardBeingLoaded);
|
||||
cardBeingLoaded.clear();
|
||||
if (!downloadRunning) {
|
||||
startNextPicDownload();
|
||||
if (picDownload) {
|
||||
qDebug() << "PictureLoader: [card: " << cardName << " set: " << setName
|
||||
<< "]: Picture not found on disk, trying to download";
|
||||
cardsToDownload.append(cardBeingLoaded);
|
||||
cardBeingLoaded.clear();
|
||||
if (!downloadRunning) {
|
||||
startNextPicDownload();
|
||||
}
|
||||
} else {
|
||||
if (cardBeingLoaded.nextSet()) {
|
||||
qDebug() << "PictureLoader: [card: " << cardName << " set: " << setName
|
||||
<< "]: Picture NOT found and download disabled, moving to next "
|
||||
"set (new set: "
|
||||
<< setName << " card: " << cardName << ")";
|
||||
mutex.lock();
|
||||
loadQueue.prepend(cardBeingLoaded);
|
||||
cardBeingLoaded.clear();
|
||||
mutex.unlock();
|
||||
} else {
|
||||
qDebug() << "PictureLoader: [card: " << cardName << " set: " << setName
|
||||
<< "]: Picture NOT found, download disabled, no more sets to "
|
||||
"try: BAILING OUT (old set: "
|
||||
<< setName << " card: " << cardName << ")";
|
||||
imageLoaded(cardBeingLoaded.getCard(), QImage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -206,33 +206,31 @@ bool PictureLoaderWorker::cardImageExistsOnDisk(QString &setName, QString &corre
|
||||
|
||||
if (!setName.isEmpty()) {
|
||||
picsPaths << picsPath + "/" + setName + "/" + correctedCardname
|
||||
// We no longer store downloaded images there, but don't just ignore
|
||||
// stuff that old versions have put there.
|
||||
<< picsPath + "/downloadedPics/" + setName + "/" + correctedCardname;
|
||||
}
|
||||
|
||||
// Iterates through the list of paths, searching for images with the desired
|
||||
// name with any QImageReader-supported
|
||||
// extension
|
||||
for (const auto &_picsPath : picsPaths) {
|
||||
imgReader.setFileName(_picsPath);
|
||||
for (const auto &picsPath : picsPaths) {
|
||||
imgReader.setFileName(picsPath);
|
||||
if (imgReader.read(&image)) {
|
||||
qDebug().nospace() << "PictureLoader: [card: " << correctedCardname << " set: " << setName
|
||||
<< "]: Picture found on disk.";
|
||||
qDebug() << "PictureLoader: [card: " << correctedCardname << " set: " << setName
|
||||
<< "]: Picture found on disk.";
|
||||
imageLoaded(cardBeingLoaded.getCard(), image);
|
||||
return true;
|
||||
}
|
||||
imgReader.setFileName(_picsPath + ".full");
|
||||
imgReader.setFileName(picsPath + ".full");
|
||||
if (imgReader.read(&image)) {
|
||||
qDebug().nospace() << "PictureLoader: [card: " << correctedCardname << " set: " << setName
|
||||
<< "]: Picture.full found on disk.";
|
||||
qDebug() << "PictureLoader: [card: " << correctedCardname << " set: " << setName
|
||||
<< "]: Picture.full found on disk.";
|
||||
imageLoaded(cardBeingLoaded.getCard(), image);
|
||||
return true;
|
||||
}
|
||||
imgReader.setFileName(_picsPath + ".xlhq");
|
||||
imgReader.setFileName(picsPath + ".xlhq");
|
||||
if (imgReader.read(&image)) {
|
||||
qDebug().nospace() << "PictureLoader: [card: " << correctedCardname << " set: " << setName
|
||||
<< "]: Picture.xlhq found on disk.";
|
||||
qDebug() << "PictureLoader: [card: " << correctedCardname << " set: " << setName
|
||||
<< "]: Picture.xlhq found on disk.";
|
||||
imageLoaded(cardBeingLoaded.getCard(), image);
|
||||
return true;
|
||||
}
|
||||
@@ -241,79 +239,6 @@ bool PictureLoaderWorker::cardImageExistsOnDisk(QString &setName, QString &corre
|
||||
return false;
|
||||
}
|
||||
|
||||
static int parse(const QString &urlTemplate,
|
||||
const QString &propType,
|
||||
const QString &cardName,
|
||||
const QString &setName,
|
||||
std::function<QString(const QString &)> getProperty,
|
||||
QMap<QString, QString> &transformMap)
|
||||
{
|
||||
static const QRegularExpression rxFillWith("^(.+)_fill_with_(.+)$");
|
||||
static const QRegularExpression rxSubStr("^(.+)_substr_(\\d+)_(\\d+)$");
|
||||
|
||||
const QRegularExpression rxCardProp("!" + propType + ":([^!]+)!");
|
||||
|
||||
auto matches = rxCardProp.globalMatch(urlTemplate);
|
||||
while (matches.hasNext()) {
|
||||
auto match = matches.next();
|
||||
QString templatePropertyName = match.captured(1);
|
||||
auto fillMatch = rxFillWith.match(templatePropertyName);
|
||||
QString cardPropertyName;
|
||||
QString fillWith;
|
||||
int subStrPos = 0;
|
||||
int subStrLen = -1;
|
||||
if (fillMatch.hasMatch()) {
|
||||
cardPropertyName = fillMatch.captured(1);
|
||||
fillWith = fillMatch.captured(2);
|
||||
} else {
|
||||
fillWith = QString();
|
||||
auto subStrMatch = rxSubStr.match(templatePropertyName);
|
||||
if (subStrMatch.hasMatch()) {
|
||||
cardPropertyName = subStrMatch.captured(1);
|
||||
subStrPos = subStrMatch.captured(2).toInt();
|
||||
subStrLen = subStrMatch.captured(3).toInt();
|
||||
} else {
|
||||
cardPropertyName = templatePropertyName;
|
||||
}
|
||||
}
|
||||
QString propertyValue = getProperty(cardPropertyName);
|
||||
if (propertyValue.isEmpty()) {
|
||||
qDebug().nospace() << "PictureLoader: [card: " << cardName << " set: " << setName << "]: Requested "
|
||||
<< propType << "property (" << cardPropertyName << ") for Url template (" << urlTemplate
|
||||
<< ") is not available";
|
||||
return 1;
|
||||
} else {
|
||||
int propLength = propertyValue.length();
|
||||
if (subStrLen > 0 && subStrPos + subStrLen > propLength) {
|
||||
qDebug().nospace() << "PictureLoader: [card: " << cardName << " set: " << setName << "]: Requested "
|
||||
<< propType << " property (" << cardPropertyName << ") for Url template ("
|
||||
<< urlTemplate << ") is smaller than substr specification (" << subStrPos << " + "
|
||||
<< subStrLen << " > " << propLength << ")";
|
||||
return 1;
|
||||
} else {
|
||||
propertyValue = propertyValue.mid(subStrPos, subStrLen);
|
||||
propLength = subStrLen;
|
||||
}
|
||||
|
||||
if (!fillWith.isEmpty()) {
|
||||
int fillLength = fillWith.length();
|
||||
if (fillLength < propLength) {
|
||||
qDebug().nospace() << "PictureLoader: [card: " << cardName << " set: " << setName << "]: Requested "
|
||||
<< propType << " property (" << cardPropertyName << ") for Url template ("
|
||||
<< urlTemplate << ") is longer than fill specification (" << fillWith << ")";
|
||||
return 1;
|
||||
} else {
|
||||
|
||||
propertyValue = fillWith.left(fillLength - propLength) + propertyValue;
|
||||
}
|
||||
}
|
||||
|
||||
transformMap["!" + propType + ":" + templatePropertyName + "!"] = propertyValue;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
QString PictureToLoad::transformUrl(const QString &urlTemplate) const
|
||||
{
|
||||
/* This function takes Url templates and substitutes actual card details
|
||||
@@ -321,23 +246,56 @@ QString PictureToLoad::transformUrl(const QString &urlTemplate) const
|
||||
for downloading images. If information is requested by the template that is
|
||||
not populated for this specific card/set combination, an empty string is returned.*/
|
||||
|
||||
static const QRegularExpression rxCardProp("!prop:([^!]+)!");
|
||||
static const QRegularExpression rxFillWith("^(.+)_fill_with_(.+)$");
|
||||
static const QRegularExpression rxSetProp("!set:([^!]+)!");
|
||||
|
||||
QString transformedUrl = urlTemplate;
|
||||
CardSetPtr set = getCurrentSet();
|
||||
|
||||
QMap<QString, QString> transformMap = QMap<QString, QString>();
|
||||
QString setName = getSetName();
|
||||
|
||||
// name
|
||||
QString cardName = card->getName();
|
||||
transformMap["!name!"] = cardName;
|
||||
transformMap["!name!"] = card->getName();
|
||||
transformMap["!name_lower!"] = card->getName().toLower();
|
||||
transformMap["!corrected_name!"] = card->getCorrectedName();
|
||||
transformMap["!corrected_name_lower!"] = card->getCorrectedName().toLower();
|
||||
|
||||
// card properties
|
||||
if (parse(
|
||||
urlTemplate, "prop", cardName, setName, [&](const QString &name) { return card->getProperty(name); },
|
||||
transformMap)) {
|
||||
return QString();
|
||||
auto matches = rxCardProp.globalMatch(transformedUrl);
|
||||
while (matches.hasNext()) {
|
||||
auto match = matches.next();
|
||||
QString propertyName = match.captured(1);
|
||||
auto fillMatch = rxFillWith.match(propertyName);
|
||||
QString fillPropertyName;
|
||||
QString fillWith;
|
||||
if (fillMatch.hasMatch()) {
|
||||
fillPropertyName = fillMatch.captured(1);
|
||||
fillWith = fillMatch.captured(2);
|
||||
} else {
|
||||
fillPropertyName = propertyName;
|
||||
fillWith = QString();
|
||||
}
|
||||
QString propertyValue = card->getProperty(fillPropertyName);
|
||||
if (propertyValue.isEmpty()) {
|
||||
qDebug() << "PictureLoader: [card: " << card->getName() << " set: " << getSetName()
|
||||
<< "]: Requested property (" << fillPropertyName << ") for Url template (" << urlTemplate
|
||||
<< ") is not available";
|
||||
return QString();
|
||||
} else {
|
||||
if (!fillWith.isEmpty()) {
|
||||
int fillLength = fillWith.length();
|
||||
int propLength = propertyValue.length();
|
||||
if (fillLength < propLength) {
|
||||
qDebug() << "PictureLoader: [card: " << card->getName() << " set: " << getSetName()
|
||||
<< "]: Requested property (" << fillPropertyName << ") for Url template (" << urlTemplate
|
||||
<< ") is longer than fill specification (" << fillWith << ")";
|
||||
return QString();
|
||||
} else {
|
||||
propertyValue = fillWith.left(fillLength - propLength) + propertyValue;
|
||||
}
|
||||
}
|
||||
transformMap["!prop:" + propertyName + "!"] = propertyValue;
|
||||
}
|
||||
}
|
||||
|
||||
if (set) {
|
||||
@@ -346,10 +304,41 @@ QString PictureToLoad::transformUrl(const QString &urlTemplate) const
|
||||
transformMap["!setname!"] = set->getLongName();
|
||||
transformMap["!setname_lower!"] = set->getLongName().toLower();
|
||||
|
||||
if (parse(
|
||||
urlTemplate, "set", cardName, setName,
|
||||
[&](const QString &name) { return card->getSetProperty(set->getShortName(), name); }, transformMap)) {
|
||||
return QString();
|
||||
auto matches = rxSetProp.globalMatch(transformedUrl);
|
||||
while (matches.hasNext()) {
|
||||
auto match = matches.next();
|
||||
QString propertyName = match.captured(1);
|
||||
auto fillMatch = rxFillWith.match(propertyName);
|
||||
QString fillPropertyName;
|
||||
QString fillWith;
|
||||
if (fillMatch.hasMatch()) {
|
||||
fillPropertyName = fillMatch.captured(1);
|
||||
fillWith = fillMatch.captured(2);
|
||||
} else {
|
||||
fillPropertyName = propertyName;
|
||||
fillWith = QString();
|
||||
}
|
||||
QString propertyValue = card->getSetProperty(set->getShortName(), fillPropertyName);
|
||||
if (propertyValue.isEmpty()) {
|
||||
qDebug() << "PictureLoader: [card: " << card->getName() << " set: " << getSetName()
|
||||
<< "]: Requested set property (" << fillPropertyName << ") for Url template (" << urlTemplate
|
||||
<< ") is not available";
|
||||
return QString();
|
||||
} else {
|
||||
if (!fillWith.isEmpty()) {
|
||||
int fillLength = fillWith.length();
|
||||
int propLength = propertyValue.length();
|
||||
if (fillLength < propLength) {
|
||||
qDebug() << "PictureLoader: [card: " << card->getName() << " set: " << getSetName()
|
||||
<< "]: Requested set property (" << fillPropertyName << ") for Url template ("
|
||||
<< urlTemplate << ") is longer than fill specification (" << fillWith << ")";
|
||||
return QString();
|
||||
} else {
|
||||
propertyValue = fillWith.left(fillLength - propLength) + propertyValue;
|
||||
}
|
||||
}
|
||||
transformMap["!set:" + propertyName + "!"] = propertyValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,7 +346,6 @@ QString PictureToLoad::transformUrl(const QString &urlTemplate) const
|
||||
transformMap["!sflang!"] = QString(QCoreApplication::translate(
|
||||
"PictureLoader", "en", "code for scryfall's language property, not available for all languages"));
|
||||
|
||||
QString transformedUrl = urlTemplate;
|
||||
for (const QString &prop : transformMap.keys()) {
|
||||
if (transformedUrl.contains(prop)) {
|
||||
if (!transformMap[prop].isEmpty()) {
|
||||
@@ -367,9 +355,9 @@ QString PictureToLoad::transformUrl(const QString &urlTemplate) const
|
||||
* populated in this card, so it should return an empty string,
|
||||
* indicating an invalid Url.
|
||||
*/
|
||||
qDebug().nospace() << "PictureLoader: [card: " << cardName << " set: " << setName
|
||||
<< "]: Requested information (" << prop << ") for Url template (" << urlTemplate
|
||||
<< ") is not available";
|
||||
qDebug() << "PictureLoader: [card: " << card->getName() << " set: " << getSetName()
|
||||
<< "]: Requested information (" << prop << ") for Url template (" << urlTemplate
|
||||
<< ") is not available";
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
@@ -397,10 +385,11 @@ void PictureLoaderWorker::startNextPicDownload()
|
||||
picDownloadFailed();
|
||||
} else {
|
||||
QUrl url(picUrl);
|
||||
qDebug().nospace() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getCorrectedName()
|
||||
<< " set: " << cardBeingDownloaded.getSetName() << "]: Trying to fetch picture from url "
|
||||
<< url.toDisplayString();
|
||||
makeRequest(url);
|
||||
QNetworkRequest req(url);
|
||||
qDebug() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getCorrectedName()
|
||||
<< " set: " << cardBeingDownloaded.getSetName()
|
||||
<< "]: Trying to download picture from url:" << url.toDisplayString();
|
||||
networkManager->get(req);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -415,10 +404,10 @@ void PictureLoaderWorker::picDownloadFailed()
|
||||
loadQueue.prepend(cardBeingDownloaded);
|
||||
mutex.unlock();
|
||||
} else {
|
||||
qDebug().nospace() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getCorrectedName()
|
||||
<< " set: " << cardBeingDownloaded.getSetName() << "]: Picture NOT found, "
|
||||
<< (picDownload ? "download failed" : "downloads disabled")
|
||||
<< ", no more url combinations to try: BAILING OUT";
|
||||
qDebug() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getCorrectedName()
|
||||
<< " set: " << cardBeingDownloaded.getSetName()
|
||||
<< "]: Picture NOT found, download failed, no more url combinations "
|
||||
"to try: BAILING OUT";
|
||||
imageLoaded(cardBeingDownloaded.getCard(), QImage());
|
||||
cardBeingDownloaded.clear();
|
||||
}
|
||||
@@ -431,53 +420,20 @@ bool PictureLoaderWorker::imageIsBlackListed(const QByteArray &picData)
|
||||
return md5Blacklist.contains(md5sum);
|
||||
}
|
||||
|
||||
QNetworkReply *PictureLoaderWorker::makeRequest(const QUrl &url)
|
||||
{
|
||||
QNetworkRequest req(url);
|
||||
if (!picDownload) {
|
||||
req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysCache);
|
||||
}
|
||||
return networkManager->get(req);
|
||||
}
|
||||
|
||||
void PictureLoaderWorker::picDownloadFinished(QNetworkReply *reply)
|
||||
{
|
||||
bool isFromCache = reply->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool();
|
||||
|
||||
if (reply->error()) {
|
||||
if (isFromCache) {
|
||||
qDebug().nospace() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName()
|
||||
<< " set: " << cardBeingDownloaded.getSetName()
|
||||
<< "]: Removing corrupted cache file for url " << reply->url().toDisplayString()
|
||||
<< " and retrying (" << reply->errorString() << ")";
|
||||
|
||||
networkManager->cache()->remove(reply->url());
|
||||
|
||||
makeRequest(reply->url());
|
||||
} else {
|
||||
qDebug().nospace() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName()
|
||||
<< " set: " << cardBeingDownloaded.getSetName()
|
||||
<< "]: " << (picDownload ? "Download" : "Cache search") << " failed for url "
|
||||
<< reply->url().toDisplayString() << " (" << reply->errorString() << ")";
|
||||
|
||||
picDownloadFailed();
|
||||
startNextPicDownload();
|
||||
}
|
||||
|
||||
reply->deleteLater();
|
||||
return;
|
||||
qDebug() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName()
|
||||
<< " set: " << cardBeingDownloaded.getSetName() << "]: Download failed:" << reply->errorString();
|
||||
}
|
||||
|
||||
// List of status codes from https://doc.qt.io/qt-6/qnetworkreply.html#redirected
|
||||
int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
if (statusCode == 301 || statusCode == 302 || statusCode == 303 || statusCode == 305 || statusCode == 307 ||
|
||||
statusCode == 308) {
|
||||
QUrl redirectUrl = reply->header(QNetworkRequest::LocationHeader).toUrl();
|
||||
qDebug().nospace() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName()
|
||||
<< " set: " << cardBeingDownloaded.getSetName() << "]: following "
|
||||
<< (isFromCache ? "cached redirect" : "redirect") << " to " << redirectUrl.toDisplayString();
|
||||
makeRequest(redirectUrl);
|
||||
reply->deleteLater();
|
||||
if (statusCode == 301 || statusCode == 302) {
|
||||
QUrl redirectUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
|
||||
QNetworkRequest req(redirectUrl);
|
||||
qDebug() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName()
|
||||
<< " set: " << cardBeingDownloaded.getSetName() << "]: following redirect:" << req.url().toString();
|
||||
networkManager->get(req);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -485,10 +441,10 @@ void PictureLoaderWorker::picDownloadFinished(QNetworkReply *reply)
|
||||
const QByteArray &picData = reply->peek(reply->size());
|
||||
|
||||
if (imageIsBlackListed(picData)) {
|
||||
qDebug().nospace() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName()
|
||||
<< " set: " << cardBeingDownloaded.getSetName()
|
||||
<< "]: Picture found, but blacklisted, will consider it as not found";
|
||||
|
||||
qDebug() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName()
|
||||
<< " set: " << cardBeingDownloaded.getSetName()
|
||||
<< "]:Picture downloaded, but blacklisted, will consider it as "
|
||||
"not found";
|
||||
picDownloadFailed();
|
||||
reply->deleteLater();
|
||||
startNextPicDownload();
|
||||
@@ -500,39 +456,41 @@ void PictureLoaderWorker::picDownloadFinished(QNetworkReply *reply)
|
||||
QImageReader imgReader;
|
||||
imgReader.setDecideFormatFromContent(true);
|
||||
imgReader.setDevice(reply);
|
||||
|
||||
bool logSuccessMessage = false;
|
||||
|
||||
static const int riffHeaderSize = 12; // RIFF_HEADER_SIZE from webp/format_constants.h
|
||||
auto replyHeader = reply->peek(riffHeaderSize);
|
||||
|
||||
if (replyHeader.startsWith("RIFF") && replyHeader.endsWith("WEBP")) {
|
||||
auto imgBuf = QBuffer(this);
|
||||
imgBuf.setData(reply->readAll());
|
||||
|
||||
auto movie = QMovie(&imgBuf);
|
||||
movie.start();
|
||||
movie.stop();
|
||||
|
||||
imageLoaded(cardBeingDownloaded.getCard(), movie.currentImage());
|
||||
logSuccessMessage = true;
|
||||
} else if (imgReader.read(&testImage)) {
|
||||
imageLoaded(cardBeingDownloaded.getCard(), testImage);
|
||||
logSuccessMessage = true;
|
||||
} else {
|
||||
qDebug().nospace() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName()
|
||||
<< " set: " << cardBeingDownloaded.getSetName() << "]: Possible "
|
||||
<< (isFromCache ? "cached" : "downloaded") << " picture at "
|
||||
<< reply->url().toDisplayString() << " could not be loaded: " << reply->errorString();
|
||||
|
||||
picDownloadFailed();
|
||||
// the format is determined prior to reading the QImageReader data into a QImage object, as that wipes the
|
||||
// QImageReader buffer
|
||||
QString extension = "." + imgReader.format();
|
||||
if (extension == ".jpeg") {
|
||||
extension = ".jpg";
|
||||
}
|
||||
|
||||
if (logSuccessMessage) {
|
||||
qDebug().nospace() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName()
|
||||
<< " set: " << cardBeingDownloaded.getSetName() << "]: Image successfully "
|
||||
<< (isFromCache ? "loaded from cached" : "downloaded from") << " url "
|
||||
<< reply->url().toDisplayString();
|
||||
if (imgReader.read(&testImage)) {
|
||||
QString setName = cardBeingDownloaded.getSetName();
|
||||
if (!setName.isEmpty()) {
|
||||
if (!QDir().mkpath(picsPath + "/downloadedPics/" + setName)) {
|
||||
qDebug() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName()
|
||||
<< " set: " << cardBeingDownloaded.getSetName()
|
||||
<< "]: " << picsPath + "/downloadedPics/" + setName + " could not be created.";
|
||||
return;
|
||||
}
|
||||
|
||||
QFile newPic(picsPath + "/downloadedPics/" + setName + "/" +
|
||||
cardBeingDownloaded.getCard()->getCorrectedName() + extension);
|
||||
if (!newPic.open(QIODevice::WriteOnly)) {
|
||||
return;
|
||||
}
|
||||
newPic.write(picData);
|
||||
newPic.close();
|
||||
}
|
||||
|
||||
imageLoaded(cardBeingDownloaded.getCard(), testImage);
|
||||
qDebug() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName()
|
||||
<< " set: " << cardBeingDownloaded.getSetName() << "]: Image successfully downloaded from "
|
||||
<< reply->request().url().toDisplayString();
|
||||
} else {
|
||||
qDebug() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName()
|
||||
<< " set: " << cardBeingDownloaded.getSetName() << "]: Possible picture at "
|
||||
<< reply->request().url().toDisplayString() << " could not be loaded";
|
||||
picDownloadFailed();
|
||||
}
|
||||
|
||||
reply->deleteLater();
|
||||
@@ -575,11 +533,6 @@ void PictureLoaderWorker::picsPathChanged()
|
||||
customPicsPath = SettingsCache::instance().getCustomPicsPath();
|
||||
}
|
||||
|
||||
void PictureLoaderWorker::clearNetworkCache()
|
||||
{
|
||||
networkManager->cache()->clear();
|
||||
}
|
||||
|
||||
PictureLoader::PictureLoader() : QObject(nullptr)
|
||||
{
|
||||
worker = new PictureLoaderWorker;
|
||||
@@ -621,7 +574,7 @@ void PictureLoader::getPixmap(QPixmap &pixmap, CardInfoPtr card, QSize size)
|
||||
QPixmap bigPixmap;
|
||||
if (QPixmapCache::find(key, &bigPixmap)) {
|
||||
QScreen *screen = qApp->primaryScreen();
|
||||
qreal dpr = screen->devicePixelRatio();
|
||||
int dpr = screen->devicePixelRatio();
|
||||
pixmap = bigPixmap.scaled(size * dpr, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
pixmap.setDevicePixelRatio(dpr);
|
||||
QPixmapCache::insert(sizeKey, pixmap);
|
||||
@@ -660,11 +613,6 @@ void PictureLoader::clearPixmapCache()
|
||||
QPixmapCache::clear();
|
||||
}
|
||||
|
||||
void PictureLoader::clearNetworkCache()
|
||||
{
|
||||
getInstance().worker->clearNetworkCache();
|
||||
}
|
||||
|
||||
void PictureLoader::cacheCardPixmaps(QList<CardInfoPtr> cards)
|
||||
{
|
||||
QPixmap tmp;
|
||||
|
||||
@@ -73,7 +73,6 @@ public:
|
||||
~PictureLoaderWorker() override;
|
||||
|
||||
void enqueueImageLoad(CardInfoPtr card);
|
||||
void clearNetworkCache();
|
||||
|
||||
private:
|
||||
static QStringList md5Blacklist;
|
||||
@@ -88,9 +87,8 @@ private:
|
||||
PictureToLoad cardBeingDownloaded;
|
||||
bool picDownload, downloadRunning, loadQueueRunning;
|
||||
void startNextPicDownload();
|
||||
bool cardImageExistsOnDisk(QString &setName, QString &correctedCardName);
|
||||
bool cardImageExistsOnDisk(QString &, QString &);
|
||||
bool imageIsBlackListed(const QByteArray &);
|
||||
QNetworkReply *makeRequest(const QUrl &url);
|
||||
private slots:
|
||||
void picDownloadFinished(QNetworkReply *reply);
|
||||
void picDownloadFailed();
|
||||
@@ -99,7 +97,6 @@ private slots:
|
||||
void picsPathChanged();
|
||||
public slots:
|
||||
void processLoadQueue();
|
||||
|
||||
signals:
|
||||
void startLoadQueue();
|
||||
void imageLoaded(CardInfoPtr card, const QImage &image);
|
||||
@@ -130,14 +127,9 @@ public:
|
||||
static void clearPixmapCache(CardInfoPtr card);
|
||||
static void clearPixmapCache();
|
||||
static void cacheCardPixmaps(QList<CardInfoPtr> cards);
|
||||
|
||||
public slots:
|
||||
static void clearNetworkCache();
|
||||
|
||||
private slots:
|
||||
void picDownloadChanged();
|
||||
void picsPathChanged();
|
||||
|
||||
public slots:
|
||||
void imageLoaded(CardInfoPtr card, const QImage &image);
|
||||
};
|
||||
|
||||
@@ -28,20 +28,13 @@ QRectF PileZone::boundingRect() const
|
||||
return QRectF(0, 0, CARD_WIDTH, CARD_HEIGHT);
|
||||
}
|
||||
|
||||
QPainterPath PileZone::shape() const
|
||||
{
|
||||
QPainterPath shape;
|
||||
shape.addRoundedRect(boundingRect(), 0.05 * CARD_WIDTH, 0.05 * CARD_WIDTH);
|
||||
return shape;
|
||||
}
|
||||
|
||||
void PileZone::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/)
|
||||
{
|
||||
painter->drawPath(shape());
|
||||
|
||||
if (!cards.isEmpty())
|
||||
cards.at(0)->paintPicture(painter, cards.at(0)->getTranslatedSize(painter), 90);
|
||||
|
||||
painter->drawRect(QRectF(0.5, 0.5, CARD_WIDTH - 1, CARD_HEIGHT - 1));
|
||||
|
||||
painter->translate((float)CARD_WIDTH / 2, (float)CARD_HEIGHT / 2);
|
||||
painter->rotate(-90);
|
||||
painter->translate((float)-CARD_WIDTH / 2, (float)-CARD_HEIGHT / 2);
|
||||
|
||||
@@ -18,18 +18,17 @@ public:
|
||||
bool _isShufflable,
|
||||
bool _contentsKnown,
|
||||
QGraphicsItem *parent = nullptr);
|
||||
QRectF boundingRect() const override;
|
||||
QPainterPath shape() const override;
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
|
||||
void reorganizeCards() override;
|
||||
void handleDropEvent(const QList<CardDragItem *> &dragItems, CardZone *startZone, const QPoint &dropPoint) override;
|
||||
QRectF boundingRect() const;
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
|
||||
void reorganizeCards();
|
||||
void handleDropEvent(const QList<CardDragItem *> &dragItems, CardZone *startZone, const QPoint &dropPoint);
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;
|
||||
void addCardImpl(CardItem *card, int x, int y) override;
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent *event);
|
||||
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
|
||||
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
|
||||
void addCardImpl(CardItem *card, int x, int y);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include "counter_general.h"
|
||||
#include "deck_loader.h"
|
||||
#include "dlg_create_token.h"
|
||||
#include "dlg_roll_dice.h"
|
||||
#include "gamescene.h"
|
||||
#include "gettextwithmax.h"
|
||||
#include "handcounter.h"
|
||||
@@ -58,24 +57,20 @@
|
||||
#include "playertarget.h"
|
||||
#include "settingscache.h"
|
||||
#include "stackzone.h"
|
||||
#include "stringsizes.h"
|
||||
#include "tab_game.h"
|
||||
#include "tablezone.h"
|
||||
#include "thememanager.h"
|
||||
#include "trice_limits.h"
|
||||
#include "zoneviewwidget.h"
|
||||
#include "zoneviewzone.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QMenu>
|
||||
#include <QMessageBox>
|
||||
#include <QMetaType>
|
||||
#include <QPainter>
|
||||
#include <QRegularExpression>
|
||||
#include <QRegularExpressionMatch>
|
||||
|
||||
// milliseconds in between triggers of the move top cards until action
|
||||
static constexpr int MOVE_TOP_CARD_UNTIL_INTERVAL = 100;
|
||||
|
||||
PlayerArea::PlayerArea(QGraphicsItem *parentItem) : QObject(), QGraphicsItem(parentItem)
|
||||
{
|
||||
setCacheMode(DeviceCoordinateCache);
|
||||
@@ -111,9 +106,9 @@ void PlayerArea::setPlayerZoneId(int _playerZoneId)
|
||||
}
|
||||
|
||||
Player::Player(const ServerInfo_User &info, int _id, bool _local, bool _judge, TabGame *_parent)
|
||||
: QObject(_parent), game(_parent), movingCardsUntil(false), shortcutsActive(false), lastTokenDestroy(true),
|
||||
lastTokenTableRow(0), id(_id), active(false), local(_local), judge(_judge), mirrored(false), handVisible(false),
|
||||
conceded(false), zoneId(0), dialogSemaphore(false), deck(nullptr)
|
||||
: QObject(_parent), game(_parent), shortcutsActive(false), lastTokenDestroy(true), lastTokenTableRow(0), id(_id),
|
||||
active(false), local(_local), judge(_judge), mirrored(false), handVisible(false), conceded(false), zoneId(0),
|
||||
dialogSemaphore(false), deck(nullptr)
|
||||
{
|
||||
userInfo = new ServerInfo_User;
|
||||
userInfo->CopyFrom(info);
|
||||
@@ -127,12 +122,12 @@ Player::Player(const ServerInfo_User &info, int _id, bool _local, bool _judge, T
|
||||
qreal avatarMargin = (counterAreaWidth + CARD_HEIGHT + 15 - playerTarget->boundingRect().width()) / 2.0;
|
||||
playerTarget->setPos(QPointF(avatarMargin, avatarMargin));
|
||||
|
||||
auto *_deck = new PileZone(this, "deck", true, false, playerArea);
|
||||
PileZone *deck = new PileZone(this, "deck", true, false, playerArea);
|
||||
QPointF base = QPointF(counterAreaWidth + (CARD_HEIGHT - CARD_WIDTH + 15) / 2.0,
|
||||
10 + playerTarget->boundingRect().height() + 5 - (CARD_HEIGHT - CARD_WIDTH) / 2.0);
|
||||
_deck->setPos(base);
|
||||
deck->setPos(base);
|
||||
|
||||
qreal h = _deck->boundingRect().width() + 5;
|
||||
qreal h = deck->boundingRect().width() + 5;
|
||||
|
||||
auto *handCounter = new HandCounter(playerArea);
|
||||
handCounter->setPos(base + QPointF(0, h + 10));
|
||||
@@ -152,7 +147,7 @@ Player::Player(const ServerInfo_User &info, int _id, bool _local, bool _judge, T
|
||||
|
||||
stack = new StackZone(this, (int)table->boundingRect().height(), this);
|
||||
|
||||
hand = new HandZone(this, _local || _judge || (_parent->getSpectator() && _parent->getSpectatorsSeeEverything()),
|
||||
hand = new HandZone(this, _local || (_parent->getSpectator() && _parent->getSpectatorsSeeEverything()),
|
||||
(int)table->boundingRect().height(), this);
|
||||
connect(hand, SIGNAL(cardCountChanged()), handCounter, SLOT(updateNumber()));
|
||||
connect(handCounter, SIGNAL(showContextMenu(const QPoint &)), hand, SLOT(showContextMenu(const QPoint &)));
|
||||
@@ -258,8 +253,6 @@ Player::Player(const ServerInfo_User &info, int _id, bool _local, bool _judge, T
|
||||
connect(aMoveTopCardsToGraveyard, SIGNAL(triggered()), this, SLOT(actMoveTopCardsToGrave()));
|
||||
aMoveTopCardsToExile = new QAction(this);
|
||||
connect(aMoveTopCardsToExile, SIGNAL(triggered()), this, SLOT(actMoveTopCardsToExile()));
|
||||
aMoveTopCardsUntil = new QAction(this);
|
||||
connect(aMoveTopCardsUntil, SIGNAL(triggered()), this, SLOT(actMoveTopCardsUntil()));
|
||||
aMoveTopCardToBottom = new QAction(this);
|
||||
connect(aMoveTopCardToBottom, SIGNAL(triggered()), this, SLOT(actMoveTopCardToBottom()));
|
||||
|
||||
@@ -314,7 +307,6 @@ Player::Player(const ServerInfo_User &info, int _id, bool _local, bool _judge, T
|
||||
libraryMenu->addAction(aViewTopCards);
|
||||
libraryMenu->addSeparator();
|
||||
playerLists.append(mRevealLibrary = libraryMenu->addMenu(QString()));
|
||||
singlePlayerLists.append(mLendLibrary = libraryMenu->addMenu(QString()));
|
||||
playerLists.append(mRevealTopCard = libraryMenu->addMenu(QString()));
|
||||
libraryMenu->addAction(aAlwaysRevealTopCard);
|
||||
libraryMenu->addAction(aAlwaysLookAtTopCard);
|
||||
@@ -323,7 +315,7 @@ Player::Player(const ServerInfo_User &info, int _id, bool _local, bool _judge, T
|
||||
bottomLibraryMenu = libraryMenu->addTearOffMenu(QString());
|
||||
libraryMenu->addSeparator();
|
||||
libraryMenu->addAction(aOpenDeckInDeckEditor);
|
||||
_deck->setMenu(libraryMenu, aDrawCard);
|
||||
deck->setMenu(libraryMenu, aDrawCard);
|
||||
|
||||
topLibraryMenu->addAction(aMoveTopToPlay);
|
||||
topLibraryMenu->addAction(aMoveTopToPlayFaceDown);
|
||||
@@ -333,7 +325,6 @@ Player::Player(const ServerInfo_User &info, int _id, bool _local, bool _judge, T
|
||||
topLibraryMenu->addAction(aMoveTopCardsToGraveyard);
|
||||
topLibraryMenu->addAction(aMoveTopCardToExile);
|
||||
topLibraryMenu->addAction(aMoveTopCardsToExile);
|
||||
topLibraryMenu->addAction(aMoveTopCardsUntil);
|
||||
|
||||
bottomLibraryMenu->addAction(aDrawBottomCard);
|
||||
bottomLibraryMenu->addAction(aDrawBottomCards);
|
||||
@@ -537,11 +528,6 @@ Player::Player(const ServerInfo_User &info, int _id, bool _local, bool _judge, T
|
||||
addPlayer(player);
|
||||
}
|
||||
|
||||
moveTopCardTimer = new QTimer(this);
|
||||
moveTopCardTimer->setInterval(MOVE_TOP_CARD_UNTIL_INTERVAL);
|
||||
moveTopCardTimer->setSingleShot(true);
|
||||
connect(moveTopCardTimer, &QTimer::timeout, [this]() { actMoveTopCardToPlay(); });
|
||||
|
||||
rearrangeZones();
|
||||
retranslateUi();
|
||||
connect(&SettingsCache::instance().shortcuts(), SIGNAL(shortCutChanged()), this, SLOT(refreshShortcuts()));
|
||||
@@ -583,20 +569,10 @@ void Player::addPlayer(Player *player)
|
||||
}
|
||||
|
||||
for (auto &playerList : playerLists) {
|
||||
addPlayerToList(playerList, player);
|
||||
QAction *newAction = playerList->addAction(player->getName());
|
||||
newAction->setData(player->getId());
|
||||
connect(newAction, SIGNAL(triggered()), this, SLOT(playerListActionTriggered()));
|
||||
}
|
||||
for (auto &playerList : singlePlayerLists) {
|
||||
addPlayerToList(playerList, player);
|
||||
}
|
||||
|
||||
playersInfo.append(qMakePair(player->getName(), player->getId()));
|
||||
}
|
||||
|
||||
void Player::addPlayerToList(QMenu *playerList, Player *player)
|
||||
{
|
||||
QAction *newAction = playerList->addAction(player->getName());
|
||||
newAction->setData(player->getId());
|
||||
connect(newAction, SIGNAL(triggered()), this, SLOT(playerListActionTriggered()));
|
||||
}
|
||||
|
||||
void Player::removePlayer(Player *player)
|
||||
@@ -606,29 +582,13 @@ void Player::removePlayer(Player *player)
|
||||
}
|
||||
|
||||
for (auto &playerList : playerLists) {
|
||||
removePlayerFromList(playerList, player);
|
||||
QList<QAction *> actionList = playerList->actions();
|
||||
for (auto &j : actionList)
|
||||
if (j->data().toInt() == player->getId()) {
|
||||
playerList->removeAction(j);
|
||||
j->deleteLater();
|
||||
}
|
||||
}
|
||||
for (auto &playerList : singlePlayerLists) {
|
||||
removePlayerFromList(playerList, player);
|
||||
}
|
||||
|
||||
for (auto it = playersInfo.begin(); it != playersInfo.end();) {
|
||||
if (it->second == player->getId()) {
|
||||
it = playersInfo.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Player::removePlayerFromList(QMenu *playerList, Player *player)
|
||||
{
|
||||
QList<QAction *> actionList = playerList->actions();
|
||||
for (auto &j : actionList)
|
||||
if (j->data().toInt() == player->getId()) {
|
||||
playerList->removeAction(j);
|
||||
j->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
void Player::playerListActionTriggered()
|
||||
@@ -642,9 +602,8 @@ void Player::playerListActionTriggered()
|
||||
cmd.set_player_id(otherPlayerId);
|
||||
}
|
||||
|
||||
if (menu == mRevealLibrary || menu == mLendLibrary) {
|
||||
if (menu == mRevealLibrary) {
|
||||
cmd.set_zone_name("deck");
|
||||
cmd.set_grant_write_access(menu == mLendLibrary);
|
||||
} else if (menu == mRevealTopCard) {
|
||||
int deckSize = zones.value("deck")->getCards().size();
|
||||
bool ok;
|
||||
@@ -655,14 +614,14 @@ void Player::playerListActionTriggered()
|
||||
cmd.set_zone_name("deck");
|
||||
cmd.set_top_cards(number);
|
||||
// backward compatibility: servers before #1051 only permits to reveal the first card
|
||||
cmd.add_card_id(0);
|
||||
cmd.set_card_id(0);
|
||||
}
|
||||
|
||||
} else if (menu == mRevealHand) {
|
||||
cmd.set_zone_name("hand");
|
||||
} else if (menu == mRevealRandomHandCard) {
|
||||
cmd.set_zone_name("hand");
|
||||
cmd.add_card_id(RANDOM_CARD_FROM_ZONE);
|
||||
cmd.set_card_id(RANDOM_CARD_FROM_ZONE);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
@@ -770,7 +729,6 @@ void Player::retranslateUi()
|
||||
aViewHand->setText(tr("&View hand"));
|
||||
aViewTopCards->setText(tr("View &top cards of library..."));
|
||||
mRevealLibrary->setTitle(tr("Reveal &library to..."));
|
||||
mLendLibrary->setTitle(tr("Lend library to..."));
|
||||
mRevealTopCard->setTitle(tr("Reveal &top cards to..."));
|
||||
topLibraryMenu->setTitle(tr("&Top of library..."));
|
||||
bottomLibraryMenu->setTitle(tr("&Bottom of library..."));
|
||||
@@ -786,12 +744,11 @@ void Player::retranslateUi()
|
||||
|
||||
aMoveTopToPlay->setText(tr("&Play top card"));
|
||||
aMoveTopToPlayFaceDown->setText(tr("Play top card &face down"));
|
||||
aMoveTopCardToBottom->setText(tr("Put top card on &bottom"));
|
||||
aMoveTopCardToGraveyard->setText(tr("Move top card to grave&yard"));
|
||||
aMoveTopCardToExile->setText(tr("Move top card to e&xile"));
|
||||
aMoveTopCardsToGraveyard->setText(tr("Move top cards to &graveyard..."));
|
||||
aMoveTopCardsToExile->setText(tr("Move top cards to &exile..."));
|
||||
aMoveTopCardsUntil->setText(tr("Put top cards on stack &until..."));
|
||||
aMoveTopCardToBottom->setText(tr("Put top card on &bottom"));
|
||||
|
||||
aDrawBottomCard->setText(tr("&Draw bottom card"));
|
||||
aDrawBottomCards->setText(tr("D&raw bottom cards..."));
|
||||
@@ -875,7 +832,7 @@ void Player::retranslateUi()
|
||||
aSetCounter[i]->setText(tr("&Set counters (%1)...").arg(counterColors[i]));
|
||||
}
|
||||
|
||||
aMoveToTopLibrary->setText(tr("&Top of library in random order"));
|
||||
aMoveToTopLibrary->setText(tr("&Top of library"));
|
||||
aMoveToXfromTopOfLibrary->setText(tr("X cards from the top of library..."));
|
||||
aMoveToBottomLibrary->setText(tr("&Bottom of library in random order"));
|
||||
aMoveToHand->setText(tr("&Hand"));
|
||||
@@ -971,7 +928,6 @@ void Player::setShortcutsActive()
|
||||
aMoveTopCardsToGraveyard->setShortcut(shortcuts.getSingleShortcut("Player/aMoveTopCardsToGraveyard"));
|
||||
aMoveTopCardToExile->setShortcut(shortcuts.getSingleShortcut("Player/aMoveTopCardToExile"));
|
||||
aMoveTopCardsToExile->setShortcut(shortcuts.getSingleShortcut("Player/aMoveTopCardsToExile"));
|
||||
aMoveTopCardsUntil->setShortcut(shortcuts.getSingleShortcut("Player/aMoveTopCardsUntil"));
|
||||
aMoveTopCardToBottom->setShortcut(shortcuts.getSingleShortcut("Player/aMoveTopCardToBottom"));
|
||||
aDrawBottomCard->setShortcut(shortcuts.getSingleShortcut("Player/aDrawBottomCard"));
|
||||
aDrawBottomCards->setShortcut(shortcuts.getSingleShortcut("Player/aDrawBottomCards"));
|
||||
@@ -1012,7 +968,6 @@ void Player::setShortcutsInactive()
|
||||
aMoveTopCardsToGraveyard->setShortcut(QKeySequence());
|
||||
aMoveTopCardToExile->setShortcut(QKeySequence());
|
||||
aMoveTopCardsToExile->setShortcut(QKeySequence());
|
||||
aMoveTopCardsUntil->setShortcut(QKeySequence());
|
||||
aDrawBottomCard->setShortcut(QKeySequence());
|
||||
aDrawBottomCards->setShortcut(QKeySequence());
|
||||
aMoveBottomToPlay->setShortcut(QKeySequence());
|
||||
@@ -1045,16 +1000,6 @@ void Player::initSayMenu()
|
||||
}
|
||||
}
|
||||
|
||||
void Player::initContextualPlayersMenu(QMenu *menu)
|
||||
{
|
||||
menu->addAction(tr("&All players"))->setData(-1);
|
||||
menu->addSeparator();
|
||||
|
||||
for (const auto &playerInfo : playersInfo) {
|
||||
menu->addAction(playerInfo.first)->setData(playerInfo.second);
|
||||
}
|
||||
}
|
||||
|
||||
void Player::setDeck(const DeckLoader &_deck)
|
||||
{
|
||||
deck = new DeckLoader(_deck);
|
||||
@@ -1141,7 +1086,7 @@ void Player::actRevealRandomGraveyardCard()
|
||||
cmd.set_player_id(otherPlayerId);
|
||||
}
|
||||
cmd.set_zone_name("grave");
|
||||
cmd.add_card_id(RANDOM_CARD_FROM_ZONE);
|
||||
cmd.set_card_id(RANDOM_CARD_FROM_ZONE);
|
||||
sendGameCommand(cmd);
|
||||
}
|
||||
|
||||
@@ -1326,47 +1271,6 @@ void Player::actMoveTopCardsToExile()
|
||||
sendGameCommand(cmd);
|
||||
}
|
||||
|
||||
void Player::actMoveTopCardsUntil()
|
||||
{
|
||||
moveTopCardTimer->stop();
|
||||
movingCardsUntil = false;
|
||||
QString expr = previousMovingCardsUntilExpr;
|
||||
for (;;) {
|
||||
bool ok;
|
||||
expr = QInputDialog::getText(game, "Put top cards on stack until", "Card name (or search expressions)", {},
|
||||
expr, &ok);
|
||||
if (!ok) {
|
||||
return;
|
||||
}
|
||||
movingCardsUntilFilter = FilterString(expr);
|
||||
if (movingCardsUntilFilter.valid()) {
|
||||
break;
|
||||
} else {
|
||||
auto button = QMessageBox::warning(game, "Invalid filter", movingCardsUntilFilter.error());
|
||||
if (button != QMessageBox::Ok) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
previousMovingCardsUntilExpr = expr;
|
||||
if (zones.value("deck")->getCards().empty()) {
|
||||
movingCardsUntil = false;
|
||||
} else {
|
||||
movingCardsUntil = true;
|
||||
actMoveTopCardToPlay();
|
||||
}
|
||||
}
|
||||
|
||||
void Player::moveOneCardUntil(const CardInfoPtr card)
|
||||
{
|
||||
moveTopCardTimer->stop();
|
||||
if (zones.value("deck")->getCards().empty() || card.isNull() || movingCardsUntilFilter.check(card)) {
|
||||
movingCardsUntil = false;
|
||||
} else {
|
||||
moveTopCardTimer->start();
|
||||
}
|
||||
}
|
||||
|
||||
void Player::actMoveTopCardToBottom()
|
||||
{
|
||||
if (zones.value("deck")->getCards().empty()) {
|
||||
@@ -1621,15 +1525,15 @@ void Player::actUntapAll()
|
||||
|
||||
void Player::actRollDie()
|
||||
{
|
||||
DlgRollDice dlg(game);
|
||||
if (!dlg.exec()) {
|
||||
return;
|
||||
bool ok;
|
||||
int sides = QInputDialog::getInt(game, tr("Roll die"), tr("Number of sides:"), defaultNumberDieRoll, minDieRoll,
|
||||
maxDieRoll, 1, &ok);
|
||||
if (ok) {
|
||||
defaultNumberDieRoll = sides;
|
||||
Command_RollDie cmd;
|
||||
cmd.set_sides(static_cast<google::protobuf::uint32>(sides));
|
||||
sendGameCommand(cmd);
|
||||
}
|
||||
|
||||
Command_RollDie cmd;
|
||||
cmd.set_sides(dlg.getDieSideCount());
|
||||
cmd.set_count(dlg.getDiceToRollCount());
|
||||
sendGameCommand(cmd);
|
||||
}
|
||||
|
||||
void Player::actCreateToken()
|
||||
@@ -1753,7 +1657,7 @@ void Player::actCreateAllRelatedCards()
|
||||
dbName = cardRelationAll->getName();
|
||||
bool persistent = cardRelationAll->getIsPersistent();
|
||||
for (int i = 0; i < cardRelationAll->getDefaultCount(); ++i) {
|
||||
createCard(sourceCard, dbName, CardRelation::DoesNotAttach, persistent);
|
||||
createCard(sourceCard, dbName, false, persistent);
|
||||
}
|
||||
++tokensTypesCreated;
|
||||
if (tokensTypesCreated == 1) {
|
||||
@@ -1768,7 +1672,7 @@ void Player::actCreateAllRelatedCards()
|
||||
dbName = cardRelationNotExcluded->getName();
|
||||
bool persistent = cardRelationNotExcluded->getIsPersistent();
|
||||
for (int i = 0; i < cardRelationNotExcluded->getDefaultCount(); ++i) {
|
||||
createCard(sourceCard, dbName, CardRelation::DoesNotAttach, persistent);
|
||||
createCard(sourceCard, dbName, false, persistent);
|
||||
}
|
||||
++tokensTypesCreated;
|
||||
if (tokensTypesCreated == 1) {
|
||||
@@ -1807,22 +1711,23 @@ bool Player::createRelatedFromRelation(const CardItem *sourceCard, const CardRel
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < count; ++i) {
|
||||
createCard(sourceCard, dbName, CardRelation::DoesNotAttach, persistent);
|
||||
createCard(sourceCard, dbName, false, persistent);
|
||||
}
|
||||
} else if (cardRelation->getDefaultCount() > 1) {
|
||||
for (int i = 0; i < cardRelation->getDefaultCount(); ++i) {
|
||||
createCard(sourceCard, dbName, CardRelation::DoesNotAttach, persistent);
|
||||
createCard(sourceCard, dbName, false, persistent);
|
||||
}
|
||||
} else {
|
||||
createCard(sourceCard, dbName, cardRelation->getAttachType(), persistent);
|
||||
if (cardRelation->getDoesAttach()) {
|
||||
createAttachedCard(sourceCard, dbName, persistent);
|
||||
} else {
|
||||
createCard(sourceCard, dbName, false, persistent);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Player::createCard(const CardItem *sourceCard,
|
||||
const QString &dbCardName,
|
||||
CardRelation::AttachType attachType,
|
||||
bool persistent)
|
||||
void Player::createCard(const CardItem *sourceCard, const QString &dbCardName, bool attach, bool persistent)
|
||||
{
|
||||
CardInfoPtr cardInfo = db->getCard(dbCardName);
|
||||
|
||||
@@ -1861,24 +1766,18 @@ void Player::createCard(const CardItem *sourceCard,
|
||||
cmd.set_x(gridPoint.x());
|
||||
cmd.set_y(gridPoint.y());
|
||||
|
||||
switch (attachType) {
|
||||
case CardRelation::DoesNotAttach:
|
||||
break;
|
||||
|
||||
case CardRelation::AttachTo:
|
||||
cmd.set_target_card_id(sourceCard->getId());
|
||||
cmd.set_target_mode(Command_CreateToken::ATTACH_TO);
|
||||
break;
|
||||
|
||||
case CardRelation::TransformInto:
|
||||
cmd.set_target_card_id(sourceCard->getId());
|
||||
cmd.set_target_mode(Command_CreateToken::TRANSFORM_INTO);
|
||||
break;
|
||||
if (attach) {
|
||||
cmd.set_target_card_id(sourceCard->getId());
|
||||
}
|
||||
|
||||
sendGameCommand(cmd);
|
||||
}
|
||||
|
||||
void Player::createAttachedCard(const CardItem *sourceCard, const QString &dbCardName, bool persistent)
|
||||
{
|
||||
createCard(sourceCard, dbCardName, true, persistent);
|
||||
}
|
||||
|
||||
void Player::actSayMessage()
|
||||
{
|
||||
auto *a = qobject_cast<QAction *>(sender());
|
||||
@@ -1982,21 +1881,7 @@ void Player::eventShuffle(const Event_Shuffle &event)
|
||||
|
||||
void Player::eventRollDie(const Event_RollDie &event)
|
||||
{
|
||||
if (!event.values().empty()) {
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
QList<uint> rolls(event.values().begin(), event.values().end());
|
||||
#else
|
||||
QList<uint> rolls;
|
||||
for (const auto &value : event.values()) {
|
||||
rolls.append(value);
|
||||
}
|
||||
#endif
|
||||
std::sort(rolls.begin(), rolls.end());
|
||||
emit logRollDie(this, static_cast<int>(event.sides()), rolls);
|
||||
} else if (event.value()) {
|
||||
// Backwards compatibility for old clients
|
||||
emit logRollDie(this, static_cast<int>(event.sides()), {event.value()});
|
||||
}
|
||||
emit logRollDie(this, event.sides(), event.value());
|
||||
}
|
||||
|
||||
void Player::eventCreateArrow(const Event_CreateArrow &event)
|
||||
@@ -2131,8 +2016,7 @@ void Player::eventMoveCard(const Event_MoveCard &event, const GameEventContext &
|
||||
if (!startPlayer) {
|
||||
return;
|
||||
}
|
||||
QString startZoneString = QString::fromStdString(event.start_zone());
|
||||
CardZone *startZone = startPlayer->getZones().value(startZoneString, 0);
|
||||
CardZone *startZone = startPlayer->getZones().value(QString::fromStdString(event.start_zone()), 0);
|
||||
Player *targetPlayer = game->getPlayers().value(event.target_player_id());
|
||||
if (!targetPlayer) {
|
||||
return;
|
||||
@@ -2224,10 +2108,6 @@ void Player::eventMoveCard(const Event_MoveCard &event, const GameEventContext &
|
||||
}
|
||||
}
|
||||
updateCardMenu(card);
|
||||
|
||||
if (movingCardsUntil && startZoneString == "deck" && targetZone->getName() == "stack") {
|
||||
moveOneCardUntil(card->getInfo());
|
||||
}
|
||||
}
|
||||
|
||||
void Player::eventFlipCard(const Event_FlipCard &event)
|
||||
@@ -2316,27 +2196,27 @@ void Player::eventAttachCard(const Event_AttachCard &event)
|
||||
|
||||
void Player::eventDrawCards(const Event_DrawCards &event)
|
||||
{
|
||||
CardZone *_deck = zones.value("deck");
|
||||
CardZone *_hand = zones.value("hand");
|
||||
CardZone *deck = zones.value("deck");
|
||||
CardZone *hand = zones.value("hand");
|
||||
|
||||
const int listSize = event.cards_size();
|
||||
if (listSize) {
|
||||
for (int i = 0; i < listSize; ++i) {
|
||||
const ServerInfo_Card &cardInfo = event.cards(i);
|
||||
CardItem *card = _deck->takeCard(0, cardInfo.id());
|
||||
CardItem *card = deck->takeCard(0, cardInfo.id());
|
||||
card->setName(QString::fromStdString(cardInfo.name()));
|
||||
_hand->addCard(card, false, -1);
|
||||
hand->addCard(card, false, -1);
|
||||
}
|
||||
} else {
|
||||
const int number = event.number();
|
||||
for (int i = 0; i < number; ++i) {
|
||||
_hand->addCard(_deck->takeCard(0, -1), false, -1);
|
||||
hand->addCard(deck->takeCard(0, -1), false, -1);
|
||||
}
|
||||
}
|
||||
|
||||
_hand->reorganizeCards();
|
||||
_deck->reorganizeCards();
|
||||
emit logDrawCards(this, event.number(), _deck->getCards().size() == 0);
|
||||
hand->reorganizeCards();
|
||||
deck->reorganizeCards();
|
||||
emit logDrawCards(this, event.number(), deck->getCards().size() == 0);
|
||||
}
|
||||
|
||||
void Player::eventRevealCards(const Event_RevealCards &event)
|
||||
@@ -2377,10 +2257,9 @@ void Player::eventRevealCards(const Event_RevealCards &event)
|
||||
} else {
|
||||
bool showZoneView = true;
|
||||
QString cardName;
|
||||
auto cardId = event.card_id_size() == 0 ? -1 : event.card_id(0);
|
||||
if (cardList.size() == 1) {
|
||||
cardName = QString::fromStdString(cardList.first()->name());
|
||||
if ((cardId == 0) && dynamic_cast<PileZone *>(zone)) {
|
||||
if ((event.card_id() == 0) && dynamic_cast<PileZone *>(zone)) {
|
||||
zone->getCards().first()->setName(cardName);
|
||||
zone->update();
|
||||
showZoneView = false;
|
||||
@@ -2390,9 +2269,8 @@ void Player::eventRevealCards(const Event_RevealCards &event)
|
||||
static_cast<GameScene *>(scene())->addRevealedZoneView(this, zone, cardList, event.grant_write_access());
|
||||
}
|
||||
|
||||
emit logRevealCards(this, zone, cardId, cardName, otherPlayer, false,
|
||||
event.has_number_of_cards() ? event.number_of_cards() : cardList.size(),
|
||||
event.grant_write_access());
|
||||
emit logRevealCards(this, zone, event.card_id(), cardName, otherPlayer, false,
|
||||
event.has_number_of_cards() ? event.number_of_cards() : cardList.size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2602,7 +2480,7 @@ void Player::playCard(CardItem *card, bool faceDown, bool tapped)
|
||||
} else if (!faceDown &&
|
||||
((!playToStack && tableRow == 3) || ((playToStack && tableRow != 0) && currentZone != "stack"))) {
|
||||
cmd.set_target_zone("stack");
|
||||
cmd.set_x(-1);
|
||||
cmd.set_x(0);
|
||||
cmd.set_y(0);
|
||||
} else {
|
||||
tableRow = faceDown ? 2 : info->getTableRow();
|
||||
@@ -2948,7 +2826,7 @@ void Player::cardMenuAction()
|
||||
case cmPeek: {
|
||||
auto *cmd = new Command_RevealCards;
|
||||
cmd->set_zone_name(card->getZone()->getName().toStdString());
|
||||
cmd->add_card_id(card->getId());
|
||||
cmd->set_card_id(card->getId());
|
||||
cmd->set_player_id(id);
|
||||
commandList.append(cmd);
|
||||
break;
|
||||
@@ -2988,16 +2866,6 @@ void Player::cardMenuAction()
|
||||
cmd->set_target_zone("deck");
|
||||
cmd->set_x(0);
|
||||
cmd->set_y(0);
|
||||
|
||||
if (idList.card_size() > 1) {
|
||||
auto *scmd = new Command_Shuffle;
|
||||
scmd->set_zone_name("deck");
|
||||
scmd->set_start(0);
|
||||
scmd->set_end(idList.card_size());
|
||||
// Server process events backwards, so...
|
||||
commandList.append(scmd);
|
||||
}
|
||||
|
||||
commandList.append(cmd);
|
||||
break;
|
||||
}
|
||||
@@ -3202,16 +3070,16 @@ void Player::actSetPT()
|
||||
if (!empty) {
|
||||
const auto oldpt = parsePT(card->getPT());
|
||||
int ptIter = 0;
|
||||
for (const auto &_item : ptList) {
|
||||
for (const auto &item : ptList) {
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
if (_item.typeId() == QMetaType::Type::Int) {
|
||||
if (item.typeId() == QMetaType::Type::Int) {
|
||||
#else
|
||||
if (_item.type() == QVariant::Int) {
|
||||
if (item.type() == QVariant::Int) {
|
||||
#endif
|
||||
int oldItem = ptIter < oldpt.size() ? oldpt.at(ptIter).toInt() : 0;
|
||||
newpt += '/' + QString::number(oldItem + _item.toInt());
|
||||
newpt += '/' + QString::number(oldItem + item.toInt());
|
||||
} else {
|
||||
newpt += '/' + _item.toString();
|
||||
newpt += '/' + item.toString();
|
||||
}
|
||||
++ptIter;
|
||||
}
|
||||
@@ -3281,16 +3149,6 @@ void Player::actFlowT()
|
||||
actIncPT(-1, 1);
|
||||
}
|
||||
|
||||
void AnnotationDialog::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
if (event->key() == Qt::Key_Return && event->modifiers() & Qt::ControlModifier) {
|
||||
event->accept();
|
||||
accept();
|
||||
return;
|
||||
}
|
||||
QInputDialog::keyPressEvent(event);
|
||||
}
|
||||
|
||||
void Player::actSetAnnotation()
|
||||
{
|
||||
QString oldAnnotation;
|
||||
@@ -3302,18 +3160,15 @@ void Player::actSetAnnotation()
|
||||
}
|
||||
}
|
||||
|
||||
bool ok;
|
||||
dialogSemaphore = true;
|
||||
AnnotationDialog *dialog = new AnnotationDialog(game);
|
||||
dialog->setOptions(QInputDialog::UsePlainTextEditForTextInput);
|
||||
dialog->setWindowTitle(tr("Set annotation"));
|
||||
dialog->setLabelText(tr("Please enter the new annotation:"));
|
||||
dialog->setTextValue(oldAnnotation);
|
||||
bool ok = dialog->exec();
|
||||
QString annotation = QInputDialog::getMultiLineText(game, tr("Set annotation"),
|
||||
tr("Please enter the new annotation:"), oldAnnotation, &ok)
|
||||
.left(MAX_NAME_LENGTH);
|
||||
dialogSemaphore = false;
|
||||
if (clearCardsToDelete() || !ok) {
|
||||
return;
|
||||
}
|
||||
QString annotation = dialog->textValue().left(MAX_NAME_LENGTH);
|
||||
|
||||
QList<const ::google::protobuf::Message *> commandList;
|
||||
for (const auto &item : sel) {
|
||||
@@ -3449,27 +3304,6 @@ void Player::actPlayFacedown()
|
||||
playCard(game->getActiveCard(), true, false);
|
||||
}
|
||||
|
||||
void Player::actReveal(QAction *action)
|
||||
{
|
||||
const int otherPlayerId = action->data().toInt();
|
||||
|
||||
Command_RevealCards cmd;
|
||||
if (otherPlayerId != -1) {
|
||||
cmd.set_player_id(otherPlayerId);
|
||||
}
|
||||
|
||||
QList<QGraphicsItem *> sel = scene()->selectedItems();
|
||||
while (!sel.isEmpty()) {
|
||||
const auto *card = qgraphicsitem_cast<CardItem *>(sel.takeFirst());
|
||||
if (!cmd.has_zone_name()) {
|
||||
cmd.set_zone_name(card->getZone()->getName().toStdString());
|
||||
}
|
||||
cmd.add_card_id(card->getId());
|
||||
}
|
||||
|
||||
sendGameCommand(cmd);
|
||||
}
|
||||
|
||||
void Player::refreshShortcuts()
|
||||
{
|
||||
if (shortcutsActive) {
|
||||
@@ -3595,11 +3429,6 @@ void Player::updateCardMenu(const CardItem *card)
|
||||
// Card is in hand or a custom zone specified by server
|
||||
cardMenu->addAction(aPlay);
|
||||
cardMenu->addAction(aPlayFacedown);
|
||||
|
||||
QMenu *revealMenu = cardMenu->addMenu(tr("Re&veal to..."));
|
||||
initContextualPlayersMenu(revealMenu);
|
||||
connect(revealMenu, &QMenu::triggered, this, &Player::actReveal);
|
||||
|
||||
cardMenu->addMenu(moveMenu);
|
||||
addRelatedCardView(card, cardMenu);
|
||||
}
|
||||
@@ -3674,7 +3503,6 @@ void Player::addRelatedCardActions(const CardItem *card, QMenu *cardMenu)
|
||||
CardInfoPtr relatedCard = db->getCard(cardRelation->getName());
|
||||
if (relatedCard == nullptr)
|
||||
continue;
|
||||
|
||||
QString relatedCardName;
|
||||
if (relatedCard->getPowTough().size() > 0) {
|
||||
relatedCardName = relatedCard->getPowTough() + " " + relatedCard->getName(); // "n/n name"
|
||||
@@ -3684,8 +3512,7 @@ void Player::addRelatedCardActions(const CardItem *card, QMenu *cardMenu)
|
||||
|
||||
QString text = tr("Token: ");
|
||||
if (cardRelation->getDoesAttach()) {
|
||||
text +=
|
||||
tr(cardRelation->getDoesTransform() ? "Transform into " : "Attach to ") + "\"" + relatedCardName + "\"";
|
||||
text += tr("Attach to ") + "\"" + relatedCardName + "\"";
|
||||
} else if (cardRelation->getIsVariable()) {
|
||||
text += "X " + relatedCardName;
|
||||
} else if (cardRelation->getDefaultCount() != 1) {
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
#include "abstractgraphicsitem.h"
|
||||
#include "carddatabase.h"
|
||||
#include "filter_string.h"
|
||||
#include "pb/card_attributes.pb.h"
|
||||
#include "pb/game_event.pb.h"
|
||||
#include "tearoffmenu.h"
|
||||
@@ -11,7 +10,6 @@
|
||||
#include <QInputDialog>
|
||||
#include <QMap>
|
||||
#include <QPoint>
|
||||
#include <QTimer>
|
||||
|
||||
namespace google
|
||||
{
|
||||
@@ -114,7 +112,7 @@ signals:
|
||||
// Log events
|
||||
void logSay(Player *player, QString message);
|
||||
void logShuffle(Player *player, CardZone *zone, int start, int end);
|
||||
void logRollDie(Player *player, int sides, const QList<uint> &rolls);
|
||||
void logRollDie(Player *player, int sides, int roll);
|
||||
void logCreateArrow(Player *player,
|
||||
Player *startPlayer,
|
||||
QString startCard,
|
||||
@@ -142,8 +140,7 @@ signals:
|
||||
QString cardName,
|
||||
Player *otherPlayer,
|
||||
bool faceDown,
|
||||
int amount,
|
||||
bool isLentToAnotherPlayer = false);
|
||||
int amount);
|
||||
void logAlwaysRevealTopCard(Player *player, CardZone *zone, bool reveal);
|
||||
void logAlwaysLookAtTopCard(Player *player, CardZone *zone, bool reveal);
|
||||
|
||||
@@ -165,7 +162,6 @@ public slots:
|
||||
void actMoveTopCardToExile();
|
||||
void actMoveTopCardsToGrave();
|
||||
void actMoveTopCardsToExile();
|
||||
void actMoveTopCardsUntil();
|
||||
void actMoveTopCardToBottom();
|
||||
void actDrawBottomCard();
|
||||
void actDrawBottomCards();
|
||||
@@ -221,29 +217,26 @@ private slots:
|
||||
void actPlay();
|
||||
void actHide();
|
||||
void actPlayFacedown();
|
||||
void actReveal(QAction *action);
|
||||
void refreshShortcuts();
|
||||
|
||||
private:
|
||||
TabGame *game;
|
||||
QMenu *sbMenu, *countersMenu, *sayMenu, *createPredefinedTokenMenu, *mRevealLibrary, *mLendLibrary, *mRevealTopCard,
|
||||
*mRevealHand, *mRevealRandomHandCard, *mRevealRandomGraveyardCard;
|
||||
QMenu *sbMenu, *countersMenu, *sayMenu, *createPredefinedTokenMenu, *mRevealLibrary, *mRevealTopCard, *mRevealHand,
|
||||
*mRevealRandomHandCard, *mRevealRandomGraveyardCard;
|
||||
TearOffMenu *moveGraveMenu, *moveRfgMenu, *graveMenu, *moveHandMenu, *handMenu, *libraryMenu, *topLibraryMenu,
|
||||
*bottomLibraryMenu, *rfgMenu, *playerMenu;
|
||||
QList<QMenu *> playerLists;
|
||||
QList<QMenu *> singlePlayerLists;
|
||||
QList<QAction *> allPlayersActions;
|
||||
QList<QPair<QString, int>> playersInfo;
|
||||
QAction *aMoveHandToTopLibrary, *aMoveHandToBottomLibrary, *aMoveHandToGrave, *aMoveHandToRfg,
|
||||
*aMoveGraveToTopLibrary, *aMoveGraveToBottomLibrary, *aMoveGraveToHand, *aMoveGraveToRfg, *aMoveRfgToTopLibrary,
|
||||
*aMoveRfgToBottomLibrary, *aMoveRfgToHand, *aMoveRfgToGrave, *aViewHand, *aViewLibrary, *aViewTopCards,
|
||||
*aAlwaysRevealTopCard, *aAlwaysLookAtTopCard, *aOpenDeckInDeckEditor, *aMoveTopCardToGraveyard,
|
||||
*aMoveTopCardToExile, *aMoveTopCardsToGraveyard, *aMoveTopCardsToExile, *aMoveTopCardsUntil,
|
||||
*aMoveTopCardToBottom, *aViewGraveyard, *aViewRfg, *aViewSideboard, *aDrawCard, *aDrawCards, *aUndoDraw,
|
||||
*aMulligan, *aShuffle, *aMoveTopToPlay, *aMoveTopToPlayFaceDown, *aUntapAll, *aRollDie, *aCreateToken,
|
||||
*aCreateAnotherToken, *aCardMenu, *aMoveBottomToPlay, *aMoveBottomToPlayFaceDown, *aMoveBottomCardToTop,
|
||||
*aMoveBottomCardToGraveyard, *aMoveBottomCardToExile, *aMoveBottomCardsToGraveyard, *aMoveBottomCardsToExile,
|
||||
*aDrawBottomCard, *aDrawBottomCards;
|
||||
*aMoveTopCardToExile, *aMoveTopCardsToGraveyard, *aMoveTopCardsToExile, *aMoveTopCardToBottom, *aViewGraveyard,
|
||||
*aViewRfg, *aViewSideboard, *aDrawCard, *aDrawCards, *aUndoDraw, *aMulligan, *aShuffle, *aMoveTopToPlay,
|
||||
*aMoveTopToPlayFaceDown, *aUntapAll, *aRollDie, *aCreateToken, *aCreateAnotherToken, *aCardMenu,
|
||||
*aMoveBottomToPlay, *aMoveBottomToPlayFaceDown, *aMoveBottomCardToTop, *aMoveBottomCardToGraveyard,
|
||||
*aMoveBottomCardToExile, *aMoveBottomCardsToGraveyard, *aMoveBottomCardsToExile, *aDrawBottomCard,
|
||||
*aDrawBottomCards;
|
||||
|
||||
QList<QAction *> aAddCounter, aSetCounter, aRemoveCounter;
|
||||
QAction *aPlay, *aPlayFacedown, *aHide, *aTap, *aDoesntUntap, *aAttach, *aUnattach, *aDrawArrow, *aSetPT, *aResetPT,
|
||||
@@ -251,16 +244,13 @@ private:
|
||||
*aMoveToTopLibrary, *aMoveToBottomLibrary, *aMoveToHand, *aMoveToGraveyard, *aMoveToExile,
|
||||
*aMoveToXfromTopOfLibrary;
|
||||
|
||||
bool movingCardsUntil;
|
||||
QTimer *moveTopCardTimer;
|
||||
QString previousMovingCardsUntilExpr = {};
|
||||
FilterString movingCardsUntilFilter;
|
||||
|
||||
bool shortcutsActive;
|
||||
int defaultNumberTopCards = 1;
|
||||
int defaultNumberTopCardsToPlaceBelow = 1;
|
||||
int defaultNumberBottomCards = 1;
|
||||
int defaultNumberDieRoll = 20;
|
||||
static constexpr int minDieRoll = 2;
|
||||
static constexpr int maxDieRoll = 1000000;
|
||||
QString lastTokenName, lastTokenColor, lastTokenPT, lastTokenAnnotation;
|
||||
bool lastTokenDestroy;
|
||||
int lastTokenTableRow;
|
||||
@@ -295,14 +285,10 @@ private:
|
||||
bool allCards);
|
||||
void addRelatedCardActions(const CardItem *card, QMenu *cardMenu);
|
||||
void addRelatedCardView(const CardItem *card, QMenu *cardMenu);
|
||||
void createCard(const CardItem *sourceCard,
|
||||
const QString &dbCardName,
|
||||
CardRelation::AttachType attach = CardRelation::DoesNotAttach,
|
||||
bool persistent = false);
|
||||
void
|
||||
createCard(const CardItem *sourceCard, const QString &dbCardName, bool attach = false, bool persistent = false);
|
||||
void createAttachedCard(const CardItem *sourceCard, const QString &dbCardName, bool persistent = false);
|
||||
bool createRelatedFromRelation(const CardItem *sourceCard, const CardRelation *cardRelation);
|
||||
void moveOneCardUntil(const CardInfoPtr card);
|
||||
void addPlayerToList(QMenu *playerList, Player *player);
|
||||
static void removePlayerFromList(QMenu *playerList, Player *player);
|
||||
|
||||
QRectF bRect;
|
||||
|
||||
@@ -311,7 +297,6 @@ private:
|
||||
void rearrangeCounters();
|
||||
|
||||
void initSayMenu();
|
||||
void initContextualPlayersMenu(QMenu *menu);
|
||||
|
||||
// void eventConnectionStateChanged(const Event_ConnectionStateChanged &event);
|
||||
void eventGameSay(const Event_GameSay &event);
|
||||
@@ -479,15 +464,4 @@ public:
|
||||
void setLastToken(CardInfoPtr cardInfo);
|
||||
};
|
||||
|
||||
class AnnotationDialog : public QInputDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
void keyPressEvent(QKeyEvent *e) override;
|
||||
|
||||
public:
|
||||
AnnotationDialog(QWidget *parent) : QInputDialog(parent)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -42,7 +42,7 @@ void ReleaseChannel::checkForUpdates()
|
||||
}
|
||||
|
||||
// Different release channel checking functions for different operating systems
|
||||
#if defined(Q_OS_MACOS)
|
||||
#if defined(Q_OS_OSX)
|
||||
bool ReleaseChannel::downloadMatchesCurrentOS(const QString &fileName)
|
||||
{
|
||||
static QRegularExpression version_regex("macOS-(\\d+)\\.(\\d+)");
|
||||
|
||||
@@ -32,7 +32,6 @@ RemoteClient::RemoteClient(QObject *parent)
|
||||
{
|
||||
|
||||
clearNewClientFeatures();
|
||||
maxTimeout = SettingsCache::instance().getTimeOut();
|
||||
int keepalive = SettingsCache::instance().getKeepAlive();
|
||||
timer = new QTimer(this);
|
||||
timer->setInterval(keepalive * 1000);
|
||||
|
||||
@@ -89,7 +89,7 @@ private slots:
|
||||
void submitForgotPasswordChallengeResponse(const Response &response);
|
||||
|
||||
private:
|
||||
int maxTimeout;
|
||||
static const int maxTimeout = 5;
|
||||
int timeRunning, lastDataReceived;
|
||||
QByteArray inputBuffer;
|
||||
bool messageInProgress;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user