Compare commits

..

18 Commits

Author SHA1 Message Date
tooomm
ad7e1795db tweaks 2022-01-19 01:06:22 +01:00
tooomm
8b809826d5 fix 2022-01-19 00:10:09 +01:00
tooomm
121fcf09d4 rewording 2022-01-19 00:09:23 +01:00
tooomm
717a272291 Update dlg_settings.cpp 2022-01-18 23:37:25 +01:00
tooomm
4fc81b159d fix label 2022-01-18 23:23:32 +01:00
tooomm
66bcedd9c4 reorder 2022-01-18 23:16:04 +01:00
tooomm
c450471f12 Update dlg_settings.cpp 2022-01-18 22:52:10 +01:00
tooomm
56fb4e09e0 hex label 2022-01-18 22:45:55 +01:00
tooomm
7a7db574b3 stretch adjustments 2022-01-18 22:01:32 +01:00
tooomm
5f8d5479da fix 2022-01-18 21:34:50 +01:00
tooomm
1538d4b187 set column stretch 2022-01-18 21:32:30 +01:00
tooomm
0ea4a73fd2 fix 2022-01-18 21:26:01 +01:00
tooomm
cb5b8d34b2 simplify hex hint 2022-01-18 21:14:01 +01:00
tooomm
a7faa5c139 clear buttons 2022-01-18 21:00:42 +01:00
tooomm
6561ca216c Revert "grid adjustments"
This reverts commit 2f924ccb4e.
2022-01-18 20:58:31 +01:00
tooomm
2f924ccb4e grid adjustments 2022-01-18 20:34:13 +01:00
tooomm
f98809eabf adjust span 2022-01-18 16:40:26 +01:00
tooomm
71b79915d3 fix layout 2022-01-18 15:29:36 +01:00
531 changed files with 85988 additions and 123615 deletions

View File

@@ -8,11 +8,9 @@ RUN pacman --sync --refresh --sysupgrade --needed --noconfirm \
gtest \
mariadb-libs \
protobuf \
qt6-base \
qt6-imageformats \
qt6-multimedia \
qt6-svg \
qt6-tools \
qt6-translations \
qt6-websockets \
qt5-base \
qt5-multimedia \
qt5-svg \
qt5-tools \
qt5-websockets \
&& pacman --sync --clean --clean --noconfirm

24
.ci/Debian10/Dockerfile Normal file
View File

@@ -0,0 +1,24 @@
FROM debian:10
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
ccache \
clang-format \
cmake \
file \
g++ \
git \
liblzma-dev \
libmariadb-dev-compat \
libprotobuf-dev \
libqt5multimedia5-plugins \
libqt5sql5-mysql \
libqt5svg5-dev \
libqt5websockets5-dev \
protobuf-compiler \
qt5-default \
qtbase5-dev \
qtmultimedia5-dev \
qttools5-dev-tools \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

View File

@@ -17,7 +17,6 @@ RUN apt-get update && \
libqt5svg5-dev \
libqt5websockets5-dev \
protobuf-compiler \
qt5-image-formats-plugins \
qtmultimedia5-dev \
qttools5-dev \
qttools5-dev-tools \

21
.ci/Fedora34/Dockerfile Normal file
View File

@@ -0,0 +1,21 @@
FROM fedora:34
RUN dnf install -y \
@development-tools \
ccache \
cmake \
desktop-file-utils \
file \
gcc-c++ \
git \
hicolor-icon-theme \
libappstream-glib \
mariadb-devel \
protobuf-devel \
qt5-{qttools,qtsvg,qtmultimedia,qtwebsockets}-devel \
rpm-build \
sqlite-devel \
wget \
xz-devel \
zlib-devel \
&& dnf clean all

21
.ci/Fedora35/Dockerfile Normal file
View File

@@ -0,0 +1,21 @@
FROM fedora:35
RUN dnf install -y \
@development-tools \
ccache \
cmake \
desktop-file-utils \
file \
gcc-c++ \
git \
hicolor-icon-theme \
libappstream-glib \
mariadb-devel \
protobuf-devel \
qt5-{qttools,qtsvg,qtmultimedia,qtwebsockets}-devel \
rpm-build \
sqlite-devel \
wget \
xz-devel \
zlib-devel \
&& dnf clean all

View File

@@ -1,15 +0,0 @@
FROM fedora:39
RUN dnf install -y \
ccache \
cmake \
gcc-c++ \
git \
mariadb-devel \
protobuf-devel \
qt6-{qttools,qtsvg,qtmultimedia,qtwebsockets}-devel \
qt6-qtimageformats \
rpm-build \
xz-devel \
zlib-devel \
&& dnf clean all

View File

@@ -1,15 +0,0 @@
FROM fedora:40
RUN dnf install -y \
ccache \
cmake \
gcc-c++ \
git \
mariadb-devel \
protobuf-devel \
qt6-{qttools,qtsvg,qtmultimedia,qtwebsockets}-devel \
qt6-qtimageformats \
rpm-build \
xz-devel \
zlib-devel \
&& dnf clean all

View File

@@ -17,7 +17,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
libqt5websockets5-dev \
protobuf-compiler \
qt5-default \
qt5-image-formats-plugins \
qtmultimedia5-dev \
qttools5-dev \
qttools5-dev-tools \

View File

@@ -18,7 +18,6 @@ RUN apt-get update && \
libqt5websockets5-dev \
protobuf-compiler \
qt5-default \
qt5-image-formats-plugins \
qtmultimedia5-dev \
qttools5-dev \
qttools5-dev-tools \

View File

@@ -1,4 +1,4 @@
FROM debian:12
FROM ubuntu:hirsute
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
@@ -9,19 +9,16 @@ RUN apt-get update && \
file \
g++ \
git \
libgl-dev \
liblzma-dev \
libmariadb-dev-compat \
libprotobuf-dev \
libqt6multimedia6 \
libqt6sql6-mysql \
qt6-svg-dev \
qt6-websockets-dev \
libqt5multimedia5-plugins \
libqt5sql5-mysql \
libqt5svg5-dev \
libqt5websockets5-dev \
protobuf-compiler \
qt6-image-formats-plugins \
qt6-l10n-tools \
qt6-multimedia-dev \
qt6-tools-dev \
qt6-tools-dev-tools \
qtmultimedia5-dev \
qttools5-dev \
qttools5-dev-tools \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

View File

@@ -1,4 +1,4 @@
FROM ubuntu:noble
FROM ubuntu:impish
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
@@ -9,19 +9,16 @@ RUN apt-get update && \
file \
g++ \
git \
libgl-dev \
liblzma-dev \
libmariadb-dev-compat \
libprotobuf-dev \
libqt6multimedia6 \
libqt6sql6-mysql \
qt6-svg-dev \
qt6-websockets-dev \
libqt5multimedia5-plugins \
libqt5sql5-mysql \
libqt5svg5-dev \
libqt5websockets5-dev \
protobuf-compiler \
qt6-image-formats-plugins \
qt6-l10n-tools \
qt6-multimedia-dev \
qt6-tools-dev \
qt6-tools-dev-tools \
qtmultimedia5-dev \
qttools5-dev \
qttools5-dev-tools \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

View File

@@ -1,27 +0,0 @@
FROM ubuntu:jammy
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
build-essential \
ccache \
clang-format \
cmake \
file \
g++ \
git \
libgl-dev \
liblzma-dev \
libmariadb-dev-compat \
libprotobuf-dev \
libqt6multimedia6 \
libqt6sql6-mysql \
libqt6svg6-dev \
libqt6websockets6-dev \
protobuf-compiler \
qt6-image-formats-plugins \
qt6-l10n-tools \
qt6-multimedia-dev \
qt6-tools-dev \
qt6-tools-dev-tools \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

View File

@@ -2,26 +2,16 @@
# This script is to be used by the ci environment from the project root directory, do not use it from somewhere else.
# Compiles cockatrice inside of a ci environment
# --install runs make install
# --package [<package type>] runs make package, optionally force the type
# --suffix <suffix> renames package with this suffix, requires arg
# --server compiles servatrice
# --test runs tests
# --debug or --release sets the build type ie CMAKE_BUILD_TYPE
# --ccache [<size>] uses ccache and shows stats, optionally provide size
# --dir <dir> sets the name of the build dir, default is "build"
# --parallel <core count> sets how many cores cmake should build with in parallel
# uses env: BUILDTYPE MAKE_INSTALL MAKE_PACKAGE PACKAGE_TYPE PACKAGE_SUFFIX MAKE_SERVER MAKE_TEST USE_CCACHE CCACHE_SIZE BUILD_DIR PARALLEL_COUNT
# (correspond to args: --debug/--release --install --package <package type> --suffix <suffix> --server --test --ccache <ccache_size> --dir <dir> --parallel <core_count>)
# exitcode: 1 for failure, 3 for invalid arguments
# Read arguments
while [[ $# != 0 ]]; do
while [[ "$@" ]]; do
case "$1" in
'--')
shift
;;
'--format')
CHECK_FORMAT=1
shift
;;
'--install')
MAKE_INSTALL=1
shift
@@ -29,7 +19,7 @@ while [[ $# != 0 ]]; do
'--package')
MAKE_PACKAGE=1
shift
if [[ $# != 0 && ${1:0:1} != - ]]; then
if [[ $# != 0 && $1 != -* ]]; then
PACKAGE_TYPE="$1"
shift
fi
@@ -38,7 +28,7 @@ while [[ $# != 0 ]]; do
shift
if [[ $# == 0 ]]; then
echo "::error file=$0::--suffix expects an argument"
exit 3
exit 1
fi
PACKAGE_SUFFIX="$1"
shift
@@ -62,140 +52,101 @@ while [[ $# != 0 ]]; do
'--ccache')
USE_CCACHE=1
shift
if [[ $# != 0 && ${1:0:1} != - ]]; then
CCACHE_SIZE="$1"
shift
fi
;;
'--dir')
shift
if [[ $# == 0 ]]; then
echo "::error file=$0::--dir expects an argument"
exit 3
fi
BUILD_DIR="$1"
shift
;;
'--parallel')
shift
if [[ $# == 0 ]]; then
echo "::error file=$0::--parallel expects an argument"
exit 3
fi
PARALLEL_COUNT="$1"
shift
;;
*)
echo "::error file=$0::unrecognized option: $1"
exit 3
if [[ $1 == -* ]]; then
echo "::error file=$0::unrecognized option: $1"
exit 3
fi
BUILDTYPE="$1"
shift
;;
esac
done
# Check formatting using clang-format
if [[ $CHECK_FORMAT ]]; then
echo "::group::Run linter"
source ./.ci/lint.sh
echo "::endgroup::"
fi
set -e
# Setup
./servatrice/check_schema_version.sh
if [[ ! $BUILDTYPE ]]; then
BUILDTYPE=Release
mkdir -p build
cd build
if [[ ! $CMAKE_BUILD_PARALLEL_LEVEL ]]; then
CMAKE_BUILD_PARALLEL_LEVEL=2 # default machines have 2 cores
fi
if [[ ! $BUILD_DIR ]]; then
BUILD_DIR="build"
fi
mkdir -p "$BUILD_DIR"
cd "$BUILD_DIR"
# Add cmake flags
flags=("-DCMAKE_BUILD_TYPE=$BUILDTYPE")
if [[ $MAKE_SERVER ]]; then
flags+=("-DWITH_SERVER=1")
flags+=" -DWITH_SERVER=1"
fi
if [[ $MAKE_TEST ]]; then
flags+=("-DTEST=1")
flags+=" -DTEST=1"
fi
if [[ $USE_CCACHE ]]; then
flags+=("-DUSE_CCACHE=1")
if [[ $CCACHE_SIZE ]]; then
# note, this setting persists after running the script
ccache --max-size "$CCACHE_SIZE"
fi
if [[ $BUILDTYPE ]]; then
flags+=" -DCMAKE_BUILD_TYPE=$BUILDTYPE"
fi
if [[ $PACKAGE_TYPE ]]; then
flags+=("-DCPACK_GENERATOR=$PACKAGE_TYPE")
flags+=" -DCPACK_GENERATOR=$PACKAGE_TYPE"
fi
# Add cmake --build flags
buildflags=(--config "$BUILDTYPE")
if [[ $PARALLEL_COUNT ]]; then
if [[ $(cmake --build /not_a_dir --parallel 2>&1 | head -1) =~ parallel ]]; then
# workaround for bionic having an old cmake
echo "this version of cmake does not support --parallel, using native build tool -j instead"
buildflags+=(-- -j "$PARALLEL_COUNT")
# note, no normal build flags should be added after this
else
buildflags+=(--parallel "$PARALLEL_COUNT")
if [[ $(uname) == "Darwin" ]]; then
if [[ $USE_CCACHE ]]; then
# prepend ccache compiler binaries to path
PATH="/usr/local/opt/ccache/libexec:$PATH"
fi
# Add qt install location when using homebrew
flags+=" -DCMAKE_PREFIX_PATH=/usr/local/opt/qt5/"
fi
function ccachestatsverbose() {
# note, verbose only works on newer ccache, discard the error
local got
if got="$(ccache --show-stats --verbose 2>/dev/null)"; then
echo "$got"
else
ccache --show-stats
fi
}
# Compile
if [[ $USE_CCACHE ]]; then
echo "::group::Show ccache stats"
ccachestatsverbose
ccache --show-stats
echo "::endgroup::"
fi
echo "::group::Configure cmake"
cmake --version
cmake .. "${flags[@]}"
cmake .. $flags
echo "::endgroup::"
echo "::group::Build project"
if [[ $RUNNER_OS == Windows ]]; then
# Enable MTT, see https://devblogs.microsoft.com/cppblog/improved-parallelism-in-msbuild/
# and https://devblogs.microsoft.com/cppblog/cpp-build-throughput-investigation-and-tune-up/#multitooltask-mtt
cmake --build . "${buildflags[@]}" -- -p:UseMultiToolTask=true -p:EnableClServerMode=true
else
cmake --build . "${buildflags[@]}"
fi
cmake --build .
echo "::endgroup::"
if [[ $USE_CCACHE ]]; then
echo "::group::Show ccache stats again"
ccachestatsverbose
ccache --show-stats
echo "::endgroup::"
fi
if [[ $MAKE_TEST ]]; then
echo "::group::Run tests"
ctest -C "$BUILDTYPE" --output-on-failure
cmake --build . --target test
echo "::endgroup::"
fi
if [[ $MAKE_INSTALL ]]; then
echo "::group::Install"
cmake --build . --target install --config "$BUILDTYPE"
cmake --build . --target install
echo "::endgroup::"
fi
if [[ $MAKE_PACKAGE ]]; then
echo "::group::Create package"
cmake --build . --target package --config "$BUILDTYPE"
cmake --build . --target package
echo "::endgroup::"
if [[ $PACKAGE_SUFFIX ]]; then
echo "::group::Update package name"
cd ..
BUILD_DIR="$BUILD_DIR" .ci/name_build.sh "$PACKAGE_SUFFIX"
../.ci/name_build.sh "$PACKAGE_SUFFIX"
echo "::endgroup::"
fi
fi

View File

@@ -3,15 +3,11 @@
# 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.
# <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)
# uses env: NAME CACHE BUILD GET SAVE (correspond to args: <name> --set-cache <cache> --build --get --save)
# 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
export BUILD_SCRIPT=".ci/compile.sh"
@@ -22,7 +18,7 @@ image_cache="image"
ccache_cache=".ccache"
# Read arguments
while [[ $# != 0 ]]; do
while [[ "$@" ]]; do
case "$1" in
'--build')
BUILD=1
@@ -32,10 +28,6 @@ while [[ $# != 0 ]]; do
GET=1
shift
;;
'--interactive')
INTERACTIVE=1
shift
;;
'--save')
SAVE=1
shift
@@ -44,12 +36,12 @@ while [[ $# != 0 ]]; do
CACHE=$2
if ! [[ -d $CACHE ]]; then
echo "could not find cache path: $CACHE" >&2
return 3
exit 3
fi
shift 2
;;
*)
if [[ ${1:0:1} == - ]]; then
if [[ $1 == -* ]]; then
echo "unrecognized option: $1"
return 3
fi
@@ -75,27 +67,27 @@ fi
if ! [[ $CACHE ]]; then
echo "cache dir is not set!" >&2
CACHE="$(mktemp -d)"
echo "set cache dir to $CACHE" >&2
fi
if ! [[ -d $CACHE ]]; then
echo "could not find cache dir: $CACHE" >&2
mkdir -p "$CACHE"
unset GET # the dir is empty
fi
if [[ $GET || $SAVE ]]; then
img_dir="$CACHE/$image_cache"
img_save="$img_dir/$IMAGE_NAME$save_extension"
if ! [[ -d $img_dir ]]; then
echo "could not find image dir: $img_dir" >&2
mkdir -p "$img_dir"
else
if ! [[ -d $CACHE ]]; then
echo "could not find cache dir: $CACHE" >&2
mkdir -p $CACHE
unset GET # the dir is empty
fi
if [[ $GET || $SAVE ]]; then
img_dir="$CACHE/$image_cache"
img_save="$img_dir/$IMAGE_NAME$save_extension"
if ! [[ -d $img_dir ]]; then
echo "could not find image dir: $img_dir" >&2
mkdir -p "$img_dir"
fi
fi
export CCACHE_DIR="$CACHE/$ccache_cache"
if ! [[ -d $CCACHE_DIR ]]; then
echo "could not find ccache dir: $CCACHE_DIR" >&2
mkdir -p "$CCACHE_DIR"
fi
fi
export CCACHE_DIR="$CACHE/$ccache_cache"
if ! [[ -d $CCACHE_DIR ]]; then
echo "could not find ccache dir: $CCACHE_DIR" >&2
mkdir -p "$CCACHE_DIR"
fi
# Get the docker image from previously stored save
if [[ $GET ]]; then
@@ -140,26 +132,15 @@ fi
function RUN ()
{
echo "running image:"
if [[ $(docker images) =~ "$IMAGE_NAME" ]]; then
local args=(--mount "type=bind,source=$PWD,target=/src")
args+=(--workdir "/src")
args+=(--user "$(id -u):$(id -g)")
if docker images | grep "$IMAGE_NAME"; then
args="--mount type=bind,source=$PWD,target=/src -w=/src"
if [[ $CCACHE_DIR ]]; then
args+=(--mount "type=bind,source=$CCACHE_DIR,target=/.ccache")
args+=(--env "CCACHE_DIR=/.ccache")
args+=" --mount type=bind,source=$CCACHE_DIR,target=/.ccache -e CCACHE_DIR=/.ccache"
fi
docker run "${args[@]}" $RUN_ARGS "$IMAGE_NAME" bash "$BUILD_SCRIPT" $RUN_OPTS "$@"
docker run $args $RUN_ARGS "$IMAGE_NAME" bash "$BUILD_SCRIPT" $RUN_OPTS $@
return $?
else
echo "could not find docker image: $IMAGE_NAME" >&2
return 3
fi
}
# for debugging, start the docker image interactively instead of building
# starts immediately, does not require sourcing or RUN
if [[ $INTERACTIVE ]]; then
export BUILD_SCRIPT="-i"
export RUN_ARGS="$RUN_ARGS -it"
RUN
fi

View File

@@ -10,10 +10,10 @@ if ! git merge-base origin/master HEAD; then
git fetch --unshallow
fi
# Check formatting using format.sh
echo "Checking your code using clang-format/cmake-format..."
# Check formatting using clangify
echo "Checking your code using clang-format..."
diff="$(./format.sh --diff --cmake --cf-version --branch origin/master)"
diff="$(./clangify.sh --diff --cf-version --branch origin/master)"
err=$?
case $err in
@@ -24,7 +24,7 @@ case $err in
*** ***
*** Your code does not comply with our style guide. ***
*** ***
*** Please correct it or run the "format.sh" script. ***
*** Please correct it or run the "clangify.sh" script. ***
*** Then commit and push those changes to this branch. ***
*** Check our CONTRIBUTING.md file for more details. ***
*** ***
@@ -32,23 +32,21 @@ case $err in
*** ***
***********************************************************
Used version:
Used clang-format version:
${diff%%
----------
*}
The following changes should be made:
${diff#*
----------
}
Exiting...
EOM
exit 2
;;
exit 2
;;
0)
cat <<EOM
0)
cat <<EOM
***********************************************************
*** ***
@@ -60,10 +58,12 @@ EOM
Exiting...
EOM
exit 0
;;
exit 0
;;
*)
echo "Something went wrong in our formatting checks: format.sh returned $err" >&2
;;
esac
*)
echo ""
echo "Something went wrong in our formatting checks: clangify returned $err" >&2
echo ""
;;
esac

View File

@@ -3,9 +3,8 @@
# 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:=.}"
# expected to be run in the build directory
builddir="."
findrx="Cockatrice-*.*"
if [[ $1 ]]; then
@@ -28,7 +27,6 @@ if [[ ! $file ]]; then
echo "::error file=$0::could not find package"
exit 1
fi
oldpwd="$PWD"
if ! cd "$path"; then
echo "::error file=$0::could not get file path"
exit 1
@@ -47,9 +45,6 @@ else
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=$filename" >>"$GITHUB_OUTPUT"
ls -l "$PWD/$filename"
echo "::set-output name=path::$PWD/$filename"
echo "::set-output name=name::$filename"

View File

@@ -4,7 +4,6 @@
# the releases are first made as drafts and will be vetted by a human
# it just has to provide a template
# this requires the repo to be unshallowed
# adds output to GITHUB_OUTPUT
template_path=".ci/release_template.md"
body_path="/tmp/release.md"
beta_regex='beta'
@@ -23,22 +22,22 @@ fi
# create title
if [[ $TAG =~ $beta_regex ]]; then
echo "is_beta=yes" >>"$GITHUB_OUTPUT"
echo "::set-output name=is_beta::yes"
title="$TAG"
echo "creating beta release '$title'"
elif [[ ! $(cat CMakeLists.txt) =~ $name_regex ]]; then
echo "::error file=$0::could not find releasename in CMakeLists.txt"
exit 1
else
echo "is_beta=no" >>"$GITHUB_OUTPUT"
echo "::set-output name=is_beta::no"
name="${BASH_REMATCH[1]}"
version="${TAG##*-}"
title="Cockatrice $version: $name"
no_beta=1
echo "friendly_name=$name" >>"$GITHUB_OUTPUT"
echo "::set-output name=friendly_name::$name"
echo "creating full release '$title'"
fi
echo "title=$title" >>"$GITHUB_OUTPUT"
echo "::set-output name=title::$title"
# add release notes template
if [[ $no_beta ]]; then
@@ -61,9 +60,9 @@ fi
all_tags="
$(git tag)" # tags are ordered alphabetically
before="${all_tags%%
"$TAG"*}" # strip line with current tag an all lines after it
$TAG*}" # strip line with current tag an all lines after it
# note the extra newlines are needed to always have a last line
if [[ $all_tags == "$before" ]]; then
if [[ $all_tags == $before ]]; then
echo "::warning file=$0::could not find current tag"
else
while
@@ -75,7 +74,7 @@ else
beta_list+=" $previous" # add to list of skipped betas
next_before="${before%
*}" # strip the last line
if [[ $next_before == "$before" ]]; then
if [[ $next_before == $before ]]; then
unset previous
break
fi
@@ -109,5 +108,5 @@ else
fi
# write to file
echo "body_path=$body_path" >>"$GITHUB_OUTPUT"
echo "::set-output name=body_path::$body_path"
echo "$body" >"$body_path"

View File

@@ -8,25 +8,26 @@ git push -d origin --REPLACE-WITH-BETA-LIST--
include different targets -->
<pre>
<b>Pre-compiled binaries we serve:</b>
- <kbd>Windows 7+</kbd>
- <kbd>Windows 10+</kbd>
- <kbd>macOS 10.15+</kbd> ("Catalina")
- <kbd>macOS 13+</kbd> ("Ventura")
- <kbd>Ubuntu 18.04 LTS</kbd> ("Bionic Beaver")
- <kbd>Ubuntu 20.04 LTS</kbd> ("Focal Fossa")
- <kbd>Ubuntu 22.04 LTS</kbd> ("Jammy Jellyfish")
- <kbd>Ubuntu 24.04 LTS</kbd> ("Noble Numbat")
- <kbd>Debian 11</kbd> ("Bullseye")
- <kbd>Debian 12</kbd> ("Bookworm")
- <kbd>Fedora 39</kbd>
- <kbd>Fedora 40</kbd>
- <kbd>Windows 7/8/10 (32-bit)</kbd></i>
- <kbd>Windows 7/8/10 (64-bit)</kbd></i>
- <kbd>macOS 10.14</kbd> ("Mojave")</i>
- <kbd>macOS 10.15</kbd> ("Catalina")</i>
- <kbd>macOS 11.0</kbd> ("Big Sur")</i>
- <kbd>Ubuntu 18.04</kbd> ("Bionic Beaver")</i>
- <kbd>Ubuntu 20.04</kbd> ("Focal Fossa")</i>
- <kbd>Ubuntu 20.10</kbd> ("Groovy Gorilla")</i>
- <kbd>Ubuntu 21.04</kbd> ("Hirsute Hippo")</i>
- <kbd>Debian 10</kbd> ("Buster")</i>
- <kbd>Fedora 33</kbd></i>
- <kbd>Fedora 34</kbd></i>
<kbd>We are also packaged in Arch Linux's official community repository, courtesy of @FFY00</kbd></i>
<kbd>General Linux support is available via a flatpak package (Flathub)</kbd></i>
<kbd>General linux support is available via a flatpak package (Flathub)</kbd></i>
</pre>
## General Notes
<!-- --REPLACE-WITH-RELEASE-TITLE-- should be placed here by the ci -->
We're pleased to announce the newest official release: <kbd>--REPLACE-WITH-RELEASE-TITLE--</kbd>
We hope you enjoy the changes made and we have listed all changes, with their corresponding tickets, since the last version of Cockatrice was released for your convenience.

View File

@@ -1,58 +0,0 @@
#!/bin/bash
# ci script to update translation files
# usage:
# $0 cockatrice/cockatrice_en@source.ts cockatrice/src common
# or
# FILE="cockatrice/cockatrice_en@source.ts"
# DIRS="cockatrice/src common"
# $0
# note: directories can't contain spaces
# check parameters
if [[ ! $FILE ]]; then
FILE="$1"
shift
fi
if [[ ! $FILE ]]; then
echo "no output file selected" >&2
exit 2;
fi
if [[ ! $DIRS ]]; then
DIRS="$*"
fi
if [[ ! $DIRS ]]; then
echo "no source directories selected to translate" >&2
exit 2;
fi
if [[ ! -e $FILE ]]; then
echo "output file does not exist at: $FILE" >&2
exit 3;
fi
# print version
if ! lupdate -version; then
echo "failed to run lupdate" >&2
exit 4;
fi
# run lupdate, duplicating the output in stderr and saving it
# for convenience we ignore that $DIRS will be split on spaces
# shellcheck disable=SC2086
if ! got="$(lupdate $DIRS -ts "$FILE" | tee /dev/stderr)"; then
echo "failed to update $FILE with $DIRS" >&2
exit 4;
fi
# trim output
# the line we are interested in is:
# Found xxx source text(s) (x new and xxx already existing)
output="${got##* source text(s) (}" # get stuff in between brackets
output="${output%%)*}" # trim everything after first )
if [[ $output == "$got" ]]; then
echo "could not parse generated output" >&2
exit 4;
fi
# write output to ci environment file
echo "output=$output" >> "$GITHUB_OUTPUT"

View File

@@ -1,14 +0,0 @@
Updated source strings for translations:
- {{ .cockatrice_output }} (Cockatrice)
- {{ .oracle_output }} (Oracle)
<br>
Last changes are based on commit {{ .commit }}.
---
*This PR is automatically generated and updated by the workflow at `.github/workflows/translations-push.yml`. Review [action runs][2].*<br>
*After merging, all changes to the source language are available for translation at [Transifex][1] shortly.*
[1]: https://app.transifex.com/cockatrice/cockatrice/
[2]: https://github.com/Cockatrice/Cockatrice/actions/workflows/translations-push.yml?query=branch%3Amaster

View File

@@ -1,109 +0,0 @@
{
"format": {
"_help_line_width": [
"How wide to allow formatted cmake files"
],
"line_width": 120,
"_help_tab_size": [
"How many spaces to tab for indent"
],
"tab_size": 2,
"_help_max_subgroups_hwrap": [
"If an argument group contains more than this many sub-groups",
"(parg or kwarg groups) then force it to a vertical layout."
],
"max_subgroups_hwrap": 2,
"_help_max_pargs_hwrap": [
"If a positional argument group contains more than this many",
"arguments, then force it to a vertical layout."
],
"max_pargs_hwrap": 6,
"_help_max_rows_cmdline": [
"If a cmdline positional group consumes more than this many",
"lines without nesting, then invalidate the layout (and nest)"
],
"max_rows_cmdline": 5,
"_help_separate_ctrl_name_with_space": [
"If true, separate flow control names from their parentheses",
"with a space"
],
"separate_ctrl_name_with_space": false,
"_help_separate_fn_name_with_space": [
"If true, separate function names from parentheses with a",
"space"
],
"separate_fn_name_with_space": false,
"_help_dangle_parens": [
"If a statement is wrapped to more than one line, than dangle",
"the closing parenthesis on its own line."
],
"dangle_parens": true,
"_help_dangle_align": [
"If the trailing parenthesis must be 'dangled' on its on",
"line, then align it to this reference: `prefix`: the start",
"of the statement, `prefix-indent`: the start of the",
"statement, plus one indentation level, `child`: align to",
"the column of the arguments"
],
"dangle_align": "prefix",
"_help_min_prefix_chars": [
"If the statement spelling length (including space and",
"parenthesis) is smaller than this amount, then force reject",
"nested layouts."
],
"min_prefix_chars": 4,
"_help_max_prefix_chars": [
"If the statement spelling length (including space and",
"parenthesis) is larger than the tab width by more than this",
"amount, then force reject un-nested layouts."
],
"max_prefix_chars": 10,
"_help_max_lines_hwrap": [
"If a candidate layout is wrapped horizontally but it exceeds",
"this many lines, then reject the layout."
],
"max_lines_hwrap": 2,
"_help_line_ending": [
"What style line endings to use in the output."
],
"line_ending": "auto",
"_help_command_case": [
"Format command names consistently as 'lower' or 'upper' case"
],
"command_case": "lower",
"_help_keyword_case": [
"Format keywords consistently as 'lower' or 'upper' case"
],
"keyword_case": "upper",
"_help_always_wrap": [
"A list of command names which should always be wrapped"
],
"always_wrap": [],
"_help_enable_sort": [
"If true, the argument lists which are known to be sortable",
"will be sorted lexicographically"
],
"enable_sort": true,
"_help_autosort": [
"If true, the parsers may infer whether or not an argument",
"list is sortable (without annotation)."
],
"autosort": true,
"_help_require_valid_layout": [
"By default, if cmake-format cannot successfully fit",
"everything into the desired line-width it will apply the",
"last, most aggressive attempt that it made. If this flag is",
"True, however, cmake-format will print error, exit with non-",
"zero status code, and write-out nothing"
],
"require_valid_layout": false,
"_help_layout_passes": [
"A dictionary mapping layout nodes to a list of wrap",
"decisions. See the documentation for more information."
],
"layout_passes": {}
},
"markup": {
"enable_markup": false
}
}

View File

@@ -41,8 +41,8 @@ albeit slightly less active.
We use a separate job on the CI to check your code for formatting issues. If
your pull request failed the test, you can check the output on the checks tab.
It's the first job called "linter", you can click the "Check code formatting"
step to see the output of the test.
It's the first job called "linter", you can click the "Run clangify" step to
see the output of the test.
The message will look like this:
```
@@ -50,7 +50,7 @@ The message will look like this:
*** ***
*** Your code does not comply with our style guide. ***
*** ***
*** Please correct it or run the "format.sh" script. ***
*** Please correct it or run the "clangify.sh" script. ***
*** Then commit and push those changes to this branch. ***
*** Check our CONTRIBUTING.md file for more details. ***
*** ***
@@ -81,9 +81,9 @@ The handy tool `clang-format` can format your code for you, it is available for
almost any environment. A special `.clang-format` configuration file is
included in the project and is used to format your code.
We've also included a bash script, `format.sh`, that will use clang-format to
format all files in your pr in one go. Use `./format.sh --help` to show a full
help page.
We've also included a bash script, `clangify.sh`, that will use clang-format to
format all files in your pr in one go. Use `./clangify.sh --help` to show a
full help page.
To run clang-format on a single source file simply use the command
`clang-format -i <filename>` to format it in place. (Some systems install
@@ -290,21 +290,20 @@ be included in the next release 👍
Basic workflow for translations:
1. Developer adds a `tr("foo")` string in the code;
2. CI updates the `*_en@source.ts files` regularly and creates a PR automatically;
3. Maintainer verifies and merges the change;
4. Transifex picks up the new files from GitHub automatically;
5. Translators translate the new untranslated strings on Transifex;
6. Before a release, a maintainer fetches the updated translations from Transifex.
2. Every few days, a maintainer updates the `*_en.ts files` with the new strings;
3. Transifex picks up the new files from GitHub every 24 hours;
4. Translators translate the new untranslated strings on Transifex;
5. Before a release, a maintainer fetches the updated translations from Transifex.
### Using Translations (for developers) ###
All user interface strings inside Cockatrice's source code must be written
in English (US).
All the user-interface strings inside Cockatrice's source code must be written
in English(US).
Translations to other languages are managed using [Transifex](
https://www.transifex.com/projects/p/cockatrice/).
Adding a new string to translate is as easy as adding the string in the
`tr("")` function, the string will be picked up as translatable automatically
'tr("")' function, the string will be picked up as translatable automatically
and translated as needed.
For example, setting the text of a label in the way that the string
`"My name is:"` can be translated:
@@ -313,7 +312,7 @@ nameLabel.setText(tr("My name is:"));
```
To translate a string that would have plural forms you can add the amount to
the tr() call, also you can add an extra string as a hint for translators:
the tr call, also you can add an extra string as a hint for translators:
```c++
QString message = tr("Everyone draws %n cards", "pop up message", amount);
```
@@ -322,46 +321,20 @@ https://doc.qt.io/qt-5/i18n-source-translation.html#handling-plurals)
If you're about to propose a change that adds or modifies any translatable
string in the code, you don't need to take care of adding the new strings to
the translation files.<br>
We have an automated process to update our language source files on a schedule
and provide the translators on Transifex with the new contents.<br>
Maintainers can also manually trigger this on demand.
the translation files.
Every few days, or when a lot of new strings have been added, someone from the
development team will take care of extracting all the new strings and adding
them to the english translation files and making them available to translators
on Transifex.
### Maintaining Translations (for maintainers) ###
When new translatable strings have been added to the code, a maintainer has to
make them available to translators on Transifex.
When new translatable strings have been added to the code, a maintainer should
make them available to translators on Transifex. Every few days, or when a lot
of new strings have been added, a maintainer should take care of extracting all
the new strings and add them to the english translation files.
To help with that, we have an automated CI workflow, that regularly looks at the
code in the master branch, extracts all strings and updates dedicated source string
files with any changes. These updates are not commited right away, the CI creates a
PR for reviewing instead.<br>
After approval, our translation tool automatically picks the changes up and deploys
them to our translators. Be mindful when merging only a few changes!
Once a release is planned, or when a lot of strings have been added or changed, a
maintainer can manually trigger a CI run to extract all strings on demand.
<details>
<summary><b>Manually trigger CI run (Workflow Dispatch)</b></summary>
Maintainers can always request the CI to run on demand if it's required.
Go to the `Actions` tab and select our dedicated translation workflow:
https://github.com/Cockatrice/Cockatrice/actions/workflows/translations.yml
You see a "This workflow has a workflow_dispatch event trigger." hint at the top of
the list.<br>
Select `Run workflow` on the right and trigger a run from master branch.
The CI will now check for changed strings and create a PR if there are any updates.
</details>
<details>
<summary><b>Manually update source strings locally</b></summary>
To update the english source files for translation, re-run cmake enabling the appropriate
To update the english translation files, re-run cmake enabling the appropriate
parameter and then run make:
```sh
cd cockatrice/build
@@ -371,26 +344,24 @@ make
If the parameter has been enabled correctly, when running "make" you should see
a line similar to this one (the numbers may vary):
```sh
[ 76%] Generating ../../cockatrice/translations/cockatrice_en@source.ts
Updating '../../cockatrice/translations/cockatrice_en@source.ts'...
[ 76%] Generating ../../cockatrice/translations/cockatrice_en.ts
Updating '../../cockatrice/translations/cockatrice_en.ts'...
Found 857 source text(s) (8 new and 849 already existing)
```
You should then notice that the following files have uncommitted changes:
cockatrice/translations/cockatrice_en@source.ts
oracle/translations/oracle_en@source.ts
cockatrice/translations/cockatrice_en.ts
oracle/translations/oracle_en.ts
It is recommended to disable the parameter afterwards using:
```sh
cmake .. -DUPDATE_TRANSLATIONS=OFF
```
Now you are ready to commit your changes and open a PR.
Now you are ready to propose your change.
</details>
Once the changes get merged, Transifex will pick up the modified files
automatically (checked every few hours) and update their online editor where
translators will be able to translate the new strings right in the browser.
Once your change gets merged, Transifex will pick up the modified files
automatically (checked every 24 hours) and update the interface where
translators will be able to translate the new strings.
### Releasing Translations (for maintainers) ###

View File

@@ -1,49 +0,0 @@
# Configuration options: https://docs.github.com/en/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
# # Enable version updates for git submodules
# Not yet possible to bump only on tags or releases, see:
# https://github.com/dependabot/dependabot-core/issues/1639
# https://github.com/dependabot/dependabot-core/issues/2192
# Alternative: Action that updates submodule and can be manually run on demand (workflow_dispatch)
# - package-ecosystem: "gitsubmodule"
# # Look for `.gitmodules` in the `root` directory
# directory: "/"
# # Check for updates once a month
# schedule:
# interval: "monthly"
# # Limit the amout of open PR's (default = 5, disabled = 0, security updates are not impacted)
# open-pull-requests-limit: 1
# # Enable version updates for Docker
# Not yet possible to bump from one LTS version to the next and skip others, see:
# https://github.com/dependabot/dependabot-core/issues/2247
# - package-ecosystem: "docker"
# # Look for a `Dockerfile` in the `root` directory
# directory: "/"
# # Check for updates once a week
# schedule:
# interval: "weekly"
# # Limit the amout of open PR's (default = 5, disabled = 0, security updates are not impacted)
# open-pull-requests-limit: 1
# Enable version updates for GitHub Actions
- package-ecosystem: "github-actions"
# Directory must be set to "/" to check for workflow files in .github/workflows
directory: "/"
# Check for updates to GitHub Actions once a week
schedule:
interval: "weekly"
# Limit the amout of open PR's (default = 5, disabled = 0, security updates are not impacted)
open-pull-requests-limit: 2
# # Enable version updates for npm
# - package-ecosystem: "npm"
# # Look for `package.json` and `lock` files in the `webclient` subdirectory
# directory: "/webclient"
# # Check the npm registry for updates once a week
# schedule:
# interval: "weekly"
# # Limit the amout of open PR's (default = 5, disabled = 0, security updates are not impacted)
# open-pull-requests-limit: 5

View File

@@ -8,30 +8,33 @@ on:
- '**.md'
- 'webclient/**'
- '.github/workflows/web-*.yml'
- '.github/workflows/translations-*.yml'
tags:
- '*'
pull_request:
branches:
- master
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 master)
concurrency:
group: "${{ github.workflow }} @ ${{ github.ref_name }}"
cancel-in-progress: ${{ github.ref_name != 'master' }}
jobs:
configure:
name: Configure
runs-on: ubuntu-latest
outputs:
tag: ${{steps.configure.outputs.tag}}
sha: ${{steps.configure.outputs.sha}}
upload_url: ${{steps.create_release.outputs.upload_url}}
steps:
- name: Cancel previous runs
uses: styfle/cancel-workflow-action@0.6.0
with:
access_token: ${{github.token}} # needs other token https://github.com/styfle/cancel-workflow-action/issues/7
steps:
- name: Configure
id: configure
shell: bash
@@ -42,19 +45,19 @@ jobs:
elif [[ $GITHUB_REF =~ $tag_regex ]]; then # release
sha="$GITHUB_SHA"
tag="${GITHUB_REF/refs\/tags\//}"
echo "tag=$tag" >>"$GITHUB_OUTPUT"
echo "::set-output name=tag::$tag"
else # push to branch
sha="$GITHUB_SHA"
fi
echo "sha=$sha" >>"$GITHUB_OUTPUT"
echo "::set-output name=sha::$sha"
- name: Checkout
if: steps.configure.outputs.tag != null
uses: actions/checkout@v4
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Prepare release parameters
- name: Prepare release paramaters
id: prepare
if: steps.configure.outputs.tag != null
shell: bash
@@ -65,21 +68,15 @@ jobs:
- name: Create release
if: steps.configure.outputs.tag != null
id: create_release
shell: bash
uses: actions/create-release@v1
env:
GH_TOKEN: ${{github.token}}
tag_name: ${{steps.configure.outputs.tag}}
target: ${{steps.configure.outputs.sha}}
GITHUB_TOKEN: ${{github.token}}
with:
tag_name: ${{github.ref}}
release_name: ${{steps.prepare.outputs.title}}
body_path: ${{steps.prepare.outputs.body_path}}
prerelease: ${{steps.prepare.outputs.is_beta}}
run: |
if [[ $prerelease == yes ]]; then
args="--prerelease"
fi
gh release create "$tag_name" --draft --verify-tag $args \
--target "$target" --title "$release_name" \
--notes-file "$body_path"
draft: true
prerelease: ${{steps.prepare.outputs.is_beta == 'yes'}}
build-linux:
strategy:
@@ -87,58 +84,61 @@ jobs:
matrix:
# these names correspond to the files in .ci/$distro
include:
- distro: ArchLinux
package: skip # we are packaged in arch already
allow-failure: yes
- distro: Debian11
- distro: UbuntuImpish
package: DEB
- distro: Debian12
package: DEB
- distro: Fedora39
package: RPM
- distro: Fedora40
package: RPM
- distro: UbuntuBionic
- distro: UbuntuHirsute
package: DEB
test: skip
- distro: UbuntuFocal
package: DEB
test: skip # UbuntuFocal has a broken qt for debug builds
- distro: UbuntuJammy
- distro: UbuntuBionic
package: DEB
test: skip # running tests on all distros is superfluous
- distro: UbuntuNoble
- distro: ArchLinux
package: skip # we are packaged in arch already
allow-failure: yes
- distro: Debian10
package: DEB
- distro: Debian11
package: DEB
- distro: Fedora34
package: RPM
test: skip # gtest does not compile for some reason
- distro: Fedora35
package: RPM
name: ${{matrix.distro}}
needs: configure
runs-on: ubuntu-latest
continue-on-error: ${{matrix.allow-failure == 'yes'}}
env:
NAME: ${{matrix.distro}}
CACHE: /tmp/${{matrix.distro}}-cache # ${{runner.temp}} does not work?
# cache size over the entire repo is 10Gi link:
# https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#usage-limits-and-eviction-policy
CCACHE_SIZE: 200M
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v2
- name: Get cache timestamp
id: cache_timestamp
shell: bash
run: echo "timestamp=$(date -u '+%Y%m%d%H%M%S')" >>"$GITHUB_OUTPUT"
run: echo "::set-output name=timestamp::$(date -u '+%Y%m%d%H%M%S')"
- name: Restore cache
uses: actions/cache@v4
uses: actions/cache@v2
env:
timestamp: ${{steps.cache_timestamp.outputs.timestamp}}
with:
@@ -154,197 +154,245 @@ jobs:
- name: Build debug and test
if: matrix.test != 'skip'
shell: bash
env:
distro: '${{matrix.distro}}'
run: |
source .ci/docker.sh
RUN --server --debug --test --ccache "$CCACHE_SIZE" --parallel 4
RUN --server --debug --test --ccache
- name: Build release package
id: build
id: package
if: matrix.package != 'skip'
shell: bash
env:
BUILD_DIR: build
SUFFIX: '-${{matrix.distro}}'
distro: '${{matrix.distro}}'
suffix: '-${{matrix.distro}}'
type: '${{matrix.package}}'
run: |
source .ci/docker.sh
RUN --server --release --package "$type" --dir "$BUILD_DIR" \
--ccache "$CCACHE_SIZE" --parallel 4
.ci/name_build.sh
RUN --server --release --package "$type" --suffix "$suffix"
- name: Upload artifact
if: matrix.package != 'skip'
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v2
with:
name: ${{matrix.distro}}-package
path: ${{steps.build.outputs.path}}
path: ./build/${{steps.package.outputs.name}}
if-no-files-found: error
- name: Upload to release
if: matrix.package != 'skip' && needs.configure.outputs.tag != null
shell: bash
uses: actions/upload-release-asset@v1
env:
GH_TOKEN: ${{github.token}}
tag_name: ${{needs.configure.outputs.tag}}
asset_path: ${{steps.build.outputs.path}}
asset_name: ${{steps.build.outputs.name}}
run: gh release upload "$tag_name" "$asset_path#$asset_name"
GITHUB_TOKEN: ${{github.token}}
with:
upload_url: ${{needs.configure.outputs.upload_url}}
asset_path: ./build/${{steps.package.outputs.name}}
asset_name: ${{steps.package.outputs.name}}
asset_content_type: application/octet-stream
build-macos:
strategy:
fail-fast: false
matrix:
target:
- Debug
- 10.14_Mojave
- 10.15_Catalina
- 11_Big_Sur
include:
- target: 12_Monterey_and_13_Ventura
os: macos-12
xcode: "14.0.1"
type: Release
make_package: 1
- target: 14_Sonoma
os: macos-14
xcode: "15.4"
type: Release
make_package: 1
- target: 14_Sonoma_Debug
os: macos-14
xcode: "15.4"
- target: Debug # tests only
os: macos-latest
xcode: 12.5.1
type: Debug
do_tests: 0 # tests do not work yet on mac
make_package: false
- target: 10.14_Mojave
os: macos-10.15 # runs on Catalina
xcode: 10.3 # allows compatibility with macOS 10.14
type: Release
do_tests: 0
make_package: true
- target: 10.15_Catalina
os: macos-10.15
xcode: 12.1
type: Release
do_tests: 0
make_package: true
- target: 11_Big_Sur
os: macos-11
xcode: 12.5.1
type: Release
do_tests: 0
make_package: true
name: macOS ${{matrix.target}}
name: macOS${{matrix.target}}
needs: configure
runs-on: ${{matrix.os}}
continue-on-error: ${{matrix.allow-failure == 'yes'}}
env:
DEVELOPER_DIR:
/Applications/Xcode_${{matrix.xcode}}.app/Contents/Developer
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v2
- name: Install dependencies using Homebrew
- name: Install dependencies using homebrew
shell: bash
# cmake cannot find the mysql connector
# neither of these works: mariadb-connector-c mysql-connector-c++
env:
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1
run: |
brew update
brew install protobuf qt --force-bottle
run: brew update && brew install protobuf
- name: Install QT using homebrew
id: brew_install_qt
continue-on-error: true
shell: bash
run: brew install qt@5 --force-bottle
- name: Install QT using actions
if: steps.brew_install_qt.outcome != 'success'
uses: jurplel/install-qt-action@v2
- name: Build on Xcode ${{matrix.xcode}}
shell: bash
id: build
env:
BUILDTYPE: '${{matrix.type}}'
MAKE_TEST: 1
MAKE_PACKAGE: '${{matrix.make_package}}'
PACKAGE_SUFFIX: '-macOS-${{matrix.target}}'
# macOS runner actually have only 3 cores
# See https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources
run: .ci/compile.sh --server --parallel 3
CMAKE_BUILD_PARALLEL_LEVEL: 3 # mac machines actually have 3 cores
run: .ci/compile.sh ${{matrix.type}} --server
- name: Test
if: matrix.do_tests == 1
shell: bash
working-directory: build
run: cmake --build . --target test
- name: Package for ${{matrix.target}}
id: package
if: matrix.make_package
shell: bash
working-directory: build
run: |
cmake --build . --target package
../.ci/name_build.sh "-macOS-${{matrix.target}}"
- name: Upload artifact
if: matrix.make_package
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v2
with:
name: macOS-${{matrix.target}}-dmg
path: ${{steps.build.outputs.path}}
name: macOS-${{matrix.target}}-xcode-${{matrix.xcode}}-dmg
path: ${{steps.package.outputs.path}}
if-no-files-found: error
- name: Upload to release
if: matrix.package != 'skip' && needs.configure.outputs.tag != null
shell: bash
if: matrix.make_package && needs.configure.outputs.tag != null
uses: actions/upload-release-asset@v1
env:
GH_TOKEN: ${{github.token}}
tag_name: ${{needs.configure.outputs.tag}}
asset_path: ${{steps.build.outputs.path}}
asset_name: ${{steps.build.outputs.name}}
run: gh release upload "$tag_name" "$asset_path#$asset_name"
GITHUB_TOKEN: ${{github.token}}
with:
upload_url: ${{needs.configure.outputs.upload_url}}
asset_path: ${{steps.package.outputs.path}}
asset_name: ${{steps.package.outputs.name}}
asset_content_type: application/octet-stream
build-windows:
strategy:
fail-fast: false
matrix:
arch:
- 64
- 32
include:
- target: 7
qt_version: 5.15.*
qt_arch: msvc2019_64
qt_tools: "tools_opensslv3_x64"
- arch: 64
triplet: x64
cmake: x64
append: _64
- target: 10
qt_version: 6.5.*
qt_arch: msvc2019_64
qt_tools: "tools_opensslv3_x64"
qt_modules: "qtmultimedia qtwebsockets"
- arch: 32
triplet: x86
cmake: Win32
name: Windows ${{matrix.arch}}
name: Windows ${{matrix.target}}
needs: configure
runs-on: windows-2022
runs-on: windows-latest
env:
CMAKE_GENERATOR: 'Visual Studio 17 2022'
QT_VERSION: '5.15.2'
QT_ARCH: msvc2019${{matrix.append}}
CMAKE_GENERATOR: 'Visual Studio 16 2019'
steps:
- name: Add msbuild to PATH
id: add-msbuild
uses: microsoft/setup-msbuild@v2
with:
msbuild-architecture: x64
uses: microsoft/setup-msbuild@v1.0.2
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v2
with:
submodules: recursive
- name: Install Qt ${{matrix.qt_version}}
uses: jurplel/install-qt-action@v3
- name: Restore Qt ${{env.QT_VERSION}} ${{matrix.arch}}-bit from cache
id: cache-qt
uses: actions/cache@v2
with:
cache: true
setup-python: false
version: ${{matrix.qt_version}}
arch: win64_${{matrix.qt_arch}}
tools: ${{matrix.qt_tools}}
modules: ${{matrix.qt_modules}}
key: ${{runner.os}}-QtCache-${{env.QT_VERSION}}-${{matrix.arch}}
path: ${{runner.workspace}}/Qt
- name: Run vcpkg
uses: lukka/run-vcpkg@v11
- name: Install ${{matrix.arch}}-bit Qt
uses: jurplel/install-qt-action@v2
with:
runVcpkgInstall: true
doNotCache: false
env:
VCPKG_DEFAULT_TRIPLET: 'x64-windows'
VCPKG_DISABLE_METRICS: 1
cached: ${{steps.cache-qt.outputs.cache-hit}}
version: ${{env.QT_VERSION}}
arch: win${{matrix.arch}}_${{env.QT_ARCH}}
- name: Build Cockatrice
id: build
- name: Restore or setup vcpkg
uses: lukka/run-vcpkg@v6
with:
vcpkgArguments: '@${{github.workspace}}/vcpkg.txt'
vcpkgDirectory: ${{github.workspace}}/vcpkg
appendedCacheKey: ${{hashFiles('**/vcpkg.txt')}}
vcpkgTriplet: ${{matrix.triplet}}-windows
- name: Configure Cockatrice ${{matrix.arch}}-bit
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}}'
# 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
run: |
mkdir -p build
cd build
export QTDIR="${{runner.workspace}}/Qt/${{env.QT_VERSION}}/${{env.QT_ARCH}}"
cmake .. -G "${{env.CMAKE_GENERATOR}}" -A "${{matrix.cmake}}" -DCMAKE_BUILD_TYPE="Release" -DWITH_SERVER=1 -DTEST=1
- name: Build Cockatrice ${{matrix.arch}}-bit
id: package
shell: bash
working-directory: build
run: |
cmake --build . --target package --config Release
../.ci/name_build.sh "-win${{matrix.arch}}"
- name: Run tests
shell: bash
working-directory: build
run: ctest -T Test -C Release
- name: Upload artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v2
with:
name: Windows${{matrix.target}}-installer
path: ${{steps.build.outputs.path}}
name: Windows-${{matrix.arch}}bit-installer
path: ./build/${{steps.package.outputs.name}}
if-no-files-found: error
- name: Upload to release
if: matrix.package != 'skip' && needs.configure.outputs.tag != null
shell: bash
if: needs.configure.outputs.tag != null
uses: actions/upload-release-asset@v1
env:
GH_TOKEN: ${{github.token}}
tag_name: ${{needs.configure.outputs.tag}}
asset_path: ${{steps.build.outputs.path}}
asset_name: ${{steps.build.outputs.name}}
run: gh release upload "$tag_name" "$asset_path#$asset_name"
GITHUB_TOKEN: ${{github.token}}
with:
upload_url: ${{needs.configure.outputs.upload_url}}
asset_path: ./build/${{steps.package.outputs.name}}
asset_name: ${{steps.package.outputs.name}}
asset_content_type: application/octet-stream

View File

@@ -2,28 +2,29 @@ name: Code Style (C++)
on:
pull_request:
branches:
- master
paths-ignore:
- '**.md'
- 'webclient/**'
- '.github/workflows/web-*.yml'
- '.github/workflows/translations-*.yml'
jobs:
format:
runs-on: ubuntu-22.04
clang-format:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v2
with:
fetch-depth: 20 # should be enough to find merge base
- name: Install dependencies
- name: Install clang-format
shell: bash
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends clang-format cmake-format
sudo apt-get install -y --no-install-recommends clang-format
- name: Check code formatting
- name: Run clangify
shell: bash
run: ./.ci/lint_cpp.sh

View File

@@ -1,72 +0,0 @@
name: Update Translations
on:
workflow_dispatch:
schedule:
# runs in the middle of each month starting a quarter (UTC) = two weeks after new strings are built
- cron: '0 0 15 1,4,7,10 *'
pull_request:
paths:
- '.github/workflows/translations-pull.yml'
jobs:
translations:
# Do not run the scheduled workflow on forks
if: github.event_name != 'schedule' || github.repository_owner == 'Cockatrice'
name: Pull languages
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Pull translated strings from Transifex
uses: transifex/cli-action@v2
with:
# used config file: https://github.com/Cockatrice/Cockatrice/blob/master/.tx/config
# https://github.com/transifex/cli#pulling-files-from-transifex
token: ${{ secrets.TX_TOKEN }}
args: pull --force --all
- name: Create pull request
if: github.event_name != 'pull_request'
id: create_pr
uses: peter-evans/create-pull-request@v6
with:
add-paths: |
cockatrice/translations/*.ts
oracle/translations/*.ts
webclient/public/locales/*/translation.json
commit-message: Update translation files
# author is the owner of the commit
author: github-actions <github-actions@github.com>
branch: ci-update_translations
delete-branch: true
title: 'Update translations'
body: |
Pulled all translated strings from [Transifex][1].
---
*This PR is automatically generated and updated by the workflow at `.github/workflows/translations-pull.yml`. Review [action runs][2].*<br>
*After merging, all new languages and translations are available in the next build.*
[1]: https://app.transifex.com/cockatrice/cockatrice/
[2]: https://github.com/Cockatrice/Cockatrice/actions/workflows/translations-pull.yml?query=branch%3Amaster
labels: |
CI
Translation
draft: false
- name: PR Status
if: github.event_name != 'pull_request'
shell: bash
env:
STATUS: ${{ steps.create_pr.outputs.pull-request-operation }}
run: |
if [[ "$STATUS" == "" ]]; then
echo "PR #${{ steps.create_pr.outputs.pull-request-number }} unchanged!" >> $GITHUB_STEP_SUMMARY
else
echo "PR #${{ steps.create_pr.outputs.pull-request-number }} $STATUS!" >> $GITHUB_STEP_SUMMARY
fi
echo "URL: ${{ steps.create_pr.outputs.pull-request-url }}" >> $GITHUB_STEP_SUMMARY

View File

@@ -1,87 +0,0 @@
name: Update Translation Source
on:
workflow_dispatch:
schedule:
# runs at the start of each quarter (UTC)
- cron: '0 0 1 1,4,7,10 *'
pull_request:
paths:
- '.github/workflows/translations-push.yml'
jobs:
translations:
# Do not run the scheduled workflow on forks
if: github.event_name != 'schedule' || github.repository_owner == 'Cockatrice'
name: Push strings
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Install lupdate
shell: bash
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends qttools5-dev-tools
- name: Update Cockatrice translation source
id: cockatrice
shell: bash
env:
FILE: 'cockatrice/cockatrice_en@source.ts'
DIRS: 'cockatrice/src common'
run: .ci/update_translation_source_strings.sh
- name: Update Oracle translation source
id: oracle
shell: bash
env:
FILE: 'oracle/oracle_en@source.ts'
DIRS: 'oracle/src'
run: .ci/update_translation_source_strings.sh
- name: Render template
id: template
uses: chuhlomin/render-template@v1
with:
template: .ci/update_translation_source_strings_template.md
vars: |
cockatrice_output: ${{ steps.cockatrice.outputs.output }}
oracle_output: ${{ steps.oracle.outputs.output }}
commit: ${{ github.sha }}
- name: Create pull request
if: github.event_name != 'pull_request'
id: create_pr
uses: peter-evans/create-pull-request@v6
with:
add-paths: |
cockatrice/cockatrice_en@source.ts
oracle/oracle_en@source.ts
commit-message: Update translation source strings
# author is the owner of the commit
author: github-actions <github-actions@github.com>
branch: ci-update_translation_source
delete-branch: true
title: 'Update source strings'
body: ${{ steps.template.outputs.result }}
labels: |
CI
Translation
draft: false
- name: PR Status
if: github.event_name != 'pull_request'
shell: bash
env:
STATUS: ${{ steps.create_pr.outputs.pull-request-operation }}
run: |
if [[ "$STATUS" == "" ]]; then
echo "PR #${{ steps.create_pr.outputs.pull-request-number }} unchanged!" >> $GITHUB_STEP_SUMMARY
else
echo "PR #${{ steps.create_pr.outputs.pull-request-number }} $STATUS!" >> $GITHUB_STEP_SUMMARY
fi
echo "URL: ${{ steps.create_pr.outputs.pull-request-url }}" >> $GITHUB_STEP_SUMMARY

View File

@@ -9,6 +9,8 @@ on:
- 'webclient/**'
- '!**.md'
pull_request:
branches:
- master
paths:
- '.github/workflows/web-*.yml'
- 'webclient/**'
@@ -28,15 +30,15 @@ jobs:
fail-fast: false
matrix:
node_version:
- 16
- 12
- lts/*
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v2
with:
node-version: ${{matrix.node_version}}
cache: 'npm'
@@ -50,3 +52,4 @@ jobs:
- name: Test app
run: npm run test

View File

@@ -2,6 +2,8 @@ name: Code Style (TypeScript)
on:
pull_request:
branches:
- master
paths:
- '.github/workflows/web-*.yml'
- 'webclient/**'
@@ -17,10 +19,10 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v2
with:
cache: 'npm'
cache-dependency-path: 'webclient/package-lock.json'

4
.gitignore vendored
View File

@@ -6,10 +6,8 @@ mysql.cnf
.DS_Store
.idea/
*.aps
cmake-build-debug*
cmake-build-debug/
preferences
compile_commands.json
.vs/
.vscode/
.cache
.gdb_history

View File

@@ -1,7 +0,0 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
cd webclient
npm run translate
git add src/i18n-default.json

View File

@@ -1,26 +1,13 @@
[main]
host = https://app.transifex.com
host = https://www.transifex.com
[o:cockatrice:p:cockatrice:r:cockatrice-cockatrice-en-source-ts--master]
resource_name = Cockatrice
source_lang = en
source_file = cockatrice/cockatrice_en@source.ts
[cockatrice.cockatrice]
file_filter = cockatrice/translations/cockatrice_<lang>.ts
type = QT
minimum_perc = 10
[o:cockatrice:p:cockatrice:r:oracle-oracle-en-source-ts--master]
resource_name = Oracle
source_file = cockatrice/translations/cockatrice_en.ts
source_lang = en
source_file = oracle/oracle_en@source.ts
[cockatrice.oracle]
file_filter = oracle/translations/oracle_<lang>.ts
type = QT
minimum_perc = 10
[o:cockatrice:p:cockatrice:r:webclient-src-i18n-default-json--master]
resource_name = Webclient
source_file = oracle/translations/oracle_en.ts
source_lang = en
source_file = webclient/src/i18n-default.json
file_filter = webclient/public/locales/<lang>/translation.json
type = KEYVALUEJSON
minimum_perc = 10

View File

@@ -5,95 +5,58 @@
# This file sets all the variables shared between the projects
# like the installation path, compilation flags etc..
# cmake 3.16 is required if using qt6
# Cmake 3.1 is required to enable C++11 support correctly
cmake_minimum_required(VERSION 3.10)
# Early detect ccache
option(USE_CCACHE "Cache the build results with ccache" ON)
# Treat warnings as errors (Debug builds only)
option(WARNING_AS_ERROR "Treat warnings as errors in debug builds" ON)
# Check for translation updates
option(UPDATE_TRANSLATIONS "Update translations on compile" OFF)
# Compile servatrice
option(WITH_SERVER "build servatrice" OFF)
# Compile cockatrice
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)
# Default to "Release" build type
# User-provided value for CMAKE_BUILD_TYPE must be checked before the PROJECT() call
if(DEFINED CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE
${CMAKE_BUILD_TYPE}
CACHE STRING "Type of build"
)
else()
set(CMAKE_BUILD_TYPE
Release
CACHE STRING "Type of build"
)
endif()
IF(DEFINED CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "Type of build")
ELSE()
SET(CMAKE_BUILD_TYPE Release CACHE STRING "Type of build")
ENDIF()
# Early detect ccache
OPTION(USE_CCACHE "Cache the build results with ccache" ON)
if(USE_CCACHE)
find_program(CCACHE_PROGRAM ccache)
if(CCACHE_PROGRAM)
# Support Unix Makefiles and Ninja
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}")
message(STATUS "Found CCache ${CCACHE_PROGRAM}")
endif()
find_program(CCACHE_PROGRAM ccache)
if(CCACHE_PROGRAM)
# Support Unix Makefiles and Ninja
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}")
MESSAGE(STATUS "Found CCache ${CCACHE_PROGRAM}")
endif()
endif()
if(WIN32)
# Use vcpkg toolchain on Windows
set(CMAKE_TOOLCHAIN_FILE
${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake
CACHE STRING "Vcpkg toolchain file"
)
# Qt path set by user or env var
if(QTDIR
OR DEFINED ENV{QTDIR}
OR DEFINED ENV{QTDIR32}
OR DEFINED ENV{QTDIR64}
)
else()
set(QTDIR
""
CACHE PATH "Path to Qt (e.g. C:/Qt/5.7/msvc2015_64)"
)
message(
WARNING "QTDIR variable is missing. Please set this variable to specify path to Qt (e.g. C:/Qt/5.7/msvc2015_64)"
)
endif()
# Use vcpkg toolchain on Windows
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake
CACHE STRING "Vcpkg toolchain file")
# Qt path set by user or env var
if (QTDIR OR DEFINED ENV{QTDIR} OR DEFINED ENV{QTDIR32} OR DEFINED ENV{QTDIR64})
else()
set(QTDIR "" CACHE PATH "Path to Qt (e.g. C:/Qt/5.7/msvc2015_64)")
message(WARNING "QTDIR variable is missing. Please set this variable to specify path to Qt (e.g. C:/Qt/5.7/msvc2015_64)")
endif()
endif()
# A project name is needed for CPack
# Version can be overriden by git tags, see cmake/getversion.cmake
project("Cockatrice" VERSION 2.9.1)
PROJECT("Cockatrice" VERSION 2.8.1)
# Set release name if not provided via env/cmake var
if(NOT DEFINED GIT_TAG_RELEASENAME)
set(GIT_TAG_RELEASENAME "Rings of the Wild")
set(GIT_TAG_RELEASENAME "Prismatic Bridge")
endif()
# Use c++17 for all targets
set(CMAKE_CXX_STANDARD
17
CACHE STRING "C++ ISO Standard"
)
# Use c++11 for all targets
set(CMAKE_CXX_STANDARD 11 CACHE STRING "C++ ISO Standard")
set(CMAKE_CXX_STANDARD_REQUIRED True)
# Set conventional loops
set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true)
# Search path for cmake modules
set(COCKATRICE_CMAKE_PATH "${PROJECT_SOURCE_DIR}/cmake")
list(INSERT CMAKE_MODULE_PATH 0 "${COCKATRICE_CMAKE_PATH}")
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
include(getversion)
@@ -102,150 +65,152 @@ include(createversionfile)
# Define a proper install path
if(UNIX)
if(APPLE)
# macOS
# Due to the special bundle structure ignore
# the prefix eventually set by the user.
set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/release)
if(APPLE)
# macOS
# Due to the special bundle structure ignore
# the prefix eventually set by the user.
set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/release)
# Force ccache usage if available
get_property(RULE_LAUNCH_COMPILE GLOBAL PROPERTY RULE_LAUNCH_COMPILE)
if(RULE_LAUNCH_COMPILE)
message(STATUS "Force enabling CCache usage under macOS")
# Set up wrapper scripts
configure_file("${COCKATRICE_CMAKE_PATH}/launch-c.in" launch-c)
configure_file("${COCKATRICE_CMAKE_PATH}/launch-cxx.in" launch-cxx)
execute_process(COMMAND chmod a+rx "${CMAKE_BINARY_DIR}/launch-c" "${CMAKE_BINARY_DIR}/launch-cxx")
# Force ccache usage if available
get_property(RULE_LAUNCH_COMPILE GLOBAL PROPERTY RULE_LAUNCH_COMPILE)
if(RULE_LAUNCH_COMPILE)
MESSAGE(STATUS "Force enabling CCache usage under macOS")
# Set up wrapper scripts
configure_file(${CMAKE_MODULE_PATH}/launch-c.in launch-c)
configure_file(${CMAKE_MODULE_PATH}/launch-cxx.in launch-cxx)
execute_process(COMMAND chmod a+rx
"${CMAKE_BINARY_DIR}/launch-c"
"${CMAKE_BINARY_DIR}/launch-cxx")
# Set Xcode project attributes to route compilation through our scripts
set(CMAKE_XCODE_ATTRIBUTE_CC "${CMAKE_BINARY_DIR}/launch-c")
set(CMAKE_XCODE_ATTRIBUTE_CXX "${CMAKE_BINARY_DIR}/launch-cxx")
set(CMAKE_XCODE_ATTRIBUTE_LD "${CMAKE_BINARY_DIR}/launch-c")
set(CMAKE_XCODE_ATTRIBUTE_LDPLUSPLUS "${CMAKE_BINARY_DIR}/launch-cxx")
# Set Xcode project attributes to route compilation through our scripts
set(CMAKE_XCODE_ATTRIBUTE_CC "${CMAKE_BINARY_DIR}/launch-c")
set(CMAKE_XCODE_ATTRIBUTE_CXX "${CMAKE_BINARY_DIR}/launch-cxx")
set(CMAKE_XCODE_ATTRIBUTE_LD "${CMAKE_BINARY_DIR}/launch-c")
set(CMAKE_XCODE_ATTRIBUTE_LDPLUSPLUS "${CMAKE_BINARY_DIR}/launch-cxx")
endif()
else()
# Linux / BSD
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
#fix package build
if(PREFIX)
set(CMAKE_INSTALL_PREFIX ${PREFIX})
else()
set(CMAKE_INSTALL_PREFIX /usr/local)
endif()
endif()
endif()
else()
# Linux / BSD
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
#fix package build
if(PREFIX)
set(CMAKE_INSTALL_PREFIX ${PREFIX})
else()
set(CMAKE_INSTALL_PREFIX /usr/local)
endif()
endif()
endif()
elseif(WIN32)
set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/rundir/${CMAKE_BUILD_TYPE})
set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/rundir/${CMAKE_BUILD_TYPE})
endif()
# Treat warnings as errors (Debug builds only)
option(WARNING_AS_ERROR "Treat warnings as errors in debug builds" ON)
# Define proper compilation flags
if(MSVC)
# Visual Studio: Maximum optimization, disable warning C4251, establish C++17 compatibility
set(CMAKE_CXX_FLAGS_RELEASE "/Ox /MD /wd4251 /Zc:__cplusplus /std:c++17 /permissive- /W4")
# Generate complete debugging information
#set(CMAKE_CXX_FLAGS_DEBUG "/Zi")
elseif(CMAKE_COMPILER_IS_GNUCXX)
# linux/gcc, bsd/gcc, windows/mingw
include(CheckCXXCompilerFlag)
IF(MSVC)
# Visual Studio: Maximum optimization, disable warning C4251
set(CMAKE_CXX_FLAGS_RELEASE "/Ox /MD /wd4251 ")
# Generate complete debugging information
#set(CMAKE_CXX_FLAGS_DEBUG "/Zi")
ELSEIF (CMAKE_COMPILER_IS_GNUCXX)
# linux/gcc, bsd/gcc, windows/mingw
include(CheckCXXCompilerFlag)
set(CMAKE_CXX_FLAGS_RELEASE "-s -O2")
if(WARNING_AS_ERROR)
set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -Wall -Wextra -Werror")
else()
set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -Wall -Wextra")
endif()
if(APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++17")
endif()
set(ADDITIONAL_DEBUG_FLAGS
-Wcast-align
-Wmissing-declarations
-Wno-long-long
-Wno-error=extra
-Wno-error=delete-non-virtual-dtor
-Wno-error=sign-compare
-Wno-error=missing-declarations
)
foreach(FLAG ${ADDITIONAL_DEBUG_FLAGS})
check_cxx_compiler_flag("${FLAG}" CXX_HAS_WARNING_${FLAG})
if(CXX_HAS_WARNING_${FLAG})
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${FLAG}")
set(CMAKE_CXX_FLAGS_RELEASE "-s -O2")
if(WARNING_AS_ERROR)
set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -Wall -Wextra -Werror")
else()
set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -Wall -Wextra")
endif()
endforeach()
else()
# other: osx/llvm, bsd/llvm
set(CMAKE_CXX_FLAGS_RELEASE "-O2")
if(WARNING_AS_ERROR)
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -Wall -Wextra -Werror -Wno-unused-parameter")
else()
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -Wall -Wextra")
endif()
endif()
set(ADDITIONAL_DEBUG_FLAGS -Wcast-align -Wmissing-declarations -Wno-long-long -Wno-error=extra -Wno-error=delete-non-virtual-dtor -Wno-error=sign-compare -Wno-error=missing-declarations)
FOREACH(FLAG ${ADDITIONAL_DEBUG_FLAGS})
CHECK_CXX_COMPILER_FLAG("${FLAG}" CXX_HAS_WARNING_${FLAG})
IF(CXX_HAS_WARNING_${FLAG})
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${FLAG}")
ENDIF()
ENDFOREACH()
ELSE()
# other: osx/llvm, bsd/llvm
set(CMAKE_CXX_FLAGS_RELEASE "-O2")
if(WARNING_AS_ERROR)
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -Wall -Wextra -Werror")
else()
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -Wall -Wextra")
endif()
ENDIF()
# GNU systems need to define the Mersenne exponent for the RNG to compile w/o warning
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
add_definitions("-DSFMT_MEXP=19937")
endif()
IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
ADD_DEFINITIONS("-DSFMT_MEXP=19937")
ENDIF()
find_package(Threads REQUIRED)
FIND_PACKAGE(Threads REQUIRED)
# Determine 32 or 64 bit build
# Find Qt5
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(_lib_suffix 64)
set(_lib_suffix 64)
else()
set(_lib_suffix 32)
set(_lib_suffix 32)
endif()
if(DEFINED QTDIR${_lib_suffix})
list(APPEND CMAKE_PREFIX_PATH "${QTDIR${_lib_suffix}}")
list(APPEND CMAKE_PREFIX_PATH "${QTDIR${_lib_suffix}}")
elseif(DEFINED QTDIR)
list(APPEND CMAKE_PREFIX_PATH "${QTDIR}")
list(APPEND CMAKE_PREFIX_PATH "${QTDIR}")
elseif(DEFINED ENV{QTDIR${_lib_suffix}})
list(APPEND CMAKE_PREFIX_PATH "$ENV{QTDIR${_lib_suffix}}")
list(APPEND CMAKE_PREFIX_PATH "$ENV{QTDIR${_lib_suffix}}")
elseif(DEFINED ENV{QTDIR})
list(APPEND CMAKE_PREFIX_PATH "$ENV{QTDIR}")
list(APPEND CMAKE_PREFIX_PATH "$ENV{QTDIR}")
endif()
message(STATUS "Update Translations: ${UPDATE_TRANSLATIONS}")
FIND_PACKAGE(Qt5Core 5.5.0 REQUIRED)
include(FindQtRuntime)
IF(Qt5Core_FOUND)
MESSAGE(STATUS "Found Qt ${Qt5Core_VERSION_STRING}")
# FIX: Qt was built with -reduce-relocations
if (Qt5_POSITION_INDEPENDENT_CODE)
SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif()
# guess plugins and libraries directory
set(QT_PLUGINS_DIR "${Qt5Core_DIR}/../../../plugins")
get_target_property(QT_LIBRARY_DIR Qt5::Core LOCATION)
get_filename_component(QT_LIBRARY_DIR ${QT_LIBRARY_DIR} PATH)
ELSE()
MESSAGE(FATAL_ERROR "No Qt5 found!")
ENDIF()
# Check for translation updates
OPTION(UPDATE_TRANSLATIONS "Update translations on compile" OFF)
MESSAGE(STATUS "UPDATE TRANSLATIONS: ${UPDATE_TRANSLATIONS}")
set(CMAKE_AUTOMOC TRUE)
# Find other needed libraries
find_package(Protobuf CONFIG)
if(NOT Protobuf_FOUND)
find_package(Protobuf REQUIRED)
endif()
if(${Protobuf_VERSION} VERSION_LESS "3.21.0.0" AND NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
message(FATAL_ERROR "No protoc command found!")
endif()
FIND_PACKAGE(Protobuf REQUIRED)
IF(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
MESSAGE(FATAL_ERROR "No protoc command found!")
ELSE()
MESSAGE(STATUS "Protoc version ${Protobuf_VERSION} found!")
ENDIF()
#Find OpenSSL
if(WIN32)
find_package(OpenSSL REQUIRED)
if(OPENSSL_FOUND)
include_directories(${OPENSSL_INCLUDE_DIRS})
else()
message(
WARNING
"Could not find OpenSSL runtime libraries. They are not required for compiling, but needs to be available at runtime."
)
endif()
endif()
IF(WIN32)
FIND_PACKAGE(Win32SslRuntime)
ENDIF()
#Find VCredist
if(MSVC)
find_package(VCredistRuntime)
endif()
IF(MSVC)
FIND_PACKAGE(VCredistRuntime)
ENDIF()
# Package builder
set(CPACK_PACKAGE_CONTACT "Zach Halpern <zach@cockatrice.us>")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PROJECT_NAME}")
set(CPACK_PACKAGE_CONTACT "Zach Halpern <zahalpern+github@gmail.com>")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY ${PROJECT_NAME})
set(CPACK_PACKAGE_VENDOR "Cockatrice Development Team")
set(CPACK_PACKAGE_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/README.md")
set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
@@ -255,95 +220,82 @@ set(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}")
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_VERSION_FILENAME}")
if(UNIX)
if(APPLE)
set(CPACK_GENERATOR DragNDrop ${CPACK_GENERATOR})
set(CPACK_GENERATOR "DragNDrop")
set(CPACK_DMG_FORMAT "UDBZ")
set(CPACK_DMG_VOLUME_NAME "${PROJECT_NAME}")
set(CPACK_SYSTEM_NAME "OSX")
set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/cockatrice/resources/appicon.icns")
set(CPACK_DMG_DS_STORE_SETUP_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/cmake/CMakeDMGSetup.script")
set(CPACK_DMG_BACKGROUND_IMAGE "${CMAKE_CURRENT_SOURCE_DIR}/cmake/dmgBackground.tif")
else()
# linux
if(CPACK_GENERATOR STREQUAL "RPM")
set(CPACK_RPM_PACKAGE_LICENSE "GPLv2")
set(CPACK_RPM_MAIN_COMPONENT "cockatrice")
if(Qt6_FOUND)
set(CPACK_RPM_PACKAGE_REQUIRES "protobuf, qt6-qttools, qt6-qtsvg, qt6-qtmultimedia")
elseif(Qt5_FOUND)
set(CPACK_RPM_PACKAGE_REQUIRES "protobuf, qt5-qttools, qt5-qtsvg, qt5-qtmultimedia")
endif()
set(CPACK_RPM_PACKAGE_GROUP "Amusements/Games")
set(CPACK_RPM_PACKAGE_URL "http://github.com/Cockatrice/Cockatrice")
# stop directories from making package conflicts
set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION
/usr/share/applications
/usr/share/icons
/usr/share/icons/hicolor
/usr/share/icons/hicolor/48x48
/usr/share/icons/hicolor/48x48/apps
/usr/share/icons/hicolor/scalable
/usr/share/icons/hicolor/scalable/apps
)
if(APPLE)
set(CPACK_GENERATOR DragNDrop ${CPACK_GENERATOR})
set(CPACK_GENERATOR "DragNDrop")
set(CPACK_DMG_FORMAT "UDBZ")
set(CPACK_DMG_VOLUME_NAME "${PROJECT_NAME}")
set(CPACK_SYSTEM_NAME "OSX")
set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/cockatrice/resources/appicon.icns")
else()
set(CPACK_GENERATOR DEB)
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
set(CPACK_DEBIAN_PACKAGE_SECTION "games")
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "http://github.com/Cockatrice/Cockatrice")
if(Qt6_FOUND)
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt6multimedia6, libqt6svg6, qt6-qpa-plugins")
elseif(Qt5_FOUND)
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt5multimedia5-plugins, libqt5svg5")
endif()
# linux
IF(CPACK_GENERATOR STREQUAL "RPM")
set(CPACK_RPM_PACKAGE_LICENSE "GPLv2")
set(CPACK_RPM_PACKAGE_REQUIRES "protobuf, qt5-qttools, qt5-qtsvg, qt5-qtmultimedia")
set(CPACK_RPM_PACKAGE_GROUP "Amusements/Games")
set(CPACK_RPM_PACKAGE_URL "http://github.com/Cockatrice/Cockatrice")
ELSE()
set(CPACK_GENERATOR DEB)
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
set(CPACK_DEBIAN_PACKAGE_SECTION "games")
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "http://github.com/Cockatrice/Cockatrice")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt5multimedia5-plugins, libqt5svg5")
ENDIF()
endif()
endif()
elseif(WIN32)
set(CPACK_GENERATOR NSIS ${CPACK_GENERATOR})
if("${CMAKE_GENERATOR_PLATFORM}" MATCHES "(x64)")
set(TRICE_IS_64_BIT 1)
else()
set(TRICE_IS_64_BIT 0)
endif()
set(CPACK_GENERATOR NSIS ${CPACK_GENERATOR})
if("${CMAKE_GENERATOR_PLATFORM}" MATCHES "(x64)")
set(TRICE_IS_64_BIT 1)
else()
set(TRICE_IS_64_BIT 0)
endif()
# Configure file with custom definitions for NSIS.
configure_file("${COCKATRICE_CMAKE_PATH}/NSIS.definitions.nsh.in" "${PROJECT_BINARY_DIR}/NSIS.definitions.nsh")
# Configure file with custom definitions for NSIS.
configure_file(
${CMAKE_MODULE_PATH}/NSIS.definitions.nsh.in
${PROJECT_BINARY_DIR}/NSIS.definitions.nsh
)
# include vcredist into the package; NSIS will take care of running it
if(VCREDISTRUNTIME_FOUND)
install(FILES "${VCREDISTRUNTIME_FILE}" DESTINATION ./)
endif()
# include vcredist into the package; NSIS will take care of running it
if(VCREDISTRUNTIME_FOUND)
INSTALL(FILES "${VCREDISTRUNTIME_FILE}" DESTINATION ./)
endif()
endif()
include(CPack)
# Compile servatrice (default off)
option(WITH_SERVER "build servatrice" OFF)
add_subdirectory(common)
if(WITH_SERVER)
add_subdirectory(servatrice)
set(CPACK_INSTALL_CMAKE_PROJECTS "Servatrice;Servatrice;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
add_subdirectory(servatrice)
SET(CPACK_INSTALL_CMAKE_PROJECTS "Servatrice;Servatrice;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
endif()
# Compile cockatrice (default on)
option(WITH_CLIENT "build cockatrice" ON)
if(WITH_CLIENT)
add_subdirectory(cockatrice)
set(CPACK_INSTALL_CMAKE_PROJECTS "Cockatrice;Cockatrice;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
add_subdirectory(cockatrice)
SET(CPACK_INSTALL_CMAKE_PROJECTS "Cockatrice;Cockatrice;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
endif()
# Compile oracle (default on)
option(WITH_ORACLE "build oracle" ON)
if(WITH_ORACLE)
add_subdirectory(oracle)
set(CPACK_INSTALL_CMAKE_PROJECTS "Oracle;Oracle;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
add_subdirectory(oracle)
SET(CPACK_INSTALL_CMAKE_PROJECTS "Oracle;Oracle;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
endif()
# Compile dbconverter (default on)
option(WITH_DBCONVERTER "build dbconverter" ON)
if(WITH_DBCONVERTER)
add_subdirectory(dbconverter)
set(CPACK_INSTALL_CMAKE_PROJECTS "Dbconverter;Dbconverter;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
add_subdirectory(dbconverter)
SET(CPACK_INSTALL_CMAKE_PROJECTS "Dbconverter;Dbconverter;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
endif()
# Compile tests (default off)
option(TEST "build tests" OFF)
if(TEST)
include(CTest)
add_subdirectory(tests)
endif()
if(Qt6_FOUND AND Qt6_VERSION_MINOR GREATER_EQUAL 3)
# Qt6.3+ requires project finalization to support translations
qt6_finalize_project()
include(CTest)
add_subdirectory(tests)
endif()

View File

@@ -18,7 +18,7 @@
<br><pre>
<b>To get started, &#8674; [view our webpage](https://cockatrice.github.io/)</b><br>
<b>To get support or suggest changes &#8674; [file an issue](https://github.com/Cockatrice/Cockatrice/issues) ([How?](https://github.com/Cockatrice/Cockatrice/wiki/How-to-Create-a-GitHub-Ticket-Regarding-Cockatrice))</b>
<b>To help with development, see how to [get involved](#get-involved--)</b>
<b>To help with development, see how to [get involved](#get-involved-)</b>
</pre><br>
@@ -40,7 +40,7 @@ Downloads are available for full releases and the current beta version in develo
- To be a Cockatrice Beta Tester, use this version. Find more information [here](https://github.com/Cockatrice/Cockatrice/wiki/Release-Channels)!
# Get Involved [![Discord](https://img.shields.io/discord/314987288398659595?label=Discord&logo=discord&logoColor=white)](https://discord.gg/3Z9yzmA)
# Get Involved [![Discord](https://img.shields.io/discord/314987288398659595?label=Discord&logo=discord&logoColor=white)](https://discord.gg/3Z9yzmA) [![Gitter Chat](https://img.shields.io/gitter/room/Cockatrice/Cockatrice)](https://gitter.im/Cockatrice/Cockatrice)
Join our [Discord community](https://discord.gg/3Z9yzmA) to connect with the project or fellow users of the app. The Cockatrice developers are also available on [Gitter](https://gitter.im/Cockatrice/Cockatrice). Come here to talk about the application, features, or just to hang out.<br>
For support regarding specific servers, please contact that server's admin or forum for support rather than asking here.<br>
@@ -52,6 +52,8 @@ We maintain two tags for contributors to find issues to work on:
For both tags, we're willing to provide help to contributors in showing them where and how they can make changes, as well as code review for changes they submit.
Read the long-term project **roadmap** to see planned edits and milestones [here](https://docs.google.com/document/d/1Ewe5uSaRE2nR2pNPMaGmP6gVZdqgFbBgwSscGqIr4W0/edit).
We try to be responsive to new issues. We'll provide advice on how best to implement a feature; alternately, we can show you where the codebase is doing something similar before you get too far along.
Cockatrice uses the [Google Developer Documentation Style Guide](https://developers.google.com/style/) to ensure consistent documentation. We encourage you to improve the documentation by suggesting edits based on this guide.
@@ -65,9 +67,13 @@ Cockatrice uses the [Google Developer Documentation Style Guide](https://develop
- [reddit r/Cockatrice](https://reddit.com/r/cockatrice)
# Translations [![Transifex Project](https://img.shields.io/badge/translate-on%20transifex-brightgreen)](https://transifex.com/cockatrice/cockatrice/)
# Translations [![Transifex Project](https://img.shields.io/badge/translate-on%20transifex-brightgreen)](https://www.transifex.com/projects/p/cockatrice/)
Cockatrice uses Transifex for translations. You can help us bring Cockatrice, Oracle and Webatrice to your language or just adjust single wordings right from within your browser by visiting our [Transifex project page](https://transifex.com/cockatrice/cockatrice/).<br>
Cockatrice uses Transifex for translations. You can help us bring Cockatrice and Oracle to your language or just edit single wordings right from within your browser by visiting our [Transifex project page](https://www.transifex.com/projects/p/cockatrice/).<br>
| Cockatrice | Oracle |
|:-:|:-:|
| [![Cockatrice Translation Status](https://www.transifex.com/projects/p/cockatrice/resource/cockatrice/chart/image_png/)](https://www.transifex.com/projects/p/cockatrice/) | [![Oracle Translation Status](https://www.transifex.com/projects/p/cockatrice/resource/oracle/chart/image_png/)](https://www.transifex.com/projects/p/cockatrice/) |
Check out our [Translator FAQ](https://github.com/Cockatrice/Cockatrice/wiki/Translation-FAQ) for more information about contributing!<br>
@@ -111,7 +117,6 @@ The following flags can be passed to `cmake`:
- `-DWARNING_AS_ERROR=0` Whether to treat compilation warnings as errors in debug mode (default 1 = yes).
- `-DUPDATE_TRANSLATIONS=1` Configure `make` to update the translation .ts files for new strings in the source code. Note: Running `make clean` will remove the .ts files (default 0 = no).
- `-DTEST=1` Enable regression tests (default 0 = no). Note: needs googletest, will be downloaded on the fly if unavailable. To run tests: ```make test```.
- `-DFORCE_USE_QT5=1` Skip looking for Qt6 before trying to find Qt5
# Run

View File

@@ -1,20 +1,15 @@
#!/bin/bash
# This script will run clang-format on all modified, non-3rd-party C++/Header files.
# Optionally runs cmake-format on all modified cmake files.
# Uses clang-format cmake-format git diff find
# Never, ever, should this receive a path with a newline in it. Don't bother proofing it for that.
# Never, ever, should this recieve a path with a newline in it. Don't bother proofing it for that.
set -o pipefail
# go to the project root directory, this file should be located in the project root directory
olddir="$PWD"
cd "${BASH_SOURCE%/*}/" || exit 2 # could not find path, this could happen with special links etc.
# defaults
include=("common" \
"cockatrice/src" \
"dbconverter/src" \
"oracle/src" \
"servatrice/src" \
"tests")
@@ -27,30 +22,22 @@ exclude=("servatrice/src/smtp" \
exts=("cpp" "h" "proto")
cf_cmd="clang-format"
branch="origin/master"
cmakefile="CMakeLists.txt"
cmakedir="cmake/.*\\.cmake"
cmakeinclude=("cmake/gtest-CMakeLists.txt.in")
color="--"
# parse options
while [[ $* ]]; do
while [[ $@ ]]; do
case "$1" in
'-b'|'--branch')
branch=$2
set_branch=1
shift 2
;;
'--cmake')
do_cmake=1
shift
;;
'-c'|'--color-diff')
color="--color=always"
mode="diff"
color=" --color=always"
mode=diff
shift
;;
'-d'|'--diff')
mode="diff"
mode=diff
shift
;;
'-h'|'--help')
@@ -62,6 +49,7 @@ If <dir>s are given, all source files in those directories of the project root
path are formatted. To only format changed files in these directories use the
--branch option in combination. <dir> has to be a path relative to the project
root path or a full path inside $PWD.
. can not be specified as a dir, if you really want to format everything use */.
USAGE: $0 [option] [--branch <git branch or object>] [<dir> ...]
@@ -80,9 +68,6 @@ OPTIONS:
When not comparing to a branch, git will not be used at all and every
source file in the entire project will be parsed.
--cmake
Use cmake-format to format cmake files as well.
-c, --color-diff
Display a colored diff. Implies --diff.
Only available on systems which support 'diff --color'.
@@ -109,25 +94,22 @@ EXIT CODES:
3 if clang-format could not be found.
EXAMPLES:
$0 --branch $USER/patch-2 ${include[0]}
Formats all changed files compared to the git branch "$USER/patch-2"
in the directory ${include[0]}.
$0 --test . || echo "code requires formatting"
$0 --test \$PWD || echo "code requires formatting"
Tests if the source files in the current directory are correctly
formatted and prints an error message if formatting is required.
$0 --cmake --branch "" ""
Unconditionally format all cmake files and no source files.
$0 --branch $USER/patch-2 ${include[0]}
Formats all changed files compared to the git branch "$USER/patch-2"
in the directory ${include[0]}.
EOM
exit 0
;;
'-n'|'--names')
mode="name"
mode=name
shift
;;
'-t'|'--test')
mode="code"
mode=code
shift
;;
'--cf-version')
@@ -135,28 +117,20 @@ EOM
shift
;;
'--')
dashdash=1
shift
;;
*)
if [[ ! $dashdash && $1 =~ ^-- ]]; then
echo "error in parsing arguments of $0: $1 is an unrecognized option" >&2
exit 2 # input error
fi
if [[ ! $1 ]] || next_dir=$(cd "$olddir" && cd -- "$1" && pwd); then
if ! [[ $set_include ]]; then
if next_dir=$(cd "$1" && pwd); then
if [[ ${next_dir#$PWD/} == /* ]]; then
echo "error in parsing arguments of $0: $next_dir is not in $PWD" >&2
exit 2 # input error
elif ! [[ $set_include ]]; then
include=() # remove default includes
set_include=1
fi
if [[ $1 ]]; then
if [[ $next_dir != $PWD/* ]]; then
echo "error in parsing arguments of $0: $next_dir is not in $PWD" >&2
exit 2 # input error
fi
include+=("$next_dir")
fi
include+=("${next_dir#$PWD/}")
else
echo "error in parsing arguments of $0: $1 is not a directory" >&2
echo "error in parsing arguments of $0: $PWD/$1 is not a directory" >&2
exit 2 # input error
fi
if ! [[ $set_branch ]]; then
@@ -179,93 +153,37 @@ if ! hash $cf_cmd 2>/dev/null; then
fi
fi
# check availability of cmake-format
if [[ $do_cmake ]] && ! hash cmake-format 2>/dev/null; then
echo "could not find cmake-format" >&2
exit 3
fi
if [[ $branch ]]; then
# get all dirty files through git
if ! base=$(git merge-base "$branch" HEAD); then
if ! base=$(git merge-base ${branch} HEAD); then
echo "could not find git merge base" >&2
exit 2 # input error
fi
mapfile -t basenames < <(git diff --diff-filter=d --name-only "$base")
names=()
for ex in "${exts[@]}"; do
for path in "${include[@]}"; do
for name in "${basenames[@]}"; do
rx="^$path/.*\\.$ex$"
if [[ $name =~ $rx ]]; then
names+=("$name")
fi
done
done
declare -a reg
for ex in ${exts[@]}; do
reg+=(${include[@]/%/.*\\.$ex\$})
done
if [[ $do_cmake ]]; then
cmake_names=()
for name in "${basenames[@]}"; do
dirrx="^$cmakedir$"
filerx="(^|/)$cmakefile$"
if [[ $name =~ $dirrx || $name =~ $filerx ]]; then
cmake_names+=("$name")
fi
for include in "${cmakeinclude[@]}"; do
if [[ $name == "$include" ]]; then
cmake_names+=("$name")
fi
done
done
fi
names=$(git diff --diff-filter=d --name-only $base | grep ${reg[@]/#/-e ^})
else
exts_o=()
for ext in "${exts[@]}"; do
exts_o+=(-o -name "*\\.$ext")
done
unset "exts_o[0]" # remove first -o
mapfile -t names < <(find "${include[@]}" -type f "${exts_o[@]}")
if [[ $do_cmake ]]; then
mapfile -t cmake_names < <(find . -maxdepth 2 -type f -name "$cmakefile" -o -path "./${cmakedir/.}")
cmake_names+=("${cmakeinclude[@]}")
fi
names=$(find ${include[@]} -type f -false ${exts[@]/#/-o -name *\\.})
fi
# filter excludes
for path in "${exclude[@]}"; do
for i in "${!names[@]}"; do
rx="^$path/"
if [[ ${names[$i]} =~ $rx ]]; then
unset "names[$i]"
fi
done
done
names=$(<<<"$names" grep -v ${exclude[@]/#/-e ^})
# optionally print version
if [[ $print_version ]]; then
$cf_cmd -version
[[ $do_cmake ]] && echo "cmake-format $(cmake-format --version)"
echo "----------"
fi
if [[ ! ${cmake_names[*]} ]]; then
unset do_cmake
fi
if [[ ! ( ${names[*]} || $do_cmake ) ]]; then
if ! [[ $names ]]; then
exit 0 # nothing to format means format is successful!
fi
# optionally print version
[[ $print_version ]] && $cf_cmd -version
# format
case $mode in
diff)
declare -i code=0
for name in "${names[@]}"; do
if ! $cf_cmd "$name" | diff "$name" - -p "$color"; then
code=1
fi
done
for name in "${cmake_names[@]}"; do
if ! cmake-format "$name" | diff "$name" - -p "$color"; then
for name in ${names[@]}; do
if ! $cf_cmd "$name" | diff "$name" - -p $color; then
code=1
fi
done
@@ -273,34 +191,20 @@ case $mode in
;;
name)
declare -i code=0
for name in "${names[@]}"; do
for name in ${names[@]}; do
if ! $cf_cmd "$name" | diff "$name" - -q >/dev/null; then
echo "$name"
code=1
fi
done
for name in "${cmake_names[@]}"; do
if ! cmake-format "$name" --check; then
echo "$name"
code=1
fi
done
exit $code
;;
code)
for name in "${names[@]}"; do
for name in ${names[@]}; do
$cf_cmd "$name" | diff "$name" - -q >/dev/null || exit 1
done
for name in "${cmake_names[@]}"; do
cmake-format "$name" --check || exit 1
done
;;
*)
if [[ "${names[*]}" ]]; then
$cf_cmd -i "${names[@]}"
fi
if [[ $do_cmake ]]; then
cmake-format -i "${cmake_names[@]}"
fi
$cf_cmd -i $names
;;
esac

View File

@@ -1,55 +0,0 @@
on run argv
set image_name to item 1 of argv
tell application "Finder"
tell disk image_name
-- wait for the image to finish mounting
set open_attempts to 0
repeat while open_attempts < 4
try
open
delay 1
set open_attempts to 5
close
on error errStr number errorNumber
set open_attempts to open_attempts + 1
delay 10
end try
end repeat
delay 5
-- open the image the first time and save a DS_Store with just
-- background and icon setup
open
set current view of container window to icon view
set theViewOptions to the icon view options of container window
set background picture of theViewOptions to file ".background:background.tif"
set arrangement of theViewOptions to not arranged
set icon size of theViewOptions to 128
delay 5
close
-- next setup the position of the app and Applications symlink
-- plus hide all the window decoration
open
update without registering applications
tell container window
set sidebar width to 0
set statusbar visible to false
set toolbar visible to false
set the bounds to { 400, 100, 1400, 922 }
set position of item "Cockatrice.app" to { 139, 214 }
set position of item "Oracle.app" to { 139, 414 }
set position of item "Servatrice.app" to { 139, 614 }
set position of item "dbconverter.app" to { 1400, 1400 }
set position of item "Applications" to { 861, 414 }
end tell
update without registering applications
delay 5
close
end tell
delay 1
end tell
end run

View File

@@ -1,18 +1,18 @@
# Find the LibExecinfo library - FreeBSD only
find_path(LIBEXECINFO_INCLUDE_DIR execinfo.h)
find_library(LIBEXECINFO_LIBRARY NAMES execinfo)
FIND_PATH(LIBEXECINFO_INCLUDE_DIR execinfo.h)
FIND_LIBRARY(LIBEXECINFO_LIBRARY NAMES execinfo)
if(LIBEXECINFO_INCLUDE_DIR AND LIBEXECINFO_LIBRARY)
set(LIBEXECINFO_FOUND TRUE)
endif()
IF(LIBEXECINFO_INCLUDE_DIR AND LIBEXECINFO_LIBRARY)
SET(LIBEXECINFO_FOUND TRUE)
ENDIF()
if(LIBEXECINFO_FOUND)
if(NOT LIBEXECINFO_FIND_QUIETLY)
message(STATUS "Found LibExecinfo: ${EXECINFO_LIBRARY}")
endif()
else()
if(LIBEXECINFO_FIND_REQUIRED)
message(FATAL_ERROR "Could not find LibExecinfo")
endif()
endif()
IF(LIBEXECINFO_FOUND)
IF(NOT LIBEXECINFO_FIND_QUIETLY)
MESSAGE(STATUS "Found LibExecinfo: ${EXECINFO_LIBRARY}")
ENDIF()
ELSE()
IF(LIBEXECINFO_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find LibExecinfo")
ENDIF()
ENDIF()

View File

@@ -1,117 +0,0 @@
# Find a compatible Qt version
# 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)
if(WITH_SERVER)
set(_SERVATRICE_NEEDED Network Sql WebSockets)
endif()
if(WITH_CLIENT)
set(_COCKATRICE_NEEDED
Concurrent
Gui
Multimedia
Network
PrintSupport
Svg
WebSockets
Widgets
)
endif()
if(WITH_ORACLE)
set(_ORACLE_NEEDED Concurrent Network Svg Widgets)
endif()
if(WITH_DBCONVERTER)
set(_DBCONVERTER_NEEDED Network Widgets)
endif()
if(TEST)
set(_TEST_NEEDED Widgets)
endif()
set(REQUIRED_QT_COMPONENTS ${REQUIRED_QT_COMPONENTS} ${_SERVATRICE_NEEDED} ${_COCKATRICE_NEEDED} ${_ORACLE_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.2.3
COMPONENTS ${REQUIRED_QT_COMPONENTS} Linguist
QUIET HINTS ${Qt6_DIR}
)
endif()
if(Qt6_FOUND)
set(COCKATRICE_QT_VERSION_NAME Qt6)
list(FIND Qt6LinguistTools_TARGETS Qt6::lrelease QT6_LRELEASE_INDEX)
if(QT6_LRELEASE_INDEX EQUAL -1)
message(WARNING "Qt6 lrelease not found.")
endif()
list(FIND Qt6LinguistTools_TARGETS Qt6::lupdate QT6_LUPDATE_INDEX)
if(QT6_LUPDATE_INDEX EQUAL -1)
message(WARNING "Qt6 lupdate not found.")
endif()
else()
find_package(
Qt5 5.8.0
COMPONENTS ${REQUIRED_QT_COMPONENTS}
QUIET HINTS ${Qt5_DIR}
)
if(Qt5_FOUND)
set(COCKATRICE_QT_VERSION_NAME Qt5)
else()
message(FATAL_ERROR "No suitable version of Qt was found")
endif()
# Qt5 Linguist is in a separate package
find_package(Qt5LinguistTools QUIET)
if(Qt5LinguistTools_FOUND)
if(NOT Qt5_LRELEASE_EXECUTABLE)
message(WARNING "Qt5 lrelease not found.")
endif()
if(NOT Qt5_LUPDATE_EXECUTABLE)
message(WARNING "Qt5 lupdate not found.")
endif()
else()
message(WARNING "Linguist Tools not found, cannot handle translations")
endif()
endif()
if(Qt5_POSITION_INDEPENDENT_CODE OR Qt6_FOUND)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif()
# Establish Qt Plugins directory & Library directories
get_target_property(QT_LIBRARY_DIR ${COCKATRICE_QT_VERSION_NAME}::Core LOCATION)
get_filename_component(QT_LIBRARY_DIR ${QT_LIBRARY_DIR} DIRECTORY)
if(Qt6_FOUND)
get_filename_component(QT_PLUGINS_DIR "${Qt6Core_DIR}/../../../${QT6_INSTALL_PLUGINS}" ABSOLUTE)
get_filename_component(QT_LIBRARY_DIR "${QT_LIBRARY_DIR}/../../.." ABSOLUTE)
if(UNIX AND APPLE)
# Mac needs a bit more help finding all necessary components
list(APPEND QT_LIBRARY_DIR "/usr/local/lib")
endif()
elseif(Qt5_FOUND)
get_filename_component(QT_PLUGINS_DIR "${Qt5Core_DIR}/../../../plugins" ABSOLUTE)
get_filename_component(QT_LIBRARY_DIR "${QT_LIBRARY_DIR}/.." ABSOLUTE)
endif()
message(DEBUG "QT_PLUGINS_DIR = ${QT_PLUGINS_DIR}")
message(DEBUG "QT_LIBRARY_DIR = ${QT_LIBRARY_DIR}")
# Establish exports
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}")
message(STATUS "Found Qt ${${COCKATRICE_QT_VERSION_NAME}_VERSION} at: ${${COCKATRICE_QT_VERSION_NAME}_DIR}")

View File

@@ -1,42 +1,36 @@
# Find the MS Visual Studio VC redistributable package
if(WIN32)
set(VCREDISTRUNTIME_FOUND "NO")
if (WIN32)
set(VCREDISTRUNTIME_FOUND "NO")
if(CMAKE_SIZEOF_VOID_P EQUAL 8) # 64-bit
set(REDIST_ARCH x64)
else()
set(REDIST_ARCH x86)
endif()
if(CMAKE_SIZEOF_VOID_P EQUAL 8) # 64-bit
set(REDIST_ARCH x64)
else()
set(REDIST_ARCH x86)
endif()
# VS 2017 uses vcredist_ARCH.exe, VS 2022 uses vc_redist.ARCH.exe
set(REDIST_FILE_NAMES vcredist_${REDIST_ARCH}.exe vcredist.${REDIST_ARCH}.exe vc_redist.${REDIST_ARCH}.exe)
set(REDIST_FILE vcredist_${REDIST_ARCH}.exe)
set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP TRUE)
include(InstallRequiredSystemLibraries)
set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP TRUE)
include(InstallRequiredSystemLibraries)
# Check if the list contains minimum one element, to get the path from
list(LENGTH CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS libsCount)
if(libsCount GREATER 0)
list(GET CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS 0 _path)
# Check if the list contains minimum one element, to get the path from
list(LENGTH CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS libsCount)
if (libsCount GREATER 0)
list(GET CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS 0 _path)
get_filename_component(_path ${_path} DIRECTORY)
get_filename_component(_path ${_path}/../../ ABSOLUTE)
get_filename_component(_path ${_path} DIRECTORY)
get_filename_component(_path ${_path}/../../ ABSOLUTE)
foreach(redist_file ${REDIST_FILE_NAMES})
if(EXISTS "${_path}/${redist_file}")
set(VCREDISTRUNTIME_FOUND "YES")
set(VCREDISTRUNTIME_FILE ${_path}/${redist_file})
break()
endif()
endforeach()
endif()
if (EXISTS "${_path}/${REDIST_FILE}") # VS 2017
set(VCREDISTRUNTIME_FOUND "YES")
set(VCREDISTRUNTIME_FILE ${_path}/${REDIST_FILE})
endif()
endif()
if(VCREDISTRUNTIME_FOUND)
message(STATUS "Found VCredist ${VCREDISTRUNTIME_FILE}")
else()
message(
WARNING "Could not find VCredist package. It's not required for compiling, but needs to be available at runtime."
)
endif()
if(VCREDISTRUNTIME_FOUND)
message(STATUS "Found VCredist ${VCREDISTRUNTIME_FILE}")
else()
message(WARNING "Could not find VCredist package. It's not required for compiling, but needs to be available at runtime.")
endif()
endif()

View File

@@ -0,0 +1,77 @@
# Find the OpenSSL runtime libraries (.dll) for Windows that
# will be needed by Qt in order to access https urls.
if (WIN32)
# Get standard installation paths for OpenSSL under Windows
# http://www.slproweb.com/products/Win32OpenSSL.html
if( CMAKE_SIZEOF_VOID_P EQUAL 8 )
# target win64
set(_OPENSSL_ROOT_HINTS
${OPENSSL_ROOT_DIR}
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (64-bit)_is1;Inno Setup: App Path]"
ENV OPENSSL_ROOT_DIR
)
file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _programfiles)
set(_OPENSSL_ROOT_PATHS
"C:/Tools/vcpkg/installed/x64-windows/bin"
"${_programfiles}/OpenSSL-Win64"
"C:/OpenSSL-Win64/"
)
unset(_programfiles)
else( CMAKE_SIZEOF_VOID_P EQUAL 8 )
# target win32
set(_OPENSSL_ROOT_HINTS
${OPENSSL_ROOT_DIR}
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (32-bit)_is1;Inno Setup: App Path]"
ENV OPENSSL_ROOT_DIR
)
file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _programfiles)
set(_OPENSSL_ROOT_PATHS
"C:/Tools/vcpkg/installed/x86-windows/bin"
"${_programfiles}/OpenSSL"
"${_programfiles}/OpenSSL-Win32"
"C:/OpenSSL/"
"C:/OpenSSL-Win32/"
)
unset(_programfiles)
endif( CMAKE_SIZEOF_VOID_P EQUAL 8 )
else ()
set(_OPENSSL_ROOT_HINTS
${OPENSSL_ROOT_DIR}
ENV OPENSSL_ROOT_DIR
)
endif ()
set(_OPENSSL_ROOT_HINTS_AND_PATHS
HINTS ${_OPENSSL_ROOT_HINTS}
PATHS ${_OPENSSL_ROOT_PATHS}
)
# For OpenSSL < 1.1, they are named libeay32 and ssleay32 and even if the dll is 64bit, it's still suffixed as *32.dll
# For OpenSSL >= 1.1, they are named libcrypto and libssl with no suffix
if( CMAKE_SIZEOF_VOID_P EQUAL 8 )
# target win64
FIND_FILE(WIN32SSLRUNTIME_LIBEAY NAMES libcrypto-1_1-x64.dll libcrypto.dll libeay32.dll ${_OPENSSL_ROOT_HINTS_AND_PATHS})
FIND_FILE(WIN32SSLRUNTIME_SSLEAY NAMES libssl-1_1-x64.dll libssl.dll ssleay32.dll ${_OPENSSL_ROOT_HINTS_AND_PATHS})
else( CMAKE_SIZEOF_VOID_P EQUAL 8 )
# target win32
FIND_FILE(WIN32SSLRUNTIME_LIBEAY NAMES libcrypto-1_1.dll libcrypto.dll libeay32.dll ${_OPENSSL_ROOT_HINTS_AND_PATHS})
FIND_FILE(WIN32SSLRUNTIME_SSLEAY NAMES libssl-1_1.dll libssl.dll ssleay32.dll ${_OPENSSL_ROOT_HINTS_AND_PATHS})
endif( CMAKE_SIZEOF_VOID_P EQUAL 8 )
IF(WIN32SSLRUNTIME_LIBEAY AND WIN32SSLRUNTIME_SSLEAY)
SET(WIN32SSLRUNTIME_LIBRARIES "${WIN32SSLRUNTIME_LIBEAY}" "${WIN32SSLRUNTIME_SSLEAY}")
SET(WIN32SSLRUNTIME_FOUND "YES")
message(STATUS "Found OpenSSL ${WIN32SSLRUNTIME_LIBRARIES}")
ELSE()
SET(WIN32SSLRUNTIME_FOUND "NO")
message(WARNING "Could not find OpenSSL runtime libraries. They are not required for compiling, but needs to be available at runtime.")
ENDIF()
MARK_AS_ADVANCED(
WIN32SSLRUNTIME_LIBEAY
WIN32SSLRUNTIME_SSLEAY
)

View File

@@ -248,20 +248,20 @@ ${If} $PortableMode = 0
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "VersionMajor" "@CPACK_PACKAGE_VERSION_MAJOR@"
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "VersionMinor" "@CPACK_PACKAGE_VERSION_MINOR@"
IfFileExists "$INSTDIR\vc_redist.x86.exe" VcRedist86Exists PastVcRedist86Check
IfFileExists "$INSTDIR\vcredist_x86.exe" VcRedist86Exists PastVcRedist86Check
VcRedist86Exists:
ExecWait '"$INSTDIR\vc_redist.x86.exe" /passive /norestart'
ExecWait '"$INSTDIR\vcredist_x86.exe" /passive /norestart'
DetailPrint "Wait to ensure unlock of vc_redist file after installation..."
Sleep 3000
Delete "$INSTDIR\vc_redist.x86.exe"
Delete "$INSTDIR\vcredist_x86.exe"
PastVcRedist86Check:
IfFileExists "$INSTDIR\vc_redist.x64.exe" VcRedist64Exists PastVcRedist64Check
IfFileExists "$INSTDIR\vcredist_x64.exe" VcRedist64Exists PastVcRedist64Check
VcRedist64Exists:
ExecWait '"$INSTDIR\vc_redist.x64.exe" /passive /norestart'
ExecWait '"$INSTDIR\vcredist_x64.exe" /passive /norestart'
DetailPrint "Sleep to ensure unlock of vc_redist file after installation..."
Sleep 3000
Delete "$INSTDIR\vc_redist.x64.exe"
Delete "$INSTDIR\vcredist_x64.exe"
PastVcRedist64Check:
${Else}

View File

@@ -1,24 +1,21 @@
set(VERSION_STRING_CPP "${PROJECT_BINARY_DIR}/version_string.cpp")
set(VERSION_STRING_H "${PROJECT_BINARY_DIR}/version_string.h")
include_directories(${PROJECT_BINARY_DIR})
INCLUDE_DIRECTORIES(${PROJECT_BINARY_DIR})
set(hstring
"extern const char *VERSION_STRING\;
set( hstring "extern const char *VERSION_STRING\;
extern const char *VERSION_COMMIT\;
extern const char *VERSION_DATE\;\n"
)
set(cppstring
"const char *VERSION_STRING = \"${PROJECT_VERSION_FRIENDLY}\"\;
extern const char *VERSION_DATE\;\n" )
set( cppstring "const char *VERSION_STRING = \"${PROJECT_VERSION_FRIENDLY}\"\;
const char *VERSION_COMMIT = \"${GIT_COMMIT_ID}\"\;
const char *VERSION_DATE = \"${GIT_COMMIT_DATE_FRIENDLY}\"\;\n"
)
const char *VERSION_DATE = \"${GIT_COMMIT_DATE_FRIENDLY}\"\;\n")
file(WRITE ${PROJECT_BINARY_DIR}/version_string.cpp.txt ${cppstring})
file(WRITE ${PROJECT_BINARY_DIR}/version_string.h.txt ${hstring})
file(WRITE ${PROJECT_BINARY_DIR}/version_string.cpp.txt ${cppstring} )
file(WRITE ${PROJECT_BINARY_DIR}/version_string.h.txt ${hstring} )
execute_process(
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PROJECT_BINARY_DIR}/version_string.h.txt ${VERSION_STRING_H}
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PROJECT_BINARY_DIR}/version_string.h.txt ${VERSION_STRING_H}
)
execute_process(
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PROJECT_BINARY_DIR}/version_string.cpp.txt ${VERSION_STRING_CPP}
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PROJECT_BINARY_DIR}/version_string.cpp.txt ${VERSION_STRING_CPP}
)

Binary file not shown.

View File

@@ -1,187 +1,154 @@
# HELPER FUNCTIONS
function(get_commit_id)
# get last commit hash
execute_process(
COMMAND ${GIT_EXECUTABLE} log -1 --abbrev=7 --date=short "--pretty=%h"
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
RESULT_VARIABLE res_var
OUTPUT_VARIABLE GIT_COM_ID
)
if(NOT ${res_var} EQUAL 0)
message(WARNING "Git failed (not a repo, or no tags). Build will not contain git revision info.")
return()
endif()
# get last commit hash
execute_process(
COMMAND ${GIT_EXECUTABLE} log -1 --abbrev=7 --date=short "--pretty=%h"
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
RESULT_VARIABLE res_var
OUTPUT_VARIABLE GIT_COM_ID
)
if(NOT ${res_var} EQUAL 0)
message(WARNING "Git failed (not a repo, or no tags). Build will not contain git revision info.")
return()
endif()
string(REPLACE "\n" "" GIT_COM_ID "${GIT_COM_ID}")
set(GIT_COMMIT_ID
"${GIT_COM_ID}"
PARENT_SCOPE
)
set(PROJECT_VERSION_LABEL
"custom(${GIT_COM_ID})"
PARENT_SCOPE
)
string(REPLACE "\n" "" GIT_COM_ID "${GIT_COM_ID}")
set(GIT_COMMIT_ID "${GIT_COM_ID}" PARENT_SCOPE)
set(PROJECT_VERSION_LABEL "custom(${GIT_COM_ID})" PARENT_SCOPE)
endfunction()
function(get_commit_date)
# get last commit date
execute_process(
COMMAND ${GIT_EXECUTABLE} log -1 --date=short "--pretty=%cd"
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
RESULT_VARIABLE res_var
OUTPUT_VARIABLE GIT_COM_DATE
)
if(NOT ${res_var} EQUAL 0)
message(WARNING "Git failed (not a repo, or no tags). Build will not contain git revision info.")
return()
endif()
# get last commit date
execute_process(
COMMAND ${GIT_EXECUTABLE} log -1 --date=short "--pretty=%cd"
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
RESULT_VARIABLE res_var
OUTPUT_VARIABLE GIT_COM_DATE
)
if(NOT ${res_var} EQUAL 0)
message(WARNING "Git failed (not a repo, or no tags). Build will not contain git revision info.")
return()
endif()
string(REPLACE "\n" "" GIT_COM_DATE "${GIT_COM_DATE}")
set(GIT_COMMIT_DATE_FRIENDLY
"${GIT_COM_DATE}"
PARENT_SCOPE
)
string(REPLACE "\n" "" GIT_COM_DATE "${GIT_COM_DATE}")
set(GIT_COMMIT_DATE_FRIENDLY "${GIT_COM_DATE}" PARENT_SCOPE)
string(REPLACE "-" "" GIT_COM_DATE "${GIT_COM_DATE}")
set(GIT_COMMIT_DATE
"${GIT_COM_DATE}"
PARENT_SCOPE
)
string(REPLACE "-" "" GIT_COM_DATE "${GIT_COM_DATE}")
set(GIT_COMMIT_DATE "${GIT_COM_DATE}" PARENT_SCOPE)
endfunction()
function(get_tag_name commit)
if(${commit} STREQUAL "unknown")
return()
endif()
if(${commit} STREQUAL "unknown")
return()
endif()
execute_process(
COMMAND ${GIT_EXECUTABLE} describe --exact-match --tags ${commit}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
RESULT_VARIABLE res_var
OUTPUT_VARIABLE GIT_TAG
ERROR_VARIABLE GIT_TAG_ERR
)
execute_process(
COMMAND ${GIT_EXECUTABLE} describe --exact-match --tags ${commit}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
RESULT_VARIABLE res_var
OUTPUT_VARIABLE GIT_TAG
ERROR_VARIABLE GIT_TAG_ERR
)
if((NOT ${res_var} EQUAL 0) OR (${GIT_TAG_ERR} MATCHES "fatal: no tag exactly matches.*"))
message(STATUS "Commit is not a release or prerelease (no git tag found)")
return()
endif()
if((NOT ${res_var} EQUAL 0) OR (${GIT_TAG_ERR} MATCHES "fatal: no tag exactly matches.*"))
message(STATUS "Commit is not a release or prerelease (no git tag found)")
return()
endif()
string(REPLACE "\n" "" GIT_TAG "${GIT_TAG}")
message(STATUS "Commit is a release or prerelease, git tag: ${GIT_TAG}")
string(REPLACE "\n" "" GIT_TAG "${GIT_TAG}")
message(STATUS "Commit is a release or prerelease, git tag: ${GIT_TAG}")
# Extract information from tag:
# YYYY-MM-DD-Release-MAJ.MIN.PATCH
# YYYY-MM-DD-Development-MAJ.MIN.PATCH-beta.X
string(REPLACE "-" ";" GIT_TAG_EXPLODED "${GIT_TAG}")
string(REPLACE "." ";" GIT_TAG_EXPLODED "${GIT_TAG_EXPLODED}")
# Extract information from tag:
# YYYY-MM-DD-Release-MAJ.MIN.PATCH
# YYYY-MM-DD-Development-MAJ.MIN.PATCH-beta.X
string(REPLACE "-" ";" GIT_TAG_EXPLODED "${GIT_TAG}")
string(REPLACE "." ";" GIT_TAG_EXPLODED "${GIT_TAG_EXPLODED}")
# Sanity checks: length
list(LENGTH GIT_TAG_EXPLODED GIT_TAG_LISTCOUNT)
if(${GIT_TAG_LISTCOUNT} LESS 7 OR ${GIT_TAG_LISTCOUNT} GREATER 9)
message(WARNING "Invalid tag format, got ${GIT_TAG_LISTCOUNT} tokens")
return()
endif()
# Sanity checks: length
list(LENGTH GIT_TAG_EXPLODED GIT_TAG_LISTCOUNT)
if(${GIT_TAG_LISTCOUNT} LESS 7 OR ${GIT_TAG_LISTCOUNT} GREATER 9)
message(WARNING "Invalid tag format, got ${GIT_TAG_LISTCOUNT} tokens")
return()
endif()
# Year
list(GET GIT_TAG_EXPLODED 0 GIT_TAG_YEAR)
if(${GIT_TAG_YEAR} LESS 2017 OR ${GIT_TAG_LISTCOUNT} GREATER 2100)
message(WARNING "Invalid tag year ${GIT_TAG_YEAR}")
return()
endif()
# Year
list(GET GIT_TAG_EXPLODED 0 GIT_TAG_YEAR)
if(${GIT_TAG_YEAR} LESS 2017 OR ${GIT_TAG_LISTCOUNT} GREATER 2100)
message(WARNING "Invalid tag year ${GIT_TAG_YEAR}")
return()
endif()
# Month
list(GET GIT_TAG_EXPLODED 1 GIT_TAG_MONTH)
if(${GIT_TAG_MONTH} LESS 1 OR ${GIT_TAG_MONTH} GREATER 12)
message(WARNING "Invalid tag month ${GIT_TAG_MONTH}")
return()
endif()
# Month
list(GET GIT_TAG_EXPLODED 1 GIT_TAG_MONTH)
if(${GIT_TAG_MONTH} LESS 1 OR ${GIT_TAG_MONTH} GREATER 12)
message(WARNING "Invalid tag month ${GIT_TAG_MONTH}")
return()
endif()
# Day
list(GET GIT_TAG_EXPLODED 2 GIT_TAG_DAY)
if(${GIT_TAG_DAY} LESS 1 OR ${GIT_TAG_DAY} GREATER 31)
message(WARNING "Invalid tag day ${GIT_TAG_DAY}")
return()
endif()
# Day
list(GET GIT_TAG_EXPLODED 2 GIT_TAG_DAY)
if(${GIT_TAG_DAY} LESS 1 OR ${GIT_TAG_DAY} GREATER 31)
message(WARNING "Invalid tag day ${GIT_TAG_DAY}")
return()
endif()
# Type
list(GET GIT_TAG_EXPLODED 3 GIT_TAG_TYPE)
if(NOT (${GIT_TAG_TYPE} STREQUAL "Release" OR ${GIT_TAG_TYPE} STREQUAL "Development"))
message(WARNING "Invalid tag type ${GIT_TAG_TYPE}")
return()
endif()
# Type
list(GET GIT_TAG_EXPLODED 3 GIT_TAG_TYPE)
if(NOT(${GIT_TAG_TYPE} STREQUAL "Release" OR ${GIT_TAG_TYPE} STREQUAL "Development"))
message(WARNING "Invalid tag type ${GIT_TAG_TYPE}")
return()
endif()
# Major
list(GET GIT_TAG_EXPLODED 4 GIT_TAG_MAJOR)
if(${GIT_TAG_MAJOR} LESS 0 OR ${GIT_TAG_MAJOR} GREATER 99)
message(WARNING "Invalid tag major version ${GIT_TAG_MAJOR}")
return()
endif()
# Major
list(GET GIT_TAG_EXPLODED 4 GIT_TAG_MAJOR)
if(${GIT_TAG_MAJOR} LESS 0 OR ${GIT_TAG_MAJOR} GREATER 99)
message(WARNING "Invalid tag major version ${GIT_TAG_MAJOR}")
return()
endif()
# Minor
list(GET GIT_TAG_EXPLODED 5 GIT_TAG_MINOR)
if(${GIT_TAG_MINOR} LESS 0 OR ${GIT_TAG_MINOR} GREATER 99)
message(WARNING "Invalid tag minor version ${GIT_TAG_MINOR}")
return()
endif()
# Minor
list(GET GIT_TAG_EXPLODED 5 GIT_TAG_MINOR)
if(${GIT_TAG_MINOR} LESS 0 OR ${GIT_TAG_MINOR} GREATER 99)
message(WARNING "Invalid tag minor version ${GIT_TAG_MINOR}")
return()
endif()
# Patch
list(GET GIT_TAG_EXPLODED 6 GIT_TAG_PATCH)
if(${GIT_TAG_PATCH} LESS 0 OR ${GIT_TAG_PATCH} GREATER 99)
message(WARNING "Invalid tag patch version ${GIT_TAG_PATCH}")
return()
endif()
# Patch
list(GET GIT_TAG_EXPLODED 6 GIT_TAG_PATCH)
if(${GIT_TAG_PATCH} LESS 0 OR ${GIT_TAG_PATCH} GREATER 99)
message(WARNING "Invalid tag patch version ${GIT_TAG_PATCH}")
return()
endif()
# Label
# 7 = Stable release
# 8 = Dev release, first beta so only "beta" attached
# 9 = Dev release, subsequent beta so "beta.N" attached (N>=2)
if(${GIT_TAG_LISTCOUNT} EQUAL 8)
list(GET GIT_TAG_EXPLODED 7 GIT_TAG_LABEL)
elseif(${GIT_TAG_LISTCOUNT} EQUAL 9)
list(GET GIT_TAG_EXPLODED 7 GIT_TAG_LABEL)
list(GET GIT_TAG_EXPLODED 8 GIT_TAG_LABEL_NUM)
set(GIT_TAG_LABEL ${GIT_TAG_LABEL} ${GIT_TAG_LABEL_NUM})
string(REPLACE ";" "." GIT_TAG_LABEL "${GIT_TAG_LABEL}")
else()
set(GIT_TAG_LABEL "")
endif()
# Label
# 7 = Stable release
# 8 = Dev release, first beta so only "beta" attached
# 9 = Dev release, subsequent beta so "beta.N" attached (N>=2)
if(${GIT_TAG_LISTCOUNT} EQUAL 8)
list(GET GIT_TAG_EXPLODED 7 GIT_TAG_LABEL)
elseif(${GIT_TAG_LISTCOUNT} EQUAL 9)
list(GET GIT_TAG_EXPLODED 7 GIT_TAG_LABEL)
list(GET GIT_TAG_EXPLODED 8 GIT_TAG_LABEL_NUM)
set(GIT_TAG_LABEL ${GIT_TAG_LABEL} ${GIT_TAG_LABEL_NUM})
string(REPLACE ";" "." GIT_TAG_LABEL "${GIT_TAG_LABEL}")
else()
SET(GIT_TAG_LABEL "")
endif()
# Override hardcoded version with the informations from the tag
set(PROJECT_VERSION_MAJOR
${GIT_TAG_MAJOR}
PARENT_SCOPE
)
set(PROJECT_VERSION_MINOR
${GIT_TAG_MINOR}
PARENT_SCOPE
)
set(PROJECT_VERSION_PATCH
${GIT_TAG_PATCH}
PARENT_SCOPE
)
set(PROJECT_VERSION_LABEL
${GIT_TAG_LABEL}
PARENT_SCOPE
)
# Override hardcoded version with the informations from the tag
set(PROJECT_VERSION_MAJOR ${GIT_TAG_MAJOR} PARENT_SCOPE)
set(PROJECT_VERSION_MINOR ${GIT_TAG_MINOR} PARENT_SCOPE)
set(PROJECT_VERSION_PATCH ${GIT_TAG_PATCH} PARENT_SCOPE)
set(PROJECT_VERSION_LABEL ${GIT_TAG_LABEL} PARENT_SCOPE)
if(${GIT_TAG_TYPE} STREQUAL "Development")
set(PROJECT_VERSION_LABEL
${GIT_TAG_LABEL}
PARENT_SCOPE
)
elseif(${GIT_TAG_TYPE} STREQUAL "Release")
set(PROJECT_VERSION_LABEL
""
PARENT_SCOPE
)
# set release name from env var
set(PROJECT_VERSION_RELEASENAME
"${GIT_TAG_RELEASENAME}"
PARENT_SCOPE
)
endif()
if(${GIT_TAG_TYPE} STREQUAL "Development")
set(PROJECT_VERSION_LABEL ${GIT_TAG_LABEL} PARENT_SCOPE)
elseif(${GIT_TAG_TYPE} STREQUAL "Release")
set(PROJECT_VERSION_LABEL "" PARENT_SCOPE)
# set release name from env var
set(PROJECT_VERSION_RELEASENAME "${GIT_TAG_RELEASENAME}" PARENT_SCOPE)
endif()
endfunction()
@@ -196,16 +163,16 @@ set(PROJECT_VERSION_RELEASENAME "")
find_package(Git)
if(GIT_FOUND)
get_commit_id()
get_commit_date()
get_tag_name(${GIT_COMMIT_ID})
get_commit_id()
get_commit_date()
get_tag_name(${GIT_COMMIT_ID})
else()
message(WARNING "Git not found. Build will not contain git revision info.")
message( WARNING "Git not found. Build will not contain git revision info." )
endif()
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
if(PROJECT_VERSION_LABEL)
set(PROJECT_VERSION "${PROJECT_VERSION}-${PROJECT_VERSION_LABEL}")
set(PROJECT_VERSION "${PROJECT_VERSION}-${PROJECT_VERSION_LABEL}")
endif()
set(PROJECT_VERSION_FRIENDLY "${PROJECT_VERSION} (${GIT_COMMIT_DATE_FRIENDLY})")
@@ -213,7 +180,7 @@ set(PROJECT_VERSION_FRIENDLY "${PROJECT_VERSION} (${GIT_COMMIT_DATE_FRIENDLY})")
# Format: <program name>[-ReleaseName]-MAJ.MIN.PATCH[-prerelease_label]
set(PROJECT_VERSION_FILENAME "${PROJECT_NAME}")
if(PROJECT_VERSION_RELEASENAME)
set(PROJECT_VERSION_FILENAME "${PROJECT_VERSION_FILENAME}-${PROJECT_VERSION_RELEASENAME}")
set(PROJECT_VERSION_FILENAME "${PROJECT_VERSION_FILENAME}-${PROJECT_VERSION_RELEASENAME}")
endif()
set(PROJECT_VERSION_FILENAME "${PROJECT_VERSION_FILENAME}-${PROJECT_VERSION}")

View File

@@ -2,9 +2,9 @@
#
# provides the cockatrice binary
project(Cockatrice VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
PROJECT(Cockatrice VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
set(cockatrice_SOURCES
SET(cockatrice_SOURCES
src/abstractcarddragitem.cpp
src/abstractcarditem.cpp
src/abstractclient.cpp
@@ -48,7 +48,6 @@ set(cockatrice_SOURCES
src/dlg_load_remote_deck.cpp
src/dlg_manage_sets.cpp
src/dlg_register.cpp
src/dlg_roll_dice.cpp
src/dlg_settings.cpp
src/dlg_tip_of_the_day.cpp
src/dlg_update.cpp
@@ -128,260 +127,160 @@ set(cockatrice_SOURCES
src/zoneviewwidget.cpp
src/zoneviewzone.cpp
${VERSION_STRING_CPP}
)
)
add_subdirectory(sounds)
add_subdirectory(themes)
set(cockatrice_RESOURCES cockatrice.qrc)
if(UPDATE_TRANSLATIONS)
file(GLOB_RECURSE translate_cockatrice_SRCS ${CMAKE_SOURCE_DIR}/cockatrice/src/*.cpp
${CMAKE_SOURCE_DIR}/cockatrice/src/*.h
)
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(UPDATE_TRANSLATIONS)
IF(UPDATE_TRANSLATIONS)
FILE(GLOB_RECURSE translate_cockatrice_SRCS ${CMAKE_SOURCE_DIR}/cockatrice/src/*.cpp ${CMAKE_SOURCE_DIR}/cockatrice/src/*.h)
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}/translations/cockatrice_en.ts")
ELSE()
FILE(GLOB cockatrice_TS "${CMAKE_CURRENT_SOURCE_DIR}/translations/*.ts")
ENDIF(UPDATE_TRANSLATIONS)
if(WIN32)
set(cockatrice_SOURCES ${cockatrice_SOURCES} cockatrice.rc)
set(cockatrice_SOURCES ${cockatrice_SOURCES} cockatrice.rc)
endif(WIN32)
if(APPLE)
set(MACOSX_BUNDLE_ICON_FILE appicon.icns)
set_source_files_properties(
${CMAKE_CURRENT_SOURCE_DIR}/resources/appicon.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources
)
set(cockatrice_SOURCES ${cockatrice_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/resources/appicon.icns)
endif(APPLE)
set(MACOSX_BUNDLE_ICON_FILE appicon.icns)
set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/resources/appicon.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
set(cockatrice_SOURCES ${cockatrice_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/resources/appicon.icns)
ENDIF(APPLE)
if(Qt6_FOUND)
qt6_add_resources(cockatrice_RESOURCES_RCC ${cockatrice_RESOURCES})
elseif(Qt5_FOUND)
qt5_add_resources(cockatrice_RESOURCES_RCC ${cockatrice_RESOURCES})
# Qt5
find_package(Qt5 COMPONENTS Concurrent Multimedia Network PrintSupport Svg WebSockets Widgets REQUIRED)
set(COCKATRICE_QT_MODULES Qt5::Concurrent Qt5::Multimedia Qt5::Network Qt5::PrintSupport Qt5::Svg Qt5::Widgets Qt5::WebSockets)
# Qt5LinguistTools
find_package(Qt5LinguistTools)
if(Qt5LinguistTools_FOUND)
list(APPEND COCKATRICE_LIBS Qt5::LinguistTools)
if(NOT Qt5_LRELEASE_EXECUTABLE)
MESSAGE(WARNING "Qt's lrelease not found.")
endif()
if(UPDATE_TRANSLATIONS)
if(NOT Qt5_LUPDATE_EXECUTABLE)
MESSAGE(WARNING "Qt's lupdate not found.")
endif()
QT5_CREATE_TRANSLATION(cockatrice_QM ${translate_SRCS} ${cockatrice_TS})
else()
QT5_ADD_TRANSLATION(cockatrice_QM ${cockatrice_TS})
endif()
endif()
QT5_ADD_RESOURCES(cockatrice_RESOURCES_RCC ${cockatrice_RESOURCES})
# Declare path variables
set(ICONDIR
share/icons
CACHE STRING "icon dir"
)
set(DESKTOPDIR
share/applications
CACHE STRING "desktop file destination"
)
set(ICONDIR share/icons CACHE STRING "icon dir")
set(DESKTOPDIR share/applications 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})
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")
# Build cockatrice binary and link it
ADD_EXECUTABLE(cockatrice WIN32 MACOSX_BUNDLE ${cockatrice_SOURCES} ${cockatrice_QM} ${cockatrice_RESOURCES_RCC} ${cockatrice_MOC_SRCS})
if(Qt6_FOUND)
qt6_add_executable(
cockatrice
WIN32
MACOSX_BUNDLE
${cockatrice_SOURCES}
${cockatrice_RESOURCES_RCC}
${cockatrice_MOC_SRCS}
MANUAL_FINALIZATION
)
elseif(Qt5_FOUND)
# Qt5 Translations need to be linked at executable creation time
if(Qt5LinguistTools_FOUND)
if(UPDATE_TRANSLATIONS)
qt5_create_translation(cockatrice_QM ${translate_SRCS} ${cockatrice_TS})
else()
qt5_add_translation(cockatrice_QM ${cockatrice_TS})
endif()
endif()
add_executable(
cockatrice WIN32 MACOSX_BUNDLE ${cockatrice_MOC_SRCS} ${cockatrice_QM} ${cockatrice_RESOURCES_RCC}
${cockatrice_SOURCES}
)
if(UNIX)
if(APPLE)
install(FILES ${cockatrice_QM} DESTINATION ${COCKATRICE_MAC_QM_INSTALL_DIR})
else()
install(FILES ${cockatrice_QM} DESTINATION ${COCKATRICE_UNIX_QM_INSTALL_DIR})
endif()
elseif(WIN32)
install(FILES ${cockatrice_QM} DESTINATION ${COCKATRICE_WIN32_QM_INSTALL_DIR})
endif()
endif()
if(Qt5_FOUND)
target_link_libraries(cockatrice cockatrice_common ${COCKATRICE_QT_MODULES})
else()
target_link_libraries(cockatrice PUBLIC cockatrice_common ${COCKATRICE_QT_MODULES})
endif()
TARGET_LINK_LIBRARIES(cockatrice cockatrice_common ${COCKATRICE_QT_MODULES})
if(UNIX)
if(APPLE)
set(MACOSX_BUNDLE_INFO_STRING "${PROJECT_NAME}")
set(MACOSX_BUNDLE_GUI_IDENTIFIER "com.cockatrice.${PROJECT_NAME}")
set(MACOSX_BUNDLE_LONG_VERSION_STRING "${PROJECT_NAME}-${PROJECT_VERSION}")
set(MACOSX_BUNDLE_BUNDLE_NAME "${PROJECT_NAME}")
set(MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION})
set(MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION})
if(APPLE)
set(MACOSX_BUNDLE_INFO_STRING "${PROJECT_NAME}")
set(MACOSX_BUNDLE_GUI_IDENTIFIER "com.cockatrice.${PROJECT_NAME}")
set(MACOSX_BUNDLE_LONG_VERSION_STRING "${PROJECT_NAME}-${PROJECT_VERSION}")
set(MACOSX_BUNDLE_BUNDLE_NAME "${PROJECT_NAME}")
set(MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION})
set(MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION})
set_target_properties(cockatrice PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/cmake/Info.plist)
set_target_properties(cockatrice PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/cmake/Info.plist)
install(TARGETS cockatrice BUNDLE DESTINATION ./)
else()
# Assume linux
install(TARGETS cockatrice RUNTIME DESTINATION bin/)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/cockatrice.png DESTINATION ${ICONDIR}/hicolor/48x48/apps)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/cockatrice.svg DESTINATION ${ICONDIR}/hicolor/scalable/apps)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/cockatrice.desktop DESTINATION ${DESKTOPDIR})
endif()
INSTALL(TARGETS cockatrice BUNDLE DESTINATION ./)
INSTALL(FILES ${cockatrice_QM} DESTINATION ./cockatrice.app/Contents/Resources/translations)
else()
# Assume linux
INSTALL(TARGETS cockatrice RUNTIME DESTINATION bin/)
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/cockatrice.png DESTINATION ${ICONDIR}/hicolor/48x48/apps)
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/cockatrice.svg DESTINATION ${ICONDIR}/hicolor/scalable/apps)
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/cockatrice.desktop DESTINATION ${DESKTOPDIR})
INSTALL(FILES ${cockatrice_QM} DESTINATION share/cockatrice/translations)
endif()
elseif(WIN32)
install(TARGETS cockatrice RUNTIME DESTINATION ./)
INSTALL(TARGETS cockatrice RUNTIME DESTINATION ./)
INSTALL(FILES ${cockatrice_QM} DESTINATION ./translations)
endif()
if(APPLE)
# these needs to be relative to CMAKE_INSTALL_PREFIX
set(plugin_dest_dir cockatrice.app/Contents/Plugins)
set(qtconf_dest_dir cockatrice.app/Contents/Resources)
# these needs to be relative to CMAKE_INSTALL_PREFIX
set(plugin_dest_dir cockatrice.app/Contents/Plugins)
set(qtconf_dest_dir cockatrice.app/Contents/Resources)
get_filename_component(QT_LIBRARY_DIR "${QT_LIBRARY_DIR}/.." ABSOLUTE)
# Qt plugins: audio (Qt5), iconengines, imageformats, platforms, printsupport (Qt5), styles, tls (Qt6)
install(
DIRECTORY "${QT_PLUGINS_DIR}/"
DESTINATION ${plugin_dest_dir}
COMPONENT Runtime
FILES_MATCHING
PATTERN "*.dSYM" EXCLUDE
PATTERN "*_debug.dylib" EXCLUDE
PATTERN "audio/*.dylib"
PATTERN "iconengines/*.dylib"
PATTERN "imageformats/*.dylib"
PATTERN "platforms/*.dylib"
PATTERN "printsupport/*.dylib"
PATTERN "styles/*.dylib"
PATTERN "tls/*.dylib"
)
# qt5 plugins: audio, iconengines, imageformats, platforms, printsupport
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime
FILES_MATCHING
PATTERN "*.dSYM" EXCLUDE
PATTERN "*_debug.dylib" EXCLUDE
PATTERN "audio/*.dylib"
PATTERN "iconengines/*.dylib"
PATTERN "imageformats/*.dylib"
PATTERN "platforms/*.dylib"
PATTERN "printsupport/*.dylib"
PATTERN "styles/*.dylib"
)
install(
CODE "
install(CODE "
file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf\" \"[Paths]
Plugins = Plugins
Translations = Resources/translations
Data = Resources\")
"
COMPONENT Runtime
)
" COMPONENT Runtime)
install(
CODE "
install(CODE "
file(GLOB_RECURSE QTPLUGINS
\"\${CMAKE_INSTALL_PREFIX}/${plugin_dest_dir}/*.dylib\")
set(BU_CHMOD_BUNDLE_ITEMS ON)
include(BundleUtilities)
fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/cockatrice.app\" \"\${QTPLUGINS}\" \"${QT_LIBRARY_DIR}\")
"
COMPONENT Runtime
)
" COMPONENT Runtime)
endif()
if(WIN32)
# these needs to be relative to CMAKE_INSTALL_PREFIX
set(plugin_dest_dir Plugins)
set(qtconf_dest_dir .)
# these needs to be relative to CMAKE_INSTALL_PREFIX
set(plugin_dest_dir Plugins)
set(qtconf_dest_dir .)
install(
DIRECTORY "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/${CMAKE_BUILD_TYPE}/"
DESTINATION ./
FILES_MATCHING
PATTERN "*.dll"
)
install(DIRECTORY "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/${CMAKE_BUILD_TYPE}/" DESTINATION ./ FILES_MATCHING PATTERN "*.dll")
# Qt plugins: audio (Qt5), iconengines, imageformats, platforms, printsupport (Qt5), styles, tls (Qt6)
install(
DIRECTORY "${QT_PLUGINS_DIR}/"
DESTINATION ${plugin_dest_dir}
COMPONENT Runtime
FILES_MATCHING
PATTERN "audio/qtaudio_wasapi.dll"
PATTERN "audio/qtaudio_windows.dll"
PATTERN "iconengines/qsvgicon.dll"
PATTERN "imageformats/*.dll"
PATTERN "mediaservice/dsengine.dll"
PATTERN "mediaservice/wmfengine.dll"
PATTERN "platforms/qdirect2d.dll"
PATTERN "platforms/qminimal.dll"
PATTERN "platforms/qoffscreen.dll"
PATTERN "platforms/qwindows.dll"
PATTERN "printsupport/windowsprintersupport.dll"
PATTERN "styles/qcertonlybackend.dll"
PATTERN "styles/qopensslbackend.dll"
PATTERN "styles/qschannelbackend.dll"
PATTERN "styles/qwindowsvistastyle.dll"
PATTERN "tls/qcertonlybackend.dll"
PATTERN "tls/qopensslbackend.dll"
PATTERN "tls/qschannelbackend.dll"
)
# qt5 plugins: audio, iconengines, imageformats, platforms, printsupport
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime
FILES_MATCHING REGEX "(audio|iconengines|imageformats|platforms|printsupport|styles)/.*[^d]\\.dll")
install(
CODE "
install(CODE "
file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf\" \"[Paths]
Plugins = Plugins
Translations = Resources/translations
Data = Resources\")
"
COMPONENT Runtime
)
" COMPONENT Runtime)
install(
CODE "
install(CODE "
file(GLOB_RECURSE QTPLUGINS
\"\${CMAKE_INSTALL_PREFIX}/${plugin_dest_dir}/*.dll\")
set(BU_CHMOD_BUNDLE_ITEMS ON)
include(BundleUtilities)
fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/Cockatrice.exe\" \"\${QTPLUGINS}\" \"${QT_LIBRARY_DIR}\")
"
COMPONENT Runtime
)
" COMPONENT Runtime)
if(OPENSSL_FOUND)
install(FILES ${OPENSSL_INCLUDE_DIRS} DESTINATION ./)
endif()
endif()
if(Qt6_FOUND AND Qt6LinguistTools_FOUND)
#Qt6 Translations happen after the executable is built up
if(UPDATE_TRANSLATIONS)
qt6_add_translations(
cockatrice
TS_FILES
${cockatrice_TS}
SOURCES
${translate_SRCS}
QM_FILES_OUTPUT_VARIABLE
cockatrice_QM
)
else()
qt6_add_translations(cockatrice TS_FILES ${cockatrice_TS} QM_FILES_OUTPUT_VARIABLE cockatrice_QM)
endif()
if(UNIX)
if(APPLE)
install(FILES ${cockatrice_QM} DESTINATION ${COCKATRICE_MAC_QM_INSTALL_DIR})
else()
install(FILES ${cockatrice_QM} DESTINATION ${COCKATRICE_UNIX_QM_INSTALL_DIR})
if(WIN32SSLRUNTIME_FOUND)
install(FILES ${WIN32SSLRUNTIME_LIBRARIES} DESTINATION ./)
endif()
elseif(WIN32)
install(FILES ${cockatrice_QM} DESTINATION ${COCKATRICE_WIN32_QM_INSTALL_DIR})
endif()
endif()
if(Qt6_FOUND)
qt6_finalize_target(cockatrice)
endif()

View File

@@ -126,7 +126,6 @@
<file>resources/countries/er.svg</file>
<file>resources/countries/es.svg</file>
<file>resources/countries/et.svg</file>
<file>resources/countries/eu.svg</file>
<file>resources/countries/fi.svg</file>
<file>resources/countries/fj.svg</file>
<file>resources/countries/fk.svg</file>
@@ -302,7 +301,6 @@
<file>resources/countries/vu.svg</file>
<file>resources/countries/wf.svg</file>
<file>resources/countries/ws.svg</file>
<file>resources/countries/xk.svg</file>
<file>resources/countries/ye.svg</file>
<file>resources/countries/yt.svg</file>
<file>resources/countries/za.svg</file>
@@ -351,10 +349,10 @@
<file>resources/tips/images/cockatrice_wiki.png</file>
<file>resources/tips/images/coin_flip.png</file>
<file>resources/tips/images/counter_expression.png</file>
<file>resources/tips/images/discord.png</file>
<file>resources/tips/images/face_down.png</file>
<file>resources/tips/images/filter_games.png</file>
<file>resources/tips/images/github_logo.png</file>
<file>resources/tips/images/gitter.png</file>
<file>resources/tips/images/setpt.png</file>
<file>resources/tips/images/shortcuts.png</file>
<file>resources/tips/images/themes.png</file>

Binary file not shown.

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 8.3 KiB

View File

@@ -1,7 +1,6 @@
## Search Syntax Help
## Syntax Help
-----
The search bar recognizes a set of special commands similar to some other card databases.<br>
In this list of examples below, each entry has an explanation and can be clicked to test the query. Note that all searches are case insensitive.
The search bar recognizes a set of special commands similar to some other card databases. Here is a list with examples. Each entry can be clicked to test the query and has a small explanation. Note that all searches are case insensitive.
<dl>
<dt>Name:</dt>
<dd>[birds of paradise](#birds of paradise) <small>(Any card name containing the words birds, of, and paradise)</small></dd>
@@ -47,7 +46,8 @@ In this list of examples below, each entry has an explanation and can be clicked
<dt><u>E</u>dition:</dt>
<dd>[set:lea](#set:lea) <small>(Cards that appear in Alpha, which has the set code LEA)</small></dd>
<dd>[e:lea or e:leb](#e:lea or e:leb) <small>(Cards that appear in Alpha or Beta)</small></dd>
<dd>[e:lea,leb](#e:lea,leb) <small>(Cards that appear in Alpha or Beta)</small></dd>
<dd><a href="#e:lea,leb -(e:lea e:leb)">e:lea,leb -(e:lea e:leb)</a> <small>(Cards that appear in Alpha or Beta but not in both editions)</small></dd>
<dt>Negate:</dt>
<dd>[c:wu -c:m](#c:wu -c:m) <small>(Any card that is white or blue, but not multicolored)</small></dd>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

@@ -7,9 +7,9 @@
</tip>
<tip>
<title>Suggesting New Tips</title>
<text>You can suggest new Tips of the Day by reaching out to the development team on &lt;a href="https://discord.gg/3Z9yzmA"&gt;Discord&lt;/a&gt;!</text>
<image>discord.png</image>
<date>2023-10-18</date>
<text>You can suggest new Tips of the Day by reaching out to the development team on &lt;a href="https://gitter.im/cockatrice/cockatrice"&gt;Gitter&lt;/a&gt;!</text>
<image>gitter.png</image>
<date>2018-03-01</date>
</tip>
<tip>
<title>Reporting Bugs</title>

View File

@@ -2,15 +2,18 @@
#
# add sounds subfolders
set(defsounds Default Legacy)
SET(defsounds
Default
Legacy
)
if(UNIX)
if(APPLE)
install(DIRECTORY ${defsounds} DESTINATION Cockatrice.app/Contents/Resources/sounds/)
else()
# Assume linux
install(DIRECTORY ${defsounds} DESTINATION share/cockatrice/sounds/)
endif()
if(APPLE)
INSTALL(DIRECTORY ${defsounds} DESTINATION Cockatrice.app/Contents/Resources/sounds/)
else()
# Assume linux
INSTALL(DIRECTORY ${defsounds} DESTINATION share/cockatrice/sounds/)
endif()
elseif(WIN32)
install(DIRECTORY ${defsounds} DESTINATION sounds/)
INSTALL(DIRECTORY ${defsounds} DESTINATION sounds/)
endif()

View File

@@ -20,8 +20,13 @@ AbstractCardDragItem::AbstractCardDragItem(AbstractCardItem *_item,
parentDrag->addChildDrag(this);
setZValue(2000000007 + hotSpot.x() * 1000000 + hotSpot.y() * 1000 + 1000);
} else {
hotSpot = QPointF{qBound(0.0, hotSpot.x(), static_cast<qreal>(CARD_WIDTH - 1)),
qBound(0.0, hotSpot.y(), static_cast<qreal>(CARD_HEIGHT - 1))};
if ((hotSpot.x() < 0) || (hotSpot.y() < 0)) {
qDebug() << "CardDragItem: coordinate overflow: x =" << hotSpot.x() << ", y =" << hotSpot.y();
hotSpot = QPointF();
} else if ((hotSpot.x() > CARD_WIDTH) || (hotSpot.y() > CARD_HEIGHT)) {
qDebug() << "CardDragItem: coordinate overflow: x =" << hotSpot.x() << ", y =" << hotSpot.y();
hotSpot = QPointF(CARD_WIDTH, CARD_HEIGHT);
}
setCursor(Qt::ClosedHandCursor);
setZValue(2000000007);
}
@@ -40,19 +45,12 @@ AbstractCardDragItem::~AbstractCardDragItem()
delete childDrags[i];
}
QPainterPath AbstractCardDragItem::shape() const
{
QPainterPath shape;
shape.addRoundedRect(boundingRect(), 0.05 * CARD_WIDTH, 0.05 * CARD_WIDTH);
return shape;
}
void AbstractCardDragItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
item->paint(painter, option, widget);
// adds a mask to the card so it looks like the card hasnt been placed yet
painter->fillPath(shape(), GHOST_MASK);
painter->fillRect(boundingRect(), GHOST_MASK);
}
void AbstractCardDragItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)

View File

@@ -21,18 +21,17 @@ public:
{
Type = typeCardDrag
};
int type() const override
int type() const
{
return Type;
}
AbstractCardDragItem(AbstractCardItem *_item, const QPointF &_hotSpot, AbstractCardDragItem *parentDrag = 0);
~AbstractCardDragItem();
QRectF boundingRect() const override
QRectF boundingRect() const
{
return QRectF(0, 0, CARD_WIDTH, CARD_HEIGHT);
}
QPainterPath shape() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
AbstractCardItem *getItem() const
{
return item;
@@ -45,7 +44,7 @@ public:
virtual void updatePosition(const QPointF &cursorScenePos) = 0;
protected:
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
};
#endif

View File

@@ -34,13 +34,6 @@ QRectF AbstractCardItem::boundingRect() const
return QRectF(0, 0, CARD_WIDTH, CARD_HEIGHT);
}
QPainterPath AbstractCardItem::shape() const
{
QPainterPath shape;
shape.addRoundedRect(boundingRect(), 0.05 * CARD_WIDTH, 0.05 * CARD_WIDTH);
return shape;
}
void AbstractCardItem::pixmapUpdated()
{
update();
@@ -120,14 +113,24 @@ void AbstractCardItem::paintPicture(QPainter *painter, const QSizeF &translatedS
if (paintImage) {
painter->save();
painter->setClipPath(shape());
painter->drawPixmap(boundingRect(), translatedPixmap, QRectF({0, 0}, translatedPixmap.size()));
transformPainter(painter, translatedSize, angle);
painter->drawPixmap(QPointF(1, 1), translatedPixmap);
painter->restore();
} else {
painter->setBrush(bgColor);
painter->drawPath(shape());
}
QPen pen(Qt::black);
pen.setJoinStyle(Qt::MiterJoin);
const int penWidth = 2;
pen.setWidth(penWidth);
painter->setPen(pen);
if (!angle)
painter->drawRect(QRectF(0, 0, CARD_WIDTH - 1, CARD_HEIGHT - penWidth));
else
painter->drawRect(QRectF(1, 1, CARD_WIDTH - 2, CARD_HEIGHT - 1.5));
if (translatedPixmap.isNull() || SettingsCache::instance().getDisplayCardNames() || facedown) {
painter->save();
transformPainter(painter, translatedSize, angle);
@@ -155,7 +158,9 @@ void AbstractCardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *
QSizeF translatedSize = getTranslatedSize(painter);
paintPicture(painter, translatedSize, tapAngle);
painter->save();
painter->setRenderHint(QPainter::Antialiasing, false);
transformPainter(painter, translatedSize, tapAngle);
if (isSelected() || isHovered) {
QPen pen;
@@ -163,12 +168,15 @@ void AbstractCardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *
pen.setColor(Qt::yellow);
if (isSelected())
pen.setColor(Qt::red);
pen.setWidth(0); // Cosmetic pen
const int penWidth = 1;
pen.setWidth(penWidth);
painter->setPen(pen);
painter->drawPath(shape());
painter->drawRect(QRectF(0, 0, translatedSize.width() + penWidth, translatedSize.height() - penWidth));
}
painter->restore();
painter->restore();
}
void AbstractCardItem::setName(const QString &_name)

View File

@@ -44,7 +44,7 @@ public:
{
Type = typeCard
};
int type() const override
int type() const
{
return Type;
}
@@ -53,11 +53,10 @@ public:
int _id = -1,
QGraphicsItem *parent = nullptr);
~AbstractCardItem();
QRectF boundingRect() const override;
QPainterPath shape() const override;
QRectF boundingRect() const;
QSizeF getTranslatedSize(QPainter *painter) const;
void paintPicture(QPainter *painter, const QSizeF &translatedSize, int angle);
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
CardInfoPtr getInfo() const
{
return info;
@@ -104,9 +103,9 @@ public:
protected:
void transformPainter(QPainter *painter, const QSizeF &translatedSize, int angle);
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) override;
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value);
void cacheBgColor();
};

View File

@@ -1,5 +1,6 @@
#include "abstractclient.h"
#include "client_metatypes.h"
#include "featureset.h"
#include "get_pb_extension.h"
#include "pb/commands.pb.h"
@@ -47,7 +48,6 @@ AbstractClient::AbstractClient(QObject *parent)
qRegisterMetaType<QList<ServerInfo_User>>("QList<ServerInfo_User>");
qRegisterMetaType<Event_ReplayAdded>("Event_ReplayAdded");
qRegisterMetaType<QList<QString>>("missingFeatures");
qRegisterMetaType<PendingCommand *>("pendingCommand");
FeatureSet features;
features.initalizeFeatureList(clientFeatures);

View File

@@ -16,7 +16,7 @@
#include <QGraphicsScene>
#include <QGraphicsSceneMouseEvent>
#include <QPainter>
#include <QtMath>
#include <cmath>
ArrowItem::ArrowItem(Player *_player, int _id, ArrowTarget *_startItem, ArrowTarget *_targetItem, const QColor &_color)
: QGraphicsItem(), player(_player), id(_id), startItem(_startItem), targetItem(_targetItem), color(_color),
@@ -71,7 +71,7 @@ void ArrowItem::updatePath(const QPointF &endPoint)
const double arrowWidth = 15.0;
const double headWidth = 40.0;
const double headLength =
headWidth / qPow(2, 0.5); // aka headWidth / sqrt (2) but this produces a compile error with MSVC++
headWidth / pow(2, 0.5); // aka headWidth / sqrt (2) but this produces a compile error with MSVC++
const double phi = 15;
if (!startItem)
@@ -86,7 +86,7 @@ void ArrowItem::updatePath(const QPointF &endPoint)
if (lineLength < 30)
path = QPainterPath();
else {
QPointF c(lineLength / 2, qTan(phi * M_PI / 180) * lineLength);
QPointF c(lineLength / 2, tan(phi * M_PI / 180) * lineLength);
QPainterPath centerLine;
centerLine.moveTo(0, 0);
@@ -97,22 +97,22 @@ void ArrowItem::updatePath(const QPointF &endPoint)
QLineF testLine(arrowBodyEndPoint, centerLine.pointAtPercent(percentage + 0.001));
qreal alpha = testLine.angle() - 90;
QPointF endPoint1 =
arrowBodyEndPoint + arrowWidth / 2 * QPointF(qCos(alpha * M_PI / 180), -qSin(alpha * M_PI / 180));
arrowBodyEndPoint + arrowWidth / 2 * QPointF(cos(alpha * M_PI / 180), -sin(alpha * M_PI / 180));
QPointF endPoint2 =
arrowBodyEndPoint + arrowWidth / 2 * QPointF(-qCos(alpha * M_PI / 180), qSin(alpha * M_PI / 180));
arrowBodyEndPoint + arrowWidth / 2 * QPointF(-cos(alpha * M_PI / 180), sin(alpha * M_PI / 180));
QPointF point1 =
endPoint1 + (headWidth - arrowWidth) / 2 * QPointF(qCos(alpha * M_PI / 180), -qSin(alpha * M_PI / 180));
endPoint1 + (headWidth - arrowWidth) / 2 * QPointF(cos(alpha * M_PI / 180), -sin(alpha * M_PI / 180));
QPointF point2 =
endPoint2 + (headWidth - arrowWidth) / 2 * QPointF(-qCos(alpha * M_PI / 180), qSin(alpha * M_PI / 180));
endPoint2 + (headWidth - arrowWidth) / 2 * QPointF(-cos(alpha * M_PI / 180), sin(alpha * M_PI / 180));
path = QPainterPath(-arrowWidth / 2 * QPointF(qCos((phi - 90) * M_PI / 180), qSin((phi - 90) * M_PI / 180)));
path = QPainterPath(-arrowWidth / 2 * QPointF(cos((phi - 90) * M_PI / 180), sin((phi - 90) * M_PI / 180)));
path.quadTo(c, endPoint1);
path.lineTo(point1);
path.lineTo(QPointF(lineLength, 0));
path.lineTo(point2);
path.lineTo(endPoint2);
path.quadTo(c, arrowWidth / 2 * QPointF(qCos((phi - 90) * M_PI / 180), qSin((phi - 90) * M_PI / 180)));
path.lineTo(-arrowWidth / 2 * QPointF(qCos((phi - 90) * M_PI / 180), qSin((phi - 90) * M_PI / 180)));
path.quadTo(c, arrowWidth / 2 * QPointF(cos((phi - 90) * M_PI / 180), sin((phi - 90) * M_PI / 180)));
path.lineTo(-arrowWidth / 2 * QPointF(cos((phi - 90) * M_PI / 180), sin((phi - 90) * M_PI / 180)));
}
setPos(startPoint);
@@ -138,8 +138,8 @@ void ArrowItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
}
QList<QGraphicsItem *> colliding = scene()->items(event->scenePos());
for (QGraphicsItem *item : colliding) {
if (qgraphicsitem_cast<CardItem *>(item)) {
for (int i = 0; i < colliding.size(); ++i) {
if (qgraphicsitem_cast<CardItem *>(colliding[i])) {
event->ignore();
return;
}
@@ -205,8 +205,8 @@ void ArrowDragItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
}
update();
for (ArrowDragItem *child : childArrows) {
child->mouseMoveEvent(event);
for (int i = 0; i < childArrows.size(); ++i) {
childArrows[i]->mouseMoveEvent(event);
}
}
@@ -251,9 +251,8 @@ void ArrowDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
}
delArrow();
for (ArrowDragItem *child : childArrows) {
child->mouseReleaseEvent(event);
}
for (int i = 0; i < childArrows.size(); ++i)
childArrows[i]->mouseReleaseEvent(event);
}
ArrowAttachItem::ArrowAttachItem(ArrowTarget *_startItem)
@@ -261,11 +260,6 @@ ArrowAttachItem::ArrowAttachItem(ArrowTarget *_startItem)
{
}
void ArrowAttachItem::addChildArrow(ArrowAttachItem *childArrow)
{
childArrows.append(childArrow);
}
void ArrowAttachItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if (!startItem)
@@ -301,13 +295,9 @@ void ArrowAttachItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
updatePath();
}
update();
for (ArrowAttachItem *child : childArrows) {
child->mouseMoveEvent(event);
}
}
void ArrowAttachItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
void ArrowAttachItem::mouseReleaseEvent(QGraphicsSceneMouseEvent * /*event*/)
{
if (!startItem)
return;
@@ -329,8 +319,4 @@ void ArrowAttachItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
}
delArrow();
for (ArrowAttachItem *child : childArrows) {
child->mouseReleaseEvent(event);
}
}

View File

@@ -85,12 +85,8 @@ protected:
class ArrowAttachItem : public ArrowItem
{
Q_OBJECT
private:
QList<ArrowAttachItem *> childArrows;
public:
ArrowAttachItem(ArrowTarget *_startItem);
void addChildArrow(ArrowAttachItem *childArrow);
protected:
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);

View File

@@ -43,8 +43,9 @@ public:
}
void removeArrowFrom(ArrowItem *arrow)
{
arrowsFrom.removeOne(arrow);
arrowsFrom.removeAt(arrowsFrom.indexOf(arrow));
}
const QList<ArrowItem *> &getArrowsTo() const
{
return arrowsTo;
@@ -55,7 +56,8 @@ public:
}
void removeArrowTo(ArrowItem *arrow)
{
arrowsTo.removeOne(arrow);
arrowsTo.removeAt(arrowsTo.indexOf(arrow));
}
};
#endif

View File

@@ -266,14 +266,9 @@ CardInfoPtr CardInfo::newInstance(const QString &_name,
QString CardInfo::getCorrectedName() const
{
// remove all the characters reserved in windows file paths,
// other oses only disallow a subset of these so it covers all
static const QRegularExpression rmrx(R"(( // |[*<>:"\\?\x00-\x08\x10-\x1f]))");
static const QRegularExpression spacerx(R"([/\x09-\x0f])");
static const QString space(' ');
QString result = name;
// Fire // Ice, Circle of Protection: Red, "Ach! Hans, Run!", Who/What/When/Where/Why, Question Elemental?
return result.remove(rmrx).replace(spacerx, space);
return result.remove(" // ").remove(':').remove('"').remove('?').replace('/', ' ');
}
void CardInfo::addToSet(const CardSetPtr &_set, const CardInfoPerSet _info)
@@ -592,9 +587,9 @@ void CardDatabase::refreshCachedReverseRelatedCards()
continue;
}
auto *newCardRelation = new CardRelation(
card->getName(), cardRelation->getAttachType(), cardRelation->getIsCreateAllExclusion(),
cardRelation->getIsVariable(), cardRelation->getDefaultCount(), cardRelation->getIsPersistent());
auto *newCardRelation = new CardRelation(card->getName(), cardRelation->getDoesAttach(),
cardRelation->getIsCreateAllExclusion(),
cardRelation->getIsVariable(), cardRelation->getDefaultCount());
cards.value(targetCard)->addReverseRelatedCards2Me(newCardRelation);
}
}
@@ -612,22 +607,22 @@ QStringList CardDatabase::getAllMainCardTypes() const
void CardDatabase::checkUnknownSets()
{
auto _sets = getSetList();
SetList sets = getSetList();
if (_sets.getEnabledSetsNum()) {
if (sets.getEnabledSetsNum()) {
// if some sets are first found on this run, ask the user
int numUnknownSets = _sets.getUnknownSetsNum();
QStringList unknownSetNames = _sets.getUnknownSetsNames();
int numUnknownSets = sets.getUnknownSetsNum();
QStringList unknownSetNames = sets.getUnknownSetsNames();
if (numUnknownSets > 0) {
emit cardDatabaseNewSetsFound(numUnknownSets, unknownSetNames);
} else {
_sets.markAllAsKnown();
sets.markAllAsKnown();
}
} else {
// No set enabled. Probably this is the first time running trice
_sets.guessSortKeys();
_sets.sortByKey();
_sets.enableAll();
sets.guessSortKeys();
sets.sortByKey();
sets.enableAll();
notifyEnabledSetsChanged();
emit cardDatabaseAllNewSetsEnabled();
@@ -636,14 +631,14 @@ void CardDatabase::checkUnknownSets()
void CardDatabase::enableAllUnknownSets()
{
auto _sets = getSetList();
_sets.enableAllUnknown();
SetList sets = getSetList();
sets.enableAllUnknown();
}
void CardDatabase::markAllSetsAsKnown()
{
auto _sets = getSetList();
_sets.markAllAsKnown();
SetList sets = getSetList();
sets.markAllAsKnown();
}
void CardDatabase::notifyEnabledSetsChanged()
@@ -677,13 +672,12 @@ bool CardDatabase::saveCustomTokensToFile()
}
CardRelation::CardRelation(const QString &_name,
AttachType _attachType,
bool _doesAttach,
bool _isCreateAllExclusion,
bool _isVariableCount,
int _defaultCount,
bool _isPersistent)
: name(_name), attachType(_attachType), isCreateAllExclusion(_isCreateAllExclusion),
isVariableCount(_isVariableCount), defaultCount(_defaultCount), isPersistent(_isPersistent)
int _defaultCount)
: name(_name), doesAttach(_doesAttach), isCreateAllExclusion(_isCreateAllExclusion),
isVariableCount(_isVariableCount), defaultCount(_defaultCount)
{
}

View File

@@ -452,60 +452,31 @@ signals:
class CardRelation : public QObject
{
Q_OBJECT
public:
enum AttachType
{
DoesNotAttach = 0,
AttachTo = 1,
TransformInto = 2,
};
private:
QString name;
AttachType attachType;
bool doesAttach;
bool isCreateAllExclusion;
bool isVariableCount;
int defaultCount;
bool isPersistent;
public:
explicit CardRelation(const QString &_name = QString(),
AttachType _attachType = DoesNotAttach,
bool _doesAttach = false,
bool _isCreateAllExclusion = false,
bool _isVariableCount = false,
int _defaultCount = 1,
bool _isPersistent = false);
int _defaultCount = 1);
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 "";
}
return doesAttach;
}
bool getCanCreateAnother() const
{
return !getDoesAttach();
return !doesAttach;
}
bool getIsCreateAllExclusion() const
{
@@ -519,9 +490,5 @@ public:
{
return defaultCount;
}
bool getIsPersistent() const
{
return isPersistent;
}
};
#endif

View File

@@ -326,12 +326,12 @@ void CardDatabaseDisplayModel::clearFilterAll()
invalidateFilter();
}
void CardDatabaseDisplayModel::setFilterTree(FilterTree *_filterTree)
void CardDatabaseDisplayModel::setFilterTree(FilterTree *filterTree)
{
if (this->filterTree != nullptr)
disconnect(this->filterTree, nullptr, this, nullptr);
this->filterTree = _filterTree;
this->filterTree = filterTree;
connect(this->filterTree, SIGNAL(changed()), this, SLOT(filterTreeChanged()));
invalidate();
}

View File

@@ -82,7 +82,7 @@ private:
public:
explicit CardDatabaseDisplayModel(QObject *parent = nullptr);
void setFilterTree(FilterTree *_filterTree);
void setFilterTree(FilterTree *filterTree);
void setIsToken(FilterBool _isToken)
{
isToken = _isToken;

View File

@@ -23,7 +23,7 @@ bool CockatriceXml3Parser::getCanParseFile(const QString &fileName, QIODevice &d
QXmlStreamReader xml(&device);
while (!xml.atEnd()) {
if (xml.readNext() == QXmlStreamReader::StartElement) {
if (xml.name().toString() == COCKATRICE_XML3_TAGNAME) {
if (xml.name() == COCKATRICE_XML3_TAGNAME) {
int version = xml.attributes().value("version").toString().toInt();
if (version == COCKATRICE_XML3_TAGVER) {
return true;
@@ -52,13 +52,12 @@ void CockatriceXml3Parser::parseFile(QIODevice &device)
break;
}
auto name = xml.name().toString();
if (name == "sets") {
if (xml.name() == "sets") {
loadSetsFromXml(xml);
} else if (name == "cards") {
} else if (xml.name() == "cards") {
loadCardsFromXml(xml);
} else if (!name.isEmpty()) {
qDebug() << "[CockatriceXml3Parser] Unknown item" << name << ", trying to continue anyway";
} else if (xml.name() != "") {
qDebug() << "[CockatriceXml3Parser] Unknown item" << xml.name() << ", trying to continue anyway";
xml.skipCurrentElement();
}
}
@@ -73,27 +72,26 @@ void CockatriceXml3Parser::loadSetsFromXml(QXmlStreamReader &xml)
break;
}
auto name = xml.name().toString();
if (name == "set") {
if (xml.name() == "set") {
QString shortName, longName, setType;
QDate releaseDate;
while (!xml.atEnd()) {
if (xml.readNext() == QXmlStreamReader::EndElement) {
break;
}
name = xml.name().toString();
if (name == "name") {
if (xml.name() == "name") {
shortName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
} else if (name == "longname") {
} else if (xml.name() == "longname") {
longName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
} else if (name == "settype") {
} else if (xml.name() == "settype") {
setType = xml.readElementText(QXmlStreamReader::IncludeChildElements);
} else if (name == "releasedate") {
} else if (xml.name() == "releasedate") {
releaseDate =
QDate::fromString(xml.readElementText(QXmlStreamReader::IncludeChildElements), Qt::ISODate);
} else if (!name.isEmpty()) {
qDebug() << "[CockatriceXml3Parser] Unknown set property" << name << ", trying to continue anyway";
} else if (xml.name() != "") {
qDebug() << "[CockatriceXml3Parser] Unknown set property" << xml.name()
<< ", trying to continue anyway";
xml.skipCurrentElement();
}
}
@@ -148,14 +146,13 @@ void CockatriceXml3Parser::loadCardsFromXml(QXmlStreamReader &xml)
break;
}
auto xmlName = xml.name().toString();
if (xmlName == "card") {
if (xml.name() == "card") {
QString name = QString("");
QString text = QString("");
QVariantHash properties = QVariantHash();
QString colors = QString("");
QList<CardRelation *> relatedCards, reverseRelatedCards;
auto _sets = CardInfoPerSetMap();
CardInfoPerSetMap sets = CardInfoPerSetMap();
int tableRow = 0;
bool cipt = false;
bool isToken = false;
@@ -165,39 +162,37 @@ void CockatriceXml3Parser::loadCardsFromXml(QXmlStreamReader &xml)
if (xml.readNext() == QXmlStreamReader::EndElement) {
break;
}
xmlName = xml.name().toString();
// variable - assigned properties
if (xmlName == "name") {
if (xml.name() == "name") {
name = xml.readElementText(QXmlStreamReader::IncludeChildElements);
} else if (xmlName == "text") {
} else if (xml.name() == "text") {
text = xml.readElementText(QXmlStreamReader::IncludeChildElements);
} else if (xmlName == "color") {
} else if (xml.name() == "color") {
colors.append(xml.readElementText(QXmlStreamReader::IncludeChildElements));
} else if (xmlName == "token") {
} else if (xml.name() == "token") {
isToken = static_cast<bool>(xml.readElementText(QXmlStreamReader::IncludeChildElements).toInt());
// generic properties
} else if (xmlName == "manacost") {
} else if (xml.name() == "manacost") {
properties.insert("manacost", xml.readElementText(QXmlStreamReader::IncludeChildElements));
} else if (xmlName == "cmc") {
} else if (xml.name() == "cmc") {
properties.insert("cmc", xml.readElementText(QXmlStreamReader::IncludeChildElements));
} else if (xmlName == "type") {
} else if (xml.name() == "type") {
QString type = xml.readElementText(QXmlStreamReader::IncludeChildElements);
properties.insert("type", type);
properties.insert("maintype", getMainCardType(type));
} else if (xmlName == "pt") {
} else if (xml.name() == "pt") {
properties.insert("pt", xml.readElementText(QXmlStreamReader::IncludeChildElements));
} else if (xmlName == "loyalty") {
} else if (xml.name() == "loyalty") {
properties.insert("loyalty", xml.readElementText(QXmlStreamReader::IncludeChildElements));
// positioning info
} else if (xmlName == "tablerow") {
} else if (xml.name() == "tablerow") {
tableRow = xml.readElementText(QXmlStreamReader::IncludeChildElements).toInt();
} else if (xmlName == "cipt") {
} else if (xml.name() == "cipt") {
cipt = (xml.readElementText(QXmlStreamReader::IncludeChildElements) == "1");
} else if (xmlName == "upsidedown") {
} else if (xml.name() == "upsidedown") {
upsideDown = (xml.readElementText(QXmlStreamReader::IncludeChildElements) == "1");
// sets
} else if (xmlName == "set") {
} else if (xml.name() == "set") {
// NOTE: attributes must be read before readElementText()
QXmlStreamAttributes attrs = xml.attributes();
QString setName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
@@ -221,10 +216,10 @@ void CockatriceXml3Parser::loadCardsFromXml(QXmlStreamReader &xml)
if (attrs.hasAttribute("rarity")) {
setInfo.setProperty("rarity", attrs.value("rarity").toString());
}
_sets.insert(setName, setInfo);
// related cards
} else if (xmlName == "related" || xmlName == "reverse-related") {
CardRelation::AttachType attach = CardRelation::DoesNotAttach;
sets.insert(setName, setInfo);
// relatd cards
} else if (xml.name() == "related" || xml.name() == "reverse-related") {
bool attach = false;
bool exclude = false;
bool variable = false;
int count = 1;
@@ -246,7 +241,7 @@ void CockatriceXml3Parser::loadCardsFromXml(QXmlStreamReader &xml)
}
if (attrs.hasAttribute("attach")) {
attach = CardRelation::AttachTo;
attach = true;
}
if (attrs.hasAttribute("exclude")) {
@@ -254,13 +249,13 @@ void CockatriceXml3Parser::loadCardsFromXml(QXmlStreamReader &xml)
}
auto *relation = new CardRelation(cardName, attach, exclude, variable, count);
if (xmlName == "reverse-related") {
if (xml.name() == "reverse-related") {
reverseRelatedCards << relation;
} else {
relatedCards << relation;
}
} else if (!xmlName.isEmpty()) {
qDebug() << "[CockatriceXml3Parser] Unknown card property" << xmlName
} else if (xml.name() != "") {
qDebug() << "[CockatriceXml3Parser] Unknown card property" << xml.name()
<< ", trying to continue anyway";
xml.skipCurrentElement();
}
@@ -268,7 +263,7 @@ void CockatriceXml3Parser::loadCardsFromXml(QXmlStreamReader &xml)
properties.insert("colors", colors);
CardInfoPtr newCard = CardInfo::newInstance(name, text, isToken, properties, relatedCards,
reverseRelatedCards, _sets, cipt, tableRow, upsideDown);
reverseRelatedCards, sets, cipt, tableRow, upsideDown);
emit addCard(newCard);
}
}
@@ -412,7 +407,7 @@ static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfoPtr &in
return xml;
}
bool CockatriceXml3Parser::saveToFile(SetNameMap _sets,
bool CockatriceXml3Parser::saveToFile(SetNameMap sets,
CardNameMap cards,
const QString &fileName,
const QString &sourceUrl,
@@ -439,9 +434,9 @@ bool CockatriceXml3Parser::saveToFile(SetNameMap _sets,
xml.writeTextElement("sourceVersion", sourceVersion);
xml.writeEndElement();
if (_sets.count() > 0) {
if (sets.count() > 0) {
xml.writeStartElement("sets");
for (CardSetPtr set : _sets) {
for (CardSetPtr set : sets) {
xml << set;
}
xml.writeEndElement();
@@ -459,4 +454,4 @@ bool CockatriceXml3Parser::saveToFile(SetNameMap _sets,
xml.writeEndDocument();
return true;
}
}

View File

@@ -14,7 +14,7 @@ public:
~CockatriceXml3Parser() override = default;
bool getCanParseFile(const QString &name, QIODevice &device) override;
void parseFile(QIODevice &device) override;
bool saveToFile(SetNameMap _sets,
bool saveToFile(SetNameMap sets,
CardNameMap cards,
const QString &fileName,
const QString &sourceUrl = "unknown",

View File

@@ -23,7 +23,7 @@ bool CockatriceXml4Parser::getCanParseFile(const QString &fileName, QIODevice &d
QXmlStreamReader xml(&device);
while (!xml.atEnd()) {
if (xml.readNext() == QXmlStreamReader::StartElement) {
if (xml.name().toString() == COCKATRICE_XML4_TAGNAME) {
if (xml.name() == COCKATRICE_XML4_TAGNAME) {
int version = xml.attributes().value("version").toString().toInt();
if (version == COCKATRICE_XML4_TAGVER) {
return true;
@@ -52,13 +52,12 @@ void CockatriceXml4Parser::parseFile(QIODevice &device)
break;
}
auto xmlName = xml.name().toString();
if (xmlName == "sets") {
if (xml.name() == "sets") {
loadSetsFromXml(xml);
} else if (xmlName == "cards") {
} else if (xml.name() == "cards") {
loadCardsFromXml(xml);
} else if (!xmlName.isEmpty()) {
qDebug() << "[CockatriceXml4Parser] Unknown item" << xmlName << ", trying to continue anyway";
} else if (xml.name() != "") {
qDebug() << "[CockatriceXml4Parser] Unknown item" << xml.name() << ", trying to continue anyway";
xml.skipCurrentElement();
}
}
@@ -73,27 +72,25 @@ void CockatriceXml4Parser::loadSetsFromXml(QXmlStreamReader &xml)
break;
}
auto xmlName = xml.name().toString();
if (xmlName == "set") {
if (xml.name() == "set") {
QString shortName, longName, setType;
QDate releaseDate;
while (!xml.atEnd()) {
if (xml.readNext() == QXmlStreamReader::EndElement) {
break;
}
xmlName = xml.name().toString();
if (xmlName == "name") {
if (xml.name() == "name") {
shortName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
} else if (xmlName == "longname") {
} else if (xml.name() == "longname") {
longName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
} else if (xmlName == "settype") {
} else if (xml.name() == "settype") {
setType = xml.readElementText(QXmlStreamReader::IncludeChildElements);
} else if (xmlName == "releasedate") {
} else if (xml.name() == "releasedate") {
releaseDate =
QDate::fromString(xml.readElementText(QXmlStreamReader::IncludeChildElements), Qt::ISODate);
} else if (!xmlName.isEmpty()) {
qDebug() << "[CockatriceXml4Parser] Unknown set property" << xmlName
} else if (xml.name() != "") {
qDebug() << "[CockatriceXml4Parser] Unknown set property" << xml.name()
<< ", trying to continue anyway";
xml.skipCurrentElement();
}
@@ -112,9 +109,8 @@ QVariantHash CockatriceXml4Parser::loadCardPropertiesFromXml(QXmlStreamReader &x
break;
}
auto xmlName = xml.name().toString();
if (!xmlName.isEmpty()) {
properties.insert(xmlName, xml.readElementText(QXmlStreamReader::IncludeChildElements));
if (xml.name() != "") {
properties.insert(xml.name().toString(), xml.readElementText(QXmlStreamReader::IncludeChildElements));
}
}
return properties;
@@ -127,14 +123,12 @@ void CockatriceXml4Parser::loadCardsFromXml(QXmlStreamReader &xml)
break;
}
auto xmlName = xml.name().toString();
if (xmlName == "card") {
if (xml.name() == "card") {
QString name = QString("");
QString text = QString("");
QVariantHash properties = QVariantHash();
QList<CardRelation *> relatedCards, reverseRelatedCards;
auto _sets = CardInfoPerSetMap();
CardInfoPerSetMap sets = CardInfoPerSetMap();
int tableRow = 0;
bool cipt = false;
bool isToken = false;
@@ -144,28 +138,25 @@ void CockatriceXml4Parser::loadCardsFromXml(QXmlStreamReader &xml)
if (xml.readNext() == QXmlStreamReader::EndElement) {
break;
}
xmlName = xml.name().toString();
// variable - assigned properties
if (xmlName == "name") {
if (xml.name() == "name") {
name = xml.readElementText(QXmlStreamReader::IncludeChildElements);
} else if (xmlName == "text") {
} else if (xml.name() == "text") {
text = xml.readElementText(QXmlStreamReader::IncludeChildElements);
} else if (xmlName == "token") {
} else if (xml.name() == "token") {
isToken = static_cast<bool>(xml.readElementText(QXmlStreamReader::IncludeChildElements).toInt());
// generic properties
} else if (xmlName == "prop") {
} else if (xml.name() == "prop") {
properties = loadCardPropertiesFromXml(xml);
// positioning info
} else if (xmlName == "tablerow") {
} else if (xml.name() == "tablerow") {
tableRow = xml.readElementText(QXmlStreamReader::IncludeChildElements).toInt();
} else if (xmlName == "cipt") {
} else if (xml.name() == "cipt") {
cipt = (xml.readElementText(QXmlStreamReader::IncludeChildElements) == "1");
} else if (xmlName == "upsidedown") {
} else if (xml.name() == "upsidedown") {
upsideDown = (xml.readElementText(QXmlStreamReader::IncludeChildElements) == "1");
// sets
} else if (xmlName == "set") {
} else if (xml.name() == "set") {
// NOTE: attributes but be read before readElementText()
QXmlStreamAttributes attrs = xml.attributes();
QString setName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
@@ -178,14 +169,13 @@ void CockatriceXml4Parser::loadCardsFromXml(QXmlStreamReader &xml)
attrName = "picurl";
setInfo.setProperty(attrName, attr.value().toString());
}
_sets.insert(setName, setInfo);
sets.insert(setName, setInfo);
}
// related cards
} else if (xmlName == "related" || xmlName == "reverse-related") {
CardRelation::AttachType attachType = CardRelation::DoesNotAttach;
// relatd cards
} else if (xml.name() == "related" || xml.name() == "reverse-related") {
bool attach = false;
bool exclude = false;
bool variable = false;
bool persistent = false;
int count = 1;
QXmlStreamAttributes attrs = xml.attributes();
QString cardName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
@@ -205,33 +195,28 @@ void CockatriceXml4Parser::loadCardsFromXml(QXmlStreamReader &xml)
}
if (attrs.hasAttribute("attach")) {
attachType = attrs.value("attach").toString() == "transform" ? CardRelation::TransformInto
: CardRelation::AttachTo;
attach = true;
}
if (attrs.hasAttribute("exclude")) {
exclude = true;
}
if (attrs.hasAttribute("persistent")) {
persistent = true;
}
auto *relation = new CardRelation(cardName, attachType, exclude, variable, count, persistent);
if (xmlName == "reverse-related") {
auto *relation = new CardRelation(cardName, attach, exclude, variable, count);
if (xml.name() == "reverse-related") {
reverseRelatedCards << relation;
} else {
relatedCards << relation;
}
} else if (!xmlName.isEmpty()) {
qDebug() << "[CockatriceXml4Parser] Unknown card property" << xmlName
} else if (xml.name() != "") {
qDebug() << "[CockatriceXml4Parser] Unknown card property" << xml.name()
<< ", trying to continue anyway";
xml.skipCurrentElement();
}
}
CardInfoPtr newCard = CardInfo::newInstance(name, text, isToken, properties, relatedCards,
reverseRelatedCards, _sets, cipt, tableRow, upsideDown);
reverseRelatedCards, sets, cipt, tableRow, upsideDown);
emit addCard(newCard);
}
}
@@ -295,14 +280,12 @@ static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfoPtr &in
for (auto i : related) {
xml.writeStartElement("related");
if (i->getDoesAttach()) {
xml.writeAttribute("attach", i->getAttachTypeAsString());
xml.writeAttribute("attach", "attach");
}
if (i->getIsCreateAllExclusion()) {
xml.writeAttribute("exclude", "exclude");
}
if (i->getIsPersistent()) {
xml.writeAttribute("persistent", "persistent");
}
if (i->getIsVariable()) {
if (1 == i->getDefaultCount()) {
xml.writeAttribute("count", "x");
@@ -319,16 +302,13 @@ static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfoPtr &in
for (auto i : reverseRelated) {
xml.writeStartElement("reverse-related");
if (i->getDoesAttach()) {
xml.writeAttribute("attach", i->getAttachTypeAsString());
xml.writeAttribute("attach", "attach");
}
if (i->getIsCreateAllExclusion()) {
xml.writeAttribute("exclude", "exclude");
}
if (i->getIsPersistent()) {
xml.writeAttribute("persistent", "persistent");
}
if (i->getIsVariable()) {
if (1 == i->getDefaultCount()) {
xml.writeAttribute("count", "x");
@@ -356,7 +336,7 @@ static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfoPtr &in
return xml;
}
bool CockatriceXml4Parser::saveToFile(SetNameMap _sets,
bool CockatriceXml4Parser::saveToFile(SetNameMap sets,
CardNameMap cards,
const QString &fileName,
const QString &sourceUrl,
@@ -383,9 +363,9 @@ bool CockatriceXml4Parser::saveToFile(SetNameMap _sets,
xml.writeTextElement("sourceVersion", sourceVersion);
xml.writeEndElement();
if (_sets.count() > 0) {
if (sets.count() > 0) {
xml.writeStartElement("sets");
for (CardSetPtr set : _sets) {
for (CardSetPtr set : sets) {
xml << set;
}
xml.writeEndElement();

View File

@@ -14,7 +14,7 @@ public:
~CockatriceXml4Parser() override = default;
bool getCanParseFile(const QString &name, QIODevice &device) override;
void parseFile(QIODevice &device) override;
bool saveToFile(SetNameMap _sets,
bool saveToFile(SetNameMap sets,
CardNameMap cards,
const QString &fileName,
const QString &sourceUrl = "unknown",

View File

@@ -24,7 +24,7 @@ void CardDragItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti
AbstractCardDragItem::paint(painter, option, widget);
if (occupied)
painter->fillPath(shape(), QColor(200, 0, 0, 100));
painter->fillRect(boundingRect(), QColor(200, 0, 0, 100));
}
void CardDragItem::updatePosition(const QPointF &cursorScenePos)
@@ -53,20 +53,8 @@ void CardDragItem::updatePosition(const QPointF &cursorScenePos)
QPointF zonePos = currentZone->scenePos();
QPointF cursorPosInZone = cursorScenePos - zonePos;
// If we are on a Table, we center the card around the cursor, because we
// snap it into place and no longer see it being dragged.
//
// For other zones (where we do display the card under the cursor), we use
// the hotspot to feel like the card was dragged at the corresponding
// position.
TableZone *tableZone = qobject_cast<TableZone *>(cursorZone);
QPointF closestGridPoint;
if (tableZone)
closestGridPoint = tableZone->closestGridPoint(cursorPosInZone);
else
closestGridPoint = cursorPosInZone - hotSpot;
QPointF cardTopLeft = cursorPosInZone - hotSpot;
QPointF closestGridPoint = cursorZone->closestGridPoint(cardTopLeft);
QPointF newPos = zonePos + closestGridPoint;
if (newPos != pos()) {
@@ -95,7 +83,7 @@ void CardDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
QList<CardDragItem *> dragItemList;
CardZone *startZone = static_cast<CardItem *>(item)->getZone();
if (currentZone && !(static_cast<CardItem *>(item)->getAttachedTo() && (startZone == currentZone)) && !occupied) {
if (currentZone && !(static_cast<CardItem *>(item)->getAttachedTo() && (startZone == currentZone))) {
dragItemList.append(this);
for (int i = 0; i < childDrags.size(); i++) {
CardDragItem *c = static_cast<CardDragItem *>(childDrags[i]);

View File

@@ -4,7 +4,8 @@
#include "main.h"
#include "pictureloader.h"
#include <QStylePainter>
#include <QPainter>
#include <QStyle>
#include <QWidget>
CardInfoPicture::CardInfoPicture(QWidget *parent) : QWidget(parent), info(nullptr), pixmapDirty(true)
@@ -54,13 +55,6 @@ void CardInfoPicture::paintEvent(QPaintEvent *)
if (pixmapDirty)
loadPixmap();
QSize scaledSize = resizedPixmap.size().scaled(size(), Qt::KeepAspectRatio);
QPoint topLeft{(width() - scaledSize.width()) / 2, (height() - scaledSize.height()) / 2};
qreal radius = 0.05 * scaledSize.width();
QStylePainter painter(this);
QPainterPath shape;
shape.addRoundedRect(QRect(topLeft, scaledSize), radius, radius);
painter.setClipPath(shape);
painter.drawItemPixmap(QRect(topLeft, scaledSize), Qt::AlignCenter, resizedPixmap);
QPainter painter(this);
style()->drawItemPixmap(&painter, rect(), Qt::AlignHCenter, resizedPixmap);
}

View File

@@ -6,9 +6,13 @@
#include "main.h"
#include <QApplication>
#include <QScreen>
#include <QVBoxLayout>
#include <utility>
#if (QT_VERSION >= QT_VERSION_CHECK(5, 13, 0))
#include <QScreen>
#else
#include <QDesktopWidget>
#endif
#include <QVBoxLayout>
CardInfoWidget::CardInfoWidget(const QString &cardName, QWidget *parent, Qt::WindowFlags flags)
: QFrame(parent, flags), aspectRatio((qreal)CARD_HEIGHT / (qreal)CARD_WIDTH), info(nullptr)
@@ -30,7 +34,12 @@ CardInfoWidget::CardInfoWidget(const QString &cardName, QWidget *parent, Qt::Win
setFrameStyle(QFrame::Panel | QFrame::Raised);
int pixmapHeight = QGuiApplication::primaryScreen()->geometry().height() / 3;
#if (QT_VERSION >= QT_VERSION_CHECK(5, 13, 0))
int pixmapHeight = qApp->primaryScreen()->geometry().height() / 3;
#else
QDesktopWidget desktopWidget;
int pixmapHeight = desktopWidget.screenGeometry().height() / 3;
#endif
int pixmapWidth = static_cast<int>(pixmapHeight / aspectRatio);
pic->setFixedWidth(pixmapWidth);
pic->setFixedHeight(pixmapHeight);

View File

@@ -97,10 +97,10 @@ void CardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QMapIterator<int, int> counterIterator(counters);
while (counterIterator.hasNext()) {
counterIterator.next();
QColor _color;
_color.setHsv(counterIterator.key() * 60, 150, 255);
QColor color;
color.setHsv(counterIterator.key() * 60, 150, 255);
paintNumberEllipse(counterIterator.value(), 14, _color, i, counters.size(), painter);
paintNumberEllipse(counterIterator.value(), 14, color, i, counters.size(), painter);
++i;
}
@@ -141,19 +141,21 @@ void CardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
}
if (getBeingPointedAt()) {
painter->fillPath(shape(), QBrush(QColor(255, 0, 0, 100)));
painter->fillRect(boundingRect(), QBrush(QColor(255, 0, 0, 100)));
}
if (doesntUntap) {
painter->save();
painter->setRenderHint(QPainter::Antialiasing, false);
transformPainter(painter, translatedSize, tapAngle);
QPen pen;
pen.setColor(Qt::magenta);
pen.setWidth(0); // Cosmetic pen
const int penWidth = 1;
pen.setWidth(penWidth);
painter->setPen(pen);
painter->drawPath(shape());
painter->drawRect(QRectF(0, 0, translatedSize.width() + penWidth, translatedSize.height() - penWidth));
painter->restore();
}
@@ -233,25 +235,25 @@ void CardItem::resetState()
update();
}
void CardItem::processCardInfo(const ServerInfo_Card &_info)
void CardItem::processCardInfo(const ServerInfo_Card &info)
{
counters.clear();
const int counterListSize = _info.counter_list_size();
const int counterListSize = info.counter_list_size();
for (int i = 0; i < counterListSize; ++i) {
const ServerInfo_CardCounter &counterInfo = _info.counter_list(i);
const ServerInfo_CardCounter &counterInfo = info.counter_list(i);
counters.insert(counterInfo.id(), counterInfo.value());
}
setId(_info.id());
setName(QString::fromStdString(_info.name()));
setAttacking(_info.attacking());
setFaceDown(_info.face_down());
setPT(QString::fromStdString(_info.pt()));
setAnnotation(QString::fromStdString(_info.annotation()));
setColor(QString::fromStdString(_info.color()));
setTapped(_info.tapped());
setDestroyOnZoneChange(_info.destroy_on_zone_change());
setDoesntUntap(_info.doesnt_untap());
setId(info.id());
setName(QString::fromStdString(info.name()));
setAttacking(info.attacking());
setFaceDown(info.face_down());
setPT(QString::fromStdString(info.pt()));
setAnnotation(QString::fromStdString(info.annotation()));
setColor(QString::fromStdString(info.color()));
setTapped(info.tapped());
setDestroyOnZoneChange(info.destroy_on_zone_change());
setDoesntUntap(info.doesnt_untap());
}
CardDragItem *CardItem::createDragItem(int _id, const QPointF &_pos, const QPointF &_scenePos, bool faceDown)
@@ -284,36 +286,15 @@ void CardItem::drawArrow(const QColor &arrowColor)
scene()->addItem(arrow);
arrow->grabMouse();
for (const auto &item : scene()->selectedItems()) {
CardItem *card = qgraphicsitem_cast<CardItem *>(item);
if (card == nullptr || card == this)
QListIterator<QGraphicsItem *> itemIterator(scene()->selectedItems());
while (itemIterator.hasNext()) {
CardItem *c = qgraphicsitem_cast<CardItem *>(itemIterator.next());
if (!c || (c == this))
continue;
if (card->getZone() != zone)
if (c->getZone() != zone)
continue;
ArrowDragItem *childArrow = new ArrowDragItem(arrowOwner, card, arrowColor);
scene()->addItem(childArrow);
arrow->addChildArrow(childArrow);
}
}
void CardItem::drawAttachArrow()
{
if (static_cast<TabGame *>(owner->parent())->getSpectator())
return;
auto *arrow = new ArrowAttachItem(this);
scene()->addItem(arrow);
arrow->grabMouse();
for (const auto &item : scene()->selectedItems()) {
CardItem *card = qgraphicsitem_cast<CardItem *>(item);
if (card == nullptr)
continue;
if (card->getZone() != zone)
continue;
ArrowAttachItem *childArrow = new ArrowAttachItem(card);
ArrowDragItem *childArrow = new ArrowDragItem(arrowOwner, c, arrowColor);
scene()->addItem(childArrow);
arrow->addChildArrow(childArrow);
}
@@ -348,24 +329,22 @@ void CardItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
bool forceFaceDown = event->modifiers().testFlag(Qt::ShiftModifier);
// Use the buttonDownPos to align the hot spot with the position when
// the user originally clicked
createDragItem(id, event->buttonDownPos(Qt::LeftButton), event->scenePos(), facedown || forceFaceDown);
createDragItem(id, event->pos(), event->scenePos(), facedown || forceFaceDown);
dragItem->grabMouse();
int childIndex = 0;
for (const auto &item : scene()->selectedItems()) {
CardItem *card = static_cast<CardItem *>(item);
if ((card == this) || (card->getZone() != zone))
QList<QGraphicsItem *> sel = scene()->selectedItems();
int j = 0;
for (int i = 0; i < sel.size(); i++) {
CardItem *c = static_cast<CardItem *>(sel.at(i));
if ((c == this) || (c->getZone() != zone))
continue;
++childIndex;
++j;
QPointF childPos;
if (zone->getHasCardAttr())
childPos = card->pos() - pos();
childPos = c->pos() - pos();
else
childPos = QPointF(childIndex * CARD_WIDTH / 2, 0);
CardDragItem *drag =
new CardDragItem(card, card->getId(), childPos, card->getFaceDown() || forceFaceDown, dragItem);
childPos = QPointF(j * CARD_WIDTH / 2, 0);
CardDragItem *drag = new CardDragItem(c, c->getId(), childPos, c->getFaceDown() || forceFaceDown, dragItem);
drag->setPos(dragItem->pos() + childPos);
scene()->addItem(drag);
}
@@ -390,8 +369,7 @@ void CardItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
if (event->button() == Qt::RightButton) {
if (cardMenu != nullptr && !cardMenu->isEmpty() && owner != nullptr) {
cardMenu->popup(event->screenPos());
return;
cardMenu->exec(event->screenPos());
}
} else if ((event->modifiers() != Qt::AltModifier) && (event->button() == Qt::LeftButton) &&
(!SettingsCache::instance().getDoubleClickToPlay())) {

View File

@@ -2,7 +2,6 @@
#define CARDITEM_H
#include "abstractcarditem.h"
#include "server_card.h"
class CardDatabase;
class CardDragItem;
@@ -131,14 +130,14 @@ public:
}
void removeAttachedCard(CardItem *card)
{
attachedCards.removeOne(card);
attachedCards.removeAt(attachedCards.indexOf(card));
}
const QList<CardItem *> &getAttachedCards() const
{
return attachedCards;
}
void resetState();
void processCardInfo(const ServerInfo_Card &_info);
void processCardInfo(const ServerInfo_Card &info);
QMenu *getCardMenu() const
{
@@ -157,7 +156,6 @@ public:
CardDragItem *createDragItem(int _id, const QPointF &_pos, const QPointF &_scenePos, bool faceDown);
void deleteDragItem();
void drawArrow(const QColor &arrowColor);
void drawAttachArrow();
void playCard(bool faceDown);
protected:

View File

@@ -187,7 +187,7 @@ CardItem *CardZone::takeCard(int position, int cardId, bool /*canResize*/)
void CardZone::removeCard(CardItem *card)
{
cards.removeOne(card);
cards.removeAt(cards.indexOf(card));
reorganizeCards();
emit cardCountChanged();
player->deleteCard(card);

View File

@@ -21,7 +21,7 @@ UserMessagePosition::UserMessagePosition(QTextCursor &cursor)
relativePosition = cursor.position() - block.position();
}
ChatView::ChatView(TabSupervisor *_tabSupervisor,
ChatView::ChatView(const TabSupervisor *_tabSupervisor,
const UserlistProxy *_userlistProxy,
TabGame *_game,
bool _showTimestamps,
@@ -321,7 +321,7 @@ void ChatView::checkTag(QTextCursor &cursor, QString &message)
void ChatView::checkMention(QTextCursor &cursor, QString &message, const QString &userName, UserLevelFlags userLevel)
{
const static auto notALetterOrNumber = QRegularExpression("[^a-zA-Z0-9]");
const QRegExp notALetterOrNumber = QRegExp("[^a-zA-Z0-9]");
int firstSpace = message.indexOf(' ');
QString fullMentionUpToSpaceOrEnd = (firstSpace == -1) ? message.mid(1) : message.mid(1, firstSpace - 1);
@@ -470,23 +470,15 @@ void ChatView::showSystemPopup(const QString &userName)
QColor ChatView::getCustomMentionColor()
{
#if (QT_VERSION >= QT_VERSION_CHECK(6, 4, 0))
QColor customColor = QColor::fromString("#" + SettingsCache::instance().getChatMentionColor());
#else
QColor customColor;
customColor.setNamedColor("#" + SettingsCache::instance().getChatMentionColor());
#endif
return customColor.isValid() ? customColor : DEFAULT_MENTION_COLOR;
}
QColor ChatView::getCustomHighlightColor()
{
#if (QT_VERSION >= QT_VERSION_CHECK(6, 4, 0))
QColor customColor = QColor::fromString("#" + SettingsCache::instance().getChatMentionColor());
#else
QColor customColor;
customColor.setNamedColor("#" + SettingsCache::instance().getChatMentionColor());
#endif
customColor.setNamedColor("#" + SettingsCache::instance().getChatHighlightColor());
return customColor.isValid() ? customColor : DEFAULT_MENTION_COLOR;
}
@@ -518,11 +510,7 @@ void ChatView::redactMessages(const QString &userName, int amount)
}
}
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
void ChatView::enterEvent(QEnterEvent * /*event*/)
#else
void ChatView::enterEvent(QEvent * /*event*/)
#endif
{
setMouseTracking(true);
}
@@ -578,11 +566,7 @@ void ChatView::mousePressEvent(QMouseEvent *event)
switch (hoveredItemType) {
case HoveredCard: {
if ((event->button() == Qt::MiddleButton) || (event->button() == Qt::LeftButton))
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
emit showCardInfoPopup(event->globalPosition().toPoint(), hoveredContent);
#else
emit showCardInfoPopup(event->globalPos(), hoveredContent);
#endif
break;
}
case HoveredUser: {
@@ -592,11 +576,7 @@ void ChatView::mousePressEvent(QMouseEvent *event)
switch (event->button()) {
case Qt::RightButton: {
UserLevelFlags userLevel(hoveredContent.left(delimiterIndex).toInt());
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
userContextMenu->showContextMenu(event->globalPosition().toPoint(), userName, userLevel, this);
#else
userContextMenu->showContextMenu(event->globalPos(), userName, userLevel, this);
#endif
break;
}
case Qt::LeftButton: {

View File

@@ -33,7 +33,7 @@ class ChatView : public QTextBrowser
{
Q_OBJECT
protected:
TabSupervisor *const tabSupervisor;
const TabSupervisor *const tabSupervisor;
TabGame *const game;
private:
@@ -65,8 +65,8 @@ private:
QTextCursor prepareBlock(bool same = false);
void appendCardTag(QTextCursor &cursor, const QString &cardName);
void appendUrlTag(QTextCursor &cursor, QString url);
static QColor getCustomMentionColor();
static QColor getCustomHighlightColor();
QColor getCustomMentionColor();
QColor getCustomHighlightColor();
void showSystemPopup(const QString &userName);
bool isModeratorSendingGlobal(QFlags<ServerInfo_User::UserLevelFlag> userLevelFlag, QString message);
void checkTag(QTextCursor &cursor, QString &message);
@@ -83,7 +83,7 @@ private slots:
void actMessageClicked();
public:
ChatView(TabSupervisor *_tabSupervisor,
ChatView(const TabSupervisor *_tabSupervisor,
const UserlistProxy *_userlistProxy,
TabGame *_game,
bool _showTimestamps,
@@ -103,11 +103,7 @@ public:
void redactMessages(const QString &userName, int amount);
protected:
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
void enterEvent(QEnterEvent *event);
#else
void enterEvent(QEvent *event);
#endif
void leaveEvent(QEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void mousePressEvent(QMouseEvent *event);

View File

@@ -0,0 +1,29 @@
#ifndef CLIENT_METATYPES_H
#define CLIENT_METATYPES_H
#include <QMetaType>
Q_DECLARE_METATYPE(QVariant)
Q_DECLARE_METATYPE(CommandContainer)
Q_DECLARE_METATYPE(Response)
Q_DECLARE_METATYPE(Response::ResponseCode)
Q_DECLARE_METATYPE(ClientStatus)
Q_DECLARE_METATYPE(RoomEvent)
Q_DECLARE_METATYPE(GameEventContainer)
Q_DECLARE_METATYPE(Event_ServerIdentification)
Q_DECLARE_METATYPE(Event_ConnectionClosed)
Q_DECLARE_METATYPE(Event_ServerShutdown)
Q_DECLARE_METATYPE(Event_AddToList)
Q_DECLARE_METATYPE(Event_RemoveFromList)
Q_DECLARE_METATYPE(Event_UserJoined)
Q_DECLARE_METATYPE(Event_UserLeft)
Q_DECLARE_METATYPE(Event_ServerMessage)
Q_DECLARE_METATYPE(Event_ListRooms)
Q_DECLARE_METATYPE(Event_GameJoined)
Q_DECLARE_METATYPE(Event_UserMessage)
Q_DECLARE_METATYPE(ServerInfo_User)
Q_DECLARE_METATYPE(QList<ServerInfo_User>)
Q_DECLARE_METATYPE(Event_ReplayAdded)
Q_DECLARE_METATYPE(QList<QString>)
#endif

View File

@@ -6,7 +6,6 @@
#include <QDebug>
#include <QFile>
#include <QRegularExpression>
#include <QStringList>
const QStringList DeckLoader::fileNameFilters = QStringList()
@@ -209,7 +208,7 @@ void DeckLoader::saveToStream_DeckHeader(QTextStream &out)
}
if (!getComments().isEmpty()) {
QStringList commentRows = getComments().split(QRegularExpression("\n|\r\n|\r"));
QStringList commentRows = getComments().split(QRegExp("\n|\r\n|\r"));
foreach (QString row, commentRows) {
out << "// " << row << "\n";
}
@@ -289,7 +288,7 @@ QString DeckLoader::getCardZoneFromName(QString cardName, QString currentZoneNam
return currentZoneName;
}
QString DeckLoader::getCompleteCardName(const QString &cardName) const
QString DeckLoader::getCompleteCardName(const QString cardName) const
{
if (db) {
CardInfoPtr temp = db->guessCard(cardName);

View File

@@ -57,8 +57,8 @@ protected:
const InnerDecklistNode *zoneNode,
QList<DecklistCardNode *> cards,
bool addComments = true);
[[nodiscard]] QString getCardZoneFromName(QString cardName, QString currentZoneName) override;
[[nodiscard]] QString getCompleteCardName(const QString &cardName) const override;
virtual QString getCardZoneFromName(QString cardName, QString currentZoneName);
virtual QString getCompleteCardName(const QString cardName) const;
};
#endif

View File

@@ -7,7 +7,7 @@
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QRegularExpression>
#include <QRegExp>
#include <QUrlQuery>
DeckStatsInterface::DeckStatsInterface(CardDatabase &_cardDatabase, QObject *parent)
@@ -20,7 +20,7 @@ DeckStatsInterface::DeckStatsInterface(CardDatabase &_cardDatabase, QObject *par
void DeckStatsInterface::queryFinished(QNetworkReply *reply)
{
if (reply->error() != QNetworkReply::NoError) {
QMessageBox::critical(nullptr, tr("Error"), reply->errorString());
QMessageBox::critical(0, tr("Error"), reply->errorString());
reply->deleteLater();
deleteLater();
return;
@@ -29,15 +29,14 @@ void DeckStatsInterface::queryFinished(QNetworkReply *reply)
QString data(reply->readAll());
reply->deleteLater();
static const QRegularExpression rx("<meta property=\"og:url\" content=\"([^\"]+)\"");
auto match = rx.match(data);
if (!match.hasMatch()) {
QMessageBox::critical(nullptr, tr("Error"), tr("The reply from the server could not be parsed."));
QRegExp rx("<meta property=\"og:url\" content=\"([^\"]+)\"");
if (-1 == rx.indexIn(data)) {
QMessageBox::critical(0, tr("Error"), tr("The reply from the server could not be parsed."));
deleteLater();
return;
}
QString deckUrl = match.captured(1);
QString deckUrl = rx.cap(1);
QDesktopServices::openUrl(deckUrl);
deleteLater();

View File

@@ -9,8 +9,8 @@
#include <QApplication>
#include <QGraphicsSceneMouseEvent>
#include <QMouseEvent>
#include <QtMath>
#include <algorithm>
#include <math.h>
DeckViewCardDragItem::DeckViewCardDragItem(DeckViewCard *_item,
const QPointF &_hotSpot,
@@ -89,8 +89,7 @@ void DeckViewCard::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti
pen.setJoinStyle(Qt::MiterJoin);
pen.setColor(originZone == DECK_ZONE_MAIN ? Qt::green : Qt::red);
painter->setPen(pen);
qreal cardRadius = 0.05 * (CARD_WIDTH - 3);
painter->drawRoundedRect(QRectF(1.5, 1.5, CARD_WIDTH - 3., CARD_HEIGHT - 3.), cardRadius, cardRadius);
painter->drawRect(QRectF(1, 1, CARD_WIDTH - 2, CARD_HEIGHT - 2.5));
painter->restore();
}
@@ -217,7 +216,7 @@ void DeckViewCardContainer::addCard(DeckViewCard *card)
void DeckViewCardContainer::removeCard(DeckViewCard *card)
{
cards.removeOne(card);
cards.removeAt(cards.indexOf(card));
cardsByType.remove(card->getInfo() ? card->getInfo()->getMainCardType() : "", card);
}
@@ -239,9 +238,11 @@ int DeckViewCardContainer::getCardTypeTextWidth() const
QFontMetrics fm(f);
int maxCardTypeWidth = 0;
for (const auto &key : cardsByType.keys()) {
int cardTypeWidth = fm.size(Qt::TextSingleLine, key).width();
maxCardTypeWidth = qMax(maxCardTypeWidth, cardTypeWidth);
QMapIterator<QString, DeckViewCard *> i(cardsByType);
while (i.hasNext()) {
int cardTypeWidth = fm.size(Qt::TextSingleLine, i.next().key()).width();
if (cardTypeWidth > maxCardTypeWidth)
maxCardTypeWidth = cardTypeWidth;
}
return maxCardTypeWidth + 15;
@@ -273,11 +274,16 @@ void DeckViewCardContainer::rearrangeItems(const QList<QPair<int, int>> &rowsAnd
{
currentRowsAndCols = rowsAndCols;
int totalCols = 0, totalRows = 0;
qreal yUntilNow = separatorY + paddingY;
qreal x = (qreal)getCardTypeTextWidth();
for (int i = 0; i < rowsAndCols.size(); ++i) {
const int tempRows = rowsAndCols[i].first;
const int tempCols = rowsAndCols[i].second;
totalRows += tempRows;
if (tempCols > totalCols)
totalCols = tempCols;
QList<QString> cardTypeList = cardsByType.uniqueKeys();
QList<DeckViewCard *> row = cardsByType.values(cardTypeList[i]);
std::sort(row.begin(), row.end(), DeckViewCardContainer::sortCardsByName);
@@ -434,7 +440,7 @@ void DeckViewScene::rearrangeItems()
const int maxRows = rowsAndColsList[maxIndex1][maxIndex2].first;
const int maxCardCount = cardCountList[maxIndex1][maxIndex2];
rowsAndColsList[maxIndex1][maxIndex2] =
QPair<int, int>(maxRows + 1, (int)qCeil((qreal)maxCardCount / (qreal)(maxRows + 1)));
QPair<int, int>(maxRows + 1, (int)ceil((qreal)maxCardCount / (qreal)(maxRows + 1)));
}
totalHeight = -spacing;

View File

@@ -1,7 +1,7 @@
#include "dlg_connect.h"
#include "settingscache.h"
#include "trice_limits.h"
#include "stringsizes.h"
#include "userconnection_information.h"
#include <QCheckBox>
@@ -162,7 +162,8 @@ DlgConnect::DlgConnect(QWidget *parent) : QDialog(parent)
previousHostButton->setChecked(true);
connect(previousHosts, SIGNAL(currentTextChanged(const QString &)), this, SLOT(updateDisplayInfo(const QString &)));
connect(previousHosts, SIGNAL(currentIndexChanged(const QString &)), this,
SLOT(updateDisplayInfo(const QString &)));
playernameEdit->setFocus();
}
@@ -245,22 +246,22 @@ void DlgConnect::updateDisplayInfo(const QString &saveName)
}
UserConnection_Information uci;
QStringList _data = uci.getServerInfo(saveName);
QStringList data = uci.getServerInfo(saveName);
bool savePasswordStatus = (_data.at(5) == "1");
bool savePasswordStatus = (data.at(5) == "1");
saveEdit->setText(_data.at(0));
hostEdit->setText(_data.at(1));
portEdit->setText(_data.at(2));
playernameEdit->setText(_data.at(3));
saveEdit->setText(data.at(0));
hostEdit->setText(data.at(1));
portEdit->setText(data.at(2));
playernameEdit->setText(data.at(3));
savePasswordCheckBox->setChecked(savePasswordStatus);
if (savePasswordStatus) {
passwordEdit->setText(_data.at(4));
passwordEdit->setText(data.at(4));
}
if (!_data.at(6).isEmpty()) {
QString formattedLink = "<a href=\"" + _data.at(6) + "\">" + _data.at(6) + "</a>";
if (!data.at(6).isEmpty()) {
QString formattedLink = "<a href=\"" + data.at(6) + "\">" + data.at(6) + "</a>";
serverContactLabel->setText(tr("Webpage") + ":");
serverContactLink->setText(formattedLink);
} else {

View File

@@ -5,7 +5,7 @@
#include "decklist.h"
#include "main.h"
#include "settingscache.h"
#include "trice_limits.h"
#include "stringsizes.h"
#include <QCheckBox>
#include <QCloseEvent>

View File

@@ -3,8 +3,8 @@
#include "pb/serverinfo_game.pb.h"
#include "pending_command.h"
#include "settingscache.h"
#include "stringsizes.h"
#include "tab_room.h"
#include "trice_limits.h"
#include <QApplication>
#include <QCheckBox>
@@ -235,13 +235,13 @@ void DlgCreateGame::actOK()
cmd.set_join_as_judge(QApplication::keyboardModifiers() & Qt::ShiftModifier);
cmd.set_join_as_spectator(createGameAsSpectatorCheckBox->isChecked());
QString _gameTypes = QString();
QString gameTypes = QString();
QMapIterator<int, QRadioButton *> gameTypeCheckBoxIterator(gameTypeCheckBoxes);
while (gameTypeCheckBoxIterator.hasNext()) {
gameTypeCheckBoxIterator.next();
if (gameTypeCheckBoxIterator.value()->isChecked()) {
cmd.add_game_type_ids(gameTypeCheckBoxIterator.key());
_gameTypes += gameTypeCheckBoxIterator.value()->text() + ", ";
gameTypes += gameTypeCheckBoxIterator.value()->text() + ", ";
}
}
@@ -256,7 +256,7 @@ void DlgCreateGame::actOK()
SettingsCache::instance().setSpectatorsCanTalk(spectatorsCanTalkCheckBox->isChecked());
SettingsCache::instance().setSpectatorsCanSeeEverything(spectatorsSeeEverythingCheckBox->isChecked());
SettingsCache::instance().setCreateGameAsSpectator(createGameAsSpectatorCheckBox->isChecked());
SettingsCache::instance().setGameTypes(_gameTypes);
SettingsCache::instance().setGameTypes(gameTypes);
}
PendingCommand *pend = room->prepareRoomCommand(cmd);
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(checkResponse(Response)));

View File

@@ -1,6 +1,6 @@
#include "dlg_edit_avatar.h"
#include "trice_limits.h"
#include "stringsizes.h"
#include <QBuffer>
#include <QDebug>
@@ -74,12 +74,13 @@ QByteArray DlgEditAvatar::getImage()
return QByteArray();
}
QByteArray ba;
QBuffer buffer(&ba);
buffer.open(QIODevice::WriteOnly);
for (;;) {
QByteArray ba;
QBuffer buffer(&ba);
buffer.open(QIODevice::WriteOnly);
image.save(&buffer, "JPG");
if (ba.length() > MAX_FILE_LENGTH) {
ba.clear();
image = image.scaledToWidth(image.width() / 2); // divide the amount of pixels in four to get the size down
} else {
return ba;

View File

@@ -1,7 +1,7 @@
#include "dlg_edit_password.h"
#include "settingscache.h"
#include "trice_limits.h"
#include "stringsizes.h"
#include <QDialogButtonBox>
#include <QGridLayout>

View File

@@ -4,7 +4,7 @@
#include "carddatabasemodel.h"
#include "gettextwithmax.h"
#include "main.h"
#include "trice_limits.h"
#include "stringsizes.h"
#include <QAction>
#include <QComboBox>

View File

@@ -1,7 +1,7 @@
#include "dlg_edit_user.h"
#include "settingscache.h"
#include "trice_limits.h"
#include "stringsizes.h"
#include <QDebug>
#include <QDialogButtonBox>

View File

@@ -1,7 +1,7 @@
#include "dlg_forgotpasswordchallenge.h"
#include "settingscache.h"
#include "trice_limits.h"
#include "stringsizes.h"
#include <QCheckBox>
#include <QDebug>

View File

@@ -1,7 +1,7 @@
#include "dlg_forgotpasswordrequest.h"
#include "settingscache.h"
#include "trice_limits.h"
#include "stringsizes.h"
#include <QCheckBox>
#include <QDebug>

View File

@@ -1,7 +1,7 @@
#include "dlg_forgotpasswordreset.h"
#include "settingscache.h"
#include "trice_limits.h"
#include "stringsizes.h"
#include <QCheckBox>
#include <QDebug>

View File

@@ -4,7 +4,6 @@
#include "main.h"
#include "pictureloader.h"
#include "setsmodel.h"
#include "settingscache.h"
#include <QAction>
#include <QDebug>
@@ -85,6 +84,7 @@ WndSets::WndSets(QWidget *parent) : QMainWindow(parent)
displayModel->setDynamicSortFilter(false);
view = new QTreeView;
view->setModel(displayModel);
view->setMinimumSize(QSize(500, 250));
view->setAlternatingRowColors(true);
view->setUniformRowHeights(true);
@@ -98,6 +98,10 @@ WndSets::WndSets(QWidget *parent) : QMainWindow(parent)
view->setDropIndicatorShown(true);
view->setDragDropMode(QAbstractItemView::InternalMove);
view->header()->setSectionResizeMode(QHeaderView::Stretch);
view->header()->setSectionResizeMode(SetsModel::EnabledCol, QHeaderView::ResizeToContents);
view->header()->setSectionResizeMode(SetsModel::LongNameCol, QHeaderView::ResizeToContents);
view->sortByColumn(SetsModel::SortKeyCol, Qt::AscendingOrder);
view->setColumnHidden(SetsModel::SortKeyCol, true);
view->setColumnHidden(SetsModel::IsKnownCol, true);
@@ -117,12 +121,7 @@ WndSets::WndSets(QWidget *parent) : QMainWindow(parent)
connect(disableSomeButton, SIGNAL(clicked()), this, SLOT(actDisableSome()));
connect(view->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), this,
SLOT(actToggleButtons(const QItemSelection &, const QItemSelection &)));
#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0))
connect(searchField, SIGNAL(textChanged(const QString &)), displayModel,
SLOT(setFilterRegularExpression(const QString &)));
#else
connect(searchField, SIGNAL(textChanged(const QString &)), displayModel, SLOT(setFilterRegExp(const QString &)));
#endif
connect(view->header(), SIGNAL(sortIndicatorChanged(int, Qt::SortOrder)), this, SLOT(actDisableSortButtons(int)));
connect(searchField, SIGNAL(textChanged(const QString &)), this, SLOT(actDisableResetButton(const QString &)));
@@ -140,6 +139,7 @@ WndSets::WndSets(QWidget *parent) : QMainWindow(parent)
tr("How to use custom card art") + "</a>"));
QGridLayout *hintsGrid = new QGridLayout;
hintsGrid->setMargin(2);
hintsGrid->addWidget(labNotes, 0, 0);
hintsGroupBox = new QGroupBox(tr("Hints"));
hintsGroupBox->setLayout(hintsGrid);
@@ -166,7 +166,7 @@ WndSets::WndSets(QWidget *parent) : QMainWindow(parent)
mainLayout = new QGridLayout;
mainLayout->addLayout(filterBox, 0, 1, 1, 2);
mainLayout->addWidget(setsEditToolBar, 1, 0, 4, 1);
mainLayout->addWidget(setsEditToolBar, 1, 0, 2, 1);
mainLayout->addWidget(view, 1, 1, 1, 2);
mainLayout->addWidget(enableAllButton, 2, 1);
mainLayout->addWidget(disableAllButton, 2, 2);
@@ -186,35 +186,13 @@ WndSets::WndSets(QWidget *parent) : QMainWindow(parent)
setCentralWidget(centralWidget);
setWindowTitle(tr("Manage sets"));
setMinimumSize(800, 500);
auto &geometry = SettingsCache::instance().getSetsDialogGeometry();
if (!geometry.isEmpty()) {
restoreGeometry(geometry);
}
auto &headerState = SettingsCache::instance().layouts().getSetsDialogHeaderState();
if (!headerState.isEmpty()) {
view->header()->restoreState(headerState);
view->header()->setSortIndicator(SORT_RESET, Qt::DescendingOrder);
} else {
view->header()->resizeSections(QHeaderView::ResizeToContents);
}
connect(view->header(), &QHeaderView::geometriesChanged, this, &WndSets::saveHeaderState);
resize(800, 500);
}
WndSets::~WndSets()
{
}
void WndSets::closeEvent(QCloseEvent * /*ev*/)
{
SettingsCache::instance().setSetsDialogGeometry(saveGeometry());
}
void WndSets::saveHeaderState()
{
SettingsCache::instance().layouts().setSetsDialogHeaderState(view->header()->saveState());
}
void WndSets::rebuildMainLayout(int actionToTake)
{
if (mainLayout == nullptr)

View File

@@ -40,8 +40,6 @@ private:
QHBoxLayout *filterBox;
int sortIndex;
Qt::SortOrder sortOrder;
void closeEvent(QCloseEvent *ev) override;
void saveHeaderState();
void rebuildMainLayout(int actionToTake);
bool setOrderIsSorted;
enum

View File

@@ -2,7 +2,7 @@
#include "pb/serverinfo_user.pb.h"
#include "settingscache.h"
#include "trice_limits.h"
#include "stringsizes.h"
#include <QCheckBox>
#include <QDebug>
@@ -129,7 +129,6 @@ DlgRegister::DlgRegister(QWidget *parent) : QDialog(parent)
countryEdit->addItem(QPixmap("theme:countries/er"), "er");
countryEdit->addItem(QPixmap("theme:countries/es"), "es");
countryEdit->addItem(QPixmap("theme:countries/et"), "et");
countryEdit->addItem(QPixmap("theme:countries/eu"), "eu");
countryEdit->addItem(QPixmap("theme:countries/fi"), "fi");
countryEdit->addItem(QPixmap("theme:countries/fj"), "fj");
countryEdit->addItem(QPixmap("theme:countries/fk"), "fk");
@@ -305,7 +304,6 @@ DlgRegister::DlgRegister(QWidget *parent) : QDialog(parent)
countryEdit->addItem(QPixmap("theme:countries/vu"), "vu");
countryEdit->addItem(QPixmap("theme:countries/wf"), "wf");
countryEdit->addItem(QPixmap("theme:countries/ws"), "ws");
countryEdit->addItem(QPixmap("theme:countries/xk"), "xk");
countryEdit->addItem(QPixmap("theme:countries/ye"), "ye");
countryEdit->addItem(QPixmap("theme:countries/yt"), "yt");
countryEdit->addItem(QPixmap("theme:countries/za"), "za");

View File

@@ -1,52 +0,0 @@
#include "dlg_roll_dice.h"
#include "trice_limits.h"
#include <QDialogButtonBox>
#include <QLabel>
#include <QSpinBox>
#include <QVBoxLayout>
#include <QWidget>
DlgRollDice::DlgRollDice(QWidget *parent) : QDialog(parent)
{
numberOfSidesLabel = new QLabel(tr("Number of sides:"));
numberOfSidesEdit = new QSpinBox(this);
numberOfSidesEdit->setValue(DEFAULT_NUMBER_SIDES_DIE);
numberOfSidesEdit->setRange(MINIMUM_DIE_SIDES, MAXIMUM_DIE_SIDES);
numberOfSidesEdit->setFocus();
numberOfSidesLabel->setBuddy(numberOfSidesEdit);
numberOfDiceLabel = new QLabel(tr("Number of dice:"));
numberOfDiceEdit = new QSpinBox(this);
numberOfDiceEdit->setValue(DEFAULT_NUMBER_DICE_TO_ROLL);
numberOfDiceEdit->setRange(MINIMUM_DICE_TO_ROLL, MAXIMUM_DICE_TO_ROLL);
numberOfDiceLabel->setBuddy(numberOfDiceEdit);
auto *grid = new QGridLayout;
grid->addWidget(numberOfSidesLabel, 0, 0);
grid->addWidget(numberOfSidesEdit, 0, 1);
grid->addWidget(numberOfDiceLabel, 1, 0);
grid->addWidget(numberOfDiceEdit, 1, 1);
buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
auto *mainLayout = new QVBoxLayout;
mainLayout->addItem(grid);
mainLayout->addWidget(buttonBox);
setLayout(mainLayout);
setWindowTitle(tr("Roll Dice"));
}
uint DlgRollDice::getDieSideCount() const
{
return numberOfSidesEdit->text().toUInt();
}
uint DlgRollDice::getDiceToRollCount() const
{
return numberOfDiceEdit->text().toUInt();
}

View File

@@ -1,26 +0,0 @@
#ifndef DLG_ROLL_DICE_H
#define DLG_ROLL_DICE_H
#include <QDialog>
#include <QDialogButtonBox>
#include <QLabel>
#include <QSpinBox>
class DlgRollDice : public QDialog
{
Q_OBJECT
static constexpr uint DEFAULT_NUMBER_SIDES_DIE = 20;
static constexpr uint DEFAULT_NUMBER_DICE_TO_ROLL = 1;
QLabel *numberOfSidesLabel, *numberOfDiceLabel;
QSpinBox *numberOfSidesEdit, *numberOfDiceEdit;
QDialogButtonBox *buttonBox;
public:
explicit DlgRollDice(QWidget *parent = nullptr);
[[nodiscard]] uint getDieSideCount() const;
[[nodiscard]] uint getDiceToRollCount() const;
};
#endif // DLG_ROLL_DICE_H

View File

@@ -3,7 +3,6 @@
#include "carddatabase.h"
#include "gettextwithmax.h"
#include "main.h"
#include "pictureloader.h"
#include "releasechannel.h"
#include "sequenceEdit/sequenceedit.h"
#include "settingscache.h"
@@ -18,6 +17,7 @@
#include <QComboBox>
#include <QDebug>
#include <QDesktopServices>
#include <QDesktopWidget>
#include <QDialogButtonBox>
#include <QFileDialog>
#include <QGridLayout>
@@ -44,22 +44,18 @@
GeneralSettingsPage::GeneralSettingsPage()
{
QStringList languageCodes = findQmFiles();
for (const QString &code : languageCodes) {
QString langName = languageName(code);
languageBox.addItem(langName, code);
}
QString setLanguage = QCoreApplication::translate("i18n", DEFAULT_LANG_NAME);
int index = languageBox.findText(setLanguage, Qt::MatchExactly);
if (index == -1) {
qWarning() << "could not find language" << setLanguage;
} else {
languageBox.setCurrentIndex(index);
SettingsCache &settings = SettingsCache::instance();
QString setLanguage = settings.getLang();
QStringList qmFiles = findQmFiles();
for (int i = 0; i < qmFiles.size(); i++) {
QString langName = languageName(qmFiles[i]);
languageBox.addItem(langName, qmFiles[i]);
if ((qmFiles[i] == setLanguage) ||
(setLanguage.isEmpty() && langName == QCoreApplication::translate("i18n", DEFAULT_LANG_NAME)))
languageBox.setCurrentIndex(i);
}
// updates
SettingsCache &settings = SettingsCache::instance();
QList<ReleaseChannel *> channels = settings.getUpdateReleaseChannels();
foreach (ReleaseChannel *chan, channels) {
updateReleaseChannelBox.insertItem(chan->getIndex(), tr(chan->getName().toUtf8()));
@@ -69,9 +65,18 @@ GeneralSettingsPage::GeneralSettingsPage()
updateNotificationCheckBox.setChecked(settings.getNotifyAboutUpdates());
newVersionOracleCheckBox.setChecked(settings.getNotifyAboutNewVersion());
// pixmap cache
pixmapCacheEdit.setMinimum(PIXMAPCACHE_SIZE_MIN);
// 2047 is the max value to avoid overflowing of QPixmapCache::setCacheLimit(int size)
pixmapCacheEdit.setMaximum(PIXMAPCACHE_SIZE_MAX);
pixmapCacheEdit.setSingleStep(64);
pixmapCacheEdit.setValue(settings.getPixmapCacheSize());
pixmapCacheEdit.setSuffix(" MB");
showTipsOnStartup.setChecked(settings.getShowTipsOnStartup());
connect(&languageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(languageBoxChanged(int)));
connect(&pixmapCacheEdit, SIGNAL(valueChanged(int)), &settings, SLOT(setPixmapCacheSize(int)));
connect(&updateReleaseChannelBox, SIGNAL(currentIndexChanged(int)), &settings, SLOT(setUpdateReleaseChannel(int)));
connect(&updateNotificationCheckBox, SIGNAL(stateChanged(int)), &settings, SLOT(setNotifyAboutUpdate(int)));
connect(&newVersionOracleCheckBox, SIGNAL(stateChanged(int)), &settings, SLOT(setNotifyAboutNewVersion(int)));
@@ -82,6 +87,8 @@ GeneralSettingsPage::GeneralSettingsPage()
personalGrid->addWidget(&languageBox, 0, 1);
personalGrid->addWidget(&updateReleaseChannelLabel, 1, 0);
personalGrid->addWidget(&updateReleaseChannelBox, 1, 1);
personalGrid->addWidget(&pixmapCacheLabel, 2, 0);
personalGrid->addWidget(&pixmapCacheEdit, 2, 1);
personalGrid->addWidget(&updateNotificationCheckBox, 3, 0, 1, 2);
personalGrid->addWidget(&newVersionOracleCheckBox, 4, 0, 1, 2);
personalGrid->addWidget(&showTipsOnStartup, 5, 0, 1, 2);
@@ -179,21 +186,19 @@ QStringList GeneralSettingsPage::findQmFiles()
{
QDir dir(translationPath);
QStringList fileNames = dir.entryList(QStringList(translationPrefix + "_*.qm"), QDir::Files, QDir::Name);
fileNames.replaceInStrings(QRegularExpression(translationPrefix + "_(.*)\\.qm"), "\\1");
fileNames.replaceInStrings(QRegExp(translationPrefix + "_(.*)\\.qm"), "\\1");
return fileNames;
}
QString GeneralSettingsPage::languageName(const QString &lang)
QString GeneralSettingsPage::languageName(const QString &qmFile)
{
QTranslator qTranslator;
if (qmFile == DEFAULT_LANG_CODE)
return DEFAULT_LANG_NAME;
QString appNameHint = translationPrefix + "_" + lang;
bool appTranslationLoaded = qTranslator.load(appNameHint, translationPath);
if (!appTranslationLoaded) {
qDebug() << "Unable to load" << translationPrefix << "translation" << appNameHint << "at" << translationPath;
}
QTranslator translator;
translator.load(translationPrefix + "_" + qmFile + ".qm", translationPath);
return qTranslator.translate("i18n", DEFAULT_LANG_NAME);
return translator.translate("i18n", DEFAULT_LANG_NAME);
}
void GeneralSettingsPage::deckPathButtonClicked()
@@ -291,6 +296,7 @@ void GeneralSettingsPage::retranslateUi()
cardDatabasePathLabel.setText(tr("Card database:"));
customCardDatabasePathLabel.setText(tr("Custom database directory:"));
tokenDatabasePathLabel.setText(tr("Token database:"));
pixmapCacheLabel.setText(tr("Picture cache size:"));
updateReleaseChannelLabel.setText(tr("Update channel"));
updateNotificationCheckBox.setText(tr("Notify if a feature supported by the server is missing in my client"));
newVersionOracleCheckBox.setText(tr("Automatically run Oracle when running a new version of Cockatrice"));
@@ -299,7 +305,6 @@ void GeneralSettingsPage::retranslateUi()
AppearanceSettingsPage::AppearanceSettingsPage()
{
SettingsCache &settings = SettingsCache::instance();
QString themeName = SettingsCache::instance().getThemeName();
QStringList themeDirs = themeManager->getAvailableThemes().keys();
@@ -320,31 +325,27 @@ AppearanceSettingsPage::AppearanceSettingsPage()
themeGroupBox = new QGroupBox;
themeGroupBox->setLayout(themeGrid);
displayCardNamesCheckBox.setChecked(settings.getDisplayCardNames());
connect(&displayCardNamesCheckBox, SIGNAL(stateChanged(int)), &settings, SLOT(setDisplayCardNames(int)));
displayCardNamesCheckBox.setChecked(SettingsCache::instance().getDisplayCardNames());
connect(&displayCardNamesCheckBox, SIGNAL(stateChanged(int)), &SettingsCache::instance(),
SLOT(setDisplayCardNames(int)));
cardScalingCheckBox.setChecked(settings.getScaleCards());
connect(&cardScalingCheckBox, SIGNAL(stateChanged(int)), &settings, SLOT(setCardScaling(int)));
verticalCardOverlapPercentBox.setValue(settings.getStackCardOverlapPercent());
verticalCardOverlapPercentBox.setRange(0, 80);
connect(&verticalCardOverlapPercentBox, SIGNAL(valueChanged(int)), &settings,
SLOT(setStackCardOverlapPercent(int)));
cardScalingCheckBox.setChecked(SettingsCache::instance().getScaleCards());
connect(&cardScalingCheckBox, SIGNAL(stateChanged(int)), &SettingsCache::instance(), SLOT(setCardScaling(int)));
auto *cardsGrid = new QGridLayout;
cardsGrid->addWidget(&displayCardNamesCheckBox, 0, 0, 1, 2);
cardsGrid->addWidget(&cardScalingCheckBox, 1, 0, 1, 2);
cardsGrid->addWidget(&verticalCardOverlapPercentLabel, 2, 0, 1, 1);
cardsGrid->addWidget(&verticalCardOverlapPercentBox, 2, 1, 1, 1);
cardsGroupBox = new QGroupBox;
cardsGroupBox->setLayout(cardsGrid);
horizontalHandCheckBox.setChecked(settings.getHorizontalHand());
connect(&horizontalHandCheckBox, SIGNAL(stateChanged(int)), &settings, SLOT(setHorizontalHand(int)));
horizontalHandCheckBox.setChecked(SettingsCache::instance().getHorizontalHand());
connect(&horizontalHandCheckBox, SIGNAL(stateChanged(int)), &SettingsCache::instance(),
SLOT(setHorizontalHand(int)));
leftJustifiedHandCheckBox.setChecked(settings.getLeftJustified());
connect(&leftJustifiedHandCheckBox, SIGNAL(stateChanged(int)), &settings, SLOT(setLeftJustified(int)));
leftJustifiedHandCheckBox.setChecked(SettingsCache::instance().getLeftJustified());
connect(&leftJustifiedHandCheckBox, SIGNAL(stateChanged(int)), &SettingsCache::instance(),
SLOT(setLeftJustified(int)));
auto *handGrid = new QGridLayout;
handGrid->addWidget(&horizontalHandCheckBox, 0, 0, 1, 2);
@@ -353,18 +354,18 @@ AppearanceSettingsPage::AppearanceSettingsPage()
handGroupBox = new QGroupBox;
handGroupBox->setLayout(handGrid);
invertVerticalCoordinateCheckBox.setChecked(settings.getInvertVerticalCoordinate());
connect(&invertVerticalCoordinateCheckBox, SIGNAL(stateChanged(int)), &settings,
invertVerticalCoordinateCheckBox.setChecked(SettingsCache::instance().getInvertVerticalCoordinate());
connect(&invertVerticalCoordinateCheckBox, SIGNAL(stateChanged(int)), &SettingsCache::instance(),
SLOT(setInvertVerticalCoordinate(int)));
minPlayersForMultiColumnLayoutEdit.setMinimum(2);
minPlayersForMultiColumnLayoutEdit.setValue(settings.getMinPlayersForMultiColumnLayout());
connect(&minPlayersForMultiColumnLayoutEdit, SIGNAL(valueChanged(int)), &settings,
minPlayersForMultiColumnLayoutEdit.setValue(SettingsCache::instance().getMinPlayersForMultiColumnLayout());
connect(&minPlayersForMultiColumnLayoutEdit, SIGNAL(valueChanged(int)), &SettingsCache::instance(),
SLOT(setMinPlayersForMultiColumnLayout(int)));
minPlayersForMultiColumnLayoutLabel.setBuddy(&minPlayersForMultiColumnLayoutEdit);
connect(&maxFontSizeForCardsEdit, SIGNAL(valueChanged(int)), &settings, SLOT(setMaxFontSize(int)));
maxFontSizeForCardsEdit.setValue(settings.getMaxFontSize());
connect(&maxFontSizeForCardsEdit, SIGNAL(valueChanged(int)), &SettingsCache::instance(), SLOT(setMaxFontSize(int)));
maxFontSizeForCardsEdit.setValue(SettingsCache::instance().getMaxFontSize());
maxFontSizeForCardsLabel.setBuddy(&maxFontSizeForCardsEdit);
maxFontSizeForCardsEdit.setMinimum(9);
maxFontSizeForCardsEdit.setMaximum(100);
@@ -418,11 +419,9 @@ void AppearanceSettingsPage::retranslateUi()
cardsGroupBox->setTitle(tr("Card rendering"));
displayCardNamesCheckBox.setText(tr("Display card names on cards having a picture"));
cardScalingCheckBox.setText(tr("Scale cards on mouse over"));
verticalCardOverlapPercentLabel.setText(
tr("Minimum overlap percentage of cards on the stack and in vertical hand"));
handGroupBox->setTitle(tr("Hand layout"));
horizontalHandCheckBox.setText(tr("Display hand horizontally (wastes space)"));
horizontalHandCheckBox.setText(tr("Display hand horizontally (requires more space)"));
leftJustifiedHandCheckBox.setText(tr("Enable left justification"));
tableGroupBox->setTitle(tr("Table grid layout"));
@@ -587,38 +586,12 @@ DeckEditorSettingsPage::DeckEditorSettingsPage()
messageListLayout->addWidget(messageToolBar);
messageListLayout->addWidget(urlList);
// pixmap cache
pixmapCacheEdit.setMinimum(PIXMAPCACHE_SIZE_MIN);
// 2047 is the max value to avoid overflowing of QPixmapCache::setCacheLimit(int size)
pixmapCacheEdit.setMaximum(PIXMAPCACHE_SIZE_MAX);
pixmapCacheEdit.setSingleStep(64);
pixmapCacheEdit.setValue(SettingsCache::instance().getPixmapCacheSize());
pixmapCacheEdit.setSuffix(" MB");
networkCacheEdit.setMinimum(NETWORK_CACHE_SIZE_MIN);
networkCacheEdit.setMaximum(NETWORK_CACHE_SIZE_MAX);
networkCacheEdit.setSingleStep(1);
networkCacheEdit.setValue(SettingsCache::instance().getNetworkCacheSizeInMB());
networkCacheEdit.setSuffix(" MB");
auto networkCacheLayout = new QHBoxLayout;
networkCacheLayout->addStretch();
networkCacheLayout->addWidget(&networkCacheLabel);
networkCacheLayout->addWidget(&networkCacheEdit);
auto pixmapCacheLayout = new QHBoxLayout;
pixmapCacheLayout->addStretch();
pixmapCacheLayout->addWidget(&pixmapCacheLabel);
pixmapCacheLayout->addWidget(&pixmapCacheEdit);
// Top Layout
lpGeneralGrid->addWidget(&picDownloadCheckBox, 0, 0);
lpGeneralGrid->addWidget(&resetDownloadURLs, 0, 1);
lpGeneralGrid->addLayout(messageListLayout, 1, 0, 1, 2);
lpGeneralGrid->addLayout(networkCacheLayout, 2, 0, 1, 2);
lpGeneralGrid->addLayout(pixmapCacheLayout, 3, 0, 1, 2);
lpGeneralGrid->addWidget(&urlLinkLabel, 4, 0);
lpGeneralGrid->addWidget(&clearDownloadedPicsButton, 4, 1);
lpGeneralGrid->addWidget(&urlLinkLabel, 2, 0);
lpGeneralGrid->addWidget(&clearDownloadedPicsButton, 2, 1);
// Spoiler Layout
lpSpoilerGrid->addWidget(&mcDownloadSpoilersCheckBox, 0, 0);
@@ -633,9 +606,6 @@ DeckEditorSettingsPage::DeckEditorSettingsPage()
connect(&mcDownloadSpoilersCheckBox, SIGNAL(toggled(bool)), &SettingsCache::instance(),
SLOT(setDownloadSpoilerStatus(bool)));
connect(&mcDownloadSpoilersCheckBox, SIGNAL(toggled(bool)), this, SLOT(setSpoilersEnabled(bool)));
connect(&pixmapCacheEdit, SIGNAL(valueChanged(int)), &SettingsCache::instance(), SLOT(setPixmapCacheSize(int)));
connect(&networkCacheEdit, SIGNAL(valueChanged(int)), &SettingsCache::instance(),
SLOT(setNetworkCacheSizeInMB(int)));
mpGeneralGroupBox = new QGroupBox;
mpGeneralGroupBox->setLayout(lpGeneralGrid);
@@ -660,11 +630,6 @@ void DeckEditorSettingsPage::resetDownloadedURLsButtonClicked()
void DeckEditorSettingsPage::clearDownloadedPicsButtonClicked()
{
PictureLoader::clearNetworkCache();
// These are not used anymore, but we don't delete them automatically, so
// we should do it here lest we leave pictures hanging around on users'
// machines.
QString picsPath = SettingsCache::instance().getPicsPath() + "/downloadedPics/";
QStringList dirs = QDir(picsPath).entryList(QDir::AllDirs | QDir::NoDotAndDotDot);
bool outerSuccessRemove = true;
@@ -692,7 +657,6 @@ void DeckEditorSettingsPage::clearDownloadedPicsButtonClicked()
}
if (outerSuccessRemove) {
QMessageBox::information(this, tr("Success"), tr("Downloaded card pictures have been reset."));
QDir(SettingsCache::instance().getPicsPath()).rmdir("downloadedPics");
} else {
QMessageBox::critical(this, tr("Error"), tr("One or more downloaded card pictures could not be cleared."));
}
@@ -816,10 +780,6 @@ void DeckEditorSettingsPage::retranslateUi()
urlLinkLabel.setText(QString("<a href='%1'>%2</a>").arg(WIKI_CUSTOM_PIC_URL).arg(tr("How to add a custom URL")));
clearDownloadedPicsButton.setText(tr("Delete Downloaded Images"));
resetDownloadURLs.setText(tr("Reset Download URLs"));
networkCacheLabel.setText(tr("Downloaded images directory size:"));
networkCacheEdit.setToolTip(tr("On-disk cache for downloaded pictures"));
pixmapCacheLabel.setText(tr("Picture cache size:"));
pixmapCacheEdit.setToolTip(tr("In-memory cache for pictures not currently on screen"));
}
MessagesSettingsPage::MessagesSettingsPage()
@@ -831,9 +791,6 @@ MessagesSettingsPage::MessagesSettingsPage()
connect(&chatMentionCompleterCheckbox, SIGNAL(stateChanged(int)), &SettingsCache::instance(),
SLOT(setChatMentionCompleter(int)));
explainMessagesLabel.setTextInteractionFlags(Qt::LinksAccessibleByMouse);
explainMessagesLabel.setOpenExternalLinks(true);
ignoreUnregUsersMainChat.setChecked(SettingsCache::instance().getIgnoreUnregisteredUsers());
ignoreUnregUserMessages.setChecked(SettingsCache::instance().getIgnoreUnregisteredUserMessages());
connect(&ignoreUnregUsersMainChat, SIGNAL(stateChanged(int)), &SettingsCache::instance(),
@@ -848,6 +805,7 @@ MessagesSettingsPage::MessagesSettingsPage()
connect(&invertHighlightForeground, SIGNAL(stateChanged(int)), this, SLOT(updateTextHighlightColor(int)));
mentionColor = new QLineEdit();
mentionColor->setPlaceholderText(tr("Enter HEX code"));
mentionColor->setText(SettingsCache::instance().getChatMentionColor());
updateMentionPreview();
connect(mentionColor, SIGNAL(textChanged(QString)), this, SLOT(updateColor(QString)));
@@ -869,29 +827,36 @@ MessagesSettingsPage::MessagesSettingsPage()
auto *chatGrid = new QGridLayout;
chatGrid->addWidget(&chatMentionCheckBox, 0, 0);
chatGrid->addWidget(&invertMentionForeground, 0, 1);
chatGrid->addWidget(&mentionColorStringLabel, 0, 1, Qt::AlignRight);
chatGrid->addWidget(mentionColor, 0, 2);
chatGrid->addWidget(&chatMentionCompleterCheckbox, 1, 0);
chatGrid->addWidget(&ignoreUnregUsersMainChat, 2, 0);
chatGrid->addWidget(&hexLabel, 1, 2);
chatGrid->addWidget(&ignoreUnregUserMessages, 3, 0);
chatGrid->addWidget(&messagePopups, 4, 0);
chatGrid->addWidget(&mentionPopups, 5, 0);
chatGrid->addWidget(&roomHistory, 6, 0);
chatGrid->addWidget(&invertMentionForeground, 0, 3);
chatGrid->addWidget(&chatMentionCompleterCheckbox, 1, 0, 1, -1);
chatGrid->addWidget(&ignoreUnregUsersMainChat, 2, 0, 1, -1);
chatGrid->addWidget(&ignoreUnregUserMessages, 3, 0, 1, -1);
chatGrid->addWidget(&messagePopups, 4, 0, 1, -1);
chatGrid->addWidget(&mentionPopups, 5, 0, 1, -1);
chatGrid->addWidget(&roomHistory, 6, 0, 1, -1);
// Expand first column more than following ones
chatGrid->setColumnStretch(0, 3);
chatGrid->setColumnStretch(1, 1);
chatGroupBox = new QGroupBox;
chatGroupBox->setLayout(chatGrid);
highlightColor = new QLineEdit();
highlightColor->setPlaceholderText(tr("Enter HEX code"));
highlightColor->setText(SettingsCache::instance().getChatHighlightColor());
updateHighlightPreview();
connect(highlightColor, SIGNAL(textChanged(QString)), this, SLOT(updateHighlightColor(QString)));
auto *highlightNotice = new QGridLayout;
highlightNotice->addWidget(highlightColor, 0, 2);
highlightNotice->addWidget(&invertHighlightForeground, 0, 1);
highlightNotice->addWidget(&hexHighlightLabel, 1, 2);
highlightNotice->addWidget(customAlertString, 0, 0);
highlightNotice->addWidget(&customAlertStringLabel, 1, 0);
highlightNotice->addWidget(&highlightColorStringLabel, 0, 1, Qt::AlignRight);
highlightNotice->addWidget(highlightColor, 0, 2);
highlightNotice->addWidget(&invertHighlightForeground, 0, 3);
highlightNotice->addWidget(&customAlertStringLabel, 1, 0, 1, -1);
// Expand first column more than following ones
highlightNotice->setColumnStretch(0, 3);
highlightNotice->setColumnStretch(1, 1);
highlightGroupBox = new QGroupBox;
highlightGroupBox->setLayout(highlightNotice);
@@ -925,15 +890,12 @@ MessagesSettingsPage::MessagesSettingsPage()
messageListLayout->addWidget(messageToolBar);
messageListLayout->addWidget(messageList);
auto *messagesLayout = new QVBoxLayout; // combines the explainer label with the actual messages widget pieces
messagesLayout->addLayout(messageListLayout);
messagesLayout->addWidget(&explainMessagesLabel);
messageShortcuts = new QGroupBox;
messageShortcuts->setLayout(messageListLayout);
messageGroupBox = new QGroupBox; // draws a box around the above layout and allows it to be titled
messageGroupBox->setLayout(messagesLayout);
auto *mainLayout = new QVBoxLayout;
auto *mainLayout = new QVBoxLayout; // combines the messages groupbox with the rest of the menu
mainLayout->addWidget(messageGroupBox);
mainLayout->addWidget(messageShortcuts);
mainLayout->addWidget(chatGroupBox);
mainLayout->addWidget(highlightGroupBox);
@@ -944,12 +906,8 @@ MessagesSettingsPage::MessagesSettingsPage()
void MessagesSettingsPage::updateColor(const QString &value)
{
#if (QT_VERSION >= QT_VERSION_CHECK(6, 4, 0))
QColor colorToSet = QColor::fromString("#" + value);
#else
QColor colorToSet;
colorToSet.setNamedColor("#" + value);
#endif
if (colorToSet.isValid()) {
SettingsCache::instance().setChatMentionColor(value);
updateMentionPreview();
@@ -958,12 +916,8 @@ void MessagesSettingsPage::updateColor(const QString &value)
void MessagesSettingsPage::updateHighlightColor(const QString &value)
{
#if (QT_VERSION >= QT_VERSION_CHECK(6, 4, 0))
QColor colorToSet = QColor::fromString("#" + value);
#else
QColor colorToSet;
colorToSet.setNamedColor("#" + value);
#endif
if (colorToSet.isValid()) {
SettingsCache::instance().setChatHighlightColor(value);
updateHighlightPreview();
@@ -1042,18 +996,16 @@ void MessagesSettingsPage::retranslateUi()
highlightGroupBox->setTitle(tr("Custom alert words"));
chatMentionCheckBox.setText(tr("Enable chat mentions"));
chatMentionCompleterCheckbox.setText(tr("Enable mention completer"));
messageGroupBox->setTitle(tr("In-game message macros"));
explainMessagesLabel.setText(
QString("<a href='%1'>%2</a>").arg(WIKI_CUSTOM_SHORTCUTS).arg(tr("How to use in-game message macros")));
messageShortcuts->setTitle(tr("In-game message macros"));
ignoreUnregUsersMainChat.setText(tr("Ignore chat room messages sent by unregistered users"));
ignoreUnregUserMessages.setText(tr("Ignore private messages sent by unregistered users"));
invertMentionForeground.setText(tr("Invert text color"));
invertHighlightForeground.setText(tr("Invert text color"));
mentionColorStringLabel.setText(tr("Color"));
highlightColorStringLabel.setText(tr("Color"));
messagePopups.setText(tr("Enable desktop notifications for private messages"));
mentionPopups.setText(tr("Enable desktop notification for mentions"));
roomHistory.setText(tr("Enable room message history on join"));
hexLabel.setText(tr("(Color is hexadecimal)"));
hexHighlightLabel.setText(tr("(Color is hexadecimal)"));
customAlertStringLabel.setText(tr("Separate words with a space, alphanumeric characters only"));
}
@@ -1161,28 +1113,28 @@ ShortcutSettingsPage::ShortcutSettingsPage()
btnClearAll->setIcon(QPixmap("theme:icons/clearsearch"));
// layout
auto *_editLayout = new QGridLayout;
_editLayout->addWidget(currentActionGroupLabel, 0, 0);
_editLayout->addWidget(currentActionGroupName, 0, 1);
_editLayout->addWidget(currentActionLabel, 1, 0);
_editLayout->addWidget(currentActionName, 1, 1);
_editLayout->addWidget(currentShortcutLabel, 2, 0);
_editLayout->addWidget(editTextBox, 2, 1);
auto *editLayout = new QGridLayout;
editLayout->addWidget(currentActionGroupLabel, 0, 0);
editLayout->addWidget(currentActionGroupName, 0, 1);
editLayout->addWidget(currentActionLabel, 1, 0);
editLayout->addWidget(currentActionName, 1, 1);
editLayout->addWidget(currentShortcutLabel, 2, 0);
editLayout->addWidget(editTextBox, 2, 1);
editShortcutGroupBox = new QGroupBox;
editShortcutGroupBox->setLayout(_editLayout);
editShortcutGroupBox->setLayout(editLayout);
auto *_buttonsLayout = new QHBoxLayout;
_buttonsLayout->addWidget(faqLabel);
_buttonsLayout->addWidget(btnResetAll);
_buttonsLayout->addWidget(btnClearAll);
auto *buttonsLayout = new QHBoxLayout;
buttonsLayout->addWidget(faqLabel);
buttonsLayout->addWidget(btnResetAll);
buttonsLayout->addWidget(btnClearAll);
auto *_mainLayout = new QVBoxLayout;
_mainLayout->addWidget(shortcutsTable);
_mainLayout->addWidget(editShortcutGroupBox);
_mainLayout->addLayout(_buttonsLayout);
auto *mainLayout = new QVBoxLayout;
mainLayout->addWidget(shortcutsTable);
mainLayout->addWidget(editShortcutGroupBox);
mainLayout->addLayout(buttonsLayout);
setLayout(_mainLayout);
setLayout(mainLayout);
connect(btnResetAll, SIGNAL(clicked()), this, SLOT(resetShortcuts()));
connect(btnClearAll, SIGNAL(clicked()), this, SLOT(clearShortcuts()));
@@ -1288,13 +1240,17 @@ void ShortcutSettingsPage::retranslateUi()
currentShortcutLabel->setText(tr("Shortcut:"));
editTextBox->retranslateUi();
faqLabel->setText(QString("<a href='%1'>%2</a>").arg(WIKI_CUSTOM_SHORTCUTS).arg(tr("How to set custom shortcuts")));
btnResetAll->setText(tr("Restore all default shortcuts"));
btnClearAll->setText(tr("Clear all shortcuts"));
btnResetAll->setText("Restore all default shortcuts");
btnClearAll->setText("Clear all shortcuts");
}
DlgSettings::DlgSettings(QWidget *parent) : QDialog(parent)
{
auto rec = QGuiApplication::primaryScreen()->availableGeometry();
#if (QT_VERSION >= QT_VERSION_CHECK(5, 13, 0))
auto rec = qApp->primaryScreen()->availableGeometry();
#else
auto rec = QApplication::desktop()->availableGeometry();
#endif
this->setMinimumSize(qMin(700, rec.width()), qMin(700, rec.height()));
connect(&SettingsCache::instance(), SIGNAL(langChanged()), this, SLOT(updateLanguage()));

View File

@@ -49,7 +49,7 @@ private slots:
private:
QStringList findQmFiles();
QString languageName(const QString &lang);
QString languageName(const QString &qmFile);
QLineEdit *deckPathEdit;
QLineEdit *replaysPathEdit;
QLineEdit *picsPathEdit;
@@ -58,6 +58,7 @@ private:
QLineEdit *tokenDatabasePathEdit;
QPushButton *resetAllPathsButton;
QLabel *allPathsResetLabel;
QSpinBox pixmapCacheEdit;
QGroupBox *personalGroupBox;
QGroupBox *pathsGroupBox;
QComboBox languageBox;
@@ -65,6 +66,7 @@ private:
QCheckBox newVersionOracleCheckBox;
QComboBox updateReleaseChannelBox;
QLabel languageLabel;
QLabel pixmapCacheLabel;
QLabel deckPathLabel;
QLabel replaysPathLabel;
QLabel picsPathLabel;
@@ -90,8 +92,6 @@ private:
QLabel maxFontSizeForCardsLabel;
QCheckBox displayCardNamesCheckBox;
QCheckBox cardScalingCheckBox;
QLabel verticalCardOverlapPercentLabel;
QSpinBox verticalCardOverlapPercentBox;
QCheckBox horizontalHandCheckBox;
QCheckBox leftJustifiedHandCheckBox;
QCheckBox invertVerticalCoordinateCheckBox;
@@ -168,10 +168,6 @@ private:
QLabel infoOnSpoilersLabel;
QPushButton *mpSpoilerPathButton;
QPushButton *updateNowButton;
QLabel networkCacheLabel;
QSpinBox networkCacheEdit;
QSpinBox pixmapCacheEdit;
QLabel pixmapCacheLabel;
};
class MessagesSettingsPage : public AbstractSettingsPage
@@ -206,14 +202,13 @@ private:
QCheckBox roomHistory;
QGroupBox *chatGroupBox;
QGroupBox *highlightGroupBox;
QGroupBox *messageGroupBox;
QGroupBox *messageShortcuts;
QLineEdit *mentionColor;
QLineEdit *highlightColor;
QLineEdit *customAlertString;
QLabel hexLabel;
QLabel hexHighlightLabel;
QLabel customAlertStringLabel;
QLabel explainMessagesLabel;
QLabel mentionColorStringLabel;
QLabel highlightColorStringLabel;
void storeSettings();
void updateMentionPreview();

View File

@@ -154,7 +154,7 @@ void DlgTipOfTheDay::updateTip(int tipId)
imageLabel->setPixmap(image->scaled(w, h, Qt::KeepAspectRatio, Qt::SmoothTransformation));
}
date->setText("<i>Tip added on: " + tip.getDate().toString("yyyy-MM-dd") + "</i>");
date->setText("<i>Tip added on: " + tip.getDate().toString("yyyy.MM.dd") + "</i>");
tipNumber->setText("Tip " + QString::number(tipId + 1) + " / " + QString::number(tipDatabase->rowCount()));

Some files were not shown because too many files have changed in this diff Show More