Compare commits
No commits in common. "master" and "2025-09-29-Development-2.11.0-beta.32" have entirely different histories.
master
...
2025-09-29
|
|
@ -1,4 +1,4 @@
|
|||
FROM fedora:43
|
||||
FROM fedora:41
|
||||
|
||||
RUN dnf install -y \
|
||||
ccache \
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
FROM debian:11
|
||||
|
||||
RUN apt-get update && \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||
build-essential \
|
||||
ccache \
|
||||
clang-format \
|
||||
cmake \
|
||||
file \
|
||||
g++ \
|
||||
git \
|
||||
libmariadb-dev-compat \
|
||||
libprotobuf-dev \
|
||||
libqt5sql5-mysql \
|
||||
libqt5websockets5-dev \
|
||||
ninja-build \
|
||||
protobuf-compiler \
|
||||
qttools5-dev \
|
||||
qttools5-dev-tools \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
|
@ -9,18 +9,20 @@ RUN apt-get update && \
|
|||
file \
|
||||
g++ \
|
||||
git \
|
||||
libgl-dev \
|
||||
liblzma-dev \
|
||||
libmariadb-dev-compat \
|
||||
libprotobuf-dev \
|
||||
libqt5multimedia5-plugins \
|
||||
libqt5sql5-mysql \
|
||||
libqt5svg5-dev \
|
||||
libqt5websockets5-dev \
|
||||
libqt6multimedia6 \
|
||||
libqt6sql6-mysql \
|
||||
libqt6svg6-dev \
|
||||
libqt6websockets6-dev \
|
||||
ninja-build \
|
||||
protobuf-compiler \
|
||||
qt5-image-formats-plugins \
|
||||
qtmultimedia5-dev \
|
||||
qttools5-dev \
|
||||
qttools5-dev-tools \
|
||||
qt6-image-formats-plugins \
|
||||
qt6-l10n-tools \
|
||||
qt6-multimedia-dev \
|
||||
qt6-tools-dev \
|
||||
qt6-tools-dev-tools \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
|
|
|||
|
|
@ -1,29 +0,0 @@
|
|||
FROM ubuntu:26.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 \
|
||||
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/*
|
||||
145
.ci/compile.sh
|
|
@ -10,11 +10,8 @@
|
|||
# --test runs tests
|
||||
# --debug or --release sets the build type ie CMAKE_BUILD_TYPE
|
||||
# --ccache [<size>] uses ccache and shows stats, optionally provide size
|
||||
# --evict-ccache <age> runs ccache eviction based on given age after build
|
||||
# --dir <dir> sets the name of the build dir, default is "build"
|
||||
# --cmake-generator <generator> sets CMAKE_GENERATOR as used by cmake
|
||||
# --target-macos-version <version> sets the min os version - only used for macOS builds
|
||||
# uses env: BUILDTYPE MAKE_INSTALL MAKE_PACKAGE PACKAGE_TYPE PACKAGE_SUFFIX MAKE_SERVER MAKE_NO_CLIENT MAKE_TEST USE_CCACHE CCACHE_SIZE CCACHE_EVICTION_AGE BUILD_DIR CMAKE_GENERATOR TARGET_MACOS_VERSION
|
||||
# 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>)
|
||||
# exitcode: 1 for failure, 3 for invalid arguments
|
||||
|
||||
|
|
@ -49,10 +46,6 @@ while [[ $# != 0 ]]; do
|
|||
MAKE_SERVER=1
|
||||
shift
|
||||
;;
|
||||
'--no-client')
|
||||
MAKE_NO_CLIENT=1
|
||||
shift
|
||||
;;
|
||||
'--test')
|
||||
MAKE_TEST=1
|
||||
shift
|
||||
|
|
@ -73,19 +66,6 @@ while [[ $# != 0 ]]; do
|
|||
shift
|
||||
fi
|
||||
;;
|
||||
'--evict-ccache')
|
||||
shift
|
||||
if [[ $# == 0 ]]; then
|
||||
echo "::error file=$0::--evict-ccache expects an argument"
|
||||
exit 3
|
||||
fi
|
||||
CCACHE_EVICTION_AGE=$1
|
||||
shift
|
||||
;;
|
||||
'--vcpkg')
|
||||
USE_VCPKG=1
|
||||
shift
|
||||
;;
|
||||
'--dir')
|
||||
shift
|
||||
if [[ $# == 0 ]]; then
|
||||
|
|
@ -95,24 +75,6 @@ while [[ $# != 0 ]]; do
|
|||
BUILD_DIR="$1"
|
||||
shift
|
||||
;;
|
||||
'--cmake-generator')
|
||||
shift
|
||||
if [[ $# == 0 ]]; then
|
||||
echo "::error file=$0::--cmake-generator expects an argument"
|
||||
exit 3
|
||||
fi
|
||||
export CMAKE_GENERATOR=$1
|
||||
shift
|
||||
;;
|
||||
'--target-macos-version')
|
||||
shift
|
||||
if [[ $# == 0 ]]; then
|
||||
echo "::error file=$0::--target-macos-version expects an argument"
|
||||
exit 3
|
||||
fi
|
||||
TARGET_MACOS_VERSION="$1"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
echo "::error file=$0::unrecognized option: $1"
|
||||
exit 3
|
||||
|
|
@ -141,9 +103,6 @@ flags=("-DCMAKE_BUILD_TYPE=$BUILDTYPE")
|
|||
if [[ $MAKE_SERVER ]]; then
|
||||
flags+=("-DWITH_SERVER=1")
|
||||
fi
|
||||
if [[ $MAKE_NO_CLIENT ]]; then
|
||||
flags+=("-DWITH_CLIENT=0" "-DWITH_ORACLE=0")
|
||||
fi
|
||||
if [[ $MAKE_TEST ]]; then
|
||||
flags+=("-DTEST=1")
|
||||
fi
|
||||
|
|
@ -157,9 +116,6 @@ fi
|
|||
if [[ $PACKAGE_TYPE ]]; then
|
||||
flags+=("-DCPACK_GENERATOR=$PACKAGE_TYPE")
|
||||
fi
|
||||
if [[ $USE_VCPKG ]]; then
|
||||
flags+=("-DUSE_VCPKG=1")
|
||||
fi
|
||||
|
||||
# Add cmake --build flags
|
||||
buildflags=(--config "$BUILDTYPE")
|
||||
|
|
@ -176,47 +132,9 @@ function ccachestatsverbose() {
|
|||
|
||||
# Compile
|
||||
if [[ $RUNNER_OS == macOS ]]; then
|
||||
# QTDIR is needed for macOS since we actually only use the cached thin Qt binaries instead of the install-qt-action,
|
||||
# which sets a few environment variables
|
||||
if QTDIR=$(find "$GITHUB_WORKSPACE/Qt" -depth -maxdepth 2 -name macos -type d -print -quit); then
|
||||
echo "found QTDIR at $QTDIR"
|
||||
else
|
||||
echo "could not find QTDIR!"
|
||||
exit 2
|
||||
fi
|
||||
# the qtdir is located at Qt/[qtversion]/macos
|
||||
# we use find to get the first subfolder with the name "macos"
|
||||
# this works independent of the qt version as there should be only one version installed on the runner at a time
|
||||
export QTDIR
|
||||
|
||||
if [[ $TARGET_MACOS_VERSION ]]; then
|
||||
# CMAKE_OSX_DEPLOYMENT_TARGET is a vanilla cmake flag needed to compile to target macOS version
|
||||
flags+=("-DCMAKE_OSX_DEPLOYMENT_TARGET=$TARGET_MACOS_VERSION")
|
||||
|
||||
# vcpkg dependencies need a vcpkg triplet file to compile to the target macOS version
|
||||
# an easy way is to copy the x64-osx.cmake file and modify it
|
||||
triplets_dir="/tmp/cmake/triplets"
|
||||
triplet_version="custom-triplet"
|
||||
triplet_file="$triplets_dir/$triplet_version.cmake"
|
||||
arch=$(uname -m)
|
||||
if [[ $arch == x86_64 ]]; then
|
||||
arch="x64"
|
||||
fi
|
||||
mkdir -p "$triplets_dir"
|
||||
cp "../vcpkg/triplets/$arch-osx.cmake" "$triplet_file"
|
||||
echo "set(VCPKG_CMAKE_SYSTEM_VERSION $TARGET_MACOS_VERSION)" >>"$triplet_file"
|
||||
echo "set(VCPKG_OSX_DEPLOYMENT_TARGET $TARGET_MACOS_VERSION)" >>"$triplet_file"
|
||||
flags+=("-DVCPKG_OVERLAY_TRIPLETS=$triplets_dir")
|
||||
flags+=("-DVCPKG_HOST_TRIPLET=$triplet_version")
|
||||
flags+=("-DVCPKG_TARGET_TRIPLET=$triplet_version")
|
||||
echo "::group::Generated triplet $triplet_file"
|
||||
cat "$triplet_file"
|
||||
echo "::endgroup::"
|
||||
fi
|
||||
|
||||
echo "::group::Signing Certificate"
|
||||
if [[ -n "$MACOS_CERTIFICATE_NAME" ]]; then
|
||||
echo "$MACOS_CERTIFICATE" | base64 --decode >"certificate.p12"
|
||||
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
|
||||
|
|
@ -228,29 +146,6 @@ if [[ $RUNNER_OS == macOS ]]; then
|
|||
echo "No signing certificate configured. Skipping set up of keychain in macOS environment."
|
||||
fi
|
||||
echo "::endgroup::"
|
||||
|
||||
if [[ $MAKE_PACKAGE ]]; then
|
||||
# Workaround https://github.com/actions/runner-images/issues/7522
|
||||
# have hdiutil repeat the command 10 times in hope of success
|
||||
hdiutil_script="/tmp/hdiutil.sh"
|
||||
# shellcheck disable=SC2016
|
||||
echo '#!/bin/bash
|
||||
i=0
|
||||
while ! hdiutil "$@"; do
|
||||
if (( ++i >= 10 )); then
|
||||
echo "Error: hdiutil failed $i times!" >&2
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done' >"$hdiutil_script"
|
||||
chmod +x "$hdiutil_script"
|
||||
flags+=(-DCPACK_COMMAND_HDIUTIL="$hdiutil_script")
|
||||
fi
|
||||
|
||||
elif [[ $RUNNER_OS == Windows ]]; then
|
||||
# Enable MTT, see https://devblogs.microsoft.com/cppblog/improved-parallelism-in-msbuild/
|
||||
# and https://devblogs.microsoft.com/cppblog/cpp-build-throughput-investigation-and-tune-up/#multitooltask-mtt
|
||||
buildflags+=(-- -p:UseMultiToolTask=true -p:EnableClServerMode=true)
|
||||
fi
|
||||
|
||||
if [[ $USE_CCACHE ]]; then
|
||||
|
|
@ -261,39 +156,23 @@ fi
|
|||
|
||||
echo "::group::Configure cmake"
|
||||
cmake --version
|
||||
echo "Running cmake with flags: ${flags[*]}"
|
||||
cmake .. "${flags[@]}"
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Build project"
|
||||
echo "Running cmake --build with flags: ${buildflags[*]}"
|
||||
cmake --build . "${buildflags[@]}"
|
||||
if [[ $RUNNER_OS == Windows ]]; then
|
||||
# Enable MTT, see https://devblogs.microsoft.com/cppblog/improved-parallelism-in-msbuild/
|
||||
# and https://devblogs.microsoft.com/cppblog/cpp-build-throughput-investigation-and-tune-up/#multitooltask-mtt
|
||||
cmake --build . "${buildflags[@]}" -- -p:UseMultiToolTask=true -p:EnableClServerMode=true
|
||||
else
|
||||
cmake --build . "${buildflags[@]}"
|
||||
fi
|
||||
echo "::endgroup::"
|
||||
|
||||
if [[ $USE_CCACHE ]]; then
|
||||
if [[ $CCACHE_EVICTION_AGE ]]; then
|
||||
echo "::group::evict ccache files older than $CCACHE_EVICTION_AGE"
|
||||
ccache --evict-older-than "$CCACHE_EVICTION_AGE"
|
||||
echo "::endgroup::"
|
||||
fi
|
||||
echo "::group::Show ccache stats again"
|
||||
ccachestatsverbose
|
||||
echo "::endgroup::"
|
||||
elif [[ $CCACHE_EVICTION_AGE ]]; then
|
||||
echo "::error file=$0::ccache eviction is enabled while ccache is disabled!"
|
||||
fi
|
||||
|
||||
if [[ $RUNNER_OS == macOS ]]; then
|
||||
echo "::group::Inspect Mach-O binaries"
|
||||
for app in cockatrice oracle servatrice; do
|
||||
binary="$GITHUB_WORKSPACE/build/$app/$app.app/Contents/MacOS/$app"
|
||||
echo "Inspecting $app..."
|
||||
vtool -show-build "$binary"
|
||||
file "$binary"
|
||||
lipo -info "$binary"
|
||||
echo ""
|
||||
done
|
||||
echo "::endgroup::"
|
||||
fi
|
||||
|
||||
if [[ $MAKE_TEST ]]; then
|
||||
|
|
@ -310,6 +189,12 @@ fi
|
|||
|
||||
if [[ $MAKE_PACKAGE ]]; then
|
||||
echo "::group::Create package"
|
||||
|
||||
if [[ $RUNNER_OS == macOS ]]; then
|
||||
# Workaround https://github.com/actions/runner-images/issues/7522
|
||||
echo "killing XProtectBehaviorService"; sudo pkill -9 XProtect >/dev/null || true;
|
||||
echo "waiting for XProtectBehaviorService kill"; while pgrep "XProtect"; do sleep 3; done;
|
||||
fi
|
||||
cmake --build . --target package --config "$BUILDTYPE"
|
||||
echo "::endgroup::"
|
||||
|
||||
|
|
|
|||
|
|
@ -3,28 +3,17 @@
|
|||
# This script is to be used by the ci environment from the project root directory, do not use it from somewhere else.
|
||||
|
||||
# Creates or loads docker images to use in compilation, creates RUN function to start compilation on the docker image.
|
||||
#
|
||||
# usage: source <script> <name> [--get] [--build] [--save] [--interactive] [--set-cache <location>]
|
||||
# <name> sets the name of the docker image, these correspond to directories in .ci
|
||||
# <arg> sets the name of the docker image, these correspond to directories in .ci
|
||||
# --get loads the image from a previously saved image cache, will build if no image is found
|
||||
# --build builds the image from the Dockerfile in .ci/$NAME
|
||||
# --save stores the image, if an image was loaded it will not be stored
|
||||
# --interactive immediately starts the image interactively for debugging
|
||||
# --set-cache <location> sets the location to cache the image or for ccache
|
||||
#
|
||||
# requires: docker
|
||||
# uses env: NAME CACHE BUILD GET SAVE INTERACTIVE
|
||||
# (correspond to args: <name> --set-cache <cache> --build --get --save --interactive)
|
||||
# sets env: RUN CCACHE_DIR IMAGE_NAME RUN_ARGS RUN_OPTS BUILD_SCRIPT
|
||||
# exitcode: 1 for failure, 2 for missing dockerfile, 3 for invalid arguments
|
||||
#
|
||||
# exported RUN function will run the BUILD_SCRIPT inside of the docker container.
|
||||
# note that the docker container will not inherit any environment variables!
|
||||
#
|
||||
# usage: RUN [arguments for build script]
|
||||
# roughly equivalent to `docker run $IMAGE_NAME bash $BUILD_SCRIPT $@`
|
||||
# uses env: CCACHE_DIR IMAGE_NAME RUN_ARGS RUN_OPTS BUILD_SCRIPT
|
||||
# exitcode: 3 for invalid arguments, returns the returncode of docker run
|
||||
export BUILD_SCRIPT=".ci/compile.sh"
|
||||
|
||||
project_name="cockatrice"
|
||||
|
|
@ -52,17 +41,12 @@ while [[ $# != 0 ]]; do
|
|||
shift
|
||||
;;
|
||||
'--set-cache')
|
||||
shift
|
||||
if [[ $# == 0 ]]; then
|
||||
echo "--set-cache expects an argument" >&2
|
||||
exit 3
|
||||
fi
|
||||
CACHE=$1
|
||||
shift
|
||||
CACHE=$2
|
||||
if ! [[ -d $CACHE ]]; then
|
||||
echo "could not find cache path: $CACHE" >&2
|
||||
return 3
|
||||
fi
|
||||
shift 2
|
||||
;;
|
||||
*)
|
||||
if [[ ${1:0:1} == - ]]; then
|
||||
|
|
@ -153,11 +137,10 @@ if [[ $SAVE ]]; then
|
|||
fi
|
||||
|
||||
# Set compile function, runs the compile script on the image, passes arguments to the script
|
||||
# shellcheck disable=2120
|
||||
function RUN ()
|
||||
{
|
||||
echo "running image:"
|
||||
if [[ $(docker images) =~ $IMAGE_NAME ]]; then
|
||||
if [[ $(docker images) =~ "$IMAGE_NAME" ]]; then
|
||||
local args=(--mount "type=bind,source=$PWD,target=/src")
|
||||
args+=(--workdir "/src")
|
||||
args+=(--user "$(id -u):$(id -g)")
|
||||
|
|
@ -165,11 +148,9 @@ function RUN ()
|
|||
args+=(--mount "type=bind,source=$CCACHE_DIR,target=/.ccache")
|
||||
args+=(--env "CCACHE_DIR=/.ccache")
|
||||
fi
|
||||
if [[ $GITHUB_OUTPUT ]]; then
|
||||
args+=(--mount "type=bind,source=$GITHUB_OUTPUT,target=/gh_output")
|
||||
args+=(--env "GITHUB_OUTPUT=/gh_output")
|
||||
if [[ -n "$CMAKE_GENERATOR" ]]; then
|
||||
args+=(--env "CMAKE_GENERATOR=$CMAKE_GENERATOR")
|
||||
fi
|
||||
# shellcheck disable=2086
|
||||
docker run "${args[@]}" $RUN_ARGS "$IMAGE_NAME" bash "$BUILD_SCRIPT" $RUN_OPTS "$@"
|
||||
return $?
|
||||
else
|
||||
|
|
@ -183,6 +164,5 @@ function RUN ()
|
|||
if [[ $INTERACTIVE ]]; then
|
||||
export BUILD_SCRIPT="-i"
|
||||
export RUN_ARGS="$RUN_ARGS -it"
|
||||
# shellcheck disable=2119
|
||||
RUN
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -11,19 +11,11 @@ if ! git merge-base origin/master HEAD; then
|
|||
fi
|
||||
|
||||
# Check formatting using format.sh
|
||||
echo "Checking your code using format.sh..."
|
||||
echo "Checking your code using clang-format/cmake-format..."
|
||||
|
||||
diff="$(./format.sh --diff --cmake --shell --print-version --branch origin/master)"
|
||||
diff="$(./format.sh --diff --cmake --cf-version --branch origin/master)"
|
||||
err=$?
|
||||
|
||||
sep="
|
||||
----------
|
||||
"
|
||||
used_version="${diff%%"$sep"*}"
|
||||
diff="${diff#*"$sep"}"
|
||||
changes_to_make="${diff%%"$sep"*}"
|
||||
files_to_edit="${diff#*"$sep"}"
|
||||
|
||||
case $err in
|
||||
1)
|
||||
cat <<EOM
|
||||
|
|
@ -41,13 +33,14 @@ case $err in
|
|||
***********************************************************
|
||||
|
||||
Used version:
|
||||
$used_version
|
||||
|
||||
Affected files:
|
||||
$files_to_edit
|
||||
${diff%%
|
||||
----------
|
||||
*}
|
||||
|
||||
The following changes should be made:
|
||||
$changes_to_make
|
||||
${diff#*
|
||||
----------
|
||||
}
|
||||
|
||||
Exiting...
|
||||
EOM
|
||||
|
|
@ -65,9 +58,6 @@ EOM
|
|||
*** ***
|
||||
***********************************************************
|
||||
|
||||
Used version:
|
||||
$used_version
|
||||
|
||||
Exiting...
|
||||
EOM
|
||||
exit 0
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
# used by the ci to rename build artifacts
|
||||
# renames the file to [original name][SUFFIX].[original extension]
|
||||
# where SUFFIX is either available in the environment or as the first arg
|
||||
# if MAKE_ZIP is set instead a zip is made
|
||||
# expected to be run in the build directory unless BUILD_DIR is set
|
||||
# adds output to GITHUB_OUTPUT
|
||||
builddir="${BUILD_DIR:=.}"
|
||||
|
|
@ -21,8 +22,8 @@ set -e
|
|||
|
||||
# find file
|
||||
found="$(find "$builddir" -maxdepth 1 -type f -name "$findrx" -print -quit)"
|
||||
path="${found%/*}" # remove all including first "/" from right side
|
||||
file="${found##*/}" # remove all including last "/" from left side
|
||||
path="${found%/*}" # remove all after last /
|
||||
file="${found##*/}" # remove all before last /
|
||||
if [[ ! $file ]]; then
|
||||
echo "::error file=$0::could not find package"
|
||||
exit 1
|
||||
|
|
@ -34,16 +35,21 @@ if ! cd "$path"; then
|
|||
fi
|
||||
|
||||
# set filename
|
||||
name="${file%.*}" # remove all including first "." from right side
|
||||
new_name="$name$SUFFIX"
|
||||
extension="${file##*.}" # remove all including last "." from left side
|
||||
filename="$new_name.$extension"
|
||||
echo "renaming '$file' to '$filename'"
|
||||
mv "$file" "$filename"
|
||||
name="${file%.*}" # remove all after last .
|
||||
new_name="$name$SUFFIX."
|
||||
if [[ $MAKE_ZIP ]]; then
|
||||
filename="${new_name}zip"
|
||||
echo "creating zip '$filename' from '$file'"
|
||||
zip "$filename" "$file"
|
||||
else
|
||||
extension="${file##*.}" # remove all before last .
|
||||
filename="$new_name$extension"
|
||||
echo "renaming '$file' to '$filename'"
|
||||
mv "$file" "$filename"
|
||||
fi
|
||||
|
||||
cd "$oldpwd"
|
||||
relative_path="$path/$filename"
|
||||
ls -l "$relative_path"
|
||||
echo "path=$relative_path" >>"$GITHUB_OUTPUT"
|
||||
echo "name=$new_name" >>"$GITHUB_OUTPUT"
|
||||
echo "fullname=$filename" >>"$GITHUB_OUTPUT"
|
||||
echo "name=$filename" >>"$GITHUB_OUTPUT"
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ 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>
|
||||
|
|
@ -17,19 +18,16 @@ Available pre-compiled binaries for installation:
|
|||
• <kbd>macOS 13+</kbd> <sub><i>Ventura</i></sub> <sub>Intel</sub>
|
||||
|
||||
<b>Linux</b>
|
||||
• <kbd>Ubuntu 26.04 LTS</kbd> <sub><i>Resolute Racoon</i></sub>
|
||||
• <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 43</kbd>
|
||||
• <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>
|
||||
|
||||
<sub>We provide a <kbd>Docker</kbd> image for "Servatrice" in <a href="https://github.com/Cockatrice/Cockatrice/pkgs/container/servatrice">GHCR</a>. You can docker pull it or use our Docker Compose files!</sub>
|
||||
</pre>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,49 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# This script is used to resolve the latest patch version of Qt using aqtinstall.
|
||||
# It interprets wildcards to get the latest patch version. E.g. "6.6.*" -> "6.6.3".
|
||||
|
||||
# This script is meant to be used by the ci enironment.
|
||||
# It uses the runner's GITHUB_OUTPUT env variable.
|
||||
|
||||
# Usage example: .ci/resolve_latest_aqt_qt_version.sh "6.6.*"
|
||||
|
||||
qt_spec=$1
|
||||
if [[ ! $qt_spec ]]; then
|
||||
echo "usage: $0 [version]"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# If version is already specific (no wildcard), use it as-is
|
||||
if [[ $qt_spec != *"*" ]]; then
|
||||
echo "version $qt_spec is already resolved"
|
||||
echo "version=$qt_spec" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if ! hash aqt; then
|
||||
echo "aqt could not be found, has aqtinstall been installed?"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Resolve latest patch
|
||||
if [[ $RUNNER_OS == macOS ]]; then
|
||||
if ! qt_resolved=$(aqt list-qt mac desktop --spec "$qt_spec" --latest-version); then
|
||||
exit 1
|
||||
fi
|
||||
elif [[ $RUNNER_OS == Windows ]]; then
|
||||
if ! qt_resolved=$(aqt list-qt windows desktop --spec "$qt_spec" --latest-version); then
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "aqt command for $RUNNER_OS not defined."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "resolved $qt_spec to $qt_resolved"
|
||||
if [[ ! $qt_resolved ]]; then
|
||||
echo "Error: Could not resolve Qt version for $qt_spec"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "version=$qt_resolved" >> "$GITHUB_OUTPUT"
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# The macos binaries from aqt are fat (universal), so we thin them to the target architecture to reduce the size of
|
||||
# the packages and caches using lipo.
|
||||
|
||||
# This script is meant to be used by the ci enironment on macos runners only.
|
||||
# It uses the runner's GITHUB_WORKSPACE env variable.
|
||||
arch=$(uname -m)
|
||||
nproc=$(sysctl -n hw.ncpu)
|
||||
|
||||
function thin() {
|
||||
local libfile=$1
|
||||
if [[ $(file -b --mime-type "$libfile") == application/x-mach-binary* ]]; then
|
||||
echo "Processing $libfile"
|
||||
lipo "$libfile" -thin "$arch" -output "$libfile"
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
export -f thin # export to allow use in xargs
|
||||
export arch
|
||||
set -eo pipefail
|
||||
|
||||
echo "::group::Thinning Qt libraries to $arch using $nproc cores"
|
||||
find "$GITHUB_WORKSPACE/Qt" -type f -print0 | xargs -0 -n1 -P"$nproc" -I{} bash -c "thin '{}'"
|
||||
echo "::endgroup::"
|
||||
|
|
@ -25,9 +25,6 @@ IndentCaseLabels: true
|
|||
PointerAlignment: Right
|
||||
SortIncludes: true
|
||||
IncludeBlocks: Regroup
|
||||
StatementAttributeLikeMacros: [emit]
|
||||
# requires clang-format 16
|
||||
# RemoveSemicolon: true
|
||||
---
|
||||
Language: Proto
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
|
|
|
|||
8
.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)
|
||||
|
|
@ -461,11 +459,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.
|
||||
|
||||
> [!NOTE]
|
||||
> If you want to push a new release to replace it immediately with the same
|
||||
> name you have to delete the automatically created release first!
|
||||
You can also do this on GitHub, you'll also want to delete the false release.
|
||||
|
||||
In the first lines of [CMakeLists.txt](
|
||||
https://github.com/Cockatrice/Cockatrice/blob/master/CMakeLists.txt)
|
||||
|
|
|
|||
5
.github/ISSUE_TEMPLATE/config.yml
vendored
|
|
@ -1,12 +1,9 @@
|
|||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: 💬 Discord Community (Get help with server issues, e.g. Login)
|
||||
url: https://discord.com/invite/3Z9yzmA
|
||||
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/
|
||||
# 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!
|
||||
- name: 📖 Code Documentation
|
||||
url: https://cockatrice.github.io/docs/
|
||||
about: Helpful source focusing on developers, but there are also references for users!
|
||||
|
|
|
|||
24
.github/dependabot.yml
vendored
|
|
@ -2,21 +2,19 @@
|
|||
|
||||
version: 2
|
||||
updates:
|
||||
# Enable version updates for git submodules
|
||||
# If SemVer is used, updates will happen to new releases only (not HEAD)
|
||||
# # Enable version updates for git submodules
|
||||
# Not yet possible to bump only on tags or releases, see:
|
||||
# https://github.com/dependabot/dependabot-core/issues/1639
|
||||
# https://github.com/dependabot/dependabot-core/issues/2192
|
||||
- package-ecosystem: "gitsubmodule"
|
||||
# Look for `.gitmodules` in the `root` directory
|
||||
directory: "/"
|
||||
ignore:
|
||||
# Ignore updates for vcpkg (Bump to latest tag not working (no SemVer used) & macOS Intel triplet broken with newer releases)
|
||||
- dependency-name: "vcpkg"
|
||||
# Check for updates once a month
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
# Limit the amout of open PR's (default = 5, disabled = 0, security updates are not impacted)
|
||||
open-pull-requests-limit: 2
|
||||
# Alternative: Action that updates submodule and can be manually run on demand (workflow_dispatch)
|
||||
# - package-ecosystem: "gitsubmodule"
|
||||
# # Look for `.gitmodules` in the `root` directory
|
||||
# directory: "/"
|
||||
# # Check for updates once a month
|
||||
# schedule:
|
||||
# interval: "monthly"
|
||||
# # Limit the amout of open PR's (default = 5, disabled = 0, security updates are not impacted)
|
||||
# open-pull-requests-limit: 1
|
||||
|
||||
# # Enable version updates for Docker
|
||||
# Not yet possible to bump from one LTS version to the next and skip others, see:
|
||||
|
|
|
|||
474
.github/workflows/desktop-build.yml
vendored
|
|
@ -4,49 +4,35 @@ permissions:
|
|||
contents: write
|
||||
id-token: write
|
||||
attestations: write
|
||||
actions: write # needed for ccache action to be able to delete gha caches
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- '*/**' # matches all files not in root
|
||||
- '!**.md'
|
||||
- '!.github/**'
|
||||
- '!.husky/**'
|
||||
- '!.tx/**'
|
||||
- '!doc/**'
|
||||
- '!webclient/**'
|
||||
- '.github/workflows/desktop-build.yml'
|
||||
- 'CMakeLists.txt'
|
||||
- 'vcpkg.json'
|
||||
- 'vcpkg'
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
- 'webclient/**'
|
||||
- '.github/workflows/web-*.yml'
|
||||
- '.github/workflows/translations-*.yml'
|
||||
- '.github/workflows/docker-release.yml'
|
||||
tags:
|
||||
- '*'
|
||||
pull_request:
|
||||
paths:
|
||||
- '*/**' # matches all files not in root
|
||||
- '!**.md'
|
||||
- '!.github/**'
|
||||
- '!.husky/**'
|
||||
- '!.tx/**'
|
||||
- '!doc/**'
|
||||
- '!webclient/**'
|
||||
- '.github/workflows/desktop-build.yml'
|
||||
- 'CMakeLists.txt'
|
||||
- 'vcpkg.json'
|
||||
- 'vcpkg'
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
- 'webclient/**'
|
||||
- '.github/workflows/web-*.yml'
|
||||
- '.github/workflows/translations-*.yml'
|
||||
|
||||
# Cancel earlier, unfinished runs of this workflow on the same branch (unless on release)
|
||||
# Cancel earlier, unfinished runs of this workflow on the same branch (unless on master)
|
||||
concurrency:
|
||||
group: "${{ github.workflow }} @ ${{ github.ref_name }}"
|
||||
cancel-in-progress: ${{ github.ref_type != 'tag' }}
|
||||
cancel-in-progress: ${{ github.ref_name != 'master' }}
|
||||
|
||||
jobs:
|
||||
configure:
|
||||
name: Configure
|
||||
runs-on: ubuntu-slim
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
tag: ${{steps.configure.outputs.tag}}
|
||||
sha: ${{steps.configure.outputs.sha}}
|
||||
|
|
@ -70,7 +56,7 @@ jobs:
|
|||
|
||||
- name: Checkout
|
||||
if: steps.configure.outputs.tag != null
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
|
@ -114,12 +100,7 @@ jobs:
|
|||
- distro: Debian
|
||||
version: 11
|
||||
package: DEB
|
||||
|
||||
- distro: Servatrice_Debian
|
||||
version: 11
|
||||
package: DEB
|
||||
test: skip
|
||||
server_only: yes
|
||||
test: skip # Running tests on all distros is superfluous
|
||||
|
||||
- distro: Debian
|
||||
version: 12
|
||||
|
|
@ -131,12 +112,12 @@ jobs:
|
|||
package: DEB
|
||||
|
||||
- distro: Fedora
|
||||
version: 42
|
||||
version: 41
|
||||
package: RPM
|
||||
test: skip # Running tests on all distros is superfluous
|
||||
|
||||
- distro: Fedora
|
||||
version: 43
|
||||
version: 42
|
||||
package: RPM
|
||||
|
||||
- distro: Ubuntu
|
||||
|
|
@ -148,31 +129,25 @@ jobs:
|
|||
version: 24.04
|
||||
package: DEB
|
||||
|
||||
- distro: Ubuntu
|
||||
version: 26.04
|
||||
package: DEB
|
||||
|
||||
name: ${{matrix.distro}} ${{matrix.version}}
|
||||
needs: configure
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: ${{matrix.allow-failure == 'yes'}}
|
||||
timeout-minutes: 70
|
||||
env:
|
||||
NAME: ${{matrix.distro}}${{matrix.version}}
|
||||
CACHE: ${{github.workspace}}/.cache/${{matrix.distro}}${{matrix.version}} # directory for caching docker image and ccache
|
||||
# Cache size over the entire repo is 10Gi:
|
||||
# https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#usage-limits-and-eviction-policy
|
||||
CCACHE_SIZE: 550M
|
||||
CCACHE_EVICTION_AGE: 7d
|
||||
CCACHE_SIZE: 500M
|
||||
CMAKE_GENERATOR: 'Ninja'
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Restore compiler cache (ccache)
|
||||
id: ccache_restore
|
||||
uses: actions/cache/restore@v5
|
||||
uses: actions/cache/restore@v4
|
||||
env:
|
||||
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
|
||||
with:
|
||||
|
|
@ -187,47 +162,30 @@ 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" \
|
||||
--cmake-generator "$CMAKE_GENERATOR"
|
||||
RUN --server --debug --test --ccache "$CCACHE_SIZE"
|
||||
|
||||
- name: Build release package
|
||||
id: build
|
||||
if: matrix.package != 'skip'
|
||||
shell: bash
|
||||
env:
|
||||
BUILD_DIR: build
|
||||
SUFFIX: '-${{matrix.distro}}${{matrix.version}}'
|
||||
package: '${{matrix.package}}'
|
||||
server_only: '${{matrix.server_only}}'
|
||||
CMAKE_GENERATOR: '${{env.CMAKE_GENERATOR}}'
|
||||
run: |
|
||||
source .ci/docker.sh
|
||||
args=()
|
||||
if [[ $server_only == yes ]]; then
|
||||
args+=(--no-client)
|
||||
fi
|
||||
if [[ $GITHUB_REF == "refs/heads/master" ]]; then
|
||||
args+=(--evict-ccache "$CCACHE_EVICTION_AGE")
|
||||
fi
|
||||
args+=(--ccache "$CCACHE_SIZE")
|
||||
args+=(--cmake-generator "$CMAKE_GENERATOR")
|
||||
args+=(--suffix "$SUFFIX")
|
||||
RUN --server --release --package "$package" "${args[@]}"
|
||||
RUN --server --release --package "$package" --dir "$BUILD_DIR" \
|
||||
--ccache "$CCACHE_SIZE"
|
||||
.ci/name_build.sh
|
||||
|
||||
# Delete used cache to emulate a ccache update. See https://github.com/actions/cache/issues/342
|
||||
- name: Delete remote compiler cache (ccache)
|
||||
if: github.ref == 'refs/heads/master' && steps.ccache_restore.outputs.cache-hit
|
||||
continue-on-error: true
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
if gh cache delete --repo ${{ github.repository }} ${{ steps.ccache_restore.outputs.cache-primary-key }}; then
|
||||
echo "Cache deleted successfully"
|
||||
fi
|
||||
|
||||
- name: Save updated compiler cache (ccache)
|
||||
- name: Save compiler cache (ccache)
|
||||
if: github.ref == 'refs/heads/master'
|
||||
uses: actions/cache/save@v5
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ${{env.CACHE}}
|
||||
key: ${{ steps.ccache_restore.outputs.cache-primary-key }}
|
||||
|
|
@ -235,10 +193,10 @@ jobs:
|
|||
- name: Upload artifact
|
||||
id: upload_artifact
|
||||
if: matrix.package != 'skip'
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{matrix.distro}}${{matrix.version}}-package
|
||||
path: ${{steps.build.outputs.path}}
|
||||
archive: false
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload to release
|
||||
|
|
@ -248,194 +206,97 @@ jobs:
|
|||
env:
|
||||
GH_TOKEN: ${{github.token}}
|
||||
tag_name: ${{needs.configure.outputs.tag}}
|
||||
asset_name: ${{steps.build.outputs.fullname}}
|
||||
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@v4
|
||||
uses: actions/attest-build-provenance@v3
|
||||
with:
|
||||
subject-path: ${{steps.build.outputs.path}}
|
||||
show-summary: false
|
||||
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}} --repo Cockatrice/Cockatrice
|
||||
run: gh attestation verify ${{steps.build.outputs.path}} -R Cockatrice/Cockatrice
|
||||
|
||||
build-vcpkg:
|
||||
build-macos:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: macOS
|
||||
target: 13
|
||||
runner: macos-15-intel
|
||||
- target: 13
|
||||
soc: Intel
|
||||
xcode: "16.4"
|
||||
os: macos-13
|
||||
xcode: "14.3.1"
|
||||
type: Release
|
||||
override_target: 13
|
||||
make_package: 1
|
||||
package_suffix: "-macOS13_Intel"
|
||||
qt_version: 6.11.*
|
||||
qt_arch: clang_64
|
||||
qt_modules: qtimageformats qtmultimedia qtwebsockets
|
||||
cmake_generator: Ninja
|
||||
use_ccache: 1
|
||||
ccache_eviction_age: 7d
|
||||
|
||||
- os: macOS
|
||||
target: 14
|
||||
runner: macos-14
|
||||
- target: 14
|
||||
soc: Apple
|
||||
os: macos-14
|
||||
xcode: "15.4"
|
||||
type: Release
|
||||
make_package: 1
|
||||
package_suffix: "-macOS14"
|
||||
qt_version: 6.11.*
|
||||
qt_arch: clang_64
|
||||
qt_modules: qtimageformats qtmultimedia qtwebsockets
|
||||
cmake_generator: Ninja
|
||||
use_ccache: 1
|
||||
ccache_eviction_age: 7d
|
||||
|
||||
- os: macOS
|
||||
target: 15
|
||||
runner: macos-15
|
||||
- target: 15
|
||||
soc: Apple
|
||||
xcode: "16.4"
|
||||
os: macos-15
|
||||
xcode: "16.2"
|
||||
type: Release
|
||||
make_package: 1
|
||||
package_suffix: "-macOS15"
|
||||
qt_version: 6.11.*
|
||||
qt_arch: clang_64
|
||||
qt_modules: qtimageformats qtmultimedia qtwebsockets
|
||||
cmake_generator: Ninja
|
||||
use_ccache: 1
|
||||
ccache_eviction_age: 7d
|
||||
|
||||
- os: macOS
|
||||
target: 15
|
||||
runner: macos-15
|
||||
- target: 15
|
||||
soc: Apple
|
||||
xcode: "16.4"
|
||||
os: macos-15
|
||||
xcode: "16.2"
|
||||
type: Debug
|
||||
qt_version: 6.11.*
|
||||
qt_arch: clang_64
|
||||
qt_modules: qtimageformats qtmultimedia qtwebsockets
|
||||
cmake_generator: Ninja
|
||||
use_ccache: 1
|
||||
ccache_eviction_age: 7d
|
||||
|
||||
- os: Windows
|
||||
target: 10
|
||||
runner: windows-2025
|
||||
type: Release
|
||||
make_package: 1
|
||||
package_suffix: "-Win10"
|
||||
qt_version: 6.11.*
|
||||
qt_arch: win64_msvc2022_64
|
||||
qt_modules: qtimageformats qtmultimedia qtwebsockets
|
||||
cmake_generator: "Visual Studio 17 2022"
|
||||
cmake_generator_platform: x64
|
||||
|
||||
name: ${{matrix.os}} ${{matrix.target}}${{ matrix.soc == 'Intel' && ' Intel' || '' }}${{ matrix.type == 'Debug' && ' Debug' || '' }}
|
||||
name: macOS ${{matrix.target}}${{ matrix.soc == 'Intel' && ' Intel' || '' }}${{ matrix.type == 'Debug' && ' Debug' || '' }}
|
||||
needs: configure
|
||||
runs-on: ${{matrix.runner}}
|
||||
timeout-minutes: 100
|
||||
runs-on: ${{matrix.os}}
|
||||
continue-on-error: ${{matrix.allow-failure == 'yes'}}
|
||||
env:
|
||||
CCACHE_DIR: ${{github.workspace}}/.cache/
|
||||
# Cache size over the entire repo is 10Gi:
|
||||
# https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#usage-limits-and-eviction-policy
|
||||
CCACHE_SIZE: 550M
|
||||
# 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@v6
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Add msbuild to PATH
|
||||
if: matrix.os == 'Windows'
|
||||
id: add-msbuild
|
||||
uses: microsoft/setup-msbuild@v3
|
||||
with:
|
||||
msbuild-architecture: x64
|
||||
|
||||
# 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
|
||||
if: matrix.use_ccache == 1 && matrix.os == 'macOS'
|
||||
run: brew install ccache
|
||||
|
||||
- name: Restore compiler cache (ccache)
|
||||
if: matrix.use_ccache == 1
|
||||
id: ccache_restore
|
||||
uses: actions/cache/restore@v5
|
||||
env:
|
||||
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
|
||||
uses: jianmingyong/ccache-action@v1
|
||||
with:
|
||||
path: ${{env.CCACHE_DIR}}
|
||||
key: ccache-${{matrix.runner}}-${{matrix.soc}}-${{matrix.type}}-${{env.BRANCH_NAME}}
|
||||
restore-keys: ccache-${{matrix.runner}}-${{matrix.soc}}-${{matrix.type}}-
|
||||
|
||||
- name: Install aqtinstall
|
||||
run: pipx install aqtinstall
|
||||
|
||||
# Resolve given wildcard versions (e.g. Qt 6.6.*) to latest version via aqtinstall to avoid stale caches on new releases
|
||||
- name: Resolve latest Qt patch version
|
||||
id: resolve_qt_version
|
||||
shell: bash
|
||||
run: .ci/resolve_latest_aqt_qt_version.sh "${{matrix.qt_version}}"
|
||||
|
||||
- name: Restore thin Qt ${{ steps.resolve_qt_version.outputs.version }} libraries (${{ matrix.soc }} macOS)
|
||||
if: matrix.os == 'macOS'
|
||||
id: restore_qt
|
||||
uses: actions/cache/restore@v5
|
||||
with:
|
||||
path: ${{ github.workspace }}/Qt
|
||||
key: thin-qt-macos-${{ matrix.soc }}-${{ steps.resolve_qt_version.outputs.version }}
|
||||
install-type: "binary"
|
||||
ccache-key-prefix: ccache-${{matrix.os}}-${{matrix.soc}}-${{matrix.type}}
|
||||
gh-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# 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 fat Qt ${{ steps.resolve_qt_version.outputs.version }} (${{ matrix.soc }} macOS)
|
||||
if: matrix.os == 'macOS' && steps.restore_qt.outputs.cache-hit != 'true'
|
||||
- name: Install Qt ${{env.QT_VERSION}}
|
||||
uses: jurplel/install-qt-action@v4
|
||||
with:
|
||||
version: ${{ steps.resolve_qt_version.outputs.version }}
|
||||
arch: ${{matrix.qt_arch}}
|
||||
modules: ${{matrix.qt_modules}}
|
||||
cache: false
|
||||
dir: ${{github.workspace}}
|
||||
|
||||
- name: Thin Qt libraries (${{ matrix.soc }} macOS)
|
||||
if: matrix.os == 'macOS' && steps.restore_qt.outputs.cache-hit != 'true'
|
||||
run: .ci/thin_macos_qtlib.sh
|
||||
|
||||
- name: Cache thin Qt libraries (${{ matrix.soc }} macOS)
|
||||
if: matrix.os == 'macOS' && steps.restore_qt.outputs.cache-hit != 'true'
|
||||
uses: actions/cache/save@v5
|
||||
with:
|
||||
path: ${{ github.workspace }}/Qt
|
||||
key: thin-qt-macos-${{ matrix.soc }}-${{ steps.resolve_qt_version.outputs.version }}
|
||||
|
||||
- name: Install Qt ${{matrix.qt_version}} (Windows)
|
||||
if: matrix.os == 'Windows'
|
||||
uses: jurplel/install-qt-action@v4
|
||||
with:
|
||||
# qt 6.11.0 only works with aqtinstall directly from git until aqtinstall 3.4 is released
|
||||
aqtsource: git+https://github.com/miurahr/aqtinstall.git
|
||||
version: ${{ steps.resolve_qt_version.outputs.version }}
|
||||
arch: ${{matrix.qt_arch}}
|
||||
modules: ${{matrix.qt_modules}}
|
||||
cache: true
|
||||
|
||||
- name: Install NSIS
|
||||
if: matrix.os == 'Windows'
|
||||
shell: bash
|
||||
run: choco install nsis
|
||||
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
|
||||
|
|
@ -443,50 +304,24 @@ jobs:
|
|||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# uses environment variables, see compile.sh for more details
|
||||
- name: Build Cockatrice
|
||||
id: build
|
||||
- name: Build on Xcode ${{matrix.xcode}}
|
||||
shell: bash
|
||||
id: build
|
||||
env:
|
||||
BUILDTYPE: '${{matrix.type}}'
|
||||
MAKE_PACKAGE: '${{matrix.make_package}}'
|
||||
PACKAGE_SUFFIX: '${{matrix.package_suffix}}'
|
||||
CMAKE_GENERATOR: ${{matrix.cmake_generator}}
|
||||
CMAKE_GENERATOR_PLATFORM: ${{matrix.cmake_generator_platform}}
|
||||
USE_CCACHE: ${{matrix.use_ccache}}
|
||||
VCPKG_DISABLE_METRICS: 1
|
||||
VCPKG_BINARY_SOURCES: 'clear;files,${{ steps.vcpkg-cache.outputs.path }},readwrite'
|
||||
# macOS-specific environment variables, will be ignored on Windows
|
||||
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 }}
|
||||
DEVELOPER_DIR: '/Applications/Xcode_${{matrix.xcode}}.app/Contents/Developer'
|
||||
TARGET_MACOS_VERSION: ${{ matrix.override_target }}
|
||||
CCACHE_EVICTION_AGE: ${{ matrix.ccache_eviction_age }}
|
||||
run: .ci/compile.sh --server --test --vcpkg
|
||||
|
||||
# Delete used cache to emulate a ccache update. See https://github.com/actions/cache/issues/342
|
||||
- name: Delete remote compiler cache (ccache)
|
||||
if: github.ref == 'refs/heads/master' && matrix.use_ccache == 1 && steps.ccache_restore.outputs.cache-hit
|
||||
continue-on-error: true
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
if gh cache delete --repo ${{ github.repository }} ${{ steps.ccache_restore.outputs.cache-primary-key }}; then
|
||||
echo "Cache deleted successfully"
|
||||
fi
|
||||
|
||||
- name: Save updated compiler cache (ccache)
|
||||
if: github.ref == 'refs/heads/master' && matrix.use_ccache == 1
|
||||
uses: actions/cache/save@v5
|
||||
with:
|
||||
path: ${{env.CCACHE_DIR}}
|
||||
key: ${{ steps.ccache_restore.outputs.cache-primary-key }}
|
||||
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"
|
||||
|
||||
- name: Sign app bundle
|
||||
if: matrix.os == 'macOS' && matrix.make_package && needs.configure.outputs.tag != null
|
||||
id: sign_macos
|
||||
if: matrix.make_package && (github.ref == 'refs/heads/master' || needs.configure.outputs.tag != null)
|
||||
env:
|
||||
MACOS_CERTIFICATE_NAME: ${{ secrets.PROD_MACOS_CERTIFICATE_NAME }}
|
||||
MACOS_CI_KEYCHAIN_PWD: ${{ secrets.PROD_MACOS_CI_KEYCHAIN_PWD }}
|
||||
|
|
@ -498,7 +333,7 @@ jobs:
|
|||
fi
|
||||
|
||||
- name: Notarize app bundle
|
||||
if: steps.sign_macos.outcome == 'success'
|
||||
if: matrix.make_package && (github.ref == 'refs/heads/master' || needs.configure.outputs.tag != null)
|
||||
env:
|
||||
MACOS_NOTARIZATION_APPLE_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_APPLE_ID }}
|
||||
MACOS_NOTARIZATION_TEAM_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_TEAM_ID }}
|
||||
|
|
@ -509,20 +344,20 @@ jobs:
|
|||
# Store the notarization credentials so that we can prevent a UI password dialog from blocking the CI
|
||||
echo "Create keychain profile"
|
||||
xcrun notarytool store-credentials "notarytool-profile" --apple-id "$MACOS_NOTARIZATION_APPLE_ID" --team-id "$MACOS_NOTARIZATION_TEAM_ID" --password "$MACOS_NOTARIZATION_PWD"
|
||||
|
||||
|
||||
# We can't notarize an app bundle directly, but we need to compress it as an archive.
|
||||
# Therefore, we create a zip file containing our app bundle, so that we can send it to the
|
||||
# notarization service
|
||||
echo "Creating temp notarization archive"
|
||||
ditto -c -k --keepParent ${{steps.build.outputs.path}} "notarization.zip"
|
||||
|
||||
|
||||
# Here we send the notarization request to the Apple's Notarization service, waiting for the result.
|
||||
# This typically takes a few seconds inside a CI environment, but it might take more depending on the App
|
||||
# characteristics. Visit the Notarization docs for more information and strategies on how to optimize it if
|
||||
# you're curious
|
||||
echo "Notarize app"
|
||||
xcrun notarytool submit "notarization.zip" --keychain-profile "notarytool-profile" --wait
|
||||
|
||||
|
||||
# Finally, we need to "attach the staple" to our executable, which will allow our app to be
|
||||
# validated by macOS even when an internet connection is not available.
|
||||
echo "Attach staple"
|
||||
|
|
@ -530,47 +365,140 @@ jobs:
|
|||
fi
|
||||
|
||||
- name: Upload artifact
|
||||
if: matrix.make_package
|
||||
id: upload_artifact
|
||||
uses: actions/upload-artifact@v7
|
||||
if: matrix.make_package
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: macOS${{matrix.target}}${{ matrix.soc == 'Intel' && '_Intel' || '' }}${{ matrix.type == 'Debug' && '_Debug' || '' }}-package
|
||||
path: ${{steps.build.outputs.path}}
|
||||
archive: false
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload PDBs (Program Databases)
|
||||
if: matrix.os == 'Windows' && github.ref_type != 'tag'
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: ${{steps.build.outputs.name}}-PDBs
|
||||
path: |
|
||||
build/cockatrice/Release/*.pdb
|
||||
build/oracle/Release/*.pdb
|
||||
build/servatrice/Release/*.pdb
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload to release
|
||||
if: needs.configure.outputs.tag != null && matrix.make_package == '1'
|
||||
id: upload_release
|
||||
if: matrix.make_package && needs.configure.outputs.tag != null
|
||||
shell: bash
|
||||
env:
|
||||
GH_TOKEN: ${{github.token}}
|
||||
tag_name: ${{needs.configure.outputs.tag}}
|
||||
asset_name: ${{steps.build.outputs.fullname}}
|
||||
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
|
||||
if: steps.upload_release.outcome == 'success'
|
||||
id: attestation
|
||||
uses: actions/attest@v4
|
||||
if: steps.upload_release.outcome == 'success'
|
||||
uses: actions/attest-build-provenance@v3
|
||||
with:
|
||||
subject-path: ${{steps.build.outputs.path}}
|
||||
show-summary: false
|
||||
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}} --repo Cockatrice/Cockatrice
|
||||
run: gh attestation verify ${{steps.build.outputs.path}} -R Cockatrice/Cockatrice
|
||||
|
||||
build-windows:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- target: 7
|
||||
qt_version: 5.15.*
|
||||
qt_arch: msvc2019_64
|
||||
|
||||
- target: 10
|
||||
qt_version: 6.6.*
|
||||
qt_arch: msvc2019_64
|
||||
qt_modules: "qtimageformats qtmultimedia qtwebsockets"
|
||||
|
||||
name: Windows ${{matrix.target}}
|
||||
needs: configure
|
||||
runs-on: windows-2022
|
||||
env:
|
||||
CMAKE_GENERATOR: 'Visual Studio 17 2022'
|
||||
|
||||
steps:
|
||||
- name: Add msbuild to PATH
|
||||
id: add-msbuild
|
||||
uses: microsoft/setup-msbuild@v2
|
||||
with:
|
||||
msbuild-architecture: x64
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Install Qt ${{matrix.qt_version}}
|
||||
uses: jurplel/install-qt-action@v4
|
||||
with:
|
||||
cache: true
|
||||
setup-python: true
|
||||
version: ${{matrix.qt_version}}
|
||||
arch: win64_${{matrix.qt_arch}}
|
||||
modules: ${{matrix.qt_modules}}
|
||||
|
||||
- name: Setup vcpkg cache
|
||||
id: vcpkg-cache
|
||||
uses: TAServers/vcpkg-cache@v3
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build Cockatrice
|
||||
id: build
|
||||
shell: bash
|
||||
env:
|
||||
PACKAGE_SUFFIX: '-Win${{matrix.target}}'
|
||||
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
|
||||
path: ${{steps.build.outputs.path}}
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload pdb database
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Windows${{matrix.target}}-debug-pdbs
|
||||
path: |
|
||||
build/cockatrice/Release/*.pdb
|
||||
build/servatrice/Release/*.pdb
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload to release
|
||||
id: upload_release
|
||||
if: needs.configure.outputs.tag != null
|
||||
shell: bash
|
||||
env:
|
||||
GH_TOKEN: ${{github.token}}
|
||||
tag_name: ${{needs.configure.outputs.tag}}
|
||||
asset_path: ${{steps.build.outputs.path}}
|
||||
asset_name: ${{steps.build.outputs.name}}
|
||||
run: gh release upload "$tag_name" "$asset_path#$asset_name"
|
||||
|
||||
- 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
|
||||
|
|
|
|||
29
.github/workflows/desktop-lint.yml
vendored
|
|
@ -1,38 +1,29 @@
|
|||
name: Code Style (C++)
|
||||
|
||||
on:
|
||||
# push trigger not needed for linting, we do not allow direct pushes to master
|
||||
pull_request:
|
||||
paths:
|
||||
- '*/**' # matches all files not in root
|
||||
- '!**.md'
|
||||
- '!.ci/**'
|
||||
- '!.github/**'
|
||||
- '!.husky/**'
|
||||
- '!.tx/**'
|
||||
- '!doc/**'
|
||||
- '!webclient/**'
|
||||
- '.ci/lint_cpp.sh'
|
||||
- '.github/workflows/desktop-lint.yml'
|
||||
- '.clang-format'
|
||||
- '.cmake-format.json'
|
||||
- 'format.sh'
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
- 'webclient/**'
|
||||
- '.github/workflows/web-*.yml'
|
||||
- '.github/workflows/translations-*.yml'
|
||||
- '.github/workflows/docker-release.yml'
|
||||
|
||||
jobs:
|
||||
format:
|
||||
runs-on: ubuntu-slim
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 20 # should be enough to find merge base
|
||||
fetch-depth: 20 # should be enough to find merge base
|
||||
|
||||
- name: Install dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --no-install-recommends clang-format cmake-format shellcheck
|
||||
sudo apt-get install -y --no-install-recommends clang-format cmake-format
|
||||
|
||||
- name: Check code formatting
|
||||
shell: bash
|
||||
|
|
|
|||
23
.github/workflows/docker-release.yml
vendored
|
|
@ -11,12 +11,6 @@ on:
|
|||
- master
|
||||
paths:
|
||||
- '.github/workflows/docker-release.yml'
|
||||
- 'Dockerfile'
|
||||
|
||||
# Cancel earlier, unfinished runs of this workflow on the same branch (unless on release)
|
||||
concurrency:
|
||||
group: "${{ github.workflow }} @ ${{ github.ref_name }}"
|
||||
cancel-in-progress: ${{ github.ref_type != 'tag' }}
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
|
|
@ -28,11 +22,11 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Docker metadata
|
||||
id: metadata
|
||||
uses: docker/metadata-action@v6
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: |
|
||||
ghcr.io/cockatrice/servatrice
|
||||
|
|
@ -46,27 +40,26 @@ jobs:
|
|||
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@v4
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker buildx
|
||||
uses: docker/setup-buildx-action@v4
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
if: github.ref_type == 'tag'
|
||||
uses: docker/login-action@v4
|
||||
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@v7
|
||||
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 }}
|
||||
annotations: ${{ steps.metadata.outputs.annotations }}
|
||||
cache-from: type=gha,scope=servatrice
|
||||
cache-to: type=gha,mode=max,scope=servatrice
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
|
|
|||
36
.github/workflows/documentation-build.yml
vendored
|
|
@ -6,14 +6,11 @@ on:
|
|||
- '*' # Only re-generate docs when a new tagged version is pushed
|
||||
pull_request:
|
||||
paths:
|
||||
- 'doc/doxygen/**'
|
||||
- '.github/workflows/documentation-build.yml'
|
||||
- 'Doxyfile'
|
||||
- 'doxygen_style.css'
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
COCKATRICE_REF: ${{ github.ref_name }} # Tag name if the commit is tagged, otherwise branch name
|
||||
|
||||
jobs:
|
||||
docs:
|
||||
name: Doxygen
|
||||
|
|
@ -21,40 +18,17 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Install Graphviz
|
||||
run: |
|
||||
sudo apt-get install -y graphviz
|
||||
dot -V
|
||||
|
||||
- name: Install Doxygen
|
||||
uses: ssciwr/doxygen-install@v2
|
||||
with:
|
||||
version: "1.14.0"
|
||||
|
||||
- name: Update Doxygen Configuration
|
||||
run: |
|
||||
git diff Doxyfile
|
||||
doxygen -u Doxyfile
|
||||
if git diff --quiet Doxyfile; then
|
||||
echo "::notice::No config changes in Doxyfile detected."
|
||||
else
|
||||
echo "::error::Config changes in Doxyfile detected! Please update the file by running 'doxygen -u Doxyfile'."
|
||||
echo ""
|
||||
git diff --color=always Doxyfile
|
||||
exit 1
|
||||
fi
|
||||
- name: Install Doxygen and Graphviz
|
||||
run: sudo apt-get install -y doxygen graphviz
|
||||
|
||||
- name: Generate Documentation
|
||||
if: always()
|
||||
run: doxygen Doxyfile
|
||||
|
||||
- name: Deploy to cockatrice.github.io
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: peaceiris/actions-gh-pages@v4
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
deploy_key: ${{ secrets.DOCS_DEPLOY_KEY }}
|
||||
external_repository: Cockatrice/cockatrice.github.io
|
||||
|
|
|
|||
7
.github/workflows/translations-pull.yml
vendored
|
|
@ -7,7 +7,6 @@ on:
|
|||
- cron: '0 0 15 1,4,7,10 *'
|
||||
pull_request:
|
||||
paths:
|
||||
- '.tx/**'
|
||||
- '.github/workflows/translations-pull.yml'
|
||||
|
||||
jobs:
|
||||
|
|
@ -16,11 +15,11 @@ jobs:
|
|||
if: github.event_name != 'schedule' || github.repository_owner == 'Cockatrice'
|
||||
|
||||
name: Pull languages
|
||||
runs-on: ubuntu-slim
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Pull translated strings from Transifex
|
||||
uses: transifex/cli-action@v2
|
||||
|
|
@ -33,7 +32,7 @@ jobs:
|
|||
- name: Create pull request
|
||||
if: github.event_name != 'pull_request'
|
||||
id: create_pr
|
||||
uses: peter-evans/create-pull-request@v8
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
with:
|
||||
add-paths: |
|
||||
cockatrice/translations/*.ts
|
||||
|
|
|
|||
17
.github/workflows/translations-push.yml
vendored
|
|
@ -7,7 +7,6 @@ on:
|
|||
- cron: '0 0 1 1,4,7,10 *'
|
||||
pull_request:
|
||||
paths:
|
||||
- '.ci/update_translation_source_strings.sh'
|
||||
- '.github/workflows/translations-push.yml'
|
||||
|
||||
jobs:
|
||||
|
|
@ -16,11 +15,11 @@ jobs:
|
|||
if: github.event_name != 'schedule' || github.repository_owner == 'Cockatrice'
|
||||
|
||||
name: Push strings
|
||||
runs-on: ubuntu-slim
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Install lupdate
|
||||
shell: bash
|
||||
|
|
@ -31,10 +30,10 @@ jobs:
|
|||
- name: Update Cockatrice translation source
|
||||
id: cockatrice
|
||||
shell: bash
|
||||
run: |
|
||||
FILE="cockatrice/cockatrice_en@source.ts"
|
||||
export DIRS="cockatrice/src $(find . -maxdepth 1 -type d -name 'libcockatrice_*')"
|
||||
FILE="$FILE" DIRS="$DIRS" .ci/update_translation_source_strings.sh
|
||||
env:
|
||||
FILE: 'cockatrice/cockatrice_en@source.ts'
|
||||
DIRS: 'cockatrice/src common'
|
||||
run: .ci/update_translation_source_strings.sh
|
||||
|
||||
- name: Update Oracle translation source
|
||||
id: oracle
|
||||
|
|
@ -46,7 +45,7 @@ jobs:
|
|||
|
||||
- name: Render template
|
||||
id: template
|
||||
uses: chuhlomin/render-template/binary@v1
|
||||
uses: chuhlomin/render-template@v1
|
||||
with:
|
||||
template: .ci/update_translation_source_strings_template.md
|
||||
vars: |
|
||||
|
|
@ -57,7 +56,7 @@ jobs:
|
|||
- name: Create pull request
|
||||
if: github.event_name != 'pull_request'
|
||||
id: create_pr
|
||||
uses: peter-evans/create-pull-request@v8
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
with:
|
||||
add-paths: |
|
||||
cockatrice/cockatrice_en@source.ts
|
||||
|
|
|
|||
10
.github/workflows/web-build.yml
vendored
|
|
@ -5,16 +5,14 @@ on:
|
|||
branches:
|
||||
- master
|
||||
paths:
|
||||
- '.husky/**'
|
||||
- '.github/workflows/web-*.yml'
|
||||
- 'webclient/**'
|
||||
- '!**.md'
|
||||
- '.github/workflows/web-build.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- '.husky/**'
|
||||
- '.github/workflows/web-*.yml'
|
||||
- 'webclient/**'
|
||||
- '!**.md'
|
||||
- '.github/workflows/web-build.yml'
|
||||
|
||||
jobs:
|
||||
build-web:
|
||||
|
|
@ -35,10 +33,10 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: ${{matrix.node_version}}
|
||||
cache: 'npm'
|
||||
|
|
|
|||
9
.github/workflows/web-lint.yml
vendored
|
|
@ -1,16 +1,15 @@
|
|||
name: Code Style (TypeScript)
|
||||
|
||||
on:
|
||||
# push trigger not needed for linting, we do not allow direct pushes to master
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/web-*.yml'
|
||||
- 'webclient/**'
|
||||
- '!**.md'
|
||||
- '.github/workflows/web-lint.yml'
|
||||
|
||||
jobs:
|
||||
ESLint:
|
||||
runs-on: ubuntu-slim
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
defaults:
|
||||
run:
|
||||
|
|
@ -18,10 +17,10 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
cache: 'npm'
|
||||
cache-dependency-path: 'webclient/package-lock.json'
|
||||
|
|
|
|||
1
.gitignore
vendored
|
|
@ -14,4 +14,3 @@ compile_commands.json
|
|||
.cache
|
||||
.gdb_history
|
||||
cockatrice/resources/config/qtlogging.ini
|
||||
docs/
|
||||
|
|
|
|||
3
.gitmodules
vendored
|
|
@ -1,6 +1,3 @@
|
|||
[submodule "vcpkg"]
|
||||
path = vcpkg
|
||||
url = https://github.com/microsoft/vcpkg.git
|
||||
[submodule "doxygen-awesome-css"]
|
||||
path = doc/doxygen/theme
|
||||
url = https://github.com/jothepro/doxygen-awesome-css.git
|
||||
|
|
|
|||
|
|
@ -20,10 +20,10 @@ option(WITH_SERVER "build servatrice" OFF)
|
|||
option(WITH_CLIENT "build cockatrice" ON)
|
||||
# Compile oracle
|
||||
option(WITH_ORACLE "build oracle" ON)
|
||||
# Compile dbconverter
|
||||
option(WITH_DBCONVERTER "build dbconverter" ON)
|
||||
# Compile tests
|
||||
option(TEST "build tests" OFF)
|
||||
# Use vcpkg regardless of OS
|
||||
option(USE_VCPKG "Use vcpkg regardless of OS" OFF)
|
||||
|
||||
# Default to "Release" build type
|
||||
# User-provided value for CMAKE_BUILD_TYPE must be checked before the PROJECT() call
|
||||
|
|
@ -48,8 +48,8 @@ if(USE_CCACHE)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
if(WIN32 OR USE_VCPKG)
|
||||
# Use vcpkg toolchain on Windows (and on macOS in CI)
|
||||
if(WIN32 OR APPLE)
|
||||
# Use vcpkg toolchain on Windows and macOS
|
||||
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 3.0.0)
|
||||
project("Cockatrice" VERSION 2.11.0)
|
||||
|
||||
# Set release name if not provided via env/cmake var
|
||||
if(NOT DEFINED GIT_TAG_RELEASENAME)
|
||||
set(GIT_TAG_RELEASENAME "Graduation Day")
|
||||
set(GIT_TAG_RELEASENAME "Omenpath")
|
||||
endif()
|
||||
|
||||
# Use c++20 for all targets
|
||||
|
|
@ -254,9 +254,7 @@ endif()
|
|||
set(CPACK_PACKAGE_CONTACT "Zach Halpern <zach@cockatrice.us>")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PROJECT_NAME}")
|
||||
set(CPACK_PACKAGE_VENDOR "Cockatrice Development Team")
|
||||
set(CPACK_PACKAGE_DESCRIPTION
|
||||
"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."
|
||||
)
|
||||
set(CPACK_PACKAGE_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/README.md")
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}")
|
||||
set(CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}")
|
||||
|
|
@ -328,24 +326,7 @@ endif()
|
|||
|
||||
include(CPack)
|
||||
|
||||
add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_interfaces ${CMAKE_BINARY_DIR}/libcockatrice_interfaces)
|
||||
add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_protocol ${CMAKE_BINARY_DIR}/libcockatrice_protocol)
|
||||
if(WITH_CLIENT
|
||||
OR WITH_SERVER
|
||||
OR WITH_ORACLE
|
||||
)
|
||||
add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_network ${CMAKE_BINARY_DIR}/libcockatrice_network)
|
||||
endif()
|
||||
add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_deck_list ${CMAKE_BINARY_DIR}/libcockatrice_deck_list)
|
||||
add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_rng ${CMAKE_BINARY_DIR}/libcockatrice_rng)
|
||||
add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_card ${CMAKE_BINARY_DIR}/libcockatrice_card)
|
||||
add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_utility ${CMAKE_BINARY_DIR}/libcockatrice_utility)
|
||||
if(WITH_ORACLE OR WITH_CLIENT)
|
||||
add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_settings ${CMAKE_BINARY_DIR}/libcockatrice_settings)
|
||||
add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_models ${CMAKE_BINARY_DIR}/libcockatrice_models)
|
||||
add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_filters ${CMAKE_BINARY_DIR}/libcockatrice_filters)
|
||||
endif()
|
||||
|
||||
add_subdirectory(common)
|
||||
if(WITH_SERVER)
|
||||
add_subdirectory(servatrice)
|
||||
set(CPACK_INSTALL_CMAKE_PROJECTS "Servatrice;Servatrice;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
|
||||
|
|
@ -361,6 +342,11 @@ if(WITH_ORACLE)
|
|||
set(CPACK_INSTALL_CMAKE_PROJECTS "Oracle;Oracle;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
|
||||
endif()
|
||||
|
||||
if(WITH_DBCONVERTER)
|
||||
add_subdirectory(dbconverter)
|
||||
set(CPACK_INSTALL_CMAKE_PROJECTS "Dbconverter;Dbconverter;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
|
||||
endif()
|
||||
|
||||
if(TEST)
|
||||
include(CTest)
|
||||
add_subdirectory(tests)
|
||||
|
|
|
|||
33
Dockerfile
|
|
@ -1,9 +1,8 @@
|
|||
# -------- Build Stage --------
|
||||
FROM ubuntu:24.04 AS build
|
||||
FROM ubuntu:24.04
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
RUN apt-get update && apt-get install -y\
|
||||
build-essential \
|
||||
cmake \
|
||||
file \
|
||||
|
|
@ -17,28 +16,20 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||
qt6-tools-dev \
|
||||
qt6-tools-dev-tools
|
||||
|
||||
WORKDIR /src
|
||||
COPY . .
|
||||
RUN mkdir build && cd build && \
|
||||
cmake .. -DWITH_SERVER=1 -DWITH_CLIENT=0 -DWITH_ORACLE=0 && \
|
||||
make -j$(nproc) && \
|
||||
make install
|
||||
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
|
||||
|
||||
WORKDIR /home/servatrice/code
|
||||
|
||||
# -------- Runtime Stage (clean) --------
|
||||
FROM ubuntu:24.04
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
libprotobuf32t64 \
|
||||
libqt6sql6-mysql \
|
||||
libqt6websockets6 \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Only copy installed binaries, not source
|
||||
COPY --from=build /usr/local /usr/local
|
||||
WORKDIR build
|
||||
RUN cmake .. -DWITH_SERVER=1 -DWITH_CLIENT=0 -DWITH_ORACLE=0 -DWITH_DBCONVERTER=0 &&\
|
||||
make &&\
|
||||
make install
|
||||
|
||||
WORKDIR /home/servatrice
|
||||
|
||||
EXPOSE 4748
|
||||
|
||||
ENTRYPOINT [ "servatrice", "--log-to-console" ]
|
||||
|
|
|
|||
113
Doxyfile
|
|
@ -42,32 +42,32 @@ DOXYFILE_ENCODING = UTF-8
|
|||
# title of most generated pages and in a few other places.
|
||||
# The default value is: My Project.
|
||||
|
||||
PROJECT_NAME = Cockatrice
|
||||
PROJECT_NAME = "Cockatrice"
|
||||
|
||||
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = $(COCKATRICE_REF)
|
||||
PROJECT_NUMBER =
|
||||
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears at the top of each page and should give viewers a
|
||||
# quick idea about the purpose of the project. Keep the description short.
|
||||
|
||||
PROJECT_BRIEF = "A virtual tabletop for multiplayer card games"
|
||||
PROJECT_BRIEF =
|
||||
|
||||
# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
|
||||
# in the documentation. The maximum height of the logo should not exceed 55
|
||||
# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
|
||||
# the logo to the output directory.
|
||||
|
||||
PROJECT_LOGO = cockatrice/resources/cockatrice.png
|
||||
PROJECT_LOGO =
|
||||
|
||||
# With the PROJECT_ICON tag one can specify an icon that is included in the tabs
|
||||
# when the HTML document is shown. Doxygen will copy the logo to the output
|
||||
# directory.
|
||||
|
||||
PROJECT_ICON = cockatrice/resources/cockatrice.png
|
||||
PROJECT_ICON =
|
||||
|
||||
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
|
||||
# into which the generated documentation will be written. If a relative path is
|
||||
|
|
@ -379,7 +379,7 @@ TOC_INCLUDE_HEADINGS = 6
|
|||
# The default value is: DOXYGEN.
|
||||
# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
|
||||
|
||||
MARKDOWN_ID_STYLE = GITHUB
|
||||
MARKDOWN_ID_STYLE = DOXYGEN
|
||||
|
||||
# When enabled Doxygen tries to link words that correspond to documented
|
||||
# classes, or namespaces to their corresponding documentation. Such a link can
|
||||
|
|
@ -839,7 +839,7 @@ FILE_VERSION_FILTER =
|
|||
# DoxygenLayout.xml, Doxygen will parse it automatically even if the LAYOUT_FILE
|
||||
# tag is left empty.
|
||||
|
||||
LAYOUT_FILE = doc/doxygen/DoxygenLayout.xml
|
||||
LAYOUT_FILE =
|
||||
|
||||
# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
|
||||
# the reference definitions. This must be a list of .bib files. The .bib
|
||||
|
|
@ -991,7 +991,7 @@ WARN_LOGFILE =
|
|||
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
|
||||
# Note: If this tag is empty the current directory is searched.
|
||||
|
||||
INPUT = .
|
||||
INPUT = cockatrice common
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
# that Doxygen parses. Internally Doxygen uses the UTF-8 encoding. Doxygen uses
|
||||
|
|
@ -1031,7 +1031,8 @@ INPUT_FILE_ENCODING =
|
|||
# provided as Doxygen C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
|
||||
# *.f18, *.f, *.for, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice.
|
||||
|
||||
FILE_PATTERNS = *.cc \
|
||||
FILE_PATTERNS = *.c \
|
||||
*.cc \
|
||||
*.cxx \
|
||||
*.cxxm \
|
||||
*.cpp \
|
||||
|
|
@ -1039,19 +1040,47 @@ FILE_PATTERNS = *.cc \
|
|||
*.ccm \
|
||||
*.c++ \
|
||||
*.c++m \
|
||||
*.java \
|
||||
*.ii \
|
||||
*.ixx \
|
||||
*.ipp \
|
||||
*.i++ \
|
||||
*.inl \
|
||||
*.idl \
|
||||
*.ddl \
|
||||
*.odl \
|
||||
*.h \
|
||||
*.hh \
|
||||
*.hxx \
|
||||
*.hpp \
|
||||
*.h++ \
|
||||
*.l \
|
||||
*.cs \
|
||||
*.d \
|
||||
*.php \
|
||||
*.php4 \
|
||||
*.php5 \
|
||||
*.phtml \
|
||||
*.inc \
|
||||
*.m \
|
||||
*.markdown \
|
||||
*.md \
|
||||
*.dox
|
||||
*.mm \
|
||||
*.dox \
|
||||
*.py \
|
||||
*.pyw \
|
||||
*.f90 \
|
||||
*.f95 \
|
||||
*.f03 \
|
||||
*.f08 \
|
||||
*.f18 \
|
||||
*.f \
|
||||
*.for \
|
||||
*.vhd \
|
||||
*.vhdl \
|
||||
*.ucf \
|
||||
*.qsf \
|
||||
*.ice
|
||||
|
||||
# The RECURSIVE tag can be used to specify whether or not subdirectories should
|
||||
# be searched for input files as well.
|
||||
|
|
@ -1066,12 +1095,7 @@ RECURSIVE = YES
|
|||
# Note that relative paths are relative to the directory from which Doxygen is
|
||||
# run.
|
||||
|
||||
EXCLUDE = build/ \
|
||||
cmake/ \
|
||||
doc/doxygen/theme/docs/ \
|
||||
doc/doxygen/theme/include/ \
|
||||
vcpkg/ \
|
||||
webclient/
|
||||
EXCLUDE = common/lib
|
||||
|
||||
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
|
||||
# directories that are symbolic links (a Unix file system feature) are excluded
|
||||
|
|
@ -1087,8 +1111,7 @@ EXCLUDE_SYMLINKS = NO
|
|||
# Note that the wildcards are matched against the file with absolute path, so to
|
||||
# exclude all test directories for example use the pattern */test/*
|
||||
|
||||
EXCLUDE_PATTERNS = .* \
|
||||
.*/
|
||||
EXCLUDE_PATTERNS =
|
||||
|
||||
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
|
||||
# (namespaces, classes, functions, etc.) that should be excluded from the
|
||||
|
|
@ -1122,7 +1145,7 @@ EXAMPLE_RECURSIVE = NO
|
|||
# that contain images that are to be included in the documentation (see the
|
||||
# \image command).
|
||||
|
||||
IMAGE_PATH = doc/doxygen/images
|
||||
IMAGE_PATH =
|
||||
|
||||
# The INPUT_FILTER tag can be used to specify a program that Doxygen should
|
||||
# invoke to filter for each input file. Doxygen will invoke the filter program
|
||||
|
|
@ -1290,46 +1313,6 @@ USE_HTAGS = NO
|
|||
|
||||
VERBATIM_HEADERS = YES
|
||||
|
||||
# If the CLANG_ASSISTED_PARSING tag is set to YES then Doxygen will use the
|
||||
# clang parser (see:
|
||||
# http://clang.llvm.org/) for more accurate parsing at the cost of reduced
|
||||
# performance. This can be particularly helpful with template rich C++ code for
|
||||
# which Doxygen's built-in parser lacks the necessary type information.
|
||||
# Note: The availability of this option depends on whether or not Doxygen was
|
||||
# generated with the -Duse_libclang=ON option for CMake.
|
||||
# The default value is: NO.
|
||||
|
||||
CLANG_ASSISTED_PARSING = NO
|
||||
|
||||
# If the CLANG_ASSISTED_PARSING tag is set to YES and the CLANG_ADD_INC_PATHS
|
||||
# tag is set to YES then Doxygen will add the directory of each input to the
|
||||
# include path.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
|
||||
|
||||
CLANG_ADD_INC_PATHS = YES
|
||||
|
||||
# If clang assisted parsing is enabled you can provide the compiler with command
|
||||
# line options that you would normally use when invoking the compiler. Note that
|
||||
# the include paths will already be set by Doxygen for the files and directories
|
||||
# specified with INPUT and INCLUDE_PATH.
|
||||
# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
|
||||
|
||||
CLANG_OPTIONS =
|
||||
|
||||
# If clang assisted parsing is enabled you can provide the clang parser with the
|
||||
# path to the directory containing a file called compile_commands.json. This
|
||||
# file is the compilation database (see:
|
||||
# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the
|
||||
# options used when the source files were built. This is equivalent to
|
||||
# specifying the -p option to a clang tool, such as clang-check. These options
|
||||
# will then be passed to the parser. Any options specified with CLANG_OPTIONS
|
||||
# will be added as well.
|
||||
# Note: The availability of this option depends on whether or not Doxygen was
|
||||
# generated with the -Duse_libclang=ON option for CMake.
|
||||
|
||||
CLANG_DATABASE_PATH =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the alphabetical class index
|
||||
#---------------------------------------------------------------------------
|
||||
|
|
@ -1432,9 +1415,7 @@ HTML_STYLESHEET =
|
|||
# documentation.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_EXTRA_STYLESHEET = doc/doxygen/theme/doxygen-awesome.css \
|
||||
doc/doxygen/css/hide_nav_sync.css \
|
||||
doc/doxygen/css/cockatrice_docs_style.css
|
||||
HTML_EXTRA_STYLESHEET = doc/doxygen/css/doxygen_style.css
|
||||
|
||||
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
|
||||
# other source files which should be copied to the HTML output directory. Note
|
||||
|
|
@ -1457,7 +1438,7 @@ HTML_EXTRA_FILES = doc/doxygen/js/graph_toggle.js
|
|||
# The default value is: AUTO_LIGHT.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_COLORSTYLE = LIGHT
|
||||
HTML_COLORSTYLE = DARK
|
||||
|
||||
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
|
||||
# will adjust the colors in the style sheet and background images according to
|
||||
|
|
@ -2040,7 +2021,7 @@ EXTRA_SEARCH_MAPPINGS =
|
|||
# If the GENERATE_LATEX tag is set to YES, Doxygen will generate LaTeX output.
|
||||
# The default value is: YES.
|
||||
|
||||
GENERATE_LATEX = NO
|
||||
GENERATE_LATEX = YES
|
||||
|
||||
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
|
||||
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
|
||||
|
|
@ -2626,7 +2607,7 @@ DOT_COMMON_ATTR = "fontname=Helvetica,fontsize=10"
|
|||
# The default value is: labelfontname=Helvetica,labelfontsize=10.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
DOT_EDGE_ATTR = "labelfontname=Helvetica,labelfontsize=10,arrowhead=open, arrowtail=open, arrowsize=0.5"
|
||||
DOT_EDGE_ATTR = "labelfontname=Helvetica,labelfontsize=10,arrowhead=open, arrowtail=open, arrowsize=0.5"
|
||||
|
||||
# DOT_NODE_ATTR is concatenated with DOT_COMMON_ATTR. For view without boxes
|
||||
# around nodes set 'shape=plain' or 'shape=plaintext' <a
|
||||
|
|
@ -2634,7 +2615,7 @@ DOT_EDGE_ATTR = "labelfontname=Helvetica,labelfontsize=10,arrowhead=ope
|
|||
# The default value is: shape=box,height=0.2,width=0.4.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
DOT_NODE_ATTR = "shape=box,height=0.2,width=0.4"
|
||||
DOT_NODE_ATTR = "shape=box,height=0.2,width=0.4"
|
||||
|
||||
# You can set the path where dot can find font specified with fontname in
|
||||
# DOT_COMMON_ATTR and others dot attributes.
|
||||
|
|
|
|||
57
README.md
|
|
@ -44,42 +44,24 @@ Latest <kbd>beta</kbd> version:
|
|||
|
||||
# Related Repositories
|
||||
|
||||
- [Magic-Token](https://github.com/Cockatrice/Magic-Token): File with MtG token data for use in Cockatrice
|
||||
- [Magic-Spoiler](https://github.com/Cockatrice/Magic-Spoiler): Code to generate MtG spoiler data from [MTGJSON](https://github.com/mtgjson/mtgjson) for use in Cockatrice
|
||||
- [cockatrice.github.io](https://github.com/Cockatrice/cockatrice.github.io): Code of the official Cockatrice webpage
|
||||
- [io.github.Cockatrice.cockatrice](https://github.com/flathub/io.github.Cockatrice.cockatrice): Configuration of our Linux `flatpak` package hosted at [Flathub](https://flathub.org/en/apps/io.github.Cockatrice.cockatrice)
|
||||
- [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
|
||||
|
||||
|
||||
# Community Resources [](https://discord.gg/3Z9yzmA)
|
||||
|
||||
Join our [Discord community](https://discord.gg/3Z9yzmA) to connect with other project contributors (`#dev` channel) or fellow users of the app. Come here to talk about the application, features, or just to hang out.
|
||||
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)
|
||||
- [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.
|
||||
>[!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.
|
||||
|
||||
|
||||
# Contribute
|
||||
<p>
|
||||
<a href="#code">Code</a> <b>|</b>
|
||||
<a href="#documentation-">Documentation</a> <b>|</b>
|
||||
<a href="#translation-">Translation</a>
|
||||
</p>
|
||||
|
||||
#### Repository Activity
|
||||

|
||||
|
||||
<details>
|
||||
<summary><b>Kudos to all 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>
|
||||
|
||||
### Code
|
||||
|
||||
|
|
@ -93,23 +75,22 @@ This tag is used for issues that we are looking for somebody to pick up. Often t
|
|||
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!
|
||||
|
||||
You can also have a look at our `Todo List` in our [Code Documentation](https://cockatrice.github.io/docs) or search the repo for [`\todo` comments](https://github.com/search?q=repo%3ACockatrice%2FCockatrice%20%5Ctodo&type=code).
|
||||
|
||||
### Documentation [](https://github.com/Cockatrice/Cockatrice/actions/workflows/documentation-build.yml?query=event%3Apush)
|
||||
|
||||
There are various places where useful information for different needs are maintained:
|
||||
- [Official Code Documentation](https://cockatrice.github.io/docs/)
|
||||
- [Official Wiki](https://github.com/Cockatrice/Cockatrice/wiki) `Community supported`
|
||||
- [Official Webpage](https://cockatrice.github.io/)
|
||||
- [Official README](https://github.com/Cockatrice/Cockatrice/blob/master/README.md) `This file`
|
||||
|
||||
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.
|
||||
|
||||
### Translation [](https://explore.transifex.com/cockatrice/cockatrice/)
|
||||
<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 involved, and join a group of hundreds of others!<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)
|
||||
|
|
@ -143,8 +124,8 @@ You can then
|
|||
make package
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> Detailed compiling instructions can be found in the Cockatrice wiki at [Compiling Cockatrice](https://github.com/Cockatrice/Cockatrice/wiki/Compiling-Cockatrice)
|
||||
>[!NOTE]
|
||||
>Detailed compiling instructions can be found in the Cockatrice wiki at [Compiling Cockatrice](https://github.com/Cockatrice/Cockatrice/wiki/Compiling-Cockatrice)
|
||||
|
||||
<br>
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ tell disk image_name
|
|||
set position of item "Cockatrice.app" to { 139, 214 }
|
||||
set position of item "Oracle.app" to { 139, 414 }
|
||||
set position of item "Servatrice.app" to { 139, 614 }
|
||||
set position of item "dbconverter.app" to { 1400, 1400 }
|
||||
set position of item "Applications" to { 861, 414 }
|
||||
end tell
|
||||
update without registering applications
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
# Find a compatible Qt version
|
||||
# Inputs: WITH_SERVER, WITH_CLIENT, WITH_ORACLE, FORCE_USE_QT5
|
||||
# Inputs: WITH_SERVER, WITH_CLIENT, WITH_ORACLE, WITH_DBCONVERTER, FORCE_USE_QT5
|
||||
# Optional Input: QT6_DIR -- Hint as to where Qt6 lives on the system
|
||||
# Optional Input: QT5_DIR -- Hint as to where Qt5 lives on the system
|
||||
# Output: COCKATRICE_QT_VERSION_NAME -- Example values: Qt5, Qt6
|
||||
# Output: SERVATRICE_QT_MODULES
|
||||
# Output: COCKATRICE_QT_MODULES
|
||||
# Output: ORACLE_QT_MODULES
|
||||
# Output: DBCONVERTER_QT_MODULES
|
||||
# Output: TEST_QT_MODULES
|
||||
|
||||
set(REQUIRED_QT_COMPONENTS Core)
|
||||
|
|
@ -28,21 +29,22 @@ endif()
|
|||
if(WITH_ORACLE)
|
||||
set(_ORACLE_NEEDED Concurrent Network Svg Widgets)
|
||||
endif()
|
||||
if(WITH_DBCONVERTER)
|
||||
set(_DBCONVERTER_NEEDED Network Widgets)
|
||||
endif()
|
||||
if(TEST)
|
||||
# Union of Qt modules required across all test targets (independent of application targets).
|
||||
# When adding a new test that needs additional Qt modules, add them here rather than in the test's CMakeLists.txt.
|
||||
set(_TEST_NEEDED Concurrent Network Svg Widgets)
|
||||
set(_TEST_NEEDED Widgets)
|
||||
endif()
|
||||
|
||||
set(REQUIRED_QT_COMPONENTS ${REQUIRED_QT_COMPONENTS} ${_SERVATRICE_NEEDED} ${_COCKATRICE_NEEDED} ${_ORACLE_NEEDED}
|
||||
${_TEST_NEEDED}
|
||||
${_DBCONVERTER_NEEDED} ${_TEST_NEEDED}
|
||||
)
|
||||
list(REMOVE_DUPLICATES REQUIRED_QT_COMPONENTS)
|
||||
|
||||
if(NOT FORCE_USE_QT5)
|
||||
# Linguist is now a component in Qt6 instead of an external package
|
||||
find_package(
|
||||
Qt6 6.4.2
|
||||
Qt6 6.2.3
|
||||
COMPONENTS ${REQUIRED_QT_COMPONENTS} Linguist
|
||||
QUIET HINTS ${Qt6_DIR}
|
||||
)
|
||||
|
|
@ -61,7 +63,7 @@ if(Qt6_FOUND)
|
|||
endif()
|
||||
else()
|
||||
find_package(
|
||||
Qt5 5.15.2
|
||||
Qt5 5.8.0
|
||||
COMPONENTS ${REQUIRED_QT_COMPONENTS}
|
||||
QUIET HINTS ${Qt5_DIR}
|
||||
)
|
||||
|
|
@ -110,9 +112,7 @@ message(DEBUG "QT_LIBRARY_DIR = ${QT_LIBRARY_DIR}")
|
|||
string(REGEX REPLACE "([^;]+)" "${COCKATRICE_QT_VERSION_NAME}::\\1" SERVATRICE_QT_MODULES "${_SERVATRICE_NEEDED}")
|
||||
string(REGEX REPLACE "([^;]+)" "${COCKATRICE_QT_VERSION_NAME}::\\1" COCKATRICE_QT_MODULES "${_COCKATRICE_NEEDED}")
|
||||
string(REGEX REPLACE "([^;]+)" "${COCKATRICE_QT_VERSION_NAME}::\\1" ORACLE_QT_MODULES "${_ORACLE_NEEDED}")
|
||||
string(REGEX REPLACE "([^;]+)" "${COCKATRICE_QT_VERSION_NAME}::\\1" DB_CONVERTER_QT_MODULES "${_DBCONVERTER_NEEDED}")
|
||||
string(REGEX REPLACE "([^;]+)" "${COCKATRICE_QT_VERSION_NAME}::\\1" TEST_QT_MODULES "${_TEST_NEEDED}")
|
||||
|
||||
# Core-only export (useful for headless libs)
|
||||
set(QT_CORE_MODULE "${COCKATRICE_QT_VERSION_NAME}::Core")
|
||||
|
||||
message(STATUS "Found Qt ${${COCKATRICE_QT_VERSION_NAME}_VERSION} at: ${${COCKATRICE_QT_VERSION_NAME}_DIR}")
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ SetCompressor LZMA
|
|||
Var NormalDestDir
|
||||
Var PortableDestDir
|
||||
Var PortableMode
|
||||
Var ReinstallMode
|
||||
|
||||
!include LogicLib.nsh
|
||||
!include FileFunc.nsh
|
||||
|
|
@ -27,25 +26,14 @@ Var ReinstallMode
|
|||
!define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the installation of Cockatrice.$\r$\n$\r$\nClick Next to continue."
|
||||
!define MUI_FINISHPAGE_RUN "$INSTDIR/cockatrice.exe"
|
||||
!define MUI_FINISHPAGE_RUN_TEXT "Run 'Cockatrice' now"
|
||||
!define MUI_ICON "${NSIS_SOURCE_PATH}\cockatrice\resources\appicon.ico"
|
||||
|
||||
!define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfReinstall
|
||||
!insertmacro MUI_PAGE_WELCOME
|
||||
|
||||
!define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfReinstall
|
||||
!insertmacro MUI_PAGE_LICENSE "${NSIS_SOURCE_PATH}\LICENSE"
|
||||
|
||||
Page Custom PortableModePageCreate PortableModePageLeave
|
||||
!define MUI_PAGE_CUSTOMFUNCTION_PRE componentsPagePre
|
||||
!insertmacro MUI_PAGE_COMPONENTS
|
||||
|
||||
!define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfReinstall
|
||||
!insertmacro MUI_PAGE_DIRECTORY
|
||||
|
||||
!define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfReinstall
|
||||
!insertmacro MUI_PAGE_INSTFILES
|
||||
|
||||
!define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfReinstall
|
||||
!insertmacro MUI_PAGE_FINISH
|
||||
|
||||
!insertmacro MUI_UNPAGE_CONFIRM
|
||||
|
|
@ -84,7 +72,6 @@ ${IfNot} ${Errors}
|
|||
MessageBox MB_ICONINFORMATION|MB_SETFOREGROUND "\
|
||||
/PORTABLE : Install in portable mode$\n\
|
||||
/S : Silent install$\n\
|
||||
/R : Silent upgrade$\n\
|
||||
/D=%directory% : Specify destination directory$\n"
|
||||
Quit
|
||||
${EndIf}
|
||||
|
|
@ -102,16 +89,6 @@ ${Else}
|
|||
${EndIf}
|
||||
${EndIf}
|
||||
|
||||
ClearErrors
|
||||
${GetOptions} $9 "/R" $8
|
||||
${IfNot} ${Errors}
|
||||
StrCpy $ReinstallMode 1
|
||||
SetSilent silent
|
||||
SetAutoClose true
|
||||
${Else}
|
||||
StrCpy $ReinstallMode 0
|
||||
${EndIf}
|
||||
|
||||
${If} $InstDir == ""
|
||||
; User did not use /D to specify a directory,
|
||||
; we need to set a default based on the install mode
|
||||
|
|
@ -119,22 +96,6 @@ ${If} $InstDir == ""
|
|||
${EndIf}
|
||||
Call SetModeDestinationFromInstdir
|
||||
|
||||
; --- Detect portable install when using /R ---
|
||||
${If} $ReinstallMode = 1
|
||||
IfFileExists "$InstDir\portable.dat" 0 not_portable
|
||||
StrCpy $PortableMode 1
|
||||
Goto portable_done
|
||||
|
||||
not_portable:
|
||||
StrCpy $PortableMode 0
|
||||
|
||||
portable_done:
|
||||
${EndIf}
|
||||
|
||||
${If} $ReinstallMode = 1
|
||||
Call AutoUninstallIfNeeded
|
||||
${EndIf}
|
||||
|
||||
FunctionEnd
|
||||
|
||||
Function un.onInit
|
||||
|
|
@ -164,46 +125,8 @@ ${Else}
|
|||
${EndIf}
|
||||
FunctionEnd
|
||||
|
||||
Function SkipIfReinstall
|
||||
${If} $ReinstallMode = 1
|
||||
Abort
|
||||
${EndIf}
|
||||
FunctionEnd
|
||||
|
||||
Function AutoUninstallIfNeeded
|
||||
|
||||
SetShellVarContext all
|
||||
|
||||
; --- 32-bit uninstall ---
|
||||
SetRegView 32
|
||||
ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "QuietUninstallString"
|
||||
|
||||
StrCmp $R0 "" done32
|
||||
DetailPrint "Removing previous version (32-bit)..."
|
||||
ExecWait '$R0'
|
||||
|
||||
done32:
|
||||
|
||||
; --- 64-bit uninstall ---
|
||||
${If} ${RunningX64}
|
||||
SetRegView 64
|
||||
ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "QuietUninstallString"
|
||||
|
||||
StrCmp $R0 "" done64
|
||||
DetailPrint "Removing previous version (64-bit)..."
|
||||
ExecWait '$R0'
|
||||
|
||||
done64:
|
||||
${EndIf}
|
||||
|
||||
FunctionEnd
|
||||
|
||||
Function PortableModePageCreate
|
||||
|
||||
${If} $ReinstallMode = 1
|
||||
Abort
|
||||
${EndIf}
|
||||
|
||||
Call SetModeDestinationFromInstdir ; If the user clicks BACK on the directory page we will remember their mode specific directory
|
||||
!insertmacro MUI_HEADER_TEXT "Install Mode" "Choose how you want to install Cockatrice."
|
||||
nsDialogs::Create 1018
|
||||
|
|
@ -235,11 +158,6 @@ ${EndIf}
|
|||
FunctionEnd
|
||||
|
||||
Function componentsPagePre
|
||||
|
||||
${If} $ReinstallMode = 1
|
||||
Return
|
||||
${EndIf}
|
||||
|
||||
${If} $PortableMode = 0
|
||||
SetShellVarContext all
|
||||
|
||||
|
|
@ -249,12 +167,8 @@ ${If} $PortableMode = 0
|
|||
ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "UninstallString"
|
||||
StrCmp $R0 "" done32
|
||||
|
||||
${If} $ReinstallMode = 0
|
||||
MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION "A previous version of Cockatrice must be uninstalled before installing the new one." IDOK uninst32
|
||||
Abort
|
||||
${Else}
|
||||
Goto uninst32
|
||||
${EndIf}
|
||||
MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION "A previous version of Cockatrice must be uninstalled before installing the new one." IDOK uninst32
|
||||
Abort
|
||||
|
||||
uninst32:
|
||||
ClearErrors
|
||||
|
|
@ -269,12 +183,8 @@ ${If} $PortableMode = 0
|
|||
ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "UninstallString"
|
||||
StrCmp $R0 "" done64
|
||||
|
||||
${If} $ReinstallMode = 0
|
||||
MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION "A previous version of Cockatrice must be uninstalled before installing the new one." IDOK uninst64
|
||||
Abort
|
||||
${Else}
|
||||
Goto uninst64
|
||||
${EndIf}
|
||||
MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION "A previous version of Cockatrice must be uninstalled before installing the new one." IDOK uninst64
|
||||
Abort
|
||||
|
||||
uninst64:
|
||||
ClearErrors
|
||||
|
|
@ -303,6 +213,7 @@ ${AndIf} ${FileExists} "$INSTDIR\portable.dat"
|
|||
Delete "$INSTDIR\uninstall.exe"
|
||||
Delete "$INSTDIR\cockatrice.exe"
|
||||
Delete "$INSTDIR\oracle.exe"
|
||||
Delete "$INSTDIR\dbconverter.exe"
|
||||
Delete "$INSTDIR\servatrice.exe"
|
||||
Delete "$INSTDIR\Qt*.dll"
|
||||
Delete "$INSTDIR\libmysql.dll"
|
||||
|
|
@ -366,12 +277,6 @@ ${Else}
|
|||
FileWrite $0 "PORTABLE"
|
||||
FileClose $0
|
||||
${EndIf}
|
||||
|
||||
${If} $ReinstallMode = 1
|
||||
IfFileExists "$INSTDIR\cockatrice.exe" 0 +2
|
||||
Exec '"$INSTDIR\cockatrice.exe"'
|
||||
${EndIf}
|
||||
|
||||
SectionEnd
|
||||
|
||||
Section "Start menu item" SecStartMenu
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
string(LENGTH "$ENV{MACOS_CERTIFICATE_NAME}" MACOS_CERTIFICATE_NAME_LEN)
|
||||
|
||||
if(APPLE AND MACOS_CERTIFICATE_NAME_LEN GREATER 0)
|
||||
set(APPLICATIONS "cockatrice" "servatrice" "oracle")
|
||||
set(APPLICATIONS "cockatrice" "servatrice" "oracle" "dbconverter")
|
||||
foreach(app_name IN LISTS APPLICATIONS)
|
||||
set(FULL_APP_PATH "${CPACK_TEMPORARY_INSTALL_DIRECTORY}/${app_name}.app")
|
||||
|
||||
|
|
|
|||
|
|
@ -7,57 +7,74 @@ project(Cockatrice VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${
|
|||
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/client/network/update/client/update_downloader.cpp
|
||||
src/client/network/interfaces/deck_stats_interface.cpp
|
||||
src/client/network/interfaces/tapped_out_interface.cpp
|
||||
src/card/card_info.cpp
|
||||
src/card/exact_card.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/update/client/client_update_checker.cpp
|
||||
src/client/network/update/client/release_channel.cpp
|
||||
src/client/network/update/card_spoiler/spoiler_background_updater.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/settings/cache_settings.cpp
|
||||
src/client/settings/card_counter_settings.cpp
|
||||
src/client/settings/shortcut_treeview.cpp
|
||||
src/client/settings/shortcuts_settings.cpp
|
||||
src/interface/deck_loader/card_node_function.cpp
|
||||
src/interface/deck_loader/deck_file_format.cpp
|
||||
src/interface/deck_loader/deck_loader.cpp
|
||||
src/interface/deck_loader/loaded_deck.cpp
|
||||
src/interface/widgets/dialogs/dlg_connect.cpp
|
||||
src/interface/widgets/dialogs/dlg_convert_deck_to_cod_format.cpp
|
||||
src/interface/widgets/dialogs/dlg_create_game.cpp
|
||||
src/interface/widgets/dialogs/dlg_default_tags_editor.cpp
|
||||
src/interface/widgets/dialogs/dlg_edit_avatar.cpp
|
||||
src/interface/widgets/dialogs/dlg_edit_password.cpp
|
||||
src/interface/widgets/dialogs/dlg_edit_tokens.cpp
|
||||
src/interface/widgets/dialogs/dlg_edit_user.cpp
|
||||
src/interface/widgets/dialogs/dlg_filter_games.cpp
|
||||
src/interface/widgets/dialogs/dlg_forgot_password_challenge.cpp
|
||||
src/interface/widgets/dialogs/dlg_forgot_password_request.cpp
|
||||
src/interface/widgets/dialogs/dlg_forgot_password_reset.cpp
|
||||
src/interface/widgets/dialogs/dlg_load_deck.cpp
|
||||
src/interface/widgets/dialogs/dlg_load_deck_from_clipboard.cpp
|
||||
src/interface/widgets/dialogs/dlg_load_deck_from_website.cpp
|
||||
src/interface/widgets/dialogs/dlg_load_remote_deck.cpp
|
||||
src/interface/widgets/dialogs/dlg_local_game_options.cpp
|
||||
src/interface/widgets/dialogs/dlg_manage_sets.cpp
|
||||
src/interface/widgets/dialogs/dlg_register.cpp
|
||||
src/interface/widgets/dialogs/dlg_select_set_for_cards.cpp
|
||||
src/interface/widgets/dialogs/dlg_settings.cpp
|
||||
src/interface/widgets/dialogs/dlg_startup_card_check.cpp
|
||||
src/interface/widgets/dialogs/dlg_tip_of_the_day.cpp
|
||||
src/interface/widgets/dialogs/dlg_update.cpp
|
||||
src/interface/widgets/dialogs/dlg_view_log.cpp
|
||||
src/interface/widgets/dialogs/override_printing_warning.cpp
|
||||
src/interface/widgets/dialogs/tip_of_the_day.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/deck/custom_line_edit.cpp
|
||||
src/deck/deck_list_model.cpp
|
||||
src/deck/deck_loader.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_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
|
||||
src/dialogs/dlg_edit_user.cpp
|
||||
src/dialogs/dlg_filter_games.cpp
|
||||
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_register.cpp
|
||||
src/dialogs/dlg_select_set_for_cards.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
|
||||
|
|
@ -117,17 +134,9 @@ set(cockatrice_SOURCES
|
|||
src/game/zones/table_zone.cpp
|
||||
src/game/zones/view_zone.cpp
|
||||
src/game/zones/view_zone_widget.cpp
|
||||
src/game_graphics/board/abstract_graphics_item.cpp
|
||||
src/interface/card_picture_loader/card_picture_loader.cpp
|
||||
src/interface/card_picture_loader/card_picture_loader_local.cpp
|
||||
src/interface/card_picture_loader/card_picture_loader_request_status_display_widget.cpp
|
||||
src/interface/card_picture_loader/card_picture_loader_status_bar.cpp
|
||||
src/interface/card_picture_loader/card_picture_loader_worker.cpp
|
||||
src/interface/card_picture_loader/card_picture_loader_worker_work.cpp
|
||||
src/interface/card_picture_loader/card_picture_to_load.cpp
|
||||
src/interface/layouts/flow_layout.cpp
|
||||
src/interface/layouts/overlap_layout.cpp
|
||||
src/interface/widgets/utility/line_edit_completer.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
|
||||
|
|
@ -146,104 +155,47 @@ set(cockatrice_SOURCES
|
|||
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/abstract_analytics_panel_widget.cpp
|
||||
src/interface/widgets/deck_analytics/add_analytics_panel_dialog.cpp
|
||||
src/interface/widgets/deck_analytics/analytics_panel_widget_factory.cpp
|
||||
src/interface/widgets/deck_analytics/analytics_panel_widget_registrar.cpp
|
||||
src/interface/widgets/deck_analytics/deck_analytics_widget.cpp
|
||||
src/interface/widgets/deck_analytics/deck_list_statistics_analyzer.cpp
|
||||
src/interface/widgets/deck_analytics/resizable_panel.cpp
|
||||
src/interface/widgets/deck_analytics/analyzer_modules/draw_probability/draw_probability_config.cpp
|
||||
src/interface/widgets/deck_analytics/analyzer_modules/draw_probability/draw_probability_config_dialog.cpp
|
||||
src/interface/widgets/deck_analytics/analyzer_modules/draw_probability/draw_probability_widget.cpp
|
||||
src/interface/widgets/deck_analytics/analyzer_modules/mana_base/mana_base_config.cpp
|
||||
src/interface/widgets/deck_analytics/analyzer_modules/mana_base/mana_base_config_dialog.cpp
|
||||
src/interface/widgets/deck_analytics/analyzer_modules/mana_base/mana_base_widget.cpp
|
||||
src/interface/widgets/deck_analytics/analyzer_modules/mana_curve/mana_curve_config.cpp
|
||||
src/interface/widgets/deck_analytics/analyzer_modules/mana_curve/mana_curve_config_dialog.cpp
|
||||
src/interface/widgets/deck_analytics/analyzer_modules/mana_curve/mana_curve_widget.cpp
|
||||
src/interface/widgets/deck_analytics/analyzer_modules/mana_devotion/mana_devotion_config.cpp
|
||||
src/interface/widgets/deck_analytics/analyzer_modules/mana_devotion/mana_devotion_config_dialog.cpp
|
||||
src/interface/widgets/deck_analytics/analyzer_modules/mana_devotion/mana_devotion_widget.cpp
|
||||
src/interface/widgets/deck_analytics/analyzer_modules/mana_distribution/mana_distribution_config.cpp
|
||||
src/interface/widgets/deck_analytics/analyzer_modules/mana_distribution/mana_distribution_config_dialog.cpp
|
||||
src/interface/widgets/deck_analytics/analyzer_modules/mana_distribution/mana_distribution_widget.cpp
|
||||
src/interface/widgets/deck_analytics/analyzer_modules/mana_distribution/mana_distribution_single_display_widget.cpp
|
||||
src/interface/widgets/deck_analytics/analyzer_modules/mana_curve/mana_curve_total_widget.cpp
|
||||
src/interface/widgets/deck_analytics/analyzer_modules/mana_curve/mana_curve_category_widget.cpp
|
||||
src/interface/widgets/deck_editor/deck_list_history_manager_widget.cpp
|
||||
src/interface/widgets/deck_editor/deck_editor_card_database_dock_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/deck_editor/deck_list_style_proxy.cpp
|
||||
src/interface/widgets/deck_editor/deck_state_manager.cpp
|
||||
src/interface/widgets/deck_editor/printing_disabled_info_widget.cpp
|
||||
src/interface/widgets/general/background_sources.cpp
|
||||
src/interface/widgets/general/display/background_plate_widget.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/display/charts/bars/bar_widget.cpp
|
||||
src/interface/widgets/general/display/charts/bars/color_bar.cpp
|
||||
src/interface/widgets/general/display/charts/bars/percent_bar_widget.cpp
|
||||
src/interface/widgets/general/display/charts/bars/bar_chart_widget.cpp
|
||||
src/interface/widgets/general/display/charts/bars/bar_chart_background_widget.cpp
|
||||
src/interface/widgets/general/display/charts/bars/segmented_bar_widget.cpp
|
||||
src/interface/widgets/general/display/charts/pies/color_pie.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/menus/deck_editor_menu.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_placeholder_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/replay/replay_manager.cpp
|
||||
src/interface/widgets/replay/replay_timeline_widget.cpp
|
||||
src/interface/widgets/server/chat_view/chat_view.cpp
|
||||
src/interface/widgets/server/game_selector.cpp
|
||||
src/interface/widgets/server/game_selector_quick_filter_toolbar.cpp
|
||||
src/interface/widgets/server/games_model.cpp
|
||||
src/interface/widgets/server/handle_public_servers.cpp
|
||||
src/interface/widgets/server/remote/remote_decklist_tree_widget.cpp
|
||||
src/interface/widgets/server/remote/remote_replay_list_tree_widget.cpp
|
||||
src/interface/widgets/server/user/user_context_menu.cpp
|
||||
src/interface/widgets/server/user/user_info_box.cpp
|
||||
src/interface/widgets/server/user/user_info_connection.cpp
|
||||
src/interface/widgets/server/user/user_list_manager.cpp
|
||||
src/interface/widgets/server/user/user_list_widget.cpp
|
||||
src/interface/widgets/utility/custom_line_edit.cpp
|
||||
src/interface/widgets/utility/get_text_with_max.cpp
|
||||
src/interface/widgets/utility/sequence_edit.cpp
|
||||
src/interface/widgets/utility/visibility_change_listener.cpp
|
||||
src/interface/widgets/utility/visibility_change_listener.h
|
||||
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_filter_toolbar_widget.cpp
|
||||
src/interface/widgets/visual_database_display/visual_database_display_format_legality_filter_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_display_options_widget.cpp
|
||||
src/interface/widgets/visual_deck_editor/visual_deck_editor_placeholder_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
|
||||
|
|
@ -261,70 +213,94 @@ set(cockatrice_SOURCES
|
|||
src/interface/widgets/visual_deck_storage/visual_deck_storage_widget.cpp
|
||||
src/interface/window_main.cpp
|
||||
src/main.cpp
|
||||
src/interface/widgets/tabs/abstract_tab_deck_editor.cpp
|
||||
src/interface/widgets/tabs/api/archidekt/tab_archidekt.cpp
|
||||
src/interface/widgets/tabs/api/archidekt/api_response/archidekt_deck_listing_api_response.cpp
|
||||
src/interface/widgets/tabs/api/archidekt/api_response/archidekt_formats.h
|
||||
src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card.cpp
|
||||
src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card_entry.cpp
|
||||
src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_edition.cpp
|
||||
src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck.cpp
|
||||
src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck_category.cpp
|
||||
src/interface/widgets/tabs/api/archidekt/api_response/deck_listings/archidekt_api_response_deck_listing_container.cpp
|
||||
src/interface/widgets/tabs/api/archidekt/api_response/deck_listings/archidekt_api_response_deck_owner.cpp
|
||||
src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_display_widget.cpp
|
||||
src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_entry_display_widget.cpp
|
||||
src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_listings_display_widget.cpp
|
||||
src/interface/widgets/tabs/api/archidekt/display/archidekt_deck_preview_image_display_widget.cpp
|
||||
src/interface/widgets/tabs/api/edhrec/api_response/archidekt_links/edhrec_api_response_archidekt_links.cpp
|
||||
src/interface/widgets/tabs/api/edhrec/api_response/average_deck/edhrec_average_deck_api_response.cpp
|
||||
src/interface/widgets/tabs/api/edhrec/api_response/average_deck/edhrec_deck_api_response.cpp
|
||||
src/interface/widgets/tabs/api/edhrec/api_response/card_prices/edhrec_api_response_card_prices.cpp
|
||||
src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_container.cpp
|
||||
src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_details.cpp
|
||||
src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_list.cpp
|
||||
src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_commander_api_response_commander_details.cpp
|
||||
src/interface/widgets/tabs/api/edhrec/api_response/commander/edhrec_commander_api_response.cpp
|
||||
src/interface/widgets/tabs/api/edhrec/api_response/commander/edhrec_commander_api_response_average_deck_statistics.cpp
|
||||
src/interface/widgets/tabs/api/edhrec/api_response/top_cards/edhrec_top_cards_api_response.cpp
|
||||
src/interface/widgets/tabs/api/edhrec/api_response/top_commanders/edhrec_top_commanders_api_response.cpp
|
||||
src/interface/widgets/tabs/api/edhrec/api_response/top_tags/edhrec_top_tags_api_response.cpp
|
||||
src/interface/widgets/tabs/api/edhrec/display/card_prices/edhrec_api_response_card_prices_display_widget.cpp
|
||||
src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_details_display_widget.cpp
|
||||
src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_inclusion_display_widget.cpp
|
||||
src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_list_display_widget.cpp
|
||||
src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_synergy_display_widget.cpp
|
||||
src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_api_response_commander_details_display_widget.cpp
|
||||
src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_display_widget.cpp
|
||||
src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_navigation_widget.cpp
|
||||
src/interface/widgets/tabs/api/edhrec/display/top_cards/edhrec_top_cards_api_response_display_widget.cpp
|
||||
src/interface/widgets/tabs/api/edhrec/display/top_commander/edhrec_top_commanders_api_response_display_widget.cpp
|
||||
src/interface/widgets/tabs/api/edhrec/display/top_tags/edhrec_top_tags_api_response_display_widget.cpp
|
||||
src/interface/widgets/tabs/api/edhrec/tab_edhrec.cpp
|
||||
src/interface/widgets/tabs/api/edhrec/tab_edhrec_main.cpp
|
||||
src/interface/widgets/tabs/tab.cpp
|
||||
src/interface/widgets/tabs/tab_account.cpp
|
||||
src/interface/widgets/tabs/tab_admin.cpp
|
||||
src/interface/widgets/tabs/tab_deck_editor.cpp
|
||||
src/interface/widgets/tabs/tab_deck_storage.cpp
|
||||
src/interface/widgets/tabs/tab_game.cpp
|
||||
src/interface/widgets/tabs/tab_home.cpp
|
||||
src/interface/widgets/tabs/tab_logs.cpp
|
||||
src/interface/widgets/tabs/tab_message.cpp
|
||||
src/interface/widgets/tabs/tab_replays.cpp
|
||||
src/interface/widgets/tabs/tab_room.cpp
|
||||
src/interface/widgets/tabs/tab_server.cpp
|
||||
src/interface/widgets/tabs/tab_supervisor.cpp
|
||||
src/interface/widgets/tabs/tab_visual_database_display.cpp
|
||||
src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual.cpp
|
||||
src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.cpp
|
||||
src/interface/widgets/tabs/visual_deck_storage/tab_deck_storage_visual.cpp
|
||||
src/interface/key_signals.cpp
|
||||
src/interface/logger.cpp
|
||||
src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_bracket_navigation_widget.cpp
|
||||
src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_bracket_navigation_widget.h
|
||||
src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_budget_navigation_widget.cpp
|
||||
src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_budget_navigation_widget.h
|
||||
src/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/server/local_client.cpp
|
||||
src/server/local_server.cpp
|
||||
src/server/local_server_interface.cpp
|
||||
src/server/pending_command.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/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
|
||||
src/settings/message_settings.cpp
|
||||
src/settings/recents_settings.cpp
|
||||
src/settings/servers_settings.cpp
|
||||
src/settings/settings_manager.cpp
|
||||
src/settings/shortcut_treeview.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
|
||||
)
|
||||
|
||||
add_subdirectory(sounds)
|
||||
|
|
@ -336,23 +312,15 @@ configure_file(
|
|||
set(cockatrice_RESOURCES cockatrice.qrc)
|
||||
|
||||
if(UPDATE_TRANSLATIONS)
|
||||
# Cockatrice main sources
|
||||
file(GLOB_RECURSE translate_cockatrice_SRCS ${CMAKE_SOURCE_DIR}/cockatrice/src/*.cpp
|
||||
${CMAKE_SOURCE_DIR}/cockatrice/src/*.h
|
||||
)
|
||||
|
||||
# All libcockatrice_* libraries (recursively)
|
||||
file(GLOB_RECURSE translate_lib_SRCS ${CMAKE_SOURCE_DIR}/libcockatrice_*/**/*.cpp
|
||||
${CMAKE_SOURCE_DIR}/libcockatrice_*/**/*.h
|
||||
)
|
||||
|
||||
# Combine all sources for translation
|
||||
set(translate_SRCS ${translate_cockatrice_SRCS} ${translate_lib_SRCS})
|
||||
|
||||
file(GLOB_RECURSE translate_common_SRCS ${CMAKE_SOURCE_DIR}/common/*.cpp ${CMAKE_SOURCE_DIR}/common/*.h)
|
||||
set(translate_SRCS ${translate_cockatrice_SRCS} ${translate_common_SRCS})
|
||||
set(cockatrice_TS "${CMAKE_CURRENT_SOURCE_DIR}/cockatrice_en@source.ts")
|
||||
else()
|
||||
file(GLOB cockatrice_TS "${CMAKE_CURRENT_SOURCE_DIR}/translations/*.ts")
|
||||
endif()
|
||||
endif(UPDATE_TRANSLATIONS)
|
||||
|
||||
if(WIN32)
|
||||
set(cockatrice_SOURCES ${cockatrice_SOURCES} cockatrice.rc)
|
||||
|
|
@ -382,6 +350,12 @@ set(DESKTOPDIR
|
|||
CACHE STRING "desktop file destination"
|
||||
)
|
||||
|
||||
# Include directories
|
||||
include_directories(../common)
|
||||
include_directories(${PROTOBUF_INCLUDE_DIR})
|
||||
include_directories(${CMAKE_BINARY_DIR}/common)
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
set(COCKATRICE_MAC_QM_INSTALL_DIR "cockatrice.app/Contents/Resources/translations")
|
||||
set(COCKATRICE_UNIX_QM_INSTALL_DIR "share/cockatrice/translations")
|
||||
set(COCKATRICE_WIN32_QM_INSTALL_DIR "translations")
|
||||
|
|
@ -421,31 +395,9 @@ elseif(Qt5_FOUND)
|
|||
endif()
|
||||
|
||||
if(Qt5_FOUND)
|
||||
target_link_libraries(
|
||||
cockatrice
|
||||
libcockatrice_card
|
||||
libcockatrice_deck_list
|
||||
libcockatrice_filters
|
||||
libcockatrice_utility
|
||||
libcockatrice_network
|
||||
libcockatrice_models
|
||||
libcockatrice_rng
|
||||
libcockatrice_settings
|
||||
${COCKATRICE_QT_MODULES}
|
||||
)
|
||||
target_link_libraries(cockatrice cockatrice_common ${COCKATRICE_QT_MODULES})
|
||||
else()
|
||||
target_link_libraries(
|
||||
cockatrice
|
||||
PUBLIC libcockatrice_card
|
||||
libcockatrice_deck_list
|
||||
libcockatrice_filters
|
||||
libcockatrice_utility
|
||||
libcockatrice_network
|
||||
libcockatrice_models
|
||||
libcockatrice_rng
|
||||
libcockatrice_settings
|
||||
${COCKATRICE_QT_MODULES}
|
||||
)
|
||||
target_link_libraries(cockatrice PUBLIC cockatrice_common ${COCKATRICE_QT_MODULES})
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
|
|
@ -564,9 +516,6 @@ if(WIN32)
|
|||
PATTERN "styles/qopensslbackend.dll"
|
||||
PATTERN "styles/qschannelbackend.dll"
|
||||
PATTERN "styles/qwindowsvistastyle.dll"
|
||||
PATTERN "styles/qwindows11style.dll"
|
||||
PATTERN "styles/qmodernwindowsstyle.dll"
|
||||
PATTERN "styles/qmodernwindowsstyled.dll"
|
||||
PATTERN "tls/qcertonlybackend.dll"
|
||||
PATTERN "tls/qopensslbackend.dll"
|
||||
PATTERN "tls/qschannelbackend.dll"
|
||||
|
|
|
|||
|
|
@ -7,46 +7,33 @@
|
|||
|
||||
<file>resources/icons/arrow_bottom_green.svg</file>
|
||||
<file>resources/icons/arrow_down_green.svg</file>
|
||||
<file>resources/icons/arrow_history.svg</file>
|
||||
<file>resources/icons/arrow_left_green.svg</file>
|
||||
<file>resources/icons/arrow_redo.svg</file>
|
||||
<file>resources/icons/arrow_right_blue.svg</file>
|
||||
<file>resources/icons/arrow_right_green.svg</file>
|
||||
<file>resources/icons/arrow_top_green.svg</file>
|
||||
<file>resources/icons/arrow_up_green.svg</file>
|
||||
<file>resources/icons/arrow_undo.svg</file>
|
||||
<file>resources/icons/circle_half_stroke.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/dragon.svg</file>
|
||||
<file>resources/icons/dropdown_collapsed.svg</file>
|
||||
<file>resources/icons/dropdown_expanded.svg</file>
|
||||
<file>resources/icons/filter.svg</file>
|
||||
<file>resources/icons/floppy_disk.svg</file>
|
||||
<file>resources/icons/forgot_password.svg</file>
|
||||
<file>resources/icons/gear.svg</file>
|
||||
<file>resources/icons/increment.svg</file>
|
||||
<file>resources/icons/info.svg</file>
|
||||
<file>resources/icons/lock.svg</file>
|
||||
<file>resources/icons/not_ready_start.svg</file>
|
||||
<file>resources/icons/pen_to_square.svg</file>
|
||||
<file>resources/icons/pencil.svg</file>
|
||||
<file>resources/icons/pin.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/scale_balanced.svg</file>
|
||||
<file>resources/icons/scales.svg</file>
|
||||
<file>resources/icons/scroll.svg</file>
|
||||
<file>resources/icons/search.svg</file>
|
||||
<file>resources/icons/settings.svg</file>
|
||||
<file>resources/icons/share.svg</file>
|
||||
<file>resources/icons/sort_arrow_down.svg</file>
|
||||
<file>resources/icons/spectator.svg</file>
|
||||
<file>resources/icons/swap.svg</file>
|
||||
<file>resources/icons/sync.svg</file>
|
||||
|
|
@ -61,8 +48,6 @@
|
|||
<file>resources/icons/mana/W.svg</file>
|
||||
|
||||
<file>resources/backgrounds/home.png</file>
|
||||
<file>resources/backgrounds/card_triplet.svg</file>
|
||||
<file>resources/backgrounds/placeholder_printing_selector.svg</file>
|
||||
|
||||
<file>resources/config/general.svg</file>
|
||||
<file>resources/config/appearance.svg</file>
|
||||
|
|
|
|||
|
|
@ -1,31 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
version="1.1"
|
||||
width="250"
|
||||
id="svg13"
|
||||
height="231.66667"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs13" />
|
||||
<g
|
||||
transform="matrix(1.705559,0,0,1.705559,-18.310328,-4.2419088)"
|
||||
id="g13">
|
||||
<path
|
||||
d="M 90.069854,3.479957 C 89.356513,1.2235709 86.980392,-0.01102897 84.723451,0.70218215 L 3.4767601,26.377781 C 1.2199188,27.090982 -0.01486587,29.46663 0.69839437,31.723116 L 33.512365,135.52112 c 0.713341,2.25639 3.089462,3.49099 5.346403,2.77777 l 81.246672,-25.6756 c 2.25684,-0.71319 3.49163,-3.08884 2.77837,-5.34533 L 90.074852,3.479957 Z"
|
||||
style="display:none;fill:#c0c0c0;fill-opacity:1;stroke:#989898;stroke-width:1;stroke-opacity:1"
|
||||
id="path1" />
|
||||
<path
|
||||
d="m 110.61293,7.4983294 c -0.36657,-2.337853 -2.53055,-3.9150142 -4.86886,-3.5484627 L 21.563382,17.14452 c -2.338314,0.366502 -3.915784,2.529976 -3.549207,4.867929 L 34.876507,129.55893 c 0.366577,2.33786 2.530549,3.91502 4.868863,3.54847 l 84.18069,-13.19466 c 2.33831,-0.3665 3.91578,-2.52997 3.5492,-4.86793 L 110.61093,7.4983294 Z"
|
||||
style="fill:#c0c0c0;fill-opacity:1;stroke:#989898;stroke-width:1;stroke-opacity:1"
|
||||
id="path4" />
|
||||
<path
|
||||
d="m 130.53623,15.555064 c 0,-2.366441 -1.89356,-4.259575 -4.26046,-4.259575 H 41.067426 c -2.366905,0 -4.260468,1.893134 -4.260468,4.259575 V 124.41102 c 0,2.36644 1.893563,4.25957 4.260468,4.25957 h 85.208344 c 2.3669,0 4.26046,-1.89313 4.26046,-4.25957 z"
|
||||
style="fill:#c0c0c0;fill-opacity:1;stroke:#989898;stroke-width:1;stroke-opacity:1"
|
||||
id="path7" />
|
||||
<path
|
||||
d="m 149.43988,26.480639 c 0.38018,-2.335754 -1.1846,-4.508374 -3.52082,-4.88852 L 61.817351,7.9076636 C 59.481136,7.5275576 57.308066,9.0920839 56.927894,11.427736 L 39.439773,118.87426 c -0.380182,2.33576 1.184602,4.50838 3.520816,4.88852 l 84.102711,13.68346 c 2.33622,0.38011 4.50929,-1.18442 4.88946,-3.52007 L 149.43688,26.479639 Z"
|
||||
style="display:inline;fill:#c0c0c0;fill-opacity:1;stroke:#989898;stroke-width:1;stroke-opacity:1"
|
||||
id="path10" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.1 KiB |
|
|
@ -1,29 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!--!Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2026 Fonticons, Inc.-->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
width="172.65051"
|
||||
id="svg13"
|
||||
height="213.30714"
|
||||
xml:space="preserve"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"><defs
|
||||
id="defs13" /><g
|
||||
transform="matrix(1.705559,0,0,1.705559,-97.653345,-68.741256)"
|
||||
id="g13"><path
|
||||
d="m 151.48519,45.063813 c 0,-2.366441 -1.89356,-4.259575 -4.26046,-4.259575 H 62.016385 c -2.366905,0 -4.260468,1.893134 -4.260468,4.259575 V 153.91977 c 0,2.36644 1.893563,4.25957 4.260468,4.25957 h 85.208345 c 2.3669,0 4.26046,-1.89313 4.26046,-4.25957 z"
|
||||
style="fill:#c0c0c0;fill-opacity:1;stroke:#989898;stroke-width:1;stroke-opacity:1"
|
||||
id="path7" /><path
|
||||
d="m 154.70135,48.441704 c 0,-2.366441 -1.89356,-4.259575 -4.26046,-4.259575 H 65.232545 c -2.366905,0 -4.260468,1.893134 -4.260468,4.259575 V 157.29767 c 0,2.36644 1.893563,4.25957 4.260468,4.25957 h 85.208345 c 2.3669,0 4.26046,-1.89313 4.26046,-4.25957 z"
|
||||
style="fill:#c0c0c0;fill-opacity:1;stroke:#989898;stroke-width:1;stroke-opacity:1"
|
||||
id="path7-5" /><path
|
||||
d="m 157.98403,51.75453 c 0,-2.366441 -1.89356,-4.259575 -4.26046,-4.259575 H 68.515228 c -2.366905,0 -4.260468,1.893134 -4.260468,4.259575 v 108.85596 c 0,2.36644 1.893563,4.25957 4.260468,4.25957 h 85.208342 c 2.3669,0 4.26046,-1.89313 4.26046,-4.25957 z"
|
||||
style="fill:#c0c0c0;fill-opacity:1;stroke:#989898;stroke-width:1;stroke-opacity:1"
|
||||
id="path7-6" /></g><path
|
||||
d="m 196.24576,207.42361 c 0,0.11213 0,0.22413 0,0.33621 -0.0498,4.54511 -4.18399,7.63329 -8.72909,7.63329 h -12.19086 c -3.29988,0 -5.97713,2.67727 -5.97713,5.97712 0,0.4234 0.0498,0.83433 0.12449,1.23279 0.26149,1.27014 0.80939,2.49046 1.34485,3.72325 0.75959,1.71843 1.50674,3.4244 1.50674,5.22998 0,3.95986 -2.68971,7.55859 -6.64956,7.72046 -0.43583,0.0128 -0.87166,0.025 -1.31995,0.025 -17.60761,0 -31.878,-14.27038 -31.878,-31.878 0,-17.60761 14.28284,-31.878 31.89046,-31.878 17.60762,0 31.87801,14.27039 31.87801,31.878 z m -47.81703,3.98475 c 0,-2.20407 -1.78067,-3.98475 -3.98473,-3.98475 -2.20407,0 -3.98477,1.78068 -3.98477,3.98475 0,2.20406 1.7807,3.98475 3.98477,3.98475 2.20406,0 3.98473,-1.78069 3.98473,-3.98475 z m 0,-11.95426 c 2.20407,0 3.98477,-1.78068 3.98477,-3.98475 0,-2.20407 -1.7807,-3.98475 -3.98477,-3.98475 -2.20405,0 -3.98473,1.78068 -3.98473,3.98475 0,2.20407 1.78068,3.98475 3.98473,3.98475 z m 19.92376,-11.95424 c 0,-2.20408 -1.78068,-3.98477 -3.98473,-3.98477 -2.20407,0 -3.98477,1.78069 -3.98477,3.98477 0,2.20405 1.7807,3.98474 3.98477,3.98474 2.20405,0 3.98473,-1.78069 3.98473,-3.98474 z m 11.95426,11.95424 c 2.20407,0 3.98475,-1.78068 3.98475,-3.98475 0,-2.20407 -1.78068,-3.98475 -3.98475,-3.98475 -2.20406,0 -3.98475,1.78068 -3.98475,3.98475 0,2.20407 1.78069,3.98475 3.98475,3.98475 z"
|
||||
id="path1"
|
||||
style="display:none;fill:#3b3b3b;fill-opacity:1;stroke:#000000;stroke-width:2.53798;stroke-dasharray:none;stroke-opacity:1" /><path
|
||||
d="M 126.20915,54.574783 82.324247,83.8512 c -5.76807,3.845383 -9.435059,10.089163 -10.029703,16.90777 12.348823,2.53716 22.081191,12.26955 24.638191,24.63819 6.838435,-0.59465 13.062395,-4.26163 16.907775,-10.0297 l 29.2566,-43.904722 c 1.32804,-2.001984 2.04162,-4.340923 2.04162,-6.75915 0,-6.719506 -5.45092,-12.170428 -12.17043,-12.170428 -2.3984,0 -4.75718,0.713573 -6.75915,2.041623 z M 88.052677,131.81933 c 0,-12.26953 -9.930593,-22.20012 -22.200138,-22.20012 -12.269532,0 -22.200126,9.93059 -22.200126,22.20012 0,0.77305 0.03966,1.54609 0.118929,2.2993 0.356787,3.46877 -2.021792,7.21505 -5.510393,7.21505 h -0.951431 c -3.508409,0 -6.342895,2.83447 -6.342895,6.3429 0,3.5084 2.834486,6.34289 6.342895,6.34289 h 28.543021 c 12.269545,0 22.200138,-9.93059 22.200138,-22.20014 z"
|
||||
id="path1-2"
|
||||
style="fill:#989898;fill-opacity:1;stroke-width:0.198215" /></svg>
|
||||
|
Before Width: | Height: | Size: 3.9 KiB |
|
|
@ -1,10 +1,6 @@
|
|||
[Rules]
|
||||
# The default log level is info
|
||||
*.debug = false
|
||||
#*.info = true
|
||||
#*.warning = true
|
||||
#*.critical = true
|
||||
#*.fatal = true
|
||||
|
||||
# Uncomment a rule to see debug level logs for that category,
|
||||
# or set <category> = false to disable logging
|
||||
|
|
@ -41,14 +37,12 @@
|
|||
#card_zone = true
|
||||
#view_zone = true
|
||||
|
||||
#game_event_handler = true
|
||||
|
||||
#user_info_connection = true
|
||||
|
||||
#card_picture_loader = true
|
||||
#card_picture_loader.worker = true
|
||||
#card_picture_loader.card_back_cache_fail = true
|
||||
#card_picture_loader.picture_to_load = true
|
||||
#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
|
||||
|
|
|
|||
|
|
@ -1,13 +1,9 @@
|
|||
@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>
|
||||
|
|
@ -17,23 +13,15 @@ searches are case insensitive.
|
|||
<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 <u>N</u>ame:</dt>
|
||||
<dd>[fn:aggro](#fn:aggro) <small>(Any deck with a filename containing the word aggro)</small></dd>
|
||||
<dd>[fn:red fn:deck fn:wins](#fn:red fn:deck fn:wins) <small>(Any deck with a filename containing the words red, deck, and wins)</small></dd>
|
||||
<dd>[fn:"red deck wins"](#fn:%22red deck wins%22) <small>(Any deck with a filename 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><u>F</u>ormat:</dt>
|
||||
<dd>[f:standard](#f:standard) <small>(Any deck with format set to standard)</small></dd>
|
||||
|
||||
<dt><u>C</u>omments:</dt>
|
||||
<dd>[c:good](#c:good) <small>(Any deck with comments containing the word good)</small></dd>
|
||||
<dd>[c:good c:deck](#c:good c:deck) <small>(Any deck with comments containing the words good and deck)</small></dd>
|
||||
<dd>[c:"good deck"](#c:%22good deck%22) <small>(Any deck with comments containing the exact phrase "good deck")</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>
|
||||
|
|
@ -47,6 +35,6 @@ searches are case insensitive.
|
|||
<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>
|
||||
<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>
|
||||
</dl>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,8 @@
|
|||
@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>
|
||||
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>Name:</dt>
|
||||
<dd>[birds of paradise](#birds of paradise) <small>(Any card name containing the words birds, of, and paradise)</small></dd>
|
||||
<dd>["birds of paradise"](#%22birds of paradise%22) <small>(Any card name containing the exact phrase "birds of paradise")</small></dd>
|
||||
|
|
@ -51,20 +47,20 @@ In this list of examples below, each entry has an explanation and can be clicked
|
|||
|
||||
<dt><u>E</u>dition:</dt>
|
||||
<dd>[set:lea](#set:lea) <small>(Cards that appear in Alpha, which has the set code LEA)</small></dd>
|
||||
<dd>[e:lea OR e:leb](#e:lea OR e:leb) <small>(Cards that appear in Alpha or Beta)</small></dd>
|
||||
<dd>[e:lea or e:leb](#e:lea or e:leb) <small>(Cards that appear in Alpha or Beta)</small></dd>
|
||||
|
||||
<dt>Negate:</dt>
|
||||
<dd>[c:wu -c:m](#c:wu -c:m) <small>(Any card that is white or blue, but not multicolored)</small></dd>
|
||||
|
||||
<dt>Branching:</dt>
|
||||
<dd>[t:sliver OR o:changeling](#t:sliver OR o:changeling) <small>(Any card that is either a sliver or has changeling)</small></dd>
|
||||
<dd>[t:sliver or o:changeling](#t:sliver or o:changeling) <small>(Any card that is either a sliver or has changeling)</small></dd>
|
||||
|
||||
<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>
|
||||
<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>
|
||||
</dl>
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
|
||||
<title>
|
||||
history
|
||||
</title>
|
||||
<path d="M9 6v5h.06l2.48 2.47 1.41-1.41L11 10.11V6H9z"/>
|
||||
<path d="M10 1a9 9 0 0 0-7.85 13.35L.5 16H6v-5.5l-2.38 2.38A7 7 0 1 1 10 17v2a9 9 0 0 0 0-18z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 332 B |
|
|
@ -1,40 +0,0 @@
|
|||
<?xml version="1.0" encoding="windows-1252"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" x="0px"
|
||||
y="0px" width="485.212px" height="485.212px" viewBox="0 0 485.212 485.212"
|
||||
style="enable-background:new 0 0 485.212 485.212;" xml:space="preserve">
|
||||
<g>
|
||||
<path d="M242.607,424.559c-75.252,0-136.468-61.209-136.468-136.465c0-75.252,61.216-136.466,136.468-136.466v90.978 l151.629-121.302L242.607,0v90.978c-108.687,0-197.117,88.432-197.117,197.117c0,108.691,88.43,197.118,197.117,197.118 c108.687,0,197.114-88.427,197.114-197.118h-60.645C379.077,363.35,317.859,424.559,242.607,424.559z"/>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1,018 B |
|
|
@ -1,40 +0,0 @@
|
|||
<?xml version="1.0" encoding="windows-1252"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" x="0px"
|
||||
y="0px" width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;"
|
||||
xml:space="preserve">
|
||||
<g>
|
||||
<path d="M256,448c79.406,0,144-64.594,144-144s-64.594-144-144-144v96L96,128L256,0v96c114.688,0,208,93.313,208,208 c0,114.688-93.312,208-208,208c-114.687,0-208-93.312-208-208h64C112,383.406,176.594,448,256,448z"/>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 874 B |
|
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2026 Fonticons, Inc.--><path d="M512 320C512 214 426 128 320 128L320 512C426 512 512 426 512 320zM64 320C64 178.6 178.6 64 320 64C461.4 64 576 178.6 576 320C576 461.4 461.4 576 320 576C178.6 576 64 461.4 64 320z"/></svg>
|
||||
|
Before Width: | Height: | Size: 410 B |
|
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2026 Fonticons, Inc.--><path d="M352 188.5L300.1 175.5C293.6 173.9 288.8 168.4 288.1 161.7C287.4 155 290.9 148.6 296.8 145.6L337.6 125.2L294.3 92.7C288.8 88.6 286.5 81.4 288.7 74.8C290.9 68.2 297.1 64 304 64L464 64C494.2 64 522.7 78.2 540.8 102.4L598.4 179.2C604.6 187.5 608 197.6 608 208C608 234.5 586.5 256 560 256L538.5 256C521.5 256 505.2 249.3 493.2 237.3L479.9 224L447.9 224L447.9 245.5C447.9 270.3 460.7 293.4 481.7 306.6L588.3 373.2C620.4 393.3 639.9 428.4 639.9 466.3C639.9 526.9 590.8 576.1 530.1 576.1L32.3 576C29 576 25.7 575.6 22.7 574.6C13.5 571.8 6 565 2.3 556C1 552.7 .1 549.1 0 545.3C-.2 541.6 .3 538 1.3 534.6C4.1 525.4 10.9 517.9 19.9 514.2C22.9 513 26.1 512.2 29.4 512L433.3 476C441.6 475.3 448 468.3 448 459.9C448 455.6 446.3 451.5 443.3 448.5L398.9 404.1C368.9 374.1 352 333.4 352 291L352 188.5zM512 136.3C512 136.2 512 136.1 512 136C512 135.9 512 135.8 512 135.7L512 136.3zM510.7 143.7L464.3 132.1C464.1 133.4 464 134.7 464 136C464 149.3 474.7 160 488 160C498.6 160 507.5 153.2 510.7 143.7zM130.9 180.5C147.2 166 171.3 164.3 189.4 176.4L320 263.4L320 290.9C320 323.7 328.4 355.7 344 383.9L112 383.9C105.3 383.9 99.3 379.7 97 373.5C94.7 367.3 96.5 360.2 101.6 355.8L171 296.3L18.4 319.8C11.4 320.9 4.5 317.2 1.5 310.8C-1.5 304.4 .1 296.8 5.4 292L130.9 180.5z"/></svg>
|
||||
|
Before Width: | Height: | Size: 1.4 KiB |
|
|
@ -1,12 +0,0 @@
|
|||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg fill="#000000" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg"
|
||||
width="800px" height="800px" viewBox="0 0 971.986 971.986"
|
||||
xml:space="preserve">
|
||||
<g>
|
||||
<path d="M370.216,459.3c10.2,11.1,15.8,25.6,15.8,40.6v442c0,26.601,32.1,40.101,51.1,21.4l123.3-141.3
|
||||
c16.5-19.8,25.6-29.601,25.6-49.2V500c0-15,5.7-29.5,15.8-40.601L955.615,75.5c26.5-28.8,6.101-75.5-33.1-75.5h-873
|
||||
c-39.2,0-59.7,46.6-33.1,75.5L370.216,459.3z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 676 B |
|
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2026 Fonticons, Inc.--><path d="M160 96C124.7 96 96 124.7 96 160L96 480C96 515.3 124.7 544 160 544L480 544C515.3 544 544 515.3 544 480L544 237.3C544 220.3 537.3 204 525.3 192L448 114.7C436 102.7 419.7 96 402.7 96L160 96zM192 192C192 174.3 206.3 160 224 160L384 160C401.7 160 416 174.3 416 192L416 256C416 273.7 401.7 288 384 288L224 288C206.3 288 192 273.7 192 256L192 192zM320 352C355.3 352 384 380.7 384 416C384 451.3 355.3 480 320 480C284.7 480 256 451.3 256 416C256 380.7 284.7 352 320 352z"/></svg>
|
||||
|
Before Width: | Height: | Size: 693 B |
|
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2026 Fonticons, Inc.--><path d="M259.1 73.5C262.1 58.7 275.2 48 290.4 48L350.2 48C365.4 48 378.5 58.7 381.5 73.5L396 143.5C410.1 149.5 423.3 157.2 435.3 166.3L503.1 143.8C517.5 139 533.3 145 540.9 158.2L570.8 210C578.4 223.2 575.7 239.8 564.3 249.9L511 297.3C511.9 304.7 512.3 312.3 512.3 320C512.3 327.7 511.8 335.3 511 342.7L564.4 390.2C575.8 400.3 578.4 417 570.9 430.1L541 481.9C533.4 495 517.6 501.1 503.2 496.3L435.4 473.8C423.3 482.9 410.1 490.5 396.1 496.6L381.7 566.5C378.6 581.4 365.5 592 350.4 592L290.6 592C275.4 592 262.3 581.3 259.3 566.5L244.9 496.6C230.8 490.6 217.7 482.9 205.6 473.8L137.5 496.3C123.1 501.1 107.3 495.1 99.7 481.9L69.8 430.1C62.2 416.9 64.9 400.3 76.3 390.2L129.7 342.7C128.8 335.3 128.4 327.7 128.4 320C128.4 312.3 128.9 304.7 129.7 297.3L76.3 249.8C64.9 239.7 62.3 223 69.8 209.9L99.7 158.1C107.3 144.9 123.1 138.9 137.5 143.7L205.3 166.2C217.4 157.1 230.6 149.5 244.6 143.4L259.1 73.5zM320.3 400C364.5 399.8 400.2 363.9 400 319.7C399.8 275.5 363.9 239.8 319.7 240C275.5 240.2 239.8 276.1 240 320.3C240.2 364.5 276.1 400.2 320.3 400z"/></svg>
|
||||
|
Before Width: | Height: | Size: 1.2 KiB |
|
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2026 Fonticons, Inc.--><path d="M535.6 85.7C513.7 63.8 478.3 63.8 456.4 85.7L432 110.1L529.9 208L554.3 183.6C576.2 161.7 576.2 126.3 554.3 104.4L535.6 85.7zM236.4 305.7C230.3 311.8 225.6 319.3 222.9 327.6L193.3 416.4C190.4 425 192.7 434.5 199.1 441C205.5 447.5 215 449.7 223.7 446.8L312.5 417.2C320.7 414.5 328.2 409.8 334.4 403.7L496 241.9L398.1 144L236.4 305.7zM160 128C107 128 64 171 64 224L64 480C64 533 107 576 160 576L416 576C469 576 512 533 512 480L512 384C512 366.3 497.7 352 480 352C462.3 352 448 366.3 448 384L448 480C448 497.7 433.7 512 416 512L160 512C142.3 512 128 497.7 128 480L128 224C128 206.3 142.3 192 160 192L256 192C273.7 192 288 177.7 288 160C288 142.3 273.7 128 256 128L160 128z"/></svg>
|
||||
|
Before Width: | Height: | Size: 899 B |
|
|
@ -1,24 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="64" height="64">
|
||||
<g transform="matrix(0 1 -1 0 99.465813 0)" opacity="0.7">
|
||||
<path fill="#000000" fill-rule="evenodd" clip-rule="evenodd"
|
||||
stroke="#ffffff"
|
||||
stroke-width="4"
|
||||
stroke-linejoin="round"
|
||||
stroke-linecap="round"
|
||||
d="M65.5 62
|
||||
L78 49
|
||||
C73.5 44.5 69.5 42 63 44
|
||||
L45 31 C47 25 46 22 41.5 18
|
||||
L19 41.5
|
||||
C23 45.5 25 46.5 31 45
|
||||
L44 62.5
|
||||
C42.3 69 45 73.5 49 78
|
||||
L61.5 65.5
|
||||
L84 87
|
||||
L87 87
|
||||
L87.5 86.5
|
||||
L87.5 83.5 Z" />
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 736 B |
|
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2026 Fonticons, Inc.--><path d="M384 96L512 96C529.7 96 544 110.3 544 128C544 145.7 529.7 160 512 160L398.4 160C393.2 185.8 375.5 207.1 352 217.3L352 512L512 512C529.7 512 544 526.3 544 544C544 561.7 529.7 576 512 576L128 576C110.3 576 96 561.7 96 544C96 526.3 110.3 512 128 512L288 512L288 217.3C264.5 207 246.8 185.7 241.6 160L128 160C110.3 160 96 145.7 96 128C96 110.3 110.3 96 128 96L256 96C270.6 76.6 293.8 64 320 64C346.2 64 369.4 76.6 384 96zM439.6 384L584.4 384L512 259.8L439.6 384zM512 480C449.1 480 396.8 446 386 401.1C383.4 390.1 387 378.8 392.7 369L487.9 205.8C492.9 197.2 502.1 192 512 192C521.9 192 531.1 197.3 536.1 205.8L631.3 369C637 378.8 640.6 390.1 638 401.1C627.2 445.9 574.9 480 512 480zM126.8 259.8L54.4 384L199.3 384L126.8 259.8zM.9 401.1C-1.7 390.1 1.9 378.8 7.6 369L102.8 205.8C107.8 197.2 117 192 126.9 192C136.8 192 146 197.3 151 205.8L246.2 369C251.9 378.8 255.5 390.1 252.9 401.1C242.1 445.9 189.8 480 126.9 480C64 480 11.7 446 .9 401.1z"/></svg>
|
||||
|
Before Width: | Height: | Size: 1.1 KiB |
|
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2026 Fonticons, Inc.--><path d="M32 176C32 134.5 63.6 100.4 104 96.4L104 96L384 96C437 96 480 139 480 192L480 368L304 368C264.2 368 232 400.2 232 440L232 500C232 524.3 212.3 544 188 544C163.7 544 144 524.3 144 500L144 272L80 272C53.5 272 32 250.5 32 224L32 176zM268.8 544C275.9 530.9 280 515.9 280 500L280 440C280 426.7 290.7 416 304 416L552 416C565.3 416 576 426.7 576 440L576 464C576 508.2 540.2 544 496 544L268.8 544zM112 144C94.3 144 80 158.3 80 176L80 224L144 224L144 176C144 158.3 129.7 144 112 144z"/></svg>
|
||||
|
Before Width: | Height: | Size: 704 B |
|
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2026 Fonticons, Inc.--><path d="M278.6 438.6L182.6 534.6C170.1 547.1 149.8 547.1 137.3 534.6L41.3 438.6C28.8 426.1 28.8 405.8 41.3 393.3C53.8 380.8 74.1 380.8 86.6 393.3L128 434.7L128 128C128 110.3 142.3 96 160 96C177.7 96 192 110.3 192 128L192 434.7L233.4 393.3C245.9 380.8 266.2 380.8 278.7 393.3C291.2 405.8 291.2 426.1 278.7 438.6zM352 544C334.3 544 320 529.7 320 512C320 494.3 334.3 480 352 480L384 480C401.7 480 416 494.3 416 512C416 529.7 401.7 544 384 544L352 544zM352 416C334.3 416 320 401.7 320 384C320 366.3 334.3 352 352 352L448 352C465.7 352 480 366.3 480 384C480 401.7 465.7 416 448 416L352 416zM352 288C334.3 288 320 273.7 320 256C320 238.3 334.3 224 352 224L512 224C529.7 224 544 238.3 544 256C544 273.7 529.7 288 512 288L352 288zM352 160C334.3 160 320 145.7 320 128C320 110.3 334.3 96 352 96L576 96C593.7 96 608 110.3 608 128C608 145.7 593.7 160 576 160L352 160z"/></svg>
|
||||
|
Before Width: | Height: | Size: 1.1 KiB |
|
|
@ -350,11 +350,11 @@
|
|||
style="fill-opacity:1;stroke:black;stroke-width:2.78220296;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="M 49.84375 1.71875 C 36.719738 1.71875 26.0625 12.375988 26.0625 25.5 C 26.0625 32.977454 29.538325 39.612734 34.9375 43.96875 C 24.439951 49.943698 17.919149 62.196126 14.3125 75.65625 C 9.0380874 95.34065 30.224013 98.21875 49.84375 98.21875 C 69.463486 98.21875 90.549327 94.96715 85.375 75.65625 C 81.693381 61.916246 75.224585 49.827177 64.8125 43.9375 C 70.181573 39.580662 73.59375 32.953205 73.59375 25.5 C 73.59375 12.375988 62.967762 1.71875 49.84375 1.71875 z "
|
||||
transform="translate(0,952.36218)"
|
||||
id="left" />
|
||||
id="right" />
|
||||
<path
|
||||
style="opacity:1;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.73577702;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 51.28696,1001.834 0,-46.98372 1.434151,0.16768 c 5.155008,0.60274 9.462857,2.72154 12.938257,6.36366 4.74393,4.9715 6.87913,11.35611 6.16464,18.43328 -0.53702,5.31935 -3.09008,10.59498 -6.83833,14.13074 l -1.94072,1.83069 3.04083,2.20427 c 3.58084,2.5957 7.18975,6.4912 9.55296,10.3116 4.89572,7.9144 9.23593,21.4918 8.50487,26.6055 -0.81312,5.6877 -5.43872,9.6977 -13.62216,11.8093 -3.80822,0.9826 -7.68056,1.4713 -14.763321,1.8633 l -4.471177,0.2474 0,-46.9837 z"
|
||||
id="right"
|
||||
id="left"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="display:inline;fill:url(#linearGradient3);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.77952756;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
|
@ -321,11 +321,11 @@
|
|||
style="fill-opacity:1;stroke:black;stroke-width:2.78220296;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="M 49.84375 1.71875 C 36.719738 1.71875 26.0625 12.375988 26.0625 25.5 C 26.0625 32.977454 29.538325 39.612734 34.9375 43.96875 C 24.439951 49.943698 17.919149 62.196126 14.3125 75.65625 C 9.0380874 95.34065 30.224013 98.21875 49.84375 98.21875 C 69.463486 98.21875 90.549327 94.96715 85.375 75.65625 C 81.693381 61.916246 75.224585 49.827177 64.8125 43.9375 C 70.181573 39.580662 73.59375 32.953205 73.59375 25.5 C 73.59375 12.375988 62.967762 1.71875 49.84375 1.71875 z "
|
||||
transform="translate(0,952.36218)"
|
||||
id="left" />
|
||||
id="right" />
|
||||
<path
|
||||
style="opacity:1;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.73577702;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 51.28696,1001.834 0,-46.98372 1.434151,0.16768 c 5.155008,0.60274 9.462857,2.72154 12.938257,6.36366 4.74393,4.9715 6.87913,11.35611 6.16464,18.43328 -0.53702,5.31935 -3.09008,10.59498 -6.83833,14.13074 l -1.94072,1.83069 3.04083,2.20427 c 3.58084,2.5957 7.18975,6.4912 9.55296,10.3116 4.89572,7.9144 9.23593,21.4918 8.50487,26.6055 -0.81312,5.6877 -5.43872,9.6977 -13.62216,11.8093 -3.80822,0.9826 -7.68056,1.4713 -14.763321,1.8633 l -4.471177,0.2474 0,-46.9837 z"
|
||||
id="right"
|
||||
id="left"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 46.656521,12.167234 18.055171,18.054184 a 6.6081919,6.6078288 0 0 1 -0.126303,9.352065 6.6804126,6.6800456 0 0 1 -8.233169,1.011048 l -7.944268,7.943843 6.463762,6.445343 a 6.9331851,6.9328042 0 0 1 5.741536,2.022073 l 28.057729,28.092294 a 6.9962797,6.9958953 0 0 1 -9.894222,9.893685 L 50.719018,66.907526 A 7.0595711,7.0591833 0 0 1 49.18433,59.270613 l -5.741527,-5.741238 -7.944298,7.943843 A 6.716523,6.7161541 0 0 1 25.134866,69.832263 L 7.079684,51.778091 a 6.716523,6.7161541 0 0 1 8.39566,-10.345064 L 36.31101,20.59853 a 6.716523,6.7161541 0 0 1 10.345612,-8.431329 z"
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
|
@ -340,11 +340,11 @@
|
|||
style="fill-opacity:1;stroke:black;stroke-width:2.78220296;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="M 49.84375 1.71875 C 36.719738 1.71875 26.0625 12.375988 26.0625 25.5 C 26.0625 32.977454 29.538325 39.612734 34.9375 43.96875 C 24.439951 49.943698 17.919149 62.196126 14.3125 75.65625 C 9.0380874 95.34065 30.224013 98.21875 49.84375 98.21875 C 69.463486 98.21875 90.549327 94.96715 85.375 75.65625 C 81.693381 61.916246 75.224585 49.827177 64.8125 43.9375 C 70.181573 39.580662 73.59375 32.953205 73.59375 25.5 C 73.59375 12.375988 62.967762 1.71875 49.84375 1.71875 z "
|
||||
transform="translate(0,952.36218)"
|
||||
id="left" />
|
||||
id="right" />
|
||||
<path
|
||||
style="opacity:1;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.73577702;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 51.28696,1001.834 0,-46.98372 1.434151,0.16768 c 5.155008,0.60274 9.462857,2.72154 12.938257,6.36366 4.74393,4.9715 6.87913,11.35611 6.16464,18.43328 -0.53702,5.31935 -3.09008,10.59498 -6.83833,14.13074 l -1.94072,1.83069 3.04083,2.20427 c 3.58084,2.5957 7.18975,6.4912 9.55296,10.3116 4.89572,7.9144 9.23593,21.4918 8.50487,26.6055 -0.81312,5.6877 -5.43872,9.6977 -13.62216,11.8093 -3.80822,0.9826 -7.68056,1.4713 -14.763321,1.8633 l -4.471177,0.2474 0,-46.9837 z"
|
||||
id="right"
|
||||
id="left"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
|
|
@ -363,6 +363,6 @@
|
|||
d="m 38.011063,984.77381 -10.143601,-5.23583 -10.063711,5.38779 1.845023,-11.2651 -8.233948,-7.90624 11.283888,-1.72639 4.974851,-10.27411 5.128803,10.19813 11.308575,1.55649 -8.114112,8.02918 z"
|
||||
inkscape:transform-center-x="0.094945927"
|
||||
inkscape:transform-center-y="-3.9764964"
|
||||
transform="matrix(-2.3768784,0,0,2.4799382,115.920285,-1400.1716)" />
|
||||
transform="matrix(2.3768784,0,0,2.4799382,-15.920285,-1400.1716)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
426
cockatrice/src/card/card_info.cpp
Normal file
|
|
@ -0,0 +1,426 @@
|
|||
#include "card_info.h"
|
||||
|
||||
#include "../picture_loader/picture_loader.h"
|
||||
#include "../settings/cache_settings.h"
|
||||
#include "game_specific_terms.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QMessageBox>
|
||||
#include <QRegularExpression>
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
class SetList::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 SetList::sortByKey()
|
||||
{
|
||||
std::sort(begin(), end(), KeyCompareFunctor());
|
||||
}
|
||||
|
||||
int SetList::getEnabledSetsNum()
|
||||
{
|
||||
int num = 0;
|
||||
for (int i = 0; i < size(); ++i) {
|
||||
CardSetPtr set = at(i);
|
||||
if (set && set->getEnabled()) {
|
||||
++num;
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
int SetList::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 SetList::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 SetList::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 SetList::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 SetList::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 SetList::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 SetList::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
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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');
|
||||
}
|
||||
}
|
||||
|
||||
CardRelation::CardRelation(const QString &_name,
|
||||
AttachType _attachType,
|
||||
bool _isCreateAllExclusion,
|
||||
bool _isVariableCount,
|
||||
int _defaultCount,
|
||||
bool _isPersistent)
|
||||
: name(_name), attachType(_attachType), isCreateAllExclusion(_isCreateAllExclusion),
|
||||
isVariableCount(_isVariableCount), defaultCount(_defaultCount), isPersistent(_isPersistent)
|
||||
{
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
470
cockatrice/src/card/card_info.h
Normal file
|
|
@ -0,0 +1,470 @@
|
|||
#ifndef CARD_INFO_H
|
||||
#define CARD_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 PrintingInfo;
|
||||
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 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);
|
||||
|
||||
// Determine incomplete sets.
|
||||
bool getIsKnownIgnored() const
|
||||
{
|
||||
return longName.length() + setType.length() + releaseDate.toString().length() == 0;
|
||||
}
|
||||
};
|
||||
|
||||
class SetList : 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();
|
||||
};
|
||||
|
||||
/**
|
||||
* 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;
|
||||
};
|
||||
|
||||
class CardInfo : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
CardInfoPtr smartThis;
|
||||
// The card name
|
||||
QString name;
|
||||
// The name without punctuation or capitalization, for better card name recognition.
|
||||
QString simpleName;
|
||||
// card text
|
||||
QString text;
|
||||
// whether this is not a "real" card but a token
|
||||
bool isToken;
|
||||
// basic card properties; common for all the sets
|
||||
QVariantHash properties;
|
||||
// the cards i'm related to
|
||||
QList<CardRelation *> relatedCards;
|
||||
// the card i'm reverse-related to
|
||||
QList<CardRelation *> reverseRelatedCards;
|
||||
// the cards thare are reverse-related to me
|
||||
QList<CardRelation *> reverseRelatedCardsToMe;
|
||||
// card sets
|
||||
SetToPrintingsMap setsToPrintings;
|
||||
// cached set names
|
||||
QString setsNames;
|
||||
// positioning properties; used by UI
|
||||
bool cipt;
|
||||
bool landscapeOrientation;
|
||||
int tableRow;
|
||||
bool upsideDownArt;
|
||||
|
||||
public:
|
||||
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);
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
static CardInfoPtr newInstance(const QString &_name);
|
||||
|
||||
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);
|
||||
|
||||
CardInfoPtr clone() const
|
||||
{
|
||||
// Use the copy constructor to create a new instance
|
||||
CardInfoPtr newCardInfo = CardInfoPtr(new CardInfo(*this));
|
||||
newCardInfo->setSmartPointer(newCardInfo); // Set the smart pointer for the new instance
|
||||
return newCardInfo;
|
||||
}
|
||||
|
||||
void setSmartPointer(CardInfoPtr _ptr)
|
||||
{
|
||||
smartThis = std::move(_ptr);
|
||||
}
|
||||
|
||||
// basic properties
|
||||
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;
|
||||
}
|
||||
|
||||
// related cards
|
||||
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);
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
// Back-compatibility methods. Remove ASAP
|
||||
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);
|
||||
|
||||
QString getCorrectedName() const;
|
||||
void addToSet(const CardSetPtr &_set, PrintingInfo _info = PrintingInfo());
|
||||
void combineLegalities(const QVariantHash &props);
|
||||
void refreshCachedSetNames();
|
||||
|
||||
/**
|
||||
* Simplify a name to have no punctuation and lowercase all letters, for
|
||||
* less strict name-matching.
|
||||
*/
|
||||
static QString simplifyName(const QString &name);
|
||||
|
||||
signals:
|
||||
/**
|
||||
* Emit this when a pixmap for this card finishes loading.
|
||||
* @param printing The specific printing the pixmap is for.
|
||||
*/
|
||||
void pixmapUpdated(const PrintingInfo &printing);
|
||||
void cardInfoChanged(CardInfoPtr card);
|
||||
};
|
||||
|
||||
class CardRelation : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum AttachType
|
||||
{
|
||||
DoesNotAttach = 0,
|
||||
AttachTo = 1,
|
||||
TransformInto = 2,
|
||||
};
|
||||
|
||||
private:
|
||||
QString name;
|
||||
AttachType attachType;
|
||||
bool isCreateAllExclusion;
|
||||
bool isVariableCount;
|
||||
int defaultCount;
|
||||
bool isPersistent;
|
||||
|
||||
public:
|
||||
explicit CardRelation(const QString &_name = QString(),
|
||||
AttachType _attachType = DoesNotAttach,
|
||||
bool _isCreateAllExclusion = false,
|
||||
bool _isVariableCount = false,
|
||||
int _defaultCount = 1,
|
||||
bool _isPersistent = false);
|
||||
|
||||
inline const QString &getName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
AttachType getAttachType() const
|
||||
{
|
||||
return attachType;
|
||||
}
|
||||
bool getDoesAttach() const
|
||||
{
|
||||
return attachType != DoesNotAttach;
|
||||
}
|
||||
bool getDoesTransform() const
|
||||
{
|
||||
return attachType == TransformInto;
|
||||
}
|
||||
QString getAttachTypeAsString() const
|
||||
{
|
||||
switch (attachType) {
|
||||
case AttachTo:
|
||||
return "attach";
|
||||
case TransformInto:
|
||||
return "transform";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
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
|
||||
|
|
@ -1,8 +1,5 @@
|
|||
#include "exact_card.h"
|
||||
|
||||
#include "../card_info.h"
|
||||
#include "printing_info.h"
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
* This will set the CardInfoPtr to null.
|
||||
46
cockatrice/src/card/exact_card.h
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
#ifndef EXACT_CARD_H
|
||||
#define EXACT_CARD_H
|
||||
|
||||
#include "card_info.h"
|
||||
|
||||
/**
|
||||
* Identifies the card along with its exact printing
|
||||
*/
|
||||
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,9 +1,3 @@
|
|||
/**
|
||||
* @file game_specific_terms.h
|
||||
* @ingroup Cards
|
||||
* @brief TODO: Document this.
|
||||
*/
|
||||
|
||||
#ifndef GAME_SPECIFIC_TERMS_H
|
||||
#define GAME_SPECIFIC_TERMS_H
|
||||
|
||||
|
|
@ -53,6 +47,6 @@ inline static const QString getNicePropertyName(QString key)
|
|||
return QCoreApplication::translate("Mtg", "Color Identity");
|
||||
return key;
|
||||
}
|
||||
} // namespace Mtg
|
||||
}; // namespace Mtg
|
||||
|
||||
#endif
|
||||
|
|
@ -1,8 +1,7 @@
|
|||
#include "../../../interface/widgets/menus/deck_editor_menu.h"
|
||||
#include "deck_editor_menu.h"
|
||||
|
||||
#include "../../../client/settings/cache_settings.h"
|
||||
#include "../../../client/settings/shortcuts_settings.h"
|
||||
#include "../tabs/abstract_tab_deck_editor.h"
|
||||
#include "../settings/cache_settings.h"
|
||||
#include "../settings/shortcuts_settings.h"
|
||||
|
||||
DeckEditorMenu::DeckEditorMenu(AbstractTabDeckEditor *parent) : QMenu(parent), deckEditor(parent)
|
||||
{
|
||||
|
|
@ -1,12 +1,8 @@
|
|||
/**
|
||||
* @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;
|
||||
|
|
@ -1,7 +1,5 @@
|
|||
#include "get_text_with_max.h"
|
||||
|
||||
#include <QInputDialog>
|
||||
|
||||
QString getTextWithMax(QWidget *parent,
|
||||
const QString &title,
|
||||
const QString &label,
|
||||
|
|
@ -1,15 +1,10 @@
|
|||
/**
|
||||
* @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
|
||||
|
||||
#include <QLineEdit>
|
||||
#include <QWidget>
|
||||
#include <libcockatrice/utility/trice_limits.h>
|
||||
#include "trice_limits.h"
|
||||
|
||||
#include <QInputDialog>
|
||||
|
||||
QString getTextWithMax(QWidget *parent,
|
||||
const QString &title,
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
#include "client_update_checker.h"
|
||||
|
||||
#include "../../../settings/cache_settings.h"
|
||||
#include "../../settings/cache_settings.h"
|
||||
#include "release_channel.h"
|
||||
|
||||
ClientUpdateChecker::ClientUpdateChecker(QObject *parent) : QObject(parent)
|
||||
|
|
@ -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,9 +1,3 @@
|
|||
/**
|
||||
* @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
|
||||
|
||||
|
|
|
|||
|
|
@ -1,39 +1,30 @@
|
|||
/**
|
||||
* @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 "../../../interface/deck_loader/card_node_function.h"
|
||||
#include "../../../deck/deck_loader.h"
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <libcockatrice/card/import/card_name_normalizer.h>
|
||||
#include <libcockatrice/deck_list/deck_list.h>
|
||||
|
||||
class IJsonDeckParser
|
||||
{
|
||||
public:
|
||||
virtual ~IJsonDeckParser() = default;
|
||||
|
||||
virtual DeckList parse(const QJsonObject &obj) = 0;
|
||||
virtual DeckLoader *parse(const QJsonObject &obj) = 0;
|
||||
};
|
||||
|
||||
class ArchidektJsonParser : public IJsonDeckParser
|
||||
{
|
||||
public:
|
||||
DeckList parse(const QJsonObject &obj) override
|
||||
DeckLoader *parse(const QJsonObject &obj) override
|
||||
{
|
||||
DeckList deckList;
|
||||
DeckLoader *list = new DeckLoader();
|
||||
|
||||
QString deckName = obj.value("name").toString();
|
||||
QString deckDescription = obj.value("description").toString();
|
||||
|
||||
deckList.setName(deckName);
|
||||
deckList.setComments(deckDescription);
|
||||
list->setName(deckName);
|
||||
list->setComments(deckDescription);
|
||||
|
||||
QString outputText;
|
||||
QTextStream outStream(&outputText);
|
||||
|
|
@ -50,25 +41,25 @@ public:
|
|||
outStream << quantity << ' ' << cardName << " (" << setName << ") " << collectorNumber << '\n';
|
||||
}
|
||||
|
||||
deckList.loadFromStream_Plain(outStream, false, CardNameNormalizer());
|
||||
deckList.forEachCard(CardNodeFunction::ResolveProviderId());
|
||||
list->loadFromStream_Plain(outStream, false);
|
||||
list->resolveSetNameAndNumberToProviderID();
|
||||
|
||||
return deckList;
|
||||
return list;
|
||||
}
|
||||
};
|
||||
|
||||
class MoxfieldJsonParser : public IJsonDeckParser
|
||||
{
|
||||
public:
|
||||
DeckList parse(const QJsonObject &obj) override
|
||||
DeckLoader *parse(const QJsonObject &obj) override
|
||||
{
|
||||
DeckList deckList;
|
||||
DeckLoader *list = new DeckLoader();
|
||||
|
||||
QString deckName = obj.value("name").toString();
|
||||
QString deckDescription = obj.value("description").toString();
|
||||
|
||||
deckList.setName(deckName);
|
||||
deckList.setComments(deckDescription);
|
||||
list->setName(deckName);
|
||||
list->setComments(deckDescription);
|
||||
|
||||
QString outputText;
|
||||
QTextStream outStream(&outputText);
|
||||
|
|
@ -97,8 +88,8 @@ public:
|
|||
outStream << quantity << ' ' << cardName << " (" << setName << ") " << collectorNumber << '\n';
|
||||
}
|
||||
|
||||
deckList.loadFromStream_Plain(outStream, false, CardNameNormalizer());
|
||||
deckList.forEachCard(CardNodeFunction::ResolveProviderId());
|
||||
list->loadFromStream_Plain(outStream, false);
|
||||
list->resolveSetNameAndNumberToProviderID();
|
||||
|
||||
QJsonObject commandersObj = obj.value("commanders").toObject();
|
||||
if (!commandersObj.isEmpty()) {
|
||||
|
|
@ -109,12 +100,12 @@ public:
|
|||
QString collectorNumber = cardData.value("cn").toString();
|
||||
QString providerId = cardData.value("scryfall_id").toString();
|
||||
|
||||
deckList.setBannerCard({commanderName, providerId});
|
||||
deckList.addCard(commanderName, DECK_ZONE_MAIN, -1, setName, collectorNumber, providerId);
|
||||
list->setBannerCard({commanderName, providerId});
|
||||
list->addCard(commanderName, DECK_ZONE_MAIN, -1, setName, collectorNumber, providerId);
|
||||
}
|
||||
}
|
||||
|
||||
return deckList;
|
||||
return list;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,3 @@
|
|||
/**
|
||||
* @file release_channel.h
|
||||
* @ingroup ClientUpdate
|
||||
* @brief TODO: Document this.
|
||||
*/
|
||||
|
||||
#ifndef RELEASECHANNEL_H
|
||||
#define RELEASECHANNEL_H
|
||||
|
||||
|
|
@ -57,27 +51,27 @@ protected:
|
|||
}
|
||||
|
||||
public:
|
||||
[[nodiscard]] QString getName() const
|
||||
QString getName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
[[nodiscard]] QString getDescriptionUrl() const
|
||||
QString getDescriptionUrl() const
|
||||
{
|
||||
return descriptionUrl;
|
||||
}
|
||||
[[nodiscard]] QString getDownloadUrl() const
|
||||
QString getDownloadUrl() const
|
||||
{
|
||||
return downloadUrl;
|
||||
}
|
||||
[[nodiscard]] QString getCommitHash() const
|
||||
QString getCommitHash() const
|
||||
{
|
||||
return commitHash;
|
||||
}
|
||||
[[nodiscard]] QDate getPublishDate() const
|
||||
QDate getPublishDate() const
|
||||
{
|
||||
return publishDate;
|
||||
}
|
||||
[[nodiscard]] bool isCompatibleVersionFound() const
|
||||
bool isCompatibleVersionFound() const
|
||||
{
|
||||
return compatibleVersionFound;
|
||||
}
|
||||
|
|
@ -97,15 +91,15 @@ protected:
|
|||
|
||||
protected:
|
||||
static bool downloadMatchesCurrentOS(const QString &fileName);
|
||||
[[nodiscard]] virtual QString getReleaseChannelUrl() const = 0;
|
||||
virtual QString getReleaseChannelUrl() const = 0;
|
||||
|
||||
public:
|
||||
Release *getLastRelease()
|
||||
{
|
||||
return lastRelease;
|
||||
}
|
||||
[[nodiscard]] virtual QString getManualDownloadUrl() const = 0;
|
||||
[[nodiscard]] virtual QString getName() const = 0;
|
||||
virtual QString getManualDownloadUrl() const = 0;
|
||||
virtual QString getName() const = 0;
|
||||
void checkForUpdates();
|
||||
signals:
|
||||
void finishedCheck(bool needToUpdate, bool isCompatible, Release *release);
|
||||
|
|
@ -122,12 +116,12 @@ public:
|
|||
explicit StableReleaseChannel() = default;
|
||||
~StableReleaseChannel() override = default;
|
||||
|
||||
[[nodiscard]] QString getManualDownloadUrl() const override;
|
||||
QString getManualDownloadUrl() const override;
|
||||
|
||||
[[nodiscard]] QString getName() const override;
|
||||
QString getName() const override;
|
||||
|
||||
protected:
|
||||
[[nodiscard]] QString getReleaseChannelUrl() const override;
|
||||
QString getReleaseChannelUrl() const override;
|
||||
protected slots:
|
||||
|
||||
void releaseListFinished() override;
|
||||
|
|
@ -143,12 +137,12 @@ public:
|
|||
BetaReleaseChannel() = default;
|
||||
~BetaReleaseChannel() override = default;
|
||||
|
||||
[[nodiscard]] QString getManualDownloadUrl() const override;
|
||||
QString getManualDownloadUrl() const override;
|
||||
|
||||
[[nodiscard]] QString getName() const override;
|
||||
QString getName() const override;
|
||||
|
||||
protected:
|
||||
[[nodiscard]] QString getReleaseChannelUrl() const override;
|
||||
QString getReleaseChannelUrl() const override;
|
||||
protected slots:
|
||||
|
||||
void releaseListFinished() override;
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
#include "replay_timeline_widget.h"
|
||||
|
||||
#include "../../../client/settings/cache_settings.h"
|
||||
#include "../../settings/cache_settings.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <QPalette>
|
||||
#include <QTimer>
|
||||
|
||||
ReplayTimelineWidget::ReplayTimelineWidget(QWidget *parent)
|
||||
|
|
@ -1,14 +1,9 @@
|
|||
/**
|
||||
* @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/event_processing_options.h"
|
||||
|
||||
#include <QList>
|
||||
#include <QMouseEvent>
|
||||
#include <QWidget>
|
||||
|
||||
|
|
@ -59,10 +54,10 @@ public:
|
|||
|
||||
explicit ReplayTimelineWidget(QWidget *parent = nullptr);
|
||||
void setTimeline(const QList<int> &_replayTimeline);
|
||||
[[nodiscard]] QSize sizeHint() const override;
|
||||
[[nodiscard]] QSize minimumSizeHint() const override;
|
||||
QSize sizeHint() const override;
|
||||
QSize minimumSizeHint() const override;
|
||||
void setTimeScaleFactor(qreal _timeScaleFactor);
|
||||
[[nodiscard]] int getCurrentEvent() const
|
||||
int getCurrentEvent() const
|
||||
{
|
||||
return currentEvent;
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
#include "card_sets_model.h"
|
||||
#include "sets_model.h"
|
||||
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
|
|
@ -45,7 +45,7 @@ QVariant SetsModel::data(const QModelIndex &index, int role) const
|
|||
|
||||
switch (index.column()) {
|
||||
case SortKeyCol:
|
||||
return QString("%1").arg(index.row(), 8, 10, QChar('0'));
|
||||
return QString("%1").arg(set->getSortKey(), 8, 10, QChar('0'));
|
||||
case IsKnownCol:
|
||||
return set->getIsKnown();
|
||||
case SetTypeCol:
|
||||
|
|
@ -283,7 +283,11 @@ bool SetsDisplayModel::filterAcceptsRow(int sourceRow, const QModelIndex &source
|
|||
auto nameIndex = sourceModel()->index(sourceRow, SetsModel::LongNameCol, sourceParent);
|
||||
auto shortNameIndex = sourceModel()->index(sourceRow, SetsModel::ShortNameCol, sourceParent);
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0))
|
||||
const auto filter = filterRegularExpression();
|
||||
#else
|
||||
const auto filter = filterRegExp();
|
||||
#endif
|
||||
|
||||
return (sourceModel()->data(typeIndex).toString().contains(filter) ||
|
||||
sourceModel()->data(nameIndex).toString().contains(filter) ||
|
||||
|
|
@ -1,17 +1,12 @@
|
|||
/**
|
||||
* @file sets_model.h
|
||||
* @ingroup CardDatabaseModels
|
||||
* @brief TODO: Document this.
|
||||
*/
|
||||
|
||||
#ifndef SETSMODEL_H
|
||||
#define SETSMODEL_H
|
||||
|
||||
#include "../../database/card_database.h"
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include <QMimeData>
|
||||
#include <QSet>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <libcockatrice/card/database/card_database.h>
|
||||
|
||||
class SetsProxyModel;
|
||||
|
||||
|
|
@ -25,11 +20,11 @@ public:
|
|||
SetsMimeData(int _oldRow) : oldRow(_oldRow)
|
||||
{
|
||||
}
|
||||
[[nodiscard]] int getOldRow() const
|
||||
int getOldRow() const
|
||||
{
|
||||
return oldRow;
|
||||
}
|
||||
[[nodiscard]] QStringList formats() const
|
||||
QStringList formats() const
|
||||
{
|
||||
return QStringList() << "application/x-cockatricecardset";
|
||||
}
|
||||
|
|
@ -42,7 +37,7 @@ class SetsModel : public QAbstractTableModel
|
|||
|
||||
private:
|
||||
static const int NUM_COLS = 7;
|
||||
CardSetList sets;
|
||||
SetList sets;
|
||||
QSet<CardSetPtr> enabledSets;
|
||||
|
||||
public:
|
||||
|
|
@ -64,23 +59,22 @@ public:
|
|||
|
||||
explicit SetsModel(CardDatabase *_db, QObject *parent = nullptr);
|
||||
~SetsModel() override;
|
||||
[[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
[[nodiscard]] int columnCount(const QModelIndex &parent = QModelIndex()) const override
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
return NUM_COLS;
|
||||
}
|
||||
[[nodiscard]] QVariant data(const QModelIndex &index, int role) const override;
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
|
||||
[[nodiscard]] QVariant
|
||||
headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
[[nodiscard]] Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
[[nodiscard]] Qt::DropActions supportedDropActions() const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
Qt::DropActions supportedDropActions() const override;
|
||||
|
||||
[[nodiscard]] QMimeData *mimeData(const QModelIndexList &indexes) const override;
|
||||
QMimeData *mimeData(const QModelIndexList &indexes) const override;
|
||||
bool
|
||||
dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
|
||||
[[nodiscard]] QStringList mimeTypes() const override;
|
||||
QStringList mimeTypes() const override;
|
||||
void swapRows(int oldRow, int newRow);
|
||||
void toggleRow(int row, bool enable);
|
||||
void toggleRow(int row);
|
||||
|
|
@ -98,8 +92,8 @@ public:
|
|||
explicit SetsDisplayModel(QObject *parent = nullptr);
|
||||
|
||||
protected:
|
||||
[[nodiscard]] bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
|
||||
[[nodiscard]] bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
|
||||
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
|
||||
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
|
||||
void fetchMore(const QModelIndex &index) override;
|
||||
};
|
||||
|
||||
|
|
@ -1,20 +1,21 @@
|
|||
#include "spoiler_background_updater.h"
|
||||
|
||||
#include "../../../../interface/window_main.h"
|
||||
#include "../../../../main.h"
|
||||
#include "../../../settings/cache_settings.h"
|
||||
#include "../../database/card_database.h"
|
||||
#include "../../database/card_database_manager.h"
|
||||
#include "../../interface/window_main.h"
|
||||
#include "../../main.h"
|
||||
#include "../../settings/cache_settings.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCryptographicHash>
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QLocale>
|
||||
#include <QMessageBox>
|
||||
#include <QNetworkReply>
|
||||
#include <QUrl>
|
||||
#include <QtConcurrent>
|
||||
#include <libcockatrice/card/database/card_database.h>
|
||||
#include <libcockatrice/card/database/card_database_manager.h>
|
||||
#include <version_string.h>
|
||||
|
||||
#define SPOILERS_STATUS_URL "https://raw.githubusercontent.com/Cockatrice/Magic-Spoiler/files/SpoilerSeasonEnabled"
|
||||
#define SPOILERS_URL "https://raw.githubusercontent.com/Cockatrice/Magic-Spoiler/files/spoiler.xml"
|
||||
|
|
@ -40,9 +41,7 @@ void SpoilerBackgroundUpdater::startSpoilerDownloadProcess(QString url, bool sav
|
|||
void SpoilerBackgroundUpdater::downloadFromURL(QUrl url, bool saveResults)
|
||||
{
|
||||
auto *nam = new QNetworkAccessManager(this);
|
||||
auto request = QNetworkRequest(url);
|
||||
request.setHeader(QNetworkRequest::UserAgentHeader, QString("Cockatrice %1").arg(VERSION_STRING));
|
||||
QNetworkReply *reply = nam->get(request);
|
||||
QNetworkReply *reply = nam->get(QNetworkRequest(url));
|
||||
|
||||
if (saveResults) {
|
||||
// This will write out to the file (used for spoiler.xml)
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -22,7 +16,7 @@ public:
|
|||
inline QString getCardUpdaterBinaryName()
|
||||
{
|
||||
return "oracle";
|
||||
}
|
||||
};
|
||||
QByteArray getHash(const QString fileName);
|
||||
QByteArray getHash(QByteArray data);
|
||||
static bool deleteSpoilerFile();
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
#include "replay_manager.h"
|
||||
|
||||
#include "../interface/widgets/tabs/tab_game.h"
|
||||
#include "../tabs/tab_game.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QToolButton>
|
||||
|
|
@ -1,18 +1,11 @@
|
|||
/**
|
||||
* @file replay_manager.h
|
||||
* @ingroup Core
|
||||
* @ingroup Replay
|
||||
* @brief TODO: Document this.
|
||||
*/
|
||||
|
||||
#ifndef REPLAY_MANAGER_H
|
||||
#define REPLAY_MANAGER_H
|
||||
|
||||
#include "replay_timeline_widget.h"
|
||||
#include "network/replay_timeline_widget.h"
|
||||
#include "pb/game_replay.pb.h"
|
||||
|
||||
#include <QToolButton>
|
||||
#include <QWidget>
|
||||
#include <libcockatrice/protocol/pb/game_replay.pb.h>
|
||||
|
||||
class TabGame;
|
||||
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
#include "sound_engine.h"
|
||||
|
||||
#include "settings/cache_settings.h"
|
||||
#include "../settings/cache_settings.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QMediaPlayer>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,3 @@
|
|||
/**
|
||||
* @file sound_engine.h
|
||||
* @ingroup Core
|
||||
* @brief TODO: Document this.
|
||||
*/
|
||||
|
||||
#ifndef SOUNDENGINE_H
|
||||
#define SOUNDENGINE_H
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,15 @@
|
|||
#include "tapped_out_interface.h"
|
||||
|
||||
#include "deck_list.h"
|
||||
#include "deck_list_card_node.h"
|
||||
|
||||
#include <QDesktopServices>
|
||||
#include <QMessageBox>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkRequest>
|
||||
#include <QRegularExpression>
|
||||
#include <QUrlQuery>
|
||||
#include <libcockatrice/deck_list/deck_list.h>
|
||||
#include <libcockatrice/deck_list/tree/deck_list_card_node.h>
|
||||
#include <version_string.h>
|
||||
|
||||
TappedOutInterface::TappedOutInterface(CardDatabase &_cardDatabase, QObject *parent)
|
||||
: QObject(parent), cardDatabase(_cardDatabase)
|
||||
|
|
@ -67,35 +68,32 @@ void TappedOutInterface::queryFinished(QNetworkReply *reply)
|
|||
deleteLater();
|
||||
}
|
||||
|
||||
void TappedOutInterface::getAnalyzeRequestData(const DeckList &deck, QByteArray &data)
|
||||
void TappedOutInterface::getAnalyzeRequestData(DeckList *deck, QByteArray *data)
|
||||
{
|
||||
DeckList mainboard, sideboard;
|
||||
copyDeckSplitMainAndSide(deck, mainboard, sideboard);
|
||||
copyDeckSplitMainAndSide(*deck, mainboard, sideboard);
|
||||
|
||||
QUrl params;
|
||||
QUrlQuery urlQuery;
|
||||
urlQuery.addQueryItem("name", deck.getName());
|
||||
urlQuery.addQueryItem("name", deck->getName());
|
||||
urlQuery.addQueryItem("mainboard", mainboard.writeToString_Plain(false, true));
|
||||
urlQuery.addQueryItem("sideboard", sideboard.writeToString_Plain(false, true));
|
||||
params.setQuery(urlQuery);
|
||||
data.append(params.query(QUrl::EncodeReserved).toUtf8());
|
||||
data->append(params.query(QUrl::EncodeReserved).toUtf8());
|
||||
}
|
||||
|
||||
void TappedOutInterface::analyzeDeck(const DeckList &deck)
|
||||
void TappedOutInterface::analyzeDeck(DeckList *deck)
|
||||
{
|
||||
QByteArray data;
|
||||
getAnalyzeRequestData(deck, data);
|
||||
getAnalyzeRequestData(deck, &data);
|
||||
|
||||
QNetworkRequest request(QUrl("https://tappedout.net/mtg-decks/paste/"));
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
|
||||
request.setHeader(QNetworkRequest::UserAgentHeader, QString("Cockatrice %1").arg(VERSION_STRING));
|
||||
// we interpret the redirect and open it in the browser instead, do not follow redirects
|
||||
request.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::ManualRedirectPolicy);
|
||||
|
||||
manager->post(request, data);
|
||||
}
|
||||
|
||||
void TappedOutInterface::copyDeckSplitMainAndSide(const DeckList &source, DeckList &mainboard, DeckList &sideboard)
|
||||
void TappedOutInterface::copyDeckSplitMainAndSide(DeckList &source, DeckList &mainboard, DeckList &sideboard)
|
||||
{
|
||||
auto copyMainOrSide = [this, &mainboard, &sideboard](const auto node, const auto card) {
|
||||
CardInfoPtr dbCard = cardDatabase.query()->getCardInfo(card->getName());
|
||||
|
|
@ -1,14 +1,11 @@
|
|||
/**
|
||||
* @file tapped_out_interface.h
|
||||
* @ingroup ApiInterfaces
|
||||
* @brief TODO: Document this.
|
||||
*/
|
||||
|
||||
#ifndef TAPPEDOUT_INTERFACE_H
|
||||
#define TAPPEDOUT_INTERFACE_H
|
||||
|
||||
#include <libcockatrice/card/database/card_database.h>
|
||||
#include <libcockatrice/deck_list/deck_list.h>
|
||||
#include "../database/card_database.h"
|
||||
#include "deck_list.h"
|
||||
|
||||
#include <QLoggingCategory>
|
||||
#include <QObject>
|
||||
|
||||
inline Q_LOGGING_CATEGORY(TappedOutInterfaceLog, "tapped_out_interface");
|
||||
|
||||
|
|
@ -30,14 +27,14 @@ private:
|
|||
QNetworkAccessManager *manager;
|
||||
|
||||
CardDatabase &cardDatabase;
|
||||
void copyDeckSplitMainAndSide(const DeckList &source, DeckList &mainboard, DeckList &sideboard);
|
||||
void copyDeckSplitMainAndSide(DeckList &source, DeckList &mainboard, DeckList &sideboard);
|
||||
private slots:
|
||||
void queryFinished(QNetworkReply *reply);
|
||||
void getAnalyzeRequestData(const DeckList &deck, QByteArray &data);
|
||||
void getAnalyzeRequestData(DeckList *deck, QByteArray *data);
|
||||
|
||||
public:
|
||||
explicit TappedOutInterface(CardDatabase &_cardDatabase, QObject *parent = nullptr);
|
||||
void analyzeDeck(const DeckList &deck);
|
||||
void analyzeDeck(DeckList *deck);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
#include "update_downloader.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QUrl>
|
||||
|
||||
UpdateDownloader::UpdateDownloader(QObject *parent) : QObject(parent), response(nullptr)
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
/**
|
||||
* @file update_downloader.h
|
||||
* @ingroup ClientUpdate
|
||||
* @brief TODO: Document this.
|
||||
*/
|
||||
//
|
||||
// Created by miguel on 28/12/15.
|
||||
//
|
||||
|
||||
#ifndef COCKATRICE_UPDATEDOWNLOADER_H
|
||||
#define COCKATRICE_UPDATEDOWNLOADER_H
|
||||
|
||||
#include <QDate>
|
||||
#include <QObject>
|
||||
#include <QUrl>
|
||||
#include <QtNetwork>
|
||||
|
||||
class UpdateDownloader : public QObject
|
||||
|
|
@ -1,34 +1,34 @@
|
|||
#include "card_database.h"
|
||||
|
||||
#include "../relation/card_relation.h"
|
||||
#include "../picture_loader/picture_loader.h"
|
||||
#include "../settings/cache_settings.h"
|
||||
#include "parser/cockatrice_xml_3.h"
|
||||
#include "parser/cockatrice_xml_4.h"
|
||||
|
||||
#include <QCryptographicHash>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QDirIterator>
|
||||
#include <QFile>
|
||||
#include <QMessageBox>
|
||||
#include <QRegularExpression>
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
CardDatabase::CardDatabase(QObject *parent,
|
||||
ICardPreferenceProvider *prefs,
|
||||
ICardDatabasePathProvider *pathProvider,
|
||||
ICardSetPriorityController *_setPriorityController)
|
||||
: QObject(parent), setPriorityController(_setPriorityController), loadStatus(NotLoaded)
|
||||
CardDatabase::CardDatabase(QObject *parent) : QObject(parent), loadStatus(NotLoaded)
|
||||
{
|
||||
qRegisterMetaType<CardInfoPtr>("CardInfoPtr");
|
||||
qRegisterMetaType<CardInfoPtr>("CardSetPtr");
|
||||
|
||||
// create loader and wire it up
|
||||
loader = new CardDatabaseLoader(this, this, pathProvider, prefs, setPriorityController);
|
||||
loader = new CardDatabaseLoader(this, this);
|
||||
// re-emit loader signals (so other code doesn't need to know about internals)
|
||||
connect(loader, &CardDatabaseLoader::loadingFinished, this, &CardDatabase::cardDatabaseLoadingFinished);
|
||||
connect(loader, &CardDatabaseLoader::loadingFailed, this, &CardDatabase::cardDatabaseLoadingFailed);
|
||||
connect(loader, &CardDatabaseLoader::newSetsFound, this, &CardDatabase::cardDatabaseNewSetsFound);
|
||||
connect(loader, &CardDatabaseLoader::allNewSetsEnabled, this, &CardDatabase::cardDatabaseAllNewSetsEnabled);
|
||||
|
||||
querier = new CardDatabaseQuerier(this, this, prefs);
|
||||
querier = new CardDatabaseQuerier(this, this);
|
||||
}
|
||||
|
||||
CardDatabase::~CardDatabase()
|
||||
|
|
@ -138,15 +138,15 @@ CardSetPtr CardDatabase::getSet(const QString &setName)
|
|||
if (sets.contains(setName)) {
|
||||
return sets.value(setName);
|
||||
} else {
|
||||
CardSetPtr newSet = CardSet::newInstance(setPriorityController, setName);
|
||||
CardSetPtr newSet = CardSet::newInstance(setName);
|
||||
sets.insert(setName, newSet);
|
||||
return newSet;
|
||||
}
|
||||
}
|
||||
|
||||
CardSetList CardDatabase::getSetList() const
|
||||
SetList CardDatabase::getSetList() const
|
||||
{
|
||||
CardSetList result;
|
||||
SetList result;
|
||||
for (auto set : sets.values()) {
|
||||
result << set;
|
||||
}
|
||||
|
|
@ -192,15 +192,9 @@ void CardDatabase::markAllSetsAsKnown()
|
|||
void CardDatabase::notifyEnabledSetsChanged()
|
||||
{
|
||||
// refresh the list of cached set names
|
||||
for (const CardInfoPtr &card : cards) {
|
||||
card->refreshCachedSets();
|
||||
}
|
||||
for (const CardInfoPtr &card : cards)
|
||||
card->refreshCachedSetNames();
|
||||
|
||||
// inform the carddatabasemodels that they need to re-check their list of cards
|
||||
emit cardDatabaseEnabledSetsChanged();
|
||||
}
|
||||
|
||||
void CardDatabase::addFormat(FormatRulesPtr format)
|
||||
{
|
||||
formats.insert(format->formatName.toLower(), format);
|
||||
}
|
||||
96
cockatrice/src/database/card_database.h
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
#ifndef CARDDATABASE_H
|
||||
#define CARDDATABASE_H
|
||||
|
||||
#include "../card/exact_card.h"
|
||||
#include "../common/card_ref.h"
|
||||
#include "card_database_loader.h"
|
||||
#include "card_database_querier.h"
|
||||
|
||||
#include <QBasicMutex>
|
||||
#include <QDate>
|
||||
#include <QHash>
|
||||
#include <QList>
|
||||
#include <QLoggingCategory>
|
||||
#include <QStringList>
|
||||
#include <QVector>
|
||||
#include <utility>
|
||||
|
||||
inline Q_LOGGING_CATEGORY(CardDatabaseLog, "card_database");
|
||||
|
||||
class CardDatabase : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
protected:
|
||||
/*
|
||||
* The cards, indexed by name.
|
||||
*/
|
||||
CardNameMap cards;
|
||||
|
||||
/**
|
||||
* The cards, indexed by their simple name.
|
||||
*/
|
||||
CardNameMap simpleNameCards;
|
||||
|
||||
/*
|
||||
* The sets, indexed by short name.
|
||||
*/
|
||||
SetNameMap sets;
|
||||
|
||||
// loader responsible for file discovery & parsing
|
||||
CardDatabaseLoader *loader;
|
||||
|
||||
LoadStatus loadStatus;
|
||||
|
||||
CardDatabaseQuerier *querier;
|
||||
|
||||
private:
|
||||
void checkUnknownSets();
|
||||
void refreshCachedReverseRelatedCards();
|
||||
|
||||
QBasicMutex *clearDatabaseMutex = new QBasicMutex(), *addCardMutex = new QBasicMutex(),
|
||||
*removeCardMutex = new QBasicMutex();
|
||||
|
||||
public:
|
||||
explicit CardDatabase(QObject *parent = nullptr);
|
||||
~CardDatabase() override;
|
||||
|
||||
void removeCard(CardInfoPtr card);
|
||||
void clear();
|
||||
|
||||
const CardNameMap &getCardList() const
|
||||
{
|
||||
return cards;
|
||||
}
|
||||
CardSetPtr getSet(const QString &setName);
|
||||
SetList getSetList() const;
|
||||
LoadStatus getLoadStatus() const
|
||||
{
|
||||
return loadStatus;
|
||||
}
|
||||
CardDatabaseQuerier *query() const
|
||||
{
|
||||
return querier;
|
||||
}
|
||||
void enableAllUnknownSets();
|
||||
void markAllSetsAsKnown();
|
||||
void notifyEnabledSetsChanged();
|
||||
|
||||
public slots:
|
||||
void addCard(CardInfoPtr card);
|
||||
void addSet(CardSetPtr set);
|
||||
void loadCardDatabases();
|
||||
bool saveCustomTokensToFile();
|
||||
signals:
|
||||
void cardDatabaseLoadingFinished();
|
||||
void cardDatabaseLoadingFailed();
|
||||
void cardDatabaseNewSetsFound(int numUnknownSets, QStringList unknownSetsNames);
|
||||
void cardDatabaseAllNewSetsEnabled();
|
||||
void cardDatabaseEnabledSetsChanged();
|
||||
void cardAdded(CardInfoPtr card);
|
||||
void cardRemoved(CardInfoPtr card);
|
||||
|
||||
friend class CardDatabaseLoader;
|
||||
friend class CardDatabaseQuerier;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
#include "card_database_loader.h"
|
||||
|
||||
#include "../settings/cache_settings.h"
|
||||
#include "card_database.h"
|
||||
#include "parser/cockatrice_xml_3.h"
|
||||
#include "parser/cockatrice_xml_4.h"
|
||||
|
|
@ -9,26 +10,20 @@
|
|||
#include <QFile>
|
||||
#include <QTime>
|
||||
|
||||
CardDatabaseLoader::CardDatabaseLoader(QObject *parent,
|
||||
CardDatabase *db,
|
||||
ICardDatabasePathProvider *_pathProvider,
|
||||
ICardPreferenceProvider *_preferenceProvider,
|
||||
ICardSetPriorityController *_priorityController)
|
||||
: QObject(parent), database(db), pathProvider(_pathProvider)
|
||||
CardDatabaseLoader::CardDatabaseLoader(QObject *parent, CardDatabase *db) : QObject(parent), database(db)
|
||||
{
|
||||
// instantiate available parsers here and connect them to the database
|
||||
availableParsers << new CockatriceXml4Parser(_preferenceProvider, _priorityController);
|
||||
availableParsers << new CockatriceXml3Parser(_priorityController);
|
||||
availableParsers << new CockatriceXml4Parser;
|
||||
availableParsers << new CockatriceXml3Parser;
|
||||
|
||||
for (auto *p : availableParsers) {
|
||||
// connect parser outputs to the database adders
|
||||
connect(p, &ICardDatabaseParser::addCard, database, &CardDatabase::addCard, Qt::DirectConnection);
|
||||
connect(p, &ICardDatabaseParser::addSet, database, &CardDatabase::addSet, Qt::DirectConnection);
|
||||
connect(p, &ICardDatabaseParser::addFormat, database, &CardDatabase::addFormat, Qt::DirectConnection);
|
||||
}
|
||||
|
||||
// when SettingsCache's path changes, trigger reloads
|
||||
connect(pathProvider, &ICardDatabasePathProvider::cardDatabasePathChanged, this,
|
||||
connect(&SettingsCache::instance(), &SettingsCache::cardDatabasePathChanged, this,
|
||||
&CardDatabaseLoader::loadCardDatabases);
|
||||
}
|
||||
|
||||
|
|
@ -41,7 +36,8 @@ CardDatabaseLoader::~CardDatabaseLoader()
|
|||
LoadStatus CardDatabaseLoader::loadFromFile(const QString &fileName)
|
||||
{
|
||||
QFile file(fileName);
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
file.open(QIODevice::ReadOnly);
|
||||
if (!file.isOpen()) {
|
||||
return FileError;
|
||||
}
|
||||
|
||||
|
|
@ -88,9 +84,10 @@ LoadStatus CardDatabaseLoader::loadCardDatabases()
|
|||
|
||||
database->clear(); // remove old db
|
||||
|
||||
LoadStatus loadStatus = loadCardDatabase(pathProvider->getCardDatabasePath()); // load main card database
|
||||
loadCardDatabase(pathProvider->getTokenDatabasePath()); // load tokens database
|
||||
loadCardDatabase(pathProvider->getSpoilerCardDatabasePath()); // load spoilers database
|
||||
LoadStatus loadStatus =
|
||||
loadCardDatabase(SettingsCache::instance().getCardDatabasePath()); // load main card database
|
||||
loadCardDatabase(SettingsCache::instance().getTokenDatabasePath()); // load tokens database
|
||||
loadCardDatabase(SettingsCache::instance().getSpoilerCardDatabasePath()); // load spoilers database
|
||||
|
||||
// find all custom card databases, recursively & following symlinks
|
||||
// then load them alphabetically
|
||||
|
|
@ -121,7 +118,7 @@ LoadStatus CardDatabaseLoader::loadCardDatabases()
|
|||
|
||||
QStringList CardDatabaseLoader::collectCustomDatabasePaths() const
|
||||
{
|
||||
QDirIterator it(pathProvider->getCustomCardDatabasePath(), {"*.xml"}, QDir::Files,
|
||||
QDirIterator it(SettingsCache::instance().getCustomCardDatabasePath(), {"*.xml"}, QDir::Files,
|
||||
QDirIterator::Subdirectories | QDirIterator::FollowSymlinks);
|
||||
|
||||
QStringList paths;
|
||||
|
|
@ -138,7 +135,7 @@ bool CardDatabaseLoader::saveCustomTokensToFile()
|
|||
return false;
|
||||
}
|
||||
|
||||
QString fileName = pathProvider->getCustomCardDatabasePath() + "/" + CardSet::TOKENS_SETNAME + ".xml";
|
||||
QString fileName = SettingsCache::instance().getCustomCardDatabasePath() + "/" + CardSet::TOKENS_SETNAME + ".xml";
|
||||
|
||||
SetNameMap tmpSets;
|
||||
CardSetPtr customTokensSet = database->getSet(CardSet::TOKENS_SETNAME);
|
||||
|
|
@ -151,6 +148,6 @@ bool CardDatabaseLoader::saveCustomTokensToFile()
|
|||
}
|
||||
}
|
||||
|
||||
availableParsers.first()->saveToFile(FormatRulesNameMap(), tmpSets, tmpCards, fileName);
|
||||
availableParsers.first()->saveToFile(tmpSets, tmpCards, fileName);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
57
cockatrice/src/database/card_database_loader.h
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
#ifndef COCKATRICE_CARD_DATABASE_LOADER_H
|
||||
#define COCKATRICE_CARD_DATABASE_LOADER_H
|
||||
|
||||
#include <QBasicMutex>
|
||||
#include <QList>
|
||||
#include <QLoggingCategory>
|
||||
#include <QObject>
|
||||
|
||||
inline Q_LOGGING_CATEGORY(CardDatabaseLoadingLog, "card_database.loading");
|
||||
inline Q_LOGGING_CATEGORY(CardDatabaseLoadingSuccessOrFailureLog, "card_database.loading.success_or_failure");
|
||||
|
||||
class CardDatabase;
|
||||
class ICardDatabaseParser;
|
||||
|
||||
enum LoadStatus
|
||||
{
|
||||
Ok,
|
||||
VersionTooOld,
|
||||
Invalid,
|
||||
NotLoaded,
|
||||
FileError,
|
||||
NoCards
|
||||
};
|
||||
|
||||
class CardDatabaseLoader : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit CardDatabaseLoader(QObject *parent, CardDatabase *db);
|
||||
~CardDatabaseLoader() override;
|
||||
|
||||
public slots:
|
||||
LoadStatus loadCardDatabases(); // discover & load the configured databases
|
||||
LoadStatus loadCardDatabase(const QString &path); // load a single file
|
||||
bool saveCustomTokensToFile(); // write tokens to custom DB path
|
||||
|
||||
signals:
|
||||
void loadingStarted();
|
||||
void loadingFinished();
|
||||
void loadingFailed();
|
||||
void newSetsFound(int numSets, const QStringList &setNames);
|
||||
void allNewSetsEnabled();
|
||||
|
||||
private:
|
||||
LoadStatus loadFromFile(const QString &fileName); // internal helper
|
||||
QStringList collectCustomDatabasePaths() const;
|
||||
|
||||
CardDatabase *database; // non-owning pointer to the container
|
||||
|
||||
// parsers
|
||||
QList<ICardDatabaseParser *> availableParsers;
|
||||
|
||||
QBasicMutex *loadFromFileMutex = new QBasicMutex();
|
||||
QBasicMutex *reloadDatabaseMutex = new QBasicMutex();
|
||||
};
|
||||
|
||||
#endif // COCKATRICE_CARD_DATABASE_LOADER_H
|
||||
12
cockatrice/src/database/card_database_manager.cpp
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#include "card_database_manager.h"
|
||||
|
||||
CardDatabase *CardDatabaseManager::getInstance()
|
||||
{
|
||||
static CardDatabase instance; // Created only once, on first access
|
||||
return &instance;
|
||||
}
|
||||
|
||||
CardDatabaseQuerier *CardDatabaseManager::query()
|
||||
{
|
||||
return getInstance()->query();
|
||||
}
|
||||
23
cockatrice/src/database/card_database_manager.h
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef CARD_DATABASE_ACCESSOR_H
|
||||
#define CARD_DATABASE_ACCESSOR_H
|
||||
|
||||
#pragma once
|
||||
#include "card_database.h"
|
||||
|
||||
class CardDatabaseManager
|
||||
{
|
||||
public:
|
||||
// Delete copy constructor and assignment operator to enforce singleton
|
||||
CardDatabaseManager(const CardDatabaseManager &) = delete;
|
||||
CardDatabaseManager &operator=(const CardDatabaseManager &) = delete;
|
||||
|
||||
// Static method to access the singleton instance
|
||||
static CardDatabase *getInstance();
|
||||
static CardDatabaseQuerier *query();
|
||||
|
||||
private:
|
||||
CardDatabaseManager() = default; // Private constructor
|
||||
~CardDatabaseManager() = default;
|
||||
};
|
||||
|
||||
#endif // CARD_DATABASE_ACCESSOR_H
|
||||
|
|
@ -1,16 +1,11 @@
|
|||
#include "card_database_querier.h"
|
||||
|
||||
#include "../card_info.h"
|
||||
#include "../printing/exact_card.h"
|
||||
#include "../set/card_set_comparator.h"
|
||||
#include "../utility/card_set_comparator.h"
|
||||
#include "card_database.h"
|
||||
|
||||
#include <qrandom.h>
|
||||
|
||||
CardDatabaseQuerier::CardDatabaseQuerier(QObject *_parent,
|
||||
const CardDatabase *_db,
|
||||
const ICardPreferenceProvider *prefs)
|
||||
: QObject(_parent), db(_db), prefs(prefs)
|
||||
CardDatabaseQuerier::CardDatabaseQuerier(QObject *_parent, const CardDatabase *_db) : QObject(_parent), db(_db)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -133,7 +128,7 @@ ExactCard CardDatabaseQuerier::getRandomCard() const
|
|||
ExactCard CardDatabaseQuerier::getCardFromSameSet(const QString &cardName, const PrintingInfo &otherPrinting) const
|
||||
{
|
||||
// The source card does not have a printing defined, which means we can't get a card from the same set.
|
||||
if (otherPrinting.isEmpty()) {
|
||||
if (otherPrinting == PrintingInfo()) {
|
||||
return getCard({cardName});
|
||||
}
|
||||
|
||||
|
|
@ -207,17 +202,6 @@ PrintingInfo CardDatabaseQuerier::getSpecificPrinting(const QString &cardName,
|
|||
return PrintingInfo(nullptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the card representing the preferred printing of the cardInfo
|
||||
*
|
||||
* @param cardName The cardName to find the preferred card and printing for
|
||||
* @return A specific printing of a card
|
||||
*/
|
||||
ExactCard CardDatabaseQuerier::getPreferredCard(const QString &cardName) const
|
||||
{
|
||||
return getPreferredCard(getCardInfo(cardName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the card representing the preferred printing of the cardInfo
|
||||
*
|
||||
|
|
@ -250,12 +234,6 @@ PrintingInfo CardDatabaseQuerier::getPreferredPrinting(const CardInfoPtr &cardIn
|
|||
return PrintingInfo(nullptr);
|
||||
}
|
||||
|
||||
const auto &pinnedPrintingProviderId = prefs->getCardPreferenceOverride(cardInfo->getName());
|
||||
|
||||
if (!pinnedPrintingProviderId.isEmpty()) {
|
||||
return getSpecificPrinting({cardInfo->getName(), pinnedPrintingProviderId});
|
||||
}
|
||||
|
||||
SetToPrintingsMap setMap = cardInfo->getSets();
|
||||
if (setMap.empty()) {
|
||||
return PrintingInfo(nullptr);
|
||||
|
|
@ -328,7 +306,11 @@ QMap<QString, int> CardDatabaseQuerier::getAllSubCardTypesWithCount() const
|
|||
QStringList parts = type.split(" — ");
|
||||
|
||||
if (parts.size() > 1) { // Ensure there are subtypes
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
QStringList subtypes = parts[1].split(" ", Qt::SkipEmptyParts);
|
||||
#else
|
||||
QStringList subtypes = parts[1].split(" ", QString::SkipEmptyParts);
|
||||
#endif
|
||||
|
||||
for (const QString &subtype : subtypes) {
|
||||
typeCounts[subtype]++;
|
||||
|
|
@ -337,27 +319,4 @@ QMap<QString, int> CardDatabaseQuerier::getAllSubCardTypesWithCount() const
|
|||
}
|
||||
|
||||
return typeCounts;
|
||||
}
|
||||
|
||||
FormatRulesPtr CardDatabaseQuerier::getFormat(const QString &formatName) const
|
||||
{
|
||||
return db->formats.value(formatName.toLower());
|
||||
}
|
||||
|
||||
QMap<QString, int> CardDatabaseQuerier::getAllFormatsWithCount() const
|
||||
{
|
||||
QMap<QString, int> formatCounts;
|
||||
|
||||
for (const auto &card : db->cards.values()) {
|
||||
QStringList allProps = card->getProperties();
|
||||
|
||||
for (const QString &prop : allProps) {
|
||||
if (prop.startsWith("format-")) {
|
||||
QString formatName = prop.mid(QStringLiteral("format-").size());
|
||||
formatCounts[formatName]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return formatCounts;
|
||||
}
|
||||
}
|
||||
54
cockatrice/src/database/card_database_querier.h
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
#ifndef COCKATRICE_CARD_DATABASE_QUERIER_H
|
||||
#define COCKATRICE_CARD_DATABASE_QUERIER_H
|
||||
|
||||
#include "../card/exact_card.h"
|
||||
#include "../common/card_ref.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class CardDatabase;
|
||||
class CardDatabaseQuerier : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CardDatabaseQuerier(QObject *parent, const CardDatabase *db);
|
||||
|
||||
[[nodiscard]] CardInfoPtr getCardInfo(const QString &cardName) const;
|
||||
[[nodiscard]] QList<CardInfoPtr> getCardInfos(const QStringList &cardNames) const;
|
||||
|
||||
/*
|
||||
* Get a card by its simple name. The name will be simplified in this
|
||||
* function, so you don't need to simplify it beforehand.
|
||||
*/
|
||||
[[nodiscard]] CardInfoPtr getCardBySimpleName(const QString &cardName) const;
|
||||
|
||||
[[nodiscard]] ExactCard guessCard(const CardRef &cardRef) const;
|
||||
[[nodiscard]] ExactCard getCard(const CardRef &cardRef) const;
|
||||
[[nodiscard]] QList<ExactCard> getCards(const QList<CardRef> &cardRefs) const;
|
||||
|
||||
[[nodiscard]] ExactCard getRandomCard() const;
|
||||
[[nodiscard]] ExactCard getCardFromSameSet(const QString &cardName, const PrintingInfo &otherPrinting) const;
|
||||
|
||||
[[nodiscard]] ExactCard getPreferredCard(const CardInfoPtr &card) const;
|
||||
[[nodiscard]] bool isPreferredPrinting(const CardRef &cardRef) const;
|
||||
[[nodiscard]] PrintingInfo getPreferredPrinting(const CardInfoPtr &card) const;
|
||||
[[nodiscard]] PrintingInfo getPreferredPrinting(const QString &cardName) const;
|
||||
[[nodiscard]] QString getPreferredPrintingProviderId(const QString &cardName) const;
|
||||
|
||||
[[nodiscard]] PrintingInfo getSpecificPrinting(const CardRef &cardRef) const;
|
||||
[[nodiscard]] PrintingInfo
|
||||
getSpecificPrinting(const QString &cardName, const QString &setCode, const QString &collectorNumber) const;
|
||||
[[nodiscard]] PrintingInfo findPrintingWithId(const CardInfoPtr &card, const QString &providerId) const;
|
||||
|
||||
[[nodiscard]] QStringList getAllMainCardTypes() const;
|
||||
[[nodiscard]] QMap<QString, int> getAllMainCardTypesWithCount() const;
|
||||
[[nodiscard]] QMap<QString, int> getAllSubCardTypesWithCount() const;
|
||||
|
||||
private:
|
||||
const CardDatabase *db;
|
||||
|
||||
CardInfoPtr lookupCardByName(const QString &name) const;
|
||||
};
|
||||
|
||||
#endif // COCKATRICE_CARD_DATABASE_QUERIER_H
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
#ifndef COCKATRICE_SETTINGS_CARD_PREFERENCE_PROVIDER_H
|
||||
#define COCKATRICE_SETTINGS_CARD_PREFERENCE_PROVIDER_H
|
||||
#include "../../client/settings/cache_settings.h"
|
||||
|
||||
#include <libcockatrice/interfaces/interface_card_preference_provider.h>
|
||||
|
||||
class SettingsCardPreferenceProvider : public ICardPreferenceProvider
|
||||
{
|
||||
public:
|
||||
[[nodiscard]] QString getCardPreferenceOverride(const QString &cardName) const override
|
||||
{
|
||||
return SettingsCache::instance().cardOverrides().getCardPreferenceOverride(cardName);
|
||||
}
|
||||
|
||||
[[nodiscard]] bool getIncludeRebalancedCards() const override
|
||||
{
|
||||
return SettingsCache::instance().getIncludeRebalancedCards();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // COCKATRICE_SETTINGS_CARD_PREFERENCE_PROVIDER_H
|
||||
|
|
@ -1,9 +1,3 @@
|
|||
/**
|
||||
* @file card_completer_proxy_model.h
|
||||
* @ingroup CardDatabaseModels
|
||||
* @brief TODO: Document this.
|
||||
*/
|
||||
|
||||
#ifndef CARD_COMPLETER_PROXY_MODEL_H
|
||||
#define CARD_COMPLETER_PROXY_MODEL_H
|
||||
|
||||
|
|
@ -16,7 +10,7 @@ public:
|
|||
explicit CardCompleterProxyModel(QObject *parent = nullptr);
|
||||
|
||||
protected:
|
||||
[[nodiscard]] bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
|
||||
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
|
||||
};
|
||||
|
||||
#endif // CARD_COMPLETER_PROXY_MODEL_H
|
||||
|
|
@ -1,10 +1,9 @@
|
|||
#include "card_search_model.h"
|
||||
|
||||
#include "../card_database_display_model.h"
|
||||
#include "../../../utility/levenshtein.h"
|
||||
#include "../card_database_model.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <libcockatrice/utility/levenshtein.h>
|
||||
|
||||
CardSearchModel::CardSearchModel(CardDatabaseDisplayModel *sourceModel, QObject *parent)
|
||||
: QAbstractListModel(parent), sourceModel(sourceModel)
|
||||
|
|
@ -1,9 +1,3 @@
|
|||
/**
|
||||
* @file card_search_model.h
|
||||
* @ingroup CardDatabaseModels
|
||||
* @brief TODO: Document this.
|
||||
*/
|
||||
|
||||
#ifndef CARD_SEARCH_MODEL_H
|
||||
#define CARD_SEARCH_MODEL_H
|
||||
|
||||
|
|
@ -17,8 +11,8 @@ class CardSearchModel : public QAbstractListModel
|
|||
public:
|
||||
explicit CardSearchModel(CardDatabaseDisplayModel *sourceModel, QObject *parent = nullptr);
|
||||
|
||||
[[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
[[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
void updateSearchResults(const QString &query); // Update results based on input
|
||||
|
||||
|
|
@ -184,20 +184,13 @@ bool CardDatabaseDisplayModel::rowMatchesCardName(CardInfoPtr info) const
|
|||
|
||||
void CardDatabaseDisplayModel::clearFilterAll()
|
||||
{
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 9, 0))
|
||||
beginFilterChange();
|
||||
#endif
|
||||
cardName.clear();
|
||||
cardText.clear();
|
||||
cardTypes.clear();
|
||||
cardColors.clear();
|
||||
if (filterTree != nullptr)
|
||||
filterTree->clear();
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 10, 0))
|
||||
endFilterChange(QSortFilterProxyModel::Direction::Rows);
|
||||
#else
|
||||
invalidateFilter();
|
||||
#endif
|
||||
}
|
||||
|
||||
void CardDatabaseDisplayModel::setFilterTree(FilterTree *_filterTree)
|
||||
|
|
@ -224,4 +217,4 @@ const QString CardDatabaseDisplayModel::sanitizeCardName(const QString &dirtyNam
|
|||
}
|
||||
}
|
||||
return QString::fromStdWString(toReturn);
|
||||
}
|
||||
}
|
||||