Support Qt6, Min Qt5.8, Fix Win32, Fix Servatrice
Add lock around deleting arrows for commanding cards Add support for Qt6 w/ Backwards Qt5 Handle Qt5/6 cross compilation better Last cleanups caps matter Fix serv Prevent crash on 6.3.0 Linux & bump to 5.8 min Prevent out of bounds indexing Delete shutdown timer if it exists Fixup ticket comments, remove unneeded guards Try to add support for missing OSes Update .ci/release_template.md Update PR based on comments Update XML name after done and remove Hirsute Address local game crash Address comments from PR (again) Tests don't work on mac, will see if a problem on other OSes make soundengine more consistent across qt versions disable tests on distros that are covered by others Fix Oracle Crash due to bad memory access Update Oracle to use new Qt6 way of adding translations Add support for Qt5/Qt6 compiling of Cockatrice Remove unneeded calls to QtMath/cmath/math.h Update how we handle bitwise comparisons for enums with Tray Icon Change header guards to not duplicate function Leave comment & Fix Path for GHA Qt Update common/server.h Update cockatrice/src/window_main.cpp Rollback change on cmake module path for NSIS check docker image requirements add size limit to ccache put variables in quotes properly set build type on mac avoid names used in cmake fix up cmake module path cmake 3.10 does not recognize prepend Support Tests in FindQtRuntime set ccache size on non debug builds as well immediately return when removing non existing client handle incTxBytes with a signal instead don't set common link libraries in cockatrice/CMakeLists.txt add comments set macos qt version to 6 Try upgrading XCode versions to latest they can be supported on Ensure Qt gets linked add tmate so i can see what's going on Qt6 points two directories further down than Qt5 with regard to the top lib path, so we need to account for this Establish Plugins directory for Qt6 Establish TLS plugins for Qt6 services Minor change for release channel network manager Let windows build in parallel cores Wrong symbols Qt6 patch up for signal add missing qt6 package on deb builds boolean expressions are hard negative indexes should go to the end Intentionally fail cache move size checks to individual zone types Hardcode libs needed for building on Windows, as the regex was annoying Update wording use the --parallel option in all builds clean up the .ci scripts some more tweak fedora build add os parameter to compile.sh I don't really like this but it seems the easiest way I'd prefer if these types of quirks would live in the main configuration file, the yml fixup yml readd appended cache key to vcpkg step fix windows 32 quirk the json hash is already added to the key as well remove os parameter and clean up ci files set name_build.sh to output relative paths set backwards compatible version of xcode and qt on mac set QTDIR for mac builds on qt5 has no effect for qt6 export BUILD_DIR to name_build.sh merge mac build steps merge homebrew steps, set package suffix link qt5 remove brew link set qtdir to qt5 only compile.sh vars need to be empty not 0 fix sets manager search bar on qt 5.12/15 fix oracle subprocess errors being ignored on qt 5 clean up translation loading move en@source translation file so it will not get included in packages NOTE: this needs to be done at transifex as well! Use generator platform over osname Short circuit if not Win defined
This commit is contained in:
parent
accd5e4df7
commit
b02adccf87
114 changed files with 1925 additions and 1603 deletions
|
@ -19,6 +19,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
qt5-default \
|
qt5-default \
|
||||||
qtbase5-dev \
|
qtbase5-dev \
|
||||||
qtmultimedia5-dev \
|
qtmultimedia5-dev \
|
||||||
|
qttools5-dev \
|
||||||
qttools5-dev-tools \
|
qttools5-dev-tools \
|
||||||
&& apt-get clean \
|
&& apt-get clean \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
14
.ci/Fedora36/Dockerfile
Normal file
14
.ci/Fedora36/Dockerfile
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
FROM fedora:36
|
||||||
|
|
||||||
|
RUN dnf install -y \
|
||||||
|
ccache \
|
||||||
|
cmake \
|
||||||
|
gcc-c++ \
|
||||||
|
git \
|
||||||
|
mariadb-devel \
|
||||||
|
protobuf-devel \
|
||||||
|
qt6-{qttools,qtsvg,qtmultimedia,qtwebsockets,qt5compat}-devel \
|
||||||
|
rpm-build \
|
||||||
|
xz-devel \
|
||||||
|
zlib-devel \
|
||||||
|
&& dnf clean all
|
|
@ -1,4 +1,4 @@
|
||||||
FROM ubuntu:hirsute
|
FROM ubuntu:jammy
|
||||||
|
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||||
|
@ -9,16 +9,19 @@ RUN apt-get update && \
|
||||||
file \
|
file \
|
||||||
g++ \
|
g++ \
|
||||||
git \
|
git \
|
||||||
|
libgl-dev \
|
||||||
liblzma-dev \
|
liblzma-dev \
|
||||||
libmariadb-dev-compat \
|
libmariadb-dev-compat \
|
||||||
libprotobuf-dev \
|
libprotobuf-dev \
|
||||||
libqt5multimedia5-plugins \
|
libqt6core5compat6-dev \
|
||||||
libqt5sql5-mysql \
|
libqt6multimedia6 \
|
||||||
libqt5svg5-dev \
|
libqt6sql6-mysql \
|
||||||
libqt5websockets5-dev \
|
libqt6svg6-dev \
|
||||||
|
libqt6websockets6-dev \
|
||||||
protobuf-compiler \
|
protobuf-compiler \
|
||||||
qtmultimedia5-dev \
|
qt6-l10n-tools \
|
||||||
qttools5-dev \
|
qt6-multimedia-dev \
|
||||||
qttools5-dev-tools \
|
qt6-tools-dev \
|
||||||
|
qt6-tools-dev-tools \
|
||||||
&& apt-get clean \
|
&& apt-get clean \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
|
@ -3,18 +3,18 @@
|
||||||
# This script is to be used by the ci environment from the project root directory, do not use it from somewhere else.
|
# 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
|
# Compiles cockatrice inside of a ci environment
|
||||||
# --format runs the clang-format script first
|
|
||||||
# --install runs make install
|
# --install runs make install
|
||||||
# --package [<package type>] runs make package, optionally force the type
|
# --package [<package type>] runs make package, optionally force the type
|
||||||
# --suffix <suffix> renames package with this suffix, requires arg
|
# --suffix <suffix> renames package with this suffix, requires arg
|
||||||
# --server compiles servatrice
|
# --server compiles servatrice
|
||||||
# --test runs tests
|
# --test runs tests
|
||||||
# --debug or --release or <arg> sets the build type ie CMAKE_BUILD_TYPE
|
# --debug or --release sets the build type ie CMAKE_BUILD_TYPE
|
||||||
# --ccache uses ccache and shows stats
|
# --ccache [<size>] uses ccache and shows stats, optionally provide size
|
||||||
# --dir <dir> sets the name of the build dir, default is "build"
|
# --dir <dir> sets the name of the build dir, default is "build"
|
||||||
# uses env: BUILDTYPE CHECK_FORMAT MAKE_INSTALL MAKE_PACKAGE PACKAGE_TYPE PACKAGE_SUFFIX MAKE_SERVER MAKE_TEST USE_CCACHE BUILD_DIR (correspond to args: <buildtype>/--debug/--release --format --install --package <package type> --suffix <suffix> --server --test --ccache --dir <dir>)
|
# --parallel <core count> sets how many cores cmake should build with in parallel
|
||||||
|
# uses env: BUILDTYPE MAKE_INSTALL MAKE_PACKAGE PACKAGE_TYPE PACKAGE_SUFFIX MAKE_SERVER MAKE_TEST USE_CCACHE CCACHE_SIZE BUILD_DIR PARALLEL_COUNT
|
||||||
|
# (correspond to args: --debug/--release --install --package <package type> --suffix <suffix> --server --test --ccache <ccache_size> --dir <dir> --parallel <core_count>)
|
||||||
# exitcode: 1 for failure, 3 for invalid arguments
|
# exitcode: 1 for failure, 3 for invalid arguments
|
||||||
LINT_SCRIPT=".ci/lint_cpp.sh"
|
|
||||||
|
|
||||||
# Read arguments
|
# Read arguments
|
||||||
while [[ $# != 0 ]]; do
|
while [[ $# != 0 ]]; do
|
||||||
|
@ -22,10 +22,6 @@ while [[ $# != 0 ]]; do
|
||||||
'--')
|
'--')
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
'--format')
|
|
||||||
CHECK_FORMAT=1
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
'--install')
|
'--install')
|
||||||
MAKE_INSTALL=1
|
MAKE_INSTALL=1
|
||||||
shift
|
shift
|
||||||
|
@ -33,7 +29,7 @@ while [[ $# != 0 ]]; do
|
||||||
'--package')
|
'--package')
|
||||||
MAKE_PACKAGE=1
|
MAKE_PACKAGE=1
|
||||||
shift
|
shift
|
||||||
if [[ $# != 0 && $1 != -* ]]; then
|
if [[ $# != 0 && ${1:0:1} != - ]]; then
|
||||||
PACKAGE_TYPE="$1"
|
PACKAGE_TYPE="$1"
|
||||||
shift
|
shift
|
||||||
fi
|
fi
|
||||||
|
@ -66,6 +62,10 @@ while [[ $# != 0 ]]; do
|
||||||
'--ccache')
|
'--ccache')
|
||||||
USE_CCACHE=1
|
USE_CCACHE=1
|
||||||
shift
|
shift
|
||||||
|
if [[ $# != 0 && ${1:0:1} != - ]]; then
|
||||||
|
CCACHE_SIZE="$1"
|
||||||
|
shift
|
||||||
|
fi
|
||||||
;;
|
;;
|
||||||
'--dir')
|
'--dir')
|
||||||
shift
|
shift
|
||||||
|
@ -76,67 +76,81 @@ while [[ $# != 0 ]]; do
|
||||||
BUILD_DIR="$1"
|
BUILD_DIR="$1"
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
*)
|
'--parallel')
|
||||||
if [[ $1 == -* ]]; then
|
shift
|
||||||
echo "::error file=$0::unrecognized option: $1"
|
if [[ $# == 0 ]]; then
|
||||||
|
echo "::error file=$0::--parallel expects an argument"
|
||||||
exit 3
|
exit 3
|
||||||
fi
|
fi
|
||||||
BUILDTYPE="$1"
|
PARALLEL_COUNT="$1"
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
|
*)
|
||||||
|
echo "::error file=$0::unrecognized option: $1"
|
||||||
|
exit 3
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
# Check formatting using clang-format
|
|
||||||
if [[ $CHECK_FORMAT ]]; then
|
|
||||||
echo "::group::Run linter"
|
|
||||||
source "$LINT_SCRIPT"
|
|
||||||
echo "::endgroup::"
|
|
||||||
fi
|
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
# Setup
|
# Setup
|
||||||
./servatrice/check_schema_version.sh
|
./servatrice/check_schema_version.sh
|
||||||
|
if [[ ! $BUILDTYPE ]]; then
|
||||||
|
BUILDTYPE=Release
|
||||||
|
fi
|
||||||
if [[ ! $BUILD_DIR ]]; then
|
if [[ ! $BUILD_DIR ]]; then
|
||||||
BUILD_DIR="build"
|
BUILD_DIR="build"
|
||||||
fi
|
fi
|
||||||
mkdir -p "$BUILD_DIR"
|
mkdir -p "$BUILD_DIR"
|
||||||
cd "$BUILD_DIR"
|
cd "$BUILD_DIR"
|
||||||
|
|
||||||
if [[ ! $CMAKE_BUILD_PARALLEL_LEVEL ]]; then
|
|
||||||
CMAKE_BUILD_PARALLEL_LEVEL=2 # default machines have 2 cores
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Add cmake flags
|
# Add cmake flags
|
||||||
flags=()
|
flags=("-DCMAKE_BUILD_TYPE=$BUILDTYPE")
|
||||||
if [[ $MAKE_SERVER ]]; then
|
if [[ $MAKE_SERVER ]]; then
|
||||||
flags+=("-DWITH_SERVER=1")
|
flags+=("-DWITH_SERVER=1")
|
||||||
fi
|
fi
|
||||||
if [[ $MAKE_TEST ]]; then
|
if [[ $MAKE_TEST ]]; then
|
||||||
flags+=("-DTEST=1")
|
flags+=("-DTEST=1")
|
||||||
fi
|
fi
|
||||||
if [[ ! $BUILDTYPE ]]; then
|
if [[ $USE_CCACHE ]]; then
|
||||||
BUILDTYPE=Release
|
flags+=("-DUSE_CCACHE=1")
|
||||||
|
if [[ $CCACHE_SIZE ]]; then
|
||||||
|
# note, this setting persists after running the script
|
||||||
|
ccache --max-size "$CCACHE_SIZE"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
flags+=("-DCMAKE_BUILD_TYPE=$BUILDTYPE")
|
|
||||||
if [[ $PACKAGE_TYPE ]]; then
|
if [[ $PACKAGE_TYPE ]]; then
|
||||||
flags+=("-DCPACK_GENERATOR=$PACKAGE_TYPE")
|
flags+=("-DCPACK_GENERATOR=$PACKAGE_TYPE")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ $(uname) == "Darwin" ]]; then
|
# Add cmake --build flags
|
||||||
if [[ $USE_CCACHE ]]; then
|
buildflags=(--config "$BUILDTYPE")
|
||||||
# prepend ccache compiler binaries to path
|
if [[ $PARALLEL_COUNT ]]; then
|
||||||
PATH="/usr/local/opt/ccache/libexec:$PATH"
|
if [[ $(cmake --build /not_a_dir --parallel |& head -1) =~ parallel ]]; then
|
||||||
|
# workaround for bionic having an old cmake
|
||||||
|
echo "this version of cmake does not support --parallel, using native build tool -j instead"
|
||||||
|
buildflags+=(-- -j "$PARALLEL_COUNT")
|
||||||
|
# note, no normal build flags should be added after this
|
||||||
|
else
|
||||||
|
buildflags+=(--parallel "$PARALLEL_COUNT")
|
||||||
fi
|
fi
|
||||||
# Add qt install location when using homebrew
|
|
||||||
flags+=("-DCMAKE_PREFIX_PATH=/usr/local/opt/qt5/")
|
|
||||||
fi
|
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
|
# Compile
|
||||||
if [[ $USE_CCACHE ]]; then
|
if [[ $USE_CCACHE ]]; then
|
||||||
echo "::group::Show ccache stats"
|
echo "::group::Show ccache stats"
|
||||||
ccache --show-stats
|
ccachestatsverbose
|
||||||
echo "::endgroup::"
|
echo "::endgroup::"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -146,12 +160,12 @@ cmake .. "${flags[@]}"
|
||||||
echo "::endgroup::"
|
echo "::endgroup::"
|
||||||
|
|
||||||
echo "::group::Build project"
|
echo "::group::Build project"
|
||||||
cmake --build . --config "$BUILDTYPE"
|
cmake --build . "${buildflags[@]}"
|
||||||
echo "::endgroup::"
|
echo "::endgroup::"
|
||||||
|
|
||||||
if [[ $USE_CCACHE ]]; then
|
if [[ $USE_CCACHE ]]; then
|
||||||
echo "::group::Show ccache stats again"
|
echo "::group::Show ccache stats again"
|
||||||
ccache --show-stats
|
ccachestatsverbose
|
||||||
echo "::endgroup::"
|
echo "::endgroup::"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -174,7 +188,8 @@ if [[ $MAKE_PACKAGE ]]; then
|
||||||
|
|
||||||
if [[ $PACKAGE_SUFFIX ]]; then
|
if [[ $PACKAGE_SUFFIX ]]; then
|
||||||
echo "::group::Update package name"
|
echo "::group::Update package name"
|
||||||
../.ci/name_build.sh "$PACKAGE_SUFFIX"
|
cd ..
|
||||||
|
BUILD_DIR="$BUILD_DIR" .ci/name_build.sh "$PACKAGE_SUFFIX"
|
||||||
echo "::endgroup::"
|
echo "::endgroup::"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -10,7 +10,8 @@
|
||||||
# --interactive immediately starts the image interactively for debugging
|
# --interactive immediately starts the image interactively for debugging
|
||||||
# --set-cache <location> sets the location to cache the image or for ccache
|
# --set-cache <location> sets the location to cache the image or for ccache
|
||||||
# requires: docker
|
# 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 INTERACTIVE
|
||||||
|
# (correspond to args: <name> --set-cache <cache> --build --get --save --interactive)
|
||||||
# sets env: RUN CCACHE_DIR IMAGE_NAME RUN_ARGS RUN_OPTS BUILD_SCRIPT
|
# 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
|
# exitcode: 1 for failure, 2 for missing dockerfile, 3 for invalid arguments
|
||||||
export BUILD_SCRIPT=".ci/compile.sh"
|
export BUILD_SCRIPT=".ci/compile.sh"
|
||||||
|
@ -48,7 +49,7 @@ while [[ $# != 0 ]]; do
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
if [[ $1 == -* ]]; then
|
if [[ ${1:0:1} == - ]]; then
|
||||||
echo "unrecognized option: $1"
|
echo "unrecognized option: $1"
|
||||||
return 3
|
return 3
|
||||||
fi
|
fi
|
||||||
|
@ -74,26 +75,27 @@ fi
|
||||||
|
|
||||||
if ! [[ $CACHE ]]; then
|
if ! [[ $CACHE ]]; then
|
||||||
echo "cache dir is not set!" >&2
|
echo "cache dir is not set!" >&2
|
||||||
else
|
CACHE="$(mktemp -d)"
|
||||||
if ! [[ -d $CACHE ]]; then
|
echo "set cache dir to $CACHE" >&2
|
||||||
echo "could not find cache dir: $CACHE" >&2
|
fi
|
||||||
mkdir -p "$CACHE"
|
if ! [[ -d $CACHE ]]; then
|
||||||
unset GET # the dir is empty
|
echo "could not find cache dir: $CACHE" >&2
|
||||||
fi
|
mkdir -p "$CACHE"
|
||||||
if [[ $GET || $SAVE ]]; then
|
unset GET # the dir is empty
|
||||||
img_dir="$CACHE/$image_cache"
|
fi
|
||||||
img_save="$img_dir/$IMAGE_NAME$save_extension"
|
if [[ $GET || $SAVE ]]; then
|
||||||
if ! [[ -d $img_dir ]]; then
|
img_dir="$CACHE/$image_cache"
|
||||||
echo "could not find image dir: $img_dir" >&2
|
img_save="$img_dir/$IMAGE_NAME$save_extension"
|
||||||
mkdir -p "$img_dir"
|
if ! [[ -d $img_dir ]]; then
|
||||||
fi
|
echo "could not find image dir: $img_dir" >&2
|
||||||
fi
|
mkdir -p "$img_dir"
|
||||||
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
|
||||||
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
|
# Get the docker image from previously stored save
|
||||||
if [[ $GET ]]; then
|
if [[ $GET ]]; then
|
||||||
|
@ -138,7 +140,7 @@ fi
|
||||||
function RUN ()
|
function RUN ()
|
||||||
{
|
{
|
||||||
echo "running image:"
|
echo "running image:"
|
||||||
if docker images | grep "$IMAGE_NAME"; then
|
if [[ $(docker images) =~ "$IMAGE_NAME" ]]; then
|
||||||
local args=(--mount "type=bind,source=$PWD,target=/src")
|
local args=(--mount "type=bind,source=$PWD,target=/src")
|
||||||
args+=(--workdir "/src")
|
args+=(--workdir "/src")
|
||||||
args+=(--user "$(id -u):$(id -g)")
|
args+=(--user "$(id -u):$(id -g)")
|
||||||
|
|
35
.ci/download_openssl.sh
Normal file
35
.ci/download_openssl.sh
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Read arguments
|
||||||
|
while [[ $# != 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
'--')
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
'--arch')
|
||||||
|
shift
|
||||||
|
if [[ $# == 0 ]]; then
|
||||||
|
echo "::error file=$0::--arch expects an argument"
|
||||||
|
exit 3
|
||||||
|
fi
|
||||||
|
OS_ARCH="$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "::error file=$0::unrecognized option: $1"
|
||||||
|
exit 3
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
OPEN_SSL_VERSION="1.1.1n"
|
||||||
|
DEST_PATH="C:\OpenSSL-Win$OS_ARCH"
|
||||||
|
|
||||||
|
curl -JLSs "https://github.com/CristiFati/Prebuilt-Binaries/raw/master/OpenSSL/v1.1.1/OpenSSL-$OPEN_SSL_VERSION-Win-pc0$OS_ARCH.zip" -o OpenSSL.zip
|
||||||
|
unzip -q "OpenSSL.zip"
|
||||||
|
rm "OpenSSL.zip"
|
||||||
|
mv "OpenSSL\OpenSSL\\$OPEN_SSL_VERSION" "$DEST_PATH"
|
||||||
|
rm -r "OpenSSL"
|
||||||
|
echo "Installed OpenSSL v$OPEN_SSL_VERSION to $DEST_PATH"
|
|
@ -42,11 +42,11 @@ ${diff#*
|
||||||
|
|
||||||
Exiting...
|
Exiting...
|
||||||
EOM
|
EOM
|
||||||
exit 2
|
exit 2
|
||||||
;;
|
;;
|
||||||
|
|
||||||
0)
|
0)
|
||||||
cat <<EOM
|
cat <<EOM
|
||||||
|
|
||||||
***********************************************************
|
***********************************************************
|
||||||
*** ***
|
*** ***
|
||||||
|
@ -58,12 +58,12 @@ EOM
|
||||||
|
|
||||||
Exiting...
|
Exiting...
|
||||||
EOM
|
EOM
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
|
|
||||||
*)
|
*)
|
||||||
echo ""
|
echo ""
|
||||||
echo "Something went wrong in our formatting checks: clangify returned $err" >&2
|
echo "Something went wrong in our formatting checks: clangify returned $err" >&2
|
||||||
echo ""
|
echo ""
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
# renames the file to [original name][SUFFIX].[original extension]
|
# renames the file to [original name][SUFFIX].[original extension]
|
||||||
# where SUFFIX is either available in the environment or as the first arg
|
# where SUFFIX is either available in the environment or as the first arg
|
||||||
# if MAKE_ZIP is set instead a zip is made
|
# if MAKE_ZIP is set instead a zip is made
|
||||||
# expected to be run in the build directory
|
# expected to be run in the build directory unless BUILD_DIR is set
|
||||||
builddir="."
|
builddir="${BUILD_DIR:=.}"
|
||||||
findrx="Cockatrice-*.*"
|
findrx="Cockatrice-*.*"
|
||||||
|
|
||||||
if [[ $1 ]]; then
|
if [[ $1 ]]; then
|
||||||
|
@ -27,6 +27,7 @@ if [[ ! $file ]]; then
|
||||||
echo "::error file=$0::could not find package"
|
echo "::error file=$0::could not find package"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
oldpwd="$PWD"
|
||||||
if ! cd "$path"; then
|
if ! cd "$path"; then
|
||||||
echo "::error file=$0::could not get file path"
|
echo "::error file=$0::could not get file path"
|
||||||
exit 1
|
exit 1
|
||||||
|
@ -45,6 +46,9 @@ else
|
||||||
echo "renaming '$file' to '$filename'"
|
echo "renaming '$file' to '$filename'"
|
||||||
mv "$file" "$filename"
|
mv "$file" "$filename"
|
||||||
fi
|
fi
|
||||||
ls -l "$PWD/$filename"
|
|
||||||
echo "::set-output name=path::$PWD/$filename"
|
cd "$oldpwd"
|
||||||
|
relative_path="$path/$filename"
|
||||||
|
ls -l "$relative_path"
|
||||||
|
echo "::set-output name=path::$relative_path"
|
||||||
echo "::set-output name=name::$filename"
|
echo "::set-output name=name::$filename"
|
||||||
|
|
|
@ -8,18 +8,20 @@ git push -d origin --REPLACE-WITH-BETA-LIST--
|
||||||
include different targets -->
|
include different targets -->
|
||||||
<pre>
|
<pre>
|
||||||
<b>Pre-compiled binaries we serve:</b>
|
<b>Pre-compiled binaries we serve:</b>
|
||||||
- <kbd>Windows 7/8/10 (32-bit)</kbd></i>
|
- <kbd>Windows 7/8/10/11 (32-bit)</kbd>
|
||||||
- <kbd>Windows 7/8/10 (64-bit)</kbd></i>
|
- <kbd>Windows 7/8/10/11 (64-bit)</kbd>
|
||||||
- <kbd>macOS 10.14</kbd> ("Mojave")</i>
|
- <kbd>macOS 10.14</kbd> ("Mojave")
|
||||||
- <kbd>macOS 10.15</kbd> ("Catalina")</i>
|
- <kbd>macOS 10.15</kbd> ("Catalina")
|
||||||
- <kbd>macOS 11.0</kbd> ("Big Sur")</i>
|
- <kbd>macOS 11.0</kbd> ("Big Sur")
|
||||||
- <kbd>Ubuntu 18.04</kbd> ("Bionic Beaver")</i>
|
- <kbd>Ubuntu 18.04</kbd> ("Bionic Beaver")
|
||||||
- <kbd>Ubuntu 20.04</kbd> ("Focal Fossa")</i>
|
- <kbd>Ubuntu 20.04</kbd> ("Focal Fossa")
|
||||||
- <kbd>Ubuntu 20.10</kbd> ("Groovy Gorilla")</i>
|
- <kbd>Ubuntu 21.10</kbd> ("Impish Indri")
|
||||||
- <kbd>Ubuntu 21.04</kbd> ("Hirsute Hippo")</i>
|
- <kbd>Ubuntu 22.04</kbd> ("Jammy Jellyfish")
|
||||||
- <kbd>Debian 10</kbd> ("Buster")</i>
|
- <kbd>Debian 10</kbd> ("Buster")
|
||||||
- <kbd>Fedora 33</kbd></i>
|
- <kbd>Debian 11</kbd> ("Bullseye")
|
||||||
- <kbd>Fedora 34</kbd></i>
|
- <kbd>Fedora 34</kbd>
|
||||||
|
- <kbd>Fedora 35</kbd>
|
||||||
|
- <kbd>Fedora 36</kbd>
|
||||||
<kbd>We are also packaged in Arch Linux's official community repository, courtesy of @FFY00</kbd></i>
|
<kbd>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>
|
</pre>
|
||||||
|
|
193
.github/workflows/desktop-build.yml
vendored
193
.github/workflows/desktop-build.yml
vendored
|
@ -19,9 +19,7 @@ on:
|
||||||
jobs:
|
jobs:
|
||||||
configure:
|
configure:
|
||||||
name: Configure
|
name: Configure
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
outputs:
|
outputs:
|
||||||
tag: ${{steps.configure.outputs.tag}}
|
tag: ${{steps.configure.outputs.tag}}
|
||||||
sha: ${{steps.configure.outputs.sha}}
|
sha: ${{steps.configure.outputs.sha}}
|
||||||
|
@ -55,7 +53,7 @@ jobs:
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Prepare release paramaters
|
- name: Prepare release parameters
|
||||||
id: prepare
|
id: prepare
|
||||||
if: steps.configure.outputs.tag != null
|
if: steps.configure.outputs.tag != null
|
||||||
shell: bash
|
shell: bash
|
||||||
|
@ -88,6 +86,7 @@ jobs:
|
||||||
|
|
||||||
- distro: Debian10
|
- distro: Debian10
|
||||||
package: DEB
|
package: DEB
|
||||||
|
test: skip # running tests on all distros is superfluous
|
||||||
|
|
||||||
- distro: Debian11
|
- distro: Debian11
|
||||||
package: DEB
|
package: DEB
|
||||||
|
@ -98,6 +97,10 @@ jobs:
|
||||||
|
|
||||||
- distro: Fedora35
|
- distro: Fedora35
|
||||||
package: RPM
|
package: RPM
|
||||||
|
test: skip
|
||||||
|
|
||||||
|
- distro: Fedora36
|
||||||
|
package: RPM
|
||||||
|
|
||||||
- distro: UbuntuBionic
|
- distro: UbuntuBionic
|
||||||
package: DEB
|
package: DEB
|
||||||
|
@ -106,24 +109,23 @@ jobs:
|
||||||
package: DEB
|
package: DEB
|
||||||
test: skip # UbuntuFocal has a broken qt for debug builds
|
test: skip # UbuntuFocal has a broken qt for debug builds
|
||||||
|
|
||||||
- distro: UbuntuHirsute
|
- distro: UbuntuImpish
|
||||||
package: DEB
|
package: DEB
|
||||||
test: skip
|
test: skip
|
||||||
|
|
||||||
- distro: UbuntuImpish
|
- distro: UbuntuJammy
|
||||||
package: DEB
|
package: DEB
|
||||||
|
|
||||||
name: ${{matrix.distro}}
|
name: ${{matrix.distro}}
|
||||||
|
|
||||||
needs: configure
|
needs: configure
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
continue-on-error: ${{matrix.allow-failure == 'yes'}}
|
continue-on-error: ${{matrix.allow-failure == 'yes'}}
|
||||||
|
|
||||||
env:
|
env:
|
||||||
NAME: ${{matrix.distro}}
|
NAME: ${{matrix.distro}}
|
||||||
CACHE: /tmp/${{matrix.distro}}-cache # ${{runner.temp}} does not work?
|
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:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
|
@ -151,9 +153,11 @@ jobs:
|
||||||
- name: Build debug and test
|
- name: Build debug and test
|
||||||
if: matrix.test != 'skip'
|
if: matrix.test != 'skip'
|
||||||
shell: bash
|
shell: bash
|
||||||
|
env:
|
||||||
|
distro: '${{matrix.distro}}'
|
||||||
run: |
|
run: |
|
||||||
source .ci/docker.sh
|
source .ci/docker.sh
|
||||||
RUN --server --debug --test --ccache
|
RUN --server --debug --test --ccache "$CCACHE_SIZE" --parallel 2
|
||||||
|
|
||||||
- name: Build release package
|
- name: Build release package
|
||||||
id: package
|
id: package
|
||||||
|
@ -162,16 +166,18 @@ jobs:
|
||||||
env:
|
env:
|
||||||
suffix: '-${{matrix.distro}}'
|
suffix: '-${{matrix.distro}}'
|
||||||
type: '${{matrix.package}}'
|
type: '${{matrix.package}}'
|
||||||
|
distro: '${{matrix.distro}}'
|
||||||
run: |
|
run: |
|
||||||
source .ci/docker.sh
|
source .ci/docker.sh
|
||||||
RUN --server --release --package "$type" --suffix "$suffix"
|
RUN --server --release --package "$type" --suffix "$suffix" \
|
||||||
|
--ccache "$CCACHE_SIZE" --parallel 2
|
||||||
|
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
if: matrix.package != 'skip'
|
if: matrix.package != 'skip'
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: ${{matrix.distro}}-package
|
name: ${{matrix.distro}}-package
|
||||||
path: ./build/${{steps.package.outputs.name}}
|
path: ${{steps.package.outputs.path}}
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload to release
|
- name: Upload to release
|
||||||
|
@ -181,7 +187,7 @@ jobs:
|
||||||
GITHUB_TOKEN: ${{github.token}}
|
GITHUB_TOKEN: ${{github.token}}
|
||||||
with:
|
with:
|
||||||
upload_url: ${{needs.configure.outputs.upload_url}}
|
upload_url: ${{needs.configure.outputs.upload_url}}
|
||||||
asset_path: ./build/${{steps.package.outputs.name}}
|
asset_path: ${{steps.package.outputs.path}}
|
||||||
asset_name: ${{steps.package.outputs.name}}
|
asset_name: ${{steps.package.outputs.name}}
|
||||||
asset_content_type: application/octet-stream
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
|
@ -193,39 +199,46 @@ jobs:
|
||||||
- target: Debug # tests only
|
- target: Debug # tests only
|
||||||
os: macos-latest
|
os: macos-latest
|
||||||
xcode: 12.5.1
|
xcode: 12.5.1
|
||||||
|
qt_version: 6
|
||||||
type: Debug
|
type: Debug
|
||||||
do_tests: 0 # tests do not work yet on mac
|
do_tests: 1
|
||||||
make_package: false
|
|
||||||
|
|
||||||
- target: 10.14_Mojave
|
- target: 10.14_Mojave
|
||||||
os: macos-10.15 # runs on Catalina
|
os: macos-10.15 # runs on Catalina
|
||||||
xcode: 10.3 # allows compatibility with macOS 10.14
|
xcode: 10.3 # allows compatibility with macOS 10.14
|
||||||
|
qt_version: 5
|
||||||
type: Release
|
type: Release
|
||||||
do_tests: 0
|
# do_tests: 1 # tests do not work on qt5?
|
||||||
make_package: true
|
make_package: 1
|
||||||
|
|
||||||
- target: 10.15_Catalina
|
- target: 10.15_Catalina
|
||||||
os: macos-10.15
|
os: macos-10.15
|
||||||
xcode: 12.1
|
xcode: 12.4
|
||||||
|
qt_version: 6
|
||||||
type: Release
|
type: Release
|
||||||
do_tests: 0
|
do_tests: 1
|
||||||
make_package: true
|
make_package: 1
|
||||||
|
|
||||||
- target: 11_Big_Sur
|
- target: 11_Big_Sur
|
||||||
os: macos-11
|
os: macos-11
|
||||||
xcode: 12.5.1
|
xcode: 13.2
|
||||||
|
qt_version: 6
|
||||||
type: Release
|
type: Release
|
||||||
do_tests: 0
|
do_tests: 1
|
||||||
make_package: true
|
make_package: 1
|
||||||
|
|
||||||
|
# - target: 12_Monterey
|
||||||
|
# os: macos-12
|
||||||
|
# xcode: 13.3
|
||||||
|
# qt_version: 6
|
||||||
|
# type: Release
|
||||||
|
# do_tests: 1
|
||||||
|
# make_package: 1
|
||||||
|
|
||||||
name: macOS ${{matrix.target}}
|
name: macOS ${{matrix.target}}
|
||||||
|
|
||||||
needs: configure
|
needs: configure
|
||||||
|
|
||||||
runs-on: ${{matrix.os}}
|
runs-on: ${{matrix.os}}
|
||||||
|
|
||||||
continue-on-error: ${{matrix.allow-failure == 'yes'}}
|
continue-on-error: ${{matrix.allow-failure == 'yes'}}
|
||||||
|
|
||||||
env:
|
env:
|
||||||
DEVELOPER_DIR:
|
DEVELOPER_DIR:
|
||||||
/Applications/Xcode_${{matrix.xcode}}.app/Contents/Developer
|
/Applications/Xcode_${{matrix.xcode}}.app/Contents/Developer
|
||||||
|
@ -238,45 +251,32 @@ jobs:
|
||||||
shell: bash
|
shell: bash
|
||||||
# cmake cannot find the mysql connector
|
# cmake cannot find the mysql connector
|
||||||
# neither of these works: mariadb-connector-c mysql-connector-c++
|
# neither of these works: mariadb-connector-c mysql-connector-c++
|
||||||
run: brew update && brew install protobuf
|
env:
|
||||||
|
qt_version: 'qt@${{matrix.qt_version}}'
|
||||||
- name: Install QT using homebrew
|
run: |
|
||||||
id: brew_install_qt
|
brew update
|
||||||
continue-on-error: true
|
brew install protobuf
|
||||||
shell: bash
|
brew install "$qt_version" --force-bottle
|
||||||
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}}
|
- name: Build on Xcode ${{matrix.xcode}}
|
||||||
shell: bash
|
shell: bash
|
||||||
|
id: build
|
||||||
env:
|
env:
|
||||||
CMAKE_BUILD_PARALLEL_LEVEL: 3 # mac machines actually have 3 cores
|
BUILDTYPE: '${{matrix.type}}'
|
||||||
run: .ci/compile.sh ${{matrix.type}} --server
|
MAKE_TEST: '${{matrix.do_tests}}'
|
||||||
|
MAKE_PACKAGE: '${{matrix.make_package}}'
|
||||||
- name: Test
|
PACKAGE_SUFFIX: '-macOS-${{matrix.target}}'
|
||||||
if: matrix.do_tests == 1
|
# set QTDIR to find qt5, qt6 can be found without this
|
||||||
shell: bash
|
QTDIR: '/usr/local/opt/qt5'
|
||||||
working-directory: build
|
# Mac machines actually have 3 cores
|
||||||
run: cmake --build . --target test
|
run: .ci/compile.sh --server --parallel 3
|
||||||
|
|
||||||
- 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
|
- name: Upload artifact
|
||||||
if: matrix.make_package
|
if: matrix.make_package
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: macOS-${{matrix.target}}-dmg
|
name: macOS-${{matrix.target}}-dmg
|
||||||
path: ${{steps.package.outputs.path}}
|
path: ${{steps.build.outputs.path}}
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload to release
|
- name: Upload to release
|
||||||
|
@ -286,8 +286,8 @@ jobs:
|
||||||
GITHUB_TOKEN: ${{github.token}}
|
GITHUB_TOKEN: ${{github.token}}
|
||||||
with:
|
with:
|
||||||
upload_url: ${{needs.configure.outputs.upload_url}}
|
upload_url: ${{needs.configure.outputs.upload_url}}
|
||||||
asset_path: ${{steps.package.outputs.path}}
|
asset_path: ${{steps.build.outputs.path}}
|
||||||
asset_name: ${{steps.package.outputs.name}}
|
asset_name: ${{steps.build.outputs.name}}
|
||||||
asset_content_type: application/octet-stream
|
asset_content_type: application/octet-stream
|
||||||
|
|
||||||
build-windows:
|
build-windows:
|
||||||
|
@ -296,24 +296,22 @@ jobs:
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- arch: 32
|
- arch: 32
|
||||||
triplet: x86
|
vcpkg_default_triplet: x86
|
||||||
cmake: Win32
|
qt_version: '5.15.2'
|
||||||
|
cmake_generator_platform: Win32
|
||||||
|
qt_arch: msvc2019
|
||||||
- arch: 64
|
- arch: 64
|
||||||
triplet: x64
|
vcpkg_default_triplet: x64
|
||||||
cmake: x64
|
qt_version: '6.3.0'
|
||||||
append: _64
|
cmake_generator_platform: x64
|
||||||
|
qt_arch: msvc2019_64
|
||||||
name: Windows ${{matrix.arch}}-bit
|
qt_modules: "qt5compat qtmultimedia qtwebsockets"
|
||||||
|
|
||||||
|
name: Windows (${{matrix.arch}}-bit)
|
||||||
needs: configure
|
needs: configure
|
||||||
|
|
||||||
runs-on: windows-2019
|
runs-on: windows-2019
|
||||||
|
|
||||||
env:
|
env:
|
||||||
QT_VERSION: '5.15.2'
|
CMAKE_GENERATOR: 'Visual Studio 16 2019'
|
||||||
QT_ARCH: msvc2022${{matrix.append}}
|
|
||||||
CMAKE_GENERATOR: 'Visual Studio 17 2022'
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Add msbuild to PATH
|
- name: Add msbuild to PATH
|
||||||
|
@ -321,46 +319,57 @@ jobs:
|
||||||
uses: microsoft/setup-msbuild@v1.1
|
uses: microsoft/setup-msbuild@v1.1
|
||||||
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
|
||||||
- name: Restore Qt ${{env.QT_VERSION}} ${{matrix.arch}}-bit from cache
|
- name: Restore Qt ${{matrix.qt_version}} (${{matrix.arch}}-bit) from cache
|
||||||
id: cache-qt
|
id: cache-qt
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v1 # Intentionally v1, based on jurplel documentation
|
||||||
with:
|
with:
|
||||||
key: ${{runner.os}}-QtCache-${{env.QT_VERSION}}-${{matrix.arch}}
|
key: ${{runner.os}}-QtCache-${{matrix.qt_version}}-${{matrix.arch}}
|
||||||
path: ${{runner.workspace}}/Qt
|
path: '${{github.workspace}}/../Qt'
|
||||||
|
|
||||||
- name: Install ${{matrix.arch}}-bit Qt
|
- name: Install Qt ${{matrix.qt_version}} (${{matrix.arch}}-bit)
|
||||||
uses: jurplel/install-qt-action@v2
|
uses: jurplel/install-qt-action@v3
|
||||||
with:
|
with:
|
||||||
cached: ${{steps.cache-qt.outputs.cache-hit}}
|
cached: ${{steps.cache-qt.outputs.cache-hit}}
|
||||||
version: ${{env.QT_VERSION}}
|
version: ${{matrix.qt_version}}
|
||||||
arch: win${{matrix.arch}}_${{env.QT_ARCH}}
|
arch: win${{matrix.arch}}_${{matrix.qt_arch}}
|
||||||
|
modules: ${{matrix.qt_modules}}
|
||||||
|
|
||||||
- name: Restore or setup vcpkg
|
- name: Run vcpkg
|
||||||
uses: lukka/run-vcpkg@v6
|
uses: lukka/run-vcpkg@v10.2
|
||||||
with:
|
with:
|
||||||
vcpkgArguments: '@${{github.workspace}}/vcpkg.txt'
|
runVcpkgInstall: true
|
||||||
vcpkgDirectory: ${{github.workspace}}/vcpkg
|
appendedCacheKey: ${{matrix.arch}}-bit
|
||||||
appendedCacheKey: ${{hashFiles('**/vcpkg.txt')}}
|
env:
|
||||||
vcpkgTriplet: ${{matrix.triplet}}-windows
|
VCPKG_DEFAULT_TRIPLET: '${{matrix.vcpkg_default_triplet}}-windows'
|
||||||
|
VCPKG_DISABLE_METRICS: 1
|
||||||
|
|
||||||
- name: Build Cockatrice ${{matrix.arch}}-bit
|
- name: Install OpenSSL (${{matrix.arch}}-bit)
|
||||||
|
shell: bash
|
||||||
|
run: .ci/download_openssl.sh --arch ${{matrix.arch}}
|
||||||
|
|
||||||
|
- name: Build Cockatrice (${{matrix.arch}}-bit)
|
||||||
id: build
|
id: build
|
||||||
shell: bash
|
shell: bash
|
||||||
env:
|
env:
|
||||||
PACKAGE_SUFFIX: '-win${{matrix.arch}}'
|
PACKAGE_SUFFIX: '-win${{matrix.arch}}'
|
||||||
CMAKE_GENERATOR: '${{env.CMAKE_GENERATOR}}'
|
CMAKE_GENERATOR: '${{env.CMAKE_GENERATOR}}'
|
||||||
CMAKE_GENERATOR_PLATFORM: '${{matrix.cmake}}'
|
CMAKE_GENERATOR_PLATFORM: '${{matrix.cmake_generator_platform}}'
|
||||||
run: ./.ci/compile.sh --server --release --test --package
|
QTDIR: '${{github.workspace}}\Qt\${{matrix.qt_version}}\win${{matrix.arch}}_${{matrix.qt_arch}}'
|
||||||
|
run: .ci/compile.sh --server --release --test --package --parallel 2
|
||||||
|
|
||||||
|
- name: Setup tmate session
|
||||||
|
if: ${{ failure() }}
|
||||||
|
uses: mxschmitt/action-tmate@v3
|
||||||
|
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: Windows-${{matrix.arch}}bit-installer
|
name: Windows-${{matrix.arch}}bit-installer
|
||||||
path: ./build/${{steps.build.outputs.name}}
|
path: ${{steps.build.outputs.path}}
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload to release
|
- name: Upload to release
|
||||||
|
@ -370,6 +379,6 @@ jobs:
|
||||||
GITHUB_TOKEN: ${{github.token}}
|
GITHUB_TOKEN: ${{github.token}}
|
||||||
with:
|
with:
|
||||||
upload_url: ${{needs.configure.outputs.upload_url}}
|
upload_url: ${{needs.configure.outputs.upload_url}}
|
||||||
asset_path: ./build/${{steps.build.outputs.name}}
|
asset_path: ${{steps.build.outputs.path}}
|
||||||
asset_name: ${{steps.build.outputs.name}}
|
asset_name: ${{steps.build.outputs.name}}
|
||||||
asset_content_type: application/octet-stream
|
asset_content_type: application/octet-stream
|
||||||
|
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -6,7 +6,7 @@ mysql.cnf
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.idea/
|
.idea/
|
||||||
*.aps
|
*.aps
|
||||||
cmake-build-debug/
|
cmake-build-debug*
|
||||||
preferences
|
preferences
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
.vs/
|
.vs/
|
||||||
|
|
117
CMakeLists.txt
117
CMakeLists.txt
|
@ -5,9 +5,26 @@
|
||||||
# This file sets all the variables shared between the projects
|
# This file sets all the variables shared between the projects
|
||||||
# like the installation path, compilation flags etc..
|
# like the installation path, compilation flags etc..
|
||||||
|
|
||||||
# Cmake 3.1 is required to enable C++11 support correctly
|
# cmake 3.16 is required if using qt6
|
||||||
cmake_minimum_required(VERSION 3.10)
|
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
|
# Default to "Release" build type
|
||||||
# User-provided value for CMAKE_BUILD_TYPE must be checked before the PROJECT() call
|
# User-provided value for CMAKE_BUILD_TYPE must be checked before the PROJECT() call
|
||||||
IF(DEFINED CMAKE_BUILD_TYPE)
|
IF(DEFINED CMAKE_BUILD_TYPE)
|
||||||
|
@ -16,8 +33,6 @@ ELSE()
|
||||||
SET(CMAKE_BUILD_TYPE Release CACHE STRING "Type of build")
|
SET(CMAKE_BUILD_TYPE Release CACHE STRING "Type of build")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
# Early detect ccache
|
|
||||||
OPTION(USE_CCACHE "Cache the build results with ccache" ON)
|
|
||||||
if(USE_CCACHE)
|
if(USE_CCACHE)
|
||||||
find_program(CCACHE_PROGRAM ccache)
|
find_program(CCACHE_PROGRAM ccache)
|
||||||
if(CCACHE_PROGRAM)
|
if(CCACHE_PROGRAM)
|
||||||
|
@ -41,22 +56,23 @@ endif()
|
||||||
|
|
||||||
# A project name is needed for CPack
|
# A project name is needed for CPack
|
||||||
# Version can be overriden by git tags, see cmake/getversion.cmake
|
# Version can be overriden by git tags, see cmake/getversion.cmake
|
||||||
PROJECT("Cockatrice" VERSION 2.8.1)
|
project("Cockatrice" VERSION 2.8.1)
|
||||||
|
|
||||||
# Set release name if not provided via env/cmake var
|
# Set release name if not provided via env/cmake var
|
||||||
if(NOT DEFINED GIT_TAG_RELEASENAME)
|
if(NOT DEFINED GIT_TAG_RELEASENAME)
|
||||||
set(GIT_TAG_RELEASENAME "Prismatic Bridge")
|
set(GIT_TAG_RELEASENAME "Prismatic Bridge")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Use c++11 for all targets
|
# Use c++17 for all targets
|
||||||
set(CMAKE_CXX_STANDARD 11 CACHE STRING "C++ ISO Standard")
|
set(CMAKE_CXX_STANDARD 17 CACHE STRING "C++ ISO Standard")
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||||
|
|
||||||
# Set conventional loops
|
# Set conventional loops
|
||||||
set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true)
|
set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true)
|
||||||
|
|
||||||
# Search path for cmake modules
|
# Search path for cmake modules
|
||||||
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
|
set(COCKATRICE_CMAKE_PATH "${PROJECT_SOURCE_DIR}/cmake")
|
||||||
|
list(INSERT CMAKE_MODULE_PATH 0 "${COCKATRICE_CMAKE_PATH}")
|
||||||
|
|
||||||
include(getversion)
|
include(getversion)
|
||||||
|
|
||||||
|
@ -76,8 +92,8 @@ if(UNIX)
|
||||||
if(RULE_LAUNCH_COMPILE)
|
if(RULE_LAUNCH_COMPILE)
|
||||||
MESSAGE(STATUS "Force enabling CCache usage under macOS")
|
MESSAGE(STATUS "Force enabling CCache usage under macOS")
|
||||||
# Set up wrapper scripts
|
# Set up wrapper scripts
|
||||||
configure_file(${CMAKE_MODULE_PATH}/launch-c.in launch-c)
|
configure_file("${COCKATRICE_CMAKE_PATH}/launch-c.in" launch-c)
|
||||||
configure_file(${CMAKE_MODULE_PATH}/launch-cxx.in launch-cxx)
|
configure_file("${COCKATRICE_CMAKE_PATH}/launch-cxx.in" launch-cxx)
|
||||||
execute_process(COMMAND chmod a+rx
|
execute_process(COMMAND chmod a+rx
|
||||||
"${CMAKE_BINARY_DIR}/launch-c"
|
"${CMAKE_BINARY_DIR}/launch-c"
|
||||||
"${CMAKE_BINARY_DIR}/launch-cxx")
|
"${CMAKE_BINARY_DIR}/launch-cxx")
|
||||||
|
@ -103,13 +119,10 @@ 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()
|
endif()
|
||||||
|
|
||||||
# Treat warnings as errors (Debug builds only)
|
|
||||||
option(WARNING_AS_ERROR "Treat warnings as errors in debug builds" ON)
|
|
||||||
|
|
||||||
# Define proper compilation flags
|
# Define proper compilation flags
|
||||||
IF(MSVC)
|
IF(MSVC)
|
||||||
# Visual Studio: Maximum optimization, disable warning C4251
|
# Visual Studio: Maximum optimization, disable warning C4251, establish C++17 compatibility
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "/Ox /MD /wd4251 ")
|
SET(CMAKE_CXX_FLAGS_RELEASE "/Ox /MD /wd4251 /Zc:__cplusplus /std:c++17 /permissive-")
|
||||||
# Generate complete debugging information
|
# Generate complete debugging information
|
||||||
#set(CMAKE_CXX_FLAGS_DEBUG "/Zi")
|
#set(CMAKE_CXX_FLAGS_DEBUG "/Zi")
|
||||||
ELSEIF (CMAKE_COMPILER_IS_GNUCXX)
|
ELSEIF (CMAKE_COMPILER_IS_GNUCXX)
|
||||||
|
@ -123,6 +136,10 @@ ELSEIF (CMAKE_COMPILER_IS_GNUCXX)
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -Wall -Wextra")
|
set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -Wall -Wextra")
|
||||||
endif()
|
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)
|
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})
|
FOREACH(FLAG ${ADDITIONAL_DEBUG_FLAGS})
|
||||||
|
@ -148,7 +165,7 @@ ENDIF()
|
||||||
|
|
||||||
FIND_PACKAGE(Threads REQUIRED)
|
FIND_PACKAGE(Threads REQUIRED)
|
||||||
|
|
||||||
# Find Qt5
|
# Determine 32 or 64 bit build
|
||||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
set(_lib_suffix 64)
|
set(_lib_suffix 64)
|
||||||
else()
|
else()
|
||||||
|
@ -165,28 +182,9 @@ elseif(DEFINED ENV{QTDIR})
|
||||||
list(APPEND CMAKE_PREFIX_PATH "$ENV{QTDIR}")
|
list(APPEND CMAKE_PREFIX_PATH "$ENV{QTDIR}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
FIND_PACKAGE(Qt5Core 5.5.0 REQUIRED)
|
MESSAGE(STATUS "Update Translations: ${UPDATE_TRANSLATIONS}")
|
||||||
|
|
||||||
IF(Qt5Core_FOUND)
|
include(FindQtRuntime)
|
||||||
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)
|
set(CMAKE_AUTOMOC TRUE)
|
||||||
|
|
||||||
|
@ -195,7 +193,7 @@ FIND_PACKAGE(Protobuf REQUIRED)
|
||||||
IF(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
|
IF(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
|
||||||
MESSAGE(FATAL_ERROR "No protoc command found!")
|
MESSAGE(FATAL_ERROR "No protoc command found!")
|
||||||
ELSE()
|
ELSE()
|
||||||
MESSAGE(STATUS "Protoc version ${Protobuf_VERSION} found!")
|
MESSAGE(STATUS "Found Protobuf ${Protobuf_VERSION} at: ${Protobuf_LIBRARIES}")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
#Find OpenSSL
|
#Find OpenSSL
|
||||||
|
@ -209,8 +207,8 @@ IF(MSVC)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
# Package builder
|
# Package builder
|
||||||
set(CPACK_PACKAGE_CONTACT "Zach Halpern <zahalpern+github@gmail.com>")
|
set(CPACK_PACKAGE_CONTACT "Zach Halpern <zach@cockatrice.us>")
|
||||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY ${PROJECT_NAME})
|
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PROJECT_NAME}")
|
||||||
set(CPACK_PACKAGE_VENDOR "Cockatrice Development Team")
|
set(CPACK_PACKAGE_VENDOR "Cockatrice Development Team")
|
||||||
set(CPACK_PACKAGE_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/README.md")
|
set(CPACK_PACKAGE_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/README.md")
|
||||||
set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
|
set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
|
||||||
|
@ -231,15 +229,33 @@ if(UNIX)
|
||||||
# linux
|
# linux
|
||||||
IF(CPACK_GENERATOR STREQUAL "RPM")
|
IF(CPACK_GENERATOR STREQUAL "RPM")
|
||||||
set(CPACK_RPM_PACKAGE_LICENSE "GPLv2")
|
set(CPACK_RPM_PACKAGE_LICENSE "GPLv2")
|
||||||
set(CPACK_RPM_PACKAGE_REQUIRES "protobuf, qt5-qttools, qt5-qtsvg, qt5-qtmultimedia")
|
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_GROUP "Amusements/Games")
|
||||||
set(CPACK_RPM_PACKAGE_URL "http://github.com/Cockatrice/Cockatrice")
|
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)
|
||||||
ELSE()
|
ELSE()
|
||||||
set(CPACK_GENERATOR DEB)
|
set(CPACK_GENERATOR DEB)
|
||||||
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
|
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
|
||||||
set(CPACK_DEBIAN_PACKAGE_SECTION "games")
|
set(CPACK_DEBIAN_PACKAGE_SECTION "games")
|
||||||
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "http://github.com/Cockatrice/Cockatrice")
|
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "http://github.com/Cockatrice/Cockatrice")
|
||||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt5multimedia5-plugins, libqt5svg5")
|
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()
|
||||||
ENDIF()
|
ENDIF()
|
||||||
endif()
|
endif()
|
||||||
elseif(WIN32)
|
elseif(WIN32)
|
||||||
|
@ -252,8 +268,8 @@ elseif(WIN32)
|
||||||
|
|
||||||
# Configure file with custom definitions for NSIS.
|
# Configure file with custom definitions for NSIS.
|
||||||
configure_file(
|
configure_file(
|
||||||
${CMAKE_MODULE_PATH}/NSIS.definitions.nsh.in
|
"${COCKATRICE_CMAKE_PATH}/NSIS.definitions.nsh.in"
|
||||||
${PROJECT_BINARY_DIR}/NSIS.definitions.nsh
|
"${PROJECT_BINARY_DIR}/NSIS.definitions.nsh"
|
||||||
)
|
)
|
||||||
|
|
||||||
# include vcredist into the package; NSIS will take care of running it
|
# include vcredist into the package; NSIS will take care of running it
|
||||||
|
@ -264,38 +280,33 @@ endif()
|
||||||
|
|
||||||
include(CPack)
|
include(CPack)
|
||||||
|
|
||||||
# Compile servatrice (default off)
|
|
||||||
option(WITH_SERVER "build servatrice" OFF)
|
|
||||||
add_subdirectory(common)
|
add_subdirectory(common)
|
||||||
if(WITH_SERVER)
|
if(WITH_SERVER)
|
||||||
add_subdirectory(servatrice)
|
add_subdirectory(servatrice)
|
||||||
SET(CPACK_INSTALL_CMAKE_PROJECTS "Servatrice;Servatrice;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
|
SET(CPACK_INSTALL_CMAKE_PROJECTS "Servatrice;Servatrice;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Compile cockatrice (default on)
|
|
||||||
option(WITH_CLIENT "build cockatrice" ON)
|
|
||||||
if(WITH_CLIENT)
|
if(WITH_CLIENT)
|
||||||
add_subdirectory(cockatrice)
|
add_subdirectory(cockatrice)
|
||||||
SET(CPACK_INSTALL_CMAKE_PROJECTS "Cockatrice;Cockatrice;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
|
SET(CPACK_INSTALL_CMAKE_PROJECTS "Cockatrice;Cockatrice;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Compile oracle (default on)
|
|
||||||
option(WITH_ORACLE "build oracle" ON)
|
|
||||||
if(WITH_ORACLE)
|
if(WITH_ORACLE)
|
||||||
add_subdirectory(oracle)
|
add_subdirectory(oracle)
|
||||||
SET(CPACK_INSTALL_CMAKE_PROJECTS "Oracle;Oracle;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
|
SET(CPACK_INSTALL_CMAKE_PROJECTS "Oracle;Oracle;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Compile dbconverter (default on)
|
|
||||||
option(WITH_DBCONVERTER "build dbconverter" ON)
|
|
||||||
if(WITH_DBCONVERTER)
|
if(WITH_DBCONVERTER)
|
||||||
add_subdirectory(dbconverter)
|
add_subdirectory(dbconverter)
|
||||||
SET(CPACK_INSTALL_CMAKE_PROJECTS "Dbconverter;Dbconverter;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
|
SET(CPACK_INSTALL_CMAKE_PROJECTS "Dbconverter;Dbconverter;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Compile tests (default off)
|
|
||||||
option(TEST "build tests" OFF)
|
|
||||||
if(TEST)
|
if(TEST)
|
||||||
include(CTest)
|
include(CTest)
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(Qt6Found AND Qt6_VERSION_MINOR GREATER_EQUAL 3)
|
||||||
|
# Qt6.3+ requires project finalization to support translations
|
||||||
|
qt6_finalize_project()
|
||||||
|
endif()
|
||||||
|
|
|
@ -117,6 +117,7 @@ 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).
|
- `-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).
|
- `-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```.
|
- `-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
|
# Run
|
||||||
|
|
118
cmake/FindQtRuntime.cmake
Normal file
118
cmake/FindQtRuntime.cmake
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
# 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 Widgets WebSockets)
|
||||||
|
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)
|
||||||
|
# Core5Compat is Qt6 Only, Linguist is now a component in Qt6 instead of an external package
|
||||||
|
find_package(Qt6 6.2.3
|
||||||
|
COMPONENTS Core5Compat ${REQUIRED_QT_COMPONENTS}
|
||||||
|
OPTIONAL_COMPONENTS Linguist
|
||||||
|
QUIET
|
||||||
|
HINTS ${Qt6_DIR})
|
||||||
|
endif()
|
||||||
|
if(Qt6_FOUND)
|
||||||
|
set(COCKATRICE_QT_VERSION_NAME Qt6)
|
||||||
|
|
||||||
|
if(Qt6LinguistTools_FOUND)
|
||||||
|
list(FIND Qt6LinguistTools_TARGETS Qt6::lrelease QT6_LRELEASE_INDEX)
|
||||||
|
if(QT6_LRELEASE_INDEX EQUAL -1)
|
||||||
|
message(WARNING "Qt6 lrelease not found.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
list(FIND Qt6LinguistTools_TARGETS Qt6::lupdate QT6_LUPDATE_INDEX)
|
||||||
|
if(QT6_LUPDATE_INDEX EQUAL -1)
|
||||||
|
message(WARNING "Qt6 lupdate not found.")
|
||||||
|
endif()
|
||||||
|
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}")
|
||||||
|
if(Qt6_FOUND)
|
||||||
|
list(APPEND SERVATRICE_QT_MODULES ${COCKATRICE_QT_VERSION_NAME}::Core5Compat)
|
||||||
|
list(APPEND COCKATRICE_QT_MODULES ${COCKATRICE_QT_VERSION_NAME}::Core5Compat)
|
||||||
|
LIST(APPEND ORACLE_QT_MODULES ${COCKATRICE_QT_VERSION_NAME}::Core5Compat)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "Found Qt ${${COCKATRICE_QT_VERSION_NAME}_VERSION} at: ${${COCKATRICE_QT_VERSION_NAME}_DIR}")
|
|
@ -1,66 +1,44 @@
|
||||||
# Find the OpenSSL runtime libraries (.dll) for Windows that
|
# Find the OpenSSL runtime libraries (.dll) for Windows that
|
||||||
# will be needed by Qt in order to access https urls.
|
# will be needed by Qt in order to access https urls.
|
||||||
|
if(NOT DEFINED WIN32 OR NOT ${WIN32})
|
||||||
|
message(STATUS "Non-Windows device trying to execute FindWin32SslRuntime, skipping")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
if (WIN32)
|
if("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "x64")
|
||||||
# Get standard installation paths for OpenSSL under Windows
|
message(STATUS "Looking for OpenSSL for ${CMAKE_GENERATOR_PLATFORM}")
|
||||||
|
file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _programfiles)
|
||||||
|
set(_OPENSSL_ROOT_PATHS
|
||||||
|
"$ENV{VCPKG_PACKAGES_DIR}/x64-windows/bin"
|
||||||
|
"C:/OpenSSL-Win64/bin"
|
||||||
|
"C:/OpenSSL-Win64"
|
||||||
|
"C:/Tools/vcpkg/installed/x64-windows/bin"
|
||||||
|
"${_programfiles}/OpenSSL-Win64"
|
||||||
|
)
|
||||||
|
unset(_programfiles)
|
||||||
|
elseif("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "Win32")
|
||||||
|
message(STATUS "Looking for OpenSSL for ${CMAKE_GENERATOR_PLATFORM}")
|
||||||
|
file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _programfiles)
|
||||||
|
set(_OPENSSL_ROOT_PATHS
|
||||||
|
"$ENV{VCPKG_PACKAGES_DIR}/x86-windows/bin"
|
||||||
|
"C:/OpenSSL-Win32/bin"
|
||||||
|
"C:/OpenSSL-Win32"
|
||||||
|
"C:/OpenSSL"
|
||||||
|
"C:/Tools/vcpkg/installed/x86-windows/bin"
|
||||||
|
"${_programfiles}/OpenSSL"
|
||||||
|
"${_programfiles}/OpenSSL-Win32"
|
||||||
|
)
|
||||||
|
unset(_programfiles)
|
||||||
|
endif()
|
||||||
|
|
||||||
# http://www.slproweb.com/products/Win32OpenSSL.html
|
message(STATUS "Looking for OpenSSL @ $ENV{CMAKE_GENERATOR_PLATFORM} in ${_OPENSSL_ROOT_PATHS}")
|
||||||
|
if("$ENV{CMAKE_GENERATOR_PLATFORM}" STREQUAL "x64")
|
||||||
if( CMAKE_SIZEOF_VOID_P EQUAL 8 )
|
FIND_FILE(WIN32SSLRUNTIME_LIBEAY NAMES libcrypto-1_1-x64.dll libcrypto.dll PATHS ${_OPENSSL_ROOT_PATHS} NO_DEFAULT_PATH)
|
||||||
# target win64
|
FIND_FILE(WIN32SSLRUNTIME_SSLEAY NAMES libssl-1_1-x64.dll libssl.dll PATHS ${_OPENSSL_ROOT_PATHS} NO_DEFAULT_PATH)
|
||||||
set(_OPENSSL_ROOT_HINTS
|
elseif("$ENV{CMAKE_GENERATOR_PLATFORM}" STREQUAL "Win32")
|
||||||
${OPENSSL_ROOT_DIR}
|
FIND_FILE(WIN32SSLRUNTIME_LIBEAY NAMES libcrypto-1_1.dll libcrypto.dll PATHS ${_OPENSSL_ROOT_PATHS} NO_DEFAULT_PATH)
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (64-bit)_is1;Inno Setup: App Path]"
|
FIND_FILE(WIN32SSLRUNTIME_SSLEAY NAMES libssl-1_1.dll libssl.dll PATHS ${_OPENSSL_ROOT_PATHS} NO_DEFAULT_PATH)
|
||||||
ENV OPENSSL_ROOT_DIR
|
endif()
|
||||||
)
|
|
||||||
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)
|
IF(WIN32SSLRUNTIME_LIBEAY AND WIN32SSLRUNTIME_SSLEAY)
|
||||||
SET(WIN32SSLRUNTIME_LIBRARIES "${WIN32SSLRUNTIME_LIBEAY}" "${WIN32SSLRUNTIME_SSLEAY}")
|
SET(WIN32SSLRUNTIME_LIBRARIES "${WIN32SSLRUNTIME_LIBEAY}" "${WIN32SSLRUNTIME_SSLEAY}")
|
||||||
|
|
|
@ -138,7 +138,7 @@ 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_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)
|
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(translate_SRCS ${translate_cockatrice_SRCS} ${translate_common_SRCS})
|
||||||
SET(cockatrice_TS "${CMAKE_CURRENT_SOURCE_DIR}/translations/cockatrice_en@source.ts")
|
SET(cockatrice_TS "${CMAKE_CURRENT_SOURCE_DIR}/cockatrice_en@source.ts")
|
||||||
ELSE()
|
ELSE()
|
||||||
FILE(GLOB cockatrice_TS "${CMAKE_CURRENT_SOURCE_DIR}/translations/*.ts")
|
FILE(GLOB cockatrice_TS "${CMAKE_CURRENT_SOURCE_DIR}/translations/*.ts")
|
||||||
ENDIF(UPDATE_TRANSLATIONS)
|
ENDIF(UPDATE_TRANSLATIONS)
|
||||||
|
@ -153,30 +153,11 @@ if(APPLE)
|
||||||
set(cockatrice_SOURCES ${cockatrice_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/resources/appicon.icns)
|
set(cockatrice_SOURCES ${cockatrice_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/resources/appicon.icns)
|
||||||
ENDIF(APPLE)
|
ENDIF(APPLE)
|
||||||
|
|
||||||
# Qt5
|
IF(Qt6_FOUND)
|
||||||
find_package(Qt5 COMPONENTS Concurrent Multimedia Network PrintSupport Svg WebSockets Widgets REQUIRED)
|
Qt6_ADD_RESOURCES(cockatrice_RESOURCES_RCC ${cockatrice_RESOURCES})
|
||||||
set(COCKATRICE_QT_MODULES Qt5::Concurrent Qt5::Multimedia Qt5::Network Qt5::PrintSupport Qt5::Svg Qt5::Widgets Qt5::WebSockets)
|
ELSEIF(Qt5_FOUND)
|
||||||
|
Qt5_ADD_RESOURCES(cockatrice_RESOURCES_RCC ${cockatrice_RESOURCES})
|
||||||
# Qt5LinguistTools
|
ENDIF()
|
||||||
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
|
# Declare path variables
|
||||||
set(ICONDIR share/icons CACHE STRING "icon dir")
|
set(ICONDIR share/icons CACHE STRING "icon dir")
|
||||||
|
@ -188,10 +169,38 @@ INCLUDE_DIRECTORIES(${PROTOBUF_INCLUDE_DIR})
|
||||||
INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/common)
|
INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/common)
|
||||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
|
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
# Build cockatrice binary and link it
|
set(COCKATRICE_MAC_QM_INSTALL_DIR "cockatrice.app/Contents/Resources/translations")
|
||||||
ADD_EXECUTABLE(cockatrice WIN32 MACOSX_BUNDLE ${cockatrice_SOURCES} ${cockatrice_QM} ${cockatrice_RESOURCES_RCC} ${cockatrice_MOC_SRCS})
|
set(COCKATRICE_UNIX_QM_INSTALL_DIR "share/cockatrice/translations")
|
||||||
|
set(COCKATRICE_WIN32_QM_INSTALL_DIR "translations")
|
||||||
|
|
||||||
TARGET_LINK_LIBRARIES(cockatrice cockatrice_common ${COCKATRICE_QT_MODULES})
|
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_SOURCES} ${cockatrice_QM} ${cockatrice_RESOURCES_RCC} ${cockatrice_MOC_SRCS})
|
||||||
|
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()
|
||||||
|
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
|
@ -205,27 +214,23 @@ if(UNIX)
|
||||||
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 ./)
|
INSTALL(TARGETS cockatrice BUNDLE DESTINATION ./)
|
||||||
INSTALL(FILES ${cockatrice_QM} DESTINATION ./cockatrice.app/Contents/Resources/translations)
|
|
||||||
else()
|
else()
|
||||||
# Assume linux
|
# Assume linux
|
||||||
INSTALL(TARGETS cockatrice RUNTIME DESTINATION bin/)
|
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.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}/resources/cockatrice.svg DESTINATION ${ICONDIR}/hicolor/scalable/apps)
|
||||||
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/cockatrice.desktop DESTINATION ${DESKTOPDIR})
|
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/cockatrice.desktop DESTINATION ${DESKTOPDIR})
|
||||||
INSTALL(FILES ${cockatrice_QM} DESTINATION share/cockatrice/translations)
|
|
||||||
endif()
|
endif()
|
||||||
elseif(WIN32)
|
elseif(WIN32)
|
||||||
INSTALL(TARGETS cockatrice RUNTIME DESTINATION ./)
|
INSTALL(TARGETS cockatrice RUNTIME DESTINATION ./)
|
||||||
INSTALL(FILES ${cockatrice_QM} DESTINATION ./translations)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
# these needs to be relative to CMAKE_INSTALL_PREFIX
|
# these needs to be relative to CMAKE_INSTALL_PREFIX
|
||||||
set(plugin_dest_dir cockatrice.app/Contents/Plugins)
|
set(plugin_dest_dir cockatrice.app/Contents/Plugins)
|
||||||
set(qtconf_dest_dir cockatrice.app/Contents/Resources)
|
set(qtconf_dest_dir cockatrice.app/Contents/Resources)
|
||||||
get_filename_component(QT_LIBRARY_DIR "${QT_LIBRARY_DIR}/.." ABSOLUTE)
|
|
||||||
|
|
||||||
# qt5 plugins: audio, iconengines, imageformats, platforms, printsupport
|
# Qt plugins: audio (Qt5), iconengines, imageformats, platforms, printsupport (Qt5), styles, tls (Qt6)
|
||||||
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime
|
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime
|
||||||
FILES_MATCHING
|
FILES_MATCHING
|
||||||
PATTERN "*.dSYM" EXCLUDE
|
PATTERN "*.dSYM" EXCLUDE
|
||||||
|
@ -236,6 +241,7 @@ if(APPLE)
|
||||||
PATTERN "platforms/*.dylib"
|
PATTERN "platforms/*.dylib"
|
||||||
PATTERN "printsupport/*.dylib"
|
PATTERN "printsupport/*.dylib"
|
||||||
PATTERN "styles/*.dylib"
|
PATTERN "styles/*.dylib"
|
||||||
|
PATTERN "tls/*.dylib"
|
||||||
)
|
)
|
||||||
|
|
||||||
install(CODE "
|
install(CODE "
|
||||||
|
@ -261,9 +267,32 @@ if(WIN32)
|
||||||
|
|
||||||
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")
|
||||||
|
|
||||||
# qt5 plugins: audio, iconengines, imageformats, platforms, printsupport
|
# Qt plugins: audio (Qt5), iconengines, imageformats, platforms, printsupport (Qt5), styles, tls (Qt6)
|
||||||
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime
|
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime FILES_MATCHING
|
||||||
FILES_MATCHING REGEX "(audio|iconengines|imageformats|platforms|printsupport|styles)/.*[^d]\\.dll")
|
PATTERN "audio/qtaudio_wasapi.dll"
|
||||||
|
PATTERN "audio/qtaudio_windows.dll"
|
||||||
|
PATTERN "iconengines/qsvgicon.dll"
|
||||||
|
PATTERN "imageformats/qgif.dll"
|
||||||
|
PATTERN "imageformats/qicns.dll"
|
||||||
|
PATTERN "imageformats/qico.dll"
|
||||||
|
PATTERN "imageformats/qjpeg.dll"
|
||||||
|
PATTERN "imageformats/qsvg.dll"
|
||||||
|
PATTERN "imageformats/qtga.dll"
|
||||||
|
PATTERN "imageformats/qtiff.dll"
|
||||||
|
PATTERN "imageformats/qwbmp.dll"
|
||||||
|
PATTERN "imageformats/qwebp.dll"
|
||||||
|
PATTERN "platforms/qdirect2d.dll"
|
||||||
|
PATTERN "platforms/qminimal.dll"
|
||||||
|
PATTERN "platforms/qoffscreen.dll"
|
||||||
|
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")
|
||||||
|
|
||||||
install(CODE "
|
install(CODE "
|
||||||
file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf\" \"[Paths]
|
file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf\" \"[Paths]
|
||||||
|
@ -284,3 +313,26 @@ Data = Resources\")
|
||||||
install(FILES ${WIN32SSLRUNTIME_LIBRARIES} DESTINATION ./)
|
install(FILES ${WIN32SSLRUNTIME_LIBRARIES} DESTINATION ./)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(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})
|
||||||
|
endif()
|
||||||
|
elseif(WIN32)
|
||||||
|
install(FILES ${cockatrice_QM} DESTINATION ${COCKATRICE_WIN32_QM_INSTALL_DIR})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(Qt6_FOUND)
|
||||||
|
qt6_finalize_target(cockatrice)
|
||||||
|
endif()
|
||||||
|
|
|
@ -48,6 +48,7 @@ AbstractClient::AbstractClient(QObject *parent)
|
||||||
qRegisterMetaType<QList<ServerInfo_User>>("QList<ServerInfo_User>");
|
qRegisterMetaType<QList<ServerInfo_User>>("QList<ServerInfo_User>");
|
||||||
qRegisterMetaType<Event_ReplayAdded>("Event_ReplayAdded");
|
qRegisterMetaType<Event_ReplayAdded>("Event_ReplayAdded");
|
||||||
qRegisterMetaType<QList<QString>>("missingFeatures");
|
qRegisterMetaType<QList<QString>>("missingFeatures");
|
||||||
|
qRegisterMetaType<PendingCommand *>("pendingCommand");
|
||||||
|
|
||||||
FeatureSet features;
|
FeatureSet features;
|
||||||
features.initalizeFeatureList(clientFeatures);
|
features.initalizeFeatureList(clientFeatures);
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
#include <QGraphicsScene>
|
#include <QGraphicsScene>
|
||||||
#include <QGraphicsSceneMouseEvent>
|
#include <QGraphicsSceneMouseEvent>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <cmath>
|
#include <QtMath>
|
||||||
|
|
||||||
ArrowItem::ArrowItem(Player *_player, int _id, ArrowTarget *_startItem, ArrowTarget *_targetItem, const QColor &_color)
|
ArrowItem::ArrowItem(Player *_player, int _id, ArrowTarget *_startItem, ArrowTarget *_targetItem, const QColor &_color)
|
||||||
: QGraphicsItem(), player(_player), id(_id), startItem(_startItem), targetItem(_targetItem), color(_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 arrowWidth = 15.0;
|
||||||
const double headWidth = 40.0;
|
const double headWidth = 40.0;
|
||||||
const double headLength =
|
const double headLength =
|
||||||
headWidth / pow(2, 0.5); // aka headWidth / sqrt (2) but this produces a compile error with MSVC++
|
headWidth / qPow(2, 0.5); // aka headWidth / sqrt (2) but this produces a compile error with MSVC++
|
||||||
const double phi = 15;
|
const double phi = 15;
|
||||||
|
|
||||||
if (!startItem)
|
if (!startItem)
|
||||||
|
@ -86,7 +86,7 @@ void ArrowItem::updatePath(const QPointF &endPoint)
|
||||||
if (lineLength < 30)
|
if (lineLength < 30)
|
||||||
path = QPainterPath();
|
path = QPainterPath();
|
||||||
else {
|
else {
|
||||||
QPointF c(lineLength / 2, tan(phi * M_PI / 180) * lineLength);
|
QPointF c(lineLength / 2, qTan(phi * M_PI / 180) * lineLength);
|
||||||
|
|
||||||
QPainterPath centerLine;
|
QPainterPath centerLine;
|
||||||
centerLine.moveTo(0, 0);
|
centerLine.moveTo(0, 0);
|
||||||
|
@ -97,22 +97,22 @@ void ArrowItem::updatePath(const QPointF &endPoint)
|
||||||
QLineF testLine(arrowBodyEndPoint, centerLine.pointAtPercent(percentage + 0.001));
|
QLineF testLine(arrowBodyEndPoint, centerLine.pointAtPercent(percentage + 0.001));
|
||||||
qreal alpha = testLine.angle() - 90;
|
qreal alpha = testLine.angle() - 90;
|
||||||
QPointF endPoint1 =
|
QPointF endPoint1 =
|
||||||
arrowBodyEndPoint + arrowWidth / 2 * QPointF(cos(alpha * M_PI / 180), -sin(alpha * M_PI / 180));
|
arrowBodyEndPoint + arrowWidth / 2 * QPointF(qCos(alpha * M_PI / 180), -qSin(alpha * M_PI / 180));
|
||||||
QPointF endPoint2 =
|
QPointF endPoint2 =
|
||||||
arrowBodyEndPoint + arrowWidth / 2 * QPointF(-cos(alpha * M_PI / 180), sin(alpha * M_PI / 180));
|
arrowBodyEndPoint + arrowWidth / 2 * QPointF(-qCos(alpha * M_PI / 180), qSin(alpha * M_PI / 180));
|
||||||
QPointF point1 =
|
QPointF point1 =
|
||||||
endPoint1 + (headWidth - arrowWidth) / 2 * QPointF(cos(alpha * M_PI / 180), -sin(alpha * M_PI / 180));
|
endPoint1 + (headWidth - arrowWidth) / 2 * QPointF(qCos(alpha * M_PI / 180), -qSin(alpha * M_PI / 180));
|
||||||
QPointF point2 =
|
QPointF point2 =
|
||||||
endPoint2 + (headWidth - arrowWidth) / 2 * QPointF(-cos(alpha * M_PI / 180), sin(alpha * M_PI / 180));
|
endPoint2 + (headWidth - arrowWidth) / 2 * QPointF(-qCos(alpha * M_PI / 180), qSin(alpha * M_PI / 180));
|
||||||
|
|
||||||
path = QPainterPath(-arrowWidth / 2 * QPointF(cos((phi - 90) * M_PI / 180), sin((phi - 90) * M_PI / 180)));
|
path = QPainterPath(-arrowWidth / 2 * QPointF(qCos((phi - 90) * M_PI / 180), qSin((phi - 90) * M_PI / 180)));
|
||||||
path.quadTo(c, endPoint1);
|
path.quadTo(c, endPoint1);
|
||||||
path.lineTo(point1);
|
path.lineTo(point1);
|
||||||
path.lineTo(QPointF(lineLength, 0));
|
path.lineTo(QPointF(lineLength, 0));
|
||||||
path.lineTo(point2);
|
path.lineTo(point2);
|
||||||
path.lineTo(endPoint2);
|
path.lineTo(endPoint2);
|
||||||
path.quadTo(c, arrowWidth / 2 * QPointF(cos((phi - 90) * M_PI / 180), sin((phi - 90) * M_PI / 180)));
|
path.quadTo(c, arrowWidth / 2 * QPointF(qCos((phi - 90) * M_PI / 180), qSin((phi - 90) * M_PI / 180)));
|
||||||
path.lineTo(-arrowWidth / 2 * QPointF(cos((phi - 90) * M_PI / 180), sin((phi - 90) * M_PI / 180)));
|
path.lineTo(-arrowWidth / 2 * QPointF(qCos((phi - 90) * M_PI / 180), qSin((phi - 90) * M_PI / 180)));
|
||||||
}
|
}
|
||||||
|
|
||||||
setPos(startPoint);
|
setPos(startPoint);
|
||||||
|
|
|
@ -23,7 +23,7 @@ bool CockatriceXml3Parser::getCanParseFile(const QString &fileName, QIODevice &d
|
||||||
QXmlStreamReader xml(&device);
|
QXmlStreamReader xml(&device);
|
||||||
while (!xml.atEnd()) {
|
while (!xml.atEnd()) {
|
||||||
if (xml.readNext() == QXmlStreamReader::StartElement) {
|
if (xml.readNext() == QXmlStreamReader::StartElement) {
|
||||||
if (xml.name() == COCKATRICE_XML3_TAGNAME) {
|
if (xml.name().toString() == COCKATRICE_XML3_TAGNAME) {
|
||||||
int version = xml.attributes().value("version").toString().toInt();
|
int version = xml.attributes().value("version").toString().toInt();
|
||||||
if (version == COCKATRICE_XML3_TAGVER) {
|
if (version == COCKATRICE_XML3_TAGVER) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -52,12 +52,13 @@ void CockatriceXml3Parser::parseFile(QIODevice &device)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xml.name() == "sets") {
|
auto name = xml.name().toString();
|
||||||
|
if (name == "sets") {
|
||||||
loadSetsFromXml(xml);
|
loadSetsFromXml(xml);
|
||||||
} else if (xml.name() == "cards") {
|
} else if (name == "cards") {
|
||||||
loadCardsFromXml(xml);
|
loadCardsFromXml(xml);
|
||||||
} else if (xml.name() != "") {
|
} else if (!name.isEmpty()) {
|
||||||
qDebug() << "[CockatriceXml3Parser] Unknown item" << xml.name() << ", trying to continue anyway";
|
qDebug() << "[CockatriceXml3Parser] Unknown item" << name << ", trying to continue anyway";
|
||||||
xml.skipCurrentElement();
|
xml.skipCurrentElement();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,26 +73,27 @@ void CockatriceXml3Parser::loadSetsFromXml(QXmlStreamReader &xml)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xml.name() == "set") {
|
auto name = xml.name().toString();
|
||||||
|
if (name == "set") {
|
||||||
QString shortName, longName, setType;
|
QString shortName, longName, setType;
|
||||||
QDate releaseDate;
|
QDate releaseDate;
|
||||||
while (!xml.atEnd()) {
|
while (!xml.atEnd()) {
|
||||||
if (xml.readNext() == QXmlStreamReader::EndElement) {
|
if (xml.readNext() == QXmlStreamReader::EndElement) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
name = xml.name().toString();
|
||||||
|
|
||||||
if (xml.name() == "name") {
|
if (name == "name") {
|
||||||
shortName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
shortName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||||
} else if (xml.name() == "longname") {
|
} else if (name == "longname") {
|
||||||
longName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
longName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||||
} else if (xml.name() == "settype") {
|
} else if (name == "settype") {
|
||||||
setType = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
setType = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||||
} else if (xml.name() == "releasedate") {
|
} else if (name == "releasedate") {
|
||||||
releaseDate =
|
releaseDate =
|
||||||
QDate::fromString(xml.readElementText(QXmlStreamReader::IncludeChildElements), Qt::ISODate);
|
QDate::fromString(xml.readElementText(QXmlStreamReader::IncludeChildElements), Qt::ISODate);
|
||||||
} else if (xml.name() != "") {
|
} else if (!name.isEmpty()) {
|
||||||
qDebug() << "[CockatriceXml3Parser] Unknown set property" << xml.name()
|
qDebug() << "[CockatriceXml3Parser] Unknown set property" << name << ", trying to continue anyway";
|
||||||
<< ", trying to continue anyway";
|
|
||||||
xml.skipCurrentElement();
|
xml.skipCurrentElement();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -146,7 +148,8 @@ void CockatriceXml3Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xml.name() == "card") {
|
auto xmlName = xml.name().toString();
|
||||||
|
if (xmlName == "card") {
|
||||||
QString name = QString("");
|
QString name = QString("");
|
||||||
QString text = QString("");
|
QString text = QString("");
|
||||||
QVariantHash properties = QVariantHash();
|
QVariantHash properties = QVariantHash();
|
||||||
|
@ -162,37 +165,39 @@ void CockatriceXml3Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
||||||
if (xml.readNext() == QXmlStreamReader::EndElement) {
|
if (xml.readNext() == QXmlStreamReader::EndElement) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
xmlName = xml.name().toString();
|
||||||
|
|
||||||
// variable - assigned properties
|
// variable - assigned properties
|
||||||
if (xml.name() == "name") {
|
if (xmlName == "name") {
|
||||||
name = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
name = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||||
} else if (xml.name() == "text") {
|
} else if (xmlName == "text") {
|
||||||
text = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
text = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||||
} else if (xml.name() == "color") {
|
} else if (xmlName == "color") {
|
||||||
colors.append(xml.readElementText(QXmlStreamReader::IncludeChildElements));
|
colors.append(xml.readElementText(QXmlStreamReader::IncludeChildElements));
|
||||||
} else if (xml.name() == "token") {
|
} else if (xmlName == "token") {
|
||||||
isToken = static_cast<bool>(xml.readElementText(QXmlStreamReader::IncludeChildElements).toInt());
|
isToken = static_cast<bool>(xml.readElementText(QXmlStreamReader::IncludeChildElements).toInt());
|
||||||
// generic properties
|
// generic properties
|
||||||
} else if (xml.name() == "manacost") {
|
} else if (xmlName == "manacost") {
|
||||||
properties.insert("manacost", xml.readElementText(QXmlStreamReader::IncludeChildElements));
|
properties.insert("manacost", xml.readElementText(QXmlStreamReader::IncludeChildElements));
|
||||||
} else if (xml.name() == "cmc") {
|
} else if (xmlName == "cmc") {
|
||||||
properties.insert("cmc", xml.readElementText(QXmlStreamReader::IncludeChildElements));
|
properties.insert("cmc", xml.readElementText(QXmlStreamReader::IncludeChildElements));
|
||||||
} else if (xml.name() == "type") {
|
} else if (xmlName == "type") {
|
||||||
QString type = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
QString type = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||||
properties.insert("type", type);
|
properties.insert("type", type);
|
||||||
properties.insert("maintype", getMainCardType(type));
|
properties.insert("maintype", getMainCardType(type));
|
||||||
} else if (xml.name() == "pt") {
|
} else if (xmlName == "pt") {
|
||||||
properties.insert("pt", xml.readElementText(QXmlStreamReader::IncludeChildElements));
|
properties.insert("pt", xml.readElementText(QXmlStreamReader::IncludeChildElements));
|
||||||
} else if (xml.name() == "loyalty") {
|
} else if (xmlName == "loyalty") {
|
||||||
properties.insert("loyalty", xml.readElementText(QXmlStreamReader::IncludeChildElements));
|
properties.insert("loyalty", xml.readElementText(QXmlStreamReader::IncludeChildElements));
|
||||||
// positioning info
|
// positioning info
|
||||||
} else if (xml.name() == "tablerow") {
|
} else if (xmlName == "tablerow") {
|
||||||
tableRow = xml.readElementText(QXmlStreamReader::IncludeChildElements).toInt();
|
tableRow = xml.readElementText(QXmlStreamReader::IncludeChildElements).toInt();
|
||||||
} else if (xml.name() == "cipt") {
|
} else if (xmlName == "cipt") {
|
||||||
cipt = (xml.readElementText(QXmlStreamReader::IncludeChildElements) == "1");
|
cipt = (xml.readElementText(QXmlStreamReader::IncludeChildElements) == "1");
|
||||||
} else if (xml.name() == "upsidedown") {
|
} else if (xmlName == "upsidedown") {
|
||||||
upsideDown = (xml.readElementText(QXmlStreamReader::IncludeChildElements) == "1");
|
upsideDown = (xml.readElementText(QXmlStreamReader::IncludeChildElements) == "1");
|
||||||
// sets
|
// sets
|
||||||
} else if (xml.name() == "set") {
|
} else if (xmlName == "set") {
|
||||||
// NOTE: attributes must be read before readElementText()
|
// NOTE: attributes must be read before readElementText()
|
||||||
QXmlStreamAttributes attrs = xml.attributes();
|
QXmlStreamAttributes attrs = xml.attributes();
|
||||||
QString setName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
QString setName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||||
|
@ -217,8 +222,8 @@ void CockatriceXml3Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
||||||
setInfo.setProperty("rarity", attrs.value("rarity").toString());
|
setInfo.setProperty("rarity", attrs.value("rarity").toString());
|
||||||
}
|
}
|
||||||
sets.insert(setName, setInfo);
|
sets.insert(setName, setInfo);
|
||||||
// relatd cards
|
// related cards
|
||||||
} else if (xml.name() == "related" || xml.name() == "reverse-related") {
|
} else if (xmlName == "related" || xmlName == "reverse-related") {
|
||||||
bool attach = false;
|
bool attach = false;
|
||||||
bool exclude = false;
|
bool exclude = false;
|
||||||
bool variable = false;
|
bool variable = false;
|
||||||
|
@ -249,13 +254,13 @@ void CockatriceXml3Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *relation = new CardRelation(cardName, attach, exclude, variable, count);
|
auto *relation = new CardRelation(cardName, attach, exclude, variable, count);
|
||||||
if (xml.name() == "reverse-related") {
|
if (xmlName == "reverse-related") {
|
||||||
reverseRelatedCards << relation;
|
reverseRelatedCards << relation;
|
||||||
} else {
|
} else {
|
||||||
relatedCards << relation;
|
relatedCards << relation;
|
||||||
}
|
}
|
||||||
} else if (xml.name() != "") {
|
} else if (!xmlName.isEmpty()) {
|
||||||
qDebug() << "[CockatriceXml3Parser] Unknown card property" << xml.name()
|
qDebug() << "[CockatriceXml3Parser] Unknown card property" << xmlName
|
||||||
<< ", trying to continue anyway";
|
<< ", trying to continue anyway";
|
||||||
xml.skipCurrentElement();
|
xml.skipCurrentElement();
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ bool CockatriceXml4Parser::getCanParseFile(const QString &fileName, QIODevice &d
|
||||||
QXmlStreamReader xml(&device);
|
QXmlStreamReader xml(&device);
|
||||||
while (!xml.atEnd()) {
|
while (!xml.atEnd()) {
|
||||||
if (xml.readNext() == QXmlStreamReader::StartElement) {
|
if (xml.readNext() == QXmlStreamReader::StartElement) {
|
||||||
if (xml.name() == COCKATRICE_XML4_TAGNAME) {
|
if (xml.name().toString() == COCKATRICE_XML4_TAGNAME) {
|
||||||
int version = xml.attributes().value("version").toString().toInt();
|
int version = xml.attributes().value("version").toString().toInt();
|
||||||
if (version == COCKATRICE_XML4_TAGVER) {
|
if (version == COCKATRICE_XML4_TAGVER) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -52,12 +52,13 @@ void CockatriceXml4Parser::parseFile(QIODevice &device)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xml.name() == "sets") {
|
auto xmlName = xml.name().toString();
|
||||||
|
if (xmlName == "sets") {
|
||||||
loadSetsFromXml(xml);
|
loadSetsFromXml(xml);
|
||||||
} else if (xml.name() == "cards") {
|
} else if (xmlName == "cards") {
|
||||||
loadCardsFromXml(xml);
|
loadCardsFromXml(xml);
|
||||||
} else if (xml.name() != "") {
|
} else if (!xmlName.isEmpty()) {
|
||||||
qDebug() << "[CockatriceXml4Parser] Unknown item" << xml.name() << ", trying to continue anyway";
|
qDebug() << "[CockatriceXml4Parser] Unknown item" << xmlName << ", trying to continue anyway";
|
||||||
xml.skipCurrentElement();
|
xml.skipCurrentElement();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,25 +73,27 @@ void CockatriceXml4Parser::loadSetsFromXml(QXmlStreamReader &xml)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xml.name() == "set") {
|
auto xmlName = xml.name().toString();
|
||||||
|
if (xmlName == "set") {
|
||||||
QString shortName, longName, setType;
|
QString shortName, longName, setType;
|
||||||
QDate releaseDate;
|
QDate releaseDate;
|
||||||
while (!xml.atEnd()) {
|
while (!xml.atEnd()) {
|
||||||
if (xml.readNext() == QXmlStreamReader::EndElement) {
|
if (xml.readNext() == QXmlStreamReader::EndElement) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
xmlName = xml.name().toString();
|
||||||
|
|
||||||
if (xml.name() == "name") {
|
if (xmlName == "name") {
|
||||||
shortName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
shortName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||||
} else if (xml.name() == "longname") {
|
} else if (xmlName == "longname") {
|
||||||
longName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
longName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||||
} else if (xml.name() == "settype") {
|
} else if (xmlName == "settype") {
|
||||||
setType = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
setType = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||||
} else if (xml.name() == "releasedate") {
|
} else if (xmlName == "releasedate") {
|
||||||
releaseDate =
|
releaseDate =
|
||||||
QDate::fromString(xml.readElementText(QXmlStreamReader::IncludeChildElements), Qt::ISODate);
|
QDate::fromString(xml.readElementText(QXmlStreamReader::IncludeChildElements), Qt::ISODate);
|
||||||
} else if (xml.name() != "") {
|
} else if (!xmlName.isEmpty()) {
|
||||||
qDebug() << "[CockatriceXml4Parser] Unknown set property" << xml.name()
|
qDebug() << "[CockatriceXml4Parser] Unknown set property" << xmlName
|
||||||
<< ", trying to continue anyway";
|
<< ", trying to continue anyway";
|
||||||
xml.skipCurrentElement();
|
xml.skipCurrentElement();
|
||||||
}
|
}
|
||||||
|
@ -109,8 +112,9 @@ QVariantHash CockatriceXml4Parser::loadCardPropertiesFromXml(QXmlStreamReader &x
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xml.name() != "") {
|
auto xmlName = xml.name().toString();
|
||||||
properties.insert(xml.name().toString(), xml.readElementText(QXmlStreamReader::IncludeChildElements));
|
if (!xmlName.isEmpty()) {
|
||||||
|
properties.insert(xmlName, xml.readElementText(QXmlStreamReader::IncludeChildElements));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return properties;
|
return properties;
|
||||||
|
@ -123,7 +127,9 @@ void CockatriceXml4Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xml.name() == "card") {
|
auto xmlName = xml.name().toString();
|
||||||
|
|
||||||
|
if (xmlName == "card") {
|
||||||
QString name = QString("");
|
QString name = QString("");
|
||||||
QString text = QString("");
|
QString text = QString("");
|
||||||
QVariantHash properties = QVariantHash();
|
QVariantHash properties = QVariantHash();
|
||||||
|
@ -138,25 +144,28 @@ void CockatriceXml4Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
||||||
if (xml.readNext() == QXmlStreamReader::EndElement) {
|
if (xml.readNext() == QXmlStreamReader::EndElement) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xmlName = xml.name().toString();
|
||||||
|
|
||||||
// variable - assigned properties
|
// variable - assigned properties
|
||||||
if (xml.name() == "name") {
|
if (xmlName == "name") {
|
||||||
name = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
name = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||||
} else if (xml.name() == "text") {
|
} else if (xmlName == "text") {
|
||||||
text = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
text = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||||
} else if (xml.name() == "token") {
|
} else if (xmlName == "token") {
|
||||||
isToken = static_cast<bool>(xml.readElementText(QXmlStreamReader::IncludeChildElements).toInt());
|
isToken = static_cast<bool>(xml.readElementText(QXmlStreamReader::IncludeChildElements).toInt());
|
||||||
// generic properties
|
// generic properties
|
||||||
} else if (xml.name() == "prop") {
|
} else if (xmlName == "prop") {
|
||||||
properties = loadCardPropertiesFromXml(xml);
|
properties = loadCardPropertiesFromXml(xml);
|
||||||
// positioning info
|
// positioning info
|
||||||
} else if (xml.name() == "tablerow") {
|
} else if (xmlName == "tablerow") {
|
||||||
tableRow = xml.readElementText(QXmlStreamReader::IncludeChildElements).toInt();
|
tableRow = xml.readElementText(QXmlStreamReader::IncludeChildElements).toInt();
|
||||||
} else if (xml.name() == "cipt") {
|
} else if (xmlName == "cipt") {
|
||||||
cipt = (xml.readElementText(QXmlStreamReader::IncludeChildElements) == "1");
|
cipt = (xml.readElementText(QXmlStreamReader::IncludeChildElements) == "1");
|
||||||
} else if (xml.name() == "upsidedown") {
|
} else if (xmlName == "upsidedown") {
|
||||||
upsideDown = (xml.readElementText(QXmlStreamReader::IncludeChildElements) == "1");
|
upsideDown = (xml.readElementText(QXmlStreamReader::IncludeChildElements) == "1");
|
||||||
// sets
|
// sets
|
||||||
} else if (xml.name() == "set") {
|
} else if (xmlName == "set") {
|
||||||
// NOTE: attributes but be read before readElementText()
|
// NOTE: attributes but be read before readElementText()
|
||||||
QXmlStreamAttributes attrs = xml.attributes();
|
QXmlStreamAttributes attrs = xml.attributes();
|
||||||
QString setName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
QString setName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||||
|
@ -171,8 +180,8 @@ void CockatriceXml4Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
||||||
}
|
}
|
||||||
sets.insert(setName, setInfo);
|
sets.insert(setName, setInfo);
|
||||||
}
|
}
|
||||||
// relatd cards
|
// related cards
|
||||||
} else if (xml.name() == "related" || xml.name() == "reverse-related") {
|
} else if (xmlName == "related" || xmlName == "reverse-related") {
|
||||||
bool attach = false;
|
bool attach = false;
|
||||||
bool exclude = false;
|
bool exclude = false;
|
||||||
bool variable = false;
|
bool variable = false;
|
||||||
|
@ -203,13 +212,13 @@ void CockatriceXml4Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *relation = new CardRelation(cardName, attach, exclude, variable, count);
|
auto *relation = new CardRelation(cardName, attach, exclude, variable, count);
|
||||||
if (xml.name() == "reverse-related") {
|
if (xmlName == "reverse-related") {
|
||||||
reverseRelatedCards << relation;
|
reverseRelatedCards << relation;
|
||||||
} else {
|
} else {
|
||||||
relatedCards << relation;
|
relatedCards << relation;
|
||||||
}
|
}
|
||||||
} else if (xml.name() != "") {
|
} else if (!xmlName.isEmpty()) {
|
||||||
qDebug() << "[CockatriceXml4Parser] Unknown card property" << xml.name()
|
qDebug() << "[CockatriceXml4Parser] Unknown card property" << xmlName
|
||||||
<< ", trying to continue anyway";
|
<< ", trying to continue anyway";
|
||||||
xml.skipCurrentElement();
|
xml.skipCurrentElement();
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,13 +6,9 @@
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <utility>
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 13, 0))
|
|
||||||
#include <QScreen>
|
#include <QScreen>
|
||||||
#else
|
|
||||||
#include <QDesktopWidget>
|
|
||||||
#endif
|
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
CardInfoWidget::CardInfoWidget(const QString &cardName, QWidget *parent, Qt::WindowFlags flags)
|
CardInfoWidget::CardInfoWidget(const QString &cardName, QWidget *parent, Qt::WindowFlags flags)
|
||||||
: QFrame(parent, flags), aspectRatio((qreal)CARD_HEIGHT / (qreal)CARD_WIDTH), info(nullptr)
|
: QFrame(parent, flags), aspectRatio((qreal)CARD_HEIGHT / (qreal)CARD_WIDTH), info(nullptr)
|
||||||
|
@ -34,12 +30,7 @@ CardInfoWidget::CardInfoWidget(const QString &cardName, QWidget *parent, Qt::Win
|
||||||
|
|
||||||
setFrameStyle(QFrame::Panel | QFrame::Raised);
|
setFrameStyle(QFrame::Panel | QFrame::Raised);
|
||||||
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 13, 0))
|
int pixmapHeight = QGuiApplication::primaryScreen()->geometry().height() / 3;
|
||||||
int pixmapHeight = qApp->primaryScreen()->geometry().height() / 3;
|
|
||||||
#else
|
|
||||||
QDesktopWidget desktopWidget;
|
|
||||||
int pixmapHeight = desktopWidget.screenGeometry().height() / 3;
|
|
||||||
#endif
|
|
||||||
int pixmapWidth = static_cast<int>(pixmapHeight / aspectRatio);
|
int pixmapWidth = static_cast<int>(pixmapHeight / aspectRatio);
|
||||||
pic->setFixedWidth(pixmapWidth);
|
pic->setFixedWidth(pixmapWidth);
|
||||||
pic->setFixedHeight(pixmapHeight);
|
pic->setFixedHeight(pixmapHeight);
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define CARDITEM_H
|
#define CARDITEM_H
|
||||||
|
|
||||||
#include "abstractcarditem.h"
|
#include "abstractcarditem.h"
|
||||||
|
#include "server_card.h"
|
||||||
|
|
||||||
class CardDatabase;
|
class CardDatabase;
|
||||||
class CardDragItem;
|
class CardDragItem;
|
||||||
|
|
|
@ -321,7 +321,7 @@ void ChatView::checkTag(QTextCursor &cursor, QString &message)
|
||||||
|
|
||||||
void ChatView::checkMention(QTextCursor &cursor, QString &message, const QString &userName, UserLevelFlags userLevel)
|
void ChatView::checkMention(QTextCursor &cursor, QString &message, const QString &userName, UserLevelFlags userLevel)
|
||||||
{
|
{
|
||||||
const QRegExp notALetterOrNumber = QRegExp("[^a-zA-Z0-9]");
|
const static auto notALetterOrNumber = QRegularExpression("[^a-zA-Z0-9]");
|
||||||
|
|
||||||
int firstSpace = message.indexOf(' ');
|
int firstSpace = message.indexOf(' ');
|
||||||
QString fullMentionUpToSpaceOrEnd = (firstSpace == -1) ? message.mid(1) : message.mid(1, firstSpace - 1);
|
QString fullMentionUpToSpaceOrEnd = (firstSpace == -1) ? message.mid(1) : message.mid(1, firstSpace - 1);
|
||||||
|
@ -510,7 +510,11 @@ 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*/)
|
void ChatView::enterEvent(QEvent * /*event*/)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
}
|
}
|
||||||
|
@ -566,7 +570,11 @@ void ChatView::mousePressEvent(QMouseEvent *event)
|
||||||
switch (hoveredItemType) {
|
switch (hoveredItemType) {
|
||||||
case HoveredCard: {
|
case HoveredCard: {
|
||||||
if ((event->button() == Qt::MiddleButton) || (event->button() == Qt::LeftButton))
|
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);
|
emit showCardInfoPopup(event->globalPos(), hoveredContent);
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case HoveredUser: {
|
case HoveredUser: {
|
||||||
|
@ -576,7 +584,11 @@ void ChatView::mousePressEvent(QMouseEvent *event)
|
||||||
switch (event->button()) {
|
switch (event->button()) {
|
||||||
case Qt::RightButton: {
|
case Qt::RightButton: {
|
||||||
UserLevelFlags userLevel(hoveredContent.left(delimiterIndex).toInt());
|
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);
|
userContextMenu->showContextMenu(event->globalPos(), userName, userLevel, this);
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Qt::LeftButton: {
|
case Qt::LeftButton: {
|
||||||
|
|
|
@ -103,7 +103,11 @@ public:
|
||||||
void redactMessages(const QString &userName, int amount);
|
void redactMessages(const QString &userName, int amount);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
void enterEvent(QEnterEvent *event);
|
||||||
|
#else
|
||||||
void enterEvent(QEvent *event);
|
void enterEvent(QEvent *event);
|
||||||
|
#endif
|
||||||
void leaveEvent(QEvent *event);
|
void leaveEvent(QEvent *event);
|
||||||
void mouseMoveEvent(QMouseEvent *event);
|
void mouseMoveEvent(QMouseEvent *event);
|
||||||
void mousePressEvent(QMouseEvent *event);
|
void mousePressEvent(QMouseEvent *event);
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
#include <QRegularExpression>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
|
||||||
const QStringList DeckLoader::fileNameFilters = QStringList()
|
const QStringList DeckLoader::fileNameFilters = QStringList()
|
||||||
|
@ -208,7 +209,7 @@ void DeckLoader::saveToStream_DeckHeader(QTextStream &out)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!getComments().isEmpty()) {
|
if (!getComments().isEmpty()) {
|
||||||
QStringList commentRows = getComments().split(QRegExp("\n|\r\n|\r"));
|
QStringList commentRows = getComments().split(QRegularExpression("\n|\r\n|\r"));
|
||||||
foreach (QString row, commentRows) {
|
foreach (QString row, commentRows) {
|
||||||
out << "// " << row << "\n";
|
out << "// " << row << "\n";
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QGraphicsSceneMouseEvent>
|
#include <QGraphicsSceneMouseEvent>
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
|
#include <QtMath>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
DeckViewCardDragItem::DeckViewCardDragItem(DeckViewCard *_item,
|
DeckViewCardDragItem::DeckViewCardDragItem(DeckViewCard *_item,
|
||||||
const QPointF &_hotSpot,
|
const QPointF &_hotSpot,
|
||||||
|
@ -238,11 +238,9 @@ int DeckViewCardContainer::getCardTypeTextWidth() const
|
||||||
QFontMetrics fm(f);
|
QFontMetrics fm(f);
|
||||||
|
|
||||||
int maxCardTypeWidth = 0;
|
int maxCardTypeWidth = 0;
|
||||||
QMapIterator<QString, DeckViewCard *> i(cardsByType);
|
for (const auto &key : cardsByType.keys()) {
|
||||||
while (i.hasNext()) {
|
int cardTypeWidth = fm.size(Qt::TextSingleLine, key).width();
|
||||||
int cardTypeWidth = fm.size(Qt::TextSingleLine, i.next().key()).width();
|
maxCardTypeWidth = qMax(maxCardTypeWidth, cardTypeWidth);
|
||||||
if (cardTypeWidth > maxCardTypeWidth)
|
|
||||||
maxCardTypeWidth = cardTypeWidth;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return maxCardTypeWidth + 15;
|
return maxCardTypeWidth + 15;
|
||||||
|
@ -440,7 +438,7 @@ void DeckViewScene::rearrangeItems()
|
||||||
const int maxRows = rowsAndColsList[maxIndex1][maxIndex2].first;
|
const int maxRows = rowsAndColsList[maxIndex1][maxIndex2].first;
|
||||||
const int maxCardCount = cardCountList[maxIndex1][maxIndex2];
|
const int maxCardCount = cardCountList[maxIndex1][maxIndex2];
|
||||||
rowsAndColsList[maxIndex1][maxIndex2] =
|
rowsAndColsList[maxIndex1][maxIndex2] =
|
||||||
QPair<int, int>(maxRows + 1, (int)ceil((qreal)maxCardCount / (qreal)(maxRows + 1)));
|
QPair<int, int>(maxRows + 1, (int)qCeil((qreal)maxCardCount / (qreal)(maxRows + 1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
totalHeight = -spacing;
|
totalHeight = -spacing;
|
||||||
|
|
|
@ -162,8 +162,7 @@ DlgConnect::DlgConnect(QWidget *parent) : QDialog(parent)
|
||||||
|
|
||||||
previousHostButton->setChecked(true);
|
previousHostButton->setChecked(true);
|
||||||
|
|
||||||
connect(previousHosts, SIGNAL(currentIndexChanged(const QString &)), this,
|
connect(previousHosts, SIGNAL(currentTextChanged(const QString &)), this, SLOT(updateDisplayInfo(const QString &)));
|
||||||
SLOT(updateDisplayInfo(const QString &)));
|
|
||||||
|
|
||||||
playernameEdit->setFocus();
|
playernameEdit->setFocus();
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,7 +121,12 @@ WndSets::WndSets(QWidget *parent) : QMainWindow(parent)
|
||||||
connect(disableSomeButton, SIGNAL(clicked()), this, SLOT(actDisableSome()));
|
connect(disableSomeButton, SIGNAL(clicked()), this, SLOT(actDisableSome()));
|
||||||
connect(view->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), this,
|
connect(view->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), this,
|
||||||
SLOT(actToggleButtons(const QItemSelection &, const QItemSelection &)));
|
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 &)));
|
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(view->header(), SIGNAL(sortIndicatorChanged(int, Qt::SortOrder)), this, SLOT(actDisableSortButtons(int)));
|
||||||
connect(searchField, SIGNAL(textChanged(const QString &)), this, SLOT(actDisableResetButton(const QString &)));
|
connect(searchField, SIGNAL(textChanged(const QString &)), this, SLOT(actDisableResetButton(const QString &)));
|
||||||
|
|
||||||
|
@ -139,7 +144,6 @@ WndSets::WndSets(QWidget *parent) : QMainWindow(parent)
|
||||||
tr("How to use custom card art") + "</a>"));
|
tr("How to use custom card art") + "</a>"));
|
||||||
|
|
||||||
QGridLayout *hintsGrid = new QGridLayout;
|
QGridLayout *hintsGrid = new QGridLayout;
|
||||||
hintsGrid->setMargin(2);
|
|
||||||
hintsGrid->addWidget(labNotes, 0, 0);
|
hintsGrid->addWidget(labNotes, 0, 0);
|
||||||
hintsGroupBox = new QGroupBox(tr("Hints"));
|
hintsGroupBox = new QGroupBox(tr("Hints"));
|
||||||
hintsGroupBox->setLayout(hintsGrid);
|
hintsGroupBox->setLayout(hintsGrid);
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
#include <QDesktopWidget>
|
|
||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QGridLayout>
|
#include <QGridLayout>
|
||||||
|
@ -44,18 +43,22 @@
|
||||||
|
|
||||||
GeneralSettingsPage::GeneralSettingsPage()
|
GeneralSettingsPage::GeneralSettingsPage()
|
||||||
{
|
{
|
||||||
SettingsCache &settings = SettingsCache::instance();
|
QStringList languageCodes = findQmFiles();
|
||||||
QString setLanguage = settings.getLang();
|
for (const QString &code : languageCodes) {
|
||||||
QStringList qmFiles = findQmFiles();
|
QString langName = languageName(code);
|
||||||
for (int i = 0; i < qmFiles.size(); i++) {
|
languageBox.addItem(langName, code);
|
||||||
QString langName = languageName(qmFiles[i]);
|
}
|
||||||
languageBox.addItem(langName, qmFiles[i]);
|
|
||||||
if ((qmFiles[i] == setLanguage) ||
|
QString setLanguage = QCoreApplication::translate("i18n", DEFAULT_LANG_NAME);
|
||||||
(setLanguage.isEmpty() && langName == QCoreApplication::translate("i18n", DEFAULT_LANG_NAME)))
|
int index = languageBox.findText(setLanguage, Qt::MatchExactly);
|
||||||
languageBox.setCurrentIndex(i);
|
if (index == -1) {
|
||||||
|
qWarning() << "could not find language" << setLanguage;
|
||||||
|
} else {
|
||||||
|
languageBox.setCurrentIndex(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// updates
|
// updates
|
||||||
|
SettingsCache &settings = SettingsCache::instance();
|
||||||
QList<ReleaseChannel *> channels = settings.getUpdateReleaseChannels();
|
QList<ReleaseChannel *> channels = settings.getUpdateReleaseChannels();
|
||||||
foreach (ReleaseChannel *chan, channels) {
|
foreach (ReleaseChannel *chan, channels) {
|
||||||
updateReleaseChannelBox.insertItem(chan->getIndex(), tr(chan->getName().toUtf8()));
|
updateReleaseChannelBox.insertItem(chan->getIndex(), tr(chan->getName().toUtf8()));
|
||||||
|
@ -186,15 +189,20 @@ QStringList GeneralSettingsPage::findQmFiles()
|
||||||
{
|
{
|
||||||
QDir dir(translationPath);
|
QDir dir(translationPath);
|
||||||
QStringList fileNames = dir.entryList(QStringList(translationPrefix + "_*.qm"), QDir::Files, QDir::Name);
|
QStringList fileNames = dir.entryList(QStringList(translationPrefix + "_*.qm"), QDir::Files, QDir::Name);
|
||||||
fileNames.replaceInStrings(QRegExp(translationPrefix + "_(.*)\\.qm"), "\\1");
|
fileNames.replaceInStrings(QRegularExpression(translationPrefix + "_(.*)\\.qm"), "\\1");
|
||||||
fileNames.removeOne("en@source");
|
|
||||||
return fileNames;
|
return fileNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString GeneralSettingsPage::languageName(const QString &qmFile)
|
QString GeneralSettingsPage::languageName(const QString &lang)
|
||||||
{
|
{
|
||||||
QTranslator qTranslator;
|
QTranslator qTranslator;
|
||||||
qTranslator.load(translationPrefix + "_" + qmFile + ".qm", translationPath);
|
|
||||||
|
QString appNameHint = translationPrefix + "_" + lang;
|
||||||
|
bool appTranslationLoaded = qTranslator.load(appNameHint, translationPath);
|
||||||
|
if (!appTranslationLoaded) {
|
||||||
|
qDebug() << "Unable to load" << translationPrefix << "translation" << appNameHint << "at" << translationPath;
|
||||||
|
}
|
||||||
|
|
||||||
return qTranslator.translate("i18n", DEFAULT_LANG_NAME);
|
return qTranslator.translate("i18n", DEFAULT_LANG_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1235,11 +1243,7 @@ void ShortcutSettingsPage::retranslateUi()
|
||||||
|
|
||||||
DlgSettings::DlgSettings(QWidget *parent) : QDialog(parent)
|
DlgSettings::DlgSettings(QWidget *parent) : QDialog(parent)
|
||||||
{
|
{
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 13, 0))
|
auto rec = QGuiApplication::primaryScreen()->availableGeometry();
|
||||||
auto rec = qApp->primaryScreen()->availableGeometry();
|
|
||||||
#else
|
|
||||||
auto rec = QApplication::desktop()->availableGeometry();
|
|
||||||
#endif
|
|
||||||
this->setMinimumSize(qMin(700, rec.width()), qMin(700, rec.height()));
|
this->setMinimumSize(qMin(700, rec.width()), qMin(700, rec.height()));
|
||||||
|
|
||||||
connect(&SettingsCache::instance(), SIGNAL(langChanged()), this, SLOT(updateLanguage()));
|
connect(&SettingsCache::instance(), SIGNAL(langChanged()), this, SLOT(updateLanguage()));
|
||||||
|
|
|
@ -49,7 +49,7 @@ private slots:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QStringList findQmFiles();
|
QStringList findQmFiles();
|
||||||
QString languageName(const QString &qmFile);
|
QString languageName(const QString &lang);
|
||||||
QLineEdit *deckPathEdit;
|
QLineEdit *deckPathEdit;
|
||||||
QLineEdit *replaysPathEdit;
|
QLineEdit *replaysPathEdit;
|
||||||
QLineEdit *picsPathEdit;
|
QLineEdit *picsPathEdit;
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <cmath>
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
peg::parser search(R"(
|
peg::parser search(R"(
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
#include <QGraphicsSceneMouseEvent>
|
#include <QGraphicsSceneMouseEvent>
|
||||||
#include <QGraphicsView>
|
#include <QGraphicsView>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
#include <math.h>
|
#include <QtMath>
|
||||||
|
|
||||||
GameScene::GameScene(PhasesToolbar *_phasesToolbar, QObject *parent)
|
GameScene::GameScene(PhasesToolbar *_phasesToolbar, QObject *parent)
|
||||||
: QGraphicsScene(parent), phasesToolbar(_phasesToolbar), viewSize(QSize()), playerRotation(0)
|
: QGraphicsScene(parent), phasesToolbar(_phasesToolbar), viewSize(QSize()), playerRotation(0)
|
||||||
|
@ -97,7 +97,7 @@ void GameScene::rearrange()
|
||||||
|
|
||||||
const int playersCount = playersPlaying.size();
|
const int playersCount = playersPlaying.size();
|
||||||
const int columns = playersCount < SettingsCache::instance().getMinPlayersForMultiColumnLayout() ? 1 : 2;
|
const int columns = playersCount < SettingsCache::instance().getMinPlayersForMultiColumnLayout() ? 1 : 2;
|
||||||
const int rows = ceil((qreal)playersCount / columns);
|
const int rows = qCeil((qreal)playersCount / columns);
|
||||||
qreal sceneHeight = 0, sceneWidth = -playerAreaSpacing;
|
qreal sceneHeight = 0, sceneWidth = -playerAreaSpacing;
|
||||||
QList<int> columnWidth;
|
QList<int> columnWidth;
|
||||||
|
|
||||||
|
|
|
@ -93,11 +93,7 @@ QVariant GamesModel::data(const QModelIndex &index, int role) const
|
||||||
case CREATED: {
|
case CREATED: {
|
||||||
switch (role) {
|
switch (role) {
|
||||||
case Qt::DisplayRole: {
|
case Qt::DisplayRole: {
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0))
|
|
||||||
QDateTime then = QDateTime::fromSecsSinceEpoch(gameentry.start_time(), Qt::UTC);
|
QDateTime then = QDateTime::fromSecsSinceEpoch(gameentry.start_time(), Qt::UTC);
|
||||||
#else
|
|
||||||
QDateTime then = QDateTime::fromTime_t(gameentry.start_time(), Qt::UTC);
|
|
||||||
#endif
|
|
||||||
int secs = then.secsTo(QDateTime::currentDateTimeUtc());
|
int secs = then.secsTo(QDateTime::currentDateTimeUtc());
|
||||||
return getGameCreatedString(secs);
|
return getGameCreatedString(secs);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,10 @@ void HandZone::updateBg()
|
||||||
|
|
||||||
void HandZone::addCardImpl(CardItem *card, int x, int /*y*/)
|
void HandZone::addCardImpl(CardItem *card, int x, int /*y*/)
|
||||||
{
|
{
|
||||||
if (x == -1)
|
// if x is negative set it to add at end
|
||||||
|
if (x < 0 || x >= cards.size()) {
|
||||||
x = cards.size();
|
x = cards.size();
|
||||||
|
}
|
||||||
cards.insert(x, card);
|
cards.insert(x, card);
|
||||||
|
|
||||||
if (!cards.getContentsKnown()) {
|
if (!cards.getContentsKnown()) {
|
||||||
|
|
|
@ -12,8 +12,9 @@ LocalServer::LocalServer(QObject *parent) : Server(parent)
|
||||||
LocalServer::~LocalServer()
|
LocalServer::~LocalServer()
|
||||||
{
|
{
|
||||||
// LocalServer is single threaded so it doesn't need locks on this
|
// LocalServer is single threaded so it doesn't need locks on this
|
||||||
while (!clients.isEmpty())
|
for (auto *client : clients) {
|
||||||
clients.first()->prepareDestroy();
|
client->prepareDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
prepareDestroy();
|
prepareDestroy();
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ protected:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LocalServer_DatabaseInterface(LocalServer *_localServer);
|
LocalServer_DatabaseInterface(LocalServer *_localServer);
|
||||||
|
~LocalServer_DatabaseInterface() = default;
|
||||||
AuthenticationResult checkUserPassword(Server_ProtocolHandler *handler,
|
AuthenticationResult checkUserPassword(Server_ProtocolHandler *handler,
|
||||||
const QString &user,
|
const QString &user,
|
||||||
const QString &password,
|
const QString &password,
|
||||||
|
|
|
@ -67,11 +67,29 @@ void installNewTranslator()
|
||||||
{
|
{
|
||||||
QString lang = SettingsCache::instance().getLang();
|
QString lang = SettingsCache::instance().getLang();
|
||||||
|
|
||||||
qtTranslator->load("qt_" + lang, QLibraryInfo::location(QLibraryInfo::TranslationsPath));
|
QString qtNameHint = "qt_" + lang;
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
QString qtTranslationPath = QLibraryInfo::path(QLibraryInfo::TranslationsPath);
|
||||||
|
#else
|
||||||
|
QString qtTranslationPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool qtTranslationLoaded = qtTranslator->load(qtNameHint, qtTranslationPath);
|
||||||
|
if (!qtTranslationLoaded) {
|
||||||
|
qDebug() << "Unable to load qt translation" << qtNameHint << "at" << qtTranslationPath;
|
||||||
|
} else {
|
||||||
|
qDebug() << "Loaded qt translation" << qtNameHint << "at" << qtTranslationPath;
|
||||||
|
}
|
||||||
qApp->installTranslator(qtTranslator);
|
qApp->installTranslator(qtTranslator);
|
||||||
translator->load(translationPrefix + "_" + lang, translationPath);
|
|
||||||
|
QString appNameHint = translationPrefix + "_" + lang;
|
||||||
|
bool appTranslationLoaded = qtTranslator->load(appNameHint, translationPath);
|
||||||
|
if (!appTranslationLoaded) {
|
||||||
|
qDebug() << "Unable to load" << translationPrefix << "translation" << appNameHint << "at" << translationPath;
|
||||||
|
} else {
|
||||||
|
qDebug() << "Loaded" << translationPrefix << "translation" << appNameHint << "at" << translationPath;
|
||||||
|
}
|
||||||
qApp->installTranslator(translator);
|
qApp->installTranslator(translator);
|
||||||
qDebug() << "Language changed:" << lang;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString const generateClientID()
|
QString const generateClientID()
|
||||||
|
@ -165,7 +183,9 @@ int main(int argc, char *argv[])
|
||||||
ui.show();
|
ui.show();
|
||||||
qDebug("main(): ui.show() finished");
|
qDebug("main(): ui.show() finished");
|
||||||
|
|
||||||
|
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||||
app.setAttribute(Qt::AA_UseHighDpiPixmaps);
|
app.setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||||
|
#endif
|
||||||
app.exec();
|
app.exec();
|
||||||
|
|
||||||
qDebug("Event loop finished, terminating...");
|
qDebug("Event loop finished, terminating...");
|
||||||
|
|
|
@ -44,6 +44,10 @@ void PileZone::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*optio
|
||||||
void PileZone::addCardImpl(CardItem *card, int x, int /*y*/)
|
void PileZone::addCardImpl(CardItem *card, int x, int /*y*/)
|
||||||
{
|
{
|
||||||
connect(card, SIGNAL(sigPixmapUpdated()), this, SLOT(callUpdate()));
|
connect(card, SIGNAL(sigPixmapUpdated()), this, SLOT(callUpdate()));
|
||||||
|
// if x is negative set it to add at end
|
||||||
|
if (x < 0 || x >= cards.size()) {
|
||||||
|
x = cards.size();
|
||||||
|
}
|
||||||
cards.insert(x, card);
|
cards.insert(x, card);
|
||||||
card->setPos(0, 0);
|
card->setPos(0, 0);
|
||||||
if (!contentsKnown()) {
|
if (!contentsKnown()) {
|
||||||
|
|
|
@ -99,7 +99,7 @@ QMap<QString, QPixmap> CountryPixmapGenerator::pmCache;
|
||||||
QPixmap UserLevelPixmapGenerator::generatePixmap(int height, UserLevelFlags userLevel, bool isBuddy, QString privLevel)
|
QPixmap UserLevelPixmapGenerator::generatePixmap(int height, UserLevelFlags userLevel, bool isBuddy, QString privLevel)
|
||||||
{
|
{
|
||||||
|
|
||||||
QString key = QString::number(height * 10000) + ":" + (int)userLevel + ":" + (int)isBuddy + ":" + privLevel;
|
QString key = QString::number(height * 10000) + ":" + (short)userLevel + ":" + (short)isBuddy + ":" + privLevel;
|
||||||
if (pmCache.contains(key))
|
if (pmCache.contains(key))
|
||||||
return pmCache.value(key);
|
return pmCache.value(key);
|
||||||
|
|
||||||
|
|
|
@ -66,6 +66,7 @@
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
|
#include <QMetaType>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <QRegularExpressionMatch>
|
#include <QRegularExpressionMatch>
|
||||||
|
@ -3066,7 +3067,11 @@ void Player::actSetPT()
|
||||||
const auto oldpt = parsePT(card->getPT());
|
const auto oldpt = parsePT(card->getPT());
|
||||||
int ptIter = 0;
|
int ptIter = 0;
|
||||||
for (const auto &item : ptList) {
|
for (const auto &item : ptList) {
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
if (item.typeId() == QMetaType::Type::Int) {
|
||||||
|
#else
|
||||||
if (item.type() == QVariant::Int) {
|
if (item.type() == QVariant::Int) {
|
||||||
|
#endif
|
||||||
int oldItem = ptIter < oldpt.size() ? oldpt.at(ptIter).toInt() : 0;
|
int oldItem = ptIter < oldpt.size() ? oldpt.at(ptIter).toInt() : 0;
|
||||||
newpt += '/' + QString::number(oldItem + item.toInt());
|
newpt += '/' + QString::number(oldItem + item.toInt());
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -28,7 +28,11 @@ bool PlayerListItemDelegate::editorEvent(QEvent *event,
|
||||||
if ((event->type() == QEvent::MouseButtonPress) && index.isValid()) {
|
if ((event->type() == QEvent::MouseButtonPress) && index.isValid()) {
|
||||||
QMouseEvent *const mouseEvent = static_cast<QMouseEvent *>(event);
|
QMouseEvent *const mouseEvent = static_cast<QMouseEvent *>(event);
|
||||||
if (mouseEvent->button() == Qt::RightButton) {
|
if (mouseEvent->button() == Qt::RightButton) {
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
static_cast<PlayerListWidget *>(parent())->showContextMenu(mouseEvent->globalPosition().toPoint(), index);
|
||||||
|
#else
|
||||||
static_cast<PlayerListWidget *>(parent())->showContextMenu(mouseEvent->globalPos(), index);
|
static_cast<PlayerListWidget *>(parent())->showContextMenu(mouseEvent->globalPos(), index);
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,10 +23,9 @@
|
||||||
|
|
||||||
int ReleaseChannel::sharedIndex = 0;
|
int ReleaseChannel::sharedIndex = 0;
|
||||||
|
|
||||||
ReleaseChannel::ReleaseChannel() : response(nullptr), lastRelease(nullptr)
|
ReleaseChannel::ReleaseChannel() : netMan(new QNetworkAccessManager(this)), response(nullptr), lastRelease(nullptr)
|
||||||
{
|
{
|
||||||
index = sharedIndex++;
|
index = sharedIndex++;
|
||||||
netMan = new QNetworkAccessManager(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReleaseChannel::~ReleaseChannel()
|
ReleaseChannel::~ReleaseChannel()
|
||||||
|
|
|
@ -78,7 +78,7 @@ class ReleaseChannel : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
ReleaseChannel();
|
explicit ReleaseChannel();
|
||||||
~ReleaseChannel() override;
|
~ReleaseChannel() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -117,7 +117,7 @@ class StableReleaseChannel : public ReleaseChannel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
StableReleaseChannel() = default;
|
explicit StableReleaseChannel() = default;
|
||||||
~StableReleaseChannel() override = default;
|
~StableReleaseChannel() override = default;
|
||||||
|
|
||||||
QString getManualDownloadUrl() const override;
|
QString getManualDownloadUrl() const override;
|
||||||
|
|
|
@ -41,8 +41,13 @@ RemoteClient::RemoteClient(QObject *parent)
|
||||||
socket->setSocketOption(QAbstractSocket::LowDelayOption, 1);
|
socket->setSocketOption(QAbstractSocket::LowDelayOption, 1);
|
||||||
connect(socket, SIGNAL(connected()), this, SLOT(slotConnected()));
|
connect(socket, SIGNAL(connected()), this, SLOT(slotConnected()));
|
||||||
connect(socket, SIGNAL(readyRead()), this, SLOT(readData()));
|
connect(socket, SIGNAL(readyRead()), this, SLOT(readData()));
|
||||||
|
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
connect(socket, &QTcpSocket::errorOccurred, this, &RemoteClient::slotSocketError);
|
||||||
|
#else
|
||||||
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this,
|
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this,
|
||||||
SLOT(slotSocketError(QAbstractSocket::SocketError)));
|
SLOT(slotSocketError(QAbstractSocket::SocketError)));
|
||||||
|
#endif
|
||||||
|
|
||||||
websocket = new QWebSocket(QString(), QWebSocketProtocol::VersionLatest, this);
|
websocket = new QWebSocket(QString(), QWebSocketProtocol::VersionLatest, this);
|
||||||
connect(websocket, &QWebSocket::binaryMessageReceived, this, &RemoteClient::websocketMessageReceived);
|
connect(websocket, &QWebSocket::binaryMessageReceived, this, &RemoteClient::websocketMessageReceived);
|
||||||
|
|
|
@ -221,7 +221,7 @@ void RemoteDeckList_TreeModel::addFileToTree(const ServerInfo_DeckStorage_TreeIt
|
||||||
{
|
{
|
||||||
const ServerInfo_DeckStorage_File &fileInfo = file.file();
|
const ServerInfo_DeckStorage_File &fileInfo = file.file();
|
||||||
QDateTime time;
|
QDateTime time;
|
||||||
time.setTime_t(fileInfo.creation_time());
|
time.setSecsSinceEpoch(fileInfo.creation_time());
|
||||||
|
|
||||||
beginInsertRows(nodeToIndex(parent), parent->size(), parent->size());
|
beginInsertRows(nodeToIndex(parent), parent->size(), parent->size());
|
||||||
parent->append(new FileNode(QString::fromStdString(file.name()), file.id(), time, parent));
|
parent->append(new FileNode(QString::fromStdString(file.name()), file.id(), time, parent));
|
||||||
|
|
|
@ -111,7 +111,7 @@ QVariant RemoteReplayList_TreeModel::data(const QModelIndex &index, int role) co
|
||||||
return playerList.join(", ");
|
return playerList.join(", ");
|
||||||
}
|
}
|
||||||
case 4:
|
case 4:
|
||||||
return QDateTime::fromTime_t(matchInfo.time_started());
|
return QDateTime::fromSecsSinceEpoch(matchInfo.time_started());
|
||||||
case 5:
|
case 5:
|
||||||
return matchInfo.length();
|
return matchInfo.length();
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -62,7 +62,11 @@ void ReplayTimelineWidget::paintEvent(QPaintEvent * /* event */)
|
||||||
|
|
||||||
void ReplayTimelineWidget::mousePressEvent(QMouseEvent *event)
|
void ReplayTimelineWidget::mousePressEvent(QMouseEvent *event)
|
||||||
{
|
{
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
int newTime = static_cast<int>((qint64)maxTime * (qint64)event->position().x() / width());
|
||||||
|
#else
|
||||||
int newTime = static_cast<int>((qint64)maxTime * (qint64)event->x() / width());
|
int newTime = static_cast<int>((qint64)maxTime * (qint64)event->x() / width());
|
||||||
|
#endif
|
||||||
newTime -= newTime % 200; // Time should always be a multiple of 200
|
newTime -= newTime % 200; // Time should always be a multiple of 200
|
||||||
if (newTime < currentTime) {
|
if (newTime < currentTime) {
|
||||||
currentTime = 0;
|
currentTime = 0;
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "setsmodel.h"
|
#include "setsmodel.h"
|
||||||
|
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
|
||||||
SetsModel::SetsModel(CardDatabase *_db, QObject *parent) : QAbstractTableModel(parent), sets(_db->getSetList())
|
SetsModel::SetsModel(CardDatabase *_db, QObject *parent) : QAbstractTableModel(parent), sets(_db->getSetList())
|
||||||
{
|
{
|
||||||
sets.sortByKey();
|
sets.sortByKey();
|
||||||
|
@ -274,9 +276,15 @@ bool SetsDisplayModel::filterAcceptsRow(int sourceRow, const QModelIndex &source
|
||||||
auto nameIndex = sourceModel()->index(sourceRow, SetsModel::LongNameCol, sourceParent);
|
auto nameIndex = sourceModel()->index(sourceRow, SetsModel::LongNameCol, sourceParent);
|
||||||
auto shortNameIndex = sourceModel()->index(sourceRow, SetsModel::ShortNameCol, sourceParent);
|
auto shortNameIndex = sourceModel()->index(sourceRow, SetsModel::ShortNameCol, sourceParent);
|
||||||
|
|
||||||
return (sourceModel()->data(typeIndex).toString().contains(filterRegExp()) ||
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0))
|
||||||
sourceModel()->data(nameIndex).toString().contains(filterRegExp()) ||
|
const auto filter = filterRegularExpression();
|
||||||
sourceModel()->data(shortNameIndex).toString().contains(filterRegExp()));
|
#else
|
||||||
|
const auto filter = filterRegExp();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return (sourceModel()->data(typeIndex).toString().contains(filter) ||
|
||||||
|
sourceModel()->data(nameIndex).toString().contains(filter) ||
|
||||||
|
sourceModel()->data(shortNameIndex).toString().contains(filter));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SetsDisplayModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
|
bool SetsDisplayModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
|
||||||
|
|
|
@ -18,7 +18,7 @@ QString SettingsCache::getDataPath()
|
||||||
if (isPortableBuild)
|
if (isPortableBuild)
|
||||||
return qApp->applicationDirPath() + "/data";
|
return qApp->applicationDirPath() + "/data";
|
||||||
else
|
else
|
||||||
return QStandardPaths::writableLocation(QStandardPaths::DataLocation);
|
return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString SettingsCache::getSettingsPath()
|
QString SettingsCache::getSettingsPath()
|
||||||
|
|
|
@ -2,21 +2,15 @@
|
||||||
|
|
||||||
#include "settingscache.h"
|
#include "settingscache.h"
|
||||||
|
|
||||||
#include <QApplication>
|
|
||||||
#include <QAudioOutput>
|
#include <QAudioOutput>
|
||||||
#include <QBuffer>
|
#include <QDir>
|
||||||
#include <QDebug>
|
#include <QMediaPlayer>
|
||||||
#include <QFileInfo>
|
|
||||||
#include <QLibraryInfo>
|
|
||||||
#include <QStandardPaths>
|
|
||||||
|
|
||||||
#define DEFAULT_THEME_NAME "Default"
|
#define DEFAULT_THEME_NAME "Default"
|
||||||
#define TEST_SOUND_FILENAME "player_join"
|
#define TEST_SOUND_FILENAME "player_join"
|
||||||
|
|
||||||
SoundEngine::SoundEngine(QObject *parent) : QObject(parent), player(0)
|
SoundEngine::SoundEngine(QObject *parent) : QObject(parent), player(0)
|
||||||
{
|
{
|
||||||
inputBuffer = new QBuffer(this);
|
|
||||||
|
|
||||||
ensureThemeDirectoryExists();
|
ensureThemeDirectoryExists();
|
||||||
connect(&SettingsCache::instance(), SIGNAL(soundThemeChanged()), this, SLOT(themeChangedSlot()));
|
connect(&SettingsCache::instance(), SIGNAL(soundThemeChanged()), this, SLOT(themeChangedSlot()));
|
||||||
connect(&SettingsCache::instance(), SIGNAL(soundEnabledChanged()), this, SLOT(soundEnabledChanged()));
|
connect(&SettingsCache::instance(), SIGNAL(soundEnabledChanged()), this, SLOT(soundEnabledChanged()));
|
||||||
|
@ -31,8 +25,6 @@ SoundEngine::~SoundEngine()
|
||||||
player->deleteLater();
|
player->deleteLater();
|
||||||
player = 0;
|
player = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inputBuffer->deleteLater();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoundEngine::soundEnabledChanged()
|
void SoundEngine::soundEnabledChanged()
|
||||||
|
@ -40,14 +32,11 @@ void SoundEngine::soundEnabledChanged()
|
||||||
if (SettingsCache::instance().getSoundEnabled()) {
|
if (SettingsCache::instance().getSoundEnabled()) {
|
||||||
qDebug("SoundEngine: enabling sound");
|
qDebug("SoundEngine: enabling sound");
|
||||||
if (!player) {
|
if (!player) {
|
||||||
QAudioFormat format;
|
player = new QMediaPlayer;
|
||||||
format.setSampleRate(44100);
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
format.setChannelCount(1);
|
auto qAudioOutput = new QAudioOutput;
|
||||||
format.setSampleSize(16);
|
player->setAudioOutput(qAudioOutput);
|
||||||
format.setCodec("audio/pcm");
|
#endif
|
||||||
format.setByteOrder(QAudioFormat::LittleEndian);
|
|
||||||
format.setSampleType(QAudioFormat::SignedInt);
|
|
||||||
player = new QAudioOutput(format, this);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
qDebug("SoundEngine: disabling sound");
|
qDebug("SoundEngine: disabling sound");
|
||||||
|
@ -61,25 +50,35 @@ void SoundEngine::soundEnabledChanged()
|
||||||
|
|
||||||
void SoundEngine::playSound(QString fileName)
|
void SoundEngine::playSound(QString fileName)
|
||||||
{
|
{
|
||||||
if (!player)
|
if (!player) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// still playing the previous sound?
|
// still playing the previous sound?
|
||||||
if (player->state() == QAudio::ActiveState)
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
if (player->playbackState() == QMediaPlayer::PlaybackState::PlayingState) {
|
||||||
|
#else
|
||||||
|
if (player->state() == QMediaPlayer::PlayingState) {
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!audioData.contains(fileName))
|
if (!audioData.contains(fileName)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
qDebug() << "playing" << fileName;
|
qDebug() << "playing" << fileName;
|
||||||
|
|
||||||
inputBuffer->close();
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
inputBuffer->setData(audioData[fileName]);
|
player->audioOutput()->setVolume(SettingsCache::instance().getMasterVolume());
|
||||||
inputBuffer->open(QIODevice::ReadOnly);
|
|
||||||
|
|
||||||
player->setVolume(SettingsCache::instance().getMasterVolume() / 100.0);
|
|
||||||
player->stop();
|
player->stop();
|
||||||
player->start(inputBuffer);
|
player->setSource(QUrl::fromLocalFile(audioData[fileName]));
|
||||||
|
#else
|
||||||
|
player->setVolume(SettingsCache::instance().getMasterVolume());
|
||||||
|
player->stop();
|
||||||
|
player->setMedia(QUrl::fromLocalFile(audioData[fileName]));
|
||||||
|
#endif
|
||||||
|
player->play();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoundEngine::testSound()
|
void SoundEngine::testSound()
|
||||||
|
@ -105,7 +104,7 @@ QStringMap &SoundEngine::getAvailableThemes()
|
||||||
|
|
||||||
dir.setPath(SettingsCache::instance().getDataPath() + "/sounds");
|
dir.setPath(SettingsCache::instance().getDataPath() + "/sounds");
|
||||||
|
|
||||||
foreach (QString themeName, dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name)) {
|
for (const QString &themeName : dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name)) {
|
||||||
if (!availableThemes.contains(themeName))
|
if (!availableThemes.contains(themeName))
|
||||||
availableThemes.insert(themeName, dir.absoluteFilePath(themeName));
|
availableThemes.insert(themeName, dir.absoluteFilePath(themeName));
|
||||||
}
|
}
|
||||||
|
@ -121,7 +120,7 @@ QStringMap &SoundEngine::getAvailableThemes()
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
|
|
||||||
foreach (QString themeName, dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name)) {
|
for (const QString &themeName : dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name)) {
|
||||||
if (!availableThemes.contains(themeName))
|
if (!availableThemes.contains(themeName))
|
||||||
availableThemes.insert(themeName, dir.absoluteFilePath(themeName));
|
availableThemes.insert(themeName, dir.absoluteFilePath(themeName));
|
||||||
}
|
}
|
||||||
|
@ -181,10 +180,7 @@ void SoundEngine::themeChangedSlot()
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
QFile file(dir.filePath(fileNames[i] + ".wav"));
|
QFile file(dir.filePath(fileNames[i] + ".wav"));
|
||||||
file.open(QIODevice::ReadOnly);
|
audioData.insert(fileNames[i], file.fileName());
|
||||||
// 44 = length of wav header
|
|
||||||
audioData.insert(fileNames[i], file.readAll().mid(44));
|
|
||||||
file.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
soundEnabledChanged();
|
soundEnabledChanged();
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#ifndef SOUNDENGINE_H
|
#ifndef SOUNDENGINE_H
|
||||||
#define SOUNDENGINE_H
|
#define SOUNDENGINE_H
|
||||||
|
|
||||||
#include <QDir>
|
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
|
#include <QMediaPlayer>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
|
@ -21,10 +21,9 @@ public:
|
||||||
QStringMap &getAvailableThemes();
|
QStringMap &getAvailableThemes();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QMap<QString, QByteArray> audioData;
|
|
||||||
QBuffer *inputBuffer;
|
|
||||||
QAudioOutput *player;
|
|
||||||
QStringMap availableThemes;
|
QStringMap availableThemes;
|
||||||
|
QMap<QString, QString> audioData;
|
||||||
|
QMediaPlayer *player;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void ensureThemeDirectoryExists();
|
void ensureThemeDirectoryExists();
|
||||||
|
|
|
@ -114,7 +114,7 @@ void SpoilerBackgroundUpdater::actCheckIfSpoilerSeasonEnabled()
|
||||||
emit spoilerCheckerDone();
|
emit spoilerCheckerDone();
|
||||||
} else {
|
} else {
|
||||||
if (trayIcon) {
|
if (trayIcon) {
|
||||||
trayIcon->showMessage(tr("Spoilers download failed"), tr("Error") + " " + errorCode);
|
trayIcon->showMessage(tr("Spoilers download failed"), tr("Error") + " " + (short)errorCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "Spoiler download failed with reason" << errorCode;
|
qDebug() << "Spoiler download failed with reason" << errorCode;
|
||||||
|
@ -159,7 +159,7 @@ bool SpoilerBackgroundUpdater::saveDownloadedFile(QByteArray data)
|
||||||
|
|
||||||
// Data written, so reload the card database
|
// Data written, so reload the card database
|
||||||
qDebug() << "Spoiler Service Data Written";
|
qDebug() << "Spoiler Service Data Written";
|
||||||
QtConcurrent::run(db, &CardDatabase::loadCardDatabases);
|
const auto reloadOk = QtConcurrent::run([] { db->loadCardDatabases(); });
|
||||||
|
|
||||||
// If the user has notifications enabled, let them know
|
// If the user has notifications enabled, let them know
|
||||||
// when the database was last updated
|
// when the database was last updated
|
||||||
|
|
|
@ -26,8 +26,10 @@ void StackZone::updateBg()
|
||||||
|
|
||||||
void StackZone::addCardImpl(CardItem *card, int x, int /*y*/)
|
void StackZone::addCardImpl(CardItem *card, int x, int /*y*/)
|
||||||
{
|
{
|
||||||
if (x == -1)
|
// if x is negative set it to add at end
|
||||||
|
if (x < 0 || x >= cards.size()) {
|
||||||
x = cards.size();
|
x = cards.size();
|
||||||
|
}
|
||||||
cards.insert(x, card);
|
cards.insert(x, card);
|
||||||
|
|
||||||
if (!cards.getContentsKnown()) {
|
if (!cards.getContentsKnown()) {
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QDesktopWidget>
|
#include <QScreen>
|
||||||
|
|
||||||
Tab::Tab(TabSupervisor *_tabSupervisor, QWidget *parent)
|
Tab::Tab(TabSupervisor *_tabSupervisor, QWidget *parent)
|
||||||
: QMainWindow(parent), tabSupervisor(_tabSupervisor), contentsChanged(false), infoPopup(0)
|
: QMainWindow(parent), tabSupervisor(_tabSupervisor), contentsChanged(false), infoPopup(0)
|
||||||
{
|
{
|
||||||
|
@ -20,7 +21,8 @@ void Tab::showCardInfoPopup(const QPoint &pos, const QString &cardName)
|
||||||
infoPopup = new CardInfoWidget(
|
infoPopup = new CardInfoWidget(
|
||||||
cardName, 0, Qt::Widget | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint | Qt::WindowStaysOnTopHint);
|
cardName, 0, Qt::Widget | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint | Qt::WindowStaysOnTopHint);
|
||||||
infoPopup->setAttribute(Qt::WA_TransparentForMouseEvents);
|
infoPopup->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||||
QRect screenRect = qApp->desktop()->screenGeometry(this);
|
|
||||||
|
auto screenRect = qApp->primaryScreen()->geometry();
|
||||||
infoPopup->move(qMax(screenRect.left(), qMin(pos.x() - infoPopup->width() / 2,
|
infoPopup->move(qMax(screenRect.left(), qMin(pos.x() - infoPopup->width() / 2,
|
||||||
screenRect.left() + screenRect.width() - infoPopup->width())),
|
screenRect.left() + screenRect.width() - infoPopup->width())),
|
||||||
qMax(screenRect.top(), qMin(pos.y() - infoPopup->height() / 2,
|
qMax(screenRect.top(), qMin(pos.y() - infoPopup->height() / 2,
|
||||||
|
|
|
@ -52,7 +52,7 @@ TabRoom::TabRoom(TabSupervisor *_tabSupervisor,
|
||||||
SIGNAL(openMessageDialog(const QString &, bool)));
|
SIGNAL(openMessageDialog(const QString &, bool)));
|
||||||
|
|
||||||
chatView = new ChatView(tabSupervisor, tabSupervisor, nullptr, true, this);
|
chatView = new ChatView(tabSupervisor, tabSupervisor, nullptr, true, this);
|
||||||
connect(chatView, SIGNAL(showMentionPopup(QString &)), this, SLOT(actShowMentionPopup(QString &)));
|
connect(chatView, SIGNAL(showMentionPopup(const QString &)), this, SLOT(actShowMentionPopup(const QString &)));
|
||||||
connect(chatView, SIGNAL(messageClickedSignal()), this, SLOT(focusTab()));
|
connect(chatView, SIGNAL(messageClickedSignal()), this, SLOT(focusTab()));
|
||||||
connect(chatView, SIGNAL(openMessageDialog(QString, bool)), this, SIGNAL(openMessageDialog(QString, bool)));
|
connect(chatView, SIGNAL(openMessageDialog(QString, bool)), this, SIGNAL(openMessageDialog(QString, bool)));
|
||||||
connect(chatView, SIGNAL(showCardInfoPopup(QPoint, QString)), this, SLOT(showCardInfoPopup(QPoint, QString)));
|
connect(chatView, SIGNAL(showCardInfoPopup(QPoint, QString)), this, SLOT(showCardInfoPopup(QPoint, QString)));
|
||||||
|
@ -160,7 +160,7 @@ void TabRoom::focusTab()
|
||||||
emit maximizeClient();
|
emit maximizeClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabRoom::actShowMentionPopup(QString &sender)
|
void TabRoom::actShowMentionPopup(const QString &sender)
|
||||||
{
|
{
|
||||||
this->actShowPopup(sender + tr(" mentioned you."));
|
this->actShowPopup(sender + tr(" mentioned you."));
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,7 +75,7 @@ private slots:
|
||||||
void actOpenChatSettings();
|
void actOpenChatSettings();
|
||||||
void addMentionTag(QString mentionTag);
|
void addMentionTag(QString mentionTag);
|
||||||
void focusTab();
|
void focusTab();
|
||||||
void actShowMentionPopup(QString &sender);
|
void actShowMentionPopup(const QString &sender);
|
||||||
void actShowPopup(const QString &message);
|
void actShowPopup(const QString &message);
|
||||||
void actCompleterChanged();
|
void actCompleterChanged();
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,11 @@ QSize CloseButton::sizeHint() const
|
||||||
return QSize(width, height);
|
return QSize(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
void CloseButton::enterEvent(QEnterEvent *event)
|
||||||
|
#else
|
||||||
void CloseButton::enterEvent(QEvent *event)
|
void CloseButton::enterEvent(QEvent *event)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
update();
|
update();
|
||||||
QAbstractButton::enterEvent(event);
|
QAbstractButton::enterEvent(event);
|
||||||
|
@ -74,7 +78,7 @@ void CloseButton::paintEvent(QPaintEvent * /*event*/)
|
||||||
{
|
{
|
||||||
QPainter p(this);
|
QPainter p(this);
|
||||||
QStyleOption opt;
|
QStyleOption opt;
|
||||||
opt.init(this);
|
opt.initFrom(this);
|
||||||
opt.state |= QStyle::State_AutoRaise;
|
opt.state |= QStyle::State_AutoRaise;
|
||||||
if (isEnabled() && underMouse() && !isChecked() && !isDown())
|
if (isEnabled() && underMouse() && !isChecked() && !isDown())
|
||||||
opt.state |= QStyle::State_Raised;
|
opt.state |= QStyle::State_Raised;
|
||||||
|
|
|
@ -52,7 +52,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
void enterEvent(QEnterEvent *event);
|
||||||
|
#else
|
||||||
void enterEvent(QEvent *event);
|
void enterEvent(QEvent *event);
|
||||||
|
#endif
|
||||||
void leaveEvent(QEvent *event);
|
void leaveEvent(QEvent *event);
|
||||||
void paintEvent(QPaintEvent *event);
|
void paintEvent(QPaintEvent *event);
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
#include <QRegExp>
|
#include <QRegExp>
|
||||||
|
#include <QRegularExpression>
|
||||||
#include <QUrlQuery>
|
#include <QUrlQuery>
|
||||||
|
|
||||||
TappedOutInterface::TappedOutInterface(CardDatabase &_cardDatabase, QObject *parent)
|
TappedOutInterface::TappedOutInterface(CardDatabase &_cardDatabase, QObject *parent)
|
||||||
|
@ -53,7 +54,7 @@ void TappedOutInterface::queryFinished(QNetworkReply *reply)
|
||||||
|
|
||||||
int captures = rx2.captureCount();
|
int captures = rx2.captureCount();
|
||||||
for (int i = 1; i <= captures; i++) {
|
for (int i = 1; i <= captures; i++) {
|
||||||
errorMessage += QString("\n") + rx2.cap(i).remove(QRegExp("<[^>]*>")).simplified();
|
errorMessage += QString("\n") + rx2.cap(i).remove(QRegularExpression("<[^>]*>")).simplified();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,9 @@ TipsOfTheDay::TipsOfTheDay(QString xmlPath, QObject *parent) : QAbstractListMode
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reader.name() == "tip") {
|
auto readerName = reader.name().toString();
|
||||||
|
|
||||||
|
if (readerName == "tip") {
|
||||||
QString title, content, imagePath;
|
QString title, content, imagePath;
|
||||||
QDate date;
|
QDate date;
|
||||||
reader.readNext();
|
reader.readNext();
|
||||||
|
@ -45,16 +47,18 @@ TipsOfTheDay::TipsOfTheDay(QString xmlPath, QObject *parent) : QAbstractListMode
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reader.name() == "title") {
|
readerName = reader.name().toString();
|
||||||
|
|
||||||
|
if (readerName == "title") {
|
||||||
title = reader.readElementText();
|
title = reader.readElementText();
|
||||||
} else if (reader.name() == "text") {
|
} else if (readerName == "text") {
|
||||||
content = reader.readElementText();
|
content = reader.readElementText();
|
||||||
} else if (reader.name() == "image") {
|
} else if (readerName == "image") {
|
||||||
imagePath = "theme:tips/images/" + reader.readElementText();
|
imagePath = "theme:tips/images/" + reader.readElementText();
|
||||||
} else if (reader.name() == "date") {
|
} else if (readerName == "date") {
|
||||||
date = QDate::fromString(reader.readElementText(), Qt::ISODate);
|
date = QDate::fromString(reader.readElementText(), Qt::ISODate);
|
||||||
} else {
|
} else {
|
||||||
// unkown element, do nothing
|
// unknown element, do nothing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tipList->append(TipOfTheDay(title, content, imagePath, date));
|
tipList->append(TipOfTheDay(title, content, imagePath, date));
|
||||||
|
|
|
@ -137,7 +137,7 @@ QString UserInfoBox::getAgeString(int ageSeconds)
|
||||||
if (ageSeconds == 0)
|
if (ageSeconds == 0)
|
||||||
return accountAgeString;
|
return accountAgeString;
|
||||||
|
|
||||||
auto date = QDateTime::fromTime_t(QDateTime::currentSecsSinceEpoch() - ageSeconds).date();
|
auto date = QDateTime::fromSecsSinceEpoch(QDateTime::currentSecsSinceEpoch() - ageSeconds).date();
|
||||||
if (!date.isValid())
|
if (!date.isValid())
|
||||||
return accountAgeString;
|
return accountAgeString;
|
||||||
|
|
||||||
|
|
|
@ -296,7 +296,11 @@ bool UserListItemDelegate::editorEvent(QEvent *event,
|
||||||
if ((event->type() == QEvent::MouseButtonPress) && index.isValid()) {
|
if ((event->type() == QEvent::MouseButtonPress) && index.isValid()) {
|
||||||
QMouseEvent *const mouseEvent = static_cast<QMouseEvent *>(event);
|
QMouseEvent *const mouseEvent = static_cast<QMouseEvent *>(event);
|
||||||
if (mouseEvent->button() == Qt::RightButton) {
|
if (mouseEvent->button() == Qt::RightButton) {
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
static_cast<UserList *>(parent())->showContextMenu(mouseEvent->globalPosition().toPoint(), index);
|
||||||
|
#else
|
||||||
static_cast<UserList *>(parent())->showContextMenu(mouseEvent->globalPos(), index);
|
static_cast<UserList *>(parent())->showContextMenu(mouseEvent->globalPos(), index);
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,8 +101,8 @@ void MainWindow::processConnectionClosedEvent(const Event_ConnectionClosed &even
|
||||||
case Event_ConnectionClosed::BANNED: {
|
case Event_ConnectionClosed::BANNED: {
|
||||||
reasonStr = tr("Banned by moderator");
|
reasonStr = tr("Banned by moderator");
|
||||||
if (event.has_end_time())
|
if (event.has_end_time())
|
||||||
reasonStr.append("\n" +
|
reasonStr.append(
|
||||||
tr("Expected end time: %1").arg(QDateTime::fromTime_t(event.end_time()).toString()));
|
"\n" + tr("Expected end time: %1").arg(QDateTime::fromSecsSinceEpoch(event.end_time()).toString()));
|
||||||
else
|
else
|
||||||
reasonStr.append("\n" + tr("This ban lasts indefinitely."));
|
reasonStr.append("\n" + tr("This ban lasts indefinitely."));
|
||||||
if (event.has_reason_str())
|
if (event.has_reason_str())
|
||||||
|
@ -393,7 +393,7 @@ void MainWindow::loginError(Response::ResponseCode r,
|
||||||
case Response::RespUserIsBanned: {
|
case Response::RespUserIsBanned: {
|
||||||
QString bannedStr;
|
QString bannedStr;
|
||||||
if (endTime)
|
if (endTime)
|
||||||
bannedStr = tr("You are banned until %1.").arg(QDateTime::fromTime_t(endTime).toString());
|
bannedStr = tr("You are banned until %1.").arg(QDateTime::fromSecsSinceEpoch(endTime).toString());
|
||||||
else
|
else
|
||||||
bannedStr = tr("You are banned indefinitely.");
|
bannedStr = tr("You are banned indefinitely.");
|
||||||
if (!reasonStr.isEmpty())
|
if (!reasonStr.isEmpty())
|
||||||
|
@ -530,7 +530,7 @@ void MainWindow::registerError(Response::ResponseCode r, QString reasonStr, quin
|
||||||
case Response::RespUserIsBanned: {
|
case Response::RespUserIsBanned: {
|
||||||
QString bannedStr;
|
QString bannedStr;
|
||||||
if (endTime)
|
if (endTime)
|
||||||
bannedStr = tr("You are banned until %1.").arg(QDateTime::fromTime_t(endTime).toString());
|
bannedStr = tr("You are banned until %1.").arg(QDateTime::fromSecsSinceEpoch(endTime).toString());
|
||||||
else
|
else
|
||||||
bannedStr = tr("You are banned indefinitely.");
|
bannedStr = tr("You are banned indefinitely.");
|
||||||
if (!reasonStr.isEmpty())
|
if (!reasonStr.isEmpty())
|
||||||
|
@ -865,13 +865,13 @@ void MainWindow::startupConfigCheck()
|
||||||
if (SettingsCache::instance().getNotifyAboutNewVersion()) {
|
if (SettingsCache::instance().getNotifyAboutNewVersion()) {
|
||||||
alertForcedOracleRun(VERSION_STRING, true);
|
alertForcedOracleRun(VERSION_STRING, true);
|
||||||
} else {
|
} else {
|
||||||
QtConcurrent::run(db, &CardDatabase::loadCardDatabases);
|
const auto reloadOk0 = QtConcurrent::run([] { db->loadCardDatabases(); });
|
||||||
}
|
}
|
||||||
SettingsCache::instance().setClientVersion(VERSION_STRING);
|
SettingsCache::instance().setClientVersion(VERSION_STRING);
|
||||||
} else {
|
} else {
|
||||||
// previous config from this version found
|
// previous config from this version found
|
||||||
qDebug() << "Startup: found config with current version";
|
qDebug() << "Startup: found config with current version";
|
||||||
QtConcurrent::run(db, &CardDatabase::loadCardDatabases);
|
const auto reloadOk1 = QtConcurrent::run([] { db->loadCardDatabases(); });
|
||||||
|
|
||||||
// Run the tips dialog only on subsequent startups.
|
// Run the tips dialog only on subsequent startups.
|
||||||
// On the first run after an install/update the startup is already crowded enough
|
// On the first run after an install/update the startup is already crowded enough
|
||||||
|
@ -932,9 +932,9 @@ void MainWindow::createTrayIcon()
|
||||||
void MainWindow::iconActivated(QSystemTrayIcon::ActivationReason reason)
|
void MainWindow::iconActivated(QSystemTrayIcon::ActivationReason reason)
|
||||||
{
|
{
|
||||||
if (reason == QSystemTrayIcon::DoubleClick) {
|
if (reason == QSystemTrayIcon::DoubleClick) {
|
||||||
if (windowState() != Qt::WindowMinimized && windowState() != Qt::WindowMinimized + Qt::WindowMaximized)
|
if ((windowState() & Qt::WindowMinimized) == 0) {
|
||||||
showMinimized();
|
showMinimized();
|
||||||
else {
|
} else {
|
||||||
showNormal();
|
showNormal();
|
||||||
QApplication::setActiveWindow(this);
|
QApplication::setActiveWindow(this);
|
||||||
}
|
}
|
||||||
|
@ -1058,7 +1058,7 @@ void MainWindow::cardDatabaseNewSetsFound(int numUnknownSets, QStringList unknow
|
||||||
|
|
||||||
if (msgBox.clickedButton() == yesButton) {
|
if (msgBox.clickedButton() == yesButton) {
|
||||||
db->enableAllUnknownSets();
|
db->enableAllUnknownSets();
|
||||||
QtConcurrent::run(db, &CardDatabase::loadCardDatabases);
|
const auto reloadOk1 = QtConcurrent::run([] { db->loadCardDatabases(); });
|
||||||
} else if (msgBox.clickedButton() == noButton) {
|
} else if (msgBox.clickedButton() == noButton) {
|
||||||
db->markAllSetsAsKnown();
|
db->markAllSetsAsKnown();
|
||||||
} else if (msgBox.clickedButton() == settingsButton) {
|
} else if (msgBox.clickedButton() == settingsButton) {
|
||||||
|
@ -1086,8 +1086,9 @@ void MainWindow::actCheckCardUpdates()
|
||||||
}
|
}
|
||||||
|
|
||||||
cardUpdateProcess = new QProcess(this);
|
cardUpdateProcess = new QProcess(this);
|
||||||
connect(cardUpdateProcess, SIGNAL(error(QProcess::ProcessError)), this,
|
|
||||||
SLOT(cardUpdateError(QProcess::ProcessError)));
|
connect(cardUpdateProcess, &QProcess::errorOccurred, this, &MainWindow::cardUpdateError);
|
||||||
|
|
||||||
connect(cardUpdateProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this,
|
connect(cardUpdateProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this,
|
||||||
SLOT(cardUpdateFinished(int, QProcess::ExitStatus)));
|
SLOT(cardUpdateFinished(int, QProcess::ExitStatus)));
|
||||||
|
|
||||||
|
@ -1148,7 +1149,7 @@ void MainWindow::exitCardDatabaseUpdate()
|
||||||
cardUpdateProcess->deleteLater();
|
cardUpdateProcess->deleteLater();
|
||||||
cardUpdateProcess = nullptr;
|
cardUpdateProcess = nullptr;
|
||||||
|
|
||||||
QtConcurrent::run(db, &CardDatabase::loadCardDatabases);
|
const auto reloadOk1 = QtConcurrent::run([] { db->loadCardDatabases(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::cardUpdateError(QProcess::ProcessError err)
|
void MainWindow::cardUpdateError(QProcess::ProcessError err)
|
||||||
|
@ -1278,7 +1279,7 @@ void MainWindow::actAddCustomSet()
|
||||||
QMessageBox::information(
|
QMessageBox::information(
|
||||||
this, tr("Load sets/cards"),
|
this, tr("Load sets/cards"),
|
||||||
tr("The new sets/cards have been added successfully.\nCockatrice will now reload the card database."));
|
tr("The new sets/cards have been added successfully.\nCockatrice will now reload the card database."));
|
||||||
QtConcurrent::run(db, &CardDatabase::loadCardDatabases);
|
const auto reloadOk1 = QtConcurrent::run([] { db->loadCardDatabases(); });
|
||||||
} else {
|
} else {
|
||||||
QMessageBox::warning(this, tr("Load sets/cards"), tr("Sets/cards failed to import."));
|
QMessageBox::warning(this, tr("Load sets/cards"), tr("Sets/cards failed to import."));
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QGraphicsSceneWheelEvent>
|
#include <QGraphicsSceneWheelEvent>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <math.h>
|
#include <QtMath>
|
||||||
|
|
||||||
ZoneViewZone::ZoneViewZone(Player *_p,
|
ZoneViewZone::ZoneViewZone(Player *_p,
|
||||||
CardZone *_origZone,
|
CardZone *_origZone,
|
||||||
|
@ -103,17 +103,17 @@ void ZoneViewZone::reorganizeCards()
|
||||||
for (int i = 0; i < cardCount; ++i)
|
for (int i = 0; i < cardCount; ++i)
|
||||||
cards[i]->setId(i);
|
cards[i]->setId(i);
|
||||||
|
|
||||||
int cols = floor(sqrt((double)cardCount / 2));
|
int cols = qFloor(qSqrt((double)cardCount / 2));
|
||||||
if (cols > 7)
|
if (cols > 7)
|
||||||
cols = 7;
|
cols = 7;
|
||||||
int rows = ceil((double)cardCount / cols);
|
int rows = qCeil((double)cardCount / cols);
|
||||||
if (rows < 1)
|
if (rows < 1)
|
||||||
rows = 1;
|
rows = 1;
|
||||||
if (minRows == 0)
|
if (minRows == 0)
|
||||||
minRows = rows;
|
minRows = rows;
|
||||||
else if (rows < minRows) {
|
else if (rows < minRows) {
|
||||||
rows = minRows;
|
rows = minRows;
|
||||||
cols = ceil((double)cardCount / minRows);
|
cols = qCeil((double)cardCount / minRows);
|
||||||
}
|
}
|
||||||
if (cols < 2)
|
if (cols < 2)
|
||||||
cols = 2;
|
cols = 2;
|
||||||
|
@ -193,6 +193,10 @@ void ZoneViewZone::setPileView(int _pileView)
|
||||||
|
|
||||||
void ZoneViewZone::addCardImpl(CardItem *card, int x, int /*y*/)
|
void ZoneViewZone::addCardImpl(CardItem *card, int x, int /*y*/)
|
||||||
{
|
{
|
||||||
|
// if x is negative set it to add at end
|
||||||
|
if (x < 0 || x >= cards.size()) {
|
||||||
|
x = cards.size();
|
||||||
|
}
|
||||||
cards.insert(x, card);
|
cards.insert(x, card);
|
||||||
card->setParentItem(this);
|
card->setParentItem(this);
|
||||||
card->update();
|
card->update();
|
||||||
|
|
|
@ -36,8 +36,8 @@ set(ORACLE_LIBS)
|
||||||
INCLUDE_DIRECTORIES(pb)
|
INCLUDE_DIRECTORIES(pb)
|
||||||
INCLUDE_DIRECTORIES(sfmt)
|
INCLUDE_DIRECTORIES(sfmt)
|
||||||
INCLUDE_DIRECTORIES(${PROTOBUF_INCLUDE_DIR})
|
INCLUDE_DIRECTORIES(${PROTOBUF_INCLUDE_DIR})
|
||||||
include_directories(${Qt5Core_INCLUDE_DIRS})
|
include_directories(${${COCKATRICE_QT_VERSION_NAME}Core_INCLUDE_DIRS})
|
||||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
|
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
add_library(cockatrice_common ${common_SOURCES} ${common_MOC_SRCS})
|
add_library(cockatrice_common ${common_SOURCES} ${common_MOC_SRCS})
|
||||||
target_link_libraries(cockatrice_common cockatrice_protocol)
|
target_link_libraries(cockatrice_common PUBLIC cockatrice_protocol)
|
||||||
|
|
|
@ -292,7 +292,7 @@ bool AbstractDecklistCardNode::readElement(QXmlStreamReader *xml)
|
||||||
{
|
{
|
||||||
while (!xml->atEnd()) {
|
while (!xml->atEnd()) {
|
||||||
xml->readNext();
|
xml->readNext();
|
||||||
if (xml->isEndElement() && xml->name() == "card")
|
if (xml->isEndElement() && xml->name().toString() == "card")
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -435,7 +435,7 @@ bool DeckList::loadFromXml(QXmlStreamReader *xml)
|
||||||
while (!xml->atEnd()) {
|
while (!xml->atEnd()) {
|
||||||
xml->readNext();
|
xml->readNext();
|
||||||
if (xml->isStartElement()) {
|
if (xml->isStartElement()) {
|
||||||
if (xml->name() != "cockatrice_deck")
|
if (xml->name().toString() != "cockatrice_deck")
|
||||||
return false;
|
return false;
|
||||||
while (!xml->atEnd()) {
|
while (!xml->atEnd()) {
|
||||||
xml->readNext();
|
xml->readNext();
|
||||||
|
@ -602,7 +602,7 @@ bool DeckList::loadFromStream_Plain(QTextStream &in)
|
||||||
int amount = 1;
|
int amount = 1;
|
||||||
match = reMultiplier.match(cardName);
|
match = reMultiplier.match(cardName);
|
||||||
if (match.hasMatch()) {
|
if (match.hasMatch()) {
|
||||||
amount = match.capturedRef(1).toInt();
|
amount = match.captured(1).toInt();
|
||||||
cardName = match.captured(2);
|
cardName = match.captured(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <cmath>
|
#include <QtMath>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
peg::parser math(R"(
|
peg::parser math(R"(
|
||||||
|
@ -32,19 +32,17 @@ Expression::Expression(double initial) : value(initial)
|
||||||
{
|
{
|
||||||
if (default_functions == nullptr) {
|
if (default_functions == nullptr) {
|
||||||
default_functions = new QMap<QString, std::function<double(double)>>();
|
default_functions = new QMap<QString, std::function<double(double)>>();
|
||||||
default_functions->insert("sin", [](double a) { return sin(a); });
|
default_functions->insert("abs", [](double a) { return qFabs(a); });
|
||||||
default_functions->insert("cos", [](double a) { return cos(a); });
|
default_functions->insert("ceil", [](double a) { return qCeil(a); });
|
||||||
default_functions->insert("tan", [](double a) { return tan(a); });
|
default_functions->insert("cos", [](double a) { return qCos(a); });
|
||||||
default_functions->insert("sqrt", [](double a) { return sqrt(a); });
|
default_functions->insert("floor", [](double a) { return qFloor(a); });
|
||||||
default_functions->insert("log", [](double a) { return log(a); });
|
default_functions->insert("log", [](double a) { return qLn(a); });
|
||||||
default_functions->insert("log10", [](double a) { return log(a); });
|
default_functions->insert("log10", [](double a) { return qLn(a); });
|
||||||
default_functions->insert("trunc", [](double a) { return trunc(a); });
|
default_functions->insert("round", [](double a) { return qRound(a); });
|
||||||
default_functions->insert("abs", [](double a) { return fabs(a); });
|
default_functions->insert("sin", [](double a) { return qSin(a); });
|
||||||
|
default_functions->insert("sqrt", [](double a) { return qSqrt(a); });
|
||||||
default_functions->insert("floor", [](double a) { return floor(a); });
|
default_functions->insert("tan", [](double a) { return qTan(a); });
|
||||||
default_functions->insert("ceil", [](double a) { return ceil(a); });
|
default_functions->insert("trunc", [](double a) { return std::trunc(a); });
|
||||||
default_functions->insert("round", [](double a) { return round(a); });
|
|
||||||
default_functions->insert("trunc", [](double a) { return trunc(a); });
|
|
||||||
}
|
}
|
||||||
fns = QMap<QString, std::function<double(double)>>(*default_functions);
|
fns = QMap<QString, std::function<double(double)>>(*default_functions);
|
||||||
}
|
}
|
||||||
|
@ -80,7 +78,7 @@ double Expression::eval(const peg::Ast &ast)
|
||||||
result /= arg;
|
result /= arg;
|
||||||
break;
|
break;
|
||||||
case '^':
|
case '^':
|
||||||
result = pow(result, arg);
|
result = qPow(result, arg);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
result = 0;
|
result = 0;
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
RNG_SFMT::RNG_SFMT(QObject *parent) : RNG_Abstract(parent)
|
RNG_SFMT::RNG_SFMT(QObject *parent) : RNG_Abstract(parent)
|
||||||
{
|
{
|
||||||
// initialize the random number generator with a 32bit integer seed (timestamp)
|
// initialize the random number generator with a 32bit integer seed (timestamp)
|
||||||
sfmt_init_gen_rand(&sfmt, QDateTime::currentDateTime().toTime_t());
|
sfmt_init_gen_rand(&sfmt, QDateTime::currentDateTime().toSecsSinceEpoch());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -118,7 +118,7 @@ AuthenticationResult Server::loginUser(Server_ProtocolHandler *session,
|
||||||
Event_ConnectionClosed event;
|
Event_ConnectionClosed event;
|
||||||
event.set_reason(Event_ConnectionClosed::LOGGEDINELSEWERE);
|
event.set_reason(Event_ConnectionClosed::LOGGEDINELSEWERE);
|
||||||
event.set_reason_str("You have been logged out due to logging in at another location.");
|
event.set_reason_str("You have been logged out due to logging in at another location.");
|
||||||
event.set_end_time(QDateTime::currentDateTime().toTime_t());
|
event.set_end_time(QDateTime::currentDateTime().toSecsSinceEpoch());
|
||||||
|
|
||||||
SessionEvent *se = users.value(name)->prepareSessionEvent(event);
|
SessionEvent *se = users.value(name)->prepareSessionEvent(event);
|
||||||
users.value(name)->sendProtocolItem(*se);
|
users.value(name)->sendProtocolItem(*se);
|
||||||
|
@ -230,6 +230,11 @@ void Server::addClient(Server_ProtocolHandler *client)
|
||||||
|
|
||||||
void Server::removeClient(Server_ProtocolHandler *client)
|
void Server::removeClient(Server_ProtocolHandler *client)
|
||||||
{
|
{
|
||||||
|
int clientIndex = clients.indexOf(client);
|
||||||
|
if (clientIndex == -1) {
|
||||||
|
qWarning() << "tried to remove non existing client";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (client->getConnectionType() == "tcp")
|
if (client->getConnectionType() == "tcp")
|
||||||
tcpUserCount--;
|
tcpUserCount--;
|
||||||
|
@ -238,7 +243,7 @@ void Server::removeClient(Server_ProtocolHandler *client)
|
||||||
webSocketUserCount--;
|
webSocketUserCount--;
|
||||||
|
|
||||||
QWriteLocker locker(&clientsLock);
|
QWriteLocker locker(&clientsLock);
|
||||||
clients.removeAt(clients.indexOf(client));
|
clients.removeAt(clientIndex);
|
||||||
ServerInfo_User *data = client->getUserInfo();
|
ServerInfo_User *data = client->getUserInfo();
|
||||||
if (data) {
|
if (data) {
|
||||||
Event_UserLeft event;
|
Event_UserLeft event;
|
||||||
|
|
|
@ -57,8 +57,8 @@ private slots:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
mutable QReadWriteLock clientsLock, roomsLock; // locking order: roomsLock before clientsLock
|
mutable QReadWriteLock clientsLock, roomsLock; // locking order: roomsLock before clientsLock
|
||||||
Server(QObject *parent = nullptr);
|
explicit Server(QObject *parent = nullptr);
|
||||||
~Server() = default;
|
virtual ~Server() = default;
|
||||||
AuthenticationResult loginUser(Server_ProtocolHandler *session,
|
AuthenticationResult loginUser(Server_ProtocolHandler *session,
|
||||||
QString &name,
|
QString &name,
|
||||||
const QString &password,
|
const QString &password,
|
||||||
|
|
|
@ -21,13 +21,13 @@
|
||||||
#define SERVER_CARD_H
|
#define SERVER_CARD_H
|
||||||
|
|
||||||
#include "pb/card_attributes.pb.h"
|
#include "pb/card_attributes.pb.h"
|
||||||
|
#include "pb/serverinfo_card.pb.h"
|
||||||
#include "server_arrowtarget.h"
|
#include "server_arrowtarget.h"
|
||||||
|
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
class Server_CardZone;
|
class Server_CardZone;
|
||||||
class ServerInfo_Card;
|
|
||||||
|
|
||||||
class Server_Card : public Server_ArrowTarget
|
class Server_Card : public Server_ArrowTarget
|
||||||
{
|
{
|
||||||
|
@ -52,7 +52,7 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Server_Card(QString _name, int _id, int _coord_x, int _coord_y, Server_CardZone *_zone = 0);
|
Server_Card(QString _name, int _id, int _coord_x, int _coord_y, Server_CardZone *_zone = 0);
|
||||||
~Server_Card();
|
~Server_Card() override;
|
||||||
|
|
||||||
Server_CardZone *getZone() const
|
Server_CardZone *getZone() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -292,10 +292,10 @@ void Server_CardZone::insertCard(Server_Card *card, int x, int y)
|
||||||
insertCardIntoCoordMap(card, x, y);
|
insertCardIntoCoordMap(card, x, y);
|
||||||
} else {
|
} else {
|
||||||
card->setCoords(0, 0);
|
card->setCoords(0, 0);
|
||||||
if (x == -1) {
|
if (0 <= x && x < cards.length()) {
|
||||||
cards.append(card);
|
|
||||||
} else {
|
|
||||||
cards.insert(x, card);
|
cards.insert(x, card);
|
||||||
|
} else {
|
||||||
|
cards.append(card);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
card->setZone(this);
|
card->setZone(this);
|
||||||
|
|
|
@ -147,7 +147,12 @@ public:
|
||||||
LogMessage_TargetType /* targetType */,
|
LogMessage_TargetType /* targetType */,
|
||||||
const int /* targetId */,
|
const int /* targetId */,
|
||||||
const QString & /* targetName */){};
|
const QString & /* targetName */){};
|
||||||
bool checkUserIsBanned(Server_ProtocolHandler *session, QString &banReason, int &banSecondsRemaining);
|
virtual bool checkUserIsBanned(Server_ProtocolHandler * /* session */,
|
||||||
|
QString & /* banReason */,
|
||||||
|
int & /* banSecondsRemaining */)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
};
|
||||||
virtual int checkNumberOfUserAccounts(const QString & /* email */)
|
virtual int checkNumberOfUserAccounts(const QString & /* email */)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -69,6 +69,7 @@ Server_Game::Server_Game(const ServerInfo_User &_creatorInfo,
|
||||||
spectatorsNeedPassword(_spectatorsNeedPassword), spectatorsCanTalk(_spectatorsCanTalk),
|
spectatorsNeedPassword(_spectatorsNeedPassword), spectatorsCanTalk(_spectatorsCanTalk),
|
||||||
spectatorsSeeEverything(_spectatorsSeeEverything), inactivityCounter(0), startTimeOfThisGame(0),
|
spectatorsSeeEverything(_spectatorsSeeEverything), inactivityCounter(0), startTimeOfThisGame(0),
|
||||||
secondsElapsed(0), firstGameStarted(false), turnOrderReversed(false), startTime(QDateTime::currentDateTime()),
|
secondsElapsed(0), firstGameStarted(false), turnOrderReversed(false), startTime(QDateTime::currentDateTime()),
|
||||||
|
pingClock(nullptr),
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||||
gameMutex()
|
gameMutex()
|
||||||
#else
|
#else
|
||||||
|
@ -97,7 +98,7 @@ Server_Game::~Server_Game()
|
||||||
|
|
||||||
gameClosed = true;
|
gameClosed = true;
|
||||||
sendGameEventContainer(prepareGameEvent(Event_GameClosed(), -1));
|
sendGameEventContainer(prepareGameEvent(Event_GameClosed(), -1));
|
||||||
for (Server_Player *player : players.values()) {
|
for (auto *player : players.values()) {
|
||||||
player->prepareDestroy();
|
player->prepareDestroy();
|
||||||
}
|
}
|
||||||
players.clear();
|
players.clear();
|
||||||
|
@ -112,10 +113,22 @@ Server_Game::~Server_Game()
|
||||||
replayList.append(currentReplay);
|
replayList.append(currentReplay);
|
||||||
storeGameInformation();
|
storeGameInformation();
|
||||||
|
|
||||||
for (int i = 0; i < replayList.size(); ++i)
|
for (auto *replay : replayList) {
|
||||||
delete replayList[i];
|
delete replay;
|
||||||
|
}
|
||||||
|
replayList.clear();
|
||||||
|
|
||||||
|
room = nullptr;
|
||||||
|
currentReplay = nullptr;
|
||||||
|
creatorInfo = nullptr;
|
||||||
|
|
||||||
|
if (pingClock) {
|
||||||
|
delete pingClock;
|
||||||
|
pingClock = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
qDebug() << "Server_Game destructor: gameId=" << gameId;
|
qDebug() << "Server_Game destructor: gameId=" << gameId;
|
||||||
|
deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server_Game::storeGameInformation()
|
void Server_Game::storeGameInformation()
|
||||||
|
@ -126,7 +139,7 @@ void Server_Game::storeGameInformation()
|
||||||
ServerInfo_ReplayMatch *replayMatchInfo = replayEvent.mutable_match_info();
|
ServerInfo_ReplayMatch *replayMatchInfo = replayEvent.mutable_match_info();
|
||||||
replayMatchInfo->set_game_id(gameInfo.game_id());
|
replayMatchInfo->set_game_id(gameInfo.game_id());
|
||||||
replayMatchInfo->set_room_name(room->getName().toStdString());
|
replayMatchInfo->set_room_name(room->getName().toStdString());
|
||||||
replayMatchInfo->set_time_started(QDateTime::currentDateTime().addSecs(-secondsElapsed).toTime_t());
|
replayMatchInfo->set_time_started(QDateTime::currentDateTime().addSecs(-secondsElapsed).toSecsSinceEpoch());
|
||||||
replayMatchInfo->set_length(secondsElapsed);
|
replayMatchInfo->set_length(secondsElapsed);
|
||||||
replayMatchInfo->set_game_name(gameInfo.description());
|
replayMatchInfo->set_game_name(gameInfo.description());
|
||||||
|
|
||||||
|
@ -769,6 +782,6 @@ void Server_Game::getInfo(ServerInfo_Game &result) const
|
||||||
result.set_spectators_can_chat(spectatorsCanTalk);
|
result.set_spectators_can_chat(spectatorsCanTalk);
|
||||||
result.set_spectators_omniscient(spectatorsSeeEverything);
|
result.set_spectators_omniscient(spectatorsSeeEverything);
|
||||||
result.set_spectators_count(getSpectatorCount());
|
result.set_spectators_count(getSpectatorCount());
|
||||||
result.set_start_time(startTime.toTime_t());
|
result.set_start_time(startTime.toSecsSinceEpoch());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,6 +120,7 @@ Server_Player::~Server_Player() = default;
|
||||||
void Server_Player::prepareDestroy()
|
void Server_Player::prepareDestroy()
|
||||||
{
|
{
|
||||||
delete deck;
|
delete deck;
|
||||||
|
deck = nullptr;
|
||||||
|
|
||||||
playerMutex.lock();
|
playerMutex.lock();
|
||||||
if (userInterface) {
|
if (userInterface) {
|
||||||
|
@ -1234,7 +1235,6 @@ Server_Player::cmdAttachCard(const Command_AttachCard &cmd, ResponseContainer &
|
||||||
return Response::RespContextError;
|
return Response::RespContextError;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all arrows pointing to or originating from the card being attached and delete them.
|
|
||||||
QMapIterator<int, Server_Player *> playerIterator(game->getPlayers());
|
QMapIterator<int, Server_Player *> playerIterator(game->getPlayers());
|
||||||
while (playerIterator.hasNext()) {
|
while (playerIterator.hasNext()) {
|
||||||
Server_Player *p = playerIterator.next().value();
|
Server_Player *p = playerIterator.next().value();
|
||||||
|
|
|
@ -25,8 +25,8 @@
|
||||||
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QtMath>
|
||||||
#include <google/protobuf/descriptor.h>
|
#include <google/protobuf/descriptor.h>
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
Server_ProtocolHandler::Server_ProtocolHandler(Server *_server,
|
Server_ProtocolHandler::Server_ProtocolHandler(Server *_server,
|
||||||
Server_DatabaseInterface *_databaseInterface,
|
Server_DatabaseInterface *_databaseInterface,
|
||||||
|
@ -44,6 +44,7 @@ Server_ProtocolHandler::~Server_ProtocolHandler()
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function must only be called from the thread this object lives in.
|
// This function must only be called from the thread this object lives in.
|
||||||
|
// Except when the server is shutting down.
|
||||||
// The thread must not hold any server locks when calling this (e.g. clientsLock, roomsLock).
|
// The thread must not hold any server locks when calling this (e.g. clientsLock, roomsLock).
|
||||||
void Server_ProtocolHandler::prepareDestroy()
|
void Server_ProtocolHandler::prepareDestroy()
|
||||||
{
|
{
|
||||||
|
@ -412,7 +413,7 @@ void Server_ProtocolHandler::pingClockTimeout()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((timeRunning - lastActionReceived) >= ceil(server->getIdleClientTimeout() * .9)) &&
|
if (((timeRunning - lastActionReceived) >= qCeil(server->getIdleClientTimeout() * .9)) &&
|
||||||
(!idleClientWarningSent) && (server->getIdleClientTimeout() > 0)) {
|
(!idleClientWarningSent) && (server->getIdleClientTimeout() > 0)) {
|
||||||
Event_NotifyUser event;
|
Event_NotifyUser event;
|
||||||
event.set_type(Event_NotifyUser::IDLEWARNING);
|
event.set_type(Event_NotifyUser::IDLEWARNING);
|
||||||
|
@ -489,7 +490,7 @@ Response::ResponseCode Server_ProtocolHandler::cmdLogin(const Command_Login &cmd
|
||||||
Response_Login *re = new Response_Login;
|
Response_Login *re = new Response_Login;
|
||||||
re->set_denied_reason_str(reasonStr.toStdString());
|
re->set_denied_reason_str(reasonStr.toStdString());
|
||||||
if (banSecondsLeft != 0)
|
if (banSecondsLeft != 0)
|
||||||
re->set_denied_end_time(QDateTime::currentDateTime().addSecs(banSecondsLeft).toTime_t());
|
re->set_denied_end_time(QDateTime::currentDateTime().addSecs(banSecondsLeft).toSecsSinceEpoch());
|
||||||
rc.setResponseExtension(re);
|
rc.setResponseExtension(re);
|
||||||
return Response::RespUserIsBanned;
|
return Response::RespUserIsBanned;
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,6 @@ protected:
|
||||||
private:
|
private:
|
||||||
QList<int> messageSizeOverTime, messageCountOverTime, commandCountOverTime;
|
QList<int> messageSizeOverTime, messageCountOverTime, commandCountOverTime;
|
||||||
int timeRunning, lastDataReceived, lastActionReceived;
|
int timeRunning, lastDataReceived, lastActionReceived;
|
||||||
QTimer *pingClock;
|
|
||||||
|
|
||||||
virtual void transmitProtocolItem(const ServerMessage &item) = 0;
|
virtual void transmitProtocolItem(const ServerMessage &item) = 0;
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ ServerInfo_User_Container::ServerInfo_User_Container(const ServerInfo_User_Conta
|
||||||
if (other.userInfo)
|
if (other.userInfo)
|
||||||
userInfo = new ServerInfo_User(*other.userInfo);
|
userInfo = new ServerInfo_User(*other.userInfo);
|
||||||
else
|
else
|
||||||
userInfo = 0;
|
userInfo = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerInfo_User_Container::~ServerInfo_User_Container()
|
ServerInfo_User_Container::~ServerInfo_User_Container()
|
||||||
|
|
|
@ -9,7 +9,7 @@ protected:
|
||||||
ServerInfo_User *userInfo;
|
ServerInfo_User *userInfo;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ServerInfo_User_Container(ServerInfo_User *_userInfo = 0);
|
ServerInfo_User_Container(ServerInfo_User *_userInfo = nullptr);
|
||||||
ServerInfo_User_Container(const ServerInfo_User &_userInfo);
|
ServerInfo_User_Container(const ServerInfo_User &_userInfo);
|
||||||
ServerInfo_User_Container(const ServerInfo_User_Container &other);
|
ServerInfo_User_Container(const ServerInfo_User_Container &other);
|
||||||
ServerInfo_User_Container &operator=(const ServerInfo_User_Container &other) = default;
|
ServerInfo_User_Container &operator=(const ServerInfo_User_Container &other) = default;
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
#define STRINGSIZES_H
|
#define STRINGSIZES_H
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QtMath>
|
|
||||||
|
|
||||||
// max size for short strings, like names and things that are generally a single phrase
|
// max size for short strings, like names and things that are generally a single phrase
|
||||||
constexpr int MAX_NAME_LENGTH = 0xff;
|
constexpr int MAX_NAME_LENGTH = 0xff;
|
||||||
|
|
|
@ -13,24 +13,25 @@ SET(dbconverter_SOURCES
|
||||||
${VERSION_STRING_CPP}
|
${VERSION_STRING_CPP}
|
||||||
)
|
)
|
||||||
|
|
||||||
# Qt5
|
|
||||||
find_package(Qt5 COMPONENTS Network Widgets REQUIRED)
|
|
||||||
set(dbconverter_QT_MODULES Qt5::Core Qt5::Network Qt5::Widgets)
|
|
||||||
SET(QT_DONT_USE_QTGUI TRUE)
|
SET(QT_DONT_USE_QTGUI TRUE)
|
||||||
|
|
||||||
QT5_WRAP_CPP(dbconverter_SOURCES
|
IF(Qt6_FOUND)
|
||||||
../cockatrice/src/settingscache.h
|
Qt6_WRAP_CPP(dbconverter_SOURCES
|
||||||
../cockatrice/src/settings/carddatabasesettings.h
|
../cockatrice/src/settingscache.h
|
||||||
)
|
../cockatrice/src/settings/carddatabasesettings.h
|
||||||
|
)
|
||||||
|
ELSEIF(Qt5_FOUND)
|
||||||
|
Qt5_WRAP_CPP(dbconverter_SOURCES
|
||||||
|
../cockatrice/src/settingscache.h
|
||||||
|
../cockatrice/src/settings/carddatabasesettings.h
|
||||||
|
)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
# Build servatrice binary and link it
|
# Build servatrice binary and link it
|
||||||
ADD_EXECUTABLE(dbconverter MACOSX_BUNDLE ${dbconverter_SOURCES} ${dbconverter_MOC_SRCS})
|
ADD_EXECUTABLE(dbconverter MACOSX_BUNDLE ${dbconverter_SOURCES} ${dbconverter_MOC_SRCS})
|
||||||
|
|
||||||
if(MSVC)
|
TARGET_LINK_LIBRARIES(dbconverter ${DB_CONVERTER_QT_MODULES})
|
||||||
TARGET_LINK_LIBRARIES(dbconverter ${dbconverter_QT_MODULES} Qt5::WinMain)
|
|
||||||
else()
|
|
||||||
TARGET_LINK_LIBRARIES(dbconverter ${dbconverter_QT_MODULES})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# install rules
|
# install rules
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
|
@ -55,9 +56,8 @@ if(APPLE)
|
||||||
# these needs to be relative to CMAKE_INSTALL_PREFIX
|
# these needs to be relative to CMAKE_INSTALL_PREFIX
|
||||||
set(plugin_dest_dir dbconverter.app/Contents/Plugins)
|
set(plugin_dest_dir dbconverter.app/Contents/Plugins)
|
||||||
set(qtconf_dest_dir dbconverter.app/Contents/Resources)
|
set(qtconf_dest_dir dbconverter.app/Contents/Resources)
|
||||||
get_filename_component(QT_LIBRARY_DIR "${QT_LIBRARY_DIR}/.." ABSOLUTE)
|
|
||||||
|
|
||||||
# qt5 plugins: platforms, sqldrivers/mysql
|
# Qt plugins: platforms
|
||||||
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime
|
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime
|
||||||
FILES_MATCHING
|
FILES_MATCHING
|
||||||
PATTERN "*.dSYM" EXCLUDE
|
PATTERN "*.dSYM" EXCLUDE
|
||||||
|
@ -87,10 +87,12 @@ if(WIN32)
|
||||||
|
|
||||||
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")
|
||||||
|
|
||||||
# qt5 plugins: platforms, sqldrivers/mysql
|
# Qt plugins: platforms
|
||||||
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime
|
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime FILES_MATCHING
|
||||||
FILES_MATCHING REGEX "(platforms/.*)\\.dll"
|
PATTERN "platforms/qdirect2d.dll"
|
||||||
REGEX ".*d\\.dll" EXCLUDE)
|
PATTERN "platforms/qminimal.dll"
|
||||||
|
PATTERN "platforms/qoffscreen.dll"
|
||||||
|
PATTERN "platforms/qwindows.dll")
|
||||||
|
|
||||||
install(CODE "
|
install(CODE "
|
||||||
file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf\" \"[Paths]
|
file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf\" \"[Paths]
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
#
|
#
|
||||||
# provides the oracle binary
|
# provides the oracle binary
|
||||||
|
|
||||||
PROJECT(Oracle VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
|
project(Oracle VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
|
||||||
|
|
||||||
# paths
|
# paths
|
||||||
set(DESKTOPDIR share/applications CACHE STRING "path to .desktop files")
|
set(DESKTOPDIR share/applications CACHE STRING "path to .desktop files")
|
||||||
|
|
||||||
SET(oracle_SOURCES
|
set(oracle_SOURCES
|
||||||
src/main.cpp
|
src/main.cpp
|
||||||
src/oraclewizard.cpp
|
src/oraclewizard.cpp
|
||||||
src/oracleimporter.cpp
|
src/oracleimporter.cpp
|
||||||
|
@ -34,13 +34,13 @@ SET(oracle_SOURCES
|
||||||
|
|
||||||
set(oracle_RESOURCES oracle.qrc)
|
set(oracle_RESOURCES oracle.qrc)
|
||||||
|
|
||||||
IF(UPDATE_TRANSLATIONS)
|
if(UPDATE_TRANSLATIONS)
|
||||||
FILE(GLOB_RECURSE translate_oracle_SRCS src/*.cpp src/*.h ../cockatrice/src/settingscache.cpp)
|
FILE(GLOB_RECURSE translate_oracle_SRCS src/*.cpp src/*.h ../cockatrice/src/settingscache.cpp)
|
||||||
SET(translate_SRCS ${translate_oracle_SRCS})
|
SET(translate_SRCS ${translate_oracle_SRCS})
|
||||||
SET(oracle_TS "${CMAKE_CURRENT_SOURCE_DIR}/translations/oracle_en@source.ts")
|
SET(oracle_TS "${CMAKE_CURRENT_SOURCE_DIR}/oracle_en@source.ts")
|
||||||
ELSE()
|
else()
|
||||||
FILE(GLOB oracle_TS "${CMAKE_CURRENT_SOURCE_DIR}/translations/*.ts")
|
FILE(GLOB oracle_TS "${CMAKE_CURRENT_SOURCE_DIR}/translations/*.ts")
|
||||||
ENDIF(UPDATE_TRANSLATIONS)
|
endif(UPDATE_TRANSLATIONS)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(oracle_SOURCES ${oracle_SOURCES} oracle.rc)
|
set(oracle_SOURCES ${oracle_SOURCES} oracle.rc)
|
||||||
|
@ -50,38 +50,19 @@ if(APPLE)
|
||||||
set(MACOSX_BUNDLE_ICON_FILE appicon.icns)
|
set(MACOSX_BUNDLE_ICON_FILE appicon.icns)
|
||||||
set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/resources/appicon.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
|
set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/resources/appicon.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
|
||||||
set(oracle_SOURCES ${oracle_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/resources/appicon.icns)
|
set(oracle_SOURCES ${oracle_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/resources/appicon.icns)
|
||||||
ENDIF(APPLE)
|
endif(APPLE)
|
||||||
|
|
||||||
# Qt5
|
if(Qt6_FOUND)
|
||||||
find_package(Qt5 COMPONENTS Concurrent Network Svg Widgets REQUIRED)
|
Qt6_ADD_RESOURCES(oracle_RESOURCES_RCC ${oracle_RESOURCES})
|
||||||
set(ORACLE_QT_MODULES Qt5::Concurrent Qt5::Network Qt5::Svg Qt5::Widgets)
|
elseif(Qt5_FOUND)
|
||||||
|
Qt5_ADD_RESOURCES(oracle_RESOURCES_RCC ${oracle_RESOURCES})
|
||||||
# Qt5LinguistTools
|
|
||||||
find_package(Qt5LinguistTools)
|
|
||||||
if(Qt5LinguistTools_FOUND)
|
|
||||||
list(APPEND ORACLE_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(oracle_QM ${translate_SRCS} ${oracle_TS})
|
|
||||||
else()
|
|
||||||
QT5_ADD_TRANSLATION(oracle_QM ${oracle_TS})
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
QT5_ADD_RESOURCES(oracle_RESOURCES_RCC ${oracle_RESOURCES})
|
|
||||||
|
|
||||||
INCLUDE_DIRECTORIES(../cockatrice/src)
|
INCLUDE_DIRECTORIES(../cockatrice/src)
|
||||||
|
|
||||||
# Libz is required to support zipped files
|
# Libz is required to support zipped files
|
||||||
FIND_PACKAGE(ZLIB)
|
FIND_PACKAGE(ZLIB)
|
||||||
IF(ZLIB_FOUND)
|
if(ZLIB_FOUND)
|
||||||
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIRS})
|
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIRS})
|
||||||
ADD_DEFINITIONS("-DHAS_ZLIB")
|
ADD_DEFINITIONS("-DHAS_ZLIB")
|
||||||
|
|
||||||
|
@ -89,34 +70,60 @@ IF(ZLIB_FOUND)
|
||||||
src/zip/unzip.cpp
|
src/zip/unzip.cpp
|
||||||
src/zip/zipglobal.cpp
|
src/zip/zipglobal.cpp
|
||||||
)
|
)
|
||||||
ELSE()
|
else()
|
||||||
MESSAGE(STATUS "Oracle: zlib not found; ZIP support disabled")
|
MESSAGE(STATUS "Oracle: zlib not found; ZIP support disabled")
|
||||||
ENDIF()
|
endif()
|
||||||
|
|
||||||
# LibLZMA is required to support xz files
|
# LibLZMA is required to support xz files
|
||||||
FIND_PACKAGE(LibLZMA)
|
FIND_PACKAGE(LibLZMA)
|
||||||
IF(LIBLZMA_FOUND)
|
if(LIBLZMA_FOUND)
|
||||||
INCLUDE_DIRECTORIES(${LIBLZMA_INCLUDE_DIRS})
|
INCLUDE_DIRECTORIES(${LIBLZMA_INCLUDE_DIRS})
|
||||||
ADD_DEFINITIONS("-DHAS_LZMA")
|
ADD_DEFINITIONS("-DHAS_LZMA")
|
||||||
|
|
||||||
set(oracle_SOURCES ${oracle_SOURCES}
|
set(oracle_SOURCES ${oracle_SOURCES}
|
||||||
src/lzma/decompress.cpp
|
src/lzma/decompress.cpp
|
||||||
)
|
)
|
||||||
ELSE()
|
else()
|
||||||
MESSAGE(STATUS "Oracle: LibLZMA not found; xz support disabled")
|
MESSAGE(STATUS "Oracle: LibLZMA not found; xz support disabled")
|
||||||
ENDIF()
|
endif()
|
||||||
|
|
||||||
# Build oracle binary and link it
|
set(ORACLE_MAC_QM_INSTALL_DIR "oracle.app/Contents/Resources/translations")
|
||||||
ADD_EXECUTABLE(oracle WIN32 MACOSX_BUNDLE ${oracle_SOURCES} ${oracle_QM} ${oracle_RESOURCES_RCC} ${oracle_MOC_SRCS})
|
set(ORACLE_UNIX_QM_INSTALL_DIR "share/oracle/translations")
|
||||||
TARGET_LINK_LIBRARIES(oracle ${ORACLE_QT_MODULES})
|
set(ORACLE_WIN32_QM_INSTALL_DIR "translations")
|
||||||
|
|
||||||
IF(ZLIB_FOUND)
|
if(Qt6_FOUND)
|
||||||
TARGET_LINK_LIBRARIES(oracle ${ZLIB_LIBRARIES})
|
# Qt6 Translations are linked after the executable is created in manual mode
|
||||||
ENDIF()
|
qt6_add_executable(oracle WIN32 MACOSX_BUNDLE ${oracle_SOURCES} ${oracle_RESOURCES_RCC} ${oracle_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(oracle_QM ${translate_SRCS} ${oracle_TS})
|
||||||
|
else()
|
||||||
|
qt5_add_translation(oracle_QM ${oracle_TS})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
add_executable(oracle WIN32 MACOSX_BUNDLE ${oracle_SOURCES} ${oracle_QM} ${oracle_RESOURCES_RCC} ${oracle_MOC_SRCS})
|
||||||
|
if(UNIX)
|
||||||
|
if(APPLE)
|
||||||
|
install(FILES ${oracle_QM} DESTINATION ${ORACLE_MAC_QM_INSTALL_DIR})
|
||||||
|
else()
|
||||||
|
install(FILES ${oracle_QM} DESTINATION ${ORACLE_UNIX_QM_INSTALL_DIR})
|
||||||
|
endif()
|
||||||
|
elseif(WIN32)
|
||||||
|
install(FILES ${oracle_QM} DESTINATION ${ORACLE_WIN32_QM_INSTALL_DIR})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
IF(LIBLZMA_FOUND)
|
TARGET_LINK_LIBRARIES(oracle PUBLIC ${ORACLE_QT_MODULES})
|
||||||
TARGET_LINK_LIBRARIES(oracle ${LIBLZMA_LIBRARIES})
|
|
||||||
ENDIF()
|
if(ZLIB_FOUND)
|
||||||
|
TARGET_LINK_LIBRARIES(oracle PUBLIC ${ZLIB_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(LIBLZMA_FOUND)
|
||||||
|
TARGET_LINK_LIBRARIES(oracle PUBLIC ${LIBLZMA_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
|
@ -129,17 +136,14 @@ if(UNIX)
|
||||||
set_target_properties(oracle PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/cmake/Info.plist)
|
set_target_properties(oracle PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/cmake/Info.plist)
|
||||||
|
|
||||||
INSTALL(TARGETS oracle BUNDLE DESTINATION ./)
|
INSTALL(TARGETS oracle BUNDLE DESTINATION ./)
|
||||||
INSTALL(FILES ${oracle_QM} DESTINATION ./oracle.app/Contents/Resources/translations)
|
|
||||||
else()
|
else()
|
||||||
# Assume linux
|
# Assume linux
|
||||||
INSTALL(TARGETS oracle RUNTIME DESTINATION bin/)
|
INSTALL(TARGETS oracle RUNTIME DESTINATION bin/)
|
||||||
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/oracle.png DESTINATION ${ICONDIR}/hicolor/48x48/apps)
|
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/oracle.png DESTINATION ${ICONDIR}/hicolor/48x48/apps)
|
||||||
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/oracle.svg DESTINATION ${ICONDIR}/hicolor/scalable/apps)
|
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/oracle.svg DESTINATION ${ICONDIR}/hicolor/scalable/apps)
|
||||||
INSTALL(FILES ${oracle_QM} DESTINATION share/oracle/translations)
|
|
||||||
endif()
|
endif()
|
||||||
elseif(WIN32)
|
elseif(WIN32)
|
||||||
INSTALL(TARGETS oracle RUNTIME DESTINATION ./)
|
INSTALL(TARGETS oracle RUNTIME DESTINATION ./)
|
||||||
INSTALL(FILES ${oracle_QM} DESTINATION ./translations)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
IF (NOT WIN32 AND NOT APPLE)
|
IF (NOT WIN32 AND NOT APPLE)
|
||||||
|
@ -150,9 +154,8 @@ if(APPLE)
|
||||||
# these needs to be relative to CMAKE_INSTALL_PREFIX
|
# these needs to be relative to CMAKE_INSTALL_PREFIX
|
||||||
set(plugin_dest_dir oracle.app/Contents/Plugins)
|
set(plugin_dest_dir oracle.app/Contents/Plugins)
|
||||||
set(qtconf_dest_dir oracle.app/Contents/Resources)
|
set(qtconf_dest_dir oracle.app/Contents/Resources)
|
||||||
get_filename_component(QT_LIBRARY_DIR "${QT_LIBRARY_DIR}/.." ABSOLUTE)
|
|
||||||
|
|
||||||
# qt5 plugins: iconengines, platforms
|
# Qt plugins: iconengines, platforms, styles, tls (Qt6)
|
||||||
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime
|
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime
|
||||||
FILES_MATCHING
|
FILES_MATCHING
|
||||||
PATTERN "*.dSYM" EXCLUDE
|
PATTERN "*.dSYM" EXCLUDE
|
||||||
|
@ -160,6 +163,7 @@ if(APPLE)
|
||||||
PATTERN "iconengines/*.dylib"
|
PATTERN "iconengines/*.dylib"
|
||||||
PATTERN "platforms/*.dylib"
|
PATTERN "platforms/*.dylib"
|
||||||
PATTERN "styles/*.dylib"
|
PATTERN "styles/*.dylib"
|
||||||
|
PATTERN "tls/*.dylib"
|
||||||
)
|
)
|
||||||
|
|
||||||
install(CODE "
|
install(CODE "
|
||||||
|
@ -177,7 +181,7 @@ Translations = Resources/translations\")
|
||||||
" COMPONENT Runtime)
|
" COMPONENT Runtime)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
IF(WIN32)
|
if(WIN32)
|
||||||
# these needs to be relative to CMAKE_INSTALL_PREFIX
|
# these needs to be relative to CMAKE_INSTALL_PREFIX
|
||||||
set(plugin_dest_dir Plugins)
|
set(plugin_dest_dir Plugins)
|
||||||
set(qtconf_dest_dir .)
|
set(qtconf_dest_dir .)
|
||||||
|
@ -185,10 +189,20 @@ IF(WIN32)
|
||||||
|
|
||||||
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")
|
||||||
|
|
||||||
# qt5 plugins: iconengines, platforms
|
# Qt plugins: iconengines, platforms, styles, tls (Qt6)
|
||||||
|
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime FILES_MATCHING
|
||||||
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime
|
PATTERN "iconengines/qsvgicon.dll"
|
||||||
FILES_MATCHING REGEX "(iconengines|platforms|styles)/.*[^d]\\.dll")
|
PATTERN "platforms/qdirect2d.dll"
|
||||||
|
PATTERN "platforms/qminimal.dll"
|
||||||
|
PATTERN "platforms/qoffscreen.dll"
|
||||||
|
PATTERN "platforms/qwindows.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")
|
||||||
|
|
||||||
install(CODE "
|
install(CODE "
|
||||||
file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf\" \"[Paths]
|
file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf\" \"[Paths]
|
||||||
|
@ -204,3 +218,26 @@ Translations = Resources/translations\")
|
||||||
fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/Oracle.exe\" \"\${QTPLUGINS}\" \"${libSearchDirs}\")
|
fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/Oracle.exe\" \"\${QTPLUGINS}\" \"${libSearchDirs}\")
|
||||||
" COMPONENT Runtime)
|
" COMPONENT Runtime)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(Qt6LinguistTools_FOUND)
|
||||||
|
#Qt6 Translations happen after the executable is built up
|
||||||
|
if(UPDATE_TRANSLATIONS)
|
||||||
|
qt6_add_translations(oracle TS_FILES ${oracle_TS} SOURCES ${translate_SRCS} QM_FILES_OUTPUT_VARIABLE oracle_QM)
|
||||||
|
else()
|
||||||
|
qt6_add_translations(oracle TS_FILES ${oracle_TS} QM_FILES_OUTPUT_VARIABLE oracle_QM)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(UNIX)
|
||||||
|
if(APPLE)
|
||||||
|
install(FILES ${oracle_QM} DESTINATION ${ORACLE_MAC_QM_INSTALL_DIR})
|
||||||
|
else()
|
||||||
|
install(FILES ${oracle_QM} DESTINATION ${ORACLE_UNIX_QM_INSTALL_DIR})
|
||||||
|
endif()
|
||||||
|
elseif(WIN32)
|
||||||
|
install(FILES ${oracle_QM} DESTINATION ${ORACLE_WIN32_QM_INSTALL_DIR})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(Qt6_FOUND)
|
||||||
|
qt6_finalize_target(oracle)
|
||||||
|
endif()
|
||||||
|
|
|
@ -22,9 +22,28 @@ void installNewTranslator()
|
||||||
{
|
{
|
||||||
QString lang = SettingsCache::instance().getLang();
|
QString lang = SettingsCache::instance().getLang();
|
||||||
|
|
||||||
qtTranslator->load("qt_" + lang, QLibraryInfo::location(QLibraryInfo::TranslationsPath));
|
QString qtNameHint = "qt_" + lang;
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
QString qtTranslationPath = QLibraryInfo::path(QLibraryInfo::TranslationsPath);
|
||||||
|
#else
|
||||||
|
QString qtTranslationPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool qtTranslationLoaded = qtTranslator->load(qtNameHint, qtTranslationPath);
|
||||||
|
if (!qtTranslationLoaded) {
|
||||||
|
qDebug() << "Unable to load qt translation" << qtNameHint << "at" << qtTranslationPath;
|
||||||
|
} else {
|
||||||
|
qDebug() << "Loaded qt translation" << qtNameHint << "at" << qtTranslationPath;
|
||||||
|
}
|
||||||
qApp->installTranslator(qtTranslator);
|
qApp->installTranslator(qtTranslator);
|
||||||
translator->load(translationPrefix + "_" + lang, translationPath);
|
|
||||||
|
QString appNameHint = translationPrefix + "_" + lang;
|
||||||
|
bool appTranslationLoaded = qtTranslator->load(appNameHint, translationPath);
|
||||||
|
if (!appTranslationLoaded) {
|
||||||
|
qDebug() << "Unable to load" << translationPrefix << "translation" << appNameHint << "at" << translationPath;
|
||||||
|
} else {
|
||||||
|
qDebug() << "Loaded" << translationPrefix << "translation" << appNameHint << "at" << translationPath;
|
||||||
|
}
|
||||||
qApp->installTranslator(translator);
|
qApp->installTranslator(translator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,10 +81,8 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
QIcon icon("theme:appicon.svg");
|
QIcon icon("theme:appicon.svg");
|
||||||
wizard.setWindowIcon(icon);
|
wizard.setWindowIcon(icon);
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0)
|
|
||||||
// set name of the app desktop file; used by wayland to load the window icon
|
// set name of the app desktop file; used by wayland to load the window icon
|
||||||
QGuiApplication::setDesktopFileName("oracle");
|
QGuiApplication::setDesktopFileName("oracle");
|
||||||
#endif
|
|
||||||
|
|
||||||
wizard.show();
|
wizard.show();
|
||||||
|
|
||||||
|
|
|
@ -116,7 +116,7 @@ CardInfoPtr OracleImporter::addCard(QString name,
|
||||||
QStringList symbols = manacost.split("}");
|
QStringList symbols = manacost.split("}");
|
||||||
QString formattedCardCost;
|
QString formattedCardCost;
|
||||||
for (QString symbol : symbols) {
|
for (QString symbol : symbols) {
|
||||||
if (symbol.contains(QRegExp("[0-9WUBGRP]/[0-9WUBGRP]"))) {
|
if (symbol.contains(QRegularExpression("[0-9WUBGRP]/[0-9WUBGRP]"))) {
|
||||||
symbol.append("}");
|
symbol.append("}");
|
||||||
} else {
|
} else {
|
||||||
symbol.remove(QChar('{'));
|
symbol.remove(QChar('{'));
|
||||||
|
|
|
@ -143,16 +143,19 @@ IntroPage::IntroPage(QWidget *parent) : OracleWizardPage(parent)
|
||||||
languageLabel = new QLabel(this);
|
languageLabel = new QLabel(this);
|
||||||
versionLabel = new QLabel(this);
|
versionLabel = new QLabel(this);
|
||||||
languageBox = new QComboBox(this);
|
languageBox = new QComboBox(this);
|
||||||
QString setLanguage = SettingsCache::instance().getLang();
|
|
||||||
|
|
||||||
QStringList qmFiles = findQmFiles();
|
QStringList languageCodes = findQmFiles();
|
||||||
for (int i = 0; i < qmFiles.size(); i++) {
|
for (const QString &code : languageCodes) {
|
||||||
QString langName = languageName(qmFiles[i]);
|
QString langName = languageName(code);
|
||||||
languageBox->addItem(langName, qmFiles[i]);
|
languageBox->addItem(langName, code);
|
||||||
if ((qmFiles[i] == setLanguage) ||
|
}
|
||||||
(setLanguage.isEmpty() && langName == QCoreApplication::translate("i18n", DEFAULT_LANG_NAME))) {
|
|
||||||
languageBox->setCurrentIndex(i);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
connect(languageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(languageBoxChanged(int)));
|
connect(languageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(languageBoxChanged(int)));
|
||||||
|
@ -170,15 +173,20 @@ QStringList IntroPage::findQmFiles()
|
||||||
{
|
{
|
||||||
QDir dir(translationPath);
|
QDir dir(translationPath);
|
||||||
QStringList fileNames = dir.entryList(QStringList(translationPrefix + "_*.qm"), QDir::Files, QDir::Name);
|
QStringList fileNames = dir.entryList(QStringList(translationPrefix + "_*.qm"), QDir::Files, QDir::Name);
|
||||||
fileNames.replaceInStrings(QRegExp(translationPrefix + "_(.*)\\.qm"), "\\1");
|
fileNames.replaceInStrings(QRegularExpression(translationPrefix + "_(.*)\\.qm"), "\\1");
|
||||||
fileNames.removeOne("en@source");
|
|
||||||
return fileNames;
|
return fileNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString IntroPage::languageName(const QString &qmFile)
|
QString IntroPage::languageName(const QString &lang)
|
||||||
{
|
{
|
||||||
QTranslator qTranslator;
|
QTranslator qTranslator;
|
||||||
qTranslator.load(translationPrefix + "_" + qmFile + ".qm", translationPath);
|
|
||||||
|
QString appNameHint = translationPrefix + "_" + lang;
|
||||||
|
bool appTranslationLoaded = qTranslator.load(appNameHint, translationPath);
|
||||||
|
if (!appTranslationLoaded) {
|
||||||
|
qDebug() << "Unable to load" << translationPrefix << "translation" << appNameHint << "at" << translationPath;
|
||||||
|
}
|
||||||
|
|
||||||
return qTranslator.translate("i18n", DEFAULT_LANG_NAME);
|
return qTranslator.translate("i18n", DEFAULT_LANG_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -454,8 +462,10 @@ void LoadSetsPage::readSetsFromByteArray(QByteArray data)
|
||||||
zipDownloadFailed(tr("Xz extraction failed."));
|
zipDownloadFailed(tr("Xz extraction failed."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const auto &outBufferData = outBuffer->data();
|
||||||
|
|
||||||
future = QtConcurrent::run(wizard()->importer, &OracleImporter::readSetsFromByteArray, outBuffer->data());
|
future = QtConcurrent::run(
|
||||||
|
[this, &outBufferData] { return wizard()->importer->readSetsFromByteArray(outBufferData); });
|
||||||
watcher.setFuture(future);
|
watcher.setFuture(future);
|
||||||
return;
|
return;
|
||||||
#else
|
#else
|
||||||
|
@ -495,8 +505,10 @@ void LoadSetsPage::readSetsFromByteArray(QByteArray data)
|
||||||
uz.closeArchive();
|
uz.closeArchive();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const auto &outBufferData = outBuffer->data();
|
||||||
|
|
||||||
future = QtConcurrent::run(wizard()->importer, &OracleImporter::readSetsFromByteArray, outBuffer->data());
|
future = QtConcurrent::run(
|
||||||
|
[this, &outBufferData] { return wizard()->importer->readSetsFromByteArray(outBufferData); });
|
||||||
watcher.setFuture(future);
|
watcher.setFuture(future);
|
||||||
return;
|
return;
|
||||||
#else
|
#else
|
||||||
|
@ -510,7 +522,7 @@ void LoadSetsPage::readSetsFromByteArray(QByteArray data)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
// Start the computation.
|
// Start the computation.
|
||||||
future = QtConcurrent::run(wizard()->importer, &OracleImporter::readSetsFromByteArray, data);
|
future = QtConcurrent::run([this, &data] { return wizard()->importer->readSetsFromByteArray(data); });
|
||||||
watcher.setFuture(future);
|
watcher.setFuture(future);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QStringList findQmFiles();
|
QStringList findQmFiles();
|
||||||
QString languageName(const QString &qmFile);
|
QString languageName(const QString &lang);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QLabel *label, *languageLabel, *versionLabel;
|
QLabel *label, *languageLabel, *versionLabel;
|
||||||
|
@ -189,4 +189,4 @@ protected:
|
||||||
QString getFileType() override;
|
QString getFileType() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -31,36 +31,35 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "json.h"
|
#include "json.h"
|
||||||
|
|
||||||
|
#include <QMetaType>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
namespace QtJson
|
namespace QtJson
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
static QString sanitizeString(QString str)
|
static QString sanitizeString(QString str)
|
||||||
{
|
{
|
||||||
str.replace(QLatin1String("\\"), QLatin1String("\\\\"));
|
str.replace(QLatin1String("\\"), QLatin1String("\\\\"));
|
||||||
str.replace(QLatin1String("\""), QLatin1String("\\\""));
|
str.replace(QLatin1String("\""), QLatin1String("\\\""));
|
||||||
str.replace(QLatin1String("\b"), QLatin1String("\\b"));
|
str.replace(QLatin1String("\b"), QLatin1String("\\b"));
|
||||||
str.replace(QLatin1String("\f"), QLatin1String("\\f"));
|
str.replace(QLatin1String("\f"), QLatin1String("\\f"));
|
||||||
str.replace(QLatin1String("\n"), QLatin1String("\\n"));
|
str.replace(QLatin1String("\n"), QLatin1String("\\n"));
|
||||||
str.replace(QLatin1String("\r"), QLatin1String("\\r"));
|
str.replace(QLatin1String("\r"), QLatin1String("\\r"));
|
||||||
str.replace(QLatin1String("\t"), QLatin1String("\\t"));
|
str.replace(QLatin1String("\t"), QLatin1String("\\t"));
|
||||||
return QString(QLatin1String("\"%1\"")).arg(str);
|
return QString(QLatin1String("\"%1\"")).arg(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
static QByteArray join(const QList<QByteArray> &list, const QByteArray &sep)
|
static QByteArray join(const QList<QByteArray> &list, const QByteArray &sep)
|
||||||
{
|
{
|
||||||
QByteArray res;
|
QByteArray res;
|
||||||
Q_FOREACH(const QByteArray &i, list)
|
Q_FOREACH (const QByteArray &i, list) {
|
||||||
{
|
if (!res.isEmpty()) {
|
||||||
if(!res.isEmpty())
|
res += sep;
|
||||||
{
|
|
||||||
res += sep;
|
|
||||||
}
|
|
||||||
res += i;
|
|
||||||
}
|
}
|
||||||
return res;
|
res += i;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -68,8 +67,8 @@ static QByteArray join(const QList<QByteArray> &list, const QByteArray &sep)
|
||||||
*/
|
*/
|
||||||
QVariant Json::parse(const QString &json)
|
QVariant Json::parse(const QString &json)
|
||||||
{
|
{
|
||||||
bool success = true;
|
bool success = true;
|
||||||
return Json::parse(json, success);
|
return Json::parse(json, success);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -77,149 +76,160 @@ QVariant Json::parse(const QString &json)
|
||||||
*/
|
*/
|
||||||
QVariant Json::parse(const QString &json, bool &success)
|
QVariant Json::parse(const QString &json, bool &success)
|
||||||
{
|
{
|
||||||
success = true;
|
success = true;
|
||||||
|
|
||||||
//Return an empty QVariant if the JSON data is either null or empty
|
// Return an empty QVariant if the JSON data is either null or empty
|
||||||
if(!json.isNull() || !json.isEmpty())
|
if (!json.isNull() || !json.isEmpty()) {
|
||||||
{
|
QString data = json;
|
||||||
QString data = json;
|
// We'll start from index 0
|
||||||
//We'll start from index 0
|
int index = 0;
|
||||||
int index = 0;
|
|
||||||
|
|
||||||
//Parse the first value
|
// Parse the first value
|
||||||
QVariant value = Json::parseValue(data, index, success);
|
QVariant value = Json::parseValue(data, index, success);
|
||||||
|
|
||||||
//Return the parsed value
|
// Return the parsed value
|
||||||
return value;
|
return value;
|
||||||
}
|
} else {
|
||||||
else
|
// Return the empty QVariant
|
||||||
{
|
return QVariant();
|
||||||
//Return the empty QVariant
|
}
|
||||||
return QVariant();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray Json::serialize(const QVariant &data)
|
QByteArray Json::serialize(const QVariant &data)
|
||||||
{
|
{
|
||||||
bool success = true;
|
bool success = true;
|
||||||
return Json::serialize(data, success);
|
return Json::serialize(data, success);
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray Json::serialize(const QVariant &data, bool &success)
|
QByteArray Json::serialize(const QVariant &data, bool &success)
|
||||||
{
|
{
|
||||||
QByteArray str;
|
QByteArray str;
|
||||||
success = true;
|
success = true;
|
||||||
|
|
||||||
if(!data.isValid()) // invalid or null?
|
if (!data.isValid()) // invalid or null?
|
||||||
{
|
{
|
||||||
str = "null";
|
str = "null";
|
||||||
|
}
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
else if ((data.typeId() == QMetaType::Type::QVariantList) ||
|
||||||
|
(data.typeId() == QMetaType::Type::QStringList)) // variant is a list?
|
||||||
|
#else
|
||||||
|
else if ((data.type() == QVariant::List) || (data.type() == QVariant::StringList)) // variant is a list?
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
QList<QByteArray> values;
|
||||||
|
const QVariantList list = data.toList();
|
||||||
|
Q_FOREACH (const QVariant &v, list) {
|
||||||
|
QByteArray serializedValue = serialize(v);
|
||||||
|
if (serializedValue.isNull()) {
|
||||||
|
success = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
values << serializedValue;
|
||||||
}
|
}
|
||||||
else if((data.type() == QVariant::List) || (data.type() == QVariant::StringList)) // variant is a list?
|
|
||||||
{
|
|
||||||
QList<QByteArray> values;
|
|
||||||
const QVariantList list = data.toList();
|
|
||||||
Q_FOREACH(const QVariant& v, list)
|
|
||||||
{
|
|
||||||
QByteArray serializedValue = serialize(v);
|
|
||||||
if(serializedValue.isNull())
|
|
||||||
{
|
|
||||||
success = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
values << serializedValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
str = "[ " + join( values, ", " ) + " ]";
|
str = "[ " + join(values, ", ") + " ]";
|
||||||
}
|
}
|
||||||
else if(data.type() == QVariant::Hash) // variant is a hash?
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
{
|
else if ((data.typeId() == QMetaType::Type::QVariantHash)) // variant is a list?
|
||||||
const QVariantHash vhash = data.toHash();
|
#else
|
||||||
QHashIterator<QString, QVariant> it( vhash );
|
else if (data.type() == QVariant::Hash) // variant is a hash?
|
||||||
str = "{ ";
|
#endif
|
||||||
QList<QByteArray> pairs;
|
{
|
||||||
|
const QVariantHash vhash = data.toHash();
|
||||||
|
QHashIterator<QString, QVariant> it(vhash);
|
||||||
|
str = "{ ";
|
||||||
|
QList<QByteArray> pairs;
|
||||||
|
|
||||||
while(it.hasNext())
|
while (it.hasNext()) {
|
||||||
{
|
it.next();
|
||||||
it.next();
|
QByteArray serializedValue = serialize(it.value());
|
||||||
QByteArray serializedValue = serialize(it.value());
|
|
||||||
|
|
||||||
if(serializedValue.isNull())
|
if (serializedValue.isNull()) {
|
||||||
{
|
success = false;
|
||||||
success = false;
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
pairs << sanitizeString(it.key()).toUtf8() + " : " + serializedValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
str += join(pairs, ", ");
|
pairs << sanitizeString(it.key()).toUtf8() + " : " + serializedValue;
|
||||||
str += " }";
|
|
||||||
}
|
}
|
||||||
else if(data.type() == QVariant::Map) // variant is a map?
|
|
||||||
{
|
str += join(pairs, ", ");
|
||||||
const QVariantMap vmap = data.toMap();
|
str += " }";
|
||||||
QMapIterator<QString, QVariant> it( vmap );
|
}
|
||||||
str = "{ ";
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
QList<QByteArray> pairs;
|
else if ((data.typeId() == QMetaType::Type::QVariantMap)) // variant is a list?
|
||||||
while(it.hasNext())
|
#else
|
||||||
{
|
else if (data.type() == QVariant::Map) // variant is a map?
|
||||||
it.next();
|
#endif
|
||||||
QByteArray serializedValue = serialize(it.value());
|
{
|
||||||
if(serializedValue.isNull())
|
const QVariantMap vmap = data.toMap();
|
||||||
{
|
QMapIterator<QString, QVariant> it(vmap);
|
||||||
success = false;
|
str = "{ ";
|
||||||
break;
|
QList<QByteArray> pairs;
|
||||||
}
|
while (it.hasNext()) {
|
||||||
pairs << sanitizeString(it.key()).toUtf8() + " : " + serializedValue;
|
it.next();
|
||||||
}
|
QByteArray serializedValue = serialize(it.value());
|
||||||
str += join(pairs, ", ");
|
if (serializedValue.isNull()) {
|
||||||
str += " }";
|
|
||||||
}
|
|
||||||
else if((data.type() == QVariant::String) || (data.type() == QVariant::ByteArray)) // a string or a byte array?
|
|
||||||
{
|
|
||||||
str = sanitizeString(data.toString()).toUtf8();
|
|
||||||
}
|
|
||||||
else if(data.type() == QVariant::Double) // double?
|
|
||||||
{
|
|
||||||
str = QByteArray::number(data.toDouble(), 'g', 20);
|
|
||||||
if(!str.contains(".") && ! str.contains("e"))
|
|
||||||
{
|
|
||||||
str += ".0";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (data.type() == QVariant::Bool) // boolean value?
|
|
||||||
{
|
|
||||||
str = data.toBool() ? "true" : "false";
|
|
||||||
}
|
|
||||||
else if (data.type() == QVariant::ULongLong) // large unsigned number?
|
|
||||||
{
|
|
||||||
str = QByteArray::number(data.value<qulonglong>());
|
|
||||||
}
|
|
||||||
else if ( data.canConvert<qlonglong>() ) // any signed number?
|
|
||||||
{
|
|
||||||
str = QByteArray::number(data.value<qlonglong>());
|
|
||||||
}
|
|
||||||
else if (data.canConvert<long>())
|
|
||||||
{
|
|
||||||
str = QString::number(data.value<long>()).toUtf8();
|
|
||||||
}
|
|
||||||
else if (data.canConvert<QString>()) // can value be converted to string?
|
|
||||||
{
|
|
||||||
// this will catch QDate, QDateTime, QUrl, ...
|
|
||||||
str = sanitizeString(data.toString()).toUtf8();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
success = false;
|
success = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pairs << sanitizeString(it.key()).toUtf8() + " : " + serializedValue;
|
||||||
}
|
}
|
||||||
if (success)
|
str += join(pairs, ", ");
|
||||||
{
|
str += " }";
|
||||||
return str;
|
}
|
||||||
}
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
else
|
else if ((data.typeId() == QMetaType::Type::QString) ||
|
||||||
{
|
(data.typeId() == QMetaType::Type::QByteArray)) // variant is a list?
|
||||||
return QByteArray();
|
#else
|
||||||
|
else if ((data.type() == QVariant::String) || (data.type() == QVariant::ByteArray)) // a string or a byte array?
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
str = sanitizeString(data.toString()).toUtf8();
|
||||||
|
}
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
else if (data.typeId() == QMetaType::Type::Double)
|
||||||
|
#else
|
||||||
|
else if (data.type() == QVariant::Double) // double?
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
str = QByteArray::number(data.toDouble(), 'g', 20);
|
||||||
|
if (!str.contains(".") && !str.contains("e")) {
|
||||||
|
str += ".0";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
else if (data.typeId() == QMetaType::Type::Bool)
|
||||||
|
#else
|
||||||
|
else if (data.type() == QVariant::Bool) // boolean value?
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
str = data.toBool() ? "true" : "false";
|
||||||
|
}
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
else if (data.typeId() == QMetaType::Type::ULongLong)
|
||||||
|
#else
|
||||||
|
else if (data.type() == QVariant::ULongLong) // large unsigned number?
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
str = QByteArray::number(data.value<qulonglong>());
|
||||||
|
} else if (data.canConvert<qlonglong>()) // any signed number?
|
||||||
|
{
|
||||||
|
str = QByteArray::number(data.value<qlonglong>());
|
||||||
|
} else if (data.canConvert<long>()) {
|
||||||
|
str = QString::number(data.value<long>()).toUtf8();
|
||||||
|
} else if (data.canConvert<QString>()) // can value be converted to string?
|
||||||
|
{
|
||||||
|
// this will catch QDate, QDateTime, QUrl, ...
|
||||||
|
str = sanitizeString(data.toString()).toUtf8();
|
||||||
|
} else {
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
if (success) {
|
||||||
|
return str;
|
||||||
|
} else {
|
||||||
|
return QByteArray();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -227,34 +237,33 @@ QByteArray Json::serialize(const QVariant &data, bool &success)
|
||||||
*/
|
*/
|
||||||
QVariant Json::parseValue(const QString &json, int &index, bool &success)
|
QVariant Json::parseValue(const QString &json, int &index, bool &success)
|
||||||
{
|
{
|
||||||
//Determine what kind of data we should parse by
|
// Determine what kind of data we should parse by
|
||||||
//checking out the upcoming token
|
// checking out the upcoming token
|
||||||
switch(Json::lookAhead(json, index))
|
switch (Json::lookAhead(json, index)) {
|
||||||
{
|
case JsonTokenString:
|
||||||
case JsonTokenString:
|
return Json::parseString(json, index, success);
|
||||||
return Json::parseString(json, index, success);
|
case JsonTokenNumber:
|
||||||
case JsonTokenNumber:
|
return Json::parseNumber(json, index);
|
||||||
return Json::parseNumber(json, index);
|
case JsonTokenCurlyOpen:
|
||||||
case JsonTokenCurlyOpen:
|
return Json::parseObject(json, index, success);
|
||||||
return Json::parseObject(json, index, success);
|
case JsonTokenSquaredOpen:
|
||||||
case JsonTokenSquaredOpen:
|
return Json::parseArray(json, index, success);
|
||||||
return Json::parseArray(json, index, success);
|
case JsonTokenTrue:
|
||||||
case JsonTokenTrue:
|
Json::nextToken(json, index);
|
||||||
Json::nextToken(json, index);
|
return QVariant(true);
|
||||||
return QVariant(true);
|
case JsonTokenFalse:
|
||||||
case JsonTokenFalse:
|
Json::nextToken(json, index);
|
||||||
Json::nextToken(json, index);
|
return QVariant(false);
|
||||||
return QVariant(false);
|
case JsonTokenNull:
|
||||||
case JsonTokenNull:
|
Json::nextToken(json, index);
|
||||||
Json::nextToken(json, index);
|
return QVariant();
|
||||||
return QVariant();
|
case JsonTokenNone:
|
||||||
case JsonTokenNone:
|
break;
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
//If there were no tokens, flag the failure and return an empty QVariant
|
// If there were no tokens, flag the failure and return an empty QVariant
|
||||||
success = false;
|
success = false;
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -262,69 +271,58 @@ QVariant Json::parseValue(const QString &json, int &index, bool &success)
|
||||||
*/
|
*/
|
||||||
QVariant Json::parseObject(const QString &json, int &index, bool &success)
|
QVariant Json::parseObject(const QString &json, int &index, bool &success)
|
||||||
{
|
{
|
||||||
QVariantMap map;
|
QVariantMap map;
|
||||||
int token;
|
int token;
|
||||||
|
|
||||||
//Get rid of the whitespace and increment index
|
// Get rid of the whitespace and increment index
|
||||||
Json::nextToken(json, index);
|
Json::nextToken(json, index);
|
||||||
|
|
||||||
//Loop through all of the key/value pairs of the object
|
// Loop through all of the key/value pairs of the object
|
||||||
bool done = false;
|
bool done = false;
|
||||||
while(!done)
|
while (!done) {
|
||||||
{
|
// Get the upcoming token
|
||||||
//Get the upcoming token
|
token = Json::lookAhead(json, index);
|
||||||
token = Json::lookAhead(json, index);
|
|
||||||
|
|
||||||
if(token == JsonTokenNone)
|
if (token == JsonTokenNone) {
|
||||||
{
|
success = false;
|
||||||
success = false;
|
return QVariantMap();
|
||||||
return QVariantMap();
|
} else if (token == JsonTokenComma) {
|
||||||
}
|
Json::nextToken(json, index);
|
||||||
else if(token == JsonTokenComma)
|
} else if (token == JsonTokenCurlyClose) {
|
||||||
{
|
Json::nextToken(json, index);
|
||||||
Json::nextToken(json, index);
|
return map;
|
||||||
}
|
} else {
|
||||||
else if(token == JsonTokenCurlyClose)
|
// Parse the key/value pair's name
|
||||||
{
|
QString name = Json::parseString(json, index, success).toString();
|
||||||
Json::nextToken(json, index);
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//Parse the key/value pair's name
|
|
||||||
QString name = Json::parseString(json, index, success).toString();
|
|
||||||
|
|
||||||
if(!success)
|
if (!success) {
|
||||||
{
|
return QVariantMap();
|
||||||
return QVariantMap();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
//Get the next token
|
// Get the next token
|
||||||
token = Json::nextToken(json, index);
|
token = Json::nextToken(json, index);
|
||||||
|
|
||||||
//If the next token is not a colon, flag the failure
|
// If the next token is not a colon, flag the failure
|
||||||
//return an empty QVariant
|
// return an empty QVariant
|
||||||
if(token != JsonTokenColon)
|
if (token != JsonTokenColon) {
|
||||||
{
|
success = false;
|
||||||
success = false;
|
return QVariant(QVariantMap());
|
||||||
return QVariant(QVariantMap());
|
}
|
||||||
}
|
|
||||||
|
|
||||||
//Parse the key/value pair's value
|
// Parse the key/value pair's value
|
||||||
QVariant value = Json::parseValue(json, index, success);
|
QVariant value = Json::parseValue(json, index, success);
|
||||||
|
|
||||||
if(!success)
|
if (!success) {
|
||||||
{
|
return QVariantMap();
|
||||||
return QVariantMap();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
//Assign the value to the key in the map
|
// Assign the value to the key in the map
|
||||||
map[name] = value;
|
map[name] = value;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Return the map successfully
|
// Return the map successfully
|
||||||
return QVariant(map);
|
return QVariant(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -332,43 +330,34 @@ QVariant Json::parseObject(const QString &json, int &index, bool &success)
|
||||||
*/
|
*/
|
||||||
QVariant Json::parseArray(const QString &json, int &index, bool &success)
|
QVariant Json::parseArray(const QString &json, int &index, bool &success)
|
||||||
{
|
{
|
||||||
QVariantList list;
|
QVariantList list;
|
||||||
|
|
||||||
Json::nextToken(json, index);
|
Json::nextToken(json, index);
|
||||||
|
|
||||||
bool done = false;
|
bool done = false;
|
||||||
while(!done)
|
while (!done) {
|
||||||
{
|
int token = Json::lookAhead(json, index);
|
||||||
int token = Json::lookAhead(json, index);
|
|
||||||
|
|
||||||
if(token == JsonTokenNone)
|
if (token == JsonTokenNone) {
|
||||||
{
|
success = false;
|
||||||
success = false;
|
return QVariantList();
|
||||||
return QVariantList();
|
} else if (token == JsonTokenComma) {
|
||||||
}
|
Json::nextToken(json, index);
|
||||||
else if(token == JsonTokenComma)
|
} else if (token == JsonTokenSquaredClose) {
|
||||||
{
|
Json::nextToken(json, index);
|
||||||
Json::nextToken(json, index);
|
break;
|
||||||
}
|
} else {
|
||||||
else if(token == JsonTokenSquaredClose)
|
QVariant value = Json::parseValue(json, index, success);
|
||||||
{
|
|
||||||
Json::nextToken(json, index);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QVariant value = Json::parseValue(json, index, success);
|
|
||||||
|
|
||||||
if(!success)
|
if (!success) {
|
||||||
{
|
return QVariantList();
|
||||||
return QVariantList();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
list.push_back(value);
|
list.push_back(value);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return QVariant(list);
|
return QVariant(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -376,102 +365,73 @@ QVariant Json::parseArray(const QString &json, int &index, bool &success)
|
||||||
*/
|
*/
|
||||||
QVariant Json::parseString(const QString &json, int &index, bool &success)
|
QVariant Json::parseString(const QString &json, int &index, bool &success)
|
||||||
{
|
{
|
||||||
QString s;
|
QString s;
|
||||||
QChar c;
|
QChar c;
|
||||||
|
|
||||||
Json::eatWhitespace(json, index);
|
Json::eatWhitespace(json, index);
|
||||||
|
|
||||||
|
c = json[index++];
|
||||||
|
|
||||||
|
bool complete = false;
|
||||||
|
while (!complete) {
|
||||||
|
if (index == json.size()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
c = json[index++];
|
c = json[index++];
|
||||||
|
|
||||||
bool complete = false;
|
if (c == '\"') {
|
||||||
while(!complete)
|
complete = true;
|
||||||
{
|
break;
|
||||||
if(index == json.size())
|
} else if (c == '\\') {
|
||||||
{
|
if (index == json.size()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
c = json[index++];
|
c = json[index++];
|
||||||
|
|
||||||
if(c == '\"')
|
if (c == '\"') {
|
||||||
{
|
s.append('\"');
|
||||||
complete = true;
|
} else if (c == '\\') {
|
||||||
break;
|
s.append('\\');
|
||||||
}
|
} else if (c == '/') {
|
||||||
else if(c == '\\')
|
s.append('/');
|
||||||
{
|
} else if (c == 'b') {
|
||||||
if(index == json.size())
|
s.append('\b');
|
||||||
{
|
} else if (c == 'f') {
|
||||||
break;
|
s.append('\f');
|
||||||
}
|
} else if (c == 'n') {
|
||||||
|
s.append('\n');
|
||||||
c = json[index++];
|
} else if (c == 'r') {
|
||||||
|
s.append('\r');
|
||||||
if(c == '\"')
|
} else if (c == 't') {
|
||||||
{
|
s.append('\t');
|
||||||
s.append('\"');
|
} else if (c == 'u') {
|
||||||
}
|
int remainingLength = json.size() - index;
|
||||||
else if(c == '\\')
|
|
||||||
{
|
if (remainingLength >= 4) {
|
||||||
s.append('\\');
|
QString unicodeStr = json.mid(index, 4);
|
||||||
}
|
|
||||||
else if(c == '/')
|
int symbol = unicodeStr.toInt(0, 16);
|
||||||
{
|
|
||||||
s.append('/');
|
s.append(QChar(symbol));
|
||||||
}
|
|
||||||
else if(c == 'b')
|
index += 4;
|
||||||
{
|
} else {
|
||||||
s.append('\b');
|
break;
|
||||||
}
|
|
||||||
else if(c == 'f')
|
|
||||||
{
|
|
||||||
s.append('\f');
|
|
||||||
}
|
|
||||||
else if(c == 'n')
|
|
||||||
{
|
|
||||||
s.append('\n');
|
|
||||||
}
|
|
||||||
else if(c == 'r')
|
|
||||||
{
|
|
||||||
s.append('\r');
|
|
||||||
}
|
|
||||||
else if(c == 't')
|
|
||||||
{
|
|
||||||
s.append('\t');
|
|
||||||
}
|
|
||||||
else if(c == 'u')
|
|
||||||
{
|
|
||||||
int remainingLength = json.size() - index;
|
|
||||||
|
|
||||||
if(remainingLength >= 4)
|
|
||||||
{
|
|
||||||
QString unicodeStr = json.mid(index, 4);
|
|
||||||
|
|
||||||
int symbol = unicodeStr.toInt(0, 16);
|
|
||||||
|
|
||||||
s.append(QChar(symbol));
|
|
||||||
|
|
||||||
index += 4;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
s.append(c);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
s.append(c);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(!complete)
|
if (!complete) {
|
||||||
{
|
success = false;
|
||||||
success = false;
|
return QVariant();
|
||||||
return QVariant();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return QVariant(s);
|
return QVariant(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -479,23 +439,23 @@ QVariant Json::parseString(const QString &json, int &index, bool &success)
|
||||||
*/
|
*/
|
||||||
QVariant Json::parseNumber(const QString &json, int &index)
|
QVariant Json::parseNumber(const QString &json, int &index)
|
||||||
{
|
{
|
||||||
Json::eatWhitespace(json, index);
|
Json::eatWhitespace(json, index);
|
||||||
|
|
||||||
int lastIndex = Json::lastIndexOfNumber(json, index);
|
int lastIndex = Json::lastIndexOfNumber(json, index);
|
||||||
int charLength = (lastIndex - index) + 1;
|
int charLength = (lastIndex - index) + 1;
|
||||||
QString numberStr;
|
QString numberStr;
|
||||||
|
|
||||||
numberStr = json.mid(index, charLength);
|
numberStr = json.mid(index, charLength);
|
||||||
|
|
||||||
index = lastIndex + 1;
|
index = lastIndex + 1;
|
||||||
|
|
||||||
if (numberStr.contains('.')) {
|
if (numberStr.contains('.')) {
|
||||||
return QVariant(numberStr.toDouble(NULL));
|
return QVariant(numberStr.toDouble(NULL));
|
||||||
} else if (numberStr.startsWith('-')) {
|
} else if (numberStr.startsWith('-')) {
|
||||||
return QVariant(numberStr.toLongLong(NULL));
|
return QVariant(numberStr.toLongLong(NULL));
|
||||||
} else {
|
} else {
|
||||||
return QVariant(numberStr.toULongLong(NULL));
|
return QVariant(numberStr.toULongLong(NULL));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -503,18 +463,16 @@ QVariant Json::parseNumber(const QString &json, int &index)
|
||||||
*/
|
*/
|
||||||
int Json::lastIndexOfNumber(const QString &json, int index)
|
int Json::lastIndexOfNumber(const QString &json, int index)
|
||||||
{
|
{
|
||||||
static const QString numericCharacters("0123456789+-.eE");
|
static const QString numericCharacters("0123456789+-.eE");
|
||||||
int lastIndex;
|
int lastIndex;
|
||||||
|
|
||||||
for(lastIndex = index; lastIndex < json.size(); lastIndex++)
|
for (lastIndex = index; lastIndex < json.size(); lastIndex++) {
|
||||||
{
|
if (numericCharacters.indexOf(json[lastIndex]) == -1) {
|
||||||
if(numericCharacters.indexOf(json[lastIndex]) == -1)
|
break;
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return lastIndex -1;
|
return lastIndex - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -522,14 +480,12 @@ int Json::lastIndexOfNumber(const QString &json, int index)
|
||||||
*/
|
*/
|
||||||
void Json::eatWhitespace(const QString &json, int &index)
|
void Json::eatWhitespace(const QString &json, int &index)
|
||||||
{
|
{
|
||||||
static const QString whitespaceChars(" \t\n\r");
|
static const QString whitespaceChars(" \t\n\r");
|
||||||
for(; index < json.size(); index++)
|
for (; index < json.size(); index++) {
|
||||||
{
|
if (whitespaceChars.indexOf(json[index]) == -1) {
|
||||||
if(whitespaceChars.indexOf(json[index]) == -1)
|
break;
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -537,8 +493,8 @@ void Json::eatWhitespace(const QString &json, int &index)
|
||||||
*/
|
*/
|
||||||
int Json::lookAhead(const QString &json, int index)
|
int Json::lookAhead(const QString &json, int index)
|
||||||
{
|
{
|
||||||
int saveIndex = index;
|
int saveIndex = index;
|
||||||
return Json::nextToken(json, saveIndex);
|
return Json::nextToken(json, saveIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -546,69 +502,73 @@ int Json::lookAhead(const QString &json, int index)
|
||||||
*/
|
*/
|
||||||
int Json::nextToken(const QString &json, int &index)
|
int Json::nextToken(const QString &json, int &index)
|
||||||
{
|
{
|
||||||
Json::eatWhitespace(json, index);
|
Json::eatWhitespace(json, index);
|
||||||
|
|
||||||
if(index == json.size())
|
|
||||||
{
|
|
||||||
return JsonTokenNone;
|
|
||||||
}
|
|
||||||
|
|
||||||
QChar c = json[index];
|
|
||||||
index++;
|
|
||||||
switch(c.toLatin1())
|
|
||||||
{
|
|
||||||
case '{': return JsonTokenCurlyOpen;
|
|
||||||
case '}': return JsonTokenCurlyClose;
|
|
||||||
case '[': return JsonTokenSquaredOpen;
|
|
||||||
case ']': return JsonTokenSquaredClose;
|
|
||||||
case ',': return JsonTokenComma;
|
|
||||||
case '"': return JsonTokenString;
|
|
||||||
case '0': case '1': case '2': case '3': case '4':
|
|
||||||
case '5': case '6': case '7': case '8': case '9':
|
|
||||||
case '-': return JsonTokenNumber;
|
|
||||||
case ':': return JsonTokenColon;
|
|
||||||
}
|
|
||||||
|
|
||||||
index--;
|
|
||||||
|
|
||||||
int remainingLength = json.size() - index;
|
|
||||||
|
|
||||||
//True
|
|
||||||
if(remainingLength >= 4)
|
|
||||||
{
|
|
||||||
if (json[index] == 't' && json[index + 1] == 'r' &&
|
|
||||||
json[index + 2] == 'u' && json[index + 3] == 'e')
|
|
||||||
{
|
|
||||||
index += 4;
|
|
||||||
return JsonTokenTrue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//False
|
|
||||||
if (remainingLength >= 5)
|
|
||||||
{
|
|
||||||
if (json[index] == 'f' && json[index + 1] == 'a' &&
|
|
||||||
json[index + 2] == 'l' && json[index + 3] == 's' &&
|
|
||||||
json[index + 4] == 'e')
|
|
||||||
{
|
|
||||||
index += 5;
|
|
||||||
return JsonTokenFalse;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Null
|
|
||||||
if (remainingLength >= 4)
|
|
||||||
{
|
|
||||||
if (json[index] == 'n' && json[index + 1] == 'u' &&
|
|
||||||
json[index + 2] == 'l' && json[index + 3] == 'l')
|
|
||||||
{
|
|
||||||
index += 4;
|
|
||||||
return JsonTokenNull;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (index == json.size()) {
|
||||||
return JsonTokenNone;
|
return JsonTokenNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
QChar c = json[index];
|
||||||
|
index++;
|
||||||
|
switch (c.toLatin1()) {
|
||||||
|
case '{':
|
||||||
|
return JsonTokenCurlyOpen;
|
||||||
|
case '}':
|
||||||
|
return JsonTokenCurlyClose;
|
||||||
|
case '[':
|
||||||
|
return JsonTokenSquaredOpen;
|
||||||
|
case ']':
|
||||||
|
return JsonTokenSquaredClose;
|
||||||
|
case ',':
|
||||||
|
return JsonTokenComma;
|
||||||
|
case '"':
|
||||||
|
return JsonTokenString;
|
||||||
|
case '0':
|
||||||
|
case '1':
|
||||||
|
case '2':
|
||||||
|
case '3':
|
||||||
|
case '4':
|
||||||
|
case '5':
|
||||||
|
case '6':
|
||||||
|
case '7':
|
||||||
|
case '8':
|
||||||
|
case '9':
|
||||||
|
case '-':
|
||||||
|
return JsonTokenNumber;
|
||||||
|
case ':':
|
||||||
|
return JsonTokenColon;
|
||||||
|
}
|
||||||
|
|
||||||
|
index--;
|
||||||
|
|
||||||
|
int remainingLength = json.size() - index;
|
||||||
|
|
||||||
|
// True
|
||||||
|
if (remainingLength >= 4) {
|
||||||
|
if (json[index] == 't' && json[index + 1] == 'r' && json[index + 2] == 'u' && json[index + 3] == 'e') {
|
||||||
|
index += 4;
|
||||||
|
return JsonTokenTrue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// False
|
||||||
|
if (remainingLength >= 5) {
|
||||||
|
if (json[index] == 'f' && json[index + 1] == 'a' && json[index + 2] == 'l' && json[index + 3] == 's' &&
|
||||||
|
json[index + 4] == 'e') {
|
||||||
|
index += 5;
|
||||||
|
return JsonTokenFalse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Null
|
||||||
|
if (remainingLength >= 4) {
|
||||||
|
if (json[index] == 'n' && json[index + 1] == 'u' && json[index + 2] == 'l' && json[index + 3] == 'l') {
|
||||||
|
index += 4;
|
||||||
|
return JsonTokenNull;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return JsonTokenNone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace QtJson
|
||||||
} //end namespace
|
|
||||||
|
|
135
oracle/src/zip/unzip.h
Executable file → Normal file
135
oracle/src/zip/unzip.h
Executable file → Normal file
|
@ -33,14 +33,12 @@
|
||||||
#include <QtCore/QDateTime>
|
#include <QtCore/QDateTime>
|
||||||
#include <QtCore/QMap>
|
#include <QtCore/QMap>
|
||||||
#include <QtCore/QtGlobal>
|
#include <QtCore/QtGlobal>
|
||||||
|
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
|
||||||
class QDir;
|
class QDir;
|
||||||
class QFile;
|
class QFile;
|
||||||
class QIODevice;
|
class QIODevice;
|
||||||
class QString;
|
class QString;
|
||||||
class QStringList;
|
|
||||||
|
|
||||||
OSDAB_BEGIN_NAMESPACE(Zip)
|
OSDAB_BEGIN_NAMESPACE(Zip)
|
||||||
|
|
||||||
|
@ -49,100 +47,105 @@ class UnzipPrivate;
|
||||||
class OSDAB_ZIP_EXPORT UnZip
|
class OSDAB_ZIP_EXPORT UnZip
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum ErrorCode
|
enum ErrorCode
|
||||||
{
|
{
|
||||||
Ok,
|
Ok,
|
||||||
ZlibInit,
|
ZlibInit,
|
||||||
ZlibError,
|
ZlibError,
|
||||||
OpenFailed,
|
OpenFailed,
|
||||||
PartiallyCorrupted,
|
PartiallyCorrupted,
|
||||||
Corrupted,
|
Corrupted,
|
||||||
WrongPassword,
|
WrongPassword,
|
||||||
NoOpenArchive,
|
NoOpenArchive,
|
||||||
FileNotFound,
|
FileNotFound,
|
||||||
ReadFailed,
|
ReadFailed,
|
||||||
WriteFailed,
|
WriteFailed,
|
||||||
SeekFailed,
|
SeekFailed,
|
||||||
CreateDirFailed,
|
CreateDirFailed,
|
||||||
InvalidDevice,
|
InvalidDevice,
|
||||||
InvalidArchive,
|
InvalidArchive,
|
||||||
HeaderConsistencyError,
|
HeaderConsistencyError,
|
||||||
|
|
||||||
Skip, SkipAll // internal use only
|
Skip,
|
||||||
};
|
SkipAll // internal use only
|
||||||
|
};
|
||||||
|
|
||||||
enum ExtractionOption
|
enum ExtractionOption
|
||||||
{
|
{
|
||||||
ExtractPaths = 0x0001,
|
ExtractPaths = 0x0001,
|
||||||
SkipPaths = 0x0002,
|
SkipPaths = 0x0002,
|
||||||
VerifyOnly = 0x0004,
|
VerifyOnly = 0x0004,
|
||||||
NoSilentDirectoryCreation = 0x0008
|
NoSilentDirectoryCreation = 0x0008
|
||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(ExtractionOptions, ExtractionOption)
|
Q_DECLARE_FLAGS(ExtractionOptions, ExtractionOption)
|
||||||
|
|
||||||
enum CompressionMethod
|
enum CompressionMethod
|
||||||
{
|
{
|
||||||
NoCompression, Deflated, UnknownCompression
|
NoCompression,
|
||||||
};
|
Deflated,
|
||||||
|
UnknownCompression
|
||||||
|
};
|
||||||
|
|
||||||
enum FileType
|
enum FileType
|
||||||
{
|
{
|
||||||
File, Directory
|
File,
|
||||||
};
|
Directory
|
||||||
|
};
|
||||||
|
|
||||||
struct ZipEntry
|
struct ZipEntry
|
||||||
{
|
{
|
||||||
ZipEntry();
|
ZipEntry();
|
||||||
|
|
||||||
QString filename;
|
QString filename;
|
||||||
QString comment;
|
QString comment;
|
||||||
|
|
||||||
quint32 compressedSize;
|
quint32 compressedSize;
|
||||||
quint32 uncompressedSize;
|
quint32 uncompressedSize;
|
||||||
quint32 crc32;
|
quint32 crc32;
|
||||||
|
|
||||||
QDateTime lastModified;
|
QDateTime lastModified;
|
||||||
|
|
||||||
CompressionMethod compression;
|
CompressionMethod compression;
|
||||||
FileType type;
|
FileType type;
|
||||||
|
|
||||||
bool encrypted;
|
bool encrypted;
|
||||||
};
|
};
|
||||||
|
|
||||||
UnZip();
|
UnZip();
|
||||||
virtual ~UnZip();
|
virtual ~UnZip();
|
||||||
|
|
||||||
bool isOpen() const;
|
bool isOpen() const;
|
||||||
|
|
||||||
ErrorCode openArchive(const QString& filename);
|
ErrorCode openArchive(const QString &filename);
|
||||||
ErrorCode openArchive(QIODevice* device);
|
ErrorCode openArchive(QIODevice *device);
|
||||||
void closeArchive();
|
void closeArchive();
|
||||||
|
|
||||||
QString archiveComment() const;
|
QString archiveComment() const;
|
||||||
|
|
||||||
QString formatError(UnZip::ErrorCode c) const;
|
QString formatError(UnZip::ErrorCode c) const;
|
||||||
|
|
||||||
bool contains(const QString& file) const;
|
bool contains(const QString &file) const;
|
||||||
|
|
||||||
QStringList fileList() const;
|
QStringList fileList() const;
|
||||||
QList<ZipEntry> entryList() const;
|
QList<ZipEntry> entryList() const;
|
||||||
|
|
||||||
ErrorCode verifyArchive();
|
ErrorCode verifyArchive();
|
||||||
|
|
||||||
ErrorCode extractAll(const QString& dirname, ExtractionOptions options = ExtractPaths);
|
ErrorCode extractAll(const QString &dirname, ExtractionOptions options = ExtractPaths);
|
||||||
ErrorCode extractAll(const QDir& dir, ExtractionOptions options = ExtractPaths);
|
ErrorCode extractAll(const QDir &dir, ExtractionOptions options = ExtractPaths);
|
||||||
|
|
||||||
ErrorCode extractFile(const QString& filename, const QString& dirname, ExtractionOptions options = ExtractPaths);
|
ErrorCode extractFile(const QString &filename, const QString &dirname, ExtractionOptions options = ExtractPaths);
|
||||||
ErrorCode extractFile(const QString& filename, const QDir& dir, ExtractionOptions options = ExtractPaths);
|
ErrorCode extractFile(const QString &filename, const QDir &dir, ExtractionOptions options = ExtractPaths);
|
||||||
ErrorCode extractFile(const QString& filename, QIODevice* device, ExtractionOptions options = ExtractPaths);
|
ErrorCode extractFile(const QString &filename, QIODevice *device, ExtractionOptions options = ExtractPaths);
|
||||||
|
|
||||||
ErrorCode extractFiles(const QStringList& filenames, const QString& dirname, ExtractionOptions options = ExtractPaths);
|
ErrorCode
|
||||||
ErrorCode extractFiles(const QStringList& filenames, const QDir& dir, ExtractionOptions options = ExtractPaths);
|
extractFiles(const QStringList &filenames, const QString &dirname, ExtractionOptions options = ExtractPaths);
|
||||||
|
ErrorCode extractFiles(const QStringList &filenames, const QDir &dir, ExtractionOptions options = ExtractPaths);
|
||||||
|
|
||||||
void setPassword(const QString& pwd);
|
void setPassword(const QString &pwd);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UnzipPrivate* d;
|
UnzipPrivate *d;
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_OPERATORS_FOR_FLAGS(UnZip::ExtractionOptions)
|
Q_DECLARE_OPERATORS_FOR_FLAGS(UnZip::ExtractionOptions)
|
||||||
|
|
18
oracle/src/zip/zipglobal.cpp
Executable file → Normal file
18
oracle/src/zip/zipglobal.cpp
Executable file → Normal file
|
@ -27,7 +27,7 @@
|
||||||
|
|
||||||
#include "zipglobal.h"
|
#include "zipglobal.h"
|
||||||
|
|
||||||
#if defined(Q_OS_WIN) || defined(Q_OS_WINCE) || defined(Q_OS_LINUX) || defined (Q_OS_MACX)
|
#if defined(Q_OS_WIN) || defined(Q_OS_WINCE) || defined(Q_OS_LINUX) || defined(Q_OS_MACX)
|
||||||
#define OSDAB_ZIP_HAS_UTC
|
#define OSDAB_ZIP_HAS_UTC
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#else
|
#else
|
||||||
|
@ -55,9 +55,9 @@ int OSDAB_ZIP_MANGLE(currentUtcOffset)()
|
||||||
|
|
||||||
#if defined Q_OS_WIN
|
#if defined Q_OS_WIN
|
||||||
struct tm _tm_struct;
|
struct tm _tm_struct;
|
||||||
struct tm* tm_struct = &_tm_struct;
|
struct tm *tm_struct = &_tm_struct;
|
||||||
#else
|
#else
|
||||||
struct tm* tm_struct = 0;
|
struct tm *tm_struct = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
|
#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
|
||||||
|
@ -92,14 +92,14 @@ int OSDAB_ZIP_MANGLE(currentUtcOffset)()
|
||||||
|
|
||||||
const time_t local_time_t = mktime(tm_struct);
|
const time_t local_time_t = mktime(tm_struct);
|
||||||
|
|
||||||
const int utcOffset = - qRound(difftime(global_time_t, local_time_t));
|
const int utcOffset = -qRound(difftime(global_time_t, local_time_t));
|
||||||
return tm_struct->tm_isdst > 0 ? utcOffset + 3600 : utcOffset;
|
return tm_struct->tm_isdst > 0 ? utcOffset + 3600 : utcOffset;
|
||||||
#endif // No UTC
|
#endif // No UTC
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDateTime OSDAB_ZIP_MANGLE(fromFileTimestamp)(const QDateTime& dateTime)
|
QDateTime OSDAB_ZIP_MANGLE(fromFileTimestamp)(const QDateTime &dateTime)
|
||||||
{
|
{
|
||||||
#if !defined OSDAB_ZIP_NO_UTC && defined OSDAB_ZIP_HAS_UTC
|
#if !defined OSDAB_ZIP_NO_UTC && defined OSDAB_ZIP_HAS_UTC
|
||||||
const int utc = OSDAB_ZIP_MANGLE(currentUtcOffset)();
|
const int utc = OSDAB_ZIP_MANGLE(currentUtcOffset)();
|
||||||
|
@ -109,14 +109,14 @@ QDateTime OSDAB_ZIP_MANGLE(fromFileTimestamp)(const QDateTime& dateTime)
|
||||||
#endif // OSDAB_ZIP_NO_UTC
|
#endif // OSDAB_ZIP_NO_UTC
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OSDAB_ZIP_MANGLE(setFileTimestamp)(const QString& fileName, const QDateTime& dateTime)
|
bool OSDAB_ZIP_MANGLE(setFileTimestamp)(const QString &fileName, const QDateTime &dateTime)
|
||||||
{
|
{
|
||||||
if (fileName.isEmpty())
|
if (fileName.isEmpty())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
HANDLE hFile = CreateFileW(fileName.toStdWString().c_str(),
|
HANDLE hFile =
|
||||||
GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
|
CreateFileW(fileName.toStdWString().c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
|
||||||
if (hFile == INVALID_HANDLE_VALUE) {
|
if (hFile == INVALID_HANDLE_VALUE) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -143,7 +143,7 @@ bool OSDAB_ZIP_MANGLE(setFileTimestamp)(const QString& fileName, const QDateTime
|
||||||
#elif defined(Q_OS_LINUX) || defined(Q_OS_MACX)
|
#elif defined(Q_OS_LINUX) || defined(Q_OS_MACX)
|
||||||
|
|
||||||
struct utimbuf t_buffer;
|
struct utimbuf t_buffer;
|
||||||
t_buffer.actime = t_buffer.modtime = dateTime.toTime_t();
|
t_buffer.actime = t_buffer.modtime = dateTime.toSecsSinceEpoch();
|
||||||
return utime(fileName.toLocal8Bit().constData(), &t_buffer) == 0;
|
return utime(fileName.toLocal8Bit().constData(), &t_buffer) == 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -41,11 +41,12 @@ if(APPLE)
|
||||||
set(servatrice_SOURCES ${servatrice_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/resources/appicon.icns)
|
set(servatrice_SOURCES ${servatrice_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/resources/appicon.icns)
|
||||||
ENDIF(APPLE)
|
ENDIF(APPLE)
|
||||||
|
|
||||||
# Qt5
|
IF(Qt6_FOUND)
|
||||||
find_package(Qt5 COMPONENTS Network Sql WebSockets REQUIRED)
|
Qt6_ADD_RESOURCES(servatrice_RESOURCES_RCC ${servatrice_RESOURCES})
|
||||||
set(SERVATRICE_QT_MODULES Qt5::Core Qt5::Network Qt5::Sql Qt5::WebSockets)
|
ELSEIF(Qt5_FOUND)
|
||||||
|
Qt5_ADD_RESOURCES(servatrice_RESOURCES_RCC ${servatrice_RESOURCES})
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
QT5_ADD_RESOURCES(servatrice_RESOURCES_RCC ${servatrice_RESOURCES})
|
|
||||||
SET(QT_DONT_USE_QTGUI TRUE)
|
SET(QT_DONT_USE_QTGUI TRUE)
|
||||||
|
|
||||||
# Mysql connector
|
# Mysql connector
|
||||||
|
@ -59,15 +60,15 @@ elseif(WIN32)
|
||||||
SET(MYSQLCLIENT_DEFAULT_PATHS "C:\\Program Files\\MySQL\\MySQL Server 5.7\\lib" "C:\\Program Files (x86)\\MySQL\\MySQL Server 5.7\\lib")
|
SET(MYSQLCLIENT_DEFAULT_PATHS "C:\\Program Files\\MySQL\\MySQL Server 5.7\\lib" "C:\\Program Files (x86)\\MySQL\\MySQL Server 5.7\\lib")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_library(MYSQLCLIENT_LIBRARIES NAMES mysqlclient PATHS ${MYSQLCLIENT_DEFAULT_PATHS} PATH_SUFFIXES mysql mariadb)
|
find_library(MYSQL_CLIENT_LIBRARIES NAMES mysqlclient PATHS ${MYSQLCLIENT_DEFAULT_PATHS} PATH_SUFFIXES mysql mariadb)
|
||||||
if(${MYSQLCLIENT_LIBRARIES} MATCHES "NOTFOUND")
|
if(${MYSQL_CLIENT_LIBRARIES} MATCHES "NOTFOUND")
|
||||||
set(MYSQLCLIENT_FOUND FALSE CACHE INTERNAL "")
|
set(MYSQLCLIENT_FOUND FALSE CACHE INTERNAL "")
|
||||||
MESSAGE(STATUS "Mysql connector NOT FOUND: servatrice won't be able to connect to a mysql server")
|
MESSAGE(STATUS "MySQL connector NOT FOUND: Servatrice won't be able to connect to a MySQL server")
|
||||||
unset(MYSQLCLIENT_LIBRARIES)
|
unset(MYSQL_CLIENT_LIBRARIES)
|
||||||
else()
|
else()
|
||||||
set(MYSQLCLIENT_FOUND TRUE CACHE INTERNAL "")
|
set(MYSQLCLIENT_FOUND TRUE CACHE INTERNAL "")
|
||||||
get_filename_component(MYSQLCLIENT_LIBRARY_DIR ${MYSQLCLIENT_LIBRARIES} PATH)
|
get_filename_component(MYSQLCLIENT_LIBRARY_DIR ${MYSQL_CLIENT_LIBRARIES} PATH)
|
||||||
MESSAGE(STATUS "Mysql connector found at: ${MYSQLCLIENT_LIBRARY_DIR}")
|
MESSAGE(STATUS "Found MySQL connector at: ${MYSQL_CLIENT_LIBRARIES}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Declare path variables
|
# Declare path variables
|
||||||
|
@ -83,9 +84,7 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
|
||||||
# Build servatrice binary and link it
|
# Build servatrice binary and link it
|
||||||
ADD_EXECUTABLE(servatrice MACOSX_BUNDLE ${servatrice_SOURCES} ${servatrice_RESOURCES_RCC} ${servatrice_MOC_SRCS})
|
ADD_EXECUTABLE(servatrice MACOSX_BUNDLE ${servatrice_SOURCES} ${servatrice_RESOURCES_RCC} ${servatrice_MOC_SRCS})
|
||||||
|
|
||||||
if(MSVC)
|
if(CMAKE_HOST_SYSTEM MATCHES "FreeBSD")
|
||||||
TARGET_LINK_LIBRARIES(servatrice cockatrice_common Threads::Threads ${SERVATRICE_QT_MODULES} Qt5::WinMain)
|
|
||||||
elseif(CMAKE_HOST_SYSTEM MATCHES "FreeBSD")
|
|
||||||
TARGET_LINK_LIBRARIES(servatrice cockatrice_common Threads::Threads ${SERVATRICE_QT_MODULES} ${LIBEXECINFO_LIBRARY})
|
TARGET_LINK_LIBRARIES(servatrice cockatrice_common Threads::Threads ${SERVATRICE_QT_MODULES} ${LIBEXECINFO_LIBRARY})
|
||||||
else()
|
else()
|
||||||
TARGET_LINK_LIBRARIES(servatrice cockatrice_common Threads::Threads ${SERVATRICE_QT_MODULES})
|
TARGET_LINK_LIBRARIES(servatrice cockatrice_common Threads::Threads ${SERVATRICE_QT_MODULES})
|
||||||
|
@ -124,15 +123,15 @@ if(APPLE)
|
||||||
# these needs to be relative to CMAKE_INSTALL_PREFIX
|
# these needs to be relative to CMAKE_INSTALL_PREFIX
|
||||||
set(plugin_dest_dir servatrice.app/Contents/Plugins)
|
set(plugin_dest_dir servatrice.app/Contents/Plugins)
|
||||||
set(qtconf_dest_dir servatrice.app/Contents/Resources)
|
set(qtconf_dest_dir servatrice.app/Contents/Resources)
|
||||||
get_filename_component(QT_LIBRARY_DIR "${QT_LIBRARY_DIR}/.." ABSOLUTE)
|
|
||||||
|
|
||||||
# qt5 plugins: platforms, sqldrivers/mysql
|
# Qt plugins: platforms, sqldrivers/mysql, tls (Qt6)
|
||||||
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime
|
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime
|
||||||
FILES_MATCHING
|
FILES_MATCHING
|
||||||
PATTERN "*.dSYM" EXCLUDE
|
PATTERN "*.dSYM" EXCLUDE
|
||||||
PATTERN "*_debug.dylib" EXCLUDE
|
PATTERN "*_debug.dylib" EXCLUDE
|
||||||
PATTERN "platforms/*.dylib"
|
PATTERN "platforms/*.dylib"
|
||||||
PATTERN "sqldrivers/libqsqlmysql*.dylib"
|
PATTERN "sqldrivers/libqsqlmysql*.dylib"
|
||||||
|
PATTERN "tls/*.dylib"
|
||||||
)
|
)
|
||||||
|
|
||||||
install(CODE "
|
install(CODE "
|
||||||
|
@ -157,10 +156,18 @@ if(WIN32)
|
||||||
|
|
||||||
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")
|
||||||
|
|
||||||
# qt5 plugins: platforms, sqldrivers/mysql
|
# Qt plugins: platforms, sqldrivers, tls (Qt6)
|
||||||
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime
|
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime FILES_MATCHING
|
||||||
FILES_MATCHING REGEX "(platforms/.*|sqldrivers/qsqlmysql)\\.dll"
|
PATTERN "platforms/qdirect2d.dll"
|
||||||
REGEX ".*d\\.dll" EXCLUDE)
|
PATTERN "platforms/qminimal.dll"
|
||||||
|
PATTERN "platforms/qoffscreen.dll"
|
||||||
|
PATTERN "platforms/qwindows.dll"
|
||||||
|
PATTERN "tls/qcertonlybackend.dll"
|
||||||
|
PATTERN "tls/qopensslbackend.dll"
|
||||||
|
PATTERN "tls/qschannelbackend.dll"
|
||||||
|
PATTERN "sqldrivers/qsqlite.dll"
|
||||||
|
PATTERN "sqldrivers/qsqlodbc.dll"
|
||||||
|
PATTERN "sqldrivers/qsqlpsql.dll")
|
||||||
|
|
||||||
install(CODE "
|
install(CODE "
|
||||||
file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf\" \"[Paths]
|
file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf\" \"[Paths]
|
||||||
|
|
|
@ -34,7 +34,6 @@
|
||||||
#include <QMetaType>
|
#include <QMetaType>
|
||||||
#include <QTextCodec>
|
#include <QTextCodec>
|
||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
#include <google/protobuf/stubs/common.h>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
RNG_Abstract *rng;
|
RNG_Abstract *rng;
|
||||||
|
@ -70,17 +69,17 @@ void testRNG()
|
||||||
}
|
}
|
||||||
for (int i = 0; i <= maxMax - min; ++i) {
|
for (int i = 0; i <= maxMax - min; ++i) {
|
||||||
std::cerr << (min + i);
|
std::cerr << (min + i);
|
||||||
for (int j = 0; j < numbers.size(); ++j) {
|
for (auto &number : numbers) {
|
||||||
if (i < numbers[j].size())
|
if (i < number.size())
|
||||||
std::cerr << "\t" << numbers[j][i];
|
std::cerr << "\t" << number[i];
|
||||||
else
|
else
|
||||||
std::cerr << "\t";
|
std::cerr << "\t";
|
||||||
}
|
}
|
||||||
std::cerr << std::endl;
|
std::cerr << std::endl;
|
||||||
}
|
}
|
||||||
std::cerr << std::endl << "Chi^2 =";
|
std::cerr << std::endl << "Chi^2 =";
|
||||||
for (int j = 0; j < chisq.size(); ++j)
|
for (double j : chisq)
|
||||||
std::cerr << "\t" << QString::number(chisq[j], 'f', 3).toStdString();
|
std::cerr << "\t" << QString::number(j, 'f', 3).toStdString();
|
||||||
std::cerr << std::endl << "k =";
|
std::cerr << std::endl << "k =";
|
||||||
for (int j = 0; j < chisq.size(); ++j)
|
for (int j = 0; j < chisq.size(); ++j)
|
||||||
std::cerr << "\t" << (j - min + minMax);
|
std::cerr << "\t" << (j - min + minMax);
|
||||||
|
@ -112,9 +111,9 @@ void myMessageOutput2(QtMsgType /*type*/, const QMessageLogContext &, const QStr
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
QCoreApplication app(argc, argv);
|
QCoreApplication app(argc, argv);
|
||||||
app.setOrganizationName("Cockatrice");
|
QCoreApplication::setOrganizationName("Cockatrice");
|
||||||
app.setApplicationName("Servatrice");
|
QCoreApplication::setApplicationName("Servatrice");
|
||||||
app.setApplicationVersion(VERSION_STRING);
|
QCoreApplication::setApplicationVersion(VERSION_STRING);
|
||||||
|
|
||||||
QCommandLineParser parser;
|
QCommandLineParser parser;
|
||||||
parser.addHelpOption();
|
parser.addHelpOption();
|
||||||
|
@ -183,7 +182,7 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
smtpClient = new SmtpClient();
|
smtpClient = new SmtpClient();
|
||||||
|
|
||||||
Servatrice *server = new Servatrice();
|
auto *server = new Servatrice();
|
||||||
QObject::connect(server, SIGNAL(destroyed()), &app, SLOT(quit()), Qt::QueuedConnection);
|
QObject::connect(server, SIGNAL(destroyed()), &app, SLOT(quit()), Qt::QueuedConnection);
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
if (server->initServer()) {
|
if (server->initServer()) {
|
||||||
|
@ -192,7 +191,7 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
qInstallMessageHandler(myMessageOutput);
|
qInstallMessageHandler(myMessageOutput);
|
||||||
|
|
||||||
retval = app.exec();
|
retval = QCoreApplication::exec();
|
||||||
|
|
||||||
std::cerr << "Server quit." << std::endl;
|
std::cerr << "Server quit." << std::endl;
|
||||||
std::cerr << "-------------------------" << std::endl;
|
std::cerr << "-------------------------" << std::endl;
|
||||||
|
@ -210,5 +209,6 @@ int main(int argc, char *argv[])
|
||||||
// Delete all global objects allocated by libprotobuf.
|
// Delete all global objects allocated by libprotobuf.
|
||||||
google::protobuf::ShutdownProtobufLibrary();
|
google::protobuf::ShutdownProtobufLibrary();
|
||||||
|
|
||||||
|
QCoreApplication::quit();
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,7 @@ Servatrice_GameServer::~Servatrice_GameServer()
|
||||||
QThread *poolThread = connectionPools[i]->thread();
|
QThread *poolThread = connectionPools[i]->thread();
|
||||||
connectionPools[i]->deleteLater(); // pool destructor calls thread()->quit()
|
connectionPools[i]->deleteLater(); // pool destructor calls thread()->quit()
|
||||||
poolThread->wait();
|
poolThread->wait();
|
||||||
|
poolThread->deleteLater();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,6 +85,7 @@ void Servatrice_GameServer::incomingConnection(qintptr socketDescriptor)
|
||||||
Servatrice_ConnectionPool *pool = findLeastUsedConnectionPool();
|
Servatrice_ConnectionPool *pool = findLeastUsedConnectionPool();
|
||||||
|
|
||||||
auto ssi = new TcpServerSocketInterface(server, pool->getDatabaseInterface());
|
auto ssi = new TcpServerSocketInterface(server, pool->getDatabaseInterface());
|
||||||
|
connect(ssi, SIGNAL(incTxBytes), this, SLOT(incTxBytes));
|
||||||
ssi->moveToThread(pool->thread());
|
ssi->moveToThread(pool->thread());
|
||||||
pool->addClient();
|
pool->addClient();
|
||||||
connect(ssi, SIGNAL(destroyed()), pool, SLOT(removeClient()));
|
connect(ssi, SIGNAL(destroyed()), pool, SLOT(removeClient()));
|
||||||
|
@ -144,6 +146,7 @@ Servatrice_WebsocketGameServer::~Servatrice_WebsocketGameServer()
|
||||||
QThread *poolThread = connectionPools[i]->thread();
|
QThread *poolThread = connectionPools[i]->thread();
|
||||||
connectionPools[i]->deleteLater(); // pool destructor calls thread()->quit()
|
connectionPools[i]->deleteLater(); // pool destructor calls thread()->quit()
|
||||||
poolThread->wait();
|
poolThread->wait();
|
||||||
|
poolThread->deleteLater();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,6 +155,7 @@ void Servatrice_WebsocketGameServer::onNewConnection()
|
||||||
Servatrice_ConnectionPool *pool = findLeastUsedConnectionPool();
|
Servatrice_ConnectionPool *pool = findLeastUsedConnectionPool();
|
||||||
|
|
||||||
auto ssi = new WebsocketServerSocketInterface(server, pool->getDatabaseInterface());
|
auto ssi = new WebsocketServerSocketInterface(server, pool->getDatabaseInterface());
|
||||||
|
connect(ssi, SIGNAL(incTxBytes), this, SLOT(incTxBytes));
|
||||||
/*
|
/*
|
||||||
* Due to a Qt limitation, websockets can't be moved to another thread.
|
* Due to a Qt limitation, websockets can't be moved to another thread.
|
||||||
* This will hopefully change in Qt6 if QtWebSocket will be integrated in QtNetwork
|
* This will hopefully change in Qt6 if QtWebSocket will be integrated in QtNetwork
|
||||||
|
@ -195,7 +199,7 @@ void Servatrice_IslServer::incomingConnection(qintptr socketDescriptor)
|
||||||
|
|
||||||
Servatrice::Servatrice(QObject *parent)
|
Servatrice::Servatrice(QObject *parent)
|
||||||
: Server(parent), authenticationMethod(AuthenticationNone), uptime(0), txBytes(0), rxBytes(0),
|
: Server(parent), authenticationMethod(AuthenticationNone), uptime(0), txBytes(0), rxBytes(0),
|
||||||
shutdownTimer(nullptr), isFirstShutdownMessage(true)
|
shutdownTimer(nullptr)
|
||||||
{
|
{
|
||||||
qRegisterMetaType<QSqlDatabase>("QSqlDatabase");
|
qRegisterMetaType<QSqlDatabase>("QSqlDatabase");
|
||||||
}
|
}
|
||||||
|
@ -204,21 +208,16 @@ Servatrice::~Servatrice()
|
||||||
{
|
{
|
||||||
gameServer->close();
|
gameServer->close();
|
||||||
|
|
||||||
// clients live in other threads, we need to lock them
|
// we are destroying the clients outside their thread!
|
||||||
clientsLock.lockForRead();
|
|
||||||
for (auto *client : clients) {
|
for (auto *client : clients) {
|
||||||
QMetaObject::invokeMethod(client, "prepareDestroy", Qt::QueuedConnection);
|
client->prepareDestroy();
|
||||||
}
|
|
||||||
clientsLock.unlock();
|
|
||||||
|
|
||||||
// client destruction is asynchronous, wait for all clients to be gone
|
|
||||||
for (;;) {
|
|
||||||
QThread::usleep(10);
|
|
||||||
QReadLocker locker(&clientsLock);
|
|
||||||
if (clients.isEmpty())
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (shutdownTimer) {
|
||||||
|
shutdownTimer->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
servatriceDatabaseInterface->deleteLater();
|
||||||
prepareDestroy();
|
prepareDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -559,7 +558,7 @@ void Servatrice::updateLoginMessage()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Servatrice::setRequiredFeatures(const QString featureList)
|
void Servatrice::setRequiredFeatures(const QString &featureList)
|
||||||
{
|
{
|
||||||
FeatureSet features;
|
FeatureSet features;
|
||||||
serverRequiredFeatureList.clear();
|
serverRequiredFeatureList.clear();
|
||||||
|
@ -570,8 +569,9 @@ void Servatrice::setRequiredFeatures(const QString featureList)
|
||||||
QStringList listReqFeatures = featureList.split(",", QString::SkipEmptyParts);
|
QStringList listReqFeatures = featureList.split(",", QString::SkipEmptyParts);
|
||||||
#endif
|
#endif
|
||||||
if (!listReqFeatures.isEmpty())
|
if (!listReqFeatures.isEmpty())
|
||||||
foreach (QString reqFeature, listReqFeatures)
|
for (const QString &reqFeature : listReqFeatures) {
|
||||||
features.enableRequiredFeature(serverRequiredFeatureList, reqFeature);
|
features.enableRequiredFeature(serverRequiredFeatureList, reqFeature);
|
||||||
|
}
|
||||||
|
|
||||||
qDebug() << "Set required client features to:" << serverRequiredFeatureList;
|
qDebug() << "Set required client features to:" << serverRequiredFeatureList;
|
||||||
}
|
}
|
||||||
|
@ -715,8 +715,9 @@ void Servatrice::shutdownTimeout()
|
||||||
clientsLock.unlock();
|
clientsLock.unlock();
|
||||||
delete se;
|
delete se;
|
||||||
|
|
||||||
if (!shutdownMinutes)
|
if (!shutdownMinutes) {
|
||||||
deleteLater();
|
deleteLater();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
shutdownMinutes--;
|
shutdownMinutes--;
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,9 +96,9 @@ private:
|
||||||
public:
|
public:
|
||||||
Servatrice_IslServer(Servatrice *_server,
|
Servatrice_IslServer(Servatrice *_server,
|
||||||
const QSslCertificate &_cert,
|
const QSslCertificate &_cert,
|
||||||
const QSslKey &_privateKey,
|
QSslKey _privateKey,
|
||||||
QObject *parent = nullptr)
|
QObject *parent = nullptr)
|
||||||
: QTcpServer(parent), server(_server), cert(_cert), privateKey(_privateKey)
|
: QTcpServer(parent), server(_server), cert(_cert), privateKey(std::move(_privateKey))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ private slots:
|
||||||
void shutdownTimeout();
|
void shutdownTimeout();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void doSendIslMessage(const IslMessage &msg, int serverId) override;
|
void doSendIslMessage(const IslMessage &msg, int islServerId) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum DatabaseType
|
enum DatabaseType
|
||||||
|
@ -160,7 +160,6 @@ private:
|
||||||
mutable QMutex loginMessageMutex;
|
mutable QMutex loginMessageMutex;
|
||||||
QString loginMessage;
|
QString loginMessage;
|
||||||
QString dbPrefix;
|
QString dbPrefix;
|
||||||
QString requiredFeatures;
|
|
||||||
QMap<QString, bool> serverRequiredFeatureList;
|
QMap<QString, bool> serverRequiredFeatureList;
|
||||||
QString officialWarnings;
|
QString officialWarnings;
|
||||||
Servatrice_DatabaseInterface *servatriceDatabaseInterface;
|
Servatrice_DatabaseInterface *servatriceDatabaseInterface;
|
||||||
|
@ -173,7 +172,6 @@ private:
|
||||||
int shutdownMinutes;
|
int shutdownMinutes;
|
||||||
int nextShutdownMessageMinutes;
|
int nextShutdownMessageMinutes;
|
||||||
QTimer *shutdownTimer;
|
QTimer *shutdownTimer;
|
||||||
bool isFirstShutdownMessage;
|
|
||||||
|
|
||||||
mutable QMutex serverListMutex;
|
mutable QMutex serverListMutex;
|
||||||
QList<ServerProperties> serverList;
|
QList<ServerProperties> serverList;
|
||||||
|
@ -203,7 +201,7 @@ private:
|
||||||
public slots:
|
public slots:
|
||||||
void scheduleShutdown(const QString &reason, int minutes);
|
void scheduleShutdown(const QString &reason, int minutes);
|
||||||
void updateLoginMessage();
|
void updateLoginMessage();
|
||||||
void setRequiredFeatures(QString featureList);
|
void setRequiredFeatures(const QString &featureList);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Servatrice(QObject *parent = nullptr);
|
explicit Servatrice(QObject *parent = nullptr);
|
||||||
|
@ -213,10 +211,6 @@ public:
|
||||||
{
|
{
|
||||||
return serverRequiredFeatureList;
|
return serverRequiredFeatureList;
|
||||||
}
|
}
|
||||||
QString getOfficialWarningsList() const
|
|
||||||
{
|
|
||||||
return officialWarnings;
|
|
||||||
}
|
|
||||||
QString getServerName() const;
|
QString getServerName() const;
|
||||||
QString getLoginMessage() const override
|
QString getLoginMessage() const override
|
||||||
{
|
{
|
||||||
|
@ -282,9 +276,9 @@ public:
|
||||||
void incRxBytes(quint64 num);
|
void incRxBytes(quint64 num);
|
||||||
void addDatabaseInterface(QThread *thread, Servatrice_DatabaseInterface *databaseInterface);
|
void addDatabaseInterface(QThread *thread, Servatrice_DatabaseInterface *databaseInterface);
|
||||||
|
|
||||||
bool islConnectionExists(int serverId) const;
|
bool islConnectionExists(int islServerId) const;
|
||||||
void addIslInterface(int serverId, IslInterface *interface);
|
void addIslInterface(int islServerId, IslInterface *interface);
|
||||||
void removeIslInterface(int serverId);
|
void removeIslInterface(int islServerId);
|
||||||
QReadWriteLock islLock;
|
QReadWriteLock islLock;
|
||||||
|
|
||||||
QList<ServerProperties> getServerList() const;
|
QList<ServerProperties> getServerList() const;
|
||||||
|
|
|
@ -17,8 +17,8 @@ private:
|
||||||
int clientCount;
|
int clientCount;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Servatrice_ConnectionPool(Servatrice_DatabaseInterface *_databaseInterface);
|
explicit Servatrice_ConnectionPool(Servatrice_DatabaseInterface *_databaseInterface);
|
||||||
~Servatrice_ConnectionPool();
|
~Servatrice_ConnectionPool() override;
|
||||||
|
|
||||||
Servatrice_DatabaseInterface *getDatabaseInterface() const
|
Servatrice_DatabaseInterface *getDatabaseInterface() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -113,12 +113,13 @@ bool Servatrice_DatabaseInterface::checkSql()
|
||||||
|
|
||||||
QSqlQuery *Servatrice_DatabaseInterface::prepareQuery(const QString &queryText)
|
QSqlQuery *Servatrice_DatabaseInterface::prepareQuery(const QString &queryText)
|
||||||
{
|
{
|
||||||
if (preparedStatements.contains(queryText))
|
if (preparedStatements.contains(queryText)) {
|
||||||
return preparedStatements.value(queryText);
|
return preparedStatements.value(queryText);
|
||||||
|
}
|
||||||
|
|
||||||
QString prefixedQueryText = queryText;
|
QString prefixedQueryText = queryText;
|
||||||
prefixedQueryText.replace("{prefix}", server->getDbPrefix());
|
prefixedQueryText.replace("{prefix}", server->getDbPrefix());
|
||||||
QSqlQuery *query = new QSqlQuery(sqlDatabase);
|
auto *query = new QSqlQuery(sqlDatabase);
|
||||||
query->prepare(prefixedQueryText);
|
query->prepare(prefixedQueryText);
|
||||||
|
|
||||||
preparedStatements.insert(queryText, query);
|
preparedStatements.insert(queryText, query);
|
||||||
|
|
|
@ -36,14 +36,14 @@ protected:
|
||||||
const QString &clientId,
|
const QString &clientId,
|
||||||
QString &reasonStr,
|
QString &reasonStr,
|
||||||
int &banSecondsLeft,
|
int &banSecondsLeft,
|
||||||
bool passwordNeedsHash);
|
bool passwordNeedsHash) override;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void initDatabase(const QSqlDatabase &_sqlDatabase);
|
void initDatabase(const QSqlDatabase &_sqlDatabase);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Servatrice_DatabaseInterface(int _instanceId, Servatrice *_server);
|
explicit Servatrice_DatabaseInterface(int _instanceId, Servatrice *_server);
|
||||||
~Servatrice_DatabaseInterface();
|
~Servatrice_DatabaseInterface() override;
|
||||||
bool initDatabase(const QString &type,
|
bool initDatabase(const QString &type,
|
||||||
const QString &hostName,
|
const QString &hostName,
|
||||||
const QString &databaseName,
|
const QString &databaseName,
|
||||||
|
@ -58,66 +58,66 @@ public:
|
||||||
return sqlDatabase;
|
return sqlDatabase;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool activeUserExists(const QString &user);
|
bool activeUserExists(const QString &user) override;
|
||||||
bool userExists(const QString &user);
|
bool userExists(const QString &user) override;
|
||||||
QString getUserSalt(const QString &user);
|
QString getUserSalt(const QString &user) override;
|
||||||
int getUserIdInDB(const QString &name);
|
int getUserIdInDB(const QString &name);
|
||||||
QMap<QString, ServerInfo_User> getBuddyList(const QString &name);
|
QMap<QString, ServerInfo_User> getBuddyList(const QString &name) override;
|
||||||
QMap<QString, ServerInfo_User> getIgnoreList(const QString &name);
|
QMap<QString, ServerInfo_User> getIgnoreList(const QString &name) override;
|
||||||
bool isInBuddyList(const QString &whoseList, const QString &who);
|
bool isInBuddyList(const QString &whoseList, const QString &who) override;
|
||||||
bool isInIgnoreList(const QString &whoseList, const QString &who);
|
bool isInIgnoreList(const QString &whoseList, const QString &who) override;
|
||||||
ServerInfo_User getUserData(const QString &name, bool withId = false);
|
ServerInfo_User getUserData(const QString &name, bool withId = false) override;
|
||||||
void storeGameInformation(const QString &roomName,
|
void storeGameInformation(const QString &roomName,
|
||||||
const QStringList &roomGameTypes,
|
const QStringList &roomGameTypes,
|
||||||
const ServerInfo_Game &gameInfo,
|
const ServerInfo_Game &gameInfo,
|
||||||
const QSet<QString> &allPlayersEver,
|
const QSet<QString> &allPlayersEver,
|
||||||
const QSet<QString> &allSpectatorsEver,
|
const QSet<QString> &allSpectatorsEver,
|
||||||
const QList<GameReplay *> &replayList);
|
const QList<GameReplay *> &replayList) override;
|
||||||
DeckList *getDeckFromDatabase(int deckId, int userId);
|
DeckList *getDeckFromDatabase(int deckId, int userId) override;
|
||||||
|
|
||||||
int getNextGameId();
|
int getNextGameId() override;
|
||||||
int getNextReplayId();
|
int getNextReplayId() override;
|
||||||
int getActiveUserCount(QString connectionType = QString());
|
int getActiveUserCount(QString connectionType = QString()) override;
|
||||||
|
|
||||||
qint64 startSession(const QString &userName,
|
qint64 startSession(const QString &userName,
|
||||||
const QString &address,
|
const QString &address,
|
||||||
const QString &clientId,
|
const QString &clientId,
|
||||||
const QString &connectionType);
|
const QString &connectionType) override;
|
||||||
void endSession(qint64 sessionId);
|
void endSession(qint64 sessionId) override;
|
||||||
void clearSessionTables();
|
void clearSessionTables() override;
|
||||||
void lockSessionTables();
|
void lockSessionTables() override;
|
||||||
void unlockSessionTables();
|
void unlockSessionTables() override;
|
||||||
bool userSessionExists(const QString &userName);
|
bool userSessionExists(const QString &userName) override;
|
||||||
bool usernameIsValid(const QString &user, QString &error);
|
bool usernameIsValid(const QString &user, QString &error) override;
|
||||||
bool checkUserIsBanned(const QString &ipAddress,
|
bool checkUserIsBanned(const QString &ipAddress,
|
||||||
const QString &userName,
|
const QString &userName,
|
||||||
const QString &clientId,
|
const QString &clientId,
|
||||||
QString &banReason,
|
QString &banReason,
|
||||||
int &banSecondsRemaining);
|
int &banSecondsRemaining) override;
|
||||||
int checkNumberOfUserAccounts(const QString &email);
|
int checkNumberOfUserAccounts(const QString &email) override;
|
||||||
bool registerUser(const QString &userName,
|
bool registerUser(const QString &userName,
|
||||||
const QString &realName,
|
const QString &realName,
|
||||||
const QString &password,
|
const QString &password,
|
||||||
bool passwordNeedsHash,
|
bool passwordNeedsHash,
|
||||||
const QString &emailAddress,
|
const QString &emailAddress,
|
||||||
const QString &country,
|
const QString &country,
|
||||||
bool active = false);
|
bool active = false) override;
|
||||||
bool activateUser(const QString &userName, const QString &token);
|
bool activateUser(const QString &userName, const QString &token) override;
|
||||||
void updateUsersClientID(const QString &userName, const QString &userClientID);
|
void updateUsersClientID(const QString &userName, const QString &userClientID) override;
|
||||||
void updateUsersLastLoginData(const QString &userName, const QString &clientVersion);
|
void updateUsersLastLoginData(const QString &userName, const QString &clientVersion) override;
|
||||||
void logMessage(const int senderId,
|
void logMessage(const int senderId,
|
||||||
const QString &senderName,
|
const QString &senderName,
|
||||||
const QString &senderIp,
|
const QString &senderIp,
|
||||||
const QString &logMessage,
|
const QString &logMessage,
|
||||||
LogMessage_TargetType targetType,
|
LogMessage_TargetType targetType,
|
||||||
const int targetId,
|
const int targetId,
|
||||||
const QString &targetName);
|
const QString &targetName) override;
|
||||||
bool changeUserPassword(const QString &user, const QString &password, bool passwordNeedsHash);
|
bool changeUserPassword(const QString &user, const QString &password, bool passwordNeedsHash) override;
|
||||||
bool changeUserPassword(const QString &user,
|
bool changeUserPassword(const QString &user,
|
||||||
const QString &oldPassword,
|
const QString &oldPassword,
|
||||||
bool oldPasswordNeedsHash,
|
bool oldPasswordNeedsHash,
|
||||||
const QString &newPassword,
|
const QString &newPassword,
|
||||||
bool newPasswordNeedsHash);
|
bool newPasswordNeedsHash) override;
|
||||||
QList<ServerInfo_Ban> getUserBanHistory(const QString userName);
|
QList<ServerInfo_Ban> getUserBanHistory(const QString userName);
|
||||||
bool
|
bool
|
||||||
addWarning(const QString userName, const QString adminName, const QString warningReason, const QString clientID);
|
addWarning(const QString userName, const QString adminName, const QString warningReason, const QString clientID);
|
||||||
|
@ -133,7 +133,7 @@ public:
|
||||||
int &range,
|
int &range,
|
||||||
int &maxresults);
|
int &maxresults);
|
||||||
bool addForgotPassword(const QString &user);
|
bool addForgotPassword(const QString &user);
|
||||||
bool removeForgotPassword(const QString &user);
|
bool removeForgotPassword(const QString &user) override;
|
||||||
bool doesForgotPasswordExist(const QString &user);
|
bool doesForgotPasswordExist(const QString &user);
|
||||||
bool updateUserToken(const QString &token, const QString &user);
|
bool updateUserToken(const QString &token, const QString &user);
|
||||||
bool validateTableColumnStringData(const QString &table,
|
bool validateTableColumnStringData(const QString &table,
|
||||||
|
|
|
@ -45,7 +45,7 @@ void ServerLogger::startLog(const QString &logFileName)
|
||||||
connect(this, SIGNAL(sigFlushBuffer()), this, SLOT(flushBuffer()), Qt::QueuedConnection);
|
connect(this, SIGNAL(sigFlushBuffer()), this, SLOT(flushBuffer()), Qt::QueuedConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerLogger::logMessage(QString message, void *caller)
|
void ServerLogger::logMessage(const QString &message, void *caller)
|
||||||
{
|
{
|
||||||
if (!logFile)
|
if (!logFile)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -18,7 +18,7 @@ public:
|
||||||
~ServerLogger();
|
~ServerLogger();
|
||||||
public slots:
|
public slots:
|
||||||
void startLog(const QString &logFileName);
|
void startLog(const QString &logFileName);
|
||||||
void logMessage(QString message, void *caller = 0);
|
void logMessage(const QString &message, void *caller = 0);
|
||||||
void rotateLogs();
|
void rotateLogs();
|
||||||
private slots:
|
private slots:
|
||||||
void flushBuffer();
|
void flushBuffer();
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue