mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-07-02 03:23:56 -07:00
Merge branch 'master' into 2474-server-status
This commit is contained in:
commit
894828962b
146 changed files with 18357 additions and 12225 deletions
|
|
@ -24,66 +24,25 @@ clone_depth: 50 #same as travis, see https://www.appveyor.com/blog/2014/06/04
|
||||||
image: Visual Studio 2017
|
image: Visual Studio 2017
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
- c:\openssl-release
|
- c:\Tools\vcpkg\installed
|
||||||
- c:\protobuf-release
|
|
||||||
- c:\zlib-release
|
|
||||||
# TODO: set dependency on ps skript file (in ./ci) / "-> appveyor.yml" maybe not ideal
|
|
||||||
# that way when we update specific cached tools there (like protobuf or zlib), cache will be newly created automatically
|
|
||||||
# https://www.appveyor.com/docs/build-cache/#cleaning-up-cache
|
|
||||||
|
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
openssl_ver: 1.0.2o
|
|
||||||
protobuf_ver: 3.6.0
|
|
||||||
zlib_ver: 1.2.11
|
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
- target_arch: win64
|
- target_arch: win64
|
||||||
qt_ver: 5.9\msvc2017_64
|
qt_ver: 5.9\msvc2017_64
|
||||||
cmake_generator: Visual Studio 15 2017 Win64
|
cmake_generator: Visual Studio 15 2017 Win64
|
||||||
cmake_toolset: v141,host=x64
|
cmake_toolset: v141,host=x64
|
||||||
vc_arch: amd64
|
vcpkg_arch: x64
|
||||||
|
|
||||||
- target_arch: win32
|
- target_arch: win32
|
||||||
qt_ver: 5.9\msvc2015 # Qt doesn't provide a msvc2017_32
|
qt_ver: 5.9\msvc2015 # Qt doesn't provide a msvc2017_32
|
||||||
cmake_generator: Visual Studio 15 2017
|
cmake_generator: Visual Studio 15 2017
|
||||||
cmake_toolset: v141
|
cmake_toolset: v141
|
||||||
vc_arch: amd64_x86
|
vcpkg_arch: x86
|
||||||
|
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- ps: |
|
- vcpkg remove --outdated --recurse
|
||||||
if (Test-Path c:\openssl-release) {
|
- vcpkg install openssl protobuf liblzma zlib --triplet %vcpkg_arch%-windows
|
||||||
echo "using openssl from cache"
|
|
||||||
} else {
|
|
||||||
if ($env:target_arch -eq "win64") { # 64bit filename
|
|
||||||
# echo "downloading 64bit version of openssl"
|
|
||||||
Invoke-WebRequest "https://indy.fulgan.com/SSL/openssl-$env:openssl_ver-x64_86-win64.zip" -OutFile c:\openssl-$env:openssl_ver.zip
|
|
||||||
} else { # 32bit filename
|
|
||||||
# echo "downloading 32bit version of openssl"
|
|
||||||
Invoke-WebRequest "https://indy.fulgan.com/SSL/openssl-$env:openssl_ver-i386-win32.zip" -OutFile c:\openssl-$env:openssl_ver.zip
|
|
||||||
}
|
|
||||||
Expand-Archive -Path c:\openssl-$env:openssl_ver.zip -DestinationPath c:\openssl-release
|
|
||||||
Set-Location -Path C:\openssl-release
|
|
||||||
}
|
|
||||||
if (Test-Path c:\protobuf-release) {
|
|
||||||
echo "using protobuf from cache"
|
|
||||||
} else {
|
|
||||||
Invoke-WebRequest "https://github.com/protocolbuffers/protobuf/releases/download/v$env:protobuf_ver/protobuf-cpp-$env:protobuf_ver.zip" -OutFile c:\protobuf-cpp-$env:protobuf_ver.zip
|
|
||||||
Expand-Archive -Path c:\protobuf-cpp-$env:protobuf_ver.zip -DestinationPath c:\
|
|
||||||
Set-Location -Path C:\protobuf-$env:protobuf_ver\cmake
|
|
||||||
cmake . -G "$env:cmake_generator" -T "$env:cmake_toolset" -Dprotobuf_BUILD_TESTS=0 -Dprotobuf_MSVC_STATIC_RUNTIME=0 -DCMAKE_INSTALL_PREFIX=c:/protobuf-release
|
|
||||||
msbuild INSTALL.vcxproj /p:Configuration=Release
|
|
||||||
}
|
|
||||||
if (Test-Path c:\zlib-release) {
|
|
||||||
echo "using zlib from cache"
|
|
||||||
} else {
|
|
||||||
Invoke-WebRequest "https://github.com/madler/zlib/archive/v$env:zlib_ver.zip" -OutFile c:\zlib-$env:zlib_ver.zip
|
|
||||||
Expand-Archive -Path c:\zlib-$env:zlib_ver.zip -DestinationPath c:\
|
|
||||||
Set-Location -Path C:\zlib-$env:zlib_ver
|
|
||||||
cmake . -G "$env:cmake_generator" -T "$env:cmake_toolset" -DCMAKE_INSTALL_PREFIX=c:/zlib-release
|
|
||||||
msbuild INSTALL.vcxproj /p:Configuration=Release
|
|
||||||
}
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
- mysql
|
- mysql
|
||||||
|
|
@ -92,13 +51,10 @@ build_script:
|
||||||
- ps: |
|
- ps: |
|
||||||
New-Item -ItemType directory -Path $env:APPVEYOR_BUILD_FOLDER\build
|
New-Item -ItemType directory -Path $env:APPVEYOR_BUILD_FOLDER\build
|
||||||
Set-Location -Path $env:APPVEYOR_BUILD_FOLDER\build
|
Set-Location -Path $env:APPVEYOR_BUILD_FOLDER\build
|
||||||
$zlibdir = "c:\zlib-release"
|
$vcpkgbindir = "C:\Tools\vcpkg\installed\$env:vcpkg_arch-windows\bin"
|
||||||
$openssldir = "C:\openssl-release"
|
|
||||||
$protodir = "c:\protobuf-release"
|
|
||||||
$protoc = "c:\protobuf-release\bin\protoc.exe"
|
|
||||||
$mysqldll = "c:\Program Files\MySQL\MySQL Server 5.7\lib\libmysql.dll"
|
$mysqldll = "c:\Program Files\MySQL\MySQL Server 5.7\lib\libmysql.dll"
|
||||||
cmake --version
|
cmake --version
|
||||||
cmake .. -G "$env:cmake_generator" -T "$env:cmake_toolset" "-DCMAKE_PREFIX_PATH=c:/Qt/$env:qt_ver;$protodir;$zlibdir;$openssldir" "-DWITH_SERVER=1" "-DPROTOBUF_PROTOC_EXECUTABLE=$protoc" "-DMYSQLCLIENT_LIBRARIES=$mysqldll"
|
cmake .. -G "$env:cmake_generator" -T "$env:cmake_toolset" "-DCMAKE_TOOLCHAIN_FILE=c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake" "-DCMAKE_PREFIX_PATH=c:/Qt/$env:qt_ver;$vcpkgbindir" "-DWITH_SERVER=1" "-DMYSQLCLIENT_LIBRARIES=$mysqldll"
|
||||||
- msbuild PACKAGE.vcxproj /p:Configuration=Release
|
- msbuild PACKAGE.vcxproj /p:Configuration=Release
|
||||||
- ps: |
|
- ps: |
|
||||||
$exe = dir -name *.exe
|
$exe = dir -name *.exe
|
||||||
|
|
@ -110,7 +66,7 @@ build_script:
|
||||||
(New-Object PSObject | Add-Member -PassThru NoteProperty bin $new_name | Add-Member -PassThru NoteProperty cmake $cmake_name | Add-Member -PassThru NoteProperty commit $env:APPVEYOR_REPO_COMMIT) | ConvertTo-JSON | Out-File -FilePath "latest-$env:target_arch" -Encoding ASCII
|
(New-Object PSObject | Add-Member -PassThru NoteProperty bin $new_name | Add-Member -PassThru NoteProperty cmake $cmake_name | Add-Member -PassThru NoteProperty commit $env:APPVEYOR_REPO_COMMIT) | ConvertTo-JSON | Out-File -FilePath "latest-$env:target_arch" -Encoding ASCII
|
||||||
Push-AppveyorArtifact "latest-$env:target_arch"
|
Push-AppveyorArtifact "latest-$env:target_arch"
|
||||||
$version = $matches['content']
|
$version = $matches['content']
|
||||||
|
|
||||||
test: off
|
test: off
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
19
.ci/Fedora29/Dockerfile
Normal file
19
.ci/Fedora29/Dockerfile
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
FROM fedora:29
|
||||||
|
|
||||||
|
RUN dnf install -y \
|
||||||
|
@development-tools \
|
||||||
|
ccache \
|
||||||
|
cmake \
|
||||||
|
desktop-file-utils \
|
||||||
|
file \
|
||||||
|
gcc-c++ \
|
||||||
|
hicolor-icon-theme \
|
||||||
|
libappstream-glib \
|
||||||
|
protobuf-devel \
|
||||||
|
qt5-{qttools,qtsvg,qtmultimedia,qtwebsockets}-devel-5.11.1-2.fc29 \
|
||||||
|
rpm-build \
|
||||||
|
sqlite-devel \
|
||||||
|
wget \
|
||||||
|
zlib-devel \
|
||||||
|
xz-devel \
|
||||||
|
&& dnf clean all
|
||||||
22
.ci/UbuntuBionic/Dockerfile
Normal file
22
.ci/UbuntuBionic/Dockerfile
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
FROM ubuntu:bionic
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
build-essential \
|
||||||
|
clang-format \
|
||||||
|
file \
|
||||||
|
g++ \
|
||||||
|
git \
|
||||||
|
ccache \
|
||||||
|
cmake \
|
||||||
|
liblzma-dev \
|
||||||
|
libprotobuf-dev \
|
||||||
|
libqt5multimedia5-plugins \
|
||||||
|
libqt5svg5-dev \
|
||||||
|
libqt5sql5-mysql \
|
||||||
|
libqt5websockets5-dev \
|
||||||
|
protobuf-compiler \
|
||||||
|
qt5-default \
|
||||||
|
qttools5-dev \
|
||||||
|
qttools5-dev-tools \
|
||||||
|
qtmultimedia5-dev \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
@ -1,59 +1,149 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
# This script is to be used in .travis.yaml from the project root directory, do not use it from somewhere else.
|
||||||
|
|
||||||
|
# Read arguments
|
||||||
|
while [[ "$@" ]]; do
|
||||||
|
case "$1" in
|
||||||
|
'--format')
|
||||||
|
CHECK_FORMAT=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
'--install')
|
||||||
|
MAKE_INSTALL=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
'--package')
|
||||||
|
MAKE_PACKAGE=1
|
||||||
|
shift
|
||||||
|
if [[ $# != 0 && $1 != -* ]]; then
|
||||||
|
PACKAGE_NAME="$1"
|
||||||
|
shift
|
||||||
|
if [[ $# != 0 && $1 != -* ]]; then
|
||||||
|
PACKAGE_TYPE="$1"
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
'--server')
|
||||||
|
MAKE_SERVER=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
'--test')
|
||||||
|
MAKE_TEST=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
'--debug')
|
||||||
|
BUILDTYPE="Debug"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
'--release')
|
||||||
|
BUILDTYPE="Release"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if [[ $1 == -* ]]; then
|
||||||
|
echo "unrecognized option: $1"
|
||||||
|
exit 3
|
||||||
|
fi
|
||||||
|
BUILDTYPE="$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Check formatting using clang-format
|
||||||
|
if [[ $CHECK_FORMAT ]]; then
|
||||||
|
echo "Checking your code using clang-format..."
|
||||||
|
diff="$(./clangify.sh --diff --cf-version)"
|
||||||
|
err=$?
|
||||||
|
case $err in
|
||||||
|
1)
|
||||||
|
cat <<EOM
|
||||||
|
***********************************************************
|
||||||
|
*** ***
|
||||||
|
*** Your code does not comply with our styleguide. ***
|
||||||
|
*** ***
|
||||||
|
*** Please correct it or run the "clangify.sh" script. ***
|
||||||
|
*** Then commit and push those changes to this branch. ***
|
||||||
|
*** Check our CONTRIBUTING.md file for more details. ***
|
||||||
|
*** ***
|
||||||
|
*** Thank you ♥ ***
|
||||||
|
*** ***
|
||||||
|
***********************************************************
|
||||||
|
|
||||||
|
Used clang-format version:
|
||||||
|
${diff%%
|
||||||
|
*}
|
||||||
|
|
||||||
|
The following changes should be made:
|
||||||
|
${diff#*
|
||||||
|
}
|
||||||
|
|
||||||
|
Exiting...
|
||||||
|
EOM
|
||||||
|
exit 2
|
||||||
|
;;
|
||||||
|
0)
|
||||||
|
echo "Thank you for complying with our code standards."
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Something went wrong in our formatting checks: clangify returned $err" >&2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
# Setup
|
||||||
./servatrice/check_schema_version.sh
|
./servatrice/check_schema_version.sh
|
||||||
|
|
||||||
mkdir -p build
|
mkdir -p build
|
||||||
cd build
|
cd build
|
||||||
prefix=""
|
|
||||||
|
|
||||||
if [[ $TRAVIS_OS_NAME == "osx" ]]; then
|
# Add cmake flags
|
||||||
export PATH="/usr/local/opt/ccache/bin:$PATH"
|
if [[ $MAKE_SERVER ]]; then
|
||||||
prefix="-DCMAKE_PREFIX_PATH=$(echo /usr/local/opt/qt5/)"
|
flags+=" -DWITH_SERVER=1"
|
||||||
fi
|
fi
|
||||||
if [[ $TRAVIS_OS_NAME == "linux" ]]; then
|
if [[ $MAKE_TEST ]]; then
|
||||||
prefix="-DCMAKE_PREFIX_PATH=$(echo /opt/qt5*/lib/cmake/)"
|
flags+=" -DTEST=1"
|
||||||
|
BUILDTYPE="Debug" # test requires buildtype Debug
|
||||||
|
fi
|
||||||
|
if [[ $BUILDTYPE ]]; then
|
||||||
|
flags+=" -DCMAKE_BUILD_TYPE=$BUILDTYPE"
|
||||||
|
fi
|
||||||
|
if [[ $PACKAGE_TYPE ]]; then
|
||||||
|
flags+=" -DCPACK_GENERATOR=$PACKAGE_TYPE"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Add qt install location when using brew
|
||||||
|
if [[ $(uname) == "Darwin" ]]; then
|
||||||
|
PATH="/usr/local/opt/ccache/bin:$PATH"
|
||||||
|
flags+=" -DCMAKE_PREFIX_PATH=/usr/local/opt/qt5/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Compile
|
||||||
cmake --version
|
cmake --version
|
||||||
|
cmake .. $flags
|
||||||
|
make -j2
|
||||||
|
|
||||||
if [[ $BUILDTYPE == "Debug" ]]; then
|
if [[ $MAKE_TEST ]]; then
|
||||||
cmake .. -DWITH_SERVER=1 -DCMAKE_BUILD_TYPE=$BUILDTYPE $prefix -DTEST=1
|
|
||||||
make -j2
|
|
||||||
make test
|
make test
|
||||||
|
|
||||||
if [[ $TRAVIS_OS_NAME == "osx" ]]; then
|
|
||||||
make install
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $TRAVIS_OS_NAME == "linux" ]]; then
|
|
||||||
cd ..
|
|
||||||
clang-format -version
|
|
||||||
clang-format -i \
|
|
||||||
common/*.h \
|
|
||||||
common/*.cpp \
|
|
||||||
cockatrice/src/*.h \
|
|
||||||
cockatrice/src/*.cpp \
|
|
||||||
oracle/src/*.h \
|
|
||||||
oracle/src/*.cpp \
|
|
||||||
servatrice/src/*.h \
|
|
||||||
servatrice/src/*.cpp
|
|
||||||
|
|
||||||
git clean -f
|
|
||||||
git diff --quiet || (
|
|
||||||
echo "*****************************************************";
|
|
||||||
echo "*** This PR is not clean against our code style ***";
|
|
||||||
echo "*** Run clang-format and fix up any differences ***";
|
|
||||||
echo "*** Check our CONTRIBUTING.md file for details! ***";
|
|
||||||
echo "*** Thank you ♥ ***";
|
|
||||||
echo "*****************************************************";
|
|
||||||
)
|
|
||||||
git diff --exit-code
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ $BUILDTYPE == "Release" ]]; then
|
if [[ $MAKE_INSTALL ]]; then
|
||||||
cmake .. -DWITH_SERVER=1 -DCMAKE_BUILD_TYPE=$BUILDTYPE $prefix
|
make install
|
||||||
make package -j2
|
fi
|
||||||
|
|
||||||
|
if [[ $MAKE_PACKAGE ]]; then
|
||||||
|
make package
|
||||||
|
if [[ $PACKAGE_NAME ]]; then
|
||||||
|
found=$(find . -maxdepth 1 -type f -name "Cockatrice-*.*" -print -quit)
|
||||||
|
path=${found%/*}
|
||||||
|
file=${found##*/}
|
||||||
|
if [[ ! $file ]]; then
|
||||||
|
echo "could not find package" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
mv "$path/$file" "$path/${file%.*}-$PACKAGE_NAME.${file##*.}"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
if [[ $TRAVIS_OS_NAME == "osx" ]] ; then
|
|
||||||
brew update
|
|
||||||
brew install ccache protobuf qt
|
|
||||||
fi
|
|
||||||
if [[ $TRAVIS_OS_NAME == "linux" ]] ; then
|
|
||||||
echo Skipping... packages are installed with the Travis apt addon for sudo disabled container builds
|
|
||||||
fi
|
|
||||||
119
.github/CONTRIBUTING.md
vendored
119
.github/CONTRIBUTING.md
vendored
|
|
@ -21,6 +21,20 @@ If you have any questions on IDEs, feel free to chat with us on [Gitter](https:/
|
||||||
|
|
||||||
# Code Style Guide #
|
# Code Style Guide #
|
||||||
|
|
||||||
|
### Formatting and continuous integration (ci) ###
|
||||||
|
|
||||||
|
We currently use Travis CI to check your code for formatting issues, if your pull request was rejected because of this it would show a message in the logs. Click on "Details" next to the failed Travis CI build and then click on the failed build (most likely the fastest one) to see the log.
|
||||||
|
|
||||||
|
The message will look somewhat similar to this:
|
||||||
|
```
|
||||||
|
************************************************************
|
||||||
|
*** Your code does not meet our formatting guidelines. ***
|
||||||
|
*** Please correct it then commit and push your changes. ***
|
||||||
|
*** See our CONTRIBUTING.md file for more information. ***
|
||||||
|
************************************************************
|
||||||
|
```
|
||||||
|
The CONTRIBUTING.md file mentioned is this file. Please read [this section](#Formatting) for full information on our formatting guidelines.
|
||||||
|
|
||||||
### Compatibility ###
|
### Compatibility ###
|
||||||
|
|
||||||
Cockatrice is currently compiled on all platforms using <kbd>C++11</kbd>. You'll notice <kbd>C++03</kbd> code throughout the codebase. Please feel free to help convert it over!
|
Cockatrice is currently compiled on all platforms using <kbd>C++11</kbd>. You'll notice <kbd>C++03</kbd> code throughout the codebase. Please feel free to help convert it over!
|
||||||
|
|
@ -28,7 +42,17 @@ Cockatrice is currently compiled on all platforms using <kbd>C++11</kbd>. You'll
|
||||||
For consistency, we use Qt data structures where possible. For example, `QString` over
|
For consistency, we use Qt data structures where possible. For example, `QString` over
|
||||||
`std::string` and `QList` over `std::vector`.
|
`std::string` and `QList` over `std::vector`.
|
||||||
|
|
||||||
### Header files ###
|
### Formatting ###
|
||||||
|
|
||||||
|
The handy tool `clang-format` can format your code for you, it is available for almost any environment. A special `.clang-format` configuration file is included in the project and is used to format your code.
|
||||||
|
|
||||||
|
We've also included a bash script, `clangify.sh`, that will use clang-format to format all files in one go. Use `./clangify.sh --help` to show a full help page.
|
||||||
|
|
||||||
|
To run clang-format on a single source file simply use the command `clang-format -i <filename>` to format it in place. (some systems install clang-format with a specific version number appended, `find /usr/bin -name clang-format*` should find it for you)
|
||||||
|
|
||||||
|
See [the clang-format documentation](https://clang.llvm.org/docs/ClangFormat.html) for more information about the tool.
|
||||||
|
|
||||||
|
#### Header files ####
|
||||||
|
|
||||||
Use header files with the extension `.h` and source files with the extension
|
Use header files with the extension `.h` and source files with the extension
|
||||||
`.cpp`.
|
`.cpp`.
|
||||||
|
|
@ -38,28 +62,28 @@ Use header guards in the form of `FILE_NAME_H`.
|
||||||
Simple functions, such as getters, may be written inline in the header file,
|
Simple functions, such as getters, may be written inline in the header file,
|
||||||
but other functions should be written in the source file.
|
but other functions should be written in the source file.
|
||||||
|
|
||||||
Keep library includes and project includes grouped together. So this is okay:
|
Group library includes after project includes, and in alphabetic order. Like this:
|
||||||
```c++
|
```c++
|
||||||
// Good
|
|
||||||
#include <QList>
|
|
||||||
#include <QString>
|
|
||||||
#include "card.h"
|
|
||||||
#include "deck.h"
|
|
||||||
|
|
||||||
// Good
|
// Good
|
||||||
#include "card.h"
|
#include "card.h"
|
||||||
#include "deck.h"
|
#include "deck.h"
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
// Bad:
|
// Bad
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include "card.h"
|
#include "card.h"
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include "deck.h"
|
#include "deck.h"
|
||||||
|
|
||||||
|
// Bad
|
||||||
|
#include "card.h"
|
||||||
|
#include "deck.h"
|
||||||
|
#include <QString>
|
||||||
|
#include <QList>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Naming ###
|
#### Naming ####
|
||||||
|
|
||||||
Use `UpperCamelCase` for classes, structs, enums, etc. and `lowerCamelCase` for
|
Use `UpperCamelCase` for classes, structs, enums, etc. and `lowerCamelCase` for
|
||||||
function and variable names.
|
function and variable names.
|
||||||
|
|
@ -89,16 +113,16 @@ Bar& bar2 = *bar1;
|
||||||
Use `nullptr` instead of `NULL` (or `0`) for null pointers.
|
Use `nullptr` instead of `NULL` (or `0`) for null pointers.
|
||||||
If you find any usage of the old keywords, we encourage you to fix it.
|
If you find any usage of the old keywords, we encourage you to fix it.
|
||||||
|
|
||||||
### Braces ###
|
#### Braces ####
|
||||||
|
|
||||||
Braces should go on their own line except for control statements, the use of braces around single line statements is preferred.
|
Braces should go on their own line except for control statements, the use of braces around single line statements is preferred.
|
||||||
See the following example:
|
See the following example:
|
||||||
```c++
|
```c++
|
||||||
int main()
|
int main()
|
||||||
{ // function or class: own line
|
{ // function or class: own line
|
||||||
if (someCondition) { // control statement: same line
|
if (someCondition) { // control statement: same line
|
||||||
doSomething(); // single line statement, braces preferred
|
doSomething(); // single line statement, braces preferred
|
||||||
} else if (someOtherCondition1) { // else goes after closing brace
|
} else if (someOtherCondition1) { // else goes on the same line as a closing brace
|
||||||
for (int i = 0; i < 100; i++) {
|
for (int i = 0; i < 100; i++) {
|
||||||
doSomethingElse();
|
doSomethingElse();
|
||||||
}
|
}
|
||||||
|
|
@ -110,20 +134,19 @@ int main()
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Indentation ###
|
#### Indentation and Spacing ####
|
||||||
|
|
||||||
Always indent using 4 spaces, do not use tabs. Opening and closing braces should be on the same indentation layer, member access specifiers in classes or structs should not be indented.
|
Always indent using 4 spaces, do not use tabs. Opening and closing braces should be on the same indentation layer, member access specifiers in classes or structs should not be indented.
|
||||||
|
|
||||||
### Lines ###
|
All operators and braces should be separated by spaces, do not add a space next to the inside of a brace.
|
||||||
|
|
||||||
Do not have trailing whitespace in your lines, if possible. Most IDEs check for this nowadays and clean it up for you.
|
If multiple lines of code that follow eachother have single line comments behind them, place all of them on the same indentation level. This indentation level should be equal to the longest line of code for each of these comments, without added spacing.
|
||||||
|
|
||||||
Lines should be 120 characters or less, but you can exceed this if you find it necessary.
|
#### Lines ####
|
||||||
|
|
||||||
### Automatic Formatting ###
|
Do not have trailing whitespace in your lines. Most IDEs check for this nowadays and clean it up for you.
|
||||||
|
|
||||||
The handy tool `clang-format` can format your code for you, a special `.clang-format` configuration file is included [here](https://github.com/Cockatrice/Cockatrice/blob/master/.clang-format).
|
Lines should be 120 characters or less. Please break up lines that are too long into smaller parts, for example at spaces or after opening a brace.
|
||||||
See [the clang-format documentation](https://clang.llvm.org/docs/ClangFormat.html) for more information.
|
|
||||||
|
|
||||||
### Memory Management ###
|
### Memory Management ###
|
||||||
|
|
||||||
|
|
@ -177,35 +200,32 @@ You can find more information on how we use Protobuf on [our wiki!](https://gith
|
||||||
|
|
||||||
# Translations #
|
# Translations #
|
||||||
|
|
||||||
**Basic workflow for translations:**
|
Basic workflow for translations:
|
||||||
1. Developer adds a `tr("foo")` string in the code;
|
1. Developer adds a `tr("foo")` string in the code;
|
||||||
2. Every few days, a maintainer updates the `*_en.ts files` with the new strings;
|
2. Every few days, a maintainer updates the `*_en.ts files` with the new strings;
|
||||||
3. Transifex picks up the new files from github every 24 hours;
|
3. Transifex picks up the new files from github every 24 hours;
|
||||||
4. Translators translate the new untraslated strings on Transifex;
|
4. Translators translate the new untranslated strings on Transifex;
|
||||||
5. Before a release, a maintainer fetches the updated translations from Transifex.
|
5. Before a release, a maintainer fetches the updated translations from Transifex.
|
||||||
|
|
||||||
### Translations (for developers) ###
|
### Using Translations (for developers) ###
|
||||||
|
|
||||||
**Step 1: Adding translatable strings to the code (`tr("foo")`)**
|
All the user-interface strings inside Cockatrice's source code must be written in english.
|
||||||
|
|
||||||
All the user-interface strings inside Cockatrice's source code must be written in
|
|
||||||
english language.<br>
|
|
||||||
Translations to other languages are managed using [Transifex](https://www.transifex.com/projects/p/cockatrice/).
|
Translations to other languages are managed using [Transifex](https://www.transifex.com/projects/p/cockatrice/).
|
||||||
|
|
||||||
If you're about to propose a change that adds or modifies any translatable string
|
Adding a new string to translate is as easy as adding the string in the 'tr("")' function, the string will be picked up as translatable automatically and translated as needed.
|
||||||
in the code, you don't need to take care of adding the new strings to the
|
For example setting the text of this label in a way that the string "My name is:" can be translated:
|
||||||
translation files. Every few days, or when a lot of new strings have been added,
|
```c++
|
||||||
someone from the development team will take care of extracing all the new strings,
|
nameLabel.setText(tr("My name is:"));
|
||||||
adding them to the english translation files and making them available to
|
```
|
||||||
translators on Transifex.
|
|
||||||
|
|
||||||
### Translations (for maintainers) ###
|
If you're about to propose a change that adds or modifies any translatable string in the code, you don't need to take care of adding the new strings to the translation files.
|
||||||
|
Every few days, or when a lot of new strings have been added, someone from the development team will take care of extracting all the new strings and adding them to the english translation files and making them available to translators on Transifex.
|
||||||
|
|
||||||
**Step 2: Updating `*_en.ts` files with new strings**
|
### Maintaining Translations (for maintainers) ###
|
||||||
|
|
||||||
When new translatable strings have been added to the code, it would be nice to
|
When new translatable strings have been added to the code, a maintainer should
|
||||||
make them available to translators on Transifex. Every few days, or when a lot
|
make them available to translators on Transifex. Every few days, or when a lot
|
||||||
of new strings have been added, a maintainer should take care of extracing all
|
of new strings have been added, a maintainer should take care of extracting all
|
||||||
the new strings and add them to the english translation files.
|
the new strings and add them to the english translation files.
|
||||||
|
|
||||||
To update the english translation files, re-run cmake enabling the appropriate
|
To update the english translation files, re-run cmake enabling the appropriate
|
||||||
|
|
@ -227,20 +247,18 @@ You should then notice that the following files have uncommitted changes:
|
||||||
cockatrice/translations/cockatrice_en.ts
|
cockatrice/translations/cockatrice_en.ts
|
||||||
oracle/translations/oracle_en.ts
|
oracle/translations/oracle_en.ts
|
||||||
|
|
||||||
It's now suggested to disable the parameter using:
|
It is recommended to disable the parameter afterwards using:
|
||||||
```sh
|
```sh
|
||||||
cmake .. -DUPDATE_TRANSLATIONS=OFF
|
cmake .. -DUPDATE_TRANSLATIONS=OFF
|
||||||
```
|
```
|
||||||
Now you are ready to propose your change.
|
Now you are ready to propose your change.
|
||||||
|
|
||||||
**Step 3: Automatic pushing to Transifex**
|
Once your change gets merged, Transifex will pick up the modified files automatically (checked every 24 hours)
|
||||||
|
|
||||||
Once your change gets merged, Transifex will pick up the modified files automatically (checks every 24 hours)
|
|
||||||
and update the interface where translators will be able to translate the new strings.
|
and update the interface where translators will be able to translate the new strings.
|
||||||
|
|
||||||
**Step 5: Fetching new translations from Transifex**
|
### Releasing Translations (for maintainers) ###
|
||||||
|
|
||||||
Before rushing out a new release, it would be nice to fetch the most up to date
|
Before rushing out a new release, a maintainer should fetch the most up to date
|
||||||
translations from Transifex and commit them into the Cockatrice source code.
|
translations from Transifex and commit them into the Cockatrice source code.
|
||||||
This can be done manually from the Transifex web interface, but it's quite time
|
This can be done manually from the Transifex web interface, but it's quite time
|
||||||
consuming.
|
consuming.
|
||||||
|
|
@ -252,10 +270,9 @@ As an alternative, you can install the Transifex CLI:
|
||||||
You'll then be able to use a git-like cli command to push and pull translations
|
You'll then be able to use a git-like cli command to push and pull translations
|
||||||
from Transifex to the source code and vice versa.
|
from Transifex to the source code and vice versa.
|
||||||
|
|
||||||
### Translations (for translators) ###
|
### Adding Translations (for translators) ###
|
||||||
|
|
||||||
**Step 4: Editing translations at Transifex**
|
|
||||||
|
|
||||||
|
As a translator you can help translate the new strings on [Transifex](https://www.transifex.com/projects/p/cockatrice/).
|
||||||
Please have a look at the specific [FAQ for translators](https://github.com/Cockatrice/Cockatrice/wiki/Translation-FAQ).
|
Please have a look at the specific [FAQ for translators](https://github.com/Cockatrice/Cockatrice/wiki/Translation-FAQ).
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -295,11 +312,11 @@ git tag -d $TAG_NAME
|
||||||
|
|
||||||
**NOTE:** Unfortunately, due to the method of how Travis and AppVeyor work, to publish a stable release you will need to make a copy of the release notes locally and then paste them into the GitHub GUI once the binaries have been uploaded by them. These CI services will automatically overwrite the name of the release (to "Cockatrice $TAG_NAME"), the status of the release (to "Pre-release"), and the release body (to "Beta build of Cockatrice").
|
**NOTE:** Unfortunately, due to the method of how Travis and AppVeyor work, to publish a stable release you will need to make a copy of the release notes locally and then paste them into the GitHub GUI once the binaries have been uploaded by them. These CI services will automatically overwrite the name of the release (to "Cockatrice $TAG_NAME"), the status of the release (to "Pre-release"), and the release body (to "Beta build of Cockatrice").
|
||||||
|
|
||||||
**NOTE 2:** In the first lines of https://github.com/Cockatrice/Cockatrice/blob/master/CMakeLists.txt there's an hardcoded version number used when compiling custom (not tagged) versions. While on tagged versions these numbers are overriden by the version numbers coming from the tag title, it's a good practice to keep them aligned with the real ones.
|
**NOTE 2:** In the first lines of https://github.com/Cockatrice/Cockatrice/blob/master/CMakeLists.txt there's an hardcoded version number used when compiling custom (not tagged) versions. While on tagged versions these numbers are overridden by the version numbers coming from the tag title, it's good practice to keep them aligned with the real ones.
|
||||||
The preferred flow of operations is:
|
The preferred flow of operation is:
|
||||||
* just before a release, update the version number in CMakeLists.txt to "next release version";
|
* just before a release, update the version number in CMakeLists.txt to "next release version";
|
||||||
* tag the release following the previously described syntax in order to get it built by CI;
|
* tag the release following the previously described syntax in order to get it built by CI;
|
||||||
* wait for CI to upload the binaries, double check if everything is in order
|
* wait for CI to upload the binaries, double check if everything is in order
|
||||||
* after the release is complete, update the version number again to "next targeted beta version", typically increasing `PROJECT_VERSION_PATCH` by one.
|
* after the release is complete, update the version number again to "next targeted beta version", typically increasing `PROJECT_VERSION_PATCH` by one.
|
||||||
|
|
||||||
**NOTE 3:** When releasing a new stable version, all the previous beta versions should be deleted. This is needed for Cockatrice to pick up the stable release also for users that chose the "beta" release channel.
|
**NOTE 3:** When releasing a new stable version, all the previous beta versions should be deleted. This is needed for Cockatrice to update users of the "beta" release channel to the latest version like other users.
|
||||||
|
|
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -7,3 +7,4 @@ mysql.cnf
|
||||||
.idea/
|
.idea/
|
||||||
*.aps
|
*.aps
|
||||||
cmake-build-debug/
|
cmake-build-debug/
|
||||||
|
preferences
|
||||||
|
|
|
||||||
132
.travis.yml
132
.travis.yml
|
|
@ -1,54 +1,114 @@
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
cache: ccache
|
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
#Ubuntu
|
#Ubuntu Xenial (Debug only)
|
||||||
- name: Ubuntu (Debug)
|
- name: Ubuntu Xenial (Debug)
|
||||||
if: tag IS NOT present
|
if: tag IS NOT present
|
||||||
os: linux
|
os: linux
|
||||||
dist: xenial
|
dist: xenial
|
||||||
group: stable
|
group: stable
|
||||||
env: BUILDTYPE=Debug
|
cache: ccache
|
||||||
- name: Ubuntu (Release)
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- libprotobuf-dev
|
||||||
|
- protobuf-compiler
|
||||||
|
- liblzma-dev
|
||||||
|
- qt5-default
|
||||||
|
- qttools5-dev
|
||||||
|
- qttools5-dev-tools
|
||||||
|
- qtmultimedia5-dev
|
||||||
|
- libqt5multimedia5-plugins
|
||||||
|
- libqt5svg5-dev
|
||||||
|
- libqt5sql5-mysql
|
||||||
|
- libqt5websockets5-dev
|
||||||
|
script: bash ./.ci/travis-compile.sh --format --server --test --debug
|
||||||
|
|
||||||
|
#Ubuntu Bionic (on docker)
|
||||||
|
- name: Ubuntu Bionic (Debug)
|
||||||
|
if: tag IS NOT present
|
||||||
|
services: docker
|
||||||
|
env: NAME=UbuntuBionic
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- $HOME/$NAME/
|
||||||
|
before_install: docker build -t "cockatrice_${NAME,,}" .ci/$NAME && mkdir -p $HOME/$NAME/.ccache
|
||||||
|
script: docker run --mount "type=bind,source=$(pwd),target=/src" -w="/src"
|
||||||
|
--mount "type=bind,source=$HOME/$NAME/.ccache,target=/.ccache" -e "CCACHE_DIR=/.ccache"
|
||||||
|
"cockatrice_${NAME,,}"
|
||||||
|
bash .ci/travis-compile.sh --server --debug
|
||||||
|
|
||||||
|
- name: Ubuntu Bionic (Release)
|
||||||
if: (branch = master AND NOT type = pull_request) OR tag IS present
|
if: (branch = master AND NOT type = pull_request) OR tag IS present
|
||||||
os: linux
|
services: docker
|
||||||
dist: xenial
|
env: NAME=UbuntuBionic
|
||||||
group: stable
|
cache:
|
||||||
env: BUILDTYPE=Release
|
directories:
|
||||||
|
- $HOME/$NAME/
|
||||||
|
before_install: docker build -t "cockatrice_${NAME,,}" .ci/$NAME && mkdir -p $HOME/$NAME/.ccache
|
||||||
|
script: docker run --mount "type=bind,source=$(pwd),target=/src" -w="/src"
|
||||||
|
--mount "type=bind,source=$HOME/$NAME/.ccache,target=/.ccache" -e "CCACHE_DIR=/.ccache"
|
||||||
|
"cockatrice_${NAME,,}"
|
||||||
|
bash .ci/travis-compile.sh --server --package "$NAME" --release
|
||||||
|
|
||||||
|
#Fedora 29 (on docker)
|
||||||
|
- name: Fedora 29 (Debug)
|
||||||
|
if: tag IS NOT present
|
||||||
|
services: docker
|
||||||
|
env: NAME=Fedora29
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- $HOME/$NAME/
|
||||||
|
before_install: docker build -t "cockatrice_${NAME,,}" .ci/$NAME && mkdir -p $HOME/$NAME/.ccache
|
||||||
|
script: docker run --mount "type=bind,source=$(pwd),target=/src" -w="/src"
|
||||||
|
--mount "type=bind,source=$HOME/$NAME/.ccache,target=/.ccache" -e "CCACHE_DIR=/.ccache"
|
||||||
|
"cockatrice_${NAME,,}"
|
||||||
|
bash .ci/travis-compile.sh --server --debug
|
||||||
|
|
||||||
|
- name: Fedora 29 (Release)
|
||||||
|
if: (branch = master AND NOT type = pull_request) OR tag IS present
|
||||||
|
services: docker
|
||||||
|
env: NAME=Fedora29
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- $HOME/$NAME/
|
||||||
|
before_install: docker build -t "cockatrice_${NAME,,}" .ci/$NAME && mkdir -p $HOME/$NAME/.ccache
|
||||||
|
script: docker run --mount "type=bind,source=$(pwd),target=/src" -w="/src"
|
||||||
|
--mount "type=bind,source=$HOME/$NAME/.ccache,target=/.ccache" -e "CCACHE_DIR=/.ccache"
|
||||||
|
"cockatrice_${NAME,,}"
|
||||||
|
bash .ci/travis-compile.sh --server --package "$NAME" "RPM" --release
|
||||||
|
|
||||||
#macOS
|
#macOS
|
||||||
- name: macOS (Debug)
|
- name: macOS (Debug)
|
||||||
if: tag IS NOT present
|
if: tag IS NOT present
|
||||||
os: osx
|
os: osx
|
||||||
osx_image: xcode8
|
osx_image: xcode10.1
|
||||||
env: BUILDTYPE=Debug
|
cache: ccache
|
||||||
|
addons:
|
||||||
|
homebrew:
|
||||||
|
packages:
|
||||||
|
- ccache
|
||||||
|
- protobuf
|
||||||
|
- qt
|
||||||
|
- xz
|
||||||
|
script: bash ./.ci/travis-compile.sh --server --install --debug
|
||||||
|
|
||||||
- name: macOS (Release)
|
- name: macOS (Release)
|
||||||
if: (branch = master AND NOT type = pull_request) OR tag IS present
|
if: (branch = master AND NOT type = pull_request) OR tag IS present
|
||||||
os: osx
|
os: osx
|
||||||
osx_image: xcode8
|
osx_image: xcode9.2
|
||||||
env: BUILDTYPE=Release
|
cache: ccache
|
||||||
|
addons:
|
||||||
#install dependencies for container-based "linux" builds
|
homebrew:
|
||||||
addons:
|
packages:
|
||||||
apt:
|
- ccache
|
||||||
packages:
|
- protobuf
|
||||||
- libprotobuf-dev
|
- qt
|
||||||
- protobuf-compiler
|
- xz
|
||||||
- qt5-default
|
update: true
|
||||||
- qttools5-dev
|
script: bash ./.ci/travis-compile.sh --server --package "$TRAVIS_OS_NAME" --release
|
||||||
- qttools5-dev-tools
|
|
||||||
- qtmultimedia5-dev
|
|
||||||
- libqt5multimedia5-plugins
|
|
||||||
- libqt5svg5-dev
|
|
||||||
- libqt5sql5-mysql
|
|
||||||
- libqt5websockets5-dev
|
|
||||||
|
|
||||||
|
|
||||||
before_install: bash ./.ci/travis-dependencies.sh
|
|
||||||
|
|
||||||
script: bash ./.ci/travis-compile.sh
|
|
||||||
|
|
||||||
|
|
||||||
# Builds for pull requests skip the deployment step altogether
|
# Builds for pull requests skip the deployment step altogether
|
||||||
deploy:
|
deploy:
|
||||||
|
|
@ -67,7 +127,7 @@ deploy:
|
||||||
on:
|
on:
|
||||||
tags: true
|
tags: true
|
||||||
repo: Cockatrice/Cockatrice
|
repo: Cockatrice/Cockatrice
|
||||||
condition: $BUILDTYPE = Release && $TRAVIS_TAG =~ ([0-9]|[1-9][0-9])(\.([0-9]|[1-9][0-9])){2}-beta(\.([2-9]|[1-9][0-9]))?$ # regex to match semver naming convention for beta pre-releases
|
condition: $TRAVIS_TAG =~ ([0-9]|[1-9][0-9])(\.([0-9]|[1-9][0-9])){2}-beta(\.([2-9]|[1-9][0-9]))?$ # regex to match semver naming convention for beta pre-releases
|
||||||
|
|
||||||
# Deploy configuration for "stable" releases
|
# Deploy configuration for "stable" releases
|
||||||
- provider: releases
|
- provider: releases
|
||||||
|
|
@ -82,7 +142,7 @@ deploy:
|
||||||
on:
|
on:
|
||||||
tags: true
|
tags: true
|
||||||
repo: Cockatrice/Cockatrice
|
repo: Cockatrice/Cockatrice
|
||||||
condition: $BUILDTYPE = Release && $TRAVIS_TAG =~ ([0-9]|[1-9][0-9])(\.([0-9]|[1-9][0-9])){2}$ # regex to match semver naming convention for stable full releases
|
condition: $TRAVIS_TAG =~ ([0-9]|[1-9][0-9])(\.([0-9]|[1-9][0-9])){2}$ # regex to match semver naming convention for stable full releases
|
||||||
|
|
||||||
|
|
||||||
notifications:
|
notifications:
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ endif()
|
||||||
|
|
||||||
# A project name is needed for CPack
|
# A project name is needed for CPack
|
||||||
# Version can be overriden by git tags, see cmake/getversion.cmake
|
# Version can be overriden by git tags, see cmake/getversion.cmake
|
||||||
PROJECT("Cockatrice" VERSION 2.6.1)
|
PROJECT("Cockatrice" VERSION 2.6.3)
|
||||||
|
|
||||||
# Use c++11 for all targets
|
# Use c++11 for all targets
|
||||||
set(CMAKE_CXX_STANDARD 11 CACHE STRING "C++ ISO Standard")
|
set(CMAKE_CXX_STANDARD 11 CACHE STRING "C++ ISO Standard")
|
||||||
|
|
@ -99,7 +99,8 @@ option(WARNING_AS_ERROR "Treat warnings as errors in debug builds" ON)
|
||||||
IF(MSVC)
|
IF(MSVC)
|
||||||
# Visual Studio:
|
# Visual Studio:
|
||||||
# Maximum optimization
|
# Maximum optimization
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "/Ox /MD")
|
# Disable warning C4251
|
||||||
|
set(CMAKE_CXX_FLAGS_RELEASE "/Ox /MD /wd4251")
|
||||||
# Generate complete debugging information
|
# Generate complete debugging information
|
||||||
#set(CMAKE_CXX_FLAGS_DEBUG "/Zi")
|
#set(CMAKE_CXX_FLAGS_DEBUG "/Zi")
|
||||||
ELSEIF (CMAKE_COMPILER_IS_GNUCXX)
|
ELSEIF (CMAKE_COMPILER_IS_GNUCXX)
|
||||||
|
|
@ -171,7 +172,7 @@ IF(MSVC)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
# Package builder
|
# Package builder
|
||||||
set(CPACK_PACKAGE_CONTACT "Gavin Bisesi <Daenyth+github@gmail.com>")
|
set(CPACK_PACKAGE_CONTACT "Zach Halpern <zahalpern+github@gmail.com>")
|
||||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY ${PROJECT_NAME})
|
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY ${PROJECT_NAME})
|
||||||
set(CPACK_PACKAGE_VENDOR "Cockatrice Development Team")
|
set(CPACK_PACKAGE_VENDOR "Cockatrice Development Team")
|
||||||
set(CPACK_PACKAGE_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/README.md")
|
set(CPACK_PACKAGE_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/README.md")
|
||||||
|
|
|
||||||
27
Dockerfile
27
Dockerfile
|
|
@ -1,30 +1,21 @@
|
||||||
FROM ubuntu:trusty
|
FROM ubuntu:bionic
|
||||||
MAINTAINER Gavin Bisesi <Daenyth@gmail.com>
|
MAINTAINER Zach Halpern <zahalpern+github@gmail.com>
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y software-properties-common
|
|
||||||
RUN apt-add-repository ppa:ubuntu-sdk-team/ppa
|
|
||||||
RUN add-apt-repository -y ppa:smspillaz/cmake-master
|
|
||||||
RUN apt-get update && apt-get install -y\
|
RUN apt-get update && apt-get install -y\
|
||||||
build-essential g++\
|
build-essential\
|
||||||
cmake\
|
cmake\
|
||||||
git\
|
git\
|
||||||
libprotobuf-dev\
|
libprotobuf-dev\
|
||||||
|
libqt5sql5-mysql\
|
||||||
|
libqt5websockets5-dev\
|
||||||
protobuf-compiler\
|
protobuf-compiler\
|
||||||
qt5-default\
|
qt5-default\
|
||||||
qtbase5-dev\
|
qtbase5-dev\
|
||||||
qttools5-dev-tools\
|
qttools5-dev-tools\
|
||||||
qttools5-dev\
|
qttools5-dev
|
||||||
libqt5sql5-mysql
|
|
||||||
|
|
||||||
ENV dir /home/servatrice/code
|
COPY . /home/servatrice/code/
|
||||||
WORKDIR $dir
|
WORKDIR /home/servatrice/code
|
||||||
RUN mkdir oracle
|
|
||||||
COPY LICENSE LICENSE
|
|
||||||
COPY CMakeLists.txt CMakeLists.txt
|
|
||||||
COPY cmake/ cmake/
|
|
||||||
COPY common/ common/
|
|
||||||
COPY servatrice/ servatrice/
|
|
||||||
COPY README.md README.md
|
|
||||||
|
|
||||||
WORKDIR build
|
WORKDIR build
|
||||||
RUN cmake .. -DWITH_SERVER=1 -DWITH_CLIENT=0 -DWITH_ORACLE=0 &&\
|
RUN cmake .. -DWITH_SERVER=1 -DWITH_CLIENT=0 -DWITH_ORACLE=0 &&\
|
||||||
|
|
@ -35,4 +26,4 @@ WORKDIR /home/servatrice
|
||||||
|
|
||||||
EXPOSE 4747
|
EXPOSE 4747
|
||||||
|
|
||||||
ENTRYPOINT [ "servatrice" ]
|
CMD [ "servatrice", "--log-to-console" ]
|
||||||
|
|
|
||||||
|
|
@ -82,13 +82,14 @@ Check out our [Translator FAQ](https://github.com/Cockatrice/Cockatrice/wiki/Tra
|
||||||
|
|
||||||
**Detailed compiling instructions are on the Cockatrice wiki under [Compiling Cockatrice](https://github.com/Cockatrice/Cockatrice/wiki/Compiling-Cockatrice)**
|
**Detailed compiling instructions are on the Cockatrice wiki under [Compiling Cockatrice](https://github.com/Cockatrice/Cockatrice/wiki/Compiling-Cockatrice)**
|
||||||
|
|
||||||
Dependencies:
|
Dependencies: *(for minimum requirements search our [CMake file](https://github.com/Cockatrice/Cockatrice/blob/master/CMakeLists.txt))*
|
||||||
- [Qt](https://www.qt.io/developers/)
|
- [Qt](https://www.qt.io/developers/)
|
||||||
- [protobuf](https://github.com/google/protobuf)
|
- [protobuf](https://github.com/google/protobuf)
|
||||||
- [CMake](https://www.cmake.org/)
|
- [CMake](https://www.cmake.org/)
|
||||||
|
|
||||||
Oracle can optionally use zlib to load zipped files:
|
Oracle can optionally use zlib and xz to load compressed files:
|
||||||
- [zlib](https://www.zlib.net/)
|
- [zlib](https://www.zlib.net/)
|
||||||
|
- [xz](https://tukaani.org/xz/)
|
||||||
|
|
||||||
To compile:
|
To compile:
|
||||||
|
|
||||||
|
|
|
||||||
217
clangify.sh
217
clangify.sh
|
|
@ -1,22 +1,209 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# This script will run clang-format on all modified, non-3rd-party C++/Header files.
|
# This script will run clang-format on all modified, non-3rd-party C++/Header files.
|
||||||
|
# Never, ever, should this recieve a path with a newline in it. Don't bother proofing it for that.
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
if hash clang-format 2>/dev/null && hash git 2>/dev/null; then
|
# go to the project root directory, this file should be located in the project root directory
|
||||||
files_to_clean=($(git diff --name-only $(git merge-base origin/master HEAD)))
|
cd "${BASH_SOURCE%/*}/" || exit 2 # could not find path, this could happen with special links etc.
|
||||||
|
|
||||||
printf "%s\n" ${files_to_clean[@]} | \
|
# defaults
|
||||||
xargs -I{} find '{}' \( -name "*.cpp" -o -name "*.h" \) \
|
include=("common" \
|
||||||
-not -path "./cockatrice/src/qt-json/*" \
|
"cockatrice/src" \
|
||||||
-not -path "./servatrice/src/smtp/*" \
|
"oracle/src" \
|
||||||
-not -path "./common/sfmt/*" \
|
"servatrice/src")
|
||||||
-not -path "./oracle/src/zip/*" \
|
exclude=("servatrice/src/smtp" \
|
||||||
-not -path "./build*/*" \
|
"common/sfmt" \
|
||||||
-exec clang-format -style=file -i {} \;
|
"common/lib" \
|
||||||
echo "Successfully formatted following files:"
|
"oracle/src/zip" \
|
||||||
printf "%s\n" ${files_to_clean[@]}
|
"oracle/src/lzma" \
|
||||||
else
|
"oracle/src/qt-json")
|
||||||
echo "Please install clang-format and git to use this program"
|
exts=("cpp" "h")
|
||||||
|
cf_cmd="clang-format"
|
||||||
|
branch="origin/master"
|
||||||
|
|
||||||
|
# parse options
|
||||||
|
while [[ $@ ]]; do
|
||||||
|
case "$1" in
|
||||||
|
'-b'|'--branch')
|
||||||
|
branch=$2
|
||||||
|
set_branch=1
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
'-c'|'--color-diff')
|
||||||
|
color=" --color=always"
|
||||||
|
mode=diff
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
'-d'|'--diff')
|
||||||
|
mode=diff
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
'-h'|'--help')
|
||||||
|
cat <<EOM
|
||||||
|
A bash script to automatically format your code using clang-format.
|
||||||
|
|
||||||
|
If no options are given, all dirty source files are edited in place.
|
||||||
|
If <dir>s are given, all source files in those directories of the project root
|
||||||
|
path are formatted. To only format changed files in these directories use the
|
||||||
|
--branch option in combination. <dir> has to be a path relative to the project
|
||||||
|
root path or a full path inside $PWD.
|
||||||
|
. can not be specified as a dir, if you really want to format everything use */.
|
||||||
|
|
||||||
|
USAGE: $0 [option] [--branch <git branch or object>] [<dir> ...]
|
||||||
|
|
||||||
|
DEFAULTS:
|
||||||
|
Current includes are:
|
||||||
|
${include[@]/%/
|
||||||
|
}
|
||||||
|
Default excludes are:
|
||||||
|
${exclude[@]/%/
|
||||||
|
}
|
||||||
|
OPTIONS:
|
||||||
|
-b, --branch <branch>
|
||||||
|
Compare to this git branch and format only files that differ.
|
||||||
|
If unspecified it defaults to origin/master.
|
||||||
|
To not compare to a branch this has to be explicitly set to "".
|
||||||
|
When not comparing to a branch, git will not be used at all and every
|
||||||
|
source file in the entire project will be parsed.
|
||||||
|
|
||||||
|
-c, --color-diff
|
||||||
|
Display a colored diff. Implies --diff.
|
||||||
|
Only available on systems which support 'diff --color'.
|
||||||
|
|
||||||
|
-d, --diff
|
||||||
|
Display a diff. Implies --test.
|
||||||
|
|
||||||
|
-h, --help
|
||||||
|
Display this message and exit.
|
||||||
|
|
||||||
|
-n, --names
|
||||||
|
Display a list of filenames that require formatting. Implies --test.
|
||||||
|
|
||||||
|
-t, --test
|
||||||
|
Do not edit files in place. Set exit code to 1 if changes are required.
|
||||||
|
|
||||||
|
--cf-version
|
||||||
|
Print the version of clang-format being used before continuing.
|
||||||
|
|
||||||
|
EXIT CODES:
|
||||||
|
0 on a successful format or if no files require formatting.
|
||||||
|
1 if a file requires formatting.
|
||||||
|
2 if given incorrect arguments.
|
||||||
|
3 if clang-format could not be found.
|
||||||
|
|
||||||
|
EXAMPLES:
|
||||||
|
$0 --test \$PWD || echo "code requires formatting"
|
||||||
|
Tests if the source files in the current directory are correctly
|
||||||
|
formatted and prints an error message if formatting is required.
|
||||||
|
|
||||||
|
$0 --branch $USER/patch-2 ${include[0]}
|
||||||
|
Formats all changed files compared to the git branch "$USER/patch-2"
|
||||||
|
in the directory ${include[0]}.
|
||||||
|
EOM
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
'-n'|'--names')
|
||||||
|
mode=name
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
'-t'|'--test')
|
||||||
|
mode=code
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
'--cf-version')
|
||||||
|
print_version=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
'--')
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if next_dir=$(cd "$1" && pwd); then
|
||||||
|
if [[ ${next_dir#$PWD/} == /* ]]; then
|
||||||
|
echo "error in parsing arguments of $0: $next_dir is not in $PWD" >&2
|
||||||
|
exit 2 # input error
|
||||||
|
elif ! [[ $set_include ]]; then
|
||||||
|
include=() # remove default includes
|
||||||
|
set_include=1
|
||||||
|
fi
|
||||||
|
include+=("${next_dir#$PWD/}")
|
||||||
|
else
|
||||||
|
echo "error in parsing arguments of $0: $PWD/$1 is not a directory" >&2
|
||||||
|
exit 2 # input error
|
||||||
|
fi
|
||||||
|
if ! [[ $set_branch ]]; then
|
||||||
|
unset branch # unset branch if not set explicitly
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# check availability of clang-format
|
||||||
|
if ! hash $cf_cmd 2>/dev/null; then
|
||||||
|
echo "could not find $cf_cmd" >&2
|
||||||
|
# find any clang-format-x.x in /usr/bin
|
||||||
|
cf_cmd=$(find /usr/bin -regex '.*/clang-format-[0-9]+\.[0-9]+' -print -quit)
|
||||||
|
if [[ $cf_cmd ]]; then
|
||||||
|
echo "found $cf_cmd instead" >&2
|
||||||
|
else
|
||||||
|
exit 3 # special exit code for missing dependency
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ $branch ]]; then
|
||||||
|
# get all dirty files through git
|
||||||
|
if ! base=$(git merge-base ${branch} HEAD); then
|
||||||
|
echo "could not find git merge base" >&2
|
||||||
|
exit 2 # input error
|
||||||
|
fi
|
||||||
|
declare -a reg
|
||||||
|
for ex in ${exts[@]}; do
|
||||||
|
reg+=(${include[@]/%/.*\\.$ex\$})
|
||||||
|
done
|
||||||
|
names=$(git diff --name-only $base | grep ${reg[@]/#/-e ^})
|
||||||
|
else
|
||||||
|
names=$(find ${include[@]} -type f -false ${exts[@]/#/-o -name *\\.})
|
||||||
|
fi
|
||||||
|
|
||||||
|
# filter excludes
|
||||||
|
names=$(<<<"$names" grep -v ${exclude[@]/#/-e ^})
|
||||||
|
|
||||||
|
if ! [[ $names ]]; then
|
||||||
|
exit 0 # nothing to format means format is successful!
|
||||||
|
fi
|
||||||
|
|
||||||
|
# optionally print version
|
||||||
|
[[ $print_version ]] && $cf_cmd -version
|
||||||
|
|
||||||
|
# format
|
||||||
|
case $mode in
|
||||||
|
diff)
|
||||||
|
declare -i code=0
|
||||||
|
for name in ${names[@]}; do
|
||||||
|
if ! $cf_cmd "$name" | diff "$name" - -p $color; then
|
||||||
|
code=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
exit $code
|
||||||
|
;;
|
||||||
|
name)
|
||||||
|
declare -i code=0
|
||||||
|
for name in ${names[@]}; do
|
||||||
|
if ! $cf_cmd "$name" | diff "$name" - -q >/dev/null; then
|
||||||
|
echo "$name"
|
||||||
|
code=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
exit $code
|
||||||
|
;;
|
||||||
|
code)
|
||||||
|
for name in ${names[@]}; do
|
||||||
|
$cf_cmd "$name" | diff "$name" - -q >/dev/null || exit 1
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
$cf_cmd -i $names
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
|
||||||
|
|
@ -1,36 +1,36 @@
|
||||||
# Find the MS Visual Studio VC redistributable package
|
# Find the MS Visual Studio VC redistributable package
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
set(VCREDISTRUNTIME_FOUND "NO")
|
set(VCREDISTRUNTIME_FOUND "NO")
|
||||||
|
|
||||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8) # 64-bit
|
if(CMAKE_SIZEOF_VOID_P EQUAL 8) # 64-bit
|
||||||
set(REDIST_ARCH x64)
|
set(REDIST_ARCH x64)
|
||||||
else()
|
else()
|
||||||
set(REDIST_ARCH x86)
|
set(REDIST_ARCH x86)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(REDIST_FILE vc_redist.${REDIST_ARCH}.exe)
|
set(REDIST_FILE vcredist_${REDIST_ARCH}.exe)
|
||||||
|
|
||||||
set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP TRUE)
|
set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP TRUE)
|
||||||
include(InstallRequiredSystemLibraries)
|
include(InstallRequiredSystemLibraries)
|
||||||
|
|
||||||
# Check if the list contains minimum one element, to get the path from
|
# Check if the list contains minimum one element, to get the path from
|
||||||
list(LENGTH CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS libsCount)
|
list(LENGTH CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS libsCount)
|
||||||
if (libsCount GREATER 0)
|
if (libsCount GREATER 0)
|
||||||
list(GET CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS 0 _path)
|
list(GET CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS 0 _path)
|
||||||
|
|
||||||
get_filename_component(_path ${_path} DIRECTORY)
|
get_filename_component(_path ${_path} DIRECTORY)
|
||||||
get_filename_component(_path ${_path}/../../ ABSOLUTE)
|
get_filename_component(_path ${_path}/../../ ABSOLUTE)
|
||||||
|
|
||||||
if (EXISTS "${_path}/${REDIST_FILE}") # VS 2017
|
if (EXISTS "${_path}/${REDIST_FILE}") # VS 2017
|
||||||
set(VCREDISTRUNTIME_FOUND "YES")
|
set(VCREDISTRUNTIME_FOUND "YES")
|
||||||
set(VCREDISTRUNTIME_FILE ${_path}/${REDIST_FILE})
|
set(VCREDISTRUNTIME_FILE ${_path}/${REDIST_FILE})
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(VCREDISTRUNTIME_FOUND)
|
if(VCREDISTRUNTIME_FOUND)
|
||||||
message(STATUS "Found VCredist ${VCREDISTRUNTIME_FILE}")
|
message(STATUS "Found VCredist ${VCREDISTRUNTIME_FILE}")
|
||||||
else()
|
else()
|
||||||
message(WARNING "Could not find VCredist package. It's not required for compiling, but needs to be available at runtime.")
|
message(WARNING "Could not find VCredist package. It's not required for compiling, but needs to be available at runtime.")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
|
||||||
|
|
@ -1,69 +1,71 @@
|
||||||
# Find the OpenSSL runtime libraries (.dll) for Windows that
|
# Find the OpenSSL runtime libraries (.dll) for Windows that
|
||||||
# will be needed by Qt in order to access https urls.
|
# will be needed by Qt in order to access https urls.
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
# Get standard installation paths for OpenSSL under Windows
|
# Get standard installation paths for OpenSSL under Windows
|
||||||
|
|
||||||
# http://www.slproweb.com/products/Win32OpenSSL.html
|
# http://www.slproweb.com/products/Win32OpenSSL.html
|
||||||
|
|
||||||
if( CMAKE_SIZEOF_VOID_P EQUAL 8 )
|
if( CMAKE_SIZEOF_VOID_P EQUAL 8 )
|
||||||
# target win64
|
# target win64
|
||||||
set(_OPENSSL_ROOT_HINTS
|
set(_OPENSSL_ROOT_HINTS
|
||||||
${OPENSSL_ROOT_DIR}
|
${OPENSSL_ROOT_DIR}
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (64-bit)_is1;Inno Setup: App Path]"
|
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (64-bit)_is1;Inno Setup: App Path]"
|
||||||
ENV OPENSSL_ROOT_DIR
|
ENV OPENSSL_ROOT_DIR
|
||||||
)
|
)
|
||||||
file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _programfiles)
|
file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _programfiles)
|
||||||
set(_OPENSSL_ROOT_PATHS
|
set(_OPENSSL_ROOT_PATHS
|
||||||
"${_programfiles}/OpenSSL-Win64"
|
"C:/Tools/vcpkg/installed/x64-windows/bin"
|
||||||
"C:/OpenSSL-Win64/"
|
"${_programfiles}/OpenSSL-Win64"
|
||||||
)
|
"C:/OpenSSL-Win64/"
|
||||||
unset(_programfiles)
|
)
|
||||||
else( CMAKE_SIZEOF_VOID_P EQUAL 8 )
|
unset(_programfiles)
|
||||||
# target win32
|
else( CMAKE_SIZEOF_VOID_P EQUAL 8 )
|
||||||
set(_OPENSSL_ROOT_HINTS
|
# target win32
|
||||||
${OPENSSL_ROOT_DIR}
|
set(_OPENSSL_ROOT_HINTS
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (32-bit)_is1;Inno Setup: App Path]"
|
${OPENSSL_ROOT_DIR}
|
||||||
ENV OPENSSL_ROOT_DIR
|
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (32-bit)_is1;Inno Setup: App Path]"
|
||||||
)
|
ENV OPENSSL_ROOT_DIR
|
||||||
file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _programfiles)
|
)
|
||||||
set(_OPENSSL_ROOT_PATHS
|
file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _programfiles)
|
||||||
"${_programfiles}/OpenSSL"
|
set(_OPENSSL_ROOT_PATHS
|
||||||
"${_programfiles}/OpenSSL-Win32"
|
"C:/Tools/vcpkg/installed/x86-windows/bin"
|
||||||
"C:/OpenSSL/"
|
"${_programfiles}/OpenSSL"
|
||||||
"C:/OpenSSL-Win32/"
|
"${_programfiles}/OpenSSL-Win32"
|
||||||
)
|
"C:/OpenSSL/"
|
||||||
unset(_programfiles)
|
"C:/OpenSSL-Win32/"
|
||||||
endif( CMAKE_SIZEOF_VOID_P EQUAL 8 )
|
)
|
||||||
|
unset(_programfiles)
|
||||||
else ()
|
endif( CMAKE_SIZEOF_VOID_P EQUAL 8 )
|
||||||
set(_OPENSSL_ROOT_HINTS
|
|
||||||
${OPENSSL_ROOT_DIR}
|
else ()
|
||||||
ENV OPENSSL_ROOT_DIR
|
set(_OPENSSL_ROOT_HINTS
|
||||||
)
|
${OPENSSL_ROOT_DIR}
|
||||||
endif ()
|
ENV OPENSSL_ROOT_DIR
|
||||||
|
)
|
||||||
set(_OPENSSL_ROOT_HINTS_AND_PATHS
|
endif ()
|
||||||
HINTS ${_OPENSSL_ROOT_HINTS}
|
|
||||||
PATHS ${_OPENSSL_ROOT_PATHS}
|
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
|
|
||||||
FIND_FILE(WIN32SSLRUNTIME_LIBEAY NAMES libeay32.dll libcrypto.dll ${_OPENSSL_ROOT_HINTS_AND_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
|
||||||
FIND_FILE(WIN32SSLRUNTIME_SSLEAY NAMES ssleay32.dll libssl.dll ${_OPENSSL_ROOT_HINTS_AND_PATHS})
|
# For OpenSSL >= 1.1, they are named libcrypto and libssl with no suffix
|
||||||
|
FIND_FILE(WIN32SSLRUNTIME_LIBEAY NAMES libeay32.dll libcrypto.dll ${_OPENSSL_ROOT_HINTS_AND_PATHS})
|
||||||
|
FIND_FILE(WIN32SSLRUNTIME_SSLEAY NAMES ssleay32.dll libssl.dll ${_OPENSSL_ROOT_HINTS_AND_PATHS})
|
||||||
IF(WIN32SSLRUNTIME_LIBEAY AND WIN32SSLRUNTIME_SSLEAY)
|
|
||||||
SET(WIN32SSLRUNTIME_LIBRARIES "${WIN32SSLRUNTIME_LIBEAY}" "${WIN32SSLRUNTIME_SSLEAY}")
|
|
||||||
SET(WIN32SSLRUNTIME_FOUND "YES")
|
IF(WIN32SSLRUNTIME_LIBEAY AND WIN32SSLRUNTIME_SSLEAY)
|
||||||
message(STATUS "Found OpenSSL ${WIN32SSLRUNTIME_LIBRARIES}")
|
SET(WIN32SSLRUNTIME_LIBRARIES "${WIN32SSLRUNTIME_LIBEAY}" "${WIN32SSLRUNTIME_SSLEAY}")
|
||||||
ELSE()
|
SET(WIN32SSLRUNTIME_FOUND "YES")
|
||||||
SET(WIN32SSLRUNTIME_FOUND "NO")
|
message(STATUS "Found OpenSSL ${WIN32SSLRUNTIME_LIBRARIES}")
|
||||||
message(WARNING "Could not find OpenSSL runtime libraries. They are not required for compiling, but needs to be available at runtime.")
|
ELSE()
|
||||||
ENDIF()
|
SET(WIN32SSLRUNTIME_FOUND "NO")
|
||||||
|
message(WARNING "Could not find OpenSSL runtime libraries. They are not required for compiling, but needs to be available at runtime.")
|
||||||
MARK_AS_ADVANCED(
|
ENDIF()
|
||||||
WIN32SSLRUNTIME_LIBEAY
|
|
||||||
WIN32SSLRUNTIME_SSLEAY
|
MARK_AS_ADVANCED(
|
||||||
)
|
WIN32SSLRUNTIME_LIBEAY
|
||||||
|
WIN32SSLRUNTIME_SSLEAY
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -34,5 +34,7 @@
|
||||||
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
|
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
|
||||||
<key>NSHighResolutionCapable</key>
|
<key>NSHighResolutionCapable</key>
|
||||||
<true/>
|
<true/>
|
||||||
|
<key>NSRequiresAquaSystemAppearance</key>
|
||||||
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|
|
||||||
|
|
@ -247,20 +247,20 @@ ${If} $PortableMode = 0
|
||||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "VersionMajor" "@CPACK_PACKAGE_VERSION_MAJOR@"
|
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "VersionMajor" "@CPACK_PACKAGE_VERSION_MAJOR@"
|
||||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "VersionMinor" "@CPACK_PACKAGE_VERSION_MINOR@"
|
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "VersionMinor" "@CPACK_PACKAGE_VERSION_MINOR@"
|
||||||
|
|
||||||
IfFileExists "$INSTDIR\vc_redist.x86.exe" VcRedist86Exists PastVcRedist86Check
|
IfFileExists "$INSTDIR\vcredist_x86.exe" VcRedist86Exists PastVcRedist86Check
|
||||||
VcRedist86Exists:
|
VcRedist86Exists:
|
||||||
ExecWait '"$INSTDIR\vc_redist.x86.exe" /passive /norestart'
|
ExecWait '"$INSTDIR\vcredist_x86.exe" /passive /norestart'
|
||||||
DetailPrint "Sleep to ensure unlock of vc_redist file after installation..."
|
DetailPrint "Sleep to ensure unlock of vc_redist file after installation..."
|
||||||
Sleep 3000
|
Sleep 3000
|
||||||
Delete "$INSTDIR\vc_redist.x86.exe"
|
Delete "$INSTDIR\vcredist_x86.exe"
|
||||||
PastVcRedist86Check:
|
PastVcRedist86Check:
|
||||||
|
|
||||||
IfFileExists "$INSTDIR\vc_redist.x64.exe" VcRedist64Exists PastVcRedist64Check
|
IfFileExists "$INSTDIR\vcredist_x64.exe" VcRedist64Exists PastVcRedist64Check
|
||||||
VcRedist64Exists:
|
VcRedist64Exists:
|
||||||
ExecWait '"$INSTDIR\vc_redist.x64.exe" /passive /norestart'
|
ExecWait '"$INSTDIR\vcredist_x64.exe" /passive /norestart'
|
||||||
DetailPrint "Sleep to ensure unlock of vc_redist file after installation..."
|
DetailPrint "Sleep to ensure unlock of vc_redist file after installation..."
|
||||||
Sleep 3000
|
Sleep 3000
|
||||||
Delete "$INSTDIR\vc_redist.x64.exe"
|
Delete "$INSTDIR\vcredist_x64.exe"
|
||||||
PastVcRedist64Check:
|
PastVcRedist64Check:
|
||||||
|
|
||||||
${Else}
|
${Else}
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,6 @@ SET(cockatrice_SOURCES
|
||||||
src/localserver.cpp
|
src/localserver.cpp
|
||||||
src/localserverinterface.cpp
|
src/localserverinterface.cpp
|
||||||
src/localclient.cpp
|
src/localclient.cpp
|
||||||
src/qt-json/json.cpp
|
|
||||||
src/soundengine.cpp
|
src/soundengine.cpp
|
||||||
src/pending_command.cpp
|
src/pending_command.cpp
|
||||||
src/pictureloader.cpp
|
src/pictureloader.cpp
|
||||||
|
|
@ -114,15 +113,18 @@ SET(cockatrice_SOURCES
|
||||||
src/settings/messagesettings.cpp
|
src/settings/messagesettings.cpp
|
||||||
src/settings/gamefilterssettings.cpp
|
src/settings/gamefilterssettings.cpp
|
||||||
src/settings/layoutssettings.cpp
|
src/settings/layoutssettings.cpp
|
||||||
|
src/settings/downloadsettings.cpp
|
||||||
src/update_downloader.cpp
|
src/update_downloader.cpp
|
||||||
src/logger.cpp
|
src/logger.cpp
|
||||||
src/releasechannel.cpp
|
src/releasechannel.cpp
|
||||||
src/userconnection_information.cpp
|
src/userconnection_information.cpp
|
||||||
src/spoilerbackgroundupdater.cpp
|
src/spoilerbackgroundupdater.cpp
|
||||||
src/handle_public_servers.cpp
|
src/handle_public_servers.cpp
|
||||||
|
src/carddbparser/carddatabaseparser.cpp
|
||||||
src/carddbparser/cockatricexml3.cpp
|
src/carddbparser/cockatricexml3.cpp
|
||||||
|
src/carddbparser/cockatricexml4.cpp
|
||||||
${VERSION_STRING_CPP}
|
${VERSION_STRING_CPP}
|
||||||
)
|
)
|
||||||
|
|
||||||
add_subdirectory(sounds)
|
add_subdirectory(sounds)
|
||||||
add_subdirectory(themes)
|
add_subdirectory(themes)
|
||||||
|
|
@ -149,8 +151,8 @@ if(APPLE)
|
||||||
ENDIF(APPLE)
|
ENDIF(APPLE)
|
||||||
|
|
||||||
# Qt5
|
# Qt5
|
||||||
find_package(Qt5 COMPONENTS Concurrent Multimedia Network PrintSupport Svg Widgets REQUIRED)
|
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)
|
set(COCKATRICE_QT_MODULES Qt5::Concurrent Qt5::Multimedia Qt5::Network Qt5::PrintSupport Qt5::Svg Qt5::Widgets Qt5::WebSockets)
|
||||||
|
|
||||||
# Qt5LinguistTools
|
# Qt5LinguistTools
|
||||||
find_package(Qt5LinguistTools)
|
find_package(Qt5LinguistTools)
|
||||||
|
|
@ -254,6 +256,8 @@ if(WIN32)
|
||||||
set(plugin_dest_dir Plugins)
|
set(plugin_dest_dir Plugins)
|
||||||
set(qtconf_dest_dir .)
|
set(qtconf_dest_dir .)
|
||||||
|
|
||||||
|
install(DIRECTORY "${CMAKE_BINARY_DIR}/${PROJECT_NAME}/${CMAKE_BUILD_TYPE}/" DESTINATION ./ FILES_MATCHING PATTERN "*.dll")
|
||||||
|
|
||||||
# qt5 plugins: audio, iconengines, imageformats, platforms, printsupport
|
# qt5 plugins: audio, iconengines, imageformats, platforms, printsupport
|
||||||
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime
|
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime
|
||||||
FILES_MATCHING REGEX "(audio|iconengines|imageformats|platforms|printsupport)/.*[^d]\\.dll")
|
FILES_MATCHING REGEX "(audio|iconengines|imageformats|platforms|printsupport)/.*[^d]\\.dll")
|
||||||
|
|
|
||||||
|
|
@ -351,6 +351,7 @@
|
||||||
<file>resources/tips/images/cockatrice_register.png</file>
|
<file>resources/tips/images/cockatrice_register.png</file>
|
||||||
<file>resources/tips/images/cockatrice_wiki.png</file>
|
<file>resources/tips/images/cockatrice_wiki.png</file>
|
||||||
<file>resources/tips/images/coin_flip.png</file>
|
<file>resources/tips/images/coin_flip.png</file>
|
||||||
|
<file>resources/tips/images/counter_expression.png</file>
|
||||||
<file>resources/tips/images/face_down.png</file>
|
<file>resources/tips/images/face_down.png</file>
|
||||||
<file>resources/tips/images/filter_games.png</file>
|
<file>resources/tips/images/filter_games.png</file>
|
||||||
<file>resources/tips/images/github_logo.png</file>
|
<file>resources/tips/images/github_logo.png</file>
|
||||||
|
|
|
||||||
BIN
cockatrice/resources/tips/images/counter_expression.png
Normal file
BIN
cockatrice/resources/tips/images/counter_expression.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 44 KiB |
|
|
@ -83,4 +83,10 @@
|
||||||
<image>face_down.png</image>
|
<image>face_down.png</image>
|
||||||
<date>2018-03-01</date>
|
<date>2018-03-01</date>
|
||||||
</tip>
|
</tip>
|
||||||
|
<tip>
|
||||||
|
<title>Counter expressions</title>
|
||||||
|
<text>When setting a counter value, you can type a math expression in the box and the counter will be set to the result.<br>The "x" variable contains the current counter value.</text>
|
||||||
|
<image>counter_expression.png</image>
|
||||||
|
<date>2019-02-02</date>
|
||||||
|
</tip>
|
||||||
</tips>
|
</tips>
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
#include "abstractcounter.h"
|
#include "abstractcounter.h"
|
||||||
|
#include "expression.h"
|
||||||
#include "pb/command_inc_counter.pb.h"
|
#include "pb/command_inc_counter.pb.h"
|
||||||
#include "pb/command_set_counter.pb.h"
|
#include "pb/command_set_counter.pb.h"
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "settingscache.h"
|
#include "settingscache.h"
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
|
#include <QApplication>
|
||||||
#include <QGraphicsSceneHoverEvent>
|
#include <QGraphicsSceneHoverEvent>
|
||||||
#include <QGraphicsSceneMouseEvent>
|
#include <QGraphicsSceneMouseEvent>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
|
|
@ -17,7 +19,7 @@ AbstractCounter::AbstractCounter(Player *_player,
|
||||||
bool _useNameForShortcut,
|
bool _useNameForShortcut,
|
||||||
QGraphicsItem *parent)
|
QGraphicsItem *parent)
|
||||||
: QGraphicsItem(parent), player(_player), id(_id), name(_name), value(_value),
|
: QGraphicsItem(parent), player(_player), id(_id), name(_name), value(_value),
|
||||||
useNameForShortcut(_useNameForShortcut), hovered(false), aDec(0), aInc(0), dialogSemaphore(false),
|
useNameForShortcut(_useNameForShortcut), hovered(false), aDec(nullptr), aInc(nullptr), dialogSemaphore(false),
|
||||||
deleteAfterDialog(false), shownInCounterArea(_shownInCounterArea)
|
deleteAfterDialog(false), shownInCounterArea(_shownInCounterArea)
|
||||||
{
|
{
|
||||||
setAcceptHoverEvents(true);
|
setAcceptHoverEvents(true);
|
||||||
|
|
@ -46,7 +48,7 @@ AbstractCounter::AbstractCounter(Player *_player,
|
||||||
} else
|
} else
|
||||||
menu = nullptr;
|
menu = nullptr;
|
||||||
|
|
||||||
connect(&settingsCache->shortcuts(), SIGNAL(shortCutchanged()), this, SLOT(refreshShortcuts()));
|
connect(&settingsCache->shortcuts(), SIGNAL(shortCutChanged()), this, SLOT(refreshShortcuts()));
|
||||||
refreshShortcuts();
|
refreshShortcuts();
|
||||||
retranslateUi();
|
retranslateUi();
|
||||||
}
|
}
|
||||||
|
|
@ -114,7 +116,11 @@ void AbstractCounter::setValue(int _value)
|
||||||
void AbstractCounter::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
void AbstractCounter::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||||
{
|
{
|
||||||
if (isUnderMouse() && player->getLocal()) {
|
if (isUnderMouse() && player->getLocal()) {
|
||||||
if (event->button() == Qt::LeftButton) {
|
if (event->button() == Qt::MidButton || (QApplication::keyboardModifiers() & Qt::ShiftModifier)) {
|
||||||
|
if (menu)
|
||||||
|
menu->exec(event->screenPos());
|
||||||
|
event->accept();
|
||||||
|
} else if (event->button() == Qt::LeftButton) {
|
||||||
Command_IncCounter cmd;
|
Command_IncCounter cmd;
|
||||||
cmd.set_counter_id(id);
|
cmd.set_counter_id(id);
|
||||||
cmd.set_delta(1);
|
cmd.set_delta(1);
|
||||||
|
|
@ -126,10 +132,6 @@ void AbstractCounter::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||||
cmd.set_delta(-1);
|
cmd.set_delta(-1);
|
||||||
player->sendGameCommand(cmd);
|
player->sendGameCommand(cmd);
|
||||||
event->accept();
|
event->accept();
|
||||||
} else if (event->button() == Qt::MidButton) {
|
|
||||||
if (menu)
|
|
||||||
menu->exec(event->screenPos());
|
|
||||||
event->accept();
|
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
event->ignore();
|
event->ignore();
|
||||||
|
|
@ -160,8 +162,12 @@ void AbstractCounter::setCounter()
|
||||||
{
|
{
|
||||||
bool ok;
|
bool ok;
|
||||||
dialogSemaphore = true;
|
dialogSemaphore = true;
|
||||||
int newValue = QInputDialog::getInt(0, tr("Set counter"), tr("New value for counter '%1':").arg(name), value,
|
QString expression = QInputDialog::getText(nullptr, tr("Set counter"), tr("New value for counter '%1':").arg(name),
|
||||||
-2000000000, 2000000000, 1, &ok);
|
QLineEdit::Normal, QString::number(value), &ok);
|
||||||
|
|
||||||
|
Expression exp(value);
|
||||||
|
int newValue = static_cast<int>(exp.parse(expression));
|
||||||
|
|
||||||
if (deleteAfterDialog) {
|
if (deleteAfterDialog) {
|
||||||
deleteLater();
|
deleteLater();
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ class AbstractCounter : public QObject, public QGraphicsItem
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_INTERFACES(QGraphicsItem)
|
Q_INTERFACES(QGraphicsItem)
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Player *player;
|
Player *player;
|
||||||
int id;
|
int id;
|
||||||
|
|
@ -18,15 +19,17 @@ protected:
|
||||||
int value;
|
int value;
|
||||||
bool useNameForShortcut, hovered;
|
bool useNameForShortcut, hovered;
|
||||||
|
|
||||||
void mousePressEvent(QGraphicsSceneMouseEvent *event);
|
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
|
||||||
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
|
void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;
|
||||||
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
|
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QAction *aSet, *aDec, *aInc;
|
QAction *aSet, *aDec, *aInc;
|
||||||
QMenu *menu;
|
QMenu *menu;
|
||||||
bool dialogSemaphore, deleteAfterDialog;
|
bool dialogSemaphore, deleteAfterDialog;
|
||||||
bool shownInCounterArea;
|
bool shownInCounterArea;
|
||||||
|
bool shortcutActive;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void refreshShortcuts();
|
void refreshShortcuts();
|
||||||
void incrementCounter();
|
void incrementCounter();
|
||||||
|
|
@ -39,14 +42,19 @@ public:
|
||||||
bool _shownInCounterArea,
|
bool _shownInCounterArea,
|
||||||
int _value,
|
int _value,
|
||||||
bool _useNameForShortcut = false,
|
bool _useNameForShortcut = false,
|
||||||
QGraphicsItem *parent = 0);
|
QGraphicsItem *parent = nullptr);
|
||||||
~AbstractCounter();
|
~AbstractCounter() override;
|
||||||
|
|
||||||
|
void retranslateUi();
|
||||||
|
void setValue(int _value);
|
||||||
|
void setShortcutsActive();
|
||||||
|
void setShortcutsInactive();
|
||||||
|
void delCounter();
|
||||||
|
|
||||||
QMenu *getMenu() const
|
QMenu *getMenu() const
|
||||||
{
|
{
|
||||||
return menu;
|
return menu;
|
||||||
}
|
}
|
||||||
void retranslateUi();
|
|
||||||
|
|
||||||
int getId() const
|
int getId() const
|
||||||
{
|
{
|
||||||
|
|
@ -64,12 +72,6 @@ public:
|
||||||
{
|
{
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
void setValue(int _value);
|
|
||||||
void delCounter();
|
|
||||||
|
|
||||||
void setShortcutsActive();
|
|
||||||
void setShortcutsInactive();
|
|
||||||
bool shortcutActive;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
#include "carddatabase.h"
|
#include "carddatabase.h"
|
||||||
#include "carddbparser/cockatricexml3.h"
|
#include "carddbparser/cockatricexml3.h"
|
||||||
|
#include "carddbparser/cockatricexml4.h"
|
||||||
|
#include "game_specific_terms.h"
|
||||||
#include "pictureloader.h"
|
#include "pictureloader.h"
|
||||||
#include "settingscache.h"
|
#include "settingscache.h"
|
||||||
#include "spoilerbackgroundupdater.h"
|
#include "spoilerbackgroundupdater.h"
|
||||||
|
|
@ -207,30 +209,23 @@ void SetList::guessSortKeys()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CardInfoPerSet::CardInfoPerSet(const CardSetPtr &_set) : set(_set)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
CardInfo::CardInfo(const QString &_name,
|
CardInfo::CardInfo(const QString &_name,
|
||||||
bool _isToken,
|
|
||||||
const QString &_manacost,
|
|
||||||
const QString &_cmc,
|
|
||||||
const QString &_cardtype,
|
|
||||||
const QString &_powtough,
|
|
||||||
const QString &_text,
|
const QString &_text,
|
||||||
const QStringList &_colors,
|
bool _isToken,
|
||||||
|
QVariantHash _properties,
|
||||||
const QList<CardRelation *> &_relatedCards,
|
const QList<CardRelation *> &_relatedCards,
|
||||||
const QList<CardRelation *> &_reverseRelatedCards,
|
const QList<CardRelation *> &_reverseRelatedCards,
|
||||||
bool _upsideDownArt,
|
CardInfoPerSetMap _sets,
|
||||||
const QString &_loyalty,
|
|
||||||
bool _cipt,
|
bool _cipt,
|
||||||
int _tableRow,
|
int _tableRow,
|
||||||
const SetList &_sets,
|
bool _upsideDownArt)
|
||||||
const QStringMap &_customPicURLs,
|
: name(_name), text(_text), isToken(_isToken), properties(std::move(_properties)), relatedCards(_relatedCards),
|
||||||
MuidMap _muIds,
|
reverseRelatedCards(_reverseRelatedCards), sets(std::move(_sets)), cipt(_cipt), tableRow(_tableRow),
|
||||||
QStringMap _collectorNumbers,
|
upsideDownArt(_upsideDownArt)
|
||||||
QStringMap _rarities)
|
|
||||||
: name(_name), isToken(_isToken), sets(_sets), manacost(_manacost), cmc(_cmc), cardtype(_cardtype),
|
|
||||||
powtough(_powtough), text(_text), colors(_colors), relatedCards(_relatedCards),
|
|
||||||
reverseRelatedCards(_reverseRelatedCards), setsNames(), upsideDownArt(_upsideDownArt), loyalty(_loyalty),
|
|
||||||
customPicURLs(_customPicURLs), muIds(std::move(_muIds)), collectorNumbers(std::move(_collectorNumbers)),
|
|
||||||
rarities(std::move(_rarities)), cipt(_cipt), tableRow(_tableRow)
|
|
||||||
{
|
{
|
||||||
pixmapCacheKey = QLatin1String("card_") + name;
|
pixmapCacheKey = QLatin1String("card_") + name;
|
||||||
simpleName = CardInfo::simplifyName(name);
|
simpleName = CardInfo::simplifyName(name);
|
||||||
|
|
@ -244,76 +239,27 @@ CardInfo::~CardInfo()
|
||||||
}
|
}
|
||||||
|
|
||||||
CardInfoPtr CardInfo::newInstance(const QString &_name,
|
CardInfoPtr CardInfo::newInstance(const QString &_name,
|
||||||
bool _isToken,
|
|
||||||
const QString &_manacost,
|
|
||||||
const QString &_cmc,
|
|
||||||
const QString &_cardtype,
|
|
||||||
const QString &_powtough,
|
|
||||||
const QString &_text,
|
const QString &_text,
|
||||||
const QStringList &_colors,
|
bool _isToken,
|
||||||
|
QVariantHash _properties,
|
||||||
const QList<CardRelation *> &_relatedCards,
|
const QList<CardRelation *> &_relatedCards,
|
||||||
const QList<CardRelation *> &_reverseRelatedCards,
|
const QList<CardRelation *> &_reverseRelatedCards,
|
||||||
bool _upsideDownArt,
|
CardInfoPerSetMap _sets,
|
||||||
const QString &_loyalty,
|
|
||||||
bool _cipt,
|
bool _cipt,
|
||||||
int _tableRow,
|
int _tableRow,
|
||||||
const SetList &_sets,
|
bool _upsideDownArt)
|
||||||
const QStringMap &_customPicURLs,
|
|
||||||
MuidMap _muIds,
|
|
||||||
QStringMap _collectorNumbers,
|
|
||||||
QStringMap _rarities)
|
|
||||||
{
|
{
|
||||||
CardInfoPtr ptr(new CardInfo(_name, _isToken, _manacost, _cmc, _cardtype, _powtough, _text, _colors, _relatedCards,
|
CardInfoPtr ptr(new CardInfo(_name, _text, _isToken, std::move(_properties), _relatedCards, _reverseRelatedCards,
|
||||||
_reverseRelatedCards, _upsideDownArt, _loyalty, _cipt, _tableRow, _sets,
|
_sets, _cipt, _tableRow, _upsideDownArt));
|
||||||
_customPicURLs, std::move(_muIds), std::move(_collectorNumbers),
|
|
||||||
std::move(_rarities)));
|
|
||||||
ptr->setSmartPointer(ptr);
|
ptr->setSmartPointer(ptr);
|
||||||
|
|
||||||
for (int i = 0; i < _sets.size(); i++) {
|
for (const CardInfoPerSet &set : _sets) {
|
||||||
_sets[i]->append(ptr);
|
set.getPtr()->append(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CardInfo::getMainCardType() const
|
|
||||||
{
|
|
||||||
QString result = getCardType();
|
|
||||||
/*
|
|
||||||
Legendary Artifact Creature - Golem
|
|
||||||
Instant // Instant
|
|
||||||
*/
|
|
||||||
|
|
||||||
int pos;
|
|
||||||
if ((pos = result.indexOf('-')) != -1) {
|
|
||||||
result.remove(pos, result.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((pos = result.indexOf("—")) != -1) {
|
|
||||||
result.remove(pos, result.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((pos = result.indexOf("//")) != -1) {
|
|
||||||
result.remove(pos, result.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
result = result.simplified();
|
|
||||||
/*
|
|
||||||
Legendary Artifact Creature
|
|
||||||
Instant
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ((pos = result.lastIndexOf(' ')) != -1) {
|
|
||||||
result = result.mid(pos + 1);
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
Creature
|
|
||||||
Instant
|
|
||||||
*/
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString CardInfo::getCorrectedName() const
|
QString CardInfo::getCorrectedName() const
|
||||||
{
|
{
|
||||||
QString result = name;
|
QString result = name;
|
||||||
|
|
@ -321,26 +267,21 @@ QString CardInfo::getCorrectedName() const
|
||||||
return result.remove(" // ").remove(':').remove('"').remove('?').replace('/', ' ');
|
return result.remove(" // ").remove(':').remove('"').remove('?').replace('/', ' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardInfo::addToSet(CardSetPtr set)
|
void CardInfo::addToSet(const CardSetPtr &_set, const CardInfoPerSet _info)
|
||||||
{
|
{
|
||||||
if (set.isNull()) {
|
_set->append(smartThis);
|
||||||
qDebug() << "addToSet(nullptr)";
|
sets.insert(_set->getShortName(), _info);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
set->append(smartThis);
|
|
||||||
sets << set;
|
|
||||||
|
|
||||||
refreshCachedSetNames();
|
refreshCachedSetNames();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardInfo::refreshCachedSetNames()
|
void CardInfo::refreshCachedSetNames()
|
||||||
{
|
{
|
||||||
// update the cached list of set names
|
|
||||||
QStringList setList;
|
QStringList setList;
|
||||||
for (int i = 0; i < sets.size(); i++) {
|
// update the cached list of set names
|
||||||
if (sets[i]->getEnabled()) {
|
for (const auto &set : sets) {
|
||||||
setList << sets[i]->getShortName();
|
if (set.getPtr()->getEnabled()) {
|
||||||
|
setList << set.getPtr()->getShortName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setsNames = setList.join(", ");
|
setsNames = setList.join(", ");
|
||||||
|
|
@ -369,11 +310,12 @@ QString CardInfo::simplifyName(const QString &name)
|
||||||
|
|
||||||
const QChar CardInfo::getColorChar() const
|
const QChar CardInfo::getColorChar() const
|
||||||
{
|
{
|
||||||
|
QString colors = getColors();
|
||||||
switch (colors.size()) {
|
switch (colors.size()) {
|
||||||
case 0:
|
case 0:
|
||||||
return QChar();
|
return QChar();
|
||||||
case 1:
|
case 1:
|
||||||
return colors.first().isEmpty() ? QChar() : colors.first().at(0);
|
return colors.at(0);
|
||||||
default:
|
default:
|
||||||
return QChar('m');
|
return QChar('m');
|
||||||
}
|
}
|
||||||
|
|
@ -386,6 +328,7 @@ CardDatabase::CardDatabase(QObject *parent) : QObject(parent), loadStatus(NotLoa
|
||||||
|
|
||||||
// add new parsers here
|
// add new parsers here
|
||||||
availableParsers << new CockatriceXml3Parser;
|
availableParsers << new CockatriceXml3Parser;
|
||||||
|
availableParsers << new CockatriceXml4Parser;
|
||||||
|
|
||||||
for (auto &parser : availableParsers) {
|
for (auto &parser : availableParsers) {
|
||||||
connect(parser, SIGNAL(addCard(CardInfoPtr)), this, SLOT(addCard(CardInfoPtr)), Qt::DirectConnection);
|
connect(parser, SIGNAL(addCard(CardInfoPtr)), this, SLOT(addCard(CardInfoPtr)), Qt::DirectConnection);
|
||||||
|
|
@ -417,9 +360,7 @@ void CardDatabase::clear()
|
||||||
simpleNameCards.clear();
|
simpleNameCards.clear();
|
||||||
|
|
||||||
sets.clear();
|
sets.clear();
|
||||||
for (auto parser : availableParsers) {
|
ICardDatabaseParser::clearSetlist();
|
||||||
parser->clearSetlist();
|
|
||||||
}
|
|
||||||
|
|
||||||
loadStatus = NotLoaded;
|
loadStatus = NotLoaded;
|
||||||
|
|
||||||
|
|
@ -436,12 +377,8 @@ void CardDatabase::addCard(CardInfoPtr card)
|
||||||
// if card already exists just add the new set property
|
// if card already exists just add the new set property
|
||||||
if (cards.contains(card->getName())) {
|
if (cards.contains(card->getName())) {
|
||||||
CardInfoPtr sameCard = cards[card->getName()];
|
CardInfoPtr sameCard = cards[card->getName()];
|
||||||
for (auto set : card->getSets()) {
|
for (const CardInfoPerSet &set : card->getSets()) {
|
||||||
QString setName = set->getCorrectedShortName();
|
sameCard->addToSet(set.getPtr(), set);
|
||||||
sameCard->setSet(set);
|
|
||||||
sameCard->setMuId(setName, card->getMuId(setName));
|
|
||||||
sameCard->setRarity(setName, card->getRarity(setName));
|
|
||||||
sameCard->setSetNumber(setName, card->getCollectorNumber(setName));
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -582,7 +519,7 @@ LoadStatus CardDatabase::loadCardDatabases()
|
||||||
|
|
||||||
// load custom card databases
|
// load custom card databases
|
||||||
QDir dir(settingsCache->getCustomCardDatabasePath());
|
QDir dir(settingsCache->getCustomCardDatabasePath());
|
||||||
for (QString fileName :
|
for (const QString &fileName :
|
||||||
dir.entryList(QStringList("*.xml"), QDir::Files | QDir::Readable, QDir::Name | QDir::IgnoreCase)) {
|
dir.entryList(QStringList("*.xml"), QDir::Files | QDir::Readable, QDir::Name | QDir::IgnoreCase)) {
|
||||||
loadCardDatabase(dir.absoluteFilePath(fileName));
|
loadCardDatabase(dir.absoluteFilePath(fileName));
|
||||||
}
|
}
|
||||||
|
|
@ -614,20 +551,13 @@ void CardDatabase::refreshCachedReverseRelatedCards()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString relatedCardName;
|
|
||||||
if (card->getPowTough().size() > 0) {
|
|
||||||
relatedCardName = card->getPowTough() + " " + card->getName(); // "n/n name"
|
|
||||||
} else {
|
|
||||||
relatedCardName = card->getName(); // "name"
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (CardRelation *cardRelation, card->getReverseRelatedCards()) {
|
foreach (CardRelation *cardRelation, card->getReverseRelatedCards()) {
|
||||||
const QString &targetCard = cardRelation->getName();
|
const QString &targetCard = cardRelation->getName();
|
||||||
if (!cards.contains(targetCard)) {
|
if (!cards.contains(targetCard)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *newCardRelation = new CardRelation(relatedCardName, cardRelation->getDoesAttach(),
|
auto *newCardRelation = new CardRelation(card->getName(), cardRelation->getDoesAttach(),
|
||||||
cardRelation->getIsCreateAllExclusion(),
|
cardRelation->getIsCreateAllExclusion(),
|
||||||
cardRelation->getIsVariable(), cardRelation->getDefaultCount());
|
cardRelation->getIsVariable(), cardRelation->getDefaultCount());
|
||||||
cards.value(targetCard)->addReverseRelatedCards2Me(newCardRelation);
|
cards.value(targetCard)->addReverseRelatedCards2Me(newCardRelation);
|
||||||
|
|
@ -635,23 +565,6 @@ void CardDatabase::refreshCachedReverseRelatedCards()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList CardDatabase::getAllColors() const
|
|
||||||
{
|
|
||||||
QSet<QString> colors;
|
|
||||||
QHashIterator<QString, CardInfoPtr> cardIterator(cards);
|
|
||||||
while (cardIterator.hasNext()) {
|
|
||||||
const QStringList &cardColors = cardIterator.next().value()->getColors();
|
|
||||||
if (cardColors.isEmpty()) {
|
|
||||||
colors.insert("X");
|
|
||||||
} else {
|
|
||||||
for (int i = 0; i < cardColors.size(); ++i) {
|
|
||||||
colors.insert(cardColors[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return colors.toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList CardDatabase::getAllMainCardTypes() const
|
QStringList CardDatabase::getAllMainCardTypes() const
|
||||||
{
|
{
|
||||||
QSet<QString> types;
|
QSet<QString> types;
|
||||||
|
|
@ -717,8 +630,8 @@ bool CardDatabase::saveCustomTokensToFile()
|
||||||
tmpSets.insert(CardDatabase::TOKENS_SETNAME, customTokensSet);
|
tmpSets.insert(CardDatabase::TOKENS_SETNAME, customTokensSet);
|
||||||
|
|
||||||
CardNameMap tmpCards;
|
CardNameMap tmpCards;
|
||||||
for (CardInfoPtr card : cards) {
|
for (const CardInfoPtr &card : cards) {
|
||||||
if (card->getSets().contains(customTokensSet)) {
|
if (card->getSets().contains(CardDatabase::TOKENS_SETNAME)) {
|
||||||
tmpCards.insert(card->getName(), card);
|
tmpCards.insert(card->getName(), card);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -743,4 +656,46 @@ void CardInfo::resetReverseRelatedCards2Me()
|
||||||
cardRelation->deleteLater();
|
cardRelation->deleteLater();
|
||||||
}
|
}
|
||||||
reverseRelatedCardsToMe = QList<CardRelation *>();
|
reverseRelatedCardsToMe = QList<CardRelation *>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Back-compatibility methods. Remove ASAP
|
||||||
|
const QString CardInfo::getCardType() const
|
||||||
|
{
|
||||||
|
return getProperty(Mtg::CardType);
|
||||||
|
}
|
||||||
|
void CardInfo::setCardType(const QString &value)
|
||||||
|
{
|
||||||
|
setProperty(Mtg::CardType, value);
|
||||||
|
}
|
||||||
|
const QString CardInfo::getCmc() const
|
||||||
|
{
|
||||||
|
return getProperty(Mtg::ConvertedManaCost);
|
||||||
|
}
|
||||||
|
const QString CardInfo::getColors() const
|
||||||
|
{
|
||||||
|
return getProperty(Mtg::Colors);
|
||||||
|
}
|
||||||
|
void CardInfo::setColors(const QString &value)
|
||||||
|
{
|
||||||
|
setProperty(Mtg::Colors, value);
|
||||||
|
}
|
||||||
|
const QString CardInfo::getLoyalty() const
|
||||||
|
{
|
||||||
|
return getProperty(Mtg::Loyalty);
|
||||||
|
}
|
||||||
|
const QString CardInfo::getMainCardType() const
|
||||||
|
{
|
||||||
|
return getProperty(Mtg::MainCardType);
|
||||||
|
}
|
||||||
|
const QString CardInfo::getManaCost() const
|
||||||
|
{
|
||||||
|
return getProperty(Mtg::ManaCost);
|
||||||
|
}
|
||||||
|
const QString CardInfo::getPowTough() const
|
||||||
|
{
|
||||||
|
return getProperty(Mtg::PowTough);
|
||||||
|
}
|
||||||
|
void CardInfo::setPowTough(const QString &value)
|
||||||
|
{
|
||||||
|
setProperty(Mtg::PowTough, value);
|
||||||
}
|
}
|
||||||
|
|
@ -9,10 +9,13 @@
|
||||||
#include <QMetaType>
|
#include <QMetaType>
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
#include <QVariant>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
class CardDatabase;
|
class CardDatabase;
|
||||||
class CardInfo;
|
class CardInfo;
|
||||||
|
class CardInfoPerSet;
|
||||||
class CardSet;
|
class CardSet;
|
||||||
class CardRelation;
|
class CardRelation;
|
||||||
class ICardDatabaseParser;
|
class ICardDatabaseParser;
|
||||||
|
|
@ -21,6 +24,7 @@ typedef QMap<QString, QString> QStringMap;
|
||||||
typedef QMap<QString, int> MuidMap;
|
typedef QMap<QString, int> MuidMap;
|
||||||
typedef QSharedPointer<CardInfo> CardInfoPtr;
|
typedef QSharedPointer<CardInfo> CardInfoPtr;
|
||||||
typedef QSharedPointer<CardSet> CardSetPtr;
|
typedef QSharedPointer<CardSet> CardSetPtr;
|
||||||
|
typedef QMap<QString, CardInfoPerSet> CardInfoPerSetMap;
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(CardInfoPtr)
|
Q_DECLARE_METATYPE(CardInfoPtr)
|
||||||
|
|
||||||
|
|
@ -112,175 +116,162 @@ public:
|
||||||
QStringList getUnknownSetsNames();
|
QStringList getUnknownSetsNames();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CardInfoPerSet
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit CardInfoPerSet(const CardSetPtr &_set = QSharedPointer<CardSet>(nullptr));
|
||||||
|
~CardInfoPerSet() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
CardSetPtr set;
|
||||||
|
// per-set card properties;
|
||||||
|
QVariantHash properties;
|
||||||
|
|
||||||
|
public:
|
||||||
|
const CardSetPtr getPtr() const
|
||||||
|
{
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
const QStringList getProperties() const
|
||||||
|
{
|
||||||
|
return properties.keys();
|
||||||
|
}
|
||||||
|
const QString getProperty(const QString &propertyName) const
|
||||||
|
{
|
||||||
|
return properties.value(propertyName).toString();
|
||||||
|
}
|
||||||
|
void setProperty(const QString &_name, const QString &_value)
|
||||||
|
{
|
||||||
|
properties.insert(_name, _value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class CardInfo : public QObject
|
class CardInfo : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
private:
|
private:
|
||||||
CardInfoPtr smartThis;
|
CardInfoPtr smartThis;
|
||||||
|
// The card name
|
||||||
QString name;
|
QString name;
|
||||||
|
// The name without punctuation or capitalization, for better card name recognition.
|
||||||
/*
|
|
||||||
* The name without punctuation or capitalization, for better card tag name
|
|
||||||
* recognition.
|
|
||||||
*/
|
|
||||||
QString simpleName;
|
QString simpleName;
|
||||||
|
// The key used to identify this card in the cache
|
||||||
bool isToken;
|
QString pixmapCacheKey;
|
||||||
SetList sets;
|
// card text
|
||||||
QString manacost;
|
|
||||||
QString cmc;
|
|
||||||
QString cardtype;
|
|
||||||
QString powtough;
|
|
||||||
QString text;
|
QString text;
|
||||||
QStringList colors;
|
// whether this is not a "real" card but a token
|
||||||
|
bool isToken;
|
||||||
|
// basic card properties; common for all the sets
|
||||||
|
QVariantHash properties;
|
||||||
// the cards i'm related to
|
// the cards i'm related to
|
||||||
QList<CardRelation *> relatedCards;
|
QList<CardRelation *> relatedCards;
|
||||||
|
|
||||||
// the card i'm reverse-related to
|
// the card i'm reverse-related to
|
||||||
QList<CardRelation *> reverseRelatedCards;
|
QList<CardRelation *> reverseRelatedCards;
|
||||||
|
|
||||||
// the cards thare are reverse-related to me
|
// the cards thare are reverse-related to me
|
||||||
QList<CardRelation *> reverseRelatedCardsToMe;
|
QList<CardRelation *> reverseRelatedCardsToMe;
|
||||||
|
// card sets
|
||||||
|
CardInfoPerSetMap sets;
|
||||||
|
// cached set names
|
||||||
QString setsNames;
|
QString setsNames;
|
||||||
|
// positioning properties; used by UI
|
||||||
bool upsideDownArt;
|
|
||||||
QString loyalty;
|
|
||||||
QStringMap customPicURLs;
|
|
||||||
MuidMap muIds;
|
|
||||||
QStringMap collectorNumbers;
|
|
||||||
QStringMap rarities;
|
|
||||||
bool cipt;
|
bool cipt;
|
||||||
int tableRow;
|
int tableRow;
|
||||||
QString pixmapCacheKey;
|
bool upsideDownArt;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit CardInfo(const QString &_name = QString(),
|
explicit CardInfo(const QString &_name = QString(),
|
||||||
bool _isToken = false,
|
|
||||||
const QString &_manacost = QString(),
|
|
||||||
const QString &_cmc = QString(),
|
|
||||||
const QString &_cardtype = QString(),
|
|
||||||
const QString &_powtough = QString(),
|
|
||||||
const QString &_text = QString(),
|
const QString &_text = QString(),
|
||||||
const QStringList &_colors = QStringList(),
|
bool _isToken = false,
|
||||||
|
QVariantHash _properties = QVariantHash(),
|
||||||
const QList<CardRelation *> &_relatedCards = QList<CardRelation *>(),
|
const QList<CardRelation *> &_relatedCards = QList<CardRelation *>(),
|
||||||
const QList<CardRelation *> &_reverseRelatedCards = QList<CardRelation *>(),
|
const QList<CardRelation *> &_reverseRelatedCards = QList<CardRelation *>(),
|
||||||
bool _upsideDownArt = false,
|
CardInfoPerSetMap _sets = CardInfoPerSetMap(),
|
||||||
const QString &_loyalty = QString(),
|
|
||||||
bool _cipt = false,
|
bool _cipt = false,
|
||||||
int _tableRow = 0,
|
int _tableRow = 0,
|
||||||
const SetList &_sets = SetList(),
|
bool _upsideDownArt = false);
|
||||||
const QStringMap &_customPicURLs = QStringMap(),
|
|
||||||
MuidMap muids = MuidMap(),
|
|
||||||
QStringMap _collectorNumbers = QStringMap(),
|
|
||||||
QStringMap _rarities = QStringMap());
|
|
||||||
~CardInfo() override;
|
~CardInfo() override;
|
||||||
|
|
||||||
static CardInfoPtr newInstance(const QString &_name = QString(),
|
static CardInfoPtr newInstance(const QString &_name = QString(),
|
||||||
bool _isToken = false,
|
|
||||||
const QString &_manacost = QString(),
|
|
||||||
const QString &_cmc = QString(),
|
|
||||||
const QString &_cardtype = QString(),
|
|
||||||
const QString &_powtough = QString(),
|
|
||||||
const QString &_text = QString(),
|
const QString &_text = QString(),
|
||||||
const QStringList &_colors = QStringList(),
|
bool _isToken = false,
|
||||||
|
QVariantHash _properties = QVariantHash(),
|
||||||
const QList<CardRelation *> &_relatedCards = QList<CardRelation *>(),
|
const QList<CardRelation *> &_relatedCards = QList<CardRelation *>(),
|
||||||
const QList<CardRelation *> &_reverseRelatedCards = QList<CardRelation *>(),
|
const QList<CardRelation *> &_reverseRelatedCards = QList<CardRelation *>(),
|
||||||
bool _upsideDownArt = false,
|
CardInfoPerSetMap _sets = CardInfoPerSetMap(),
|
||||||
const QString &_loyalty = QString(),
|
|
||||||
bool _cipt = false,
|
bool _cipt = false,
|
||||||
int _tableRow = 0,
|
int _tableRow = 0,
|
||||||
const SetList &_sets = SetList(),
|
bool _upsideDownArt = false);
|
||||||
const QStringMap &_customPicURLs = QStringMap(),
|
|
||||||
MuidMap muids = MuidMap(),
|
|
||||||
QStringMap _collectorNumbers = QStringMap(),
|
|
||||||
QStringMap _rarities = QStringMap());
|
|
||||||
|
|
||||||
void setSmartPointer(CardInfoPtr _ptr)
|
void setSmartPointer(CardInfoPtr _ptr)
|
||||||
{
|
{
|
||||||
smartThis = _ptr;
|
smartThis = std::move(_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// basic properties
|
||||||
inline const QString &getName() const
|
inline const QString &getName() const
|
||||||
{
|
{
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
inline const QString &getSetsNames() const
|
|
||||||
{
|
|
||||||
return setsNames;
|
|
||||||
}
|
|
||||||
const QString &getSimpleName() const
|
const QString &getSimpleName() const
|
||||||
{
|
{
|
||||||
return simpleName;
|
return simpleName;
|
||||||
}
|
}
|
||||||
bool getIsToken() const
|
|
||||||
{
|
|
||||||
return isToken;
|
|
||||||
}
|
|
||||||
const SetList &getSets() const
|
|
||||||
{
|
|
||||||
return sets;
|
|
||||||
}
|
|
||||||
inline const QString &getManaCost() const
|
|
||||||
{
|
|
||||||
return manacost;
|
|
||||||
}
|
|
||||||
inline const QString &getCmc() const
|
|
||||||
{
|
|
||||||
return cmc;
|
|
||||||
}
|
|
||||||
inline const QString &getCardType() const
|
|
||||||
{
|
|
||||||
return cardtype;
|
|
||||||
}
|
|
||||||
inline const QString &getPowTough() const
|
|
||||||
{
|
|
||||||
return powtough;
|
|
||||||
}
|
|
||||||
const QString &getText() const
|
|
||||||
{
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
const QString &getPixmapCacheKey() const
|
const QString &getPixmapCacheKey() const
|
||||||
{
|
{
|
||||||
return pixmapCacheKey;
|
return pixmapCacheKey;
|
||||||
}
|
}
|
||||||
const QString &getLoyalty() const
|
|
||||||
|
const QString &getText() const
|
||||||
{
|
{
|
||||||
return loyalty;
|
return text;
|
||||||
}
|
|
||||||
bool getCipt() const
|
|
||||||
{
|
|
||||||
return cipt;
|
|
||||||
}
|
|
||||||
// void setManaCost(const QString &_manaCost) { manacost = _manaCost; emit cardInfoChanged(smartThis); }
|
|
||||||
// void setCmc(const QString &_cmc) { cmc = _cmc; emit cardInfoChanged(smartThis); }
|
|
||||||
void setCardType(const QString &_cardType)
|
|
||||||
{
|
|
||||||
cardtype = _cardType;
|
|
||||||
emit cardInfoChanged(smartThis);
|
|
||||||
}
|
|
||||||
void setPowTough(const QString &_powTough)
|
|
||||||
{
|
|
||||||
powtough = _powTough;
|
|
||||||
emit cardInfoChanged(smartThis);
|
|
||||||
}
|
}
|
||||||
void setText(const QString &_text)
|
void setText(const QString &_text)
|
||||||
{
|
{
|
||||||
text = _text;
|
text = _text;
|
||||||
emit cardInfoChanged(smartThis);
|
emit cardInfoChanged(smartThis);
|
||||||
}
|
}
|
||||||
void setColors(const QStringList &_colors)
|
|
||||||
|
bool getIsToken() const
|
||||||
{
|
{
|
||||||
colors = _colors;
|
return isToken;
|
||||||
|
}
|
||||||
|
const QStringList getProperties() const
|
||||||
|
{
|
||||||
|
return properties.keys();
|
||||||
|
}
|
||||||
|
const QString getProperty(const QString &propertyName) const
|
||||||
|
{
|
||||||
|
return properties.value(propertyName).toString();
|
||||||
|
}
|
||||||
|
void setProperty(const QString &_name, const QString &_value)
|
||||||
|
{
|
||||||
|
properties.insert(_name, _value);
|
||||||
emit cardInfoChanged(smartThis);
|
emit cardInfoChanged(smartThis);
|
||||||
}
|
}
|
||||||
const QChar getColorChar() const;
|
const CardInfoPerSetMap &getSets() const
|
||||||
const QStringList &getColors() const
|
|
||||||
{
|
{
|
||||||
return colors;
|
return sets;
|
||||||
}
|
}
|
||||||
|
const QString &getSetsNames() const
|
||||||
|
{
|
||||||
|
return setsNames;
|
||||||
|
}
|
||||||
|
const QString getSetProperty(const QString &setName, const QString &propertyName) const
|
||||||
|
{
|
||||||
|
if (!sets.contains(setName))
|
||||||
|
return "";
|
||||||
|
return sets[setName].getProperty(propertyName);
|
||||||
|
}
|
||||||
|
void setSetProperty(const QString &setName, const QString &_name, const QString &_value)
|
||||||
|
{
|
||||||
|
if (!sets.contains(setName))
|
||||||
|
return;
|
||||||
|
|
||||||
|
sets[setName].setProperty(_name, _value);
|
||||||
|
emit cardInfoChanged(smartThis);
|
||||||
|
}
|
||||||
|
|
||||||
|
// related cards
|
||||||
const QList<CardRelation *> &getRelatedCards() const
|
const QList<CardRelation *> &getRelatedCards() const
|
||||||
{
|
{
|
||||||
return relatedCards;
|
return relatedCards;
|
||||||
|
|
@ -298,32 +289,12 @@ public:
|
||||||
{
|
{
|
||||||
reverseRelatedCardsToMe.append(cardRelation);
|
reverseRelatedCardsToMe.append(cardRelation);
|
||||||
}
|
}
|
||||||
bool getUpsideDownArt() const
|
|
||||||
|
// positioning
|
||||||
|
bool getCipt() const
|
||||||
{
|
{
|
||||||
return upsideDownArt;
|
return cipt;
|
||||||
}
|
}
|
||||||
QString getCustomPicURL(const QString &set) const
|
|
||||||
{
|
|
||||||
return customPicURLs.value(set);
|
|
||||||
}
|
|
||||||
int getMuId(const QString &set) const
|
|
||||||
{
|
|
||||||
return muIds.value(set);
|
|
||||||
}
|
|
||||||
QString getCollectorNumber(const QString &set) const
|
|
||||||
{
|
|
||||||
return collectorNumbers.value(set);
|
|
||||||
}
|
|
||||||
QString getRarity(const QString &set) const
|
|
||||||
{
|
|
||||||
return rarities.value(set);
|
|
||||||
}
|
|
||||||
QStringMap getRarities() const
|
|
||||||
{
|
|
||||||
return rarities;
|
|
||||||
}
|
|
||||||
QString getMainCardType() const;
|
|
||||||
QString getCorrectedName() const;
|
|
||||||
int getTableRow() const
|
int getTableRow() const
|
||||||
{
|
{
|
||||||
return tableRow;
|
return tableRow;
|
||||||
|
|
@ -332,27 +303,31 @@ public:
|
||||||
{
|
{
|
||||||
tableRow = _tableRow;
|
tableRow = _tableRow;
|
||||||
}
|
}
|
||||||
// void setLoyalty(int _loyalty) { loyalty = _loyalty; emit cardInfoChanged(smartThis); }
|
bool getUpsideDownArt() const
|
||||||
// void setCustomPicURL(const QString &_set, const QString &_customPicURL) { customPicURLs.insert(_set,
|
|
||||||
// _customPicURL); }
|
|
||||||
void setSet(const CardSetPtr &_set)
|
|
||||||
{
|
{
|
||||||
sets.append(_set);
|
return upsideDownArt;
|
||||||
refreshCachedSetNames();
|
|
||||||
}
|
}
|
||||||
void setMuId(const QString &_set, const int &_muId)
|
const QChar getColorChar() const;
|
||||||
|
|
||||||
|
// Back-compatibility methods. Remove ASAP
|
||||||
|
const QString getCardType() const;
|
||||||
|
void setCardType(const QString &value);
|
||||||
|
const QString getCmc() const;
|
||||||
|
const QString getColors() const;
|
||||||
|
void setColors(const QString &value);
|
||||||
|
const QString getLoyalty() const;
|
||||||
|
const QString getMainCardType() const;
|
||||||
|
const QString getManaCost() const;
|
||||||
|
const QString getPowTough() const;
|
||||||
|
void setPowTough(const QString &value);
|
||||||
|
|
||||||
|
// methods using per-set properties
|
||||||
|
QString getCustomPicURL(const QString &set) const
|
||||||
{
|
{
|
||||||
muIds.insert(_set, _muId);
|
return getSetProperty(set, "picurl");
|
||||||
}
|
}
|
||||||
void setSetNumber(const QString &_set, const QString &_setNumber)
|
QString getCorrectedName() const;
|
||||||
{
|
void addToSet(const CardSetPtr &_set, CardInfoPerSet _info = CardInfoPerSet());
|
||||||
collectorNumbers.insert(_set, _setNumber);
|
|
||||||
}
|
|
||||||
void setRarity(const QString &_set, const QString &_setNumber)
|
|
||||||
{
|
|
||||||
rarities.insert(_set, _setNumber);
|
|
||||||
}
|
|
||||||
void addToSet(CardSetPtr set);
|
|
||||||
void emitPixmapUpdated()
|
void emitPixmapUpdated()
|
||||||
{
|
{
|
||||||
emit pixmapUpdated();
|
emit pixmapUpdated();
|
||||||
|
|
@ -439,7 +414,6 @@ public:
|
||||||
SetList getSetList() const;
|
SetList getSetList() const;
|
||||||
LoadStatus loadFromFile(const QString &fileName);
|
LoadStatus loadFromFile(const QString &fileName);
|
||||||
bool saveCustomTokensToFile();
|
bool saveCustomTokensToFile();
|
||||||
QStringList getAllColors() const;
|
|
||||||
QStringList getAllMainCardTypes() const;
|
QStringList getAllMainCardTypes() const;
|
||||||
LoadStatus getLoadStatus() const
|
LoadStatus getLoadStatus() const
|
||||||
{
|
{
|
||||||
|
|
@ -506,4 +480,4 @@ public:
|
||||||
return defaultCount;
|
return defaultCount;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,7 @@ CardDatabaseModel::CardDatabaseModel(CardDatabase *_db, bool _showOnlyCardsFromE
|
||||||
cardDatabaseEnabledSetsChanged();
|
cardDatabaseEnabledSetsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
CardDatabaseModel::~CardDatabaseModel()
|
CardDatabaseModel::~CardDatabaseModel() = default;
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
QMap<wchar_t, wchar_t> CardDatabaseDisplayModel::characterTranslation = {{L'“', L'\"'},
|
QMap<wchar_t, wchar_t> CardDatabaseDisplayModel::characterTranslation = {{L'“', L'\"'},
|
||||||
{L'”', L'\"'},
|
{L'”', L'\"'},
|
||||||
|
|
@ -53,7 +51,7 @@ QVariant CardDatabaseModel::data(const QModelIndex &index, int role) const
|
||||||
case PTColumn:
|
case PTColumn:
|
||||||
return card->getPowTough();
|
return card->getPowTough();
|
||||||
case ColorColumn:
|
case ColorColumn:
|
||||||
return card->getColors().join("");
|
return card->getColors();
|
||||||
default:
|
default:
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
@ -97,8 +95,8 @@ bool CardDatabaseModel::checkCardHasAtLeastOneEnabledSet(CardInfoPtr card)
|
||||||
if (!showOnlyCardsFromEnabledSets)
|
if (!showOnlyCardsFromEnabledSets)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
for (CardSetPtr set : card->getSets()) {
|
for (const auto &set : card->getSets()) {
|
||||||
if (set->getEnabled())
|
if (set.getPtr()->getEnabled())
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,12 +26,12 @@ public:
|
||||||
{
|
{
|
||||||
SortRole = Qt::UserRole
|
SortRole = Qt::UserRole
|
||||||
};
|
};
|
||||||
CardDatabaseModel(CardDatabase *_db, bool _showOnlyCardsFromEnabledSets, QObject *parent = 0);
|
CardDatabaseModel(CardDatabase *_db, bool _showOnlyCardsFromEnabledSets, QObject *parent = nullptr);
|
||||||
~CardDatabaseModel();
|
~CardDatabaseModel() override;
|
||||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
QVariant data(const QModelIndex &index, int role) const;
|
QVariant data(const QModelIndex &index, int role) const override;
|
||||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||||
CardDatabase *getDatabase() const
|
CardDatabase *getDatabase() const
|
||||||
{
|
{
|
||||||
return db;
|
return db;
|
||||||
|
|
@ -77,7 +77,7 @@ private:
|
||||||
static QMap<wchar_t, wchar_t> characterTranslation;
|
static QMap<wchar_t, wchar_t> characterTranslation;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CardDatabaseDisplayModel(QObject *parent = 0);
|
explicit CardDatabaseDisplayModel(QObject *parent = nullptr);
|
||||||
void setFilterTree(FilterTree *filterTree);
|
void setFilterTree(FilterTree *filterTree);
|
||||||
void setIsToken(FilterBool _isToken)
|
void setIsToken(FilterBool _isToken)
|
||||||
{
|
{
|
||||||
|
|
@ -119,15 +119,15 @@ public:
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
void clearFilterAll();
|
void clearFilterAll();
|
||||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
|
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
|
||||||
static int lessThanNumerically(const QString &left, const QString &right);
|
static int lessThanNumerically(const QString &left, const QString &right);
|
||||||
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
|
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
|
||||||
bool rowMatchesCardName(CardInfoPtr info) const;
|
bool rowMatchesCardName(CardInfoPtr info) const;
|
||||||
bool canFetchMore(const QModelIndex &parent) const;
|
bool canFetchMore(const QModelIndex &parent) const override;
|
||||||
void fetchMore(const QModelIndex &parent);
|
void fetchMore(const QModelIndex &parent) override;
|
||||||
private slots:
|
private slots:
|
||||||
void filterTreeChanged();
|
void filterTreeChanged();
|
||||||
/** Will translate all undesirable characters in DIRTYNAME according to the TABLE. */
|
/** Will translate all undesirable characters in DIRTYNAME according to the TABLE. */
|
||||||
|
|
@ -138,11 +138,11 @@ class TokenDisplayModel : public CardDatabaseDisplayModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
TokenDisplayModel(QObject *parent = 0);
|
explicit TokenDisplayModel(QObject *parent = nullptr);
|
||||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
|
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
27
cockatrice/src/carddbparser/carddatabaseparser.cpp
Normal file
27
cockatrice/src/carddbparser/carddatabaseparser.cpp
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
#include "carddatabaseparser.h"
|
||||||
|
|
||||||
|
SetNameMap ICardDatabaseParser::sets;
|
||||||
|
|
||||||
|
void ICardDatabaseParser::clearSetlist()
|
||||||
|
{
|
||||||
|
sets.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
CardSetPtr ICardDatabaseParser::internalAddSet(const QString &setName,
|
||||||
|
const QString &longName,
|
||||||
|
const QString &setType,
|
||||||
|
const QDate &releaseDate)
|
||||||
|
{
|
||||||
|
if (sets.contains(setName)) {
|
||||||
|
return sets.value(setName);
|
||||||
|
}
|
||||||
|
|
||||||
|
CardSetPtr newSet = CardSet::newInstance(setName);
|
||||||
|
newSet->setLongName(longName);
|
||||||
|
newSet->setSetType(setType);
|
||||||
|
newSet->setReleaseDate(releaseDate);
|
||||||
|
|
||||||
|
sets.insert(setName, newSet);
|
||||||
|
emit addSet(newSet);
|
||||||
|
return newSet;
|
||||||
|
}
|
||||||
|
|
@ -9,15 +9,27 @@
|
||||||
class ICardDatabaseParser : public QObject
|
class ICardDatabaseParser : public QObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~ICardDatabaseParser()
|
~ICardDatabaseParser() override = default;
|
||||||
{
|
|
||||||
}
|
|
||||||
virtual bool getCanParseFile(const QString &name, QIODevice &device) = 0;
|
virtual bool getCanParseFile(const QString &name, QIODevice &device) = 0;
|
||||||
virtual void parseFile(QIODevice &device) = 0;
|
virtual void parseFile(QIODevice &device) = 0;
|
||||||
virtual bool saveToFile(SetNameMap sets, CardNameMap cards, const QString &fileName) = 0;
|
virtual bool saveToFile(SetNameMap sets, CardNameMap cards, const QString &fileName) = 0;
|
||||||
virtual void clearSetlist() = 0;
|
static void clearSetlist();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/*
|
||||||
|
* A cached list of the available sets, needed to cross-reference sets from cards.
|
||||||
|
* Shared between all parsers
|
||||||
|
*/
|
||||||
|
static SetNameMap sets;
|
||||||
|
|
||||||
|
CardSetPtr internalAddSet(const QString &setName,
|
||||||
|
const QString &longName = "",
|
||||||
|
const QString &setType = "",
|
||||||
|
const QDate &releaseDate = QDate());
|
||||||
signals:
|
signals:
|
||||||
virtual void addCard(CardInfoPtr card) = 0;
|
virtual void addCard(CardInfoPtr card) = 0;
|
||||||
|
virtual void addSet(CardSetPtr set) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_INTERFACE(ICardDatabaseParser, "ICardDatabaseParser")
|
Q_DECLARE_INTERFACE(ICardDatabaseParser, "ICardDatabaseParser")
|
||||||
|
|
|
||||||
|
|
@ -61,30 +61,6 @@ void CockatriceXml3Parser::parseFile(QIODevice &device)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CardSetPtr CockatriceXml3Parser::internalAddSet(const QString &setName,
|
|
||||||
const QString &longName,
|
|
||||||
const QString &setType,
|
|
||||||
const QDate &releaseDate)
|
|
||||||
{
|
|
||||||
if (sets.contains(setName)) {
|
|
||||||
return sets.value(setName);
|
|
||||||
}
|
|
||||||
|
|
||||||
CardSetPtr newSet = CardSet::newInstance(setName);
|
|
||||||
newSet->setLongName(longName);
|
|
||||||
newSet->setSetType(setType);
|
|
||||||
newSet->setReleaseDate(releaseDate);
|
|
||||||
|
|
||||||
sets.insert(setName, newSet);
|
|
||||||
emit addSet(newSet);
|
|
||||||
return newSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CockatriceXml3Parser::clearSetlist()
|
|
||||||
{
|
|
||||||
sets.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CockatriceXml3Parser::loadSetsFromXml(QXmlStreamReader &xml)
|
void CockatriceXml3Parser::loadSetsFromXml(QXmlStreamReader &xml)
|
||||||
{
|
{
|
||||||
while (!xml.atEnd()) {
|
while (!xml.atEnd()) {
|
||||||
|
|
@ -120,6 +96,44 @@ void CockatriceXml3Parser::loadSetsFromXml(QXmlStreamReader &xml)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString CockatriceXml3Parser::getMainCardType(QString &type)
|
||||||
|
{
|
||||||
|
QString result = type;
|
||||||
|
/*
|
||||||
|
Legendary Artifact Creature - Golem
|
||||||
|
Instant // Instant
|
||||||
|
*/
|
||||||
|
|
||||||
|
int pos;
|
||||||
|
if ((pos = result.indexOf('-')) != -1) {
|
||||||
|
result.remove(pos, result.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((pos = result.indexOf("—")) != -1) {
|
||||||
|
result.remove(pos, result.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((pos = result.indexOf("//")) != -1) {
|
||||||
|
result.remove(pos, result.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
result = result.simplified();
|
||||||
|
/*
|
||||||
|
Legendary Artifact Creature
|
||||||
|
Instant
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((pos = result.lastIndexOf(' ')) != -1) {
|
||||||
|
result = result.mid(pos + 1);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Creature
|
||||||
|
Instant
|
||||||
|
*/
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void CockatriceXml3Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
void CockatriceXml3Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
||||||
{
|
{
|
||||||
while (!xml.atEnd()) {
|
while (!xml.atEnd()) {
|
||||||
|
|
@ -128,55 +142,77 @@ void CockatriceXml3Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xml.name() == "card") {
|
if (xml.name() == "card") {
|
||||||
QString name, manacost, cmc, type, pt, text, loyalty;
|
QString name = QString("");
|
||||||
QStringList colors;
|
QString text = QString("");
|
||||||
|
QVariantHash properties = QVariantHash();
|
||||||
|
QString colors = QString("");
|
||||||
QList<CardRelation *> relatedCards, reverseRelatedCards;
|
QList<CardRelation *> relatedCards, reverseRelatedCards;
|
||||||
QStringMap customPicURLs;
|
CardInfoPerSetMap sets = CardInfoPerSetMap();
|
||||||
MuidMap muids;
|
|
||||||
QStringMap collectorNumbers, rarities;
|
|
||||||
SetList sets;
|
|
||||||
int tableRow = 0;
|
int tableRow = 0;
|
||||||
bool cipt = false;
|
bool cipt = false;
|
||||||
bool isToken = false;
|
bool isToken = false;
|
||||||
bool upsideDown = false;
|
bool upsideDown = false;
|
||||||
|
|
||||||
while (!xml.atEnd()) {
|
while (!xml.atEnd()) {
|
||||||
if (xml.readNext() == QXmlStreamReader::EndElement) {
|
if (xml.readNext() == QXmlStreamReader::EndElement) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// variable - assigned properties
|
||||||
if (xml.name() == "name") {
|
if (xml.name() == "name") {
|
||||||
name = xml.readElementText();
|
name = xml.readElementText();
|
||||||
} else if (xml.name() == "manacost") {
|
|
||||||
manacost = xml.readElementText();
|
|
||||||
} else if (xml.name() == "cmc") {
|
|
||||||
cmc = xml.readElementText();
|
|
||||||
} else if (xml.name() == "type") {
|
|
||||||
type = xml.readElementText();
|
|
||||||
} else if (xml.name() == "pt") {
|
|
||||||
pt = xml.readElementText();
|
|
||||||
} else if (xml.name() == "text") {
|
} else if (xml.name() == "text") {
|
||||||
text = xml.readElementText();
|
text = xml.readElementText();
|
||||||
|
} else if (xml.name() == "color") {
|
||||||
|
colors.append(xml.readElementText());
|
||||||
|
} else if (xml.name() == "token") {
|
||||||
|
isToken = static_cast<bool>(xml.readElementText().toInt());
|
||||||
|
// generic properties
|
||||||
|
} else if (xml.name() == "manacost") {
|
||||||
|
properties.insert("manacost", xml.readElementText());
|
||||||
|
} else if (xml.name() == "cmc") {
|
||||||
|
properties.insert("cmc", xml.readElementText());
|
||||||
|
} else if (xml.name() == "type") {
|
||||||
|
QString type = xml.readElementText();
|
||||||
|
properties.insert("type", type);
|
||||||
|
properties.insert("maintype", getMainCardType(type));
|
||||||
|
} else if (xml.name() == "pt") {
|
||||||
|
properties.insert("pt", xml.readElementText());
|
||||||
|
} else if (xml.name() == "loyalty") {
|
||||||
|
properties.insert("loyalty", xml.readElementText());
|
||||||
|
// positioning info
|
||||||
|
} else if (xml.name() == "tablerow") {
|
||||||
|
tableRow = xml.readElementText().toInt();
|
||||||
|
} else if (xml.name() == "cipt") {
|
||||||
|
cipt = (xml.readElementText() == "1");
|
||||||
|
} else if (xml.name() == "upsidedown") {
|
||||||
|
upsideDown = (xml.readElementText() == "1");
|
||||||
|
// sets
|
||||||
} else if (xml.name() == "set") {
|
} else if (xml.name() == "set") {
|
||||||
|
// NOTE: attributes must be read before readElementText()
|
||||||
QXmlStreamAttributes attrs = xml.attributes();
|
QXmlStreamAttributes attrs = xml.attributes();
|
||||||
QString setName = xml.readElementText();
|
QString setName = xml.readElementText();
|
||||||
sets.append(internalAddSet(setName));
|
CardInfoPerSet setInfo(internalAddSet(setName));
|
||||||
if (attrs.hasAttribute("muId")) {
|
if (attrs.hasAttribute("muId")) {
|
||||||
muids[setName] = attrs.value("muId").toString().toInt();
|
setInfo.setProperty("muid", attrs.value("muId").toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attrs.hasAttribute("muId")) {
|
||||||
|
setInfo.setProperty("uuid", attrs.value("uuId").toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attrs.hasAttribute("picURL")) {
|
if (attrs.hasAttribute("picURL")) {
|
||||||
customPicURLs[setName] = attrs.value("picURL").toString();
|
setInfo.setProperty("picurl", attrs.value("picURL").toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attrs.hasAttribute("num")) {
|
if (attrs.hasAttribute("num")) {
|
||||||
collectorNumbers[setName] = attrs.value("num").toString();
|
setInfo.setProperty("num", attrs.value("num").toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attrs.hasAttribute("rarity")) {
|
if (attrs.hasAttribute("rarity")) {
|
||||||
rarities[setName] = attrs.value("rarity").toString();
|
setInfo.setProperty("rarity", attrs.value("rarity").toString());
|
||||||
}
|
}
|
||||||
} else if (xml.name() == "color") {
|
sets.insert(setName, setInfo);
|
||||||
colors << xml.readElementText();
|
// relatd cards
|
||||||
} else if (xml.name() == "related" || xml.name() == "reverse-related") {
|
} else if (xml.name() == "related" || xml.name() == "reverse-related") {
|
||||||
bool attach = false;
|
bool attach = false;
|
||||||
bool exclude = false;
|
bool exclude = false;
|
||||||
|
|
@ -213,16 +249,6 @@ void CockatriceXml3Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
||||||
} else {
|
} else {
|
||||||
relatedCards << relation;
|
relatedCards << relation;
|
||||||
}
|
}
|
||||||
} else if (xml.name() == "tablerow") {
|
|
||||||
tableRow = xml.readElementText().toInt();
|
|
||||||
} else if (xml.name() == "cipt") {
|
|
||||||
cipt = (xml.readElementText() == "1");
|
|
||||||
} else if (xml.name() == "upsidedown") {
|
|
||||||
upsideDown = (xml.readElementText() == "1");
|
|
||||||
} else if (xml.name() == "loyalty") {
|
|
||||||
loyalty = xml.readElementText();
|
|
||||||
} else if (xml.name() == "token") {
|
|
||||||
isToken = static_cast<bool>(xml.readElementText().toInt());
|
|
||||||
} else if (xml.name() != "") {
|
} else if (xml.name() != "") {
|
||||||
qDebug() << "[CockatriceXml3Parser] Unknown card property" << xml.name()
|
qDebug() << "[CockatriceXml3Parser] Unknown card property" << xml.name()
|
||||||
<< ", trying to continue anyway";
|
<< ", trying to continue anyway";
|
||||||
|
|
@ -230,9 +256,9 @@ void CockatriceXml3Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CardInfoPtr newCard = CardInfo::newInstance(
|
properties.insert("colors", colors);
|
||||||
name, isToken, manacost, cmc, type, pt, text, colors, relatedCards, reverseRelatedCards, upsideDown,
|
CardInfoPtr newCard = CardInfo::newInstance(name, text, isToken, properties, relatedCards,
|
||||||
loyalty, cipt, tableRow, sets, customPicURLs, muids, collectorNumbers, rarities);
|
reverseRelatedCards, sets, cipt, tableRow, upsideDown);
|
||||||
emit addCard(newCard);
|
emit addCard(newCard);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -262,37 +288,60 @@ static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfoPtr &in
|
||||||
return xml;
|
return xml;
|
||||||
}
|
}
|
||||||
|
|
||||||
xml.writeStartElement("card");
|
|
||||||
xml.writeTextElement("name", info->getName());
|
|
||||||
|
|
||||||
const SetList &sets = info->getSets();
|
|
||||||
QString tmpString;
|
QString tmpString;
|
||||||
QString tmpSet;
|
|
||||||
for (int i = 0; i < sets.size(); i++) {
|
xml.writeStartElement("card");
|
||||||
|
|
||||||
|
// variable - assigned properties
|
||||||
|
xml.writeTextElement("name", info->getName());
|
||||||
|
xml.writeTextElement("text", info->getText());
|
||||||
|
if (info->getIsToken()) {
|
||||||
|
xml.writeTextElement("token", "1");
|
||||||
|
}
|
||||||
|
|
||||||
|
// generic properties
|
||||||
|
xml.writeTextElement("manacost", info->getProperty("manacost"));
|
||||||
|
xml.writeTextElement("cmc", info->getProperty("cmc"));
|
||||||
|
xml.writeTextElement("type", info->getProperty("type"));
|
||||||
|
|
||||||
|
int colorSize = info->getColors().size();
|
||||||
|
for (int i = 0; i < colorSize; ++i) {
|
||||||
|
xml.writeTextElement("color", info->getColors().at(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpString = info->getProperty("pt");
|
||||||
|
if (!tmpString.isEmpty()) {
|
||||||
|
xml.writeTextElement("pt", tmpString);
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpString = info->getProperty("loyalty");
|
||||||
|
if (!tmpString.isEmpty()) {
|
||||||
|
xml.writeTextElement("loyalty", tmpString);
|
||||||
|
}
|
||||||
|
|
||||||
|
// sets
|
||||||
|
const CardInfoPerSetMap sets = info->getSets();
|
||||||
|
for (CardInfoPerSet set : sets) {
|
||||||
xml.writeStartElement("set");
|
xml.writeStartElement("set");
|
||||||
|
xml.writeAttribute("rarity", set.getProperty("rarity"));
|
||||||
|
xml.writeAttribute("muId", set.getProperty("muid"));
|
||||||
|
xml.writeAttribute("uuId", set.getProperty("uuid"));
|
||||||
|
|
||||||
tmpSet = sets[i]->getShortName();
|
tmpString = set.getProperty("num");
|
||||||
xml.writeAttribute("rarity", info->getRarity(tmpSet));
|
|
||||||
xml.writeAttribute("muId", QString::number(info->getMuId(tmpSet)));
|
|
||||||
|
|
||||||
tmpString = info->getCollectorNumber(tmpSet);
|
|
||||||
if (!tmpString.isEmpty()) {
|
if (!tmpString.isEmpty()) {
|
||||||
xml.writeAttribute("num", info->getCollectorNumber(tmpSet));
|
xml.writeAttribute("num", tmpString);
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpString = info->getCustomPicURL(tmpSet);
|
tmpString = set.getProperty("picurl");
|
||||||
if (!tmpString.isEmpty()) {
|
if (!tmpString.isEmpty()) {
|
||||||
xml.writeAttribute("picURL", tmpString);
|
xml.writeAttribute("picURL", tmpString);
|
||||||
}
|
}
|
||||||
|
|
||||||
xml.writeCharacters(tmpSet);
|
xml.writeCharacters(set.getPtr()->getShortName());
|
||||||
xml.writeEndElement();
|
xml.writeEndElement();
|
||||||
}
|
}
|
||||||
const QStringList &colors = info->getColors();
|
|
||||||
for (int i = 0; i < colors.size(); i++) {
|
|
||||||
xml.writeTextElement("color", colors[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// related cards
|
||||||
const QList<CardRelation *> related = info->getRelatedCards();
|
const QList<CardRelation *> related = info->getRelatedCards();
|
||||||
for (auto i : related) {
|
for (auto i : related) {
|
||||||
xml.writeStartElement("related");
|
xml.writeStartElement("related");
|
||||||
|
|
@ -338,23 +387,12 @@ static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfoPtr &in
|
||||||
xml.writeCharacters(i->getName());
|
xml.writeCharacters(i->getName());
|
||||||
xml.writeEndElement();
|
xml.writeEndElement();
|
||||||
}
|
}
|
||||||
xml.writeTextElement("manacost", info->getManaCost());
|
|
||||||
xml.writeTextElement("cmc", info->getCmc());
|
// positioning
|
||||||
xml.writeTextElement("type", info->getCardType());
|
|
||||||
if (!info->getPowTough().isEmpty()) {
|
|
||||||
xml.writeTextElement("pt", info->getPowTough());
|
|
||||||
}
|
|
||||||
xml.writeTextElement("tablerow", QString::number(info->getTableRow()));
|
xml.writeTextElement("tablerow", QString::number(info->getTableRow()));
|
||||||
xml.writeTextElement("text", info->getText());
|
|
||||||
if (info->getMainCardType() == "Planeswalker") {
|
|
||||||
xml.writeTextElement("loyalty", info->getLoyalty());
|
|
||||||
}
|
|
||||||
if (info->getCipt()) {
|
if (info->getCipt()) {
|
||||||
xml.writeTextElement("cipt", "1");
|
xml.writeTextElement("cipt", "1");
|
||||||
}
|
}
|
||||||
if (info->getIsToken()) {
|
|
||||||
xml.writeTextElement("token", "1");
|
|
||||||
}
|
|
||||||
if (info->getUpsideDownArt()) {
|
if (info->getUpsideDownArt()) {
|
||||||
xml.writeTextElement("upsidedown", "1");
|
xml.writeTextElement("upsidedown", "1");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,27 +11,18 @@ class CockatriceXml3Parser : public ICardDatabaseParser
|
||||||
Q_INTERFACES(ICardDatabaseParser)
|
Q_INTERFACES(ICardDatabaseParser)
|
||||||
public:
|
public:
|
||||||
CockatriceXml3Parser() = default;
|
CockatriceXml3Parser() = default;
|
||||||
~CockatriceXml3Parser() = default;
|
~CockatriceXml3Parser() override = default;
|
||||||
bool getCanParseFile(const QString &name, QIODevice &device);
|
bool getCanParseFile(const QString &name, QIODevice &device) override;
|
||||||
void parseFile(QIODevice &device);
|
void parseFile(QIODevice &device) override;
|
||||||
bool saveToFile(SetNameMap sets, CardNameMap cards, const QString &fileName);
|
bool saveToFile(SetNameMap sets, CardNameMap cards, const QString &fileName) override;
|
||||||
void clearSetlist();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*
|
|
||||||
* A cached list of the available sets, needed to cross-reference sets from cards.
|
|
||||||
*/
|
|
||||||
SetNameMap sets;
|
|
||||||
|
|
||||||
CardSetPtr internalAddSet(const QString &setName,
|
|
||||||
const QString &longName = "",
|
|
||||||
const QString &setType = "",
|
|
||||||
const QDate &releaseDate = QDate());
|
|
||||||
void loadCardsFromXml(QXmlStreamReader &xml);
|
void loadCardsFromXml(QXmlStreamReader &xml);
|
||||||
void loadSetsFromXml(QXmlStreamReader &xml);
|
void loadSetsFromXml(QXmlStreamReader &xml);
|
||||||
|
QString getMainCardType(QString &type);
|
||||||
signals:
|
signals:
|
||||||
void addCard(CardInfoPtr card);
|
void addCard(CardInfoPtr card) override;
|
||||||
void addSet(CardSetPtr set);
|
void addSet(CardSetPtr set) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
362
cockatrice/src/carddbparser/cockatricexml4.cpp
Normal file
362
cockatrice/src/carddbparser/cockatricexml4.cpp
Normal file
|
|
@ -0,0 +1,362 @@
|
||||||
|
#include "cockatricexml4.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QXmlStreamReader>
|
||||||
|
|
||||||
|
#define COCKATRICE_XML4_TAGNAME "cockatrice_carddatabase"
|
||||||
|
#define COCKATRICE_XML4_TAGVER 4
|
||||||
|
|
||||||
|
bool CockatriceXml4Parser::getCanParseFile(const QString &fileName, QIODevice &device)
|
||||||
|
{
|
||||||
|
qDebug() << "[CockatriceXml4Parser] Trying to parse: " << fileName;
|
||||||
|
|
||||||
|
if (!fileName.endsWith(".xml", Qt::CaseInsensitive)) {
|
||||||
|
qDebug() << "[CockatriceXml4Parser] Parsing failed: wrong extension";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QXmlStreamReader xml(&device);
|
||||||
|
while (!xml.atEnd()) {
|
||||||
|
if (xml.readNext() == QXmlStreamReader::StartElement) {
|
||||||
|
if (xml.name() == COCKATRICE_XML4_TAGNAME) {
|
||||||
|
int version = xml.attributes().value("version").toString().toInt();
|
||||||
|
if (version == COCKATRICE_XML4_TAGVER) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
qDebug() << "[CockatriceXml4Parser] Parsing failed: wrong version" << version;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
qDebug() << "[CockatriceXml4Parser] Parsing failed: wrong element tag" << xml.name();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CockatriceXml4Parser::parseFile(QIODevice &device)
|
||||||
|
{
|
||||||
|
QXmlStreamReader xml(&device);
|
||||||
|
while (!xml.atEnd()) {
|
||||||
|
if (xml.readNext() == QXmlStreamReader::StartElement) {
|
||||||
|
while (!xml.atEnd()) {
|
||||||
|
if (xml.readNext() == QXmlStreamReader::EndElement) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xml.name() == "sets") {
|
||||||
|
loadSetsFromXml(xml);
|
||||||
|
} else if (xml.name() == "cards") {
|
||||||
|
loadCardsFromXml(xml);
|
||||||
|
} else if (xml.name() != "") {
|
||||||
|
qDebug() << "[CockatriceXml4Parser] Unknown item" << xml.name() << ", trying to continue anyway";
|
||||||
|
xml.skipCurrentElement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CockatriceXml4Parser::loadSetsFromXml(QXmlStreamReader &xml)
|
||||||
|
{
|
||||||
|
while (!xml.atEnd()) {
|
||||||
|
if (xml.readNext() == QXmlStreamReader::EndElement) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xml.name() == "set") {
|
||||||
|
QString shortName, longName, setType;
|
||||||
|
QDate releaseDate;
|
||||||
|
while (!xml.atEnd()) {
|
||||||
|
if (xml.readNext() == QXmlStreamReader::EndElement) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xml.name() == "name") {
|
||||||
|
shortName = xml.readElementText();
|
||||||
|
} else if (xml.name() == "longname") {
|
||||||
|
longName = xml.readElementText();
|
||||||
|
} else if (xml.name() == "settype") {
|
||||||
|
setType = xml.readElementText();
|
||||||
|
} else if (xml.name() == "releasedate") {
|
||||||
|
releaseDate = QDate::fromString(xml.readElementText(), Qt::ISODate);
|
||||||
|
} else if (xml.name() != "") {
|
||||||
|
qDebug() << "[CockatriceXml4Parser] Unknown set property" << xml.name()
|
||||||
|
<< ", trying to continue anyway";
|
||||||
|
xml.skipCurrentElement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internalAddSet(shortName, longName, setType, releaseDate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantHash CockatriceXml4Parser::loadCardPropertiesFromXml(QXmlStreamReader &xml)
|
||||||
|
{
|
||||||
|
QVariantHash properties = QVariantHash();
|
||||||
|
while (!xml.atEnd()) {
|
||||||
|
if (xml.readNext() == QXmlStreamReader::EndElement) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xml.name() != "") {
|
||||||
|
properties.insert(xml.name().toString(), xml.readElementText());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CockatriceXml4Parser::loadCardsFromXml(QXmlStreamReader &xml)
|
||||||
|
{
|
||||||
|
while (!xml.atEnd()) {
|
||||||
|
if (xml.readNext() == QXmlStreamReader::EndElement) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xml.name() == "card") {
|
||||||
|
QString name = QString("");
|
||||||
|
QString text = QString("");
|
||||||
|
QVariantHash properties = QVariantHash();
|
||||||
|
QList<CardRelation *> relatedCards, reverseRelatedCards;
|
||||||
|
CardInfoPerSetMap sets = CardInfoPerSetMap();
|
||||||
|
int tableRow = 0;
|
||||||
|
bool cipt = false;
|
||||||
|
bool isToken = false;
|
||||||
|
bool upsideDown = false;
|
||||||
|
|
||||||
|
while (!xml.atEnd()) {
|
||||||
|
if (xml.readNext() == QXmlStreamReader::EndElement) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// variable - assigned properties
|
||||||
|
if (xml.name() == "name") {
|
||||||
|
name = xml.readElementText();
|
||||||
|
} else if (xml.name() == "text") {
|
||||||
|
text = xml.readElementText();
|
||||||
|
} else if (xml.name() == "token") {
|
||||||
|
isToken = static_cast<bool>(xml.readElementText().toInt());
|
||||||
|
// generic properties
|
||||||
|
} else if (xml.name() == "prop") {
|
||||||
|
properties = loadCardPropertiesFromXml(xml);
|
||||||
|
// positioning info
|
||||||
|
} else if (xml.name() == "tablerow") {
|
||||||
|
tableRow = xml.readElementText().toInt();
|
||||||
|
} else if (xml.name() == "cipt") {
|
||||||
|
cipt = (xml.readElementText() == "1");
|
||||||
|
} else if (xml.name() == "upsidedown") {
|
||||||
|
upsideDown = (xml.readElementText() == "1");
|
||||||
|
// sets
|
||||||
|
} else if (xml.name() == "set") {
|
||||||
|
// NOTE: attributes but be read before readElementText()
|
||||||
|
QXmlStreamAttributes attrs = xml.attributes();
|
||||||
|
QString setName = xml.readElementText();
|
||||||
|
CardInfoPerSet setInfo(internalAddSet(setName));
|
||||||
|
for (QXmlStreamAttribute attr : attrs) {
|
||||||
|
setInfo.setProperty(attr.name().toString(), attr.value().toString());
|
||||||
|
}
|
||||||
|
sets.insert(setName, setInfo);
|
||||||
|
// relatd cards
|
||||||
|
} else if (xml.name() == "related" || xml.name() == "reverse-related") {
|
||||||
|
bool attach = false;
|
||||||
|
bool exclude = false;
|
||||||
|
bool variable = false;
|
||||||
|
int count = 1;
|
||||||
|
QXmlStreamAttributes attrs = xml.attributes();
|
||||||
|
QString cardName = xml.readElementText();
|
||||||
|
if (attrs.hasAttribute("count")) {
|
||||||
|
if (attrs.value("count").toString().indexOf("x=") == 0) {
|
||||||
|
variable = true;
|
||||||
|
count = attrs.value("count").toString().remove(0, 2).toInt();
|
||||||
|
} else if (attrs.value("count").toString().indexOf("x") == 0) {
|
||||||
|
variable = true;
|
||||||
|
} else {
|
||||||
|
count = attrs.value("count").toString().toInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count < 1) {
|
||||||
|
count = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attrs.hasAttribute("attach")) {
|
||||||
|
attach = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attrs.hasAttribute("exclude")) {
|
||||||
|
exclude = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto *relation = new CardRelation(cardName, attach, exclude, variable, count);
|
||||||
|
if (xml.name() == "reverse-related") {
|
||||||
|
reverseRelatedCards << relation;
|
||||||
|
} else {
|
||||||
|
relatedCards << relation;
|
||||||
|
}
|
||||||
|
} else if (xml.name() != "") {
|
||||||
|
qDebug() << "[CockatriceXml4Parser] Unknown card property" << xml.name()
|
||||||
|
<< ", trying to continue anyway";
|
||||||
|
xml.skipCurrentElement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CardInfoPtr newCard = CardInfo::newInstance(name, text, isToken, properties, relatedCards,
|
||||||
|
reverseRelatedCards, sets, cipt, tableRow, upsideDown);
|
||||||
|
emit addCard(newCard);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardSetPtr &set)
|
||||||
|
{
|
||||||
|
if (set.isNull()) {
|
||||||
|
qDebug() << "&operator<< set is nullptr";
|
||||||
|
return xml;
|
||||||
|
}
|
||||||
|
|
||||||
|
xml.writeStartElement("set");
|
||||||
|
xml.writeTextElement("name", set->getShortName());
|
||||||
|
xml.writeTextElement("longname", set->getLongName());
|
||||||
|
xml.writeTextElement("settype", set->getSetType());
|
||||||
|
xml.writeTextElement("releasedate", set->getReleaseDate().toString(Qt::ISODate));
|
||||||
|
xml.writeEndElement();
|
||||||
|
|
||||||
|
return xml;
|
||||||
|
}
|
||||||
|
|
||||||
|
static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfoPtr &info)
|
||||||
|
{
|
||||||
|
if (info.isNull()) {
|
||||||
|
qDebug() << "operator<< info is nullptr";
|
||||||
|
return xml;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString tmpString;
|
||||||
|
|
||||||
|
xml.writeStartElement("card");
|
||||||
|
|
||||||
|
// variable - assigned properties
|
||||||
|
xml.writeTextElement("name", info->getName());
|
||||||
|
xml.writeTextElement("text", info->getText());
|
||||||
|
if (info->getIsToken()) {
|
||||||
|
xml.writeTextElement("token", "1");
|
||||||
|
}
|
||||||
|
|
||||||
|
// generic properties
|
||||||
|
xml.writeStartElement("prop");
|
||||||
|
for (QString propName : info->getProperties()) {
|
||||||
|
xml.writeTextElement(propName, info->getProperty(propName));
|
||||||
|
}
|
||||||
|
xml.writeEndElement();
|
||||||
|
|
||||||
|
// sets
|
||||||
|
for (CardInfoPerSet set : info->getSets()) {
|
||||||
|
xml.writeStartElement("set");
|
||||||
|
for (QString propName : set.getProperties()) {
|
||||||
|
xml.writeAttribute(propName, set.getProperty(propName));
|
||||||
|
}
|
||||||
|
|
||||||
|
xml.writeCharacters(set.getPtr()->getShortName());
|
||||||
|
xml.writeEndElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
// related cards
|
||||||
|
const QList<CardRelation *> related = info->getRelatedCards();
|
||||||
|
for (auto i : related) {
|
||||||
|
xml.writeStartElement("related");
|
||||||
|
if (i->getDoesAttach()) {
|
||||||
|
xml.writeAttribute("attach", "attach");
|
||||||
|
}
|
||||||
|
if (i->getIsCreateAllExclusion()) {
|
||||||
|
xml.writeAttribute("exclude", "exclude");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i->getIsVariable()) {
|
||||||
|
if (1 == i->getDefaultCount()) {
|
||||||
|
xml.writeAttribute("count", "x");
|
||||||
|
} else {
|
||||||
|
xml.writeAttribute("count", "x=" + QString::number(i->getDefaultCount()));
|
||||||
|
}
|
||||||
|
} else if (1 != i->getDefaultCount()) {
|
||||||
|
xml.writeAttribute("count", QString::number(i->getDefaultCount()));
|
||||||
|
}
|
||||||
|
xml.writeCharacters(i->getName());
|
||||||
|
xml.writeEndElement();
|
||||||
|
}
|
||||||
|
const QList<CardRelation *> reverseRelated = info->getReverseRelatedCards();
|
||||||
|
for (auto i : reverseRelated) {
|
||||||
|
xml.writeStartElement("reverse-related");
|
||||||
|
if (i->getDoesAttach()) {
|
||||||
|
xml.writeAttribute("attach", "attach");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i->getIsCreateAllExclusion()) {
|
||||||
|
xml.writeAttribute("exclude", "exclude");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i->getIsVariable()) {
|
||||||
|
if (1 == i->getDefaultCount()) {
|
||||||
|
xml.writeAttribute("count", "x");
|
||||||
|
} else {
|
||||||
|
xml.writeAttribute("count", "x=" + QString::number(i->getDefaultCount()));
|
||||||
|
}
|
||||||
|
} else if (1 != i->getDefaultCount()) {
|
||||||
|
xml.writeAttribute("count", QString::number(i->getDefaultCount()));
|
||||||
|
}
|
||||||
|
xml.writeCharacters(i->getName());
|
||||||
|
xml.writeEndElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
// positioning
|
||||||
|
xml.writeTextElement("tablerow", QString::number(info->getTableRow()));
|
||||||
|
if (info->getCipt()) {
|
||||||
|
xml.writeTextElement("cipt", "1");
|
||||||
|
}
|
||||||
|
if (info->getUpsideDownArt()) {
|
||||||
|
xml.writeTextElement("upsidedown", "1");
|
||||||
|
}
|
||||||
|
|
||||||
|
xml.writeEndElement(); // card
|
||||||
|
|
||||||
|
return xml;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CockatriceXml4Parser::saveToFile(SetNameMap sets, CardNameMap cards, const QString &fileName)
|
||||||
|
{
|
||||||
|
QFile file(fileName);
|
||||||
|
if (!file.open(QIODevice::WriteOnly)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QXmlStreamWriter xml(&file);
|
||||||
|
|
||||||
|
xml.setAutoFormatting(true);
|
||||||
|
xml.writeStartDocument();
|
||||||
|
xml.writeStartElement(COCKATRICE_XML4_TAGNAME);
|
||||||
|
xml.writeAttribute("version", QString::number(COCKATRICE_XML4_TAGVER));
|
||||||
|
|
||||||
|
if (sets.count() > 0) {
|
||||||
|
xml.writeStartElement("sets");
|
||||||
|
for (CardSetPtr set : sets) {
|
||||||
|
xml << set;
|
||||||
|
}
|
||||||
|
xml.writeEndElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cards.count() > 0) {
|
||||||
|
xml.writeStartElement("cards");
|
||||||
|
for (CardInfoPtr card : cards) {
|
||||||
|
xml << card;
|
||||||
|
}
|
||||||
|
xml.writeEndElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
xml.writeEndElement(); // cockatrice_carddatabase
|
||||||
|
xml.writeEndDocument();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
28
cockatrice/src/carddbparser/cockatricexml4.h
Normal file
28
cockatrice/src/carddbparser/cockatricexml4.h
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
#ifndef COCKATRICE_XML4_H
|
||||||
|
#define COCKATRICE_XML4_H
|
||||||
|
|
||||||
|
#include <QXmlStreamReader>
|
||||||
|
|
||||||
|
#include "carddatabaseparser.h"
|
||||||
|
|
||||||
|
class CockatriceXml4Parser : public ICardDatabaseParser
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_INTERFACES(ICardDatabaseParser)
|
||||||
|
public:
|
||||||
|
CockatriceXml4Parser() = default;
|
||||||
|
~CockatriceXml4Parser() override = default;
|
||||||
|
bool getCanParseFile(const QString &name, QIODevice &device) override;
|
||||||
|
void parseFile(QIODevice &device) override;
|
||||||
|
bool saveToFile(SetNameMap sets, CardNameMap cards, const QString &fileName) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QVariantHash loadCardPropertiesFromXml(QXmlStreamReader &xml);
|
||||||
|
void loadCardsFromXml(QXmlStreamReader &xml);
|
||||||
|
void loadSetsFromXml(QXmlStreamReader &xml);
|
||||||
|
signals:
|
||||||
|
void addCard(CardInfoPtr card) override;
|
||||||
|
void addSet(CardSetPtr set) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -1,47 +1,47 @@
|
||||||
#include "cardfilter.h"
|
#include "cardfilter.h"
|
||||||
|
|
||||||
const char *CardFilter::typeName(Type t)
|
const QString CardFilter::typeName(Type t)
|
||||||
{
|
{
|
||||||
switch (t) {
|
switch (t) {
|
||||||
case TypeAnd:
|
case TypeAnd:
|
||||||
return "AND";
|
return tr("AND", "Logical conjunction operator used in card filter");
|
||||||
case TypeOr:
|
case TypeOr:
|
||||||
return "OR";
|
return tr("OR", "Logical disjunction operator used in card filter");
|
||||||
case TypeAndNot:
|
case TypeAndNot:
|
||||||
return "AND NOT";
|
return tr("AND NOT", "Negated logical conjunction operator used in card filter");
|
||||||
case TypeOrNot:
|
case TypeOrNot:
|
||||||
return "OR NOT";
|
return tr("OR NOT", "Negated logical disjunction operator used in card filter");
|
||||||
default:
|
default:
|
||||||
return "";
|
return QString("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *CardFilter::attrName(Attr a)
|
const QString CardFilter::attrName(Attr a)
|
||||||
{
|
{
|
||||||
switch (a) {
|
switch (a) {
|
||||||
case AttrName:
|
case AttrName:
|
||||||
return "Name";
|
return tr("Name");
|
||||||
case AttrType:
|
case AttrType:
|
||||||
return "Type";
|
return tr("Type");
|
||||||
case AttrColor:
|
case AttrColor:
|
||||||
return "Color";
|
return tr("Color");
|
||||||
case AttrText:
|
case AttrText:
|
||||||
return "Text";
|
return tr("Text");
|
||||||
case AttrSet:
|
case AttrSet:
|
||||||
return "Set";
|
return tr("Set");
|
||||||
case AttrManaCost:
|
case AttrManaCost:
|
||||||
return "Mana Cost";
|
return tr("Mana Cost");
|
||||||
case AttrCmc:
|
case AttrCmc:
|
||||||
return "CMC";
|
return tr("CMC");
|
||||||
case AttrRarity:
|
case AttrRarity:
|
||||||
return "Rarity";
|
return tr("Rarity");
|
||||||
case AttrPow:
|
case AttrPow:
|
||||||
return "Power";
|
return tr("Power");
|
||||||
case AttrTough:
|
case AttrTough:
|
||||||
return "Toughness";
|
return tr("Toughness");
|
||||||
case AttrLoyalty:
|
case AttrLoyalty:
|
||||||
return "Loyalty";
|
return tr("Loyalty");
|
||||||
default:
|
default:
|
||||||
return "";
|
return QString("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,13 @@
|
||||||
#ifndef CARDFILTER_H
|
#ifndef CARDFILTER_H
|
||||||
#define CARDFILTER_H
|
#define CARDFILTER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
class CardFilter
|
class CardFilter : public QObject
|
||||||
{
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum Type
|
enum Type
|
||||||
{
|
{
|
||||||
|
|
@ -54,8 +57,8 @@ public:
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *typeName(Type t);
|
static const QString typeName(Type t);
|
||||||
static const char *attrName(Attr a);
|
static const QString attrName(Attr a);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "cardframe.h"
|
#include "cardframe.h"
|
||||||
|
|
||||||
#include "cardinfopicture.h"
|
#include "cardinfopicture.h"
|
||||||
|
|
@ -16,6 +18,7 @@ CardFrame::CardFrame(const QString &cardName, QWidget *parent) : QTabWidget(pare
|
||||||
pic->setObjectName("pic");
|
pic->setObjectName("pic");
|
||||||
text = new CardInfoText();
|
text = new CardInfoText();
|
||||||
text->setObjectName("text");
|
text->setObjectName("text");
|
||||||
|
connect(text, SIGNAL(linkActivated(const QString &)), this, SLOT(setCard(const QString &)));
|
||||||
|
|
||||||
tab1 = new QWidget(this);
|
tab1 = new QWidget(this);
|
||||||
tab2 = new QWidget(this);
|
tab2 = new QWidget(this);
|
||||||
|
|
@ -93,10 +96,10 @@ void CardFrame::setCard(CardInfoPtr card)
|
||||||
disconnect(info.data(), nullptr, this, nullptr);
|
disconnect(info.data(), nullptr, this, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
info = card;
|
info = std::move(card);
|
||||||
|
|
||||||
if (info) {
|
if (info) {
|
||||||
connect(info.data(), SIGNAL(destroyed()), this, SLOT(clear()));
|
connect(info.data(), SIGNAL(destroyed()), this, SLOT(clearCard()));
|
||||||
}
|
}
|
||||||
|
|
||||||
text->setCard(info);
|
text->setCard(info);
|
||||||
|
|
@ -115,7 +118,7 @@ void CardFrame::setCard(AbstractCardItem *card)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardFrame::clear()
|
void CardFrame::clearCard()
|
||||||
{
|
{
|
||||||
setCard((CardInfoPtr) nullptr);
|
setCard((CardInfoPtr) nullptr);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ public slots:
|
||||||
void setCard(CardInfoPtr card);
|
void setCard(CardInfoPtr card);
|
||||||
void setCard(const QString &cardName);
|
void setCard(const QString &cardName);
|
||||||
void setCard(AbstractCardItem *card);
|
void setCard(AbstractCardItem *card);
|
||||||
void clear();
|
void clearCard();
|
||||||
void setViewMode(int mode);
|
void setViewMode(int mode);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,137 +1,83 @@
|
||||||
#include "cardinfotext.h"
|
#include "cardinfotext.h"
|
||||||
|
|
||||||
#include "carditem.h"
|
#include "carditem.h"
|
||||||
|
#include "game_specific_terms.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
#include <QGridLayout>
|
#include <QGridLayout>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QTextEdit>
|
#include <QTextEdit>
|
||||||
|
|
||||||
CardInfoText::CardInfoText(QWidget *parent) : QFrame(parent), info(nullptr)
|
CardInfoText::CardInfoText(QWidget *parent) : QFrame(parent), info(nullptr)
|
||||||
{
|
{
|
||||||
nameLabel1 = new QLabel;
|
nameLabel = new QLabel;
|
||||||
nameLabel2 = new QLabel;
|
nameLabel->setOpenExternalLinks(false);
|
||||||
nameLabel2->setWordWrap(true);
|
connect(nameLabel, SIGNAL(linkActivated(const QString &)), this, SIGNAL(linkActivated(const QString &)));
|
||||||
nameLabel2->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
|
||||||
manacostLabel1 = new QLabel;
|
|
||||||
manacostLabel2 = new QLabel;
|
|
||||||
manacostLabel2->setWordWrap(true);
|
|
||||||
manacostLabel2->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
|
||||||
colorLabel1 = new QLabel;
|
|
||||||
colorLabel2 = new QLabel;
|
|
||||||
colorLabel2->setWordWrap(true);
|
|
||||||
colorLabel2->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
|
||||||
cardtypeLabel1 = new QLabel;
|
|
||||||
cardtypeLabel2 = new QLabel;
|
|
||||||
cardtypeLabel2->setWordWrap(true);
|
|
||||||
cardtypeLabel2->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
|
||||||
powtoughLabel1 = new QLabel;
|
|
||||||
powtoughLabel2 = new QLabel;
|
|
||||||
powtoughLabel2->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
|
||||||
loyaltyLabel1 = new QLabel;
|
|
||||||
loyaltyLabel2 = new QLabel;
|
|
||||||
loyaltyLabel1->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
|
||||||
|
|
||||||
textLabel = new QTextEdit();
|
textLabel = new QTextEdit();
|
||||||
textLabel->setReadOnly(true);
|
textLabel->setReadOnly(true);
|
||||||
|
|
||||||
QGridLayout *grid = new QGridLayout(this);
|
QGridLayout *grid = new QGridLayout(this);
|
||||||
int row = 0;
|
grid->addWidget(nameLabel, 0, 0);
|
||||||
grid->addWidget(nameLabel1, row, 0);
|
grid->addWidget(textLabel, 1, 0, -1, 2);
|
||||||
grid->addWidget(nameLabel2, row++, 1);
|
grid->setRowStretch(1, 1);
|
||||||
grid->addWidget(manacostLabel1, row, 0);
|
|
||||||
grid->addWidget(manacostLabel2, row++, 1);
|
|
||||||
grid->addWidget(colorLabel1, row, 0);
|
|
||||||
grid->addWidget(colorLabel2, row++, 1);
|
|
||||||
grid->addWidget(cardtypeLabel1, row, 0);
|
|
||||||
grid->addWidget(cardtypeLabel2, row++, 1);
|
|
||||||
grid->addWidget(powtoughLabel1, row, 0);
|
|
||||||
grid->addWidget(powtoughLabel2, row++, 1);
|
|
||||||
grid->addWidget(loyaltyLabel1, row, 0);
|
|
||||||
grid->addWidget(loyaltyLabel2, row++, 1);
|
|
||||||
grid->addWidget(textLabel, row, 0, -1, 2);
|
|
||||||
grid->setRowStretch(row, 1);
|
|
||||||
grid->setColumnStretch(1, 1);
|
grid->setColumnStretch(1, 1);
|
||||||
|
|
||||||
retranslateUi();
|
retranslateUi();
|
||||||
}
|
}
|
||||||
// Reset every label which is optionally hidden
|
|
||||||
void CardInfoText::resetLabels()
|
|
||||||
{
|
|
||||||
nameLabel1->show();
|
|
||||||
nameLabel2->show();
|
|
||||||
manacostLabel1->show();
|
|
||||||
manacostLabel2->show();
|
|
||||||
colorLabel1->show();
|
|
||||||
colorLabel2->show();
|
|
||||||
cardtypeLabel1->show();
|
|
||||||
cardtypeLabel2->show();
|
|
||||||
powtoughLabel1->show();
|
|
||||||
powtoughLabel2->show();
|
|
||||||
loyaltyLabel1->show();
|
|
||||||
loyaltyLabel2->show();
|
|
||||||
textLabel->show();
|
|
||||||
}
|
|
||||||
void CardInfoText::setCard(CardInfoPtr card)
|
void CardInfoText::setCard(CardInfoPtr card)
|
||||||
{
|
{
|
||||||
if (card) {
|
if (card == nullptr) {
|
||||||
resetLabels();
|
nameLabel->setText("");
|
||||||
nameLabel2->setText(card->getName());
|
textLabel->setText("");
|
||||||
if (!card->getManaCost().isEmpty()) {
|
return;
|
||||||
manacostLabel2->setText(card->getManaCost());
|
|
||||||
} else {
|
|
||||||
manacostLabel1->hide();
|
|
||||||
manacostLabel2->hide();
|
|
||||||
}
|
|
||||||
if (!card->getColors().isEmpty()) {
|
|
||||||
colorLabel2->setText(card->getColors().join(""));
|
|
||||||
} else {
|
|
||||||
colorLabel2->setText("Colorless");
|
|
||||||
}
|
|
||||||
cardtypeLabel2->setText(card->getCardType());
|
|
||||||
if (!card->getPowTough().isEmpty()) {
|
|
||||||
powtoughLabel2->setText(card->getPowTough());
|
|
||||||
} else {
|
|
||||||
powtoughLabel1->hide();
|
|
||||||
powtoughLabel2->hide();
|
|
||||||
}
|
|
||||||
if (!card->getLoyalty().isEmpty()) {
|
|
||||||
loyaltyLabel2->setText(card->getLoyalty());
|
|
||||||
} else {
|
|
||||||
loyaltyLabel1->hide();
|
|
||||||
loyaltyLabel2->hide();
|
|
||||||
}
|
|
||||||
textLabel->setText(card->getText());
|
|
||||||
} else {
|
|
||||||
nameLabel1->hide();
|
|
||||||
nameLabel2->hide();
|
|
||||||
manacostLabel1->hide();
|
|
||||||
manacostLabel2->hide();
|
|
||||||
colorLabel1->hide();
|
|
||||||
colorLabel2->hide();
|
|
||||||
cardtypeLabel1->hide();
|
|
||||||
cardtypeLabel2->hide();
|
|
||||||
powtoughLabel1->hide();
|
|
||||||
powtoughLabel2->hide();
|
|
||||||
loyaltyLabel1->hide();
|
|
||||||
loyaltyLabel2->hide();
|
|
||||||
textLabel->hide();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString text = "<table width=\"100%\" border=0 cellspacing=0 cellpadding=0>";
|
||||||
|
text += QString("<tr><td>%1</td><td width=\"5\"></td><td>%2</td></tr>")
|
||||||
|
.arg(tr("Name:"), card->getName().toHtmlEscaped());
|
||||||
|
|
||||||
|
QStringList cardProps = card->getProperties();
|
||||||
|
foreach (QString key, cardProps) {
|
||||||
|
QString keyText = Mtg::getNicePropertyName(key).toHtmlEscaped() + ":";
|
||||||
|
text +=
|
||||||
|
QString("<tr><td>%1</td><td></td><td>%2</td></tr>").arg(keyText, card->getProperty(key).toHtmlEscaped());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto relatedCards = card->getRelatedCards();
|
||||||
|
auto reverserelatedCards2Me = card->getReverseRelatedCards2Me();
|
||||||
|
if (relatedCards.size() || reverserelatedCards2Me.size()) {
|
||||||
|
text += QString("<tr><td>%1</td><td width=\"5\"></td><td>").arg(tr("Related cards:"));
|
||||||
|
|
||||||
|
for (int i = 0; i < relatedCards.size(); ++i) {
|
||||||
|
QString tmp = relatedCards.at(i)->getName().toHtmlEscaped();
|
||||||
|
text += "<a href=\"" + tmp + "\">" + tmp + "</a><br>";
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < reverserelatedCards2Me.size(); ++i) {
|
||||||
|
QString tmp = reverserelatedCards2Me.at(i)->getName().toHtmlEscaped();
|
||||||
|
text += "<a href=\"" + tmp + "\">" + tmp + "</a><br>";
|
||||||
|
}
|
||||||
|
|
||||||
|
text += "</td></tr>";
|
||||||
|
}
|
||||||
|
|
||||||
|
text += "</table>";
|
||||||
|
nameLabel->setText(text);
|
||||||
|
textLabel->setText(card->getText());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardInfoText::setInvalidCardName(const QString &cardName)
|
void CardInfoText::setInvalidCardName(const QString &cardName)
|
||||||
{
|
{
|
||||||
nameLabel1->setText(tr("Unknown card:"));
|
nameLabel->setText(tr("Unknown card:") + " " + cardName);
|
||||||
nameLabel1->show();
|
textLabel->setText("");
|
||||||
nameLabel2->setText(cardName);
|
|
||||||
nameLabel2->show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardInfoText::retranslateUi()
|
void CardInfoText::retranslateUi()
|
||||||
{
|
{
|
||||||
nameLabel1->setText(tr("Name:"));
|
/*
|
||||||
manacostLabel1->setText(tr("Mana cost:"));
|
* There's no way we can really translate the text currently being rendered.
|
||||||
colorLabel1->setText(tr("Color(s):"));
|
* The best we can do is invalidate the current text.
|
||||||
cardtypeLabel1->setText(tr("Card type:"));
|
*/
|
||||||
powtoughLabel1->setText(tr("P / T:"));
|
setInvalidCardName("");
|
||||||
loyaltyLabel1->setText(tr("Loyalty:"));
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,23 +12,17 @@ class CardInfoText : public QFrame
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QLabel *nameLabel1, *nameLabel2;
|
QLabel *nameLabel;
|
||||||
QLabel *manacostLabel1, *manacostLabel2;
|
|
||||||
QLabel *colorLabel1, *colorLabel2;
|
|
||||||
QLabel *cardtypeLabel1, *cardtypeLabel2;
|
|
||||||
QLabel *powtoughLabel1, *powtoughLabel2;
|
|
||||||
QLabel *loyaltyLabel1, *loyaltyLabel2;
|
|
||||||
QTextEdit *textLabel;
|
QTextEdit *textLabel;
|
||||||
|
|
||||||
CardInfoPtr info;
|
CardInfoPtr info;
|
||||||
|
|
||||||
void resetLabels();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CardInfoText(QWidget *parent = 0);
|
CardInfoText(QWidget *parent = 0);
|
||||||
void retranslateUi();
|
void retranslateUi();
|
||||||
void setInvalidCardName(const QString &cardName);
|
void setInvalidCardName(const QString &cardName);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void linkActivated(const QString &link);
|
||||||
public slots:
|
public slots:
|
||||||
void setCard(CardInfoPtr card);
|
void setCard(CardInfoPtr card);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
#include "cardinfowidget.h"
|
#include <utility>
|
||||||
|
|
||||||
#include "cardinfopicture.h"
|
#include "cardinfopicture.h"
|
||||||
#include "cardinfotext.h"
|
#include "cardinfotext.h"
|
||||||
|
#include "cardinfowidget.h"
|
||||||
#include "carditem.h"
|
#include "carditem.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include <QDesktopWidget>
|
#include <QDesktopWidget>
|
||||||
|
|
@ -14,8 +16,9 @@ CardInfoWidget::CardInfoWidget(const QString &cardName, QWidget *parent, Qt::Win
|
||||||
pic->setObjectName("pic");
|
pic->setObjectName("pic");
|
||||||
text = new CardInfoText();
|
text = new CardInfoText();
|
||||||
text->setObjectName("text");
|
text->setObjectName("text");
|
||||||
|
connect(text, SIGNAL(linkActivated(const QString &)), this, SLOT(setCard(const QString &)));
|
||||||
|
|
||||||
QVBoxLayout *layout = new QVBoxLayout();
|
auto *layout = new QVBoxLayout();
|
||||||
layout->setObjectName("layout");
|
layout->setObjectName("layout");
|
||||||
layout->setContentsMargins(0, 0, 0, 0);
|
layout->setContentsMargins(0, 0, 0, 0);
|
||||||
layout->setSpacing(0);
|
layout->setSpacing(0);
|
||||||
|
|
@ -26,7 +29,7 @@ CardInfoWidget::CardInfoWidget(const QString &cardName, QWidget *parent, Qt::Win
|
||||||
setFrameStyle(QFrame::Panel | QFrame::Raised);
|
setFrameStyle(QFrame::Panel | QFrame::Raised);
|
||||||
QDesktopWidget desktopWidget;
|
QDesktopWidget desktopWidget;
|
||||||
int pixmapHeight = desktopWidget.screenGeometry().height() / 3;
|
int pixmapHeight = desktopWidget.screenGeometry().height() / 3;
|
||||||
int pixmapWidth = pixmapHeight / aspectRatio;
|
int pixmapWidth = static_cast<int>(pixmapHeight / aspectRatio);
|
||||||
pic->setFixedWidth(pixmapWidth);
|
pic->setFixedWidth(pixmapWidth);
|
||||||
pic->setFixedHeight(pixmapHeight);
|
pic->setFixedHeight(pixmapHeight);
|
||||||
setFixedWidth(pixmapWidth + 150);
|
setFixedWidth(pixmapWidth + 150);
|
||||||
|
|
@ -41,7 +44,7 @@ void CardInfoWidget::setCard(CardInfoPtr card)
|
||||||
{
|
{
|
||||||
if (info)
|
if (info)
|
||||||
disconnect(info.data(), nullptr, this, nullptr);
|
disconnect(info.data(), nullptr, this, nullptr);
|
||||||
info = card;
|
info = std::move(card);
|
||||||
if (info)
|
if (info)
|
||||||
connect(info.data(), SIGNAL(destroyed()), this, SLOT(clear()));
|
connect(info.data(), SIGNAL(destroyed()), this, SLOT(clear()));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ private:
|
||||||
CardInfoText *text;
|
CardInfoText *text;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CardInfoWidget(const QString &cardName, QWidget *parent = 0, Qt::WindowFlags f = 0);
|
explicit CardInfoWidget(const QString &cardName, QWidget *parent = nullptr, Qt::WindowFlags f = nullptr);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setCard(CardInfoPtr card);
|
void setCard(CardInfoPtr card);
|
||||||
|
|
|
||||||
|
|
@ -322,9 +322,7 @@ QModelIndex DeckListModel::addCard(const QString &cardName, const QString &zoneN
|
||||||
// This is usually called from tab_deck_editor
|
// This is usually called from tab_deck_editor
|
||||||
// So we'll create a new CardInfo with the name
|
// So we'll create a new CardInfo with the name
|
||||||
// and default values for all fields
|
// and default values for all fields
|
||||||
info = CardInfo::newInstance(cardName, false, nullptr, nullptr, "unknown", nullptr, nullptr, QStringList(),
|
info = CardInfo::newInstance(cardName);
|
||||||
QList<CardRelation *>(), QList<CardRelation *>(), false, 0, false, 0,
|
|
||||||
SetList(), QStringMap(), MuidMap(), QStringMap(), QStringMap());
|
|
||||||
} else {
|
} else {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
|
|
||||||
class DeckLoader;
|
class DeckLoader;
|
||||||
class CardDatabase;
|
class CardDatabase;
|
||||||
class QProgressDialog;
|
|
||||||
class QPrinter;
|
class QPrinter;
|
||||||
class QTextCursor;
|
class QTextCursor;
|
||||||
|
|
||||||
|
|
@ -21,19 +20,19 @@ public:
|
||||||
: AbstractDecklistCardNode(_parent), dataNode(_dataNode)
|
: AbstractDecklistCardNode(_parent), dataNode(_dataNode)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
int getNumber() const
|
int getNumber() const override
|
||||||
{
|
{
|
||||||
return dataNode->getNumber();
|
return dataNode->getNumber();
|
||||||
}
|
}
|
||||||
void setNumber(int _number)
|
void setNumber(int _number) override
|
||||||
{
|
{
|
||||||
dataNode->setNumber(_number);
|
dataNode->setNumber(_number);
|
||||||
}
|
}
|
||||||
QString getName() const
|
QString getName() const override
|
||||||
{
|
{
|
||||||
return dataNode->getName();
|
return dataNode->getName();
|
||||||
}
|
}
|
||||||
void setName(const QString &_name)
|
void setName(const QString &_name) override
|
||||||
{
|
{
|
||||||
dataNode->setName(_name);
|
dataNode->setName(_name);
|
||||||
}
|
}
|
||||||
|
|
@ -54,20 +53,20 @@ signals:
|
||||||
void deckHashChanged();
|
void deckHashChanged();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DeckListModel(QObject *parent = 0);
|
explicit DeckListModel(QObject *parent = nullptr);
|
||||||
~DeckListModel();
|
~DeckListModel() override;
|
||||||
int rowCount(const QModelIndex &parent) const;
|
int rowCount(const QModelIndex &parent) const override;
|
||||||
int columnCount(const QModelIndex & /*parent*/ = QModelIndex()) const;
|
int columnCount(const QModelIndex & /*parent*/ = QModelIndex()) const override;
|
||||||
QVariant data(const QModelIndex &index, int role) const;
|
QVariant data(const QModelIndex &index, int role) const override;
|
||||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
|
||||||
QModelIndex index(int row, int column, const QModelIndex &parent) const;
|
QModelIndex index(int row, int column, const QModelIndex &parent) const override;
|
||||||
QModelIndex parent(const QModelIndex &index) const;
|
QModelIndex parent(const QModelIndex &index) const override;
|
||||||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||||
bool setData(const QModelIndex &index, const QVariant &value, int role);
|
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
|
||||||
bool removeRows(int row, int count, const QModelIndex &parent);
|
bool removeRows(int row, int count, const QModelIndex &parent) override;
|
||||||
QModelIndex findCard(const QString &cardName, const QString &zoneName) const;
|
QModelIndex findCard(const QString &cardName, const QString &zoneName) const;
|
||||||
QModelIndex addCard(const QString &cardName, const QString &zoneName, bool abAddAnyway = false);
|
QModelIndex addCard(const QString &cardName, const QString &zoneName, bool abAddAnyway = false);
|
||||||
void sort(int column, Qt::SortOrder order);
|
void sort(int column, Qt::SortOrder order) override;
|
||||||
void cleanList();
|
void cleanList();
|
||||||
DeckLoader *getDeckList() const
|
DeckLoader *getDeckList() const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,6 @@
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QRadioButton>
|
#include <QRadioButton>
|
||||||
|
|
||||||
#define PUBLIC_SERVERS_URL "https://github.com/Cockatrice/Cockatrice/wiki/Public-Servers"
|
|
||||||
|
|
||||||
DlgConnect::DlgConnect(QWidget *parent) : QDialog(parent)
|
DlgConnect::DlgConnect(QWidget *parent) : QDialog(parent)
|
||||||
{
|
{
|
||||||
previousHostButton = new QRadioButton(tr("Known Hosts"), this);
|
previousHostButton = new QRadioButton(tr("Known Hosts"), this);
|
||||||
|
|
@ -273,15 +271,15 @@ void DlgConnect::newHostSelected(bool state)
|
||||||
previousHosts->setDisabled(true);
|
previousHosts->setDisabled(true);
|
||||||
btnRefreshServers->setDisabled(true);
|
btnRefreshServers->setDisabled(true);
|
||||||
hostEdit->clear();
|
hostEdit->clear();
|
||||||
hostEdit->setPlaceholderText("Server URL");
|
hostEdit->setPlaceholderText(tr("Server URL"));
|
||||||
hostEdit->setDisabled(false);
|
hostEdit->setDisabled(false);
|
||||||
portEdit->clear();
|
portEdit->clear();
|
||||||
portEdit->setPlaceholderText("Communication Port");
|
portEdit->setPlaceholderText(tr("Communication Port"));
|
||||||
portEdit->setDisabled(false);
|
portEdit->setDisabled(false);
|
||||||
playernameEdit->clear();
|
playernameEdit->clear();
|
||||||
passwordEdit->clear();
|
passwordEdit->clear();
|
||||||
saveEdit->clear();
|
saveEdit->clear();
|
||||||
saveEdit->setPlaceholderText("Unique Server Name");
|
saveEdit->setPlaceholderText(tr("Unique Server Name"));
|
||||||
saveEdit->setDisabled(false);
|
saveEdit->setDisabled(false);
|
||||||
serverContactLabel->setText("");
|
serverContactLabel->setText("");
|
||||||
serverContactLink->setText("");
|
serverContactLink->setText("");
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
#include <QTreeView>
|
#include <QTreeView>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
DlgEditTokens::DlgEditTokens(QWidget *parent) : QDialog(parent), currentCard(0)
|
DlgEditTokens::DlgEditTokens(QWidget *parent) : QDialog(parent), currentCard(nullptr)
|
||||||
{
|
{
|
||||||
nameLabel = new QLabel(tr("&Name:"));
|
nameLabel = new QLabel(tr("&Name:"));
|
||||||
nameEdit = new QLineEdit;
|
nameEdit = new QLineEdit;
|
||||||
|
|
@ -46,7 +46,7 @@ DlgEditTokens::DlgEditTokens(QWidget *parent) : QDialog(parent), currentCard(0)
|
||||||
annotationLabel->setBuddy(annotationEdit);
|
annotationLabel->setBuddy(annotationEdit);
|
||||||
connect(annotationEdit, SIGNAL(textChanged(QString)), this, SLOT(annotationChanged(QString)));
|
connect(annotationEdit, SIGNAL(textChanged(QString)), this, SLOT(annotationChanged(QString)));
|
||||||
|
|
||||||
QGridLayout *grid = new QGridLayout;
|
auto *grid = new QGridLayout;
|
||||||
grid->addWidget(nameLabel, 0, 0);
|
grid->addWidget(nameLabel, 0, 0);
|
||||||
grid->addWidget(nameEdit, 0, 1);
|
grid->addWidget(nameEdit, 0, 1);
|
||||||
grid->addWidget(colorLabel, 1, 0);
|
grid->addWidget(colorLabel, 1, 0);
|
||||||
|
|
@ -89,15 +89,15 @@ DlgEditTokens::DlgEditTokens(QWidget *parent) : QDialog(parent), currentCard(0)
|
||||||
aRemoveToken->setIcon(QPixmap("theme:icons/decrement"));
|
aRemoveToken->setIcon(QPixmap("theme:icons/decrement"));
|
||||||
connect(aRemoveToken, SIGNAL(triggered()), this, SLOT(actRemoveToken()));
|
connect(aRemoveToken, SIGNAL(triggered()), this, SLOT(actRemoveToken()));
|
||||||
|
|
||||||
QToolBar *databaseToolBar = new QToolBar;
|
auto *databaseToolBar = new QToolBar;
|
||||||
databaseToolBar->addAction(aAddToken);
|
databaseToolBar->addAction(aAddToken);
|
||||||
databaseToolBar->addAction(aRemoveToken);
|
databaseToolBar->addAction(aRemoveToken);
|
||||||
|
|
||||||
QVBoxLayout *leftVBox = new QVBoxLayout;
|
auto *leftVBox = new QVBoxLayout;
|
||||||
leftVBox->addWidget(chooseTokenView);
|
leftVBox->addWidget(chooseTokenView);
|
||||||
leftVBox->addWidget(databaseToolBar);
|
leftVBox->addWidget(databaseToolBar);
|
||||||
|
|
||||||
QHBoxLayout *hbox = new QHBoxLayout;
|
auto *hbox = new QHBoxLayout;
|
||||||
hbox->addLayout(leftVBox);
|
hbox->addLayout(leftVBox);
|
||||||
hbox->addWidget(tokenDataGroupBox);
|
hbox->addWidget(tokenDataGroupBox);
|
||||||
|
|
||||||
|
|
@ -105,7 +105,7 @@ DlgEditTokens::DlgEditTokens(QWidget *parent) : QDialog(parent), currentCard(0)
|
||||||
connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
||||||
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
||||||
|
|
||||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
auto *mainLayout = new QVBoxLayout;
|
||||||
mainLayout->addLayout(hbox);
|
mainLayout->addLayout(hbox);
|
||||||
mainLayout->addWidget(buttonBox);
|
mainLayout->addWidget(buttonBox);
|
||||||
|
|
||||||
|
|
@ -154,9 +154,10 @@ void DlgEditTokens::actAddToken()
|
||||||
}
|
}
|
||||||
} while (askAgain);
|
} while (askAgain);
|
||||||
|
|
||||||
CardInfoPtr card = CardInfo::newInstance(name, true);
|
CardInfoPtr card = CardInfo::newInstance(name, "", true);
|
||||||
card->addToSet(databaseModel->getDatabase()->getSet(CardDatabase::TOKENS_SETNAME));
|
|
||||||
card->setCardType("Token");
|
card->setCardType("Token");
|
||||||
|
card->addToSet(databaseModel->getDatabase()->getSet(CardDatabase::TOKENS_SETNAME));
|
||||||
|
|
||||||
databaseModel->getDatabase()->addCard(card);
|
databaseModel->getDatabase()->addCard(card);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -172,7 +173,7 @@ void DlgEditTokens::actRemoveToken()
|
||||||
void DlgEditTokens::colorChanged(int colorIndex)
|
void DlgEditTokens::colorChanged(int colorIndex)
|
||||||
{
|
{
|
||||||
if (currentCard)
|
if (currentCard)
|
||||||
currentCard->setColors(QStringList() << QString(colorEdit->itemData(colorIndex).toChar()));
|
currentCard->setColors(QString(colorEdit->itemData(colorIndex).toChar()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DlgEditTokens::ptChanged(const QString &_pt)
|
void DlgEditTokens::ptChanged(const QString &_pt)
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ private:
|
||||||
QTreeView *chooseTokenView;
|
QTreeView *chooseTokenView;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DlgEditTokens(QWidget *parent = nullptr);
|
explicit DlgEditTokens(QWidget *parent = nullptr);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ DlgLoadDeckFromClipboard::DlgLoadDeckFromClipboard(QWidget *parent) : QDialog(pa
|
||||||
resize(500, 500);
|
resize(500, 500);
|
||||||
|
|
||||||
actRefresh();
|
actRefresh();
|
||||||
connect(&settingsCache->shortcuts(), SIGNAL(shortCutchanged()), this, SLOT(refreshShortcuts()));
|
connect(&settingsCache->shortcuts(), SIGNAL(shortCutChanged()), this, SLOT(refreshShortcuts()));
|
||||||
refreshShortcuts();
|
refreshShortcuts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,8 +45,6 @@ GeneralSettingsPage::GeneralSettingsPage()
|
||||||
languageBox.setCurrentIndex(i);
|
languageBox.setCurrentIndex(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
picDownloadCheckBox.setChecked(settingsCache->getPicDownload());
|
|
||||||
|
|
||||||
// updates
|
// updates
|
||||||
QList<ReleaseChannel *> channels = settingsCache->getUpdateReleaseChannels();
|
QList<ReleaseChannel *> channels = settingsCache->getUpdateReleaseChannels();
|
||||||
foreach (ReleaseChannel *chan, channels) {
|
foreach (ReleaseChannel *chan, channels) {
|
||||||
|
|
@ -55,6 +53,7 @@ GeneralSettingsPage::GeneralSettingsPage()
|
||||||
updateReleaseChannelBox.setCurrentIndex(settingsCache->getUpdateReleaseChannel()->getIndex());
|
updateReleaseChannelBox.setCurrentIndex(settingsCache->getUpdateReleaseChannel()->getIndex());
|
||||||
|
|
||||||
updateNotificationCheckBox.setChecked(settingsCache->getNotifyAboutUpdates());
|
updateNotificationCheckBox.setChecked(settingsCache->getNotifyAboutUpdates());
|
||||||
|
newVersionOracleCheckBox.setChecked(settingsCache->getNotifyAboutNewVersion());
|
||||||
|
|
||||||
// pixmap cache
|
// pixmap cache
|
||||||
pixmapCacheEdit.setMinimum(PIXMAPCACHE_SIZE_MIN);
|
pixmapCacheEdit.setMinimum(PIXMAPCACHE_SIZE_MIN);
|
||||||
|
|
@ -64,27 +63,16 @@ GeneralSettingsPage::GeneralSettingsPage()
|
||||||
pixmapCacheEdit.setValue(settingsCache->getPixmapCacheSize());
|
pixmapCacheEdit.setValue(settingsCache->getPixmapCacheSize());
|
||||||
pixmapCacheEdit.setSuffix(" MB");
|
pixmapCacheEdit.setSuffix(" MB");
|
||||||
|
|
||||||
defaultUrlEdit = new QLineEdit(settingsCache->getPicUrl());
|
|
||||||
fallbackUrlEdit = new QLineEdit(settingsCache->getPicUrlFallback());
|
|
||||||
|
|
||||||
showTipsOnStartup.setChecked(settingsCache->getShowTipsOnStartup());
|
showTipsOnStartup.setChecked(settingsCache->getShowTipsOnStartup());
|
||||||
|
|
||||||
connect(&clearDownloadedPicsButton, SIGNAL(clicked()), this, SLOT(clearDownloadedPicsButtonClicked()));
|
|
||||||
connect(&languageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(languageBoxChanged(int)));
|
connect(&languageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(languageBoxChanged(int)));
|
||||||
connect(&picDownloadCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setPicDownload(int)));
|
|
||||||
connect(&pixmapCacheEdit, SIGNAL(valueChanged(int)), settingsCache, SLOT(setPixmapCacheSize(int)));
|
connect(&pixmapCacheEdit, SIGNAL(valueChanged(int)), settingsCache, SLOT(setPixmapCacheSize(int)));
|
||||||
connect(&updateReleaseChannelBox, SIGNAL(currentIndexChanged(int)), settingsCache,
|
connect(&updateReleaseChannelBox, SIGNAL(currentIndexChanged(int)), settingsCache,
|
||||||
SLOT(setUpdateReleaseChannel(int)));
|
SLOT(setUpdateReleaseChannel(int)));
|
||||||
connect(&updateNotificationCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setNotifyAboutUpdate(int)));
|
connect(&updateNotificationCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setNotifyAboutUpdate(int)));
|
||||||
connect(&picDownloadCheckBox, SIGNAL(clicked(bool)), this, SLOT(setEnabledStatus(bool)));
|
connect(&newVersionOracleCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setNotifyAboutNewVersion(int)));
|
||||||
connect(defaultUrlEdit, SIGNAL(textChanged(QString)), settingsCache, SLOT(setPicUrl(QString)));
|
|
||||||
connect(fallbackUrlEdit, SIGNAL(textChanged(QString)), settingsCache, SLOT(setPicUrlFallback(QString)));
|
|
||||||
connect(&defaultUrlRestoreButton, SIGNAL(clicked()), this, SLOT(defaultUrlRestoreButtonClicked()));
|
|
||||||
connect(&fallbackUrlRestoreButton, SIGNAL(clicked()), this, SLOT(fallbackUrlRestoreButtonClicked()));
|
|
||||||
connect(&showTipsOnStartup, SIGNAL(clicked(bool)), settingsCache, SLOT(setShowTipsOnStartup(bool)));
|
connect(&showTipsOnStartup, SIGNAL(clicked(bool)), settingsCache, SLOT(setShowTipsOnStartup(bool)));
|
||||||
|
|
||||||
setEnabledStatus(settingsCache->getPicDownload());
|
|
||||||
|
|
||||||
auto *personalGrid = new QGridLayout;
|
auto *personalGrid = new QGridLayout;
|
||||||
personalGrid->addWidget(&languageLabel, 0, 0);
|
personalGrid->addWidget(&languageLabel, 0, 0);
|
||||||
personalGrid->addWidget(&languageBox, 0, 1);
|
personalGrid->addWidget(&languageBox, 0, 1);
|
||||||
|
|
@ -93,19 +81,8 @@ GeneralSettingsPage::GeneralSettingsPage()
|
||||||
personalGrid->addWidget(&pixmapCacheLabel, 2, 0);
|
personalGrid->addWidget(&pixmapCacheLabel, 2, 0);
|
||||||
personalGrid->addWidget(&pixmapCacheEdit, 2, 1);
|
personalGrid->addWidget(&pixmapCacheEdit, 2, 1);
|
||||||
personalGrid->addWidget(&updateNotificationCheckBox, 3, 0);
|
personalGrid->addWidget(&updateNotificationCheckBox, 3, 0);
|
||||||
personalGrid->addWidget(&showTipsOnStartup, 4, 0);
|
personalGrid->addWidget(&newVersionOracleCheckBox, 4, 0);
|
||||||
personalGrid->addWidget(&picDownloadCheckBox, 5, 0);
|
personalGrid->addWidget(&showTipsOnStartup, 5, 0);
|
||||||
personalGrid->addWidget(&urlLinkLabel, 5, 1);
|
|
||||||
personalGrid->addWidget(&defaultUrlLabel, 6, 0, 1, 1);
|
|
||||||
personalGrid->addWidget(defaultUrlEdit, 6, 1, 1, 1);
|
|
||||||
personalGrid->addWidget(&defaultUrlRestoreButton, 6, 2, 1, 1);
|
|
||||||
personalGrid->addWidget(&fallbackUrlLabel, 7, 0, 1, 1);
|
|
||||||
personalGrid->addWidget(fallbackUrlEdit, 7, 1, 1, 1);
|
|
||||||
personalGrid->addWidget(&fallbackUrlRestoreButton, 7, 2, 1, 1);
|
|
||||||
personalGrid->addWidget(&clearDownloadedPicsButton, 8, 1);
|
|
||||||
|
|
||||||
urlLinkLabel.setTextInteractionFlags(Qt::LinksAccessibleByMouse);
|
|
||||||
urlLinkLabel.setOpenExternalLinks(true);
|
|
||||||
|
|
||||||
personalGroupBox = new QGroupBox;
|
personalGroupBox = new QGroupBox;
|
||||||
personalGroupBox->setLayout(personalGrid);
|
personalGroupBox->setLayout(personalGrid);
|
||||||
|
|
@ -194,20 +171,6 @@ QString GeneralSettingsPage::languageName(const QString &qmFile)
|
||||||
return translator.translate("i18n", DEFAULT_LANG_NAME);
|
return translator.translate("i18n", DEFAULT_LANG_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeneralSettingsPage::defaultUrlRestoreButtonClicked()
|
|
||||||
{
|
|
||||||
QString path = PIC_URL_DEFAULT;
|
|
||||||
defaultUrlEdit->setText(path);
|
|
||||||
settingsCache->setPicUrl(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GeneralSettingsPage::fallbackUrlRestoreButtonClicked()
|
|
||||||
{
|
|
||||||
QString path = PIC_URL_FALLBACK;
|
|
||||||
fallbackUrlEdit->setText(path);
|
|
||||||
settingsCache->setPicUrlFallback(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GeneralSettingsPage::deckPathButtonClicked()
|
void GeneralSettingsPage::deckPathButtonClicked()
|
||||||
{
|
{
|
||||||
QString path = QFileDialog::getExistingDirectory(this, tr("Choose path"));
|
QString path = QFileDialog::getExistingDirectory(this, tr("Choose path"));
|
||||||
|
|
@ -238,30 +201,6 @@ void GeneralSettingsPage::picsPathButtonClicked()
|
||||||
settingsCache->setPicsPath(path);
|
settingsCache->setPicsPath(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeneralSettingsPage::clearDownloadedPicsButtonClicked()
|
|
||||||
{
|
|
||||||
QString picsPath = settingsCache->getPicsPath() + "/downloadedPics/";
|
|
||||||
QStringList dirs = QDir(picsPath).entryList(QDir::AllDirs | QDir::NoDotAndDotDot);
|
|
||||||
bool outerSuccessRemove = true;
|
|
||||||
for (int i = 0; i < dirs.length(); i++) {
|
|
||||||
QString currentPath = picsPath + dirs.at(i) + "/";
|
|
||||||
QStringList files = QDir(currentPath).entryList(QDir::Files);
|
|
||||||
bool innerSuccessRemove = true;
|
|
||||||
for (int j = 0; j < files.length(); j++)
|
|
||||||
if (!QDir(currentPath).remove(files.at(j))) {
|
|
||||||
qDebug() << "Failed to remove " + currentPath.toUtf8() + files.at(j).toUtf8();
|
|
||||||
outerSuccessRemove = false;
|
|
||||||
innerSuccessRemove = false;
|
|
||||||
}
|
|
||||||
if (innerSuccessRemove)
|
|
||||||
QDir(picsPath).rmdir(dirs.at(i));
|
|
||||||
}
|
|
||||||
if (outerSuccessRemove)
|
|
||||||
QMessageBox::information(this, tr("Success"), tr("Downloaded card pictures have been reset."));
|
|
||||||
else
|
|
||||||
QMessageBox::critical(this, tr("Error"), tr("One or more downloaded card pictures could not be cleared."));
|
|
||||||
}
|
|
||||||
|
|
||||||
void GeneralSettingsPage::cardDatabasePathButtonClicked()
|
void GeneralSettingsPage::cardDatabasePathButtonClicked()
|
||||||
{
|
{
|
||||||
QString path = QFileDialog::getOpenFileName(this, tr("Choose path"));
|
QString path = QFileDialog::getOpenFileName(this, tr("Choose path"));
|
||||||
|
|
@ -291,7 +230,6 @@ void GeneralSettingsPage::retranslateUi()
|
||||||
{
|
{
|
||||||
personalGroupBox->setTitle(tr("Personal settings"));
|
personalGroupBox->setTitle(tr("Personal settings"));
|
||||||
languageLabel.setText(tr("Language:"));
|
languageLabel.setText(tr("Language:"));
|
||||||
picDownloadCheckBox.setText(tr("Download card pictures on the fly"));
|
|
||||||
|
|
||||||
if (settingsCache->getIsPortableBuild()) {
|
if (settingsCache->getIsPortableBuild()) {
|
||||||
pathsGroupBox->setTitle(tr("Paths (editing disabled in portable mode)"));
|
pathsGroupBox->setTitle(tr("Paths (editing disabled in portable mode)"));
|
||||||
|
|
@ -305,26 +243,12 @@ void GeneralSettingsPage::retranslateUi()
|
||||||
cardDatabasePathLabel.setText(tr("Card database:"));
|
cardDatabasePathLabel.setText(tr("Card database:"));
|
||||||
tokenDatabasePathLabel.setText(tr("Token database:"));
|
tokenDatabasePathLabel.setText(tr("Token database:"));
|
||||||
pixmapCacheLabel.setText(tr("Picture cache size:"));
|
pixmapCacheLabel.setText(tr("Picture cache size:"));
|
||||||
defaultUrlLabel.setText(tr("Primary download URL:"));
|
|
||||||
fallbackUrlLabel.setText(tr("Fallback download URL:"));
|
|
||||||
urlLinkLabel.setText(
|
|
||||||
QString("<a href='%1'>%2</a>").arg(WIKI_CUSTOM_PIC_URL).arg(tr("How to set a custom picture url")));
|
|
||||||
clearDownloadedPicsButton.setText(tr("Reset/clear downloaded pictures"));
|
|
||||||
updateReleaseChannelLabel.setText(tr("Update channel"));
|
updateReleaseChannelLabel.setText(tr("Update channel"));
|
||||||
updateNotificationCheckBox.setText(tr("Notify if a feature supported by the server is missing in my client"));
|
updateNotificationCheckBox.setText(tr("Notify if a feature supported by the server is missing in my client"));
|
||||||
defaultUrlRestoreButton.setText(tr("Reset"));
|
newVersionOracleCheckBox.setText(tr("Automatically run Oracle when running a new version of Cockatrice"));
|
||||||
fallbackUrlRestoreButton.setText(tr("Reset"));
|
|
||||||
showTipsOnStartup.setText(tr("Show tips on startup"));
|
showTipsOnStartup.setText(tr("Show tips on startup"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeneralSettingsPage::setEnabledStatus(bool status)
|
|
||||||
{
|
|
||||||
defaultUrlEdit->setEnabled(status);
|
|
||||||
fallbackUrlEdit->setEnabled(status);
|
|
||||||
defaultUrlRestoreButton.setEnabled(status);
|
|
||||||
fallbackUrlRestoreButton.setEnabled(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
AppearanceSettingsPage::AppearanceSettingsPage()
|
AppearanceSettingsPage::AppearanceSettingsPage()
|
||||||
{
|
{
|
||||||
QString themeName = settingsCache->getThemeName();
|
QString themeName = settingsCache->getThemeName();
|
||||||
|
|
@ -498,6 +422,15 @@ void UserInterfaceSettingsPage::retranslateUi()
|
||||||
|
|
||||||
DeckEditorSettingsPage::DeckEditorSettingsPage()
|
DeckEditorSettingsPage::DeckEditorSettingsPage()
|
||||||
{
|
{
|
||||||
|
picDownloadCheckBox.setChecked(settingsCache->getPicDownload());
|
||||||
|
connect(&picDownloadCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setPicDownload(int)));
|
||||||
|
|
||||||
|
urlLinkLabel.setTextInteractionFlags(Qt::LinksAccessibleByMouse);
|
||||||
|
urlLinkLabel.setOpenExternalLinks(true);
|
||||||
|
|
||||||
|
connect(&clearDownloadedPicsButton, SIGNAL(clicked()), this, SLOT(clearDownloadedPicsButtonClicked()));
|
||||||
|
connect(&resetDownloadURLs, SIGNAL(clicked()), this, SLOT(resetDownloadedURLsButtonClicked()));
|
||||||
|
|
||||||
auto *lpGeneralGrid = new QGridLayout;
|
auto *lpGeneralGrid = new QGridLayout;
|
||||||
auto *lpSpoilerGrid = new QGridLayout;
|
auto *lpSpoilerGrid = new QGridLayout;
|
||||||
|
|
||||||
|
|
@ -515,9 +448,46 @@ DeckEditorSettingsPage::DeckEditorSettingsPage()
|
||||||
// Update the GUI depending on if the box is ticked or not
|
// Update the GUI depending on if the box is ticked or not
|
||||||
setSpoilersEnabled(mcDownloadSpoilersCheckBox.isChecked());
|
setSpoilersEnabled(mcDownloadSpoilersCheckBox.isChecked());
|
||||||
|
|
||||||
// Create the layout
|
urlList = new QListWidget;
|
||||||
lpGeneralGrid->addWidget(&mcGeneralMessageLabel, 0, 0);
|
urlList->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||||
|
urlList->setAlternatingRowColors(true);
|
||||||
|
urlList->setDragEnabled(true);
|
||||||
|
urlList->setDragDropMode(QAbstractItemView::InternalMove);
|
||||||
|
connect(urlList->model(), SIGNAL(rowsMoved(const QModelIndex, int, int, const QModelIndex, int)), this,
|
||||||
|
SLOT(urlListChanged(const QModelIndex, int, int, const QModelIndex, int)));
|
||||||
|
|
||||||
|
for (int i = 0; i < settingsCache->downloads().getCount(); i++)
|
||||||
|
urlList->addItem(settingsCache->downloads().getDownloadUrlAt(i));
|
||||||
|
|
||||||
|
auto aAdd = new QAction(this);
|
||||||
|
aAdd->setIcon(QPixmap("theme:icons/increment"));
|
||||||
|
connect(aAdd, SIGNAL(triggered()), this, SLOT(actAddURL()));
|
||||||
|
auto aEdit = new QAction(this);
|
||||||
|
aEdit->setIcon(QPixmap("theme:icons/pencil"));
|
||||||
|
connect(aEdit, SIGNAL(triggered()), this, SLOT(actEditURL()));
|
||||||
|
auto aRemove = new QAction(this);
|
||||||
|
aRemove->setIcon(QPixmap("theme:icons/decrement"));
|
||||||
|
connect(aRemove, SIGNAL(triggered()), this, SLOT(actRemoveURL()));
|
||||||
|
|
||||||
|
auto *messageToolBar = new QToolBar;
|
||||||
|
messageToolBar->setOrientation(Qt::Vertical);
|
||||||
|
messageToolBar->addAction(aAdd);
|
||||||
|
messageToolBar->addAction(aRemove);
|
||||||
|
messageToolBar->addAction(aEdit);
|
||||||
|
messageToolBar->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
|
||||||
|
|
||||||
|
auto *messageListLayout = new QHBoxLayout;
|
||||||
|
messageListLayout->addWidget(messageToolBar);
|
||||||
|
messageListLayout->addWidget(urlList);
|
||||||
|
|
||||||
|
// Top Layout
|
||||||
|
lpGeneralGrid->addWidget(&picDownloadCheckBox, 0, 0);
|
||||||
|
lpGeneralGrid->addWidget(&resetDownloadURLs, 0, 1);
|
||||||
|
lpGeneralGrid->addLayout(messageListLayout, 1, 0, 1, 2);
|
||||||
|
lpGeneralGrid->addWidget(&urlLinkLabel, 2, 0);
|
||||||
|
lpGeneralGrid->addWidget(&clearDownloadedPicsButton, 2, 1);
|
||||||
|
|
||||||
|
// Spoiler Layout
|
||||||
lpSpoilerGrid->addWidget(&mcDownloadSpoilersCheckBox, 0, 0);
|
lpSpoilerGrid->addWidget(&mcDownloadSpoilersCheckBox, 0, 0);
|
||||||
lpSpoilerGrid->addWidget(&mcSpoilerSaveLabel, 1, 0);
|
lpSpoilerGrid->addWidget(&mcSpoilerSaveLabel, 1, 0);
|
||||||
lpSpoilerGrid->addWidget(mpSpoilerSavePathLineEdit, 1, 1);
|
lpSpoilerGrid->addWidget(mpSpoilerSavePathLineEdit, 1, 1);
|
||||||
|
|
@ -543,6 +513,94 @@ DeckEditorSettingsPage::DeckEditorSettingsPage()
|
||||||
setLayout(lpMainLayout);
|
setLayout(lpMainLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DeckEditorSettingsPage::resetDownloadedURLsButtonClicked()
|
||||||
|
{
|
||||||
|
settingsCache->downloads().clear();
|
||||||
|
urlList->clear();
|
||||||
|
urlList->addItems(settingsCache->downloads().getAllURLs());
|
||||||
|
QMessageBox::information(this, tr("Success"), tr("Download URLs have been reset."));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeckEditorSettingsPage::clearDownloadedPicsButtonClicked()
|
||||||
|
{
|
||||||
|
QString picsPath = settingsCache->getPicsPath() + "/downloadedPics/";
|
||||||
|
QStringList dirs = QDir(picsPath).entryList(QDir::AllDirs | QDir::NoDotAndDotDot);
|
||||||
|
bool outerSuccessRemove = true;
|
||||||
|
for (const auto &dir : dirs) {
|
||||||
|
QString currentPath = picsPath + dir + "/";
|
||||||
|
QStringList files = QDir(currentPath).entryList(QDir::Files);
|
||||||
|
bool innerSuccessRemove = true;
|
||||||
|
for (int j = 0; j < files.length(); j++) {
|
||||||
|
if (!QDir(currentPath).remove(files.at(j))) {
|
||||||
|
qInfo() << "Failed to remove " + currentPath.toUtf8() + files.at(j).toUtf8();
|
||||||
|
outerSuccessRemove = false;
|
||||||
|
innerSuccessRemove = false;
|
||||||
|
}
|
||||||
|
qInfo() << "Removed " << currentPath << files.at(j);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (innerSuccessRemove) {
|
||||||
|
bool success = QDir(picsPath).rmdir(dir);
|
||||||
|
if (!success) {
|
||||||
|
qInfo() << "Failed to remove inner directory" << picsPath;
|
||||||
|
} else {
|
||||||
|
qInfo() << "Removed" << currentPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (outerSuccessRemove) {
|
||||||
|
QMessageBox::information(this, tr("Success"), tr("Downloaded card pictures have been reset."));
|
||||||
|
} else {
|
||||||
|
QMessageBox::critical(this, tr("Error"), tr("One or more downloaded card pictures could not be cleared."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeckEditorSettingsPage::actAddURL()
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
QString msg = QInputDialog::getText(this, tr("Add URL"), tr("URL:"), QLineEdit::Normal, QString(), &ok);
|
||||||
|
if (ok) {
|
||||||
|
urlList->addItem(msg);
|
||||||
|
storeSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeckEditorSettingsPage::actRemoveURL()
|
||||||
|
{
|
||||||
|
if (urlList->currentItem() != nullptr) {
|
||||||
|
delete urlList->takeItem(urlList->currentRow());
|
||||||
|
storeSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeckEditorSettingsPage::actEditURL()
|
||||||
|
{
|
||||||
|
if (urlList->currentItem()) {
|
||||||
|
QString oldText = urlList->currentItem()->text();
|
||||||
|
bool ok;
|
||||||
|
QString msg = QInputDialog::getText(this, tr("Edit URL"), tr("URL:"), QLineEdit::Normal, oldText, &ok);
|
||||||
|
if (ok) {
|
||||||
|
urlList->currentItem()->setText(msg);
|
||||||
|
storeSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeckEditorSettingsPage::storeSettings()
|
||||||
|
{
|
||||||
|
qInfo() << "URL Priority Reset";
|
||||||
|
settingsCache->downloads().clear();
|
||||||
|
for (int i = 0; i < urlList->count(); i++) {
|
||||||
|
qInfo() << "Priority" << i << ":" << urlList->item(i)->text();
|
||||||
|
settingsCache->downloads().setDownloadUrlAt(i, urlList->item(i)->text());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeckEditorSettingsPage::urlListChanged(const QModelIndex &, int, int, const QModelIndex &, int)
|
||||||
|
{
|
||||||
|
storeSettings();
|
||||||
|
}
|
||||||
|
|
||||||
void DeckEditorSettingsPage::updateSpoilers()
|
void DeckEditorSettingsPage::updateSpoilers()
|
||||||
{
|
{
|
||||||
// Disable the button so the user can only press it once at a time
|
// Disable the button so the user can only press it once at a time
|
||||||
|
|
@ -603,14 +661,18 @@ void DeckEditorSettingsPage::setSpoilersEnabled(bool anInput)
|
||||||
|
|
||||||
void DeckEditorSettingsPage::retranslateUi()
|
void DeckEditorSettingsPage::retranslateUi()
|
||||||
{
|
{
|
||||||
|
mpGeneralGroupBox->setTitle(tr("URL Download Priority"));
|
||||||
mpSpoilerGroupBox->setTitle(tr("Spoilers"));
|
mpSpoilerGroupBox->setTitle(tr("Spoilers"));
|
||||||
mcDownloadSpoilersCheckBox.setText(tr("Download Spoilers Automatically"));
|
mcDownloadSpoilersCheckBox.setText(tr("Download Spoilers Automatically"));
|
||||||
mcSpoilerSaveLabel.setText(tr("Spoiler Location:"));
|
mcSpoilerSaveLabel.setText(tr("Spoiler Location:"));
|
||||||
mcGeneralMessageLabel.setText(tr("Hey, something's here finally!"));
|
|
||||||
lastUpdatedLabel.setText(tr("Last Updated") + ": " + getLastUpdateTime());
|
lastUpdatedLabel.setText(tr("Last Updated") + ": " + getLastUpdateTime());
|
||||||
infoOnSpoilersLabel.setText(tr("Spoilers download automatically on launch") + "\n" +
|
infoOnSpoilersLabel.setText(tr("Spoilers download automatically on launch") + "\n" +
|
||||||
tr("Press the button to manually update without relaunching") + "\n\n" +
|
tr("Press the button to manually update without relaunching") + "\n\n" +
|
||||||
tr("Do not close settings until manual update complete"));
|
tr("Do not close settings until manual update complete"));
|
||||||
|
picDownloadCheckBox.setText(tr("Download card pictures on the fly"));
|
||||||
|
urlLinkLabel.setText(QString("<a href='%1'>%2</a>").arg(WIKI_CUSTOM_PIC_URL).arg(tr("How to add a custom URL")));
|
||||||
|
clearDownloadedPicsButton.setText(tr("Delete Downloaded Images"));
|
||||||
|
resetDownloadURLs.setText(tr("Reset Download URLs"));
|
||||||
}
|
}
|
||||||
|
|
||||||
MessagesSettingsPage::MessagesSettingsPage()
|
MessagesSettingsPage::MessagesSettingsPage()
|
||||||
|
|
@ -649,7 +711,7 @@ MessagesSettingsPage::MessagesSettingsPage()
|
||||||
connect(&roomHistory, SIGNAL(stateChanged(int)), settingsCache, SLOT(setRoomHistory(int)));
|
connect(&roomHistory, SIGNAL(stateChanged(int)), settingsCache, SLOT(setRoomHistory(int)));
|
||||||
|
|
||||||
customAlertString = new QLineEdit();
|
customAlertString = new QLineEdit();
|
||||||
customAlertString->setPlaceholderText("Word1 Word2 Word3");
|
customAlertString->setPlaceholderText(tr("Word1 Word2 Word3"));
|
||||||
customAlertString->setText(settingsCache->getHighlightWords());
|
customAlertString->setText(settingsCache->getHighlightWords());
|
||||||
connect(customAlertString, SIGNAL(textChanged(QString)), settingsCache, SLOT(setHighlightWords(QString)));
|
connect(customAlertString, SIGNAL(textChanged(QString)), settingsCache, SLOT(setHighlightWords(QString)));
|
||||||
|
|
||||||
|
|
@ -689,12 +751,16 @@ MessagesSettingsPage::MessagesSettingsPage()
|
||||||
|
|
||||||
aAdd = new QAction(this);
|
aAdd = new QAction(this);
|
||||||
aAdd->setIcon(QPixmap("theme:icons/increment"));
|
aAdd->setIcon(QPixmap("theme:icons/increment"));
|
||||||
|
aAdd->setStatusTip(tr("Add New URL"));
|
||||||
|
|
||||||
connect(aAdd, SIGNAL(triggered()), this, SLOT(actAdd()));
|
connect(aAdd, SIGNAL(triggered()), this, SLOT(actAdd()));
|
||||||
aEdit = new QAction(this);
|
aEdit = new QAction(this);
|
||||||
aEdit->setIcon(QPixmap("theme:icons/pencil"));
|
aEdit->setIcon(QPixmap("theme:icons/pencil"));
|
||||||
|
aEdit->setStatusTip(tr("Edit URL"));
|
||||||
connect(aEdit, SIGNAL(triggered()), this, SLOT(actEdit()));
|
connect(aEdit, SIGNAL(triggered()), this, SLOT(actEdit()));
|
||||||
aRemove = new QAction(this);
|
aRemove = new QAction(this);
|
||||||
aRemove->setIcon(QPixmap("theme:icons/decrement"));
|
aRemove->setIcon(QPixmap("theme:icons/decrement"));
|
||||||
|
aRemove->setStatusTip(tr("Remove URL"));
|
||||||
connect(aRemove, SIGNAL(triggered()), this, SLOT(actRemove()));
|
connect(aRemove, SIGNAL(triggered()), this, SLOT(actRemove()));
|
||||||
|
|
||||||
auto *messageToolBar = new QToolBar;
|
auto *messageToolBar = new QToolBar;
|
||||||
|
|
@ -798,7 +864,7 @@ void MessagesSettingsPage::actEdit()
|
||||||
|
|
||||||
void MessagesSettingsPage::actRemove()
|
void MessagesSettingsPage::actRemove()
|
||||||
{
|
{
|
||||||
if (messageList->currentItem()) {
|
if (messageList->currentItem() != nullptr) {
|
||||||
delete messageList->takeItem(messageList->currentRow());
|
delete messageList->takeItem(messageList->currentRow());
|
||||||
storeSettings();
|
storeSettings();
|
||||||
}
|
}
|
||||||
|
|
@ -1000,7 +1066,7 @@ void DlgSettings::setTab(int index)
|
||||||
|
|
||||||
void DlgSettings::updateLanguage()
|
void DlgSettings::updateLanguage()
|
||||||
{
|
{
|
||||||
qApp->removeTranslator(translator);
|
qApp->removeTranslator(translator); // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast)
|
||||||
installNewTranslator();
|
installNewTranslator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1094,7 +1160,7 @@ void DlgSettings::retranslateUi()
|
||||||
generalButton->setText(tr("General"));
|
generalButton->setText(tr("General"));
|
||||||
appearanceButton->setText(tr("Appearance"));
|
appearanceButton->setText(tr("Appearance"));
|
||||||
userInterfaceButton->setText(tr("User Interface"));
|
userInterfaceButton->setText(tr("User Interface"));
|
||||||
deckEditorButton->setText(tr("Deck Editor"));
|
deckEditorButton->setText(tr("Card Sources"));
|
||||||
messagesButton->setText(tr("Chat"));
|
messagesButton->setText(tr("Chat"));
|
||||||
soundButton->setText(tr("Sound"));
|
soundButton->setText(tr("Sound"));
|
||||||
shortcutsButton->setText(tr("Shortcuts"));
|
shortcutsButton->setText(tr("Shortcuts"));
|
||||||
|
|
|
||||||
|
|
@ -43,13 +43,9 @@ private slots:
|
||||||
void deckPathButtonClicked();
|
void deckPathButtonClicked();
|
||||||
void replaysPathButtonClicked();
|
void replaysPathButtonClicked();
|
||||||
void picsPathButtonClicked();
|
void picsPathButtonClicked();
|
||||||
void clearDownloadedPicsButtonClicked();
|
|
||||||
void cardDatabasePathButtonClicked();
|
void cardDatabasePathButtonClicked();
|
||||||
void tokenDatabasePathButtonClicked();
|
void tokenDatabasePathButtonClicked();
|
||||||
void languageBoxChanged(int index);
|
void languageBoxChanged(int index);
|
||||||
void setEnabledStatus(bool);
|
|
||||||
void defaultUrlRestoreButtonClicked();
|
|
||||||
void fallbackUrlRestoreButtonClicked();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QStringList findQmFiles();
|
QStringList findQmFiles();
|
||||||
|
|
@ -59,14 +55,12 @@ private:
|
||||||
QLineEdit *picsPathEdit;
|
QLineEdit *picsPathEdit;
|
||||||
QLineEdit *cardDatabasePathEdit;
|
QLineEdit *cardDatabasePathEdit;
|
||||||
QLineEdit *tokenDatabasePathEdit;
|
QLineEdit *tokenDatabasePathEdit;
|
||||||
QLineEdit *defaultUrlEdit;
|
|
||||||
QLineEdit *fallbackUrlEdit;
|
|
||||||
QSpinBox pixmapCacheEdit;
|
QSpinBox pixmapCacheEdit;
|
||||||
QGroupBox *personalGroupBox;
|
QGroupBox *personalGroupBox;
|
||||||
QGroupBox *pathsGroupBox;
|
QGroupBox *pathsGroupBox;
|
||||||
QComboBox languageBox;
|
QComboBox languageBox;
|
||||||
QCheckBox picDownloadCheckBox;
|
|
||||||
QCheckBox updateNotificationCheckBox;
|
QCheckBox updateNotificationCheckBox;
|
||||||
|
QCheckBox newVersionOracleCheckBox;
|
||||||
QComboBox updateReleaseChannelBox;
|
QComboBox updateReleaseChannelBox;
|
||||||
QLabel languageLabel;
|
QLabel languageLabel;
|
||||||
QLabel pixmapCacheLabel;
|
QLabel pixmapCacheLabel;
|
||||||
|
|
@ -75,13 +69,7 @@ private:
|
||||||
QLabel picsPathLabel;
|
QLabel picsPathLabel;
|
||||||
QLabel cardDatabasePathLabel;
|
QLabel cardDatabasePathLabel;
|
||||||
QLabel tokenDatabasePathLabel;
|
QLabel tokenDatabasePathLabel;
|
||||||
QLabel defaultUrlLabel;
|
|
||||||
QLabel fallbackUrlLabel;
|
|
||||||
QLabel urlLinkLabel;
|
|
||||||
QLabel updateReleaseChannelLabel;
|
QLabel updateReleaseChannelLabel;
|
||||||
QPushButton clearDownloadedPicsButton;
|
|
||||||
QPushButton defaultUrlRestoreButton;
|
|
||||||
QPushButton fallbackUrlRestoreButton;
|
|
||||||
QCheckBox showTipsOnStartup;
|
QCheckBox showTipsOnStartup;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -143,19 +131,30 @@ public:
|
||||||
QString getLastUpdateTime();
|
QString getLastUpdateTime();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
void storeSettings();
|
||||||
|
void urlListChanged(const QModelIndex &, int, int, const QModelIndex &, int);
|
||||||
void setSpoilersEnabled(bool);
|
void setSpoilersEnabled(bool);
|
||||||
void spoilerPathButtonClicked();
|
void spoilerPathButtonClicked();
|
||||||
void updateSpoilers();
|
void updateSpoilers();
|
||||||
void unlockSettings();
|
void unlockSettings();
|
||||||
|
void actAddURL();
|
||||||
|
void actRemoveURL();
|
||||||
|
void actEditURL();
|
||||||
|
void clearDownloadedPicsButtonClicked();
|
||||||
|
void resetDownloadedURLsButtonClicked();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
QPushButton clearDownloadedPicsButton;
|
||||||
|
QPushButton resetDownloadURLs;
|
||||||
|
QLabel urlLinkLabel;
|
||||||
|
QCheckBox picDownloadCheckBox;
|
||||||
|
QListWidget *urlList;
|
||||||
QCheckBox mcDownloadSpoilersCheckBox;
|
QCheckBox mcDownloadSpoilersCheckBox;
|
||||||
QLabel msDownloadSpoilersLabel;
|
QLabel msDownloadSpoilersLabel;
|
||||||
QGroupBox *mpGeneralGroupBox;
|
QGroupBox *mpGeneralGroupBox;
|
||||||
QGroupBox *mpSpoilerGroupBox;
|
QGroupBox *mpSpoilerGroupBox;
|
||||||
QLineEdit *mpSpoilerSavePathLineEdit;
|
QLineEdit *mpSpoilerSavePathLineEdit;
|
||||||
QLabel mcSpoilerSaveLabel;
|
QLabel mcSpoilerSaveLabel;
|
||||||
QLabel mcGeneralMessageLabel;
|
|
||||||
QLabel lastUpdatedLabel;
|
QLabel lastUpdatedLabel;
|
||||||
QLabel infoOnSpoilersLabel;
|
QLabel infoOnSpoilersLabel;
|
||||||
QPushButton *mpSpoilerPathButton;
|
QPushButton *mpSpoilerPathButton;
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
#define MIN_TIP_IMAGE_HEIGHT 200
|
#define MIN_TIP_IMAGE_HEIGHT 200
|
||||||
#define MIN_TIP_IMAGE_WIDTH 200
|
#define MIN_TIP_IMAGE_WIDTH 200
|
||||||
#define MAX_TIP_IMAGE_HEIGHT 300
|
#define MAX_TIP_IMAGE_HEIGHT 300
|
||||||
#define MAX_TIP_IMAGE_WIDTH 300
|
#define MAX_TIP_IMAGE_WIDTH 500
|
||||||
|
|
||||||
DlgTipOfTheDay::DlgTipOfTheDay(QWidget *parent) : QDialog(parent)
|
DlgTipOfTheDay::DlgTipOfTheDay(QWidget *parent) : QDialog(parent)
|
||||||
{
|
{
|
||||||
|
|
@ -149,9 +149,9 @@ void DlgTipOfTheDay::updateTip(int tipId)
|
||||||
qDebug() << "Image failed to load from" << imagePath;
|
qDebug() << "Image failed to load from" << imagePath;
|
||||||
imageLabel->clear();
|
imageLabel->clear();
|
||||||
} else {
|
} else {
|
||||||
int h = std::min(std::max(image->height(), MIN_TIP_IMAGE_HEIGHT), MAX_TIP_IMAGE_HEIGHT);
|
int h = std::min(std::max(imageLabel->height(), MIN_TIP_IMAGE_HEIGHT), MAX_TIP_IMAGE_HEIGHT);
|
||||||
int w = std::min(std::max(imageLabel->width(), MIN_TIP_IMAGE_WIDTH), MAX_TIP_IMAGE_WIDTH);
|
int w = std::min(std::max(imageLabel->width(), MIN_TIP_IMAGE_WIDTH), MAX_TIP_IMAGE_WIDTH);
|
||||||
imageLabel->setPixmap(image->scaled(h, w, Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
imageLabel->setPixmap(image->scaled(w, h, Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
||||||
}
|
}
|
||||||
|
|
||||||
date->setText("<i>Tip added on: " + tip.getDate().toString("yyyy.MM.dd") + "</i>");
|
date->setText("<i>Tip added on: " + tip.getDate().toString("yyyy.MM.dd") + "</i>");
|
||||||
|
|
@ -163,9 +163,7 @@ void DlgTipOfTheDay::updateTip(int tipId)
|
||||||
|
|
||||||
void DlgTipOfTheDay::resizeEvent(QResizeEvent *event)
|
void DlgTipOfTheDay::resizeEvent(QResizeEvent *event)
|
||||||
{
|
{
|
||||||
int h = imageLabel->height();
|
imageLabel->setPixmap(image->scaled(imageLabel->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
||||||
int w = imageLabel->width();
|
|
||||||
imageLabel->setPixmap(image->scaled(w, h, Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
|
||||||
|
|
||||||
QWidget::resizeEvent(event);
|
QWidget::resizeEvent(event);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ FilterBuilder::FilterBuilder(QWidget *parent) : QWidget(parent)
|
||||||
filterCombo = new QComboBox;
|
filterCombo = new QComboBox;
|
||||||
filterCombo->setObjectName("filterCombo");
|
filterCombo->setObjectName("filterCombo");
|
||||||
for (int i = 0; i < CardFilter::AttrEnd; i++)
|
for (int i = 0; i < CardFilter::AttrEnd; i++)
|
||||||
filterCombo->addItem(tr(CardFilter::attrName(static_cast<CardFilter::Attr>(i))), QVariant(i));
|
filterCombo->addItem(CardFilter::attrName(static_cast<CardFilter::Attr>(i)), QVariant(i));
|
||||||
|
|
||||||
typeCombo = new QComboBox;
|
typeCombo = new QComboBox;
|
||||||
typeCombo->setObjectName("typeCombo");
|
typeCombo->setObjectName("typeCombo");
|
||||||
|
|
|
||||||
|
|
@ -187,11 +187,8 @@ bool FilterItem::acceptColor(const CardInfoPtr info) const
|
||||||
*/
|
*/
|
||||||
int match_count = 0;
|
int match_count = 0;
|
||||||
for (auto &it : converted_term) {
|
for (auto &it : converted_term) {
|
||||||
for (auto i = info->getColors().constBegin(); i != info->getColors().constEnd(); i++) {
|
if (info->getColors().contains(it, Qt::CaseInsensitive))
|
||||||
if ((*i).contains(it, Qt::CaseInsensitive)) {
|
match_count++;
|
||||||
match_count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return match_count == converted_term.length();
|
return match_count == converted_term.length();
|
||||||
|
|
@ -205,9 +202,9 @@ bool FilterItem::acceptText(const CardInfoPtr info) const
|
||||||
bool FilterItem::acceptSet(const CardInfoPtr info) const
|
bool FilterItem::acceptSet(const CardInfoPtr info) const
|
||||||
{
|
{
|
||||||
bool status = false;
|
bool status = false;
|
||||||
for (auto i = info->getSets().constBegin(); i != info->getSets().constEnd(); i++) {
|
for (const auto &set : info->getSets()) {
|
||||||
if ((*i)->getShortName().compare(term, Qt::CaseInsensitive) == 0 ||
|
if (set.getPtr()->getShortName().compare(term, Qt::CaseInsensitive) == 0 ||
|
||||||
(*i)->getLongName().compare(term, Qt::CaseInsensitive) == 0) {
|
set.getPtr()->getLongName().compare(term, Qt::CaseInsensitive) == 0) {
|
||||||
status = true;
|
status = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -299,7 +296,7 @@ bool FilterItem::acceptRarity(const CardInfoPtr info) const
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The purpose of this loop is to only apply one of the replacement
|
* The purpose of this loop is to only apply one of the replacement
|
||||||
* policies and then escape. If we attempt to layer them ontop of
|
* policies and then escape. If we attempt to layer them on top of
|
||||||
* each other, we will get awkward results (i.e. comythic rare mythic rareon)
|
* each other, we will get awkward results (i.e. comythic rare mythic rareon)
|
||||||
* Conditional statement will exit once a case is successful in
|
* Conditional statement will exit once a case is successful in
|
||||||
* replacement OR we go through all possible cases.
|
* replacement OR we go through all possible cases.
|
||||||
|
|
@ -334,8 +331,8 @@ bool FilterItem::acceptRarity(const CardInfoPtr info) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const QString &rareLevel : info->getRarities()) {
|
for (const auto &set : info->getSets()) {
|
||||||
if (rareLevel.compare(converted_term, Qt::CaseInsensitive) == 0) {
|
if (set.getProperty("rarity").compare(converted_term, Qt::CaseInsensitive) == 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
|
|
||||||
|
|
||||||
#ifndef FILTERTREE_H
|
#ifndef FILTERTREE_H
|
||||||
#define FILTERTREE_H
|
#define FILTERTREE_H
|
||||||
|
|
||||||
|
#include "carddatabase.h"
|
||||||
|
#include "cardfilter.h"
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <utility>
|
||||||
#include "carddatabase.h"
|
|
||||||
#include "cardfilter.h"
|
|
||||||
|
|
||||||
class FilterTreeNode
|
class FilterTreeNode
|
||||||
{
|
{
|
||||||
|
|
@ -33,11 +35,11 @@ public:
|
||||||
}
|
}
|
||||||
virtual FilterTreeNode *parent() const
|
virtual FilterTreeNode *parent() const
|
||||||
{
|
{
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
virtual FilterTreeNode *nodeAt(int /* i */) const
|
virtual FilterTreeNode *nodeAt(int /* i */) const
|
||||||
{
|
{
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
virtual void deleteAt(int /* i */)
|
virtual void deleteAt(int /* i */)
|
||||||
{
|
{
|
||||||
|
|
@ -52,43 +54,39 @@ public:
|
||||||
}
|
}
|
||||||
virtual int index() const
|
virtual int index() const
|
||||||
{
|
{
|
||||||
return (parent() != NULL) ? parent()->childIndex(this) : -1;
|
return (parent() != nullptr) ? parent()->childIndex(this) : -1;
|
||||||
}
|
}
|
||||||
virtual QString text() const
|
virtual const QString text() const
|
||||||
{
|
{
|
||||||
return QString(textCStr());
|
return QString("");
|
||||||
}
|
}
|
||||||
virtual bool isLeaf() const
|
virtual bool isLeaf() const
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
virtual const char *textCStr() const
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
virtual void nodeChanged() const
|
virtual void nodeChanged() const
|
||||||
{
|
{
|
||||||
if (parent() != NULL)
|
if (parent() != nullptr)
|
||||||
parent()->nodeChanged();
|
parent()->nodeChanged();
|
||||||
}
|
}
|
||||||
virtual void preInsertChild(const FilterTreeNode *p, int i) const
|
virtual void preInsertChild(const FilterTreeNode *p, int i) const
|
||||||
{
|
{
|
||||||
if (parent() != NULL)
|
if (parent() != nullptr)
|
||||||
parent()->preInsertChild(p, i);
|
parent()->preInsertChild(p, i);
|
||||||
}
|
}
|
||||||
virtual void postInsertChild(const FilterTreeNode *p, int i) const
|
virtual void postInsertChild(const FilterTreeNode *p, int i) const
|
||||||
{
|
{
|
||||||
if (parent() != NULL)
|
if (parent() != nullptr)
|
||||||
parent()->postInsertChild(p, i);
|
parent()->postInsertChild(p, i);
|
||||||
}
|
}
|
||||||
virtual void preRemoveChild(const FilterTreeNode *p, int i) const
|
virtual void preRemoveChild(const FilterTreeNode *p, int i) const
|
||||||
{
|
{
|
||||||
if (parent() != NULL)
|
if (parent() != nullptr)
|
||||||
parent()->preRemoveChild(p, i);
|
parent()->preRemoveChild(p, i);
|
||||||
}
|
}
|
||||||
virtual void postRemoveChild(const FilterTreeNode *p, int i) const
|
virtual void postRemoveChild(const FilterTreeNode *p, int i) const
|
||||||
{
|
{
|
||||||
if (parent() != NULL)
|
if (parent() != nullptr)
|
||||||
parent()->postRemoveChild(p, i);
|
parent()->postRemoveChild(p, i);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -100,13 +98,13 @@ protected:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~FilterTreeBranch();
|
virtual ~FilterTreeBranch();
|
||||||
FilterTreeNode *nodeAt(int i) const;
|
FilterTreeNode *nodeAt(int i) const override;
|
||||||
void deleteAt(int i);
|
void deleteAt(int i) override;
|
||||||
int childCount() const
|
int childCount() const override
|
||||||
{
|
{
|
||||||
return childNodes.size();
|
return childNodes.size();
|
||||||
}
|
}
|
||||||
int childIndex(const FilterTreeNode *node) const;
|
int childIndex(const FilterTreeNode *node) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FilterItemList;
|
class FilterItemList;
|
||||||
|
|
@ -125,8 +123,8 @@ public:
|
||||||
}
|
}
|
||||||
const FilterItemList *findTypeList(CardFilter::Type type) const;
|
const FilterItemList *findTypeList(CardFilter::Type type) const;
|
||||||
FilterItemList *typeList(CardFilter::Type type);
|
FilterItemList *typeList(CardFilter::Type type);
|
||||||
FilterTreeNode *parent() const;
|
FilterTreeNode *parent() const override;
|
||||||
const char *textCStr() const
|
const QString text() const override
|
||||||
{
|
{
|
||||||
return CardFilter::attrName(attr);
|
return CardFilter::attrName(attr);
|
||||||
}
|
}
|
||||||
|
|
@ -148,21 +146,21 @@ public:
|
||||||
{
|
{
|
||||||
return p->attr;
|
return p->attr;
|
||||||
}
|
}
|
||||||
FilterTreeNode *parent() const
|
FilterTreeNode *parent() const override
|
||||||
{
|
{
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
int termIndex(const QString &term) const;
|
int termIndex(const QString &term) const;
|
||||||
FilterTreeNode *termNode(const QString &term);
|
FilterTreeNode *termNode(const QString &term);
|
||||||
const char *textCStr() const
|
const QString text() const override
|
||||||
{
|
{
|
||||||
return CardFilter::typeName(type);
|
return CardFilter::typeName(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool testTypeAnd(const CardInfoPtr info, CardFilter::Attr attr) const;
|
bool testTypeAnd(CardInfoPtr info, CardFilter::Attr attr) const;
|
||||||
bool testTypeAndNot(const CardInfoPtr info, CardFilter::Attr attr) const;
|
bool testTypeAndNot(CardInfoPtr info, CardFilter::Attr attr) const;
|
||||||
bool testTypeOr(const CardInfoPtr info, CardFilter::Attr attr) const;
|
bool testTypeOr(CardInfoPtr info, CardFilter::Attr attr) const;
|
||||||
bool testTypeOrNot(const CardInfoPtr info, CardFilter::Attr attr) const;
|
bool testTypeOrNot(CardInfoPtr info, CardFilter::Attr attr) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FilterItem : public FilterTreeNode
|
class FilterItem : public FilterTreeNode
|
||||||
|
|
@ -173,10 +171,10 @@ private:
|
||||||
public:
|
public:
|
||||||
const QString term;
|
const QString term;
|
||||||
|
|
||||||
FilterItem(QString trm, FilterItemList *parent) : p(parent), term(trm)
|
FilterItem(QString trm, FilterItemList *parent) : p(parent), term(std::move(trm))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
virtual ~FilterItem(){};
|
virtual ~FilterItem() = default;
|
||||||
|
|
||||||
CardFilter::Attr attr() const
|
CardFilter::Attr attr() const
|
||||||
{
|
{
|
||||||
|
|
@ -186,34 +184,30 @@ public:
|
||||||
{
|
{
|
||||||
return p->type;
|
return p->type;
|
||||||
}
|
}
|
||||||
FilterTreeNode *parent() const
|
FilterTreeNode *parent() const override
|
||||||
{
|
{
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
QString text() const
|
const QString text() const override
|
||||||
{
|
{
|
||||||
return term;
|
return term;
|
||||||
}
|
}
|
||||||
const char *textCStr() const
|
bool isLeaf() const override
|
||||||
{
|
|
||||||
return term.toStdString().c_str();
|
|
||||||
}
|
|
||||||
bool isLeaf() const
|
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool acceptName(const CardInfoPtr info) const;
|
bool acceptName(CardInfoPtr info) const;
|
||||||
bool acceptType(const CardInfoPtr info) const;
|
bool acceptType(CardInfoPtr info) const;
|
||||||
bool acceptColor(const CardInfoPtr info) const;
|
bool acceptColor(CardInfoPtr info) const;
|
||||||
bool acceptText(const CardInfoPtr info) const;
|
bool acceptText(CardInfoPtr info) const;
|
||||||
bool acceptSet(const CardInfoPtr info) const;
|
bool acceptSet(CardInfoPtr info) const;
|
||||||
bool acceptManaCost(const CardInfoPtr info) const;
|
bool acceptManaCost(CardInfoPtr info) const;
|
||||||
bool acceptCmc(const CardInfoPtr info) const;
|
bool acceptCmc(CardInfoPtr info) const;
|
||||||
bool acceptPowerToughness(const CardInfoPtr info, CardFilter::Attr attr) const;
|
bool acceptPowerToughness(CardInfoPtr info, CardFilter::Attr attr) const;
|
||||||
bool acceptLoyalty(const CardInfoPtr info) const;
|
bool acceptLoyalty(CardInfoPtr info) const;
|
||||||
bool acceptRarity(const CardInfoPtr info) const;
|
bool acceptRarity(CardInfoPtr info) const;
|
||||||
bool acceptCardAttr(const CardInfoPtr info, CardFilter::Attr attr) const;
|
bool acceptCardAttr(CardInfoPtr info, CardFilter::Attr attr) const;
|
||||||
bool relationCheck(int cardInfo) const;
|
bool relationCheck(int cardInfo) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -232,47 +226,47 @@ private:
|
||||||
LogicMap *attrLogicMap(CardFilter::Attr attr);
|
LogicMap *attrLogicMap(CardFilter::Attr attr);
|
||||||
FilterItemList *attrTypeList(CardFilter::Attr attr, CardFilter::Type type);
|
FilterItemList *attrTypeList(CardFilter::Attr attr, CardFilter::Type type);
|
||||||
|
|
||||||
bool testAttr(const CardInfoPtr info, const LogicMap *lm) const;
|
bool testAttr(CardInfoPtr info, const LogicMap *lm) const;
|
||||||
|
|
||||||
void nodeChanged() const
|
void nodeChanged() const override
|
||||||
{
|
{
|
||||||
emit changed();
|
emit changed();
|
||||||
}
|
}
|
||||||
void preInsertChild(const FilterTreeNode *p, int i) const
|
void preInsertChild(const FilterTreeNode *p, int i) const override
|
||||||
{
|
{
|
||||||
emit preInsertRow(p, i);
|
emit preInsertRow(p, i);
|
||||||
}
|
}
|
||||||
void postInsertChild(const FilterTreeNode *p, int i) const
|
void postInsertChild(const FilterTreeNode *p, int i) const override
|
||||||
{
|
{
|
||||||
emit postInsertRow(p, i);
|
emit postInsertRow(p, i);
|
||||||
}
|
}
|
||||||
void preRemoveChild(const FilterTreeNode *p, int i) const
|
void preRemoveChild(const FilterTreeNode *p, int i) const override
|
||||||
{
|
{
|
||||||
emit preRemoveRow(p, i);
|
emit preRemoveRow(p, i);
|
||||||
}
|
}
|
||||||
void postRemoveChild(const FilterTreeNode *p, int i) const
|
void postRemoveChild(const FilterTreeNode *p, int i) const override
|
||||||
{
|
{
|
||||||
emit postRemoveRow(p, i);
|
emit postRemoveRow(p, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FilterTree();
|
FilterTree();
|
||||||
~FilterTree();
|
~FilterTree() override;
|
||||||
int findTermIndex(CardFilter::Attr attr, CardFilter::Type type, const QString &term);
|
int findTermIndex(CardFilter::Attr attr, CardFilter::Type type, const QString &term);
|
||||||
int findTermIndex(const CardFilter *f);
|
int findTermIndex(const CardFilter *f);
|
||||||
FilterTreeNode *termNode(CardFilter::Attr attr, CardFilter::Type type, const QString &term);
|
FilterTreeNode *termNode(CardFilter::Attr attr, CardFilter::Type type, const QString &term);
|
||||||
FilterTreeNode *termNode(const CardFilter *f);
|
FilterTreeNode *termNode(const CardFilter *f);
|
||||||
FilterTreeNode *attrTypeNode(CardFilter::Attr attr, CardFilter::Type type);
|
FilterTreeNode *attrTypeNode(CardFilter::Attr attr, CardFilter::Type type);
|
||||||
const char *textCStr() const
|
const QString text() const override
|
||||||
{
|
{
|
||||||
return "root";
|
return QString("root");
|
||||||
}
|
}
|
||||||
int index() const
|
int index() const override
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool acceptsCard(const CardInfoPtr info) const;
|
bool acceptsCard(CardInfoPtr info) const;
|
||||||
void clear();
|
void clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -128,10 +128,7 @@ QVariant FilterTreeModel::data(const QModelIndex &index, int role) const
|
||||||
case Qt::ToolTipRole:
|
case Qt::ToolTipRole:
|
||||||
case Qt::StatusTipRole:
|
case Qt::StatusTipRole:
|
||||||
case Qt::WhatsThisRole:
|
case Qt::WhatsThisRole:
|
||||||
if (!node->isLeaf())
|
return node->text();
|
||||||
return tr(node->textCStr());
|
|
||||||
else
|
|
||||||
return node->text();
|
|
||||||
case Qt::CheckStateRole:
|
case Qt::CheckStateRole:
|
||||||
if (node->isEnabled())
|
if (node->isEnabled())
|
||||||
return Qt::Checked;
|
return Qt::Checked;
|
||||||
|
|
|
||||||
49
cockatrice/src/game_specific_terms.h
Normal file
49
cockatrice/src/game_specific_terms.h
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
#ifndef GAME_SPECIFIC_TERMS_H
|
||||||
|
#define GAME_SPECIFIC_TERMS_H
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Collection of traslatable property names used in games,
|
||||||
|
* so we can use Game::Property instead of hardcoding strings.
|
||||||
|
* Note: Mtg = "Maybe that game"
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Mtg
|
||||||
|
{
|
||||||
|
QString const CardType("type");
|
||||||
|
QString const ConvertedManaCost("cmc");
|
||||||
|
QString const Colors("colors");
|
||||||
|
QString const Loyalty("loyalty");
|
||||||
|
QString const MainCardType("maintype");
|
||||||
|
QString const ManaCost("manacost");
|
||||||
|
QString const PowTough("pt");
|
||||||
|
QString const Side("side");
|
||||||
|
QString const Layout("layout");
|
||||||
|
|
||||||
|
inline static const QString getNicePropertyName(QString key)
|
||||||
|
{
|
||||||
|
if (key == CardType)
|
||||||
|
return QCoreApplication::translate("Mtg", "Card type");
|
||||||
|
if (key == ConvertedManaCost)
|
||||||
|
return QCoreApplication::translate("Mtg", "Converted mana cost");
|
||||||
|
if (key == Colors)
|
||||||
|
return QCoreApplication::translate("Mtg", "Color(s)");
|
||||||
|
if (key == Loyalty)
|
||||||
|
return QCoreApplication::translate("Mtg", "Loyalty");
|
||||||
|
if (key == MainCardType)
|
||||||
|
return QCoreApplication::translate("Mtg", "Main card type");
|
||||||
|
if (key == ManaCost)
|
||||||
|
return QCoreApplication::translate("Mtg", "Mana cost");
|
||||||
|
if (key == PowTough)
|
||||||
|
return QCoreApplication::translate("Mtg", "P / T");
|
||||||
|
if (key == Side)
|
||||||
|
return QCoreApplication::translate("Mtg", "Side");
|
||||||
|
if (key == Layout)
|
||||||
|
return QCoreApplication::translate("Mtg", "Layout");
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
}; // namespace Mtg
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -40,7 +40,7 @@ void GameScene::addPlayer(Player *player)
|
||||||
players << player;
|
players << player;
|
||||||
addItem(player);
|
addItem(player);
|
||||||
connect(player, SIGNAL(sizeChanged()), this, SLOT(rearrange()));
|
connect(player, SIGNAL(sizeChanged()), this, SLOT(rearrange()));
|
||||||
connect(player, SIGNAL(gameConceded()), this, SLOT(rearrange()));
|
connect(player, SIGNAL(playerCountChanged()), this, SLOT(rearrange()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameScene::removePlayer(Player *player)
|
void GameScene::removePlayer(Player *player)
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ GameView::GameView(QGraphicsScene *scene, QWidget *parent) : QGraphicsView(scene
|
||||||
|
|
||||||
connect(aCloseMostRecentZoneView, SIGNAL(triggered()), scene, SLOT(closeMostRecentZoneView()));
|
connect(aCloseMostRecentZoneView, SIGNAL(triggered()), scene, SLOT(closeMostRecentZoneView()));
|
||||||
addAction(aCloseMostRecentZoneView);
|
addAction(aCloseMostRecentZoneView);
|
||||||
connect(&settingsCache->shortcuts(), SIGNAL(shortCutchanged()), this, SLOT(refreshShortcuts()));
|
connect(&settingsCache->shortcuts(), SIGNAL(shortCutChanged()), this, SLOT(refreshShortcuts()));
|
||||||
refreshShortcuts();
|
refreshShortcuts();
|
||||||
rubberBand = new QRubberBand(QRubberBand::Rectangle, this);
|
rubberBand = new QRubberBand(QRubberBand::Rectangle, this);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#include "handle_public_servers.h"
|
#include "handle_public_servers.h"
|
||||||
#include "qt-json/json.h"
|
|
||||||
#include "settingscache.h"
|
#include "settingscache.h"
|
||||||
|
#include <QJsonDocument>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QNetworkAccessManager>
|
#include <QNetworkAccessManager>
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
|
|
@ -31,19 +31,16 @@ void HandlePublicServers::actFinishParsingDownloadedData()
|
||||||
savedHostList = uci.getServerInfo();
|
savedHostList = uci.getServerInfo();
|
||||||
|
|
||||||
// Downloaded data from GitHub
|
// Downloaded data from GitHub
|
||||||
bool jsonSuccessful;
|
QJsonParseError parseError{};
|
||||||
QString jsonData = QString(reply->readAll());
|
QJsonDocument jsonResponse = QJsonDocument::fromJson(reply->readAll(), &parseError);
|
||||||
|
if (parseError.error == QJsonParseError::NoError) {
|
||||||
auto jsonMap = QtJson::Json::parse(jsonData, jsonSuccessful).toMap();
|
QVariantMap jsonMap = jsonResponse.toVariant().toMap();
|
||||||
|
|
||||||
if (jsonSuccessful) {
|
|
||||||
updateServerINISettings(jsonMap);
|
updateServerINISettings(jsonMap);
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "[PUBLIC SERVER HANDLER]"
|
qDebug() << "[PUBLIC SERVER HANDLER]"
|
||||||
<< "JSON Parsing Error";
|
<< "JSON Parsing Error:" << parseError.errorString();
|
||||||
emit sigPublicServersDownloadedUnsuccessfully(errorCode);
|
emit sigPublicServersDownloadedUnsuccessfully(errorCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "[PUBLIC SERVER HANDLER]"
|
qDebug() << "[PUBLIC SERVER HANDLER]"
|
||||||
<< "Error Downloading Public Servers" << errorCode;
|
<< "Error Downloading Public Servers" << errorCode;
|
||||||
|
|
@ -74,6 +71,10 @@ void HandlePublicServers::updateServerINISettings(QMap<QString, QVariant> jsonMa
|
||||||
QString serverPort = serverMap["port"].toString();
|
QString serverPort = serverMap["port"].toString();
|
||||||
QString serverSite = serverMap["site"].toString();
|
QString serverSite = serverMap["site"].toString();
|
||||||
|
|
||||||
|
if (serverMap.contains("websocketPort")) {
|
||||||
|
serverPort = serverMap["websocketPort"].toString();
|
||||||
|
}
|
||||||
|
|
||||||
bool serverFound = false;
|
bool serverFound = false;
|
||||||
for (const auto &iter : savedHostList) {
|
for (const auto &iter : savedHostList) {
|
||||||
// If the URL/IP matches
|
// If the URL/IP matches
|
||||||
|
|
|
||||||
|
|
@ -156,7 +156,7 @@ void MessageLogWidget::logAlwaysRevealTopCard(Player *player, CardZone *zone, bo
|
||||||
|
|
||||||
void MessageLogWidget::logAttachCard(Player *player, QString cardName, Player *targetPlayer, QString targetCardName)
|
void MessageLogWidget::logAttachCard(Player *player, QString cardName, Player *targetPlayer, QString targetCardName)
|
||||||
{
|
{
|
||||||
appendHtmlServerMessage(QString("%1 attaches %2 to %3's %4.")
|
appendHtmlServerMessage(tr("%1 attaches %2 to %3's %4.")
|
||||||
.arg(sanitizeHtml(player->getName()))
|
.arg(sanitizeHtml(player->getName()))
|
||||||
.arg(cardLink(cardName))
|
.arg(cardLink(cardName))
|
||||||
.arg(sanitizeHtml(targetPlayer->getName()))
|
.arg(sanitizeHtml(targetPlayer->getName()))
|
||||||
|
|
@ -169,6 +169,12 @@ void MessageLogWidget::logConcede(Player *player)
|
||||||
appendHtmlServerMessage(tr("%1 has conceded the game.").arg(sanitizeHtml(player->getName())), true);
|
appendHtmlServerMessage(tr("%1 has conceded the game.").arg(sanitizeHtml(player->getName())), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MessageLogWidget::logUnconcede(Player *player)
|
||||||
|
{
|
||||||
|
soundEngine->playSound("player_concede");
|
||||||
|
appendHtmlServerMessage(tr("%1 has unconceded the game.").arg(sanitizeHtml(player->getName())), true);
|
||||||
|
}
|
||||||
|
|
||||||
void MessageLogWidget::logConnectionStateChanged(Player *player, bool connectionState)
|
void MessageLogWidget::logConnectionStateChanged(Player *player, bool connectionState)
|
||||||
{
|
{
|
||||||
if (connectionState) {
|
if (connectionState) {
|
||||||
|
|
@ -341,7 +347,7 @@ void MessageLogWidget::logDrawCards(Player *player, int number)
|
||||||
mulliganPlayer = player;
|
mulliganPlayer = player;
|
||||||
else {
|
else {
|
||||||
soundEngine->playSound("draw_card");
|
soundEngine->playSound("draw_card");
|
||||||
appendHtmlServerMessage(tr("%1 draws %2 card(s).")
|
appendHtmlServerMessage(tr("%1 draws %2 card(s).", "", number)
|
||||||
.arg(sanitizeHtml(player->getName()))
|
.arg(sanitizeHtml(player->getName()))
|
||||||
.arg("<font color=\"blue\">" + QString::number(number) + "</font>"));
|
.arg("<font color=\"blue\">" + QString::number(number) + "</font>"));
|
||||||
}
|
}
|
||||||
|
|
@ -354,10 +360,11 @@ void MessageLogWidget::logDumpZone(Player *player, CardZone *zone, int numberCar
|
||||||
.arg(sanitizeHtml(player->getName()))
|
.arg(sanitizeHtml(player->getName()))
|
||||||
.arg(zone->getTranslatedName(zone->getPlayer() == player, CaseLookAtZone)));
|
.arg(zone->getTranslatedName(zone->getPlayer() == player, CaseLookAtZone)));
|
||||||
else
|
else
|
||||||
appendHtmlServerMessage(tr("%1 is looking at the top %2 card(s) %3.")
|
appendHtmlServerMessage(
|
||||||
.arg(sanitizeHtml(player->getName()))
|
tr("%1 is looking at the top %3 card(s) %2.", "top card for singular, top %3 cards for plural", numberCards)
|
||||||
.arg("<font color=\"blue\">" + QString::number(numberCards) + "</font>")
|
.arg(sanitizeHtml(player->getName()))
|
||||||
.arg(zone->getTranslatedName(zone->getPlayer() == player, CaseTopCardsOfZone)));
|
.arg(zone->getTranslatedName(zone->getPlayer() == player, CaseTopCardsOfZone))
|
||||||
|
.arg("<font color=\"blue\">" + QString::number(numberCards) + "</font>"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageLogWidget::logFlipCard(Player *player, QString cardName, bool faceDown)
|
void MessageLogWidget::logFlipCard(Player *player, QString cardName, bool faceDown)
|
||||||
|
|
@ -456,9 +463,11 @@ void MessageLogWidget::logRevealCards(Player *player,
|
||||||
int cardId,
|
int cardId,
|
||||||
QString cardName,
|
QString cardName,
|
||||||
Player *otherPlayer,
|
Player *otherPlayer,
|
||||||
bool faceDown)
|
bool faceDown,
|
||||||
|
int amount)
|
||||||
{
|
{
|
||||||
QPair<QString, QString> temp = getFromStr(zone, cardName, cardId, false);
|
// getFromStr uses cardname.empty() to check if it should contain the start zone, it's not actually used
|
||||||
|
QPair<QString, QString> temp = getFromStr(zone, amount == 1 ? cardName : QString::number(amount), cardId, false);
|
||||||
bool cardNameContainsStartZone = false;
|
bool cardNameContainsStartZone = false;
|
||||||
if (!temp.first.isEmpty()) {
|
if (!temp.first.isEmpty()) {
|
||||||
cardNameContainsStartZone = true;
|
cardNameContainsStartZone = true;
|
||||||
|
|
@ -467,52 +476,61 @@ void MessageLogWidget::logRevealCards(Player *player,
|
||||||
QString fromStr = temp.second;
|
QString fromStr = temp.second;
|
||||||
|
|
||||||
QString cardStr;
|
QString cardStr;
|
||||||
if (cardNameContainsStartZone)
|
if (cardNameContainsStartZone) {
|
||||||
cardStr = cardName;
|
cardStr = cardName;
|
||||||
else if (cardName.isEmpty())
|
} else if (cardName.isEmpty()) {
|
||||||
cardStr = tr("a card");
|
if (amount == 0) {
|
||||||
else
|
cardStr = tr("cards", "an unknown amount of cards");
|
||||||
|
} else {
|
||||||
|
cardStr = tr("%1 card(s)", "a card for singular, %1 cards for plural", amount)
|
||||||
|
.arg("<font color=\"blue\">" + QString::number(amount) + "</font>");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
cardStr = cardLink(cardName);
|
cardStr = cardLink(cardName);
|
||||||
|
}
|
||||||
if (cardId == -1) {
|
if (cardId == -1) {
|
||||||
if (otherPlayer)
|
if (otherPlayer) {
|
||||||
appendHtmlServerMessage(tr("%1 reveals %2 to %3.")
|
appendHtmlServerMessage(tr("%1 reveals %2 to %3.")
|
||||||
.arg(sanitizeHtml(player->getName()))
|
.arg(sanitizeHtml(player->getName()))
|
||||||
.arg(zone->getTranslatedName(true, CaseRevealZone))
|
.arg(zone->getTranslatedName(true, CaseRevealZone))
|
||||||
.arg(sanitizeHtml(otherPlayer->getName())));
|
.arg(sanitizeHtml(otherPlayer->getName())));
|
||||||
else
|
} else {
|
||||||
appendHtmlServerMessage(tr("%1 reveals %2.")
|
appendHtmlServerMessage(tr("%1 reveals %2.")
|
||||||
.arg(sanitizeHtml(player->getName()))
|
.arg(sanitizeHtml(player->getName()))
|
||||||
.arg(zone->getTranslatedName(true, CaseRevealZone)));
|
.arg(zone->getTranslatedName(true, CaseRevealZone)));
|
||||||
|
}
|
||||||
} else if (cardId == -2) {
|
} else if (cardId == -2) {
|
||||||
if (otherPlayer)
|
if (otherPlayer) {
|
||||||
appendHtmlServerMessage(tr("%1 randomly reveals %2%3 to %4.")
|
appendHtmlServerMessage(tr("%1 randomly reveals %2%3 to %4.")
|
||||||
.arg(sanitizeHtml(player->getName()))
|
.arg(sanitizeHtml(player->getName()))
|
||||||
.arg(cardStr)
|
.arg(cardStr)
|
||||||
.arg(fromStr)
|
.arg(fromStr)
|
||||||
.arg(sanitizeHtml(otherPlayer->getName())));
|
.arg(sanitizeHtml(otherPlayer->getName())));
|
||||||
else
|
} else {
|
||||||
appendHtmlServerMessage(
|
appendHtmlServerMessage(
|
||||||
tr("%1 randomly reveals %2%3.").arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr));
|
tr("%1 randomly reveals %2%3.").arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (faceDown && player == otherPlayer) {
|
if (faceDown && player == otherPlayer) {
|
||||||
if (cardName.isEmpty())
|
if (cardName.isEmpty()) {
|
||||||
appendHtmlServerMessage(
|
appendHtmlServerMessage(
|
||||||
tr("%1 peeks at face down card #%2.").arg(sanitizeHtml(player->getName())).arg(cardId));
|
tr("%1 peeks at face down card #%2.").arg(sanitizeHtml(player->getName())).arg(cardId));
|
||||||
else
|
} else {
|
||||||
appendHtmlServerMessage(tr("%1 peeks at face down card #%2: %3.")
|
appendHtmlServerMessage(tr("%1 peeks at face down card #%2: %3.")
|
||||||
.arg(sanitizeHtml(player->getName()))
|
.arg(sanitizeHtml(player->getName()))
|
||||||
.arg(cardId)
|
.arg(cardId)
|
||||||
.arg(cardStr));
|
.arg(cardStr));
|
||||||
} else if (otherPlayer)
|
}
|
||||||
|
} else if (otherPlayer) {
|
||||||
appendHtmlServerMessage(tr("%1 reveals %2%3 to %4.")
|
appendHtmlServerMessage(tr("%1 reveals %2%3 to %4.")
|
||||||
.arg(sanitizeHtml(player->getName()))
|
.arg(sanitizeHtml(player->getName()))
|
||||||
.arg(cardStr)
|
.arg(cardStr)
|
||||||
.arg(fromStr)
|
.arg(fromStr)
|
||||||
.arg(sanitizeHtml(otherPlayer->getName())));
|
.arg(sanitizeHtml(otherPlayer->getName())));
|
||||||
else
|
} else {
|
||||||
appendHtmlServerMessage(
|
appendHtmlServerMessage(
|
||||||
tr("%1 reveals %2%3.").arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr));
|
tr("%1 reveals %2%3.").arg(sanitizeHtml(player->getName())).arg(cardStr).arg(fromStr));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -626,20 +644,20 @@ void MessageLogWidget::logSetCardCounter(Player *player, QString cardName, int c
|
||||||
QString finalStr;
|
QString finalStr;
|
||||||
int delta = abs(oldValue - value);
|
int delta = abs(oldValue - value);
|
||||||
if (value > oldValue)
|
if (value > oldValue)
|
||||||
finalStr = tr("%1 places %2 %3 counter(s) on %4 (now %5).");
|
finalStr = tr("%1 places %2 %3 on %4 (now %5).");
|
||||||
else
|
else
|
||||||
finalStr = tr("%1 removes %2 %3 counter(s) from %4 (now %5).");
|
finalStr = tr("%1 removes %2 %3 from %4 (now %5).");
|
||||||
|
|
||||||
QString colorStr;
|
QString colorStr;
|
||||||
switch (counterId) {
|
switch (counterId) {
|
||||||
case 0:
|
case 0:
|
||||||
colorStr = tr("red", "", delta);
|
colorStr = tr("red counter(s)", "", delta);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
colorStr = tr("yellow", "", delta);
|
colorStr = tr("yellow counter(s)", "", delta);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
colorStr = tr("green", "", delta);
|
colorStr = tr("green counter(s)", "", delta);
|
||||||
break;
|
break;
|
||||||
default:;
|
default:;
|
||||||
}
|
}
|
||||||
|
|
@ -676,13 +694,22 @@ void MessageLogWidget::logSetDoesntUntap(Player *player, CardItem *card, bool do
|
||||||
|
|
||||||
void MessageLogWidget::logSetPT(Player *player, CardItem *card, QString newPT)
|
void MessageLogWidget::logSetPT(Player *player, CardItem *card, QString newPT)
|
||||||
{
|
{
|
||||||
if (currentContext == MessageContext_MoveCard)
|
if (currentContext == MessageContext_MoveCard) {
|
||||||
moveCardPT.insert(card, newPT);
|
moveCardPT.insert(card, newPT);
|
||||||
else
|
} else {
|
||||||
appendHtmlServerMessage(tr("%1 sets PT of %2 to %3.")
|
QString name = card->getName();
|
||||||
.arg(sanitizeHtml(player->getName()))
|
if (name.isEmpty()) {
|
||||||
.arg(cardLink(card->getName()))
|
name = QString("<font color=\"blue\">card #%1</font>").arg(sanitizeHtml(QString::number(card->getId())));
|
||||||
.arg(QString("<font color=\"blue\">%1</font>").arg(sanitizeHtml(newPT))));
|
} else {
|
||||||
|
name = cardLink(name);
|
||||||
|
}
|
||||||
|
if (newPT.isEmpty()) {
|
||||||
|
appendHtmlServerMessage(tr("%1 removes the PT of %2.").arg(sanitizeHtml(player->getName())).arg(name));
|
||||||
|
} else {
|
||||||
|
appendHtmlServerMessage(
|
||||||
|
tr("%1 sets PT of %2 to %3.").arg(sanitizeHtml(player->getName())).arg(name).arg(newPT));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageLogWidget::logSetSideboardLock(Player *player, bool locked)
|
void MessageLogWidget::logSetSideboardLock(Player *player, bool locked)
|
||||||
|
|
@ -786,8 +813,8 @@ void MessageLogWidget::connectToPlayer(Player *player)
|
||||||
connect(player, SIGNAL(logStopDumpZone(Player *, CardZone *)), this, SLOT(logStopDumpZone(Player *, CardZone *)));
|
connect(player, SIGNAL(logStopDumpZone(Player *, CardZone *)), this, SLOT(logStopDumpZone(Player *, CardZone *)));
|
||||||
connect(player, SIGNAL(logDrawCards(Player *, int)), this, SLOT(logDrawCards(Player *, int)));
|
connect(player, SIGNAL(logDrawCards(Player *, int)), this, SLOT(logDrawCards(Player *, int)));
|
||||||
connect(player, SIGNAL(logUndoDraw(Player *, QString)), this, SLOT(logUndoDraw(Player *, QString)));
|
connect(player, SIGNAL(logUndoDraw(Player *, QString)), this, SLOT(logUndoDraw(Player *, QString)));
|
||||||
connect(player, SIGNAL(logRevealCards(Player *, CardZone *, int, QString, Player *, bool)), this,
|
connect(player, SIGNAL(logRevealCards(Player *, CardZone *, int, QString, Player *, bool, int)), this,
|
||||||
SLOT(logRevealCards(Player *, CardZone *, int, QString, Player *, bool)));
|
SLOT(logRevealCards(Player *, CardZone *, int, QString, Player *, bool, int)));
|
||||||
connect(player, SIGNAL(logAlwaysRevealTopCard(Player *, CardZone *, bool)), this,
|
connect(player, SIGNAL(logAlwaysRevealTopCard(Player *, CardZone *, bool)), this,
|
||||||
SLOT(logAlwaysRevealTopCard(Player *, CardZone *, bool)));
|
SLOT(logAlwaysRevealTopCard(Player *, CardZone *, bool)));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ private:
|
||||||
const QString stackConstant() const;
|
const QString stackConstant() const;
|
||||||
|
|
||||||
QString sanitizeHtml(QString dirty) const;
|
QString sanitizeHtml(QString dirty) const;
|
||||||
QString cardLink(const QString cardName) const;
|
QString cardLink(QString cardName) const;
|
||||||
QPair<QString, QString> getFromStr(CardZone *zone, QString cardName, int position, bool ownerChange) const;
|
QPair<QString, QString> getFromStr(CardZone *zone, QString cardName, int position, bool ownerChange) const;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
@ -57,6 +57,7 @@ public slots:
|
||||||
void logAlwaysRevealTopCard(Player *player, CardZone *zone, bool reveal);
|
void logAlwaysRevealTopCard(Player *player, CardZone *zone, bool reveal);
|
||||||
void logAttachCard(Player *player, QString cardName, Player *targetPlayer, QString targetCardName);
|
void logAttachCard(Player *player, QString cardName, Player *targetPlayer, QString targetCardName);
|
||||||
void logConcede(Player *player);
|
void logConcede(Player *player);
|
||||||
|
void logUnconcede(Player *player);
|
||||||
void logConnectionStateChanged(Player *player, bool connectionState);
|
void logConnectionStateChanged(Player *player, bool connectionState);
|
||||||
void logCreateArrow(Player *player,
|
void logCreateArrow(Player *player,
|
||||||
Player *startPlayer,
|
Player *startPlayer,
|
||||||
|
|
@ -83,8 +84,13 @@ public slots:
|
||||||
void logMulligan(Player *player, int number);
|
void logMulligan(Player *player, int number);
|
||||||
void logReplayStarted(int gameId);
|
void logReplayStarted(int gameId);
|
||||||
void logReadyStart(Player *player);
|
void logReadyStart(Player *player);
|
||||||
void
|
void logRevealCards(Player *player,
|
||||||
logRevealCards(Player *player, CardZone *zone, int cardId, QString cardName, Player *otherPlayer, bool faceDown);
|
CardZone *zone,
|
||||||
|
int cardId,
|
||||||
|
QString cardName,
|
||||||
|
Player *otherPlayer,
|
||||||
|
bool faceDown,
|
||||||
|
int amount);
|
||||||
void logRollDie(Player *player, int sides, int roll);
|
void logRollDie(Player *player, int sides, int roll);
|
||||||
void logSay(Player *player, QString message);
|
void logSay(Player *player, QString message);
|
||||||
void logSetActivePhase(int phase);
|
void logSetActivePhase(int phase);
|
||||||
|
|
@ -108,7 +114,7 @@ public:
|
||||||
MessageLogWidget(const TabSupervisor *_tabSupervisor,
|
MessageLogWidget(const TabSupervisor *_tabSupervisor,
|
||||||
const UserlistProxy *_userlistProxy,
|
const UserlistProxy *_userlistProxy,
|
||||||
TabGame *_game,
|
TabGame *_game,
|
||||||
QWidget *parent = 0);
|
QWidget *parent = nullptr);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -24,14 +24,14 @@ PhaseButton::PhaseButton(const QString &_name, QGraphicsItem *parent, QAction *_
|
||||||
connect(activeAnimationTimer, SIGNAL(timeout()), this, SLOT(updateAnimation()));
|
connect(activeAnimationTimer, SIGNAL(timeout()), this, SLOT(updateAnimation()));
|
||||||
activeAnimationTimer->setSingleShot(false);
|
activeAnimationTimer->setSingleShot(false);
|
||||||
} else
|
} else
|
||||||
activeAnimationCounter = 9.0;
|
activeAnimationCounter = 9;
|
||||||
|
|
||||||
setCacheMode(DeviceCoordinateCache);
|
setCacheMode(DeviceCoordinateCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
QRectF PhaseButton::boundingRect() const
|
QRectF PhaseButton::boundingRect() const
|
||||||
{
|
{
|
||||||
return QRectF(0, 0, width, width);
|
return {0, 0, width, width};
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhaseButton::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/)
|
void PhaseButton::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/)
|
||||||
|
|
@ -39,21 +39,24 @@ void PhaseButton::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*op
|
||||||
QRectF iconRect = boundingRect().adjusted(3, 3, -3, -3);
|
QRectF iconRect = boundingRect().adjusted(3, 3, -3, -3);
|
||||||
QRectF translatedIconRect = painter->combinedTransform().mapRect(iconRect);
|
QRectF translatedIconRect = painter->combinedTransform().mapRect(iconRect);
|
||||||
qreal scaleFactor = translatedIconRect.width() / iconRect.width();
|
qreal scaleFactor = translatedIconRect.width() / iconRect.width();
|
||||||
QPixmap iconPixmap = PhasePixmapGenerator::generatePixmap(round(translatedIconRect.height()), name);
|
QPixmap iconPixmap =
|
||||||
|
PhasePixmapGenerator::generatePixmap(static_cast<int>(round(translatedIconRect.height())), name);
|
||||||
|
|
||||||
painter->setBrush(QColor(220 * (activeAnimationCounter / 10.0), 220 * (activeAnimationCounter / 10.0),
|
painter->setBrush(QColor(static_cast<int>(220 * (activeAnimationCounter / 10.0)),
|
||||||
220 * (activeAnimationCounter / 10.0)));
|
static_cast<int>(220 * (activeAnimationCounter / 10.0)),
|
||||||
|
static_cast<int>(220 * (activeAnimationCounter / 10.0))));
|
||||||
painter->setPen(Qt::gray);
|
painter->setPen(Qt::gray);
|
||||||
painter->drawRect(0, 0, width - 1, width - 1);
|
painter->drawRect(0, 0, static_cast<int>(width - 1), static_cast<int>(width - 1));
|
||||||
painter->save();
|
painter->save();
|
||||||
painter->resetTransform();
|
painter->resetTransform();
|
||||||
painter->drawPixmap(iconPixmap.rect().translated(round(3 * scaleFactor), round(3 * scaleFactor)), iconPixmap,
|
painter->drawPixmap(iconPixmap.rect().translated(static_cast<int>(round(3 * scaleFactor)),
|
||||||
iconPixmap.rect());
|
static_cast<int>(round(3 * scaleFactor))),
|
||||||
|
iconPixmap, iconPixmap.rect());
|
||||||
painter->restore();
|
painter->restore();
|
||||||
|
|
||||||
painter->setBrush(QColor(0, 0, 0, 255 * ((10 - activeAnimationCounter) / 15.0)));
|
painter->setBrush(QColor(0, 0, 0, static_cast<int>(255 * ((10 - activeAnimationCounter) / 15.0))));
|
||||||
painter->setPen(Qt::gray);
|
painter->setPen(Qt::gray);
|
||||||
painter->drawRect(0, 0, width - 1, width - 1);
|
painter->drawRect(0, 0, static_cast<int>(width - 1), static_cast<int>(width - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhaseButton::setWidth(double _width)
|
void PhaseButton::setWidth(double _width)
|
||||||
|
|
@ -105,9 +108,9 @@ void PhaseButton::triggerDoubleClickAction()
|
||||||
PhasesToolbar::PhasesToolbar(QGraphicsItem *parent)
|
PhasesToolbar::PhasesToolbar(QGraphicsItem *parent)
|
||||||
: QGraphicsItem(parent), width(100), height(100), ySpacing(1), symbolSize(8)
|
: QGraphicsItem(parent), width(100), height(100), ySpacing(1), symbolSize(8)
|
||||||
{
|
{
|
||||||
QAction *aUntapAll = new QAction(this);
|
auto *aUntapAll = new QAction(this);
|
||||||
connect(aUntapAll, SIGNAL(triggered()), this, SLOT(actUntapAll()));
|
connect(aUntapAll, SIGNAL(triggered()), this, SLOT(actUntapAll()));
|
||||||
QAction *aDrawCard = new QAction(this);
|
auto *aDrawCard = new QAction(this);
|
||||||
connect(aDrawCard, SIGNAL(triggered()), this, SLOT(actDrawCard()));
|
connect(aDrawCard, SIGNAL(triggered()), this, SLOT(actDrawCard()));
|
||||||
|
|
||||||
PhaseButton *untapButton = new PhaseButton("untap", this, aUntapAll);
|
PhaseButton *untapButton = new PhaseButton("untap", this, aUntapAll);
|
||||||
|
|
@ -125,10 +128,10 @@ PhasesToolbar::PhasesToolbar(QGraphicsItem *parent)
|
||||||
buttonList << untapButton << upkeepButton << drawButton << main1Button << combatStartButton << combatAttackersButton
|
buttonList << untapButton << upkeepButton << drawButton << main1Button << combatStartButton << combatAttackersButton
|
||||||
<< combatBlockersButton << combatDamageButton << combatEndButton << main2Button << cleanupButton;
|
<< combatBlockersButton << combatDamageButton << combatEndButton << main2Button << cleanupButton;
|
||||||
|
|
||||||
for (int i = 0; i < buttonList.size(); ++i)
|
for (auto &i : buttonList)
|
||||||
connect(buttonList[i], SIGNAL(clicked()), this, SLOT(phaseButtonClicked()));
|
connect(i, SIGNAL(clicked()), this, SLOT(phaseButtonClicked()));
|
||||||
|
|
||||||
nextTurnButton = new PhaseButton("nextturn", this, 0, false);
|
nextTurnButton = new PhaseButton("nextturn", this, nullptr, false);
|
||||||
connect(nextTurnButton, SIGNAL(clicked()), this, SLOT(actNextTurn()));
|
connect(nextTurnButton, SIGNAL(clicked()), this, SLOT(actNextTurn()));
|
||||||
|
|
||||||
rearrangeButtons();
|
rearrangeButtons();
|
||||||
|
|
@ -138,7 +141,7 @@ PhasesToolbar::PhasesToolbar(QGraphicsItem *parent)
|
||||||
|
|
||||||
QRectF PhasesToolbar::boundingRect() const
|
QRectF PhasesToolbar::boundingRect() const
|
||||||
{
|
{
|
||||||
return QRectF(0, 0, width, height);
|
return {0, 0, width, height};
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhasesToolbar::retranslateUi()
|
void PhasesToolbar::retranslateUi()
|
||||||
|
|
@ -186,8 +189,8 @@ const double PhasesToolbar::marginSize = 3;
|
||||||
|
|
||||||
void PhasesToolbar::rearrangeButtons()
|
void PhasesToolbar::rearrangeButtons()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < buttonList.size(); ++i)
|
for (auto &i : buttonList)
|
||||||
buttonList[i]->setWidth(symbolSize);
|
i->setWidth(symbolSize);
|
||||||
nextTurnButton->setWidth(symbolSize);
|
nextTurnButton->setWidth(symbolSize);
|
||||||
|
|
||||||
double y = marginSize;
|
double y = marginSize;
|
||||||
|
|
@ -208,7 +211,7 @@ void PhasesToolbar::rearrangeButtons()
|
||||||
buttonList[10]->setPos(marginSize, y += symbolSize);
|
buttonList[10]->setPos(marginSize, y += symbolSize);
|
||||||
y += ySpacing;
|
y += ySpacing;
|
||||||
y += ySpacing;
|
y += ySpacing;
|
||||||
nextTurnButton->setPos(marginSize, y += symbolSize);
|
nextTurnButton->setPos(marginSize, y + symbolSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhasesToolbar::setHeight(double _height)
|
void PhasesToolbar::setHeight(double _height)
|
||||||
|
|
@ -232,14 +235,21 @@ void PhasesToolbar::setActivePhase(int phase)
|
||||||
buttonList[i]->setActive(i == phase);
|
buttonList[i]->setActive(i == phase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PhasesToolbar::triggerPhaseAction(int phase)
|
||||||
|
{
|
||||||
|
if (0 <= phase && phase < buttonList.size()) {
|
||||||
|
buttonList[phase]->triggerDoubleClickAction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PhasesToolbar::phaseButtonClicked()
|
void PhasesToolbar::phaseButtonClicked()
|
||||||
{
|
{
|
||||||
PhaseButton *button = qobject_cast<PhaseButton *>(sender());
|
auto *button = qobject_cast<PhaseButton *>(sender());
|
||||||
if (button->getActive())
|
if (button->getActive())
|
||||||
button->triggerDoubleClickAction();
|
button->triggerDoubleClickAction();
|
||||||
|
|
||||||
Command_SetActivePhase cmd;
|
Command_SetActivePhase cmd;
|
||||||
cmd.set_phase(buttonList.indexOf(button));
|
cmd.set_phase(static_cast<google::protobuf::uint32>(buttonList.indexOf(button)));
|
||||||
|
|
||||||
emit sendGameCommand(cmd, -1);
|
emit sendGameCommand(cmd, -1);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,16 +27,16 @@ private:
|
||||||
QAction *doubleClickAction;
|
QAction *doubleClickAction;
|
||||||
double width;
|
double width;
|
||||||
|
|
||||||
void updatePixmap(QPixmap &pixmap);
|
// void updatePixmap(QPixmap &pixmap);
|
||||||
private slots:
|
private slots:
|
||||||
void updateAnimation();
|
void updateAnimation();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PhaseButton(const QString &_name,
|
explicit PhaseButton(const QString &_name,
|
||||||
QGraphicsItem *parent = 0,
|
QGraphicsItem *parent = nullptr,
|
||||||
QAction *_doubleClickAction = 0,
|
QAction *_doubleClickAction = nullptr,
|
||||||
bool _highlightable = true);
|
bool _highlightable = true);
|
||||||
QRectF boundingRect() const;
|
QRectF boundingRect() const override;
|
||||||
void setWidth(double _width);
|
void setWidth(double _width);
|
||||||
void setActive(bool _active);
|
void setActive(bool _active);
|
||||||
bool getActive() const
|
bool getActive() const
|
||||||
|
|
@ -48,9 +48,9 @@ signals:
|
||||||
void clicked();
|
void clicked();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/);
|
void paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/) override;
|
||||||
void mousePressEvent(QGraphicsSceneMouseEvent *event);
|
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
|
||||||
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
|
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PhasesToolbar : public QObject, public QGraphicsItem
|
class PhasesToolbar : public QObject, public QGraphicsItem
|
||||||
|
|
@ -67,8 +67,8 @@ private:
|
||||||
void rearrangeButtons();
|
void rearrangeButtons();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PhasesToolbar(QGraphicsItem *parent = 0);
|
explicit PhasesToolbar(QGraphicsItem *parent = nullptr);
|
||||||
QRectF boundingRect() const;
|
QRectF boundingRect() const override;
|
||||||
void retranslateUi();
|
void retranslateUi();
|
||||||
void setHeight(double _height);
|
void setHeight(double _height);
|
||||||
double getWidth() const
|
double getWidth() const
|
||||||
|
|
@ -82,6 +82,7 @@ public:
|
||||||
QString getLongPhaseName(int phase) const;
|
QString getLongPhaseName(int phase) const;
|
||||||
public slots:
|
public slots:
|
||||||
void setActivePhase(int phase);
|
void setActivePhase(int phase);
|
||||||
|
void triggerPhaseAction(int phase);
|
||||||
private slots:
|
private slots:
|
||||||
void phaseButtonClicked();
|
void phaseButtonClicked();
|
||||||
void actNextTurn();
|
void actNextTurn();
|
||||||
|
|
@ -91,7 +92,7 @@ signals:
|
||||||
void sendGameCommand(const ::google::protobuf::Message &command, int playerId);
|
void sendGameCommand(const ::google::protobuf::Message &command, int playerId);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/);
|
void paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -25,32 +25,14 @@
|
||||||
// never cache more than 300 cards at once for a single deck
|
// never cache more than 300 cards at once for a single deck
|
||||||
#define CACHED_CARD_PER_DECK_MAX 300
|
#define CACHED_CARD_PER_DECK_MAX 300
|
||||||
|
|
||||||
class PictureToLoad::SetDownloadPriorityComparator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/*
|
|
||||||
* Returns true if a has higher download priority than b
|
|
||||||
* Enabled sets have priority over disabled sets
|
|
||||||
* Both groups follows the user-defined order
|
|
||||||
*/
|
|
||||||
inline bool operator()(const CardSetPtr &a, const CardSetPtr &b) const
|
|
||||||
{
|
|
||||||
if (a->getEnabled()) {
|
|
||||||
return !b->getEnabled() || a->getSortKey() < b->getSortKey();
|
|
||||||
} else {
|
|
||||||
return !b->getEnabled() && a->getSortKey() < b->getSortKey();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
PictureToLoad::PictureToLoad(CardInfoPtr _card) : card(std::move(_card))
|
PictureToLoad::PictureToLoad(CardInfoPtr _card) : card(std::move(_card))
|
||||||
{
|
{
|
||||||
/* #2479 will expand this into a list of Urls */
|
urlTemplates = settingsCache->downloads().getAllURLs();
|
||||||
urlTemplates.append(settingsCache->getPicUrl());
|
|
||||||
urlTemplates.append(settingsCache->getPicUrlFallback());
|
|
||||||
|
|
||||||
if (card) {
|
if (card) {
|
||||||
sortedSets = card->getSets();
|
for (const auto &set : card->getSets()) {
|
||||||
|
sortedSets << set.getPtr();
|
||||||
|
}
|
||||||
qSort(sortedSets.begin(), sortedSets.end(), SetDownloadPriorityComparator());
|
qSort(sortedSets.begin(), sortedSets.end(), SetDownloadPriorityComparator());
|
||||||
// The first time called, nextSet will also populate the Urls for the first set.
|
// The first time called, nextSet will also populate the Urls for the first set.
|
||||||
nextSet();
|
nextSet();
|
||||||
|
|
@ -72,7 +54,7 @@ void PictureToLoad::populateSetUrls()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (QString urlTemplate, urlTemplates) {
|
for (const QString &urlTemplate : urlTemplates) {
|
||||||
QString transformedUrl = transformUrl(urlTemplate);
|
QString transformedUrl = transformUrl(urlTemplate);
|
||||||
|
|
||||||
if (!transformedUrl.isEmpty()) {
|
if (!transformedUrl.isEmpty()) {
|
||||||
|
|
@ -115,10 +97,8 @@ QString PictureToLoad::getSetName() const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList PictureLoaderWorker::md5Blacklist = QStringList()
|
// Card back returned by gatherer when card is not found
|
||||||
<< "db0c48db407a907c16ade38de048a441"; // card back returned
|
QStringList PictureLoaderWorker::md5Blacklist = QStringList() << "db0c48db407a907c16ade38de048a441";
|
||||||
// by gatherer when
|
|
||||||
// card is not found
|
|
||||||
|
|
||||||
PictureLoaderWorker::PictureLoaderWorker() : QObject(nullptr), downloadRunning(false), loadQueueRunning(false)
|
PictureLoaderWorker::PictureLoaderWorker() : QObject(nullptr), downloadRunning(false), loadQueueRunning(false)
|
||||||
{
|
{
|
||||||
|
|
@ -145,12 +125,12 @@ PictureLoaderWorker::~PictureLoaderWorker()
|
||||||
|
|
||||||
void PictureLoaderWorker::processLoadQueue()
|
void PictureLoaderWorker::processLoadQueue()
|
||||||
{
|
{
|
||||||
if (loadQueueRunning)
|
if (loadQueueRunning) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
loadQueueRunning = true;
|
loadQueueRunning = true;
|
||||||
forever
|
while (true) {
|
||||||
{
|
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
if (loadQueue.isEmpty()) {
|
if (loadQueue.isEmpty()) {
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
|
|
@ -163,23 +143,26 @@ void PictureLoaderWorker::processLoadQueue()
|
||||||
QString setName = cardBeingLoaded.getSetName();
|
QString setName = cardBeingLoaded.getSetName();
|
||||||
QString cardName = cardBeingLoaded.getCard()->getName();
|
QString cardName = cardBeingLoaded.getCard()->getName();
|
||||||
QString correctedCardName = cardBeingLoaded.getCard()->getCorrectedName();
|
QString correctedCardName = cardBeingLoaded.getCard()->getCorrectedName();
|
||||||
|
|
||||||
qDebug() << "PictureLoader: [card: " << cardName << " set: " << setName << "]: Trying to load picture";
|
qDebug() << "PictureLoader: [card: " << cardName << " set: " << setName << "]: Trying to load picture";
|
||||||
|
|
||||||
if (cardImageExistsOnDisk(setName, correctedCardName))
|
if (cardImageExistsOnDisk(setName, correctedCardName)) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (picDownload) {
|
if (picDownload) {
|
||||||
qDebug() << "PictureLoader: [card: " << cardName << " set: " << setName
|
qDebug() << "PictureLoader: [card: " << cardName << " set: " << setName
|
||||||
<< "]: Picture not found on disk, trying to download";
|
<< "]: Picture not found on disk, trying to download";
|
||||||
cardsToDownload.append(cardBeingLoaded);
|
cardsToDownload.append(cardBeingLoaded);
|
||||||
cardBeingLoaded.clear();
|
cardBeingLoaded.clear();
|
||||||
if (!downloadRunning)
|
if (!downloadRunning) {
|
||||||
startNextPicDownload();
|
startNextPicDownload();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (cardBeingLoaded.nextSet()) {
|
if (cardBeingLoaded.nextSet()) {
|
||||||
qDebug() << "PictureLoader: [card: " << cardName << " set: " << setName
|
qDebug() << "PictureLoader: [card: " << cardName << " set: " << setName
|
||||||
<< "]: Picture NOT found and download disabled, moving to next "
|
<< "]: Picture NOT found and download disabled, moving to next "
|
||||||
"set (newset: "
|
"set (new set: "
|
||||||
<< setName << " card: " << cardName << ")";
|
<< setName << " card: " << cardName << ")";
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
loadQueue.prepend(cardBeingLoaded);
|
loadQueue.prepend(cardBeingLoaded);
|
||||||
|
|
@ -188,7 +171,7 @@ void PictureLoaderWorker::processLoadQueue()
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "PictureLoader: [card: " << cardName << " set: " << setName
|
qDebug() << "PictureLoader: [card: " << cardName << " set: " << setName
|
||||||
<< "]: Picture NOT found, download disabled, no more sets to "
|
<< "]: Picture NOT found, download disabled, no more sets to "
|
||||||
"try: BAILING OUT (oldset: "
|
"try: BAILING OUT (old set: "
|
||||||
<< setName << " card: " << cardName << ")";
|
<< setName << " card: " << cardName << ")";
|
||||||
imageLoaded(cardBeingLoaded.getCard(), QImage());
|
imageLoaded(cardBeingLoaded.getCard(), QImage());
|
||||||
}
|
}
|
||||||
|
|
@ -221,22 +204,22 @@ bool PictureLoaderWorker::cardImageExistsOnDisk(QString &setName, QString &corre
|
||||||
// Iterates through the list of paths, searching for images with the desired
|
// Iterates through the list of paths, searching for images with the desired
|
||||||
// name with any QImageReader-supported
|
// name with any QImageReader-supported
|
||||||
// extension
|
// extension
|
||||||
for (int i = 0; i < picsPaths.length(); i++) {
|
for (const auto &picsPath : picsPaths) {
|
||||||
imgReader.setFileName(picsPaths.at(i));
|
imgReader.setFileName(picsPath);
|
||||||
if (imgReader.read(&image)) {
|
if (imgReader.read(&image)) {
|
||||||
qDebug() << "PictureLoader: [card: " << correctedCardname << " set: " << setName
|
qDebug() << "PictureLoader: [card: " << correctedCardname << " set: " << setName
|
||||||
<< "]: Picture found on disk.";
|
<< "]: Picture found on disk.";
|
||||||
imageLoaded(cardBeingLoaded.getCard(), image);
|
imageLoaded(cardBeingLoaded.getCard(), image);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
imgReader.setFileName(picsPaths.at(i) + ".full");
|
imgReader.setFileName(picsPath + ".full");
|
||||||
if (imgReader.read(&image)) {
|
if (imgReader.read(&image)) {
|
||||||
qDebug() << "PictureLoader: [card: " << correctedCardname << " set: " << setName
|
qDebug() << "PictureLoader: [card: " << correctedCardname << " set: " << setName
|
||||||
<< "]: Picture.full found on disk.";
|
<< "]: Picture.full found on disk.";
|
||||||
imageLoaded(cardBeingLoaded.getCard(), image);
|
imageLoaded(cardBeingLoaded.getCard(), image);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
imgReader.setFileName(picsPaths.at(i) + ".xlhq");
|
imgReader.setFileName(picsPath + ".xlhq");
|
||||||
if (imgReader.read(&image)) {
|
if (imgReader.read(&image)) {
|
||||||
qDebug() << "PictureLoader: [card: " << correctedCardname << " set: " << setName
|
qDebug() << "PictureLoader: [card: " << correctedCardname << " set: " << setName
|
||||||
<< "]: Picture.xlhq found on disk.";
|
<< "]: Picture.xlhq found on disk.";
|
||||||
|
|
@ -248,7 +231,7 @@ bool PictureLoaderWorker::cardImageExistsOnDisk(QString &setName, QString &corre
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString PictureToLoad::transformUrl(QString urlTemplate) const
|
QString PictureToLoad::transformUrl(const QString &urlTemplate) const
|
||||||
{
|
{
|
||||||
/* This function takes Url templates and substitutes actual card details
|
/* This function takes Url templates and substitutes actual card details
|
||||||
into the url. This is used for making Urls with follow a predictable format
|
into the url. This is used for making Urls with follow a predictable format
|
||||||
|
|
@ -259,29 +242,53 @@ QString PictureToLoad::transformUrl(QString urlTemplate) const
|
||||||
CardSetPtr set = getCurrentSet();
|
CardSetPtr set = getCurrentSet();
|
||||||
|
|
||||||
QMap<QString, QString> transformMap = QMap<QString, QString>();
|
QMap<QString, QString> transformMap = QMap<QString, QString>();
|
||||||
|
// name
|
||||||
transformMap["!name!"] = card->getName();
|
transformMap["!name!"] = card->getName();
|
||||||
transformMap["!name_lower!"] = card->getName().toLower();
|
transformMap["!name_lower!"] = card->getName().toLower();
|
||||||
transformMap["!corrected_name!"] = card->getCorrectedName();
|
transformMap["!corrected_name!"] = card->getCorrectedName();
|
||||||
transformMap["!corrected_name_lower!"] = card->getCorrectedName().toLower();
|
transformMap["!corrected_name_lower!"] = card->getCorrectedName().toLower();
|
||||||
|
|
||||||
|
// card properties
|
||||||
|
QRegExp rxCardProp("!prop:([^!]+)!");
|
||||||
|
int pos = 0;
|
||||||
|
while ((pos = rxCardProp.indexIn(transformedUrl, pos)) != -1) {
|
||||||
|
QString propertyName = rxCardProp.cap(1);
|
||||||
|
pos += rxCardProp.matchedLength();
|
||||||
|
QString propertyValue = card->getProperty(propertyName);
|
||||||
|
if (propertyValue.isEmpty()) {
|
||||||
|
qDebug() << "PictureLoader: [card: " << card->getName() << " set: " << getSetName()
|
||||||
|
<< "]: Requested property (" << propertyName << ") for Url template (" << urlTemplate
|
||||||
|
<< ") is not available";
|
||||||
|
return QString();
|
||||||
|
} else {
|
||||||
|
transformMap["!prop:" + propertyName + "!"] = propertyValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (set) {
|
if (set) {
|
||||||
transformMap["!cardid!"] = QString::number(card->getMuId(set->getShortName()));
|
|
||||||
transformMap["!collectornumber!"] = card->getCollectorNumber(set->getShortName());
|
|
||||||
transformMap["!setcode!"] = set->getShortName();
|
transformMap["!setcode!"] = set->getShortName();
|
||||||
transformMap["!setcode_lower!"] = set->getShortName().toLower();
|
transformMap["!setcode_lower!"] = set->getShortName().toLower();
|
||||||
transformMap["!setname!"] = set->getLongName();
|
transformMap["!setname!"] = set->getLongName();
|
||||||
transformMap["!setname_lower!"] = set->getLongName().toLower();
|
transformMap["!setname_lower!"] = set->getLongName().toLower();
|
||||||
} else {
|
|
||||||
transformMap["!cardid!"] = QString();
|
QRegExp rxSetProp("!set:([^!]+)!");
|
||||||
transformMap["!collectornumber!"] = QString();
|
pos = 0; // Defined above
|
||||||
transformMap["!setcode!"] = QString();
|
while ((pos = rxSetProp.indexIn(transformedUrl, pos)) != -1) {
|
||||||
transformMap["!setcode_lower!"] = QString();
|
QString propertyName = rxSetProp.cap(1);
|
||||||
transformMap["!setname!"] = QString();
|
pos += rxSetProp.matchedLength();
|
||||||
transformMap["!setname_lower!"] = QString();
|
QString propertyValue = card->getSetProperty(set->getShortName(), propertyName);
|
||||||
|
if (propertyValue.isEmpty()) {
|
||||||
|
qDebug() << "PictureLoader: [card: " << card->getName() << " set: " << getSetName()
|
||||||
|
<< "]: Requested set property (" << propertyName << ") for Url template (" << urlTemplate
|
||||||
|
<< ") is not available";
|
||||||
|
return QString();
|
||||||
|
} else {
|
||||||
|
transformMap["!set:" + propertyName + "!"] = propertyValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (QString prop, transformMap.keys()) {
|
for (const QString &prop : transformMap.keys()) {
|
||||||
if (transformedUrl.contains(prop)) {
|
if (transformedUrl.contains(prop)) {
|
||||||
if (!transformMap[prop].isEmpty()) {
|
if (!transformMap[prop].isEmpty()) {
|
||||||
transformedUrl.replace(prop, QUrl::toPercentEncoding(transformMap[prop]));
|
transformedUrl.replace(prop, QUrl::toPercentEncoding(transformMap[prop]));
|
||||||
|
|
@ -372,8 +379,8 @@ void PictureLoaderWorker::picDownloadFinished(QNetworkReply *reply)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QByteArray &picData = reply->peek(reply->size()); // peek is used to keep the data in the buffer
|
// peek is used to keep the data in the buffer for use by QImageReader
|
||||||
// for use by QImageReader
|
const QByteArray &picData = reply->peek(reply->size());
|
||||||
|
|
||||||
if (imageIsBlackListed(picData)) {
|
if (imageIsBlackListed(picData)) {
|
||||||
qDebug() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName()
|
qDebug() << "PictureLoader: [card: " << cardBeingDownloaded.getCard()->getName()
|
||||||
|
|
@ -395,8 +402,9 @@ void PictureLoaderWorker::picDownloadFinished(QNetworkReply *reply)
|
||||||
// prior to reading the
|
// prior to reading the
|
||||||
// QImageReader data
|
// QImageReader data
|
||||||
// into a QImage object, as that wipes the QImageReader buffer
|
// into a QImage object, as that wipes the QImageReader buffer
|
||||||
if (extension == ".jpeg")
|
if (extension == ".jpeg") {
|
||||||
extension = ".jpg";
|
extension = ".jpg";
|
||||||
|
}
|
||||||
|
|
||||||
if (imgReader.read(&testImage)) {
|
if (imgReader.read(&testImage)) {
|
||||||
QString setName = cardBeingDownloaded.getSetName();
|
QString setName = cardBeingDownloaded.getSetName();
|
||||||
|
|
@ -410,8 +418,9 @@ void PictureLoaderWorker::picDownloadFinished(QNetworkReply *reply)
|
||||||
|
|
||||||
QFile newPic(picsPath + "/downloadedPics/" + setName + "/" +
|
QFile newPic(picsPath + "/downloadedPics/" + setName + "/" +
|
||||||
cardBeingDownloaded.getCard()->getCorrectedName() + extension);
|
cardBeingDownloaded.getCard()->getCorrectedName() + extension);
|
||||||
if (!newPic.open(QIODevice::WriteOnly))
|
if (!newPic.open(QIODevice::WriteOnly)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
newPic.write(picData);
|
newPic.write(picData);
|
||||||
newPic.close();
|
newPic.close();
|
||||||
}
|
}
|
||||||
|
|
@ -436,15 +445,16 @@ void PictureLoaderWorker::enqueueImageLoad(CardInfoPtr card)
|
||||||
QMutexLocker locker(&mutex);
|
QMutexLocker locker(&mutex);
|
||||||
|
|
||||||
// avoid queueing the same card more than once
|
// avoid queueing the same card more than once
|
||||||
if (!card || card == cardBeingLoaded.getCard() || card == cardBeingDownloaded.getCard())
|
if (!card || card == cardBeingLoaded.getCard() || card == cardBeingDownloaded.getCard()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
foreach (PictureToLoad pic, loadQueue) {
|
for (const PictureToLoad &pic : loadQueue) {
|
||||||
if (pic.getCard() == card)
|
if (pic.getCard() == card)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (PictureToLoad pic, cardsToDownload) {
|
for (const PictureToLoad &pic : cardsToDownload) {
|
||||||
if (pic.getCard() == card)
|
if (pic.getCard() == card)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -466,7 +476,7 @@ void PictureLoaderWorker::picsPathChanged()
|
||||||
customPicsPath = settingsCache->getCustomPicsPath();
|
customPicsPath = settingsCache->getCustomPicsPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
PictureLoader::PictureLoader() : QObject(0)
|
PictureLoader::PictureLoader() : QObject(nullptr)
|
||||||
{
|
{
|
||||||
worker = new PictureLoaderWorker;
|
worker = new PictureLoaderWorker;
|
||||||
connect(settingsCache, SIGNAL(picsPathChanged()), this, SLOT(picsPathChanged()));
|
connect(settingsCache, SIGNAL(picsPathChanged()), this, SLOT(picsPathChanged()));
|
||||||
|
|
@ -493,20 +503,21 @@ void PictureLoader::getCardBackPixmap(QPixmap &pixmap, QSize size)
|
||||||
|
|
||||||
void PictureLoader::getPixmap(QPixmap &pixmap, CardInfoPtr card, QSize size)
|
void PictureLoader::getPixmap(QPixmap &pixmap, CardInfoPtr card, QSize size)
|
||||||
{
|
{
|
||||||
if (card == nullptr)
|
if (card == nullptr) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// search for an exact size copy of the picure in cache
|
// search for an exact size copy of the picture in cache
|
||||||
QString key = card->getPixmapCacheKey();
|
QString key = card->getPixmapCacheKey();
|
||||||
QString sizekey = key + QLatin1Char('_') + QString::number(size.width()) + QString::number(size.height());
|
QString sizeKey = key + QLatin1Char('_') + QString::number(size.width()) + QString::number(size.height());
|
||||||
if (QPixmapCache::find(sizekey, &pixmap))
|
if (QPixmapCache::find(sizeKey, &pixmap))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// load the image and create a copy of the correct size
|
// load the image and create a copy of the correct size
|
||||||
QPixmap bigPixmap;
|
QPixmap bigPixmap;
|
||||||
if (QPixmapCache::find(key, &bigPixmap)) {
|
if (QPixmapCache::find(key, &bigPixmap)) {
|
||||||
pixmap = bigPixmap.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
pixmap = bigPixmap.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||||
QPixmapCache::insert(sizekey, pixmap);
|
QPixmapCache::insert(sizeKey, pixmap);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -532,8 +543,9 @@ void PictureLoader::imageLoaded(CardInfoPtr card, const QImage &image)
|
||||||
|
|
||||||
void PictureLoader::clearPixmapCache(CardInfoPtr card)
|
void PictureLoader::clearPixmapCache(CardInfoPtr card)
|
||||||
{
|
{
|
||||||
if (card)
|
if (card) {
|
||||||
QPixmapCache::remove(card->getPixmapCacheKey());
|
QPixmapCache::remove(card->getPixmapCacheKey());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PictureLoader::clearPixmapCache()
|
void PictureLoader::clearPixmapCache()
|
||||||
|
|
@ -546,13 +558,15 @@ void PictureLoader::cacheCardPixmaps(QList<CardInfoPtr> cards)
|
||||||
QPixmap tmp;
|
QPixmap tmp;
|
||||||
int max = qMin(cards.size(), CACHED_CARD_PER_DECK_MAX);
|
int max = qMin(cards.size(), CACHED_CARD_PER_DECK_MAX);
|
||||||
for (int i = 0; i < max; ++i) {
|
for (int i = 0; i < max; ++i) {
|
||||||
CardInfoPtr card = cards.at(i);
|
const CardInfoPtr &card = cards.at(i);
|
||||||
if (!card)
|
if (!card) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
QString key = card->getPixmapCacheKey();
|
QString key = card->getPixmapCacheKey();
|
||||||
if (QPixmapCache::find(key, &tmp))
|
if (QPixmapCache::find(key, &tmp)) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
getInstance().worker->enqueueImageLoad(card);
|
getInstance().worker->enqueueImageLoad(card);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,23 @@ class QThread;
|
||||||
class PictureToLoad
|
class PictureToLoad
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
class SetDownloadPriorityComparator;
|
class SetDownloadPriorityComparator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*
|
||||||
|
* Returns true if a has higher download priority than b
|
||||||
|
* Enabled sets have priority over disabled sets
|
||||||
|
* Both groups follows the user-defined order
|
||||||
|
*/
|
||||||
|
inline bool operator()(const CardSetPtr &a, const CardSetPtr &b) const
|
||||||
|
{
|
||||||
|
if (a->getEnabled()) {
|
||||||
|
return !b->getEnabled() || a->getSortKey() < b->getSortKey();
|
||||||
|
} else {
|
||||||
|
return !b->getEnabled() && a->getSortKey() < b->getSortKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
CardInfoPtr card;
|
CardInfoPtr card;
|
||||||
QList<CardSetPtr> sortedSets;
|
QList<CardSetPtr> sortedSets;
|
||||||
|
|
@ -24,7 +40,8 @@ private:
|
||||||
CardSetPtr currentSet;
|
CardSetPtr currentSet;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PictureToLoad(CardInfoPtr _card = CardInfoPtr());
|
explicit PictureToLoad(CardInfoPtr _card = CardInfoPtr());
|
||||||
|
|
||||||
CardInfoPtr getCard() const
|
CardInfoPtr getCard() const
|
||||||
{
|
{
|
||||||
return card;
|
return card;
|
||||||
|
|
@ -42,7 +59,7 @@ public:
|
||||||
return currentSet;
|
return currentSet;
|
||||||
}
|
}
|
||||||
QString getSetName() const;
|
QString getSetName() const;
|
||||||
QString transformUrl(QString urlTemplate) const;
|
QString transformUrl(const QString &urlTemplate) const;
|
||||||
bool nextSet();
|
bool nextSet();
|
||||||
bool nextUrl();
|
bool nextUrl();
|
||||||
void populateSetUrls();
|
void populateSetUrls();
|
||||||
|
|
@ -52,8 +69,8 @@ class PictureLoaderWorker : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
PictureLoaderWorker();
|
explicit PictureLoaderWorker();
|
||||||
~PictureLoaderWorker();
|
~PictureLoaderWorker() override;
|
||||||
|
|
||||||
void enqueueImageLoad(CardInfoPtr card);
|
void enqueueImageLoad(CardInfoPtr card);
|
||||||
|
|
||||||
|
|
@ -70,8 +87,8 @@ private:
|
||||||
PictureToLoad cardBeingDownloaded;
|
PictureToLoad cardBeingDownloaded;
|
||||||
bool picDownload, downloadRunning, loadQueueRunning;
|
bool picDownload, downloadRunning, loadQueueRunning;
|
||||||
void startNextPicDownload();
|
void startNextPicDownload();
|
||||||
bool cardImageExistsOnDisk(QString &setName, QString &correctedCardname);
|
bool cardImageExistsOnDisk(QString &, QString &);
|
||||||
bool imageIsBlackListed(const QByteArray &picData);
|
bool imageIsBlackListed(const QByteArray &);
|
||||||
private slots:
|
private slots:
|
||||||
void picDownloadFinished(QNetworkReply *reply);
|
void picDownloadFinished(QNetworkReply *reply);
|
||||||
void picDownloadFailed();
|
void picDownloadFailed();
|
||||||
|
|
@ -96,8 +113,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PictureLoader();
|
explicit PictureLoader();
|
||||||
~PictureLoader();
|
~PictureLoader() override;
|
||||||
// Singleton - Don't implement copy constructor and assign operator
|
// Singleton - Don't implement copy constructor and assign operator
|
||||||
PictureLoader(PictureLoader const &);
|
PictureLoader(PictureLoader const &);
|
||||||
void operator=(PictureLoader const &);
|
void operator=(PictureLoader const &);
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -40,7 +40,7 @@ class CommandContainer;
|
||||||
class GameCommand;
|
class GameCommand;
|
||||||
class GameEvent;
|
class GameEvent;
|
||||||
class GameEventContext;
|
class GameEventContext;
|
||||||
class Event_ConnectionStateChanged;
|
// class Event_ConnectionStateChanged;
|
||||||
class Event_GameSay;
|
class Event_GameSay;
|
||||||
class Event_Shuffle;
|
class Event_Shuffle;
|
||||||
class Event_RollDie;
|
class Event_RollDie;
|
||||||
|
|
@ -79,17 +79,17 @@ public:
|
||||||
{
|
{
|
||||||
Type = typeOther
|
Type = typeOther
|
||||||
};
|
};
|
||||||
int type() const
|
int type() const override
|
||||||
{
|
{
|
||||||
return Type;
|
return Type;
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerArea(QGraphicsItem *parent = 0);
|
explicit PlayerArea(QGraphicsItem *parent = nullptr);
|
||||||
QRectF boundingRect() const
|
QRectF boundingRect() const override
|
||||||
{
|
{
|
||||||
return bRect;
|
return bRect;
|
||||||
}
|
}
|
||||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
|
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
|
||||||
|
|
||||||
void setSize(qreal width, qreal height);
|
void setSize(qreal width, qreal height);
|
||||||
};
|
};
|
||||||
|
|
@ -127,12 +127,17 @@ signals:
|
||||||
void logSetAnnotation(Player *player, CardItem *card, QString newAnnotation);
|
void logSetAnnotation(Player *player, CardItem *card, QString newAnnotation);
|
||||||
void logDumpZone(Player *player, CardZone *zone, int numberCards);
|
void logDumpZone(Player *player, CardZone *zone, int numberCards);
|
||||||
void logStopDumpZone(Player *player, CardZone *zone);
|
void logStopDumpZone(Player *player, CardZone *zone);
|
||||||
void
|
void logRevealCards(Player *player,
|
||||||
logRevealCards(Player *player, CardZone *zone, int cardId, QString cardName, Player *otherPlayer, bool faceDown);
|
CardZone *zone,
|
||||||
|
int cardId,
|
||||||
|
QString cardName,
|
||||||
|
Player *otherPlayer,
|
||||||
|
bool faceDown,
|
||||||
|
int amount);
|
||||||
void logAlwaysRevealTopCard(Player *player, CardZone *zone, bool reveal);
|
void logAlwaysRevealTopCard(Player *player, CardZone *zone, bool reveal);
|
||||||
|
|
||||||
void sizeChanged();
|
void sizeChanged();
|
||||||
void gameConceded();
|
void playerCountChanged();
|
||||||
public slots:
|
public slots:
|
||||||
void actUntapAll();
|
void actUntapAll();
|
||||||
void actRollDie();
|
void actRollDie();
|
||||||
|
|
@ -144,6 +149,8 @@ public slots:
|
||||||
void actUndoDraw();
|
void actUndoDraw();
|
||||||
void actMulligan();
|
void actMulligan();
|
||||||
void actMoveTopCardToPlayFaceDown();
|
void actMoveTopCardToPlayFaceDown();
|
||||||
|
void actMoveTopCardToGrave();
|
||||||
|
void actMoveTopCardToExile();
|
||||||
void actMoveTopCardsToGrave();
|
void actMoveTopCardsToGrave();
|
||||||
void actMoveTopCardsToExile();
|
void actMoveTopCardsToExile();
|
||||||
void actMoveTopCardToBottom();
|
void actMoveTopCardToBottom();
|
||||||
|
|
@ -201,10 +208,10 @@ private:
|
||||||
QAction *aMoveHandToTopLibrary, *aMoveHandToBottomLibrary, *aMoveHandToGrave, *aMoveHandToRfg,
|
QAction *aMoveHandToTopLibrary, *aMoveHandToBottomLibrary, *aMoveHandToGrave, *aMoveHandToRfg,
|
||||||
*aMoveGraveToTopLibrary, *aMoveGraveToBottomLibrary, *aMoveGraveToHand, *aMoveGraveToRfg, *aMoveRfgToTopLibrary,
|
*aMoveGraveToTopLibrary, *aMoveGraveToBottomLibrary, *aMoveGraveToHand, *aMoveGraveToRfg, *aMoveRfgToTopLibrary,
|
||||||
*aMoveRfgToBottomLibrary, *aMoveRfgToHand, *aMoveRfgToGrave, *aViewLibrary, *aViewTopCards,
|
*aMoveRfgToBottomLibrary, *aMoveRfgToHand, *aMoveRfgToGrave, *aViewLibrary, *aViewTopCards,
|
||||||
*aAlwaysRevealTopCard, *aOpenDeckInDeckEditor, *aMoveTopCardsToGrave, *aMoveTopCardsToExile,
|
*aAlwaysRevealTopCard, *aOpenDeckInDeckEditor, *aMoveTopCardToGraveyard, *aMoveTopCardToExile,
|
||||||
*aMoveTopCardToBottom, *aViewGraveyard, *aViewRfg, *aViewSideboard, *aDrawCard, *aDrawCards, *aUndoDraw,
|
*aMoveTopCardsToGraveyard, *aMoveTopCardsToExile, *aMoveTopCardToBottom, *aViewGraveyard, *aViewRfg,
|
||||||
*aMulligan, *aShuffle, *aMoveTopToPlayFaceDown, *aUntapAll, *aRollDie, *aCreateToken, *aCreateAnotherToken,
|
*aViewSideboard, *aDrawCard, *aDrawCards, *aUndoDraw, *aMulligan, *aShuffle, *aMoveTopToPlayFaceDown,
|
||||||
*aCardMenu, *aMoveBottomCardToGrave;
|
*aUntapAll, *aRollDie, *aCreateToken, *aCreateAnotherToken, *aCardMenu, *aMoveBottomCardToGrave;
|
||||||
|
|
||||||
QList<QAction *> aAddCounter, aSetCounter, aRemoveCounter;
|
QList<QAction *> aAddCounter, aSetCounter, aRemoveCounter;
|
||||||
QAction *aPlay, *aPlayFacedown, *aHide, *aTap, *aDoesntUntap, *aAttach, *aUnattach, *aDrawArrow, *aSetPT, *aResetPT,
|
QAction *aPlay, *aPlayFacedown, *aHide, *aTap, *aDoesntUntap, *aAttach, *aUnattach, *aDrawArrow, *aSetPT, *aResetPT,
|
||||||
|
|
@ -249,7 +256,6 @@ private:
|
||||||
void createCard(const CardItem *sourceCard, const QString &dbCardName, bool attach = false);
|
void createCard(const CardItem *sourceCard, const QString &dbCardName, bool attach = false);
|
||||||
void createAttachedCard(const CardItem *sourceCard, const QString &dbCardName);
|
void createAttachedCard(const CardItem *sourceCard, const QString &dbCardName);
|
||||||
bool createRelatedFromRelation(const CardItem *sourceCard, const CardRelation *cardRelation);
|
bool createRelatedFromRelation(const CardItem *sourceCard, const CardRelation *cardRelation);
|
||||||
QString dbNameFromTokenDisplayName(const QString &tokenName);
|
|
||||||
|
|
||||||
QRectF bRect;
|
QRectF bRect;
|
||||||
|
|
||||||
|
|
@ -259,7 +265,7 @@ private:
|
||||||
|
|
||||||
void initSayMenu();
|
void initSayMenu();
|
||||||
|
|
||||||
void eventConnectionStateChanged(const Event_ConnectionStateChanged &event);
|
// void eventConnectionStateChanged(const Event_ConnectionStateChanged &event);
|
||||||
void eventGameSay(const Event_GameSay &event);
|
void eventGameSay(const Event_GameSay &event);
|
||||||
void eventShuffle(const Event_Shuffle &event);
|
void eventShuffle(const Event_Shuffle &event);
|
||||||
void eventRollDie(const Event_RollDie &event);
|
void eventRollDie(const Event_RollDie &event);
|
||||||
|
|
@ -306,12 +312,12 @@ public:
|
||||||
{
|
{
|
||||||
Type = typeOther
|
Type = typeOther
|
||||||
};
|
};
|
||||||
int type() const
|
int type() const override
|
||||||
{
|
{
|
||||||
return Type;
|
return Type;
|
||||||
}
|
}
|
||||||
QRectF boundingRect() const;
|
QRectF boundingRect() const override;
|
||||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
|
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
|
||||||
|
|
||||||
void playCard(CardItem *c, bool faceDown, bool tapped);
|
void playCard(CardItem *c, bool faceDown, bool tapped);
|
||||||
void addCard(CardItem *c);
|
void addCard(CardItem *c);
|
||||||
|
|
@ -334,7 +340,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
Player(const ServerInfo_User &info, int _id, bool _local, TabGame *_parent);
|
Player(const ServerInfo_User &info, int _id, bool _local, TabGame *_parent);
|
||||||
~Player();
|
~Player() override;
|
||||||
void retranslateUi();
|
void retranslateUi();
|
||||||
void clear();
|
void clear();
|
||||||
TabGame *getGame() const
|
TabGame *getGame() const
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
#include "releasechannel.h"
|
#include "releasechannel.h"
|
||||||
#include "qt-json/json.h"
|
|
||||||
#include "version_string.h"
|
#include "version_string.h"
|
||||||
|
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
|
|
@ -93,21 +92,20 @@ QString StableReleaseChannel::getReleaseChannelUrl() const
|
||||||
|
|
||||||
void StableReleaseChannel::releaseListFinished()
|
void StableReleaseChannel::releaseListFinished()
|
||||||
{
|
{
|
||||||
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
|
auto *reply = static_cast<QNetworkReply *>(sender());
|
||||||
bool ok;
|
QJsonParseError parseError{};
|
||||||
QString tmp = QString(reply->readAll());
|
QJsonDocument jsonResponse = QJsonDocument::fromJson(reply->readAll(), &parseError);
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
|
if (parseError.error != QJsonParseError::NoError) {
|
||||||
QVariantMap resultMap = QtJson::Json::parse(tmp, ok).toMap();
|
qWarning() << "No reply received from the release update server.";
|
||||||
if (!ok) {
|
|
||||||
qWarning() << "No reply received from the release update server:" << tmp;
|
|
||||||
emit error(tr("No reply received from the release update server."));
|
emit error(tr("No reply received from the release update server."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVariantMap resultMap = jsonResponse.toVariant().toMap();
|
||||||
if (!(resultMap.contains("name") && resultMap.contains("html_url") && resultMap.contains("tag_name") &&
|
if (!(resultMap.contains("name") && resultMap.contains("html_url") && resultMap.contains("tag_name") &&
|
||||||
resultMap.contains("published_at"))) {
|
resultMap.contains("published_at"))) {
|
||||||
qWarning() << "Invalid received from the release update server:" << tmp;
|
qWarning() << "Invalid received from the release update server.";
|
||||||
emit error(tr("Invalid reply received from the release update server."));
|
emit error(tr("Invalid reply received from the release update server."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -145,7 +143,7 @@ void StableReleaseChannel::releaseListFinished()
|
||||||
QString myHash = QString(VERSION_COMMIT);
|
QString myHash = QString(VERSION_COMMIT);
|
||||||
qDebug() << "Current hash=" << myHash << "update hash=" << shortHash;
|
qDebug() << "Current hash=" << myHash << "update hash=" << shortHash;
|
||||||
|
|
||||||
qDebug() << "Got reply from release server, size=" << tmp.size() << "name=" << lastRelease->getName()
|
qDebug() << "Got reply from release server, name=" << lastRelease->getName()
|
||||||
<< "desc=" << lastRelease->getDescriptionUrl() << "date=" << lastRelease->getPublishDate()
|
<< "desc=" << lastRelease->getDescriptionUrl() << "date=" << lastRelease->getPublishDate()
|
||||||
<< "url=" << lastRelease->getDownloadUrl();
|
<< "url=" << lastRelease->getDownloadUrl();
|
||||||
|
|
||||||
|
|
@ -158,26 +156,25 @@ void StableReleaseChannel::releaseListFinished()
|
||||||
|
|
||||||
void StableReleaseChannel::tagListFinished()
|
void StableReleaseChannel::tagListFinished()
|
||||||
{
|
{
|
||||||
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
|
auto *reply = static_cast<QNetworkReply *>(sender());
|
||||||
bool ok;
|
QJsonParseError parseError{};
|
||||||
QString tmp = QString(reply->readAll());
|
QJsonDocument jsonResponse = QJsonDocument::fromJson(reply->readAll(), &parseError);
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
|
if (parseError.error != QJsonParseError::NoError) {
|
||||||
QVariantMap resultMap = QtJson::Json::parse(tmp, ok).toMap();
|
qWarning() << "No reply received from the tag update server.";
|
||||||
if (!ok) {
|
|
||||||
qWarning() << "No reply received from the tag update server:" << tmp;
|
|
||||||
emit error(tr("No reply received from the tag update server."));
|
emit error(tr("No reply received from the tag update server."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVariantMap resultMap = jsonResponse.toVariant().toMap();
|
||||||
if (!(resultMap.contains("object") && resultMap["object"].toMap().contains("sha"))) {
|
if (!(resultMap.contains("object") && resultMap["object"].toMap().contains("sha"))) {
|
||||||
qWarning() << "Invalid received from the tag update server:" << tmp;
|
qWarning() << "Invalid received from the tag update server.";
|
||||||
emit error(tr("Invalid reply received from the tag update server."));
|
emit error(tr("Invalid reply received from the tag update server."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
lastRelease->setCommitHash(resultMap["object"].toMap()["sha"].toString());
|
lastRelease->setCommitHash(resultMap["object"].toMap()["sha"].toString());
|
||||||
qDebug() << "Got reply from tag server, size=" << tmp.size() << "commit=" << lastRelease->getCommitHash();
|
qDebug() << "Got reply from tag server, commit=" << lastRelease->getCommitHash();
|
||||||
|
|
||||||
QString shortHash = lastRelease->getCommitHash().left(GIT_SHORT_HASH_LEN);
|
QString shortHash = lastRelease->getCommitHash().left(GIT_SHORT_HASH_LEN);
|
||||||
QString myHash = QString(VERSION_COMMIT);
|
QString myHash = QString(VERSION_COMMIT);
|
||||||
|
|
@ -190,7 +187,6 @@ void StableReleaseChannel::tagListFinished()
|
||||||
void StableReleaseChannel::fileListFinished()
|
void StableReleaseChannel::fileListFinished()
|
||||||
{
|
{
|
||||||
// Only implemented to satisfy interface
|
// Only implemented to satisfy interface
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString BetaReleaseChannel::getManualDownloadUrl() const
|
QString BetaReleaseChannel::getManualDownloadUrl() const
|
||||||
|
|
@ -210,7 +206,7 @@ QString BetaReleaseChannel::getReleaseChannelUrl() const
|
||||||
|
|
||||||
void BetaReleaseChannel::releaseListFinished()
|
void BetaReleaseChannel::releaseListFinished()
|
||||||
{
|
{
|
||||||
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
|
auto *reply = static_cast<QNetworkReply *>(sender());
|
||||||
QByteArray jsonData = reply->readAll();
|
QByteArray jsonData = reply->readAll();
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
|
|
||||||
|
|
@ -224,7 +220,7 @@ void BetaReleaseChannel::releaseListFinished()
|
||||||
*/
|
*/
|
||||||
QVariantMap resultMap = array.at(0).toObject().toVariantMap();
|
QVariantMap resultMap = array.at(0).toObject().toVariantMap();
|
||||||
|
|
||||||
if (array.size() == 0 || resultMap.size() == 0) {
|
if (array.empty() || resultMap.empty()) {
|
||||||
qWarning() << "No reply received from the release update server:" << QString(jsonData);
|
qWarning() << "No reply received from the release update server:" << QString(jsonData);
|
||||||
emit error(tr("No reply received from the release update server."));
|
emit error(tr("No reply received from the release update server."));
|
||||||
return;
|
return;
|
||||||
|
|
@ -262,18 +258,17 @@ void BetaReleaseChannel::releaseListFinished()
|
||||||
|
|
||||||
void BetaReleaseChannel::fileListFinished()
|
void BetaReleaseChannel::fileListFinished()
|
||||||
{
|
{
|
||||||
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
|
auto *reply = static_cast<QNetworkReply *>(sender());
|
||||||
QByteArray jsonData = reply->readAll();
|
QJsonParseError parseError{};
|
||||||
|
QJsonDocument jsonResponse = QJsonDocument::fromJson(reply->readAll(), &parseError);
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
bool ok;
|
if (parseError.error != QJsonParseError::NoError) {
|
||||||
|
qWarning() << "No reply received from the file update server.";
|
||||||
QVariantList resultList = QtJson::Json::parse(jsonData, ok).toList();
|
|
||||||
if (!ok) {
|
|
||||||
qWarning() << "No reply received from the file update server:" << QString(jsonData);
|
|
||||||
emit error(tr("No reply received from the file update server."));
|
emit error(tr("No reply received from the file update server."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVariantList resultList = jsonResponse.toVariant().toList();
|
||||||
QString shortHash = lastRelease->getCommitHash().left(GIT_SHORT_HASH_LEN);
|
QString shortHash = lastRelease->getCommitHash().left(GIT_SHORT_HASH_LEN);
|
||||||
QString myHash = QString(VERSION_COMMIT);
|
QString myHash = QString(VERSION_COMMIT);
|
||||||
qDebug() << "Current hash=" << myHash << "update hash=" << shortHash;
|
qDebug() << "Current hash=" << myHash << "update hash=" << shortHash;
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QVariantMap>
|
#include <QVariantMap>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
class QNetworkReply;
|
class QNetworkReply;
|
||||||
class QNetworkAccessManager;
|
class QNetworkAccessManager;
|
||||||
|
|
@ -15,8 +16,8 @@ class Release
|
||||||
friend class BetaReleaseChannel;
|
friend class BetaReleaseChannel;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Release(){};
|
Release() = default;
|
||||||
~Release(){};
|
~Release() = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString name, descriptionUrl, downloadUrl, commitHash;
|
QString name, descriptionUrl, downloadUrl, commitHash;
|
||||||
|
|
@ -26,20 +27,20 @@ private:
|
||||||
protected:
|
protected:
|
||||||
void setName(QString _name)
|
void setName(QString _name)
|
||||||
{
|
{
|
||||||
name = _name;
|
name = std::move(_name);
|
||||||
}
|
}
|
||||||
void setDescriptionUrl(QString _descriptionUrl)
|
void setDescriptionUrl(QString _descriptionUrl)
|
||||||
{
|
{
|
||||||
descriptionUrl = _descriptionUrl;
|
descriptionUrl = std::move(_descriptionUrl);
|
||||||
}
|
}
|
||||||
void setDownloadUrl(QString _downloadUrl)
|
void setDownloadUrl(QString _downloadUrl)
|
||||||
{
|
{
|
||||||
downloadUrl = _downloadUrl;
|
downloadUrl = std::move(_downloadUrl);
|
||||||
compatibleVersionFound = true;
|
compatibleVersionFound = true;
|
||||||
}
|
}
|
||||||
void setCommitHash(QString _commitHash)
|
void setCommitHash(QString _commitHash)
|
||||||
{
|
{
|
||||||
commitHash = _commitHash;
|
commitHash = std::move(_commitHash);
|
||||||
}
|
}
|
||||||
void setPublishDate(QDate _publishDate)
|
void setPublishDate(QDate _publishDate)
|
||||||
{
|
{
|
||||||
|
|
@ -78,7 +79,7 @@ class ReleaseChannel : public QObject
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
ReleaseChannel();
|
ReleaseChannel();
|
||||||
~ReleaseChannel();
|
~ReleaseChannel() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// shared by all instances
|
// shared by all instances
|
||||||
|
|
@ -116,33 +117,41 @@ class StableReleaseChannel : public ReleaseChannel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
StableReleaseChannel(){};
|
StableReleaseChannel() = default;
|
||||||
~StableReleaseChannel(){};
|
~StableReleaseChannel() override = default;
|
||||||
virtual QString getManualDownloadUrl() const;
|
|
||||||
virtual QString getName() const;
|
QString getManualDownloadUrl() const override;
|
||||||
|
|
||||||
|
QString getName() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual QString getReleaseChannelUrl() const;
|
QString getReleaseChannelUrl() const override;
|
||||||
protected slots:
|
protected slots:
|
||||||
virtual void releaseListFinished();
|
|
||||||
|
void releaseListFinished() override;
|
||||||
void tagListFinished();
|
void tagListFinished();
|
||||||
virtual void fileListFinished();
|
|
||||||
|
void fileListFinished() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BetaReleaseChannel : public ReleaseChannel
|
class BetaReleaseChannel : public ReleaseChannel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
BetaReleaseChannel(){};
|
BetaReleaseChannel() = default;
|
||||||
~BetaReleaseChannel(){};
|
~BetaReleaseChannel() override = default;
|
||||||
virtual QString getManualDownloadUrl() const;
|
|
||||||
virtual QString getName() const;
|
QString getManualDownloadUrl() const override;
|
||||||
|
|
||||||
|
QString getName() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual QString getReleaseChannelUrl() const;
|
QString getReleaseChannelUrl() const override;
|
||||||
protected slots:
|
protected slots:
|
||||||
virtual void releaseListFinished();
|
|
||||||
virtual void fileListFinished();
|
void releaseListFinished() override;
|
||||||
|
|
||||||
|
void fileListFinished() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -18,12 +18,13 @@
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
#include <QWebSocket>
|
||||||
|
|
||||||
static const unsigned int protocolVersion = 14;
|
static const unsigned int protocolVersion = 14;
|
||||||
|
|
||||||
RemoteClient::RemoteClient(QObject *parent)
|
RemoteClient::RemoteClient(QObject *parent)
|
||||||
: AbstractClient(parent), timeRunning(0), lastDataReceived(0), messageInProgress(false), handshakeStarted(false),
|
: AbstractClient(parent), timeRunning(0), lastDataReceived(0), messageInProgress(false), handshakeStarted(false),
|
||||||
messageLength(0)
|
usingWebSocket(false), messageLength(0)
|
||||||
{
|
{
|
||||||
|
|
||||||
clearNewClientFeatures();
|
clearNewClientFeatures();
|
||||||
|
|
@ -38,6 +39,13 @@ RemoteClient::RemoteClient(QObject *parent)
|
||||||
connect(socket, SIGNAL(readyRead()), this, SLOT(readData()));
|
connect(socket, SIGNAL(readyRead()), this, SLOT(readData()));
|
||||||
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this,
|
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this,
|
||||||
SLOT(slotSocketError(QAbstractSocket::SocketError)));
|
SLOT(slotSocketError(QAbstractSocket::SocketError)));
|
||||||
|
|
||||||
|
websocket = new QWebSocket(QString(), QWebSocketProtocol::VersionLatest, this);
|
||||||
|
connect(websocket, &QWebSocket::binaryMessageReceived, this, &RemoteClient::websocketMessageReceived);
|
||||||
|
connect(websocket, &QWebSocket::connected, this, &RemoteClient::slotConnected);
|
||||||
|
connect(websocket, SIGNAL(error(QAbstractSocket::SocketError)), this,
|
||||||
|
SLOT(slotWebSocketError(QAbstractSocket::SocketError)));
|
||||||
|
|
||||||
connect(this, SIGNAL(serverIdentificationEventReceived(const Event_ServerIdentification &)), this,
|
connect(this, SIGNAL(serverIdentificationEventReceived(const Event_ServerIdentification &)), this,
|
||||||
SLOT(processServerIdentificationEvent(const Event_ServerIdentification &)));
|
SLOT(processServerIdentificationEvent(const Event_ServerIdentification &)));
|
||||||
connect(this, SIGNAL(connectionClosedEventReceived(Event_ConnectionClosed)), this,
|
connect(this, SIGNAL(connectionClosedEventReceived(Event_ConnectionClosed)), this,
|
||||||
|
|
@ -69,15 +77,25 @@ void RemoteClient::slotSocketError(QAbstractSocket::SocketError /*error*/)
|
||||||
emit socketError(errorString);
|
emit socketError(errorString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RemoteClient::slotWebSocketError(QAbstractSocket::SocketError /*error*/)
|
||||||
|
{
|
||||||
|
|
||||||
|
QString errorString = websocket->errorString();
|
||||||
|
doDisconnectFromServer();
|
||||||
|
emit socketError(errorString);
|
||||||
|
}
|
||||||
|
|
||||||
void RemoteClient::slotConnected()
|
void RemoteClient::slotConnected()
|
||||||
{
|
{
|
||||||
timeRunning = lastDataReceived = 0;
|
timeRunning = lastDataReceived = 0;
|
||||||
timer->start();
|
timer->start();
|
||||||
|
|
||||||
// dirty hack to be compatible with v14 server
|
if (!usingWebSocket) {
|
||||||
sendCommandContainer(CommandContainer());
|
// dirty hack to be compatible with v14 server
|
||||||
getNewCmdId();
|
sendCommandContainer(CommandContainer());
|
||||||
// end of hack
|
getNewCmdId();
|
||||||
|
// end of hack
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteClient::processServerIdentificationEvent(const Event_ServerIdentification &event)
|
void RemoteClient::processServerIdentificationEvent(const Event_ServerIdentification &event)
|
||||||
|
|
@ -217,7 +235,7 @@ void RemoteClient::loginResponse(const Response &response)
|
||||||
missingFeatures << QString::fromStdString(resp.missing_features(i));
|
missingFeatures << QString::fromStdString(resp.missing_features(i));
|
||||||
}
|
}
|
||||||
emit loginError(response.response_code(), QString::fromStdString(resp.denied_reason_str()),
|
emit loginError(response.response_code(), QString::fromStdString(resp.denied_reason_str()),
|
||||||
resp.denied_end_time(), missingFeatures);
|
static_cast<quint32>(resp.denied_end_time()), missingFeatures);
|
||||||
setStatus(StatusDisconnecting);
|
setStatus(StatusDisconnecting);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -236,7 +254,7 @@ void RemoteClient::registerResponse(const Response &response)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
emit registerError(response.response_code(), QString::fromStdString(resp.denied_reason_str()),
|
emit registerError(response.response_code(), QString::fromStdString(resp.denied_reason_str()),
|
||||||
resp.denied_end_time());
|
static_cast<quint32>(resp.denied_end_time()));
|
||||||
setStatus(StatusDisconnecting);
|
setStatus(StatusDisconnecting);
|
||||||
doDisconnectFromServer();
|
doDisconnectFromServer();
|
||||||
break;
|
break;
|
||||||
|
|
@ -301,21 +319,51 @@ void RemoteClient::readData()
|
||||||
} while (!inputBuffer.isEmpty());
|
} while (!inputBuffer.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RemoteClient::websocketMessageReceived(const QByteArray &message)
|
||||||
|
{
|
||||||
|
lastDataReceived = timeRunning;
|
||||||
|
ServerMessage newServerMessage;
|
||||||
|
newServerMessage.ParseFromArray(message.data(), message.length());
|
||||||
|
#ifdef QT_DEBUG
|
||||||
|
qDebug() << "IN" << messageLength << QString::fromStdString(newServerMessage.ShortDebugString());
|
||||||
|
#endif
|
||||||
|
processProtocolItem(newServerMessage);
|
||||||
|
}
|
||||||
|
|
||||||
void RemoteClient::sendCommandContainer(const CommandContainer &cont)
|
void RemoteClient::sendCommandContainer(const CommandContainer &cont)
|
||||||
{
|
{
|
||||||
QByteArray buf;
|
|
||||||
unsigned int size = cont.ByteSize();
|
auto size = static_cast<unsigned int>(cont.ByteSize());
|
||||||
#ifdef QT_DEBUG
|
#ifdef QT_DEBUG
|
||||||
qDebug() << "OUT" << size << QString::fromStdString(cont.ShortDebugString());
|
qDebug() << "OUT" << size << QString::fromStdString(cont.ShortDebugString());
|
||||||
#endif
|
#endif
|
||||||
buf.resize(size + 4);
|
|
||||||
cont.SerializeToArray(buf.data() + 4, size);
|
|
||||||
buf.data()[3] = (unsigned char)size;
|
|
||||||
buf.data()[2] = (unsigned char)(size >> 8);
|
|
||||||
buf.data()[1] = (unsigned char)(size >> 16);
|
|
||||||
buf.data()[0] = (unsigned char)(size >> 24);
|
|
||||||
|
|
||||||
socket->write(buf);
|
QByteArray buf;
|
||||||
|
if (usingWebSocket) {
|
||||||
|
buf.resize(size);
|
||||||
|
cont.SerializeToArray(buf.data(), size);
|
||||||
|
websocket->sendBinaryMessage(buf);
|
||||||
|
} else {
|
||||||
|
buf.resize(size + 4);
|
||||||
|
cont.SerializeToArray(buf.data() + 4, size);
|
||||||
|
buf.data()[3] = (unsigned char)size;
|
||||||
|
buf.data()[2] = (unsigned char)(size >> 8);
|
||||||
|
buf.data()[1] = (unsigned char)(size >> 16);
|
||||||
|
buf.data()[0] = (unsigned char)(size >> 24);
|
||||||
|
|
||||||
|
socket->write(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteClient::connectToHost(const QString &hostname, unsigned int port)
|
||||||
|
{
|
||||||
|
usingWebSocket = port == 443 || port == 80 || port == 4748 || port == 8080;
|
||||||
|
if (usingWebSocket) {
|
||||||
|
QUrl url(QString("%1://%2:%3/servatrice").arg(port == 443 ? "wss" : "ws").arg(hostname).arg(port));
|
||||||
|
websocket->open(url);
|
||||||
|
} else {
|
||||||
|
socket->connectToHost(hostname, static_cast<quint16>(port));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteClient::doConnectToServer(const QString &hostname,
|
void RemoteClient::doConnectToServer(const QString &hostname,
|
||||||
|
|
@ -330,7 +378,7 @@ void RemoteClient::doConnectToServer(const QString &hostname,
|
||||||
lastHostname = hostname;
|
lastHostname = hostname;
|
||||||
lastPort = port;
|
lastPort = port;
|
||||||
|
|
||||||
socket->connectToHost(hostname, port);
|
connectToHost(hostname, port);
|
||||||
setStatus(StatusConnecting);
|
setStatus(StatusConnecting);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -354,7 +402,7 @@ void RemoteClient::doRegisterToServer(const QString &hostname,
|
||||||
lastHostname = hostname;
|
lastHostname = hostname;
|
||||||
lastPort = port;
|
lastPort = port;
|
||||||
|
|
||||||
socket->connectToHost(hostname, port);
|
connectToHost(hostname, port);
|
||||||
setStatus(StatusRegistering);
|
setStatus(StatusRegistering);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -364,7 +412,7 @@ void RemoteClient::doActivateToServer(const QString &_token)
|
||||||
|
|
||||||
token = _token;
|
token = _token;
|
||||||
|
|
||||||
socket->connectToHost(lastHostname, lastPort);
|
connectToHost(lastHostname, static_cast<unsigned int>(lastPort));
|
||||||
setStatus(StatusActivating);
|
setStatus(StatusActivating);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -377,17 +425,19 @@ void RemoteClient::doDisconnectFromServer()
|
||||||
messageLength = 0;
|
messageLength = 0;
|
||||||
|
|
||||||
QList<PendingCommand *> pc = pendingCommands.values();
|
QList<PendingCommand *> pc = pendingCommands.values();
|
||||||
for (int i = 0; i < pc.size(); i++) {
|
for (const auto &i : pc) {
|
||||||
Response response;
|
Response response;
|
||||||
response.set_response_code(Response::RespNotConnected);
|
response.set_response_code(Response::RespNotConnected);
|
||||||
response.set_cmd_id(pc[i]->getCommandContainer().cmd_id());
|
response.set_cmd_id(i->getCommandContainer().cmd_id());
|
||||||
pc[i]->processResponse(response);
|
i->processResponse(response);
|
||||||
|
|
||||||
delete pc[i];
|
delete i;
|
||||||
}
|
}
|
||||||
pendingCommands.clear();
|
pendingCommands.clear();
|
||||||
|
|
||||||
setStatus(StatusDisconnected);
|
setStatus(StatusDisconnected);
|
||||||
|
if (websocket->isValid())
|
||||||
|
websocket->close();
|
||||||
socket->close();
|
socket->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -508,7 +558,7 @@ void RemoteClient::doRequestForgotPasswordToServer(const QString &hostname, unsi
|
||||||
lastHostname = hostname;
|
lastHostname = hostname;
|
||||||
lastPort = port;
|
lastPort = port;
|
||||||
|
|
||||||
socket->connectToHost(lastHostname, lastPort);
|
connectToHost(lastHostname, static_cast<unsigned int>(lastPort));
|
||||||
setStatus(StatusRequestingForgotPassword);
|
setStatus(StatusRequestingForgotPassword);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -540,7 +590,7 @@ void RemoteClient::doSubmitForgotPasswordResetToServer(const QString &hostname,
|
||||||
token = _token;
|
token = _token;
|
||||||
password = _newpassword;
|
password = _newpassword;
|
||||||
|
|
||||||
socket->connectToHost(lastHostname, lastPort);
|
connectToHost(lastHostname, static_cast<unsigned int>(lastPort));
|
||||||
setStatus(StatusSubmitForgotPasswordReset);
|
setStatus(StatusSubmitForgotPasswordReset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -574,7 +624,7 @@ void RemoteClient::doSubmitForgotPasswordChallengeToServer(const QString &hostna
|
||||||
lastPort = port;
|
lastPort = port;
|
||||||
email = _email;
|
email = _email;
|
||||||
|
|
||||||
socket->connectToHost(lastHostname, lastPort);
|
connectToHost(lastHostname, static_cast<unsigned int>(lastPort));
|
||||||
setStatus(StatusSubmitForgotPasswordChallenge);
|
setStatus(StatusSubmitForgotPasswordChallenge);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "abstractclient.h"
|
#include "abstractclient.h"
|
||||||
#include <QTcpSocket>
|
#include <QTcpSocket>
|
||||||
|
#include <QWebSocket>
|
||||||
|
|
||||||
class QTimer;
|
class QTimer;
|
||||||
|
|
||||||
|
|
@ -17,7 +18,6 @@ signals:
|
||||||
void activateError();
|
void activateError();
|
||||||
void socketError(const QString &errorString);
|
void socketError(const QString &errorString);
|
||||||
void protocolVersionMismatch(int clientVersion, int serverVersion);
|
void protocolVersionMismatch(int clientVersion, int serverVersion);
|
||||||
void protocolError();
|
|
||||||
void
|
void
|
||||||
sigConnectToServer(const QString &hostname, unsigned int port, const QString &_userName, const QString &_password);
|
sigConnectToServer(const QString &hostname, unsigned int port, const QString &_userName, const QString &_password);
|
||||||
void sigRegisterToServer(const QString &hostname,
|
void sigRegisterToServer(const QString &hostname,
|
||||||
|
|
@ -25,7 +25,7 @@ signals:
|
||||||
const QString &_userName,
|
const QString &_userName,
|
||||||
const QString &_password,
|
const QString &_password,
|
||||||
const QString &_email,
|
const QString &_email,
|
||||||
const int _gender,
|
int _gender,
|
||||||
const QString &_country,
|
const QString &_country,
|
||||||
const QString &_realname);
|
const QString &_realname);
|
||||||
void sigActivateToServer(const QString &_token);
|
void sigActivateToServer(const QString &_token);
|
||||||
|
|
@ -48,7 +48,9 @@ signals:
|
||||||
private slots:
|
private slots:
|
||||||
void slotConnected();
|
void slotConnected();
|
||||||
void readData();
|
void readData();
|
||||||
|
void websocketMessageReceived(const QByteArray &message);
|
||||||
void slotSocketError(QAbstractSocket::SocketError error);
|
void slotSocketError(QAbstractSocket::SocketError error);
|
||||||
|
void slotWebSocketError(QAbstractSocket::SocketError error);
|
||||||
void ping();
|
void ping();
|
||||||
void processServerIdentificationEvent(const Event_ServerIdentification &event);
|
void processServerIdentificationEvent(const Event_ServerIdentification &event);
|
||||||
void processConnectionClosedEvent(const Event_ConnectionClosed &event);
|
void processConnectionClosedEvent(const Event_ConnectionClosed &event);
|
||||||
|
|
@ -62,7 +64,7 @@ private slots:
|
||||||
const QString &_userName,
|
const QString &_userName,
|
||||||
const QString &_password,
|
const QString &_password,
|
||||||
const QString &_email,
|
const QString &_email,
|
||||||
const int _gender,
|
int _gender,
|
||||||
const QString &_country,
|
const QString &_country,
|
||||||
const QString &_realname);
|
const QString &_realname);
|
||||||
void doLogin();
|
void doLogin();
|
||||||
|
|
@ -85,28 +87,35 @@ private slots:
|
||||||
private:
|
private:
|
||||||
static const int maxTimeout = 10;
|
static const int maxTimeout = 10;
|
||||||
int timeRunning, lastDataReceived;
|
int timeRunning, lastDataReceived;
|
||||||
|
|
||||||
QByteArray inputBuffer;
|
QByteArray inputBuffer;
|
||||||
bool messageInProgress;
|
bool messageInProgress;
|
||||||
bool handshakeStarted;
|
bool handshakeStarted;
|
||||||
bool newMissingFeatureFound(QString _serversMissingFeatures);
|
bool usingWebSocket;
|
||||||
void clearNewClientFeatures();
|
|
||||||
int messageLength;
|
int messageLength;
|
||||||
|
|
||||||
QTimer *timer;
|
QTimer *timer;
|
||||||
QTcpSocket *socket;
|
QTcpSocket *socket;
|
||||||
|
QWebSocket *websocket;
|
||||||
QString lastHostname;
|
QString lastHostname;
|
||||||
int lastPort;
|
int lastPort;
|
||||||
QString getSrvClientID(const QString _hostname);
|
|
||||||
|
QString getSrvClientID(QString _hostname);
|
||||||
|
bool newMissingFeatureFound(QString _serversMissingFeatures);
|
||||||
|
void clearNewClientFeatures();
|
||||||
|
void connectToHost(const QString &hostname, unsigned int port);
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void sendCommandContainer(const CommandContainer &cont);
|
void sendCommandContainer(const CommandContainer &cont) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RemoteClient(QObject *parent = 0);
|
explicit RemoteClient(QObject *parent = nullptr);
|
||||||
~RemoteClient();
|
~RemoteClient() override;
|
||||||
QString peerName() const
|
QString peerName() const
|
||||||
{
|
{
|
||||||
return socket->peerName();
|
if (usingWebSocket) {
|
||||||
|
return websocket->peerName();
|
||||||
|
} else {
|
||||||
|
return socket->peerName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void
|
void
|
||||||
connectToServer(const QString &hostname, unsigned int port, const QString &_userName, const QString &_password);
|
connectToServer(const QString &hostname, unsigned int port, const QString &_userName, const QString &_password);
|
||||||
|
|
@ -115,7 +124,7 @@ public:
|
||||||
const QString &_userName,
|
const QString &_userName,
|
||||||
const QString &_password,
|
const QString &_password,
|
||||||
const QString &_email,
|
const QString &_email,
|
||||||
const int _gender,
|
int _gender,
|
||||||
const QString &_country,
|
const QString &_country,
|
||||||
const QString &_realname);
|
const QString &_realname);
|
||||||
void activateToServer(const QString &_token);
|
void activateToServer(const QString &_token);
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,12 @@
|
||||||
#include "sequenceedit.h"
|
#include "sequenceedit.h"
|
||||||
#include "../settingscache.h"
|
#include "../settingscache.h"
|
||||||
#include <QEvent>
|
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
#include <QLineEdit>
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QToolTip>
|
#include <QToolTip>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
SequenceEdit::SequenceEdit(QString _shorcutName, QWidget *parent) : QWidget(parent)
|
SequenceEdit::SequenceEdit(const QString &_shortcutName, QWidget *parent) : QWidget(parent), shortcutName(_shortcutName)
|
||||||
{
|
{
|
||||||
shorcutName = std::move(_shorcutName);
|
|
||||||
currentKey = 0;
|
|
||||||
keys = 0;
|
|
||||||
valid = false;
|
|
||||||
|
|
||||||
lineEdit = new QLineEdit(this);
|
lineEdit = new QLineEdit(this);
|
||||||
clearButton = new QPushButton("", this);
|
clearButton = new QPushButton("", this);
|
||||||
defaultButton = new QPushButton("", this);
|
defaultButton = new QPushButton("", this);
|
||||||
|
|
@ -42,20 +34,20 @@ SequenceEdit::SequenceEdit(QString _shorcutName, QWidget *parent) : QWidget(pare
|
||||||
connect(defaultButton, SIGNAL(clicked()), this, SLOT(restoreDefault()));
|
connect(defaultButton, SIGNAL(clicked()), this, SLOT(restoreDefault()));
|
||||||
lineEdit->installEventFilter(this);
|
lineEdit->installEventFilter(this);
|
||||||
|
|
||||||
lineEdit->setText(settingsCache->shortcuts().getShortcutString(shorcutName));
|
lineEdit->setText(settingsCache->shortcuts().getShortcutString(shortcutName));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString SequenceEdit::getSecuence()
|
QString SequenceEdit::getSequence()
|
||||||
{
|
{
|
||||||
return lineEdit->text();
|
return lineEdit->text();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SequenceEdit::removeLastShortcut()
|
void SequenceEdit::removeLastShortcut()
|
||||||
{
|
{
|
||||||
QString secuences = lineEdit->text();
|
QString sequences = lineEdit->text();
|
||||||
if (!secuences.isEmpty()) {
|
if (!sequences.isEmpty()) {
|
||||||
if (secuences.lastIndexOf(";") > 0) {
|
if (sequences.lastIndexOf(";") > 0) {
|
||||||
QString valid = secuences.left(secuences.lastIndexOf(";"));
|
QString valid = sequences.left(sequences.lastIndexOf(";"));
|
||||||
lineEdit->setText(valid);
|
lineEdit->setText(valid);
|
||||||
} else {
|
} else {
|
||||||
lineEdit->clear();
|
lineEdit->clear();
|
||||||
|
|
@ -67,18 +59,18 @@ void SequenceEdit::removeLastShortcut()
|
||||||
|
|
||||||
void SequenceEdit::restoreDefault()
|
void SequenceEdit::restoreDefault()
|
||||||
{
|
{
|
||||||
lineEdit->setText(settingsCache->shortcuts().getDefaultShortcutString(shorcutName));
|
lineEdit->setText(settingsCache->shortcuts().getDefaultShortcutString(shortcutName));
|
||||||
updateSettings();
|
updateSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SequenceEdit::refreshShortcut()
|
void SequenceEdit::refreshShortcut()
|
||||||
{
|
{
|
||||||
lineEdit->setText(settingsCache->shortcuts().getShortcutString(shorcutName));
|
lineEdit->setText(settingsCache->shortcuts().getShortcutString(shortcutName));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SequenceEdit::clear()
|
void SequenceEdit::clear()
|
||||||
{
|
{
|
||||||
this->lineEdit->setText("");
|
lineEdit->setText("");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SequenceEdit::eventFilter(QObject *, QEvent *event)
|
bool SequenceEdit::eventFilter(QObject *, QEvent *event)
|
||||||
|
|
@ -142,8 +134,8 @@ void SequenceEdit::finishShortcut()
|
||||||
QKeySequence sequence(keys);
|
QKeySequence sequence(keys);
|
||||||
if (!sequence.isEmpty() && valid) {
|
if (!sequence.isEmpty() && valid) {
|
||||||
QString sequenceString = sequence.toString();
|
QString sequenceString = sequence.toString();
|
||||||
if (settingsCache->shortcuts().isKeyAllowed(shorcutName, sequenceString)) {
|
if (settingsCache->shortcuts().isKeyAllowed(shortcutName, sequenceString)) {
|
||||||
if (settingsCache->shortcuts().isValid(shorcutName, sequenceString)) {
|
if (settingsCache->shortcuts().isValid(shortcutName, sequenceString)) {
|
||||||
if (!lineEdit->text().isEmpty()) {
|
if (!lineEdit->text().isEmpty()) {
|
||||||
if (lineEdit->text().contains(sequenceString)) {
|
if (lineEdit->text().contains(sequenceString)) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -167,5 +159,5 @@ void SequenceEdit::finishShortcut()
|
||||||
|
|
||||||
void SequenceEdit::updateSettings()
|
void SequenceEdit::updateSettings()
|
||||||
{
|
{
|
||||||
settingsCache->shortcuts().setShortcuts(shorcutName, lineEdit->text());
|
settingsCache->shortcuts().setShortcuts(shortcutName, lineEdit->text());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,18 @@
|
||||||
#ifndef SECUENCEEDIT_H
|
#ifndef SEQUENCEEDIT_H
|
||||||
#define SECUENCEEDIT_H
|
#define SEQUENCEEDIT_H
|
||||||
|
|
||||||
|
#include <QEvent>
|
||||||
#include <QKeySequence>
|
#include <QKeySequence>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QPushButton>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
class QLineEdit;
|
|
||||||
class QPushButton;
|
|
||||||
class QEvent;
|
|
||||||
|
|
||||||
class SequenceEdit : public QWidget
|
class SequenceEdit : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
SequenceEdit(QString _shorcutName, QWidget *parent = nullptr);
|
SequenceEdit(const QString &_shortcutName, QWidget *parent = nullptr);
|
||||||
QString getSecuence();
|
QString getSequence();
|
||||||
void refreshShortcut();
|
void refreshShortcut();
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
|
|
@ -25,13 +24,13 @@ protected:
|
||||||
bool eventFilter(QObject *, QEvent *event);
|
bool eventFilter(QObject *, QEvent *event);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString shorcutName;
|
QString shortcutName;
|
||||||
QLineEdit *lineEdit;
|
QLineEdit *lineEdit;
|
||||||
QPushButton *clearButton;
|
QPushButton *clearButton;
|
||||||
QPushButton *defaultButton;
|
QPushButton *defaultButton;
|
||||||
int keys;
|
int keys = 0;
|
||||||
int currentKey;
|
int currentKey = 0;
|
||||||
bool valid;
|
bool valid = false;
|
||||||
|
|
||||||
void processKey(QKeyEvent *e);
|
void processKey(QKeyEvent *e);
|
||||||
int translateModifiers(Qt::KeyboardModifiers state, const QString &text);
|
int translateModifiers(Qt::KeyboardModifiers state, const QString &text);
|
||||||
|
|
@ -39,4 +38,4 @@ private:
|
||||||
void updateSettings();
|
void updateSettings();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SECUENCEEDIT_H
|
#endif // SEQUENCEEDIT_H
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
56
cockatrice/src/settings/downloadsettings.cpp
Normal file
56
cockatrice/src/settings/downloadsettings.cpp
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
#include "downloadsettings.h"
|
||||||
|
#include "settingsmanager.h"
|
||||||
|
|
||||||
|
DownloadSettings::DownloadSettings(const QString &settingPath, QObject *parent = nullptr)
|
||||||
|
: SettingsManager(settingPath + "downloads.ini", parent)
|
||||||
|
{
|
||||||
|
downloadURLs = getValue("urls", "downloads").value<QStringList>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DownloadSettings::setDownloadUrlAt(int index, const QString &url)
|
||||||
|
{
|
||||||
|
downloadURLs.insert(index, url);
|
||||||
|
setValue(QVariant::fromValue(downloadURLs), "urls", "downloads");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If reset or first run, this method contains the default URLs we will populate
|
||||||
|
*/
|
||||||
|
QStringList DownloadSettings::getAllURLs()
|
||||||
|
{
|
||||||
|
// First run, these will be empty
|
||||||
|
if (downloadURLs.count() == 0) {
|
||||||
|
populateDefaultURLs();
|
||||||
|
}
|
||||||
|
|
||||||
|
return downloadURLs;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DownloadSettings::populateDefaultURLs()
|
||||||
|
{
|
||||||
|
downloadURLs.clear();
|
||||||
|
downloadURLs.append("https://api.scryfall.com/cards/!set:uuid!?format=image&face=!prop:side!");
|
||||||
|
downloadURLs.append("https://api.scryfall.com/cards/multiverse/!set:muid!?format=image");
|
||||||
|
downloadURLs.append("http://gatherer.wizards.com/Handlers/Image.ashx?multiverseid=!set:muid!&type=card");
|
||||||
|
downloadURLs.append("http://gatherer.wizards.com/Handlers/Image.ashx?name=!name!&type=card");
|
||||||
|
setValue(QVariant::fromValue(downloadURLs), "urls", "downloads");
|
||||||
|
}
|
||||||
|
|
||||||
|
QString DownloadSettings::getDownloadUrlAt(int index)
|
||||||
|
{
|
||||||
|
if (0 <= index && index < downloadURLs.size()) {
|
||||||
|
return downloadURLs[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
int DownloadSettings::getCount()
|
||||||
|
{
|
||||||
|
return downloadURLs.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DownloadSettings::clear()
|
||||||
|
{
|
||||||
|
downloadURLs.clear();
|
||||||
|
}
|
||||||
28
cockatrice/src/settings/downloadsettings.h
Normal file
28
cockatrice/src/settings/downloadsettings.h
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
#ifndef COCKATRICE_DOWNLOADSETTINGS_H
|
||||||
|
#define COCKATRICE_DOWNLOADSETTINGS_H
|
||||||
|
|
||||||
|
#include "settingsmanager.h"
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class DownloadSettings : public SettingsManager
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
friend class SettingsCache;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit DownloadSettings(const QString &, QObject *);
|
||||||
|
|
||||||
|
QStringList getAllURLs();
|
||||||
|
QString getDownloadUrlAt(int);
|
||||||
|
void setDownloadUrlAt(int, const QString &);
|
||||||
|
int getCount();
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QStringList downloadURLs;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void populateDefaultURLs();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // COCKATRICE_DOWNLOADSETTINGS_H
|
||||||
|
|
@ -164,6 +164,7 @@ SettingsCache::SettingsCache()
|
||||||
messageSettings = new MessageSettings(settingsPath, this);
|
messageSettings = new MessageSettings(settingsPath, this);
|
||||||
gameFiltersSettings = new GameFiltersSettings(settingsPath, this);
|
gameFiltersSettings = new GameFiltersSettings(settingsPath, this);
|
||||||
layoutsSettings = new LayoutsSettings(settingsPath, this);
|
layoutsSettings = new LayoutsSettings(settingsPath, this);
|
||||||
|
downloadSettings = new DownloadSettings(settingsPath, this);
|
||||||
|
|
||||||
if (!QFile(settingsPath + "global.ini").exists())
|
if (!QFile(settingsPath + "global.ini").exists())
|
||||||
translateLegacySettings();
|
translateLegacySettings();
|
||||||
|
|
@ -176,6 +177,7 @@ SettingsCache::SettingsCache()
|
||||||
mbDownloadSpoilers = settings->value("personal/downloadspoilers", false).toBool();
|
mbDownloadSpoilers = settings->value("personal/downloadspoilers", false).toBool();
|
||||||
|
|
||||||
notifyAboutUpdates = settings->value("personal/updatenotification", true).toBool();
|
notifyAboutUpdates = settings->value("personal/updatenotification", true).toBool();
|
||||||
|
notifyAboutNewVersion = settings->value("personal/newversionnotification", true).toBool();
|
||||||
updateReleaseChannel = settings->value("personal/updatereleasechannel", 0).toInt();
|
updateReleaseChannel = settings->value("personal/updatereleasechannel", 0).toInt();
|
||||||
|
|
||||||
lang = settings->value("personal/lang").toString();
|
lang = settings->value("personal/lang").toString();
|
||||||
|
|
@ -220,9 +222,6 @@ SettingsCache::SettingsCache()
|
||||||
|
|
||||||
picDownload = settings->value("personal/picturedownload", true).toBool();
|
picDownload = settings->value("personal/picturedownload", true).toBool();
|
||||||
|
|
||||||
picUrl = settings->value("personal/picUrl", PIC_URL_DEFAULT).toString();
|
|
||||||
picUrlFallback = settings->value("personal/picUrlFallback", PIC_URL_FALLBACK).toString();
|
|
||||||
|
|
||||||
mainWindowGeometry = settings->value("interface/main_window_geometry").toByteArray();
|
mainWindowGeometry = settings->value("interface/main_window_geometry").toByteArray();
|
||||||
tokenDialogGeometry = settings->value("interface/token_dialog_geometry").toByteArray();
|
tokenDialogGeometry = settings->value("interface/token_dialog_geometry").toByteArray();
|
||||||
notificationsEnabled = settings->value("interface/notificationsenabled", true).toBool();
|
notificationsEnabled = settings->value("interface/notificationsenabled", true).toBool();
|
||||||
|
|
@ -234,7 +233,7 @@ SettingsCache::SettingsCache()
|
||||||
displayCardNames = settings->value("cards/displaycardnames", true).toBool();
|
displayCardNames = settings->value("cards/displaycardnames", true).toBool();
|
||||||
horizontalHand = settings->value("hand/horizontal", true).toBool();
|
horizontalHand = settings->value("hand/horizontal", true).toBool();
|
||||||
invertVerticalCoordinate = settings->value("table/invert_vertical", false).toBool();
|
invertVerticalCoordinate = settings->value("table/invert_vertical", false).toBool();
|
||||||
minPlayersForMultiColumnLayout = settings->value("interface/min_players_multicolumn", 5).toInt();
|
minPlayersForMultiColumnLayout = settings->value("interface/min_players_multicolumn", 4).toInt();
|
||||||
tapAnimation = settings->value("cards/tapanimation", true).toBool();
|
tapAnimation = settings->value("cards/tapanimation", true).toBool();
|
||||||
chatMention = settings->value("chat/mention", true).toBool();
|
chatMention = settings->value("chat/mention", true).toBool();
|
||||||
chatMentionCompleter = settings->value("chat/mentioncompleter", true).toBool();
|
chatMentionCompleter = settings->value("chat/mentioncompleter", true).toBool();
|
||||||
|
|
@ -277,6 +276,7 @@ SettingsCache::SettingsCache()
|
||||||
spectatorsCanSeeEverything = settings->value("game/spectatorscanseeeverything", false).toBool();
|
spectatorsCanSeeEverything = settings->value("game/spectatorscanseeeverything", false).toBool();
|
||||||
rememberGameSettings = settings->value("game/remembergamesettings", true).toBool();
|
rememberGameSettings = settings->value("game/remembergamesettings", true).toBool();
|
||||||
clientID = settings->value("personal/clientid", "notset").toString();
|
clientID = settings->value("personal/clientid", "notset").toString();
|
||||||
|
clientVersion = settings->value("personal/clientversion", "notset").toString();
|
||||||
knownMissingFeatures = settings->value("interface/knownmissingfeatures", "").toString();
|
knownMissingFeatures = settings->value("interface/knownmissingfeatures", "").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -415,18 +415,6 @@ void SettingsCache::setPicDownload(int _picDownload)
|
||||||
emit picDownloadChanged();
|
emit picDownloadChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SettingsCache::setPicUrl(const QString &_picUrl)
|
|
||||||
{
|
|
||||||
picUrl = _picUrl;
|
|
||||||
settings->setValue("personal/picUrl", picUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SettingsCache::setPicUrlFallback(const QString &_picUrlFallback)
|
|
||||||
{
|
|
||||||
picUrlFallback = _picUrlFallback;
|
|
||||||
settings->setValue("personal/picUrlFallback", picUrlFallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SettingsCache::setNotificationsEnabled(int _notificationsEnabled)
|
void SettingsCache::setNotificationsEnabled(int _notificationsEnabled)
|
||||||
{
|
{
|
||||||
notificationsEnabled = static_cast<bool>(_notificationsEnabled);
|
notificationsEnabled = static_cast<bool>(_notificationsEnabled);
|
||||||
|
|
@ -603,6 +591,12 @@ void SettingsCache::setClientID(QString _clientID)
|
||||||
settings->setValue("personal/clientid", clientID);
|
settings->setValue("personal/clientid", clientID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SettingsCache::setClientVersion(QString _clientVersion)
|
||||||
|
{
|
||||||
|
clientVersion = std::move(_clientVersion);
|
||||||
|
settings->setValue("personal/clientversion", clientVersion);
|
||||||
|
}
|
||||||
|
|
||||||
QStringList SettingsCache::getCountries() const
|
QStringList SettingsCache::getCountries() const
|
||||||
{
|
{
|
||||||
static QStringList countries = QStringList() << "ad"
|
static QStringList countries = QStringList() << "ad"
|
||||||
|
|
@ -924,6 +918,12 @@ void SettingsCache::setNotifyAboutUpdate(int _notifyaboutupdate)
|
||||||
settings->setValue("personal/updatenotification", notifyAboutUpdates);
|
settings->setValue("personal/updatenotification", notifyAboutUpdates);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SettingsCache::setNotifyAboutNewVersion(int _notifyaboutnewversion)
|
||||||
|
{
|
||||||
|
notifyAboutNewVersion = static_cast<bool>(_notifyaboutnewversion);
|
||||||
|
settings->setValue("personal/newversionnotification", notifyAboutNewVersion);
|
||||||
|
}
|
||||||
|
|
||||||
void SettingsCache::setDownloadSpoilerStatus(bool _spoilerStatus)
|
void SettingsCache::setDownloadSpoilerStatus(bool _spoilerStatus)
|
||||||
{
|
{
|
||||||
mbDownloadSpoilers = _spoilerStatus;
|
mbDownloadSpoilers = _spoilerStatus;
|
||||||
|
|
@ -941,4 +941,4 @@ void SettingsCache::setMaxFontSize(int _max)
|
||||||
{
|
{
|
||||||
maxFontSize = _max;
|
maxFontSize = _max;
|
||||||
settings->setValue("game/maxfontsize", maxFontSize);
|
settings->setValue("game/maxfontsize", maxFontSize);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#define SETTINGSCACHE_H
|
#define SETTINGSCACHE_H
|
||||||
|
|
||||||
#include "settings/carddatabasesettings.h"
|
#include "settings/carddatabasesettings.h"
|
||||||
|
#include "settings/downloadsettings.h"
|
||||||
#include "settings/gamefilterssettings.h"
|
#include "settings/gamefilterssettings.h"
|
||||||
#include "settings/layoutssettings.h"
|
#include "settings/layoutssettings.h"
|
||||||
#include "settings/messagesettings.h"
|
#include "settings/messagesettings.h"
|
||||||
|
|
@ -13,9 +14,6 @@
|
||||||
|
|
||||||
class ReleaseChannel;
|
class ReleaseChannel;
|
||||||
|
|
||||||
// the falbacks are used for cards without a muid
|
|
||||||
#define PIC_URL_DEFAULT "http://gatherer.wizards.com/Handlers/Image.ashx?multiverseid=!cardid!&type=card"
|
|
||||||
#define PIC_URL_FALLBACK "http://gatherer.wizards.com/Handlers/Image.ashx?name=!name!&type=card"
|
|
||||||
// size should be a multiple of 64
|
// size should be a multiple of 64
|
||||||
#define PIXMAPCACHE_SIZE_DEFAULT 2047
|
#define PIXMAPCACHE_SIZE_DEFAULT 2047
|
||||||
#define PIXMAPCACHE_SIZE_MIN 64
|
#define PIXMAPCACHE_SIZE_MIN 64
|
||||||
|
|
@ -60,6 +58,7 @@ private:
|
||||||
MessageSettings *messageSettings;
|
MessageSettings *messageSettings;
|
||||||
GameFiltersSettings *gameFiltersSettings;
|
GameFiltersSettings *gameFiltersSettings;
|
||||||
LayoutsSettings *layoutsSettings;
|
LayoutsSettings *layoutsSettings;
|
||||||
|
DownloadSettings *downloadSettings;
|
||||||
|
|
||||||
QByteArray mainWindowGeometry;
|
QByteArray mainWindowGeometry;
|
||||||
QByteArray tokenDialogGeometry;
|
QByteArray tokenDialogGeometry;
|
||||||
|
|
@ -67,6 +66,7 @@ private:
|
||||||
QString deckPath, replaysPath, picsPath, customPicsPath, cardDatabasePath, customCardDatabasePath,
|
QString deckPath, replaysPath, picsPath, customPicsPath, cardDatabasePath, customCardDatabasePath,
|
||||||
spoilerDatabasePath, tokenDatabasePath, themeName;
|
spoilerDatabasePath, tokenDatabasePath, themeName;
|
||||||
bool notifyAboutUpdates;
|
bool notifyAboutUpdates;
|
||||||
|
bool notifyAboutNewVersion;
|
||||||
bool showTipsOnStartup;
|
bool showTipsOnStartup;
|
||||||
QList<int> seenTips;
|
QList<int> seenTips;
|
||||||
bool mbDownloadSpoilers;
|
bool mbDownloadSpoilers;
|
||||||
|
|
@ -98,6 +98,7 @@ private:
|
||||||
QString picUrl;
|
QString picUrl;
|
||||||
QString picUrlFallback;
|
QString picUrlFallback;
|
||||||
QString clientID;
|
QString clientID;
|
||||||
|
QString clientVersion;
|
||||||
QString knownMissingFeatures;
|
QString knownMissingFeatures;
|
||||||
int pixmapCacheSize;
|
int pixmapCacheSize;
|
||||||
bool scaleCards;
|
bool scaleCards;
|
||||||
|
|
@ -201,6 +202,10 @@ public:
|
||||||
{
|
{
|
||||||
return notifyAboutUpdates;
|
return notifyAboutUpdates;
|
||||||
}
|
}
|
||||||
|
bool getNotifyAboutNewVersion() const
|
||||||
|
{
|
||||||
|
return notifyAboutNewVersion;
|
||||||
|
}
|
||||||
bool getShowTipsOnStartup() const
|
bool getShowTipsOnStartup() const
|
||||||
{
|
{
|
||||||
return showTipsOnStartup;
|
return showTipsOnStartup;
|
||||||
|
|
@ -302,14 +307,6 @@ public:
|
||||||
{
|
{
|
||||||
return ignoreUnregisteredUserMessages;
|
return ignoreUnregisteredUserMessages;
|
||||||
}
|
}
|
||||||
QString getPicUrl() const
|
|
||||||
{
|
|
||||||
return picUrl;
|
|
||||||
}
|
|
||||||
QString getPicUrlFallback() const
|
|
||||||
{
|
|
||||||
return picUrlFallback;
|
|
||||||
}
|
|
||||||
int getPixmapCacheSize() const
|
int getPixmapCacheSize() const
|
||||||
{
|
{
|
||||||
return pixmapCacheSize;
|
return pixmapCacheSize;
|
||||||
|
|
@ -396,11 +393,16 @@ public:
|
||||||
return maxFontSize;
|
return maxFontSize;
|
||||||
}
|
}
|
||||||
void setClientID(QString clientID);
|
void setClientID(QString clientID);
|
||||||
|
void setClientVersion(QString clientVersion);
|
||||||
void setKnownMissingFeatures(QString _knownMissingFeatures);
|
void setKnownMissingFeatures(QString _knownMissingFeatures);
|
||||||
QString getClientID()
|
QString getClientID()
|
||||||
{
|
{
|
||||||
return clientID;
|
return clientID;
|
||||||
}
|
}
|
||||||
|
QString getClientVersion()
|
||||||
|
{
|
||||||
|
return clientVersion;
|
||||||
|
}
|
||||||
QString getKnownMissingFeatures()
|
QString getKnownMissingFeatures()
|
||||||
{
|
{
|
||||||
return knownMissingFeatures;
|
return knownMissingFeatures;
|
||||||
|
|
@ -429,6 +431,10 @@ public:
|
||||||
{
|
{
|
||||||
return *layoutsSettings;
|
return *layoutsSettings;
|
||||||
}
|
}
|
||||||
|
DownloadSettings &downloads() const
|
||||||
|
{
|
||||||
|
return *downloadSettings;
|
||||||
|
}
|
||||||
bool getIsPortableBuild() const
|
bool getIsPortableBuild() const
|
||||||
{
|
{
|
||||||
return isPortableBuild;
|
return isPortableBuild;
|
||||||
|
|
@ -477,8 +483,6 @@ public slots:
|
||||||
void setSoundThemeName(const QString &_soundThemeName);
|
void setSoundThemeName(const QString &_soundThemeName);
|
||||||
void setIgnoreUnregisteredUsers(int _ignoreUnregisteredUsers);
|
void setIgnoreUnregisteredUsers(int _ignoreUnregisteredUsers);
|
||||||
void setIgnoreUnregisteredUserMessages(int _ignoreUnregisteredUserMessages);
|
void setIgnoreUnregisteredUserMessages(int _ignoreUnregisteredUserMessages);
|
||||||
void setPicUrl(const QString &_picUrl);
|
|
||||||
void setPicUrlFallback(const QString &_picUrlFallback);
|
|
||||||
void setPixmapCacheSize(const int _pixmapCacheSize);
|
void setPixmapCacheSize(const int _pixmapCacheSize);
|
||||||
void setCardScaling(const int _scaleCards);
|
void setCardScaling(const int _scaleCards);
|
||||||
void setShowMessagePopups(const int _showMessagePopups);
|
void setShowMessagePopups(const int _showMessagePopups);
|
||||||
|
|
@ -499,6 +503,7 @@ public slots:
|
||||||
void setSpectatorsCanSeeEverything(const bool _spectatorsCanSeeEverything);
|
void setSpectatorsCanSeeEverything(const bool _spectatorsCanSeeEverything);
|
||||||
void setRememberGameSettings(const bool _rememberGameSettings);
|
void setRememberGameSettings(const bool _rememberGameSettings);
|
||||||
void setNotifyAboutUpdate(int _notifyaboutupdate);
|
void setNotifyAboutUpdate(int _notifyaboutupdate);
|
||||||
|
void setNotifyAboutNewVersion(int _notifyaboutnewversion);
|
||||||
void setUpdateReleaseChannel(int _updateReleaseChannel);
|
void setUpdateReleaseChannel(int _updateReleaseChannel);
|
||||||
void setMaxFontSize(int _max);
|
void setMaxFontSize(int _max);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -4,19 +4,18 @@
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
ShortcutsSettings::ShortcutsSettings(QString settingsPath, QObject *parent) : QObject(parent)
|
ShortcutsSettings::ShortcutsSettings(const QString &settingsPath, QObject *parent) : QObject(parent)
|
||||||
{
|
{
|
||||||
this->settingsFilePath = std::move(settingsPath);
|
shortCuts = defaultShortCuts;
|
||||||
this->settingsFilePath.append("shortcuts.ini");
|
settingsFilePath = settingsPath;
|
||||||
fillDefaultShorcuts();
|
settingsFilePath.append("shortcuts.ini");
|
||||||
shortCuts = QMap<QString, QList<QKeySequence>>(defaultShortCuts);
|
|
||||||
|
|
||||||
bool exists = QFile(settingsFilePath).exists();
|
bool exists = QFile(settingsFilePath).exists();
|
||||||
|
|
||||||
QSettings shortCutsFile(settingsFilePath, QSettings::IniFormat);
|
QSettings shortCutsFile(settingsFilePath, QSettings::IniFormat);
|
||||||
|
|
||||||
if (exists) {
|
if (exists) {
|
||||||
shortCutsFile.beginGroup("Custom");
|
shortCutsFile.beginGroup(custom);
|
||||||
const QStringList customKeys = shortCutsFile.allKeys();
|
const QStringList customKeys = shortCutsFile.allKeys();
|
||||||
|
|
||||||
QMap<QString, QString> invalidItems;
|
QMap<QString, QString> invalidItems;
|
||||||
|
|
@ -55,114 +54,123 @@ ShortcutsSettings::ShortcutsSettings(QString settingsPath, QObject *parent) : QO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QKeySequence> ShortcutsSettings::getShortcut(QString name)
|
QList<QKeySequence> ShortcutsSettings::getDefaultShortcut(const QString &name) const
|
||||||
|
{
|
||||||
|
return defaultShortCuts.value(name, QList<QKeySequence>());
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QKeySequence> ShortcutsSettings::getShortcut(const QString &name) const
|
||||||
{
|
{
|
||||||
if (shortCuts.contains(name)) {
|
if (shortCuts.contains(name)) {
|
||||||
return shortCuts.value(name);
|
return shortCuts.value(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return defaultShortCuts.value(name, QList<QKeySequence>());
|
return getDefaultShortcut(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
QKeySequence ShortcutsSettings::getSingleShortcut(QString name)
|
QKeySequence ShortcutsSettings::getSingleShortcut(const QString &name) const
|
||||||
{
|
{
|
||||||
return getShortcut(std::move(name)).at(0);
|
return getShortcut(name).at(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ShortcutsSettings::getDefaultShortcutString(QString name)
|
QString ShortcutsSettings::getDefaultShortcutString(const QString &name) const
|
||||||
{
|
{
|
||||||
return stringifySequence(defaultShortCuts.value(name));
|
return stringifySequence(getDefaultShortcut(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ShortcutsSettings::getShortcutString(QString name)
|
QString ShortcutsSettings::getShortcutString(const QString &name) const
|
||||||
{
|
{
|
||||||
return stringifySequence(shortCuts.value(name));
|
return stringifySequence(getShortcut(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ShortcutsSettings::stringifySequence(QList<QKeySequence> Sequence) const
|
QString ShortcutsSettings::stringifySequence(const QList<QKeySequence> &Sequence) const
|
||||||
{
|
{
|
||||||
QString stringSequence;
|
QStringList stringSequence;
|
||||||
for (int i = 0; i < Sequence.size(); ++i) {
|
for (const auto &i : Sequence) {
|
||||||
stringSequence.append(Sequence.at(i).toString(QKeySequence::PortableText));
|
stringSequence.append(i.toString(QKeySequence::PortableText));
|
||||||
if (i < Sequence.size() - 1) {
|
|
||||||
stringSequence.append(";");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return stringSequence;
|
return stringSequence.join(sep);
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QKeySequence> ShortcutsSettings::parseSequenceString(QString stringSequence)
|
QList<QKeySequence> ShortcutsSettings::parseSequenceString(const QString &stringSequence) const
|
||||||
{
|
{
|
||||||
QStringList Sequences = stringSequence.split(";");
|
|
||||||
QList<QKeySequence> SequenceList;
|
QList<QKeySequence> SequenceList;
|
||||||
for (QStringList::const_iterator ss = Sequences.constBegin(); ss != Sequences.constEnd(); ++ss) {
|
for (const QString &shortcut : stringSequence.split(sep)) {
|
||||||
SequenceList.append(QKeySequence(*ss, QKeySequence::PortableText));
|
SequenceList.append(QKeySequence(shortcut, QKeySequence::PortableText));
|
||||||
}
|
}
|
||||||
|
|
||||||
return SequenceList;
|
return SequenceList;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShortcutsSettings::setShortcuts(QString name, QList<QKeySequence> Sequence)
|
void ShortcutsSettings::setShortcuts(const QString &name, const QList<QKeySequence> &Sequence)
|
||||||
{
|
{
|
||||||
shortCuts[name] = Sequence;
|
shortCuts[name] = Sequence;
|
||||||
|
|
||||||
QSettings shortCutsFile(settingsFilePath, QSettings::IniFormat);
|
QSettings shortCutsFile(settingsFilePath, QSettings::IniFormat);
|
||||||
shortCutsFile.beginGroup("Custom");
|
shortCutsFile.beginGroup(custom);
|
||||||
QString stringSequence = stringifySequence(Sequence);
|
shortCutsFile.setValue(name, stringifySequence(Sequence));
|
||||||
shortCutsFile.setValue(name, stringSequence);
|
|
||||||
shortCutsFile.endGroup();
|
shortCutsFile.endGroup();
|
||||||
emit shortCutchanged();
|
emit shortCutChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShortcutsSettings::setShortcuts(QString name, QKeySequence Sequence)
|
void ShortcutsSettings::setShortcuts(const QString &name, const QKeySequence &Sequence)
|
||||||
{
|
{
|
||||||
setShortcuts(std::move(name), QList<QKeySequence>() << Sequence);
|
setShortcuts(name, QList<QKeySequence>{Sequence});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShortcutsSettings::setShortcuts(QString name, QString Sequences)
|
void ShortcutsSettings::setShortcuts(const QString &name, const QString &Sequences)
|
||||||
{
|
{
|
||||||
setShortcuts(std::move(name), parseSequenceString(std::move(Sequences)));
|
setShortcuts(name, parseSequenceString(Sequences));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ShortcutsSettings::isKeyAllowed(QString name, QString Sequences)
|
void ShortcutsSettings::resetAllShortcuts()
|
||||||
|
{
|
||||||
|
shortCuts = defaultShortCuts;
|
||||||
|
QSettings shortCutsFile(settingsFilePath, QSettings::IniFormat);
|
||||||
|
shortCutsFile.beginGroup(custom);
|
||||||
|
shortCutsFile.remove("");
|
||||||
|
shortCutsFile.endGroup();
|
||||||
|
emit shortCutChanged();
|
||||||
|
emit allShortCutsReset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShortcutsSettings::clearAllShortcuts()
|
||||||
|
{
|
||||||
|
QSettings shortCutsFile(settingsFilePath, QSettings::IniFormat);
|
||||||
|
shortCutsFile.beginGroup(custom);
|
||||||
|
for (auto it = shortCuts.begin(); it != shortCuts.end(); ++it) {
|
||||||
|
it.value() = parseSequenceString("");
|
||||||
|
shortCutsFile.setValue(it.key(), "");
|
||||||
|
}
|
||||||
|
shortCutsFile.endGroup();
|
||||||
|
emit shortCutChanged();
|
||||||
|
emit allShortCutsClear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ShortcutsSettings::isKeyAllowed(const QString &name, const QString &Sequences) const
|
||||||
{
|
{
|
||||||
// if the shortcut is not to be used in deck-editor then it doesn't matter
|
// if the shortcut is not to be used in deck-editor then it doesn't matter
|
||||||
if (name.startsWith("Player")) {
|
if (name.startsWith("Player")) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
QString checkSequence = Sequences.split(";").last();
|
QString checkSequence = Sequences.split(sep).last();
|
||||||
QStringList forbiddenKeys = (QStringList() << "Del"
|
QStringList forbiddenKeys{"Del", "Backspace", "Down", "Up", "Left", "Right",
|
||||||
<< "Backspace"
|
"Return", "Enter", "Menu", "Ctrl+Alt+-", "Ctrl+Alt+=", "Ctrl+Alt+[",
|
||||||
<< "Down"
|
"Ctrl+Alt+]", "Tab", "Space", "Shift+S", "Shift+Left", "Shift+Right"};
|
||||||
<< "Up"
|
|
||||||
<< "Left"
|
|
||||||
<< "Right"
|
|
||||||
<< "Return"
|
|
||||||
<< "Enter"
|
|
||||||
<< "Menu"
|
|
||||||
<< "Ctrl+Alt+-"
|
|
||||||
<< "Ctrl+Alt+="
|
|
||||||
<< "Ctrl+Alt+["
|
|
||||||
<< "Ctrl+Alt+]"
|
|
||||||
<< "Tab"
|
|
||||||
<< "Space"
|
|
||||||
<< "Shift+S"
|
|
||||||
<< "Shift+Left"
|
|
||||||
<< "Shift+Right");
|
|
||||||
return !forbiddenKeys.contains(checkSequence);
|
return !forbiddenKeys.contains(checkSequence);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ShortcutsSettings::isValid(QString name, QString Sequences)
|
bool ShortcutsSettings::isValid(const QString &name, const QString &Sequences) const
|
||||||
{
|
{
|
||||||
QString checkSequence = Sequences.split(";").last();
|
QString checkSequence = Sequences.split(sep).last();
|
||||||
QString checkKey = name.left(name.indexOf("/"));
|
QString checkKey = name.left(name.indexOf("/"));
|
||||||
|
|
||||||
QList<QString> allKeys = shortCuts.keys();
|
QList<QString> allKeys = shortCuts.keys();
|
||||||
for (const auto &key : allKeys) {
|
for (const auto &key : allKeys) {
|
||||||
if (key.startsWith(checkKey) || key.startsWith("MainWindow") || checkKey.startsWith("MainWindow")) {
|
if (key.startsWith(checkKey) || key.startsWith("MainWindow") || checkKey.startsWith("MainWindow")) {
|
||||||
QString storedSequence = stringifySequence(shortCuts.value(key));
|
QString storedSequence = stringifySequence(shortCuts.value(key));
|
||||||
QStringList stringSequences = storedSequence.split(";");
|
QStringList stringSequences = storedSequence.split(sep);
|
||||||
if (stringSequences.contains(checkSequence)) {
|
if (stringSequences.contains(checkSequence)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -170,161 +178,3 @@ bool ShortcutsSettings::isValid(QString name, QString Sequences)
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShortcutsSettings::resetAllShortcuts()
|
|
||||||
{
|
|
||||||
for (auto it = defaultShortCuts.begin(); it != defaultShortCuts.end(); ++it) {
|
|
||||||
setShortcuts(it.key(), it.value());
|
|
||||||
}
|
|
||||||
emit allShortCutsReset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShortcutsSettings::clearAllShortcuts()
|
|
||||||
{
|
|
||||||
for (auto it = shortCuts.begin(); it != shortCuts.end(); ++it) {
|
|
||||||
setShortcuts(it.key(), "");
|
|
||||||
}
|
|
||||||
emit allShortCutsClear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShortcutsSettings::fillDefaultShorcuts()
|
|
||||||
{
|
|
||||||
defaultShortCuts["MainWindow/aCheckCardUpdates"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["MainWindow/aConnect"] = parseSequenceString("Ctrl+L");
|
|
||||||
defaultShortCuts["MainWindow/aDeckEditor"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["MainWindow/aDisconnect"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["MainWindow/aExit"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["MainWindow/aFullScreen"] = parseSequenceString("Ctrl+F");
|
|
||||||
defaultShortCuts["MainWindow/aRegister"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["MainWindow/aSettings"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["MainWindow/aSinglePlayer"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["MainWindow/aWatchReplay"] = parseSequenceString("");
|
|
||||||
|
|
||||||
defaultShortCuts["TabDeckEditor/aAnalyzeDeck"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["TabDeckEditor/aClearFilterAll"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["TabDeckEditor/aClearFilterOne"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["TabDeckEditor/aClose"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["TabDeckEditor/aDecrement"] = parseSequenceString("-");
|
|
||||||
defaultShortCuts["TabDeckEditor/aManageSets"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["TabDeckEditor/aEditTokens"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["TabDeckEditor/aExportDeckDecklist"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["TabDeckEditor/aIncrement"] = parseSequenceString("+");
|
|
||||||
defaultShortCuts["TabDeckEditor/aLoadDeck"] = parseSequenceString("Ctrl+O");
|
|
||||||
defaultShortCuts["TabDeckEditor/aLoadDeckFromClipboard"] = parseSequenceString("Ctrl+Shift+V");
|
|
||||||
defaultShortCuts["TabDeckEditor/aNewDeck"] = parseSequenceString("Ctrl+N");
|
|
||||||
defaultShortCuts["TabDeckEditor/aOpenCustomFolder"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["TabDeckEditor/aPrintDeck"] = parseSequenceString("Ctrl+P");
|
|
||||||
defaultShortCuts["TabDeckEditor/aRemoveCard"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["TabDeckEditor/aResetLayout"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["TabDeckEditor/aSaveDeck"] = parseSequenceString("Ctrl+S");
|
|
||||||
defaultShortCuts["TabDeckEditor/aSaveDeckAs"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["TabDeckEditor/aSaveDeckToClipboard"] = parseSequenceString("Ctrl+Shift+C");
|
|
||||||
defaultShortCuts["TabDeckEditor/aSaveDeckToClipboardRaw"] = parseSequenceString("Ctrl+Shift+R");
|
|
||||||
|
|
||||||
defaultShortCuts["DeckViewContainer/loadLocalButton"] = parseSequenceString("Ctrl+O");
|
|
||||||
defaultShortCuts["DeckViewContainer/loadRemoteButton"] = parseSequenceString("Ctrl+Alt+O");
|
|
||||||
|
|
||||||
defaultShortCuts["Player/aDec"] = parseSequenceString("F11");
|
|
||||||
defaultShortCuts["Player/aInc"] = parseSequenceString("F12");
|
|
||||||
defaultShortCuts["Player/aSet"] = parseSequenceString("Ctrl+L");
|
|
||||||
defaultShortCuts["Player/aCloseMostRecentZoneView"] = parseSequenceString("Esc");
|
|
||||||
defaultShortCuts["Player/IncP"] = parseSequenceString("Ctrl++");
|
|
||||||
defaultShortCuts["Player/aAlwaysRevealTopCard"] = parseSequenceString("Ctrl+N");
|
|
||||||
defaultShortCuts["Player/aAttach"] = parseSequenceString("Ctrl+Alt+A");
|
|
||||||
defaultShortCuts["Player/aCCGreen"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aCCRed"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aCCYellow"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aClone"] = parseSequenceString("Ctrl+J");
|
|
||||||
defaultShortCuts["Player/aCreateAnotherToken"] = parseSequenceString("Ctrl+G");
|
|
||||||
defaultShortCuts["Player/aCreateToken"] = parseSequenceString("Ctrl+T");
|
|
||||||
defaultShortCuts["Player/aCreateRelatedTokens"] = parseSequenceString("Ctrl+Shift+T");
|
|
||||||
defaultShortCuts["Player/aDecP"] = parseSequenceString("Ctrl+-");
|
|
||||||
defaultShortCuts["Player/aDecPT"] = parseSequenceString("Ctrl+Alt+-");
|
|
||||||
defaultShortCuts["Player/aDecT"] = parseSequenceString("Alt+-");
|
|
||||||
defaultShortCuts["Player/aDoesntUntap"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aDrawArrow"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aDrawCard"] = parseSequenceString("Ctrl+D");
|
|
||||||
defaultShortCuts["Player/aDrawCards"] = parseSequenceString("Ctrl+E");
|
|
||||||
defaultShortCuts["Player/aFlip"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aIncPT"] = parseSequenceString("Ctrl+Alt++");
|
|
||||||
defaultShortCuts["Player/aIncT"] = parseSequenceString("Alt++");
|
|
||||||
defaultShortCuts["Player/aMoveToBottomLibrary"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aMoveToExile"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aMoveToGraveyard"] = parseSequenceString("Ctrl+Del");
|
|
||||||
defaultShortCuts["Player/aMoveToHand"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aMoveToTopLibrary"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aMulligan"] = parseSequenceString("Ctrl+M");
|
|
||||||
defaultShortCuts["Player/aPeek"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aPlay"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aRCGreen"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aRCRed"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aRCYellow"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aRollDie"] = parseSequenceString("Ctrl+I");
|
|
||||||
defaultShortCuts["Player/aSCGreen"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aSCRed"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aSCYellow"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aSetAnnotation"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aSetPT"] = parseSequenceString("Ctrl+P");
|
|
||||||
defaultShortCuts["Player/aResetPT"] = parseSequenceString("Ctrl+Alt+0");
|
|
||||||
defaultShortCuts["Player/aShuffle"] = parseSequenceString("Ctrl+S");
|
|
||||||
defaultShortCuts["Player/aTap"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aUnattach"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aUndoDraw"] = parseSequenceString("Ctrl+Shift+D");
|
|
||||||
defaultShortCuts["Player/aUntapAll"] = parseSequenceString("Ctrl+U");
|
|
||||||
defaultShortCuts["Player/aViewGraveyard"] = parseSequenceString("F4");
|
|
||||||
defaultShortCuts["Player/aViewLibrary"] = parseSequenceString("F3");
|
|
||||||
defaultShortCuts["Player/aViewRfg"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aViewSideboard"] = parseSequenceString("Ctrl+F3");
|
|
||||||
defaultShortCuts["Player/aViewTopCards"] = parseSequenceString("Ctrl+W");
|
|
||||||
defaultShortCuts["Player/aConcede"] = parseSequenceString("F2");
|
|
||||||
defaultShortCuts["Player/aLeaveGame"] = parseSequenceString("Ctrl+Q");
|
|
||||||
defaultShortCuts["Player/aNextPhase"] = parseSequenceString("Ctrl+Space;Tab");
|
|
||||||
defaultShortCuts["Player/aNextTurn"] = parseSequenceString("Ctrl+Return;Ctrl+Enter");
|
|
||||||
defaultShortCuts["Player/aRemoveLocalArrows"] = parseSequenceString("Ctrl+R");
|
|
||||||
defaultShortCuts["Player/aRotateViewCCW"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aRotateViewCW"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/phase0"] = parseSequenceString("F5");
|
|
||||||
defaultShortCuts["Player/phase1"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/phase10"] = parseSequenceString("F10");
|
|
||||||
defaultShortCuts["Player/phase2"] = parseSequenceString("F6");
|
|
||||||
defaultShortCuts["Player/phase3"] = parseSequenceString("F7");
|
|
||||||
defaultShortCuts["Player/phase4"] = parseSequenceString("F8");
|
|
||||||
defaultShortCuts["Player/phase5"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/phase6"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/phase7"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/phase8"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/phase9"] = parseSequenceString("F9");
|
|
||||||
|
|
||||||
defaultShortCuts["Player/aIncCounter_w"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aDecCounter_w"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aSetCounter_w"] = parseSequenceString("");
|
|
||||||
|
|
||||||
defaultShortCuts["Player/aIncCounter_u"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aDecCounter_u"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aSetCounter_u"] = parseSequenceString("");
|
|
||||||
|
|
||||||
defaultShortCuts["Player/aIncCounter_b"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aDecCounter_b"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aSetCounter_b"] = parseSequenceString("");
|
|
||||||
|
|
||||||
defaultShortCuts["Player/aIncCounter_r"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aDecCounter_r"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aSetCounter_r"] = parseSequenceString("");
|
|
||||||
|
|
||||||
defaultShortCuts["Player/aIncCounter_g"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aDecCounter_g"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aSetCounter_g"] = parseSequenceString("");
|
|
||||||
|
|
||||||
defaultShortCuts["Player/aIncCounter_x"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aDecCounter_x"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aSetCounter_x"] = parseSequenceString("");
|
|
||||||
|
|
||||||
defaultShortCuts["Player/aIncCounter_storm"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aDecCounter_storm"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aSetCounter_storm"] = parseSequenceString("");
|
|
||||||
|
|
||||||
defaultShortCuts["tab_room/aClearChat"] = parseSequenceString("F12");
|
|
||||||
defaultShortCuts["DlgLoadDeckFromClipboard/refreshButton"] = parseSequenceString("F5");
|
|
||||||
defaultShortCuts["Player/aResetLayout"] = parseSequenceString("");
|
|
||||||
defaultShortCuts["Player/aMoveTopToPlayFaceDown"] = parseSequenceString("Ctrl+Shift+E");
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
#ifndef SHORTCUTSSETTINGS_H
|
#ifndef SHORTCUTSSETTINGS_H
|
||||||
#define SHORTCUTSSETTINGS_H
|
#define SHORTCUTSSETTINGS_H
|
||||||
|
|
||||||
|
#include <QHash>
|
||||||
#include <QKeySequence>
|
#include <QKeySequence>
|
||||||
#include <QMap>
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
|
|
||||||
|
|
@ -10,37 +10,186 @@ class ShortcutsSettings : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
ShortcutsSettings(QString settingsFilePath, QObject *parent = nullptr);
|
ShortcutsSettings(const QString &settingsFilePath, QObject *parent = nullptr);
|
||||||
|
|
||||||
QList<QKeySequence> getShortcut(QString name);
|
QList<QKeySequence> getDefaultShortcut(const QString &name) const;
|
||||||
QKeySequence getSingleShortcut(QString name);
|
QList<QKeySequence> getShortcut(const QString &name) const;
|
||||||
|
QKeySequence getSingleShortcut(const QString &name) const;
|
||||||
|
QString getDefaultShortcutString(const QString &name) const;
|
||||||
|
QString getShortcutString(const QString &name) const;
|
||||||
|
|
||||||
QString getDefaultShortcutString(QString name);
|
void setShortcuts(const QString &name, const QList<QKeySequence> &Sequence);
|
||||||
QString getShortcutString(QString name);
|
void setShortcuts(const QString &name, const QKeySequence &Sequence);
|
||||||
|
void setShortcuts(const QString &name, const QString &Sequences);
|
||||||
|
|
||||||
void setShortcuts(QString name, QList<QKeySequence> Sequence);
|
bool isKeyAllowed(const QString &name, const QString &Sequences) const;
|
||||||
void setShortcuts(QString name, QKeySequence Sequence);
|
bool isValid(const QString &name, const QString &Sequences) const;
|
||||||
void setShortcuts(QString name, QString Sequences);
|
|
||||||
|
|
||||||
bool isKeyAllowed(QString name, QString Sequences);
|
|
||||||
bool isValid(QString name, QString Sequences);
|
|
||||||
|
|
||||||
void resetAllShortcuts();
|
void resetAllShortcuts();
|
||||||
void clearAllShortcuts();
|
void clearAllShortcuts();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void shortCutchanged();
|
void shortCutChanged();
|
||||||
void allShortCutsReset();
|
void allShortCutsReset();
|
||||||
void allShortCutsClear();
|
void allShortCutsClear();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
const QChar sep = ';';
|
||||||
|
const QString custom = "Custom";
|
||||||
QString settingsFilePath;
|
QString settingsFilePath;
|
||||||
QMap<QString, QList<QKeySequence>> shortCuts;
|
QHash<QString, QList<QKeySequence>> shortCuts;
|
||||||
QMap<QString, QList<QKeySequence>> defaultShortCuts;
|
|
||||||
void fillDefaultShorcuts();
|
|
||||||
|
|
||||||
QString stringifySequence(QList<QKeySequence> Sequence) const;
|
QString stringifySequence(const QList<QKeySequence> &Sequence) const;
|
||||||
QList<QKeySequence> parseSequenceString(QString stringSequence);
|
QList<QKeySequence> parseSequenceString(const QString &stringSequence) const;
|
||||||
|
|
||||||
|
const QHash<QString, QList<QKeySequence>> defaultShortCuts{
|
||||||
|
{"MainWindow/aCheckCardUpdates", parseSequenceString("")},
|
||||||
|
{"MainWindow/aConnect", parseSequenceString("Ctrl+L")},
|
||||||
|
{"MainWindow/aDeckEditor", parseSequenceString("")},
|
||||||
|
{"MainWindow/aDisconnect", parseSequenceString("")},
|
||||||
|
{"MainWindow/aExit", parseSequenceString("")},
|
||||||
|
{"MainWindow/aFullScreen", parseSequenceString("Ctrl+F")},
|
||||||
|
{"MainWindow/aRegister", parseSequenceString("")},
|
||||||
|
{"MainWindow/aSettings", parseSequenceString("")},
|
||||||
|
{"MainWindow/aSinglePlayer", parseSequenceString("")},
|
||||||
|
{"MainWindow/aWatchReplay", parseSequenceString("")},
|
||||||
|
|
||||||
|
{"TabDeckEditor/aAnalyzeDeck", parseSequenceString("")},
|
||||||
|
{"TabDeckEditor/aClearFilterAll", parseSequenceString("")},
|
||||||
|
{"TabDeckEditor/aClearFilterOne", parseSequenceString("")},
|
||||||
|
{"TabDeckEditor/aClose", parseSequenceString("")},
|
||||||
|
{"TabDeckEditor/aDecrement", parseSequenceString("-")},
|
||||||
|
{"TabDeckEditor/aManageSets", parseSequenceString("")},
|
||||||
|
{"TabDeckEditor/aEditTokens", parseSequenceString("")},
|
||||||
|
{"TabDeckEditor/aExportDeckDecklist", parseSequenceString("")},
|
||||||
|
{"TabDeckEditor/aIncrement", parseSequenceString("+")},
|
||||||
|
{"TabDeckEditor/aLoadDeck", parseSequenceString("Ctrl+O")},
|
||||||
|
{"TabDeckEditor/aLoadDeckFromClipboard", parseSequenceString("Ctrl+Shift+V")},
|
||||||
|
{"TabDeckEditor/aNewDeck", parseSequenceString("Ctrl+N")},
|
||||||
|
{"TabDeckEditor/aOpenCustomFolder", parseSequenceString("")},
|
||||||
|
{"TabDeckEditor/aPrintDeck", parseSequenceString("Ctrl+P")},
|
||||||
|
{"TabDeckEditor/aRemoveCard", parseSequenceString("")},
|
||||||
|
{"TabDeckEditor/aResetLayout", parseSequenceString("")},
|
||||||
|
{"TabDeckEditor/aSaveDeck", parseSequenceString("Ctrl+S")},
|
||||||
|
{"TabDeckEditor/aSaveDeckAs", parseSequenceString("")},
|
||||||
|
{"TabDeckEditor/aSaveDeckToClipboard", parseSequenceString("Ctrl+Shift+C")},
|
||||||
|
{"TabDeckEditor/aSaveDeckToClipboardRaw", parseSequenceString("Ctrl+Shift+R")},
|
||||||
|
|
||||||
|
{"DeckViewContainer/loadLocalButton", parseSequenceString("Ctrl+O")},
|
||||||
|
{"DeckViewContainer/loadRemoteButton", parseSequenceString("Ctrl+Alt+O")},
|
||||||
|
|
||||||
|
{"Player/aSet", parseSequenceString("Ctrl+L")},
|
||||||
|
{"Player/aAlwaysRevealTopCard", parseSequenceString("Ctrl+N")},
|
||||||
|
{"Player/aCloseMostRecentZoneView", parseSequenceString("Esc")},
|
||||||
|
{"Player/aDrawCard", parseSequenceString("Ctrl+D")},
|
||||||
|
{"Player/aDrawCards", parseSequenceString("Ctrl+E")},
|
||||||
|
{"Player/aDec", parseSequenceString("F11")},
|
||||||
|
{"Player/aInc", parseSequenceString("F12")},
|
||||||
|
{"Player/aMoveTopCardToGraveyard", parseSequenceString("")},
|
||||||
|
{"Player/aMoveTopCardsToGraveyard", parseSequenceString("Ctrl+Shift+M")},
|
||||||
|
{"Player/aMoveTopCardToExile", parseSequenceString("")},
|
||||||
|
{"Player/aMoveTopCardsToExile", parseSequenceString("")},
|
||||||
|
{"Player/aMoveTopToPlayFaceDown", parseSequenceString("Ctrl+Shift+E")},
|
||||||
|
{"Player/aMulligan", parseSequenceString("Ctrl+M")},
|
||||||
|
{"Player/aPeek", parseSequenceString("")},
|
||||||
|
{"Player/aPlay", parseSequenceString("")},
|
||||||
|
{"Player/aResetLayout", parseSequenceString("")},
|
||||||
|
{"Player/aRollDie", parseSequenceString("Ctrl+I")},
|
||||||
|
{"Player/aShuffle", parseSequenceString("Ctrl+S")},
|
||||||
|
{"Player/aUndoDraw", parseSequenceString("Ctrl+Shift+D")},
|
||||||
|
{"Player/aUntapAll", parseSequenceString("Ctrl+U")},
|
||||||
|
{"Player/aViewGraveyard", parseSequenceString("F4")},
|
||||||
|
{"Player/aViewLibrary", parseSequenceString("F3")},
|
||||||
|
{"Player/aViewRfg", parseSequenceString("")},
|
||||||
|
{"Player/aViewSideboard", parseSequenceString("Ctrl+F3")},
|
||||||
|
{"Player/aViewTopCards", parseSequenceString("Ctrl+W")},
|
||||||
|
|
||||||
|
{"Player/aAttach", parseSequenceString("Ctrl+Alt+A")},
|
||||||
|
{"Player/aClone", parseSequenceString("Ctrl+J")},
|
||||||
|
{"Player/aCreateAnotherToken", parseSequenceString("Ctrl+G")},
|
||||||
|
{"Player/aCreateToken", parseSequenceString("Ctrl+T")},
|
||||||
|
{"Player/aCreateRelatedTokens", parseSequenceString("Ctrl+Shift+T")},
|
||||||
|
{"Player/aDoesntUntap", parseSequenceString("")},
|
||||||
|
{"Player/aDrawArrow", parseSequenceString("")},
|
||||||
|
{"Player/aFlip", parseSequenceString("")},
|
||||||
|
{"Player/aMoveToBottomLibrary", parseSequenceString("")},
|
||||||
|
{"Player/aMoveToExile", parseSequenceString("")},
|
||||||
|
{"Player/aMoveToGraveyard", parseSequenceString("Ctrl+Del")},
|
||||||
|
{"Player/aMoveToHand", parseSequenceString("")},
|
||||||
|
{"Player/aMoveToTopLibrary", parseSequenceString("")},
|
||||||
|
{"Player/aSetAnnotation", parseSequenceString("")},
|
||||||
|
{"Player/aTap", parseSequenceString("")},
|
||||||
|
{"Player/aUnattach", parseSequenceString("")},
|
||||||
|
|
||||||
|
{"Player/aCCGreen", parseSequenceString("")},
|
||||||
|
{"Player/aCCRed", parseSequenceString("")},
|
||||||
|
{"Player/aCCYellow", parseSequenceString("")},
|
||||||
|
{"Player/aRCGreen", parseSequenceString("")},
|
||||||
|
{"Player/aRCRed", parseSequenceString("")},
|
||||||
|
{"Player/aRCYellow", parseSequenceString("")},
|
||||||
|
{"Player/aSCGreen", parseSequenceString("")},
|
||||||
|
{"Player/aSCRed", parseSequenceString("")},
|
||||||
|
{"Player/aSCYellow", parseSequenceString("")},
|
||||||
|
|
||||||
|
{"Player/aDecP", parseSequenceString("Ctrl+-")},
|
||||||
|
{"Player/aDecPT", parseSequenceString("Ctrl+Alt+-")},
|
||||||
|
{"Player/aDecT", parseSequenceString("Alt+-")},
|
||||||
|
{"Player/aIncP", parseSequenceString("Ctrl++")},
|
||||||
|
{"Player/aIncPT", parseSequenceString("Ctrl+Alt++")},
|
||||||
|
{"Player/aIncT", parseSequenceString("Alt++")},
|
||||||
|
{"Player/aSetPT", parseSequenceString("Ctrl+P")},
|
||||||
|
{"Player/aResetPT", parseSequenceString("Ctrl+Alt+0")},
|
||||||
|
|
||||||
|
{"Player/aConcede", parseSequenceString("F2")},
|
||||||
|
{"Player/aLeaveGame", parseSequenceString("Ctrl+Q")},
|
||||||
|
{"Player/aNextPhase", parseSequenceString("Ctrl+Space;Tab")},
|
||||||
|
{"Player/aNextPhaseAction", parseSequenceString("Shift+Tab")},
|
||||||
|
{"Player/aNextTurn", parseSequenceString("Ctrl+Return;Ctrl+Enter")},
|
||||||
|
{"Player/aRemoveLocalArrows", parseSequenceString("Ctrl+R")},
|
||||||
|
{"Player/aRotateViewCCW", parseSequenceString("")},
|
||||||
|
{"Player/aRotateViewCW", parseSequenceString("")},
|
||||||
|
{"Player/phase0", parseSequenceString("F5")},
|
||||||
|
{"Player/phase1", parseSequenceString("")},
|
||||||
|
{"Player/phase10", parseSequenceString("F10")},
|
||||||
|
{"Player/phase2", parseSequenceString("F6")},
|
||||||
|
{"Player/phase3", parseSequenceString("F7")},
|
||||||
|
{"Player/phase4", parseSequenceString("F8")},
|
||||||
|
{"Player/phase5", parseSequenceString("")},
|
||||||
|
{"Player/phase6", parseSequenceString("")},
|
||||||
|
{"Player/phase7", parseSequenceString("")},
|
||||||
|
{"Player/phase8", parseSequenceString("")},
|
||||||
|
{"Player/phase9", parseSequenceString("F9")},
|
||||||
|
|
||||||
|
{"Player/aDecCounter_w", parseSequenceString("")},
|
||||||
|
{"Player/aIncCounter_w", parseSequenceString("")},
|
||||||
|
{"Player/aSetCounter_w", parseSequenceString("")},
|
||||||
|
|
||||||
|
{"Player/aDecCounter_u", parseSequenceString("")},
|
||||||
|
{"Player/aIncCounter_u", parseSequenceString("")},
|
||||||
|
{"Player/aSetCounter_u", parseSequenceString("")},
|
||||||
|
|
||||||
|
{"Player/aDecCounter_b", parseSequenceString("")},
|
||||||
|
{"Player/aIncCounter_b", parseSequenceString("")},
|
||||||
|
{"Player/aSetCounter_b", parseSequenceString("")},
|
||||||
|
|
||||||
|
{"Player/aDecCounter_r", parseSequenceString("")},
|
||||||
|
{"Player/aIncCounter_r", parseSequenceString("")},
|
||||||
|
{"Player/aSetCounter_r", parseSequenceString("")},
|
||||||
|
|
||||||
|
{"Player/aDecCounter_g", parseSequenceString("")},
|
||||||
|
{"Player/aIncCounter_g", parseSequenceString("")},
|
||||||
|
{"Player/aSetCounter_g", parseSequenceString("")},
|
||||||
|
|
||||||
|
{"Player/aDecCounter_x", parseSequenceString("")},
|
||||||
|
{"Player/aIncCounter_x", parseSequenceString("")},
|
||||||
|
{"Player/aSetCounter_x", parseSequenceString("")},
|
||||||
|
|
||||||
|
{"Player/aDecCounter_storm", parseSequenceString("")},
|
||||||
|
{"Player/aIncCounter_storm", parseSequenceString("")},
|
||||||
|
{"Player/aSetCounter_storm", parseSequenceString("")},
|
||||||
|
|
||||||
|
{"tab_room/aClearChat", parseSequenceString("F12")},
|
||||||
|
{"DlgLoadDeckFromClipboard/refreshButton", parseSequenceString("F5")}};
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SHORTCUTSSETTINGS_H
|
#endif // SHORTCUTSSETTINGS_H
|
||||||
|
|
|
||||||
|
|
@ -590,7 +590,7 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent)
|
||||||
this->installEventFilter(this);
|
this->installEventFilter(this);
|
||||||
|
|
||||||
retranslateUi();
|
retranslateUi();
|
||||||
connect(&settingsCache->shortcuts(), SIGNAL(shortCutchanged()), this, SLOT(refreshShortcuts()));
|
connect(&settingsCache->shortcuts(), SIGNAL(shortCutChanged()), this, SLOT(refreshShortcuts()));
|
||||||
refreshShortcuts();
|
refreshShortcuts();
|
||||||
|
|
||||||
QTimer::singleShot(0, this, SLOT(loadLayout()));
|
QTimer::singleShot(0, this, SLOT(loadLayout()));
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ void ToggleButton::setState(bool _state)
|
||||||
}
|
}
|
||||||
|
|
||||||
DeckViewContainer::DeckViewContainer(int _playerId, TabGame *parent)
|
DeckViewContainer::DeckViewContainer(int _playerId, TabGame *parent)
|
||||||
: QWidget(0), parentGame(parent), playerId(_playerId)
|
: QWidget(nullptr), parentGame(parent), playerId(_playerId)
|
||||||
{
|
{
|
||||||
loadLocalButton = new QPushButton;
|
loadLocalButton = new QPushButton;
|
||||||
loadRemoteButton = new QPushButton;
|
loadRemoteButton = new QPushButton;
|
||||||
|
|
@ -112,7 +112,7 @@ DeckViewContainer::DeckViewContainer(int _playerId, TabGame *parent)
|
||||||
connect(sideboardLockButton, SIGNAL(clicked()), this, SLOT(sideboardLockButtonClicked()));
|
connect(sideboardLockButton, SIGNAL(clicked()), this, SLOT(sideboardLockButtonClicked()));
|
||||||
connect(sideboardLockButton, SIGNAL(stateChanged()), this, SLOT(updateSideboardLockButtonText()));
|
connect(sideboardLockButton, SIGNAL(stateChanged()), this, SLOT(updateSideboardLockButtonText()));
|
||||||
|
|
||||||
QHBoxLayout *buttonHBox = new QHBoxLayout;
|
auto *buttonHBox = new QHBoxLayout;
|
||||||
buttonHBox->addWidget(loadLocalButton);
|
buttonHBox->addWidget(loadLocalButton);
|
||||||
buttonHBox->addWidget(loadRemoteButton);
|
buttonHBox->addWidget(loadRemoteButton);
|
||||||
buttonHBox->addWidget(readyStartButton);
|
buttonHBox->addWidget(readyStartButton);
|
||||||
|
|
@ -123,14 +123,14 @@ DeckViewContainer::DeckViewContainer(int _playerId, TabGame *parent)
|
||||||
connect(deckView, SIGNAL(newCardAdded(AbstractCardItem *)), this, SIGNAL(newCardAdded(AbstractCardItem *)));
|
connect(deckView, SIGNAL(newCardAdded(AbstractCardItem *)), this, SIGNAL(newCardAdded(AbstractCardItem *)));
|
||||||
connect(deckView, SIGNAL(sideboardPlanChanged()), this, SLOT(sideboardPlanChanged()));
|
connect(deckView, SIGNAL(sideboardPlanChanged()), this, SLOT(sideboardPlanChanged()));
|
||||||
|
|
||||||
QVBoxLayout *deckViewLayout = new QVBoxLayout;
|
auto *deckViewLayout = new QVBoxLayout;
|
||||||
deckViewLayout->addLayout(buttonHBox);
|
deckViewLayout->addLayout(buttonHBox);
|
||||||
deckViewLayout->addWidget(deckView);
|
deckViewLayout->addWidget(deckView);
|
||||||
deckViewLayout->setContentsMargins(0, 0, 0, 0);
|
deckViewLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
setLayout(deckViewLayout);
|
setLayout(deckViewLayout);
|
||||||
|
|
||||||
retranslateUi();
|
retranslateUi();
|
||||||
connect(&settingsCache->shortcuts(), SIGNAL(shortCutchanged()), this, SLOT(refreshShortcuts()));
|
connect(&settingsCache->shortcuts(), SIGNAL(shortCutChanged()), this, SLOT(refreshShortcuts()));
|
||||||
refreshShortcuts();
|
refreshShortcuts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -209,6 +209,9 @@ void TabGame::refreshShortcuts()
|
||||||
if (aNextPhase) {
|
if (aNextPhase) {
|
||||||
aNextPhase->setShortcuts(settingsCache->shortcuts().getShortcut("Player/aNextPhase"));
|
aNextPhase->setShortcuts(settingsCache->shortcuts().getShortcut("Player/aNextPhase"));
|
||||||
}
|
}
|
||||||
|
if (aNextPhaseAction) {
|
||||||
|
aNextPhaseAction->setShortcuts(settingsCache->shortcuts().getShortcut("Player/aNextPhaseAction"));
|
||||||
|
}
|
||||||
if (aNextTurn) {
|
if (aNextTurn) {
|
||||||
aNextTurn->setShortcuts(settingsCache->shortcuts().getShortcut("Player/aNextTurn"));
|
aNextTurn->setShortcuts(settingsCache->shortcuts().getShortcut("Player/aNextTurn"));
|
||||||
}
|
}
|
||||||
|
|
@ -299,8 +302,8 @@ void DeckViewContainer::sideboardPlanChanged()
|
||||||
{
|
{
|
||||||
Command_SetSideboardPlan cmd;
|
Command_SetSideboardPlan cmd;
|
||||||
const QList<MoveCard_ToZone> &newPlan = deckView->getSideboardPlan();
|
const QList<MoveCard_ToZone> &newPlan = deckView->getSideboardPlan();
|
||||||
for (int i = 0; i < newPlan.size(); ++i)
|
for (const auto &i : newPlan)
|
||||||
cmd.add_move_list()->CopyFrom(newPlan.at(i));
|
cmd.add_move_list()->CopyFrom(i);
|
||||||
parentGame->sendGameCommand(cmd, playerId);
|
parentGame->sendGameCommand(cmd, playerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -330,7 +333,8 @@ void DeckViewContainer::setDeck(const DeckLoader &deck)
|
||||||
TabGame::TabGame(TabSupervisor *_tabSupervisor, GameReplay *_replay)
|
TabGame::TabGame(TabSupervisor *_tabSupervisor, GameReplay *_replay)
|
||||||
: Tab(_tabSupervisor), secondsElapsed(0), hostId(-1), localPlayerId(-1),
|
: Tab(_tabSupervisor), secondsElapsed(0), hostId(-1), localPlayerId(-1),
|
||||||
isLocalGame(_tabSupervisor->getIsLocalGame()), spectator(true), gameStateKnown(false), resuming(false),
|
isLocalGame(_tabSupervisor->getIsLocalGame()), spectator(true), gameStateKnown(false), resuming(false),
|
||||||
currentPhase(-1), activeCard(0), gameClosed(false), replay(_replay), currentReplayStep(0), sayLabel(0), sayEdit(0)
|
currentPhase(-1), activeCard(nullptr), gameClosed(false), replay(_replay), currentReplayStep(0),
|
||||||
|
sayLabel(nullptr), sayEdit(nullptr)
|
||||||
{
|
{
|
||||||
// THIS CTOR IS USED ON REPLAY
|
// THIS CTOR IS USED ON REPLAY
|
||||||
gameInfo.CopyFrom(replay->game_info());
|
gameInfo.CopyFrom(replay->game_info());
|
||||||
|
|
@ -375,7 +379,7 @@ TabGame::TabGame(TabSupervisor *_tabSupervisor, GameReplay *_replay)
|
||||||
createReplayMenuItems();
|
createReplayMenuItems();
|
||||||
createViewMenuItems();
|
createViewMenuItems();
|
||||||
retranslateUi();
|
retranslateUi();
|
||||||
connect(&settingsCache->shortcuts(), SIGNAL(shortCutchanged()), this, SLOT(refreshShortcuts()));
|
connect(&settingsCache->shortcuts(), SIGNAL(shortCutChanged()), this, SLOT(refreshShortcuts()));
|
||||||
refreshShortcuts();
|
refreshShortcuts();
|
||||||
messageLog->logReplayStarted(gameInfo.game_id());
|
messageLog->logReplayStarted(gameInfo.game_id());
|
||||||
|
|
||||||
|
|
@ -389,8 +393,8 @@ TabGame::TabGame(TabSupervisor *_tabSupervisor,
|
||||||
const QMap<int, QString> &_roomGameTypes)
|
const QMap<int, QString> &_roomGameTypes)
|
||||||
: Tab(_tabSupervisor), clients(_clients), gameInfo(event.game_info()), roomGameTypes(_roomGameTypes),
|
: Tab(_tabSupervisor), clients(_clients), gameInfo(event.game_info()), roomGameTypes(_roomGameTypes),
|
||||||
hostId(event.host_id()), localPlayerId(event.player_id()), isLocalGame(_tabSupervisor->getIsLocalGame()),
|
hostId(event.host_id()), localPlayerId(event.player_id()), isLocalGame(_tabSupervisor->getIsLocalGame()),
|
||||||
spectator(event.spectator()), gameStateKnown(false), resuming(event.resuming()), currentPhase(-1), activeCard(0),
|
spectator(event.spectator()), gameStateKnown(false), resuming(event.resuming()), currentPhase(-1),
|
||||||
gameClosed(false), replay(0), replayDock(0)
|
activeCard(nullptr), gameClosed(false), replay(nullptr), replayDock(nullptr)
|
||||||
{
|
{
|
||||||
// THIS CTOR IS USED ON GAMES
|
// THIS CTOR IS USED ON GAMES
|
||||||
gameInfo.set_started(false);
|
gameInfo.set_started(false);
|
||||||
|
|
@ -414,7 +418,7 @@ TabGame::TabGame(TabSupervisor *_tabSupervisor,
|
||||||
createMenuItems();
|
createMenuItems();
|
||||||
createViewMenuItems();
|
createViewMenuItems();
|
||||||
retranslateUi();
|
retranslateUi();
|
||||||
connect(&settingsCache->shortcuts(), SIGNAL(shortCutchanged()), this, SLOT(refreshShortcuts()));
|
connect(&settingsCache->shortcuts(), SIGNAL(shortCutChanged()), this, SLOT(refreshShortcuts()));
|
||||||
refreshShortcuts();
|
refreshShortcuts();
|
||||||
|
|
||||||
// append game to rooms game list for others to see
|
// append game to rooms game list for others to see
|
||||||
|
|
@ -486,6 +490,9 @@ void TabGame::retranslateUi()
|
||||||
if (aNextPhase) {
|
if (aNextPhase) {
|
||||||
aNextPhase->setText(tr("Next &phase"));
|
aNextPhase->setText(tr("Next &phase"));
|
||||||
}
|
}
|
||||||
|
if (aNextPhaseAction) {
|
||||||
|
aNextPhaseAction->setText(tr("Next phase with &action"));
|
||||||
|
}
|
||||||
if (aNextTurn) {
|
if (aNextTurn) {
|
||||||
aNextTurn->setText(tr("Next &turn"));
|
aNextTurn->setText(tr("Next &turn"));
|
||||||
}
|
}
|
||||||
|
|
@ -554,7 +561,7 @@ void TabGame::closeRequest()
|
||||||
|
|
||||||
void TabGame::replayNextEvent()
|
void TabGame::replayNextEvent()
|
||||||
{
|
{
|
||||||
processGameEventContainer(replay->event_list(timelineWidget->getCurrentEvent()), 0);
|
processGameEventContainer(replay->event_list(timelineWidget->getCurrentEvent()), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabGame::replayFinished()
|
void TabGame::replayFinished()
|
||||||
|
|
@ -620,11 +627,23 @@ void TabGame::actGameInfo()
|
||||||
|
|
||||||
void TabGame::actConcede()
|
void TabGame::actConcede()
|
||||||
{
|
{
|
||||||
if (QMessageBox::question(this, tr("Concede"), tr("Are you sure you want to concede this game?"),
|
Player *player = players.value(localPlayerId, nullptr);
|
||||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes)
|
if (player == nullptr)
|
||||||
return;
|
return;
|
||||||
|
if (!player->getConceded()) {
|
||||||
|
if (QMessageBox::question(this, tr("Concede"), tr("Are you sure you want to concede this game?"),
|
||||||
|
QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes)
|
||||||
|
return;
|
||||||
|
|
||||||
sendGameCommand(Command_Concede());
|
sendGameCommand(Command_Concede());
|
||||||
|
} else {
|
||||||
|
if (QMessageBox::question(this, tr("Unconcede"),
|
||||||
|
tr("You have already conceded. Do you want to return to this game?"),
|
||||||
|
QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sendGameCommand(Command_Unconcede());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabGame::actLeaveGame()
|
void TabGame::actLeaveGame()
|
||||||
|
|
@ -659,7 +678,7 @@ void TabGame::actPhaseAction()
|
||||||
{
|
{
|
||||||
int phase = phaseActions.indexOf(static_cast<QAction *>(sender()));
|
int phase = phaseActions.indexOf(static_cast<QAction *>(sender()));
|
||||||
Command_SetActivePhase cmd;
|
Command_SetActivePhase cmd;
|
||||||
cmd.set_phase(phase);
|
cmd.set_phase(static_cast<google::protobuf::uint32>(phase));
|
||||||
sendGameCommand(cmd);
|
sendGameCommand(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -669,10 +688,29 @@ void TabGame::actNextPhase()
|
||||||
if (++phase >= phasesToolbar->phaseCount())
|
if (++phase >= phasesToolbar->phaseCount())
|
||||||
phase = 0;
|
phase = 0;
|
||||||
Command_SetActivePhase cmd;
|
Command_SetActivePhase cmd;
|
||||||
cmd.set_phase(phase);
|
cmd.set_phase(static_cast<google::protobuf::uint32>(phase));
|
||||||
sendGameCommand(cmd);
|
sendGameCommand(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TabGame::actNextPhaseAction()
|
||||||
|
{
|
||||||
|
int phase = currentPhase + 1;
|
||||||
|
if (phase >= phasesToolbar->phaseCount()) {
|
||||||
|
phase = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (phase == 0) {
|
||||||
|
Command_NextTurn cmd;
|
||||||
|
sendGameCommand(cmd);
|
||||||
|
} else {
|
||||||
|
Command_SetActivePhase cmd;
|
||||||
|
cmd.set_phase(static_cast<google::protobuf::uint32>(phase));
|
||||||
|
sendGameCommand(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
phasesToolbar->triggerPhaseAction(phase);
|
||||||
|
}
|
||||||
|
|
||||||
void TabGame::actNextTurn()
|
void TabGame::actNextTurn()
|
||||||
{
|
{
|
||||||
sendGameCommand(Command_NextTurn());
|
sendGameCommand(Command_NextTurn());
|
||||||
|
|
@ -713,7 +751,7 @@ void TabGame::actCompleterChanged()
|
||||||
Player *TabGame::addPlayer(int playerId, const ServerInfo_User &info)
|
Player *TabGame::addPlayer(int playerId, const ServerInfo_User &info)
|
||||||
{
|
{
|
||||||
bool local = ((clients.size() > 1) || (playerId == localPlayerId));
|
bool local = ((clients.size() > 1) || (playerId == localPlayerId));
|
||||||
Player *newPlayer = new Player(info, playerId, local, this);
|
auto *newPlayer = new Player(info, playerId, local, this);
|
||||||
connect(newPlayer, SIGNAL(openDeckEditor(const DeckLoader *)), this, SIGNAL(openDeckEditor(const DeckLoader *)));
|
connect(newPlayer, SIGNAL(openDeckEditor(const DeckLoader *)), this, SIGNAL(openDeckEditor(const DeckLoader *)));
|
||||||
QString newPlayerName = "@" + newPlayer->getName();
|
QString newPlayerName = "@" + newPlayer->getName();
|
||||||
if (sayEdit && !autocompleteUserList.contains(newPlayerName)) {
|
if (sayEdit && !autocompleteUserList.contains(newPlayerName)) {
|
||||||
|
|
@ -729,7 +767,7 @@ Player *TabGame::addPlayer(int playerId, const ServerInfo_User &info)
|
||||||
if (clients.size() == 1)
|
if (clients.size() == 1)
|
||||||
newPlayer->setShortcutsActive();
|
newPlayer->setShortcutsActive();
|
||||||
|
|
||||||
DeckViewContainer *deckView = new DeckViewContainer(playerId, this);
|
auto *deckView = new DeckViewContainer(playerId, this);
|
||||||
connect(deckView, SIGNAL(newCardAdded(AbstractCardItem *)), this, SLOT(newCardAdded(AbstractCardItem *)));
|
connect(deckView, SIGNAL(newCardAdded(AbstractCardItem *)), this, SLOT(newCardAdded(AbstractCardItem *)));
|
||||||
deckViewContainers.insert(playerId, deckView);
|
deckViewContainers.insert(playerId, deckView);
|
||||||
deckViewContainerLayout->addWidget(deckView);
|
deckViewContainerLayout->addWidget(deckView);
|
||||||
|
|
@ -750,7 +788,7 @@ void TabGame::processGameEventContainer(const GameEventContainer &cont, Abstract
|
||||||
for (int i = 0; i < eventListSize; ++i) {
|
for (int i = 0; i < eventListSize; ++i) {
|
||||||
const GameEvent &event = cont.event_list(i);
|
const GameEvent &event = cont.event_list(i);
|
||||||
const int playerId = event.player_id();
|
const int playerId = event.player_id();
|
||||||
const GameEvent::GameEventType eventType = static_cast<GameEvent::GameEventType>(getPbExtension(event));
|
const auto eventType = static_cast<GameEvent::GameEventType>(getPbExtension(event));
|
||||||
if (spectators.contains(playerId)) {
|
if (spectators.contains(playerId)) {
|
||||||
switch (eventType) {
|
switch (eventType) {
|
||||||
case GameEvent::GAME_SAY:
|
case GameEvent::GAME_SAY:
|
||||||
|
|
@ -822,7 +860,7 @@ AbstractClient *TabGame::getClientForPlayer(int playerId) const
|
||||||
|
|
||||||
return clients.at(playerId);
|
return clients.at(playerId);
|
||||||
} else if (clients.isEmpty())
|
} else if (clients.isEmpty())
|
||||||
return 0;
|
return nullptr;
|
||||||
else
|
else
|
||||||
return clients.first();
|
return clients.first();
|
||||||
}
|
}
|
||||||
|
|
@ -859,7 +897,7 @@ void TabGame::commandFinished(const Response &response)
|
||||||
PendingCommand *TabGame::prepareGameCommand(const ::google::protobuf::Message &cmd)
|
PendingCommand *TabGame::prepareGameCommand(const ::google::protobuf::Message &cmd)
|
||||||
{
|
{
|
||||||
CommandContainer cont;
|
CommandContainer cont;
|
||||||
cont.set_game_id(gameInfo.game_id());
|
cont.set_game_id(static_cast<google::protobuf::uint32>(gameInfo.game_id()));
|
||||||
GameCommand *c = cont.add_game_command();
|
GameCommand *c = cont.add_game_command();
|
||||||
c->GetReflection()->MutableMessage(c, cmd.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(cmd);
|
c->GetReflection()->MutableMessage(c, cmd.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(cmd);
|
||||||
return new PendingCommand(cont);
|
return new PendingCommand(cont);
|
||||||
|
|
@ -868,13 +906,11 @@ PendingCommand *TabGame::prepareGameCommand(const ::google::protobuf::Message &c
|
||||||
PendingCommand *TabGame::prepareGameCommand(const QList<const ::google::protobuf::Message *> &cmdList)
|
PendingCommand *TabGame::prepareGameCommand(const QList<const ::google::protobuf::Message *> &cmdList)
|
||||||
{
|
{
|
||||||
CommandContainer cont;
|
CommandContainer cont;
|
||||||
cont.set_game_id(gameInfo.game_id());
|
cont.set_game_id(static_cast<google::protobuf::uint32>(gameInfo.game_id()));
|
||||||
for (int i = 0; i < cmdList.size(); ++i) {
|
for (auto i : cmdList) {
|
||||||
GameCommand *c = cont.add_game_command();
|
GameCommand *c = cont.add_game_command();
|
||||||
c->GetReflection()
|
c->GetReflection()->MutableMessage(c, i->GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(*i);
|
||||||
->MutableMessage(c, cmdList[i]->GetDescriptor()->FindExtensionByName("ext"))
|
delete i;
|
||||||
->CopyFrom(*cmdList[i]);
|
|
||||||
delete cmdList[i];
|
|
||||||
}
|
}
|
||||||
return new PendingCommand(cont);
|
return new PendingCommand(cont);
|
||||||
}
|
}
|
||||||
|
|
@ -1028,8 +1064,7 @@ void TabGame::eventPlayerPropertiesChanged(const Event_PlayerPropertiesChanged &
|
||||||
const ServerInfo_PlayerProperties &prop = event.player_properties();
|
const ServerInfo_PlayerProperties &prop = event.player_properties();
|
||||||
playerListWidget->updatePlayerProperties(prop, eventPlayerId);
|
playerListWidget->updatePlayerProperties(prop, eventPlayerId);
|
||||||
|
|
||||||
const GameEventContext::ContextType contextType =
|
const auto contextType = static_cast<GameEventContext::ContextType>(getPbExtension(context));
|
||||||
static_cast<GameEventContext::ContextType>(getPbExtension(context));
|
|
||||||
switch (contextType) {
|
switch (contextType) {
|
||||||
case GameEventContext::READY_START: {
|
case GameEventContext::READY_START: {
|
||||||
bool ready = prop.ready_start();
|
bool ready = prop.ready_start();
|
||||||
|
|
@ -1051,6 +1086,16 @@ void TabGame::eventPlayerPropertiesChanged(const Event_PlayerPropertiesChanged &
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case GameEventContext::UNCONCEDE: {
|
||||||
|
messageLog->logUnconcede(player);
|
||||||
|
player->setConceded(false);
|
||||||
|
|
||||||
|
QMapIterator<int, Player *> playerIterator(players);
|
||||||
|
while (playerIterator.hasNext())
|
||||||
|
playerIterator.next().value()->updateZones();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
case GameEventContext::DECK_SELECT: {
|
case GameEventContext::DECK_SELECT: {
|
||||||
Context_DeckSelect deckSelect = context.GetExtension(Context_DeckSelect::ext);
|
Context_DeckSelect deckSelect = context.GetExtension(Context_DeckSelect::ext);
|
||||||
messageLog->logDeckSelect(player, QString::fromStdString(deckSelect.deck_hash()),
|
messageLog->logDeckSelect(player, QString::fromStdString(deckSelect.deck_hash()),
|
||||||
|
|
@ -1173,7 +1218,7 @@ Player *TabGame::setActivePlayer(int id)
|
||||||
{
|
{
|
||||||
Player *player = players.value(id, 0);
|
Player *player = players.value(id, 0);
|
||||||
if (!player)
|
if (!player)
|
||||||
return 0;
|
return nullptr;
|
||||||
activePlayer = id;
|
activePlayer = id;
|
||||||
playerListWidget->setActivePlayer(id);
|
playerListWidget->setActivePlayer(id);
|
||||||
QMapIterator<int, Player *> i(players);
|
QMapIterator<int, Player *> i(players);
|
||||||
|
|
@ -1237,11 +1282,11 @@ CardItem *TabGame::getCard(int playerId, const QString &zoneName, int cardId) co
|
||||||
{
|
{
|
||||||
Player *player = players.value(playerId, 0);
|
Player *player = players.value(playerId, 0);
|
||||||
if (!player)
|
if (!player)
|
||||||
return 0;
|
return nullptr;
|
||||||
|
|
||||||
CardZone *zone = player->getZones().value(zoneName, 0);
|
CardZone *zone = player->getZones().value(zoneName, 0);
|
||||||
if (!zone)
|
if (!zone)
|
||||||
return 0;
|
return nullptr;
|
||||||
|
|
||||||
return zone->getCard(cardId, QString());
|
return zone->getCard(cardId, QString());
|
||||||
}
|
}
|
||||||
|
|
@ -1249,7 +1294,7 @@ CardItem *TabGame::getCard(int playerId, const QString &zoneName, int cardId) co
|
||||||
QString TabGame::getTabText() const
|
QString TabGame::getTabText() const
|
||||||
{
|
{
|
||||||
QString gameTypeInfo;
|
QString gameTypeInfo;
|
||||||
if (gameTypes.size() != 0) {
|
if (!gameTypes.empty()) {
|
||||||
gameTypeInfo = gameTypes.at(0);
|
gameTypeInfo = gameTypes.at(0);
|
||||||
if (gameTypes.size() > 1)
|
if (gameTypes.size() > 1)
|
||||||
gameTypeInfo.append("...");
|
gameTypeInfo.append("...");
|
||||||
|
|
@ -1290,7 +1335,7 @@ Player *TabGame::getActiveLocalPlayer() const
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabGame::updateCardMenu(AbstractCardItem *card)
|
void TabGame::updateCardMenu(AbstractCardItem *card)
|
||||||
|
|
@ -1307,6 +1352,8 @@ void TabGame::createMenuItems()
|
||||||
{
|
{
|
||||||
aNextPhase = new QAction(this);
|
aNextPhase = new QAction(this);
|
||||||
connect(aNextPhase, SIGNAL(triggered()), this, SLOT(actNextPhase()));
|
connect(aNextPhase, SIGNAL(triggered()), this, SLOT(actNextPhase()));
|
||||||
|
aNextPhaseAction = new QAction(this);
|
||||||
|
connect(aNextPhaseAction, SIGNAL(triggered()), this, SLOT(actNextPhaseAction()));
|
||||||
aNextTurn = new QAction(this);
|
aNextTurn = new QAction(this);
|
||||||
connect(aNextTurn, SIGNAL(triggered()), this, SLOT(actNextTurn()));
|
connect(aNextTurn, SIGNAL(triggered()), this, SLOT(actNextTurn()));
|
||||||
aRemoveLocalArrows = new QAction(this);
|
aRemoveLocalArrows = new QAction(this);
|
||||||
|
|
@ -1321,7 +1368,7 @@ void TabGame::createMenuItems()
|
||||||
connect(aConcede, SIGNAL(triggered()), this, SLOT(actConcede()));
|
connect(aConcede, SIGNAL(triggered()), this, SLOT(actConcede()));
|
||||||
aLeaveGame = new QAction(this);
|
aLeaveGame = new QAction(this);
|
||||||
connect(aLeaveGame, SIGNAL(triggered()), this, SLOT(actLeaveGame()));
|
connect(aLeaveGame, SIGNAL(triggered()), this, SLOT(actLeaveGame()));
|
||||||
aCloseReplay = 0;
|
aCloseReplay = nullptr;
|
||||||
|
|
||||||
phasesMenu = new QMenu(this);
|
phasesMenu = new QMenu(this);
|
||||||
for (int i = 0; i < phasesToolbar->phaseCount(); ++i) {
|
for (int i = 0; i < phasesToolbar->phaseCount(); ++i) {
|
||||||
|
|
@ -1333,6 +1380,7 @@ void TabGame::createMenuItems()
|
||||||
|
|
||||||
phasesMenu->addSeparator();
|
phasesMenu->addSeparator();
|
||||||
phasesMenu->addAction(aNextPhase);
|
phasesMenu->addAction(aNextPhase);
|
||||||
|
phasesMenu->addAction(aNextPhaseAction);
|
||||||
|
|
||||||
gameMenu = new QMenu(this);
|
gameMenu = new QMenu(this);
|
||||||
playersSeparator = gameMenu->addSeparator();
|
playersSeparator = gameMenu->addSeparator();
|
||||||
|
|
@ -1351,19 +1399,20 @@ void TabGame::createMenuItems()
|
||||||
|
|
||||||
void TabGame::createReplayMenuItems()
|
void TabGame::createReplayMenuItems()
|
||||||
{
|
{
|
||||||
aNextPhase = 0;
|
aNextPhase = nullptr;
|
||||||
aNextTurn = 0;
|
aNextPhaseAction = nullptr;
|
||||||
aRemoveLocalArrows = 0;
|
aNextTurn = nullptr;
|
||||||
aRotateViewCW = 0;
|
aRemoveLocalArrows = nullptr;
|
||||||
aRotateViewCCW = 0;
|
aRotateViewCW = nullptr;
|
||||||
aResetLayout = 0;
|
aRotateViewCCW = nullptr;
|
||||||
aGameInfo = 0;
|
aResetLayout = nullptr;
|
||||||
aConcede = 0;
|
aGameInfo = nullptr;
|
||||||
aLeaveGame = 0;
|
aConcede = nullptr;
|
||||||
|
aLeaveGame = nullptr;
|
||||||
aCloseReplay = new QAction(this);
|
aCloseReplay = new QAction(this);
|
||||||
connect(aCloseReplay, SIGNAL(triggered()), this, SLOT(actLeaveGame()));
|
connect(aCloseReplay, SIGNAL(triggered()), this, SLOT(actLeaveGame()));
|
||||||
|
|
||||||
phasesMenu = 0;
|
phasesMenu = nullptr;
|
||||||
gameMenu = new QMenu(this);
|
gameMenu = new QMenu(this);
|
||||||
gameMenu->addAction(aCloseReplay);
|
gameMenu->addAction(aCloseReplay);
|
||||||
addTabMenu(gameMenu);
|
addTabMenu(gameMenu);
|
||||||
|
|
@ -1637,7 +1686,7 @@ void TabGame::createCardInfoDock(bool bReplay)
|
||||||
void TabGame::createPlayerListDock(bool bReplay)
|
void TabGame::createPlayerListDock(bool bReplay)
|
||||||
{
|
{
|
||||||
if (bReplay) {
|
if (bReplay) {
|
||||||
playerListWidget = new PlayerListWidget(0, 0, this);
|
playerListWidget = new PlayerListWidget(nullptr, nullptr, this);
|
||||||
} else {
|
} else {
|
||||||
playerListWidget = new PlayerListWidget(tabSupervisor, clients.first(), this);
|
playerListWidget = new PlayerListWidget(tabSupervisor, clients.first(), this);
|
||||||
connect(playerListWidget, SIGNAL(openMessageDialog(QString, bool)), this,
|
connect(playerListWidget, SIGNAL(openMessageDialog(QString, bool)), this,
|
||||||
|
|
|
||||||
|
|
@ -163,8 +163,8 @@ private:
|
||||||
QAction *playersSeparator;
|
QAction *playersSeparator;
|
||||||
QMenu *gameMenu, *phasesMenu, *viewMenu, *cardInfoDockMenu, *messageLayoutDockMenu, *playerListDockMenu,
|
QMenu *gameMenu, *phasesMenu, *viewMenu, *cardInfoDockMenu, *messageLayoutDockMenu, *playerListDockMenu,
|
||||||
*replayDockMenu;
|
*replayDockMenu;
|
||||||
QAction *aGameInfo, *aConcede, *aLeaveGame, *aCloseReplay, *aNextPhase, *aNextTurn, *aRemoveLocalArrows,
|
QAction *aGameInfo, *aConcede, *aLeaveGame, *aCloseReplay, *aNextPhase, *aNextPhaseAction, *aNextTurn,
|
||||||
*aRotateViewCW, *aRotateViewCCW, *aResetLayout, *aResetReplayLayout;
|
*aRemoveLocalArrows, *aRotateViewCW, *aRotateViewCCW, *aResetLayout, *aResetReplayLayout;
|
||||||
QAction *aCardInfoDockVisible, *aCardInfoDockFloating, *aMessageLayoutDockVisible, *aMessageLayoutDockFloating,
|
QAction *aCardInfoDockVisible, *aCardInfoDockFloating, *aMessageLayoutDockVisible, *aMessageLayoutDockFloating,
|
||||||
*aPlayerListDockVisible, *aPlayerListDockFloating, *aReplayDockVisible, *aReplayDockFloating;
|
*aPlayerListDockVisible, *aPlayerListDockFloating, *aReplayDockVisible, *aReplayDockFloating;
|
||||||
QList<QAction *> phaseActions;
|
QList<QAction *> phaseActions;
|
||||||
|
|
@ -233,6 +233,7 @@ private slots:
|
||||||
void actSay();
|
void actSay();
|
||||||
void actPhaseAction();
|
void actPhaseAction();
|
||||||
void actNextPhase();
|
void actNextPhase();
|
||||||
|
void actNextPhaseAction();
|
||||||
void actNextTurn();
|
void actNextTurn();
|
||||||
|
|
||||||
void addMentionTag(QString value);
|
void addMentionTag(QString value);
|
||||||
|
|
@ -246,7 +247,7 @@ private slots:
|
||||||
void actResetLayout();
|
void actResetLayout();
|
||||||
void freeDocksSize();
|
void freeDocksSize();
|
||||||
|
|
||||||
bool eventFilter(QObject *o, QEvent *e);
|
bool eventFilter(QObject *o, QEvent *e) override;
|
||||||
void dockVisibleTriggered();
|
void dockVisibleTriggered();
|
||||||
void dockFloatingTriggered();
|
void dockFloatingTriggered();
|
||||||
void dockTopLevelChanged(bool topLevel);
|
void dockTopLevelChanged(bool topLevel);
|
||||||
|
|
@ -257,10 +258,10 @@ public:
|
||||||
const Event_GameJoined &event,
|
const Event_GameJoined &event,
|
||||||
const QMap<int, QString> &_roomGameTypes);
|
const QMap<int, QString> &_roomGameTypes);
|
||||||
TabGame(TabSupervisor *_tabSupervisor, GameReplay *replay);
|
TabGame(TabSupervisor *_tabSupervisor, GameReplay *replay);
|
||||||
~TabGame();
|
~TabGame() override;
|
||||||
void retranslateUi();
|
void retranslateUi() override;
|
||||||
void updatePlayerListDockTitle();
|
void updatePlayerListDockTitle();
|
||||||
void closeRequest();
|
void closeRequest() override;
|
||||||
const QMap<int, Player *> &getPlayers() const
|
const QMap<int, Player *> &getPlayers() const
|
||||||
{
|
{
|
||||||
return players;
|
return players;
|
||||||
|
|
@ -278,7 +279,7 @@ public:
|
||||||
{
|
{
|
||||||
return gameInfo.game_id();
|
return gameInfo.game_id();
|
||||||
}
|
}
|
||||||
QString getTabText() const;
|
QString getTabText() const override;
|
||||||
bool getSpectator() const
|
bool getSpectator() const
|
||||||
{
|
{
|
||||||
return spectator;
|
return spectator;
|
||||||
|
|
|
||||||
|
|
@ -299,16 +299,17 @@ void MainWindow::actAbout()
|
||||||
QMessageBox::NoIcon, tr("About Cockatrice"),
|
QMessageBox::NoIcon, tr("About Cockatrice"),
|
||||||
QString("<font size=\"8\"><b>Cockatrice</b></font> (" + QString::fromStdString(BUILD_ARCHITECTURE) + ")<br>" +
|
QString("<font size=\"8\"><b>Cockatrice</b></font> (" + QString::fromStdString(BUILD_ARCHITECTURE) + ")<br>" +
|
||||||
tr("Version") + QString(" %1").arg(VERSION_STRING) + "<br><br><b><a href='" + GITHUB_PAGES_URL + "'>" +
|
tr("Version") + QString(" %1").arg(VERSION_STRING) + "<br><br><b><a href='" + GITHUB_PAGES_URL + "'>" +
|
||||||
tr("Cockatrice Webpage") + "</a></b><br>" + "<br><br><b>" + tr("Project Manager:") +
|
tr("Cockatrice Webpage") + "</a></b><br>" + "<br><b>" + tr("Project Manager:") +
|
||||||
"</b><br>Gavin Bisesi<br><br>" + "<b>" + tr("Past Project Managers:") +
|
"</b><br>Zach Halpern<br><br>" + "<b>" + tr("Past Project Managers:") +
|
||||||
"</b><br>Max-Wilhelm Bruker<br>Marcus Schütz<br><br>" + "<b>" + tr("Developers:") + "</b><br>" +
|
"</b><br>Gavin Bisesi<br>Max-Wilhelm Bruker<br>Marcus Schütz<br><br>" + "<b>" + tr("Developers:") +
|
||||||
"<a href='" + GITHUB_CONTRIBUTORS_URL + "'>" + tr("Our Developers") + "</a><br>" + "<a href='" +
|
"</b><br>" + "<a href='" + GITHUB_CONTRIBUTORS_URL + "'>" + tr("Our Developers") + "</a><br>" +
|
||||||
GITHUB_CONTRIBUTE_URL + "'>" + tr("Help Develop!") + "</a><br><br>" + "<b>" + tr("Translators:") +
|
"<a href='" + GITHUB_CONTRIBUTE_URL + "'>" + tr("Help Develop!") + "</a><br><br>" + "<b>" +
|
||||||
"</b><br>" + "<a href='" + GITHUB_TRANSIFEX_TRANSLATORS_URL + "'>" + tr("Our Translators") +
|
tr("Translators:") + "</b><br>" + "<a href='" + GITHUB_TRANSIFEX_TRANSLATORS_URL + "'>" +
|
||||||
"</a><br>" + "<a href='" + GITHUB_TRANSLATOR_FAQ_URL + "'>" + tr("Help Translate!") + "</a><br><br>" +
|
tr("Our Translators") + "</a><br>" + "<a href='" + GITHUB_TRANSLATOR_FAQ_URL + "'>" +
|
||||||
"<b>" + tr("Support:") + "</b><br>" + "<a href='" + GITHUB_ISSUES_URL + "'>" + tr("Report an Issue") +
|
tr("Help Translate!") + "</a><br><br>" + "<b>" + tr("Support:") + "</b><br>" + "<a href='" +
|
||||||
"</a><br>" + "<a href='" + GITHUB_TROUBLESHOOTING_URL + "'>" + tr("Troubleshooting") + "</a><br>" +
|
GITHUB_ISSUES_URL + "'>" + tr("Report an Issue") + "</a><br>" + "<a href='" +
|
||||||
"<a href='" + GITHUB_FAQ_URL + "'>" + tr("F.A.Q.") + "</a><br>"),
|
GITHUB_TROUBLESHOOTING_URL + "'>" + tr("Troubleshooting") + "</a><br>" + "<a href='" + GITHUB_FAQ_URL +
|
||||||
|
"'>" + tr("F.A.Q.") + "</a><br>"),
|
||||||
QMessageBox::Ok, this);
|
QMessageBox::Ok, this);
|
||||||
mb.setIconPixmap(QPixmap("theme:cockatrice").scaled(64, 64));
|
mb.setIconPixmap(QPixmap("theme:cockatrice").scaled(64, 64));
|
||||||
mb.setTextInteractionFlags(Qt::TextBrowserInteraction);
|
mb.setTextInteractionFlags(Qt::TextBrowserInteraction);
|
||||||
|
|
@ -317,9 +318,9 @@ void MainWindow::actAbout()
|
||||||
|
|
||||||
void MainWindow::actTips()
|
void MainWindow::actTips()
|
||||||
{
|
{
|
||||||
if (tip != NULL) {
|
if (tip != nullptr) {
|
||||||
delete tip;
|
delete tip;
|
||||||
tip = NULL;
|
tip = nullptr;
|
||||||
}
|
}
|
||||||
tip = new DlgTipOfTheDay();
|
tip = new DlgTipOfTheDay();
|
||||||
if (tip->successfulInit) {
|
if (tip->successfulInit) {
|
||||||
|
|
@ -705,15 +706,33 @@ void MainWindow::createActions()
|
||||||
aExit->setMenuRole(QAction::QuitRole);
|
aExit->setMenuRole(QAction::QuitRole);
|
||||||
aAbout->setMenuRole(QAction::AboutRole);
|
aAbout->setMenuRole(QAction::AboutRole);
|
||||||
|
|
||||||
char const *foo; // avoid "warning: expression result unused" under clang
|
Q_UNUSED(QT_TRANSLATE_NOOP("QMenuBar", "Services"));
|
||||||
foo = QT_TRANSLATE_NOOP("QMenuBar", "Services");
|
Q_UNUSED(QT_TRANSLATE_NOOP("QMenuBar", "Hide %1"));
|
||||||
foo = QT_TRANSLATE_NOOP("QMenuBar", "Hide %1");
|
Q_UNUSED(QT_TRANSLATE_NOOP("QMenuBar", "Hide Others"));
|
||||||
foo = QT_TRANSLATE_NOOP("QMenuBar", "Hide Others");
|
Q_UNUSED(QT_TRANSLATE_NOOP("QMenuBar", "Show All"));
|
||||||
foo = QT_TRANSLATE_NOOP("QMenuBar", "Show All");
|
Q_UNUSED(QT_TRANSLATE_NOOP("QMenuBar", "Preferences..."));
|
||||||
foo = QT_TRANSLATE_NOOP("QMenuBar", "Preferences...");
|
Q_UNUSED(QT_TRANSLATE_NOOP("QMenuBar", "Quit %1"));
|
||||||
foo = QT_TRANSLATE_NOOP("QMenuBar", "Quit %1");
|
Q_UNUSED(QT_TRANSLATE_NOOP("QMenuBar", "About %1"));
|
||||||
foo = QT_TRANSLATE_NOOP("QMenuBar", "About %1");
|
|
||||||
#endif
|
#endif
|
||||||
|
// translate Qt's dialogs "default button text"; list taken from QPlatformTheme::defaultStandardButtonText()
|
||||||
|
Q_UNUSED(QT_TRANSLATE_NOOP("QPlatformTheme", "OK"));
|
||||||
|
Q_UNUSED(QT_TRANSLATE_NOOP("QPlatformTheme", "Save"));
|
||||||
|
Q_UNUSED(QT_TRANSLATE_NOOP("QPlatformTheme", "Save All"));
|
||||||
|
Q_UNUSED(QT_TRANSLATE_NOOP("QPlatformTheme", "Open"));
|
||||||
|
Q_UNUSED(QT_TRANSLATE_NOOP("QPlatformTheme", "&Yes"));
|
||||||
|
Q_UNUSED(QT_TRANSLATE_NOOP("QPlatformTheme", "Yes to &All"));
|
||||||
|
Q_UNUSED(QT_TRANSLATE_NOOP("QPlatformTheme", "&No"));
|
||||||
|
Q_UNUSED(QT_TRANSLATE_NOOP("QPlatformTheme", "N&o to All"));
|
||||||
|
Q_UNUSED(QT_TRANSLATE_NOOP("QPlatformTheme", "Abort"));
|
||||||
|
Q_UNUSED(QT_TRANSLATE_NOOP("QPlatformTheme", "Retry"));
|
||||||
|
Q_UNUSED(QT_TRANSLATE_NOOP("QPlatformTheme", "Ignore"));
|
||||||
|
Q_UNUSED(QT_TRANSLATE_NOOP("QPlatformTheme", "Close"));
|
||||||
|
Q_UNUSED(QT_TRANSLATE_NOOP("QPlatformTheme", "Cancel"));
|
||||||
|
Q_UNUSED(QT_TRANSLATE_NOOP("QPlatformTheme", "Discard"));
|
||||||
|
Q_UNUSED(QT_TRANSLATE_NOOP("QPlatformTheme", "Help"));
|
||||||
|
Q_UNUSED(QT_TRANSLATE_NOOP("QPlatformTheme", "Apply"));
|
||||||
|
Q_UNUSED(QT_TRANSLATE_NOOP("QPlatformTheme", "Reset"));
|
||||||
|
Q_UNUSED(QT_TRANSLATE_NOOP("QPlatformTheme", "Restore Defaults"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::createMenus()
|
void MainWindow::createMenus()
|
||||||
|
|
@ -811,7 +830,7 @@ MainWindow::MainWindow(QWidget *parent)
|
||||||
createTrayIcon();
|
createTrayIcon();
|
||||||
}
|
}
|
||||||
|
|
||||||
connect(&settingsCache->shortcuts(), SIGNAL(shortCutchanged()), this, SLOT(refreshShortcuts()));
|
connect(&settingsCache->shortcuts(), SIGNAL(shortCutChanged()), this, SLOT(refreshShortcuts()));
|
||||||
refreshShortcuts();
|
refreshShortcuts();
|
||||||
|
|
||||||
connect(db, SIGNAL(cardDatabaseLoadingFailed()), this, SLOT(cardDatabaseLoadingFailed()));
|
connect(db, SIGNAL(cardDatabaseLoadingFailed()), this, SLOT(cardDatabaseLoadingFailed()));
|
||||||
|
|
@ -828,13 +847,30 @@ MainWindow::MainWindow(QWidget *parent)
|
||||||
if (tip->successfulInit && settingsCache->getShowTipsOnStartup() && tip->newTipsAvailable) {
|
if (tip->successfulInit && settingsCache->getShowTipsOnStartup() && tip->newTipsAvailable) {
|
||||||
tip->show();
|
tip->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only run the check updater if the user wants it (defaults to on)
|
||||||
|
if (settingsCache->getNotifyAboutNewVersion()) {
|
||||||
|
auto versionUpdater = new MainUpdateHelper();
|
||||||
|
connect(versionUpdater, SIGNAL(newVersionDetected(QString)), this, SLOT(alertForcedOracleRun(QString)));
|
||||||
|
QtConcurrent::run(versionUpdater, &MainUpdateHelper::testForNewVersion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::alertForcedOracleRun(const QString &newVersion)
|
||||||
|
{
|
||||||
|
settingsCache->setClientVersion(newVersion);
|
||||||
|
QMessageBox::information(this, tr("New Version"),
|
||||||
|
tr("Congratulations on updating to Cockatrice %1!\n"
|
||||||
|
"Oracle will now launch to update your card database.")
|
||||||
|
.arg(newVersion));
|
||||||
|
actCheckCardUpdates();
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWindow::~MainWindow()
|
MainWindow::~MainWindow()
|
||||||
{
|
{
|
||||||
if (tip != NULL) {
|
if (tip != nullptr) {
|
||||||
delete tip;
|
delete tip;
|
||||||
tip = NULL;
|
tip = nullptr;
|
||||||
}
|
}
|
||||||
if (trayIcon) {
|
if (trayIcon) {
|
||||||
trayIcon->hide();
|
trayIcon->hide();
|
||||||
|
|
@ -1271,3 +1307,10 @@ void MainWindow::promptForgotPasswordReset()
|
||||||
dlg.getPlayerName(), dlg.getToken(), dlg.getPassword());
|
dlg.getPlayerName(), dlg.getToken(), dlg.getPassword());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainUpdateHelper::testForNewVersion()
|
||||||
|
{
|
||||||
|
if (settingsCache->getClientVersion() != VERSION_STRING) {
|
||||||
|
emit newVersionDetected(VERSION_STRING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,8 @@ private slots:
|
||||||
void actManageSets();
|
void actManageSets();
|
||||||
void actEditTokens();
|
void actEditTokens();
|
||||||
|
|
||||||
|
void alertForcedOracleRun(const QString &);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const QString appName;
|
static const QString appName;
|
||||||
static const QStringList fileNameFilters;
|
static const QStringList fileNameFilters;
|
||||||
|
|
@ -146,4 +148,17 @@ protected:
|
||||||
QString extractInvalidUsernameMessage(QString &in);
|
QString extractInvalidUsernameMessage(QString &in);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MainUpdateHelper : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void newVersionDetected(QString);
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit MainUpdateHelper() = default;
|
||||||
|
~MainUpdateHelper() override = default;
|
||||||
|
void testForNewVersion();
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -127,21 +127,32 @@ WndSets::WndSets(QWidget *parent) : QMainWindow(parent)
|
||||||
labNotes->setOpenExternalLinks(true);
|
labNotes->setOpenExternalLinks(true);
|
||||||
labNotes->setText(
|
labNotes->setText(
|
||||||
"<b>" + tr("Deck Editor") + ":</b> " +
|
"<b>" + tr("Deck Editor") + ":</b> " +
|
||||||
tr("Only cards in enabled sets will appear in the deck editor card list") + "<br><b>" + tr("Card Art") +
|
tr("Only cards in enabled sets will appear in the deck editor card list") + "<br><br>" + "<b>" +
|
||||||
":</b> " + tr("Image priority is decided in the following order") + "<ol><li>" + tr("The") +
|
tr("Card Art") + ":</b> " + tr("Image priority is decided in the following order") + "<ol><li>" + tr("The") +
|
||||||
"<a "
|
"<a href='https://github.com/Cockatrice/Cockatrice/wiki/"
|
||||||
"href='https://github.com/Cockatrice/Cockatrice/wiki/"
|
|
||||||
"Custom-Cards-%26-Sets#to-add-custom-art-for-cards-the-easiest-way-is-to-use-the-custom-folder'> " +
|
"Custom-Cards-%26-Sets#to-add-custom-art-for-cards-the-easiest-way-is-to-use-the-custom-folder'> " +
|
||||||
tr("CUSTOM Folder") + "</a></li><li>" + tr("Enabled Sets (Top to Bottom)") + "</li><li>" +
|
tr("CUSTOM Folder") + "</a></li><li>" + tr("Enabled Sets (Top to Bottom)") + "</li><li>" +
|
||||||
tr("Disabled Sets (Top to Bottom)") + "</li></ol>");
|
tr("Disabled Sets (Top to Bottom)") + "</li></ol>");
|
||||||
|
|
||||||
sortWarning = new QLabel;
|
QGridLayout *hintsGrid = new QGridLayout;
|
||||||
sortWarning->setWordWrap(true);
|
hintsGrid->addWidget(labNotes, 0, 0);
|
||||||
sortWarning->setText(
|
hintsGroupBox = new QGroupBox(tr("Hints"));
|
||||||
"<b>" + tr("Warning: ") + "</b><br>" +
|
hintsGroupBox->setLayout(hintsGrid);
|
||||||
tr("While the set list is sorted by any of the columns, custom art priority setting is disabled.") + "<br>" +
|
|
||||||
tr("To disable sorting click on the same column header again until this message disappears."));
|
sortWarning = new QGroupBox(tr("Note"));
|
||||||
sortWarning->setStyleSheet("QLabel { background-color:red;}");
|
QGridLayout *sortWarningLayout = new QGridLayout;
|
||||||
|
sortWarningText = new QLabel;
|
||||||
|
sortWarningText->setWordWrap(true);
|
||||||
|
sortWarningText->setText(tr("Sorting by column allows you to find a set while not changing set priority.") + " " +
|
||||||
|
tr("To enable ordering again, click the column header until this message disappears."));
|
||||||
|
sortWarningLayout->addWidget(sortWarningText, 0, 0, 1, 2);
|
||||||
|
sortWarningButton = new QPushButton;
|
||||||
|
sortWarningButton->setText(tr("Use the current sorting as the set priority instead"));
|
||||||
|
sortWarningButton->setToolTip(tr("Sorts the set priority using the same column"));
|
||||||
|
sortWarningButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||||
|
connect(sortWarningButton, SIGNAL(released()), this, SLOT(actIgnoreWarning()));
|
||||||
|
sortWarningLayout->addWidget(sortWarningButton, 1, 0);
|
||||||
|
sortWarning->setLayout(sortWarningLayout);
|
||||||
sortWarning->setVisible(false);
|
sortWarning->setVisible(false);
|
||||||
|
|
||||||
buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||||
|
|
@ -157,7 +168,7 @@ WndSets::WndSets(QWidget *parent) : QMainWindow(parent)
|
||||||
mainLayout->addWidget(enableSomeButton, 2, 1);
|
mainLayout->addWidget(enableSomeButton, 2, 1);
|
||||||
mainLayout->addWidget(disableSomeButton, 2, 2);
|
mainLayout->addWidget(disableSomeButton, 2, 2);
|
||||||
mainLayout->addWidget(sortWarning, 3, 1, 1, 2);
|
mainLayout->addWidget(sortWarning, 3, 1, 1, 2);
|
||||||
mainLayout->addWidget(labNotes, 4, 1, 1, 2);
|
mainLayout->addWidget(hintsGroupBox, 4, 1, 1, 2);
|
||||||
mainLayout->addWidget(buttonBox, 5, 1, 1, 2);
|
mainLayout->addWidget(buttonBox, 5, 1, 1, 2);
|
||||||
mainLayout->setColumnStretch(1, 1);
|
mainLayout->setColumnStretch(1, 1);
|
||||||
mainLayout->setColumnStretch(2, 1);
|
mainLayout->setColumnStretch(2, 1);
|
||||||
|
|
@ -250,6 +261,17 @@ void WndSets::actSort(int index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WndSets::actIgnoreWarning()
|
||||||
|
{
|
||||||
|
if (sortIndex < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
model->sort(sortIndex, sortOrder);
|
||||||
|
view->header()->setSortIndicator(SORT_RESET, Qt::DescendingOrder);
|
||||||
|
sortIndex = -1;
|
||||||
|
sortWarning->setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
void WndSets::actDisableSortButtons(int index)
|
void WndSets::actDisableSortButtons(int index)
|
||||||
{
|
{
|
||||||
if (index != SORT_RESET) {
|
if (index != SORT_RESET) {
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,14 @@
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
|
|
||||||
|
class CardDatabase;
|
||||||
|
class QGroupBox;
|
||||||
|
class QItemSelection;
|
||||||
|
class QPushButton;
|
||||||
|
class QTreeView;
|
||||||
|
class SetsDisplayModel;
|
||||||
class SetsModel;
|
class SetsModel;
|
||||||
class SetsProxyModel;
|
class SetsProxyModel;
|
||||||
class SetsDisplayModel;
|
|
||||||
class QPushButton;
|
|
||||||
class CardDatabase;
|
|
||||||
class QItemSelection;
|
|
||||||
class QTreeView;
|
|
||||||
|
|
||||||
class WndSets : public QMainWindow
|
class WndSets : public QMainWindow
|
||||||
{
|
{
|
||||||
|
|
@ -22,6 +23,7 @@ class WndSets : public QMainWindow
|
||||||
private:
|
private:
|
||||||
SetsModel *model;
|
SetsModel *model;
|
||||||
SetsDisplayModel *displayModel;
|
SetsDisplayModel *displayModel;
|
||||||
|
QGroupBox *hintsGroupBox;
|
||||||
QTreeView *view;
|
QTreeView *view;
|
||||||
QPushButton *toggleAllButton, *toggleSelectedButton;
|
QPushButton *toggleAllButton, *toggleSelectedButton;
|
||||||
QPushButton *enableAllButton, *disableAllButton, *enableSomeButton, *disableSomeButton;
|
QPushButton *enableAllButton, *disableAllButton, *enableSomeButton, *disableSomeButton;
|
||||||
|
|
@ -29,7 +31,10 @@ private:
|
||||||
QAction *aUp, *aDown, *aBottom, *aTop;
|
QAction *aUp, *aDown, *aBottom, *aTop;
|
||||||
QToolBar *setsEditToolBar;
|
QToolBar *setsEditToolBar;
|
||||||
QDialogButtonBox *buttonBox;
|
QDialogButtonBox *buttonBox;
|
||||||
QLabel *labNotes, *searchLabel, *sortWarning;
|
QLabel *labNotes, *searchLabel;
|
||||||
|
QGroupBox *sortWarning;
|
||||||
|
QLabel *sortWarningText;
|
||||||
|
QPushButton *sortWarningButton;
|
||||||
QLineEdit *searchField;
|
QLineEdit *searchField;
|
||||||
QGridLayout *mainLayout;
|
QGridLayout *mainLayout;
|
||||||
QHBoxLayout *filterBox;
|
QHBoxLayout *filterBox;
|
||||||
|
|
@ -65,6 +70,7 @@ private slots:
|
||||||
void actRestoreOriginalOrder();
|
void actRestoreOriginalOrder();
|
||||||
void actDisableResetButton(const QString &filterText);
|
void actDisableResetButton(const QString &filterText);
|
||||||
void actSort(int index);
|
void actSort(int index);
|
||||||
|
void actIgnoreWarning();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -193,22 +193,22 @@ Cette information sera consultable uniquement par les modérateurs et ne sera pa
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/releasechannel.cpp" line="207"/>
|
<location filename="../src/releasechannel.cpp" line="207"/>
|
||||||
<source>Beta Releases</source>
|
<source>Beta Releases</source>
|
||||||
<translation type="unfinished"/>
|
<translation>version bêta</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/releasechannel.cpp" line="233"/>
|
<location filename="../src/releasechannel.cpp" line="233"/>
|
||||||
<source>No reply received from the release update server.</source>
|
<source>No reply received from the release update server.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Le serveur de mise à jour ne répond pas.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/releasechannel.cpp" line="242"/>
|
<location filename="../src/releasechannel.cpp" line="242"/>
|
||||||
<source>Invalid reply received from the release update server.</source>
|
<source>Invalid reply received from the release update server.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Réponse reçue du serveur de mise à jour de version invalide .</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/releasechannel.cpp" line="277"/>
|
<location filename="../src/releasechannel.cpp" line="277"/>
|
||||||
<source>No reply received from the file update server.</source>
|
<source>No reply received from the file update server.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Le serveur de mise à jour de fichier ne répond pas.</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
|
|
@ -442,47 +442,47 @@ Cette information sera consultable uniquement par les modérateurs et ne sera pa
|
||||||
<location filename="../src/dlg_settings.cpp" line="511"/>
|
<location filename="../src/dlg_settings.cpp" line="511"/>
|
||||||
<location filename="../src/dlg_settings.cpp" line="561"/>
|
<location filename="../src/dlg_settings.cpp" line="561"/>
|
||||||
<source>Update Spoilers</source>
|
<source>Update Spoilers</source>
|
||||||
<translation type="unfinished"/>
|
<translation>mettre à jour les spoilers</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_settings.cpp" line="550"/>
|
<location filename="../src/dlg_settings.cpp" line="550"/>
|
||||||
<source>Updating...</source>
|
<source>Updating...</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Mise à jours</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_settings.cpp" line="580"/>
|
<location filename="../src/dlg_settings.cpp" line="580"/>
|
||||||
<source>Choose path</source>
|
<source>Choose path</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Choisir le chemin</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_settings.cpp" line="606"/>
|
<location filename="../src/dlg_settings.cpp" line="606"/>
|
||||||
<source>Spoilers</source>
|
<source>Spoilers</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Spoilers</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_settings.cpp" line="607"/>
|
<location filename="../src/dlg_settings.cpp" line="607"/>
|
||||||
<source>Download Spoilers Automatically</source>
|
<source>Download Spoilers Automatically</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Télécharger automatiquement les spoilers</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_settings.cpp" line="608"/>
|
<location filename="../src/dlg_settings.cpp" line="608"/>
|
||||||
<source>Spoiler Location:</source>
|
<source>Spoiler Location:</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Emplacement des spoilers:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_settings.cpp" line="609"/>
|
<location filename="../src/dlg_settings.cpp" line="609"/>
|
||||||
<source>Hey, something's here finally!</source>
|
<source>Hey, something's here finally!</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Hey, quelque chose est enfin là!</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_settings.cpp" line="610"/>
|
<location filename="../src/dlg_settings.cpp" line="610"/>
|
||||||
<source>Last Updated</source>
|
<source>Last Updated</source>
|
||||||
<translation type="unfinished"/>
|
<translation>dernière mise à jour</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_settings.cpp" line="611"/>
|
<location filename="../src/dlg_settings.cpp" line="611"/>
|
||||||
<source>Spoilers download automatically on launch</source>
|
<source>Spoilers download automatically on launch</source>
|
||||||
<translation type="unfinished"/>
|
<translation>spoilers téléchargé automatiquement au lancement</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_settings.cpp" line="612"/>
|
<location filename="../src/dlg_settings.cpp" line="612"/>
|
||||||
|
|
@ -585,7 +585,7 @@ Cette information sera consultable uniquement par les modérateurs et ne sera pa
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_connect.cpp" line="28"/>
|
<location filename="../src/dlg_connect.cpp" line="28"/>
|
||||||
<source>Refresh the server list with known public servers</source>
|
<source>Refresh the server list with known public servers</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Actualiser la liste de serveurs avec des serveurs publics connus</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_connect.cpp" line="40"/>
|
<location filename="../src/dlg_connect.cpp" line="40"/>
|
||||||
|
|
@ -625,33 +625,33 @@ Cette information sera consultable uniquement par les modérateurs et ne sera pa
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_connect.cpp" line="78"/>
|
<location filename="../src/dlg_connect.cpp" line="78"/>
|
||||||
<source>If you have any trouble connecting or registering then contact the server staff for help!</source>
|
<source>If you have any trouble connecting or registering then contact the server staff for help!</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Si vous rencontrez des difficultés pour vous connecter ou vous inscrire, contactez le personnel du serveur pour obtenir de l'aide!</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_connect.cpp" line="80"/>
|
<location filename="../src/dlg_connect.cpp" line="80"/>
|
||||||
<location filename="../src/dlg_connect.cpp" line="262"/>
|
<location filename="../src/dlg_connect.cpp" line="262"/>
|
||||||
<source>Webpage</source>
|
<source>Webpage</source>
|
||||||
<translation type="unfinished"/>
|
<translation>page internet</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_connect.cpp" line="90"/>
|
<location filename="../src/dlg_connect.cpp" line="90"/>
|
||||||
<source>Forgot Password</source>
|
<source>Forgot Password</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Mot de passe oublié</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_connect.cpp" line="94"/>
|
<location filename="../src/dlg_connect.cpp" line="94"/>
|
||||||
<source>&Connect</source>
|
<source>&Connect</source>
|
||||||
<translation type="unfinished"/>
|
<translation>&Connexion </translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_connect.cpp" line="136"/>
|
<location filename="../src/dlg_connect.cpp" line="136"/>
|
||||||
<source>Server Contact</source>
|
<source>Server Contact</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Contact du serveur</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_connect.cpp" line="149"/>
|
<location filename="../src/dlg_connect.cpp" line="149"/>
|
||||||
<source>Connect to Server</source>
|
<source>Connect to Server</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Connecter au serveur</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_connect.cpp" line="117"/>
|
<location filename="../src/dlg_connect.cpp" line="117"/>
|
||||||
|
|
@ -686,7 +686,7 @@ Cette information sera consultable uniquement par les modérateurs et ne sera pa
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_connect.h" line="76"/>
|
<location filename="../src/dlg_connect.h" line="76"/>
|
||||||
<source>Downloading...</source>
|
<source>Downloading...</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Téléchargement</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
|
|
@ -1041,7 +1041,8 @@ Pour enlever votre avatar actuel, confirmez sans choisir une nouvelle image.</tr
|
||||||
<location filename="../src/dlg_edit_tokens.cpp" line="150"/>
|
<location filename="../src/dlg_edit_tokens.cpp" line="150"/>
|
||||||
<source>The chosen name conflicts with an existing card or token.
|
<source>The chosen name conflicts with an existing card or token.
|
||||||
Make sure to enable the 'Token' set in the "Manage sets" dialog to display them correctly.</source>
|
Make sure to enable the 'Token' set in the "Manage sets" dialog to display them correctly.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Le nom choisi est en conflit avec une carte ou un jeton existant.
|
||||||
|
Assurez-vous d'activer les set de 'jeton' dans le menu "gérer les sets" afin de les afficher correctement.</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
|
|
@ -1536,17 +1537,17 @@ Voulez vous changer les paramètres d'emplacement de base de données ?</tr
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_tip_of_the_day.cpp" line="67"/>
|
<location filename="../src/dlg_tip_of_the_day.cpp" line="67"/>
|
||||||
<source>Next</source>
|
<source>Next</source>
|
||||||
<translation type="unfinished"/>
|
<translation>suivant</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_tip_of_the_day.cpp" line="68"/>
|
<location filename="../src/dlg_tip_of_the_day.cpp" line="68"/>
|
||||||
<source>Previous</source>
|
<source>Previous</source>
|
||||||
<translation type="unfinished"/>
|
<translation>précédent</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_tip_of_the_day.cpp" line="90"/>
|
<location filename="../src/dlg_tip_of_the_day.cpp" line="90"/>
|
||||||
<source>Tip of the Day</source>
|
<source>Tip of the Day</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Conseil du jour</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
|
|
@ -1637,7 +1638,7 @@ Please visit the download page to update manually.</source>
|
||||||
<location filename="../src/dlg_update.cpp" line="147"/>
|
<location filename="../src/dlg_update.cpp" line="147"/>
|
||||||
<location filename="../src/dlg_update.cpp" line="158"/>
|
<location filename="../src/dlg_update.cpp" line="158"/>
|
||||||
<source>Released</source>
|
<source>Released</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Sortie</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_update.cpp" line="148"/>
|
<location filename="../src/dlg_update.cpp" line="148"/>
|
||||||
|
|
@ -1715,7 +1716,7 @@ Vous devez compiler les sources vous-même.</translation>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_viewlog.cpp" line="18"/>
|
<location filename="../src/dlg_viewlog.cpp" line="18"/>
|
||||||
<source>Clear log when closing</source>
|
<source>Clear log when closing</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Effacer le journal lors de la fermeture</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_viewlog.cpp" line="25"/>
|
<location filename="../src/dlg_viewlog.cpp" line="25"/>
|
||||||
|
|
@ -1728,7 +1729,7 @@ Vous devez compiler les sources vous-même.</translation>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/filterbuilder.cpp" line="28"/>
|
<location filename="../src/filterbuilder.cpp" line="28"/>
|
||||||
<source>Type your filter here</source>
|
<source>Type your filter here</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Tapez votre filtre ici</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
|
|
@ -2041,7 +2042,7 @@ Vous devez compiler les sources vous-même.</translation>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_settings.cpp" line="317"/>
|
<location filename="../src/dlg_settings.cpp" line="317"/>
|
||||||
<source>Show tips on startup</source>
|
<source>Show tips on startup</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Afficher les astuces au démarrage</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
|
|
@ -2589,7 +2590,7 @@ La version locale est %1, la nouvelle version est %2.</translation>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/window_main.cpp" line="641"/>
|
<location filename="../src/window_main.cpp" line="641"/>
|
||||||
<source>&Tip of the Day</source>
|
<source>&Tip of the Day</source>
|
||||||
<translation type="unfinished"/>
|
<translation>&Conseil du jour</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/window_main.cpp" line="642"/>
|
<location filename="../src/window_main.cpp" line="642"/>
|
||||||
|
|
@ -2764,14 +2765,14 @@ Cockatrice va maintenant recharger de nouveau la base de données de cartes.</tr
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/window_main.cpp" line="637"/>
|
<location filename="../src/window_main.cpp" line="637"/>
|
||||||
<source>&Manage sets...</source>
|
<source>&Manage sets...</source>
|
||||||
<translation type="unfinished"/>
|
<translation>&Gérer les sets...</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/window_main.cpp" line="983"/>
|
<location filename="../src/window_main.cpp" line="983"/>
|
||||||
<source>Hi! It seems like you're running this version of Cockatrice for the first time.
|
<source>Hi! It seems like you're running this version of Cockatrice for the first time.
|
||||||
All the sets in the card database have been enabled.
|
All the sets in the card database have been enabled.
|
||||||
Read more about changing the set order or disabling specific sets and consequent effects in the "Manage Sets" dialog.</source>
|
Read more about changing the set order or disabling specific sets and consequent effects in the "Manage Sets" dialog.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Salut! On dirait que vous utilisez cette version de Cockatrice pour la première fois. Tous les sets de la base de données de cartes ont été activés. Pour plus d'informations sur la modification de l'ordre des sets ou la désactivation de sets spécifiques et de leurs effets, consultez le menu "Gérer les sets".</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/window_main.cpp" line="1098"/>
|
<location filename="../src/window_main.cpp" line="1098"/>
|
||||||
|
|
@ -2920,12 +2921,12 @@ Cockactrice va maintenant recharger la base de données de cartes.</translation>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="366"/>
|
<location filename="../src/messagelogwidget.cpp" line="366"/>
|
||||||
<source>%1 turns %2 face-down.</source>
|
<source>%1 turns %2 face-down.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>%1 tourner %2 face cachée.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="368"/>
|
<location filename="../src/messagelogwidget.cpp" line="368"/>
|
||||||
<source>%1 turns %2 face-up.</source>
|
<source>%1 turns %2 face-up.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>%1 tourner %2 face visible.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="402"/>
|
<location filename="../src/messagelogwidget.cpp" line="402"/>
|
||||||
|
|
@ -3862,7 +3863,7 @@ Cockactrice va maintenant recharger la base de données de cartes.</translation>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/player.cpp" line="2722"/>
|
<location filename="../src/player.cpp" line="2722"/>
|
||||||
<source>View related cards</source>
|
<source>View related cards</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Voir les cartes associées</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/player.cpp" line="2750"/>
|
<location filename="../src/player.cpp" line="2750"/>
|
||||||
|
|
@ -3890,7 +3891,7 @@ Cockactrice va maintenant recharger la base de données de cartes.</translation>
|
||||||
<location filename="../src/player.cpp" line="690"/>
|
<location filename="../src/player.cpp" line="690"/>
|
||||||
<source>T&urn Over</source>
|
<source>T&urn Over</source>
|
||||||
<extracomment>Turn face up/face down</extracomment>
|
<extracomment>Turn face up/face down</extracomment>
|
||||||
<translation type="unfinished"/>
|
<translation>Retourner</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/player.cpp" line="713"/>
|
<location filename="../src/player.cpp" line="713"/>
|
||||||
|
|
@ -4148,7 +4149,7 @@ Cockactrice va maintenant recharger la base de données de cartes.</translation>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/sequenceEdit/sequenceedit.cpp" line="158"/>
|
<location filename="../src/sequenceEdit/sequenceedit.cpp" line="158"/>
|
||||||
<source>Invalid key</source>
|
<source>Invalid key</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Clé invalide</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
|
|
@ -4185,13 +4186,14 @@ Cockactrice va maintenant recharger la base de données de cartes.</translation>
|
||||||
<location filename="../src/shortcutssettings.cpp" line="40"/>
|
<location filename="../src/shortcutssettings.cpp" line="40"/>
|
||||||
<source>Your configuration file contained invalid shortcuts.
|
<source>Your configuration file contained invalid shortcuts.
|
||||||
Please check your shortcut settings!</source>
|
Please check your shortcut settings!</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Votre fichier de configuration contenait des raccourcis invalides. Merci de vérifier vos paramètres de raccourci !</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/shortcutssettings.cpp" line="42"/>
|
<location filename="../src/shortcutssettings.cpp" line="42"/>
|
||||||
<source>The following shortcuts have been set to default:
|
<source>The following shortcuts have been set to default:
|
||||||
</source>
|
</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Les raccourcis suivants ont été définis par défaut:
|
||||||
|
</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
|
|
@ -4268,48 +4270,48 @@ Please check your shortcut settings!</source>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/spoilerbackgroundupdater.cpp" line="99"/>
|
<location filename="../src/spoilerbackgroundupdater.cpp" line="99"/>
|
||||||
<source>Spoilers season has ended</source>
|
<source>Spoilers season has ended</source>
|
||||||
<translation type="unfinished"/>
|
<translation>La saison des spoilers est terminée</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/spoilerbackgroundupdater.cpp" line="99"/>
|
<location filename="../src/spoilerbackgroundupdater.cpp" line="99"/>
|
||||||
<source>Deleting spoiler.xml. Please run Oracle</source>
|
<source>Deleting spoiler.xml. Please run Oracle</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Suppression de spoiler.xml. S'il vous plaît exécuter Oracle</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/spoilerbackgroundupdater.cpp" line="109"/>
|
<location filename="../src/spoilerbackgroundupdater.cpp" line="109"/>
|
||||||
<location filename="../src/spoilerbackgroundupdater.cpp" line="116"/>
|
<location filename="../src/spoilerbackgroundupdater.cpp" line="116"/>
|
||||||
<source>Spoilers download failed</source>
|
<source>Spoilers download failed</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Échec du téléchargement des spoilers</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/spoilerbackgroundupdater.cpp" line="109"/>
|
<location filename="../src/spoilerbackgroundupdater.cpp" line="109"/>
|
||||||
<source>No internet connection</source>
|
<source>No internet connection</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Pas de connexion Internet</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/spoilerbackgroundupdater.cpp" line="116"/>
|
<location filename="../src/spoilerbackgroundupdater.cpp" line="116"/>
|
||||||
<source>Error</source>
|
<source>Error</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Erreur</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/spoilerbackgroundupdater.cpp" line="137"/>
|
<location filename="../src/spoilerbackgroundupdater.cpp" line="137"/>
|
||||||
<source>Spoilers already up to date</source>
|
<source>Spoilers already up to date</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Spoilers déjà à jour</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/spoilerbackgroundupdater.cpp" line="137"/>
|
<location filename="../src/spoilerbackgroundupdater.cpp" line="137"/>
|
||||||
<source>No new spoilers added</source>
|
<source>No new spoilers added</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Aucun nouveau spoilers ajouté</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/spoilerbackgroundupdater.cpp" line="178"/>
|
<location filename="../src/spoilerbackgroundupdater.cpp" line="178"/>
|
||||||
<source>Spoilers have been updated!</source>
|
<source>Spoilers have been updated!</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Les spoilers ont été mis à jour!</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/spoilerbackgroundupdater.cpp" line="178"/>
|
<location filename="../src/spoilerbackgroundupdater.cpp" line="178"/>
|
||||||
<source>Last change:</source>
|
<source>Last change:</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Dernier changement:</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
|
|
@ -4317,7 +4319,7 @@ Please check your shortcut settings!</source>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/releasechannel.cpp" line="90"/>
|
<location filename="../src/releasechannel.cpp" line="90"/>
|
||||||
<source>Stable Releases</source>
|
<source>Stable Releases</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Version stable</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/releasechannel.cpp" line="108"/>
|
<location filename="../src/releasechannel.cpp" line="108"/>
|
||||||
|
|
@ -4438,57 +4440,57 @@ Please check your shortcut settings!</source>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/tab_deck_editor.cpp" line="347"/>
|
<location filename="../src/tab_deck_editor.cpp" line="347"/>
|
||||||
<source>Search by card name</source>
|
<source>Search by card name</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Rechercher par nom de carte</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/tab_deck_editor.cpp" line="453"/>
|
<location filename="../src/tab_deck_editor.cpp" line="453"/>
|
||||||
<source>Add to Deck</source>
|
<source>Add to Deck</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Ajouter au Deck</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/tab_deck_editor.cpp" line="454"/>
|
<location filename="../src/tab_deck_editor.cpp" line="454"/>
|
||||||
<source>Add to Sideboard</source>
|
<source>Add to Sideboard</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Ajouter à la réserve</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/tab_deck_editor.cpp" line="459"/>
|
<location filename="../src/tab_deck_editor.cpp" line="459"/>
|
||||||
<source>Show Related cards</source>
|
<source>Show Related cards</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Afficher les cartes associées</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/tab_deck_editor.cpp" line="623"/>
|
<location filename="../src/tab_deck_editor.cpp" line="623"/>
|
||||||
<source>Save deck to clipboard</source>
|
<source>Save deck to clipboard</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Enregistrer le deck dans le presse-papier</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/tab_deck_editor.cpp" line="624"/>
|
<location filename="../src/tab_deck_editor.cpp" line="624"/>
|
||||||
<source>Annotated</source>
|
<source>Annotated</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Annoté</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/tab_deck_editor.cpp" line="625"/>
|
<location filename="../src/tab_deck_editor.cpp" line="625"/>
|
||||||
<source>Not Annotated</source>
|
<source>Not Annotated</source>
|
||||||
<translation type="unfinished"/>
|
<translation>sans annotation</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/tab_deck_editor.cpp" line="629"/>
|
<location filename="../src/tab_deck_editor.cpp" line="629"/>
|
||||||
<source>&Send deck to online service</source>
|
<source>&Send deck to online service</source>
|
||||||
<translation type="unfinished"/>
|
<translation>& Envoyer le Deck au service en ligne</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/tab_deck_editor.cpp" line="630"/>
|
<location filename="../src/tab_deck_editor.cpp" line="630"/>
|
||||||
<source>Create decklist (decklist.org)</source>
|
<source>Create decklist (decklist.org)</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Créer une liste de deck (decklist.org)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/tab_deck_editor.cpp" line="631"/>
|
<location filename="../src/tab_deck_editor.cpp" line="631"/>
|
||||||
<source>Analyze deck (deckstats.net)</source>
|
<source>Analyze deck (deckstats.net)</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Analyser le Deck (deckstats.net)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/tab_deck_editor.cpp" line="632"/>
|
<location filename="../src/tab_deck_editor.cpp" line="632"/>
|
||||||
<source>Analyze deck (tappedout.net)</source>
|
<source>Analyze deck (tappedout.net)</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Analyser le deck (tappedout.net)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/tab_deck_editor.cpp" line="634"/>
|
<location filename="../src/tab_deck_editor.cpp" line="634"/>
|
||||||
|
|
@ -4619,12 +4621,12 @@ Vérifiez que le répertoire ne soit pas en lecture seule et réessayez.</transl
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/tab_deck_editor.cpp" line="877"/>
|
<location filename="../src/tab_deck_editor.cpp" line="877"/>
|
||||||
<source>There are no cards in your deck to be exported</source>
|
<source>There are no cards in your deck to be exported</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Il n'y a pas de cartes dans le deck à exporter</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/tab_deck_editor.cpp" line="889"/>
|
<location filename="../src/tab_deck_editor.cpp" line="889"/>
|
||||||
<source>No deck was selected to be saved.</source>
|
<source>No deck was selected to be saved.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Aucun deck n'a été sélectionné pour être sauvegardé.</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
|
|
@ -5077,7 +5079,7 @@ Plus vous entrez d'informations, meilleurs seront les résultats.</translat
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/tab_message.cpp" line="148"/>
|
<location filename="../src/tab_message.cpp" line="148"/>
|
||||||
<source>Private message from</source>
|
<source>Private message from</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Message privé de</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/tab_message.cpp" line="165"/>
|
<location filename="../src/tab_message.cpp" line="165"/>
|
||||||
|
|
@ -5350,13 +5352,15 @@ Merci de ne pas recommencer ou d'autres mesures peuvent être prises contre
|
||||||
<location filename="../src/tip_of_the_day.cpp" line="25"/>
|
<location filename="../src/tip_of_the_day.cpp" line="25"/>
|
||||||
<source>File does not exist.
|
<source>File does not exist.
|
||||||
</source>
|
</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Le fichier n'existe pas.
|
||||||
|
</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/tip_of_the_day.cpp" line="28"/>
|
<location filename="../src/tip_of_the_day.cpp" line="28"/>
|
||||||
<source>Failed to open file.
|
<source>Failed to open file.
|
||||||
</source>
|
</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Échec de l'ouverture du fichier.
|
||||||
|
</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
|
|
@ -5810,17 +5814,17 @@ Merci de ne pas recommencer ou d'autres mesures peuvent être prises contre
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/window_sets.cpp" line="61"/>
|
<location filename="../src/window_sets.cpp" line="61"/>
|
||||||
<source>Search by set name, code, or type</source>
|
<source>Search by set name, code, or type</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Rechercher par ensemble de nom, code ou type</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/window_sets.cpp" line="66"/>
|
<location filename="../src/window_sets.cpp" line="66"/>
|
||||||
<source>Default order</source>
|
<source>Default order</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Ordre par défaut</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/window_sets.cpp" line="67"/>
|
<location filename="../src/window_sets.cpp" line="67"/>
|
||||||
<source>Restore original art priority order</source>
|
<source>Restore original art priority order</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Restaurer l'ordre originale de priorité artistique</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/window_sets.cpp" line="107"/>
|
<location filename="../src/window_sets.cpp" line="107"/>
|
||||||
|
|
@ -5885,22 +5889,22 @@ Merci de ne pas recommencer ou d'autres mesures peuvent être prises contre
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/window_sets.cpp" line="139"/>
|
<location filename="../src/window_sets.cpp" line="139"/>
|
||||||
<source>Warning: </source>
|
<source>Warning: </source>
|
||||||
<translation type="unfinished"/>
|
<translation>Attention:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/window_sets.cpp" line="140"/>
|
<location filename="../src/window_sets.cpp" line="140"/>
|
||||||
<source>While the set list is sorted by any of the columns, custom art priority setting is disabled.</source>
|
<source>While the set list is sorted by any of the columns, custom art priority setting is disabled.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>lorsque la liste est triée dans une des colonnes, la priorité personnalisée est désactivée.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/window_sets.cpp" line="141"/>
|
<location filename="../src/window_sets.cpp" line="141"/>
|
||||||
<source>To disable sorting click on the same column header again until this message disappears.</source>
|
<source>To disable sorting click on the same column header again until this message disappears.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Pour désactiver le tri, cliquez à nouveau sur la même en-tête de colonne jusqu'à ce que ce message disparaisse.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/window_sets.cpp" line="170"/>
|
<location filename="../src/window_sets.cpp" line="170"/>
|
||||||
<source>Manage sets</source>
|
<source>Manage sets</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Gérer les sets</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/window_sets.cpp" line="204"/>
|
<location filename="../src/window_sets.cpp" line="204"/>
|
||||||
|
|
@ -6330,22 +6334,22 @@ Merci de ne pas recommencer ou d'autres mesures peuvent être prises contre
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/sequenceEdit/ui_shortcutstab.h" line="1764"/>
|
<location filename="../src/sequenceEdit/ui_shortcutstab.h" line="1764"/>
|
||||||
<source>Manage sets</source>
|
<source>Manage sets</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Gérer les sets</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/sequenceEdit/ui_shortcutstab.h" line="1770"/>
|
<location filename="../src/sequenceEdit/ui_shortcutstab.h" line="1770"/>
|
||||||
<source>Export deck</source>
|
<source>Export deck</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Exporter le Deck</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/sequenceEdit/ui_shortcutstab.h" line="1774"/>
|
<location filename="../src/sequenceEdit/ui_shortcutstab.h" line="1774"/>
|
||||||
<source>Save deck (clip)</source>
|
<source>Save deck (clip)</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Sauvegarder le Deck (du presse-papier)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/sequenceEdit/ui_shortcutstab.h" line="1776"/>
|
<location filename="../src/sequenceEdit/ui_shortcutstab.h" line="1776"/>
|
||||||
<source>Save deck (clip; no annotations)</source>
|
<source>Save deck (clip; no annotations)</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Enregistrer le Deck (du presse papier; sans annotations)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/sequenceEdit/ui_shortcutstab.h" line="1855"/>
|
<location filename="../src/sequenceEdit/ui_shortcutstab.h" line="1855"/>
|
||||||
|
|
|
||||||
|
|
@ -267,7 +267,7 @@ This is only saved for moderators and cannot be seen by the banned person.</sour
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/cardinfotext.cpp" line="123"/>
|
<location filename="../src/cardinfotext.cpp" line="123"/>
|
||||||
<source>Unknown card:</source>
|
<source>Unknown card:</source>
|
||||||
<translation type="unfinished"/>
|
<translation>謎のカード:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/cardinfotext.cpp" line="131"/>
|
<location filename="../src/cardinfotext.cpp" line="131"/>
|
||||||
|
|
@ -585,7 +585,7 @@ This is only saved for moderators and cannot be seen by the banned person.</sour
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_connect.cpp" line="28"/>
|
<location filename="../src/dlg_connect.cpp" line="28"/>
|
||||||
<source>Refresh the server list with known public servers</source>
|
<source>Refresh the server list with known public servers</source>
|
||||||
<translation type="unfinished"/>
|
<translation>デフォルトの公開サーバーリストに更新します</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_connect.cpp" line="40"/>
|
<location filename="../src/dlg_connect.cpp" line="40"/>
|
||||||
|
|
@ -625,33 +625,33 @@ This is only saved for moderators and cannot be seen by the banned person.</sour
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_connect.cpp" line="78"/>
|
<location filename="../src/dlg_connect.cpp" line="78"/>
|
||||||
<source>If you have any trouble connecting or registering then contact the server staff for help!</source>
|
<source>If you have any trouble connecting or registering then contact the server staff for help!</source>
|
||||||
<translation type="unfinished"/>
|
<translation>接続や登録に問題がある場合は、サーバー管理者にお問い合わせください。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_connect.cpp" line="80"/>
|
<location filename="../src/dlg_connect.cpp" line="80"/>
|
||||||
<location filename="../src/dlg_connect.cpp" line="262"/>
|
<location filename="../src/dlg_connect.cpp" line="262"/>
|
||||||
<source>Webpage</source>
|
<source>Webpage</source>
|
||||||
<translation type="unfinished"/>
|
<translation>ウェブページ</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_connect.cpp" line="90"/>
|
<location filename="../src/dlg_connect.cpp" line="90"/>
|
||||||
<source>Forgot Password</source>
|
<source>Forgot Password</source>
|
||||||
<translation type="unfinished"/>
|
<translation>パスワード忘れちゃった</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_connect.cpp" line="94"/>
|
<location filename="../src/dlg_connect.cpp" line="94"/>
|
||||||
<source>&Connect</source>
|
<source>&Connect</source>
|
||||||
<translation type="unfinished"/>
|
<translation>接続</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_connect.cpp" line="136"/>
|
<location filename="../src/dlg_connect.cpp" line="136"/>
|
||||||
<source>Server Contact</source>
|
<source>Server Contact</source>
|
||||||
<translation type="unfinished"/>
|
<translation>サーバーの連絡先</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_connect.cpp" line="149"/>
|
<location filename="../src/dlg_connect.cpp" line="149"/>
|
||||||
<source>Connect to Server</source>
|
<source>Connect to Server</source>
|
||||||
<translation type="unfinished"/>
|
<translation>サーバーに接続</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_connect.cpp" line="117"/>
|
<location filename="../src/dlg_connect.cpp" line="117"/>
|
||||||
|
|
@ -1030,7 +1030,7 @@ To remove your current avatar, confirm without choosing a new image.</source>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_edit_tokens.cpp" line="145"/>
|
<location filename="../src/dlg_edit_tokens.cpp" line="145"/>
|
||||||
<source>Please enter the name of the token:</source>
|
<source>Please enter the name of the token:</source>
|
||||||
<translation>トークン名を入力してください:</translation>
|
<translation>トークン名を入力:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/dlg_edit_tokens.cpp" line="149"/>
|
<location filename="../src/dlg_edit_tokens.cpp" line="149"/>
|
||||||
|
|
@ -1771,7 +1771,7 @@ You may have to build from source yourself.</source>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/gameselector.cpp" line="169"/>
|
<location filename="../src/gameselector.cpp" line="169"/>
|
||||||
<source>The game does not exist any more.</source>
|
<source>The game does not exist any more.</source>
|
||||||
<translation>このゲームは既に存在しません。</translation>
|
<translation>このゲームはすでに存在しません。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/gameselector.cpp" line="172"/>
|
<location filename="../src/gameselector.cpp" line="172"/>
|
||||||
|
|
@ -2818,12 +2818,12 @@ Cockatrice will now reload the card database.</source>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="391"/>
|
<location filename="../src/messagelogwidget.cpp" line="391"/>
|
||||||
<source>%1 is now watching the game.</source>
|
<source>%1 is now watching the game.</source>
|
||||||
<translation>%1が観戦に参加した。</translation>
|
<translation>%1 が観戦に参加した。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="251"/>
|
<location filename="../src/messagelogwidget.cpp" line="251"/>
|
||||||
<source>%1 has loaded a deck (%2).</source>
|
<source>%1 has loaded a deck (%2).</source>
|
||||||
<translation>%1はデッキをロードした。ハッシュ:%2</translation>
|
<translation>%1 はデッキをロードした。ハッシュ:%2</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="253"/>
|
<location filename="../src/messagelogwidget.cpp" line="253"/>
|
||||||
|
|
@ -2889,57 +2889,57 @@ Cockatrice will now reload the card database.</source>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="290"/>
|
<location filename="../src/messagelogwidget.cpp" line="290"/>
|
||||||
<source>%1 gives %2 control over %3.</source>
|
<source>%1 gives %2 control over %3.</source>
|
||||||
<translation>%1は、%2に《%3》のコントロールを渡した。</translation>
|
<translation>%1 は %2 に %3 のコントロールを渡した。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="302"/>
|
<location filename="../src/messagelogwidget.cpp" line="302"/>
|
||||||
<source>%1 puts %2 into play tapped%3.</source>
|
<source>%1 puts %2 into play tapped%3.</source>
|
||||||
<translation>%1は《%2》を%3タップ状態でプレイした。</translation>
|
<translation>%1 は %2 を%3タップ状態でプレイした。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="304"/>
|
<location filename="../src/messagelogwidget.cpp" line="304"/>
|
||||||
<source>%1 puts %2 into play%3.</source>
|
<source>%1 puts %2 into play%3.</source>
|
||||||
<translation>%1は《%2》を%3プレイした。</translation>
|
<translation>%1 は %2 を%3プレイした。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="308"/>
|
<location filename="../src/messagelogwidget.cpp" line="308"/>
|
||||||
<source>%1 exiles %2%3.</source>
|
<source>%1 exiles %2%3.</source>
|
||||||
<translation>%1は《%2》を%3追放した。</translation>
|
<translation>%1 は %2 を%3追放した。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="321"/>
|
<location filename="../src/messagelogwidget.cpp" line="321"/>
|
||||||
<source>%1 puts %2%3 into their library %4 cards from the top.</source>
|
<source>%1 puts %2%3 into their library %4 cards from the top.</source>
|
||||||
<translation>%1は《%2》を%3ライブラリーの一番上から%4枚目に置いた。</translation>
|
<translation>%1 は %2 を%3ライブラリーの一番上から%4枚目に置いた。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="324"/>
|
<location filename="../src/messagelogwidget.cpp" line="324"/>
|
||||||
<source>%1 moves %2%3 to sideboard.</source>
|
<source>%1 moves %2%3 to sideboard.</source>
|
||||||
<translation>%1は《%2》を%3サイドボードに置いた。</translation>
|
<translation>%1 は %2 を%3サイドボードに置いた。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="327"/>
|
<location filename="../src/messagelogwidget.cpp" line="327"/>
|
||||||
<source>%1 plays %2%3.</source>
|
<source>%1 plays %2%3.</source>
|
||||||
<translation>%1は《%2》を%3プレイした。</translation>
|
<translation>%1 は %2 を%3プレイした。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="366"/>
|
<location filename="../src/messagelogwidget.cpp" line="366"/>
|
||||||
<source>%1 turns %2 face-down.</source>
|
<source>%1 turns %2 face-down.</source>
|
||||||
<translation>%1は《%2》を裏向きにした。</translation>
|
<translation>%1 は %2 を裏向きにした。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="368"/>
|
<location filename="../src/messagelogwidget.cpp" line="368"/>
|
||||||
<source>%1 turns %2 face-up.</source>
|
<source>%1 turns %2 face-up.</source>
|
||||||
<translation>%1は《%2》を表向きにした。</translation>
|
<translation>%1 は %2 を表向きにした。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="402"/>
|
<location filename="../src/messagelogwidget.cpp" line="402"/>
|
||||||
<source>%1 has left the game (%2).</source>
|
<source>%1 has left the game (%2).</source>
|
||||||
<translation>%1はゲームから離脱した(%2)。</translation>
|
<translation>%1 はゲームから離脱した(%2)。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="410"/>
|
<location filename="../src/messagelogwidget.cpp" line="410"/>
|
||||||
<source>%1 is not watching the game any more (%2).</source>
|
<source>%1 is not watching the game any more (%2).</source>
|
||||||
<translation>%1が観戦から離脱した(%2)。</translation>
|
<translation>%1 が観戦から離脱した(%2)。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="546"/>
|
<location filename="../src/messagelogwidget.cpp" line="546"/>
|
||||||
|
|
@ -3004,7 +3004,7 @@ Cockatrice will now reload the card database.</source>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="612"/>
|
<location filename="../src/messagelogwidget.cpp" line="612"/>
|
||||||
<source>%1's turn.</source>
|
<source>%1's turn.</source>
|
||||||
<translation>■%1のターン■</translation>
|
<translation>■ %1 のターン■</translation>
|
||||||
</message>
|
</message>
|
||||||
<message numerus="yes">
|
<message numerus="yes">
|
||||||
<location filename="../src/messagelogwidget.cpp" line="636"/>
|
<location filename="../src/messagelogwidget.cpp" line="636"/>
|
||||||
|
|
@ -3024,12 +3024,12 @@ Cockatrice will now reload the card database.</source>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="151"/>
|
<location filename="../src/messagelogwidget.cpp" line="151"/>
|
||||||
<source>%1 is now keeping the top card %2 revealed.</source>
|
<source>%1 is now keeping the top card %2 revealed.</source>
|
||||||
<translation>%1は、%2一番上のカードを公開した状態でゲームをプレイしている。</translation>
|
<translation>%1 は%2一番上のカードを公開した状態でゲームをプレイしている。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="152"/>
|
<location filename="../src/messagelogwidget.cpp" line="152"/>
|
||||||
<source>%1 is not revealing the top card %2 any longer.</source>
|
<source>%1 is not revealing the top card %2 any longer.</source>
|
||||||
<translation>%1は、%2一番上のカードの公開を終えた。</translation>
|
<translation>%1 は%2一番上のカードの公開を終えた。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="446"/>
|
<location filename="../src/messagelogwidget.cpp" line="446"/>
|
||||||
|
|
@ -3039,47 +3039,47 @@ Cockatrice will now reload the card database.</source>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="385"/>
|
<location filename="../src/messagelogwidget.cpp" line="385"/>
|
||||||
<source>%1 has joined the game.</source>
|
<source>%1 has joined the game.</source>
|
||||||
<translation>%1がゲームに参加した。</translation>
|
<translation>%1 がゲームに参加した。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="451"/>
|
<location filename="../src/messagelogwidget.cpp" line="451"/>
|
||||||
<source>%1 is ready to start the game.</source>
|
<source>%1 is ready to start the game.</source>
|
||||||
<translation>%1はゲーム開始の準備が完了した!!</translation>
|
<translation>%1 はゲーム開始の準備が完了した!!</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="415"/>
|
<location filename="../src/messagelogwidget.cpp" line="415"/>
|
||||||
<source>%1 is not ready to start the game any more.</source>
|
<source>%1 is not ready to start the game any more.</source>
|
||||||
<translation>%1は準備完了を解除した。</translation>
|
<translation>%1 は準備完了を解除した。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="691"/>
|
<location filename="../src/messagelogwidget.cpp" line="691"/>
|
||||||
<source>%1 has locked their sideboard.</source>
|
<source>%1 has locked their sideboard.</source>
|
||||||
<translation>%1はサイドボードをロックした。</translation>
|
<translation>%1 はサイドボードをロックした。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="693"/>
|
<location filename="../src/messagelogwidget.cpp" line="693"/>
|
||||||
<source>%1 has unlocked their sideboard.</source>
|
<source>%1 has unlocked their sideboard.</source>
|
||||||
<translation>%1はサイドボードを解禁した。</translation>
|
<translation>%1 はサイドボードを解禁した。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="169"/>
|
<location filename="../src/messagelogwidget.cpp" line="169"/>
|
||||||
<source>%1 has conceded the game.</source>
|
<source>%1 has conceded the game.</source>
|
||||||
<translation>%1が投了した!!!</translation>
|
<translation>%1 が投了した!!!</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="176"/>
|
<location filename="../src/messagelogwidget.cpp" line="176"/>
|
||||||
<source>%1 has restored connection to the game.</source>
|
<source>%1 has restored connection to the game.</source>
|
||||||
<translation>%1がゲームに再接続した。</translation>
|
<translation>%1 がゲームに再接続した。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="180"/>
|
<location filename="../src/messagelogwidget.cpp" line="180"/>
|
||||||
<source>%1 has lost connection to the game.</source>
|
<source>%1 has lost connection to the game.</source>
|
||||||
<translation>%1はゲームから切断された。</translation>
|
<translation>%1 はゲームから切断された。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="721"/>
|
<location filename="../src/messagelogwidget.cpp" line="721"/>
|
||||||
<source>%1 shuffles %2.</source>
|
<source>%1 shuffles %2.</source>
|
||||||
<translation>%1は%2を切り直した。</translation>
|
<translation>%1 は%2を切り直した。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="522"/>
|
<location filename="../src/messagelogwidget.cpp" line="522"/>
|
||||||
|
|
@ -3094,27 +3094,27 @@ Cockatrice will now reload the card database.</source>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="523"/>
|
<location filename="../src/messagelogwidget.cpp" line="523"/>
|
||||||
<source>%1 flipped a coin. It landed as %2.</source>
|
<source>%1 flipped a coin. It landed as %2.</source>
|
||||||
<translation>%1はコインを投げた。結果は……【%2】だ!</translation>
|
<translation>%1 はコインを投げた。結果は……【%2】だ!</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="527"/>
|
<location filename="../src/messagelogwidget.cpp" line="527"/>
|
||||||
<source>%1 rolls a %2 with a %3-sided die.</source>
|
<source>%1 rolls a %2 with a %3-sided die.</source>
|
||||||
<translation>%1は%3面ダイスをふり、【%2】を出した。</translation>
|
<translation>%1 は%3面ダイスをふり、【%2】を出した。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="344"/>
|
<location filename="../src/messagelogwidget.cpp" line="344"/>
|
||||||
<source>%1 draws %2 card(s).</source>
|
<source>%1 draws %2 card(s).</source>
|
||||||
<translation>%1は%2枚カードを引いた。</translation>
|
<translation>%1 は%2枚カードを引いた。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="749"/>
|
<location filename="../src/messagelogwidget.cpp" line="749"/>
|
||||||
<source>%1 undoes their last draw.</source>
|
<source>%1 undoes their last draw.</source>
|
||||||
<translation>%1は最後に引いたカードを戻した。</translation>
|
<translation>%1 は最後に引いたカードを戻した。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="752"/>
|
<location filename="../src/messagelogwidget.cpp" line="752"/>
|
||||||
<source>%1 undoes their last draw (%2).</source>
|
<source>%1 undoes their last draw (%2).</source>
|
||||||
<translation>%1は最後に引いたカード (《%2》) を戻した 。</translation>
|
<translation>%1 は最後に引いたカード ( %2 ) を戻した 。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="72"/>
|
<location filename="../src/messagelogwidget.cpp" line="72"/>
|
||||||
|
|
@ -3154,202 +3154,202 @@ Cockatrice will now reload the card database.</source>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="306"/>
|
<location filename="../src/messagelogwidget.cpp" line="306"/>
|
||||||
<source>%1 puts %2%3 into their graveyard.</source>
|
<source>%1 puts %2%3 into their graveyard.</source>
|
||||||
<translation>%1は《%2》を%3墓地に置いた。</translation>
|
<translation>%1 は %2 を%3墓地に置いた。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="310"/>
|
<location filename="../src/messagelogwidget.cpp" line="310"/>
|
||||||
<source>%1 moves %2%3 to their hand.</source>
|
<source>%1 moves %2%3 to their hand.</source>
|
||||||
<translation>%1は《%2》を%3手札に加えた。</translation>
|
<translation>% 1は %2 を%3手札に加えた。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="313"/>
|
<location filename="../src/messagelogwidget.cpp" line="313"/>
|
||||||
<source>%1 puts %2%3 into their library.</source>
|
<source>%1 puts %2%3 into their library.</source>
|
||||||
<translation>%1は《%2》を%3ライブラリーに加えた。</translation>
|
<translation>%1 は %2 を%3ライブラリーに加えた。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="315"/>
|
<location filename="../src/messagelogwidget.cpp" line="315"/>
|
||||||
<source>%1 puts %2%3 on bottom of their library.</source>
|
<source>%1 puts %2%3 on bottom of their library.</source>
|
||||||
<translation>%1は《%2》を%3ライブラリーの一番下に置いた。</translation>
|
<translation>%1 は %2 を%3ライブラリーの一番下に置いた。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="317"/>
|
<location filename="../src/messagelogwidget.cpp" line="317"/>
|
||||||
<source>%1 puts %2%3 on top of their library.</source>
|
<source>%1 puts %2%3 on top of their library.</source>
|
||||||
<translation>%1は《%2》を%3ライブラリーの一番上に置いた。</translation>
|
<translation>%1 は %2 を%3ライブラリーの一番上に置いた。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="439"/>
|
<location filename="../src/messagelogwidget.cpp" line="439"/>
|
||||||
<source>%1 takes a mulligan to %2.</source>
|
<source>%1 takes a mulligan to %2.</source>
|
||||||
<translation>%1は%2枚にマリガンした。</translation>
|
<translation>%1 は%2枚にマリガンした。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="441"/>
|
<location filename="../src/messagelogwidget.cpp" line="441"/>
|
||||||
<source>%1 draws their initial hand.</source>
|
<source>%1 draws their initial hand.</source>
|
||||||
<translation>%1は初期手札を引いた。</translation>
|
<translation>%1 は初期手札を引いた。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="261"/>
|
<location filename="../src/messagelogwidget.cpp" line="261"/>
|
||||||
<source>%1 destroys %2.</source>
|
<source>%1 destroys %2.</source>
|
||||||
<translation>%1は《%2》を取り除いた。</translation>
|
<translation>%1 は %2 を取り除いた。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="743"/>
|
<location filename="../src/messagelogwidget.cpp" line="743"/>
|
||||||
<source>%1 unattaches %2.</source>
|
<source>%1 unattaches %2.</source>
|
||||||
<translation>%1は《%2》をはずした。</translation>
|
<translation>%1 は %2 をはずした。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="242"/>
|
<location filename="../src/messagelogwidget.cpp" line="242"/>
|
||||||
<source>%1 creates token: %2%3.</source>
|
<source>%1 creates token: %2%3.</source>
|
||||||
<translation>%1はトークン:《%2》を%3作成した。</translation>
|
<translation>%1 はトークン: %2 を%3作成した。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="196"/>
|
<location filename="../src/messagelogwidget.cpp" line="196"/>
|
||||||
<source>%1 points from their %2 to themselves.</source>
|
<source>%1 points from their %2 to themselves.</source>
|
||||||
<translation>%1は《%2》から自分自身へ対象を指定した。</translation>
|
<translation>%1 は %2 から自分自身へ対象を指定した。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="199"/>
|
<location filename="../src/messagelogwidget.cpp" line="199"/>
|
||||||
<source>%1 points from their %2 to %3.</source>
|
<source>%1 points from their %2 to %3.</source>
|
||||||
<translation>%1は、《%2》から%3へ対象を指定した。</translation>
|
<translation>%1 は %2 から %3 へ対象を指定した。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="203"/>
|
<location filename="../src/messagelogwidget.cpp" line="203"/>
|
||||||
<source>%1 points from %2's %3 to themselves.</source>
|
<source>%1 points from %2's %3 to themselves.</source>
|
||||||
<translation>%1は、%2の《%3》から自分自身へ対象を指定した。</translation>
|
<translation>%1 は %2 の %3 から自分自身へ対象を指定した。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="207"/>
|
<location filename="../src/messagelogwidget.cpp" line="207"/>
|
||||||
<source>%1 points from %2's %3 to %4.</source>
|
<source>%1 points from %2's %3 to %4.</source>
|
||||||
<translation>%1は、%2の《%3》から%4へ対象を指定した。</translation>
|
<translation>%1 は %2 の %3 から %4 へ対象を指定した。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="215"/>
|
<location filename="../src/messagelogwidget.cpp" line="215"/>
|
||||||
<source>%1 points from their %2 to their %3.</source>
|
<source>%1 points from their %2 to their %3.</source>
|
||||||
<translation>%1は、《%2》から%3へ対象を指定した。</translation>
|
<translation>%1 は %2 から %3 へ対象を指定した。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="218"/>
|
<location filename="../src/messagelogwidget.cpp" line="218"/>
|
||||||
<source>%1 points from their %2 to %3's %4.</source>
|
<source>%1 points from their %2 to %3's %4.</source>
|
||||||
<translation>%1は、《%2》から%3の《%4》へ対象を指定した。</translation>
|
<translation>%1 は %2 から %3 の %4 へ対象を指定した。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="224"/>
|
<location filename="../src/messagelogwidget.cpp" line="224"/>
|
||||||
<source>%1 points from %2's %3 to their own %4.</source>
|
<source>%1 points from %2's %3 to their own %4.</source>
|
||||||
<translation>%1は、%2の《%3》から《%4》へ対象を指定した。</translation>
|
<translation>%1 は %2 の %3 から %4 へ対象を指定した。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="230"/>
|
<location filename="../src/messagelogwidget.cpp" line="230"/>
|
||||||
<source>%1 points from %2's %3 to %4's %5.</source>
|
<source>%1 points from %2's %3 to %4's %5.</source>
|
||||||
<translation>%1は、%2の《%3》から%4の《%5》へ対象を指定した。</translation>
|
<translation>%1 は %2 の %3 から %4 の %5 へ対象を指定した。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="629"/>
|
<location filename="../src/messagelogwidget.cpp" line="629"/>
|
||||||
<source>%1 places %2 %3 counter(s) on %4 (now %5).</source>
|
<source>%1 places %2 %3 counter(s) on %4 (now %5).</source>
|
||||||
<translation>%1は《%4》の上に%3カウンターを%2個置いた (計%5個) 。</translation>
|
<translation>%1 は %4 の上に%3カウンターを%2個置いた (計%5個) 。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="631"/>
|
<location filename="../src/messagelogwidget.cpp" line="631"/>
|
||||||
<source>%1 removes %2 %3 counter(s) from %4 (now %5).</source>
|
<source>%1 removes %2 %3 counter(s) from %4 (now %5).</source>
|
||||||
<translation>%1は《%4》の上から%3カウンターを%2個取り除いた (計%5個) 。</translation>
|
<translation>%1 は %4 の上から%3カウンターを%2個取り除いた (計%5個) 。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="708"/>
|
<location filename="../src/messagelogwidget.cpp" line="708"/>
|
||||||
<source>%1 taps their permanents.</source>
|
<source>%1 taps their permanents.</source>
|
||||||
<translation>%1は自分のコントロールするパーマネントをタップした。</translation>
|
<translation>%1 は自分のコントロールするパーマネントをタップした。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="708"/>
|
<location filename="../src/messagelogwidget.cpp" line="708"/>
|
||||||
<source>%1 untaps their permanents.</source>
|
<source>%1 untaps their permanents.</source>
|
||||||
<translation>%1は自分のコントロールするパーマネントをアンタップした。</translation>
|
<translation>%1 は自分のコントロールするパーマネントをアンタップした。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="711"/>
|
<location filename="../src/messagelogwidget.cpp" line="711"/>
|
||||||
<source>%1 taps %2.</source>
|
<source>%1 taps %2.</source>
|
||||||
<translation>%1は《%2》をタップした。</translation>
|
<translation>%1 は %2 をタップした。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="711"/>
|
<location filename="../src/messagelogwidget.cpp" line="711"/>
|
||||||
<source>%1 untaps %2.</source>
|
<source>%1 untaps %2.</source>
|
||||||
<translation>%1は《%2》をアンタップした。</translation>
|
<translation>%1 は %2 をアンタップした。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="659"/>
|
<location filename="../src/messagelogwidget.cpp" line="659"/>
|
||||||
<source>%1 sets counter %2 to %3 (%4%5).</source>
|
<source>%1 sets counter %2 to %3 (%4%5).</source>
|
||||||
<translation>%1は%2カウンターを%3に設定した (%4%5)。</translation>
|
<translation>%1 は%2カウンターを%3に設定した (%4%5)。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="671"/>
|
<location filename="../src/messagelogwidget.cpp" line="671"/>
|
||||||
<source>%1 sets %2 to not untap normally.</source>
|
<source>%1 sets %2 to not untap normally.</source>
|
||||||
<translation>%1は《%2》をアンタップ・ステップの間にアンタップしないようにした。</translation>
|
<translation>%1 は %2 をアンタップ・ステップの間にアンタップしないようにした。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="673"/>
|
<location filename="../src/messagelogwidget.cpp" line="673"/>
|
||||||
<source>%1 sets %2 to untap normally.</source>
|
<source>%1 sets %2 to untap normally.</source>
|
||||||
<translation>%1は《%2》を通常どおりアンタップするように設定した。</translation>
|
<translation>%1 は %2 を通常どおりアンタップするように設定した。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="682"/>
|
<location filename="../src/messagelogwidget.cpp" line="682"/>
|
||||||
<source>%1 sets PT of %2 to %3.</source>
|
<source>%1 sets PT of %2 to %3.</source>
|
||||||
<translation>%1は《%2》のP/Tを%3にした。</translation>
|
<translation>%1 は %2 のP/Tを%3にした。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="618"/>
|
<location filename="../src/messagelogwidget.cpp" line="618"/>
|
||||||
<source>%1 sets annotation of %2 to %3.</source>
|
<source>%1 sets annotation of %2 to %3.</source>
|
||||||
<translation>%1は《%2》に注釈をつけた (%3)。</translation>
|
<translation>%1 は %2 に注釈をつけた (%3)。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="353"/>
|
<location filename="../src/messagelogwidget.cpp" line="353"/>
|
||||||
<source>%1 is looking at %2.</source>
|
<source>%1 is looking at %2.</source>
|
||||||
<translation>%1は%2を見ている。</translation>
|
<translation>%1 は%2を見ている。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="357"/>
|
<location filename="../src/messagelogwidget.cpp" line="357"/>
|
||||||
<source>%1 is looking at the top %2 card(s) %3.</source>
|
<source>%1 is looking at the top %2 card(s) %3.</source>
|
||||||
<translation>%1は%3上から%2枚のカードを見ている。</translation>
|
<translation>%1 は%3上から%2枚のカードを見ている。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="736"/>
|
<location filename="../src/messagelogwidget.cpp" line="736"/>
|
||||||
<source>%1 stops looking at %2.</source>
|
<source>%1 stops looking at %2.</source>
|
||||||
<translation>%1は%2を見るのをやめた。</translation>
|
<translation>%1 は%2を見るのをやめた。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="479"/>
|
<location filename="../src/messagelogwidget.cpp" line="479"/>
|
||||||
<source>%1 reveals %2 to %3.</source>
|
<source>%1 reveals %2 to %3.</source>
|
||||||
<translation>%1は、%3に%2を見せた。</translation>
|
<translation>%1 は %3 に%2を見せた。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="484"/>
|
<location filename="../src/messagelogwidget.cpp" line="484"/>
|
||||||
<source>%1 reveals %2.</source>
|
<source>%1 reveals %2.</source>
|
||||||
<translation>%1は%2を公開した。</translation>
|
<translation>%1 は%2を公開した。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="489"/>
|
<location filename="../src/messagelogwidget.cpp" line="489"/>
|
||||||
<source>%1 randomly reveals %2%3 to %4.</source>
|
<source>%1 randomly reveals %2%3 to %4.</source>
|
||||||
<translation>%1は%3無作為に《%2》を選び、%4に見せた。</translation>
|
<translation>%1 は%3無作為に %2 を選び、%4に見せた。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="496"/>
|
<location filename="../src/messagelogwidget.cpp" line="496"/>
|
||||||
<source>%1 randomly reveals %2%3.</source>
|
<source>%1 randomly reveals %2%3.</source>
|
||||||
<translation>%1は%3無作為に《%2》を選び、公開した。</translation>
|
<translation>%1 は%3無作為に %2 を選び、公開した。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="501"/>
|
<location filename="../src/messagelogwidget.cpp" line="501"/>
|
||||||
<source>%1 peeks at face down card #%2.</source>
|
<source>%1 peeks at face down card #%2.</source>
|
||||||
<translation>%1は裏向きのカード#%2の表面を確認した。</translation>
|
<translation>%1 は裏向きのカード#%2の表面を確認した。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="503"/>
|
<location filename="../src/messagelogwidget.cpp" line="503"/>
|
||||||
<source>%1 peeks at face down card #%2: %3.</source>
|
<source>%1 peeks at face down card #%2: %3.</source>
|
||||||
<translation>%1は裏向きのカード#%2の表面を確認した (《%3》) 。</translation>
|
<translation>%1 は裏向きのカード#%2の表面を確認した ( %3 ) 。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="508"/>
|
<location filename="../src/messagelogwidget.cpp" line="508"/>
|
||||||
<source>%1 reveals %2%3 to %4.</source>
|
<source>%1 reveals %2%3 to %4.</source>
|
||||||
<translation>%1は%3《%2》を%4に見せた。</translation>
|
<translation>%1 は%3 %2 を %4 に見せた。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/messagelogwidget.cpp" line="515"/>
|
<location filename="../src/messagelogwidget.cpp" line="515"/>
|
||||||
<source>%1 reveals %2%3.</source>
|
<source>%1 reveals %2%3.</source>
|
||||||
<translation>%1は%3《%2》を公開した</translation>
|
<translation>%1 は%3 %2 を公開した。</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
|
|
@ -3515,7 +3515,7 @@ Cockatrice will now reload the card database.</source>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/player.cpp" line="617"/>
|
<location filename="../src/player.cpp" line="617"/>
|
||||||
<source>Player "%1"</source>
|
<source>Player "%1"</source>
|
||||||
<translation>プレイヤー "%1"</translation>
|
<translation>プレイヤー: %1</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/player.cpp" line="618"/>
|
<location filename="../src/player.cpp" line="618"/>
|
||||||
|
|
@ -3836,7 +3836,7 @@ Cockatrice will now reload the card database.</source>
|
||||||
<location filename="../src/player.cpp" line="1085"/>
|
<location filename="../src/player.cpp" line="1085"/>
|
||||||
<location filename="../src/player.cpp" line="2877"/>
|
<location filename="../src/player.cpp" line="2877"/>
|
||||||
<source>C&reate another %1 token</source>
|
<source>C&reate another %1 token</source>
|
||||||
<translation>別の%1トークンを出す</translation>
|
<translation>別の %1 トークンを出す</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/player.cpp" line="1228"/>
|
<location filename="../src/player.cpp" line="1228"/>
|
||||||
|
|
@ -4274,7 +4274,7 @@ Please check your shortcut settings!</source>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/spoilerbackgroundupdater.cpp" line="99"/>
|
<location filename="../src/spoilerbackgroundupdater.cpp" line="99"/>
|
||||||
<source>Spoilers season has ended</source>
|
<source>Spoilers season has ended</source>
|
||||||
<translation type="unfinished"/>
|
<translation>スポイラーシーズンが終了しました</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/spoilerbackgroundupdater.cpp" line="99"/>
|
<location filename="../src/spoilerbackgroundupdater.cpp" line="99"/>
|
||||||
|
|
@ -5063,7 +5063,7 @@ The more information you put in, the more specific your results will be.</source
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/tab_message.cpp" line="66"/>
|
<location filename="../src/tab_message.cpp" line="66"/>
|
||||||
<source>Private &chat</source>
|
<source>Private &chat</source>
|
||||||
<translation>プライベートチャット</translation>
|
<translation>個人チャット</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/tab_message.cpp" line="67"/>
|
<location filename="../src/tab_message.cpp" line="67"/>
|
||||||
|
|
@ -5073,7 +5073,7 @@ The more information you put in, the more specific your results will be.</source
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/tab_message.cpp" line="83"/>
|
<location filename="../src/tab_message.cpp" line="83"/>
|
||||||
<source>%1 - Private chat</source>
|
<source>%1 - Private chat</source>
|
||||||
<translation>%1 - プライベートチャット</translation>
|
<translation>%1 - 個人チャット</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/tab_message.cpp" line="110"/>
|
<location filename="../src/tab_message.cpp" line="110"/>
|
||||||
|
|
@ -5893,17 +5893,17 @@ Please refrain from engaging in this activity or further actions may be taken ag
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/window_sets.cpp" line="139"/>
|
<location filename="../src/window_sets.cpp" line="139"/>
|
||||||
<source>Warning: </source>
|
<source>Warning: </source>
|
||||||
<translation type="unfinished"/>
|
<translation>警告:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/window_sets.cpp" line="140"/>
|
<location filename="../src/window_sets.cpp" line="140"/>
|
||||||
<source>While the set list is sorted by any of the columns, custom art priority setting is disabled.</source>
|
<source>While the set list is sorted by any of the columns, custom art priority setting is disabled.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>セットリストがいずれかの列でソートされている間、セット読み込み順の優先度設定は無効です。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/window_sets.cpp" line="141"/>
|
<location filename="../src/window_sets.cpp" line="141"/>
|
||||||
<source>To disable sorting click on the same column header again until this message disappears.</source>
|
<source>To disable sorting click on the same column header again until this message disappears.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>このメッセージが消えるまで同じ列見出しをクリックし続けると、ソートを無効にすることができます。</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/window_sets.cpp" line="170"/>
|
<location filename="../src/window_sets.cpp" line="170"/>
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -26,6 +26,7 @@ SET(common_SOURCES
|
||||||
server_room.cpp
|
server_room.cpp
|
||||||
serverinfo_user_container.cpp
|
serverinfo_user_container.cpp
|
||||||
sfmt/SFMT.c
|
sfmt/SFMT.c
|
||||||
|
expression.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(ORACLE_LIBS)
|
set(ORACLE_LIBS)
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,17 @@
|
||||||
#include <QCryptographicHash>
|
#include <QCryptographicHash>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
#include <QRegularExpression>
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
|
|
||||||
|
#if QT_VERSION < 0x050600
|
||||||
|
// qHash on QRegularExpression was added in 5.6, FIX IT
|
||||||
|
uint qHash(const QRegularExpression &key, uint seed) noexcept
|
||||||
|
{
|
||||||
|
return qHash(key.pattern(), seed); // call qHash on pattern QString instead
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
SideboardPlan::SideboardPlan(const QString &_name, const QList<MoveCard_ToZone> &_moveList)
|
SideboardPlan::SideboardPlan(const QString &_name, const QList<MoveCard_ToZone> &_moveList)
|
||||||
: name(_name), moveList(_moveList)
|
: name(_name), moveList(_moveList)
|
||||||
{
|
{
|
||||||
|
|
@ -477,161 +486,131 @@ bool DeckList::saveToFile_Native(QIODevice *device)
|
||||||
|
|
||||||
bool DeckList::loadFromStream_Plain(QTextStream &in)
|
bool DeckList::loadFromStream_Plain(QTextStream &in)
|
||||||
{
|
{
|
||||||
|
const QRegularExpression reCardLine("^\\s*[\\w\\[\\(\\{].*$", QRegularExpression::UseUnicodePropertiesOption);
|
||||||
|
const QRegularExpression reEmpty("^\\s*$");
|
||||||
|
const QRegularExpression reComment("[\\w\\[\\(\\{].*$", QRegularExpression::UseUnicodePropertiesOption);
|
||||||
|
const QRegularExpression reSBMark("^\\s*sb:\\s*(.+)", QRegularExpression::CaseInsensitiveOption);
|
||||||
|
const QRegularExpression reSBComment("sideboard", QRegularExpression::CaseInsensitiveOption);
|
||||||
|
|
||||||
|
// simplified matches
|
||||||
|
const QRegularExpression reMultiplier("^[xX\\(\\[]*(\\d+)[xX\\*\\)\\]]* ?(.+)");
|
||||||
|
const QRegularExpression reBrace(" ?[\\[\\{][^\\]\\}]*[\\]\\}] ?"); // not nested
|
||||||
|
const QRegularExpression reRoundBrace("^\\([^\\)]*\\) ?"); // () are only matched at start of string
|
||||||
|
const QRegularExpression reDigitBrace(" ?\\(\\d*\\) ?"); // () are matched if containing digits
|
||||||
|
const QHash<QRegularExpression, QString> differences{{QRegularExpression("’"), QString("'")},
|
||||||
|
{QRegularExpression("Æ"), QString("Ae")},
|
||||||
|
{QRegularExpression("æ"), QString("ae")},
|
||||||
|
{QRegularExpression(" ?[|/]+ ?"), QString(" // ")},
|
||||||
|
{QRegularExpression("(?<![A-Z]) ?& ?"), QString(" // ")}};
|
||||||
|
|
||||||
cleanList();
|
cleanList();
|
||||||
QVector<QString> inputs; // QTextStream -> QVector
|
|
||||||
|
|
||||||
bool priorEntryIsBlank = true, isAtBeginning = true;
|
QStringList inputs = in.readAll().trimmed().split('\n');
|
||||||
int blankLines = 0;
|
int max_line = inputs.size();
|
||||||
while (!in.atEnd()) {
|
|
||||||
QString line = in.readLine().simplified().toLower();
|
|
||||||
|
|
||||||
/*
|
// start at the first empty line before the first cardline
|
||||||
* Removes all blank lines at start of inputs
|
int deckStart = inputs.indexOf(reCardLine);
|
||||||
* Ex: ("", "", "", "Card1", "Card2") => ("Card1", "Card2")
|
if (deckStart == -1) { // there are no cards?
|
||||||
*
|
if (inputs.indexOf(reComment) == -1)
|
||||||
* This will also concise multiple blank lines in a row to just one blank
|
return false; // input is empty
|
||||||
* Ex: ("Card1", "Card2", "", "", "", "Card3") => ("Card1", "Card2", "", "Card3")
|
deckStart = max_line;
|
||||||
*/
|
} else {
|
||||||
if (line.isEmpty()) {
|
deckStart = inputs.lastIndexOf(reEmpty, deckStart);
|
||||||
if (priorEntryIsBlank || isAtBeginning) {
|
if (deckStart == -1) {
|
||||||
continue;
|
deckStart = 0;
|
||||||
}
|
|
||||||
|
|
||||||
priorEntryIsBlank = true;
|
|
||||||
blankLines++;
|
|
||||||
} else {
|
|
||||||
isAtBeginning = false;
|
|
||||||
priorEntryIsBlank = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inputs.push_back(line);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// find sideboard position, if marks are used this won't be needed
|
||||||
* Removes blank line at end of inputs (if applicable)
|
int sBStart = -1;
|
||||||
* Ex: ("Card1", "Card2", "") => ("Card1", "Card2")
|
if (inputs.indexOf(reSBMark, deckStart) == -1) {
|
||||||
* NOTE: Any duplicates were taken care of above, so there can be
|
sBStart = inputs.indexOf(reSBComment, deckStart);
|
||||||
* at most one blank line at the very end
|
if (sBStart == -1) {
|
||||||
*/
|
sBStart = inputs.indexOf(reEmpty, deckStart + 1);
|
||||||
if (!inputs.empty() && inputs.last().isEmpty()) {
|
if (sBStart == -1) {
|
||||||
blankLines--;
|
sBStart = max_line;
|
||||||
inputs.erase(inputs.end() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If "Sideboard" line appears in inputs, then blank lines mean nothing
|
|
||||||
if (inputs.contains("sideboard")) {
|
|
||||||
blankLines = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool inSideboard = false, titleFound = false, isSideboard;
|
|
||||||
int okRows = 0;
|
|
||||||
|
|
||||||
foreach (QString line, inputs) {
|
|
||||||
// This is a comment line, ignore it
|
|
||||||
if (line.startsWith("//")) {
|
|
||||||
if (!titleFound) // Set the title to the first comment
|
|
||||||
{
|
|
||||||
name = line.mid(2).trimmed();
|
|
||||||
titleFound = true;
|
|
||||||
} else if (okRows == 0) // We haven't processed any cards yet
|
|
||||||
{
|
|
||||||
comments += line.mid(2).trimmed() + "\n";
|
|
||||||
}
|
}
|
||||||
|
int nextCard = inputs.indexOf(reCardLine, sBStart + 1);
|
||||||
|
if (inputs.indexOf(reEmpty, nextCard + 1) != -1) {
|
||||||
|
sBStart = max_line; // if there is another empty line all cards are mainboard
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
QRegularExpressionMatch match;
|
||||||
|
|
||||||
|
// parse name and comments
|
||||||
|
while (index < deckStart) {
|
||||||
|
const QString current = inputs.at(index++);
|
||||||
|
if (!current.contains(reEmpty)) {
|
||||||
|
match = reComment.match(current);
|
||||||
|
name = match.captured();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (index < deckStart) {
|
||||||
|
const QString current = inputs.at(index++);
|
||||||
|
if (!current.contains(reEmpty)) {
|
||||||
|
match = reComment.match(current);
|
||||||
|
comments += match.captured() + '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
comments.chop(1); // remove last newline
|
||||||
|
|
||||||
|
// parse decklist
|
||||||
|
for (; index < max_line; ++index) {
|
||||||
|
|
||||||
|
// check if line is a card
|
||||||
|
match = reCardLine.match(inputs.at(index));
|
||||||
|
if (!match.hasMatch())
|
||||||
continue;
|
continue;
|
||||||
}
|
QString cardName = match.captured().simplified();
|
||||||
|
|
||||||
// If we have a blank line and it's the _ONLY_ blank line in the paste
|
// check if card should be sideboard
|
||||||
// and it follows at least one valid card
|
bool sideboard = false;
|
||||||
// Then we assume it means to start the sideboard section of the paste.
|
if (sBStart < 0) {
|
||||||
// If we have the word "Sideboard" appear on any line, then that will
|
match = reSBMark.match(cardName);
|
||||||
// also indicate the start of the sideboard.
|
if (match.hasMatch()) {
|
||||||
if ((line.isEmpty() && blankLines == 1 && okRows > 0) || line.startsWith("sideboard")) {
|
sideboard = true;
|
||||||
inSideboard = true;
|
cardName = match.captured(1);
|
||||||
continue; // The line isn't actually a card
|
|
||||||
}
|
|
||||||
|
|
||||||
isSideboard = inSideboard;
|
|
||||||
|
|
||||||
if (line.startsWith("sb:")) {
|
|
||||||
line = line.mid(3).trimmed();
|
|
||||||
isSideboard = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (line.trimmed().isEmpty()) {
|
|
||||||
continue; // The line was " " instead of "\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter out MWS edition symbols and basic land extras
|
|
||||||
QRegExp rx("\\[.*\\]\\s?");
|
|
||||||
line.remove(rx);
|
|
||||||
rx.setPattern("\\s?\\(.*\\)");
|
|
||||||
line.remove(rx);
|
|
||||||
|
|
||||||
// Filter out post card name editions
|
|
||||||
rx.setPattern("\\|.*$");
|
|
||||||
line.remove(rx);
|
|
||||||
|
|
||||||
// If the user inputs "Quicksilver Elemental" then it will cut it off
|
|
||||||
// 1x Squishy Treaker
|
|
||||||
int i = line.indexOf(' ');
|
|
||||||
int cardNameStart = i + 1;
|
|
||||||
|
|
||||||
if (i > 0) {
|
|
||||||
// If the count ends with an 'x', ignore it. For example,
|
|
||||||
// "4x Storm Crow" will count 4 correctly.
|
|
||||||
if (line.at(i - 1) == 'x') {
|
|
||||||
i--;
|
|
||||||
} else if (!line.at(i - 1).isDigit()) {
|
|
||||||
// If the user inputs "Quicksilver Elemental" then it will work as 1x of that card
|
|
||||||
cardNameStart = 0;
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (index == sBStart) // skip sideboard line itself
|
||||||
|
continue;
|
||||||
|
sideboard = index > sBStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ok;
|
// check if a specific amount is mentioned
|
||||||
int number = line.left(i).toInt(&ok);
|
int amount = 1;
|
||||||
|
match = reMultiplier.match(cardName);
|
||||||
if (!ok) {
|
if (match.hasMatch()) {
|
||||||
number = 1; // If input is "cardName" assume it's "1x cardName"
|
amount = match.capturedRef(1).toInt();
|
||||||
|
cardName = match.captured(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString cardName = line.mid(cardNameStart);
|
// remove stuff inbetween braces
|
||||||
|
cardName.remove(reBrace);
|
||||||
|
cardName.remove(reRoundBrace); // I'll be entirely honest here, these are split to accommodate just three cards
|
||||||
|
cardName.remove(reDigitBrace); // all cards from un-sets that have a word in between round braces at the end
|
||||||
|
|
||||||
// Common differences between Cockatrice's card names
|
// replace common differences in cardnames
|
||||||
// and what's commonly used in decklists
|
for (auto diff = differences.constBegin(); diff != differences.constEnd(); ++diff) {
|
||||||
rx.setPattern("’");
|
cardName.replace(diff.key(), diff.value());
|
||||||
cardName.replace(rx, "'");
|
|
||||||
rx.setPattern("Æ");
|
|
||||||
cardName.replace(rx, "Ae");
|
|
||||||
rx.setPattern("\\s*[|/]{1,2}\\s*");
|
|
||||||
cardName.replace(rx, " // ");
|
|
||||||
|
|
||||||
// Replace only if the ampersand is preceded by a non-capital letter,
|
|
||||||
// as would happen with acronyms. So 'Fire & Ice' is replaced but not
|
|
||||||
// 'R&D' or 'R & D'.
|
|
||||||
// Qt regexes don't support lookbehind so we capture and replace instead.
|
|
||||||
rx.setPattern("([^A-Z])\\s*&\\s*");
|
|
||||||
if (rx.indexIn(cardName) != -1) {
|
|
||||||
cardName.replace(rx, QString("%1 // ").arg(rx.cap(1)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to get the name of the card from the database,
|
// get cardname, this function does nothing if the name is not found
|
||||||
// but we can't do that until we get the "real" name
|
|
||||||
// (name stored in database for the card)
|
|
||||||
// and establish a card info that is of the card, then it's
|
|
||||||
// a simple getting the _real_ name of the card
|
|
||||||
// (i.e. "STOrm, CrOW" => "Storm Crow")
|
|
||||||
cardName = getCompleteCardName(cardName);
|
cardName = getCompleteCardName(cardName);
|
||||||
|
|
||||||
// Look for the correct card zone of where to place the new card
|
// get zone name based on if it's in sideboard
|
||||||
QString zoneName = getCardZoneFromName(cardName, isSideboard ? DECK_ZONE_SIDE : DECK_ZONE_MAIN);
|
QString zoneName = getCardZoneFromName(cardName, sideboard ? DECK_ZONE_SIDE : DECK_ZONE_MAIN);
|
||||||
|
|
||||||
okRows++;
|
// make new entry in decklist
|
||||||
new DecklistCardNode(cardName, number, getZoneObjFromName(zoneName));
|
new DecklistCardNode(cardName, amount, getZoneObjFromName(zoneName));
|
||||||
}
|
}
|
||||||
|
|
||||||
updateDeckHash();
|
updateDeckHash();
|
||||||
return (okRows > 0);
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
InnerDecklistNode *DeckList::getZoneObjFromName(const QString zoneName)
|
InnerDecklistNode *DeckList::getZoneObjFromName(const QString zoneName)
|
||||||
|
|
|
||||||
108
common/expression.cpp
Normal file
108
common/expression.cpp
Normal file
|
|
@ -0,0 +1,108 @@
|
||||||
|
#include "expression.h"
|
||||||
|
#include "./lib/peglib.h"
|
||||||
|
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QString>
|
||||||
|
#include <cmath>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
peg::parser math(R"(
|
||||||
|
EXPRESSION <- P0
|
||||||
|
P0 <- P1 (P1_OPERATOR P1)*
|
||||||
|
P1 <- P2 (P2_OPERATOR P2)*
|
||||||
|
P2 <- P3 (P3_OPERATOR P3)*
|
||||||
|
P3 <- NUMBER / FUNCTION / VARIABLE / '(' P0 ')'
|
||||||
|
|
||||||
|
P1_OPERATOR <- < [-+] >
|
||||||
|
P2_OPERATOR <- < [/*] >
|
||||||
|
P3_OPERATOR <- < '^' >
|
||||||
|
|
||||||
|
NUMBER <- < '-'? [0-9]+ >
|
||||||
|
NAME <- < [a-z][a-z0-9]* >
|
||||||
|
VARIABLE <- < [x] >
|
||||||
|
FUNCTION <- NAME '(' EXPRESSION ( [,\n] EXPRESSION )* ')'
|
||||||
|
|
||||||
|
%whitespace <- [ \t\r]*
|
||||||
|
)");
|
||||||
|
|
||||||
|
QMap<QString, std::function<double(double)>> *default_functions = nullptr;
|
||||||
|
|
||||||
|
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 abs(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); });
|
||||||
|
}
|
||||||
|
fns = QMap<QString, std::function<double(double)>>(*default_functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
double Expression::eval(const peg::Ast &ast)
|
||||||
|
{
|
||||||
|
const auto &nodes = ast.nodes;
|
||||||
|
if (ast.name == "NUMBER") {
|
||||||
|
return stod(ast.token);
|
||||||
|
} else if (ast.name == "FUNCTION") {
|
||||||
|
QString name = QString::fromStdString(nodes[0]->token);
|
||||||
|
if (!fns.contains(name))
|
||||||
|
return 0;
|
||||||
|
return fns[name](eval(*nodes[1]));
|
||||||
|
} else if (ast.name == "VARIABLE") {
|
||||||
|
return value;
|
||||||
|
} else if (ast.name[0] == 'P') {
|
||||||
|
double result = eval(*nodes[0]);
|
||||||
|
for (int i = 1; i < nodes.size(); i += 2) {
|
||||||
|
double arg = eval(*nodes[i + 1]);
|
||||||
|
char operation = nodes[i]->token[0];
|
||||||
|
switch (operation) {
|
||||||
|
case '+':
|
||||||
|
result += arg;
|
||||||
|
break;
|
||||||
|
case '-':
|
||||||
|
result -= arg;
|
||||||
|
break;
|
||||||
|
case '*':
|
||||||
|
result *= arg;
|
||||||
|
break;
|
||||||
|
case '/':
|
||||||
|
result /= arg;
|
||||||
|
break;
|
||||||
|
case '^':
|
||||||
|
result = pow(result, arg);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
result = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double Expression::parse(const QString &expr)
|
||||||
|
{
|
||||||
|
QByteArray ba = expr.toLocal8Bit();
|
||||||
|
|
||||||
|
math.enable_ast();
|
||||||
|
|
||||||
|
std::shared_ptr<peg::Ast> ast;
|
||||||
|
if (math.parse(ba.data(), ast)) {
|
||||||
|
ast = peg::AstOptimizer(true).optimize(ast);
|
||||||
|
return eval(*ast);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
28
common/expression.h
Normal file
28
common/expression.h
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
#ifndef EXPRESSION_H
|
||||||
|
#define EXPRESSION_H
|
||||||
|
|
||||||
|
#include <QMap>
|
||||||
|
#include <QString>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
namespace peg
|
||||||
|
{
|
||||||
|
template <typename Annotation> struct AstBase;
|
||||||
|
struct EmptyType;
|
||||||
|
typedef AstBase<EmptyType> Ast;
|
||||||
|
} // namespace peg
|
||||||
|
|
||||||
|
class Expression
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
double value;
|
||||||
|
|
||||||
|
explicit Expression(double initial = 0);
|
||||||
|
double parse(const QString &expr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
double eval(const peg::Ast &ast);
|
||||||
|
QMap<QString, std::function<double(double)>> fns;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
3293
common/lib/peglib.h
Normal file
3293
common/lib/peglib.h
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -169,3 +169,12 @@ if (UNIX)
|
||||||
set(cockatrice_protocol_LIBS ${cockatrice_protocol_LIBS} -lpthread)
|
set(cockatrice_protocol_LIBS ${cockatrice_protocol_LIBS} -lpthread)
|
||||||
endif (UNIX)
|
endif (UNIX)
|
||||||
target_link_libraries(cockatrice_protocol ${cockatrice_protocol_LIBS})
|
target_link_libraries(cockatrice_protocol ${cockatrice_protocol_LIBS})
|
||||||
|
|
||||||
|
# ubuntu uses an outdated package for protobuf, 3.1.0 is required
|
||||||
|
if(${Protobuf_VERSION} VERSION_LESS "3.1.0")
|
||||||
|
# remove unused parameter and misleading indentation warnings when compiling to avoid errors
|
||||||
|
set(CMAKE_CXX_FLAGS_DEBUG
|
||||||
|
"${CMAKE_CXX_FLAGS_DEBUG} -Wno-unused-parameter -Wno-misleading-indentation")
|
||||||
|
message(WARNING "Outdated protobuf version found (${Protobuf_VERSION} < 3.1.0), "
|
||||||
|
"disabled warnings to avoid compilation errors.")
|
||||||
|
endif()
|
||||||
|
|
|
||||||
|
|
@ -5,3 +5,10 @@ message Command_Concede {
|
||||||
optional Command_Concede ext = 1017;
|
optional Command_Concede ext = 1017;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
message Command_Unconcede {
|
||||||
|
extend GameCommand {
|
||||||
|
optional Command_Unconcede ext = 1032;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,3 +6,9 @@ message Context_Concede {
|
||||||
optional Context_Concede ext = 1001;
|
optional Context_Concede ext = 1001;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message Context_Unconcede {
|
||||||
|
extend GameEventContext {
|
||||||
|
optional Context_Unconcede ext = 1009;
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue