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 \
|
||||
qtbase5-dev \
|
||||
qtmultimedia5-dev \
|
||||
qttools5-dev \
|
||||
qttools5-dev-tools \
|
||||
&& apt-get clean \
|
||||
&& 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 && \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||
|
@ -9,16 +9,19 @@ RUN apt-get update && \
|
|||
file \
|
||||
g++ \
|
||||
git \
|
||||
libgl-dev \
|
||||
liblzma-dev \
|
||||
libmariadb-dev-compat \
|
||||
libprotobuf-dev \
|
||||
libqt5multimedia5-plugins \
|
||||
libqt5sql5-mysql \
|
||||
libqt5svg5-dev \
|
||||
libqt5websockets5-dev \
|
||||
libqt6core5compat6-dev \
|
||||
libqt6multimedia6 \
|
||||
libqt6sql6-mysql \
|
||||
libqt6svg6-dev \
|
||||
libqt6websockets6-dev \
|
||||
protobuf-compiler \
|
||||
qtmultimedia5-dev \
|
||||
qttools5-dev \
|
||||
qttools5-dev-tools \
|
||||
qt6-l10n-tools \
|
||||
qt6-multimedia-dev \
|
||||
qt6-tools-dev \
|
||||
qt6-tools-dev-tools \
|
||||
&& apt-get clean \
|
||||
&& 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.
|
||||
|
||||
# Compiles cockatrice inside of a ci environment
|
||||
# --format runs the clang-format script first
|
||||
# --install runs make install
|
||||
# --package [<package type>] runs make package, optionally force the type
|
||||
# --suffix <suffix> renames package with this suffix, requires arg
|
||||
# --server compiles servatrice
|
||||
# --test runs tests
|
||||
# --debug or --release or <arg> sets the build type ie CMAKE_BUILD_TYPE
|
||||
# --ccache uses ccache and shows stats
|
||||
# --debug or --release sets the build type ie CMAKE_BUILD_TYPE
|
||||
# --ccache [<size>] uses ccache and shows stats, optionally provide size
|
||||
# --dir <dir> sets the name of the build dir, default is "build"
|
||||
# uses env: BUILDTYPE 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
|
||||
LINT_SCRIPT=".ci/lint_cpp.sh"
|
||||
|
||||
# Read arguments
|
||||
while [[ $# != 0 ]]; do
|
||||
|
@ -22,10 +22,6 @@ while [[ $# != 0 ]]; do
|
|||
'--')
|
||||
shift
|
||||
;;
|
||||
'--format')
|
||||
CHECK_FORMAT=1
|
||||
shift
|
||||
;;
|
||||
'--install')
|
||||
MAKE_INSTALL=1
|
||||
shift
|
||||
|
@ -33,7 +29,7 @@ while [[ $# != 0 ]]; do
|
|||
'--package')
|
||||
MAKE_PACKAGE=1
|
||||
shift
|
||||
if [[ $# != 0 && $1 != -* ]]; then
|
||||
if [[ $# != 0 && ${1:0:1} != - ]]; then
|
||||
PACKAGE_TYPE="$1"
|
||||
shift
|
||||
fi
|
||||
|
@ -66,6 +62,10 @@ while [[ $# != 0 ]]; do
|
|||
'--ccache')
|
||||
USE_CCACHE=1
|
||||
shift
|
||||
if [[ $# != 0 && ${1:0:1} != - ]]; then
|
||||
CCACHE_SIZE="$1"
|
||||
shift
|
||||
fi
|
||||
;;
|
||||
'--dir')
|
||||
shift
|
||||
|
@ -76,67 +76,81 @@ while [[ $# != 0 ]]; do
|
|||
BUILD_DIR="$1"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
if [[ $1 == -* ]]; then
|
||||
echo "::error file=$0::unrecognized option: $1"
|
||||
'--parallel')
|
||||
shift
|
||||
if [[ $# == 0 ]]; then
|
||||
echo "::error file=$0::--parallel expects an argument"
|
||||
exit 3
|
||||
fi
|
||||
BUILDTYPE="$1"
|
||||
PARALLEL_COUNT="$1"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
echo "::error file=$0::unrecognized option: $1"
|
||||
exit 3
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Check formatting using clang-format
|
||||
if [[ $CHECK_FORMAT ]]; then
|
||||
echo "::group::Run linter"
|
||||
source "$LINT_SCRIPT"
|
||||
echo "::endgroup::"
|
||||
fi
|
||||
|
||||
set -e
|
||||
|
||||
# Setup
|
||||
./servatrice/check_schema_version.sh
|
||||
if [[ ! $BUILDTYPE ]]; then
|
||||
BUILDTYPE=Release
|
||||
fi
|
||||
if [[ ! $BUILD_DIR ]]; then
|
||||
BUILD_DIR="build"
|
||||
fi
|
||||
mkdir -p "$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
|
||||
flags=()
|
||||
flags=("-DCMAKE_BUILD_TYPE=$BUILDTYPE")
|
||||
if [[ $MAKE_SERVER ]]; then
|
||||
flags+=("-DWITH_SERVER=1")
|
||||
fi
|
||||
if [[ $MAKE_TEST ]]; then
|
||||
flags+=("-DTEST=1")
|
||||
fi
|
||||
if [[ ! $BUILDTYPE ]]; then
|
||||
BUILDTYPE=Release
|
||||
if [[ $USE_CCACHE ]]; then
|
||||
flags+=("-DUSE_CCACHE=1")
|
||||
if [[ $CCACHE_SIZE ]]; then
|
||||
# note, this setting persists after running the script
|
||||
ccache --max-size "$CCACHE_SIZE"
|
||||
fi
|
||||
fi
|
||||
flags+=("-DCMAKE_BUILD_TYPE=$BUILDTYPE")
|
||||
if [[ $PACKAGE_TYPE ]]; then
|
||||
flags+=("-DCPACK_GENERATOR=$PACKAGE_TYPE")
|
||||
fi
|
||||
|
||||
if [[ $(uname) == "Darwin" ]]; then
|
||||
if [[ $USE_CCACHE ]]; then
|
||||
# prepend ccache compiler binaries to path
|
||||
PATH="/usr/local/opt/ccache/libexec:$PATH"
|
||||
# Add cmake --build flags
|
||||
buildflags=(--config "$BUILDTYPE")
|
||||
if [[ $PARALLEL_COUNT ]]; then
|
||||
if [[ $(cmake --build /not_a_dir --parallel |& head -1) =~ parallel ]]; then
|
||||
# workaround for bionic having an old cmake
|
||||
echo "this version of cmake does not support --parallel, using native build tool -j instead"
|
||||
buildflags+=(-- -j "$PARALLEL_COUNT")
|
||||
# note, no normal build flags should be added after this
|
||||
else
|
||||
buildflags+=(--parallel "$PARALLEL_COUNT")
|
||||
fi
|
||||
# Add qt install location when using homebrew
|
||||
flags+=("-DCMAKE_PREFIX_PATH=/usr/local/opt/qt5/")
|
||||
fi
|
||||
|
||||
function ccachestatsverbose() {
|
||||
# note, verbose only works on newer ccache, discard the error
|
||||
local got
|
||||
if got="$(ccache --show-stats --verbose 2>/dev/null)"; then
|
||||
echo "$got"
|
||||
else
|
||||
ccache --show-stats
|
||||
fi
|
||||
}
|
||||
|
||||
# Compile
|
||||
if [[ $USE_CCACHE ]]; then
|
||||
echo "::group::Show ccache stats"
|
||||
ccache --show-stats
|
||||
ccachestatsverbose
|
||||
echo "::endgroup::"
|
||||
fi
|
||||
|
||||
|
@ -146,12 +160,12 @@ cmake .. "${flags[@]}"
|
|||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Build project"
|
||||
cmake --build . --config "$BUILDTYPE"
|
||||
cmake --build . "${buildflags[@]}"
|
||||
echo "::endgroup::"
|
||||
|
||||
if [[ $USE_CCACHE ]]; then
|
||||
echo "::group::Show ccache stats again"
|
||||
ccache --show-stats
|
||||
ccachestatsverbose
|
||||
echo "::endgroup::"
|
||||
fi
|
||||
|
||||
|
@ -174,7 +188,8 @@ if [[ $MAKE_PACKAGE ]]; then
|
|||
|
||||
if [[ $PACKAGE_SUFFIX ]]; then
|
||||
echo "::group::Update package name"
|
||||
../.ci/name_build.sh "$PACKAGE_SUFFIX"
|
||||
cd ..
|
||||
BUILD_DIR="$BUILD_DIR" .ci/name_build.sh "$PACKAGE_SUFFIX"
|
||||
echo "::endgroup::"
|
||||
fi
|
||||
fi
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
# --interactive immediately starts the image interactively for debugging
|
||||
# --set-cache <location> sets the location to cache the image or for ccache
|
||||
# requires: docker
|
||||
# uses env: NAME CACHE BUILD GET SAVE INTERACTIVE (correspond to args: <name> --set-cache <cache> --build --get --save --interactive)
|
||||
# uses env: NAME CACHE BUILD GET SAVE INTERACTIVE
|
||||
# (correspond to args: <name> --set-cache <cache> --build --get --save --interactive)
|
||||
# sets env: RUN CCACHE_DIR IMAGE_NAME RUN_ARGS RUN_OPTS BUILD_SCRIPT
|
||||
# exitcode: 1 for failure, 2 for missing dockerfile, 3 for invalid arguments
|
||||
export BUILD_SCRIPT=".ci/compile.sh"
|
||||
|
@ -48,7 +49,7 @@ while [[ $# != 0 ]]; do
|
|||
shift 2
|
||||
;;
|
||||
*)
|
||||
if [[ $1 == -* ]]; then
|
||||
if [[ ${1:0:1} == - ]]; then
|
||||
echo "unrecognized option: $1"
|
||||
return 3
|
||||
fi
|
||||
|
@ -74,7 +75,9 @@ fi
|
|||
|
||||
if ! [[ $CACHE ]]; then
|
||||
echo "cache dir is not set!" >&2
|
||||
else
|
||||
CACHE="$(mktemp -d)"
|
||||
echo "set cache dir to $CACHE" >&2
|
||||
fi
|
||||
if ! [[ -d $CACHE ]]; then
|
||||
echo "could not find cache dir: $CACHE" >&2
|
||||
mkdir -p "$CACHE"
|
||||
|
@ -93,7 +96,6 @@ else
|
|||
echo "could not find ccache dir: $CCACHE_DIR" >&2
|
||||
mkdir -p "$CCACHE_DIR"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Get the docker image from previously stored save
|
||||
if [[ $GET ]]; then
|
||||
|
@ -138,7 +140,7 @@ fi
|
|||
function RUN ()
|
||||
{
|
||||
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")
|
||||
args+=(--workdir "/src")
|
||||
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"
|
|
@ -3,8 +3,8 @@
|
|||
# renames the file to [original name][SUFFIX].[original extension]
|
||||
# where SUFFIX is either available in the environment or as the first arg
|
||||
# if MAKE_ZIP is set instead a zip is made
|
||||
# expected to be run in the build directory
|
||||
builddir="."
|
||||
# expected to be run in the build directory unless BUILD_DIR is set
|
||||
builddir="${BUILD_DIR:=.}"
|
||||
findrx="Cockatrice-*.*"
|
||||
|
||||
if [[ $1 ]]; then
|
||||
|
@ -27,6 +27,7 @@ if [[ ! $file ]]; then
|
|||
echo "::error file=$0::could not find package"
|
||||
exit 1
|
||||
fi
|
||||
oldpwd="$PWD"
|
||||
if ! cd "$path"; then
|
||||
echo "::error file=$0::could not get file path"
|
||||
exit 1
|
||||
|
@ -45,6 +46,9 @@ else
|
|||
echo "renaming '$file' to '$filename'"
|
||||
mv "$file" "$filename"
|
||||
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"
|
||||
|
|
|
@ -8,18 +8,20 @@ git push -d origin --REPLACE-WITH-BETA-LIST--
|
|||
include different targets -->
|
||||
<pre>
|
||||
<b>Pre-compiled binaries we serve:</b>
|
||||
- <kbd>Windows 7/8/10 (32-bit)</kbd></i>
|
||||
- <kbd>Windows 7/8/10 (64-bit)</kbd></i>
|
||||
- <kbd>macOS 10.14</kbd> ("Mojave")</i>
|
||||
- <kbd>macOS 10.15</kbd> ("Catalina")</i>
|
||||
- <kbd>macOS 11.0</kbd> ("Big Sur")</i>
|
||||
- <kbd>Ubuntu 18.04</kbd> ("Bionic Beaver")</i>
|
||||
- <kbd>Ubuntu 20.04</kbd> ("Focal Fossa")</i>
|
||||
- <kbd>Ubuntu 20.10</kbd> ("Groovy Gorilla")</i>
|
||||
- <kbd>Ubuntu 21.04</kbd> ("Hirsute Hippo")</i>
|
||||
- <kbd>Debian 10</kbd> ("Buster")</i>
|
||||
- <kbd>Fedora 33</kbd></i>
|
||||
- <kbd>Fedora 34</kbd></i>
|
||||
- <kbd>Windows 7/8/10/11 (32-bit)</kbd>
|
||||
- <kbd>Windows 7/8/10/11 (64-bit)</kbd>
|
||||
- <kbd>macOS 10.14</kbd> ("Mojave")
|
||||
- <kbd>macOS 10.15</kbd> ("Catalina")
|
||||
- <kbd>macOS 11.0</kbd> ("Big Sur")
|
||||
- <kbd>Ubuntu 18.04</kbd> ("Bionic Beaver")
|
||||
- <kbd>Ubuntu 20.04</kbd> ("Focal Fossa")
|
||||
- <kbd>Ubuntu 21.10</kbd> ("Impish Indri")
|
||||
- <kbd>Ubuntu 22.04</kbd> ("Jammy Jellyfish")
|
||||
- <kbd>Debian 10</kbd> ("Buster")
|
||||
- <kbd>Debian 11</kbd> ("Bullseye")
|
||||
- <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>General linux support is available via a flatpak package (Flathub)</kbd></i>
|
||||
</pre>
|
||||
|
|
193
.github/workflows/desktop-build.yml
vendored
193
.github/workflows/desktop-build.yml
vendored
|
@ -19,9 +19,7 @@ on:
|
|||
jobs:
|
||||
configure:
|
||||
name: Configure
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
outputs:
|
||||
tag: ${{steps.configure.outputs.tag}}
|
||||
sha: ${{steps.configure.outputs.sha}}
|
||||
|
@ -55,7 +53,7 @@ jobs:
|
|||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Prepare release paramaters
|
||||
- name: Prepare release parameters
|
||||
id: prepare
|
||||
if: steps.configure.outputs.tag != null
|
||||
shell: bash
|
||||
|
@ -88,6 +86,7 @@ jobs:
|
|||
|
||||
- distro: Debian10
|
||||
package: DEB
|
||||
test: skip # running tests on all distros is superfluous
|
||||
|
||||
- distro: Debian11
|
||||
package: DEB
|
||||
|
@ -98,6 +97,10 @@ jobs:
|
|||
|
||||
- distro: Fedora35
|
||||
package: RPM
|
||||
test: skip
|
||||
|
||||
- distro: Fedora36
|
||||
package: RPM
|
||||
|
||||
- distro: UbuntuBionic
|
||||
package: DEB
|
||||
|
@ -106,24 +109,23 @@ jobs:
|
|||
package: DEB
|
||||
test: skip # UbuntuFocal has a broken qt for debug builds
|
||||
|
||||
- distro: UbuntuHirsute
|
||||
- distro: UbuntuImpish
|
||||
package: DEB
|
||||
test: skip
|
||||
|
||||
- distro: UbuntuImpish
|
||||
- distro: UbuntuJammy
|
||||
package: DEB
|
||||
|
||||
name: ${{matrix.distro}}
|
||||
|
||||
needs: configure
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
continue-on-error: ${{matrix.allow-failure == 'yes'}}
|
||||
|
||||
env:
|
||||
NAME: ${{matrix.distro}}
|
||||
CACHE: /tmp/${{matrix.distro}}-cache # ${{runner.temp}} does not work?
|
||||
# cache size over the entire repo is 10Gi link:
|
||||
# https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#usage-limits-and-eviction-policy
|
||||
CCACHE_SIZE: 200M
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
|
@ -151,9 +153,11 @@ jobs:
|
|||
- name: Build debug and test
|
||||
if: matrix.test != 'skip'
|
||||
shell: bash
|
||||
env:
|
||||
distro: '${{matrix.distro}}'
|
||||
run: |
|
||||
source .ci/docker.sh
|
||||
RUN --server --debug --test --ccache
|
||||
RUN --server --debug --test --ccache "$CCACHE_SIZE" --parallel 2
|
||||
|
||||
- name: Build release package
|
||||
id: package
|
||||
|
@ -162,16 +166,18 @@ jobs:
|
|||
env:
|
||||
suffix: '-${{matrix.distro}}'
|
||||
type: '${{matrix.package}}'
|
||||
distro: '${{matrix.distro}}'
|
||||
run: |
|
||||
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
|
||||
if: matrix.package != 'skip'
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ${{matrix.distro}}-package
|
||||
path: ./build/${{steps.package.outputs.name}}
|
||||
path: ${{steps.package.outputs.path}}
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload to release
|
||||
|
@ -181,7 +187,7 @@ jobs:
|
|||
GITHUB_TOKEN: ${{github.token}}
|
||||
with:
|
||||
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_content_type: application/octet-stream
|
||||
|
||||
|
@ -193,39 +199,46 @@ jobs:
|
|||
- target: Debug # tests only
|
||||
os: macos-latest
|
||||
xcode: 12.5.1
|
||||
qt_version: 6
|
||||
type: Debug
|
||||
do_tests: 0 # tests do not work yet on mac
|
||||
make_package: false
|
||||
do_tests: 1
|
||||
|
||||
- target: 10.14_Mojave
|
||||
os: macos-10.15 # runs on Catalina
|
||||
xcode: 10.3 # allows compatibility with macOS 10.14
|
||||
qt_version: 5
|
||||
type: Release
|
||||
do_tests: 0
|
||||
make_package: true
|
||||
# do_tests: 1 # tests do not work on qt5?
|
||||
make_package: 1
|
||||
|
||||
- target: 10.15_Catalina
|
||||
os: macos-10.15
|
||||
xcode: 12.1
|
||||
xcode: 12.4
|
||||
qt_version: 6
|
||||
type: Release
|
||||
do_tests: 0
|
||||
make_package: true
|
||||
do_tests: 1
|
||||
make_package: 1
|
||||
|
||||
- target: 11_Big_Sur
|
||||
os: macos-11
|
||||
xcode: 12.5.1
|
||||
xcode: 13.2
|
||||
qt_version: 6
|
||||
type: Release
|
||||
do_tests: 0
|
||||
make_package: true
|
||||
do_tests: 1
|
||||
make_package: 1
|
||||
|
||||
# - target: 12_Monterey
|
||||
# os: macos-12
|
||||
# xcode: 13.3
|
||||
# qt_version: 6
|
||||
# type: Release
|
||||
# do_tests: 1
|
||||
# make_package: 1
|
||||
|
||||
name: macOS ${{matrix.target}}
|
||||
|
||||
needs: configure
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
continue-on-error: ${{matrix.allow-failure == 'yes'}}
|
||||
|
||||
env:
|
||||
DEVELOPER_DIR:
|
||||
/Applications/Xcode_${{matrix.xcode}}.app/Contents/Developer
|
||||
|
@ -238,45 +251,32 @@ jobs:
|
|||
shell: bash
|
||||
# cmake cannot find the mysql connector
|
||||
# neither of these works: mariadb-connector-c mysql-connector-c++
|
||||
run: brew update && brew install protobuf
|
||||
|
||||
- name: Install QT using homebrew
|
||||
id: brew_install_qt
|
||||
continue-on-error: true
|
||||
shell: bash
|
||||
run: brew install qt@5 --force-bottle
|
||||
|
||||
- name: Install QT using actions
|
||||
if: steps.brew_install_qt.outcome != 'success'
|
||||
uses: jurplel/install-qt-action@v2
|
||||
env:
|
||||
qt_version: 'qt@${{matrix.qt_version}}'
|
||||
run: |
|
||||
brew update
|
||||
brew install protobuf
|
||||
brew install "$qt_version" --force-bottle
|
||||
|
||||
- name: Build on Xcode ${{matrix.xcode}}
|
||||
shell: bash
|
||||
id: build
|
||||
env:
|
||||
CMAKE_BUILD_PARALLEL_LEVEL: 3 # mac machines actually have 3 cores
|
||||
run: .ci/compile.sh ${{matrix.type}} --server
|
||||
|
||||
- name: Test
|
||||
if: matrix.do_tests == 1
|
||||
shell: bash
|
||||
working-directory: build
|
||||
run: cmake --build . --target test
|
||||
|
||||
- name: Package for ${{matrix.target}}
|
||||
id: package
|
||||
if: matrix.make_package
|
||||
shell: bash
|
||||
working-directory: build
|
||||
run: |
|
||||
cmake --build . --target package
|
||||
../.ci/name_build.sh "-macOS-${{matrix.target}}"
|
||||
BUILDTYPE: '${{matrix.type}}'
|
||||
MAKE_TEST: '${{matrix.do_tests}}'
|
||||
MAKE_PACKAGE: '${{matrix.make_package}}'
|
||||
PACKAGE_SUFFIX: '-macOS-${{matrix.target}}'
|
||||
# set QTDIR to find qt5, qt6 can be found without this
|
||||
QTDIR: '/usr/local/opt/qt5'
|
||||
# Mac machines actually have 3 cores
|
||||
run: .ci/compile.sh --server --parallel 3
|
||||
|
||||
- name: Upload artifact
|
||||
if: matrix.make_package
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: macOS-${{matrix.target}}-dmg
|
||||
path: ${{steps.package.outputs.path}}
|
||||
path: ${{steps.build.outputs.path}}
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload to release
|
||||
|
@ -286,8 +286,8 @@ jobs:
|
|||
GITHUB_TOKEN: ${{github.token}}
|
||||
with:
|
||||
upload_url: ${{needs.configure.outputs.upload_url}}
|
||||
asset_path: ${{steps.package.outputs.path}}
|
||||
asset_name: ${{steps.package.outputs.name}}
|
||||
asset_path: ${{steps.build.outputs.path}}
|
||||
asset_name: ${{steps.build.outputs.name}}
|
||||
asset_content_type: application/octet-stream
|
||||
|
||||
build-windows:
|
||||
|
@ -296,24 +296,22 @@ jobs:
|
|||
matrix:
|
||||
include:
|
||||
- arch: 32
|
||||
triplet: x86
|
||||
cmake: Win32
|
||||
|
||||
vcpkg_default_triplet: x86
|
||||
qt_version: '5.15.2'
|
||||
cmake_generator_platform: Win32
|
||||
qt_arch: msvc2019
|
||||
- arch: 64
|
||||
triplet: x64
|
||||
cmake: x64
|
||||
append: _64
|
||||
|
||||
name: Windows ${{matrix.arch}}-bit
|
||||
vcpkg_default_triplet: x64
|
||||
qt_version: '6.3.0'
|
||||
cmake_generator_platform: x64
|
||||
qt_arch: msvc2019_64
|
||||
qt_modules: "qt5compat qtmultimedia qtwebsockets"
|
||||
|
||||
name: Windows (${{matrix.arch}}-bit)
|
||||
needs: configure
|
||||
|
||||
runs-on: windows-2019
|
||||
|
||||
env:
|
||||
QT_VERSION: '5.15.2'
|
||||
QT_ARCH: msvc2022${{matrix.append}}
|
||||
CMAKE_GENERATOR: 'Visual Studio 17 2022'
|
||||
CMAKE_GENERATOR: 'Visual Studio 16 2019'
|
||||
|
||||
steps:
|
||||
- name: Add msbuild to PATH
|
||||
|
@ -321,46 +319,57 @@ jobs:
|
|||
uses: microsoft/setup-msbuild@v1.1
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
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
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v1 # Intentionally v1, based on jurplel documentation
|
||||
with:
|
||||
key: ${{runner.os}}-QtCache-${{env.QT_VERSION}}-${{matrix.arch}}
|
||||
path: ${{runner.workspace}}/Qt
|
||||
key: ${{runner.os}}-QtCache-${{matrix.qt_version}}-${{matrix.arch}}
|
||||
path: '${{github.workspace}}/../Qt'
|
||||
|
||||
- name: Install ${{matrix.arch}}-bit Qt
|
||||
uses: jurplel/install-qt-action@v2
|
||||
- name: Install Qt ${{matrix.qt_version}} (${{matrix.arch}}-bit)
|
||||
uses: jurplel/install-qt-action@v3
|
||||
with:
|
||||
cached: ${{steps.cache-qt.outputs.cache-hit}}
|
||||
version: ${{env.QT_VERSION}}
|
||||
arch: win${{matrix.arch}}_${{env.QT_ARCH}}
|
||||
version: ${{matrix.qt_version}}
|
||||
arch: win${{matrix.arch}}_${{matrix.qt_arch}}
|
||||
modules: ${{matrix.qt_modules}}
|
||||
|
||||
- name: Restore or setup vcpkg
|
||||
uses: lukka/run-vcpkg@v6
|
||||
- name: Run vcpkg
|
||||
uses: lukka/run-vcpkg@v10.2
|
||||
with:
|
||||
vcpkgArguments: '@${{github.workspace}}/vcpkg.txt'
|
||||
vcpkgDirectory: ${{github.workspace}}/vcpkg
|
||||
appendedCacheKey: ${{hashFiles('**/vcpkg.txt')}}
|
||||
vcpkgTriplet: ${{matrix.triplet}}-windows
|
||||
runVcpkgInstall: true
|
||||
appendedCacheKey: ${{matrix.arch}}-bit
|
||||
env:
|
||||
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
|
||||
shell: bash
|
||||
env:
|
||||
PACKAGE_SUFFIX: '-win${{matrix.arch}}'
|
||||
CMAKE_GENERATOR: '${{env.CMAKE_GENERATOR}}'
|
||||
CMAKE_GENERATOR_PLATFORM: '${{matrix.cmake}}'
|
||||
run: ./.ci/compile.sh --server --release --test --package
|
||||
CMAKE_GENERATOR_PLATFORM: '${{matrix.cmake_generator_platform}}'
|
||||
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
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: Windows-${{matrix.arch}}bit-installer
|
||||
path: ./build/${{steps.build.outputs.name}}
|
||||
path: ${{steps.build.outputs.path}}
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload to release
|
||||
|
@ -370,6 +379,6 @@ jobs:
|
|||
GITHUB_TOKEN: ${{github.token}}
|
||||
with:
|
||||
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_content_type: application/octet-stream
|
||||
|
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -6,7 +6,7 @@ mysql.cnf
|
|||
.DS_Store
|
||||
.idea/
|
||||
*.aps
|
||||
cmake-build-debug/
|
||||
cmake-build-debug*
|
||||
preferences
|
||||
compile_commands.json
|
||||
.vs/
|
||||
|
|
115
CMakeLists.txt
115
CMakeLists.txt
|
@ -5,9 +5,26 @@
|
|||
# This file sets all the variables shared between the projects
|
||||
# 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)
|
||||
|
||||
# Early detect ccache
|
||||
option(USE_CCACHE "Cache the build results with ccache" ON)
|
||||
# Treat warnings as errors (Debug builds only)
|
||||
option(WARNING_AS_ERROR "Treat warnings as errors in debug builds" ON)
|
||||
# Check for translation updates
|
||||
option(UPDATE_TRANSLATIONS "Update translations on compile" OFF)
|
||||
# Compile servatrice
|
||||
option(WITH_SERVER "build servatrice" OFF)
|
||||
# Compile cockatrice
|
||||
option(WITH_CLIENT "build cockatrice" ON)
|
||||
# Compile oracle
|
||||
option(WITH_ORACLE "build oracle" ON)
|
||||
# Compile dbconverter
|
||||
option(WITH_DBCONVERTER "build dbconverter" ON)
|
||||
# Compile tests
|
||||
option(TEST "build tests" OFF)
|
||||
|
||||
# Default to "Release" build type
|
||||
# User-provided value for CMAKE_BUILD_TYPE must be checked before the PROJECT() call
|
||||
IF(DEFINED CMAKE_BUILD_TYPE)
|
||||
|
@ -16,8 +33,6 @@ ELSE()
|
|||
SET(CMAKE_BUILD_TYPE Release CACHE STRING "Type of build")
|
||||
ENDIF()
|
||||
|
||||
# Early detect ccache
|
||||
OPTION(USE_CCACHE "Cache the build results with ccache" ON)
|
||||
if(USE_CCACHE)
|
||||
find_program(CCACHE_PROGRAM ccache)
|
||||
if(CCACHE_PROGRAM)
|
||||
|
@ -41,22 +56,23 @@ endif()
|
|||
|
||||
# A project name is needed for CPack
|
||||
# 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
|
||||
if(NOT DEFINED GIT_TAG_RELEASENAME)
|
||||
set(GIT_TAG_RELEASENAME "Prismatic Bridge")
|
||||
endif()
|
||||
|
||||
# Use c++11 for all targets
|
||||
set(CMAKE_CXX_STANDARD 11 CACHE STRING "C++ ISO Standard")
|
||||
# Use c++17 for all targets
|
||||
set(CMAKE_CXX_STANDARD 17 CACHE STRING "C++ ISO Standard")
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
|
||||
# Set conventional loops
|
||||
set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true)
|
||||
|
||||
# Search path for cmake modules
|
||||
SET(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)
|
||||
|
||||
|
@ -76,8 +92,8 @@ if(UNIX)
|
|||
if(RULE_LAUNCH_COMPILE)
|
||||
MESSAGE(STATUS "Force enabling CCache usage under macOS")
|
||||
# Set up wrapper scripts
|
||||
configure_file(${CMAKE_MODULE_PATH}/launch-c.in launch-c)
|
||||
configure_file(${CMAKE_MODULE_PATH}/launch-cxx.in launch-cxx)
|
||||
configure_file("${COCKATRICE_CMAKE_PATH}/launch-c.in" launch-c)
|
||||
configure_file("${COCKATRICE_CMAKE_PATH}/launch-cxx.in" launch-cxx)
|
||||
execute_process(COMMAND chmod a+rx
|
||||
"${CMAKE_BINARY_DIR}/launch-c"
|
||||
"${CMAKE_BINARY_DIR}/launch-cxx")
|
||||
|
@ -103,13 +119,10 @@ elseif(WIN32)
|
|||
set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/rundir/${CMAKE_BUILD_TYPE})
|
||||
endif()
|
||||
|
||||
# Treat warnings as errors (Debug builds only)
|
||||
option(WARNING_AS_ERROR "Treat warnings as errors in debug builds" ON)
|
||||
|
||||
# Define proper compilation flags
|
||||
IF(MSVC)
|
||||
# Visual Studio: Maximum optimization, disable warning C4251
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "/Ox /MD /wd4251 ")
|
||||
# Visual Studio: Maximum optimization, disable warning C4251, establish C++17 compatibility
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "/Ox /MD /wd4251 /Zc:__cplusplus /std:c++17 /permissive-")
|
||||
# Generate complete debugging information
|
||||
#set(CMAKE_CXX_FLAGS_DEBUG "/Zi")
|
||||
ELSEIF (CMAKE_COMPILER_IS_GNUCXX)
|
||||
|
@ -123,6 +136,10 @@ ELSEIF (CMAKE_COMPILER_IS_GNUCXX)
|
|||
set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -Wall -Wextra")
|
||||
endif()
|
||||
|
||||
IF(APPLE)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++17")
|
||||
ENDIF()
|
||||
|
||||
set(ADDITIONAL_DEBUG_FLAGS -Wcast-align -Wmissing-declarations -Wno-long-long -Wno-error=extra -Wno-error=delete-non-virtual-dtor -Wno-error=sign-compare -Wno-error=missing-declarations)
|
||||
|
||||
FOREACH(FLAG ${ADDITIONAL_DEBUG_FLAGS})
|
||||
|
@ -148,7 +165,7 @@ ENDIF()
|
|||
|
||||
FIND_PACKAGE(Threads REQUIRED)
|
||||
|
||||
# Find Qt5
|
||||
# Determine 32 or 64 bit build
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(_lib_suffix 64)
|
||||
else()
|
||||
|
@ -165,28 +182,9 @@ elseif(DEFINED ENV{QTDIR})
|
|||
list(APPEND CMAKE_PREFIX_PATH "$ENV{QTDIR}")
|
||||
endif()
|
||||
|
||||
FIND_PACKAGE(Qt5Core 5.5.0 REQUIRED)
|
||||
MESSAGE(STATUS "Update Translations: ${UPDATE_TRANSLATIONS}")
|
||||
|
||||
IF(Qt5Core_FOUND)
|
||||
MESSAGE(STATUS "Found Qt ${Qt5Core_VERSION_STRING}")
|
||||
|
||||
# FIX: Qt was built with -reduce-relocations
|
||||
if (Qt5_POSITION_INDEPENDENT_CODE)
|
||||
SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
endif()
|
||||
|
||||
# guess plugins and libraries directory
|
||||
set(QT_PLUGINS_DIR "${Qt5Core_DIR}/../../../plugins")
|
||||
get_target_property(QT_LIBRARY_DIR Qt5::Core LOCATION)
|
||||
get_filename_component(QT_LIBRARY_DIR ${QT_LIBRARY_DIR} PATH)
|
||||
|
||||
ELSE()
|
||||
MESSAGE(FATAL_ERROR "No Qt5 found!")
|
||||
ENDIF()
|
||||
|
||||
# Check for translation updates
|
||||
OPTION(UPDATE_TRANSLATIONS "Update translations on compile" OFF)
|
||||
MESSAGE(STATUS "UPDATE TRANSLATIONS: ${UPDATE_TRANSLATIONS}")
|
||||
include(FindQtRuntime)
|
||||
|
||||
set(CMAKE_AUTOMOC TRUE)
|
||||
|
||||
|
@ -195,7 +193,7 @@ FIND_PACKAGE(Protobuf REQUIRED)
|
|||
IF(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}")
|
||||
MESSAGE(FATAL_ERROR "No protoc command found!")
|
||||
ELSE()
|
||||
MESSAGE(STATUS "Protoc version ${Protobuf_VERSION} found!")
|
||||
MESSAGE(STATUS "Found Protobuf ${Protobuf_VERSION} at: ${Protobuf_LIBRARIES}")
|
||||
ENDIF()
|
||||
|
||||
#Find OpenSSL
|
||||
|
@ -209,8 +207,8 @@ IF(MSVC)
|
|||
ENDIF()
|
||||
|
||||
# Package builder
|
||||
set(CPACK_PACKAGE_CONTACT "Zach Halpern <zahalpern+github@gmail.com>")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY ${PROJECT_NAME})
|
||||
set(CPACK_PACKAGE_CONTACT "Zach Halpern <zach@cockatrice.us>")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PROJECT_NAME}")
|
||||
set(CPACK_PACKAGE_VENDOR "Cockatrice Development Team")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/README.md")
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
|
||||
|
@ -231,16 +229,34 @@ if(UNIX)
|
|||
# linux
|
||||
IF(CPACK_GENERATOR STREQUAL "RPM")
|
||||
set(CPACK_RPM_PACKAGE_LICENSE "GPLv2")
|
||||
set(CPACK_RPM_PACKAGE_REQUIRES "protobuf, qt5-qttools, qt5-qtsvg, qt5-qtmultimedia")
|
||||
set(CPACK_RPM_MAIN_COMPONENT "cockatrice")
|
||||
IF(Qt6_FOUND)
|
||||
SET(CPACK_RPM_PACKAGE_REQUIRES "protobuf, qt6-qttools, qt6-qtsvg, qt6-qtmultimedia")
|
||||
ELSEIF(Qt5_FOUND)
|
||||
SET(CPACK_RPM_PACKAGE_REQUIRES "protobuf, qt5-qttools, qt5-qtsvg, qt5-qtmultimedia")
|
||||
ENDIF()
|
||||
set(CPACK_RPM_PACKAGE_GROUP "Amusements/Games")
|
||||
set(CPACK_RPM_PACKAGE_URL "http://github.com/Cockatrice/Cockatrice")
|
||||
# stop directories from making package conflicts
|
||||
set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION
|
||||
/usr/share/applications
|
||||
/usr/share/icons
|
||||
/usr/share/icons/hicolor
|
||||
/usr/share/icons/hicolor/48x48
|
||||
/usr/share/icons/hicolor/48x48/apps
|
||||
/usr/share/icons/hicolor/scalable
|
||||
/usr/share/icons/hicolor/scalable/apps)
|
||||
ELSE()
|
||||
set(CPACK_GENERATOR DEB)
|
||||
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
|
||||
set(CPACK_DEBIAN_PACKAGE_SECTION "games")
|
||||
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "http://github.com/Cockatrice/Cockatrice")
|
||||
IF(Qt6_FOUND)
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt6multimedia6, libqt6svg6, qt6-qpa-plugins")
|
||||
ELSEIF(Qt5_FOUND)
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt5multimedia5-plugins, libqt5svg5")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
endif()
|
||||
elseif(WIN32)
|
||||
set(CPACK_GENERATOR NSIS ${CPACK_GENERATOR})
|
||||
|
@ -252,8 +268,8 @@ elseif(WIN32)
|
|||
|
||||
# Configure file with custom definitions for NSIS.
|
||||
configure_file(
|
||||
${CMAKE_MODULE_PATH}/NSIS.definitions.nsh.in
|
||||
${PROJECT_BINARY_DIR}/NSIS.definitions.nsh
|
||||
"${COCKATRICE_CMAKE_PATH}/NSIS.definitions.nsh.in"
|
||||
"${PROJECT_BINARY_DIR}/NSIS.definitions.nsh"
|
||||
)
|
||||
|
||||
# include vcredist into the package; NSIS will take care of running it
|
||||
|
@ -264,38 +280,33 @@ endif()
|
|||
|
||||
include(CPack)
|
||||
|
||||
# Compile servatrice (default off)
|
||||
option(WITH_SERVER "build servatrice" OFF)
|
||||
add_subdirectory(common)
|
||||
if(WITH_SERVER)
|
||||
add_subdirectory(servatrice)
|
||||
SET(CPACK_INSTALL_CMAKE_PROJECTS "Servatrice;Servatrice;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
|
||||
endif()
|
||||
|
||||
# Compile cockatrice (default on)
|
||||
option(WITH_CLIENT "build cockatrice" ON)
|
||||
if(WITH_CLIENT)
|
||||
add_subdirectory(cockatrice)
|
||||
SET(CPACK_INSTALL_CMAKE_PROJECTS "Cockatrice;Cockatrice;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
|
||||
endif()
|
||||
|
||||
# Compile oracle (default on)
|
||||
option(WITH_ORACLE "build oracle" ON)
|
||||
if(WITH_ORACLE)
|
||||
add_subdirectory(oracle)
|
||||
SET(CPACK_INSTALL_CMAKE_PROJECTS "Oracle;Oracle;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
|
||||
endif()
|
||||
|
||||
# Compile dbconverter (default on)
|
||||
option(WITH_DBCONVERTER "build dbconverter" ON)
|
||||
if(WITH_DBCONVERTER)
|
||||
add_subdirectory(dbconverter)
|
||||
SET(CPACK_INSTALL_CMAKE_PROJECTS "Dbconverter;Dbconverter;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
|
||||
endif()
|
||||
|
||||
# Compile tests (default off)
|
||||
option(TEST "build tests" OFF)
|
||||
if(TEST)
|
||||
include(CTest)
|
||||
add_subdirectory(tests)
|
||||
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).
|
||||
- `-DUPDATE_TRANSLATIONS=1` Configure `make` to update the translation .ts files for new strings in the source code. Note: Running `make clean` will remove the .ts files (default 0 = no).
|
||||
- `-DTEST=1` Enable regression tests (default 0 = no). Note: needs googletest, will be downloaded on the fly if unavailable. To run tests: ```make test```.
|
||||
- `-DFORCE_USE_QT5=1` Skip looking for Qt6 before trying to find Qt5
|
||||
|
||||
|
||||
# Run
|
||||
|
|
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
|
||||
# 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)
|
||||
# Get standard installation paths for OpenSSL under Windows
|
||||
|
||||
# http://www.slproweb.com/products/Win32OpenSSL.html
|
||||
|
||||
if( CMAKE_SIZEOF_VOID_P EQUAL 8 )
|
||||
# target win64
|
||||
set(_OPENSSL_ROOT_HINTS
|
||||
${OPENSSL_ROOT_DIR}
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (64-bit)_is1;Inno Setup: App Path]"
|
||||
ENV OPENSSL_ROOT_DIR
|
||||
)
|
||||
if("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "x64")
|
||||
message(STATUS "Looking for OpenSSL for ${CMAKE_GENERATOR_PLATFORM}")
|
||||
file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _programfiles)
|
||||
set(_OPENSSL_ROOT_PATHS
|
||||
"$ENV{VCPKG_PACKAGES_DIR}/x64-windows/bin"
|
||||
"C:/OpenSSL-Win64/bin"
|
||||
"C:/OpenSSL-Win64"
|
||||
"C:/Tools/vcpkg/installed/x64-windows/bin"
|
||||
"${_programfiles}/OpenSSL-Win64"
|
||||
"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
|
||||
)
|
||||
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"
|
||||
"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 )
|
||||
message(STATUS "Looking for OpenSSL @ $ENV{CMAKE_GENERATOR_PLATFORM} in ${_OPENSSL_ROOT_PATHS}")
|
||||
if("$ENV{CMAKE_GENERATOR_PLATFORM}" STREQUAL "x64")
|
||||
FIND_FILE(WIN32SSLRUNTIME_LIBEAY NAMES libcrypto-1_1-x64.dll libcrypto.dll PATHS ${_OPENSSL_ROOT_PATHS} NO_DEFAULT_PATH)
|
||||
FIND_FILE(WIN32SSLRUNTIME_SSLEAY NAMES libssl-1_1-x64.dll libssl.dll PATHS ${_OPENSSL_ROOT_PATHS} NO_DEFAULT_PATH)
|
||||
elseif("$ENV{CMAKE_GENERATOR_PLATFORM}" STREQUAL "Win32")
|
||||
FIND_FILE(WIN32SSLRUNTIME_LIBEAY NAMES libcrypto-1_1.dll libcrypto.dll PATHS ${_OPENSSL_ROOT_PATHS} NO_DEFAULT_PATH)
|
||||
FIND_FILE(WIN32SSLRUNTIME_SSLEAY NAMES libssl-1_1.dll libssl.dll PATHS ${_OPENSSL_ROOT_PATHS} NO_DEFAULT_PATH)
|
||||
endif()
|
||||
|
||||
IF(WIN32SSLRUNTIME_LIBEAY AND WIN32SSLRUNTIME_SSLEAY)
|
||||
SET(WIN32SSLRUNTIME_LIBRARIES "${WIN32SSLRUNTIME_LIBEAY}" "${WIN32SSLRUNTIME_SSLEAY}")
|
||||
|
|
|
@ -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_common_SRCS ${CMAKE_SOURCE_DIR}/common/*.cpp ${CMAKE_SOURCE_DIR}/common/*.h)
|
||||
SET(translate_SRCS ${translate_cockatrice_SRCS} ${translate_common_SRCS})
|
||||
SET(cockatrice_TS "${CMAKE_CURRENT_SOURCE_DIR}/translations/cockatrice_en@source.ts")
|
||||
SET(cockatrice_TS "${CMAKE_CURRENT_SOURCE_DIR}/cockatrice_en@source.ts")
|
||||
ELSE()
|
||||
FILE(GLOB cockatrice_TS "${CMAKE_CURRENT_SOURCE_DIR}/translations/*.ts")
|
||||
ENDIF(UPDATE_TRANSLATIONS)
|
||||
|
@ -153,30 +153,11 @@ if(APPLE)
|
|||
set(cockatrice_SOURCES ${cockatrice_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/resources/appicon.icns)
|
||||
ENDIF(APPLE)
|
||||
|
||||
# Qt5
|
||||
find_package(Qt5 COMPONENTS Concurrent Multimedia Network PrintSupport Svg WebSockets Widgets REQUIRED)
|
||||
set(COCKATRICE_QT_MODULES Qt5::Concurrent Qt5::Multimedia Qt5::Network Qt5::PrintSupport Qt5::Svg Qt5::Widgets Qt5::WebSockets)
|
||||
|
||||
# Qt5LinguistTools
|
||||
find_package(Qt5LinguistTools)
|
||||
if(Qt5LinguistTools_FOUND)
|
||||
list(APPEND COCKATRICE_LIBS Qt5::LinguistTools)
|
||||
|
||||
if(NOT Qt5_LRELEASE_EXECUTABLE)
|
||||
MESSAGE(WARNING "Qt's lrelease not found.")
|
||||
endif()
|
||||
|
||||
if(UPDATE_TRANSLATIONS)
|
||||
if(NOT Qt5_LUPDATE_EXECUTABLE)
|
||||
MESSAGE(WARNING "Qt's lupdate not found.")
|
||||
endif()
|
||||
QT5_CREATE_TRANSLATION(cockatrice_QM ${translate_SRCS} ${cockatrice_TS})
|
||||
else()
|
||||
QT5_ADD_TRANSLATION(cockatrice_QM ${cockatrice_TS})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
QT5_ADD_RESOURCES(cockatrice_RESOURCES_RCC ${cockatrice_RESOURCES})
|
||||
IF(Qt6_FOUND)
|
||||
Qt6_ADD_RESOURCES(cockatrice_RESOURCES_RCC ${cockatrice_RESOURCES})
|
||||
ELSEIF(Qt5_FOUND)
|
||||
Qt5_ADD_RESOURCES(cockatrice_RESOURCES_RCC ${cockatrice_RESOURCES})
|
||||
ENDIF()
|
||||
|
||||
# Declare path variables
|
||||
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_CURRENT_BINARY_DIR})
|
||||
|
||||
# Build cockatrice binary and link it
|
||||
ADD_EXECUTABLE(cockatrice WIN32 MACOSX_BUNDLE ${cockatrice_SOURCES} ${cockatrice_QM} ${cockatrice_RESOURCES_RCC} ${cockatrice_MOC_SRCS})
|
||||
set(COCKATRICE_MAC_QM_INSTALL_DIR "cockatrice.app/Contents/Resources/translations")
|
||||
set(COCKATRICE_UNIX_QM_INSTALL_DIR "share/cockatrice/translations")
|
||||
set(COCKATRICE_WIN32_QM_INSTALL_DIR "translations")
|
||||
|
||||
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(APPLE)
|
||||
|
@ -205,27 +214,23 @@ if(UNIX)
|
|||
set_target_properties(cockatrice PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/cmake/Info.plist)
|
||||
|
||||
INSTALL(TARGETS cockatrice BUNDLE DESTINATION ./)
|
||||
INSTALL(FILES ${cockatrice_QM} DESTINATION ./cockatrice.app/Contents/Resources/translations)
|
||||
else()
|
||||
# Assume linux
|
||||
INSTALL(TARGETS cockatrice RUNTIME DESTINATION bin/)
|
||||
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/cockatrice.png DESTINATION ${ICONDIR}/hicolor/48x48/apps)
|
||||
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/cockatrice.svg DESTINATION ${ICONDIR}/hicolor/scalable/apps)
|
||||
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/cockatrice.desktop DESTINATION ${DESKTOPDIR})
|
||||
INSTALL(FILES ${cockatrice_QM} DESTINATION share/cockatrice/translations)
|
||||
endif()
|
||||
elseif(WIN32)
|
||||
INSTALL(TARGETS cockatrice RUNTIME DESTINATION ./)
|
||||
INSTALL(FILES ${cockatrice_QM} DESTINATION ./translations)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
# these needs to be relative to CMAKE_INSTALL_PREFIX
|
||||
set(plugin_dest_dir cockatrice.app/Contents/Plugins)
|
||||
set(qtconf_dest_dir cockatrice.app/Contents/Resources)
|
||||
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
|
||||
FILES_MATCHING
|
||||
PATTERN "*.dSYM" EXCLUDE
|
||||
|
@ -236,6 +241,7 @@ if(APPLE)
|
|||
PATTERN "platforms/*.dylib"
|
||||
PATTERN "printsupport/*.dylib"
|
||||
PATTERN "styles/*.dylib"
|
||||
PATTERN "tls/*.dylib"
|
||||
)
|
||||
|
||||
install(CODE "
|
||||
|
@ -261,9 +267,32 @@ if(WIN32)
|
|||
|
||||
install(DIRECTORY "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/${CMAKE_BUILD_TYPE}/" DESTINATION ./ FILES_MATCHING PATTERN "*.dll")
|
||||
|
||||
# qt5 plugins: audio, iconengines, imageformats, platforms, printsupport
|
||||
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime
|
||||
FILES_MATCHING REGEX "(audio|iconengines|imageformats|platforms|printsupport|styles)/.*[^d]\\.dll")
|
||||
# Qt plugins: audio (Qt5), iconengines, imageformats, platforms, printsupport (Qt5), styles, tls (Qt6)
|
||||
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime FILES_MATCHING
|
||||
PATTERN "audio/qtaudio_wasapi.dll"
|
||||
PATTERN "audio/qtaudio_windows.dll"
|
||||
PATTERN "iconengines/qsvgicon.dll"
|
||||
PATTERN "imageformats/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 "
|
||||
file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf\" \"[Paths]
|
||||
|
@ -284,3 +313,26 @@ Data = Resources\")
|
|||
install(FILES ${WIN32SSLRUNTIME_LIBRARIES} DESTINATION ./)
|
||||
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<Event_ReplayAdded>("Event_ReplayAdded");
|
||||
qRegisterMetaType<QList<QString>>("missingFeatures");
|
||||
qRegisterMetaType<PendingCommand *>("pendingCommand");
|
||||
|
||||
FeatureSet features;
|
||||
features.initalizeFeatureList(clientFeatures);
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include <QGraphicsScene>
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
#include <QPainter>
|
||||
#include <cmath>
|
||||
#include <QtMath>
|
||||
|
||||
ArrowItem::ArrowItem(Player *_player, int _id, ArrowTarget *_startItem, ArrowTarget *_targetItem, const QColor &_color)
|
||||
: QGraphicsItem(), player(_player), id(_id), startItem(_startItem), targetItem(_targetItem), color(_color),
|
||||
|
@ -71,7 +71,7 @@ void ArrowItem::updatePath(const QPointF &endPoint)
|
|||
const double arrowWidth = 15.0;
|
||||
const double headWidth = 40.0;
|
||||
const double headLength =
|
||||
headWidth / 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;
|
||||
|
||||
if (!startItem)
|
||||
|
@ -86,7 +86,7 @@ void ArrowItem::updatePath(const QPointF &endPoint)
|
|||
if (lineLength < 30)
|
||||
path = QPainterPath();
|
||||
else {
|
||||
QPointF c(lineLength / 2, tan(phi * M_PI / 180) * lineLength);
|
||||
QPointF c(lineLength / 2, qTan(phi * M_PI / 180) * lineLength);
|
||||
|
||||
QPainterPath centerLine;
|
||||
centerLine.moveTo(0, 0);
|
||||
|
@ -97,22 +97,22 @@ void ArrowItem::updatePath(const QPointF &endPoint)
|
|||
QLineF testLine(arrowBodyEndPoint, centerLine.pointAtPercent(percentage + 0.001));
|
||||
qreal alpha = testLine.angle() - 90;
|
||||
QPointF endPoint1 =
|
||||
arrowBodyEndPoint + arrowWidth / 2 * QPointF(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 =
|
||||
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 =
|
||||
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 =
|
||||
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.lineTo(point1);
|
||||
path.lineTo(QPointF(lineLength, 0));
|
||||
path.lineTo(point2);
|
||||
path.lineTo(endPoint2);
|
||||
path.quadTo(c, arrowWidth / 2 * QPointF(cos((phi - 90) * M_PI / 180), sin((phi - 90) * M_PI / 180)));
|
||||
path.lineTo(-arrowWidth / 2 * QPointF(cos((phi - 90) * M_PI / 180), sin((phi - 90) * M_PI / 180)));
|
||||
path.quadTo(c, arrowWidth / 2 * QPointF(qCos((phi - 90) * M_PI / 180), qSin((phi - 90) * M_PI / 180)));
|
||||
path.lineTo(-arrowWidth / 2 * QPointF(qCos((phi - 90) * M_PI / 180), qSin((phi - 90) * M_PI / 180)));
|
||||
}
|
||||
|
||||
setPos(startPoint);
|
||||
|
|
|
@ -23,7 +23,7 @@ bool CockatriceXml3Parser::getCanParseFile(const QString &fileName, QIODevice &d
|
|||
QXmlStreamReader xml(&device);
|
||||
while (!xml.atEnd()) {
|
||||
if (xml.readNext() == QXmlStreamReader::StartElement) {
|
||||
if (xml.name() == COCKATRICE_XML3_TAGNAME) {
|
||||
if (xml.name().toString() == COCKATRICE_XML3_TAGNAME) {
|
||||
int version = xml.attributes().value("version").toString().toInt();
|
||||
if (version == COCKATRICE_XML3_TAGVER) {
|
||||
return true;
|
||||
|
@ -52,12 +52,13 @@ void CockatriceXml3Parser::parseFile(QIODevice &device)
|
|||
break;
|
||||
}
|
||||
|
||||
if (xml.name() == "sets") {
|
||||
auto name = xml.name().toString();
|
||||
if (name == "sets") {
|
||||
loadSetsFromXml(xml);
|
||||
} else if (xml.name() == "cards") {
|
||||
} else if (name == "cards") {
|
||||
loadCardsFromXml(xml);
|
||||
} else if (xml.name() != "") {
|
||||
qDebug() << "[CockatriceXml3Parser] Unknown item" << xml.name() << ", trying to continue anyway";
|
||||
} else if (!name.isEmpty()) {
|
||||
qDebug() << "[CockatriceXml3Parser] Unknown item" << name << ", trying to continue anyway";
|
||||
xml.skipCurrentElement();
|
||||
}
|
||||
}
|
||||
|
@ -72,26 +73,27 @@ void CockatriceXml3Parser::loadSetsFromXml(QXmlStreamReader &xml)
|
|||
break;
|
||||
}
|
||||
|
||||
if (xml.name() == "set") {
|
||||
auto name = xml.name().toString();
|
||||
if (name == "set") {
|
||||
QString shortName, longName, setType;
|
||||
QDate releaseDate;
|
||||
while (!xml.atEnd()) {
|
||||
if (xml.readNext() == QXmlStreamReader::EndElement) {
|
||||
break;
|
||||
}
|
||||
name = xml.name().toString();
|
||||
|
||||
if (xml.name() == "name") {
|
||||
if (name == "name") {
|
||||
shortName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||
} else if (xml.name() == "longname") {
|
||||
} else if (name == "longname") {
|
||||
longName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||
} else if (xml.name() == "settype") {
|
||||
} else if (name == "settype") {
|
||||
setType = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||
} else if (xml.name() == "releasedate") {
|
||||
} else if (name == "releasedate") {
|
||||
releaseDate =
|
||||
QDate::fromString(xml.readElementText(QXmlStreamReader::IncludeChildElements), Qt::ISODate);
|
||||
} else if (xml.name() != "") {
|
||||
qDebug() << "[CockatriceXml3Parser] Unknown set property" << xml.name()
|
||||
<< ", trying to continue anyway";
|
||||
} else if (!name.isEmpty()) {
|
||||
qDebug() << "[CockatriceXml3Parser] Unknown set property" << name << ", trying to continue anyway";
|
||||
xml.skipCurrentElement();
|
||||
}
|
||||
}
|
||||
|
@ -146,7 +148,8 @@ void CockatriceXml3Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
|||
break;
|
||||
}
|
||||
|
||||
if (xml.name() == "card") {
|
||||
auto xmlName = xml.name().toString();
|
||||
if (xmlName == "card") {
|
||||
QString name = QString("");
|
||||
QString text = QString("");
|
||||
QVariantHash properties = QVariantHash();
|
||||
|
@ -162,37 +165,39 @@ void CockatriceXml3Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
|||
if (xml.readNext() == QXmlStreamReader::EndElement) {
|
||||
break;
|
||||
}
|
||||
xmlName = xml.name().toString();
|
||||
|
||||
// variable - assigned properties
|
||||
if (xml.name() == "name") {
|
||||
if (xmlName == "name") {
|
||||
name = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||
} else if (xml.name() == "text") {
|
||||
} else if (xmlName == "text") {
|
||||
text = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||
} else if (xml.name() == "color") {
|
||||
} else if (xmlName == "color") {
|
||||
colors.append(xml.readElementText(QXmlStreamReader::IncludeChildElements));
|
||||
} else if (xml.name() == "token") {
|
||||
} else if (xmlName == "token") {
|
||||
isToken = static_cast<bool>(xml.readElementText(QXmlStreamReader::IncludeChildElements).toInt());
|
||||
// generic properties
|
||||
} else if (xml.name() == "manacost") {
|
||||
} else if (xmlName == "manacost") {
|
||||
properties.insert("manacost", xml.readElementText(QXmlStreamReader::IncludeChildElements));
|
||||
} else if (xml.name() == "cmc") {
|
||||
} else if (xmlName == "cmc") {
|
||||
properties.insert("cmc", xml.readElementText(QXmlStreamReader::IncludeChildElements));
|
||||
} else if (xml.name() == "type") {
|
||||
} else if (xmlName == "type") {
|
||||
QString type = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||
properties.insert("type", type);
|
||||
properties.insert("maintype", getMainCardType(type));
|
||||
} else if (xml.name() == "pt") {
|
||||
} else if (xmlName == "pt") {
|
||||
properties.insert("pt", xml.readElementText(QXmlStreamReader::IncludeChildElements));
|
||||
} else if (xml.name() == "loyalty") {
|
||||
} else if (xmlName == "loyalty") {
|
||||
properties.insert("loyalty", xml.readElementText(QXmlStreamReader::IncludeChildElements));
|
||||
// positioning info
|
||||
} else if (xml.name() == "tablerow") {
|
||||
} else if (xmlName == "tablerow") {
|
||||
tableRow = xml.readElementText(QXmlStreamReader::IncludeChildElements).toInt();
|
||||
} else if (xml.name() == "cipt") {
|
||||
} else if (xmlName == "cipt") {
|
||||
cipt = (xml.readElementText(QXmlStreamReader::IncludeChildElements) == "1");
|
||||
} else if (xml.name() == "upsidedown") {
|
||||
} else if (xmlName == "upsidedown") {
|
||||
upsideDown = (xml.readElementText(QXmlStreamReader::IncludeChildElements) == "1");
|
||||
// sets
|
||||
} else if (xml.name() == "set") {
|
||||
} else if (xmlName == "set") {
|
||||
// NOTE: attributes must be read before readElementText()
|
||||
QXmlStreamAttributes attrs = xml.attributes();
|
||||
QString setName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||
|
@ -217,8 +222,8 @@ void CockatriceXml3Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
|||
setInfo.setProperty("rarity", attrs.value("rarity").toString());
|
||||
}
|
||||
sets.insert(setName, setInfo);
|
||||
// relatd cards
|
||||
} else if (xml.name() == "related" || xml.name() == "reverse-related") {
|
||||
// related cards
|
||||
} else if (xmlName == "related" || xmlName == "reverse-related") {
|
||||
bool attach = false;
|
||||
bool exclude = false;
|
||||
bool variable = false;
|
||||
|
@ -249,13 +254,13 @@ void CockatriceXml3Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
|||
}
|
||||
|
||||
auto *relation = new CardRelation(cardName, attach, exclude, variable, count);
|
||||
if (xml.name() == "reverse-related") {
|
||||
if (xmlName == "reverse-related") {
|
||||
reverseRelatedCards << relation;
|
||||
} else {
|
||||
relatedCards << relation;
|
||||
}
|
||||
} else if (xml.name() != "") {
|
||||
qDebug() << "[CockatriceXml3Parser] Unknown card property" << xml.name()
|
||||
} else if (!xmlName.isEmpty()) {
|
||||
qDebug() << "[CockatriceXml3Parser] Unknown card property" << xmlName
|
||||
<< ", trying to continue anyway";
|
||||
xml.skipCurrentElement();
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ bool CockatriceXml4Parser::getCanParseFile(const QString &fileName, QIODevice &d
|
|||
QXmlStreamReader xml(&device);
|
||||
while (!xml.atEnd()) {
|
||||
if (xml.readNext() == QXmlStreamReader::StartElement) {
|
||||
if (xml.name() == COCKATRICE_XML4_TAGNAME) {
|
||||
if (xml.name().toString() == COCKATRICE_XML4_TAGNAME) {
|
||||
int version = xml.attributes().value("version").toString().toInt();
|
||||
if (version == COCKATRICE_XML4_TAGVER) {
|
||||
return true;
|
||||
|
@ -52,12 +52,13 @@ void CockatriceXml4Parser::parseFile(QIODevice &device)
|
|||
break;
|
||||
}
|
||||
|
||||
if (xml.name() == "sets") {
|
||||
auto xmlName = xml.name().toString();
|
||||
if (xmlName == "sets") {
|
||||
loadSetsFromXml(xml);
|
||||
} else if (xml.name() == "cards") {
|
||||
} else if (xmlName == "cards") {
|
||||
loadCardsFromXml(xml);
|
||||
} else if (xml.name() != "") {
|
||||
qDebug() << "[CockatriceXml4Parser] Unknown item" << xml.name() << ", trying to continue anyway";
|
||||
} else if (!xmlName.isEmpty()) {
|
||||
qDebug() << "[CockatriceXml4Parser] Unknown item" << xmlName << ", trying to continue anyway";
|
||||
xml.skipCurrentElement();
|
||||
}
|
||||
}
|
||||
|
@ -72,25 +73,27 @@ void CockatriceXml4Parser::loadSetsFromXml(QXmlStreamReader &xml)
|
|||
break;
|
||||
}
|
||||
|
||||
if (xml.name() == "set") {
|
||||
auto xmlName = xml.name().toString();
|
||||
if (xmlName == "set") {
|
||||
QString shortName, longName, setType;
|
||||
QDate releaseDate;
|
||||
while (!xml.atEnd()) {
|
||||
if (xml.readNext() == QXmlStreamReader::EndElement) {
|
||||
break;
|
||||
}
|
||||
xmlName = xml.name().toString();
|
||||
|
||||
if (xml.name() == "name") {
|
||||
if (xmlName == "name") {
|
||||
shortName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||
} else if (xml.name() == "longname") {
|
||||
} else if (xmlName == "longname") {
|
||||
longName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||
} else if (xml.name() == "settype") {
|
||||
} else if (xmlName == "settype") {
|
||||
setType = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||
} else if (xml.name() == "releasedate") {
|
||||
} else if (xmlName == "releasedate") {
|
||||
releaseDate =
|
||||
QDate::fromString(xml.readElementText(QXmlStreamReader::IncludeChildElements), Qt::ISODate);
|
||||
} else if (xml.name() != "") {
|
||||
qDebug() << "[CockatriceXml4Parser] Unknown set property" << xml.name()
|
||||
} else if (!xmlName.isEmpty()) {
|
||||
qDebug() << "[CockatriceXml4Parser] Unknown set property" << xmlName
|
||||
<< ", trying to continue anyway";
|
||||
xml.skipCurrentElement();
|
||||
}
|
||||
|
@ -109,8 +112,9 @@ QVariantHash CockatriceXml4Parser::loadCardPropertiesFromXml(QXmlStreamReader &x
|
|||
break;
|
||||
}
|
||||
|
||||
if (xml.name() != "") {
|
||||
properties.insert(xml.name().toString(), xml.readElementText(QXmlStreamReader::IncludeChildElements));
|
||||
auto xmlName = xml.name().toString();
|
||||
if (!xmlName.isEmpty()) {
|
||||
properties.insert(xmlName, xml.readElementText(QXmlStreamReader::IncludeChildElements));
|
||||
}
|
||||
}
|
||||
return properties;
|
||||
|
@ -123,7 +127,9 @@ void CockatriceXml4Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
|||
break;
|
||||
}
|
||||
|
||||
if (xml.name() == "card") {
|
||||
auto xmlName = xml.name().toString();
|
||||
|
||||
if (xmlName == "card") {
|
||||
QString name = QString("");
|
||||
QString text = QString("");
|
||||
QVariantHash properties = QVariantHash();
|
||||
|
@ -138,25 +144,28 @@ void CockatriceXml4Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
|||
if (xml.readNext() == QXmlStreamReader::EndElement) {
|
||||
break;
|
||||
}
|
||||
|
||||
xmlName = xml.name().toString();
|
||||
|
||||
// variable - assigned properties
|
||||
if (xml.name() == "name") {
|
||||
if (xmlName == "name") {
|
||||
name = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||
} else if (xml.name() == "text") {
|
||||
} else if (xmlName == "text") {
|
||||
text = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||
} else if (xml.name() == "token") {
|
||||
} else if (xmlName == "token") {
|
||||
isToken = static_cast<bool>(xml.readElementText(QXmlStreamReader::IncludeChildElements).toInt());
|
||||
// generic properties
|
||||
} else if (xml.name() == "prop") {
|
||||
} else if (xmlName == "prop") {
|
||||
properties = loadCardPropertiesFromXml(xml);
|
||||
// positioning info
|
||||
} else if (xml.name() == "tablerow") {
|
||||
} else if (xmlName == "tablerow") {
|
||||
tableRow = xml.readElementText(QXmlStreamReader::IncludeChildElements).toInt();
|
||||
} else if (xml.name() == "cipt") {
|
||||
} else if (xmlName == "cipt") {
|
||||
cipt = (xml.readElementText(QXmlStreamReader::IncludeChildElements) == "1");
|
||||
} else if (xml.name() == "upsidedown") {
|
||||
} else if (xmlName == "upsidedown") {
|
||||
upsideDown = (xml.readElementText(QXmlStreamReader::IncludeChildElements) == "1");
|
||||
// sets
|
||||
} else if (xml.name() == "set") {
|
||||
} else if (xmlName == "set") {
|
||||
// NOTE: attributes but be read before readElementText()
|
||||
QXmlStreamAttributes attrs = xml.attributes();
|
||||
QString setName = xml.readElementText(QXmlStreamReader::IncludeChildElements);
|
||||
|
@ -171,8 +180,8 @@ void CockatriceXml4Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
|||
}
|
||||
sets.insert(setName, setInfo);
|
||||
}
|
||||
// relatd cards
|
||||
} else if (xml.name() == "related" || xml.name() == "reverse-related") {
|
||||
// related cards
|
||||
} else if (xmlName == "related" || xmlName == "reverse-related") {
|
||||
bool attach = false;
|
||||
bool exclude = false;
|
||||
bool variable = false;
|
||||
|
@ -203,13 +212,13 @@ void CockatriceXml4Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
|||
}
|
||||
|
||||
auto *relation = new CardRelation(cardName, attach, exclude, variable, count);
|
||||
if (xml.name() == "reverse-related") {
|
||||
if (xmlName == "reverse-related") {
|
||||
reverseRelatedCards << relation;
|
||||
} else {
|
||||
relatedCards << relation;
|
||||
}
|
||||
} else if (xml.name() != "") {
|
||||
qDebug() << "[CockatriceXml4Parser] Unknown card property" << xml.name()
|
||||
} else if (!xmlName.isEmpty()) {
|
||||
qDebug() << "[CockatriceXml4Parser] Unknown card property" << xmlName
|
||||
<< ", trying to continue anyway";
|
||||
xml.skipCurrentElement();
|
||||
}
|
||||
|
|
|
@ -6,13 +6,9 @@
|
|||
#include "main.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <utility>
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 13, 0))
|
||||
#include <QScreen>
|
||||
#else
|
||||
#include <QDesktopWidget>
|
||||
#endif
|
||||
#include <QVBoxLayout>
|
||||
#include <utility>
|
||||
|
||||
CardInfoWidget::CardInfoWidget(const QString &cardName, QWidget *parent, Qt::WindowFlags flags)
|
||||
: 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);
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 13, 0))
|
||||
int pixmapHeight = qApp->primaryScreen()->geometry().height() / 3;
|
||||
#else
|
||||
QDesktopWidget desktopWidget;
|
||||
int pixmapHeight = desktopWidget.screenGeometry().height() / 3;
|
||||
#endif
|
||||
int pixmapHeight = QGuiApplication::primaryScreen()->geometry().height() / 3;
|
||||
int pixmapWidth = static_cast<int>(pixmapHeight / aspectRatio);
|
||||
pic->setFixedWidth(pixmapWidth);
|
||||
pic->setFixedHeight(pixmapHeight);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define CARDITEM_H
|
||||
|
||||
#include "abstractcarditem.h"
|
||||
#include "server_card.h"
|
||||
|
||||
class CardDatabase;
|
||||
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)
|
||||
{
|
||||
const QRegExp notALetterOrNumber = QRegExp("[^a-zA-Z0-9]");
|
||||
const static auto notALetterOrNumber = QRegularExpression("[^a-zA-Z0-9]");
|
||||
|
||||
int firstSpace = message.indexOf(' ');
|
||||
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*/)
|
||||
#endif
|
||||
{
|
||||
setMouseTracking(true);
|
||||
}
|
||||
|
@ -566,7 +570,11 @@ void ChatView::mousePressEvent(QMouseEvent *event)
|
|||
switch (hoveredItemType) {
|
||||
case HoveredCard: {
|
||||
if ((event->button() == Qt::MiddleButton) || (event->button() == Qt::LeftButton))
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
emit showCardInfoPopup(event->globalPosition().toPoint(), hoveredContent);
|
||||
#else
|
||||
emit showCardInfoPopup(event->globalPos(), hoveredContent);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case HoveredUser: {
|
||||
|
@ -576,7 +584,11 @@ void ChatView::mousePressEvent(QMouseEvent *event)
|
|||
switch (event->button()) {
|
||||
case Qt::RightButton: {
|
||||
UserLevelFlags userLevel(hoveredContent.left(delimiterIndex).toInt());
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
userContextMenu->showContextMenu(event->globalPosition().toPoint(), userName, userLevel, this);
|
||||
#else
|
||||
userContextMenu->showContextMenu(event->globalPos(), userName, userLevel, this);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case Qt::LeftButton: {
|
||||
|
|
|
@ -103,7 +103,11 @@ public:
|
|||
void redactMessages(const QString &userName, int amount);
|
||||
|
||||
protected:
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
void enterEvent(QEnterEvent *event);
|
||||
#else
|
||||
void enterEvent(QEvent *event);
|
||||
#endif
|
||||
void leaveEvent(QEvent *event);
|
||||
void mouseMoveEvent(QMouseEvent *event);
|
||||
void mousePressEvent(QMouseEvent *event);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QRegularExpression>
|
||||
#include <QStringList>
|
||||
|
||||
const QStringList DeckLoader::fileNameFilters = QStringList()
|
||||
|
@ -208,7 +209,7 @@ void DeckLoader::saveToStream_DeckHeader(QTextStream &out)
|
|||
}
|
||||
|
||||
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) {
|
||||
out << "// " << row << "\n";
|
||||
}
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
#include <QApplication>
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
#include <QMouseEvent>
|
||||
#include <QtMath>
|
||||
#include <algorithm>
|
||||
#include <math.h>
|
||||
|
||||
DeckViewCardDragItem::DeckViewCardDragItem(DeckViewCard *_item,
|
||||
const QPointF &_hotSpot,
|
||||
|
@ -238,11 +238,9 @@ int DeckViewCardContainer::getCardTypeTextWidth() const
|
|||
QFontMetrics fm(f);
|
||||
|
||||
int maxCardTypeWidth = 0;
|
||||
QMapIterator<QString, DeckViewCard *> i(cardsByType);
|
||||
while (i.hasNext()) {
|
||||
int cardTypeWidth = fm.size(Qt::TextSingleLine, i.next().key()).width();
|
||||
if (cardTypeWidth > maxCardTypeWidth)
|
||||
maxCardTypeWidth = cardTypeWidth;
|
||||
for (const auto &key : cardsByType.keys()) {
|
||||
int cardTypeWidth = fm.size(Qt::TextSingleLine, key).width();
|
||||
maxCardTypeWidth = qMax(maxCardTypeWidth, cardTypeWidth);
|
||||
}
|
||||
|
||||
return maxCardTypeWidth + 15;
|
||||
|
@ -440,7 +438,7 @@ void DeckViewScene::rearrangeItems()
|
|||
const int maxRows = rowsAndColsList[maxIndex1][maxIndex2].first;
|
||||
const int maxCardCount = cardCountList[maxIndex1][maxIndex2];
|
||||
rowsAndColsList[maxIndex1][maxIndex2] =
|
||||
QPair<int, int>(maxRows + 1, (int)ceil((qreal)maxCardCount / (qreal)(maxRows + 1)));
|
||||
QPair<int, int>(maxRows + 1, (int)qCeil((qreal)maxCardCount / (qreal)(maxRows + 1)));
|
||||
}
|
||||
|
||||
totalHeight = -spacing;
|
||||
|
|
|
@ -162,8 +162,7 @@ DlgConnect::DlgConnect(QWidget *parent) : QDialog(parent)
|
|||
|
||||
previousHostButton->setChecked(true);
|
||||
|
||||
connect(previousHosts, SIGNAL(currentIndexChanged(const QString &)), this,
|
||||
SLOT(updateDisplayInfo(const QString &)));
|
||||
connect(previousHosts, SIGNAL(currentTextChanged(const QString &)), this, SLOT(updateDisplayInfo(const QString &)));
|
||||
|
||||
playernameEdit->setFocus();
|
||||
}
|
||||
|
|
|
@ -121,7 +121,12 @@ WndSets::WndSets(QWidget *parent) : QMainWindow(parent)
|
|||
connect(disableSomeButton, SIGNAL(clicked()), this, SLOT(actDisableSome()));
|
||||
connect(view->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), this,
|
||||
SLOT(actToggleButtons(const QItemSelection &, const QItemSelection &)));
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0))
|
||||
connect(searchField, SIGNAL(textChanged(const QString &)), displayModel,
|
||||
SLOT(setFilterRegularExpression(const QString &)));
|
||||
#else
|
||||
connect(searchField, SIGNAL(textChanged(const QString &)), displayModel, SLOT(setFilterRegExp(const QString &)));
|
||||
#endif
|
||||
connect(view->header(), SIGNAL(sortIndicatorChanged(int, Qt::SortOrder)), this, SLOT(actDisableSortButtons(int)));
|
||||
connect(searchField, SIGNAL(textChanged(const QString &)), this, SLOT(actDisableResetButton(const QString &)));
|
||||
|
||||
|
@ -139,7 +144,6 @@ WndSets::WndSets(QWidget *parent) : QMainWindow(parent)
|
|||
tr("How to use custom card art") + "</a>"));
|
||||
|
||||
QGridLayout *hintsGrid = new QGridLayout;
|
||||
hintsGrid->setMargin(2);
|
||||
hintsGrid->addWidget(labNotes, 0, 0);
|
||||
hintsGroupBox = new QGroupBox(tr("Hints"));
|
||||
hintsGroupBox->setLayout(hintsGrid);
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include <QComboBox>
|
||||
#include <QDebug>
|
||||
#include <QDesktopServices>
|
||||
#include <QDesktopWidget>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QFileDialog>
|
||||
#include <QGridLayout>
|
||||
|
@ -44,18 +43,22 @@
|
|||
|
||||
GeneralSettingsPage::GeneralSettingsPage()
|
||||
{
|
||||
SettingsCache &settings = SettingsCache::instance();
|
||||
QString setLanguage = settings.getLang();
|
||||
QStringList qmFiles = findQmFiles();
|
||||
for (int i = 0; i < qmFiles.size(); i++) {
|
||||
QString langName = languageName(qmFiles[i]);
|
||||
languageBox.addItem(langName, qmFiles[i]);
|
||||
if ((qmFiles[i] == setLanguage) ||
|
||||
(setLanguage.isEmpty() && langName == QCoreApplication::translate("i18n", DEFAULT_LANG_NAME)))
|
||||
languageBox.setCurrentIndex(i);
|
||||
QStringList languageCodes = findQmFiles();
|
||||
for (const QString &code : languageCodes) {
|
||||
QString langName = languageName(code);
|
||||
languageBox.addItem(langName, code);
|
||||
}
|
||||
|
||||
QString setLanguage = QCoreApplication::translate("i18n", DEFAULT_LANG_NAME);
|
||||
int index = languageBox.findText(setLanguage, Qt::MatchExactly);
|
||||
if (index == -1) {
|
||||
qWarning() << "could not find language" << setLanguage;
|
||||
} else {
|
||||
languageBox.setCurrentIndex(index);
|
||||
}
|
||||
|
||||
// updates
|
||||
SettingsCache &settings = SettingsCache::instance();
|
||||
QList<ReleaseChannel *> channels = settings.getUpdateReleaseChannels();
|
||||
foreach (ReleaseChannel *chan, channels) {
|
||||
updateReleaseChannelBox.insertItem(chan->getIndex(), tr(chan->getName().toUtf8()));
|
||||
|
@ -186,15 +189,20 @@ QStringList GeneralSettingsPage::findQmFiles()
|
|||
{
|
||||
QDir dir(translationPath);
|
||||
QStringList fileNames = dir.entryList(QStringList(translationPrefix + "_*.qm"), QDir::Files, QDir::Name);
|
||||
fileNames.replaceInStrings(QRegExp(translationPrefix + "_(.*)\\.qm"), "\\1");
|
||||
fileNames.removeOne("en@source");
|
||||
fileNames.replaceInStrings(QRegularExpression(translationPrefix + "_(.*)\\.qm"), "\\1");
|
||||
return fileNames;
|
||||
}
|
||||
|
||||
QString GeneralSettingsPage::languageName(const QString &qmFile)
|
||||
QString GeneralSettingsPage::languageName(const QString &lang)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1235,11 +1243,7 @@ void ShortcutSettingsPage::retranslateUi()
|
|||
|
||||
DlgSettings::DlgSettings(QWidget *parent) : QDialog(parent)
|
||||
{
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 13, 0))
|
||||
auto rec = qApp->primaryScreen()->availableGeometry();
|
||||
#else
|
||||
auto rec = QApplication::desktop()->availableGeometry();
|
||||
#endif
|
||||
auto rec = QGuiApplication::primaryScreen()->availableGeometry();
|
||||
this->setMinimumSize(qMin(700, rec.width()), qMin(700, rec.height()));
|
||||
|
||||
connect(&SettingsCache::instance(), SIGNAL(langChanged()), this, SLOT(updateLanguage()));
|
||||
|
|
|
@ -49,7 +49,7 @@ private slots:
|
|||
|
||||
private:
|
||||
QStringList findQmFiles();
|
||||
QString languageName(const QString &qmFile);
|
||||
QString languageName(const QString &lang);
|
||||
QLineEdit *deckPathEdit;
|
||||
QLineEdit *replaysPathEdit;
|
||||
QLineEdit *picsPathEdit;
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
#include <cmath>
|
||||
#include <functional>
|
||||
|
||||
peg::parser search(R"(
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#include <QGraphicsSceneMouseEvent>
|
||||
#include <QGraphicsView>
|
||||
#include <QSet>
|
||||
#include <math.h>
|
||||
#include <QtMath>
|
||||
|
||||
GameScene::GameScene(PhasesToolbar *_phasesToolbar, QObject *parent)
|
||||
: QGraphicsScene(parent), phasesToolbar(_phasesToolbar), viewSize(QSize()), playerRotation(0)
|
||||
|
@ -97,7 +97,7 @@ void GameScene::rearrange()
|
|||
|
||||
const int playersCount = playersPlaying.size();
|
||||
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;
|
||||
QList<int> columnWidth;
|
||||
|
||||
|
|
|
@ -93,11 +93,7 @@ QVariant GamesModel::data(const QModelIndex &index, int role) const
|
|||
case CREATED: {
|
||||
switch (role) {
|
||||
case Qt::DisplayRole: {
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0))
|
||||
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());
|
||||
return getGameCreatedString(secs);
|
||||
}
|
||||
|
|
|
@ -24,8 +24,10 @@ void HandZone::updateBg()
|
|||
|
||||
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();
|
||||
}
|
||||
cards.insert(x, card);
|
||||
|
||||
if (!cards.getContentsKnown()) {
|
||||
|
|
|
@ -12,8 +12,9 @@ LocalServer::LocalServer(QObject *parent) : Server(parent)
|
|||
LocalServer::~LocalServer()
|
||||
{
|
||||
// LocalServer is single threaded so it doesn't need locks on this
|
||||
while (!clients.isEmpty())
|
||||
clients.first()->prepareDestroy();
|
||||
for (auto *client : clients) {
|
||||
client->prepareDestroy();
|
||||
}
|
||||
|
||||
prepareDestroy();
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ protected:
|
|||
|
||||
public:
|
||||
LocalServer_DatabaseInterface(LocalServer *_localServer);
|
||||
~LocalServer_DatabaseInterface() = default;
|
||||
AuthenticationResult checkUserPassword(Server_ProtocolHandler *handler,
|
||||
const QString &user,
|
||||
const QString &password,
|
||||
|
|
|
@ -67,11 +67,29 @@ void installNewTranslator()
|
|||
{
|
||||
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);
|
||||
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);
|
||||
qDebug() << "Language changed:" << lang;
|
||||
}
|
||||
|
||||
QString const generateClientID()
|
||||
|
@ -165,7 +183,9 @@ int main(int argc, char *argv[])
|
|||
ui.show();
|
||||
qDebug("main(): ui.show() finished");
|
||||
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||
app.setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||
#endif
|
||||
app.exec();
|
||||
|
||||
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*/)
|
||||
{
|
||||
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);
|
||||
card->setPos(0, 0);
|
||||
if (!contentsKnown()) {
|
||||
|
|
|
@ -99,7 +99,7 @@ QMap<QString, QPixmap> CountryPixmapGenerator::pmCache;
|
|||
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))
|
||||
return pmCache.value(key);
|
||||
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
|
||||
#include <QDebug>
|
||||
#include <QMenu>
|
||||
#include <QMetaType>
|
||||
#include <QPainter>
|
||||
#include <QRegularExpression>
|
||||
#include <QRegularExpressionMatch>
|
||||
|
@ -3066,7 +3067,11 @@ void Player::actSetPT()
|
|||
const auto oldpt = parsePT(card->getPT());
|
||||
int ptIter = 0;
|
||||
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) {
|
||||
#endif
|
||||
int oldItem = ptIter < oldpt.size() ? oldpt.at(ptIter).toInt() : 0;
|
||||
newpt += '/' + QString::number(oldItem + item.toInt());
|
||||
} else {
|
||||
|
|
|
@ -28,7 +28,11 @@ bool PlayerListItemDelegate::editorEvent(QEvent *event,
|
|||
if ((event->type() == QEvent::MouseButtonPress) && index.isValid()) {
|
||||
QMouseEvent *const mouseEvent = static_cast<QMouseEvent *>(event);
|
||||
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);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,10 +23,9 @@
|
|||
|
||||
int ReleaseChannel::sharedIndex = 0;
|
||||
|
||||
ReleaseChannel::ReleaseChannel() : response(nullptr), lastRelease(nullptr)
|
||||
ReleaseChannel::ReleaseChannel() : netMan(new QNetworkAccessManager(this)), response(nullptr), lastRelease(nullptr)
|
||||
{
|
||||
index = sharedIndex++;
|
||||
netMan = new QNetworkAccessManager(this);
|
||||
}
|
||||
|
||||
ReleaseChannel::~ReleaseChannel()
|
||||
|
|
|
@ -78,7 +78,7 @@ class ReleaseChannel : public QObject
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ReleaseChannel();
|
||||
explicit ReleaseChannel();
|
||||
~ReleaseChannel() override;
|
||||
|
||||
protected:
|
||||
|
@ -117,7 +117,7 @@ class StableReleaseChannel : public ReleaseChannel
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
StableReleaseChannel() = default;
|
||||
explicit StableReleaseChannel() = default;
|
||||
~StableReleaseChannel() override = default;
|
||||
|
||||
QString getManualDownloadUrl() const override;
|
||||
|
|
|
@ -41,8 +41,13 @@ RemoteClient::RemoteClient(QObject *parent)
|
|||
socket->setSocketOption(QAbstractSocket::LowDelayOption, 1);
|
||||
connect(socket, SIGNAL(connected()), this, SLOT(slotConnected()));
|
||||
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,
|
||||
SLOT(slotSocketError(QAbstractSocket::SocketError)));
|
||||
#endif
|
||||
|
||||
websocket = new QWebSocket(QString(), QWebSocketProtocol::VersionLatest, this);
|
||||
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();
|
||||
QDateTime time;
|
||||
time.setTime_t(fileInfo.creation_time());
|
||||
time.setSecsSinceEpoch(fileInfo.creation_time());
|
||||
|
||||
beginInsertRows(nodeToIndex(parent), parent->size(), parent->size());
|
||||
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(", ");
|
||||
}
|
||||
case 4:
|
||||
return QDateTime::fromTime_t(matchInfo.time_started());
|
||||
return QDateTime::fromSecsSinceEpoch(matchInfo.time_started());
|
||||
case 5:
|
||||
return matchInfo.length();
|
||||
default:
|
||||
|
|
|
@ -62,7 +62,11 @@ void ReplayTimelineWidget::paintEvent(QPaintEvent * /* 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());
|
||||
#endif
|
||||
newTime -= newTime % 200; // Time should always be a multiple of 200
|
||||
if (newTime < currentTime) {
|
||||
currentTime = 0;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "setsmodel.h"
|
||||
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
SetsModel::SetsModel(CardDatabase *_db, QObject *parent) : QAbstractTableModel(parent), sets(_db->getSetList())
|
||||
{
|
||||
sets.sortByKey();
|
||||
|
@ -274,9 +276,15 @@ bool SetsDisplayModel::filterAcceptsRow(int sourceRow, const QModelIndex &source
|
|||
auto nameIndex = sourceModel()->index(sourceRow, SetsModel::LongNameCol, sourceParent);
|
||||
auto shortNameIndex = sourceModel()->index(sourceRow, SetsModel::ShortNameCol, sourceParent);
|
||||
|
||||
return (sourceModel()->data(typeIndex).toString().contains(filterRegExp()) ||
|
||||
sourceModel()->data(nameIndex).toString().contains(filterRegExp()) ||
|
||||
sourceModel()->data(shortNameIndex).toString().contains(filterRegExp()));
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0))
|
||||
const auto filter = filterRegularExpression();
|
||||
#else
|
||||
const auto filter = filterRegExp();
|
||||
#endif
|
||||
|
||||
return (sourceModel()->data(typeIndex).toString().contains(filter) ||
|
||||
sourceModel()->data(nameIndex).toString().contains(filter) ||
|
||||
sourceModel()->data(shortNameIndex).toString().contains(filter));
|
||||
}
|
||||
|
||||
bool SetsDisplayModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
|
||||
|
|
|
@ -18,7 +18,7 @@ QString SettingsCache::getDataPath()
|
|||
if (isPortableBuild)
|
||||
return qApp->applicationDirPath() + "/data";
|
||||
else
|
||||
return QStandardPaths::writableLocation(QStandardPaths::DataLocation);
|
||||
return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
||||
}
|
||||
|
||||
QString SettingsCache::getSettingsPath()
|
||||
|
|
|
@ -2,21 +2,15 @@
|
|||
|
||||
#include "settingscache.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QAudioOutput>
|
||||
#include <QBuffer>
|
||||
#include <QDebug>
|
||||
#include <QFileInfo>
|
||||
#include <QLibraryInfo>
|
||||
#include <QStandardPaths>
|
||||
#include <QDir>
|
||||
#include <QMediaPlayer>
|
||||
|
||||
#define DEFAULT_THEME_NAME "Default"
|
||||
#define TEST_SOUND_FILENAME "player_join"
|
||||
|
||||
SoundEngine::SoundEngine(QObject *parent) : QObject(parent), player(0)
|
||||
{
|
||||
inputBuffer = new QBuffer(this);
|
||||
|
||||
ensureThemeDirectoryExists();
|
||||
connect(&SettingsCache::instance(), SIGNAL(soundThemeChanged()), this, SLOT(themeChangedSlot()));
|
||||
connect(&SettingsCache::instance(), SIGNAL(soundEnabledChanged()), this, SLOT(soundEnabledChanged()));
|
||||
|
@ -31,8 +25,6 @@ SoundEngine::~SoundEngine()
|
|||
player->deleteLater();
|
||||
player = 0;
|
||||
}
|
||||
|
||||
inputBuffer->deleteLater();
|
||||
}
|
||||
|
||||
void SoundEngine::soundEnabledChanged()
|
||||
|
@ -40,14 +32,11 @@ void SoundEngine::soundEnabledChanged()
|
|||
if (SettingsCache::instance().getSoundEnabled()) {
|
||||
qDebug("SoundEngine: enabling sound");
|
||||
if (!player) {
|
||||
QAudioFormat format;
|
||||
format.setSampleRate(44100);
|
||||
format.setChannelCount(1);
|
||||
format.setSampleSize(16);
|
||||
format.setCodec("audio/pcm");
|
||||
format.setByteOrder(QAudioFormat::LittleEndian);
|
||||
format.setSampleType(QAudioFormat::SignedInt);
|
||||
player = new QAudioOutput(format, this);
|
||||
player = new QMediaPlayer;
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
auto qAudioOutput = new QAudioOutput;
|
||||
player->setAudioOutput(qAudioOutput);
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
qDebug("SoundEngine: disabling sound");
|
||||
|
@ -61,25 +50,35 @@ void SoundEngine::soundEnabledChanged()
|
|||
|
||||
void SoundEngine::playSound(QString fileName)
|
||||
{
|
||||
if (!player)
|
||||
if (!player) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
if (!audioData.contains(fileName))
|
||||
if (!audioData.contains(fileName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "playing" << fileName;
|
||||
|
||||
inputBuffer->close();
|
||||
inputBuffer->setData(audioData[fileName]);
|
||||
inputBuffer->open(QIODevice::ReadOnly);
|
||||
|
||||
player->setVolume(SettingsCache::instance().getMasterVolume() / 100.0);
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
player->audioOutput()->setVolume(SettingsCache::instance().getMasterVolume());
|
||||
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()
|
||||
|
@ -105,7 +104,7 @@ QStringMap &SoundEngine::getAvailableThemes()
|
|||
|
||||
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))
|
||||
availableThemes.insert(themeName, dir.absoluteFilePath(themeName));
|
||||
}
|
||||
|
@ -121,7 +120,7 @@ QStringMap &SoundEngine::getAvailableThemes()
|
|||
#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))
|
||||
availableThemes.insert(themeName, dir.absoluteFilePath(themeName));
|
||||
}
|
||||
|
@ -181,10 +180,7 @@ void SoundEngine::themeChangedSlot()
|
|||
continue;
|
||||
|
||||
QFile file(dir.filePath(fileNames[i] + ".wav"));
|
||||
file.open(QIODevice::ReadOnly);
|
||||
// 44 = length of wav header
|
||||
audioData.insert(fileNames[i], file.readAll().mid(44));
|
||||
file.close();
|
||||
audioData.insert(fileNames[i], file.fileName());
|
||||
}
|
||||
|
||||
soundEnabledChanged();
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#ifndef SOUNDENGINE_H
|
||||
#define SOUNDENGINE_H
|
||||
|
||||
#include <QDir>
|
||||
#include <QMap>
|
||||
#include <QMediaPlayer>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
||||
|
@ -21,10 +21,9 @@ public:
|
|||
QStringMap &getAvailableThemes();
|
||||
|
||||
private:
|
||||
QMap<QString, QByteArray> audioData;
|
||||
QBuffer *inputBuffer;
|
||||
QAudioOutput *player;
|
||||
QStringMap availableThemes;
|
||||
QMap<QString, QString> audioData;
|
||||
QMediaPlayer *player;
|
||||
|
||||
protected:
|
||||
void ensureThemeDirectoryExists();
|
||||
|
|
|
@ -114,7 +114,7 @@ void SpoilerBackgroundUpdater::actCheckIfSpoilerSeasonEnabled()
|
|||
emit spoilerCheckerDone();
|
||||
} else {
|
||||
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;
|
||||
|
@ -159,7 +159,7 @@ bool SpoilerBackgroundUpdater::saveDownloadedFile(QByteArray data)
|
|||
|
||||
// Data written, so reload the card database
|
||||
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
|
||||
// when the database was last updated
|
||||
|
|
|
@ -26,8 +26,10 @@ void StackZone::updateBg()
|
|||
|
||||
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();
|
||||
}
|
||||
cards.insert(x, card);
|
||||
|
||||
if (!cards.getContentsKnown()) {
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
#include <QDesktopWidget>
|
||||
#include <QScreen>
|
||||
|
||||
Tab::Tab(TabSupervisor *_tabSupervisor, QWidget *parent)
|
||||
: QMainWindow(parent), tabSupervisor(_tabSupervisor), contentsChanged(false), infoPopup(0)
|
||||
{
|
||||
|
@ -20,7 +21,8 @@ void Tab::showCardInfoPopup(const QPoint &pos, const QString &cardName)
|
|||
infoPopup = new CardInfoWidget(
|
||||
cardName, 0, Qt::Widget | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint | Qt::WindowStaysOnTopHint);
|
||||
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,
|
||||
screenRect.left() + screenRect.width() - infoPopup->width())),
|
||||
qMax(screenRect.top(), qMin(pos.y() - infoPopup->height() / 2,
|
||||
|
|
|
@ -52,7 +52,7 @@ TabRoom::TabRoom(TabSupervisor *_tabSupervisor,
|
|||
SIGNAL(openMessageDialog(const QString &, bool)));
|
||||
|
||||
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(openMessageDialog(QString, bool)), this, SIGNAL(openMessageDialog(QString, bool)));
|
||||
connect(chatView, SIGNAL(showCardInfoPopup(QPoint, QString)), this, SLOT(showCardInfoPopup(QPoint, QString)));
|
||||
|
@ -160,7 +160,7 @@ void TabRoom::focusTab()
|
|||
emit maximizeClient();
|
||||
}
|
||||
|
||||
void TabRoom::actShowMentionPopup(QString &sender)
|
||||
void TabRoom::actShowMentionPopup(const QString &sender)
|
||||
{
|
||||
this->actShowPopup(sender + tr(" mentioned you."));
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ private slots:
|
|||
void actOpenChatSettings();
|
||||
void addMentionTag(QString mentionTag);
|
||||
void focusTab();
|
||||
void actShowMentionPopup(QString &sender);
|
||||
void actShowMentionPopup(const QString &sender);
|
||||
void actShowPopup(const QString &message);
|
||||
void actCompleterChanged();
|
||||
|
||||
|
|
|
@ -58,7 +58,11 @@ QSize CloseButton::sizeHint() const
|
|||
return QSize(width, height);
|
||||
}
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
void CloseButton::enterEvent(QEnterEvent *event)
|
||||
#else
|
||||
void CloseButton::enterEvent(QEvent *event)
|
||||
#endif
|
||||
{
|
||||
update();
|
||||
QAbstractButton::enterEvent(event);
|
||||
|
@ -74,7 +78,7 @@ void CloseButton::paintEvent(QPaintEvent * /*event*/)
|
|||
{
|
||||
QPainter p(this);
|
||||
QStyleOption opt;
|
||||
opt.init(this);
|
||||
opt.initFrom(this);
|
||||
opt.state |= QStyle::State_AutoRaise;
|
||||
if (isEnabled() && underMouse() && !isChecked() && !isDown())
|
||||
opt.state |= QStyle::State_Raised;
|
||||
|
|
|
@ -52,7 +52,11 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
void enterEvent(QEnterEvent *event);
|
||||
#else
|
||||
void enterEvent(QEvent *event);
|
||||
#endif
|
||||
void leaveEvent(QEvent *event);
|
||||
void paintEvent(QPaintEvent *event);
|
||||
};
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <QNetworkReply>
|
||||
#include <QNetworkRequest>
|
||||
#include <QRegExp>
|
||||
#include <QRegularExpression>
|
||||
#include <QUrlQuery>
|
||||
|
||||
TappedOutInterface::TappedOutInterface(CardDatabase &_cardDatabase, QObject *parent)
|
||||
|
@ -53,7 +54,7 @@ void TappedOutInterface::queryFinished(QNetworkReply *reply)
|
|||
|
||||
int captures = rx2.captureCount();
|
||||
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;
|
||||
}
|
||||
|
||||
if (reader.name() == "tip") {
|
||||
auto readerName = reader.name().toString();
|
||||
|
||||
if (readerName == "tip") {
|
||||
QString title, content, imagePath;
|
||||
QDate date;
|
||||
reader.readNext();
|
||||
|
@ -45,16 +47,18 @@ TipsOfTheDay::TipsOfTheDay(QString xmlPath, QObject *parent) : QAbstractListMode
|
|||
break;
|
||||
}
|
||||
|
||||
if (reader.name() == "title") {
|
||||
readerName = reader.name().toString();
|
||||
|
||||
if (readerName == "title") {
|
||||
title = reader.readElementText();
|
||||
} else if (reader.name() == "text") {
|
||||
} else if (readerName == "text") {
|
||||
content = reader.readElementText();
|
||||
} else if (reader.name() == "image") {
|
||||
} else if (readerName == "image") {
|
||||
imagePath = "theme:tips/images/" + reader.readElementText();
|
||||
} else if (reader.name() == "date") {
|
||||
} else if (readerName == "date") {
|
||||
date = QDate::fromString(reader.readElementText(), Qt::ISODate);
|
||||
} else {
|
||||
// unkown element, do nothing
|
||||
// unknown element, do nothing
|
||||
}
|
||||
}
|
||||
tipList->append(TipOfTheDay(title, content, imagePath, date));
|
||||
|
|
|
@ -137,7 +137,7 @@ QString UserInfoBox::getAgeString(int ageSeconds)
|
|||
if (ageSeconds == 0)
|
||||
return accountAgeString;
|
||||
|
||||
auto date = QDateTime::fromTime_t(QDateTime::currentSecsSinceEpoch() - ageSeconds).date();
|
||||
auto date = QDateTime::fromSecsSinceEpoch(QDateTime::currentSecsSinceEpoch() - ageSeconds).date();
|
||||
if (!date.isValid())
|
||||
return accountAgeString;
|
||||
|
||||
|
|
|
@ -296,7 +296,11 @@ bool UserListItemDelegate::editorEvent(QEvent *event,
|
|||
if ((event->type() == QEvent::MouseButtonPress) && index.isValid()) {
|
||||
QMouseEvent *const mouseEvent = static_cast<QMouseEvent *>(event);
|
||||
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);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,8 +101,8 @@ void MainWindow::processConnectionClosedEvent(const Event_ConnectionClosed &even
|
|||
case Event_ConnectionClosed::BANNED: {
|
||||
reasonStr = tr("Banned by moderator");
|
||||
if (event.has_end_time())
|
||||
reasonStr.append("\n" +
|
||||
tr("Expected end time: %1").arg(QDateTime::fromTime_t(event.end_time()).toString()));
|
||||
reasonStr.append(
|
||||
"\n" + tr("Expected end time: %1").arg(QDateTime::fromSecsSinceEpoch(event.end_time()).toString()));
|
||||
else
|
||||
reasonStr.append("\n" + tr("This ban lasts indefinitely."));
|
||||
if (event.has_reason_str())
|
||||
|
@ -393,7 +393,7 @@ void MainWindow::loginError(Response::ResponseCode r,
|
|||
case Response::RespUserIsBanned: {
|
||||
QString bannedStr;
|
||||
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
|
||||
bannedStr = tr("You are banned indefinitely.");
|
||||
if (!reasonStr.isEmpty())
|
||||
|
@ -530,7 +530,7 @@ void MainWindow::registerError(Response::ResponseCode r, QString reasonStr, quin
|
|||
case Response::RespUserIsBanned: {
|
||||
QString bannedStr;
|
||||
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
|
||||
bannedStr = tr("You are banned indefinitely.");
|
||||
if (!reasonStr.isEmpty())
|
||||
|
@ -865,13 +865,13 @@ void MainWindow::startupConfigCheck()
|
|||
if (SettingsCache::instance().getNotifyAboutNewVersion()) {
|
||||
alertForcedOracleRun(VERSION_STRING, true);
|
||||
} else {
|
||||
QtConcurrent::run(db, &CardDatabase::loadCardDatabases);
|
||||
const auto reloadOk0 = QtConcurrent::run([] { db->loadCardDatabases(); });
|
||||
}
|
||||
SettingsCache::instance().setClientVersion(VERSION_STRING);
|
||||
} else {
|
||||
// previous config from this version found
|
||||
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.
|
||||
// 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)
|
||||
{
|
||||
if (reason == QSystemTrayIcon::DoubleClick) {
|
||||
if (windowState() != Qt::WindowMinimized && windowState() != Qt::WindowMinimized + Qt::WindowMaximized)
|
||||
if ((windowState() & Qt::WindowMinimized) == 0) {
|
||||
showMinimized();
|
||||
else {
|
||||
} else {
|
||||
showNormal();
|
||||
QApplication::setActiveWindow(this);
|
||||
}
|
||||
|
@ -1058,7 +1058,7 @@ void MainWindow::cardDatabaseNewSetsFound(int numUnknownSets, QStringList unknow
|
|||
|
||||
if (msgBox.clickedButton() == yesButton) {
|
||||
db->enableAllUnknownSets();
|
||||
QtConcurrent::run(db, &CardDatabase::loadCardDatabases);
|
||||
const auto reloadOk1 = QtConcurrent::run([] { db->loadCardDatabases(); });
|
||||
} else if (msgBox.clickedButton() == noButton) {
|
||||
db->markAllSetsAsKnown();
|
||||
} else if (msgBox.clickedButton() == settingsButton) {
|
||||
|
@ -1086,8 +1086,9 @@ void MainWindow::actCheckCardUpdates()
|
|||
}
|
||||
|
||||
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,
|
||||
SLOT(cardUpdateFinished(int, QProcess::ExitStatus)));
|
||||
|
||||
|
@ -1148,7 +1149,7 @@ void MainWindow::exitCardDatabaseUpdate()
|
|||
cardUpdateProcess->deleteLater();
|
||||
cardUpdateProcess = nullptr;
|
||||
|
||||
QtConcurrent::run(db, &CardDatabase::loadCardDatabases);
|
||||
const auto reloadOk1 = QtConcurrent::run([] { db->loadCardDatabases(); });
|
||||
}
|
||||
|
||||
void MainWindow::cardUpdateError(QProcess::ProcessError err)
|
||||
|
@ -1278,7 +1279,7 @@ void MainWindow::actAddCustomSet()
|
|||
QMessageBox::information(
|
||||
this, tr("Load sets/cards"),
|
||||
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 {
|
||||
QMessageBox::warning(this, tr("Load sets/cards"), tr("Sets/cards failed to import."));
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include <QDebug>
|
||||
#include <QGraphicsSceneWheelEvent>
|
||||
#include <QPainter>
|
||||
#include <math.h>
|
||||
#include <QtMath>
|
||||
|
||||
ZoneViewZone::ZoneViewZone(Player *_p,
|
||||
CardZone *_origZone,
|
||||
|
@ -103,17 +103,17 @@ void ZoneViewZone::reorganizeCards()
|
|||
for (int i = 0; i < cardCount; ++i)
|
||||
cards[i]->setId(i);
|
||||
|
||||
int cols = floor(sqrt((double)cardCount / 2));
|
||||
int cols = qFloor(qSqrt((double)cardCount / 2));
|
||||
if (cols > 7)
|
||||
cols = 7;
|
||||
int rows = ceil((double)cardCount / cols);
|
||||
int rows = qCeil((double)cardCount / cols);
|
||||
if (rows < 1)
|
||||
rows = 1;
|
||||
if (minRows == 0)
|
||||
minRows = rows;
|
||||
else if (rows < minRows) {
|
||||
rows = minRows;
|
||||
cols = ceil((double)cardCount / minRows);
|
||||
cols = qCeil((double)cardCount / minRows);
|
||||
}
|
||||
if (cols < 2)
|
||||
cols = 2;
|
||||
|
@ -193,6 +193,10 @@ void ZoneViewZone::setPileView(int _pileView)
|
|||
|
||||
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);
|
||||
card->setParentItem(this);
|
||||
card->update();
|
||||
|
|
|
@ -36,8 +36,8 @@ set(ORACLE_LIBS)
|
|||
INCLUDE_DIRECTORIES(pb)
|
||||
INCLUDE_DIRECTORIES(sfmt)
|
||||
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})
|
||||
|
||||
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()) {
|
||||
xml->readNext();
|
||||
if (xml->isEndElement() && xml->name() == "card")
|
||||
if (xml->isEndElement() && xml->name().toString() == "card")
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -435,7 +435,7 @@ bool DeckList::loadFromXml(QXmlStreamReader *xml)
|
|||
while (!xml->atEnd()) {
|
||||
xml->readNext();
|
||||
if (xml->isStartElement()) {
|
||||
if (xml->name() != "cockatrice_deck")
|
||||
if (xml->name().toString() != "cockatrice_deck")
|
||||
return false;
|
||||
while (!xml->atEnd()) {
|
||||
xml->readNext();
|
||||
|
@ -602,7 +602,7 @@ bool DeckList::loadFromStream_Plain(QTextStream &in)
|
|||
int amount = 1;
|
||||
match = reMultiplier.match(cardName);
|
||||
if (match.hasMatch()) {
|
||||
amount = match.capturedRef(1).toInt();
|
||||
amount = match.captured(1).toInt();
|
||||
cardName = match.captured(2);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
#include <cmath>
|
||||
#include <QtMath>
|
||||
#include <functional>
|
||||
|
||||
peg::parser math(R"(
|
||||
|
@ -32,19 +32,17 @@ Expression::Expression(double initial) : value(initial)
|
|||
{
|
||||
if (default_functions == nullptr) {
|
||||
default_functions = new QMap<QString, std::function<double(double)>>();
|
||||
default_functions->insert("sin", [](double a) { return sin(a); });
|
||||
default_functions->insert("cos", [](double a) { return cos(a); });
|
||||
default_functions->insert("tan", [](double a) { return tan(a); });
|
||||
default_functions->insert("sqrt", [](double a) { return sqrt(a); });
|
||||
default_functions->insert("log", [](double a) { return log(a); });
|
||||
default_functions->insert("log10", [](double a) { return log(a); });
|
||||
default_functions->insert("trunc", [](double a) { return trunc(a); });
|
||||
default_functions->insert("abs", [](double a) { return fabs(a); });
|
||||
|
||||
default_functions->insert("floor", [](double a) { return floor(a); });
|
||||
default_functions->insert("ceil", [](double a) { return ceil(a); });
|
||||
default_functions->insert("round", [](double a) { return round(a); });
|
||||
default_functions->insert("trunc", [](double a) { return trunc(a); });
|
||||
default_functions->insert("abs", [](double a) { return qFabs(a); });
|
||||
default_functions->insert("ceil", [](double a) { return qCeil(a); });
|
||||
default_functions->insert("cos", [](double a) { return qCos(a); });
|
||||
default_functions->insert("floor", [](double a) { return qFloor(a); });
|
||||
default_functions->insert("log", [](double a) { return qLn(a); });
|
||||
default_functions->insert("log10", [](double a) { return qLn(a); });
|
||||
default_functions->insert("round", [](double a) { return qRound(a); });
|
||||
default_functions->insert("sin", [](double a) { return qSin(a); });
|
||||
default_functions->insert("sqrt", [](double a) { return qSqrt(a); });
|
||||
default_functions->insert("tan", [](double a) { return qTan(a); });
|
||||
default_functions->insert("trunc", [](double a) { return std::trunc(a); });
|
||||
}
|
||||
fns = QMap<QString, std::function<double(double)>>(*default_functions);
|
||||
}
|
||||
|
@ -80,7 +78,7 @@ double Expression::eval(const peg::Ast &ast)
|
|||
result /= arg;
|
||||
break;
|
||||
case '^':
|
||||
result = pow(result, arg);
|
||||
result = qPow(result, arg);
|
||||
break;
|
||||
default:
|
||||
result = 0;
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
RNG_SFMT::RNG_SFMT(QObject *parent) : RNG_Abstract(parent)
|
||||
{
|
||||
// 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.set_reason(Event_ConnectionClosed::LOGGEDINELSEWERE);
|
||||
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);
|
||||
users.value(name)->sendProtocolItem(*se);
|
||||
|
@ -230,6 +230,11 @@ void Server::addClient(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")
|
||||
tcpUserCount--;
|
||||
|
@ -238,7 +243,7 @@ void Server::removeClient(Server_ProtocolHandler *client)
|
|||
webSocketUserCount--;
|
||||
|
||||
QWriteLocker locker(&clientsLock);
|
||||
clients.removeAt(clients.indexOf(client));
|
||||
clients.removeAt(clientIndex);
|
||||
ServerInfo_User *data = client->getUserInfo();
|
||||
if (data) {
|
||||
Event_UserLeft event;
|
||||
|
|
|
@ -57,8 +57,8 @@ private slots:
|
|||
|
||||
public:
|
||||
mutable QReadWriteLock clientsLock, roomsLock; // locking order: roomsLock before clientsLock
|
||||
Server(QObject *parent = nullptr);
|
||||
~Server() = default;
|
||||
explicit Server(QObject *parent = nullptr);
|
||||
virtual ~Server() = default;
|
||||
AuthenticationResult loginUser(Server_ProtocolHandler *session,
|
||||
QString &name,
|
||||
const QString &password,
|
||||
|
|
|
@ -21,13 +21,13 @@
|
|||
#define SERVER_CARD_H
|
||||
|
||||
#include "pb/card_attributes.pb.h"
|
||||
#include "pb/serverinfo_card.pb.h"
|
||||
#include "server_arrowtarget.h"
|
||||
|
||||
#include <QMap>
|
||||
#include <QString>
|
||||
|
||||
class Server_CardZone;
|
||||
class ServerInfo_Card;
|
||||
|
||||
class Server_Card : public Server_ArrowTarget
|
||||
{
|
||||
|
@ -52,7 +52,7 @@ private:
|
|||
|
||||
public:
|
||||
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
|
||||
{
|
||||
|
|
|
@ -292,10 +292,10 @@ void Server_CardZone::insertCard(Server_Card *card, int x, int y)
|
|||
insertCardIntoCoordMap(card, x, y);
|
||||
} else {
|
||||
card->setCoords(0, 0);
|
||||
if (x == -1) {
|
||||
cards.append(card);
|
||||
} else {
|
||||
if (0 <= x && x < cards.length()) {
|
||||
cards.insert(x, card);
|
||||
} else {
|
||||
cards.append(card);
|
||||
}
|
||||
}
|
||||
card->setZone(this);
|
||||
|
|
|
@ -147,7 +147,12 @@ public:
|
|||
LogMessage_TargetType /* targetType */,
|
||||
const int /* targetId */,
|
||||
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 */)
|
||||
{
|
||||
return 0;
|
||||
|
|
|
@ -69,6 +69,7 @@ Server_Game::Server_Game(const ServerInfo_User &_creatorInfo,
|
|||
spectatorsNeedPassword(_spectatorsNeedPassword), spectatorsCanTalk(_spectatorsCanTalk),
|
||||
spectatorsSeeEverything(_spectatorsSeeEverything), inactivityCounter(0), startTimeOfThisGame(0),
|
||||
secondsElapsed(0), firstGameStarted(false), turnOrderReversed(false), startTime(QDateTime::currentDateTime()),
|
||||
pingClock(nullptr),
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
gameMutex()
|
||||
#else
|
||||
|
@ -97,7 +98,7 @@ Server_Game::~Server_Game()
|
|||
|
||||
gameClosed = true;
|
||||
sendGameEventContainer(prepareGameEvent(Event_GameClosed(), -1));
|
||||
for (Server_Player *player : players.values()) {
|
||||
for (auto *player : players.values()) {
|
||||
player->prepareDestroy();
|
||||
}
|
||||
players.clear();
|
||||
|
@ -112,10 +113,22 @@ Server_Game::~Server_Game()
|
|||
replayList.append(currentReplay);
|
||||
storeGameInformation();
|
||||
|
||||
for (int i = 0; i < replayList.size(); ++i)
|
||||
delete replayList[i];
|
||||
for (auto *replay : replayList) {
|
||||
delete replay;
|
||||
}
|
||||
replayList.clear();
|
||||
|
||||
room = nullptr;
|
||||
currentReplay = nullptr;
|
||||
creatorInfo = nullptr;
|
||||
|
||||
if (pingClock) {
|
||||
delete pingClock;
|
||||
pingClock = nullptr;
|
||||
}
|
||||
|
||||
qDebug() << "Server_Game destructor: gameId=" << gameId;
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
void Server_Game::storeGameInformation()
|
||||
|
@ -126,7 +139,7 @@ void Server_Game::storeGameInformation()
|
|||
ServerInfo_ReplayMatch *replayMatchInfo = replayEvent.mutable_match_info();
|
||||
replayMatchInfo->set_game_id(gameInfo.game_id());
|
||||
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_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_omniscient(spectatorsSeeEverything);
|
||||
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()
|
||||
{
|
||||
delete deck;
|
||||
deck = nullptr;
|
||||
|
||||
playerMutex.lock();
|
||||
if (userInterface) {
|
||||
|
@ -1234,7 +1235,6 @@ Server_Player::cmdAttachCard(const Command_AttachCard &cmd, ResponseContainer &
|
|||
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());
|
||||
while (playerIterator.hasNext()) {
|
||||
Server_Player *p = playerIterator.next().value();
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QtMath>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <math.h>
|
||||
|
||||
Server_ProtocolHandler::Server_ProtocolHandler(Server *_server,
|
||||
Server_DatabaseInterface *_databaseInterface,
|
||||
|
@ -44,6 +44,7 @@ Server_ProtocolHandler::~Server_ProtocolHandler()
|
|||
}
|
||||
|
||||
// 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).
|
||||
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)) {
|
||||
Event_NotifyUser event;
|
||||
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;
|
||||
re->set_denied_reason_str(reasonStr.toStdString());
|
||||
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);
|
||||
return Response::RespUserIsBanned;
|
||||
}
|
||||
|
|
|
@ -63,7 +63,6 @@ protected:
|
|||
private:
|
||||
QList<int> messageSizeOverTime, messageCountOverTime, commandCountOverTime;
|
||||
int timeRunning, lastDataReceived, lastActionReceived;
|
||||
QTimer *pingClock;
|
||||
|
||||
virtual void transmitProtocolItem(const ServerMessage &item) = 0;
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ ServerInfo_User_Container::ServerInfo_User_Container(const ServerInfo_User_Conta
|
|||
if (other.userInfo)
|
||||
userInfo = new ServerInfo_User(*other.userInfo);
|
||||
else
|
||||
userInfo = 0;
|
||||
userInfo = nullptr;
|
||||
}
|
||||
|
||||
ServerInfo_User_Container::~ServerInfo_User_Container()
|
||||
|
|
|
@ -9,7 +9,7 @@ protected:
|
|||
ServerInfo_User *userInfo;
|
||||
|
||||
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_Container &other);
|
||||
ServerInfo_User_Container &operator=(const ServerInfo_User_Container &other) = default;
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
#define STRINGSIZES_H
|
||||
|
||||
#include <QString>
|
||||
#include <QtMath>
|
||||
|
||||
// max size for short strings, like names and things that are generally a single phrase
|
||||
constexpr int MAX_NAME_LENGTH = 0xff;
|
||||
|
|
|
@ -13,24 +13,25 @@ SET(dbconverter_SOURCES
|
|||
${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)
|
||||
|
||||
QT5_WRAP_CPP(dbconverter_SOURCES
|
||||
IF(Qt6_FOUND)
|
||||
Qt6_WRAP_CPP(dbconverter_SOURCES
|
||||
../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
|
||||
ADD_EXECUTABLE(dbconverter MACOSX_BUNDLE ${dbconverter_SOURCES} ${dbconverter_MOC_SRCS})
|
||||
|
||||
if(MSVC)
|
||||
TARGET_LINK_LIBRARIES(dbconverter ${dbconverter_QT_MODULES} Qt5::WinMain)
|
||||
else()
|
||||
TARGET_LINK_LIBRARIES(dbconverter ${dbconverter_QT_MODULES})
|
||||
endif()
|
||||
TARGET_LINK_LIBRARIES(dbconverter ${DB_CONVERTER_QT_MODULES})
|
||||
|
||||
# install rules
|
||||
if(UNIX)
|
||||
|
@ -55,9 +56,8 @@ if(APPLE)
|
|||
# these needs to be relative to CMAKE_INSTALL_PREFIX
|
||||
set(plugin_dest_dir dbconverter.app/Contents/Plugins)
|
||||
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
|
||||
FILES_MATCHING
|
||||
PATTERN "*.dSYM" EXCLUDE
|
||||
|
@ -87,10 +87,12 @@ if(WIN32)
|
|||
|
||||
install(DIRECTORY "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/${CMAKE_BUILD_TYPE}/" DESTINATION ./ FILES_MATCHING PATTERN "*.dll")
|
||||
|
||||
# qt5 plugins: platforms, sqldrivers/mysql
|
||||
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime
|
||||
FILES_MATCHING REGEX "(platforms/.*)\\.dll"
|
||||
REGEX ".*d\\.dll" EXCLUDE)
|
||||
# Qt plugins: platforms
|
||||
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime FILES_MATCHING
|
||||
PATTERN "platforms/qdirect2d.dll"
|
||||
PATTERN "platforms/qminimal.dll"
|
||||
PATTERN "platforms/qoffscreen.dll"
|
||||
PATTERN "platforms/qwindows.dll")
|
||||
|
||||
install(CODE "
|
||||
file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf\" \"[Paths]
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
#
|
||||
# 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
|
||||
set(DESKTOPDIR share/applications CACHE STRING "path to .desktop files")
|
||||
|
||||
SET(oracle_SOURCES
|
||||
set(oracle_SOURCES
|
||||
src/main.cpp
|
||||
src/oraclewizard.cpp
|
||||
src/oracleimporter.cpp
|
||||
|
@ -34,13 +34,13 @@ SET(oracle_SOURCES
|
|||
|
||||
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)
|
||||
SET(translate_SRCS ${translate_oracle_SRCS})
|
||||
SET(oracle_TS "${CMAKE_CURRENT_SOURCE_DIR}/translations/oracle_en@source.ts")
|
||||
ELSE()
|
||||
SET(oracle_TS "${CMAKE_CURRENT_SOURCE_DIR}/oracle_en@source.ts")
|
||||
else()
|
||||
FILE(GLOB oracle_TS "${CMAKE_CURRENT_SOURCE_DIR}/translations/*.ts")
|
||||
ENDIF(UPDATE_TRANSLATIONS)
|
||||
endif(UPDATE_TRANSLATIONS)
|
||||
|
||||
if(WIN32)
|
||||
set(oracle_SOURCES ${oracle_SOURCES} oracle.rc)
|
||||
|
@ -50,38 +50,19 @@ if(APPLE)
|
|||
set(MACOSX_BUNDLE_ICON_FILE appicon.icns)
|
||||
set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/resources/appicon.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
|
||||
set(oracle_SOURCES ${oracle_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/resources/appicon.icns)
|
||||
ENDIF(APPLE)
|
||||
endif(APPLE)
|
||||
|
||||
# Qt5
|
||||
find_package(Qt5 COMPONENTS Concurrent Network Svg Widgets REQUIRED)
|
||||
set(ORACLE_QT_MODULES Qt5::Concurrent Qt5::Network Qt5::Svg Qt5::Widgets)
|
||||
|
||||
# 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.")
|
||||
if(Qt6_FOUND)
|
||||
Qt6_ADD_RESOURCES(oracle_RESOURCES_RCC ${oracle_RESOURCES})
|
||||
elseif(Qt5_FOUND)
|
||||
Qt5_ADD_RESOURCES(oracle_RESOURCES_RCC ${oracle_RESOURCES})
|
||||
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()
|
||||
|
||||
QT5_ADD_RESOURCES(oracle_RESOURCES_RCC ${oracle_RESOURCES})
|
||||
|
||||
INCLUDE_DIRECTORIES(../cockatrice/src)
|
||||
|
||||
# Libz is required to support zipped files
|
||||
FIND_PACKAGE(ZLIB)
|
||||
IF(ZLIB_FOUND)
|
||||
if(ZLIB_FOUND)
|
||||
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIRS})
|
||||
ADD_DEFINITIONS("-DHAS_ZLIB")
|
||||
|
||||
|
@ -89,34 +70,60 @@ IF(ZLIB_FOUND)
|
|||
src/zip/unzip.cpp
|
||||
src/zip/zipglobal.cpp
|
||||
)
|
||||
ELSE()
|
||||
else()
|
||||
MESSAGE(STATUS "Oracle: zlib not found; ZIP support disabled")
|
||||
ENDIF()
|
||||
endif()
|
||||
|
||||
# LibLZMA is required to support xz files
|
||||
FIND_PACKAGE(LibLZMA)
|
||||
IF(LIBLZMA_FOUND)
|
||||
if(LIBLZMA_FOUND)
|
||||
INCLUDE_DIRECTORIES(${LIBLZMA_INCLUDE_DIRS})
|
||||
ADD_DEFINITIONS("-DHAS_LZMA")
|
||||
|
||||
set(oracle_SOURCES ${oracle_SOURCES}
|
||||
src/lzma/decompress.cpp
|
||||
)
|
||||
ELSE()
|
||||
else()
|
||||
MESSAGE(STATUS "Oracle: LibLZMA not found; xz support disabled")
|
||||
ENDIF()
|
||||
endif()
|
||||
|
||||
# Build oracle binary and link it
|
||||
ADD_EXECUTABLE(oracle WIN32 MACOSX_BUNDLE ${oracle_SOURCES} ${oracle_QM} ${oracle_RESOURCES_RCC} ${oracle_MOC_SRCS})
|
||||
TARGET_LINK_LIBRARIES(oracle ${ORACLE_QT_MODULES})
|
||||
set(ORACLE_MAC_QM_INSTALL_DIR "oracle.app/Contents/Resources/translations")
|
||||
set(ORACLE_UNIX_QM_INSTALL_DIR "share/oracle/translations")
|
||||
set(ORACLE_WIN32_QM_INSTALL_DIR "translations")
|
||||
|
||||
IF(ZLIB_FOUND)
|
||||
TARGET_LINK_LIBRARIES(oracle ${ZLIB_LIBRARIES})
|
||||
ENDIF()
|
||||
if(Qt6_FOUND)
|
||||
# Qt6 Translations are linked after the executable is created in manual mode
|
||||
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 ${LIBLZMA_LIBRARIES})
|
||||
ENDIF()
|
||||
TARGET_LINK_LIBRARIES(oracle PUBLIC ${ORACLE_QT_MODULES})
|
||||
|
||||
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(APPLE)
|
||||
|
@ -129,17 +136,14 @@ if(UNIX)
|
|||
set_target_properties(oracle PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/cmake/Info.plist)
|
||||
|
||||
INSTALL(TARGETS oracle BUNDLE DESTINATION ./)
|
||||
INSTALL(FILES ${oracle_QM} DESTINATION ./oracle.app/Contents/Resources/translations)
|
||||
else()
|
||||
# Assume linux
|
||||
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.svg DESTINATION ${ICONDIR}/hicolor/scalable/apps)
|
||||
INSTALL(FILES ${oracle_QM} DESTINATION share/oracle/translations)
|
||||
endif()
|
||||
elseif(WIN32)
|
||||
INSTALL(TARGETS oracle RUNTIME DESTINATION ./)
|
||||
INSTALL(FILES ${oracle_QM} DESTINATION ./translations)
|
||||
endif()
|
||||
|
||||
IF (NOT WIN32 AND NOT APPLE)
|
||||
|
@ -150,9 +154,8 @@ if(APPLE)
|
|||
# these needs to be relative to CMAKE_INSTALL_PREFIX
|
||||
set(plugin_dest_dir oracle.app/Contents/Plugins)
|
||||
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
|
||||
FILES_MATCHING
|
||||
PATTERN "*.dSYM" EXCLUDE
|
||||
|
@ -160,6 +163,7 @@ if(APPLE)
|
|||
PATTERN "iconengines/*.dylib"
|
||||
PATTERN "platforms/*.dylib"
|
||||
PATTERN "styles/*.dylib"
|
||||
PATTERN "tls/*.dylib"
|
||||
)
|
||||
|
||||
install(CODE "
|
||||
|
@ -177,7 +181,7 @@ Translations = Resources/translations\")
|
|||
" COMPONENT Runtime)
|
||||
endif()
|
||||
|
||||
IF(WIN32)
|
||||
if(WIN32)
|
||||
# these needs to be relative to CMAKE_INSTALL_PREFIX
|
||||
set(plugin_dest_dir Plugins)
|
||||
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")
|
||||
|
||||
# qt5 plugins: iconengines, platforms
|
||||
|
||||
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime
|
||||
FILES_MATCHING REGEX "(iconengines|platforms|styles)/.*[^d]\\.dll")
|
||||
# Qt plugins: iconengines, platforms, styles, tls (Qt6)
|
||||
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime FILES_MATCHING
|
||||
PATTERN "iconengines/qsvgicon.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 "
|
||||
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}\")
|
||||
" COMPONENT Runtime)
|
||||
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();
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -62,10 +81,8 @@ int main(int argc, char *argv[])
|
|||
|
||||
QIcon icon("theme:appicon.svg");
|
||||
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
|
||||
QGuiApplication::setDesktopFileName("oracle");
|
||||
#endif
|
||||
|
||||
wizard.show();
|
||||
|
||||
|
|
|
@ -116,7 +116,7 @@ CardInfoPtr OracleImporter::addCard(QString name,
|
|||
QStringList symbols = manacost.split("}");
|
||||
QString formattedCardCost;
|
||||
for (QString symbol : symbols) {
|
||||
if (symbol.contains(QRegExp("[0-9WUBGRP]/[0-9WUBGRP]"))) {
|
||||
if (symbol.contains(QRegularExpression("[0-9WUBGRP]/[0-9WUBGRP]"))) {
|
||||
symbol.append("}");
|
||||
} else {
|
||||
symbol.remove(QChar('{'));
|
||||
|
|
|
@ -143,16 +143,19 @@ IntroPage::IntroPage(QWidget *parent) : OracleWizardPage(parent)
|
|||
languageLabel = new QLabel(this);
|
||||
versionLabel = new QLabel(this);
|
||||
languageBox = new QComboBox(this);
|
||||
QString setLanguage = SettingsCache::instance().getLang();
|
||||
|
||||
QStringList qmFiles = findQmFiles();
|
||||
for (int i = 0; i < qmFiles.size(); i++) {
|
||||
QString langName = languageName(qmFiles[i]);
|
||||
languageBox->addItem(langName, qmFiles[i]);
|
||||
if ((qmFiles[i] == setLanguage) ||
|
||||
(setLanguage.isEmpty() && langName == QCoreApplication::translate("i18n", DEFAULT_LANG_NAME))) {
|
||||
languageBox->setCurrentIndex(i);
|
||||
QStringList languageCodes = findQmFiles();
|
||||
for (const QString &code : languageCodes) {
|
||||
QString langName = languageName(code);
|
||||
languageBox->addItem(langName, code);
|
||||
}
|
||||
|
||||
QString setLanguage = QCoreApplication::translate("i18n", DEFAULT_LANG_NAME);
|
||||
int index = languageBox->findText(setLanguage, Qt::MatchExactly);
|
||||
if (index == -1) {
|
||||
qWarning() << "could not find language" << setLanguage;
|
||||
} else {
|
||||
languageBox->setCurrentIndex(index);
|
||||
}
|
||||
|
||||
connect(languageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(languageBoxChanged(int)));
|
||||
|
@ -170,15 +173,20 @@ QStringList IntroPage::findQmFiles()
|
|||
{
|
||||
QDir dir(translationPath);
|
||||
QStringList fileNames = dir.entryList(QStringList(translationPrefix + "_*.qm"), QDir::Files, QDir::Name);
|
||||
fileNames.replaceInStrings(QRegExp(translationPrefix + "_(.*)\\.qm"), "\\1");
|
||||
fileNames.removeOne("en@source");
|
||||
fileNames.replaceInStrings(QRegularExpression(translationPrefix + "_(.*)\\.qm"), "\\1");
|
||||
return fileNames;
|
||||
}
|
||||
|
||||
QString IntroPage::languageName(const QString &qmFile)
|
||||
QString IntroPage::languageName(const QString &lang)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -454,8 +462,10 @@ void LoadSetsPage::readSetsFromByteArray(QByteArray data)
|
|||
zipDownloadFailed(tr("Xz extraction failed."));
|
||||
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);
|
||||
return;
|
||||
#else
|
||||
|
@ -495,8 +505,10 @@ void LoadSetsPage::readSetsFromByteArray(QByteArray data)
|
|||
uz.closeArchive();
|
||||
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);
|
||||
return;
|
||||
#else
|
||||
|
@ -510,7 +522,7 @@ void LoadSetsPage::readSetsFromByteArray(QByteArray data)
|
|||
#endif
|
||||
}
|
||||
// Start the computation.
|
||||
future = QtConcurrent::run(wizard()->importer, &OracleImporter::readSetsFromByteArray, data);
|
||||
future = QtConcurrent::run([this, &data] { return wizard()->importer->readSetsFromByteArray(data); });
|
||||
watcher.setFuture(future);
|
||||
}
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ public:
|
|||
|
||||
private:
|
||||
QStringList findQmFiles();
|
||||
QString languageName(const QString &qmFile);
|
||||
QString languageName(const QString &lang);
|
||||
|
||||
private:
|
||||
QLabel *label, *languageLabel, *versionLabel;
|
||||
|
|
|
@ -31,12 +31,13 @@
|
|||
*/
|
||||
|
||||
#include "json.h"
|
||||
|
||||
#include <QMetaType>
|
||||
#include <iostream>
|
||||
|
||||
namespace QtJson
|
||||
{
|
||||
|
||||
|
||||
static QString sanitizeString(QString str)
|
||||
{
|
||||
str.replace(QLatin1String("\\"), QLatin1String("\\\\"));
|
||||
|
@ -52,10 +53,8 @@ static QString sanitizeString(QString str)
|
|||
static QByteArray join(const QList<QByteArray> &list, const QByteArray &sep)
|
||||
{
|
||||
QByteArray res;
|
||||
Q_FOREACH(const QByteArray &i, list)
|
||||
{
|
||||
if(!res.isEmpty())
|
||||
{
|
||||
Q_FOREACH (const QByteArray &i, list) {
|
||||
if (!res.isEmpty()) {
|
||||
res += sep;
|
||||
}
|
||||
res += i;
|
||||
|
@ -80,8 +79,7 @@ QVariant Json::parse(const QString &json, bool &success)
|
|||
success = true;
|
||||
|
||||
// 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;
|
||||
// We'll start from index 0
|
||||
int index = 0;
|
||||
|
@ -91,9 +89,7 @@ QVariant Json::parse(const QString &json, bool &success)
|
|||
|
||||
// Return the parsed value
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// Return the empty QVariant
|
||||
return QVariant();
|
||||
}
|
||||
|
@ -114,15 +110,18 @@ QByteArray Json::serialize(const QVariant &data, bool &success)
|
|||
{
|
||||
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)
|
||||
{
|
||||
Q_FOREACH (const QVariant &v, list) {
|
||||
QByteArray serializedValue = serialize(v);
|
||||
if(serializedValue.isNull())
|
||||
{
|
||||
if (serializedValue.isNull()) {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
|
@ -131,20 +130,22 @@ QByteArray Json::serialize(const QVariant &data, bool &success)
|
|||
|
||||
str = "[ " + join(values, ", ") + " ]";
|
||||
}
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
else if ((data.typeId() == QMetaType::Type::QVariantHash)) // variant is a list?
|
||||
#else
|
||||
else if (data.type() == QVariant::Hash) // variant is a hash?
|
||||
#endif
|
||||
{
|
||||
const QVariantHash vhash = data.toHash();
|
||||
QHashIterator<QString, QVariant> it(vhash);
|
||||
str = "{ ";
|
||||
QList<QByteArray> pairs;
|
||||
|
||||
while(it.hasNext())
|
||||
{
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
QByteArray serializedValue = serialize(it.value());
|
||||
|
||||
if(serializedValue.isNull())
|
||||
{
|
||||
if (serializedValue.isNull()) {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
|
@ -155,18 +156,20 @@ QByteArray Json::serialize(const QVariant &data, bool &success)
|
|||
str += join(pairs, ", ");
|
||||
str += " }";
|
||||
}
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
else if ((data.typeId() == QMetaType::Type::QVariantMap)) // variant is a list?
|
||||
#else
|
||||
else if (data.type() == QVariant::Map) // variant is a map?
|
||||
#endif
|
||||
{
|
||||
const QVariantMap vmap = data.toMap();
|
||||
QMapIterator<QString, QVariant> it(vmap);
|
||||
str = "{ ";
|
||||
QList<QByteArray> pairs;
|
||||
while(it.hasNext())
|
||||
{
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
QByteArray serializedValue = serialize(it.value());
|
||||
if(serializedValue.isNull())
|
||||
{
|
||||
if (serializedValue.isNull()) {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
|
@ -175,49 +178,56 @@ QByteArray Json::serialize(const QVariant &data, bool &success)
|
|||
str += join(pairs, ", ");
|
||||
str += " }";
|
||||
}
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
else if ((data.typeId() == QMetaType::Type::QString) ||
|
||||
(data.typeId() == QMetaType::Type::QByteArray)) // variant is a list?
|
||||
#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"))
|
||||
{
|
||||
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?
|
||||
} else if (data.canConvert<qlonglong>()) // any signed number?
|
||||
{
|
||||
str = QByteArray::number(data.value<qlonglong>());
|
||||
}
|
||||
else if (data.canConvert<long>())
|
||||
{
|
||||
} else if (data.canConvert<long>()) {
|
||||
str = QString::number(data.value<long>()).toUtf8();
|
||||
}
|
||||
else if (data.canConvert<QString>()) // can value be converted to string?
|
||||
} else if (data.canConvert<QString>()) // can value be converted to string?
|
||||
{
|
||||
// this will catch QDate, QDateTime, QUrl, ...
|
||||
str = sanitizeString(data.toString()).toUtf8();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
success = false;
|
||||
}
|
||||
if (success)
|
||||
{
|
||||
if (success) {
|
||||
return str;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
return QByteArray();
|
||||
}
|
||||
}
|
||||
|
@ -229,8 +239,7 @@ QVariant Json::parseValue(const QString &json, int &index, bool &success)
|
|||
{
|
||||
// Determine what kind of data we should parse by
|
||||
// checking out the upcoming token
|
||||
switch(Json::lookAhead(json, index))
|
||||
{
|
||||
switch (Json::lookAhead(json, index)) {
|
||||
case JsonTokenString:
|
||||
return Json::parseString(json, index, success);
|
||||
case JsonTokenNumber:
|
||||
|
@ -270,32 +279,23 @@ QVariant Json::parseObject(const QString &json, int &index, bool &success)
|
|||
|
||||
// Loop through all of the key/value pairs of the object
|
||||
bool done = false;
|
||||
while(!done)
|
||||
{
|
||||
while (!done) {
|
||||
// Get the upcoming token
|
||||
token = Json::lookAhead(json, index);
|
||||
|
||||
if(token == JsonTokenNone)
|
||||
{
|
||||
if (token == JsonTokenNone) {
|
||||
success = false;
|
||||
return QVariantMap();
|
||||
}
|
||||
else if(token == JsonTokenComma)
|
||||
{
|
||||
} else if (token == JsonTokenComma) {
|
||||
Json::nextToken(json, index);
|
||||
}
|
||||
else if(token == JsonTokenCurlyClose)
|
||||
{
|
||||
} else if (token == JsonTokenCurlyClose) {
|
||||
Json::nextToken(json, index);
|
||||
return map;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// Parse the key/value pair's name
|
||||
QString name = Json::parseString(json, index, success).toString();
|
||||
|
||||
if(!success)
|
||||
{
|
||||
if (!success) {
|
||||
return QVariantMap();
|
||||
}
|
||||
|
||||
|
@ -304,8 +304,7 @@ QVariant Json::parseObject(const QString &json, int &index, bool &success)
|
|||
|
||||
// If the next token is not a colon, flag the failure
|
||||
// return an empty QVariant
|
||||
if(token != JsonTokenColon)
|
||||
{
|
||||
if (token != JsonTokenColon) {
|
||||
success = false;
|
||||
return QVariant(QVariantMap());
|
||||
}
|
||||
|
@ -313,8 +312,7 @@ QVariant Json::parseObject(const QString &json, int &index, bool &success)
|
|||
// Parse the key/value pair's value
|
||||
QVariant value = Json::parseValue(json, index, success);
|
||||
|
||||
if(!success)
|
||||
{
|
||||
if (!success) {
|
||||
return QVariantMap();
|
||||
}
|
||||
|
||||
|
@ -337,30 +335,21 @@ QVariant Json::parseArray(const QString &json, int &index, bool &success)
|
|||
Json::nextToken(json, index);
|
||||
|
||||
bool done = false;
|
||||
while(!done)
|
||||
{
|
||||
while (!done) {
|
||||
int token = Json::lookAhead(json, index);
|
||||
|
||||
if(token == JsonTokenNone)
|
||||
{
|
||||
if (token == JsonTokenNone) {
|
||||
success = false;
|
||||
return QVariantList();
|
||||
}
|
||||
else if(token == JsonTokenComma)
|
||||
{
|
||||
} else if (token == JsonTokenComma) {
|
||||
Json::nextToken(json, index);
|
||||
}
|
||||
else if(token == JsonTokenSquaredClose)
|
||||
{
|
||||
} else if (token == JsonTokenSquaredClose) {
|
||||
Json::nextToken(json, index);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
QVariant value = Json::parseValue(json, index, success);
|
||||
|
||||
if(!success)
|
||||
{
|
||||
if (!success) {
|
||||
return QVariantList();
|
||||
}
|
||||
|
||||
|
@ -384,67 +373,43 @@ QVariant Json::parseString(const QString &json, int &index, bool &success)
|
|||
c = json[index++];
|
||||
|
||||
bool complete = false;
|
||||
while(!complete)
|
||||
{
|
||||
if(index == json.size())
|
||||
{
|
||||
while (!complete) {
|
||||
if (index == json.size()) {
|
||||
break;
|
||||
}
|
||||
|
||||
c = json[index++];
|
||||
|
||||
if(c == '\"')
|
||||
{
|
||||
if (c == '\"') {
|
||||
complete = true;
|
||||
break;
|
||||
}
|
||||
else if(c == '\\')
|
||||
{
|
||||
if(index == json.size())
|
||||
{
|
||||
} else if (c == '\\') {
|
||||
if (index == json.size()) {
|
||||
break;
|
||||
}
|
||||
|
||||
c = json[index++];
|
||||
|
||||
if(c == '\"')
|
||||
{
|
||||
if (c == '\"') {
|
||||
s.append('\"');
|
||||
}
|
||||
else if(c == '\\')
|
||||
{
|
||||
} else if (c == '\\') {
|
||||
s.append('\\');
|
||||
}
|
||||
else if(c == '/')
|
||||
{
|
||||
} else if (c == '/') {
|
||||
s.append('/');
|
||||
}
|
||||
else if(c == 'b')
|
||||
{
|
||||
} else if (c == 'b') {
|
||||
s.append('\b');
|
||||
}
|
||||
else if(c == 'f')
|
||||
{
|
||||
} else if (c == 'f') {
|
||||
s.append('\f');
|
||||
}
|
||||
else if(c == 'n')
|
||||
{
|
||||
} else if (c == 'n') {
|
||||
s.append('\n');
|
||||
}
|
||||
else if(c == 'r')
|
||||
{
|
||||
} else if (c == 'r') {
|
||||
s.append('\r');
|
||||
}
|
||||
else if(c == 't')
|
||||
{
|
||||
} else if (c == 't') {
|
||||
s.append('\t');
|
||||
}
|
||||
else if(c == 'u')
|
||||
{
|
||||
} else if (c == 'u') {
|
||||
int remainingLength = json.size() - index;
|
||||
|
||||
if(remainingLength >= 4)
|
||||
{
|
||||
if (remainingLength >= 4) {
|
||||
QString unicodeStr = json.mid(index, 4);
|
||||
|
||||
int symbol = unicodeStr.toInt(0, 16);
|
||||
|
@ -452,21 +417,16 @@ QVariant Json::parseString(const QString &json, int &index, bool &success)
|
|||
s.append(QChar(symbol));
|
||||
|
||||
index += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
s.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
if(!complete)
|
||||
{
|
||||
if (!complete) {
|
||||
success = false;
|
||||
return QVariant();
|
||||
}
|
||||
|
@ -506,10 +466,8 @@ int Json::lastIndexOfNumber(const QString &json, int index)
|
|||
static const QString numericCharacters("0123456789+-.eE");
|
||||
int lastIndex;
|
||||
|
||||
for(lastIndex = index; lastIndex < json.size(); lastIndex++)
|
||||
{
|
||||
if(numericCharacters.indexOf(json[lastIndex]) == -1)
|
||||
{
|
||||
for (lastIndex = index; lastIndex < json.size(); lastIndex++) {
|
||||
if (numericCharacters.indexOf(json[lastIndex]) == -1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -523,10 +481,8 @@ int Json::lastIndexOfNumber(const QString &json, int index)
|
|||
void Json::eatWhitespace(const QString &json, int &index)
|
||||
{
|
||||
static const QString whitespaceChars(" \t\n\r");
|
||||
for(; index < json.size(); index++)
|
||||
{
|
||||
if(whitespaceChars.indexOf(json[index]) == -1)
|
||||
{
|
||||
for (; index < json.size(); index++) {
|
||||
if (whitespaceChars.indexOf(json[index]) == -1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -548,25 +504,39 @@ int Json::nextToken(const QString &json, int &index)
|
|||
{
|
||||
Json::eatWhitespace(json, index);
|
||||
|
||||
if(index == json.size())
|
||||
{
|
||||
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;
|
||||
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--;
|
||||
|
@ -574,34 +544,25 @@ int Json::nextToken(const QString &json, int &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')
|
||||
{
|
||||
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')
|
||||
{
|
||||
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')
|
||||
{
|
||||
if (remainingLength >= 4) {
|
||||
if (json[index] == 'n' && json[index + 1] == 'u' && json[index + 2] == 'l' && json[index + 3] == 'l') {
|
||||
index += 4;
|
||||
return JsonTokenNull;
|
||||
}
|
||||
|
@ -610,5 +571,4 @@ int Json::nextToken(const QString &json, int &index)
|
|||
return JsonTokenNone;
|
||||
}
|
||||
|
||||
|
||||
} //end namespace
|
||||
} // namespace QtJson
|
||||
|
|
15
oracle/src/zip/unzip.h
Executable file → Normal file
15
oracle/src/zip/unzip.h
Executable file → Normal file
|
@ -33,14 +33,12 @@
|
|||
#include <QtCore/QDateTime>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QtGlobal>
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
class QDir;
|
||||
class QFile;
|
||||
class QIODevice;
|
||||
class QString;
|
||||
class QStringList;
|
||||
|
||||
OSDAB_BEGIN_NAMESPACE(Zip)
|
||||
|
||||
|
@ -68,7 +66,8 @@ public:
|
|||
InvalidArchive,
|
||||
HeaderConsistencyError,
|
||||
|
||||
Skip, SkipAll // internal use only
|
||||
Skip,
|
||||
SkipAll // internal use only
|
||||
};
|
||||
|
||||
enum ExtractionOption
|
||||
|
@ -82,12 +81,15 @@ public:
|
|||
|
||||
enum CompressionMethod
|
||||
{
|
||||
NoCompression, Deflated, UnknownCompression
|
||||
NoCompression,
|
||||
Deflated,
|
||||
UnknownCompression
|
||||
};
|
||||
|
||||
enum FileType
|
||||
{
|
||||
File, Directory
|
||||
File,
|
||||
Directory
|
||||
};
|
||||
|
||||
struct ZipEntry
|
||||
|
@ -136,7 +138,8 @@ public:
|
|||
ErrorCode extractFile(const QString &filename, const QDir &dir, 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
|
||||
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);
|
||||
|
|
6
oracle/src/zip/zipglobal.cpp
Executable file → Normal file
6
oracle/src/zip/zipglobal.cpp
Executable file → Normal file
|
@ -115,8 +115,8 @@ bool OSDAB_ZIP_MANGLE(setFileTimestamp)(const QString& fileName, const QDateTime
|
|||
return true;
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
HANDLE hFile = CreateFileW(fileName.toStdWString().c_str(),
|
||||
GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
|
||||
HANDLE hFile =
|
||||
CreateFileW(fileName.toStdWString().c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
|
||||
if (hFile == INVALID_HANDLE_VALUE) {
|
||||
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)
|
||||
|
||||
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;
|
||||
#endif
|
||||
|
||||
|
|
|
@ -41,11 +41,12 @@ if(APPLE)
|
|||
set(servatrice_SOURCES ${servatrice_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/resources/appicon.icns)
|
||||
ENDIF(APPLE)
|
||||
|
||||
# Qt5
|
||||
find_package(Qt5 COMPONENTS Network Sql WebSockets REQUIRED)
|
||||
set(SERVATRICE_QT_MODULES Qt5::Core Qt5::Network Qt5::Sql Qt5::WebSockets)
|
||||
IF(Qt6_FOUND)
|
||||
Qt6_ADD_RESOURCES(servatrice_RESOURCES_RCC ${servatrice_RESOURCES})
|
||||
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)
|
||||
|
||||
# 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")
|
||||
endif()
|
||||
|
||||
find_library(MYSQLCLIENT_LIBRARIES NAMES mysqlclient PATHS ${MYSQLCLIENT_DEFAULT_PATHS} PATH_SUFFIXES mysql mariadb)
|
||||
if(${MYSQLCLIENT_LIBRARIES} MATCHES "NOTFOUND")
|
||||
find_library(MYSQL_CLIENT_LIBRARIES NAMES mysqlclient PATHS ${MYSQLCLIENT_DEFAULT_PATHS} PATH_SUFFIXES mysql mariadb)
|
||||
if(${MYSQL_CLIENT_LIBRARIES} MATCHES "NOTFOUND")
|
||||
set(MYSQLCLIENT_FOUND FALSE CACHE INTERNAL "")
|
||||
MESSAGE(STATUS "Mysql connector NOT FOUND: servatrice won't be able to connect to a mysql server")
|
||||
unset(MYSQLCLIENT_LIBRARIES)
|
||||
MESSAGE(STATUS "MySQL connector NOT FOUND: Servatrice won't be able to connect to a MySQL server")
|
||||
unset(MYSQL_CLIENT_LIBRARIES)
|
||||
else()
|
||||
set(MYSQLCLIENT_FOUND TRUE CACHE INTERNAL "")
|
||||
get_filename_component(MYSQLCLIENT_LIBRARY_DIR ${MYSQLCLIENT_LIBRARIES} PATH)
|
||||
MESSAGE(STATUS "Mysql connector found at: ${MYSQLCLIENT_LIBRARY_DIR}")
|
||||
get_filename_component(MYSQLCLIENT_LIBRARY_DIR ${MYSQL_CLIENT_LIBRARIES} PATH)
|
||||
MESSAGE(STATUS "Found MySQL connector at: ${MYSQL_CLIENT_LIBRARIES}")
|
||||
endif()
|
||||
|
||||
# Declare path variables
|
||||
|
@ -83,9 +84,7 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
|
|||
# Build servatrice binary and link it
|
||||
ADD_EXECUTABLE(servatrice MACOSX_BUNDLE ${servatrice_SOURCES} ${servatrice_RESOURCES_RCC} ${servatrice_MOC_SRCS})
|
||||
|
||||
if(MSVC)
|
||||
TARGET_LINK_LIBRARIES(servatrice cockatrice_common Threads::Threads ${SERVATRICE_QT_MODULES} Qt5::WinMain)
|
||||
elseif(CMAKE_HOST_SYSTEM MATCHES "FreeBSD")
|
||||
if(CMAKE_HOST_SYSTEM MATCHES "FreeBSD")
|
||||
TARGET_LINK_LIBRARIES(servatrice cockatrice_common Threads::Threads ${SERVATRICE_QT_MODULES} ${LIBEXECINFO_LIBRARY})
|
||||
else()
|
||||
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
|
||||
set(plugin_dest_dir servatrice.app/Contents/Plugins)
|
||||
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
|
||||
FILES_MATCHING
|
||||
PATTERN "*.dSYM" EXCLUDE
|
||||
PATTERN "*_debug.dylib" EXCLUDE
|
||||
PATTERN "platforms/*.dylib"
|
||||
PATTERN "sqldrivers/libqsqlmysql*.dylib"
|
||||
PATTERN "tls/*.dylib"
|
||||
)
|
||||
|
||||
install(CODE "
|
||||
|
@ -157,10 +156,18 @@ if(WIN32)
|
|||
|
||||
install(DIRECTORY "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/${CMAKE_BUILD_TYPE}/" DESTINATION ./ FILES_MATCHING PATTERN "*.dll")
|
||||
|
||||
# qt5 plugins: platforms, sqldrivers/mysql
|
||||
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime
|
||||
FILES_MATCHING REGEX "(platforms/.*|sqldrivers/qsqlmysql)\\.dll"
|
||||
REGEX ".*d\\.dll" EXCLUDE)
|
||||
# Qt plugins: platforms, sqldrivers, tls (Qt6)
|
||||
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime FILES_MATCHING
|
||||
PATTERN "platforms/qdirect2d.dll"
|
||||
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 "
|
||||
file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf\" \"[Paths]
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
#include <QMetaType>
|
||||
#include <QTextCodec>
|
||||
#include <QtGlobal>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <iostream>
|
||||
|
||||
RNG_Abstract *rng;
|
||||
|
@ -70,17 +69,17 @@ void testRNG()
|
|||
}
|
||||
for (int i = 0; i <= maxMax - min; ++i) {
|
||||
std::cerr << (min + i);
|
||||
for (int j = 0; j < numbers.size(); ++j) {
|
||||
if (i < numbers[j].size())
|
||||
std::cerr << "\t" << numbers[j][i];
|
||||
for (auto &number : numbers) {
|
||||
if (i < number.size())
|
||||
std::cerr << "\t" << number[i];
|
||||
else
|
||||
std::cerr << "\t";
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
std::cerr << std::endl << "Chi^2 =";
|
||||
for (int j = 0; j < chisq.size(); ++j)
|
||||
std::cerr << "\t" << QString::number(chisq[j], 'f', 3).toStdString();
|
||||
for (double j : chisq)
|
||||
std::cerr << "\t" << QString::number(j, 'f', 3).toStdString();
|
||||
std::cerr << std::endl << "k =";
|
||||
for (int j = 0; j < chisq.size(); ++j)
|
||||
std::cerr << "\t" << (j - min + minMax);
|
||||
|
@ -112,9 +111,9 @@ void myMessageOutput2(QtMsgType /*type*/, const QMessageLogContext &, const QStr
|
|||
int main(int argc, char *argv[])
|
||||
{
|
||||
QCoreApplication app(argc, argv);
|
||||
app.setOrganizationName("Cockatrice");
|
||||
app.setApplicationName("Servatrice");
|
||||
app.setApplicationVersion(VERSION_STRING);
|
||||
QCoreApplication::setOrganizationName("Cockatrice");
|
||||
QCoreApplication::setApplicationName("Servatrice");
|
||||
QCoreApplication::setApplicationVersion(VERSION_STRING);
|
||||
|
||||
QCommandLineParser parser;
|
||||
parser.addHelpOption();
|
||||
|
@ -183,7 +182,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
smtpClient = new SmtpClient();
|
||||
|
||||
Servatrice *server = new Servatrice();
|
||||
auto *server = new Servatrice();
|
||||
QObject::connect(server, SIGNAL(destroyed()), &app, SLOT(quit()), Qt::QueuedConnection);
|
||||
int retval = 0;
|
||||
if (server->initServer()) {
|
||||
|
@ -192,7 +191,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
qInstallMessageHandler(myMessageOutput);
|
||||
|
||||
retval = app.exec();
|
||||
retval = QCoreApplication::exec();
|
||||
|
||||
std::cerr << "Server quit." << std::endl;
|
||||
std::cerr << "-------------------------" << std::endl;
|
||||
|
@ -210,5 +209,6 @@ int main(int argc, char *argv[])
|
|||
// Delete all global objects allocated by libprotobuf.
|
||||
google::protobuf::ShutdownProtobufLibrary();
|
||||
|
||||
QCoreApplication::quit();
|
||||
return retval;
|
||||
}
|
||||
|
|
|
@ -76,6 +76,7 @@ Servatrice_GameServer::~Servatrice_GameServer()
|
|||
QThread *poolThread = connectionPools[i]->thread();
|
||||
connectionPools[i]->deleteLater(); // pool destructor calls thread()->quit()
|
||||
poolThread->wait();
|
||||
poolThread->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,6 +85,7 @@ void Servatrice_GameServer::incomingConnection(qintptr socketDescriptor)
|
|||
Servatrice_ConnectionPool *pool = findLeastUsedConnectionPool();
|
||||
|
||||
auto ssi = new TcpServerSocketInterface(server, pool->getDatabaseInterface());
|
||||
connect(ssi, SIGNAL(incTxBytes), this, SLOT(incTxBytes));
|
||||
ssi->moveToThread(pool->thread());
|
||||
pool->addClient();
|
||||
connect(ssi, SIGNAL(destroyed()), pool, SLOT(removeClient()));
|
||||
|
@ -144,6 +146,7 @@ Servatrice_WebsocketGameServer::~Servatrice_WebsocketGameServer()
|
|||
QThread *poolThread = connectionPools[i]->thread();
|
||||
connectionPools[i]->deleteLater(); // pool destructor calls thread()->quit()
|
||||
poolThread->wait();
|
||||
poolThread->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,6 +155,7 @@ void Servatrice_WebsocketGameServer::onNewConnection()
|
|||
Servatrice_ConnectionPool *pool = findLeastUsedConnectionPool();
|
||||
|
||||
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.
|
||||
* 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)
|
||||
: Server(parent), authenticationMethod(AuthenticationNone), uptime(0), txBytes(0), rxBytes(0),
|
||||
shutdownTimer(nullptr), isFirstShutdownMessage(true)
|
||||
shutdownTimer(nullptr)
|
||||
{
|
||||
qRegisterMetaType<QSqlDatabase>("QSqlDatabase");
|
||||
}
|
||||
|
@ -204,21 +208,16 @@ Servatrice::~Servatrice()
|
|||
{
|
||||
gameServer->close();
|
||||
|
||||
// clients live in other threads, we need to lock them
|
||||
clientsLock.lockForRead();
|
||||
// we are destroying the clients outside their thread!
|
||||
for (auto *client : clients) {
|
||||
QMetaObject::invokeMethod(client, "prepareDestroy", Qt::QueuedConnection);
|
||||
}
|
||||
clientsLock.unlock();
|
||||
|
||||
// client destruction is asynchronous, wait for all clients to be gone
|
||||
for (;;) {
|
||||
QThread::usleep(10);
|
||||
QReadLocker locker(&clientsLock);
|
||||
if (clients.isEmpty())
|
||||
break;
|
||||
client->prepareDestroy();
|
||||
}
|
||||
|
||||
if (shutdownTimer) {
|
||||
shutdownTimer->deleteLater();
|
||||
}
|
||||
|
||||
servatriceDatabaseInterface->deleteLater();
|
||||
prepareDestroy();
|
||||
}
|
||||
|
||||
|
@ -559,7 +558,7 @@ void Servatrice::updateLoginMessage()
|
|||
}
|
||||
}
|
||||
|
||||
void Servatrice::setRequiredFeatures(const QString featureList)
|
||||
void Servatrice::setRequiredFeatures(const QString &featureList)
|
||||
{
|
||||
FeatureSet features;
|
||||
serverRequiredFeatureList.clear();
|
||||
|
@ -570,8 +569,9 @@ void Servatrice::setRequiredFeatures(const QString featureList)
|
|||
QStringList listReqFeatures = featureList.split(",", QString::SkipEmptyParts);
|
||||
#endif
|
||||
if (!listReqFeatures.isEmpty())
|
||||
foreach (QString reqFeature, listReqFeatures)
|
||||
for (const QString &reqFeature : listReqFeatures) {
|
||||
features.enableRequiredFeature(serverRequiredFeatureList, reqFeature);
|
||||
}
|
||||
|
||||
qDebug() << "Set required client features to:" << serverRequiredFeatureList;
|
||||
}
|
||||
|
@ -715,9 +715,10 @@ void Servatrice::shutdownTimeout()
|
|||
clientsLock.unlock();
|
||||
delete se;
|
||||
|
||||
if (!shutdownMinutes)
|
||||
if (!shutdownMinutes) {
|
||||
deleteLater();
|
||||
}
|
||||
}
|
||||
shutdownMinutes--;
|
||||
}
|
||||
|
||||
|
|
|
@ -96,9 +96,9 @@ private:
|
|||
public:
|
||||
Servatrice_IslServer(Servatrice *_server,
|
||||
const QSslCertificate &_cert,
|
||||
const QSslKey &_privateKey,
|
||||
QSslKey _privateKey,
|
||||
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();
|
||||
|
||||
protected:
|
||||
void doSendIslMessage(const IslMessage &msg, int serverId) override;
|
||||
void doSendIslMessage(const IslMessage &msg, int islServerId) override;
|
||||
|
||||
private:
|
||||
enum DatabaseType
|
||||
|
@ -160,7 +160,6 @@ private:
|
|||
mutable QMutex loginMessageMutex;
|
||||
QString loginMessage;
|
||||
QString dbPrefix;
|
||||
QString requiredFeatures;
|
||||
QMap<QString, bool> serverRequiredFeatureList;
|
||||
QString officialWarnings;
|
||||
Servatrice_DatabaseInterface *servatriceDatabaseInterface;
|
||||
|
@ -173,7 +172,6 @@ private:
|
|||
int shutdownMinutes;
|
||||
int nextShutdownMessageMinutes;
|
||||
QTimer *shutdownTimer;
|
||||
bool isFirstShutdownMessage;
|
||||
|
||||
mutable QMutex serverListMutex;
|
||||
QList<ServerProperties> serverList;
|
||||
|
@ -203,7 +201,7 @@ private:
|
|||
public slots:
|
||||
void scheduleShutdown(const QString &reason, int minutes);
|
||||
void updateLoginMessage();
|
||||
void setRequiredFeatures(QString featureList);
|
||||
void setRequiredFeatures(const QString &featureList);
|
||||
|
||||
public:
|
||||
explicit Servatrice(QObject *parent = nullptr);
|
||||
|
@ -213,10 +211,6 @@ public:
|
|||
{
|
||||
return serverRequiredFeatureList;
|
||||
}
|
||||
QString getOfficialWarningsList() const
|
||||
{
|
||||
return officialWarnings;
|
||||
}
|
||||
QString getServerName() const;
|
||||
QString getLoginMessage() const override
|
||||
{
|
||||
|
@ -282,9 +276,9 @@ public:
|
|||
void incRxBytes(quint64 num);
|
||||
void addDatabaseInterface(QThread *thread, Servatrice_DatabaseInterface *databaseInterface);
|
||||
|
||||
bool islConnectionExists(int serverId) const;
|
||||
void addIslInterface(int serverId, IslInterface *interface);
|
||||
void removeIslInterface(int serverId);
|
||||
bool islConnectionExists(int islServerId) const;
|
||||
void addIslInterface(int islServerId, IslInterface *interface);
|
||||
void removeIslInterface(int islServerId);
|
||||
QReadWriteLock islLock;
|
||||
|
||||
QList<ServerProperties> getServerList() const;
|
||||
|
|
|
@ -17,8 +17,8 @@ private:
|
|||
int clientCount;
|
||||
|
||||
public:
|
||||
Servatrice_ConnectionPool(Servatrice_DatabaseInterface *_databaseInterface);
|
||||
~Servatrice_ConnectionPool();
|
||||
explicit Servatrice_ConnectionPool(Servatrice_DatabaseInterface *_databaseInterface);
|
||||
~Servatrice_ConnectionPool() override;
|
||||
|
||||
Servatrice_DatabaseInterface *getDatabaseInterface() const
|
||||
{
|
||||
|
|
|
@ -113,12 +113,13 @@ bool Servatrice_DatabaseInterface::checkSql()
|
|||
|
||||
QSqlQuery *Servatrice_DatabaseInterface::prepareQuery(const QString &queryText)
|
||||
{
|
||||
if (preparedStatements.contains(queryText))
|
||||
if (preparedStatements.contains(queryText)) {
|
||||
return preparedStatements.value(queryText);
|
||||
}
|
||||
|
||||
QString prefixedQueryText = queryText;
|
||||
prefixedQueryText.replace("{prefix}", server->getDbPrefix());
|
||||
QSqlQuery *query = new QSqlQuery(sqlDatabase);
|
||||
auto *query = new QSqlQuery(sqlDatabase);
|
||||
query->prepare(prefixedQueryText);
|
||||
|
||||
preparedStatements.insert(queryText, query);
|
||||
|
|
|
@ -36,14 +36,14 @@ protected:
|
|||
const QString &clientId,
|
||||
QString &reasonStr,
|
||||
int &banSecondsLeft,
|
||||
bool passwordNeedsHash);
|
||||
bool passwordNeedsHash) override;
|
||||
|
||||
public slots:
|
||||
void initDatabase(const QSqlDatabase &_sqlDatabase);
|
||||
|
||||
public:
|
||||
Servatrice_DatabaseInterface(int _instanceId, Servatrice *_server);
|
||||
~Servatrice_DatabaseInterface();
|
||||
explicit Servatrice_DatabaseInterface(int _instanceId, Servatrice *_server);
|
||||
~Servatrice_DatabaseInterface() override;
|
||||
bool initDatabase(const QString &type,
|
||||
const QString &hostName,
|
||||
const QString &databaseName,
|
||||
|
@ -58,66 +58,66 @@ public:
|
|||
return sqlDatabase;
|
||||
}
|
||||
|
||||
bool activeUserExists(const QString &user);
|
||||
bool userExists(const QString &user);
|
||||
QString getUserSalt(const QString &user);
|
||||
bool activeUserExists(const QString &user) override;
|
||||
bool userExists(const QString &user) override;
|
||||
QString getUserSalt(const QString &user) override;
|
||||
int getUserIdInDB(const QString &name);
|
||||
QMap<QString, ServerInfo_User> getBuddyList(const QString &name);
|
||||
QMap<QString, ServerInfo_User> getIgnoreList(const QString &name);
|
||||
bool isInBuddyList(const QString &whoseList, const QString &who);
|
||||
bool isInIgnoreList(const QString &whoseList, const QString &who);
|
||||
ServerInfo_User getUserData(const QString &name, bool withId = false);
|
||||
QMap<QString, ServerInfo_User> getBuddyList(const QString &name) override;
|
||||
QMap<QString, ServerInfo_User> getIgnoreList(const QString &name) override;
|
||||
bool isInBuddyList(const QString &whoseList, const QString &who) override;
|
||||
bool isInIgnoreList(const QString &whoseList, const QString &who) override;
|
||||
ServerInfo_User getUserData(const QString &name, bool withId = false) override;
|
||||
void storeGameInformation(const QString &roomName,
|
||||
const QStringList &roomGameTypes,
|
||||
const ServerInfo_Game &gameInfo,
|
||||
const QSet<QString> &allPlayersEver,
|
||||
const QSet<QString> &allSpectatorsEver,
|
||||
const QList<GameReplay *> &replayList);
|
||||
DeckList *getDeckFromDatabase(int deckId, int userId);
|
||||
const QList<GameReplay *> &replayList) override;
|
||||
DeckList *getDeckFromDatabase(int deckId, int userId) override;
|
||||
|
||||
int getNextGameId();
|
||||
int getNextReplayId();
|
||||
int getActiveUserCount(QString connectionType = QString());
|
||||
int getNextGameId() override;
|
||||
int getNextReplayId() override;
|
||||
int getActiveUserCount(QString connectionType = QString()) override;
|
||||
|
||||
qint64 startSession(const QString &userName,
|
||||
const QString &address,
|
||||
const QString &clientId,
|
||||
const QString &connectionType);
|
||||
void endSession(qint64 sessionId);
|
||||
void clearSessionTables();
|
||||
void lockSessionTables();
|
||||
void unlockSessionTables();
|
||||
bool userSessionExists(const QString &userName);
|
||||
bool usernameIsValid(const QString &user, QString &error);
|
||||
const QString &connectionType) override;
|
||||
void endSession(qint64 sessionId) override;
|
||||
void clearSessionTables() override;
|
||||
void lockSessionTables() override;
|
||||
void unlockSessionTables() override;
|
||||
bool userSessionExists(const QString &userName) override;
|
||||
bool usernameIsValid(const QString &user, QString &error) override;
|
||||
bool checkUserIsBanned(const QString &ipAddress,
|
||||
const QString &userName,
|
||||
const QString &clientId,
|
||||
QString &banReason,
|
||||
int &banSecondsRemaining);
|
||||
int checkNumberOfUserAccounts(const QString &email);
|
||||
int &banSecondsRemaining) override;
|
||||
int checkNumberOfUserAccounts(const QString &email) override;
|
||||
bool registerUser(const QString &userName,
|
||||
const QString &realName,
|
||||
const QString &password,
|
||||
bool passwordNeedsHash,
|
||||
const QString &emailAddress,
|
||||
const QString &country,
|
||||
bool active = false);
|
||||
bool activateUser(const QString &userName, const QString &token);
|
||||
void updateUsersClientID(const QString &userName, const QString &userClientID);
|
||||
void updateUsersLastLoginData(const QString &userName, const QString &clientVersion);
|
||||
bool active = false) override;
|
||||
bool activateUser(const QString &userName, const QString &token) override;
|
||||
void updateUsersClientID(const QString &userName, const QString &userClientID) override;
|
||||
void updateUsersLastLoginData(const QString &userName, const QString &clientVersion) override;
|
||||
void logMessage(const int senderId,
|
||||
const QString &senderName,
|
||||
const QString &senderIp,
|
||||
const QString &logMessage,
|
||||
LogMessage_TargetType targetType,
|
||||
const int targetId,
|
||||
const QString &targetName);
|
||||
bool changeUserPassword(const QString &user, const QString &password, bool passwordNeedsHash);
|
||||
const QString &targetName) override;
|
||||
bool changeUserPassword(const QString &user, const QString &password, bool passwordNeedsHash) override;
|
||||
bool changeUserPassword(const QString &user,
|
||||
const QString &oldPassword,
|
||||
bool oldPasswordNeedsHash,
|
||||
const QString &newPassword,
|
||||
bool newPasswordNeedsHash);
|
||||
bool newPasswordNeedsHash) override;
|
||||
QList<ServerInfo_Ban> getUserBanHistory(const QString userName);
|
||||
bool
|
||||
addWarning(const QString userName, const QString adminName, const QString warningReason, const QString clientID);
|
||||
|
@ -133,7 +133,7 @@ public:
|
|||
int &range,
|
||||
int &maxresults);
|
||||
bool addForgotPassword(const QString &user);
|
||||
bool removeForgotPassword(const QString &user);
|
||||
bool removeForgotPassword(const QString &user) override;
|
||||
bool doesForgotPasswordExist(const QString &user);
|
||||
bool updateUserToken(const QString &token, const QString &user);
|
||||
bool validateTableColumnStringData(const QString &table,
|
||||
|
|
|
@ -45,7 +45,7 @@ void ServerLogger::startLog(const QString &logFileName)
|
|||
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)
|
||||
return;
|
||||
|
|
|
@ -18,7 +18,7 @@ public:
|
|||
~ServerLogger();
|
||||
public slots:
|
||||
void startLog(const QString &logFileName);
|
||||
void logMessage(QString message, void *caller = 0);
|
||||
void logMessage(const QString &message, void *caller = 0);
|
||||
void rotateLogs();
|
||||
private slots:
|
||||
void flushBuffer();
|
||||
|
|
|
@ -74,7 +74,6 @@
|
|||
#include <QSqlError>
|
||||
#include <QSqlQuery>
|
||||
#include <QString>
|
||||
#include <QtMath>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
|
@ -388,7 +387,7 @@ bool AbstractServerSocketInterface::deckListHelper(int folderId, ServerInfo_Deck
|
|||
newItem->set_name(query->value(1).toString().toStdString());
|
||||
|
||||
ServerInfo_DeckStorage_File *newFile = newItem->mutable_file();
|
||||
newFile->set_creation_time(query->value(2).toDateTime().toTime_t());
|
||||
newFile->set_creation_time(query->value(2).toDateTime().toSecsSinceEpoch());
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -551,7 +550,7 @@ Response::ResponseCode AbstractServerSocketInterface::cmdDeckUpload(const Comman
|
|||
ServerInfo_DeckStorage_TreeItem *fileInfo = re->mutable_new_file();
|
||||
fileInfo->set_id(query->lastInsertId().toInt());
|
||||
fileInfo->set_name(deckName.toStdString());
|
||||
fileInfo->mutable_file()->set_creation_time(QDateTime::currentDateTime().toTime_t());
|
||||
fileInfo->mutable_file()->set_creation_time(QDateTime::currentDateTime().toSecsSinceEpoch());
|
||||
rc.setResponseExtension(re);
|
||||
} else if (cmd.has_deck_id()) {
|
||||
QSqlQuery *query =
|
||||
|
@ -570,7 +569,7 @@ Response::ResponseCode AbstractServerSocketInterface::cmdDeckUpload(const Comman
|
|||
ServerInfo_DeckStorage_TreeItem *fileInfo = re->mutable_new_file();
|
||||
fileInfo->set_id(cmd.deck_id());
|
||||
fileInfo->set_name(deckName.toStdString());
|
||||
fileInfo->mutable_file()->set_creation_time(QDateTime::currentDateTime().toTime_t());
|
||||
fileInfo->mutable_file()->set_creation_time(QDateTime::currentDateTime().toSecsSinceEpoch());
|
||||
rc.setResponseExtension(re);
|
||||
} else
|
||||
return Response::RespInvalidData;
|
||||
|
@ -619,8 +618,8 @@ Response::ResponseCode AbstractServerSocketInterface::cmdReplayList(const Comman
|
|||
const int gameId = query1->value(0).toInt();
|
||||
matchInfo->set_game_id(gameId);
|
||||
matchInfo->set_room_name(query1->value(2).toString().toStdString());
|
||||
const int timeStarted = query1->value(3).toDateTime().toTime_t();
|
||||
const int timeFinished = query1->value(4).toDateTime().toTime_t();
|
||||
const int timeStarted = query1->value(3).toDateTime().toSecsSinceEpoch();
|
||||
const int timeFinished = query1->value(4).toDateTime().toSecsSinceEpoch();
|
||||
matchInfo->set_time_started(timeStarted);
|
||||
matchInfo->set_length(timeFinished - timeStarted);
|
||||
matchInfo->set_game_name(query1->value(5).toString().toStdString());
|
||||
|
@ -977,7 +976,7 @@ Response::ResponseCode AbstractServerSocketInterface::cmdBanFromServer(const Com
|
|||
if (cmd.has_visible_reason())
|
||||
event.set_reason_str(visibleReason.toStdString());
|
||||
if (minutes)
|
||||
event.set_end_time(QDateTime::currentDateTime().addSecs(60 * minutes).toTime_t());
|
||||
event.set_end_time(QDateTime::currentDateTime().addSecs(60 * minutes).toSecsSinceEpoch());
|
||||
for (int i = 0; i < userList.size(); ++i) {
|
||||
SessionEvent *se = userList[i]->prepareSessionEvent(event);
|
||||
userList[i]->sendProtocolItem(*se);
|
||||
|
@ -1148,7 +1147,7 @@ Response::ResponseCode AbstractServerSocketInterface::cmdRegisterAccount(const C
|
|||
Response_Register *re = new Response_Register;
|
||||
re->set_denied_reason_str(banReason.toStdString());
|
||||
if (banSecondsRemaining != 0)
|
||||
re->set_denied_end_time(QDateTime::currentDateTime().addSecs(banSecondsRemaining).toTime_t());
|
||||
re->set_denied_end_time(QDateTime::currentDateTime().addSecs(banSecondsRemaining).toSecsSinceEpoch());
|
||||
rc.setResponseExtension(re);
|
||||
return Response::RespUserIsBanned;
|
||||
}
|
||||
|
@ -1649,7 +1648,7 @@ bool AbstractServerSocketInterface::removeAdminFlagFromUser(const QString &userN
|
|||
Event_ConnectionClosed event;
|
||||
event.set_reason(Event_ConnectionClosed::DEMOTED);
|
||||
event.set_reason_str("Your moderator and/or judge status has been revoked.");
|
||||
event.set_end_time(QDateTime::currentDateTime().toTime_t());
|
||||
event.set_end_time(QDateTime::currentDateTime().toSecsSinceEpoch());
|
||||
|
||||
SessionEvent *se = user->prepareSessionEvent(event);
|
||||
user->sendProtocolItem(*se);
|
||||
|
@ -1765,7 +1764,7 @@ void TcpServerSocketInterface::flushOutputQueue()
|
|||
locker.relock();
|
||||
}
|
||||
locker.unlock();
|
||||
servatrice->incTxBytes(totalBytes);
|
||||
emit incTxBytes(totalBytes);
|
||||
// see above wrt mutex
|
||||
flushSocket();
|
||||
}
|
||||
|
@ -1859,7 +1858,7 @@ bool TcpServerSocketInterface::initTcpSession()
|
|||
WebsocketServerSocketInterface::WebsocketServerSocketInterface(Servatrice *_server,
|
||||
Servatrice_DatabaseInterface *_databaseInterface,
|
||||
QObject *parent)
|
||||
: AbstractServerSocketInterface(_server, _databaseInterface, parent)
|
||||
: AbstractServerSocketInterface(_server, _databaseInterface, parent), socket(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -1885,17 +1884,12 @@ void WebsocketServerSocketInterface::initConnection(void *_socket)
|
|||
address = socket->peerAddress();
|
||||
|
||||
QByteArray websocketIPHeader = settingsCache->value("server/web_socket_ip_header", "").toByteArray();
|
||||
if (websocketIPHeader.length() > 0) {
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
|
||||
if (socket->request().hasRawHeader(websocketIPHeader)) {
|
||||
if (websocketIPHeader.length() > 0 && socket->request().hasRawHeader(websocketIPHeader)) {
|
||||
QString header(socket->request().rawHeader(websocketIPHeader));
|
||||
QHostAddress parsed(header);
|
||||
if (!parsed.isNull())
|
||||
if (!parsed.isNull()) {
|
||||
address = parsed;
|
||||
}
|
||||
#else
|
||||
logger->logMessage(QString("Reading the websocket IP header is unsupported on this version of QT."));
|
||||
#endif
|
||||
}
|
||||
|
||||
connect(socket, SIGNAL(binaryMessageReceived(const QByteArray &)), this,
|
||||
|
@ -1905,7 +1899,7 @@ void WebsocketServerSocketInterface::initConnection(void *_socket)
|
|||
connect(socket, SIGNAL(disconnected()), this, SLOT(catchSocketDisconnected()));
|
||||
|
||||
// Add this object to the server's list of connections before it can receive socket events.
|
||||
// Otherwise, in case a of a socket error, it could be removed from the list before it is added.
|
||||
// Otherwise, in case of a socket error, it could be removed from the list before it is added.
|
||||
server->addClient(this);
|
||||
|
||||
logger->logMessage(
|
||||
|
@ -1949,7 +1943,7 @@ void WebsocketServerSocketInterface::flushOutputQueue()
|
|||
if (outputQueue.isEmpty())
|
||||
return;
|
||||
|
||||
int totalBytes = 0;
|
||||
qint64 totalBytes = 0;
|
||||
while (!outputQueue.isEmpty()) {
|
||||
ServerMessage item = outputQueue.takeFirst();
|
||||
locker.unlock();
|
||||
|
@ -1969,7 +1963,7 @@ void WebsocketServerSocketInterface::flushOutputQueue()
|
|||
locker.relock();
|
||||
}
|
||||
locker.unlock();
|
||||
servatrice->incTxBytes(totalBytes);
|
||||
emit incTxBytes(totalBytes);
|
||||
// see above wrt mutex
|
||||
flushSocket();
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue