Compare commits
1 Commits
tooomm_dox
...
make_loggi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
48cc5e3c85 |
@@ -7,7 +7,6 @@ RUN pacman --sync --refresh --sysupgrade --needed --noconfirm \
|
||||
git \
|
||||
gtest \
|
||||
mariadb-libs \
|
||||
ninja \
|
||||
protobuf \
|
||||
qt6-base \
|
||||
qt6-imageformats \
|
||||
|
||||
@@ -16,7 +16,6 @@ RUN apt-get update && \
|
||||
libqt5sql5-mysql \
|
||||
libqt5svg5-dev \
|
||||
libqt5websockets5-dev \
|
||||
ninja-build \
|
||||
protobuf-compiler \
|
||||
qt5-image-formats-plugins \
|
||||
qtmultimedia5-dev \
|
||||
|
||||
@@ -15,14 +15,13 @@ RUN apt-get update && \
|
||||
libprotobuf-dev \
|
||||
libqt6multimedia6 \
|
||||
libqt6sql6-mysql \
|
||||
ninja-build \
|
||||
qt6-svg-dev \
|
||||
qt6-websockets-dev \
|
||||
protobuf-compiler \
|
||||
qt6-image-formats-plugins \
|
||||
qt6-l10n-tools \
|
||||
qt6-multimedia-dev \
|
||||
qt6-svg-dev \
|
||||
qt6-tools-dev \
|
||||
qt6-tools-dev-tools \
|
||||
qt6-websockets-dev \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM fedora:42
|
||||
FROM fedora:40
|
||||
|
||||
RUN dnf install -y \
|
||||
ccache \
|
||||
@@ -6,7 +6,6 @@ RUN dnf install -y \
|
||||
gcc-c++ \
|
||||
git \
|
||||
mariadb-devel \
|
||||
ninja-build \
|
||||
protobuf-devel \
|
||||
qt6-{qttools,qtsvg,qtmultimedia,qtwebsockets}-devel \
|
||||
qt6-qtimageformats \
|
||||
@@ -6,7 +6,6 @@ RUN dnf install -y \
|
||||
gcc-c++ \
|
||||
git \
|
||||
mariadb-devel \
|
||||
ninja-build \
|
||||
protobuf-devel \
|
||||
qt6-{qttools,qtsvg,qtmultimedia,qtwebsockets}-devel \
|
||||
qt6-qtimageformats \
|
||||
|
||||
@@ -1,29 +1,26 @@
|
||||
FROM debian:13
|
||||
FROM ubuntu:20.04
|
||||
|
||||
RUN apt-get update && \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||
build-essential \
|
||||
ca-certificates \
|
||||
ccache \
|
||||
clang-format \
|
||||
cmake \
|
||||
file \
|
||||
g++ \
|
||||
git \
|
||||
libgl-dev \
|
||||
liblzma-dev \
|
||||
libmariadb-dev-compat \
|
||||
libprotobuf-dev \
|
||||
libqt6multimedia6 \
|
||||
libqt6sql6-mysql \
|
||||
ninja-build \
|
||||
libqt5multimedia5-plugins \
|
||||
libqt5sql5-mysql \
|
||||
libqt5svg5-dev \
|
||||
libqt5websockets5-dev \
|
||||
protobuf-compiler \
|
||||
qt6-image-formats-plugins \
|
||||
qt6-l10n-tools \
|
||||
qt6-multimedia-dev \
|
||||
qt6-svg-dev \
|
||||
qt6-tools-dev \
|
||||
qt6-tools-dev-tools \
|
||||
qt6-websockets-dev \
|
||||
qt5-default \
|
||||
qt5-image-formats-plugins \
|
||||
qtmultimedia5-dev \
|
||||
qttools5-dev \
|
||||
qttools5-dev-tools \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
@@ -17,7 +17,6 @@ RUN apt-get update && \
|
||||
libqt6sql6-mysql \
|
||||
libqt6svg6-dev \
|
||||
libqt6websockets6-dev \
|
||||
ninja-build \
|
||||
protobuf-compiler \
|
||||
qt6-image-formats-plugins \
|
||||
qt6-l10n-tools \
|
||||
|
||||
@@ -15,14 +15,13 @@ RUN apt-get update && \
|
||||
libprotobuf-dev \
|
||||
libqt6multimedia6 \
|
||||
libqt6sql6-mysql \
|
||||
ninja-build \
|
||||
qt6-svg-dev \
|
||||
qt6-websockets-dev \
|
||||
protobuf-compiler \
|
||||
qt6-image-formats-plugins \
|
||||
qt6-l10n-tools \
|
||||
qt6-multimedia-dev \
|
||||
qt6-svg-dev \
|
||||
qt6-tools-dev \
|
||||
qt6-tools-dev-tools \
|
||||
qt6-websockets-dev \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
@@ -11,8 +11,9 @@
|
||||
# --debug or --release sets the build type ie CMAKE_BUILD_TYPE
|
||||
# --ccache [<size>] uses ccache and shows stats, optionally provide size
|
||||
# --dir <dir> sets the name of the build dir, default is "build"
|
||||
# uses env: BUILDTYPE MAKE_INSTALL MAKE_PACKAGE PACKAGE_TYPE PACKAGE_SUFFIX MAKE_SERVER MAKE_TEST USE_CCACHE CCACHE_SIZE BUILD_DIR CMAKE_GENERATOR
|
||||
# (correspond to args: --debug/--release --install --package <package type> --suffix <suffix> --server --test --ccache <ccache_size> --dir <dir>)
|
||||
# --parallel <core count> sets how many cores cmake should build with in parallel
|
||||
# uses env: BUILDTYPE MAKE_INSTALL MAKE_PACKAGE PACKAGE_TYPE PACKAGE_SUFFIX MAKE_SERVER MAKE_TEST USE_CCACHE CCACHE_SIZE BUILD_DIR PARALLEL_COUNT
|
||||
# (correspond to args: --debug/--release --install --package <package type> --suffix <suffix> --server --test --ccache <ccache_size> --dir <dir> --parallel <core_count>)
|
||||
# exitcode: 1 for failure, 3 for invalid arguments
|
||||
|
||||
# Read arguments
|
||||
@@ -75,6 +76,15 @@ while [[ $# != 0 ]]; do
|
||||
BUILD_DIR="$1"
|
||||
shift
|
||||
;;
|
||||
'--parallel')
|
||||
shift
|
||||
if [[ $# == 0 ]]; then
|
||||
echo "::error file=$0::--parallel expects an argument"
|
||||
exit 3
|
||||
fi
|
||||
PARALLEL_COUNT="$1"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
echo "::error file=$0::unrecognized option: $1"
|
||||
exit 3
|
||||
@@ -95,9 +105,6 @@ fi
|
||||
mkdir -p "$BUILD_DIR"
|
||||
cd "$BUILD_DIR"
|
||||
|
||||
# Set minimum CMake Version
|
||||
export CMAKE_POLICY_VERSION_MINIMUM=3.10
|
||||
|
||||
# Add cmake flags
|
||||
flags=("-DCMAKE_BUILD_TYPE=$BUILDTYPE")
|
||||
if [[ $MAKE_SERVER ]]; then
|
||||
@@ -119,6 +126,16 @@ 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
|
||||
# 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")
|
||||
# note, no normal build flags should be added after this
|
||||
else
|
||||
buildflags+=(--parallel "$PARALLEL_COUNT")
|
||||
fi
|
||||
fi
|
||||
|
||||
function ccachestatsverbose() {
|
||||
# note, verbose only works on newer ccache, discard the error
|
||||
@@ -131,23 +148,6 @@ function ccachestatsverbose() {
|
||||
}
|
||||
|
||||
# Compile
|
||||
if [[ $RUNNER_OS == macOS ]]; then
|
||||
echo "::group::Signing Certificate"
|
||||
if [[ -n "$MACOS_CERTIFICATE_NAME" ]]; then
|
||||
echo $MACOS_CERTIFICATE | base64 --decode > certificate.p12
|
||||
security create-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain
|
||||
security default-keychain -s build.keychain
|
||||
security set-keychain-settings -t 3600 -l build.keychain
|
||||
security unlock-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain
|
||||
security import certificate.p12 -k build.keychain -P "$MACOS_CERTIFICATE_PWD" -T /usr/bin/codesign
|
||||
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$MACOS_CI_KEYCHAIN_PWD" build.keychain
|
||||
echo "macOS signing certificate successfully imported and keychain configured."
|
||||
else
|
||||
echo "No signing certificate configured. Skipping set up of keychain in macOS environment."
|
||||
fi
|
||||
echo "::endgroup::"
|
||||
fi
|
||||
|
||||
if [[ $USE_CCACHE ]]; then
|
||||
echo "::group::Show ccache stats"
|
||||
ccachestatsverbose
|
||||
|
||||
@@ -148,9 +148,6 @@ function RUN ()
|
||||
args+=(--mount "type=bind,source=$CCACHE_DIR,target=/.ccache")
|
||||
args+=(--env "CCACHE_DIR=/.ccache")
|
||||
fi
|
||||
if [[ -n "$CMAKE_GENERATOR" ]]; then
|
||||
args+=(--env "CMAKE_GENERATOR=$CMAKE_GENERATOR")
|
||||
fi
|
||||
docker run "${args[@]}" $RUN_ARGS "$IMAGE_NAME" bash "$BUILD_SCRIPT" $RUN_OPTS "$@"
|
||||
return $?
|
||||
else
|
||||
|
||||
@@ -4,30 +4,24 @@
|
||||
git push -d origin --REPLACE-WITH-BETA-LIST--
|
||||
-->
|
||||
|
||||
<!-- This list of binaries should be updated every time the CI is changed to include all targets -->
|
||||
<!-- This list of binaries should be updated every time the CI is changed to
|
||||
include different targets -->
|
||||
<pre>
|
||||
Available pre-compiled binaries for installation:
|
||||
|
||||
<b>Windows</b>
|
||||
• <kbd>Windows 10+</kbd>
|
||||
• <kbd>Windows 7+</kbd>
|
||||
|
||||
<b>macOS</b>
|
||||
• <kbd>macOS 15+</kbd> <sub><i>Sequoia</i></sub> <sub>Apple M</sub>
|
||||
• <kbd>macOS 14+</kbd> <sub><i>Sonoma</i></sub> <sub>Apple M</sub>
|
||||
• <kbd>macOS 13+</kbd> <sub><i>Ventura</i></sub> <sub>Intel</sub>
|
||||
|
||||
<b>Linux</b>
|
||||
• <kbd>Ubuntu 24.04 LTS</kbd> <sub><i>Noble Numbat</i></sub>
|
||||
• <kbd>Ubuntu 22.04 LTS</kbd> <sub><i>Jammy Jellyfish</i></sub>
|
||||
• <kbd>Debian 13</kbd> <sub><i>Trixie</i></sub>
|
||||
• <kbd>Debian 12</kbd> <sub><i>Bookworm</i></sub>
|
||||
• <kbd>Debian 11</kbd> <sub><i>Bullseye</i></sub>
|
||||
• <kbd>Fedora 42</kbd>
|
||||
• <kbd>Fedora 41</kbd>
|
||||
|
||||
<sub>We are also packaged in <kbd>Arch Linux</kbd>'s <a href="https://archlinux.org/packages/extra/x86_64/cockatrice">official extra repository</a>, courtesy of @FFY00.</sub>
|
||||
<sub>General Linux support is available via a <kbd>flatpak</kbd> package at <a href="https://flathub.org/apps/io.github.Cockatrice.cockatrice">Flathub</a>!</sub>
|
||||
<b>Pre-compiled binaries we serve:</b>
|
||||
- <kbd>Windows 10+</kbd>
|
||||
- <kbd>Windows 7+</kbd>
|
||||
- <kbd>macOS 14+</kbd> ("Sonoma") / Apple M
|
||||
- <kbd>macOS 13+</kbd> ("Ventura") / Intel
|
||||
- <kbd>Ubuntu 24.04 LTS</kbd> ("Noble Numbat")
|
||||
- <kbd>Ubuntu 22.04 LTS</kbd> ("Jammy Jellyfish")
|
||||
- <kbd>Ubuntu 20.04 LTS</kbd> ("Focal Fossa")
|
||||
- <kbd>Debian 12</kbd> ("Bookworm")
|
||||
- <kbd>Debian 11</kbd> ("Bullseye")
|
||||
- <kbd>Fedora 41</kbd>
|
||||
- <kbd>Fedora 40</kbd>
|
||||
|
||||
<i>We are also packaged in <kbd>Arch Linux</kbd>'s official "extra" repository, courtesy of @FFY00</i>
|
||||
<i>General Linux support is available via a <kbd>flatpak</kbd> package (Flathub)</i>
|
||||
</pre>
|
||||
|
||||
|
||||
@@ -41,7 +35,7 @@ If you ever encounter a bug, have a suggestion or idea, or feel a need for a dev
|
||||
|
||||
For basic information related to the app and getting started, please take a look at our official site: **https://cockatrice.github.io**
|
||||
|
||||
If you'd like to help and contribute to Cockatrice in any way, check out our [README](https://github.com/Cockatrice/Cockatrice#contribute).
|
||||
If you'd like to help and contribute to Cockatrice in any way, check out our [README](https://github.com/Cockatrice/Cockatrice#get-involved-).
|
||||
We're always available to answer questions you may have on how the program works and how you can provide a meaningful contribution.
|
||||
|
||||
|
||||
|
||||
@@ -10,5 +10,5 @@ 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://explore.transifex.com/cockatrice/cockatrice/
|
||||
[1]: https://app.transifex.com/cockatrice/cockatrice/
|
||||
[2]: https://github.com/Cockatrice/Cockatrice/actions/workflows/translations-push.yml?query=branch%3Amaster
|
||||
|
||||
155
.github/CONTRIBUTING.md
vendored
@@ -1,5 +1,3 @@
|
||||
@page contributing Contributing
|
||||
|
||||
[Introduction](#contributing-to-cockatrice) | [Code Style Guide](
|
||||
#code-style-guide) | [Translations](#translations) | [Release Management](
|
||||
#release-management)
|
||||
@@ -9,33 +7,32 @@
|
||||
<br>
|
||||
|
||||
# Contributing to Cockatrice #
|
||||
First off, thanks for taking the time to contribute to our project! 🎉 ❤ ️✨
|
||||
|
||||
First off, thanks for taking the time and considering to lend a helping hand to our project! 🎉 ❤ ️✨
|
||||
|
||||
> [!NOTE]
|
||||
> The following is a set of guidelines for contributing to Cockatrice.
|
||||
> These are mostly guidelines, not rules. Use your best judgment, and feel free to
|
||||
> propose changes to this document in a pull request.
|
||||
>
|
||||
> [](
|
||||
> https://discord.gg/3Z9yzmA)
|
||||
> If you'd like to ask questions, get advice, or just want to say "Hi",
|
||||
> the Cockatrice Development Team uses [Discord](https://discord.gg/ZASRzKu)
|
||||
> for communications and you can reach out in the `#dev` channel.
|
||||
The following is a set of guidelines for contributing to Cockatrice. These are
|
||||
mostly guidelines, not rules. Use your best judgment, and feel free to propose
|
||||
changes to this document in a pull request.
|
||||
|
||||
|
||||
# Recommended Setups #
|
||||
|
||||
For those developers on **Linux** or **macOS** environment, many of our
|
||||
For those developers who like the Linux or MacOS environment, many of our
|
||||
developers like working with a nifty program called [CLion](
|
||||
https://www.jetbrains.com/clion/). The program is a great asset and one of the
|
||||
best tools you'll find on these systems.
|
||||
https://www.jetbrains.com/clion/). The program's a great asset and one of the
|
||||
best tools you'll find on these systems, but you're welcomed to use any IDE
|
||||
you most enjoy.
|
||||
|
||||
Developers on **Windows** systems tend to find [Visual Studio](
|
||||
Developers who like Windows development tend to find [Visual Studio](
|
||||
https://www.visualstudio.com/) the best tool for the job.
|
||||
|
||||
But you're welcomed to use any IDE you enjoy most of course!
|
||||
[](https://discord.gg/ZASRzKu)
|
||||
[](https://gitter.im/Cockatrice/Cockatrice)
|
||||
|
||||
If you'd like to ask questions, get advice, or just want to say hi,
|
||||
the Cockatrice Development Team uses [Discord](https://discord.gg/ZASRzKu)
|
||||
for communications in the #dev channel. If you're not into Discord, we also
|
||||
have a [Gitter](https://gitter.im/Cockatrice/Cockatrice) channel available,
|
||||
albeit slightly less active.
|
||||
|
||||
|
||||
# Code Style Guide #
|
||||
@@ -57,7 +54,7 @@ The message will look like this:
|
||||
*** Then commit and push those changes to this branch. ***
|
||||
*** Check our CONTRIBUTING.md file for more details. ***
|
||||
*** ***
|
||||
*** Thank you ❤️ ***
|
||||
*** Thank you ❤️ ***
|
||||
*** ***
|
||||
***********************************************************
|
||||
```
|
||||
@@ -67,7 +64,7 @@ information on our formatting guidelines.
|
||||
|
||||
### Compatibility ###
|
||||
|
||||
Cockatrice is currently compiled on all platforms using <kbd>C++20</kbd>.
|
||||
Cockatrice is currently compiled on all platforms using <kbd>C++11</kbd>.
|
||||
You'll notice <kbd>C++03</kbd> code throughout the codebase. Please feel free
|
||||
to help convert it over!
|
||||
|
||||
@@ -81,12 +78,11 @@ or other appropriate conversion.
|
||||
### Formatting ###
|
||||
|
||||
The handy tool `clang-format` can format your code for you, it is available for
|
||||
almost any environment. A special [`.clang-format`](
|
||||
https://github.com/Cockatrice/Cockatrice/blob/master/.clang-format) configuration file is
|
||||
almost any environment. A special `.clang-format` configuration file is
|
||||
included in the project and is used to format your code.
|
||||
|
||||
We've also included a bash script, `format.sh`, that will use clang-format to
|
||||
format all files in your PR in one go. Use `./format.sh --help` to show a full
|
||||
format all files in your pr in one go. Use `./format.sh --help` to show a full
|
||||
help page.
|
||||
|
||||
To run clang-format on a single source file simply use the command
|
||||
@@ -94,10 +90,10 @@ To run clang-format on a single source file simply use the command
|
||||
clang-format with a specific version number appended,
|
||||
`find /usr/bin -name clang-format*` should find it for you)
|
||||
|
||||
See the [clang-format documentation](
|
||||
See [the clang-format documentation](
|
||||
https://clang.llvm.org/docs/ClangFormat.html) for more information about the tool.
|
||||
|
||||
#### Header Files ####
|
||||
#### Header files ####
|
||||
|
||||
Use header files with the extension `.h` and source files with the extension
|
||||
`.cpp`.
|
||||
@@ -172,10 +168,10 @@ braces around single line statements is preferred.
|
||||
See the following example:
|
||||
```c++
|
||||
int main()
|
||||
{ // function or class: own line
|
||||
if (someCondition) { // control statement: same line
|
||||
doSomething(); // single line statement, braces preferred
|
||||
} else if (someOtherCondition1) { // else goes on the same line as a closing brace
|
||||
{ // function or class: own line
|
||||
if (someCondition) { // control statement: same line
|
||||
doSomething(); // single line statement, braces preferred
|
||||
} else if (someOtherCondition1) { // else goes on the same line as a closing brace
|
||||
for (int i = 0; i < 100; i++) {
|
||||
doSomethingElse();
|
||||
}
|
||||
@@ -238,7 +234,7 @@ mutating objects.)
|
||||
When pointers can't be avoided, try to use a smart pointer of some sort, such
|
||||
as `QScopedPointer`, or, less preferably, `QSharedPointer`.
|
||||
|
||||
### Database Migrations ###
|
||||
### Database migrations ###
|
||||
|
||||
The servatrice database's schema can be found at `servatrice/servatrice.sql`.
|
||||
Everytime the schema gets modified, some other steps are due:
|
||||
@@ -259,7 +255,7 @@ Ensure that the migration produces the expected effects; e.g. if you add a
|
||||
new column, make sure the migration places it in the same order as
|
||||
servatrice.sql.
|
||||
|
||||
### Protocol Buffer ###
|
||||
### Protocol buffer ###
|
||||
|
||||
Cockatrice and Servatrice exchange data using binary messages. The syntax of
|
||||
these messages is defined in the `proto` files in the `common/pb` folder. These
|
||||
@@ -272,7 +268,6 @@ new clients incompatible to the old server and vice versa.
|
||||
You can find more information on how we use Protobuf on [our wiki!](
|
||||
https://github.com/Cockatrice/Cockatrice/wiki/Client-server-protocol)
|
||||
|
||||
|
||||
# Reviewing Pull Requests #
|
||||
|
||||
After you have finished your changes to the project you should put them on a
|
||||
@@ -291,7 +286,6 @@ all changes have been approved your pull request will be squashed into a single
|
||||
commit and merged into the master branch by a team member. Your change will then
|
||||
be included in the next release 👍
|
||||
|
||||
|
||||
# Translations #
|
||||
|
||||
Basic workflow for translations:
|
||||
@@ -300,16 +294,16 @@ Basic workflow for translations:
|
||||
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 newest translations from Transifex.
|
||||
6. 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).
|
||||
Translations to other languages are managed using [Transifex](
|
||||
https://transifex.com/cockatrice/cockatrice/).
|
||||
https://www.transifex.com/projects/p/cockatrice/).
|
||||
|
||||
Adding a new string for translation is as easy as adding the string in the
|
||||
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
|
||||
and translated as needed.
|
||||
For example, setting the text of a label in the way that the string
|
||||
@@ -321,9 +315,9 @@ 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:
|
||||
```c++
|
||||
QString message = tr("Everyone draws %n cards", "english hint for translators", amount);
|
||||
QString message = tr("Everyone draws %n cards", "pop up message", amount);
|
||||
```
|
||||
See [Qt's wiki on translations](
|
||||
See [QT's wiki on translations](
|
||||
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
|
||||
@@ -331,7 +325,7 @@ 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 workflow on demand via GitHub Actions.
|
||||
Maintainers can also manually trigger this on demand.
|
||||
|
||||
### Maintaining Translations (for maintainers) ###
|
||||
|
||||
@@ -395,27 +389,27 @@ Now you are ready to commit your changes and open a PR.
|
||||
</details>
|
||||
|
||||
Once the changes get merged, Transifex will pick up the modified files
|
||||
automatically (checked every few hours) and update the web editor where
|
||||
automatically (checked every few hours) and update their online editor where
|
||||
translators will be able to translate the new strings right in the browser.
|
||||
|
||||
### Releasing Translations (for maintainers) ###
|
||||
|
||||
Before publishing a new release, a maintainer should fetch the most up to date
|
||||
Before rushing out a new release, a maintainer should fetch the most up to date
|
||||
translations from Transifex and commit them into the Cockatrice source code.
|
||||
We utilize the official GitHub integration to push all languages that are 100%
|
||||
translated from Transifex to our GitHub repo automatically.
|
||||
On top, it runs on a quarterly schedule to update changes for incomplete languages.
|
||||
A synchronisation/update can also be triggered manually from the Transifex web interface
|
||||
and a translation treshold can be set.
|
||||
This can be done manually from the Transifex web interface, but it's quite time
|
||||
consuming.
|
||||
|
||||
As an alternative, you can install the Transifex CLI:
|
||||
|
||||
http://docs.transifex.com/developer/client/
|
||||
|
||||
As an alternative, you can install the [Transifex CLI](https://developers.transifex.com/docs/cli).
|
||||
You'll then be able to use a git-like cli command to push and pull translations
|
||||
from Transifex to the source code and vice versa.
|
||||
|
||||
### Adding Translations (for translators) ###
|
||||
|
||||
As a translator, you can help to translate new strings on [Transifex](
|
||||
https://www.transifex.com/projects/p/cockatrice/) to your native language.
|
||||
As a translator you can help translate the new strings on [Transifex](
|
||||
https://www.transifex.com/projects/p/cockatrice/).
|
||||
Please have a look at the specific [FAQ for translators](
|
||||
https://github.com/Cockatrice/Cockatrice/wiki/Translation-FAQ).
|
||||
|
||||
@@ -425,9 +419,9 @@ https://github.com/Cockatrice/Cockatrice/wiki/Translation-FAQ).
|
||||
### Publishing A New Release ###
|
||||
|
||||
We use [GitHub Releases](https://github.com/Cockatrice/Cockatrice/releases) to
|
||||
publish new stable versions and beta releases.
|
||||
Whenever a git tag is pushed to the repository, GitHub will create a draft
|
||||
release and upload binaries from our CI automatically.
|
||||
publish new stable versions and betas.
|
||||
Whenever a git tag is pushed to the repository github will create a draft
|
||||
release and upload binaries automatically.
|
||||
|
||||
To create a tag, simply do the following:
|
||||
```bash
|
||||
@@ -439,16 +433,18 @@ git push $UPSTREAM $TAG_NAME
|
||||
```
|
||||
|
||||
You should define the variables as such:
|
||||
- `$UPSTREAM`: the remote for `git@github.com:Cockatrice/Cockatrice.git`
|
||||
- `$TAG_NAME` should be formatted as:
|
||||
- `YYYY-MM-DD-Release-MAJ.MIN.PATCH` for **stable releases**
|
||||
- `YYYY-MM-DD-Development-MAJ.MIN.PATCH-beta.X` for **beta releases**<br>
|
||||
With <kbd>MAJ</kbd>.<kbd>MIN</kbd>.<kbd>PATCH</kbd> being the NEXT release version!
|
||||
```
|
||||
`$UPSTREAM` - the remote for git@github.com:Cockatrice/Cockatrice.git
|
||||
`$TAG_NAME` should be formatted as:
|
||||
- `YYYY-MM-DD-Release-MAJ.MIN.PATCH` for **stable releases**
|
||||
- `YYYY-MM-DD-Development-MAJ.MIN.PATCH-beta.X` for **beta releases**<br>
|
||||
With *MAJ.MIN.PATCH* being the NEXT release version!
|
||||
```
|
||||
|
||||
This will cause a tagged release to be established on the GitHub repository,
|
||||
with the binaries being added to the release whenever they are done building in CI.
|
||||
The release is initially a draft, where the release notes can be edited and after
|
||||
all is checked and ready, it can be published as GitHub release.
|
||||
with the binaries being added to the release whenever they are ready.
|
||||
The release is initially a draft, where the path notes can be edited and after
|
||||
all is good and ready it can be published on GitHub.
|
||||
If you use a SemVer tag including "beta", the release that will be created at
|
||||
GitHub will be marked as a "Pre-release" automatically.
|
||||
The target of the `.../latest` URL will not be changed in that case, it always
|
||||
@@ -461,7 +457,7 @@ revoke the tag by doing the following:
|
||||
git push --delete upstream $TAG_NAME
|
||||
git tag -d $TAG_NAME
|
||||
```
|
||||
You can also do this on GitHub, you'll also want to delete the false release.
|
||||
You can also do this on GitHub, you'll also want to delete the new release.
|
||||
|
||||
In the first lines of [CMakeLists.txt](
|
||||
https://github.com/Cockatrice/Cockatrice/blob/master/CMakeLists.txt)
|
||||
@@ -472,24 +468,25 @@ coming from the tag title, it's good practice to increment the ones at CMake
|
||||
after every full release to stress that master is ahead of the last stable
|
||||
release.
|
||||
The preferred flow of operation is:
|
||||
- Just before a release, make sure the version number in CMakeLists.txt is set
|
||||
to the same release version you are about to tag.
|
||||
- This is also the time to change the pretty name in CMakeLists.txt called
|
||||
`GIT_TAG_RELEASENAME` and commit and push these changes.
|
||||
- Tag the release following the previously described syntax in order to get it
|
||||
correctly built and deployed by CI.
|
||||
- Wait for the configuration step to create the release and update the patch
|
||||
notes.
|
||||
- Check on the GitHub Actions page for build progress which should be the top
|
||||
listed [here](
|
||||
* Just before a release, make sure the version number in CMakeLists.txt is set
|
||||
to the same release version you are about to tag.
|
||||
* This is also the time to change the pretty name in CMakeLists.txt called
|
||||
GIT_TAG_RELEASENAME and commit and push these changes.
|
||||
* Tag the release following the previously described syntax in order to get it
|
||||
correctly built and deployed by CI.
|
||||
* Wait for the configure step to create the release and update the patch
|
||||
notes.
|
||||
* Check on the github actions page for build progress which should be the top
|
||||
listed [here](
|
||||
https://github.com/Cockatrice/Cockatrice/actions?query=event%3Apush+-branch%3Amaster
|
||||
).
|
||||
- When the build has been completed, you can verify if all uploaded files on the
|
||||
draft release are included and hit the publish button.
|
||||
- After the release is complete, update the CMake version number again to the
|
||||
next targeted beta version, typically increasing `PROJECT_VERSION_PATCH` by
|
||||
one.
|
||||
* When the build has been completed you can verify all uploaded files on the
|
||||
release are in order and hit the publish button.
|
||||
* After the release is complete, update the CMake version number again to the
|
||||
next targeted beta version, typically increasing `PROJECT_VERSION_PATCH` by
|
||||
one.
|
||||
|
||||
When releasing a new stable version, all previous beta releases (and tags)
|
||||
should be deleted as well.
|
||||
should be deleted. This is needed for Cockatrice to update users of the "Beta"
|
||||
release channel correctly to the latest stable version as well.
|
||||
This can be done the same way as revoking tags, mentioned above.
|
||||
|
||||
21
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -2,31 +2,20 @@
|
||||
name: "🐛 Bug Report"
|
||||
about: Report an issue encountered while using Cockatrice
|
||||
title: ''
|
||||
type: 'Bug'
|
||||
labels: ''
|
||||
labels: 'Bug'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!-- READ THIS BEFORE POSTING
|
||||
In Cockatrice, go to "Help" → "View Debug Log" and copy all information displayed at the
|
||||
top (above the separation line "----"), to below "System Information" section in this ticket!
|
||||
Go to "Help → View Debug Log" in Cockatrice and copy all information at the
|
||||
top (above the separation line) below "System Information" in this ticket!
|
||||
If you can't start Cockatrice to access these details, make
|
||||
sure to post your OS and the file name of the setup binary instead.
|
||||
-->
|
||||
sure to post your OS and the file name of the setup binary instead. -->
|
||||
|
||||
**System Information:**
|
||||
<!-- Read the hint above on where to find the important information to provide here! -->
|
||||
|
||||
|
||||
<details><summary>Debug Log:</summary>
|
||||
<!--
|
||||
In Cockatrice, go to "Help" → "View Debug Log", click the "Copy to clickboard" button and paste the output here.
|
||||
-->
|
||||
|
||||
|
||||
</details>
|
||||
|
||||
_______________________________________________________________________________________
|
||||
|
||||
<!-- Explain your issue in detail here! Please attach screenshots if possible. -->
|
||||
@@ -36,7 +25,7 @@ ________________________________________________________________________________
|
||||
|
||||
_______________________________________________________________________________________
|
||||
|
||||
<!-- Describe the sequence of actions needed to experience the bug. -->
|
||||
<!-- Describe the sequence of actions needed to experience the bug -->
|
||||
|
||||
**Steps to reproduce:**
|
||||
- Do A
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -4,6 +4,6 @@ contact_links:
|
||||
url: https://discord.gg/3Z9yzmA
|
||||
about: Need help with using the client? Want to find some games? Try the Discord server!
|
||||
- name: 🌐 Translations (Help improve the localization of the app)
|
||||
url: https://explore.transifex.com/cockatrice/cockatrice/
|
||||
url: https://www.transifex.com/cockatrice/cockatrice/
|
||||
# it is not possible to add a link to the wiki to this description
|
||||
about: For more information and guidance check our Translation FAQ on our wiki!
|
||||
|
||||
5
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -1,9 +1,8 @@
|
||||
---
|
||||
name: "💡 Feature Request"
|
||||
about: Request a new feature for Cockatrice
|
||||
about: Request a new feature
|
||||
title: ''
|
||||
type: 'Feature'
|
||||
labels: ''
|
||||
labels: 'Feature Request'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
216
.github/workflows/desktop-build.yml
vendored
@@ -1,10 +1,5 @@
|
||||
name: Build Desktop
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
id-token: write
|
||||
attestations: write
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
@@ -14,7 +9,6 @@ on:
|
||||
- 'webclient/**'
|
||||
- '.github/workflows/web-*.yml'
|
||||
- '.github/workflows/translations-*.yml'
|
||||
- '.github/workflows/docker-release.yml'
|
||||
tags:
|
||||
- '*'
|
||||
pull_request:
|
||||
@@ -56,7 +50,7 @@ jobs:
|
||||
|
||||
- name: Checkout
|
||||
if: steps.configure.outputs.tag != null
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -105,20 +99,20 @@ jobs:
|
||||
- distro: Debian
|
||||
version: 12
|
||||
package: DEB
|
||||
test: skip # Running tests on all distros is superfluous
|
||||
|
||||
- distro: Debian
|
||||
version: 13
|
||||
package: DEB
|
||||
- distro: Fedora
|
||||
version: 40
|
||||
package: RPM
|
||||
test: skip # Running tests on all distros is superfluous
|
||||
|
||||
- distro: Fedora
|
||||
version: 41
|
||||
package: RPM
|
||||
test: skip # Running tests on all distros is superfluous
|
||||
|
||||
- distro: Fedora
|
||||
version: 42
|
||||
package: RPM
|
||||
- distro: Ubuntu
|
||||
version: 20.04
|
||||
package: DEB
|
||||
test: skip # Ubuntu 20.04 has a broken Qt for debug builds
|
||||
|
||||
- distro: Ubuntu
|
||||
version: 22.04
|
||||
@@ -135,25 +129,29 @@ jobs:
|
||||
continue-on-error: ${{matrix.allow-failure == 'yes'}}
|
||||
env:
|
||||
NAME: ${{matrix.distro}}${{matrix.version}}
|
||||
CACHE: ${{github.workspace}}/.cache/${{matrix.distro}}${{matrix.version}} # directory for caching docker image and ccache
|
||||
CACHE: /tmp/${{matrix.distro}}${{matrix.version}}-cache # ${{runner.temp}} does not work?
|
||||
# Cache size over the entire repo is 10Gi:
|
||||
# https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#usage-limits-and-eviction-policy
|
||||
CCACHE_SIZE: 500M
|
||||
CMAKE_GENERATOR: 'Ninja'
|
||||
CCACHE_SIZE: 200M
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Restore compiler cache (ccache)
|
||||
id: ccache_restore
|
||||
uses: actions/cache/restore@v4
|
||||
- name: Generate cache timestamp
|
||||
id: cache_timestamp
|
||||
shell: bash
|
||||
run: echo "timestamp=$(date -u '+%Y%m%d%H%M%S')" >>"$GITHUB_OUTPUT"
|
||||
|
||||
- name: Restore cache
|
||||
uses: actions/cache@v4
|
||||
env:
|
||||
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
|
||||
timestamp: ${{steps.cache_timestamp.outputs.timestamp}}
|
||||
with:
|
||||
path: ${{env.CACHE}}
|
||||
key: ccache-${{matrix.distro}}${{matrix.version}}-${{env.BRANCH_NAME}}
|
||||
restore-keys: ccache-${{matrix.distro}}${{matrix.version}}-
|
||||
key: docker-${{matrix.distro}}${{matrix.version}}-cache-${{env.timestamp}}
|
||||
restore-keys: |
|
||||
docker-${{matrix.distro}}${{matrix.version}}-cache-
|
||||
|
||||
- name: Build ${{matrix.distro}} ${{matrix.version}} Docker image
|
||||
shell: bash
|
||||
@@ -162,11 +160,9 @@ jobs:
|
||||
- name: Build debug and test
|
||||
if: matrix.test != 'skip'
|
||||
shell: bash
|
||||
env:
|
||||
CMAKE_GENERATOR: '${{env.CMAKE_GENERATOR}}'
|
||||
run: |
|
||||
source .ci/docker.sh
|
||||
RUN --server --debug --test --ccache "$CCACHE_SIZE"
|
||||
RUN --server --debug --test --ccache "$CCACHE_SIZE" --parallel 4
|
||||
|
||||
- name: Build release package
|
||||
id: build
|
||||
@@ -175,23 +171,14 @@ jobs:
|
||||
env:
|
||||
BUILD_DIR: build
|
||||
SUFFIX: '-${{matrix.distro}}${{matrix.version}}'
|
||||
package: '${{matrix.package}}'
|
||||
CMAKE_GENERATOR: '${{env.CMAKE_GENERATOR}}'
|
||||
type: '${{matrix.package}}'
|
||||
run: |
|
||||
source .ci/docker.sh
|
||||
RUN --server --release --package "$package" --dir "$BUILD_DIR" \
|
||||
--ccache "$CCACHE_SIZE"
|
||||
RUN --server --release --package "$type" --dir "$BUILD_DIR" \
|
||||
--ccache "$CCACHE_SIZE" --parallel 4
|
||||
.ci/name_build.sh
|
||||
|
||||
- name: Save compiler cache (ccache)
|
||||
if: github.ref == 'refs/heads/master'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ${{env.CACHE}}
|
||||
key: ${{ steps.ccache_restore.outputs.cache-primary-key }}
|
||||
|
||||
- name: Upload artifact
|
||||
id: upload_artifact
|
||||
if: matrix.package != 'skip'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
@@ -200,7 +187,6 @@ jobs:
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload to release
|
||||
id: upload_release
|
||||
if: matrix.package != 'skip' && needs.configure.outputs.tag != null
|
||||
shell: bash
|
||||
env:
|
||||
@@ -210,21 +196,6 @@ jobs:
|
||||
asset_name: ${{steps.build.outputs.name}}
|
||||
run: gh release upload "$tag_name" "$asset_path#$asset_name"
|
||||
|
||||
- name: Attest binary provenance
|
||||
id: attestation
|
||||
if: steps.upload_release.outcome == 'success'
|
||||
uses: actions/attest-build-provenance@v3
|
||||
with:
|
||||
subject-name: ${{steps.build.outputs.name}}
|
||||
subject-digest: sha256:${{ steps.upload_artifact.outputs.artifact-digest }}
|
||||
|
||||
- name: Verify binary attestation
|
||||
if: steps.attestation.outcome == 'success'
|
||||
shell: bash
|
||||
env:
|
||||
GH_TOKEN: ${{github.token}}
|
||||
run: gh attestation verify ${{steps.build.outputs.path}} -R Cockatrice/Cockatrice
|
||||
|
||||
build-macos:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -235,6 +206,7 @@ jobs:
|
||||
os: macos-13
|
||||
xcode: "14.3.1"
|
||||
type: Release
|
||||
core_count: 4
|
||||
make_package: 1
|
||||
|
||||
- target: 14
|
||||
@@ -242,6 +214,7 @@ jobs:
|
||||
os: macos-14
|
||||
xcode: "15.4"
|
||||
type: Release
|
||||
core_count: 3
|
||||
make_package: 1
|
||||
|
||||
- target: 15
|
||||
@@ -249,6 +222,7 @@ jobs:
|
||||
os: macos-15
|
||||
xcode: "16.2"
|
||||
type: Release
|
||||
core_count: 3
|
||||
make_package: 1
|
||||
|
||||
- target: 15
|
||||
@@ -256,72 +230,60 @@ jobs:
|
||||
os: macos-15
|
||||
xcode: "16.2"
|
||||
type: Debug
|
||||
core_count: 3
|
||||
|
||||
name: macOS ${{matrix.target}}${{ matrix.soc == 'Intel' && ' Intel' || '' }}${{ matrix.type == 'Debug' && ' Debug' || '' }}
|
||||
needs: configure
|
||||
runs-on: ${{matrix.os}}
|
||||
continue-on-error: ${{matrix.allow-failure == 'yes'}}
|
||||
env:
|
||||
# Common parameters for all macOS builds
|
||||
QT_VERSION: 6.6.*
|
||||
QT_ARCH: clang_64
|
||||
QT_MODULES: "qtimageformats qtmultimedia qtwebsockets"
|
||||
# Build-specific environment variables
|
||||
CCACHE_DIR: ${{github.workspace}}/.ccache/${{matrix.os}}-${{matrix.type}}
|
||||
CCACHE_SIZE: 500M
|
||||
DEVELOPER_DIR:
|
||||
/Applications/Xcode_${{matrix.xcode}}.app/Contents/Developer
|
||||
CMAKE_GENERATOR: 'Ninja'
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: recursive
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Using jianmingyong/ccache-action to setup ccache without using brew
|
||||
# It tries to download a binary of ccache from GitHub Release and falls back to building from source if it fails
|
||||
- name: Setup ccache
|
||||
uses: jianmingyong/ccache-action@v1
|
||||
with:
|
||||
install-type: "binary"
|
||||
ccache-key-prefix: ccache-${{matrix.os}}-${{matrix.soc}}-${{matrix.type}}
|
||||
gh-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- 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
|
||||
run: |
|
||||
brew update
|
||||
brew install protobuf qt --force-bottle
|
||||
|
||||
# Using jurplel/install-qt-action to install Qt without using brew
|
||||
# qt build using vcpkg either just fails or takes too long to build
|
||||
- name: Install Qt ${{env.QT_VERSION}}
|
||||
uses: jurplel/install-qt-action@v4
|
||||
with:
|
||||
cache: false # qt caches take too much space for macOS (1.1Gi)
|
||||
version: ${{env.QT_VERSION}}
|
||||
arch: ${{env.QT_ARCH}}
|
||||
modules: ${{env.QT_MODULES}}
|
||||
|
||||
- name: Setup vcpkg cache
|
||||
id: vcpkg-cache
|
||||
uses: TAServers/vcpkg-cache@v3
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build on Xcode ${{matrix.xcode}}
|
||||
- name: Build & Sign on Xcode ${{matrix.xcode}}
|
||||
shell: bash
|
||||
id: build
|
||||
env:
|
||||
BUILDTYPE: '${{matrix.type}}'
|
||||
MAKE_TEST: 1
|
||||
MAKE_PACKAGE: '${{matrix.make_package}}'
|
||||
PACKAGE_SUFFIX: '-macOS${{matrix.target}}_${{matrix.soc}}'
|
||||
MACOS_CERTIFICATE: ${{ secrets.PROD_MACOS_CERTIFICATE }}
|
||||
MACOS_CERTIFICATE_PWD: ${{ secrets.PROD_MACOS_CERTIFICATE_PWD }}
|
||||
MACOS_CERTIFICATE_NAME: ${{ secrets.PROD_MACOS_CERTIFICATE_NAME }}
|
||||
MACOS_CI_KEYCHAIN_PWD: ${{ secrets.PROD_MACOS_CI_KEYCHAIN_PWD }}
|
||||
CMAKE_GENERATOR: '${{env.CMAKE_GENERATOR}}'
|
||||
VCPKG_DISABLE_METRICS: 1
|
||||
VCPKG_BINARY_SOURCES: 'clear;files,${{ steps.vcpkg-cache.outputs.path }},readwrite'
|
||||
run: .ci/compile.sh --server --test --ccache "$CCACHE_SIZE"
|
||||
# macOS runner have 3 cores usually - only the macos-13 image has 4:
|
||||
# https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners#standard-github-hosted-runners-for-public-repositories
|
||||
# https://github.com/actions/runner-images?tab=readme-ov-file#available-images
|
||||
run: |
|
||||
if [[ -n "$MACOS_CERTIFICATE_NAME" ]]
|
||||
then
|
||||
echo $MACOS_CERTIFICATE | base64 --decode > certificate.p12
|
||||
security create-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain
|
||||
security default-keychain -s build.keychain
|
||||
security set-keychain-settings -t 3600 -l build.keychain
|
||||
security unlock-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain
|
||||
security import certificate.p12 -k build.keychain -P "$MACOS_CERTIFICATE_PWD" -T /usr/bin/codesign
|
||||
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$MACOS_CI_KEYCHAIN_PWD" build.keychain
|
||||
fi
|
||||
.ci/compile.sh --server --parallel ${{matrix.core_count}}
|
||||
|
||||
- name: Sign app bundle
|
||||
if: matrix.make_package && (github.ref == 'refs/heads/master' || needs.configure.outputs.tag != null)
|
||||
if: matrix.make_package
|
||||
env:
|
||||
MACOS_CERTIFICATE_NAME: ${{ secrets.PROD_MACOS_CERTIFICATE_NAME }}
|
||||
MACOS_CI_KEYCHAIN_PWD: ${{ secrets.PROD_MACOS_CI_KEYCHAIN_PWD }}
|
||||
@@ -333,7 +295,7 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Notarize app bundle
|
||||
if: matrix.make_package && (github.ref == 'refs/heads/master' || needs.configure.outputs.tag != null)
|
||||
if: matrix.make_package
|
||||
env:
|
||||
MACOS_NOTARIZATION_APPLE_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_APPLE_ID }}
|
||||
MACOS_NOTARIZATION_TEAM_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_TEAM_ID }}
|
||||
@@ -365,17 +327,15 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Upload artifact
|
||||
id: upload_artifact
|
||||
if: matrix.make_package
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: macOS${{matrix.target}}${{ matrix.soc == 'Intel' && '_Intel' || '' }}${{ matrix.type == 'Debug' && '_Debug' || '' }}-package
|
||||
name: macOS${{matrix.target}}${{ matrix.soc == 'Intel' && '_Intel' || '' }}${{ matrix.type == 'Debug' && '_Debug' || '' }}-dmg
|
||||
path: ${{steps.build.outputs.path}}
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload to release
|
||||
id: upload_release
|
||||
if: matrix.make_package && needs.configure.outputs.tag != null
|
||||
if: matrix.package != 'skip' && needs.configure.outputs.tag != null
|
||||
shell: bash
|
||||
env:
|
||||
GH_TOKEN: ${{github.token}}
|
||||
@@ -384,21 +344,6 @@ jobs:
|
||||
asset_name: ${{steps.build.outputs.name}}
|
||||
run: gh release upload "$tag_name" "$asset_path#$asset_name"
|
||||
|
||||
- name: Attest binary provenance
|
||||
id: attestation
|
||||
if: steps.upload_release.outcome == 'success'
|
||||
uses: actions/attest-build-provenance@v3
|
||||
with:
|
||||
subject-name: ${{steps.build.outputs.name}}
|
||||
subject-digest: sha256:${{ steps.upload_artifact.outputs.artifact-digest }}
|
||||
|
||||
- name: Verify binary attestation
|
||||
if: steps.attestation.outcome == 'success'
|
||||
shell: bash
|
||||
env:
|
||||
GH_TOKEN: ${{github.token}}
|
||||
run: gh attestation verify ${{steps.build.outputs.path}} -R Cockatrice/Cockatrice
|
||||
|
||||
build-windows:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -427,7 +372,7 @@ jobs:
|
||||
msbuild-architecture: x64
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
@@ -435,16 +380,20 @@ jobs:
|
||||
uses: jurplel/install-qt-action@v4
|
||||
with:
|
||||
cache: true
|
||||
setup-python: true
|
||||
setup-python: false
|
||||
version: ${{matrix.qt_version}}
|
||||
arch: win64_${{matrix.qt_arch}}
|
||||
tools: ${{matrix.qt_tools}}
|
||||
modules: ${{matrix.qt_modules}}
|
||||
|
||||
- name: Setup vcpkg cache
|
||||
id: vcpkg-cache
|
||||
uses: TAServers/vcpkg-cache@v3
|
||||
- name: Run vcpkg
|
||||
uses: lukka/run-vcpkg@v11
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
runVcpkgInstall: true
|
||||
doNotCache: false
|
||||
env:
|
||||
VCPKG_DEFAULT_TRIPLET: 'x64-windows'
|
||||
VCPKG_DISABLE_METRICS: 1
|
||||
|
||||
- name: Build Cockatrice
|
||||
id: build
|
||||
@@ -454,14 +403,11 @@ jobs:
|
||||
CMAKE_GENERATOR: '${{env.CMAKE_GENERATOR}}'
|
||||
CMAKE_GENERATOR_PLATFORM: 'x64'
|
||||
QTDIR: '${{github.workspace}}\Qt\${{matrix.qt_version}}\win64_${{matrix.qt_arch}}'
|
||||
VCPKG_DISABLE_METRICS: 1
|
||||
VCPKG_BINARY_SOURCES: 'clear;files,${{ steps.vcpkg-cache.outputs.path }},readwrite'
|
||||
# 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
|
||||
|
||||
- name: Upload artifact
|
||||
id: upload_artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Windows${{matrix.target}}-installer
|
||||
@@ -478,8 +424,7 @@ jobs:
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload to release
|
||||
id: upload_release
|
||||
if: needs.configure.outputs.tag != null
|
||||
if: matrix.package != 'skip' && needs.configure.outputs.tag != null
|
||||
shell: bash
|
||||
env:
|
||||
GH_TOKEN: ${{github.token}}
|
||||
@@ -487,18 +432,3 @@ jobs:
|
||||
asset_path: ${{steps.build.outputs.path}}
|
||||
asset_name: ${{steps.build.outputs.name}}
|
||||
run: gh release upload "$tag_name" "$asset_path#$asset_name"
|
||||
|
||||
- name: Attest binary provenance
|
||||
id: attestation
|
||||
if: steps.upload_release.outcome == 'success'
|
||||
uses: actions/attest-build-provenance@v3
|
||||
with:
|
||||
subject-name: ${{steps.build.outputs.name}}
|
||||
subject-digest: sha256:${{ steps.upload_artifact.outputs.artifact-digest }}
|
||||
|
||||
- name: Verify binary attestation
|
||||
if: steps.attestation.outcome == 'success'
|
||||
shell: bash
|
||||
env:
|
||||
GH_TOKEN: ${{github.token}}
|
||||
run: gh attestation verify ${{steps.build.outputs.path}} -R Cockatrice/Cockatrice
|
||||
|
||||
3
.github/workflows/desktop-lint.yml
vendored
@@ -7,7 +7,6 @@ on:
|
||||
- 'webclient/**'
|
||||
- '.github/workflows/web-*.yml'
|
||||
- '.github/workflows/translations-*.yml'
|
||||
- '.github/workflows/docker-release.yml'
|
||||
|
||||
jobs:
|
||||
format:
|
||||
@@ -15,7 +14,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 20 # should be enough to find merge base
|
||||
|
||||
|
||||
65
.github/workflows/docker-release.yml
vendored
@@ -1,65 +0,0 @@
|
||||
name: Build Docker Image
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*Release*'
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- '.github/workflows/docker-release.yml'
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
name: amd64 & arm64
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Docker metadata
|
||||
id: metadata
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: |
|
||||
ghcr.io/cockatrice/servatrice
|
||||
labels: |
|
||||
org.opencontainers.image.title=Servatrice
|
||||
org.opencontainers.image.url=https://cockatrice.github.io/
|
||||
org.opencontainers.image.description=Server for Cockatrice, a cross-platform virtual tabletop for multiplayer card games
|
||||
annotations: |
|
||||
org.opencontainers.image.title=Servatrice
|
||||
org.opencontainers.image.url=https://cockatrice.github.io/
|
||||
org.opencontainers.image.description=Server for Cockatrice, a cross-platform virtual tabletop for multiplayer card games
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
if: github.ref_type == 'tag'
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ github.token }}
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: ${{ github.ref_type == 'tag' }}
|
||||
tags: ${{ steps.metadata.outputs.tags }}
|
||||
labels: ${{ steps.metadata.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
55
.github/workflows/documentation-build.yml
vendored
@@ -1,55 +0,0 @@
|
||||
name: Generate Docs
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*' # Only re-generate docs when a new tagged version is pushed
|
||||
pull_request:
|
||||
paths:
|
||||
- '**.h'
|
||||
- '/doc/doxygen/**'
|
||||
- '.github/workflows/documentation-build.yml'
|
||||
- 'Doxyfile'
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
COCKATRICE_REF: ${{ github.ref_name }} # Tag name if the commit is tagged, otherwise branch name
|
||||
|
||||
jobs:
|
||||
docs:
|
||||
name: Doxygen
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Install Doxygen and Graphviz
|
||||
shell: bash
|
||||
run: sudo apt-get install -y doxygen graphviz
|
||||
|
||||
- name: Generate Documentation
|
||||
shell: bash
|
||||
run: doxygen Doxyfile
|
||||
|
||||
- name: Upload Documentation
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Cockatrice_Docs
|
||||
path: ./docs/html # Main output folder + subfolder defined in Doxygen config
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Deploy to cockatrice.github.io/docs
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: peaceiris/actions-gh-pages@v4
|
||||
with:
|
||||
deploy_key: ${{ secrets.DOCS_DEPLOY_KEY }}
|
||||
external_repository: Cockatrice/cockatrice.github.io
|
||||
publish_branch: master
|
||||
publish_dir: ./docs/html # Main output folder + subfolder defined in Doxygen config
|
||||
destination_dir: docs # Subfolder of the GitHub Pages URL where the docs live
|
||||
|
||||
- name: Link to Documentation Page
|
||||
if: github.event_name != 'pull_request'
|
||||
shell: bash
|
||||
run: echo "::notice title=New documentation published ::Shortly available at https://cockatrice.github.io/docs/"
|
||||
4
.github/workflows/translations-pull.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Pull translated strings from Transifex
|
||||
uses: transifex/cli-action@v2
|
||||
@@ -51,7 +51,7 @@ jobs:
|
||||
*This PR is automatically generated and updated by the workflow at `.github/workflows/translations-pull.yml`. Review [action runs][2].*<br>
|
||||
*After merging, all new languages and translations are available in the next build.*
|
||||
|
||||
[1]: https://explore.transifex.com/cockatrice/cockatrice/
|
||||
[1]: https://app.transifex.com/cockatrice/cockatrice/
|
||||
[2]: https://github.com/Cockatrice/Cockatrice/actions/workflows/translations-pull.yml?query=branch%3Amaster
|
||||
labels: |
|
||||
CI
|
||||
|
||||
2
.github/workflows/translations-push.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install lupdate
|
||||
shell: bash
|
||||
|
||||
4
.github/workflows/web-build.yml
vendored
@@ -33,10 +33,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v5
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{matrix.node_version}}
|
||||
cache: 'npm'
|
||||
|
||||
4
.github/workflows/web-lint.yml
vendored
@@ -17,10 +17,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v5
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
cache: 'npm'
|
||||
cache-dependency-path: 'webclient/package-lock.json'
|
||||
|
||||
@@ -48,8 +48,8 @@ if(USE_CCACHE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WIN32 OR APPLE)
|
||||
# Use vcpkg toolchain on Windows and macOS
|
||||
if(WIN32)
|
||||
# Use vcpkg toolchain on Windows
|
||||
set(CMAKE_TOOLCHAIN_FILE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake
|
||||
CACHE STRING "Vcpkg toolchain file"
|
||||
@@ -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.11.0)
|
||||
project("Cockatrice" VERSION 2.10.0)
|
||||
|
||||
# Set release name if not provided via env/cmake var
|
||||
if(NOT DEFINED GIT_TAG_RELEASENAME)
|
||||
set(GIT_TAG_RELEASENAME "Omenpath")
|
||||
set(GIT_TAG_RELEASENAME "Rings of the Wild")
|
||||
endif()
|
||||
|
||||
# Use c++20 for all targets
|
||||
@@ -301,7 +301,6 @@ if(UNIX)
|
||||
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "http://github.com/Cockatrice/Cockatrice")
|
||||
if(Qt6_FOUND)
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt6multimedia6, libqt6svg6, qt6-qpa-plugins, qt6-image-formats-plugins")
|
||||
set(CPACK_DEBIAN_PACKAGE_RECOMMENDS "libqt6sql6-mysql") # for connecting servatrice to a mysql db
|
||||
elseif(Qt5_FOUND)
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt5multimedia5-plugins, libqt5svg5")
|
||||
endif()
|
||||
|
||||
@@ -16,11 +16,7 @@ RUN apt-get update && apt-get install -y\
|
||||
qt6-tools-dev \
|
||||
qt6-tools-dev-tools
|
||||
|
||||
COPY ./CMakeLists.txt ./LICENSE ./README.md /home/servatrice/code/
|
||||
COPY ./cmake /home/servatrice/code/cmake
|
||||
COPY ./common /home/servatrice/code/common
|
||||
COPY ./servatrice /home/servatrice/code/servatrice
|
||||
|
||||
COPY . /home/servatrice/code/
|
||||
WORKDIR /home/servatrice/code
|
||||
|
||||
WORKDIR build
|
||||
@@ -30,6 +26,6 @@ RUN cmake .. -DWITH_SERVER=1 -DWITH_CLIENT=0 -DWITH_ORACLE=0 -DWITH_DBCONVERTER=
|
||||
|
||||
WORKDIR /home/servatrice
|
||||
|
||||
EXPOSE 4748
|
||||
EXPOSE 4747 4748
|
||||
|
||||
ENTRYPOINT [ "servatrice", "--log-to-console" ]
|
||||
|
||||
9
LICENSE
@@ -2,7 +2,7 @@
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
<https://fsf.org/>
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
@@ -304,7 +304,8 @@ the "copyright" line and a pointer to where the full notice is found.
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, see <https://www.gnu.org/licenses/>.
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
@@ -328,8 +329,8 @@ necessary. Here is a sample; alter the names:
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Moe Ghoul>, 1 April 1989
|
||||
Moe Ghoul, President of Vice
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
|
||||
211
README.md
@@ -5,155 +5,154 @@
|
||||
<p align='center'>
|
||||
<a href="#cockatrice"><b>Cockatrice</b></a> <b>|</b>
|
||||
<a href="#download-">Download</a> <b>|</b>
|
||||
<a href="#related-repositories">Related</a> <b>|</b>
|
||||
<a href="#community-resources-">Community</a> <b>|</b>
|
||||
<a href="#contribute">Contribute</a> <b>|</b>
|
||||
<a href="#build---">Build</a> <b>|</b>
|
||||
<a href="#run">Run</a>
|
||||
<a href="#get-involved-">Get Involved</a> <b>|</b>
|
||||
<a href="#community-resources">Community</a> <b>|</b>
|
||||
<a href="#translations-">Translations</a> <b>|</b>
|
||||
<a href="#build--">Build</a> <b>|</b>
|
||||
<a href="#run">Run</a> <b>|</b>
|
||||
<a href="#license-">License</a>
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
<br><pre><p align='center'>
|
||||
<b>To get started with Cockatrice ⇢ [view our webpage](https://cockatrice.github.io/)</b><br>
|
||||
<b>To get support, or suggest changes to the app ⇢ [file an issue](https://github.com/Cockatrice/Cockatrice/issues) ([How?](https://github.com/Cockatrice/Cockatrice/wiki/How-to-Create-a-GitHub-Ticket-Regarding-Cockatrice))</b>
|
||||
<b>To help with development ⇢ learn [how to contribute](#contribute-)</b>
|
||||
</pre><p><br>
|
||||
<br><pre>
|
||||
<b>To get started, ⇢ [view our webpage](https://cockatrice.github.io/)</b><br>
|
||||
<b>To get support or suggest changes ⇢ [file an issue](https://github.com/Cockatrice/Cockatrice/issues) ([How?](https://github.com/Cockatrice/Cockatrice/wiki/How-to-Create-a-GitHub-Ticket-Regarding-Cockatrice))</b>
|
||||
<b>To help with development, see how to [get involved](#get-involved-)</b>
|
||||
</pre><br>
|
||||
|
||||
|
||||
# Cockatrice
|
||||
|
||||
Cockatrice is an open-source, multiplatform application for playing tabletop card games over a network. The program's server design prevents users from manipulating the game for unfair advantage. The client also provides a single-player mode, which allows users to brew while offline.<br><br>
|
||||
This project uses <kbd>C++</kbd> and the <kbd>Qt</kbd> libraries.<br>
|
||||
First work on a webclient with <kbd>Typescript</kbd> was started as well.<br>
|
||||
Cockatrice is an open-source, multiplatform program for playing tabletop card games over a network. The program's server design prevents users from manipulating the game for unfair advantage. The client also provides a single-player mode, which allows users to brew while offline. This project uses C++ and the Qt5 libraries.<br>
|
||||
|
||||
|
||||
# Download [](https://tooomm.github.io/github-release-stats/?username=Cockatrice&repository=Cockatrice&search=0)
|
||||
# Download [](https://tooomm.github.io/github-release-stats/?username=Cockatrice&repository=Cockatrice)
|
||||
|
||||
Downloads are available for **stable releases** and the current **beta version** in development.
|
||||
There is no strict release schedule for either of them.
|
||||
<br><pre>
|
||||
Latest <kbd>stable</kbd> release:
|
||||
[](https://github.com/cockatrice/cockatrice/releases/latest)  [](https://tooomm.github.io/github-release-stats/?username=Cockatrice&repository=Cockatrice&search=0)
|
||||
</pre><pre>
|
||||
Latest <kbd>beta</kbd> version:
|
||||
[](https://github.com/cockatrice/cockatrice/releases)  [](https://tooomm.github.io/github-release-stats/?username=Cockatrice&repository=Cockatrice&search=0) [](https://github.com/Cockatrice/Cockatrice/pulls?q=is%3Apr+is%3Aclosed)
|
||||
<sub><i>While incorporating the latest fixes and features, beta builds may not be stable or contain new bugs!</i></sub>
|
||||
<sub><b><i>Please report any findings and open new issues when testing them!</i></b></sub>
|
||||
</pre>
|
||||
Downloads are available for full releases and the current beta version in development. There is no strict release schedule for either of them.
|
||||
|
||||
# Related Repositories
|
||||
- Latest `stable` release: [](https://github.com/cockatrice/cockatrice/releases/latest) [](https://tooomm.github.io/github-release-stats/?username=Cockatrice&repository=Cockatrice)<br>
|
||||
- Stable versions are checkpoints featuring major feature and UI enhancements.
|
||||
- **Recommended for most users!**
|
||||
|
||||
- [Magic-Token](https://github.com/Cockatrice/Magic-Token): MtG token data to use in Cockatrice
|
||||
- [Magic-Spoiler](https://github.com/Cockatrice/Magic-Spoiler): Script to generate MtG spoiler data from [MTGJSON](https://github.com/mtgjson/mtgjson) to use in Cockatrice
|
||||
- [cockatrice.github.io](https://github.com/Cockatrice/cockatrice.github.io): Code of the official webpage of the Cockatrice project
|
||||
- Latest `beta` release: [](https://github.com/cockatrice/cockatrice/releases) [](https://tooomm.github.io/github-release-stats/?username=Cockatrice&repository=Cockatrice)
|
||||
- Beta versions include the most recently added features and bugfixes, but can be unstable.
|
||||
- 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)
|
||||
|
||||
Join our [Discord community](https://discord.gg/3Z9yzmA) to connect with the project, contributors or fellow users of the app. 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>
|
||||
|
||||
To contribute code to the project, please review [the guidelines](https://github.com/Cockatrice/Cockatrice/blob/master/.github/CONTRIBUTING.md).
|
||||
We maintain two tags for contributors to find issues to work on:
|
||||
- [Good first issue](https://github.com/Cockatrice/Cockatrice/issues?utf8=%E2%9C%93&q=is%3Aopen%20is%3Aissue%20label%3A%22Good%20first%20issue%22%20): issues tagged in this way provide a simple way to get started. They don't require much experience to be worked on.
|
||||
- [Help wanted](https://github.com/Cockatrice/Cockatrice/issues?utf8=%E2%9C%93&q=is%3Aopen%20is%3Aissue%20label%3A%22Help%20Wanted%22%20): This tag is used for issues that we are looking for a contributor to work on. Often this is for feature suggestions we are willing to accept, but don't have the time to work on ourselves.
|
||||
|
||||
For both tags, we're willing to provide help to contributors in showing them where and how they can make changes, as well as code review for changes they submit.
|
||||
|
||||
We try to be responsive to new issues. We'll provide advice on how best to implement a feature; alternately, we can show you where the codebase is doing something similar before you get too far along.
|
||||
|
||||
Cockatrice uses the [Google Developer Documentation Style Guide](https://developers.google.com/style/) to ensure consistent documentation. We encourage you to improve the documentation by suggesting edits based on this guide.
|
||||
|
||||
|
||||
# Community Resources [](https://discord.gg/3Z9yzmA)
|
||||
# Community Resources
|
||||
|
||||
Join our [Discord community](https://discord.gg/3Z9yzmA) to connect with other projet contributors (`#dev` channel) or fellow users of the app. Come here to talk about the application, features, or just to hang out.
|
||||
- [Official Website](https://cockatrice.github.io)
|
||||
- [Official Wiki](https://github.com/Cockatrice/Cockatrice/wiki)
|
||||
- [Official Discord](https://discord.gg/3Z9yzmA)
|
||||
- [Cockatrice Official Site](https://cockatrice.github.io)
|
||||
- [Cockatrice Official Wiki](https://github.com/Cockatrice/Cockatrice/wiki)
|
||||
- [Cockatrice Official Discord](https://discord.gg/3Z9yzmA)
|
||||
- [reddit r/Cockatrice](https://reddit.com/r/cockatrice)
|
||||
|
||||
>[!IMPORTANT]
|
||||
>For support regarding specific servers, please contact that server's admin/mods and use their dedicated communication channels rather than contacting the team building the software.
|
||||
|
||||
# Translations [](https://transifex.com/cockatrice/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>
|
||||
|
||||
Check out our [Translator FAQ](https://github.com/Cockatrice/Cockatrice/wiki/Translation-FAQ) for more information about contributing!<br>
|
||||
|
||||
|
||||
# Contribute
|
||||
# Build [](https://github.com/Cockatrice/Cockatrice/actions/workflows/desktop-build.yml?query=branch%3Amaster+event%3Apush) [](https://github.com/Cockatrice/Cockatrice/actions/workflows/web-build.yml?query=branch%3Amaster+event%3Apush)
|
||||
|
||||
### Code
|
||||
**Detailed compiling instructions can be found on the Cockatrice wiki under [Compiling Cockatrice](https://github.com/Cockatrice/Cockatrice/wiki/Compiling-Cockatrice)**
|
||||
|
||||
To contribute code to the project, please review our [guidelines](https://github.com/Cockatrice/Cockatrice/blob/master/.github/CONTRIBUTING.md) first.<br>
|
||||
We maintain two tags for contributors to easier find issues to potentially work on:
|
||||
- [](https://github.com/Cockatrice/Cockatrice/issues?utf8=%E2%9C%93&q=is%3Aopen%20is%3Aissue%20label%3A%22Good%20first%20issue%22%20)<br>
|
||||
Issues tagged in this way provide a simple way to get started. They don't require much experience to be worked on.
|
||||
- [](https://github.com/Cockatrice/Cockatrice/issues?utf8=%E2%9C%93&q=is%3Aopen%20is%3Aissue%20label%3A%22Help%20Wanted%22%20)<br>
|
||||
This tag is used for issues that we are looking for somebody to pick up. Often this is for feature suggestions we support, but don't have the time to work on ourselves.
|
||||
|
||||
For both tags, we're willing to provide help to contributors in showing them where and how they can make changes, as well as code reviews for submitted changes.<br>
|
||||
We'll happily advice on how best to implement a feature, or we can show you where the codebase is doing something similar before you get too far along - put a note on an issue you want to discuss more on!
|
||||
|
||||
Cockatrice tries to use the [Google Developer Documentation Style Guide](https://developers.google.com/style/) to ensure consistent documentation. We encourage you to improve the documentation by suggesting edits based on this guide.
|
||||
|
||||
<details>
|
||||
<summary><b>Kudos to our amazing contributors ❤️</b></summary>
|
||||
<br>
|
||||
<a href="https://github.com/Cockatrice/Cockatrice/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=Cockatrice/Cockatrice" />
|
||||
</a><br>
|
||||
<sub><i>Made with <a href="https://contrib.rocks">contrib.rocks</a></i></sub>
|
||||
</details>
|
||||
|
||||
### Translations [](https://explore.transifex.com/cockatrice/cockatrice/)
|
||||
|
||||
Cockatrice uses Transifex to manage translations. You can help us bring <kbd>Cockatrice</kbd>, <kbd>Oracle</kbd> and <kbd>Webatrice</kbd> to your language and just adjust single wordings right from within your browser by visiting our [Transifex project page](https://explore.transifex.com/cockatrice/cockatrice/).<br>
|
||||
|
||||
Check out our [Translator FAQ](https://github.com/Cockatrice/Cockatrice/wiki/Translation-FAQ) for more information about getting invovled, and join a group of hundreds of others!<br>
|
||||
|
||||
|
||||
# Build [](https://github.com/Cockatrice/Cockatrice/actions/workflows/desktop-build.yml?query=branch%3Amaster+event%3Apush) [](https://github.com/Cockatrice/Cockatrice/actions/workflows/docker-release.yml?query=branch%3Amaster+event%3Apush) [](https://github.com/Cockatrice/Cockatrice/actions/workflows/web-build.yml?query=branch%3Amaster+event%3Apush)
|
||||
|
||||
Dependencies: *(for minimum versions search our [CMake file](https://github.com/Cockatrice/Cockatrice/blob/master/CMakeLists.txt))*
|
||||
Dependencies: *(for minimum requirements search our [CMake file](https://github.com/Cockatrice/Cockatrice/blob/master/CMakeLists.txt))*
|
||||
- [Qt](https://www.qt.io/developers/)
|
||||
- [protobuf](https://github.com/protocolbuffers/protobuf)
|
||||
- [CMake](https://www.cmake.org/)
|
||||
|
||||
Oracle can *optionally* use some packages to load compressed card files:
|
||||
Oracle can optionally use zlib and xz to load compressed files:
|
||||
- [xz](https://tukaani.org/xz/)
|
||||
- [zlib](https://www.zlib.net/)
|
||||
|
||||
<br>
|
||||
To compile:
|
||||
|
||||
**Basic compilation steps:**
|
||||
```bash
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make
|
||||
```
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make
|
||||
|
||||
You can then run
|
||||
|
||||
You can then
|
||||
- Create a Cockatrice installation inside the `release` folder:
|
||||
```bash
|
||||
make install
|
||||
```
|
||||
- Or make an installation package specific to your system:
|
||||
```bash
|
||||
|
||||
to get a cockatrice installation inside the `release` folder, or:
|
||||
|
||||
make package
|
||||
```
|
||||
|
||||
>[!NOTE]
|
||||
>Detailed compiling instructions can be found in the Cockatrice wiki at [Compiling Cockatrice](https://github.com/Cockatrice/Cockatrice/wiki/Compiling-Cockatrice)
|
||||
to create a system-specific installation package.
|
||||
|
||||
<br>
|
||||
The following flags can be passed to `cmake`:
|
||||
|
||||
The following flags (with their non-default values) can be passed to `cmake`:
|
||||
| Flag | Description |
|
||||
| --- | --- |
|
||||
| `-DWITH_SERVER=1` | Build <kbd>Servatrice</kbd> server |
|
||||
| `-DWITH_CLIENT=0` | Don't build <kbd>Cockatrice</kbd> client |
|
||||
| `-DWITH_ORACLE=0` | Don't build <kbd>Oracle</kbd> card database tool |
|
||||
| `-DCMAKE_BUILD_TYPE=Debug` | Compile in debug mode<br> Enables extra logging output, debug symbols, and much more verbose compiler warnings |
|
||||
| `-DWARNING_AS_ERROR=0` | Don't treat compilation warnings as errors in debug mode |
|
||||
| `-DUPDATE_TRANSLATIONS=1` | Configure `make` to update the translation .ts files for new strings in the source code<br> **Note:** `make clean` will remove the .ts files |
|
||||
| `-DTEST=1` | Enable regression tests<br> **Note:** `make test` to run tests, *googletest* will be downloaded if not available |
|
||||
| `-DFORCE_USE_QT5=1` | Skip looking for Qt6 before trying to find Qt5 |
|
||||
- `-DWITH_SERVER=1` Whether to build the server (default 0 = no).
|
||||
- `-DWITH_CLIENT=0` Whether to build the client (default 1 = yes).
|
||||
- `-DWITH_ORACLE=0` Whether to build oracle (default 1 = yes).
|
||||
- `-DCMAKE_BUILD_TYPE=Debug` Compile in debug mode. Enables extra logging output, debug symbols, and much more verbose compiler warnings (default `Release`).
|
||||
- `-DWARNING_AS_ERROR=0` Whether to treat compilation warnings as errors in debug mode (default 1 = yes).
|
||||
- `-DUPDATE_TRANSLATIONS=1` Configure `make` to update the translation .ts files for new strings in the source code. Note: Running `make clean` will remove the .ts files (default 0 = no).
|
||||
- `-DTEST=1` Enable regression tests (default 0 = no). Note: needs googletest, will be downloaded on the fly if unavailable. To run tests: ```make test```.
|
||||
- `-DFORCE_USE_QT5=1` Skip looking for Qt6 before trying to find Qt5
|
||||
|
||||
|
||||
# Run
|
||||
|
||||
<kbd>Cockatrice</kbd> is the game client<br>
|
||||
<kbd>Oracle</kbd> fetches card data<br>
|
||||
<kbd>Servatrice</kbd> is the server<br>
|
||||
`Cockatrice` is the game client<br>
|
||||
`Oracle` fetches card data<br>
|
||||
`Servatrice` is the server<br>
|
||||
|
||||
#### Docker
|
||||
**Servatrice Docker container**
|
||||
|
||||
You can build an image & deploy a <kbd>Servatrice</kbd> (Cockatrice server) container using [Docker](https://www.docker.com/resources/what-container/) and our Dockerfile yourself.<br>
|
||||
You can run an instance of Servatrice (the Cockatrice server) using [Docker](https://www.docker.com/what-docker) and the Cockatrice Dockerfile.<br>
|
||||
|
||||
For more details, look into our wiki section on [Setting up Servatrice](https://github.com/Cockatrice/Cockatrice/wiki/Setting-up-Servatrice#using-docker).<br>
|
||||
You'll also find more hints on our **pre-build image** there, or the **docker-compose** file which will configure and run both a MySQL server and Servatrice.
|
||||
First, create an image from the Dockerfile<br>
|
||||
`cd /path/to/Cockatrice-Repo/`
|
||||
`docker build -t servatrice .`<br>
|
||||
And then run it<br>
|
||||
`docker run -i -p 4747:4747/tcp -t servatrice:latest`<br>
|
||||
|
||||
>Note: Running this command exposes the TCP port 4747 of the docker container<br>
|
||||
to permit connections to the server.
|
||||
|
||||
Find more information on how to use Servatrice with Docker in our [wiki](https://github.com/Cockatrice/Cockatrice/wiki/Setting-up-Servatrice#using-docker).
|
||||
|
||||
**Docker compose**
|
||||
|
||||
There is also a docker-compose file available which will configure and run both a MySQL server and Servatrice. The docker-compose setup scripts can be found in the `servatrice/docker` folder and vary only slightly from the default sql and server .ini files. The setup scripts can either be modified in place, or docker-compose can mount alternative files into the images, as you prefer.
|
||||
|
||||
To run Servatrice via docker-compose, first install docker-compose following the [install instructions](https://docs.docker.com/compose/install/). Once installed, run the following from the root of the repository:
|
||||
```bash
|
||||
docker-compose build # Build the Servatrice image using the same Dockerfile as above.
|
||||
docker-compose up # Setup and run both the MySQL server and Servatrice.
|
||||
```
|
||||
|
||||
>Note: Similar to the above Docker setup, this will expose TCP ports 4747 and 4748.
|
||||
|
||||
>Note: The first time running the docker-compose setup, the MySQL server will take a little time to run the initial setup scripts. Due to this, the Servatrice instance may fail the first few attempts to connect to the database. Servatrice is set to `restart: always` in the docker-compose.yml, which will allow it to continue attempting to start up. Once the MySQL scripts have completed, Servatrice should then connect automatically on the next attempt.
|
||||
|
||||
**Docker compose in Windows**
|
||||
A out of box working docker-compose file has been added to help setup in Windows.
|
||||
|
||||
Docker in Windows requires additional steps in form of using Docker Desktop to allow resource sharing from the drive the volumes are mapped from, as well as potential workarounds needed to get file sharing working in Windows. This [StackOverflow discussion sheds some light on it](https://stackoverflow.com/questions/42203488/settings-to-windows-firewall-to-allow-docker-for-windows-to-share-drive)
|
||||
|
||||
|
||||
# License [](https://github.com/Cockatrice/Cockatrice/blob/master/LICENSE)
|
||||
|
||||
@@ -5,47 +5,39 @@
|
||||
project(Cockatrice VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
|
||||
|
||||
set(cockatrice_SOURCES
|
||||
${VERSION_STRING_CPP}
|
||||
# sort by alphabetical order, so that there is no debate about where to add new sources to the list
|
||||
src/card/card_info.cpp
|
||||
src/card/card_relation.cpp
|
||||
src/card/card_set.cpp
|
||||
src/card/card_set_list.cpp
|
||||
src/card/exact_card.cpp
|
||||
src/card/printing_info.cpp
|
||||
src/client/deck_editor_menu.cpp
|
||||
src/client/get_text_with_max.cpp
|
||||
src/client/network/client_update_checker.cpp
|
||||
src/client/network/parsers/deck_link_to_api_transformer.cpp
|
||||
src/client/network/release_channel.cpp
|
||||
src/client/network/replay_timeline_widget.cpp
|
||||
src/client/network/sets_model.cpp
|
||||
src/client/network/spoiler_background_updater.cpp
|
||||
src/client/replay_manager.cpp
|
||||
src/client/sound_engine.cpp
|
||||
src/client/tapped_out_interface.cpp
|
||||
src/client/update_downloader.cpp
|
||||
src/database/card_database.cpp
|
||||
src/database/card_database_loader.cpp
|
||||
src/database/card_database_manager.cpp
|
||||
src/database/card_database_querier.cpp
|
||||
src/database/model/card_database_model.cpp
|
||||
src/database/model/card_database_display_model.cpp
|
||||
src/database/model/card/card_completer_proxy_model.cpp
|
||||
src/database/model/card/card_search_model.cpp
|
||||
src/database/model/token/token_display_model.cpp
|
||||
src/database/model/token/token_edit_model.cpp
|
||||
src/database/parser/card_database_parser.cpp
|
||||
src/database/parser/cockatrice_xml_3.cpp
|
||||
src/database/parser/cockatrice_xml_4.cpp
|
||||
src/game/cards/abstract_card_drag_item.cpp
|
||||
src/game/cards/abstract_card_item.cpp
|
||||
src/client/game_logic/abstract_client.cpp
|
||||
src/game/board/abstract_counter.cpp
|
||||
src/game/board/abstract_graphics_item.cpp
|
||||
src/game/board/arrow_item.cpp
|
||||
src/game/board/arrow_target.cpp
|
||||
src/game/cards/card_database.cpp
|
||||
src/game/cards/card_database_manager.cpp
|
||||
src/game/cards/card_database_model.cpp
|
||||
src/game/cards/card_database_parser/card_database_parser.cpp
|
||||
src/game/cards/card_database_parser/cockatrice_xml_3.cpp
|
||||
src/game/cards/card_database_parser/cockatrice_xml_4.cpp
|
||||
src/game/cards/card_drag_item.cpp
|
||||
src/game/filters/filter_card.cpp
|
||||
src/client/ui/widgets/cards/card_info_frame_widget.cpp
|
||||
src/client/ui/widgets/cards/card_info_picture_widget.cpp
|
||||
src/client/ui/widgets/cards/card_info_text_widget.cpp
|
||||
src/client/ui/widgets/cards/card_info_display_widget.cpp
|
||||
src/client/ui/widgets/cards/card_size_widget.cpp
|
||||
src/game/cards/card_item.cpp
|
||||
src/game/cards/card_list.cpp
|
||||
src/game/zones/card_zone.cpp
|
||||
src/server/chat_view/chat_view.cpp
|
||||
src/game/board/counter_general.cpp
|
||||
src/deck/custom_line_edit.cpp
|
||||
src/deck/deck_list_model.cpp
|
||||
src/deck/deck_loader.cpp
|
||||
src/deck/deck_list_model.cpp
|
||||
src/deck/deck_stats_interface.cpp
|
||||
src/dialogs/dlg_connect.cpp
|
||||
src/dialogs/dlg_convert_deck_to_cod_format.cpp
|
||||
src/dialogs/dlg_create_token.cpp
|
||||
src/dialogs/dlg_create_game.cpp
|
||||
src/dialogs/dlg_default_tags_editor.cpp
|
||||
src/dialogs/dlg_edit_avatar.cpp
|
||||
src/dialogs/dlg_edit_password.cpp
|
||||
src/dialogs/dlg_edit_tokens.cpp
|
||||
@@ -54,198 +46,83 @@ set(cockatrice_SOURCES
|
||||
src/dialogs/dlg_forgot_password_challenge.cpp
|
||||
src/dialogs/dlg_forgot_password_request.cpp
|
||||
src/dialogs/dlg_forgot_password_reset.cpp
|
||||
src/dialogs/dlg_load_deck.cpp
|
||||
src/dialogs/dlg_load_deck_from_clipboard.cpp
|
||||
src/dialogs/dlg_load_deck_from_website.cpp
|
||||
src/dialogs/dlg_load_remote_deck.cpp
|
||||
src/dialogs/dlg_manage_sets.cpp
|
||||
src/dialogs/dlg_move_top_cards_until.cpp
|
||||
src/dialogs/dlg_register.cpp
|
||||
src/dialogs/dlg_select_set_for_cards.cpp
|
||||
src/dialogs/dlg_roll_dice.cpp
|
||||
src/dialogs/dlg_settings.cpp
|
||||
src/dialogs/dlg_startup_card_check.cpp
|
||||
src/dialogs/dlg_tip_of_the_day.cpp
|
||||
src/dialogs/dlg_update.cpp
|
||||
src/dialogs/dlg_view_log.cpp
|
||||
src/dialogs/tip_of_the_day.cpp
|
||||
src/filters/deck_filter_string.cpp
|
||||
src/filters/filter_builder.cpp
|
||||
src/filters/filter_card.cpp
|
||||
src/filters/filter_string.cpp
|
||||
src/filters/filter_tree.cpp
|
||||
src/filters/filter_tree_model.cpp
|
||||
src/filters/syntax_help.cpp
|
||||
src/game/abstract_game.cpp
|
||||
src/game/board/abstract_card_drag_item.cpp
|
||||
src/game/board/abstract_card_item.cpp
|
||||
src/game/board/abstract_counter.cpp
|
||||
src/game/board/abstract_graphics_item.cpp
|
||||
src/game/board/arrow_item.cpp
|
||||
src/game/board/arrow_target.cpp
|
||||
src/game/board/card_drag_item.cpp
|
||||
src/game/board/card_item.cpp
|
||||
src/game/board/card_list.cpp
|
||||
src/game/board/counter_general.cpp
|
||||
src/game/board/translate_counter_name.cpp
|
||||
src/dialogs/dlg_load_deck.cpp
|
||||
src/game/deckview/deck_view.cpp
|
||||
src/game/deckview/deck_view_container.cpp
|
||||
src/game/deckview/tabbed_deck_view_container.cpp
|
||||
src/game/dialogs/dlg_create_token.cpp
|
||||
src/game/dialogs/dlg_move_top_cards_until.cpp
|
||||
src/game/dialogs/dlg_roll_dice.cpp
|
||||
src/game/game.cpp
|
||||
src/game/game_event_handler.cpp
|
||||
src/game/game_meta_info.cpp
|
||||
src/game/filters/filter_string.cpp
|
||||
src/game/filters/filter_builder.cpp
|
||||
src/game/filters/filter_tree.cpp
|
||||
src/game/filters/filter_tree_model.cpp
|
||||
src/client/ui/layouts/flow_layout.cpp
|
||||
src/client/ui/widgets/general/layout_containers/flow_widget.cpp
|
||||
src/game/game_scene.cpp
|
||||
src/game/game_state.cpp
|
||||
src/game/game_selector.cpp
|
||||
src/game/games_model.cpp
|
||||
src/game/game_view.cpp
|
||||
src/client/get_text_with_max.cpp
|
||||
src/game/hand_counter.cpp
|
||||
src/game/log/message_log_widget.cpp
|
||||
src/game/phase.cpp
|
||||
src/game/phases_toolbar.cpp
|
||||
src/game/player/menu/card_menu.cpp
|
||||
src/game/player/menu/custom_zone_menu.cpp
|
||||
src/game/player/menu/grave_menu.cpp
|
||||
src/game/player/menu/hand_menu.cpp
|
||||
src/game/player/menu/library_menu.cpp
|
||||
src/game/player/menu/move_menu.cpp
|
||||
src/game/player/menu/player_menu.cpp
|
||||
src/game/player/menu/pt_menu.cpp
|
||||
src/game/player/menu/rfg_menu.cpp
|
||||
src/game/player/menu/say_menu.cpp
|
||||
src/game/player/menu/sideboard_menu.cpp
|
||||
src/game/player/menu/utility_menu.cpp
|
||||
src/game/player/player.cpp
|
||||
src/game/player/player_actions.cpp
|
||||
src/game/player/player_area.cpp
|
||||
src/game/player/player_event_handler.cpp
|
||||
src/game/player/player_graphics_item.cpp
|
||||
src/game/player/player_info.cpp
|
||||
src/game/player/player_list_widget.cpp
|
||||
src/game/player/player_manager.cpp
|
||||
src/game/player/player_target.cpp
|
||||
src/game/replay.cpp
|
||||
src/game/zones/card_zone.cpp
|
||||
src/game/zones/hand_zone.cpp
|
||||
src/game/zones/logic/card_zone_logic.cpp
|
||||
src/game/zones/logic/hand_zone_logic.cpp
|
||||
src/game/zones/logic/pile_zone_logic.cpp
|
||||
src/game/zones/logic/stack_zone_logic.cpp
|
||||
src/game/zones/logic/table_zone_logic.cpp
|
||||
src/game/zones/logic/view_zone_logic.cpp
|
||||
src/game/zones/pile_zone.cpp
|
||||
src/game/zones/select_zone.cpp
|
||||
src/game/zones/stack_zone.cpp
|
||||
src/game/zones/table_zone.cpp
|
||||
src/game/zones/view_zone.cpp
|
||||
src/game/zones/view_zone_widget.cpp
|
||||
src/interface/layouts/flow_layout.cpp
|
||||
src/interface/layouts/overlap_layout.cpp
|
||||
src/interface/line_edit_completer.cpp
|
||||
src/interface/pixel_map_generator.cpp
|
||||
src/interface/theme_manager.cpp
|
||||
src/interface/widgets/cards/additional_info/color_identity_widget.cpp
|
||||
src/interface/widgets/cards/additional_info/mana_cost_widget.cpp
|
||||
src/interface/widgets/cards/additional_info/mana_symbol_widget.cpp
|
||||
src/interface/widgets/cards/card_group_display_widgets/card_group_display_widget.cpp
|
||||
src/interface/widgets/cards/card_group_display_widgets/flat_card_group_display_widget.cpp
|
||||
src/interface/widgets/cards/card_group_display_widgets/overlapped_card_group_display_widget.cpp
|
||||
src/interface/widgets/cards/card_info_display_widget.cpp
|
||||
src/interface/widgets/cards/card_info_frame_widget.cpp
|
||||
src/interface/widgets/cards/card_info_picture_art_crop_widget.cpp
|
||||
src/interface/widgets/cards/card_info_picture_enlarged_widget.cpp
|
||||
src/interface/widgets/cards/card_info_picture_widget.cpp
|
||||
src/interface/widgets/cards/card_info_picture_with_text_overlay_widget.cpp
|
||||
src/interface/widgets/cards/card_info_text_widget.cpp
|
||||
src/interface/widgets/cards/card_size_widget.cpp
|
||||
src/interface/widgets/cards/deck_card_zone_display_widget.cpp
|
||||
src/interface/widgets/cards/deck_preview_card_picture_widget.cpp
|
||||
src/interface/widgets/deck_analytics/deck_analytics_widget.cpp
|
||||
src/interface/widgets/deck_analytics/mana_base_widget.cpp
|
||||
src/interface/widgets/deck_analytics/mana_curve_widget.cpp
|
||||
src/interface/widgets/deck_analytics/mana_devotion_widget.cpp
|
||||
src/interface/widgets/deck_editor/deck_editor_card_info_dock_widget.cpp
|
||||
src/interface/widgets/deck_editor/deck_editor_database_display_widget.cpp
|
||||
src/interface/widgets/deck_editor/deck_editor_deck_dock_widget.cpp
|
||||
src/interface/widgets/deck_editor/deck_editor_filter_dock_widget.cpp
|
||||
src/interface/widgets/deck_editor/deck_editor_printing_selector_dock_widget.cpp
|
||||
src/interface/widgets/general/background_sources.cpp
|
||||
src/interface/widgets/general/display/banner_widget.cpp
|
||||
src/interface/widgets/general/display/bar_widget.cpp
|
||||
src/interface/widgets/general/display/dynamic_font_size_label.cpp
|
||||
src/interface/widgets/general/display/dynamic_font_size_push_button.cpp
|
||||
src/interface/widgets/general/display/labeled_input.cpp
|
||||
src/interface/widgets/general/display/percent_bar_widget.cpp
|
||||
src/interface/widgets/general/display/shadow_background_label.cpp
|
||||
src/interface/widgets/general/home_styled_button.cpp
|
||||
src/interface/widgets/general/home_widget.cpp
|
||||
src/interface/widgets/general/layout_containers/flow_widget.cpp
|
||||
src/interface/widgets/general/layout_containers/overlap_control_widget.cpp
|
||||
src/interface/widgets/general/layout_containers/overlap_widget.cpp
|
||||
src/interface/widgets/printing_selector/all_zones_card_amount_widget.cpp
|
||||
src/interface/widgets/printing_selector/card_amount_widget.cpp
|
||||
src/interface/widgets/printing_selector/printing_selector.cpp
|
||||
src/interface/widgets/printing_selector/printing_selector_card_display_widget.cpp
|
||||
src/interface/widgets/printing_selector/printing_selector_card_overlay_widget.cpp
|
||||
src/interface/widgets/printing_selector/printing_selector_card_search_widget.cpp
|
||||
src/interface/widgets/printing_selector/printing_selector_card_selection_widget.cpp
|
||||
src/interface/widgets/printing_selector/printing_selector_card_sorting_widget.cpp
|
||||
src/interface/widgets/printing_selector/set_name_and_collectors_number_display_widget.cpp
|
||||
src/interface/widgets/quick_settings/settings_button_widget.cpp
|
||||
src/interface/widgets/quick_settings/settings_popup_widget.cpp
|
||||
src/interface/widgets/visual_database_display/visual_database_display_color_filter_widget.cpp
|
||||
src/interface/widgets/visual_database_display/visual_database_display_filter_save_load_widget.cpp
|
||||
src/interface/widgets/visual_database_display/visual_database_display_main_type_filter_widget.cpp
|
||||
src/interface/widgets/visual_database_display/visual_database_display_name_filter_widget.cpp
|
||||
src/interface/widgets/visual_database_display/visual_database_display_set_filter_widget.cpp
|
||||
src/interface/widgets/visual_database_display/visual_database_display_sub_type_filter_widget.cpp
|
||||
src/interface/widgets/visual_database_display/visual_database_display_widget.cpp
|
||||
src/interface/widgets/visual_database_display/visual_database_filter_display_widget.cpp
|
||||
src/interface/widgets/visual_deck_editor/visual_deck_editor_sample_hand_widget.cpp
|
||||
src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.cpp
|
||||
src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_color_identity_filter_widget.cpp
|
||||
src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.cpp
|
||||
src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_addition_widget.cpp
|
||||
src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_dialog.cpp
|
||||
src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_display_widget.cpp
|
||||
src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_item_widget.cpp
|
||||
src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_widget.cpp
|
||||
src/interface/widgets/visual_deck_storage/visual_deck_storage_folder_display_widget.cpp
|
||||
src/interface/widgets/visual_deck_storage/visual_deck_storage_quick_settings_widget.cpp
|
||||
src/interface/widgets/visual_deck_storage/visual_deck_storage_search_widget.cpp
|
||||
src/interface/widgets/visual_deck_storage/visual_deck_storage_sort_widget.cpp
|
||||
src/interface/widgets/visual_deck_storage/visual_deck_storage_tag_filter_widget.cpp
|
||||
src/interface/widgets/visual_deck_storage/visual_deck_storage_widget.cpp
|
||||
src/interface/window_main.cpp
|
||||
src/main.cpp
|
||||
src/picture_loader/picture_loader.cpp
|
||||
src/picture_loader/picture_loader_local.cpp
|
||||
src/picture_loader/picture_loader_request_status_display_widget.cpp
|
||||
src/picture_loader/picture_loader_status_bar.cpp
|
||||
src/picture_loader/picture_loader_worker.cpp
|
||||
src/picture_loader/picture_loader_worker_work.cpp
|
||||
src/picture_loader/picture_to_load.cpp
|
||||
src/server/abstract_client.cpp
|
||||
src/server/chat_view/chat_view.cpp
|
||||
src/server/game_selector.cpp
|
||||
src/server/games_model.cpp
|
||||
src/server/handle_public_servers.cpp
|
||||
src/game/zones/hand_zone.cpp
|
||||
src/client/game_logic/key_signals.cpp
|
||||
src/client/ui/line_edit_completer.cpp
|
||||
src/server/local_client.cpp
|
||||
src/server/local_server.cpp
|
||||
src/server/local_server_interface.cpp
|
||||
src/utility/logger.cpp
|
||||
src/client/ui/widgets/cards/card_info_picture_enlarged_widget.cpp
|
||||
src/client/ui/widgets/cards/card_info_picture_with_text_overlay_widget.cpp
|
||||
src/client/ui/widgets/general/display/banner_widget.cpp
|
||||
src/client/ui/widgets/general/display/labeled_input.cpp
|
||||
src/client/ui/widgets/general/display/dynamic_font_size_label.cpp
|
||||
src/client/ui/widgets/general/display/dynamic_font_size_push_button.cpp
|
||||
src/client/ui/widgets/general/display/shadow_background_label.cpp
|
||||
src/main.cpp
|
||||
src/server/message_log_widget.cpp
|
||||
src/client/ui/layouts/overlap_layout.cpp
|
||||
src/client/ui/widgets/general/layout_containers/overlap_widget.cpp
|
||||
src/client/ui/widgets/general/layout_containers/overlap_control_widget.cpp
|
||||
src/server/pending_command.cpp
|
||||
src/game/phase.cpp
|
||||
src/client/ui/phases_toolbar.cpp
|
||||
src/client/ui/picture_loader/picture_loader.cpp
|
||||
src/client/ui/picture_loader/picture_loader_worker.cpp
|
||||
src/client/ui/picture_loader/picture_to_load.cpp
|
||||
src/game/zones/pile_zone.cpp
|
||||
src/client/ui/pixel_map_generator.cpp
|
||||
src/game/player/player.cpp
|
||||
src/game/player/player_list_widget.cpp
|
||||
src/game/player/player_target.cpp
|
||||
src/client/ui/widgets/printing_selector/all_zones_card_amount_widget.cpp
|
||||
src/client/ui/widgets/printing_selector/card_amount_widget.cpp
|
||||
src/client/ui/widgets/printing_selector/printing_selector.cpp
|
||||
src/client/ui/widgets/printing_selector/printing_selector_card_display_widget.cpp
|
||||
src/client/ui/widgets/printing_selector/printing_selector_card_overlay_widget.cpp
|
||||
src/client/ui/widgets/printing_selector/printing_selector_card_search_widget.cpp
|
||||
src/client/ui/widgets/printing_selector/printing_selector_card_selection_widget.cpp
|
||||
src/client/ui/widgets/printing_selector/printing_selector_card_sorting_widget.cpp
|
||||
src/client/ui/widgets/printing_selector/printing_selector_view_options_toolbar_widget.cpp
|
||||
src/client/ui/widgets/printing_selector/printing_selector_view_options_widget.cpp
|
||||
src/client/ui/widgets/printing_selector/set_name_and_collectors_number_display_widget.cpp
|
||||
src/client/network/release_channel.cpp
|
||||
src/client/network/client_update_checker.cpp
|
||||
src/server/remote/remote_client.cpp
|
||||
src/server/remote/remote_decklist_tree_widget.cpp
|
||||
src/server/remote/remote_replay_list_tree_widget.cpp
|
||||
src/server/user/user_context_menu.cpp
|
||||
src/server/user/user_info_box.cpp
|
||||
src/server/user/user_info_connection.cpp
|
||||
src/server/user/user_list_manager.cpp
|
||||
src/server/user/user_list_widget.cpp
|
||||
src/settings/cache_settings.cpp
|
||||
src/settings/card_counter_settings.cpp
|
||||
src/client/network/replay_timeline_widget.cpp
|
||||
src/game/zones/select_zone.cpp
|
||||
src/utility/sequence_edit.cpp
|
||||
src/client/network/sets_model.cpp
|
||||
src/settings/card_database_settings.cpp
|
||||
src/settings/card_override_settings.cpp
|
||||
src/settings/debug_settings.cpp
|
||||
src/settings/download_settings.cpp
|
||||
src/settings/game_filters_settings.cpp
|
||||
src/settings/layouts_settings.cpp
|
||||
@@ -253,58 +130,69 @@ set(cockatrice_SOURCES
|
||||
src/settings/recents_settings.cpp
|
||||
src/settings/servers_settings.cpp
|
||||
src/settings/settings_manager.cpp
|
||||
src/settings/shortcut_treeview.cpp
|
||||
src/settings/cache_settings.cpp
|
||||
src/settings/shortcuts_settings.cpp
|
||||
src/tabs/abstract_tab_deck_editor.cpp
|
||||
src/tabs/api/edhrec/api_response/archidekt_links/edhrec_api_response_archidekt_links.cpp
|
||||
src/tabs/api/edhrec/api_response/average_deck/edhrec_average_deck_api_response.cpp
|
||||
src/tabs/api/edhrec/api_response/average_deck/edhrec_deck_api_response.cpp
|
||||
src/tabs/api/edhrec/api_response/card_prices/edhrec_api_response_card_prices.cpp
|
||||
src/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_container.cpp
|
||||
src/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_details.cpp
|
||||
src/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_list.cpp
|
||||
src/tabs/api/edhrec/api_response/cards/edhrec_commander_api_response_commander_details.cpp
|
||||
src/tabs/api/edhrec/api_response/commander/edhrec_commander_api_response.cpp
|
||||
src/tabs/api/edhrec/api_response/commander/edhrec_commander_api_response_average_deck_statistics.cpp
|
||||
src/tabs/api/edhrec/api_response/top_cards/edhrec_top_cards_api_response.cpp
|
||||
src/tabs/api/edhrec/api_response/top_commanders/edhrec_top_commanders_api_response.cpp
|
||||
src/tabs/api/edhrec/api_response/top_tags/edhrec_top_tags_api_response.cpp
|
||||
src/tabs/api/edhrec/display/card_prices/edhrec_api_response_card_prices_display_widget.cpp
|
||||
src/tabs/api/edhrec/display/cards/edhrec_api_response_card_details_display_widget.cpp
|
||||
src/tabs/api/edhrec/display/cards/edhrec_api_response_card_inclusion_display_widget.cpp
|
||||
src/tabs/api/edhrec/display/cards/edhrec_api_response_card_list_display_widget.cpp
|
||||
src/tabs/api/edhrec/display/cards/edhrec_api_response_card_synergy_display_widget.cpp
|
||||
src/tabs/api/edhrec/display/commander/edhrec_api_response_commander_details_display_widget.cpp
|
||||
src/tabs/api/edhrec/display/commander/edhrec_commander_api_response_display_widget.cpp
|
||||
src/tabs/api/edhrec/display/commander/edhrec_commander_api_response_navigation_widget.cpp
|
||||
src/tabs/api/edhrec/display/top_cards/edhrec_top_cards_api_response_display_widget.cpp
|
||||
src/tabs/api/edhrec/display/top_commander/edhrec_top_commanders_api_response_display_widget.cpp
|
||||
src/tabs/api/edhrec/display/top_tags/edhrec_top_tags_api_response_display_widget.cpp
|
||||
src/tabs/api/edhrec/tab_edhrec.cpp
|
||||
src/tabs/api/edhrec/tab_edhrec_main.cpp
|
||||
src/tabs/tab.cpp
|
||||
src/tabs/tab_account.cpp
|
||||
src/tabs/tab_admin.cpp
|
||||
src/tabs/tab_deck_editor.cpp
|
||||
src/tabs/tab_deck_storage.cpp
|
||||
src/tabs/tab_game.cpp
|
||||
src/tabs/tab_home.cpp
|
||||
src/tabs/tab_logs.cpp
|
||||
src/tabs/tab_message.cpp
|
||||
src/tabs/tab_replays.cpp
|
||||
src/tabs/tab_room.cpp
|
||||
src/tabs/tab_server.cpp
|
||||
src/tabs/tab_supervisor.cpp
|
||||
src/tabs/tab_visual_database_display.cpp
|
||||
src/tabs/visual_deck_editor/tab_deck_editor_visual.cpp
|
||||
src/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.cpp
|
||||
src/tabs/visual_deck_storage/tab_deck_storage_visual.cpp
|
||||
src/utility/card_info_comparator.cpp
|
||||
src/utility/deck_list_sort_filter_proxy_model.cpp
|
||||
src/utility/key_signals.cpp
|
||||
src/utility/levenshtein.cpp
|
||||
src/utility/logger.cpp
|
||||
src/utility/sequence_edit.cpp
|
||||
src/settings/shortcut_treeview.cpp
|
||||
src/settings/card_override_settings.cpp
|
||||
src/settings/debug_settings.cpp
|
||||
src/client/sound_engine.cpp
|
||||
src/client/network/spoiler_background_updater.cpp
|
||||
src/game/zones/stack_zone.cpp
|
||||
src/client/tabs/tab.cpp
|
||||
src/client/tabs/tab_account.cpp
|
||||
src/client/tabs/tab_admin.cpp
|
||||
src/client/tabs/tab_deck_editor.cpp
|
||||
src/client/tabs/tab_deck_storage.cpp
|
||||
src/client/tabs/tab_game.cpp
|
||||
src/client/tabs/tab_logs.cpp
|
||||
src/client/tabs/tab_message.cpp
|
||||
src/client/tabs/tab_replays.cpp
|
||||
src/client/tabs/tab_room.cpp
|
||||
src/client/tabs/tab_server.cpp
|
||||
src/client/tabs/tab_supervisor.cpp
|
||||
src/client/tabs/api/edhrec/tab_edhrec.cpp
|
||||
src/client/tabs/api/edhrec/edhrec_commander_api_response_display_widget.cpp
|
||||
src/client/tabs/api/edhrec/edhrec_commander_api_response_card_details_display_widget.cpp
|
||||
src/client/tabs/api/edhrec/edhrec_commander_api_response_card_list_display_widget.cpp
|
||||
src/client/tabs/api/edhrec/edhrec_commander_api_response_commander_details_display_widget.cpp
|
||||
src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_archidekt_links.cpp
|
||||
src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_average_deck_statistics.cpp
|
||||
src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_details.cpp
|
||||
src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_list.cpp
|
||||
src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_container.cpp
|
||||
src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_prices.cpp
|
||||
src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_commander_details.cpp
|
||||
src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response.cpp
|
||||
src/game/zones/table_zone.cpp
|
||||
src/client/tapped_out_interface.cpp
|
||||
src/client/ui/theme_manager.cpp
|
||||
src/client/ui/tip_of_the_day.cpp
|
||||
src/client/translate_counter_name.cpp
|
||||
src/client/update_downloader.cpp
|
||||
src/server/user/user_context_menu.cpp
|
||||
src/server/user/user_info_connection.cpp
|
||||
src/server/user/user_info_box.cpp
|
||||
src/server/user/user_list_manager.cpp
|
||||
src/server/user/user_list_widget.cpp
|
||||
src/client/ui/window_main.cpp
|
||||
src/game/zones/view_zone_widget.cpp
|
||||
src/game/zones/view_zone.cpp
|
||||
src/client/tabs/visual_deck_storage/tab_deck_storage_visual.cpp
|
||||
src/client/ui/widgets/cards/deck_preview_card_picture_widget.cpp
|
||||
src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_color_identity_widget.cpp
|
||||
src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_color_identity_filter_widget.cpp
|
||||
src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_tag_addition_widget.cpp
|
||||
src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_tag_display_widget.cpp
|
||||
src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_tag_dialog.cpp
|
||||
src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_tag_item_widget.cpp
|
||||
src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.cpp
|
||||
src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_widget.cpp
|
||||
src/client/ui/widgets/visual_deck_storage/visual_deck_storage_widget.cpp
|
||||
src/client/ui/widgets/visual_deck_storage/visual_deck_storage_folder_display_widget.cpp
|
||||
src/client/ui/widgets/visual_deck_storage/visual_deck_storage_search_widget.cpp
|
||||
src/client/ui/widgets/visual_deck_storage/visual_deck_storage_sort_widget.cpp
|
||||
src/client/ui/widgets/visual_deck_storage/visual_deck_storage_tag_filter_widget.cpp
|
||||
${VERSION_STRING_CPP}
|
||||
)
|
||||
|
||||
add_subdirectory(sounds)
|
||||
@@ -450,13 +338,6 @@ if(APPLE)
|
||||
PATTERN "tls/*.dylib"
|
||||
)
|
||||
|
||||
install(
|
||||
DIRECTORY "${CMAKE_BINARY_DIR}/cockatrice/"
|
||||
DESTINATION ${qtconf_dest_dir}/
|
||||
FILES_MATCHING
|
||||
PATTERN "*.ini"
|
||||
)
|
||||
|
||||
install(
|
||||
CODE "
|
||||
file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf\" \"[Paths]
|
||||
@@ -492,10 +373,10 @@ if(WIN32)
|
||||
)
|
||||
|
||||
install(
|
||||
DIRECTORY "${CMAKE_BINARY_DIR}/cockatrice/"
|
||||
DESTINATION ./
|
||||
FILES_MATCHING
|
||||
PATTERN "*.ini"
|
||||
DIRECTORY "${CMAKE_BINARY_DIR}/cockatrice/"
|
||||
DESTINATION ./
|
||||
FILES_MATCHING
|
||||
PATTERN "*.ini"
|
||||
)
|
||||
|
||||
# Qt plugins: audio (Qt5), iconengines, imageformats, multimedia (Qt6) platforms, printsupport (Qt5), styles, tls (Qt6)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<qresource prefix="/" >
|
||||
<file>resources/cardback.svg</file>
|
||||
<file>resources/cockatrice.svg</file>
|
||||
<file>resources/hand.svg</file>
|
||||
@@ -13,12 +13,9 @@
|
||||
<file>resources/icons/arrow_top_green.svg</file>
|
||||
<file>resources/icons/arrow_up_green.svg</file>
|
||||
<file>resources/icons/clearsearch.svg</file>
|
||||
<file>resources/icons/cogwheel.svg</file>
|
||||
<file>resources/icons/conceded.svg</file>
|
||||
<file>resources/icons/decrement.svg</file>
|
||||
<file>resources/icons/delete.svg</file>
|
||||
<file>resources/icons/dropdown_collapsed.svg</file>
|
||||
<file>resources/icons/dropdown_expanded.svg</file>
|
||||
<file>resources/icons/forgot_password.svg</file>
|
||||
<file>resources/icons/increment.svg</file>
|
||||
<file>resources/icons/info.svg</file>
|
||||
@@ -27,13 +24,10 @@
|
||||
<file>resources/icons/pencil.svg</file>
|
||||
<file>resources/icons/player.svg</file>
|
||||
<file>resources/icons/ready_start.svg</file>
|
||||
<file>resources/icons/reload.svg</file>
|
||||
<file>resources/icons/remove_row.svg</file>
|
||||
<file>resources/icons/rename.svg</file>
|
||||
<file>resources/icons/scales.svg</file>
|
||||
<file>resources/icons/search.svg</file>
|
||||
<file>resources/icons/settings.svg</file>
|
||||
<file>resources/icons/share.svg</file>
|
||||
<file>resources/icons/spectator.svg</file>
|
||||
<file>resources/icons/swap.svg</file>
|
||||
<file>resources/icons/sync.svg</file>
|
||||
@@ -41,14 +35,6 @@
|
||||
<file>resources/icons/update.png</file>
|
||||
<file>resources/icons/view.svg</file>
|
||||
|
||||
<file>resources/icons/mana/B.svg</file>
|
||||
<file>resources/icons/mana/G.svg</file>
|
||||
<file>resources/icons/mana/R.svg</file>
|
||||
<file>resources/icons/mana/U.svg</file>
|
||||
<file>resources/icons/mana/W.svg</file>
|
||||
|
||||
<file>resources/backgrounds/home.png</file>
|
||||
|
||||
<file>resources/config/general.svg</file>
|
||||
<file>resources/config/appearance.svg</file>
|
||||
<file>resources/config/interface.svg</file>
|
||||
@@ -356,32 +342,21 @@
|
||||
|
||||
<!-- ADD TIP OF THE DAY IMAGES HERE -->
|
||||
<file>resources/tips/images/accounts_tab.png</file>
|
||||
<file>resources/tips/images/add_card.png</file>
|
||||
<file>resources/tips/images/arrows.png</file>
|
||||
<file>resources/tips/images/card_select.png</file>
|
||||
<file>resources/tips/images/cockatrice_register.png</file>
|
||||
<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/edhrec.png</file>
|
||||
<file>resources/tips/images/expand_card_view.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/highlight_cards.png</file>
|
||||
<file>resources/tips/images/pawns.png</file>
|
||||
<file>resources/tips/images/setpt.png</file>
|
||||
<file>resources/tips/images/shortcuts.png</file>
|
||||
<file>resources/tips/images/syntax_help.png</file>
|
||||
<file>resources/tips/images/themes.png</file>
|
||||
<file>resources/tips/images/tip_of_the_day.png</file>
|
||||
<file>resources/tips/images/token.png</file>
|
||||
<file>resources/tips/images/updates.png</file>
|
||||
<file>resources/tips/images/visual_deck_tags.png</file>
|
||||
<file>resources/tips/tips_of_the_day.xml</file>
|
||||
|
||||
<file>resources/help/search.md</file>
|
||||
<file>resources/help/deck_search.md</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
|
Before Width: | Height: | Size: 12 MiB |
|
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 42 KiB |
@@ -1,66 +1,55 @@
|
||||
[Rules]
|
||||
# The default log level is info
|
||||
*.debug = false
|
||||
# Uncomment a rule to disable logging for that category
|
||||
|
||||
# Uncomment a rule to see debug level logs for that category,
|
||||
# or set <category> = false to disable logging
|
||||
# main = false
|
||||
# qt_translator = false
|
||||
# window_main.* = false
|
||||
# release_channel = false
|
||||
# spoiler_background_updater = false
|
||||
# theme_manager = false
|
||||
# sound_engine = false
|
||||
# tapped_out_interface = false
|
||||
|
||||
#main = true
|
||||
#qt_translator = true
|
||||
#window_main.* = true
|
||||
#release_channel = true
|
||||
#spoiler_background_updater = true
|
||||
#theme_manager = true
|
||||
#sound_engine = true
|
||||
#tapped_out_interface = true
|
||||
# tab_game = false
|
||||
# tab_message = false
|
||||
# tab_supervisor = false
|
||||
|
||||
#tab_game = true
|
||||
#tab_message = true
|
||||
#tab_supervisor = true
|
||||
# dlg_edit_avatar = false
|
||||
# dlg_settings = false
|
||||
# dlg_tip_of_the_day = false
|
||||
# dlg_update = false
|
||||
|
||||
#dlg_edit_avatar = true
|
||||
#dlg_load_deck_from_website = true
|
||||
#dlg_settings = true
|
||||
#dlg_tip_of_the_day = true
|
||||
#dlg_update = true
|
||||
# settings_cache = false
|
||||
# servers_settings = false
|
||||
# shortcuts_settings = false
|
||||
|
||||
#settings_cache = true
|
||||
#servers_settings = true
|
||||
#shortcuts_settings = true
|
||||
# remote_client = false
|
||||
|
||||
#local_client = true
|
||||
#remote_client = true
|
||||
# player = false
|
||||
# game_scene = false
|
||||
# game_scene.player_addition_removal = false
|
||||
# card_zone = false
|
||||
# view_zone = false
|
||||
|
||||
#player = true
|
||||
#game_scene = true
|
||||
#game_scene.player_addition_removal = true
|
||||
#card_zone = true
|
||||
#view_zone = true
|
||||
# user_info_connection = false
|
||||
|
||||
#user_info_connection = true
|
||||
# picture_loader = false
|
||||
# picture_loader.worker = false
|
||||
# picture_loader.card_back_cache_fail = false
|
||||
# picture_loader.picture_to_load = false
|
||||
# deck_loader = false
|
||||
# card_database = false
|
||||
# card_database.loading = false
|
||||
# card_database.loading.success_or_failure = false
|
||||
# cockatrice_xml.* = false
|
||||
# cockatrice_xml.xml_3_parser = false
|
||||
# cockatrice_xml.xml_4_parser = false
|
||||
# card_list = false
|
||||
|
||||
#picture_loader = true
|
||||
#picture_loader.worker = true
|
||||
#picture_loader.card_back_cache_fail = true
|
||||
#picture_loader.picture_to_load = true
|
||||
#deck_loader = true
|
||||
#card_database = true
|
||||
#card_database.loading = true
|
||||
#card_database.loading.success_or_failure = true
|
||||
#cockatrice_xml.* = true
|
||||
#cockatrice_xml.xml_3_parser = true
|
||||
#cockatrice_xml.xml_4_parser = true
|
||||
#card_info = true
|
||||
#card_list = true
|
||||
flow_layout.debug = false
|
||||
flow_widget.debug = false
|
||||
flow_widget.size.debug = false
|
||||
|
||||
#flow_layout = true
|
||||
#flow_widget = true
|
||||
#flow_widget.size = true
|
||||
# pixel_map_generator = false
|
||||
|
||||
#card_info_picture_widget = true
|
||||
|
||||
#pixel_map_generator = true
|
||||
|
||||
#deck_filter_string = true
|
||||
#filter_string = true
|
||||
#syntax_help = true
|
||||
# filter_string = false
|
||||
@@ -1,42 +0,0 @@
|
||||
@page deck_search_syntax_help Deck Search Syntax Help
|
||||
|
||||
## Deck Search Syntax Help
|
||||
-----
|
||||
The search bar recognizes a set of special commands.<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.
|
||||
<dl>
|
||||
<dt>Display Name (The deck name, or the filename if the deck name isn't set):</dt>
|
||||
<dd>[red deck wins](#red deck wins) <small>(Any deck with a display name containing the words red, deck, and wins)</small></dd>
|
||||
<dd>["red deck wins"](#%22red deck wins%22) <small>(Any deck with a display name containing the exact phrase "red deck wins")</small></dd>
|
||||
|
||||
<dt>Deck <u>N</u>ame:</dt>
|
||||
<dd>[n:aggro](#n:aggro) <small>(Any deck with a name containing the word aggro)</small></dd>
|
||||
<dd>[n:red n:deck n:wins](#n:red n:deck n:wins) <small>(Any deck with a name containing the words red, deck, and wins)</small></dd>
|
||||
<dd>[n:"red deck wins"](#n:%22red deck wins%22) <small>(Any deck with a name containing the exact phrase "red deck wins")</small></dd>
|
||||
|
||||
<dt><u>F</u>ile Name:</dt>
|
||||
<dd>[f:aggro](#f:aggro) <small>(Any deck with a filename containing the word aggro)</small></dd>
|
||||
<dd>[f:red f:deck f:wins](#f:red f:deck f:wins) <small>(Any deck with a filename containing the words red, deck, and wins)</small></dd>
|
||||
<dd>[f:"red deck wins"](#f:%22red deck wins%22) <small>(Any deck with a filename containing the exact phrase "red deck wins")</small></dd>
|
||||
|
||||
<dt>Relative <u>P</u>ath (starting from the deck folder):</dt>
|
||||
<dd>[p:aggro](#p:aggro) <small>(Any deck that has "aggro" somewhere in its relative path)</small></dd>
|
||||
<dd>[p:edh/](#p:edh/) <small>(Any deck with "edh/" in its relative path, A.K.A. decks in the "edh" folder)</small></dd>
|
||||
|
||||
<dt>Deck Contents (Uses [card search expressions](#cardSearchSyntaxHelp)):</dt>
|
||||
<dd><a href="#[[plains]]">[[plains]]</a> <small>(Any deck that contains at least one card with "plains" in its name)</small></dd>
|
||||
<dd><a href="#[[t:legendary]]">[[t:legendary]]</a> <small>(Any deck that contains at least one legendary)</small></dd>
|
||||
<dd><a href="#[[t:legendary]]>5">[[t:legendary]]>5</a> <small>(Any card that contains at least 5 legendaries)</small></dd>
|
||||
<dd><a href="#[[]]:100">[[]]:100</a> <small>(Any deck that contains exactly 100 cards)</small></dd>
|
||||
|
||||
<dt>Negate:</dt>
|
||||
<dd>[soldier -aggro](#soldier -aggro) <small>(Any deck filename that contains "soldier", but not "aggro")</small></dd>
|
||||
|
||||
<dt>Branching:</dt>
|
||||
<dd>[t:aggro OR o:control](#t:aggro OR o:control) <small>(Any deck filename that contains either aggro or control)</small></dd>
|
||||
|
||||
<dt>Grouping:</dt>
|
||||
<dd><a href="#red -([[]]:100 or aggro)">red -([[]]:100 or aggro)</a> <small>(Any deck that has red in its filename but is not 100 cards or has aggro in its filename)</small></dd>
|
||||
|
||||
</dl>
|
||||
@@ -1,5 +1,3 @@
|
||||
@page search_syntax_help Search Syntax Help
|
||||
|
||||
## Search Syntax Help
|
||||
-----
|
||||
The search bar recognizes a set of special commands similar to some other card databases.<br>
|
||||
@@ -60,9 +58,4 @@ In this list of examples below, each entry has an explanation and can be clicked
|
||||
<dt>Grouping:</dt>
|
||||
<dd><a href="#t:angel -(angel or c:w)">t:angel -(angel or c:w)</a> <small>(Any angel that doesn't have angel in its name and isn't white)</small></dd>
|
||||
|
||||
<dt>Regular Expression:</dt>
|
||||
<dd>[/^fell/](#/^fell/) <small>(Any card name that begins with "fell")</small></dd>
|
||||
<dd>[o:/counter target .* spell/](#o:/counter target .* spell/) <small>(Any card text with "counter target *something* spell")</small></dd>
|
||||
<dd>[o:/for each .* and\/or .*/](#o:/for each .* and\/or .*/) <small>(/'s can be escaped with a \)</small></dd>
|
||||
|
||||
</dl>
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" width="102.5024mm" height="102.24421mm"
|
||||
viewBox="0 0 102.5024 102.24421" version="1.1"
|
||||
id="svg1"
|
||||
inkscape:version="1.4 (e7c3feb100, 2024-10-09)" sodipodi:docname="cog_wheel.svg"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview id="namedview1" pagecolor="#ffffff" bordercolor="#000000" borderopacity="0.25"
|
||||
inkscape:showpageshadow="2" inkscape:pageopacity="0.0" inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1" inkscape:document-units="mm" inkscape:zoom="0.66101291"
|
||||
inkscape:cx="146.74449" inkscape:cy="193.64221" inkscape:window-width="1829"
|
||||
inkscape:window-height="951" inkscape:window-x="0" inkscape:window-y="0"
|
||||
inkscape:window-maximized="1" inkscape:current-layer="layer1"/>
|
||||
<defs id="defs1"/>
|
||||
<g inkscape:label="Layer 1" inkscape:groupmode="layer" id="layer1" transform="translate(-66.148059,-97.377896)">
|
||||
<g id="g1" transform="translate(-165.09777,-82.009607)">
|
||||
<g id="g2" transform="matrix(0.26458333,0,0,0.26458333,64.983323,161.37858)">
|
||||
<path style="fill:#333333;stroke-width:94.4882"
|
||||
d="m 721.34301,94.413051 40.00966,29.763289 29.51933,-9.27053 14.63768,-46.840589 36.83817,0.48792 13.41787,46.108699 28.29952,9.5145 40.74155,-28.299519 29.0314,21.468599 -15.85748,47.08454 16.58937,23.66426 48.30432,-2.68358 12.93,34.88648 -41.71741,27.07971 -0.48792,29.27536 40.49763,26.10387 -10.2464,34.15459 -48.54834,-0.97584 -18.78502,23.42029 15.85749,45.37681 -28.29952,21.71256 -41.22947,-29.27536 -28.54348,9.75846 -13.66184,47.57246 -38.30194,-0.73188 -14.63768,-48.30435 -27.07971,-9.27054 -40.00966,29.27537 -30.25121,-20.49276 17.32125,-46.35266 -17.80918,-24.64009 -49.76812,3.17149 -11.22222,-34.64251 40.74155,-27.07971 0.48792,-30.00725 -41.71739,-27.32367 12.19807,-32.93479 48.30435,2.68358 20.24879,-24.6401 -17.32126,-47.08455 z"
|
||||
id="path1"/>
|
||||
<circle style="fill:#f9f9f9;stroke-width:72.1317" id="path2" cx="822.09906" cy="261.28262"
|
||||
r="83.434792"/>
|
||||
<circle style="fill:#4d4d4d;stroke-width:40.5147" id="circle2" cx="822.09906" cy="261.28262"
|
||||
r="46.863361"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.5 KiB |
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 12.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
|
||||
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
|
||||
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
|
||||
]>
|
||||
<svg version="1.1" id="Layer_1" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="460.5" height="531.74"
|
||||
viewBox="0 0 460.5 531.74" overflow="visible" enable-background="new 0 0 460.5 531.74" xml:space="preserve">
|
||||
<polygon fill="#918d8d" points="0.5,0.866 459.5,265.87 0.5,530.874 "/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 657 B |
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 12.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
|
||||
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
|
||||
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
|
||||
]>
|
||||
<svg version="1.1" id="Layer_1" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="531.74" height="460.5"
|
||||
viewBox="0 0 531.74 460.5" overflow="visible" enable-background="new 0 0 531.74 460.5" xml:space="preserve">
|
||||
<polygon fill="#918d8d" points="530.874,0.5 265.87,459.5 0.866,0.5 "/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 657 B |
@@ -1,47 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="169.34801mm"
|
||||
height="169.34801mm"
|
||||
viewBox="0 0 600 600"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="B.svg"
|
||||
inkscape:export-filename="B.svg"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1"/>
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:document-units="mm">
|
||||
<inkscape:page
|
||||
x="0"
|
||||
y="0"
|
||||
width="600"
|
||||
height="600"
|
||||
id="page2"
|
||||
margin="0"
|
||||
bleed="0"/>
|
||||
</sodipodi:namedview>
|
||||
<path
|
||||
id="Selection"
|
||||
fill="none"
|
||||
stroke="#000000"
|
||||
stroke-width="1"
|
||||
d="m 275,0.21 c 0,0 42,0 42,0 0,0 19,1.51 19,1.51 29.13,3.58 56.99,10.83 84,22.43 33.64,14.45 59.89,32.91 86.91,57.41 17.38,15.76 34.67,37.56 47.14,57.44 22.78,36.31 37.1,74.56 43.22,117 1.28,8.88 2.72,19.08 2.73,28 0,0 0,34 0,34 0,0 -0.91,10 -0.91,10 -2.36,32.29 -11.93,67.59 -25.4,97 -27.01,58.98 -70.49,105.42 -126.69,137.57 -34.3,19.63 -79.56,33.64 -119,36.52 0,0 -12,0.91 -12,0.91 0,0 -34,0 -34,0 0,0 -10,-0.91 -10,-0.91 -26.57,-1.94 -53.09,-8.27 -78,-17.67 C 163.49,569.9 134.12,553.46 109,532.57 79.87,508.33 54.41,478.39 36.31,445 -5.08,368.65 -11.86,276.57 18.05,195 47.85,113.75 113.21,48.92 194,18.42 213.55,11.04 236.32,5.43 257,2.43 Z"
|
||||
style="display:inline;fill:#ababab;fill-opacity:1"/>
|
||||
<path
|
||||
d="m 299.67889,84.945431 c -118.26949,0 -214.122988,83.892719 -214.122988,187.357619 0,58.63289 30.863828,110.90901 79.041488,145.28579 8.02961,5.77129 12.71356,15.13917 11.29165,25.0089 l -7.86234,55.37086 c -1.17098,8.02962 5.01851,15.22281 13.13176,15.22281 h 64.98968 v -46.83939 c 0,-3.68025 3.01111,-6.69135 6.69135,-6.69135 h 13.38268 c 3.68024,0 6.69135,3.0111 6.69135,6.69135 v 46.83939 h 53.53075 v -46.83939 c 0,-3.68025 3.01111,-6.69135 6.69134,-6.69135 h 13.38269 c 3.68023,0 6.69134,3.0111 6.69134,6.69135 v 46.83939 h 64.98967 c 8.11327,0 14.30275,-7.19319 13.13177,-15.22281 l -7.86234,-55.37086 c -1.4219,-9.78609 3.1784,-19.23761 11.29165,-25.0089 48.17767,-34.37678 79.0415,-86.6529 79.0415,-145.28579 0,-103.4649 -95.8535,-187.357619 -214.123,-187.357619 z M 219.38277,352.59917 c -29.52555,0 -53.53075,-24.0052 -53.53075,-53.53075 0,-29.52555 24.0052,-53.53075 53.53075,-53.53075 29.52555,0 53.53075,24.0052 53.53075,53.53075 0,29.52555 -24.0052,53.53075 -53.53075,53.53075 z m 160.59225,0 c -29.52555,0 -53.53075,-24.0052 -53.53075,-53.53075 0,-29.52555 24.0052,-53.53075 53.53075,-53.53075 29.52555,0 53.53075,24.0052 53.53075,53.53075 0,29.52555 -24.0052,53.53075 -53.53075,53.53075 z"
|
||||
id="path1"
|
||||
style="fill:#4d4d4d;fill-opacity:1;stroke:#000000;stroke-width:0.836419;stroke-opacity:1"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.2 KiB |
@@ -1,47 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
width="169.34801mm"
|
||||
height="169.34801mm"
|
||||
viewBox="0 0 600 600"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="B.svg"
|
||||
inkscape:export-filename="U.svg"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1"/>
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:document-units="mm">
|
||||
<inkscape:page
|
||||
x="0"
|
||||
y="0"
|
||||
width="600"
|
||||
height="600"
|
||||
id="page2"
|
||||
margin="0"
|
||||
bleed="0"/>
|
||||
</sodipodi:namedview>
|
||||
<path
|
||||
id="Selection"
|
||||
fill="none"
|
||||
stroke="#000000"
|
||||
stroke-width="1"
|
||||
d="m 275,0.21 c 0,0 42,0 42,0 0,0 19,1.51 19,1.51 29.13,3.58 56.99,10.83 84,22.43 33.64,14.45 59.89,32.91 86.91,57.41 17.38,15.76 34.67,37.56 47.14,57.44 22.78,36.31 37.1,74.56 43.22,117 1.28,8.88 2.72,19.08 2.73,28 0,0 0,34 0,34 0,0 -0.91,10 -0.91,10 -2.36,32.29 -11.93,67.59 -25.4,97 -27.01,58.98 -70.49,105.42 -126.69,137.57 -34.3,19.63 -79.56,33.64 -119,36.52 0,0 -12,0.91 -12,0.91 0,0 -34,0 -34,0 0,0 -10,-0.91 -10,-0.91 -26.57,-1.94 -53.09,-8.27 -78,-17.67 C 163.49,569.9 134.12,553.46 109,532.57 79.87,508.33 54.41,478.39 36.31,445 -5.08,368.65 -11.86,276.57 18.05,195 47.85,113.75 113.21,48.92 194,18.42 213.55,11.04 236.32,5.43 257,2.43 Z"
|
||||
style="display:inline;fill:#5f9f56;fill-opacity:1"/>
|
||||
<path
|
||||
d="m 488.52401,428.04591 -80.36527,-83.50228 h 30.81218 c 9.06362,0 17.08104,-4.61393 20.90363,-12.05153 3.82262,-7.41912 2.56521,-15.92714 -3.29949,-22.19282 l -78.59482,-83.87142 h 29.06188 c 9.15413,0 17.40291,-4.93688 20.98411,-12.55902 3.54092,-7.50219 1.87106,-16.23169 -4.26525,-22.22053 L 312.83499,83.240199 c -6.06588,-5.951919 -17.38282,-5.951919 -23.45873,0 L 178.44019,191.64831 c -6.13629,5.98884 -7.79612,14.71834 -4.26523,22.22053 3.58119,7.62214 11.84001,12.55902 20.99414,12.55902 h 29.06189 l -78.60489,83.88987 c -5.84454,6.25645 -7.10199,14.75525 -3.28944,22.18361 3.82262,7.42836 11.82996,12.04229 20.90363,12.04229 h 30.81222 l -80.36527,83.50228 c -6.03569,6.26567 -7.40379,14.84754 -3.58117,22.38663 3.7723,7.42839 12.07138,12.22682 21.13497,12.22682 h 129.63669 c 0,0 -36.12127,66.38546 0,62.75824 h 80.45578 c 33.50708,5.78651 0,-62.75824 0,-62.75824 h 129.63668 c 9.06361,0 17.36266,-4.79843 21.13499,-12.22682 3.82262,-7.53909 2.45452,-16.12096 -3.58117,-22.38663 z"
|
||||
id="ENVIR"
|
||||
style="fill:#3f6e3a;fill-opacity:1;stroke:#000000;stroke-width:1.09833;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.1 KiB |
@@ -1,47 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
width="169.34801mm"
|
||||
height="169.34801mm"
|
||||
viewBox="0 0 600 600"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="B.svg"
|
||||
inkscape:export-filename="B.svg"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1"/>
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:document-units="mm">
|
||||
<inkscape:page
|
||||
x="0"
|
||||
y="0"
|
||||
width="600"
|
||||
height="600"
|
||||
id="page2"
|
||||
margin="0"
|
||||
bleed="0"/>
|
||||
</sodipodi:namedview>
|
||||
<path
|
||||
id="Selection"
|
||||
fill="none"
|
||||
stroke="#000000"
|
||||
stroke-width="1"
|
||||
d="m 275,0.21 c 0,0 42,0 42,0 0,0 19,1.51 19,1.51 29.13,3.58 56.99,10.83 84,22.43 33.64,14.45 59.89,32.91 86.91,57.41 17.38,15.76 34.67,37.56 47.14,57.44 22.78,36.31 37.1,74.56 43.22,117 1.28,8.88 2.72,19.08 2.73,28 0,0 0,34 0,34 0,0 -0.91,10 -0.91,10 -2.36,32.29 -11.93,67.59 -25.4,97 -27.01,58.98 -70.49,105.42 -126.69,137.57 -34.3,19.63 -79.56,33.64 -119,36.52 0,0 -12,0.91 -12,0.91 0,0 -34,0 -34,0 0,0 -10,-0.91 -10,-0.91 -26.57,-1.94 -53.09,-8.27 -78,-17.67 C 163.49,569.9 134.12,553.46 109,532.57 79.87,508.33 54.41,478.39 36.31,445 -5.08,368.65 -11.86,276.57 18.05,195 47.85,113.75 113.21,48.92 194,18.42 213.55,11.04 236.32,5.43 257,2.43 Z"
|
||||
style="display:inline;fill:#c95e46;fill-opacity:1"/>
|
||||
<path
|
||||
style="display:inline;fill:#7e3525;fill-opacity:1;stroke:#000000;stroke-width:0.999129;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 278.25473,537.27772 c -22.36635,-1.29637 -48.78648,-8.31223 -69.74195,-18.51997 -47.30139,-23.04123 -75.19872,-59.72004 -85.45343,-112.35234 -2.77041,-14.21911 -2.51753,-48.32296 0.4755,-64.1246 4.84373,-25.57244 17.23939,-55.03329 30.65191,-72.85059 3.74877,-4.97991 16.33133,-18.11906 30.23479,-31.57223 13.09764,-12.67346 26.64745,-26.67202 30.11069,-31.10792 16.66894,-21.35045 26.46602,-44.71272 29.68313,-70.78286 1.93489,-15.67951 0.37962,-45.867231 -3.5802,-69.491071 -0.58906,-3.51428 0.36584,-3.52724 11.47726,-0.15583 36.51454,11.0792 67.37028,34.791071 89.32423,68.643431 9.96686,15.36862 20.07787,39.31263 24.78919,58.70364 2.23257,9.18886 2.53252,44.73878 0.46396,54.98571 -0.75708,3.75024 -1.10086,7.09425 -0.76396,7.43114 1.5021,1.5021 14.63666,-6.65479 21.98002,-13.65016 10.59844,-10.09621 14.32693,-17.61354 15.94714,-32.15254 l 1.16788,-10.47988 3.4626,3.95724 c 26.80954,30.6392 41.75268,56.11528 54.11775,92.26358 11.02075,32.21825 14.93902,62.79297 12.47422,97.33768 -1.88493,26.41774 -10.16486,50.6958 -24.95555,73.17369 -6.31625,9.59901 -30.86306,34.05172 -40.40914,40.25423 -23.44452,15.23295 -50.15355,25.25695 -77.26806,28.99903 -12.48732,1.72336 -38.04339,2.42637 -54.18798,1.49062 z m 48.34948,-30.34196 c 30.78066,-8.0491 53.53846,-30.12825 59.69792,-57.9177 2.48916,-11.23027 2.26087,-34.25269 -0.43747,-44.11787 -5.3998,-19.74181 -9.72931,-26.61651 -30.6237,-48.62658 -16.92925,-17.8332 -21.73398,-24.64464 -25.45673,-36.0889 -2.38622,-7.33554 -2.63126,-9.53814 -2.57644,-23.15876 0.0334,-8.27872 0.486,-17.4607 1.00593,-20.40441 0.75887,-4.29636 0.66928,-5.45812 -0.45409,-5.88919 -2.12997,-0.81736 -16.25071,4.45522 -21.90917,8.1807 -25.69349,16.91641 -42.62753,52.30879 -40.22917,84.07948 0.39046,5.17228 0.2831,8.79277 -0.26071,8.79277 -1.78935,0 -13.49435,-13.46378 -15.34792,-17.65406 -1.03171,-2.33236 -2.15967,-6.42651 -2.50657,-9.09812 -1.00143,-7.71233 -1.60778,-8.14619 -5.46339,-3.90915 -13.31687,14.63425 -24.58113,35.69359 -29.53283,55.21379 -11.75615,46.34414 2.14731,84.38956 37.55813,102.77397 16.56338,8.59931 29.2427,11.25369 51.26679,10.73261 12.58064,-0.29766 17.41119,-0.85366 25.26942,-2.90858 z"
|
||||
id="path8"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 4.2 KiB |
@@ -1,48 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
width="169.34801mm"
|
||||
height="169.34801mm"
|
||||
viewBox="0 0 600 600"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="U.svg"
|
||||
inkscape:export-filename="U.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1"/>
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:document-units="mm">
|
||||
<inkscape:page
|
||||
x="0"
|
||||
y="0"
|
||||
width="600"
|
||||
height="600"
|
||||
id="page2"
|
||||
margin="0"
|
||||
bleed="0"/>
|
||||
</sodipodi:namedview>
|
||||
<path
|
||||
id="Selection"
|
||||
fill="none"
|
||||
stroke="#000000"
|
||||
stroke-width="1"
|
||||
d="m 275,0.21 c 0,0 42,0 42,0 0,0 19,1.51 19,1.51 29.13,3.58 56.99,10.83 84,22.43 33.64,14.45 59.89,32.91 86.91,57.41 17.38,15.76 34.67,37.56 47.14,57.44 22.78,36.31 37.1,74.56 43.22,117 1.28,8.88 2.72,19.08 2.73,28 0,0 0,34 0,34 0,0 -0.91,10 -0.91,10 -2.36,32.29 -11.93,67.59 -25.4,97 -27.01,58.98 -70.49,105.42 -126.69,137.57 -34.3,19.63 -79.56,33.64 -119,36.52 0,0 -12,0.91 -12,0.91 0,0 -34,0 -34,0 0,0 -10,-0.91 -10,-0.91 -26.57,-1.94 -53.09,-8.27 -78,-17.67 C 163.49,569.9 134.12,553.46 109,532.57 79.87,508.33 54.41,478.39 36.31,445 -5.08,368.65 -11.86,276.57 18.05,195 47.85,113.75 113.21,48.92 194,18.42 213.55,11.04 236.32,5.43 257,2.43 Z"
|
||||
style="display:inline;fill:#4a8fd8;fill-opacity:1"/>
|
||||
<path
|
||||
style="display:inline;fill:#3266af;fill-opacity:1;stroke:#000000;stroke-width:1.06525;stroke-opacity:1"
|
||||
d="m 275.20608,536.5693 c -58.69596,-9.5447 -107.01545,-50.69962 -125.66779,-107.0344 -9.25532,-27.95342 -10.39669,-58.82111 -3.22092,-87.1088 5.31307,-20.94475 9.06296,-28.00552 81.87785,-154.17 38.54798,-66.79109 70.40461,-121.77997 70.79251,-122.19751 1.00535,-1.08215 140.3595,240.63696 145.26785,251.97682 8.6735,20.03855 12.6923,39.82747 12.6923,62.49805 0,44.25387 -16.70161,83.24077 -48.85852,114.0514 -21.46938,20.57055 -45.69209,33.39124 -76.46586,40.47213 -12.83139,2.95245 -42.64639,3.75165 -56.41742,1.51231 z"
|
||||
id="path2"
|
||||
sodipodi:nodetypes="ssssssssss"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.7 KiB |
@@ -1,47 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="169.34801mm"
|
||||
height="169.34801mm"
|
||||
viewBox="0 0 600 600"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
sodipodi:docname="W.svg"
|
||||
inkscape:export-filename="W.png"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1"/>
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:document-units="mm">
|
||||
<inkscape:page
|
||||
x="0"
|
||||
y="0"
|
||||
width="600"
|
||||
height="600"
|
||||
id="page2"
|
||||
margin="0"
|
||||
bleed="0"/>
|
||||
</sodipodi:namedview>
|
||||
<path
|
||||
id="Selection"
|
||||
fill="none"
|
||||
stroke="#000000"
|
||||
stroke-width="1"
|
||||
d="m 275,0.21 c 0,0 42,0 42,0 0,0 19,1.51 19,1.51 29.13,3.58 56.99,10.83 84,22.43 33.64,14.45 59.89,32.91 86.91,57.41 17.38,15.76 34.67,37.56 47.14,57.44 22.78,36.31 37.1,74.56 43.22,117 1.28,8.88 2.72,19.08 2.73,28 0,0 0,34 0,34 0,0 -0.91,10 -0.91,10 -2.36,32.29 -11.93,67.59 -25.4,97 -27.01,58.98 -70.49,105.42 -126.69,137.57 -34.3,19.63 -79.56,33.64 -119,36.52 0,0 -12,0.91 -12,0.91 0,0 -34,0 -34,0 0,0 -10,-0.91 -10,-0.91 -26.57,-1.94 -53.09,-8.27 -78,-17.67 C 163.49,569.9 134.12,553.46 109,532.57 79.87,508.33 54.41,478.39 36.31,445 -5.08,368.65 -11.86,276.57 18.05,195 47.85,113.75 113.21,48.92 194,18.42 213.55,11.04 236.32,5.43 257,2.43 Z"
|
||||
style="display:inline;fill:#ffefb3;fill-opacity:1"/>
|
||||
<path
|
||||
id="circle8"
|
||||
d="M 387.28106,302.711 A 85.962512,85.962512 0 0 1 301.31852,388.67353 85.962512,85.962512 0 0 1 215.35597,302.711 85.962512,85.962512 0 0 1 301.31852,216.74844 85.962512,85.962512 0 0 1 387.28106,302.711 Z M 191.75349,358.6114 143.05798,460.97151 245.4181,412.27601 A 121.73882,121.73882 0 0 1 191.75349,358.6114 Z M 178.33753,302.711 c 0,-13.16763 2.23687,-25.83857 5.96271,-38.01232 L 77.71657,302.711 184.30024,340.7233 a 119.25435,119.25435 0 0 1 -5.96271,-38.0123 z m 178.8814,109.56501 102.36011,48.6955 -48.6955,-102.36011 a 121.73882,121.73882 0 0 1 -53.66461,53.66461 z m -55.90041,13.41595 c -13.16762,0 -26.0869,-2.23687 -38.01232,-5.9627 l 38.01232,106.58368 38.01231,-106.58368 a 119.25435,119.25435 0 0 1 -38.01231,5.9627 z m 109.56502,-178.88139 48.6955,-102.36012 -102.36011,48.69551 a 122.98106,122.98106 0 0 1 53.66461,53.66461 z M 245.66643,193.14596 143.30658,144.45045 192.00209,246.81057 a 121.73882,121.73882 0 0 1 53.66434,-53.66461 z M 524.92046,302.711 418.33679,264.69868 a 119.25435,119.25435 0 0 1 0,76.02462 z M 301.31852,179.73 c 13.16761,0 26.0869,2.23688 38.01231,5.96271 L 301.31852,79.109036 263.3062,185.69271 A 119.25435,119.25435 0 0 1 301.31852,179.73 Z"
|
||||
style="fill:#b4a35e;fill-opacity:1;stroke:#000000;stroke-width:1.09833;stroke-dasharray:none;stroke-opacity:1"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.3 KiB |
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px"
|
||||
viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve">
|
||||
<metadata> Svg Vector Icons : http://www.onlinewebfonts.com/icon </metadata>
|
||||
<g><path d="M586.9,373.6l95.6-84.4c-49.6-39.2-129.4-79.1-198.2-79.1c-134.9,0-248.2,90.5-280.2,212.8L10.6,374.5C64.4,168.3,255.2,15.8,482.5,15.8c126.7,0,258.8,63.7,345.4,141.4l90.8-80.1L990,479.6L586.9,373.6z M317.5,710.8c49.6,39.2,129.4,79.1,198.2,79.1c134.9,0,248.2-90.5,280.2-212.8l193.5,48.5c-53.7,206.2-244.6,358.7-471.9,358.7c-126.7,0-258.8-63.7-345.4-141.4l-90.8,80.1L10,520.4l403.1,106L317.5,710.8z"/></g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 797 B |
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="1200pt" height="1200pt" version="1.1" viewBox="0 0 1200 1200" xmlns="http://www.w3.org/2000/svg">
|
||||
<path transform="scale(50)" d="m17 16h4v-8h-4" fill="none" stroke="#000" stroke-miterlimit="10" stroke-width="2"/>
|
||||
<path transform="scale(50)" d="m12 8h-9v8h9" fill="none" stroke="#000" stroke-miterlimit="10" stroke-width="2"/>
|
||||
<path transform="scale(50)" d="m6 12h5" fill="none" stroke="#000" stroke-miterlimit="10" stroke-width="2"/>
|
||||
<path transform="scale(50)" d="m20 4h-2c-1.1 0-2 0.9-2 2v12c0 1.1 0.9 2 2 2h2" fill="none" stroke="#000"
|
||||
stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2"/>
|
||||
<path transform="scale(50)" d="m12 20h2c1.1 0 2-0.9 2-2v-12c0-1.1-0.9-2-2-2h-2" fill="none" stroke="#000"
|
||||
stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 875 B |
@@ -1,25 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
|
||||
<svg height="800"
|
||||
width="800"
|
||||
version="1.1"
|
||||
id="_x32_"
|
||||
viewBox="0 0 512 512"
|
||||
xml:space="preserve"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs id="defs1"/>
|
||||
<style type="text/css"
|
||||
id="style1">
|
||||
.st0{fill:#64C0FF;stroke:black;stroke-width:3;stroke-miterlimit:4;stroke-opacity:1}
|
||||
</style>
|
||||
<g id="g1"
|
||||
transform="matrix(0.87097097,0,0,1.0008579,38.609049,-0.21963163)"
|
||||
style="stroke-width:3.42738;stroke-dasharray:none">
|
||||
<path class="st0"
|
||||
d="M 512,255.995 277.045,65.394 v 103.574 c -17.255,0 -36.408,0 -57.542,0 -208.59,0 -249.35,153.44 -201.394,266.128 9.586,-103.098 142.053,-100.701 237.358,-100.701 7.247,0 14.446,0 21.578,0 v 112.211 z"
|
||||
id="path1"
|
||||
style="stroke-width:20;stroke:#000000;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 9.7 KiB |
|
Before Width: | Height: | Size: 7.6 KiB |
|
Before Width: | Height: | Size: 7.4 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 227 KiB |
|
Before Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 136 KiB |
@@ -1,222 +1,99 @@
|
||||
<tips>
|
||||
<tip>
|
||||
<title>Tip of the Day</title>
|
||||
<text>Tip of the Day is a feature to Cockatrice that allows users to get information about the newest features of the program and some of the most commonly asked questions!
|
||||
Check back in with major updates for new tips to be added or old tips to be updated as features are added or expanded upon!
|
||||
</text>
|
||||
<image>tip_of_the_day.png</image>
|
||||
<date>2025-02-10</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>Join the Community</title>
|
||||
<text>You can join the community to find games, interact with other players, suggest new 'Tips of the Day' and provide user feedback to the development or support teams on <a href="https://discord.gg/3Z9yzmA">Discord</a>!</text>
|
||||
<image>discord.png</image>
|
||||
<date>2025-02-09</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>Reporting Bugs and Requesting Features</title>
|
||||
<text>If you encounter a bug while using Cockatrice, you can report the bug to and request the feature from the development team via <a href="https://github.com/cockatrice/cockatrice/issues">GitHub<a></text>
|
||||
<image>github_logo.png</image>
|
||||
<date>2025-02-09</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>FAQ/Troubleshooting Wiki</title>
|
||||
<text>You can find answers to the most common questions and some helpful Cockatrice troubleshooting over on the <a href="https://github.com/cockatrice/cockatrice/wiki">GitHub wiki<a></text>
|
||||
<image>cockatrice_wiki.png</image>
|
||||
<date>2018-03-01</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>Register for a Server</title>
|
||||
<text>Click on either Cockatrice (Windows) or Actions (Mac) and then Register to server... When the dialogue appears, fill out the desired server information.</text>
|
||||
<image>cockatrice_register.png</image>
|
||||
<date>2018-03-01</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>Filtering Games</title>
|
||||
<text>Don't see an open game or want to see a smaller selection? Use the Game Filters to change your horizon!</text>
|
||||
<image>filter_games.png</image>
|
||||
<date>2025-02-09</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>Common Shortcuts</title>
|
||||
<text>You can find a full list of default shortcuts <a href="https://github.com/Cockatrice/Cockatrice/wiki/Custom-Keyboard-Shortcuts">on the wiki</a> or in Settings -> Shortcuts, but a short list:
|
||||
<ul>
|
||||
<li>Roll a die: CMD/CTRL + I</li>
|
||||
<li>Mulligan: CMD/CTRL + M</li>
|
||||
<li>Draw 1 / X card(s): CMD/CTRL + D / E</li>
|
||||
<li>Undo a draw: CMD/CTRL + SHIFT + D</li>
|
||||
<li>View Library / Sideboard: F3 / CMD/CTRL + F3</li>
|
||||
<li>Change Life: CMD/CTRL + L</li>
|
||||
<li>Show Card Info: Middle Mouse Click</li>
|
||||
</ul>
|
||||
All shortcuts can be customized via Cockatrice -> Settings -> Shortcuts!
|
||||
</text>
|
||||
<image>shortcuts.png</image>
|
||||
<date>2025-02-09</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>Power and Toughness</title>
|
||||
<text>You can add and subtract to a creature's stats.
|
||||
With a card selected, with the following keybindings:
|
||||
|
||||
<ul>
|
||||
<li>Set P/T to any value: CTRL + P</li>
|
||||
<li>+1 or -1 to both to P/T: CMD/CTRL + ALT + '+' or '-'</li>
|
||||
<li>+1 or -1 to Power Only: CMD/CTRL + '+' or '-'</li>
|
||||
<li>+1 or -1 to Toughness Only: ALT + '+' or '-'</li>
|
||||
<li>Set P/T to Default: CMD/CTRL + ALT + 0</li>
|
||||
</ul>
|
||||
All shortcuts can be customized via Cockatrice -> Settings -> Shortcuts!
|
||||
</text>
|
||||
<image>setpt.png</image>
|
||||
<date>2025-02-09</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>Drawing Arrows</title>
|
||||
<text>You can draw arrows of different color by holding a combination of keys!
|
||||
|
||||
<ul>
|
||||
<li>Right Click: Red Arrow</li>
|
||||
<li>SHIFT + Right Click: Green Arrow</li>
|
||||
<li>ALT + Right Click: Blue Arrow</li>
|
||||
<li>CMD/CTRL + Right Click: Yellow Arrow</li>
|
||||
</ul>
|
||||
</text>
|
||||
<image>arrows.png</image>
|
||||
<date>2018-03-01</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>General Etiquette</title>
|
||||
<text>When playing on Cockatrice there are general "rules of engagement" for a better play experience for all players.
|
||||
The following are some of the expectations a player should reasonably expect for how to operate smooth and enjoyable games:
|
||||
<ul>
|
||||
<li>Have a "Rule 0" conversation pre-game with your fellow players on the expectations of the game including deck strength, house rules (e.g. no take backs and "may is not must"), etc.</li>
|
||||
<li>When rolling your die for turn order, it is often best to create a token with the text of your roll (using CTRL + T and typing the number into "Name") and then tap this token when created to show that you have resolved your mulligans and are ready to start the game.</li>
|
||||
<li>Use the phases and steps trackers on the left of the client to show others where in the turn you are and announce when moving between them. (Double Click for the action of this button)</li>
|
||||
<li>When your turn is over leave it on your end step and DO NOT HIT PASS. Allow other players to respond if they can, and then if not, let the next player pass to themselves.</li>
|
||||
<li>Please treat others kindly and respect as per <a href="https://cockatrice.us/terms.php">our Terms of Service</a>.</li>
|
||||
</ul>
|
||||
</text>
|
||||
<image>token.png</image>
|
||||
<date>2025-02-10</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>Flip of the Coin</title>
|
||||
<text>You can flip a coin instead of rolling a die by rolling a 2 sided die instead!</text>
|
||||
<image>coin_flip.png</image>
|
||||
<date>2018-03-01</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>Upload Custom Avatar</title>
|
||||
<text>Want to show off your hippo avatar? Need to update your password? Check out the Accounts Tab for more info!</text>
|
||||
<image>accounts_tab.png</image>
|
||||
<date>2018-03-01</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>Player Icon Key</title>
|
||||
<text>Besides your name is a player icon, this is a key for what they mean:
|
||||
<ul>
|
||||
<li>Flag: Country of Origin Player Selected</li>
|
||||
<li>Purple Heart: Donator (<a href="https://cockatrice.us/donate">Help support us and donate here!</a>)</li>
|
||||
<li>Gold Star: VIP (Special Admin Given Role)</li>
|
||||
<li>Brown Gavel (Hammer): Judge / Rule's Lawyer</li>
|
||||
<li>Black/White Pawn: Moderator (Support for Client Issues)</li>
|
||||
<li>Red: Administrator (Sever Operators)</li>
|
||||
</ul>
|
||||
</text>
|
||||
<image>pawns.png</image>
|
||||
<date>2025-02-09</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>Changing Themes</title>
|
||||
<text>Did you know Cockatrice has custom themes? You can either <a href="https://github.com/Cockatrice/Cockatrice/wiki/Themes">create one yourself</a> or use one of the several preloaded ones! Go to Settings->Appearance and try them out!</text>
|
||||
<image>themes.png</image>
|
||||
<date>2018-03-01</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>Face Down Cards</title>
|
||||
<text>You can hold Shift while dragging or clicking on a card to have it enter play face down.
|
||||
You can also hold CTRL + SHIFT and click and drag from your library to move bottom card face down as well!
|
||||
</text>
|
||||
<image>face_down.png</image>
|
||||
<date>2025-02-09</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>Counter expressions</title>
|
||||
<text>When setting a counter value, you can type a math expression in the box and the counter will be set to the result.<br>The "x" variable contains the current counter value.</text>
|
||||
<image>counter_expression.png</image>
|
||||
<date>2019-02-02</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>Select Multiple Cards</title>
|
||||
<text>You can click and drag in any zone in order to highlight all cards within the created box.
|
||||
You can also hold CMD/CTRL and clik or click and drag to maintain other previously selected cards while adding others!
|
||||
You can move, alter and attach multiple highlighted cards at the same time!
|
||||
Other useful multi-select keybindings:
|
||||
<ul>
|
||||
<li>Select All Cards in Zone: CMD/CTRL + A</li>
|
||||
<li>Select All Cards in Column: CMD/CTRL + SHIFT + C</li>
|
||||
<li>Select All Cards in Row: CMD/CTRL + SHIFT + X</li>
|
||||
</ul>
|
||||
</text>
|
||||
<image>highlight_cards.png</image>
|
||||
<date>2025-02-09</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>Auto Cascade and Search Parameters</title>
|
||||
<text>You can use the default keybind of CMD/CTRL + SHIFT + Y in order to perform auto cascade or similar effects from your library using Scryfall search syntax.
|
||||
If you are unfamiliar with the syntax you may find it by opening a deck in deck editor and clicking the "i" next to the search bar in order to pull up a list of syntax commands.
|
||||
This same syntax can be used in the deck editor search bar as well to help you find the best cards for your decks!
|
||||
</text>
|
||||
<image>syntax_help.png</image>
|
||||
<date>2025-02-09</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>Visual Deck Storage and Tags</title>
|
||||
<text>You can now view your saved decks visually with integrated folder,tags and filter support!
|
||||
Pro Tip: If you want to use emoji's press WinKey + '.' or CTRL + CMD + SPACE on Windows or Mac respectively!
|
||||
</text>
|
||||
<image>visual_deck_tags.png</image>
|
||||
<date>2025-02-09</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>Card Selector And Card Preferences</title>
|
||||
<text>Cockatrice's deck editor now has the ability for players to bling out their decks by selecting the arts for cards on a per-card basis!
|
||||
You can also have multiple printings of the same card in your deck if you so choose!
|
||||
Not only that, other players will see the arts you have chosen by default!
|
||||
If you want to disable this feature for other players: Settings -> Appearance -> Select "Override all card art with personal set preference"
|
||||
</text>
|
||||
<image>card_select.png</image>
|
||||
<date>2025-02-10</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>EDHREC Integration</title>
|
||||
<text>We now have in-client integration for EDHREC, which allows you to right-click on any card name in the deck editor in order to bring up the contextual menu for the card.</text>
|
||||
<image>edhrec.png</image>
|
||||
<date>2025-02-10</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>Add Cards to Deck</title>
|
||||
<text>You can now right-click anywhere on a card in any card info view in order to add it to any decks you have open in your tabs.</text>
|
||||
<image>add_card.png</image>
|
||||
<date>2025-02-10</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>Update Client and Card Database</title>
|
||||
<text>You can update your client by going to Help and selecting whichever you wish to update.
|
||||
Client Update: Updates the client (if available) for new features, fixes and changes.
|
||||
Card Update: Updates card sources for spoilers and new card printings.
|
||||
Updating your card sources can often fix issues of cards not working or displaying properly, if not, go to Cockatrice -> Settings -> Card Sources -> Update Spoilers
|
||||
</text>
|
||||
<image>updates.png</image>
|
||||
<date>2025-02-10</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>Expand Card View Window</title>
|
||||
<text>Double click on the title bar of the card view window to expand it! Double click again to shrink it back down.
|
||||
You can configure the initial and expanded heights of the window in the settings, under "Appearance".
|
||||
</text>
|
||||
<image>expand_card_view.png</image>
|
||||
<date>2025-02-27</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>Tip of the Day</title>
|
||||
<text>Tip of the Day is a new feature to Cockatrice that allows users to get information about the newest features of the program and some of the most commonly asked questions!</text>
|
||||
<image>tip_of_the_day.png</image>
|
||||
<date>2018-03-01</date>
|
||||
</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>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>Reporting Bugs</title>
|
||||
<text>If you encounter a bug while using Cockatrice, you can report the bug to the development team via <a href="https://github.com/cockatrice/cockatrice/issues">GitHub<a></text>
|
||||
<image>github_logo.png</image>
|
||||
<date>2018-03-01</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>FAQ/Troubleshooting Wiki</title>
|
||||
<text>You can find answers to the most common questions and some helpful Cockatrice toubleshooting over on the <a href="https://github.com/cockatrice/cockatrice/wiki">GitHub wiki<a></text>
|
||||
<image>cockatrice_wiki.png</image>
|
||||
<date>2018-03-01</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>Register for a Server</title>
|
||||
<text>Click on either Cockatrice (Windows) or Actions (Mac) and then Register to server... When the dialogue appears, fill out the desired server information.</text>
|
||||
<image>cockatrice_register.png</image>
|
||||
<date>2018-03-01</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>Drawing Arrows</title>
|
||||
<text>You can draw arrows of different color by holding a combination of keys!
|
||||
Right Click: Red Arrow
|
||||
Shift + Right Click: Green Arrow
|
||||
Alt + Right Click: Blue Arrow
|
||||
Cmd + Right Click: Yellow Arrow
|
||||
</text>
|
||||
<image>arrows.png</image>
|
||||
<date>2018-03-01</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>Filtering Games</title>
|
||||
<text>Don't see all the active games? Want to see a smaller selection? Use the Game Filters to change your horizon</text>
|
||||
<image>filter_games.png</image>
|
||||
<date>2018-03-01</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>Upload Custom Avatar</title>
|
||||
<text>Want to show off your hippo avatar? Need to update your password? Check out the Accounts Tab for more info!</text>
|
||||
<image>accounts_tab.png</image>
|
||||
<date>2018-03-01</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>Common Shortcuts</title>
|
||||
<text>You can find a full list of shortcuts <a href="https://github.com/Cockatrice/Cockatrice/wiki/Custom-Keyboard-Shortcuts">on the wiki</a>, but a short list:
|
||||
<br>Roll a die: CTRL + I
|
||||
<br>Mulligan: CTRL + M
|
||||
<br>Draw a card: CTRL + D
|
||||
<br>Undo a draw: CTRL + SHIFT + D
|
||||
<br>View Sideboard: CTRL + F3
|
||||
<br>Change Life: CTRL + L
|
||||
<br>All shortcuts can be customized via Settings->Shortcuts!
|
||||
</text>
|
||||
<image>shortcuts.png</image>
|
||||
<date>2018-03-01</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>Changing Themes</title>
|
||||
<text>Did you know Cockatrice has custom themes? You can either <a href="https://github.com/Cockatrice/Cockatrice/wiki/Themes">create one yourself</a> or use one of the several pre-loaded ones! Go to Settings->Appearance and try them out!</text>
|
||||
<image>themes.png</image>
|
||||
<date>2018-03-01</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>Flip of the Coin</title>
|
||||
<text>You can flip a coin instead of rolling a die by rolling a 2 sided die instead!</text>
|
||||
<image>coin_flip.png</image>
|
||||
<date>2018-03-01</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>Face Down Cards</title>
|
||||
<text>You can hold Shift while dragging or clicking on a card to have it enter play face down</text>
|
||||
<image>face_down.png</image>
|
||||
<date>2018-03-01</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>Counter expressions</title>
|
||||
<text>When setting a counter value, you can type a math expression in the box and the counter will be set to the result.<br>The "x" variable contains the current counter value.</text>
|
||||
<image>counter_expression.png</image>
|
||||
<date>2019-02-02</date>
|
||||
</tip>
|
||||
<tip>
|
||||
<title>Power and Toughness</title>
|
||||
<text>You can add and subtract to a creature's stats.<br>With a card selected, set the power and toughness ( default: ctrl + p ) and enter +3/-1 to increase power by three while decreasing toughness by one.<br>You can also reset it to the original value ( default: ctrl + alt + 0 ).</text>
|
||||
<image>setpt.png</image>
|
||||
<date>2019-03-02</date>
|
||||
</tip>
|
||||
</tips>
|
||||
|
||||
@@ -1,208 +0,0 @@
|
||||
#include "card_info.h"
|
||||
|
||||
#include "../picture_loader/picture_loader.h"
|
||||
#include "../settings/cache_settings.h"
|
||||
#include "card_relation.h"
|
||||
#include "game_specific_terms.h"
|
||||
#include "printing_info.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QRegularExpression>
|
||||
#include <QSharedPointer>
|
||||
#include <QString>
|
||||
#include <QVariant>
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
class CardRelation;
|
||||
class CardSet;
|
||||
class CardInfo;
|
||||
|
||||
using CardInfoPtr = QSharedPointer<CardInfo>;
|
||||
|
||||
CardInfo::CardInfo(const QString &_name,
|
||||
const QString &_text,
|
||||
bool _isToken,
|
||||
QVariantHash _properties,
|
||||
const QList<CardRelation *> &_relatedCards,
|
||||
const QList<CardRelation *> &_reverseRelatedCards,
|
||||
SetToPrintingsMap _sets,
|
||||
bool _cipt,
|
||||
bool _landscapeOrientation,
|
||||
int _tableRow,
|
||||
bool _upsideDownArt)
|
||||
: name(_name), text(_text), isToken(_isToken), properties(std::move(_properties)), relatedCards(_relatedCards),
|
||||
reverseRelatedCards(_reverseRelatedCards), setsToPrintings(std::move(_sets)), cipt(_cipt),
|
||||
landscapeOrientation(_landscapeOrientation), tableRow(_tableRow), upsideDownArt(_upsideDownArt)
|
||||
{
|
||||
simpleName = CardInfo::simplifyName(name);
|
||||
|
||||
refreshCachedSetNames();
|
||||
}
|
||||
|
||||
CardInfoPtr CardInfo::newInstance(const QString &_name)
|
||||
{
|
||||
return newInstance(_name, QString(), false, QVariantHash(), QList<CardRelation *>(), QList<CardRelation *>(),
|
||||
SetToPrintingsMap(), false, false, 0, false);
|
||||
}
|
||||
|
||||
CardInfoPtr CardInfo::newInstance(const QString &_name,
|
||||
const QString &_text,
|
||||
bool _isToken,
|
||||
QVariantHash _properties,
|
||||
const QList<CardRelation *> &_relatedCards,
|
||||
const QList<CardRelation *> &_reverseRelatedCards,
|
||||
SetToPrintingsMap _sets,
|
||||
bool _cipt,
|
||||
bool _landscapeOrientation,
|
||||
int _tableRow,
|
||||
bool _upsideDownArt)
|
||||
{
|
||||
CardInfoPtr ptr(new CardInfo(_name, _text, _isToken, std::move(_properties), _relatedCards, _reverseRelatedCards,
|
||||
_sets, _cipt, _landscapeOrientation, _tableRow, _upsideDownArt));
|
||||
ptr->setSmartPointer(ptr);
|
||||
|
||||
for (const auto &printings : _sets) {
|
||||
for (const PrintingInfo &printing : printings) {
|
||||
printing.getSet()->append(ptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void CardInfo::addToSet(const CardSetPtr &_set, const PrintingInfo _info)
|
||||
{
|
||||
if (!_set->contains(smartThis)) {
|
||||
_set->append(smartThis);
|
||||
}
|
||||
if (!setsToPrintings[_set->getShortName()].contains(_info)) {
|
||||
setsToPrintings[_set->getShortName()].append(_info);
|
||||
}
|
||||
|
||||
refreshCachedSetNames();
|
||||
}
|
||||
|
||||
void CardInfo::combineLegalities(const QVariantHash &props)
|
||||
{
|
||||
QHashIterator<QString, QVariant> it(props);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
if (it.key().startsWith("format-")) {
|
||||
smartThis->setProperty(it.key(), it.value().toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CardInfo::refreshCachedSetNames()
|
||||
{
|
||||
QStringList setList;
|
||||
// update the cached list of set names
|
||||
for (const auto &printings : setsToPrintings) {
|
||||
for (const auto &printing : printings) {
|
||||
if (printing.getSet()->getEnabled()) {
|
||||
setList << printing.getSet()->getShortName();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
setsNames = setList.join(", ");
|
||||
}
|
||||
|
||||
QString CardInfo::simplifyName(const QString &name)
|
||||
{
|
||||
static const QRegularExpression spaceOrSplit("(\\s+|\\/\\/.*)");
|
||||
static const QRegularExpression nonAlnum("[^a-z0-9]");
|
||||
|
||||
QString simpleName = name.toLower();
|
||||
|
||||
// remove spaces and right halves of split cards
|
||||
simpleName.remove(spaceOrSplit);
|
||||
|
||||
// So Aetherling would work, but not Ætherling since 'Æ' would get replaced
|
||||
// with nothing.
|
||||
simpleName.replace("æ", "ae");
|
||||
|
||||
// Replace Jötun Grunt with Jotun Grunt.
|
||||
simpleName = simpleName.normalized(QString::NormalizationForm_KD);
|
||||
|
||||
// remove all non alphanumeric characters from the name
|
||||
simpleName.remove(nonAlnum);
|
||||
return simpleName;
|
||||
}
|
||||
|
||||
const QChar CardInfo::getColorChar() const
|
||||
{
|
||||
QString colors = getColors();
|
||||
switch (colors.size()) {
|
||||
case 0:
|
||||
return QChar();
|
||||
case 1:
|
||||
return colors.at(0);
|
||||
default:
|
||||
return QChar('m');
|
||||
}
|
||||
}
|
||||
|
||||
void CardInfo::resetReverseRelatedCards2Me()
|
||||
{
|
||||
for (CardRelation *cardRelation : this->getReverseRelatedCards2Me()) {
|
||||
cardRelation->deleteLater();
|
||||
}
|
||||
reverseRelatedCardsToMe = QList<CardRelation *>();
|
||||
}
|
||||
|
||||
// Back-compatibility methods. Remove ASAP
|
||||
const QString CardInfo::getCardType() const
|
||||
{
|
||||
return getProperty(Mtg::CardType);
|
||||
}
|
||||
void CardInfo::setCardType(const QString &value)
|
||||
{
|
||||
setProperty(Mtg::CardType, value);
|
||||
}
|
||||
const QString CardInfo::getCmc() const
|
||||
{
|
||||
return getProperty(Mtg::ConvertedManaCost);
|
||||
}
|
||||
const QString CardInfo::getColors() const
|
||||
{
|
||||
return getProperty(Mtg::Colors);
|
||||
}
|
||||
void CardInfo::setColors(const QString &value)
|
||||
{
|
||||
setProperty(Mtg::Colors, value);
|
||||
}
|
||||
const QString CardInfo::getLoyalty() const
|
||||
{
|
||||
return getProperty(Mtg::Loyalty);
|
||||
}
|
||||
const QString CardInfo::getMainCardType() const
|
||||
{
|
||||
return getProperty(Mtg::MainCardType);
|
||||
}
|
||||
const QString CardInfo::getManaCost() const
|
||||
{
|
||||
return getProperty(Mtg::ManaCost);
|
||||
}
|
||||
const QString CardInfo::getPowTough() const
|
||||
{
|
||||
return getProperty(Mtg::PowTough);
|
||||
}
|
||||
void CardInfo::setPowTough(const QString &value)
|
||||
{
|
||||
setProperty(Mtg::PowTough, value);
|
||||
}
|
||||
@@ -1,354 +0,0 @@
|
||||
/**
|
||||
* @file card_info.h
|
||||
* @ingroup Cards
|
||||
* @brief TODO: Document this.
|
||||
*/
|
||||
|
||||
#ifndef CARD_INFO_H
|
||||
#define CARD_INFO_H
|
||||
|
||||
#include "printing_info.h"
|
||||
|
||||
#include <QDate>
|
||||
#include <QHash>
|
||||
#include <QList>
|
||||
#include <QLoggingCategory>
|
||||
#include <QMap>
|
||||
#include <QMetaType>
|
||||
#include <QSharedPointer>
|
||||
#include <QStringList>
|
||||
#include <QVariant>
|
||||
#include <utility>
|
||||
|
||||
inline Q_LOGGING_CATEGORY(CardInfoLog, "card_info");
|
||||
|
||||
class CardInfo;
|
||||
class CardSet;
|
||||
class CardRelation;
|
||||
class ICardDatabaseParser;
|
||||
|
||||
typedef QSharedPointer<CardInfo> CardInfoPtr;
|
||||
typedef QSharedPointer<CardSet> CardSetPtr;
|
||||
typedef QMap<QString, QList<PrintingInfo>> SetToPrintingsMap;
|
||||
|
||||
typedef QHash<QString, CardInfoPtr> CardNameMap;
|
||||
typedef QHash<QString, CardSetPtr> SetNameMap;
|
||||
|
||||
Q_DECLARE_METATYPE(CardInfoPtr)
|
||||
|
||||
/**
|
||||
* @class CardInfo
|
||||
* @ingroup Cards
|
||||
*
|
||||
* @brief Represents a card and its associated metadata, properties, and relationships.
|
||||
*
|
||||
* CardInfo holds both static information (name, text, flags) and dynamic data
|
||||
* (properties, set memberships, relationships). It also integrates with
|
||||
* signals/slots, allowing observers to react to property or visual updates.
|
||||
*
|
||||
* Each CardInfo may belong to multiple sets through its printings, and can
|
||||
* be related to other cards through defined relationships.
|
||||
*/
|
||||
class CardInfo : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
CardInfoPtr smartThis; ///< Smart pointer to self for safe cross-references.
|
||||
QString name; ///< Full name of the card.
|
||||
QString simpleName; ///< Simplified name for fuzzy matching.
|
||||
QString text; ///< Text description or rules text of the card.
|
||||
bool isToken; ///< Whether this card is a token or not.
|
||||
QVariantHash properties; ///< Key-value store of dynamic card properties.
|
||||
QList<CardRelation *> relatedCards; ///< Forward references to related cards.
|
||||
QList<CardRelation *> reverseRelatedCards; ///< Cards that refer back to this card.
|
||||
QList<CardRelation *> reverseRelatedCardsToMe; ///< Cards that consider this card as related.
|
||||
SetToPrintingsMap setsToPrintings; ///< Mapping from set names to printing variations.
|
||||
QString setsNames; ///< Cached, human-readable list of set names.
|
||||
bool cipt; ///< Positioning flag used by UI.
|
||||
bool landscapeOrientation; ///< Orientation flag for rendering.
|
||||
int tableRow; ///< Row index in a table or visual representation.
|
||||
bool upsideDownArt; ///< Whether artwork is flipped for visual purposes.
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Constructs a CardInfo with full initialization.
|
||||
*
|
||||
* @param _name The name of the card.
|
||||
* @param _text Rules text or description of the card.
|
||||
* @param _isToken Flag indicating whether the card is a token.
|
||||
* @param _properties Arbitrary key-value properties.
|
||||
* @param _relatedCards Forward references to related cards.
|
||||
* @param _reverseRelatedCards Backward references to related cards.
|
||||
* @param _sets Map of set names to printing information.
|
||||
* @param _cipt UI positioning flag.
|
||||
* @param _landscapeOrientation UI rendering orientation.
|
||||
* @param _tableRow Row index for table placement.
|
||||
* @param _upsideDownArt Whether the artwork should be displayed upside down.
|
||||
*/
|
||||
explicit CardInfo(const QString &_name,
|
||||
const QString &_text,
|
||||
bool _isToken,
|
||||
QVariantHash _properties,
|
||||
const QList<CardRelation *> &_relatedCards,
|
||||
const QList<CardRelation *> &_reverseRelatedCards,
|
||||
SetToPrintingsMap _sets,
|
||||
bool _cipt,
|
||||
bool _landscapeOrientation,
|
||||
int _tableRow,
|
||||
bool _upsideDownArt);
|
||||
|
||||
/**
|
||||
* @brief Copy constructor for CardInfo.
|
||||
*
|
||||
* Performs a deep copy of properties, sets, and related card lists.
|
||||
*
|
||||
* @param other Another CardInfo to copy.
|
||||
*/
|
||||
CardInfo(const CardInfo &other)
|
||||
: QObject(other.parent()), name(other.name), simpleName(other.simpleName), text(other.text),
|
||||
isToken(other.isToken), properties(other.properties), relatedCards(other.relatedCards),
|
||||
reverseRelatedCards(other.reverseRelatedCards), reverseRelatedCardsToMe(other.reverseRelatedCardsToMe),
|
||||
setsToPrintings(other.setsToPrintings), setsNames(other.setsNames), cipt(other.cipt),
|
||||
landscapeOrientation(other.landscapeOrientation), tableRow(other.tableRow), upsideDownArt(other.upsideDownArt)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates a new instance with only the card name.
|
||||
*
|
||||
* All other fields are set to defaults.
|
||||
*
|
||||
* @param _name The card name.
|
||||
* @return Shared pointer to the new CardInfo instance.
|
||||
*/
|
||||
static CardInfoPtr newInstance(const QString &_name);
|
||||
|
||||
/**
|
||||
* @brief Creates a new instance with full initialization.
|
||||
*
|
||||
* @param _name Name of the card.
|
||||
* @param _text Rules text or description.
|
||||
* @param _isToken Token flag.
|
||||
* @param _properties Arbitrary properties.
|
||||
* @param _relatedCards Forward relationships.
|
||||
* @param _reverseRelatedCards Reverse relationships.
|
||||
* @param _sets Printing information per set.
|
||||
* @param _cipt UI positioning flag.
|
||||
* @param _landscapeOrientation UI rendering orientation.
|
||||
* @param _tableRow Row index for table placement.
|
||||
* @param _upsideDownArt Artwork orientation flag.
|
||||
* @return Shared pointer to the new CardInfo instance.
|
||||
*/
|
||||
static CardInfoPtr newInstance(const QString &_name,
|
||||
const QString &_text,
|
||||
bool _isToken,
|
||||
QVariantHash _properties,
|
||||
const QList<CardRelation *> &_relatedCards,
|
||||
const QList<CardRelation *> &_reverseRelatedCards,
|
||||
SetToPrintingsMap _sets,
|
||||
bool _cipt,
|
||||
bool _landscapeOrientation,
|
||||
int _tableRow,
|
||||
bool _upsideDownArt);
|
||||
|
||||
/**
|
||||
* @brief Clones the current CardInfo instance.
|
||||
*
|
||||
* Uses the copy constructor and ensures the smart pointer is properly set.
|
||||
*
|
||||
* @return Shared pointer to the cloned CardInfo.
|
||||
*/
|
||||
CardInfoPtr clone() const
|
||||
{
|
||||
CardInfoPtr newCardInfo = CardInfoPtr(new CardInfo(*this));
|
||||
newCardInfo->setSmartPointer(newCardInfo); // Set the smart pointer for the new instance
|
||||
return newCardInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the internal smart pointer to self.
|
||||
*
|
||||
* Used internally to allow safe cross-references among CardInfo and CardSet.
|
||||
*
|
||||
* @param _ptr Shared pointer pointing to this instance.
|
||||
*/
|
||||
void setSmartPointer(CardInfoPtr _ptr)
|
||||
{
|
||||
smartThis = std::move(_ptr);
|
||||
}
|
||||
|
||||
/** @name Basic Properties Accessors */ //@{
|
||||
inline const QString &getName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
const QString &getSimpleName() const
|
||||
{
|
||||
return simpleName;
|
||||
}
|
||||
const QString &getText() const
|
||||
{
|
||||
return text;
|
||||
}
|
||||
void setText(const QString &_text)
|
||||
{
|
||||
text = _text;
|
||||
emit cardInfoChanged(smartThis);
|
||||
}
|
||||
bool getIsToken() const
|
||||
{
|
||||
return isToken;
|
||||
}
|
||||
QStringList getProperties() const
|
||||
{
|
||||
return properties.keys();
|
||||
}
|
||||
QString getProperty(const QString &propertyName) const
|
||||
{
|
||||
return properties.value(propertyName).toString();
|
||||
}
|
||||
void setProperty(const QString &_name, const QString &_value)
|
||||
{
|
||||
properties.insert(_name, _value);
|
||||
emit cardInfoChanged(smartThis);
|
||||
}
|
||||
bool hasProperty(const QString &propertyName) const
|
||||
{
|
||||
return properties.contains(propertyName);
|
||||
}
|
||||
const SetToPrintingsMap &getSets() const
|
||||
{
|
||||
return setsToPrintings;
|
||||
}
|
||||
const QString &getSetsNames() const
|
||||
{
|
||||
return setsNames;
|
||||
}
|
||||
//@}
|
||||
|
||||
/** @name Related Cards Accessors */ //@{
|
||||
const QList<CardRelation *> &getRelatedCards() const
|
||||
{
|
||||
return relatedCards;
|
||||
}
|
||||
const QList<CardRelation *> &getReverseRelatedCards() const
|
||||
{
|
||||
return reverseRelatedCards;
|
||||
}
|
||||
const QList<CardRelation *> &getReverseRelatedCards2Me() const
|
||||
{
|
||||
return reverseRelatedCardsToMe;
|
||||
}
|
||||
QList<CardRelation *> getAllRelatedCards() const
|
||||
{
|
||||
QList<CardRelation *> result;
|
||||
result.append(getRelatedCards());
|
||||
result.append(getReverseRelatedCards2Me());
|
||||
return result;
|
||||
}
|
||||
void resetReverseRelatedCards2Me();
|
||||
void addReverseRelatedCards2Me(CardRelation *cardRelation)
|
||||
{
|
||||
reverseRelatedCardsToMe.append(cardRelation);
|
||||
}
|
||||
//@}
|
||||
|
||||
/** @name UI Positioning */ //@{
|
||||
bool getCipt() const
|
||||
{
|
||||
return cipt;
|
||||
}
|
||||
bool getLandscapeOrientation() const
|
||||
{
|
||||
return landscapeOrientation;
|
||||
}
|
||||
int getTableRow() const
|
||||
{
|
||||
return tableRow;
|
||||
}
|
||||
void setTableRow(int _tableRow)
|
||||
{
|
||||
tableRow = _tableRow;
|
||||
}
|
||||
bool getUpsideDownArt() const
|
||||
{
|
||||
return upsideDownArt;
|
||||
}
|
||||
const QChar getColorChar() const;
|
||||
//@}
|
||||
|
||||
/** @name Legacy/Convenience Property Accessors */ //@{
|
||||
const QString getCardType() const;
|
||||
void setCardType(const QString &value);
|
||||
const QString getCmc() const;
|
||||
const QString getColors() const;
|
||||
void setColors(const QString &value);
|
||||
const QString getLoyalty() const;
|
||||
const QString getMainCardType() const;
|
||||
const QString getManaCost() const;
|
||||
const QString getPowTough() const;
|
||||
void setPowTough(const QString &value);
|
||||
//@}
|
||||
|
||||
/**
|
||||
* @brief Returns a version of the card name safe for file storage or fuzzy matching.
|
||||
*
|
||||
* Removes invalid characters, replaces spacing markers, and normalizes diacritics.
|
||||
*
|
||||
* @return Corrected card name as a QString.
|
||||
*/
|
||||
QString getCorrectedName() const;
|
||||
|
||||
/**
|
||||
* @brief Adds a printing to a specific set.
|
||||
*
|
||||
* Updates the mapping and refreshes the cached list of set names.
|
||||
*
|
||||
* @param _set The set to which the card should be added.
|
||||
* @param _info Optional printing information.
|
||||
*/
|
||||
void addToSet(const CardSetPtr &_set, PrintingInfo _info = PrintingInfo());
|
||||
|
||||
/**
|
||||
* @brief Combines legality properties from a provided map.
|
||||
*
|
||||
* Useful for merging format legality flags from multiple sources.
|
||||
*
|
||||
* @param props Key-value mapping of format legalities.
|
||||
*/
|
||||
void combineLegalities(const QVariantHash &props);
|
||||
|
||||
/**
|
||||
* @brief Refreshes the cached, human-readable list of set names.
|
||||
*
|
||||
* Typically called after adding or modifying set memberships.
|
||||
*/
|
||||
void refreshCachedSetNames();
|
||||
|
||||
/**
|
||||
* @brief Simplifies a name for fuzzy matching.
|
||||
*
|
||||
* Converts to lowercase, removes punctuation/spacing.
|
||||
*
|
||||
* @param name Original name string.
|
||||
* @return Simplified name string.
|
||||
*/
|
||||
static QString simplifyName(const QString &name);
|
||||
|
||||
signals:
|
||||
/**
|
||||
* @brief Emitted when a pixmap for this card has been updated or finished loading.
|
||||
*
|
||||
* @param printing Specific printing for which the pixmap has updated.
|
||||
*/
|
||||
void pixmapUpdated(const PrintingInfo &printing);
|
||||
|
||||
/**
|
||||
* @brief Emitted when card properties or state have changed.
|
||||
*
|
||||
* @param card Shared pointer to the CardInfo instance that changed.
|
||||
*/
|
||||
void cardInfoChanged(CardInfoPtr card);
|
||||
};
|
||||
#endif
|
||||
@@ -1,12 +0,0 @@
|
||||
#include "card_relation.h"
|
||||
|
||||
CardRelation::CardRelation(const QString &_name,
|
||||
CardRelationType _attachType,
|
||||
bool _isCreateAllExclusion,
|
||||
bool _isVariableCount,
|
||||
int _defaultCount,
|
||||
bool _isPersistent)
|
||||
: name(_name), attachType(_attachType), isCreateAllExclusion(_isCreateAllExclusion),
|
||||
isVariableCount(_isVariableCount), defaultCount(_defaultCount), isPersistent(_isPersistent)
|
||||
{
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
#ifndef COCKATRICE_CARD_RELATION_H
|
||||
#define COCKATRICE_CARD_RELATION_H
|
||||
|
||||
#include "card_relation_type.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
||||
class CardRelation : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
QString name;
|
||||
CardRelationType attachType;
|
||||
bool isCreateAllExclusion;
|
||||
bool isVariableCount;
|
||||
int defaultCount;
|
||||
bool isPersistent;
|
||||
|
||||
public:
|
||||
explicit CardRelation(const QString &_name = QString(),
|
||||
CardRelationType _attachType = CardRelationType::DoesNotAttach,
|
||||
bool _isCreateAllExclusion = false,
|
||||
bool _isVariableCount = false,
|
||||
int _defaultCount = 1,
|
||||
bool _isPersistent = false);
|
||||
|
||||
const QString &getName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
CardRelationType getAttachType() const
|
||||
{
|
||||
return attachType;
|
||||
}
|
||||
bool getDoesAttach() const
|
||||
{
|
||||
return attachType != CardRelationType::DoesNotAttach;
|
||||
}
|
||||
bool getDoesTransform() const
|
||||
{
|
||||
return attachType == CardRelationType::TransformInto;
|
||||
}
|
||||
|
||||
QString getAttachTypeAsString() const
|
||||
{
|
||||
return cardAttachTypeToString(attachType);
|
||||
}
|
||||
|
||||
bool getCanCreateAnother() const
|
||||
{
|
||||
return !getDoesAttach();
|
||||
}
|
||||
bool getIsCreateAllExclusion() const
|
||||
{
|
||||
return isCreateAllExclusion;
|
||||
}
|
||||
bool getIsVariable() const
|
||||
{
|
||||
return isVariableCount;
|
||||
}
|
||||
int getDefaultCount() const
|
||||
{
|
||||
return defaultCount;
|
||||
}
|
||||
bool getIsPersistent() const
|
||||
{
|
||||
return isPersistent;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // COCKATRICE_CARD_RELATION_H
|
||||
@@ -1,29 +0,0 @@
|
||||
#ifndef COCKATRICE_CARD_RELATION_TYPE_H
|
||||
#define COCKATRICE_CARD_RELATION_TYPE_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
/**
|
||||
* Represents how a card relates to another (attach, transform, etc.).
|
||||
*/
|
||||
enum class CardRelationType
|
||||
{
|
||||
DoesNotAttach = 0,
|
||||
AttachTo = 1,
|
||||
TransformInto = 2,
|
||||
};
|
||||
|
||||
// Optional helper
|
||||
inline QString cardAttachTypeToString(CardRelationType type)
|
||||
{
|
||||
switch (type) {
|
||||
case CardRelationType::AttachTo:
|
||||
return "attach";
|
||||
case CardRelationType::TransformInto:
|
||||
return "transform";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
#endif // COCKATRICE_CARD_RELATION_TYPE_H
|
||||
@@ -1,81 +0,0 @@
|
||||
#include "card_set.h"
|
||||
|
||||
#include "../settings/cache_settings.h"
|
||||
|
||||
const char *CardSet::TOKENS_SETNAME = "TK";
|
||||
|
||||
CardSet::CardSet(const QString &_shortName,
|
||||
const QString &_longName,
|
||||
const QString &_setType,
|
||||
const QDate &_releaseDate,
|
||||
const CardSet::Priority _priority)
|
||||
: shortName(_shortName), longName(_longName), releaseDate(_releaseDate), setType(_setType), priority(_priority)
|
||||
{
|
||||
loadSetOptions();
|
||||
}
|
||||
|
||||
CardSetPtr CardSet::newInstance(const QString &_shortName,
|
||||
const QString &_longName,
|
||||
const QString &_setType,
|
||||
const QDate &_releaseDate,
|
||||
const Priority _priority)
|
||||
{
|
||||
CardSetPtr ptr(new CardSet(_shortName, _longName, _setType, _releaseDate, _priority));
|
||||
// ptr->setSmartPointer(ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
QString CardSet::getCorrectedShortName() const
|
||||
{
|
||||
// For Windows machines.
|
||||
QSet<QString> invalidFileNames;
|
||||
invalidFileNames << "CON"
|
||||
<< "PRN"
|
||||
<< "AUX"
|
||||
<< "NUL"
|
||||
<< "COM1"
|
||||
<< "COM2"
|
||||
<< "COM3"
|
||||
<< "COM4"
|
||||
<< "COM5"
|
||||
<< "COM6"
|
||||
<< "COM7"
|
||||
<< "COM8"
|
||||
<< "COM9"
|
||||
<< "LPT1"
|
||||
<< "LPT2"
|
||||
<< "LPT3"
|
||||
<< "LPT4"
|
||||
<< "LPT5"
|
||||
<< "LPT6"
|
||||
<< "LPT7"
|
||||
<< "LPT8"
|
||||
<< "LPT9";
|
||||
|
||||
return invalidFileNames.contains(shortName) ? shortName + "_" : shortName;
|
||||
}
|
||||
|
||||
void CardSet::loadSetOptions()
|
||||
{
|
||||
sortKey = SettingsCache::instance().cardDatabase().getSortKey(shortName);
|
||||
enabled = SettingsCache::instance().cardDatabase().isEnabled(shortName);
|
||||
isknown = SettingsCache::instance().cardDatabase().isKnown(shortName);
|
||||
}
|
||||
|
||||
void CardSet::setSortKey(unsigned int _sortKey)
|
||||
{
|
||||
sortKey = _sortKey;
|
||||
SettingsCache::instance().cardDatabase().setSortKey(shortName, _sortKey);
|
||||
}
|
||||
|
||||
void CardSet::setEnabled(bool _enabled)
|
||||
{
|
||||
enabled = _enabled;
|
||||
SettingsCache::instance().cardDatabase().setEnabled(shortName, _enabled);
|
||||
}
|
||||
|
||||
void CardSet::setIsKnown(bool _isknown)
|
||||
{
|
||||
isknown = _isknown;
|
||||
SettingsCache::instance().cardDatabase().setIsKnown(shortName, _isknown);
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
#ifndef COCKATRICE_CARD_SET_H
|
||||
#define COCKATRICE_CARD_SET_H
|
||||
|
||||
#include <QDate>
|
||||
#include <QList>
|
||||
#include <QSharedPointer>
|
||||
#include <QString>
|
||||
|
||||
class CardInfo;
|
||||
using CardInfoPtr = QSharedPointer<CardInfo>;
|
||||
|
||||
class CardSet;
|
||||
using CardSetPtr = QSharedPointer<CardSet>;
|
||||
|
||||
class CardSet : public QList<CardInfoPtr>
|
||||
{
|
||||
public:
|
||||
enum Priority
|
||||
{
|
||||
PriorityFallback = 0,
|
||||
PriorityPrimary = 10,
|
||||
PrioritySecondary = 20,
|
||||
PriorityReprint = 30,
|
||||
PriorityOther = 40,
|
||||
PriorityLowest = 100,
|
||||
};
|
||||
|
||||
static const char *TOKENS_SETNAME;
|
||||
|
||||
private:
|
||||
QString shortName, longName;
|
||||
unsigned int sortKey;
|
||||
QDate releaseDate;
|
||||
QString setType;
|
||||
Priority priority;
|
||||
bool enabled, isknown;
|
||||
|
||||
public:
|
||||
explicit CardSet(const QString &_shortName = QString(),
|
||||
const QString &_longName = QString(),
|
||||
const QString &_setType = QString(),
|
||||
const QDate &_releaseDate = QDate(),
|
||||
const Priority _priority = PriorityFallback);
|
||||
|
||||
static CardSetPtr newInstance(const QString &_shortName = QString(),
|
||||
const QString &_longName = QString(),
|
||||
const QString &_setType = QString(),
|
||||
const QDate &_releaseDate = QDate(),
|
||||
const Priority _priority = PriorityFallback);
|
||||
|
||||
QString getCorrectedShortName() const;
|
||||
|
||||
QString getShortName() const
|
||||
{
|
||||
return shortName;
|
||||
}
|
||||
QString getLongName() const
|
||||
{
|
||||
return longName;
|
||||
}
|
||||
QString getSetType() const
|
||||
{
|
||||
return setType;
|
||||
}
|
||||
QDate getReleaseDate() const
|
||||
{
|
||||
return releaseDate;
|
||||
}
|
||||
Priority getPriority() const
|
||||
{
|
||||
return priority;
|
||||
}
|
||||
|
||||
void setLongName(const QString &_longName)
|
||||
{
|
||||
longName = _longName;
|
||||
}
|
||||
void setSetType(const QString &_setType)
|
||||
{
|
||||
setType = _setType;
|
||||
}
|
||||
void setReleaseDate(const QDate &_releaseDate)
|
||||
{
|
||||
releaseDate = _releaseDate;
|
||||
}
|
||||
void setPriority(const Priority _priority)
|
||||
{
|
||||
priority = _priority;
|
||||
}
|
||||
|
||||
void loadSetOptions();
|
||||
int getSortKey() const
|
||||
{
|
||||
return sortKey;
|
||||
}
|
||||
void setSortKey(unsigned int _sortKey);
|
||||
|
||||
bool getEnabled() const
|
||||
{
|
||||
return enabled;
|
||||
}
|
||||
void setEnabled(bool _enabled);
|
||||
|
||||
bool getIsKnown() const
|
||||
{
|
||||
return isknown;
|
||||
}
|
||||
void setIsKnown(bool _isknown);
|
||||
|
||||
bool getIsKnownIgnored() const
|
||||
{
|
||||
return longName.length() + setType.length() + releaseDate.toString().length() == 0;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // COCKATRICE_CARD_SET_H
|
||||
@@ -1,127 +0,0 @@
|
||||
#include "card_set_list.h"
|
||||
|
||||
class CardSetList::KeyCompareFunctor
|
||||
{
|
||||
public:
|
||||
inline bool operator()(const CardSetPtr &a, const CardSetPtr &b) const
|
||||
{
|
||||
if (a.isNull() || b.isNull()) {
|
||||
// qCWarning(CardInfoLog) << "SetList::KeyCompareFunctor a or b is null";
|
||||
return false;
|
||||
}
|
||||
|
||||
return a->getSortKey() < b->getSortKey();
|
||||
}
|
||||
};
|
||||
|
||||
void CardSetList::sortByKey()
|
||||
{
|
||||
std::sort(begin(), end(), KeyCompareFunctor());
|
||||
}
|
||||
|
||||
int CardSetList::getEnabledSetsNum()
|
||||
{
|
||||
int num = 0;
|
||||
for (int i = 0; i < size(); ++i) {
|
||||
CardSetPtr set = at(i);
|
||||
if (set && set->getEnabled()) {
|
||||
++num;
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
int CardSetList::getUnknownSetsNum()
|
||||
{
|
||||
int num = 0;
|
||||
for (int i = 0; i < size(); ++i) {
|
||||
CardSetPtr set = at(i);
|
||||
if (set && !set->getIsKnown() && !set->getIsKnownIgnored()) {
|
||||
++num;
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
QStringList CardSetList::getUnknownSetsNames()
|
||||
{
|
||||
QStringList sets = QStringList();
|
||||
for (int i = 0; i < size(); ++i) {
|
||||
CardSetPtr set = at(i);
|
||||
if (set && !set->getIsKnown() && !set->getIsKnownIgnored()) {
|
||||
sets << set->getShortName();
|
||||
}
|
||||
}
|
||||
return sets;
|
||||
}
|
||||
|
||||
void CardSetList::enableAllUnknown()
|
||||
{
|
||||
for (int i = 0; i < size(); ++i) {
|
||||
CardSetPtr set = at(i);
|
||||
if (set && !set->getIsKnown() && !set->getIsKnownIgnored()) {
|
||||
set->setIsKnown(true);
|
||||
set->setEnabled(true);
|
||||
} else if (set && set->getIsKnownIgnored() && !set->getEnabled()) {
|
||||
set->setEnabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CardSetList::enableAll()
|
||||
{
|
||||
for (int i = 0; i < size(); ++i) {
|
||||
CardSetPtr set = at(i);
|
||||
|
||||
if (set == nullptr) {
|
||||
// qCWarning(CardInfoLog) << "enabledAll has null";
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!set->getIsKnownIgnored()) {
|
||||
set->setIsKnown(true);
|
||||
}
|
||||
|
||||
set->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void CardSetList::markAllAsKnown()
|
||||
{
|
||||
for (int i = 0; i < size(); ++i) {
|
||||
CardSetPtr set = at(i);
|
||||
if (set && !set->getIsKnown() && !set->getIsKnownIgnored()) {
|
||||
set->setIsKnown(true);
|
||||
set->setEnabled(false);
|
||||
} else if (set && set->getIsKnownIgnored() && !set->getEnabled()) {
|
||||
set->setEnabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CardSetList::guessSortKeys()
|
||||
{
|
||||
defaultSort();
|
||||
for (int i = 0; i < size(); ++i) {
|
||||
CardSetPtr set = at(i);
|
||||
if (set.isNull()) {
|
||||
// qCWarning(CardInfoLog) << "guessSortKeys set is null";
|
||||
continue;
|
||||
}
|
||||
set->setSortKey(i);
|
||||
}
|
||||
}
|
||||
|
||||
void CardSetList::defaultSort()
|
||||
{
|
||||
std::sort(begin(), end(), [](const CardSetPtr &a, const CardSetPtr &b) {
|
||||
// Sort by priority, then by release date, then by short name
|
||||
if (a->getPriority() != b->getPriority()) {
|
||||
return a->getPriority() < b->getPriority(); // lowest first
|
||||
} else if (a->getReleaseDate() != b->getReleaseDate()) {
|
||||
return a->getReleaseDate() > b->getReleaseDate(); // most recent first
|
||||
} else {
|
||||
return a->getShortName() < b->getShortName(); // alphabetically
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
#ifndef COCKATRICE_CARD_SET_LIST_H
|
||||
#define COCKATRICE_CARD_SET_LIST_H
|
||||
|
||||
#include "card_set.h"
|
||||
|
||||
#include <QList>
|
||||
#include <QStringList>
|
||||
|
||||
class CardSetList : public QList<CardSetPtr>
|
||||
{
|
||||
private:
|
||||
class KeyCompareFunctor;
|
||||
|
||||
public:
|
||||
void sortByKey();
|
||||
void guessSortKeys();
|
||||
void enableAllUnknown();
|
||||
void enableAll();
|
||||
void markAllAsKnown();
|
||||
int getEnabledSetsNum();
|
||||
int getUnknownSetsNum();
|
||||
QStringList getUnknownSetsNames();
|
||||
void defaultSort();
|
||||
};
|
||||
|
||||
#endif // COCKATRICE_CARD_SET_LIST_H
|
||||
@@ -1,79 +0,0 @@
|
||||
#include "exact_card.h"
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
* This will set the CardInfoPtr to null.
|
||||
* The printing will be the default-constructed PrintingInfo.
|
||||
*/
|
||||
ExactCard::ExactCard()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param _card The card. Can be null.
|
||||
* @param _printing The printing. Can be empty.
|
||||
*/
|
||||
ExactCard::ExactCard(const CardInfoPtr &_card, const PrintingInfo &_printing) : card(_card), printing(_printing)
|
||||
{
|
||||
}
|
||||
|
||||
bool ExactCard::operator==(const ExactCard &other) const
|
||||
{
|
||||
return this->card == other.card && this->printing == other.printing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to safely get the card's name.
|
||||
* @return The name in the CardInfo, or an empty string if card is null
|
||||
*/
|
||||
QString ExactCard::getName() const
|
||||
{
|
||||
return card.isNull() ? "" : card->getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a view of the underlying cardInfoPtr.
|
||||
* @return A const reference to the CardInfo, or an empty CardInfo if card is null
|
||||
*/
|
||||
const CardInfo &ExactCard::getInfo() const
|
||||
{
|
||||
if (card.isNull()) {
|
||||
static CardInfoPtr emptyCard = CardInfo::newInstance("");
|
||||
return *emptyCard;
|
||||
}
|
||||
return *card;
|
||||
}
|
||||
|
||||
/**
|
||||
* The key used to identify this exact printing in the cache
|
||||
*/
|
||||
QString ExactCard::getPixmapCacheKey() const
|
||||
{
|
||||
QString uuid = printing.getUuid();
|
||||
QString suffix = uuid.isEmpty() ? "" : "_" + uuid;
|
||||
return QLatin1String("card_") + card->getName() + suffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the card is null or empty.
|
||||
*/
|
||||
bool ExactCard::isEmpty() const
|
||||
{
|
||||
return card.isNull() || card->getName().isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if isEmpty() is false
|
||||
*/
|
||||
ExactCard::operator bool() const
|
||||
{
|
||||
return !isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the CardInfo to emit the pixmapUpdated signal
|
||||
*/
|
||||
void ExactCard::emitPixmapUpdated() const
|
||||
{
|
||||
emit card->pixmapUpdated(printing);
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
#ifndef EXACT_CARD_H
|
||||
#define EXACT_CARD_H
|
||||
|
||||
#include "card_info.h"
|
||||
|
||||
/**
|
||||
* @class ExactCard
|
||||
* @ingroup Cards
|
||||
* @brief Identifies the card by its CardInfoPtr along with its exact printing by its PrintingInfo.
|
||||
*/
|
||||
class ExactCard
|
||||
{
|
||||
CardInfoPtr card;
|
||||
PrintingInfo printing;
|
||||
|
||||
public:
|
||||
ExactCard();
|
||||
explicit ExactCard(const CardInfoPtr &_card, const PrintingInfo &_printing = PrintingInfo());
|
||||
|
||||
/**
|
||||
* Gets the CardInfoPtr. Can be null.
|
||||
*/
|
||||
CardInfoPtr getCardPtr() const
|
||||
{
|
||||
return card;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the PrintingInfo. Can be empty.
|
||||
*/
|
||||
PrintingInfo getPrinting() const
|
||||
{
|
||||
return printing;
|
||||
}
|
||||
|
||||
bool operator==(const ExactCard &other) const;
|
||||
|
||||
QString getName() const;
|
||||
const CardInfo &getInfo() const;
|
||||
QString getPixmapCacheKey() const;
|
||||
|
||||
bool isEmpty() const;
|
||||
explicit operator bool() const;
|
||||
|
||||
void emitPixmapUpdated() const;
|
||||
};
|
||||
|
||||
#endif // EXACT_CARD_H
|
||||
@@ -1,13 +0,0 @@
|
||||
#include "printing_info.h"
|
||||
|
||||
PrintingInfo::PrintingInfo(const CardSetPtr &_set) : set(_set)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the uuid property of the printing, or an empty string if the property isn't present
|
||||
*/
|
||||
QString PrintingInfo::getUuid() const
|
||||
{
|
||||
return properties.value("uuid").toString();
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
#ifndef COCKATRICE_PRINTING_INFO_H
|
||||
#define COCKATRICE_PRINTING_INFO_H
|
||||
|
||||
#include "card_set.h"
|
||||
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include <QStringList>
|
||||
#include <QVariant>
|
||||
|
||||
class PrintingInfo;
|
||||
|
||||
using SetToPrintingsMap = QMap<QString, QList<PrintingInfo>>;
|
||||
|
||||
/**
|
||||
* Info relating to a specific printing for a card.
|
||||
*/
|
||||
class PrintingInfo
|
||||
{
|
||||
public:
|
||||
explicit PrintingInfo(const CardSetPtr &_set = nullptr);
|
||||
~PrintingInfo() = default;
|
||||
|
||||
bool operator==(const PrintingInfo &other) const
|
||||
{
|
||||
return this->set == other.set && this->properties == other.properties;
|
||||
}
|
||||
|
||||
private:
|
||||
CardSetPtr set;
|
||||
// per-printing card properties;
|
||||
QVariantHash properties;
|
||||
|
||||
public:
|
||||
CardSetPtr getSet() const
|
||||
{
|
||||
return set;
|
||||
}
|
||||
|
||||
QStringList getProperties() const
|
||||
{
|
||||
return properties.keys();
|
||||
}
|
||||
QString getProperty(const QString &propertyName) const
|
||||
{
|
||||
return properties.value(propertyName).toString();
|
||||
}
|
||||
void setProperty(const QString &_name, const QString &_value)
|
||||
{
|
||||
properties.insert(_name, _value);
|
||||
}
|
||||
|
||||
QString getUuid() const;
|
||||
};
|
||||
|
||||
#endif // COCKATRICE_PRINTING_INFO_H
|
||||
@@ -1,209 +0,0 @@
|
||||
#include "deck_editor_menu.h"
|
||||
|
||||
#include "../settings/cache_settings.h"
|
||||
#include "../settings/shortcuts_settings.h"
|
||||
|
||||
DeckEditorMenu::DeckEditorMenu(AbstractTabDeckEditor *parent) : QMenu(parent), deckEditor(parent)
|
||||
{
|
||||
aNewDeck = new QAction(QString(), this);
|
||||
connect(aNewDeck, &QAction::triggered, deckEditor, &AbstractTabDeckEditor::actNewDeck);
|
||||
|
||||
aLoadDeck = new QAction(QString(), this);
|
||||
connect(aLoadDeck, &QAction::triggered, deckEditor, &AbstractTabDeckEditor::actLoadDeck);
|
||||
|
||||
loadRecentDeckMenu = new QMenu(this);
|
||||
connect(&SettingsCache::instance().recents(), &RecentsSettings::recentlyOpenedDeckPathsChanged, this,
|
||||
&DeckEditorMenu::updateRecentlyOpened);
|
||||
|
||||
aClearRecents = new QAction(QString(), this);
|
||||
connect(aClearRecents, &QAction::triggered, this, &DeckEditorMenu::actClearRecents);
|
||||
|
||||
updateRecentlyOpened();
|
||||
|
||||
aSaveDeck = new QAction(QString(), this);
|
||||
connect(aSaveDeck, &QAction::triggered, deckEditor, &AbstractTabDeckEditor::actSaveDeck);
|
||||
|
||||
aSaveDeckAs = new QAction(QString(), this);
|
||||
connect(aSaveDeckAs, &QAction::triggered, deckEditor, &AbstractTabDeckEditor::actSaveDeckAs);
|
||||
|
||||
aLoadDeckFromClipboard = new QAction(QString(), this);
|
||||
connect(aLoadDeckFromClipboard, &QAction::triggered, deckEditor, &AbstractTabDeckEditor::actLoadDeckFromClipboard);
|
||||
|
||||
aEditDeckInClipboard = new QAction(QString(), this);
|
||||
connect(aEditDeckInClipboard, &QAction::triggered, deckEditor, &AbstractTabDeckEditor::actEditDeckInClipboard);
|
||||
|
||||
aEditDeckInClipboardRaw = new QAction(QString(), this);
|
||||
connect(aEditDeckInClipboardRaw, &QAction::triggered, deckEditor,
|
||||
&AbstractTabDeckEditor::actEditDeckInClipboardRaw);
|
||||
|
||||
aSaveDeckToClipboard = new QAction(QString(), this);
|
||||
connect(aSaveDeckToClipboard, &QAction::triggered, deckEditor, &AbstractTabDeckEditor::actSaveDeckToClipboard);
|
||||
|
||||
aSaveDeckToClipboardNoSetInfo = new QAction(QString(), this);
|
||||
connect(aSaveDeckToClipboardNoSetInfo, &QAction::triggered, deckEditor,
|
||||
&AbstractTabDeckEditor::actSaveDeckToClipboardNoSetInfo);
|
||||
|
||||
aSaveDeckToClipboardRaw = new QAction(QString(), this);
|
||||
connect(aSaveDeckToClipboardRaw, &QAction::triggered, deckEditor,
|
||||
&AbstractTabDeckEditor::actSaveDeckToClipboardRaw);
|
||||
|
||||
aSaveDeckToClipboardRawNoSetInfo = new QAction(QString(), this);
|
||||
connect(aSaveDeckToClipboardRawNoSetInfo, &QAction::triggered, deckEditor,
|
||||
&AbstractTabDeckEditor::actSaveDeckToClipboardRawNoSetInfo);
|
||||
|
||||
aPrintDeck = new QAction(QString(), this);
|
||||
connect(aPrintDeck, &QAction::triggered, deckEditor, &AbstractTabDeckEditor::actPrintDeck);
|
||||
|
||||
aLoadDeckFromWebsite = new QAction(QString(), this);
|
||||
connect(aLoadDeckFromWebsite, &QAction::triggered, deckEditor, &AbstractTabDeckEditor::actLoadDeckFromWebsite);
|
||||
|
||||
aExportDeckDecklist = new QAction(QString(), this);
|
||||
connect(aExportDeckDecklist, &QAction::triggered, deckEditor, &AbstractTabDeckEditor::actExportDeckDecklist);
|
||||
|
||||
aExportDeckDecklistXyz = new QAction(QString(), this);
|
||||
connect(aExportDeckDecklistXyz, &QAction::triggered, deckEditor, &AbstractTabDeckEditor::actExportDeckDecklistXyz);
|
||||
|
||||
aAnalyzeDeckDeckstats = new QAction(QString(), this);
|
||||
connect(aAnalyzeDeckDeckstats, &QAction::triggered, deckEditor, &AbstractTabDeckEditor::actAnalyzeDeckDeckstats);
|
||||
|
||||
aAnalyzeDeckTappedout = new QAction(QString(), this);
|
||||
connect(aAnalyzeDeckTappedout, &QAction::triggered, deckEditor, &AbstractTabDeckEditor::actAnalyzeDeckTappedout);
|
||||
|
||||
analyzeDeckMenu = new QMenu(this);
|
||||
analyzeDeckMenu->addAction(aExportDeckDecklist);
|
||||
analyzeDeckMenu->addAction(aExportDeckDecklistXyz);
|
||||
analyzeDeckMenu->addSeparator();
|
||||
analyzeDeckMenu->addAction(aAnalyzeDeckDeckstats);
|
||||
analyzeDeckMenu->addAction(aAnalyzeDeckTappedout);
|
||||
|
||||
aClose = new QAction(QString(), this);
|
||||
connect(aClose, &QAction::triggered, deckEditor, &AbstractTabDeckEditor::closeRequest);
|
||||
|
||||
editDeckInClipboardMenu = new QMenu(this);
|
||||
editDeckInClipboardMenu->addAction(aEditDeckInClipboard);
|
||||
editDeckInClipboardMenu->addAction(aEditDeckInClipboardRaw);
|
||||
|
||||
saveDeckToClipboardMenu = new QMenu(this);
|
||||
saveDeckToClipboardMenu->addAction(aSaveDeckToClipboard);
|
||||
saveDeckToClipboardMenu->addAction(aSaveDeckToClipboardNoSetInfo);
|
||||
saveDeckToClipboardMenu->addAction(aSaveDeckToClipboardRaw);
|
||||
saveDeckToClipboardMenu->addAction(aSaveDeckToClipboardRawNoSetInfo);
|
||||
|
||||
addAction(aNewDeck);
|
||||
addAction(aLoadDeck);
|
||||
addMenu(loadRecentDeckMenu);
|
||||
addAction(aSaveDeck);
|
||||
addAction(aSaveDeckAs);
|
||||
addSeparator();
|
||||
addAction(aLoadDeckFromClipboard);
|
||||
addMenu(editDeckInClipboardMenu);
|
||||
addMenu(saveDeckToClipboardMenu);
|
||||
addSeparator();
|
||||
addAction(aPrintDeck);
|
||||
addAction(aLoadDeckFromWebsite);
|
||||
addMenu(analyzeDeckMenu);
|
||||
addSeparator();
|
||||
addAction(deckEditor->filterDockWidget->aClearFilterOne);
|
||||
addAction(deckEditor->filterDockWidget->aClearFilterAll);
|
||||
addSeparator();
|
||||
addAction(aClose);
|
||||
|
||||
retranslateUi();
|
||||
connect(&SettingsCache::instance().shortcuts(), &ShortcutsSettings::shortCutChanged, this,
|
||||
&DeckEditorMenu::refreshShortcuts);
|
||||
refreshShortcuts();
|
||||
}
|
||||
|
||||
void DeckEditorMenu::setSaveStatus(bool newStatus)
|
||||
{
|
||||
aSaveDeck->setEnabled(newStatus);
|
||||
aSaveDeckAs->setEnabled(newStatus);
|
||||
aSaveDeckToClipboard->setEnabled(newStatus);
|
||||
aSaveDeckToClipboardNoSetInfo->setEnabled(newStatus);
|
||||
aSaveDeckToClipboardRaw->setEnabled(newStatus);
|
||||
aSaveDeckToClipboardRawNoSetInfo->setEnabled(newStatus);
|
||||
saveDeckToClipboardMenu->setEnabled(newStatus);
|
||||
aPrintDeck->setEnabled(newStatus);
|
||||
analyzeDeckMenu->setEnabled(newStatus);
|
||||
}
|
||||
|
||||
void DeckEditorMenu::updateRecentlyOpened()
|
||||
{
|
||||
loadRecentDeckMenu->clear();
|
||||
for (const auto &deckPath : SettingsCache::instance().recents().getRecentlyOpenedDeckPaths()) {
|
||||
QAction *aRecentlyOpenedDeck = new QAction(deckPath, this);
|
||||
loadRecentDeckMenu->addAction(aRecentlyOpenedDeck);
|
||||
connect(aRecentlyOpenedDeck, &QAction::triggered, deckEditor,
|
||||
[=, this] { deckEditor->actOpenRecent(aRecentlyOpenedDeck->text()); });
|
||||
}
|
||||
loadRecentDeckMenu->addSeparator();
|
||||
loadRecentDeckMenu->addAction(aClearRecents);
|
||||
aClearRecents->setEnabled(SettingsCache::instance().recents().getRecentlyOpenedDeckPaths().length() > 0);
|
||||
}
|
||||
|
||||
void DeckEditorMenu::actClearRecents()
|
||||
{
|
||||
SettingsCache::instance().recents().clearRecentlyOpenedDeckPaths();
|
||||
}
|
||||
|
||||
void DeckEditorMenu::retranslateUi()
|
||||
{
|
||||
setTitle(tr("&Deck Editor"));
|
||||
aNewDeck->setText(tr("&New deck"));
|
||||
aLoadDeck->setText(tr("&Load deck..."));
|
||||
loadRecentDeckMenu->setTitle(tr("Load recent deck..."));
|
||||
aClearRecents->setText(tr("Clear"));
|
||||
aSaveDeck->setText(tr("&Save deck"));
|
||||
aSaveDeckAs->setText(tr("Save deck &as..."));
|
||||
|
||||
aLoadDeckFromClipboard->setText(tr("Load deck from cl&ipboard..."));
|
||||
|
||||
editDeckInClipboardMenu->setTitle(tr("Edit deck in clipboard"));
|
||||
aEditDeckInClipboard->setText(tr("Annotated"));
|
||||
aEditDeckInClipboardRaw->setText(tr("Not Annotated"));
|
||||
|
||||
saveDeckToClipboardMenu->setTitle(tr("Save deck to clipboard"));
|
||||
aSaveDeckToClipboard->setText(tr("Annotated"));
|
||||
aSaveDeckToClipboardNoSetInfo->setText(tr("Annotated (No set info)"));
|
||||
aSaveDeckToClipboardRaw->setText(tr("Not Annotated"));
|
||||
aSaveDeckToClipboardRawNoSetInfo->setText(tr("Not Annotated (No set info)"));
|
||||
|
||||
aPrintDeck->setText(tr("&Print deck..."));
|
||||
|
||||
aLoadDeckFromWebsite->setText(tr("Load deck from online service..."));
|
||||
analyzeDeckMenu->setTitle(tr("&Send deck to online service"));
|
||||
aExportDeckDecklist->setText(tr("Create decklist (decklist.org)"));
|
||||
aExportDeckDecklistXyz->setText(tr("Create decklist (decklist.xyz)"));
|
||||
aAnalyzeDeckDeckstats->setText(tr("Analyze deck (deckstats.net)"));
|
||||
aAnalyzeDeckTappedout->setText(tr("Analyze deck (tappedout.net)"));
|
||||
|
||||
aClose->setText(tr("&Close"));
|
||||
}
|
||||
|
||||
void DeckEditorMenu::refreshShortcuts()
|
||||
{
|
||||
ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts();
|
||||
aNewDeck->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aNewDeck"));
|
||||
aLoadDeck->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aLoadDeck"));
|
||||
aSaveDeck->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aSaveDeck"));
|
||||
aSaveDeckAs->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aSaveDeckAs"));
|
||||
aLoadDeckFromClipboard->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aLoadDeckFromClipboard"));
|
||||
aEditDeckInClipboard->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aEditDeckInClipboard"));
|
||||
aEditDeckInClipboardRaw->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aEditDeckInClipboardRaw"));
|
||||
aPrintDeck->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aPrintDeck"));
|
||||
|
||||
aExportDeckDecklist->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aExportDeckDecklist"));
|
||||
aExportDeckDecklistXyz->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aExportDeckDecklistXyz"));
|
||||
aAnalyzeDeckDeckstats->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aAnalyzeDeck"));
|
||||
aAnalyzeDeckTappedout->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aAnalyzeDeckTappedout"));
|
||||
|
||||
aClose->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aClose"));
|
||||
|
||||
aSaveDeckToClipboard->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aSaveDeckToClipboard"));
|
||||
aSaveDeckToClipboardNoSetInfo->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aSaveDeckToClipboardNoSetInfo"));
|
||||
aSaveDeckToClipboardRaw->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aSaveDeckToClipboardRaw"));
|
||||
aSaveDeckToClipboardRawNoSetInfo->setShortcuts(
|
||||
shortcuts.getShortcut("TabDeckEditor/aSaveDeckToClipboardRawNoSetInfo"));
|
||||
|
||||
aClose->setShortcuts(shortcuts.getShortcut("TabDeckEditor/aClose"));
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/**
|
||||
* @file deck_editor_menu.h
|
||||
* @ingroup DeckEditors
|
||||
* @brief TODO: Document this.
|
||||
*/
|
||||
|
||||
#ifndef DECK_EDITOR_MENU_H
|
||||
#define DECK_EDITOR_MENU_H
|
||||
|
||||
#include "../tabs/abstract_tab_deck_editor.h"
|
||||
|
||||
#include <QMenu>
|
||||
|
||||
class AbstractTabDeckEditor;
|
||||
class DeckEditorMenu : public QMenu
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DeckEditorMenu(AbstractTabDeckEditor *parent);
|
||||
|
||||
AbstractTabDeckEditor *deckEditor;
|
||||
|
||||
QAction *aNewDeck, *aLoadDeck, *aClearRecents, *aSaveDeck, *aSaveDeckAs, *aLoadDeckFromClipboard,
|
||||
*aEditDeckInClipboard, *aEditDeckInClipboardRaw, *aSaveDeckToClipboard, *aSaveDeckToClipboardNoSetInfo,
|
||||
*aSaveDeckToClipboardRaw, *aSaveDeckToClipboardRawNoSetInfo, *aPrintDeck, *aLoadDeckFromWebsite,
|
||||
*aExportDeckDecklist, *aExportDeckDecklistXyz, *aAnalyzeDeckDeckstats, *aAnalyzeDeckTappedout, *aClose;
|
||||
QMenu *loadRecentDeckMenu, *analyzeDeckMenu, *editDeckInClipboardMenu, *saveDeckToClipboardMenu;
|
||||
|
||||
void setSaveStatus(bool newStatus);
|
||||
|
||||
public slots:
|
||||
void updateRecentlyOpened();
|
||||
void actClearRecents();
|
||||
void retranslateUi();
|
||||
void refreshShortcuts();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "abstract_client.h"
|
||||
|
||||
#include "../../server/pending_command.h"
|
||||
#include "featureset.h"
|
||||
#include "get_pb_extension.h"
|
||||
#include "pb/commands.pb.h"
|
||||
@@ -17,7 +18,6 @@
|
||||
#include "pb/event_user_left.pb.h"
|
||||
#include "pb/event_user_message.pb.h"
|
||||
#include "pb/server_message.pb.h"
|
||||
#include "pending_command.h"
|
||||
|
||||
#include <google/protobuf/descriptor.h>
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
/**
|
||||
* @file abstract_client.h
|
||||
* @ingroup Client
|
||||
* @brief TODO: Document this.
|
||||
*/
|
||||
|
||||
#ifndef ABSTRACTCLIENT_H
|
||||
#define ABSTRACTCLIENT_H
|
||||
|
||||
@@ -1,10 +1,3 @@
|
||||
/**
|
||||
* @file key_signals.h
|
||||
* @ingroup Core
|
||||
* @ingroup UI
|
||||
* @brief TODO: Document this.
|
||||
*/
|
||||
|
||||
#ifndef KEYSIGNALS_H
|
||||
#define KEYSIGNALS_H
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
/**
|
||||
* @file get_text_with_max.h
|
||||
* @ingroup UI
|
||||
* @brief Custom QInputDialog::getText implementation that allows configuration of the max length
|
||||
*/
|
||||
|
||||
// custom QInputDialog::getText implementation that allows configuration of the max length
|
||||
#ifndef GETTEXTWITHMAX_H
|
||||
#define GETTEXTWITHMAX_H
|
||||
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
/**
|
||||
* @file client_update_checker.h
|
||||
* @ingroup ClientUpdate
|
||||
* @brief TODO: Document this.
|
||||
*/
|
||||
|
||||
#ifndef CLIENT_UPDATE_CHECKER_H
|
||||
#define CLIENT_UPDATE_CHECKER_H
|
||||
#include <QObject>
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
#include "deck_link_to_api_transformer.h"
|
||||
|
||||
#include <QRegularExpression>
|
||||
|
||||
namespace DeckLinkToApiTransformer
|
||||
{
|
||||
|
||||
static const QString TAPPEDOUT_BASE = "https://tappedout.net/mtg-decks/";
|
||||
static const QString TAPPEDOUT_SUFFIX = "/?fmt=txt";
|
||||
|
||||
static const QString ARCHIDEKT_BASE = "https://archidekt.com/api/decks/";
|
||||
static const QString ARCHIDEKT_SUFFIX = "/?format=json";
|
||||
|
||||
static const QString MOXFIELD_BASE = "https://api.moxfield.com/v2/decks/all/";
|
||||
static const QString MOXFIELD_SUFFIX = "/";
|
||||
|
||||
static const QString DECKSTATS_SUFFIX = "?include_comments=1&export_mtgarena=1";
|
||||
|
||||
bool parseDeckUrl(const QString &url, ParsedDeckInfo &outInfo)
|
||||
{
|
||||
static QRegularExpression rxTappedOut("tappedout\\.net/(?:mtg-decks/)?([^/?#]+)");
|
||||
static QRegularExpression rxArchidekt("archidekt\\.com/decks/(\\d+)");
|
||||
static QRegularExpression rxMoxfield("moxfield\\.com/decks/([a-zA-Z0-9_-]+)");
|
||||
static QRegularExpression rxDeckstats("deckstats\\.net/decks/(\\d+/[a-zA-Z0-9_-]+)");
|
||||
|
||||
QRegularExpressionMatch match;
|
||||
|
||||
if ((match = rxTappedOut.match(url)).hasMatch()) {
|
||||
QString slug = match.captured(1);
|
||||
outInfo = ParsedDeckInfo{.baseUrl = TAPPEDOUT_BASE,
|
||||
.deckID = slug,
|
||||
.fullUrl = TAPPEDOUT_BASE + slug + TAPPEDOUT_SUFFIX,
|
||||
.provider = DeckProvider::TappedOut};
|
||||
return true;
|
||||
} else if ((match = rxArchidekt.match(url)).hasMatch()) {
|
||||
QString deckID = match.captured(1);
|
||||
outInfo = ParsedDeckInfo{.baseUrl = ARCHIDEKT_BASE,
|
||||
.deckID = deckID,
|
||||
.fullUrl = ARCHIDEKT_BASE + deckID + ARCHIDEKT_SUFFIX,
|
||||
.provider = DeckProvider::Archidekt};
|
||||
return true;
|
||||
} else if ((match = rxMoxfield.match(url)).hasMatch()) {
|
||||
QString deckID = match.captured(1);
|
||||
outInfo = ParsedDeckInfo{.baseUrl = MOXFIELD_BASE,
|
||||
.deckID = deckID,
|
||||
.fullUrl = MOXFIELD_BASE + deckID + MOXFIELD_SUFFIX,
|
||||
.provider = DeckProvider::Moxfield};
|
||||
return true;
|
||||
} else if ((match = rxDeckstats.match(url)).hasMatch()) {
|
||||
QString deckPath = match.captured(1);
|
||||
outInfo = ParsedDeckInfo{.baseUrl = "https://deckstats.net/decks/",
|
||||
.deckID = deckPath,
|
||||
.fullUrl = "https://deckstats.net/decks/" + deckPath + DECKSTATS_SUFFIX,
|
||||
.provider = DeckProvider::Deckstats};
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace DeckLinkToApiTransformer
|
||||
@@ -1,37 +0,0 @@
|
||||
/**
|
||||
* @file deck_link_to_api_transformer.h
|
||||
* @ingroup ApiInterfaces
|
||||
* @brief TODO: Document this.
|
||||
*/
|
||||
|
||||
#ifndef DECK_LINK_TO_API_TRANSFORMER_H
|
||||
#define DECK_LINK_TO_API_TRANSFORMER_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
enum class DeckProvider
|
||||
{
|
||||
TappedOut,
|
||||
Archidekt,
|
||||
Moxfield,
|
||||
Deckstats,
|
||||
Unknown
|
||||
};
|
||||
|
||||
struct ParsedDeckInfo
|
||||
{
|
||||
QString baseUrl;
|
||||
QString deckID;
|
||||
QString fullUrl;
|
||||
DeckProvider provider;
|
||||
};
|
||||
|
||||
namespace DeckLinkToApiTransformer
|
||||
{
|
||||
|
||||
// Returns true if the input URL is recognized and fills outInfo.
|
||||
bool parseDeckUrl(const QString &url, ParsedDeckInfo &outInfo);
|
||||
|
||||
} // namespace DeckLinkToApiTransformer
|
||||
|
||||
#endif // DECK_LINK_TO_API_TRANSFORMER_H
|
||||
@@ -1,118 +0,0 @@
|
||||
/**
|
||||
* @file interface_json_deck_parser.h
|
||||
* @ingroup ApiInterfaces
|
||||
* @brief TODO: Document this.
|
||||
*/
|
||||
|
||||
#ifndef INTERFACE_JSON_DECK_PARSER_H
|
||||
#define INTERFACE_JSON_DECK_PARSER_H
|
||||
#include "../../../deck/deck_loader.h"
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
|
||||
class IJsonDeckParser
|
||||
{
|
||||
public:
|
||||
virtual ~IJsonDeckParser() = default;
|
||||
|
||||
virtual DeckLoader *parse(const QJsonObject &obj) = 0;
|
||||
};
|
||||
|
||||
class ArchidektJsonParser : public IJsonDeckParser
|
||||
{
|
||||
public:
|
||||
DeckLoader *parse(const QJsonObject &obj) override
|
||||
{
|
||||
DeckLoader *list = new DeckLoader();
|
||||
|
||||
QString deckName = obj.value("name").toString();
|
||||
QString deckDescription = obj.value("description").toString();
|
||||
|
||||
list->setName(deckName);
|
||||
list->setComments(deckDescription);
|
||||
|
||||
QString outputText;
|
||||
QTextStream outStream(&outputText);
|
||||
|
||||
for (auto entry : obj.value("cards").toArray()) {
|
||||
auto quantity = entry.toObject().value("quantity").toInt();
|
||||
|
||||
auto card = entry.toObject().value("card").toObject();
|
||||
auto oracleCard = card.value("oracleCard").toObject();
|
||||
QString cardName = oracleCard.value("name").toString();
|
||||
QString setName = card.value("edition").toObject().value("editioncode").toString().toUpper();
|
||||
QString collectorNumber = card.value("collectorNumber").toString();
|
||||
|
||||
outStream << quantity << ' ' << cardName << " (" << setName << ") " << collectorNumber << '\n';
|
||||
}
|
||||
|
||||
list->loadFromStream_Plain(outStream, false);
|
||||
list->resolveSetNameAndNumberToProviderID();
|
||||
|
||||
return list;
|
||||
}
|
||||
};
|
||||
|
||||
class MoxfieldJsonParser : public IJsonDeckParser
|
||||
{
|
||||
public:
|
||||
DeckLoader *parse(const QJsonObject &obj) override
|
||||
{
|
||||
DeckLoader *list = new DeckLoader();
|
||||
|
||||
QString deckName = obj.value("name").toString();
|
||||
QString deckDescription = obj.value("description").toString();
|
||||
|
||||
list->setName(deckName);
|
||||
list->setComments(deckDescription);
|
||||
|
||||
QString outputText;
|
||||
QTextStream outStream(&outputText);
|
||||
|
||||
for (auto entry : obj.value("mainboard").toObject()) {
|
||||
auto quantity = entry.toObject().value("quantity").toInt();
|
||||
|
||||
auto card = entry.toObject().value("card").toObject();
|
||||
QString cardName = card.value("name").toString();
|
||||
QString setName = card.value("set").toString().toUpper();
|
||||
QString collectorNumber = card.value("cn").toString();
|
||||
|
||||
outStream << quantity << ' ' << cardName << " (" << setName << ") " << collectorNumber << '\n';
|
||||
}
|
||||
|
||||
outStream << '\n';
|
||||
|
||||
for (auto entry : obj.value("sideboard").toObject()) {
|
||||
auto quantity = entry.toObject().value("quantity").toInt();
|
||||
|
||||
auto card = entry.toObject().value("card").toObject();
|
||||
QString cardName = card.value("name").toString();
|
||||
QString setName = card.value("set").toString().toUpper();
|
||||
QString collectorNumber = card.value("cn").toString();
|
||||
|
||||
outStream << quantity << ' ' << cardName << " (" << setName << ") " << collectorNumber << '\n';
|
||||
}
|
||||
|
||||
list->loadFromStream_Plain(outStream, false);
|
||||
list->resolveSetNameAndNumberToProviderID();
|
||||
|
||||
QJsonObject commandersObj = obj.value("commanders").toObject();
|
||||
if (!commandersObj.isEmpty()) {
|
||||
for (auto it = commandersObj.begin(); it != commandersObj.end(); ++it) {
|
||||
QJsonObject cardData = it.value().toObject().value("card").toObject();
|
||||
QString commanderName = cardData.value("name").toString();
|
||||
QString setName = cardData.value("set").toString().toUpper();
|
||||
QString collectorNumber = cardData.value("cn").toString();
|
||||
QString providerId = cardData.value("scryfall_id").toString();
|
||||
|
||||
list->setBannerCard({commanderName, providerId});
|
||||
list->addCard(commanderName, DECK_ZONE_MAIN, -1, setName, collectorNumber, providerId);
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // INTERFACE_JSON_DECK_PARSER_H
|
||||
@@ -11,11 +11,6 @@
|
||||
#include <QSysInfo>
|
||||
#include <QtGlobal>
|
||||
|
||||
#if defined(Q_OS_MACOS)
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#define STABLERELEASE_URL "https://api.github.com/repos/Cockatrice/Cockatrice/releases/latest"
|
||||
#define STABLEMANUALDOWNLOAD_URL "https://github.com/Cockatrice/Cockatrice/releases/latest"
|
||||
#define STABLETAG_URL "https://api.github.com/repos/Cockatrice/Cockatrice/git/refs/tags/"
|
||||
@@ -38,42 +33,31 @@ ReleaseChannel::~ReleaseChannel()
|
||||
void ReleaseChannel::checkForUpdates()
|
||||
{
|
||||
QString releaseChannelUrl = getReleaseChannelUrl();
|
||||
qCInfo(ReleaseChannelLog) << "Searching for updates on the channel: " << releaseChannelUrl;
|
||||
qCDebug(ReleaseChannelLog) << "Searching for updates on the channel: " << releaseChannelUrl;
|
||||
response = netMan->get(QNetworkRequest(releaseChannelUrl));
|
||||
connect(response, &QNetworkReply::finished, this, &ReleaseChannel::releaseListFinished);
|
||||
}
|
||||
|
||||
// Different release channel checking functions for different operating systems
|
||||
#if defined(Q_OS_MACOS)
|
||||
bool ReleaseChannel::downloadMatchesCurrentOS(const QString &fileName)
|
||||
{
|
||||
#if defined(Q_OS_MACOS)
|
||||
static QRegularExpression version_regex("macOS(\\d+)");
|
||||
static QRegularExpression version_regex("macOS-(\\d+)\\.(\\d+)");
|
||||
auto match = version_regex.match(fileName);
|
||||
if (!match.hasMatch()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto getSystemVersion = [] {
|
||||
// QSysInfo does not go through translation layers
|
||||
// We need to use sysctl to reliably detect the underlying architecture
|
||||
char arch[255];
|
||||
size_t len = sizeof(arch);
|
||||
if (sysctlbyname("machdep.cpu.brand_string", arch, &len, nullptr, 0) == 0) {
|
||||
// Intel mac is only supported on macOS 13 versions
|
||||
if (QString::fromUtf8(arch).contains("Intel")) {
|
||||
return 13;
|
||||
}
|
||||
}
|
||||
|
||||
return QSysInfo::productVersion().split(".")[0].toInt();
|
||||
};
|
||||
|
||||
// older(smaller) releases are compatible with a newer or the same system version
|
||||
int sys_maj = getSystemVersion();
|
||||
int sys_maj = QSysInfo::productVersion().split(".")[0].toInt();
|
||||
int sys_min = QSysInfo::productVersion().split(".")[1].toInt();
|
||||
int rel_maj = match.captured(1).toInt();
|
||||
return rel_maj == sys_maj;
|
||||
|
||||
int rel_min = match.captured(2).toInt();
|
||||
return rel_maj < sys_maj || (rel_maj == sys_maj && rel_min <= sys_min);
|
||||
}
|
||||
#elif defined(Q_OS_WIN)
|
||||
bool ReleaseChannel::downloadMatchesCurrentOS(const QString &fileName)
|
||||
{
|
||||
#if Q_PROCESSOR_WORDSIZE == 4
|
||||
return fileName.contains("32bit");
|
||||
#elif Q_PROCESSOR_WORDSIZE == 8
|
||||
@@ -84,15 +68,16 @@ bool ReleaseChannel::downloadMatchesCurrentOS(const QString &fileName)
|
||||
return fileName.contains("Win10");
|
||||
}
|
||||
#else
|
||||
Q_UNUSED(fileName);
|
||||
return false;
|
||||
#endif
|
||||
|
||||
#else // If the OS doesn't fit one of the above #defines, then it will never match
|
||||
Q_UNUSED(fileName);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
bool ReleaseChannel::downloadMatchesCurrentOS(const QString &)
|
||||
{
|
||||
// If the OS doesn't fit one of the above #defines, then it will never match
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
QString StableReleaseChannel::getManualDownloadUrl() const
|
||||
{
|
||||
@@ -116,7 +101,7 @@ void StableReleaseChannel::releaseListFinished()
|
||||
QJsonDocument jsonResponse = QJsonDocument::fromJson(reply->readAll(), &parseError);
|
||||
reply->deleteLater();
|
||||
if (parseError.error != QJsonParseError::NoError) {
|
||||
qCWarning(ReleaseChannelLog) << "No reply received from the release update server.";
|
||||
qWarning() << "No reply received from the release update server.";
|
||||
emit error(tr("No reply received from the release update server."));
|
||||
return;
|
||||
}
|
||||
@@ -124,7 +109,7 @@ void StableReleaseChannel::releaseListFinished()
|
||||
QVariantMap resultMap = jsonResponse.toVariant().toMap();
|
||||
if (!(resultMap.contains("name") && resultMap.contains("html_url") && resultMap.contains("tag_name") &&
|
||||
resultMap.contains("published_at"))) {
|
||||
qCWarning(ReleaseChannelLog) << "Invalid received from the release update server:" << resultMap;
|
||||
qWarning() << "Invalid received from the release update server:" << resultMap;
|
||||
emit error(tr("Invalid reply received from the release update server."));
|
||||
return;
|
||||
}
|
||||
@@ -138,29 +123,37 @@ void StableReleaseChannel::releaseListFinished()
|
||||
|
||||
if (resultMap.contains("assets")) {
|
||||
auto rawAssets = resultMap["assets"].toList();
|
||||
for (const auto &rawAsset : rawAssets) {
|
||||
QVariantMap asset = rawAsset.toMap();
|
||||
// [(name, url)]
|
||||
QVector<std::pair<QString, QString>> assets;
|
||||
std::transform(rawAssets.begin(), rawAssets.end(), std::back_inserter(assets), [](QVariant _asset) {
|
||||
QVariantMap asset = _asset.toMap();
|
||||
QString name = asset["name"].toString();
|
||||
QString url = asset["browser_download_url"].toString();
|
||||
return std::make_pair(name, url);
|
||||
});
|
||||
|
||||
if (downloadMatchesCurrentOS(name)) {
|
||||
lastRelease->setDownloadUrl(url);
|
||||
break;
|
||||
}
|
||||
auto _releaseAsset = std::find_if(assets.begin(), assets.end(), [](std::pair<QString, QString> nameAndUrl) {
|
||||
return downloadMatchesCurrentOS(nameAndUrl.first);
|
||||
});
|
||||
|
||||
if (_releaseAsset != assets.end()) {
|
||||
std::pair<QString, QString> releaseAsset = *_releaseAsset;
|
||||
auto releaseUrl = releaseAsset.second;
|
||||
lastRelease->setDownloadUrl(releaseUrl);
|
||||
}
|
||||
}
|
||||
|
||||
QString shortHash = lastRelease->getCommitHash().left(GIT_SHORT_HASH_LEN);
|
||||
QString myHash = QString(VERSION_COMMIT);
|
||||
qCInfo(ReleaseChannelLog) << "Current hash=" << myHash << "update hash=" << shortHash;
|
||||
qCDebug(ReleaseChannelLog) << "Current hash=" << myHash << "update hash=" << shortHash;
|
||||
|
||||
qCInfo(ReleaseChannelLog) << "Got reply from release server, name=" << lastRelease->getName()
|
||||
<< "desc=" << lastRelease->getDescriptionUrl() << "date=" << lastRelease->getPublishDate()
|
||||
<< "url=" << lastRelease->getDownloadUrl();
|
||||
qCDebug(ReleaseChannelLog) << "Got reply from release server, name=" << lastRelease->getName()
|
||||
<< "desc=" << lastRelease->getDescriptionUrl()
|
||||
<< "date=" << lastRelease->getPublishDate() << "url=" << lastRelease->getDownloadUrl();
|
||||
|
||||
const QString &tagName = resultMap["tag_name"].toString();
|
||||
QString url = QString(STABLETAG_URL) + tagName;
|
||||
qCInfo(ReleaseChannelLog) << "Searching for commit hash corresponding to stable channel tag: " << tagName;
|
||||
qCDebug(ReleaseChannelLog) << "Searching for commit hash corresponding to stable channel tag: " << tagName;
|
||||
response = netMan->get(QNetworkRequest(url));
|
||||
connect(response, &QNetworkReply::finished, this, &StableReleaseChannel::tagListFinished);
|
||||
}
|
||||
@@ -172,24 +165,24 @@ void StableReleaseChannel::tagListFinished()
|
||||
QJsonDocument jsonResponse = QJsonDocument::fromJson(reply->readAll(), &parseError);
|
||||
reply->deleteLater();
|
||||
if (parseError.error != QJsonParseError::NoError) {
|
||||
qCWarning(ReleaseChannelLog) << "No reply received from the tag update server.";
|
||||
qWarning() << "No reply received from the tag update server.";
|
||||
emit error(tr("No reply received from the tag update server."));
|
||||
return;
|
||||
}
|
||||
|
||||
QVariantMap resultMap = jsonResponse.toVariant().toMap();
|
||||
if (!(resultMap.contains("object") && resultMap["object"].toMap().contains("sha"))) {
|
||||
qCWarning(ReleaseChannelLog) << "Invalid received from the tag update server.";
|
||||
qWarning() << "Invalid received from the tag update server.";
|
||||
emit error(tr("Invalid reply received from the tag update server."));
|
||||
return;
|
||||
}
|
||||
|
||||
lastRelease->setCommitHash(resultMap["object"].toMap()["sha"].toString());
|
||||
qCInfo(ReleaseChannelLog) << "Got reply from tag server, commit=" << lastRelease->getCommitHash();
|
||||
qCDebug(ReleaseChannelLog) << "Got reply from tag server, commit=" << lastRelease->getCommitHash();
|
||||
|
||||
QString shortHash = lastRelease->getCommitHash().left(GIT_SHORT_HASH_LEN);
|
||||
QString myHash = QString(VERSION_COMMIT);
|
||||
qCInfo(ReleaseChannelLog) << "Current hash=" << myHash << "update hash=" << shortHash;
|
||||
qCDebug(ReleaseChannelLog) << "Current hash=" << myHash << "update hash=" << shortHash;
|
||||
const bool needToUpdate = (QString::compare(shortHash, myHash, Qt::CaseInsensitive) != 0);
|
||||
|
||||
emit finishedCheck(needToUpdate, lastRelease->isCompatibleVersionFound(), lastRelease);
|
||||
@@ -232,7 +225,7 @@ void BetaReleaseChannel::releaseListFinished()
|
||||
QVariantMap resultMap = array.at(0).toObject().toVariantMap();
|
||||
|
||||
if (array.empty() || resultMap.empty()) {
|
||||
qCWarning(ReleaseChannelLog) << "No reply received from the release update server:" << QString(jsonData);
|
||||
qWarning() << "No reply received from the release update server:" << QString(jsonData);
|
||||
emit error(tr("No reply received from the release update server."));
|
||||
return;
|
||||
}
|
||||
@@ -241,7 +234,7 @@ void BetaReleaseChannel::releaseListFinished()
|
||||
if (!resultMap.contains("assets") || !resultMap.contains("author") || !resultMap.contains("tag_name") ||
|
||||
!resultMap.contains("target_commitish") || !resultMap.contains("assets_url") ||
|
||||
!resultMap.contains("published_at")) {
|
||||
qCWarning(ReleaseChannelLog) << "Invalid received from the release update server:" << resultMap;
|
||||
qWarning() << "Invalid received from the release update server:" << resultMap;
|
||||
emit error(tr("Invalid reply received from the release update server."));
|
||||
return;
|
||||
}
|
||||
@@ -256,13 +249,13 @@ void BetaReleaseChannel::releaseListFinished()
|
||||
lastRelease->setName(QString("%1 (%2)").arg(resultMap["tag_name"].toString()).arg(shortHash));
|
||||
lastRelease->setDescriptionUrl(QString(BETARELEASE_CHANGESURL).arg(VERSION_COMMIT, shortHash));
|
||||
|
||||
qCInfo(ReleaseChannelLog) << "Got reply from release server, size=" << resultMap.size()
|
||||
<< "name=" << lastRelease->getName() << "desc=" << lastRelease->getDescriptionUrl()
|
||||
<< "commit=" << lastRelease->getCommitHash() << "date=" << lastRelease->getPublishDate();
|
||||
qCDebug(ReleaseChannelLog) << "Got reply from release server, size=" << resultMap.size()
|
||||
<< "name=" << lastRelease->getName() << "desc=" << lastRelease->getDescriptionUrl()
|
||||
<< "commit=" << lastRelease->getCommitHash() << "date=" << lastRelease->getPublishDate();
|
||||
|
||||
QString betaBuildDownloadUrl = resultMap["assets_url"].toString();
|
||||
|
||||
qCInfo(ReleaseChannelLog) << "Searching for a corresponding file on the beta channel: " << betaBuildDownloadUrl;
|
||||
qCDebug(ReleaseChannelLog) << "Searching for a corresponding file on the beta channel: " << betaBuildDownloadUrl;
|
||||
response = netMan->get(QNetworkRequest(betaBuildDownloadUrl));
|
||||
connect(response, &QNetworkReply::finished, this, &BetaReleaseChannel::fileListFinished);
|
||||
}
|
||||
@@ -274,7 +267,7 @@ void BetaReleaseChannel::fileListFinished()
|
||||
QJsonDocument jsonResponse = QJsonDocument::fromJson(reply->readAll(), &parseError);
|
||||
reply->deleteLater();
|
||||
if (parseError.error != QJsonParseError::NoError) {
|
||||
qCWarning(ReleaseChannelLog) << "No reply received from the file update server.";
|
||||
qWarning() << "No reply received from the file update server.";
|
||||
emit error(tr("No reply received from the file update server."));
|
||||
return;
|
||||
}
|
||||
@@ -282,7 +275,7 @@ void BetaReleaseChannel::fileListFinished()
|
||||
QVariantList resultList = jsonResponse.toVariant().toList();
|
||||
QString shortHash = lastRelease->getCommitHash().left(GIT_SHORT_HASH_LEN);
|
||||
QString myHash = QString(VERSION_COMMIT);
|
||||
qCInfo(ReleaseChannelLog) << "Current hash=" << myHash << "update hash=" << shortHash;
|
||||
qCDebug(ReleaseChannelLog) << "Current hash=" << myHash << "update hash=" << shortHash;
|
||||
|
||||
bool needToUpdate = (QString::compare(shortHash, myHash, Qt::CaseInsensitive) != 0);
|
||||
bool compatibleVersion = false;
|
||||
@@ -299,7 +292,7 @@ void BetaReleaseChannel::fileListFinished()
|
||||
if (downloadMatchesCurrentOS(*url)) {
|
||||
compatibleVersion = true;
|
||||
lastRelease->setDownloadUrl(*url);
|
||||
qCInfo(ReleaseChannelLog) << "Found compatible version url=" << *url;
|
||||
qCDebug(ReleaseChannelLog) << "Found compatible version url=" << *url;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
/**
|
||||
* @file release_channel.h
|
||||
* @ingroup ClientUpdate
|
||||
* @brief TODO: Document this.
|
||||
*/
|
||||
|
||||
#ifndef RELEASECHANNEL_H
|
||||
#define RELEASECHANNEL_H
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "replay_timeline_widget.h"
|
||||
|
||||
#include "../../settings/cache_settings.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <QPalette>
|
||||
@@ -153,16 +151,16 @@ void ReplayTimelineWidget::processNewEvents(PlaybackMode playbackMode)
|
||||
currentProcessedTime = currentVisualTime;
|
||||
|
||||
while ((currentEvent < replayTimeline.size()) && (replayTimeline[currentEvent] < currentProcessedTime)) {
|
||||
EventProcessingOptions options;
|
||||
Player::EventProcessingOptions options;
|
||||
|
||||
// backwards skip => always skip reveal windows
|
||||
// forwards skip => skip reveal windows that don't happen within a big skip of the target
|
||||
if (playbackMode == BACKWARD_SKIP || currentProcessedTime - replayTimeline[currentEvent] > BIG_SKIP_MS)
|
||||
options |= SKIP_REVEAL_WINDOW;
|
||||
options |= Player::EventProcessingOption::SKIP_REVEAL_WINDOW;
|
||||
|
||||
// backwards skip => always skip tap animation
|
||||
if (playbackMode == BACKWARD_SKIP)
|
||||
options |= SKIP_TAP_ANIMATION;
|
||||
options |= Player::EventProcessingOption::SKIP_TAP_ANIMATION;
|
||||
|
||||
emit processNextEvent(options);
|
||||
++currentEvent;
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
/**
|
||||
* @file replay_timeline_widget.h
|
||||
* @ingroup Replay
|
||||
* @brief TODO: Document this.
|
||||
*/
|
||||
|
||||
#ifndef REPLAY_TIMELINE_WIDGET
|
||||
#define REPLAY_TIMELINE_WIDGET
|
||||
|
||||
#include "../../game/player/event_processing_options.h"
|
||||
#include "../../game/player/player.h"
|
||||
|
||||
#include <QList>
|
||||
#include <QMouseEvent>
|
||||
@@ -20,7 +14,7 @@ class ReplayTimelineWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
signals:
|
||||
void processNextEvent(EventProcessingOptions options);
|
||||
void processNextEvent(Player::EventProcessingOptions options);
|
||||
void replayFinished();
|
||||
void rewound();
|
||||
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
/**
|
||||
* @file sets_model.h
|
||||
* @ingroup CardDatabaseModels
|
||||
* @brief TODO: Document this.
|
||||
*/
|
||||
|
||||
#ifndef SETSMODEL_H
|
||||
#define SETSMODEL_H
|
||||
|
||||
#include "../../database/card_database.h"
|
||||
#include "../../game/cards/card_database.h"
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include <QMimeData>
|
||||
@@ -43,7 +37,7 @@ class SetsModel : public QAbstractTableModel
|
||||
|
||||
private:
|
||||
static const int NUM_COLS = 7;
|
||||
CardSetList sets;
|
||||
SetList sets;
|
||||
QSet<CardSetPtr> enabledSets;
|
||||
|
||||
public:
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#include "spoiler_background_updater.h"
|
||||
|
||||
#include "../../database/card_database.h"
|
||||
#include "../../database/card_database_manager.h"
|
||||
#include "../../interface/window_main.h"
|
||||
#include "../../game/cards/card_database.h"
|
||||
#include "../../game/cards/card_database_manager.h"
|
||||
#include "../../main.h"
|
||||
#include "../../settings/cache_settings.h"
|
||||
#include "../ui/window_main.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCryptographicHash>
|
||||
@@ -28,7 +28,7 @@ SpoilerBackgroundUpdater::SpoilerBackgroundUpdater(QObject *apParent) : QObject(
|
||||
// File exists means we're in spoiler season
|
||||
startSpoilerDownloadProcess(SPOILERS_STATUS_URL, false);
|
||||
} else {
|
||||
qCInfo(SpoilerBackgroundUpdaterLog) << "Spoilers Disabled";
|
||||
qCDebug(SpoilerBackgroundUpdaterLog) << "Spoilers Disabled";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ void SpoilerBackgroundUpdater::actDownloadFinishedSpoilersFile()
|
||||
reply->deleteLater();
|
||||
emit spoilerCheckerDone();
|
||||
} else {
|
||||
qCWarning(SpoilerBackgroundUpdaterLog) << "Error downloading spoilers file" << errorCode;
|
||||
qCDebug(SpoilerBackgroundUpdaterLog) << "Error downloading spoilers file" << errorCode;
|
||||
emit spoilerCheckerDone();
|
||||
}
|
||||
}
|
||||
@@ -81,11 +81,11 @@ bool SpoilerBackgroundUpdater::deleteSpoilerFile()
|
||||
|
||||
// Delete the spoiler.xml file
|
||||
if (file.exists() && file.remove()) {
|
||||
qCInfo(SpoilerBackgroundUpdaterLog) << "Deleting spoiler.xml";
|
||||
qCDebug(SpoilerBackgroundUpdaterLog) << "Deleting spoiler.xml";
|
||||
return true;
|
||||
}
|
||||
|
||||
qCInfo(SpoilerBackgroundUpdaterLog) << "Error: Spoiler.xml not found or not deleted";
|
||||
qCDebug(SpoilerBackgroundUpdaterLog) << "Error: Spoiler.xml not found or not deleted";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -101,24 +101,24 @@ void SpoilerBackgroundUpdater::actCheckIfSpoilerSeasonEnabled()
|
||||
trayIcon->showMessage(tr("Spoilers season has ended"), tr("Deleting spoiler.xml. Please run Oracle"));
|
||||
}
|
||||
|
||||
qCInfo(SpoilerBackgroundUpdaterLog) << "Spoiler Season Offline";
|
||||
qCDebug(SpoilerBackgroundUpdaterLog) << "Spoiler Season Offline";
|
||||
emit spoilerCheckerDone();
|
||||
} else if (errorCode == QNetworkReply::NoError) {
|
||||
qCInfo(SpoilerBackgroundUpdaterLog) << "Spoiler Service Online";
|
||||
qCDebug(SpoilerBackgroundUpdaterLog) << "Spoiler Service Online";
|
||||
startSpoilerDownloadProcess(SPOILERS_URL, true);
|
||||
} else if (errorCode == QNetworkReply::HostNotFoundError) {
|
||||
if (trayIcon) {
|
||||
trayIcon->showMessage(tr("Spoilers download failed"), tr("No internet connection"));
|
||||
}
|
||||
|
||||
qCWarning(SpoilerBackgroundUpdaterLog) << "Spoiler download failed due to no internet connection";
|
||||
qCDebug(SpoilerBackgroundUpdaterLog) << "Spoiler download failed due to no internet connection";
|
||||
emit spoilerCheckerDone();
|
||||
} else {
|
||||
if (trayIcon) {
|
||||
trayIcon->showMessage(tr("Spoilers download failed"), tr("Error") + " " + (short)errorCode);
|
||||
}
|
||||
|
||||
qCWarning(SpoilerBackgroundUpdaterLog) << "Spoiler download failed with reason" << errorCode;
|
||||
qCDebug(SpoilerBackgroundUpdaterLog) << "Spoiler download failed with reason" << errorCode;
|
||||
emit spoilerCheckerDone();
|
||||
}
|
||||
}
|
||||
@@ -139,19 +139,19 @@ bool SpoilerBackgroundUpdater::saveDownloadedFile(QByteArray data)
|
||||
trayIcon->showMessage(tr("Spoilers already up to date"), tr("No new spoilers added"));
|
||||
}
|
||||
|
||||
qCInfo(SpoilerBackgroundUpdaterLog) << "Spoilers Up to Date";
|
||||
qCDebug(SpoilerBackgroundUpdaterLog) << "Spoilers Up to Date";
|
||||
return false;
|
||||
}
|
||||
|
||||
QFile file(fileName);
|
||||
if (!file.open(QIODevice::WriteOnly)) {
|
||||
qCWarning(SpoilerBackgroundUpdaterLog) << "Spoiler Service Error: File open (w) failed for" << fileName;
|
||||
qCDebug(SpoilerBackgroundUpdaterLog) << "Spoiler Service Error: File open (w) failed for" << fileName;
|
||||
file.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (file.write(data) == -1) {
|
||||
qCWarning(SpoilerBackgroundUpdaterLog) << "Spoiler Service Error: File write (w) failed for" << fileName;
|
||||
qCDebug(SpoilerBackgroundUpdaterLog) << "Spoiler Service Error: File write (w) failed for" << fileName;
|
||||
file.close();
|
||||
return false;
|
||||
}
|
||||
@@ -159,7 +159,7 @@ bool SpoilerBackgroundUpdater::saveDownloadedFile(QByteArray data)
|
||||
file.close();
|
||||
|
||||
// Data written, so reload the card database
|
||||
qCInfo(SpoilerBackgroundUpdaterLog) << "Spoiler Service Data Written";
|
||||
qCDebug(SpoilerBackgroundUpdaterLog) << "Spoiler Service Data Written";
|
||||
const auto reloadOk = QtConcurrent::run([] { CardDatabaseManager::getInstance()->loadCardDatabases(); });
|
||||
|
||||
// If the user has notifications enabled, let them know
|
||||
@@ -202,12 +202,12 @@ QByteArray SpoilerBackgroundUpdater::getHash(const QString fileName)
|
||||
QCryptographicHash hash(QCryptographicHash::Algorithm::Md5);
|
||||
hash.addData(bytes);
|
||||
|
||||
qCInfo(SpoilerBackgroundUpdaterLog) << "File Hash =" << hash.result();
|
||||
qCDebug(SpoilerBackgroundUpdaterLog) << "File Hash =" << hash.result();
|
||||
|
||||
file.close();
|
||||
return hash.result();
|
||||
} else {
|
||||
qCWarning(SpoilerBackgroundUpdaterLog) << "getHash ReadOnly failed!";
|
||||
qCDebug(SpoilerBackgroundUpdaterLog) << "getHash ReadOnly failed!";
|
||||
file.close();
|
||||
return QByteArray();
|
||||
}
|
||||
@@ -221,7 +221,7 @@ QByteArray SpoilerBackgroundUpdater::getHash(QByteArray data)
|
||||
QCryptographicHash hash(QCryptographicHash::Algorithm::Md5);
|
||||
hash.addData(bytes);
|
||||
|
||||
qCInfo(SpoilerBackgroundUpdaterLog) << "Data Hash =" << hash.result();
|
||||
qCDebug(SpoilerBackgroundUpdaterLog) << "Data Hash =" << hash.result();
|
||||
|
||||
return hash.result();
|
||||
}
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
/**
|
||||
* @file spoiler_background_updater.h
|
||||
* @ingroup Client
|
||||
* @brief TODO: Document this.
|
||||
*/
|
||||
|
||||
#ifndef COCKATRICE_SPOILER_DOWNLOADER_H
|
||||
#define COCKATRICE_SPOILER_DOWNLOADER_H
|
||||
|
||||
|
||||
@@ -1,150 +0,0 @@
|
||||
#include "replay_manager.h"
|
||||
|
||||
#include "../tabs/tab_game.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QToolButton>
|
||||
|
||||
ReplayManager::ReplayManager(TabGame *parent, GameReplay *_replay)
|
||||
: QWidget(parent), game(parent), replay(_replay), replayPlayButton(nullptr), replayFastForwardButton(nullptr),
|
||||
aReplaySkipForward(nullptr), aReplaySkipBackward(nullptr), aReplaySkipForwardBig(nullptr),
|
||||
aReplaySkipBackwardBig(nullptr)
|
||||
{
|
||||
if (replay) {
|
||||
game->getGame()->loadReplay(replay);
|
||||
|
||||
// Create list: event number -> time [ms]
|
||||
// Distribute simultaneous events evenly across 1 second.
|
||||
unsigned int lastEventTimestamp = 0;
|
||||
const int eventCount = replay->event_list_size();
|
||||
for (int i = 0; i < eventCount; ++i) {
|
||||
int j = i + 1;
|
||||
while ((j < eventCount) && (replay->event_list(j).seconds_elapsed() == lastEventTimestamp))
|
||||
++j;
|
||||
|
||||
const int numberEventsThisSecond = j - i;
|
||||
for (int k = 0; k < numberEventsThisSecond; ++k)
|
||||
replayTimeline.append(replay->event_list(i + k).seconds_elapsed() * 1000 +
|
||||
(int)((qreal)k / (qreal)numberEventsThisSecond * 1000));
|
||||
|
||||
if (j < eventCount)
|
||||
lastEventTimestamp = replay->event_list(j).seconds_elapsed();
|
||||
i += numberEventsThisSecond - 1;
|
||||
}
|
||||
}
|
||||
|
||||
// timeline widget
|
||||
timelineWidget = new ReplayTimelineWidget;
|
||||
timelineWidget->setTimeline(replayTimeline);
|
||||
connect(timelineWidget, &ReplayTimelineWidget::processNextEvent, this, &ReplayManager::replayNextEvent);
|
||||
connect(timelineWidget, &ReplayTimelineWidget::replayFinished, this, &ReplayManager::replayFinished);
|
||||
connect(timelineWidget, &ReplayTimelineWidget::rewound, this, &ReplayManager::replayRewind);
|
||||
|
||||
// timeline skip shortcuts
|
||||
aReplaySkipForward = new QAction(timelineWidget);
|
||||
timelineWidget->addAction(aReplaySkipForward);
|
||||
connect(aReplaySkipForward, &QAction::triggered, this,
|
||||
[this] { timelineWidget->skipByAmount(ReplayTimelineWidget::SMALL_SKIP_MS); });
|
||||
|
||||
aReplaySkipBackward = new QAction(timelineWidget);
|
||||
timelineWidget->addAction(aReplaySkipBackward);
|
||||
connect(aReplaySkipBackward, &QAction::triggered, this,
|
||||
[this] { timelineWidget->skipByAmount(-ReplayTimelineWidget::SMALL_SKIP_MS); });
|
||||
|
||||
aReplaySkipForwardBig = new QAction(timelineWidget);
|
||||
timelineWidget->addAction(aReplaySkipForwardBig);
|
||||
connect(aReplaySkipForwardBig, &QAction::triggered, this,
|
||||
[this] { timelineWidget->skipByAmount(ReplayTimelineWidget::BIG_SKIP_MS); });
|
||||
|
||||
aReplaySkipBackwardBig = new QAction(timelineWidget);
|
||||
timelineWidget->addAction(aReplaySkipBackwardBig);
|
||||
connect(aReplaySkipBackwardBig, &QAction::triggered, this,
|
||||
[this] { timelineWidget->skipByAmount(-ReplayTimelineWidget::BIG_SKIP_MS); });
|
||||
|
||||
// buttons
|
||||
replayPlayButton = new QToolButton;
|
||||
replayPlayButton->setIconSize(QSize(32, 32));
|
||||
QIcon playButtonIcon = QIcon();
|
||||
playButtonIcon.addPixmap(QPixmap("theme:replay/start"), QIcon::Normal, QIcon::Off);
|
||||
playButtonIcon.addPixmap(QPixmap("theme:replay/pause"), QIcon::Normal, QIcon::On);
|
||||
replayPlayButton->setIcon(playButtonIcon);
|
||||
replayPlayButton->setCheckable(true);
|
||||
connect(replayPlayButton, &QToolButton::toggled, this, &ReplayManager::replayPlayButtonToggled);
|
||||
|
||||
replayFastForwardButton = new QToolButton;
|
||||
replayFastForwardButton->setIconSize(QSize(32, 32));
|
||||
replayFastForwardButton->setIcon(QPixmap("theme:replay/fastforward"));
|
||||
replayFastForwardButton->setCheckable(true);
|
||||
connect(replayFastForwardButton, &QToolButton::toggled, this, &ReplayManager::replayFastForwardButtonToggled);
|
||||
|
||||
// putting everything together
|
||||
auto replayControlLayout = new QHBoxLayout;
|
||||
replayControlLayout->addWidget(timelineWidget, 10);
|
||||
replayControlLayout->addWidget(replayPlayButton);
|
||||
replayControlLayout->addWidget(replayFastForwardButton);
|
||||
|
||||
setObjectName("replayControlWidget");
|
||||
setLayout(replayControlLayout);
|
||||
|
||||
connect(this, &ReplayManager::requestChatAndPhaseReset, game, &TabGame::resetChatAndPhase);
|
||||
|
||||
connect(&SettingsCache::instance().shortcuts(), &ShortcutsSettings::shortCutChanged, this,
|
||||
&ReplayManager::refreshShortcuts);
|
||||
refreshShortcuts();
|
||||
}
|
||||
|
||||
void ReplayManager::replayNextEvent(EventProcessingOptions options)
|
||||
{
|
||||
game->getGame()->getGameEventHandler()->processGameEventContainer(
|
||||
replay->event_list(timelineWidget->getCurrentEvent()), nullptr, options);
|
||||
}
|
||||
|
||||
void ReplayManager::replayFinished()
|
||||
{
|
||||
replayPlayButton->setChecked(false);
|
||||
}
|
||||
|
||||
void ReplayManager::replayPlayButtonToggled(bool checked)
|
||||
{
|
||||
if (checked) { // start replay
|
||||
timelineWidget->startReplay();
|
||||
} else { // pause replay
|
||||
timelineWidget->stopReplay();
|
||||
}
|
||||
}
|
||||
|
||||
void ReplayManager::replayFastForwardButtonToggled(bool checked)
|
||||
{
|
||||
timelineWidget->setTimeScaleFactor(checked ? ReplayTimelineWidget::FAST_FORWARD_SCALE_FACTOR : 1.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handles everything that needs to be reset when doing a replay rewind.
|
||||
*/
|
||||
void ReplayManager::replayRewind()
|
||||
{
|
||||
emit requestChatAndPhaseReset();
|
||||
}
|
||||
|
||||
void ReplayManager::refreshShortcuts()
|
||||
{
|
||||
ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts();
|
||||
if (aReplaySkipForward) {
|
||||
aReplaySkipForward->setShortcuts(shortcuts.getShortcut("Replays/aSkipForward"));
|
||||
}
|
||||
if (aReplaySkipBackward) {
|
||||
aReplaySkipBackward->setShortcuts(shortcuts.getShortcut("Replays/aSkipBackward"));
|
||||
}
|
||||
if (aReplaySkipForwardBig) {
|
||||
aReplaySkipForwardBig->setShortcuts(shortcuts.getShortcut("Replays/aSkipForwardBig"));
|
||||
}
|
||||
if (aReplaySkipBackwardBig) {
|
||||
aReplaySkipBackwardBig->setShortcuts(shortcuts.getShortcut("Replays/aSkipBackwardBig"));
|
||||
}
|
||||
if (replayPlayButton) {
|
||||
replayPlayButton->setShortcut(shortcuts.getSingleShortcut("Replays/playButton"));
|
||||
}
|
||||
if (replayFastForwardButton) {
|
||||
replayFastForwardButton->setShortcut(shortcuts.getSingleShortcut("Replays/fastForwardButton"));
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/**
|
||||
* @file replay_manager.h
|
||||
* @ingroup Core
|
||||
* @ingroup Replay
|
||||
* @brief TODO: Document this.
|
||||
*/
|
||||
|
||||
#ifndef REPLAY_MANAGER_H
|
||||
#define REPLAY_MANAGER_H
|
||||
|
||||
#include "network/replay_timeline_widget.h"
|
||||
#include "pb/game_replay.pb.h"
|
||||
|
||||
#include <QToolButton>
|
||||
#include <QWidget>
|
||||
|
||||
class TabGame;
|
||||
|
||||
class ReplayManager : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ReplayManager(TabGame *parent, GameReplay *replay);
|
||||
TabGame *game;
|
||||
GameReplay *replay;
|
||||
|
||||
signals:
|
||||
void requestChatAndPhaseReset();
|
||||
|
||||
private:
|
||||
// Replay related members
|
||||
int currentReplayStep = 0;
|
||||
QList<int> replayTimeline;
|
||||
ReplayTimelineWidget *timelineWidget;
|
||||
QToolButton *replayPlayButton, *replayFastForwardButton;
|
||||
QAction *aReplaySkipForward, *aReplaySkipBackward, *aReplaySkipForwardBig, *aReplaySkipBackwardBig;
|
||||
|
||||
private slots:
|
||||
void replayNextEvent(EventProcessingOptions options);
|
||||
void replayFinished();
|
||||
void replayPlayButtonToggled(bool checked);
|
||||
void replayFastForwardButtonToggled(bool checked);
|
||||
void replayRewind();
|
||||
void refreshShortcuts();
|
||||
};
|
||||
|
||||
#endif // REPLAY_MANAGER_H
|
||||
@@ -37,7 +37,7 @@ SoundEngine::~SoundEngine()
|
||||
void SoundEngine::soundEnabledChanged()
|
||||
{
|
||||
if (SettingsCache::instance().getSoundEnabled()) {
|
||||
qCInfo(SoundEngineLog) << "SoundEngine: enabling sound with" << audioData.size() << "sounds";
|
||||
qCDebug(SoundEngineLog) << "SoundEngine: enabling sound with" << audioData.size() << "sounds";
|
||||
if (!player) {
|
||||
player = new QMediaPlayer;
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
@@ -46,7 +46,7 @@ void SoundEngine::soundEnabledChanged()
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
qCInfo(SoundEngineLog) << "SoundEngine: disabling sound";
|
||||
qCDebug(SoundEngineLog) << "SoundEngine: disabling sound";
|
||||
if (player) {
|
||||
player->stop();
|
||||
player->deleteLater();
|
||||
@@ -90,7 +90,7 @@ void SoundEngine::ensureThemeDirectoryExists()
|
||||
{
|
||||
if (SettingsCache::instance().getSoundThemeName().isEmpty() ||
|
||||
!getAvailableThemes().contains(SettingsCache::instance().getSoundThemeName())) {
|
||||
qCInfo(SoundEngineLog) << "Sounds theme name not set, setting default value";
|
||||
qCDebug(SoundEngineLog) << "Sounds theme name not set, setting default value";
|
||||
SettingsCache::instance().setSoundThemeName(DEFAULT_THEME_NAME);
|
||||
}
|
||||
}
|
||||
@@ -131,7 +131,7 @@ QStringMap &SoundEngine::getAvailableThemes()
|
||||
void SoundEngine::themeChangedSlot()
|
||||
{
|
||||
QString themeName = SettingsCache::instance().getSoundThemeName();
|
||||
qCInfo(SoundEngineLog) << "Sound theme changed:" << themeName;
|
||||
qCDebug(SoundEngineLog) << "Sound theme changed:" << themeName;
|
||||
|
||||
QDir dir = getAvailableThemes().value(themeName);
|
||||
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
/**
|
||||
* @file sound_engine.h
|
||||
* @ingroup Core
|
||||
* @brief TODO: Document this.
|
||||
*/
|
||||
|
||||
#ifndef SOUNDENGINE_H
|
||||
#define SOUNDENGINE_H
|
||||
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
#ifndef DECKDATA_H
|
||||
#define DECKDATA_H
|
||||
|
||||
#include "../archidekt_links/edhrec_api_response_archidekt_links.h"
|
||||
#include "../cards/edhrec_api_response_card_container.h"
|
||||
#include "edhrec_commander_api_response_archidekt_links.h"
|
||||
#include "edhrec_commander_api_response_average_deck_statistics.h"
|
||||
#include "edhrec_commander_api_response_card_container.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QJsonObject>
|
||||
#include <QString>
|
||||
|
||||
/**
|
||||
* @class EdhrecCommanderApiResponse
|
||||
* @ingroup ApiResponses
|
||||
* @brief Represents the main structure of the JSON
|
||||
*/
|
||||
// Represents the main structure of the JSON
|
||||
class EdhrecCommanderApiResponse
|
||||
{
|
||||
public:
|
||||
@@ -23,7 +19,7 @@ public:
|
||||
QString header;
|
||||
QJsonObject panels;
|
||||
QString description;
|
||||
EdhrecApiResponseCardContainer container;
|
||||
EdhrecCommanderApiResponseCardContainer container;
|
||||
|
||||
void fromJson(const QJsonObject &json);
|
||||
void debugPrint() const;
|
||||
@@ -1,11 +1,11 @@
|
||||
#include "edhrec_api_response_archidekt_links.h"
|
||||
#include "edhrec_commander_api_response_archidekt_links.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
|
||||
void EdhrecApiResponseArchidektLink::fromJson(const QJsonObject &json)
|
||||
void EdhrecCommanderApiResponseArchidektLink::fromJson(const QJsonObject &json)
|
||||
{
|
||||
c = json.value("c").toString();
|
||||
f = json.value("f").toInt(0);
|
||||
@@ -13,7 +13,7 @@ void EdhrecApiResponseArchidektLink::fromJson(const QJsonObject &json)
|
||||
u = json.value("u").toString();
|
||||
}
|
||||
|
||||
void EdhrecApiResponseArchidektLink::debugPrint() const
|
||||
void EdhrecCommanderApiResponseArchidektLink::debugPrint() const
|
||||
{
|
||||
qDebug() << " C:" << c;
|
||||
qDebug() << " F:" << f;
|
||||
@@ -27,7 +27,7 @@ void EdhrecCommanderApiResponseArchidektLinks::fromJson(const QJsonArray &json)
|
||||
for (const QJsonValue &value : json) {
|
||||
if (value.isObject()) {
|
||||
QJsonObject entryJson = value.toObject();
|
||||
EdhrecApiResponseArchidektLink entry;
|
||||
EdhrecCommanderApiResponseArchidektLink entry;
|
||||
entry.fromJson(entryJson);
|
||||
entries.append(entry);
|
||||
}
|
||||