Merge branch 'master' into mod_notify_onbanwarn
This commit is contained in:
commit
3ed3919349
60 changed files with 2474 additions and 1644 deletions
44
.travis.yml
44
.travis.yml
|
@ -1,13 +1,27 @@
|
||||||
language: cpp
|
language: cpp
|
||||||
env:
|
matrix:
|
||||||
- QT4=1
|
fast_finish: true
|
||||||
- QT4=0
|
include:
|
||||||
os:
|
# linux precise debug build, precise + gcc + qt4
|
||||||
- linux
|
- os: linux
|
||||||
- osx
|
env: QT4=1 BUILDTYPE=Debug DIST=precise
|
||||||
compiler:
|
# linux debug build, trusty + gcc + qt5
|
||||||
- gcc
|
- os: linux
|
||||||
- clang
|
dist: trusty
|
||||||
|
env: QT4=0 BUILDTYPE=Debug DIST=trusty
|
||||||
|
# osx debug build, osx + clang + qt5
|
||||||
|
- os: osx
|
||||||
|
env: QT4=0 BUILDTYPE=Debug
|
||||||
|
# linux precise release build, precise + gcc + qt4
|
||||||
|
- os: linux
|
||||||
|
env: QT4=1 BUILDTYPE=Release DIST=precise
|
||||||
|
# linux trusty release build, precise + gcc + qt5
|
||||||
|
- os: linux
|
||||||
|
dist: trusty
|
||||||
|
env: QT4=0 BUILDTYPE=Release DIST=trusty
|
||||||
|
# osx release build, osx + gcc + qt5
|
||||||
|
- os: osx
|
||||||
|
env: QT4=0 BUILDTYPE=Release
|
||||||
script: ./travis-compile.sh
|
script: ./travis-compile.sh
|
||||||
install: ./travis-dependencies.sh
|
install: ./travis-dependencies.sh
|
||||||
cache: apt
|
cache: apt
|
||||||
|
@ -18,6 +32,12 @@ notifications:
|
||||||
- https://webhooks.gitter.im/e/d94969c3b01b22cbdcb7
|
- https://webhooks.gitter.im/e/d94969c3b01b22cbdcb7
|
||||||
on_success: change
|
on_success: change
|
||||||
on_failure: change
|
on_failure: change
|
||||||
on_start: false
|
on_start: never
|
||||||
matrix:
|
deploy:
|
||||||
fast_finish: true
|
provider: bintray
|
||||||
|
file: "build/bintray_deploy.json"
|
||||||
|
user: "ctrlaltca"
|
||||||
|
key:
|
||||||
|
secure: DtVeeLoi5fZG/RvLTecRnRQGW9fVNS4Oa5iut2vJa14PdKBAJiXACQ0EzcRJFsbtby7MyMc2IVtT5skpvsaSqkpaxoBaL1YtKwJ4CTkYcm2MDWHS7UlijuxxTjI6BnaL3lcCCIeG+NHBZa3dV2YNJ1sWv6Xmiiix1ujPPW8VtnM=
|
||||||
|
on:
|
||||||
|
condition: $BUILDTYPE = Release
|
|
@ -19,6 +19,10 @@ if(POLICY CMP0048)
|
||||||
cmake_policy(SET CMP0048 OLD)
|
cmake_policy(SET CMP0048 OLD)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(POLICY CMP0064)
|
||||||
|
cmake_policy(SET CMP0064 OLD)
|
||||||
|
endif()
|
||||||
|
|
||||||
set(PROJECT_NAME "Cockatrice")
|
set(PROJECT_NAME "Cockatrice")
|
||||||
|
|
||||||
# Default to "Release" build type
|
# Default to "Release" build type
|
||||||
|
@ -71,7 +75,7 @@ endif()
|
||||||
IF(MSVC)
|
IF(MSVC)
|
||||||
# Visual Studio:
|
# Visual Studio:
|
||||||
# Maximum optimization
|
# Maximum optimization
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "/Ox")
|
set(CMAKE_CXX_FLAGS_RELEASE "/Ox /MD")
|
||||||
# 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)
|
||||||
|
@ -104,7 +108,7 @@ ENDIF()
|
||||||
# Default is Qt5 unless WITH_QT4 option is enabled
|
# Default is Qt5 unless WITH_QT4 option is enabled
|
||||||
option(WITH_QT4 "Force the use of Qt4 libraries" OFF)
|
option(WITH_QT4 "Force the use of Qt4 libraries" OFF)
|
||||||
OPTION(UPDATE_TRANSLATIONS "Update translations on compile" OFF)
|
OPTION(UPDATE_TRANSLATIONS "Update translations on compile" OFF)
|
||||||
MESSAGE("UPDATE TRANSLATIONS: ${UPDATE_TRANSLATIONS}")
|
MESSAGE(STATUS "UPDATE TRANSLATIONS: ${UPDATE_TRANSLATIONS}")
|
||||||
|
|
||||||
IF(NOT WITH_QT4)
|
IF(NOT WITH_QT4)
|
||||||
# First known not-broken Qt5 version (5.0.2 available on old ubuntus is buggy).
|
# First known not-broken Qt5 version (5.0.2 available on old ubuntus is buggy).
|
||||||
|
@ -174,11 +178,6 @@ set(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}")
|
||||||
set(CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}")
|
set(CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}")
|
||||||
set(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}")
|
set(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}")
|
||||||
|
|
||||||
# Create a version string suitable for file names
|
|
||||||
string(REPLACE " " "_" PROJECT_VERSION_SAFE "${PROJECT_VERSION}")
|
|
||||||
string(REPLACE "(" "" PROJECT_VERSION_SAFE "${PROJECT_VERSION_SAFE}")
|
|
||||||
string(REPLACE ")" "" PROJECT_VERSION_SAFE "${PROJECT_VERSION_SAFE}")
|
|
||||||
|
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
set(CPACK_GENERATOR DragNDrop ${CPACK_GENERATOR})
|
set(CPACK_GENERATOR DragNDrop ${CPACK_GENERATOR})
|
||||||
|
@ -186,18 +185,22 @@ if(UNIX)
|
||||||
set(CPACK_DMG_FORMAT "UDBZ")
|
set(CPACK_DMG_FORMAT "UDBZ")
|
||||||
set(CPACK_DMG_VOLUME_NAME "${PROJECT_NAME}")
|
set(CPACK_DMG_VOLUME_NAME "${PROJECT_NAME}")
|
||||||
set(CPACK_SYSTEM_NAME "OSX")
|
set(CPACK_SYSTEM_NAME "OSX")
|
||||||
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-osx_git-${PROJECT_VERSION_SAFE}")
|
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}")
|
||||||
set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/cockatrice/resources/appicon.icns")
|
set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/cockatrice/resources/appicon.icns")
|
||||||
else()
|
else()
|
||||||
# linux
|
# linux
|
||||||
set(CPACK_GENERATOR DEB ${CPACK_GENERATOR})
|
set(CPACK_GENERATOR DEB ${CPACK_GENERATOR})
|
||||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "${PROJECT_NAME}/${PROJECT_VERSION_SAFE}")
|
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}")
|
||||||
set(CPACK_STRIP_FILES "bin/${PROJECT_NAME}")
|
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
|
||||||
set(CPACK_SOURCE_STRIP_FILES "")
|
set(CPACK_DEBIAN_PACKAGE_SECTION "games")
|
||||||
|
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "http://github.com/Cockatrice/Cockatrice")
|
||||||
|
IF(Qt5Widgets_FOUND)
|
||||||
|
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt5multimedia5-plugins")
|
||||||
|
ENDIF()
|
||||||
endif()
|
endif()
|
||||||
elseif(WIN32)
|
elseif(WIN32)
|
||||||
set(CPACK_GENERATOR NSIS ${CPACK_GENERATOR})
|
set(CPACK_GENERATOR NSIS ${CPACK_GENERATOR})
|
||||||
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}_win32_git-${PROJECT_VERSION_SAFE}")
|
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}")
|
||||||
|
|
||||||
# Configure file with custom definitions for NSIS.
|
# Configure file with custom definitions for NSIS.
|
||||||
configure_file(
|
configure_file(
|
||||||
|
@ -206,6 +209,12 @@ elseif(WIN32)
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Configure file with build deployment data for travis
|
||||||
|
configure_file(
|
||||||
|
${CMAKE_MODULE_PATH}/bintray_deploy.json.in
|
||||||
|
${PROJECT_BINARY_DIR}/bintray_deploy.json
|
||||||
|
)
|
||||||
|
|
||||||
include(CPack)
|
include(CPack)
|
||||||
|
|
||||||
# Compile servatrice (default off)
|
# Compile servatrice (default off)
|
||||||
|
@ -231,3 +240,10 @@ if(WITH_ORACLE)
|
||||||
add_subdirectory(oracle)
|
add_subdirectory(oracle)
|
||||||
SET(CPACK_INSTALL_CMAKE_PROJECTS "release/oracle.app;oracle;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
|
SET(CPACK_INSTALL_CMAKE_PROJECTS "release/oracle.app;oracle;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Compile tests (default off)
|
||||||
|
option(TEST "build tests" OFF)
|
||||||
|
if(TEST)
|
||||||
|
include(CTest)
|
||||||
|
add_subdirectory(tests)
|
||||||
|
endif()
|
||||||
|
|
35
README.md
35
README.md
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Table of Contents** [Cockatrice](#cockatrice) | [Get Involved] (#get-involved-) | [Community](#community-resources) | [Translation](#translation-status-) | [Building](#building-) | [Running](#running) | [License](#license-)
|
**Table of Contents** [Cockatrice](#cockatrice) | [Get Involved] (#get-involved-) | [Community](#community-resources) | [Translation](#translation-status-) | [Building](#building--) | [Running](#running) | [License](#license-)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -13,6 +13,12 @@ such as Magic: The Gathering, over a network. It is fully client-server based
|
||||||
to prevent any kind of cheating, though it supports single-player games without
|
to prevent any kind of cheating, though it supports single-player games without
|
||||||
a network interface as well. Both client and server are written in Qt, supporting both Qt4 and Qt5.<br>
|
a network interface as well. Both client and server are written in Qt, supporting both Qt4 and Qt5.<br>
|
||||||
|
|
||||||
|
# Downloads
|
||||||
|
We offer a download for both the last stable version (recommended for users) and the last development version. The development version contains the last implemented features, but can be unstable and unsuitable for gaming.
|
||||||
|
Downloads are hosted on [BinTray](https://bintray.com/).
|
||||||
|
|
||||||
|
- Latest stable version download: [  ](https://bintray.com/cockatrice/Cockatrice/Cockatrice/_latestVersion)
|
||||||
|
- Latest development (unstable) version download: [  ](https://bintray.com/cockatrice/Cockatrice/Cockatrice-git/_latestVersion)
|
||||||
|
|
||||||
# Get Involved [](https://gitter.im/Cockatrice/Cockatrice)
|
# Get Involved [](https://gitter.im/Cockatrice/Cockatrice)
|
||||||
|
|
||||||
|
@ -37,7 +43,7 @@ Language statistics for `Cockatrice` *(on the left)* and `Oracle` *(on the right
|
||||||
Check out our [Translator FAQ](https://github.com/Cockatrice/Cockatrice/wiki/Translation-FAQ) for more information!<br>
|
Check out our [Translator FAQ](https://github.com/Cockatrice/Cockatrice/wiki/Translation-FAQ) for more information!<br>
|
||||||
|
|
||||||
|
|
||||||
# Building [](https://travis-ci.org/Cockatrice/Cockatrice)
|
# Building [](https://travis-ci.org/Cockatrice/Cockatrice) [](https://ci.appveyor.com/project/Daenyth/cockatrice/branch/master)
|
||||||
|
|
||||||
**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)**
|
||||||
|
|
||||||
|
@ -59,17 +65,28 @@ To compile:
|
||||||
cd build
|
cd build
|
||||||
cmake ..
|
cmake ..
|
||||||
make
|
make
|
||||||
|
|
||||||
|
You can then run
|
||||||
|
|
||||||
make install
|
make install
|
||||||
|
|
||||||
|
to get a cockatrice installation inside the `release` folder, or:
|
||||||
|
|
||||||
|
make package
|
||||||
|
|
||||||
|
to create a system-specific installation package.
|
||||||
|
|
||||||
The following flags can be passed to `cmake`:
|
The following flags can be passed to `cmake`:
|
||||||
|
|
||||||
- `-DWITH_SERVER=1` Build the server.
|
- `-DWITH_SERVER=1` Whether to build the server (default 0 = no).
|
||||||
- `-DWITH_CLIENT=0` Do not build the client.
|
- `-DWITH_CLIENT=0` Whether to build the client (default 1 = yes).
|
||||||
- `-DWITH_ORACLE=0` Do not build oracle.
|
- `-DWITH_ORACLE=0` Whether to build oracle (default 1 = yes).
|
||||||
- `-DPORTABLE=1` Build portable versions of client & oracle.
|
- `-DPORTABLE=1` Build portable versions of client & oracle (default 0 = no).
|
||||||
- `-DWITH_QT4=1` Force compilation to use Qt4 instead of Qt5.
|
- `-DWITH_QT4=1` Force compilation to use Qt4 instead of Qt5 (default 0 = no).
|
||||||
- `-DCMAKE_BUILD_TYPE=Debug` Compile in debug mode. Enables extra logging output, debug symbols, and much more verbose compiler warnings.
|
- `-DCMAKE_BUILD_TYPE=Debug` Compile in debug mode. Enables extra logging output, debug symbols, and much more verbose compiler warnings (default `Release`).
|
||||||
- `-DUPDATE_TRANSLATIONS=1` Configure `make` to update the translation .ts files for new strings in the source code. Note: Running `make clean` will remove the .ts files.
|
- `-DUPDATE_TRANSLATIONS=1` Configure `make` to update the translation .ts files for new strings in the source code. Note: Running `make clean` will remove the .ts files (default 0 = no).
|
||||||
|
- `-DTEST=1` Enable regression tests (default 0 = no). Note: needs googletest, will be downloaded on the fly if unavailable. To run tests: ```make test```.
|
||||||
|
|
||||||
|
|
||||||
#### Building servatrice Docker container
|
#### Building servatrice Docker container
|
||||||
`docker build -t servatrice .`<br>
|
`docker build -t servatrice .`<br>
|
||||||
|
|
92
appveyor.yml
Normal file
92
appveyor.yml
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
version: 0.0.1-branch-{branch}-build-{build}
|
||||||
|
cache:
|
||||||
|
- c:\protobuf
|
||||||
|
- c:\protoc
|
||||||
|
- c:\zlib
|
||||||
|
environment:
|
||||||
|
matrix:
|
||||||
|
- vc_arch: amd64
|
||||||
|
choco_arch:
|
||||||
|
nuget_arch: x64
|
||||||
|
target_arch: x86_64
|
||||||
|
qt_ver: 5.5\msvc2013_64
|
||||||
|
bintray_path: Win64
|
||||||
|
- vc_arch: amd64_x86 # cross-compile from amd64 to x86
|
||||||
|
choco_arch: --x86
|
||||||
|
nuget_arch: Win32
|
||||||
|
target_arch: x86
|
||||||
|
qt_ver: 5.5\msvc2013
|
||||||
|
bintray_path: Win32
|
||||||
|
install:
|
||||||
|
- systeminfo
|
||||||
|
# upgrade cmake in order to have c++11 support
|
||||||
|
- choco install cmake -y
|
||||||
|
- choco install nsis -y
|
||||||
|
- ps: |
|
||||||
|
if (Test-Path c:\protoc) {
|
||||||
|
echo "using protoc from cache"
|
||||||
|
} else {
|
||||||
|
Invoke-WebRequest "https://github.com/google/protobuf/releases/download/v2.6.1/protoc-2.6.1-win32.zip" -OutFile c:\protoc-2.6.1-win32.zip
|
||||||
|
c:\cygwin\bin\bash -lc "cd /cygdrive/c; 7z x -y protoc-2.6.1-win32.zip -oc:\protoc"
|
||||||
|
}
|
||||||
|
- ps: |
|
||||||
|
if (Test-Path c:\protobuf) {
|
||||||
|
echo "using protobuf from cache"
|
||||||
|
} else {
|
||||||
|
nuget install protobuf-v120 -OutputDirectory c:\protobuf
|
||||||
|
}
|
||||||
|
- ps: |
|
||||||
|
if (Test-Path c:\zlib) {
|
||||||
|
echo "using zlib from cache"
|
||||||
|
} else {
|
||||||
|
nuget install zlib -OutputDirectory c:\zlib
|
||||||
|
}
|
||||||
|
build_script:
|
||||||
|
- mkdir build
|
||||||
|
- cd build
|
||||||
|
- '"c:/Program Files (x86)/Microsoft Visual Studio 12.0/VC/vcvarsall" %vc_arch%'
|
||||||
|
- path
|
||||||
|
- ps: |
|
||||||
|
$zlibinc = c:\cygwin\bin\find /cygdrive/c/zlib/ -path '*v120*/zlib.h'
|
||||||
|
$zlibinc = c:\cygwin\bin\dirname $zlibinc
|
||||||
|
$zlibinc = c:\cygwin\bin\cygpath -m $zlibinc
|
||||||
|
$zliblib = c:\cygwin\bin\find /cygdrive/c/zlib/ -path "*v120*/$env:nuget_arch/Release/zlib.lib"
|
||||||
|
$zliblib = c:\cygwin\bin\cygpath -m $zliblib
|
||||||
|
$protoinc = c:\cygwin\bin\find /cygdrive/c/protobuf/ -name 'google'
|
||||||
|
$protoinc = c:\cygwin\bin\dirname $protoinc
|
||||||
|
$protoinc = c:\cygwin\bin\cygpath -m $protoinc
|
||||||
|
$protolib = c:\cygwin\bin\find /cygdrive/c/protobuf/ -path "*/lib/$env:nuget_arch/v120/Release/libprotobuf.lib"
|
||||||
|
$protolib = c:\cygwin\bin\cygpath -m $protolib
|
||||||
|
$protoc = c:\cygwin\bin\find /cygdrive/c/protoc/ -name "protoc.exe"
|
||||||
|
$protoc = c:\cygwin\bin\cygpath -m $protoc
|
||||||
|
Write-Output "ZLIBINC = $zlibinc"
|
||||||
|
Write-Output "ZLIBLIB = $zliblib"
|
||||||
|
Write-Output "PROTOINC = $protoinc"
|
||||||
|
Write-Output "PROTOLIB = $protolib"
|
||||||
|
Write-Output "PROTOC = $protoc"
|
||||||
|
cmake .. "-GNMake Makefiles" "-DCMAKE_BUILD_TYPE=Release" "-DCMAKE_PREFIX_PATH=c:/Qt/$env:qt_ver" "-DWITH_SERVER=1" "-DZLIB_INCLUDE_DIR=$zlibinc" "-DZLIB_LIBRARY=$zliblib" "-DPROTOBUF_INCLUDE_DIR=$protoinc" "-DPROTOBUF_LIBRARIES=$protolib" "-DPROTOBUF_LIBRARIES=$protolib" "-DPROTOBUF_LIBRARY=$protolib" "-DPROTOBUF_PROTOC_EXECUTABLE=$protoc"
|
||||||
|
- nmake package
|
||||||
|
- c:\cygwin\bin\ls -l
|
||||||
|
- ps: |
|
||||||
|
$exe = dir -name *.exe
|
||||||
|
$new_name = $exe.Replace(".exe", "-${env:target_arch}_qt5.exe")
|
||||||
|
Push-AppveyorArtifact $exe -FileName $new_name
|
||||||
|
$cmake_name = $exe.Replace(".exe", "-${env:target_arch}_qt5.cmake.txt")
|
||||||
|
Push-AppveyorArtifact CMakeCache.txt -FileName $cmake_name
|
||||||
|
$json = New-Object PSObject
|
||||||
|
(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"
|
||||||
|
$bt_password = ConvertTo-SecureString $Env:BINTRAY_APIKEY -AsPlainText -Force
|
||||||
|
$bt_credentials = New-Object System.Management.Automation.PSCredential ($Env:BINTRAY_USER, $bt_password)
|
||||||
|
$exe -match "Cockatrice-(?<content>.*)\.exe"
|
||||||
|
$version = $matches['content']
|
||||||
|
$bt_headers = @{
|
||||||
|
"X-Bintray-Package" = "Cockatrice-git";
|
||||||
|
"X-Bintray-Version" = $version;
|
||||||
|
"X-Bintray-Publish" = 1;
|
||||||
|
"X-Bintray-Override" = 1;
|
||||||
|
}
|
||||||
|
$url = "https://api.bintray.com/content/cockatrice/Cockatrice/$env:bintray_path/$new_name"
|
||||||
|
$result = Invoke-WebRequest -Uri $url -Credential $bt_credentials -Method PUT -Headers $bt_headers -InFile "$exe"
|
||||||
|
Write-Host $result
|
||||||
|
test: off
|
28
cmake/bintray_deploy.json.in
Normal file
28
cmake/bintray_deploy.json.in
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
"package": {
|
||||||
|
"name": "Cockatrice-git",
|
||||||
|
"repo": "Cockatrice",
|
||||||
|
"subject": "cockatrice",
|
||||||
|
"desc": "Cockatrice master branch automated builds",
|
||||||
|
"website_url": "https://github.com/Cockatrice/Cockatrice",
|
||||||
|
"issue_tracker_url": "https://github.com/Cockatrice/Cockatrice/issues",
|
||||||
|
"vcs_url": "https://github.com/Cockatrice/Cockatrice.git",
|
||||||
|
"github_use_tag_release_notes": true,
|
||||||
|
"github_release_notes_file": "RELEASE.txt",
|
||||||
|
"licenses": ["GPL-2.0"],
|
||||||
|
"labels": ["card", "tabletop", "game"],
|
||||||
|
"public_download_numbers": false,
|
||||||
|
"public_stats": true
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"name": "@PROJECT_VERSION@",
|
||||||
|
"desc": "Unstable builds from master",
|
||||||
|
"vcs_tag": "@GIT_COMMIT_ID@",
|
||||||
|
"gpgSign": false
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
{ "includePattern": "build/(Cockatrice.*\\.deb)", "uploadPattern": "Ubuntu/$ENV{DIST}/$1" },
|
||||||
|
{ "includePattern": "build/(Cockatrice.*\\.dmg)", "uploadPattern": "MacOSX/$1" }
|
||||||
|
],
|
||||||
|
"publish": true
|
||||||
|
}
|
|
@ -3,7 +3,7 @@ set(VERSION_STRING_H "${PROJECT_BINARY_DIR}/version_string.h")
|
||||||
INCLUDE_DIRECTORIES(${PROJECT_BINARY_DIR})
|
INCLUDE_DIRECTORIES(${PROJECT_BINARY_DIR})
|
||||||
|
|
||||||
set( hstring "extern const char *VERSION_STRING\;\n" )
|
set( hstring "extern const char *VERSION_STRING\;\n" )
|
||||||
set( cppstring "const char * VERSION_STRING = \"${PROJECT_VERSION}\"\;\n")
|
set( cppstring "const char * VERSION_STRING = \"${PROJECT_VERSION_FRIENDLY}\"\;\n")
|
||||||
|
|
||||||
file(WRITE ${PROJECT_BINARY_DIR}/version_string.cpp.txt ${cppstring} )
|
file(WRITE ${PROJECT_BINARY_DIR}/version_string.cpp.txt ${cppstring} )
|
||||||
file(WRITE ${PROJECT_BINARY_DIR}/version_string.h.txt ${hstring} )
|
file(WRITE ${PROJECT_BINARY_DIR}/version_string.h.txt ${hstring} )
|
||||||
|
|
|
@ -1,20 +1,40 @@
|
||||||
find_package(Git)
|
find_package(Git)
|
||||||
if(GIT_FOUND)
|
if(GIT_FOUND)
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND ${GIT_EXECUTABLE} log -1 --date=short "--pretty=%h (%cd)"
|
COMMAND ${GIT_EXECUTABLE} log -1 --date=short "--pretty=%h"
|
||||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||||
RESULT_VARIABLE res_var
|
RESULT_VARIABLE res_var
|
||||||
OUTPUT_VARIABLE GIT_COM_ID
|
OUTPUT_VARIABLE GIT_COM_ID
|
||||||
)
|
)
|
||||||
if( NOT ${res_var} EQUAL 0 )
|
if( NOT ${res_var} EQUAL 0 )
|
||||||
set( GIT_COMMIT_ID "git commit id unknown")
|
set( GIT_COMMIT_ID "unknown")
|
||||||
message( WARNING "Git failed (not a repo, or no tags). Build will not contain git revision info." )
|
message( WARNING "Git failed (not a repo, or no tags). Build will not contain git revision info." )
|
||||||
endif()
|
endif()
|
||||||
string( REPLACE "\n" "" GIT_COMMIT_ID "${GIT_COM_ID}" )
|
string( REPLACE "\n" "" GIT_COMMIT_ID "${GIT_COM_ID}" )
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${GIT_EXECUTABLE} log -1 --date=short "--pretty=%cd"
|
||||||
|
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||||
|
RESULT_VARIABLE res_var
|
||||||
|
OUTPUT_VARIABLE GIT_COM_DATE
|
||||||
|
)
|
||||||
|
if( NOT ${res_var} EQUAL 0 )
|
||||||
|
set( GIT_COMMIT_DATE "unknown")
|
||||||
|
set( GIT_COMMIT_DATE_FRIENDLY "unknown")
|
||||||
|
message( WARNING "Git failed (not a repo, or no tags). Build will not contain git revision info." )
|
||||||
|
endif()
|
||||||
|
string( REPLACE "\n" "" GIT_COMMIT_DATE_FRIENDLY "${GIT_COM_DATE}" )
|
||||||
|
string( REPLACE "-" "" GIT_COMMIT_DATE "${GIT_COMMIT_DATE_FRIENDLY}" )
|
||||||
else()
|
else()
|
||||||
set( GIT_COMMIT_ID "unknown (git not found!)")
|
set( GIT_COMMIT_ID "unknown")
|
||||||
|
set( GIT_COMMIT_DATE "unknown")
|
||||||
|
set( GIT_COMMIT_DATE_FRIENDLY "unknown")
|
||||||
message( WARNING "Git not found. Build will not contain git revision info." )
|
message( WARNING "Git not found. Build will not contain git revision info." )
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(PROJECT_VERSION_MAJOR ${GIT_COMMIT_ID})
|
set(PROJECT_VERSION_MAJOR "0")
|
||||||
set(PROJECT_VERSION ${GIT_COMMIT_ID} )
|
set(PROJECT_VERSION_MINOR "0")
|
||||||
|
set(PROJECT_VERSION_PATCH "1~git${GIT_COMMIT_DATE}.${GIT_COMMIT_ID}")
|
||||||
|
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
|
||||||
|
set(PROJECT_VERSION_FRIENDLY "${GIT_COMMIT_ID} (${GIT_COMMIT_DATE_FRIENDLY})")
|
||||||
|
|
||||||
|
|
15
cmake/gtest-CMakeLists.txt.in
Normal file
15
cmake/gtest-CMakeLists.txt.in
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
cmake_minimum_required(VERSION 3.2)
|
||||||
|
|
||||||
|
project(gtest-download LANGUAGES NONE)
|
||||||
|
|
||||||
|
include(ExternalProject)
|
||||||
|
ExternalProject_Add(googletest
|
||||||
|
URL https://googletest.googlecode.com/files/gtest-1.7.0.zip
|
||||||
|
URL_HASH SHA1=f85f6d2481e2c6c4a18539e391aa4ea8ab0394af
|
||||||
|
SOURCE_DIR "${CMAKE_BINARY_DIR}/gtest-src"
|
||||||
|
BINARY_DIR "${CMAKE_BINARY_DIR}/gtest-build"
|
||||||
|
CONFIGURE_COMMAND ""
|
||||||
|
BUILD_COMMAND ""
|
||||||
|
INSTALL_COMMAND ""
|
||||||
|
TEST_COMMAND ""
|
||||||
|
)
|
|
@ -96,6 +96,7 @@ SET(cockatrice_SOURCES
|
||||||
src/qt-json/json.cpp
|
src/qt-json/json.cpp
|
||||||
src/soundengine.cpp
|
src/soundengine.cpp
|
||||||
src/pending_command.cpp
|
src/pending_command.cpp
|
||||||
|
src/pictureloader.cpp
|
||||||
src/shortcutssettings.cpp
|
src/shortcutssettings.cpp
|
||||||
src/sequenceEdit/sequenceedit.cpp
|
src/sequenceEdit/sequenceedit.cpp
|
||||||
src/sequenceEdit/shortcutstab.cpp
|
src/sequenceEdit/shortcutstab.cpp
|
||||||
|
@ -109,10 +110,6 @@ SET(cockatrice_SOURCES
|
||||||
${VERSION_STRING_CPP}
|
${VERSION_STRING_CPP}
|
||||||
)
|
)
|
||||||
|
|
||||||
if (UNIX AND NOT APPLE)
|
|
||||||
set_source_files_properties(src/main.cpp PROPERTIES COMPILE_FLAGS -DTRANSLATION_PATH=\\"${CMAKE_INSTALL_PREFIX}/share/cockatrice/translations\\")
|
|
||||||
endif (UNIX AND NOT APPLE)
|
|
||||||
|
|
||||||
set(cockatrice_RESOURCES cockatrice.qrc)
|
set(cockatrice_RESOURCES cockatrice.qrc)
|
||||||
|
|
||||||
IF(UPDATE_TRANSLATIONS)
|
IF(UPDATE_TRANSLATIONS)
|
||||||
|
@ -281,6 +278,7 @@ if(APPLE)
|
||||||
# these needs to be relative to CMAKE_INSTALL_PREFIX
|
# these needs to be relative to CMAKE_INSTALL_PREFIX
|
||||||
set(plugin_dest_dir cockatrice.app/Contents/Plugins)
|
set(plugin_dest_dir cockatrice.app/Contents/Plugins)
|
||||||
set(qtconf_dest_dir cockatrice.app/Contents/Resources)
|
set(qtconf_dest_dir cockatrice.app/Contents/Resources)
|
||||||
|
get_filename_component(QT_LIBRARY_DIR "${QT_LIBRARY_DIR}/.." ABSOLUTE)
|
||||||
|
|
||||||
# qt4: codecs, iconengines, imageformats
|
# qt4: codecs, iconengines, imageformats
|
||||||
# qt5: audio, iconengines, imageformats, platforms, printsupport
|
# qt5: audio, iconengines, imageformats, platforms, printsupport
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "carddatabase.h"
|
#include "carddatabase.h"
|
||||||
#include "cardinfowidget.h"
|
#include "cardinfowidget.h"
|
||||||
#include "abstractcarditem.h"
|
#include "abstractcarditem.h"
|
||||||
|
#include "pictureloader.h"
|
||||||
#include "settingscache.h"
|
#include "settingscache.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "gamescene.h"
|
#include "gamescene.h"
|
||||||
|
@ -93,7 +94,7 @@ void AbstractCardItem::paintPicture(QPainter *painter, const QSizeF &translatedS
|
||||||
QPixmap translatedPixmap;
|
QPixmap translatedPixmap;
|
||||||
// don't even spend time trying to load the picture if our size is too small
|
// don't even spend time trying to load the picture if our size is too small
|
||||||
if(translatedSize.width() > 10)
|
if(translatedSize.width() > 10)
|
||||||
imageSource->getPixmap(translatedSize.toSize(), translatedPixmap);
|
PictureLoader::getPixmap(translatedPixmap, imageSource, translatedSize.toSize());
|
||||||
|
|
||||||
painter->save();
|
painter->save();
|
||||||
QColor bgColor = Qt::transparent;
|
QColor bgColor = Qt::transparent;
|
||||||
|
|
|
@ -1,20 +1,14 @@
|
||||||
#include "carddatabase.h"
|
#include "carddatabase.h"
|
||||||
|
#include "pictureloader.h"
|
||||||
#include "settingscache.h"
|
#include "settingscache.h"
|
||||||
#include "thememanager.h"
|
#include "thememanager.h"
|
||||||
|
|
||||||
#include <QCryptographicHash>
|
#include <QCryptographicHash>
|
||||||
|
#include <QDebug>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QDirIterator>
|
#include <QDirIterator>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
#include <QPainter>
|
|
||||||
#include <QUrl>
|
|
||||||
#include <QSet>
|
|
||||||
#include <QNetworkAccessManager>
|
|
||||||
#include <QNetworkReply>
|
|
||||||
#include <QNetworkRequest>
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QImageReader>
|
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
|
||||||
const int CardDatabase::versionNeeded = 3;
|
const int CardDatabase::versionNeeded = 3;
|
||||||
|
@ -88,38 +82,6 @@ void SetList::sortByKey()
|
||||||
qSort(begin(), end(), KeyCompareFunctor());
|
qSort(begin(), end(), KeyCompareFunctor());
|
||||||
}
|
}
|
||||||
|
|
||||||
class SetList::EnabledAndKeyCompareFunctor {
|
|
||||||
public:
|
|
||||||
inline bool operator()(CardSet *a, CardSet *b) const
|
|
||||||
{
|
|
||||||
if(a->getEnabled())
|
|
||||||
{
|
|
||||||
if(b->getEnabled())
|
|
||||||
{
|
|
||||||
// both enabled: sort by key
|
|
||||||
return a->getSortKey() < b->getSortKey();
|
|
||||||
} else {
|
|
||||||
// only a enabled
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if(b->getEnabled())
|
|
||||||
{
|
|
||||||
// only b enabled
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
// both disabled: sort by key
|
|
||||||
return a->getSortKey() < b->getSortKey();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void SetList::sortByEnabledAndKey()
|
|
||||||
{
|
|
||||||
qSort(begin(), end(), EnabledAndKeyCompareFunctor());
|
|
||||||
}
|
|
||||||
|
|
||||||
int SetList::getEnabledSetsNum()
|
int SetList::getEnabledSetsNum()
|
||||||
{
|
{
|
||||||
int num=0;
|
int num=0;
|
||||||
|
@ -195,334 +157,6 @@ void SetList::guessSortKeys()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PictureToLoad::PictureToLoad(CardInfo *_card, bool _hq)
|
|
||||||
: card(_card), setIndex(0), hq(_hq)
|
|
||||||
{
|
|
||||||
if (card) {
|
|
||||||
sortedSets = card->getSets();
|
|
||||||
sortedSets.sortByEnabledAndKey();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PictureToLoad::nextSet()
|
|
||||||
{
|
|
||||||
if (setIndex == sortedSets.size() - 1)
|
|
||||||
return false;
|
|
||||||
++setIndex;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString PictureToLoad::getSetName() const
|
|
||||||
{
|
|
||||||
if (setIndex < sortedSets.size())
|
|
||||||
return sortedSets[setIndex]->getCorrectedShortName();
|
|
||||||
else
|
|
||||||
return QString("");
|
|
||||||
}
|
|
||||||
|
|
||||||
CardSet *PictureToLoad::getCurrentSet() const
|
|
||||||
{
|
|
||||||
if (setIndex < sortedSets.size())
|
|
||||||
return sortedSets[setIndex];
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList PictureLoader::md5Blacklist = QStringList()
|
|
||||||
<< "db0c48db407a907c16ade38de048a441"; // card back returned by gatherer when card is not found
|
|
||||||
|
|
||||||
PictureLoader::PictureLoader(const QString &__picsPath, bool _picDownload, bool _picDownloadHq, QObject *parent)
|
|
||||||
: QObject(parent),
|
|
||||||
_picsPath(__picsPath), picDownload(_picDownload), picDownloadHq(_picDownloadHq),
|
|
||||||
downloadRunning(false), loadQueueRunning(false)
|
|
||||||
{
|
|
||||||
connect(this, SIGNAL(startLoadQueue()), this, SLOT(processLoadQueue()), Qt::QueuedConnection);
|
|
||||||
|
|
||||||
networkManager = new QNetworkAccessManager(this);
|
|
||||||
connect(networkManager, SIGNAL(finished(QNetworkReply *)), this, SLOT(picDownloadFinished(QNetworkReply *)));
|
|
||||||
}
|
|
||||||
|
|
||||||
PictureLoader::~PictureLoader()
|
|
||||||
{
|
|
||||||
// This does not work with the destroyed() signal as this destructor is called after the main event loop is done.
|
|
||||||
thread()->quit();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PictureLoader::processLoadQueue()
|
|
||||||
{
|
|
||||||
if (loadQueueRunning)
|
|
||||||
return;
|
|
||||||
|
|
||||||
loadQueueRunning = true;
|
|
||||||
forever {
|
|
||||||
mutex.lock();
|
|
||||||
if (loadQueue.isEmpty()) {
|
|
||||||
mutex.unlock();
|
|
||||||
loadQueueRunning = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
cardBeingLoaded = loadQueue.takeFirst();
|
|
||||||
mutex.unlock();
|
|
||||||
|
|
||||||
QString setName = cardBeingLoaded.getSetName();
|
|
||||||
QString correctedCardname = cardBeingLoaded.getCard()->getCorrectedName();
|
|
||||||
qDebug() << "Trying to load picture (set: " << setName << " card: " << correctedCardname << ")";
|
|
||||||
|
|
||||||
//The list of paths to the folders in which to search for images
|
|
||||||
QList<QString> picsPaths = QList<QString>() << _picsPath + "/CUSTOM/" + correctedCardname;
|
|
||||||
|
|
||||||
if(!setName.isEmpty())
|
|
||||||
{
|
|
||||||
picsPaths << _picsPath + "/" + setName + "/" + correctedCardname
|
|
||||||
<< _picsPath + "/downloadedPics/" + setName + "/" + correctedCardname;
|
|
||||||
}
|
|
||||||
|
|
||||||
QImage image;
|
|
||||||
QImageReader imgReader;
|
|
||||||
imgReader.setDecideFormatFromContent(true);
|
|
||||||
bool found = false;
|
|
||||||
|
|
||||||
//Iterates through the list of paths, searching for images with the desired name with any QImageReader-supported extension
|
|
||||||
for (int i = 0; i < picsPaths.length() && !found; i ++) {
|
|
||||||
imgReader.setFileName(picsPaths.at(i));
|
|
||||||
if (imgReader.read(&image)) {
|
|
||||||
qDebug() << "Picture found on disk (set: " << setName << " card: " << correctedCardname << ")";
|
|
||||||
emit imageLoaded(cardBeingLoaded.getCard(), image);
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
imgReader.setFileName(picsPaths.at(i) + ".full");
|
|
||||||
if (imgReader.read(&image)) {
|
|
||||||
qDebug() << "Picture.full found on disk (set: " << setName << " card: " << correctedCardname << ")";
|
|
||||||
emit imageLoaded(cardBeingLoaded.getCard(), image);
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found) {
|
|
||||||
if (picDownload) {
|
|
||||||
qDebug() << "Picture NOT found, trying to download (set: " << setName << " card: " << correctedCardname << ")";
|
|
||||||
cardsToDownload.append(cardBeingLoaded);
|
|
||||||
cardBeingLoaded=0;
|
|
||||||
if (!downloadRunning)
|
|
||||||
startNextPicDownload();
|
|
||||||
} else {
|
|
||||||
if (cardBeingLoaded.nextSet())
|
|
||||||
{
|
|
||||||
qDebug() << "Picture NOT found and download disabled, moving to next set (newset: " << setName << " card: " << correctedCardname << ")";
|
|
||||||
mutex.lock();
|
|
||||||
loadQueue.prepend(cardBeingLoaded);
|
|
||||||
cardBeingLoaded=0;
|
|
||||||
mutex.unlock();
|
|
||||||
} else {
|
|
||||||
qDebug() << "Picture NOT found, download disabled, no more sets to try: BAILING OUT (oldset: " << setName << " card: " << correctedCardname << ")";
|
|
||||||
emit imageLoaded(cardBeingLoaded.getCard(), QImage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString PictureLoader::getPicUrl()
|
|
||||||
{
|
|
||||||
if (!picDownload) return QString("");
|
|
||||||
|
|
||||||
CardInfo *card = cardBeingDownloaded.getCard();
|
|
||||||
CardSet *set=cardBeingDownloaded.getCurrentSet();
|
|
||||||
QString picUrl = QString("");
|
|
||||||
|
|
||||||
// if sets have been defined for the card, they can contain custom picUrls
|
|
||||||
if(set)
|
|
||||||
{
|
|
||||||
// first check if Hq is enabled and a custom Hq card url exists in cards.xml
|
|
||||||
if(picDownloadHq)
|
|
||||||
{
|
|
||||||
picUrl = card->getCustomPicURLHq(set->getShortName());
|
|
||||||
if (!picUrl.isEmpty())
|
|
||||||
return picUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// then, test for a custom, non-Hq card url in cards.xml
|
|
||||||
picUrl = card->getCustomPicURL(set->getShortName());
|
|
||||||
if (!picUrl.isEmpty())
|
|
||||||
return picUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if a card has a muid, use the default url; if not, use the fallback
|
|
||||||
int muid = set ? card->getMuId(set->getShortName()) : 0;
|
|
||||||
if(muid)
|
|
||||||
picUrl = picDownloadHq ? settingsCache->getPicUrlHq() : settingsCache->getPicUrl();
|
|
||||||
else
|
|
||||||
picUrl = picDownloadHq ? settingsCache->getPicUrlHqFallback() : settingsCache->getPicUrlFallback();
|
|
||||||
|
|
||||||
picUrl.replace("!name!", QUrl::toPercentEncoding(card->getCorrectedName()));
|
|
||||||
picUrl.replace("!name_lower!", QUrl::toPercentEncoding(card->getCorrectedName().toLower()));
|
|
||||||
picUrl.replace("!cardid!", QUrl::toPercentEncoding(QString::number(muid)));
|
|
||||||
if (set)
|
|
||||||
{
|
|
||||||
picUrl.replace("!setcode!", QUrl::toPercentEncoding(set->getShortName()));
|
|
||||||
picUrl.replace("!setcode_lower!", QUrl::toPercentEncoding(set->getShortName().toLower()));
|
|
||||||
picUrl.replace("!setname!", QUrl::toPercentEncoding(set->getLongName()));
|
|
||||||
picUrl.replace("!setname_lower!", QUrl::toPercentEncoding(set->getLongName().toLower()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
picUrl.contains("!name!") ||
|
|
||||||
picUrl.contains("!name_lower!") ||
|
|
||||||
picUrl.contains("!setcode!") ||
|
|
||||||
picUrl.contains("!setcode_lower!") ||
|
|
||||||
picUrl.contains("!setname!") ||
|
|
||||||
picUrl.contains("!setname_lower!") ||
|
|
||||||
picUrl.contains("!cardid!")
|
|
||||||
)
|
|
||||||
{
|
|
||||||
qDebug() << "Insufficient card data to download" << card->getName() << "Url:" << picUrl;
|
|
||||||
return QString("");
|
|
||||||
}
|
|
||||||
|
|
||||||
return picUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PictureLoader::startNextPicDownload()
|
|
||||||
{
|
|
||||||
if (cardsToDownload.isEmpty()) {
|
|
||||||
cardBeingDownloaded = 0;
|
|
||||||
downloadRunning = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
downloadRunning = true;
|
|
||||||
|
|
||||||
cardBeingDownloaded = cardsToDownload.takeFirst();
|
|
||||||
|
|
||||||
QString picUrl = getPicUrl();
|
|
||||||
if (picUrl.isEmpty()) {
|
|
||||||
downloadRunning = false;
|
|
||||||
picDownloadFailed();
|
|
||||||
} else {
|
|
||||||
QUrl url(picUrl);
|
|
||||||
|
|
||||||
QNetworkRequest req(url);
|
|
||||||
qDebug() << "starting picture download:" << cardBeingDownloaded.getCard()->getName() << "Url:" << req.url();
|
|
||||||
networkManager->get(req);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PictureLoader::picDownloadFailed()
|
|
||||||
{
|
|
||||||
if (cardBeingDownloaded.nextSet())
|
|
||||||
{
|
|
||||||
qDebug() << "Picture NOT found, download failed, moving to next set (newset: " << cardBeingDownloaded.getSetName() << " card: " << cardBeingDownloaded.getCard()->getCorrectedName() << ")";
|
|
||||||
mutex.lock();
|
|
||||||
loadQueue.prepend(cardBeingDownloaded);
|
|
||||||
mutex.unlock();
|
|
||||||
emit startLoadQueue();
|
|
||||||
} else {
|
|
||||||
qDebug() << "Picture NOT found, download failed, no more sets to try: BAILING OUT (oldset: " << cardBeingDownloaded.getSetName() << " card: " << cardBeingDownloaded.getCard()->getCorrectedName() << ")";
|
|
||||||
cardBeingDownloaded = 0;
|
|
||||||
emit imageLoaded(cardBeingDownloaded.getCard(), QImage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PictureLoader::picDownloadFinished(QNetworkReply *reply)
|
|
||||||
{
|
|
||||||
QString picsPath = _picsPath;
|
|
||||||
if (reply->error()) {
|
|
||||||
qDebug() << "Download failed:" << reply->errorString();
|
|
||||||
}
|
|
||||||
|
|
||||||
int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
|
||||||
if (statusCode == 301 || statusCode == 302) {
|
|
||||||
QUrl redirectUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
|
|
||||||
QNetworkRequest req(redirectUrl);
|
|
||||||
qDebug() << "following redirect:" << cardBeingDownloaded.getCard()->getName() << "Url:" << req.url();
|
|
||||||
networkManager->get(req);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QByteArray &picData = reply->peek(reply->size()); //peek is used to keep the data in the buffer for use by QImageReader
|
|
||||||
|
|
||||||
// check if the image is blacklisted
|
|
||||||
QString md5sum = QCryptographicHash::hash(picData, QCryptographicHash::Md5).toHex();
|
|
||||||
if(md5Blacklist.contains(md5sum))
|
|
||||||
{
|
|
||||||
qDebug() << "Picture downloaded, but blacklisted (" << md5sum << "), will consider it as not found";
|
|
||||||
picDownloadFailed();
|
|
||||||
reply->deleteLater();
|
|
||||||
startNextPicDownload();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QImage testImage;
|
|
||||||
|
|
||||||
QImageReader imgReader;
|
|
||||||
imgReader.setDecideFormatFromContent(true);
|
|
||||||
imgReader.setDevice(reply);
|
|
||||||
QString extension = "." + imgReader.format(); //the format is determined prior to reading the QImageReader data into a QImage object, as that wipes the QImageReader buffer
|
|
||||||
if (extension == ".jpeg")
|
|
||||||
extension = ".jpg";
|
|
||||||
|
|
||||||
if (imgReader.read(&testImage)) {
|
|
||||||
QString setName = cardBeingDownloaded.getSetName();
|
|
||||||
if(!setName.isEmpty())
|
|
||||||
{
|
|
||||||
if (!QDir().mkpath(picsPath + "/downloadedPics/" + setName)) {
|
|
||||||
qDebug() << picsPath + "/downloadedPics/" + setName + " could not be created.";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QFile newPic(picsPath + "/downloadedPics/" + setName + "/" + cardBeingDownloaded.getCard()->getCorrectedName() + extension);
|
|
||||||
if (!newPic.open(QIODevice::WriteOnly))
|
|
||||||
return;
|
|
||||||
newPic.write(picData);
|
|
||||||
newPic.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
emit imageLoaded(cardBeingDownloaded.getCard(), testImage);
|
|
||||||
} else {
|
|
||||||
picDownloadFailed();
|
|
||||||
}
|
|
||||||
|
|
||||||
reply->deleteLater();
|
|
||||||
startNextPicDownload();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PictureLoader::loadImage(CardInfo *card)
|
|
||||||
{
|
|
||||||
QMutexLocker locker(&mutex);
|
|
||||||
|
|
||||||
// avoid queueing the same card more than once
|
|
||||||
if(card == cardBeingLoaded.getCard() || card == cardBeingDownloaded.getCard())
|
|
||||||
return;
|
|
||||||
|
|
||||||
foreach(PictureToLoad pic, loadQueue)
|
|
||||||
{
|
|
||||||
if(pic.getCard() == card)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
loadQueue.append(PictureToLoad(card));
|
|
||||||
emit startLoadQueue();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PictureLoader::setPicsPath(const QString &path)
|
|
||||||
{
|
|
||||||
QMutexLocker locker(&mutex);
|
|
||||||
_picsPath = path;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PictureLoader::setPicDownload(bool _picDownload)
|
|
||||||
{
|
|
||||||
QMutexLocker locker(&mutex);
|
|
||||||
picDownload = _picDownload;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PictureLoader::setPicDownloadHq(bool _picDownloadHq)
|
|
||||||
{
|
|
||||||
QMutexLocker locker(&mutex);
|
|
||||||
picDownloadHq = _picDownloadHq;
|
|
||||||
}
|
|
||||||
|
|
||||||
CardInfo::CardInfo(CardDatabase *_db,
|
CardInfo::CardInfo(CardDatabase *_db,
|
||||||
const QString &_name,
|
const QString &_name,
|
||||||
bool _isToken,
|
bool _isToken,
|
||||||
|
@ -533,13 +167,13 @@ CardInfo::CardInfo(CardDatabase *_db,
|
||||||
const QString &_text,
|
const QString &_text,
|
||||||
const QStringList &_colors,
|
const QStringList &_colors,
|
||||||
const QStringList &_relatedCards,
|
const QStringList &_relatedCards,
|
||||||
|
const QStringList &_reverseRelatedCards,
|
||||||
bool _upsideDownArt,
|
bool _upsideDownArt,
|
||||||
int _loyalty,
|
int _loyalty,
|
||||||
bool _cipt,
|
bool _cipt,
|
||||||
int _tableRow,
|
int _tableRow,
|
||||||
const SetList &_sets,
|
const SetList &_sets,
|
||||||
const QStringMap &_customPicURLs,
|
const QStringMap &_customPicURLs,
|
||||||
const QStringMap &_customPicURLsHq,
|
|
||||||
MuidMap _muIds
|
MuidMap _muIds
|
||||||
)
|
)
|
||||||
: db(_db),
|
: db(_db),
|
||||||
|
@ -553,10 +187,10 @@ CardInfo::CardInfo(CardDatabase *_db,
|
||||||
text(_text),
|
text(_text),
|
||||||
colors(_colors),
|
colors(_colors),
|
||||||
relatedCards(_relatedCards),
|
relatedCards(_relatedCards),
|
||||||
|
reverseRelatedCards(_reverseRelatedCards),
|
||||||
upsideDownArt(_upsideDownArt),
|
upsideDownArt(_upsideDownArt),
|
||||||
loyalty(_loyalty),
|
loyalty(_loyalty),
|
||||||
customPicURLs(_customPicURLs),
|
customPicURLs(_customPicURLs),
|
||||||
customPicURLsHq(_customPicURLsHq),
|
|
||||||
muIds(_muIds),
|
muIds(_muIds),
|
||||||
cipt(_cipt),
|
cipt(_cipt),
|
||||||
tableRow(_tableRow)
|
tableRow(_tableRow)
|
||||||
|
@ -570,7 +204,7 @@ CardInfo::CardInfo(CardDatabase *_db,
|
||||||
|
|
||||||
CardInfo::~CardInfo()
|
CardInfo::~CardInfo()
|
||||||
{
|
{
|
||||||
clearPixmapCache();
|
PictureLoader::clearPixmapCache(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CardInfo::getMainCardType() const
|
QString CardInfo::getMainCardType() const
|
||||||
|
@ -617,82 +251,6 @@ void CardInfo::addToSet(CardSet *set)
|
||||||
sets << set;
|
sets << set;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardInfo::loadPixmap(QPixmap &pixmap)
|
|
||||||
{
|
|
||||||
if(QPixmapCache::find(pixmapCacheKey, &pixmap))
|
|
||||||
return;
|
|
||||||
|
|
||||||
pixmap = QPixmap();
|
|
||||||
|
|
||||||
if (getName().isEmpty()) {
|
|
||||||
pixmap = QPixmap("theme:cardback");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
db->loadImage(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CardInfo::imageLoaded(const QImage &image)
|
|
||||||
{
|
|
||||||
if (!image.isNull()) {
|
|
||||||
if(upsideDownArt)
|
|
||||||
{
|
|
||||||
QImage mirrorImage = image.mirrored(true, true);
|
|
||||||
QPixmapCache::insert(pixmapCacheKey, QPixmap::fromImage(mirrorImage));
|
|
||||||
} else {
|
|
||||||
QPixmapCache::insert(pixmapCacheKey, QPixmap::fromImage(image));
|
|
||||||
}
|
|
||||||
emit pixmapUpdated();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CardInfo::getPixmap(QSize size, QPixmap &pixmap)
|
|
||||||
{
|
|
||||||
QString key = QLatin1String("card_") + name + QLatin1Char('_') + QString::number(size.width()) + QString::number(size.height());
|
|
||||||
if(QPixmapCache::find(key, &pixmap))
|
|
||||||
return;
|
|
||||||
|
|
||||||
QPixmap bigPixmap;
|
|
||||||
loadPixmap(bigPixmap);
|
|
||||||
if (bigPixmap.isNull()) {
|
|
||||||
if (getName().isEmpty()) {
|
|
||||||
pixmap = pixmap = QPixmap("theme:cardback");
|
|
||||||
} else {
|
|
||||||
pixmap = QPixmap(); // null
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pixmap = bigPixmap.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
|
||||||
QPixmapCache::insert(key, pixmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CardInfo::clearPixmapCache()
|
|
||||||
{
|
|
||||||
//qDebug() << "Deleting pixmap for" << name;
|
|
||||||
QPixmapCache::remove(pixmapCacheKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CardInfo::clearPixmapCacheMiss()
|
|
||||||
{
|
|
||||||
QPixmap pixmap;
|
|
||||||
if(!QPixmapCache::find(pixmapCacheKey, &pixmap))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (pixmap.isNull())
|
|
||||||
clearPixmapCache();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CardInfo::updatePixmapCache()
|
|
||||||
{
|
|
||||||
qDebug() << "Updating pixmap cache for" << name;
|
|
||||||
clearPixmapCache();
|
|
||||||
QPixmap tmp;
|
|
||||||
loadPixmap(tmp);
|
|
||||||
|
|
||||||
emit pixmapUpdated();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString CardInfo::simplifyName(const QString &name) {
|
QString CardInfo::simplifyName(const QString &name) {
|
||||||
QString simpleName(name);
|
QString simpleName(name);
|
||||||
|
|
||||||
|
@ -731,10 +289,6 @@ static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfo *info)
|
||||||
if(!tmpString.isEmpty())
|
if(!tmpString.isEmpty())
|
||||||
xml.writeAttribute("picURL", tmpString);
|
xml.writeAttribute("picURL", tmpString);
|
||||||
|
|
||||||
tmpString = info->getCustomPicURLHq(tmpSet);
|
|
||||||
if(!tmpString.isEmpty())
|
|
||||||
xml.writeAttribute("picURLHq", tmpString);
|
|
||||||
|
|
||||||
xml.writeCharacters(tmpSet);
|
xml.writeCharacters(tmpSet);
|
||||||
xml.writeEndElement();
|
xml.writeEndElement();
|
||||||
}
|
}
|
||||||
|
@ -746,6 +300,10 @@ static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfo *info)
|
||||||
for (int i = 0; i < related.size(); i++)
|
for (int i = 0; i < related.size(); i++)
|
||||||
xml.writeTextElement("related", related[i]);
|
xml.writeTextElement("related", related[i]);
|
||||||
|
|
||||||
|
const QStringList &reverseRelated = info->getReverseRelatedCards();
|
||||||
|
for (int i = 0; i < reverseRelated.size(); i++)
|
||||||
|
xml.writeTextElement("reverse-related", reverseRelated[i]);
|
||||||
|
|
||||||
xml.writeTextElement("manacost", info->getManaCost());
|
xml.writeTextElement("manacost", info->getManaCost());
|
||||||
xml.writeTextElement("cmc", info->getCmc());
|
xml.writeTextElement("cmc", info->getCmc());
|
||||||
xml.writeTextElement("type", info->getCardType());
|
xml.writeTextElement("type", info->getCardType());
|
||||||
|
@ -769,35 +327,19 @@ static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfo *info)
|
||||||
CardDatabase::CardDatabase(QObject *parent)
|
CardDatabase::CardDatabase(QObject *parent)
|
||||||
: QObject(parent), noCard(0), loadStatus(NotLoaded)
|
: QObject(parent), noCard(0), loadStatus(NotLoaded)
|
||||||
{
|
{
|
||||||
connect(settingsCache, SIGNAL(picsPathChanged()), this, SLOT(picsPathChanged()));
|
|
||||||
connect(settingsCache, SIGNAL(cardDatabasePathChanged()), this, SLOT(loadCardDatabase()));
|
connect(settingsCache, SIGNAL(cardDatabasePathChanged()), this, SLOT(loadCardDatabase()));
|
||||||
connect(settingsCache, SIGNAL(tokenDatabasePathChanged()), this, SLOT(loadTokenDatabase()));
|
connect(settingsCache, SIGNAL(tokenDatabasePathChanged()), this, SLOT(loadTokenDatabase()));
|
||||||
connect(settingsCache, SIGNAL(picDownloadChanged()), this, SLOT(picDownloadChanged()));
|
|
||||||
connect(settingsCache, SIGNAL(picDownloadHqChanged()), this, SLOT(picDownloadHqChanged()));
|
|
||||||
|
|
||||||
loadCardDatabase();
|
loadCardDatabase();
|
||||||
loadTokenDatabase();
|
loadTokenDatabase();
|
||||||
|
|
||||||
pictureLoaderThread = new QThread;
|
|
||||||
pictureLoader = new PictureLoader(settingsCache->getPicsPath(), settingsCache->getPicDownload(), settingsCache->getPicDownloadHq());
|
|
||||||
pictureLoader->moveToThread(pictureLoaderThread);
|
|
||||||
connect(pictureLoader, SIGNAL(imageLoaded(CardInfo *, const QImage &)), this, SLOT(imageLoaded(CardInfo *, const QImage &)));
|
|
||||||
pictureLoaderThread->start(QThread::LowPriority);
|
|
||||||
|
|
||||||
noCard = new CardInfo(this);
|
noCard = new CardInfo(this);
|
||||||
QPixmap tmp;
|
|
||||||
noCard->loadPixmap(tmp); // cache pixmap for card back
|
|
||||||
connect(themeManager, SIGNAL(themeChanged()), noCard, SLOT(updatePixmapCache()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CardDatabase::~CardDatabase()
|
CardDatabase::~CardDatabase()
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
delete noCard;
|
delete noCard;
|
||||||
|
|
||||||
pictureLoader->deleteLater();
|
|
||||||
pictureLoaderThread->wait();
|
|
||||||
delete pictureLoaderThread;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardDatabase::clear()
|
void CardDatabase::clear()
|
||||||
|
@ -839,6 +381,15 @@ CardInfo *CardDatabase::getCard(const QString &cardName, bool createIfNotFound)
|
||||||
return getCardFromMap(cards, cardName, createIfNotFound);
|
return getCardFromMap(cards, cardName, createIfNotFound);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<CardInfo *> CardDatabase::getCards(const QStringList &cardNames)
|
||||||
|
{
|
||||||
|
QList<CardInfo *> cardInfos;
|
||||||
|
foreach(QString cardName, cardNames)
|
||||||
|
cardInfos.append(getCardFromMap(cards, cardName, false));
|
||||||
|
|
||||||
|
return cardInfos;
|
||||||
|
}
|
||||||
|
|
||||||
CardInfo *CardDatabase::getCardBySimpleName(const QString &cardName, bool createIfNotFound) {
|
CardInfo *CardDatabase::getCardBySimpleName(const QString &cardName, bool createIfNotFound) {
|
||||||
QString simpleName = CardInfo::simplifyName(cardName);
|
QString simpleName = CardInfo::simplifyName(cardName);
|
||||||
return getCardFromMap(simpleNameCards, simpleName, createIfNotFound);
|
return getCardFromMap(simpleNameCards, simpleName, createIfNotFound);
|
||||||
|
@ -866,21 +417,6 @@ SetList CardDatabase::getSetList() const
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardDatabase::clearPixmapCache()
|
|
||||||
{
|
|
||||||
// This also clears the cards in simpleNameCards since they point to the
|
|
||||||
// same object.
|
|
||||||
QHashIterator<QString, CardInfo *> i(cards);
|
|
||||||
while (i.hasNext()) {
|
|
||||||
i.next();
|
|
||||||
i.value()->clearPixmapCache();
|
|
||||||
}
|
|
||||||
if (noCard)
|
|
||||||
noCard->clearPixmapCache();
|
|
||||||
|
|
||||||
QPixmapCache::clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CardDatabase::loadSetsFromXml(QXmlStreamReader &xml)
|
void CardDatabase::loadSetsFromXml(QXmlStreamReader &xml)
|
||||||
{
|
{
|
||||||
while (!xml.atEnd()) {
|
while (!xml.atEnd()) {
|
||||||
|
@ -917,8 +453,8 @@ void CardDatabase::loadCardsFromXml(QXmlStreamReader &xml, bool tokens)
|
||||||
break;
|
break;
|
||||||
if (xml.name() == "card") {
|
if (xml.name() == "card") {
|
||||||
QString name, manacost, cmc, type, pt, text;
|
QString name, manacost, cmc, type, pt, text;
|
||||||
QStringList colors, relatedCards;
|
QStringList colors, relatedCards, reverseRelatedCards;
|
||||||
QStringMap customPicURLs, customPicURLsHq;
|
QStringMap customPicURLs;
|
||||||
MuidMap muids;
|
MuidMap muids;
|
||||||
SetList sets;
|
SetList sets;
|
||||||
int tableRow = 0;
|
int tableRow = 0;
|
||||||
|
@ -951,13 +487,12 @@ void CardDatabase::loadCardsFromXml(QXmlStreamReader &xml, bool tokens)
|
||||||
if (attrs.hasAttribute("picURL")) {
|
if (attrs.hasAttribute("picURL")) {
|
||||||
customPicURLs[setName] = attrs.value("picURL").toString();
|
customPicURLs[setName] = attrs.value("picURL").toString();
|
||||||
}
|
}
|
||||||
if (attrs.hasAttribute("picURLHq")) {
|
|
||||||
customPicURLsHq[setName] = attrs.value("picURLHq").toString();
|
|
||||||
}
|
|
||||||
} else if (xml.name() == "color")
|
} else if (xml.name() == "color")
|
||||||
colors << xml.readElementText();
|
colors << xml.readElementText();
|
||||||
else if (xml.name() == "related")
|
else if (xml.name() == "related")
|
||||||
relatedCards << xml.readElementText();
|
relatedCards << xml.readElementText();
|
||||||
|
else if (xml.name() == "reverse-related")
|
||||||
|
reverseRelatedCards << xml.readElementText();
|
||||||
else if (xml.name() == "tablerow")
|
else if (xml.name() == "tablerow")
|
||||||
tableRow = xml.readElementText().toInt();
|
tableRow = xml.readElementText().toInt();
|
||||||
else if (xml.name() == "cipt")
|
else if (xml.name() == "cipt")
|
||||||
|
@ -971,24 +506,24 @@ void CardDatabase::loadCardsFromXml(QXmlStreamReader &xml, bool tokens)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isToken == tokens) {
|
if (isToken == tokens) {
|
||||||
addCard(new CardInfo(this, name, isToken, manacost, cmc, type, pt, text, colors, relatedCards, upsideDown, loyalty, cipt, tableRow, sets, customPicURLs, customPicURLsHq, muids));
|
addCard(new CardInfo(this, name, isToken, manacost, cmc, type, pt, text, colors, relatedCards, reverseRelatedCards, upsideDown, loyalty, cipt, tableRow, sets, customPicURLs, muids));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CardInfo *CardDatabase::getCardFromMap(CardNameMap &cardMap, const QString &cardName, bool createIfNotFound) {
|
CardInfo *CardDatabase::getCardFromMap(CardNameMap &cardMap, const QString &cardName, bool createIfNotFound) {
|
||||||
if (cardName.isEmpty())
|
if (cardMap.contains(cardName))
|
||||||
return noCard;
|
|
||||||
else if (cardMap.contains(cardName))
|
|
||||||
return cardMap.value(cardName);
|
return cardMap.value(cardName);
|
||||||
else if (createIfNotFound) {
|
|
||||||
|
if (createIfNotFound) {
|
||||||
CardInfo *newCard = new CardInfo(this, cardName, true);
|
CardInfo *newCard = new CardInfo(this, cardName, true);
|
||||||
newCard->addToSet(getSet(CardDatabase::TOKENS_SETNAME));
|
newCard->addToSet(getSet(CardDatabase::TOKENS_SETNAME));
|
||||||
cardMap.insert(cardName, newCard);
|
cardMap.insert(cardName, newCard);
|
||||||
return newCard;
|
return newCard;
|
||||||
} else
|
}
|
||||||
return 0;
|
|
||||||
|
return noCard;
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadStatus CardDatabase::loadFromFile(const QString &fileName, bool tokens)
|
LoadStatus CardDatabase::loadFromFile(const QString &fileName, bool tokens)
|
||||||
|
@ -1061,26 +596,6 @@ bool CardDatabase::saveToFile(const QString &fileName, bool tokens)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardDatabase::picDownloadChanged()
|
|
||||||
{
|
|
||||||
pictureLoader->setPicDownload(settingsCache->getPicDownload());
|
|
||||||
if (settingsCache->getPicDownload()) {
|
|
||||||
QHashIterator<QString, CardInfo *> cardIterator(cards);
|
|
||||||
while (cardIterator.hasNext())
|
|
||||||
cardIterator.next().value()->clearPixmapCacheMiss();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CardDatabase::picDownloadHqChanged()
|
|
||||||
{
|
|
||||||
pictureLoader->setPicDownloadHq(settingsCache->getPicDownloadHq());
|
|
||||||
if (settingsCache->getPicDownloadHq()) {
|
|
||||||
QHashIterator<QString, CardInfo *> cardIterator(cards);
|
|
||||||
while (cardIterator.hasNext())
|
|
||||||
cardIterator.next().value()->clearPixmapCacheMiss();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CardDatabase::emitCardListChanged()
|
void CardDatabase::emitCardListChanged()
|
||||||
{
|
{
|
||||||
emit cardListChanged();
|
emit cardListChanged();
|
||||||
|
@ -1135,6 +650,32 @@ void CardDatabase::loadCustomCardDatabases(const QString &path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CardDatabase::refreshCachedReverseRelatedCards()
|
||||||
|
{
|
||||||
|
foreach(CardInfo * card, cards)
|
||||||
|
card->resetReverseRelatedCards2Me();
|
||||||
|
|
||||||
|
foreach(CardInfo * card, cards)
|
||||||
|
{
|
||||||
|
if(card->getReverseRelatedCards().isEmpty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
QString relatedCardName;
|
||||||
|
if (card->getPowTough().size() > 0)
|
||||||
|
relatedCardName = card->getPowTough() + " " + card->getName(); // "n/n name"
|
||||||
|
else
|
||||||
|
relatedCardName = card->getName(); // "name"
|
||||||
|
|
||||||
|
foreach(QString targetCard, card->getReverseRelatedCards())
|
||||||
|
{
|
||||||
|
if (!cards.contains(targetCard))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
cards.value(targetCard)->addReverseRelatedCards2Me(relatedCardName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QStringList CardDatabase::getAllColors() const
|
QStringList CardDatabase::getAllColors() const
|
||||||
{
|
{
|
||||||
QSet<QString> colors;
|
QSet<QString> colors;
|
||||||
|
@ -1159,31 +700,6 @@ QStringList CardDatabase::getAllMainCardTypes() const
|
||||||
return types.toList();
|
return types.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardDatabase::cacheCardPixmaps(const QStringList &cardNames)
|
|
||||||
{
|
|
||||||
QPixmap tmp;
|
|
||||||
// never cache more than 300 cards at once for a single deck
|
|
||||||
int max = qMin(cardNames.size(), 300);
|
|
||||||
for (int i = 0; i < max; ++i)
|
|
||||||
getCard(cardNames[i])->loadPixmap(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CardDatabase::loadImage(CardInfo *card)
|
|
||||||
{
|
|
||||||
pictureLoader->loadImage(card);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CardDatabase::imageLoaded(CardInfo *card, QImage image)
|
|
||||||
{
|
|
||||||
card->imageLoaded(image);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CardDatabase::picsPathChanged()
|
|
||||||
{
|
|
||||||
pictureLoader->setPicsPath(settingsCache->getPicsPath());
|
|
||||||
clearPixmapCache();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CardDatabase::checkUnknownSets()
|
void CardDatabase::checkUnknownSets()
|
||||||
{
|
{
|
||||||
SetList sets = getSetList();
|
SetList sets = getSetList();
|
||||||
|
|
|
@ -8,17 +8,9 @@
|
||||||
#include <QDataStream>
|
#include <QDataStream>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QXmlStreamReader>
|
#include <QXmlStreamReader>
|
||||||
#include <QNetworkRequest>
|
|
||||||
#include <QThread>
|
|
||||||
#include <QMutex>
|
|
||||||
#include <QWaitCondition>
|
|
||||||
#include <QPixmapCache>
|
|
||||||
|
|
||||||
class CardDatabase;
|
class CardDatabase;
|
||||||
class CardInfo;
|
class CardInfo;
|
||||||
class QNetworkAccessManager;
|
|
||||||
class QNetworkReply;
|
|
||||||
class QNetworkRequest;
|
|
||||||
|
|
||||||
typedef QMap<QString, QString> QStringMap;
|
typedef QMap<QString, QString> QStringMap;
|
||||||
|
|
||||||
|
@ -55,9 +47,7 @@ public:
|
||||||
class SetList : public QList<CardSet *> {
|
class SetList : public QList<CardSet *> {
|
||||||
private:
|
private:
|
||||||
class KeyCompareFunctor;
|
class KeyCompareFunctor;
|
||||||
class EnabledAndKeyCompareFunctor;
|
|
||||||
public:
|
public:
|
||||||
void sortByEnabledAndKey();
|
|
||||||
void sortByKey();
|
void sortByKey();
|
||||||
void guessSortKeys();
|
void guessSortKeys();
|
||||||
void enableAllUnknown();
|
void enableAllUnknown();
|
||||||
|
@ -67,53 +57,6 @@ public:
|
||||||
int getUnknownSetsNum();
|
int getUnknownSetsNum();
|
||||||
};
|
};
|
||||||
|
|
||||||
class PictureToLoad {
|
|
||||||
private:
|
|
||||||
CardInfo *card;
|
|
||||||
SetList sortedSets;
|
|
||||||
int setIndex;
|
|
||||||
bool hq;
|
|
||||||
public:
|
|
||||||
PictureToLoad(CardInfo *_card = 0, bool _hq = true);
|
|
||||||
CardInfo *getCard() const { return card; }
|
|
||||||
CardSet *getCurrentSet() const;
|
|
||||||
QString getSetName() const;
|
|
||||||
bool nextSet();
|
|
||||||
bool getHq() const { return hq; }
|
|
||||||
void setHq(bool _hq) { hq = _hq; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class PictureLoader : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
private:
|
|
||||||
QString _picsPath;
|
|
||||||
QList<PictureToLoad> loadQueue;
|
|
||||||
QMutex mutex;
|
|
||||||
QNetworkAccessManager *networkManager;
|
|
||||||
QList<PictureToLoad> cardsToDownload;
|
|
||||||
PictureToLoad cardBeingLoaded;
|
|
||||||
PictureToLoad cardBeingDownloaded;
|
|
||||||
bool picDownload, picDownloadHq, downloadRunning, loadQueueRunning;
|
|
||||||
void startNextPicDownload();
|
|
||||||
QString getPicUrl();
|
|
||||||
static QStringList md5Blacklist;
|
|
||||||
public:
|
|
||||||
PictureLoader(const QString &__picsPath, bool _picDownload, bool _picDownloadHq, QObject *parent = 0);
|
|
||||||
~PictureLoader();
|
|
||||||
void setPicsPath(const QString &path);
|
|
||||||
void setPicDownload(bool _picDownload);
|
|
||||||
void setPicDownloadHq(bool _picDownloadHq);
|
|
||||||
void loadImage(CardInfo *card);
|
|
||||||
private slots:
|
|
||||||
void picDownloadFinished(QNetworkReply *reply);
|
|
||||||
void picDownloadFailed();
|
|
||||||
public slots:
|
|
||||||
void processLoadQueue();
|
|
||||||
signals:
|
|
||||||
void startLoadQueue();
|
|
||||||
void imageLoaded(CardInfo *card, const QImage &image);
|
|
||||||
};
|
|
||||||
|
|
||||||
class CardInfo : public QObject {
|
class CardInfo : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
private:
|
private:
|
||||||
|
@ -135,14 +78,20 @@ private:
|
||||||
QString powtough;
|
QString powtough;
|
||||||
QString text;
|
QString text;
|
||||||
QStringList colors;
|
QStringList colors;
|
||||||
|
// the cards i'm related to
|
||||||
QStringList relatedCards;
|
QStringList relatedCards;
|
||||||
|
// the card i'm reverse-related to
|
||||||
|
QStringList reverseRelatedCards;
|
||||||
|
// the cards thare are reverse-related to me
|
||||||
|
QStringList reverseRelatedCardsToMe;
|
||||||
bool upsideDownArt;
|
bool upsideDownArt;
|
||||||
int loyalty;
|
int loyalty;
|
||||||
QStringMap customPicURLs, customPicURLsHq;
|
QStringMap customPicURLs;
|
||||||
MuidMap muIds;
|
MuidMap muIds;
|
||||||
bool cipt;
|
bool cipt;
|
||||||
int tableRow;
|
int tableRow;
|
||||||
QString pixmapCacheKey;
|
QString pixmapCacheKey;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CardInfo(CardDatabase *_db,
|
CardInfo(CardDatabase *_db,
|
||||||
const QString &_name = QString(),
|
const QString &_name = QString(),
|
||||||
|
@ -154,13 +103,13 @@ public:
|
||||||
const QString &_text = QString(),
|
const QString &_text = QString(),
|
||||||
const QStringList &_colors = QStringList(),
|
const QStringList &_colors = QStringList(),
|
||||||
const QStringList &_relatedCards = QStringList(),
|
const QStringList &_relatedCards = QStringList(),
|
||||||
|
const QStringList &_reverseRelatedCards = QStringList(),
|
||||||
bool _upsideDownArt = false,
|
bool _upsideDownArt = false,
|
||||||
int _loyalty = 0,
|
int _loyalty = 0,
|
||||||
bool _cipt = false,
|
bool _cipt = false,
|
||||||
int _tableRow = 0,
|
int _tableRow = 0,
|
||||||
const SetList &_sets = SetList(),
|
const SetList &_sets = SetList(),
|
||||||
const QStringMap &_customPicURLs = QStringMap(),
|
const QStringMap &_customPicURLs = QStringMap(),
|
||||||
const QStringMap &_customPicURLsHq = QStringMap(),
|
|
||||||
MuidMap muids = MuidMap()
|
MuidMap muids = MuidMap()
|
||||||
);
|
);
|
||||||
~CardInfo();
|
~CardInfo();
|
||||||
|
@ -173,6 +122,7 @@ public:
|
||||||
const QString &getCardType() const { return cardtype; }
|
const QString &getCardType() const { return cardtype; }
|
||||||
const QString &getPowTough() const { return powtough; }
|
const QString &getPowTough() const { return powtough; }
|
||||||
const QString &getText() const { return text; }
|
const QString &getText() const { return text; }
|
||||||
|
const QString &getPixmapCacheKey() const { return pixmapCacheKey; }
|
||||||
const int &getLoyalty() const { return loyalty; }
|
const int &getLoyalty() const { return loyalty; }
|
||||||
bool getCipt() const { return cipt; }
|
bool getCipt() const { return cipt; }
|
||||||
void setManaCost(const QString &_manaCost) { manacost = _manaCost; emit cardInfoChanged(this); }
|
void setManaCost(const QString &_manaCost) { manacost = _manaCost; emit cardInfoChanged(this); }
|
||||||
|
@ -183,9 +133,12 @@ public:
|
||||||
void setColors(const QStringList &_colors) { colors = _colors; emit cardInfoChanged(this); }
|
void setColors(const QStringList &_colors) { colors = _colors; emit cardInfoChanged(this); }
|
||||||
const QStringList &getColors() const { return colors; }
|
const QStringList &getColors() const { return colors; }
|
||||||
const QStringList &getRelatedCards() const { return relatedCards; }
|
const QStringList &getRelatedCards() const { return relatedCards; }
|
||||||
|
const QStringList &getReverseRelatedCards() const { return reverseRelatedCards; }
|
||||||
|
const QStringList &getReverseRelatedCards2Me() const { return reverseRelatedCardsToMe; }
|
||||||
|
void resetReverseRelatedCards2Me() { reverseRelatedCardsToMe = QStringList(); }
|
||||||
|
void addReverseRelatedCards2Me(QString & cardName) { reverseRelatedCardsToMe.append(cardName); }
|
||||||
bool getUpsideDownArt() const { return upsideDownArt; }
|
bool getUpsideDownArt() const { return upsideDownArt; }
|
||||||
QString getCustomPicURL(const QString &set) const { return customPicURLs.value(set); }
|
QString getCustomPicURL(const QString &set) const { return customPicURLs.value(set); }
|
||||||
QString getCustomPicURLHq(const QString &set) const { return customPicURLsHq.value(set); }
|
|
||||||
int getMuId(const QString &set) const { return muIds.value(set); }
|
int getMuId(const QString &set) const { return muIds.value(set); }
|
||||||
QString getMainCardType() const;
|
QString getMainCardType() const;
|
||||||
QString getCorrectedName() const;
|
QString getCorrectedName() const;
|
||||||
|
@ -193,22 +146,15 @@ public:
|
||||||
void setTableRow(int _tableRow) { tableRow = _tableRow; }
|
void setTableRow(int _tableRow) { tableRow = _tableRow; }
|
||||||
void setLoyalty(int _loyalty) { loyalty = _loyalty; emit cardInfoChanged(this); }
|
void setLoyalty(int _loyalty) { loyalty = _loyalty; emit cardInfoChanged(this); }
|
||||||
void setCustomPicURL(const QString &_set, const QString &_customPicURL) { customPicURLs.insert(_set, _customPicURL); }
|
void setCustomPicURL(const QString &_set, const QString &_customPicURL) { customPicURLs.insert(_set, _customPicURL); }
|
||||||
void setCustomPicURLHq(const QString &_set, const QString &_customPicURL) { customPicURLsHq.insert(_set, _customPicURL); }
|
|
||||||
void setMuId(const QString &_set, const int &_muId) { muIds.insert(_set, _muId); }
|
void setMuId(const QString &_set, const int &_muId) { muIds.insert(_set, _muId); }
|
||||||
void addToSet(CardSet *set);
|
void addToSet(CardSet *set);
|
||||||
void loadPixmap(QPixmap &pixmap);
|
void emitPixmapUpdated() { emit pixmapUpdated(); }
|
||||||
void getPixmap(QSize size, QPixmap &pixmap);
|
|
||||||
void clearPixmapCache();
|
|
||||||
void clearPixmapCacheMiss();
|
|
||||||
void imageLoaded(const QImage &image);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simplify a name to have no punctuation and lowercase all letters, for
|
* Simplify a name to have no punctuation and lowercase all letters, for
|
||||||
* less strict name-matching.
|
* less strict name-matching.
|
||||||
*/
|
*/
|
||||||
static QString simplifyName(const QString &name);
|
static QString simplifyName(const QString &name);
|
||||||
public slots:
|
|
||||||
void updatePixmapCache();
|
|
||||||
signals:
|
signals:
|
||||||
void pixmapUpdated();
|
void pixmapUpdated();
|
||||||
void cardInfoChanged(CardInfo *card);
|
void cardInfoChanged(CardInfo *card);
|
||||||
|
@ -237,10 +183,11 @@ protected:
|
||||||
*/
|
*/
|
||||||
SetNameMap sets;
|
SetNameMap sets;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A dummy card returned by getCard() ad a fallback
|
||||||
|
*/
|
||||||
CardInfo *noCard;
|
CardInfo *noCard;
|
||||||
|
|
||||||
QThread *pictureLoaderThread;
|
|
||||||
PictureLoader *pictureLoader;
|
|
||||||
LoadStatus loadStatus;
|
LoadStatus loadStatus;
|
||||||
bool detectedFirstRun;
|
bool detectedFirstRun;
|
||||||
private:
|
private:
|
||||||
|
@ -258,13 +205,17 @@ public:
|
||||||
void clear();
|
void clear();
|
||||||
void addCard(CardInfo *card);
|
void addCard(CardInfo *card);
|
||||||
void removeCard(CardInfo *card);
|
void removeCard(CardInfo *card);
|
||||||
CardInfo *getCard(const QString &cardName = QString(), bool createIfNotFound = true);
|
/*
|
||||||
|
* Get card object by name. Ensured to return a valid CardInfo * object; check noCard
|
||||||
|
*/
|
||||||
|
CardInfo *getCard(const QString &cardName = QString(), bool createIfNotFound = false);
|
||||||
|
QList <CardInfo *> getCards(const QStringList &cardNames);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get a card by its simple name. The name will be simplified in this
|
* Get a card by its simple name. The name will be simplified in this
|
||||||
* function, so you don't need to simplify it beforehand.
|
* function, so you don't need to simplify it beforehand.
|
||||||
*/
|
*/
|
||||||
CardInfo *getCardBySimpleName(const QString &cardName = QString(), bool createIfNotFound = true);
|
CardInfo *getCardBySimpleName(const QString &cardName = QString(), bool createIfNotFound = false);
|
||||||
|
|
||||||
CardSet *getSet(const QString &setName);
|
CardSet *getSet(const QString &setName);
|
||||||
QList<CardInfo *> getCardList() const { return cards.values(); }
|
QList<CardInfo *> getCardList() const { return cards.values(); }
|
||||||
|
@ -275,20 +226,13 @@ public:
|
||||||
QStringList getAllMainCardTypes() const;
|
QStringList getAllMainCardTypes() const;
|
||||||
LoadStatus getLoadStatus() const { return loadStatus; }
|
LoadStatus getLoadStatus() const { return loadStatus; }
|
||||||
bool getLoadSuccess() const { return loadStatus == Ok; }
|
bool getLoadSuccess() const { return loadStatus == Ok; }
|
||||||
void cacheCardPixmaps(const QStringList &cardNames);
|
|
||||||
void loadImage(CardInfo *card);
|
|
||||||
bool hasDetectedFirstRun();
|
bool hasDetectedFirstRun();
|
||||||
|
void refreshCachedReverseRelatedCards();
|
||||||
public slots:
|
public slots:
|
||||||
void clearPixmapCache();
|
|
||||||
LoadStatus loadCardDatabase(const QString &path, bool tokens = false);
|
LoadStatus loadCardDatabase(const QString &path, bool tokens = false);
|
||||||
void loadCustomCardDatabases(const QString &path);
|
void loadCustomCardDatabases(const QString &path);
|
||||||
void emitCardListChanged();
|
void emitCardListChanged();
|
||||||
private slots:
|
private slots:
|
||||||
void imageLoaded(CardInfo *card, QImage image);
|
|
||||||
void picDownloadChanged();
|
|
||||||
void picDownloadHqChanged();
|
|
||||||
void picsPathChanged();
|
|
||||||
|
|
||||||
void loadCardDatabase();
|
void loadCardDatabase();
|
||||||
void loadTokenDatabase();
|
void loadTokenDatabase();
|
||||||
signals:
|
signals:
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include "carditem.h"
|
#include "carditem.h"
|
||||||
#include "carddatabase.h"
|
#include "carddatabase.h"
|
||||||
|
#include "pictureloader.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
CardInfoPicture::CardInfoPicture(QWidget *parent)
|
CardInfoPicture::CardInfoPicture(QWidget *parent)
|
||||||
|
@ -40,13 +41,13 @@ void CardInfoPicture::updatePixmap()
|
||||||
void CardInfoPicture::loadPixmap()
|
void CardInfoPicture::loadPixmap()
|
||||||
{
|
{
|
||||||
if(info)
|
if(info)
|
||||||
info->getPixmap(size(), resizedPixmap);
|
PictureLoader::getPixmap(resizedPixmap, info, size());
|
||||||
else
|
else
|
||||||
resizedPixmap = QPixmap();
|
resizedPixmap = QPixmap();
|
||||||
|
|
||||||
|
|
||||||
if (resizedPixmap.isNull())
|
if (resizedPixmap.isNull())
|
||||||
db->getCard()->getPixmap(size(), resizedPixmap);
|
PictureLoader::getPixmap(resizedPixmap, db->getCard(), size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardInfoPicture::paintEvent(QPaintEvent *)
|
void CardInfoPicture::paintEvent(QPaintEvent *)
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "cardinfowidget.h"
|
#include "cardinfowidget.h"
|
||||||
#include "carditem.h"
|
#include "carditem.h"
|
||||||
#include "carddatabase.h"
|
#include "carddatabase.h"
|
||||||
|
#include "pictureloader.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "settingscache.h"
|
#include "settingscache.h"
|
||||||
|
|
||||||
|
@ -195,10 +196,10 @@ void CardInfoWidget::updatePixmap()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QPixmap resizedPixmap;
|
QPixmap resizedPixmap;
|
||||||
info->getPixmap(QSize(pixmapWidth, pixmapWidth * aspectRatio), resizedPixmap);
|
PictureLoader::getPixmap(resizedPixmap, info, QSize(pixmapWidth, pixmapWidth * aspectRatio));
|
||||||
|
|
||||||
if (resizedPixmap.isNull())
|
if (resizedPixmap.isNull())
|
||||||
getCard()->getPixmap(QSize(pixmapWidth, pixmapWidth * aspectRatio), resizedPixmap);
|
PictureLoader::getPixmap(resizedPixmap, getCard(), QSize(pixmapWidth, pixmapWidth * aspectRatio));
|
||||||
cardPicture->setPixmap(resizedPixmap);
|
cardPicture->setPixmap(resizedPixmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include "decklist.h"
|
#include "decklist.h"
|
||||||
|
|
||||||
const QStringList DeckLoader::fileNameFilters = QStringList()
|
const QStringList DeckLoader::fileNameFilters = QStringList()
|
||||||
<< QObject::tr("Common deck formats (*.cod *.dec *.mwDeck)")
|
<< QObject::tr("Common deck formats (*.cod *.dec *.txt *.mwDeck)")
|
||||||
<< QObject::tr("All files (*.*)");
|
<< QObject::tr("All files (*.*)");
|
||||||
|
|
||||||
DeckLoader::DeckLoader()
|
DeckLoader::DeckLoader()
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QEvent>
|
#include <QEvent>
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
|
#include <QMessageBox>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "dlg_connect.h"
|
#include "dlg_connect.h"
|
||||||
#include "settingscache.h"
|
#include "settingscache.h"
|
||||||
|
@ -149,6 +150,12 @@ void DlgConnect::actOk()
|
||||||
settingsCache->servers().setPreviousHostList(hostList);
|
settingsCache->servers().setPreviousHostList(hostList);
|
||||||
settingsCache->servers().setPrevioushostindex(previousHosts->currentIndex());
|
settingsCache->servers().setPrevioushostindex(previousHosts->currentIndex());
|
||||||
|
|
||||||
|
if(playernameEdit->text().isEmpty())
|
||||||
|
{
|
||||||
|
QMessageBox::critical(this, tr("Connect Warning"), tr("The player name can't be empty."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
accept();
|
accept();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -133,6 +133,7 @@ DlgCreateGame::DlgCreateGame(TabRoom *_room, const QMap<int, QString> &_gameType
|
||||||
actReset();
|
actReset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
descriptionEdit->setFocus();
|
||||||
clearButton = new QPushButton(tr("&Clear"));
|
clearButton = new QPushButton(tr("&Clear"));
|
||||||
buttonBox->addButton(QDialogButtonBox::Cancel);
|
buttonBox->addButton(QDialogButtonBox::Cancel);
|
||||||
buttonBox->addButton(clearButton, QDialogButtonBox::ActionRole);
|
buttonBox->addButton(clearButton, QDialogButtonBox::ActionRole);
|
||||||
|
@ -205,7 +206,7 @@ void DlgCreateGame::actReset()
|
||||||
gameTypeCheckBoxIterator.value()->setChecked(false);
|
gameTypeCheckBoxIterator.value()->setChecked(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
descriptionEdit->setFocus();
|
descriptionEdit->setFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -361,6 +361,11 @@ void DlgRegister::actOk()
|
||||||
QMessageBox::critical(this, tr("Registration Warning"), tr("Your email addresses do not match, please try again."));
|
QMessageBox::critical(this, tr("Registration Warning"), tr("Your email addresses do not match, please try again."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if(playernameEdit->text().isEmpty())
|
||||||
|
{
|
||||||
|
QMessageBox::critical(this, tr("Registration Warning"), tr("The player name can't be empty."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
settingsCache->servers().setHostName(hostEdit->text());
|
settingsCache->servers().setHostName(hostEdit->text());
|
||||||
settingsCache->servers().setPort(portEdit->text());
|
settingsCache->servers().setPort(portEdit->text());
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
#include "soundengine.h"
|
#include "soundengine.h"
|
||||||
#include "sequenceEdit/shortcutstab.h"
|
#include "sequenceEdit/shortcutstab.h"
|
||||||
|
|
||||||
#define LINKING_FAQ_URL "https://github.com/Cockatrice/Cockatrice/wiki/Custom-Download-URLs"
|
#define WIKI_CUSTOM_PIC_URL "https://github.com/Cockatrice/Cockatrice/wiki/Custom-Download-URLs"
|
||||||
|
|
||||||
GeneralSettingsPage::GeneralSettingsPage()
|
GeneralSettingsPage::GeneralSettingsPage()
|
||||||
{
|
{
|
||||||
|
@ -44,7 +44,6 @@ GeneralSettingsPage::GeneralSettingsPage()
|
||||||
}
|
}
|
||||||
|
|
||||||
picDownloadCheckBox.setChecked(settingsCache->getPicDownload());
|
picDownloadCheckBox.setChecked(settingsCache->getPicDownload());
|
||||||
picDownloadHqCheckBox.setChecked(settingsCache->getPicDownloadHq());
|
|
||||||
updateNotificationCheckBox.setChecked(settingsCache->getNotifyAboutUpdates());
|
updateNotificationCheckBox.setChecked(settingsCache->getNotifyAboutUpdates());
|
||||||
|
|
||||||
pixmapCacheEdit.setMinimum(PIXMAPCACHE_SIZE_MIN);
|
pixmapCacheEdit.setMinimum(PIXMAPCACHE_SIZE_MIN);
|
||||||
|
@ -53,20 +52,22 @@ GeneralSettingsPage::GeneralSettingsPage()
|
||||||
pixmapCacheEdit.setSingleStep(64);
|
pixmapCacheEdit.setSingleStep(64);
|
||||||
pixmapCacheEdit.setValue(settingsCache->getPixmapCacheSize());
|
pixmapCacheEdit.setValue(settingsCache->getPixmapCacheSize());
|
||||||
pixmapCacheEdit.setSuffix(" MB");
|
pixmapCacheEdit.setSuffix(" MB");
|
||||||
picDownloadHqCheckBox.setChecked(settingsCache->getPicDownloadHq());
|
|
||||||
picDownloadCheckBox.setChecked(settingsCache->getPicDownload());
|
|
||||||
|
|
||||||
highQualityURLEdit = new QLineEdit(settingsCache->getPicUrlHq());
|
defaultUrlEdit = new QLineEdit(settingsCache->getPicUrl());
|
||||||
highQualityURLEdit->setEnabled(settingsCache->getPicDownloadHq());
|
fallbackUrlEdit = new QLineEdit(settingsCache->getPicUrlFallback());
|
||||||
|
|
||||||
connect(&clearDownloadedPicsButton, SIGNAL(clicked()), this, SLOT(clearDownloadedPicsButtonClicked()));
|
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(&picDownloadCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setPicDownload(int)));
|
||||||
connect(&picDownloadHqCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setPicDownloadHq(int)));
|
|
||||||
connect(&pixmapCacheEdit, SIGNAL(valueChanged(int)), settingsCache, SLOT(setPixmapCacheSize(int)));
|
connect(&pixmapCacheEdit, SIGNAL(valueChanged(int)), settingsCache, SLOT(setPixmapCacheSize(int)));
|
||||||
connect(&picDownloadHqCheckBox, SIGNAL(clicked(bool)), this, SLOT(setEnabledStatus(bool)));
|
|
||||||
connect(&updateNotificationCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setNotifyAboutUpdate(int)));
|
connect(&updateNotificationCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setNotifyAboutUpdate(int)));
|
||||||
connect(highQualityURLEdit, SIGNAL(textChanged(QString)), settingsCache, SLOT(setPicUrlHq(QString)));
|
connect(&picDownloadCheckBox, SIGNAL(clicked(bool)), this, SLOT(setEnabledStatus(bool)));
|
||||||
|
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()));
|
||||||
|
|
||||||
|
setEnabledStatus(settingsCache->getPicDownload());
|
||||||
|
|
||||||
QGridLayout *personalGrid = new QGridLayout;
|
QGridLayout *personalGrid = new QGridLayout;
|
||||||
personalGrid->addWidget(&languageLabel, 0, 0);
|
personalGrid->addWidget(&languageLabel, 0, 0);
|
||||||
|
@ -74,15 +75,18 @@ GeneralSettingsPage::GeneralSettingsPage()
|
||||||
personalGrid->addWidget(&pixmapCacheLabel, 1, 0);
|
personalGrid->addWidget(&pixmapCacheLabel, 1, 0);
|
||||||
personalGrid->addWidget(&pixmapCacheEdit, 1, 1);
|
personalGrid->addWidget(&pixmapCacheEdit, 1, 1);
|
||||||
personalGrid->addWidget(&updateNotificationCheckBox, 2, 0);
|
personalGrid->addWidget(&updateNotificationCheckBox, 2, 0);
|
||||||
personalGrid->addWidget(&picDownloadCheckBox, 3, 0);
|
personalGrid->addWidget(&picDownloadCheckBox, 3, 0, 1, 3);
|
||||||
personalGrid->addWidget(&picDownloadHqCheckBox, 4, 0);
|
personalGrid->addWidget(&defaultUrlLabel, 4, 0, 1, 1);
|
||||||
personalGrid->addWidget(&highQualityURLLabel, 5, 0);
|
personalGrid->addWidget(defaultUrlEdit, 4, 1, 1, 1);
|
||||||
personalGrid->addWidget(highQualityURLEdit, 5, 1);
|
personalGrid->addWidget(&defaultUrlRestoreButton, 4, 2, 1, 1);
|
||||||
personalGrid->addWidget(&highQualityURLLinkLabel, 6, 1);
|
personalGrid->addWidget(&fallbackUrlLabel, 5, 0, 1, 1);
|
||||||
personalGrid->addWidget(&clearDownloadedPicsButton, 6, 0);
|
personalGrid->addWidget(fallbackUrlEdit, 5, 1, 1, 1);
|
||||||
|
personalGrid->addWidget(&fallbackUrlRestoreButton, 5, 2, 1, 1);
|
||||||
|
personalGrid->addWidget(&urlLinkLabel, 6, 1, 1, 1);
|
||||||
|
personalGrid->addWidget(&clearDownloadedPicsButton, 7, 0, 1, 3);
|
||||||
|
|
||||||
highQualityURLLinkLabel.setTextInteractionFlags(Qt::LinksAccessibleByMouse);
|
urlLinkLabel.setTextInteractionFlags(Qt::LinksAccessibleByMouse);
|
||||||
highQualityURLLinkLabel.setOpenExternalLinks(true);
|
urlLinkLabel.setOpenExternalLinks(true);
|
||||||
|
|
||||||
personalGroupBox = new QGroupBox;
|
personalGroupBox = new QGroupBox;
|
||||||
personalGroupBox->setLayout(personalGrid);
|
personalGroupBox->setLayout(personalGrid);
|
||||||
|
@ -154,6 +158,20 @@ QString GeneralSettingsPage::languageName(const QString &qmFile)
|
||||||
return translator.translate("GeneralSettingsPage", "English");
|
return translator.translate("GeneralSettingsPage", "English");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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,7 +256,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"));
|
picDownloadCheckBox.setText(tr("Download card pictures on the fly"));
|
||||||
picDownloadHqCheckBox.setText(tr("Download card pictures from a custom URL"));
|
|
||||||
pathsGroupBox->setTitle(tr("Paths"));
|
pathsGroupBox->setTitle(tr("Paths"));
|
||||||
deckPathLabel.setText(tr("Decks directory:"));
|
deckPathLabel.setText(tr("Decks directory:"));
|
||||||
replaysPathLabel.setText(tr("Replays directory:"));
|
replaysPathLabel.setText(tr("Replays directory:"));
|
||||||
|
@ -246,15 +263,21 @@ 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:"));
|
||||||
highQualityURLLabel.setText(tr("Custom Card Download URL:"));
|
defaultUrlLabel.setText(tr("Primary download URL:"));
|
||||||
highQualityURLLinkLabel.setText(QString("<a href='%1'>%2</a>").arg(LINKING_FAQ_URL).arg(tr("Linking FAQ")));
|
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"));
|
clearDownloadedPicsButton.setText(tr("Reset/Clear Downloaded Pictures"));
|
||||||
updateNotificationCheckBox.setText(tr("Notify when new client features are available"));
|
updateNotificationCheckBox.setText(tr("Notify when new client features are available"));
|
||||||
|
defaultUrlRestoreButton.setText(tr("Reset"));
|
||||||
|
fallbackUrlRestoreButton.setText(tr("Reset"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeneralSettingsPage::setEnabledStatus(bool status)
|
void GeneralSettingsPage::setEnabledStatus(bool status)
|
||||||
{
|
{
|
||||||
highQualityURLEdit->setEnabled(status);
|
defaultUrlEdit->setEnabled(status);
|
||||||
|
fallbackUrlEdit->setEnabled(status);
|
||||||
|
defaultUrlRestoreButton.setEnabled(status);
|
||||||
|
fallbackUrlRestoreButton.setEnabled(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
AppearanceSettingsPage::AppearanceSettingsPage()
|
AppearanceSettingsPage::AppearanceSettingsPage()
|
||||||
|
|
|
@ -45,6 +45,8 @@ private slots:
|
||||||
void tokenDatabasePathButtonClicked();
|
void tokenDatabasePathButtonClicked();
|
||||||
void languageBoxChanged(int index);
|
void languageBoxChanged(int index);
|
||||||
void setEnabledStatus(bool);
|
void setEnabledStatus(bool);
|
||||||
|
void defaultUrlRestoreButtonClicked();
|
||||||
|
void fallbackUrlRestoreButtonClicked();
|
||||||
private:
|
private:
|
||||||
QStringList findQmFiles();
|
QStringList findQmFiles();
|
||||||
QString languageName(const QString &qmFile);
|
QString languageName(const QString &qmFile);
|
||||||
|
@ -53,13 +55,13 @@ private:
|
||||||
QLineEdit *picsPathEdit;
|
QLineEdit *picsPathEdit;
|
||||||
QLineEdit *cardDatabasePathEdit;
|
QLineEdit *cardDatabasePathEdit;
|
||||||
QLineEdit *tokenDatabasePathEdit;
|
QLineEdit *tokenDatabasePathEdit;
|
||||||
QLineEdit *highQualityURLEdit;
|
QLineEdit *defaultUrlEdit;
|
||||||
|
QLineEdit *fallbackUrlEdit;
|
||||||
QSpinBox pixmapCacheEdit;
|
QSpinBox pixmapCacheEdit;
|
||||||
QGroupBox *personalGroupBox;
|
QGroupBox *personalGroupBox;
|
||||||
QGroupBox *pathsGroupBox;
|
QGroupBox *pathsGroupBox;
|
||||||
QComboBox languageBox;
|
QComboBox languageBox;
|
||||||
QCheckBox picDownloadCheckBox;
|
QCheckBox picDownloadCheckBox;
|
||||||
QCheckBox picDownloadHqCheckBox;
|
|
||||||
QCheckBox updateNotificationCheckBox;
|
QCheckBox updateNotificationCheckBox;
|
||||||
QLabel languageLabel;
|
QLabel languageLabel;
|
||||||
QLabel pixmapCacheLabel;
|
QLabel pixmapCacheLabel;
|
||||||
|
@ -68,9 +70,12 @@ private:
|
||||||
QLabel picsPathLabel;
|
QLabel picsPathLabel;
|
||||||
QLabel cardDatabasePathLabel;
|
QLabel cardDatabasePathLabel;
|
||||||
QLabel tokenDatabasePathLabel;
|
QLabel tokenDatabasePathLabel;
|
||||||
QLabel highQualityURLLabel;
|
QLabel defaultUrlLabel;
|
||||||
QLabel highQualityURLLinkLabel;
|
QLabel fallbackUrlLabel;
|
||||||
|
QLabel urlLinkLabel;
|
||||||
QPushButton clearDownloadedPicsButton;
|
QPushButton clearDownloadedPicsButton;
|
||||||
|
QPushButton defaultUrlRestoreButton;
|
||||||
|
QPushButton fallbackUrlRestoreButton;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AppearanceSettingsPage : public AbstractSettingsPage {
|
class AppearanceSettingsPage : public AbstractSettingsPage {
|
||||||
|
|
|
@ -54,11 +54,7 @@ QSystemTrayIcon *trayIcon;
|
||||||
ThemeManager *themeManager;
|
ThemeManager *themeManager;
|
||||||
|
|
||||||
const QString translationPrefix = "cockatrice";
|
const QString translationPrefix = "cockatrice";
|
||||||
#ifdef TRANSLATION_PATH
|
QString translationPath;
|
||||||
QString translationPath = TRANSLATION_PATH;
|
|
||||||
#else
|
|
||||||
QString translationPath = QString();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if QT_VERSION < 0x050000
|
#if QT_VERSION < 0x050000
|
||||||
static void myMessageOutput(QtMsgType /*type*/, const char *msg)
|
static void myMessageOutput(QtMsgType /*type*/, const char *msg)
|
||||||
|
@ -136,13 +132,17 @@ int main(int argc, char *argv[])
|
||||||
QCoreApplication::setOrganizationDomain("cockatrice.de");
|
QCoreApplication::setOrganizationDomain("cockatrice.de");
|
||||||
QCoreApplication::setApplicationName("Cockatrice");
|
QCoreApplication::setApplicationName("Cockatrice");
|
||||||
|
|
||||||
if (translationPath.isEmpty()) {
|
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
translationPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
|
qApp->setAttribute(Qt::AA_DontShowIconsInMenus, true);
|
||||||
#elif defined(Q_OS_WIN)
|
#endif
|
||||||
translationPath = app.applicationDirPath() + "/translations";
|
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
translationPath = qApp->applicationDirPath() + "/../Resources/translations";
|
||||||
|
#elif defined(Q_OS_WIN)
|
||||||
|
translationPath = qApp->applicationDirPath() + "/translations";
|
||||||
|
#else // linux
|
||||||
|
translationPath = qApp->applicationDirPath() + "/../share/cockatrice/translations";
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
rng = new RNG_SFMT;
|
rng = new RNG_SFMT;
|
||||||
settingsCache = new SettingsCache;
|
settingsCache = new SettingsCache;
|
||||||
|
@ -200,6 +200,9 @@ int main(int argc, char *argv[])
|
||||||
qDebug() << "Could not create " + dataDir + "/customsets folder.";
|
qDebug() << "Could not create " + dataDir + "/customsets folder.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// when all the cards have been loaded, resolve the reverse-related tags
|
||||||
|
db->refreshCachedReverseRelatedCards();
|
||||||
|
|
||||||
if (settingsValid()) {
|
if (settingsValid()) {
|
||||||
qDebug("main(): starting main program");
|
qDebug("main(): starting main program");
|
||||||
|
|
||||||
|
@ -212,7 +215,9 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
ui.show();
|
ui.show();
|
||||||
qDebug("main(): ui.show() finished");
|
qDebug("main(): ui.show() finished");
|
||||||
|
#if QT_VERSION > 0x050000
|
||||||
|
app.setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||||
|
#endif
|
||||||
app.exec();
|
app.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -190,8 +190,15 @@ void MessageLogWidget::logShuffle(Player *player, CardZone *zone)
|
||||||
|
|
||||||
void MessageLogWidget::logRollDie(Player *player, int sides, int roll)
|
void MessageLogWidget::logRollDie(Player *player, int sides, int roll)
|
||||||
{
|
{
|
||||||
|
QString coinOptions[2] = {tr("Heads (1)"), tr("Tails (2)")};
|
||||||
soundEngine->playSound("roll_dice");
|
soundEngine->playSound("roll_dice");
|
||||||
if (isFemale(player))
|
|
||||||
|
if (sides == 2)
|
||||||
|
if (isFemale(player))
|
||||||
|
appendHtmlServerMessage(tr("%1 flipped a coin. It landed as %2.", "female").arg(sanitizeHtml(player->getName())).arg("<font color=\"blue\">" + coinOptions[roll - 1] + "</font>"));
|
||||||
|
else
|
||||||
|
appendHtmlServerMessage(tr("%1 flipped a coin. It landed as %2.", "male").arg(sanitizeHtml(player->getName())).arg("<font color=\"blue\">" + coinOptions[roll - 1] + "</font>"));
|
||||||
|
else if (isFemale(player))
|
||||||
appendHtmlServerMessage(tr("%1 rolls a %2 with a %3-sided die.", "female").arg(sanitizeHtml(player->getName())).arg("<font color=\"blue\">" + QString::number(roll) + "</font>").arg("<font color=\"blue\">" + QString::number(sides) + "</font>"));
|
appendHtmlServerMessage(tr("%1 rolls a %2 with a %3-sided die.", "female").arg(sanitizeHtml(player->getName())).arg("<font color=\"blue\">" + QString::number(roll) + "</font>").arg("<font color=\"blue\">" + QString::number(sides) + "</font>"));
|
||||||
else
|
else
|
||||||
appendHtmlServerMessage(tr("%1 rolls a %2 with a %3-sided die.", "male").arg(sanitizeHtml(player->getName())).arg("<font color=\"blue\">" + QString::number(roll) + "</font>").arg("<font color=\"blue\">" + QString::number(sides) + "</font>"));
|
appendHtmlServerMessage(tr("%1 rolls a %2 with a %3-sided die.", "male").arg(sanitizeHtml(player->getName())).arg("<font color=\"blue\">" + QString::number(roll) + "</font>").arg("<font color=\"blue\">" + QString::number(sides) + "</font>"));
|
||||||
|
|
476
cockatrice/src/pictureloader.cpp
Normal file
476
cockatrice/src/pictureloader.cpp
Normal file
|
@ -0,0 +1,476 @@
|
||||||
|
#include "pictureloader.h"
|
||||||
|
#include "carddatabase.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "settingscache.h"
|
||||||
|
#include "thememanager.h"
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QCryptographicHash>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QImageReader>
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
#include <QNetworkRequest>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QPixmapCache>
|
||||||
|
#include <QSet>
|
||||||
|
#include <QSvgRenderer>
|
||||||
|
#include <QThread>
|
||||||
|
#include <QUrl>
|
||||||
|
|
||||||
|
// never cache more than 300 cards at once for a single deck
|
||||||
|
#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()(CardSet *a, CardSet *b) const
|
||||||
|
{
|
||||||
|
if(a->getEnabled())
|
||||||
|
{
|
||||||
|
if(b->getEnabled())
|
||||||
|
{
|
||||||
|
// both enabled: sort by key
|
||||||
|
return a->getSortKey() < b->getSortKey();
|
||||||
|
} else {
|
||||||
|
// only a enabled
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(b->getEnabled())
|
||||||
|
{
|
||||||
|
// only b enabled
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
// both disabled: sort by key
|
||||||
|
return a->getSortKey() < b->getSortKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
PictureToLoad::PictureToLoad(CardInfo *_card)
|
||||||
|
: card(_card), setIndex(0)
|
||||||
|
{
|
||||||
|
if (card) {
|
||||||
|
sortedSets = card->getSets();
|
||||||
|
qSort(sortedSets.begin(), sortedSets.end(), SetDownloadPriorityComparator());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PictureToLoad::nextSet()
|
||||||
|
{
|
||||||
|
if (setIndex == sortedSets.size() - 1)
|
||||||
|
return false;
|
||||||
|
++setIndex;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString PictureToLoad::getSetName() const
|
||||||
|
{
|
||||||
|
if (setIndex < sortedSets.size())
|
||||||
|
return sortedSets[setIndex]->getCorrectedShortName();
|
||||||
|
else
|
||||||
|
return QString("");
|
||||||
|
}
|
||||||
|
|
||||||
|
CardSet *PictureToLoad::getCurrentSet() const
|
||||||
|
{
|
||||||
|
if (setIndex < sortedSets.size())
|
||||||
|
return sortedSets[setIndex];
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList PictureLoader::md5Blacklist = QStringList()
|
||||||
|
<< "db0c48db407a907c16ade38de048a441"; // card back returned by gatherer when card is not found
|
||||||
|
|
||||||
|
PictureLoader::PictureLoader()
|
||||||
|
: QObject(0),
|
||||||
|
downloadRunning(false), loadQueueRunning(false)
|
||||||
|
{
|
||||||
|
picsPath = settingsCache->getPicsPath();
|
||||||
|
picDownload = settingsCache->getPicDownload();
|
||||||
|
|
||||||
|
connect(this, SIGNAL(startLoadQueue()), this, SLOT(processLoadQueue()), Qt::QueuedConnection);
|
||||||
|
connect(settingsCache, SIGNAL(picsPathChanged()), this, SLOT(picsPathChanged()));
|
||||||
|
connect(settingsCache, SIGNAL(picDownloadChanged()), this, SLOT(picDownloadChanged()));
|
||||||
|
|
||||||
|
networkManager = new QNetworkAccessManager(this);
|
||||||
|
connect(networkManager, SIGNAL(finished(QNetworkReply *)), this, SLOT(picDownloadFinished(QNetworkReply *)));
|
||||||
|
|
||||||
|
pictureLoaderThread = new QThread;
|
||||||
|
pictureLoaderThread->start(QThread::LowPriority);
|
||||||
|
moveToThread(pictureLoaderThread);
|
||||||
|
}
|
||||||
|
|
||||||
|
PictureLoader::~PictureLoader()
|
||||||
|
{
|
||||||
|
pictureLoaderThread->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PictureLoader::processLoadQueue()
|
||||||
|
{
|
||||||
|
if (loadQueueRunning)
|
||||||
|
return;
|
||||||
|
|
||||||
|
loadQueueRunning = true;
|
||||||
|
forever {
|
||||||
|
mutex.lock();
|
||||||
|
if (loadQueue.isEmpty()) {
|
||||||
|
mutex.unlock();
|
||||||
|
loadQueueRunning = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cardBeingLoaded = loadQueue.takeFirst();
|
||||||
|
mutex.unlock();
|
||||||
|
|
||||||
|
QString setName = cardBeingLoaded.getSetName();
|
||||||
|
QString correctedCardname = cardBeingLoaded.getCard()->getCorrectedName();
|
||||||
|
qDebug() << "Trying to load picture (set: " << setName << " card: " << correctedCardname << ")";
|
||||||
|
|
||||||
|
if(cardImageExistsOnDisk(setName, correctedCardname))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (picDownload) {
|
||||||
|
qDebug() << "Picture NOT found, trying to download (set: " << setName << " card: " << correctedCardname << ")";
|
||||||
|
cardsToDownload.append(cardBeingLoaded);
|
||||||
|
cardBeingLoaded=0;
|
||||||
|
if (!downloadRunning)
|
||||||
|
startNextPicDownload();
|
||||||
|
} else {
|
||||||
|
if (cardBeingLoaded.nextSet())
|
||||||
|
{
|
||||||
|
qDebug() << "Picture NOT found and download disabled, moving to next set (newset: " << setName << " card: " << correctedCardname << ")";
|
||||||
|
mutex.lock();
|
||||||
|
loadQueue.prepend(cardBeingLoaded);
|
||||||
|
cardBeingLoaded=0;
|
||||||
|
mutex.unlock();
|
||||||
|
} else {
|
||||||
|
qDebug() << "Picture NOT found, download disabled, no more sets to try: BAILING OUT (oldset: " << setName << " card: " << correctedCardname << ")";
|
||||||
|
imageLoaded(cardBeingLoaded.getCard(), QImage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PictureLoader::cardImageExistsOnDisk(QString & setName, QString & correctedCardname)
|
||||||
|
{
|
||||||
|
QImage image;
|
||||||
|
QImageReader imgReader;
|
||||||
|
imgReader.setDecideFormatFromContent(true);
|
||||||
|
|
||||||
|
//The list of paths to the folders in which to search for images
|
||||||
|
QList<QString> picsPaths = QList<QString>() << picsPath + "/CUSTOM/" + correctedCardname;
|
||||||
|
|
||||||
|
if(!setName.isEmpty())
|
||||||
|
{
|
||||||
|
picsPaths << picsPath + "/" + setName + "/" + correctedCardname
|
||||||
|
<< picsPath + "/downloadedPics/" + setName + "/" + correctedCardname;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Iterates through the list of paths, searching for images with the desired name with any QImageReader-supported extension
|
||||||
|
for (int i = 0; i < picsPaths.length(); i ++) {
|
||||||
|
imgReader.setFileName(picsPaths.at(i));
|
||||||
|
if (imgReader.read(&image)) {
|
||||||
|
qDebug() << "Picture found on disk (set: " << setName << " card: " << correctedCardname << ")";
|
||||||
|
imageLoaded(cardBeingLoaded.getCard(), image);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
imgReader.setFileName(picsPaths.at(i) + ".full");
|
||||||
|
if (imgReader.read(&image)) {
|
||||||
|
qDebug() << "Picture.full found on disk (set: " << setName << " card: " << correctedCardname << ")";
|
||||||
|
imageLoaded(cardBeingLoaded.getCard(), image);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString PictureLoader::getPicUrl()
|
||||||
|
{
|
||||||
|
if (!picDownload) return QString("");
|
||||||
|
|
||||||
|
CardInfo *card = cardBeingDownloaded.getCard();
|
||||||
|
CardSet *set=cardBeingDownloaded.getCurrentSet();
|
||||||
|
QString picUrl = QString("");
|
||||||
|
|
||||||
|
// if sets have been defined for the card, they can contain custom picUrls
|
||||||
|
if(set)
|
||||||
|
{
|
||||||
|
picUrl = card->getCustomPicURL(set->getShortName());
|
||||||
|
if (!picUrl.isEmpty())
|
||||||
|
return picUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if a card has a muid, use the default url; if not, use the fallback
|
||||||
|
int muid = set ? card->getMuId(set->getShortName()) : 0;
|
||||||
|
picUrl = muid ? settingsCache->getPicUrl() : settingsCache->getPicUrlFallback();
|
||||||
|
|
||||||
|
picUrl.replace("!name!", QUrl::toPercentEncoding(card->getCorrectedName()));
|
||||||
|
picUrl.replace("!name_lower!", QUrl::toPercentEncoding(card->getCorrectedName().toLower()));
|
||||||
|
picUrl.replace("!cardid!", QUrl::toPercentEncoding(QString::number(muid)));
|
||||||
|
if (set)
|
||||||
|
{
|
||||||
|
picUrl.replace("!setcode!", QUrl::toPercentEncoding(set->getShortName()));
|
||||||
|
picUrl.replace("!setcode_lower!", QUrl::toPercentEncoding(set->getShortName().toLower()));
|
||||||
|
picUrl.replace("!setname!", QUrl::toPercentEncoding(set->getLongName()));
|
||||||
|
picUrl.replace("!setname_lower!", QUrl::toPercentEncoding(set->getLongName().toLower()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
picUrl.contains("!name!") ||
|
||||||
|
picUrl.contains("!name_lower!") ||
|
||||||
|
picUrl.contains("!setcode!") ||
|
||||||
|
picUrl.contains("!setcode_lower!") ||
|
||||||
|
picUrl.contains("!setname!") ||
|
||||||
|
picUrl.contains("!setname_lower!") ||
|
||||||
|
picUrl.contains("!cardid!")
|
||||||
|
)
|
||||||
|
{
|
||||||
|
qDebug() << "Insufficient card data to download" << card->getName() << "Url:" << picUrl;
|
||||||
|
return QString("");
|
||||||
|
}
|
||||||
|
|
||||||
|
return picUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PictureLoader::startNextPicDownload()
|
||||||
|
{
|
||||||
|
if (cardsToDownload.isEmpty()) {
|
||||||
|
cardBeingDownloaded = 0;
|
||||||
|
downloadRunning = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
downloadRunning = true;
|
||||||
|
|
||||||
|
cardBeingDownloaded = cardsToDownload.takeFirst();
|
||||||
|
|
||||||
|
QString picUrl = getPicUrl();
|
||||||
|
if (picUrl.isEmpty()) {
|
||||||
|
downloadRunning = false;
|
||||||
|
picDownloadFailed();
|
||||||
|
} else {
|
||||||
|
QUrl url(picUrl);
|
||||||
|
|
||||||
|
QNetworkRequest req(url);
|
||||||
|
qDebug() << "starting picture download:" << cardBeingDownloaded.getCard()->getName() << "Url:" << req.url();
|
||||||
|
networkManager->get(req);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PictureLoader::picDownloadFailed()
|
||||||
|
{
|
||||||
|
if (cardBeingDownloaded.nextSet())
|
||||||
|
{
|
||||||
|
qDebug() << "Picture NOT found, download failed, moving to next set (newset: " << cardBeingDownloaded.getSetName() << " card: " << cardBeingDownloaded.getCard()->getCorrectedName() << ")";
|
||||||
|
mutex.lock();
|
||||||
|
loadQueue.prepend(cardBeingDownloaded);
|
||||||
|
mutex.unlock();
|
||||||
|
emit startLoadQueue();
|
||||||
|
} else {
|
||||||
|
qDebug() << "Picture NOT found, download failed, no more sets to try: BAILING OUT (oldset: " << cardBeingDownloaded.getSetName() << " card: " << cardBeingDownloaded.getCard()->getCorrectedName() << ")";
|
||||||
|
cardBeingDownloaded = 0;
|
||||||
|
imageLoaded(cardBeingDownloaded.getCard(), QImage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PictureLoader::imageIsBlackListed(const QByteArray &picData)
|
||||||
|
{
|
||||||
|
QString md5sum = QCryptographicHash::hash(picData, QCryptographicHash::Md5).toHex();
|
||||||
|
return md5Blacklist.contains(md5sum);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PictureLoader::picDownloadFinished(QNetworkReply *reply)
|
||||||
|
{
|
||||||
|
if (reply->error()) {
|
||||||
|
qDebug() << "Download failed:" << reply->errorString();
|
||||||
|
}
|
||||||
|
|
||||||
|
int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
if (statusCode == 301 || statusCode == 302) {
|
||||||
|
QUrl redirectUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
|
||||||
|
QNetworkRequest req(redirectUrl);
|
||||||
|
qDebug() << "following redirect:" << cardBeingDownloaded.getCard()->getName() << "Url:" << req.url();
|
||||||
|
networkManager->get(req);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QByteArray &picData = reply->peek(reply->size()); //peek is used to keep the data in the buffer for use by QImageReader
|
||||||
|
|
||||||
|
if(imageIsBlackListed(picData))
|
||||||
|
{
|
||||||
|
qDebug() << "Picture downloaded, but blacklisted, will consider it as not found";
|
||||||
|
picDownloadFailed();
|
||||||
|
reply->deleteLater();
|
||||||
|
startNextPicDownload();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QImage testImage;
|
||||||
|
|
||||||
|
QImageReader imgReader;
|
||||||
|
imgReader.setDecideFormatFromContent(true);
|
||||||
|
imgReader.setDevice(reply);
|
||||||
|
QString extension = "." + imgReader.format(); //the format is determined prior to reading the QImageReader data into a QImage object, as that wipes the QImageReader buffer
|
||||||
|
if (extension == ".jpeg")
|
||||||
|
extension = ".jpg";
|
||||||
|
|
||||||
|
if (imgReader.read(&testImage)) {
|
||||||
|
QString setName = cardBeingDownloaded.getSetName();
|
||||||
|
if(!setName.isEmpty())
|
||||||
|
{
|
||||||
|
if (!QDir().mkpath(picsPath + "/downloadedPics/" + setName)) {
|
||||||
|
qDebug() << picsPath + "/downloadedPics/" + setName + " could not be created.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFile newPic(picsPath + "/downloadedPics/" + setName + "/" + cardBeingDownloaded.getCard()->getCorrectedName() + extension);
|
||||||
|
if (!newPic.open(QIODevice::WriteOnly))
|
||||||
|
return;
|
||||||
|
newPic.write(picData);
|
||||||
|
newPic.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
imageLoaded(cardBeingDownloaded.getCard(), testImage);
|
||||||
|
} else {
|
||||||
|
picDownloadFailed();
|
||||||
|
}
|
||||||
|
|
||||||
|
reply->deleteLater();
|
||||||
|
startNextPicDownload();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PictureLoader::enqueueImageLoad(CardInfo *card)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&mutex);
|
||||||
|
|
||||||
|
// avoid queueing the same card more than once
|
||||||
|
if(card == 0 || card == cardBeingLoaded.getCard() || card == cardBeingDownloaded.getCard())
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach(PictureToLoad pic, loadQueue)
|
||||||
|
{
|
||||||
|
if(pic.getCard() == card)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadQueue.append(PictureToLoad(card));
|
||||||
|
emit startLoadQueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PictureLoader::picDownloadChanged()
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&mutex);
|
||||||
|
picDownload = settingsCache->getPicDownload();
|
||||||
|
|
||||||
|
QPixmapCache::clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PictureLoader::picsPathChanged()
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&mutex);
|
||||||
|
picsPath = settingsCache->getPicsPath();
|
||||||
|
|
||||||
|
QPixmapCache::clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PictureLoader::internalGetCardBackPixmap(QPixmap &pixmap, QSize size)
|
||||||
|
{
|
||||||
|
QString backCacheKey = "_trice_card_back_" + QString::number(size.width()) + QString::number(size.height());
|
||||||
|
if(!QPixmapCache::find(backCacheKey, &pixmap))
|
||||||
|
{
|
||||||
|
qDebug() << "cache fail for" << backCacheKey;
|
||||||
|
pixmap = QPixmap("theme:cardback").scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||||
|
QPixmapCache::insert(backCacheKey, pixmap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PictureLoader::getPixmap(QPixmap &pixmap, CardInfo *card, QSize size)
|
||||||
|
{
|
||||||
|
if(card)
|
||||||
|
{
|
||||||
|
if (card->getName().isEmpty()) {
|
||||||
|
internalGetCardBackPixmap(pixmap, size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// search for an exact size copy of the picure in cache
|
||||||
|
QString key = card->getPixmapCacheKey();
|
||||||
|
QString sizekey = key + QLatin1Char('_') + QString::number(size.width()) + QString::number(size.height());
|
||||||
|
if(QPixmapCache::find(sizekey, &pixmap))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// load the image and create a copy of the correct size
|
||||||
|
QPixmap bigPixmap;
|
||||||
|
if(QPixmapCache::find(key, &bigPixmap))
|
||||||
|
{
|
||||||
|
pixmap = bigPixmap.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||||
|
QPixmapCache::insert(sizekey, pixmap);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// load a temporary back picture
|
||||||
|
internalGetCardBackPixmap(pixmap, size);
|
||||||
|
|
||||||
|
if(card)
|
||||||
|
{
|
||||||
|
// add the card to the load queue
|
||||||
|
getInstance().enqueueImageLoad(card);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PictureLoader::imageLoaded(CardInfo *card, const QImage &image)
|
||||||
|
{
|
||||||
|
if(image.isNull())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(card->getUpsideDownArt())
|
||||||
|
{
|
||||||
|
QImage mirrorImage = image.mirrored(true, true);
|
||||||
|
QPixmapCache::insert(card->getPixmapCacheKey(), QPixmap::fromImage(mirrorImage));
|
||||||
|
} else {
|
||||||
|
QPixmapCache::insert(card->getPixmapCacheKey(), QPixmap::fromImage(image));
|
||||||
|
}
|
||||||
|
|
||||||
|
card->emitPixmapUpdated();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PictureLoader::clearPixmapCache(CardInfo *card)
|
||||||
|
{
|
||||||
|
if(card)
|
||||||
|
QPixmapCache::remove(card->getPixmapCacheKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
void PictureLoader::clearPixmapCache()
|
||||||
|
{
|
||||||
|
QPixmapCache::clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PictureLoader::cacheCardPixmaps(QList<CardInfo *> cards)
|
||||||
|
{
|
||||||
|
QPixmap tmp;
|
||||||
|
int max = qMin(cards.size(), CACHED_CARD_PER_DECK_MAX);
|
||||||
|
for (int i = 0; i < max; ++i)
|
||||||
|
{
|
||||||
|
CardInfo * card = cards.at(i);
|
||||||
|
if(!card)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
QString key = card->getPixmapCacheKey();
|
||||||
|
if(QPixmapCache::find(key, &tmp))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
getInstance().enqueueImageLoad(card);
|
||||||
|
}
|
||||||
|
}
|
82
cockatrice/src/pictureloader.h
Normal file
82
cockatrice/src/pictureloader.h
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
#ifndef PICTURELOADER_H
|
||||||
|
#define PICTURELOADER_H
|
||||||
|
|
||||||
|
#include <QMap>
|
||||||
|
#include <QList>
|
||||||
|
#include <QNetworkRequest>
|
||||||
|
#include <QMutex>
|
||||||
|
|
||||||
|
class CardInfo;
|
||||||
|
class CardSet;
|
||||||
|
class QNetworkAccessManager;
|
||||||
|
class QNetworkReply;
|
||||||
|
class QThread;
|
||||||
|
|
||||||
|
class PictureToLoad {
|
||||||
|
private:
|
||||||
|
class SetDownloadPriorityComparator;
|
||||||
|
|
||||||
|
CardInfo *card;
|
||||||
|
QList<CardSet *> sortedSets;
|
||||||
|
int setIndex;
|
||||||
|
bool hq;
|
||||||
|
public:
|
||||||
|
PictureToLoad(CardInfo *_card = 0);
|
||||||
|
CardInfo *getCard() const { return card; }
|
||||||
|
CardSet *getCurrentSet() const;
|
||||||
|
QString getSetName() const;
|
||||||
|
bool nextSet();
|
||||||
|
};
|
||||||
|
|
||||||
|
class PictureLoader : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
static PictureLoader& getInstance()
|
||||||
|
{
|
||||||
|
static PictureLoader instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
PictureLoader();
|
||||||
|
~PictureLoader();
|
||||||
|
// Don't implement
|
||||||
|
PictureLoader(PictureLoader const&);
|
||||||
|
void operator=(PictureLoader const&);
|
||||||
|
|
||||||
|
static QStringList md5Blacklist;
|
||||||
|
|
||||||
|
QThread *pictureLoaderThread;
|
||||||
|
QString picsPath;
|
||||||
|
QList<PictureToLoad> loadQueue;
|
||||||
|
QMutex mutex;
|
||||||
|
QNetworkAccessManager *networkManager;
|
||||||
|
QList<PictureToLoad> cardsToDownload;
|
||||||
|
PictureToLoad cardBeingLoaded;
|
||||||
|
PictureToLoad cardBeingDownloaded;
|
||||||
|
bool picDownload, downloadRunning, loadQueueRunning;
|
||||||
|
void startNextPicDownload();
|
||||||
|
void imageLoaded(CardInfo *card, const QImage &image);
|
||||||
|
QString getPicUrl();
|
||||||
|
bool cardImageExistsOnDisk(QString & setName, QString & correctedCardname);
|
||||||
|
bool imageIsBlackListed(const QByteArray &picData);
|
||||||
|
public:
|
||||||
|
void enqueueImageLoad(CardInfo *card);
|
||||||
|
static void getPixmap(QPixmap &pixmap, CardInfo *card, QSize size);
|
||||||
|
static void clearPixmapCache(CardInfo *card);
|
||||||
|
static void clearPixmapCache();
|
||||||
|
static void cacheCardPixmaps(QList<CardInfo *> cards);
|
||||||
|
protected:
|
||||||
|
static void internalGetCardBackPixmap(QPixmap &pixmap, QSize size);
|
||||||
|
private slots:
|
||||||
|
void picDownloadFinished(QNetworkReply *reply);
|
||||||
|
void picDownloadFailed();
|
||||||
|
|
||||||
|
void picDownloadChanged();
|
||||||
|
void picsPathChanged();
|
||||||
|
public slots:
|
||||||
|
void processLoadQueue();
|
||||||
|
signals:
|
||||||
|
void startLoadQueue();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -1135,7 +1135,16 @@ void Player::actCreateRelatedCard()
|
||||||
|
|
||||||
// get the target card name
|
// get the target card name
|
||||||
QAction *action = static_cast<QAction *>(sender());
|
QAction *action = static_cast<QAction *>(sender());
|
||||||
CardInfo *cardInfo = db->getCard(action->text());
|
|
||||||
|
// removes p/t from tokens (and leading space))
|
||||||
|
QStringList spaces = action->text().split(" ");
|
||||||
|
if (spaces.at(0).indexOf("/") != -1) // Strip space from creatures
|
||||||
|
spaces.removeFirst();
|
||||||
|
CardInfo *cardInfo = db->getCard(spaces.join(" "));
|
||||||
|
|
||||||
|
// get the target token's location
|
||||||
|
// TODO: Define this QPoint into its own function along with the one below
|
||||||
|
QPoint gridPoint = QPoint(-1, table->clampValidTableRow(2 - cardInfo->getTableRow()));
|
||||||
|
|
||||||
// create the token for the related card
|
// create the token for the related card
|
||||||
Command_CreateToken cmd;
|
Command_CreateToken cmd;
|
||||||
|
@ -1146,7 +1155,11 @@ void Player::actCreateRelatedCard()
|
||||||
cmd.set_annotation(settingsCache->getAnnotateTokens() ? cardInfo->getText().toStdString() : QString().toStdString());
|
cmd.set_annotation(settingsCache->getAnnotateTokens() ? cardInfo->getText().toStdString() : QString().toStdString());
|
||||||
cmd.set_destroy_on_zone_change(true);
|
cmd.set_destroy_on_zone_change(true);
|
||||||
cmd.set_target_zone(sourceCard->getZone()->getName().toStdString());
|
cmd.set_target_zone(sourceCard->getZone()->getName().toStdString());
|
||||||
cmd.set_target_card_id(sourceCard->getId());
|
cmd.set_x(gridPoint.x());
|
||||||
|
cmd.set_y(gridPoint.y());
|
||||||
|
|
||||||
|
if(!cardInfo->getIsToken())
|
||||||
|
cmd.set_target_card_id(sourceCard->getId());
|
||||||
|
|
||||||
sendGameCommand(cmd);
|
sendGameCommand(cmd);
|
||||||
}
|
}
|
||||||
|
@ -2115,6 +2128,9 @@ void Player::actSetPT()
|
||||||
|
|
||||||
void Player::actDrawArrow()
|
void Player::actDrawArrow()
|
||||||
{
|
{
|
||||||
|
if(!game->getActiveCard())
|
||||||
|
return;
|
||||||
|
|
||||||
game->getActiveCard()->drawArrow(Qt::red);
|
game->getActiveCard()->drawArrow(Qt::red);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2183,6 +2199,9 @@ void Player::actSetAnnotation()
|
||||||
|
|
||||||
void Player::actAttach()
|
void Player::actAttach()
|
||||||
{
|
{
|
||||||
|
if(!game->getActiveCard())
|
||||||
|
return;
|
||||||
|
|
||||||
ArrowAttachItem *arrow = new ArrowAttachItem(game->getActiveCard());
|
ArrowAttachItem *arrow = new ArrowAttachItem(game->getActiveCard());
|
||||||
scene()->addItem(arrow);
|
scene()->addItem(arrow);
|
||||||
arrow->grabMouse();
|
arrow->grabMouse();
|
||||||
|
@ -2190,6 +2209,9 @@ void Player::actAttach()
|
||||||
|
|
||||||
void Player::actUnattach()
|
void Player::actUnattach()
|
||||||
{
|
{
|
||||||
|
if(!game->getActiveCard())
|
||||||
|
return;
|
||||||
|
|
||||||
Command_AttachCard cmd;
|
Command_AttachCard cmd;
|
||||||
cmd.set_start_zone(game->getActiveCard()->getZone()->getName().toStdString());
|
cmd.set_start_zone(game->getActiveCard()->getZone()->getName().toStdString());
|
||||||
cmd.set_card_id(game->getActiveCard()->getId());
|
cmd.set_card_id(game->getActiveCard()->getId());
|
||||||
|
@ -2268,16 +2290,25 @@ void Player::actCardCounterTrigger()
|
||||||
|
|
||||||
void Player::actPlay()
|
void Player::actPlay()
|
||||||
{
|
{
|
||||||
|
if(!game->getActiveCard())
|
||||||
|
return;
|
||||||
|
|
||||||
playCard(game->getActiveCard(), false, game->getActiveCard()->getInfo()->getCipt());
|
playCard(game->getActiveCard(), false, game->getActiveCard()->getInfo()->getCipt());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::actHide()
|
void Player::actHide()
|
||||||
{
|
{
|
||||||
|
if(!game->getActiveCard())
|
||||||
|
return;
|
||||||
|
|
||||||
game->getActiveCard()->getZone()->removeCard(game->getActiveCard());
|
game->getActiveCard()->getZone()->removeCard(game->getActiveCard());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::actPlayFacedown()
|
void Player::actPlayFacedown()
|
||||||
{
|
{
|
||||||
|
if(!game->getActiveCard())
|
||||||
|
return;
|
||||||
|
|
||||||
playCard(game->getActiveCard(), true, false);
|
playCard(game->getActiveCard(), true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2344,7 +2375,8 @@ void Player::updateCardMenu(CardItem *card)
|
||||||
cardMenu->addAction(aPeek);
|
cardMenu->addAction(aPeek);
|
||||||
|
|
||||||
QStringList relatedCards = card->getInfo()->getRelatedCards();
|
QStringList relatedCards = card->getInfo()->getRelatedCards();
|
||||||
if(relatedCards.size())
|
QStringList reverserelatedCards2Me = card->getInfo()->getReverseRelatedCards2Me();
|
||||||
|
if(relatedCards.size() || reverserelatedCards2Me.size())
|
||||||
{
|
{
|
||||||
QMenu * createRelatedCardMenu = cardMenu->addMenu(tr("Cr&eate related card"));
|
QMenu * createRelatedCardMenu = cardMenu->addMenu(tr("Cr&eate related card"));
|
||||||
|
|
||||||
|
@ -2352,6 +2384,11 @@ void Player::updateCardMenu(CardItem *card)
|
||||||
QAction *a = createRelatedCardMenu->addAction(relatedCards.at(i));
|
QAction *a = createRelatedCardMenu->addAction(relatedCards.at(i));
|
||||||
connect(a, SIGNAL(triggered()), this, SLOT(actCreateRelatedCard()));
|
connect(a, SIGNAL(triggered()), this, SLOT(actCreateRelatedCard()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < reverserelatedCards2Me.size(); ++i) {
|
||||||
|
QAction *a = createRelatedCardMenu->addAction(reverserelatedCards2Me.at(i));
|
||||||
|
connect(a, SIGNAL(triggered()), this, SLOT(actCreateRelatedCard()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
cardMenu->addSeparator();
|
cardMenu->addSeparator();
|
||||||
cardMenu->addAction(aAttach);
|
cardMenu->addAction(aAttach);
|
||||||
|
@ -2375,6 +2412,23 @@ void Player::updateCardMenu(CardItem *card)
|
||||||
} else if (card->getZone()->getName() == "stack") {
|
} else if (card->getZone()->getName() == "stack") {
|
||||||
cardMenu->addAction(aDrawArrow);
|
cardMenu->addAction(aDrawArrow);
|
||||||
cardMenu->addMenu(moveMenu);
|
cardMenu->addMenu(moveMenu);
|
||||||
|
|
||||||
|
QStringList relatedCards = card->getInfo()->getRelatedCards();
|
||||||
|
QStringList reverserelatedCards2Me = card->getInfo()->getReverseRelatedCards2Me();
|
||||||
|
if(relatedCards.size() || reverserelatedCards2Me.size())
|
||||||
|
{
|
||||||
|
QMenu * createRelatedCardMenu = cardMenu->addMenu(tr("Cr&eate related card"));
|
||||||
|
|
||||||
|
for (int i = 0; i < relatedCards.size(); ++i) {
|
||||||
|
QAction *a = createRelatedCardMenu->addAction(relatedCards.at(i));
|
||||||
|
connect(a, SIGNAL(triggered()), this, SLOT(actCreateRelatedCard()));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < reverserelatedCards2Me.size(); ++i) {
|
||||||
|
QAction *a = createRelatedCardMenu->addAction(reverserelatedCards2Me.at(i));
|
||||||
|
connect(a, SIGNAL(triggered()), this, SLOT(actCreateRelatedCard()));
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
cardMenu->addAction(aPlay);
|
cardMenu->addAction(aPlay);
|
||||||
cardMenu->addAction(aPlayFacedown);
|
cardMenu->addAction(aPlayFacedown);
|
||||||
|
|
|
@ -165,18 +165,15 @@ SettingsCache::SettingsCache()
|
||||||
pixmapCacheSize = PIXMAPCACHE_SIZE_DEFAULT;
|
pixmapCacheSize = PIXMAPCACHE_SIZE_DEFAULT;
|
||||||
|
|
||||||
picDownload = settings->value("personal/picturedownload", true).toBool();
|
picDownload = settings->value("personal/picturedownload", true).toBool();
|
||||||
picDownloadHq = settings->value("personal/picturedownloadhq", true).toBool();
|
|
||||||
|
|
||||||
picUrl = settings->value("personal/picUrl", PIC_URL_DEFAULT).toString();
|
picUrl = settings->value("personal/picUrl", PIC_URL_DEFAULT).toString();
|
||||||
picUrlHq = settings->value("personal/picUrlHq", PIC_URL_HQ_DEFAULT).toString();
|
|
||||||
picUrlFallback = settings->value("personal/picUrlFallback", PIC_URL_FALLBACK).toString();
|
picUrlFallback = settings->value("personal/picUrlFallback", PIC_URL_FALLBACK).toString();
|
||||||
picUrlHqFallback = settings->value("personal/picUrlHqFallback", PIC_URL_HQ_FALLBACK).toString();
|
|
||||||
|
|
||||||
mainWindowGeometry = settings->value("interface/main_window_geometry").toByteArray();
|
mainWindowGeometry = settings->value("interface/main_window_geometry").toByteArray();
|
||||||
notificationsEnabled = settings->value("interface/notificationsenabled", true).toBool();
|
notificationsEnabled = settings->value("interface/notificationsenabled", true).toBool();
|
||||||
spectatorNotificationsEnabled = settings->value("interface/specnotificationsenabled", false).toBool();
|
spectatorNotificationsEnabled = settings->value("interface/specnotificationsenabled", false).toBool();
|
||||||
doubleClickToPlay = settings->value("interface/doubleclicktoplay", true).toBool();
|
doubleClickToPlay = settings->value("interface/doubleclicktoplay", true).toBool();
|
||||||
playToStack = settings->value("interface/playtostack", false).toBool();
|
playToStack = settings->value("interface/playtostack", true).toBool();
|
||||||
annotateTokens = settings->value("interface/annotatetokens", false).toBool();
|
annotateTokens = settings->value("interface/annotatetokens", false).toBool();
|
||||||
cardInfoMinimized = settings->value("interface/cardinfominimized", 0).toInt();
|
cardInfoMinimized = settings->value("interface/cardinfominimized", 0).toInt();
|
||||||
tabGameSplitterSizes = settings->value("interface/tabgame_splittersizes").toByteArray();
|
tabGameSplitterSizes = settings->value("interface/tabgame_splittersizes").toByteArray();
|
||||||
|
@ -325,37 +322,18 @@ void SettingsCache::setPicDownload(int _picDownload)
|
||||||
emit picDownloadChanged();
|
emit picDownloadChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SettingsCache::setPicDownloadHq(int _picDownloadHq)
|
|
||||||
{
|
|
||||||
picDownloadHq = _picDownloadHq;
|
|
||||||
settings->setValue("personal/picturedownloadhq", picDownloadHq);
|
|
||||||
emit picDownloadHqChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SettingsCache::setPicUrl(const QString &_picUrl)
|
void SettingsCache::setPicUrl(const QString &_picUrl)
|
||||||
{
|
{
|
||||||
picUrl = _picUrl;
|
picUrl = _picUrl;
|
||||||
settings->setValue("personal/picUrl", picUrl);
|
settings->setValue("personal/picUrl", picUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SettingsCache::setPicUrlHq(const QString &_picUrlHq)
|
|
||||||
{
|
|
||||||
picUrlHq = _picUrlHq;
|
|
||||||
settings->setValue("personal/picUrlHq", picUrlHq);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SettingsCache::setPicUrlFallback(const QString &_picUrlFallback)
|
void SettingsCache::setPicUrlFallback(const QString &_picUrlFallback)
|
||||||
{
|
{
|
||||||
picUrlFallback = _picUrlFallback;
|
picUrlFallback = _picUrlFallback;
|
||||||
settings->setValue("personal/picUrlFallback", picUrlFallback);
|
settings->setValue("personal/picUrlFallback", picUrlFallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SettingsCache::setPicUrlHqFallback(const QString &_picUrlHqFallback)
|
|
||||||
{
|
|
||||||
picUrlHqFallback = _picUrlHqFallback;
|
|
||||||
settings->setValue("personal/picUrlHqFallback", picUrlHqFallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SettingsCache::setNotificationsEnabled(int _notificationsEnabled)
|
void SettingsCache::setNotificationsEnabled(int _notificationsEnabled)
|
||||||
{
|
{
|
||||||
notificationsEnabled = _notificationsEnabled;
|
notificationsEnabled = _notificationsEnabled;
|
||||||
|
|
|
@ -14,8 +14,6 @@
|
||||||
// the falbacks are used for cards without a muid
|
// 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_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"
|
#define PIC_URL_FALLBACK "http://gatherer.wizards.com/Handlers/Image.ashx?name=!name!&type=card"
|
||||||
#define PIC_URL_HQ_DEFAULT "http://gatherer.wizards.com/Handlers/Image.ashx?multiverseid=!cardid!&type=card"
|
|
||||||
#define PIC_URL_HQ_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
|
||||||
|
@ -32,7 +30,6 @@ signals:
|
||||||
void tokenDatabasePathChanged();
|
void tokenDatabasePathChanged();
|
||||||
void themeChanged();
|
void themeChanged();
|
||||||
void picDownloadChanged();
|
void picDownloadChanged();
|
||||||
void picDownloadHqChanged();
|
|
||||||
void displayCardNamesChanged();
|
void displayCardNamesChanged();
|
||||||
void horizontalHandChanged();
|
void horizontalHandChanged();
|
||||||
void handJustificationChanged();
|
void handJustificationChanged();
|
||||||
|
@ -60,7 +57,6 @@ private:
|
||||||
QString deckPath, replaysPath, picsPath, cardDatabasePath, tokenDatabasePath, themeName;
|
QString deckPath, replaysPath, picsPath, cardDatabasePath, tokenDatabasePath, themeName;
|
||||||
bool notifyAboutUpdates;
|
bool notifyAboutUpdates;
|
||||||
bool picDownload;
|
bool picDownload;
|
||||||
bool picDownloadHq;
|
|
||||||
bool notificationsEnabled;
|
bool notificationsEnabled;
|
||||||
bool spectatorNotificationsEnabled;
|
bool spectatorNotificationsEnabled;
|
||||||
bool doubleClickToPlay;
|
bool doubleClickToPlay;
|
||||||
|
@ -87,9 +83,7 @@ private:
|
||||||
bool ignoreUnregisteredUsers;
|
bool ignoreUnregisteredUsers;
|
||||||
bool ignoreUnregisteredUserMessages;
|
bool ignoreUnregisteredUserMessages;
|
||||||
QString picUrl;
|
QString picUrl;
|
||||||
QString picUrlHq;
|
|
||||||
QString picUrlFallback;
|
QString picUrlFallback;
|
||||||
QString picUrlHqFallback;
|
|
||||||
QString clientID;
|
QString clientID;
|
||||||
int pixmapCacheSize;
|
int pixmapCacheSize;
|
||||||
bool scaleCards;
|
bool scaleCards;
|
||||||
|
@ -127,7 +121,6 @@ public:
|
||||||
QString getChatMentionColor() const { return chatMentionColor; }
|
QString getChatMentionColor() const { return chatMentionColor; }
|
||||||
QString getChatHighlightColor() const { return chatHighlightColor; }
|
QString getChatHighlightColor() const { return chatHighlightColor; }
|
||||||
bool getPicDownload() const { return picDownload; }
|
bool getPicDownload() const { return picDownload; }
|
||||||
bool getPicDownloadHq() const { return picDownloadHq; }
|
|
||||||
bool getNotificationsEnabled() const { return notificationsEnabled; }
|
bool getNotificationsEnabled() const { return notificationsEnabled; }
|
||||||
bool getSpectatorNotificationsEnabled() const { return spectatorNotificationsEnabled; }
|
bool getSpectatorNotificationsEnabled() const { return spectatorNotificationsEnabled; }
|
||||||
bool getNotifyAboutUpdates() const { return notifyAboutUpdates; }
|
bool getNotifyAboutUpdates() const { return notifyAboutUpdates; }
|
||||||
|
@ -160,9 +153,7 @@ public:
|
||||||
bool getIgnoreUnregisteredUsers() const { return ignoreUnregisteredUsers; }
|
bool getIgnoreUnregisteredUsers() const { return ignoreUnregisteredUsers; }
|
||||||
bool getIgnoreUnregisteredUserMessages() const { return ignoreUnregisteredUserMessages; }
|
bool getIgnoreUnregisteredUserMessages() const { return ignoreUnregisteredUserMessages; }
|
||||||
QString getPicUrl() const { return picUrl; }
|
QString getPicUrl() const { return picUrl; }
|
||||||
QString getPicUrlHq() const { return picUrlHq; }
|
|
||||||
QString getPicUrlFallback() const { return picUrlFallback; }
|
QString getPicUrlFallback() const { return picUrlFallback; }
|
||||||
QString getPicUrlHqFallback() const { return picUrlHqFallback; }
|
|
||||||
int getPixmapCacheSize() const { return pixmapCacheSize; }
|
int getPixmapCacheSize() const { return pixmapCacheSize; }
|
||||||
bool getScaleCards() const { return scaleCards; }
|
bool getScaleCards() const { return scaleCards; }
|
||||||
bool getShowMessagePopup() const { return showMessagePopups; }
|
bool getShowMessagePopup() const { return showMessagePopups; }
|
||||||
|
@ -204,7 +195,6 @@ public slots:
|
||||||
void setChatMentionColor(const QString &_chatMentionColor);
|
void setChatMentionColor(const QString &_chatMentionColor);
|
||||||
void setChatHighlightColor(const QString &_chatHighlightColor);
|
void setChatHighlightColor(const QString &_chatHighlightColor);
|
||||||
void setPicDownload(int _picDownload);
|
void setPicDownload(int _picDownload);
|
||||||
void setPicDownloadHq(int _picDownloadHq);
|
|
||||||
void setNotificationsEnabled(int _notificationsEnabled);
|
void setNotificationsEnabled(int _notificationsEnabled);
|
||||||
void setSpectatorNotificationsEnabled(int _spectatorNotificationsEnabled);
|
void setSpectatorNotificationsEnabled(int _spectatorNotificationsEnabled);
|
||||||
void setDoubleClickToPlay(int _doubleClickToPlay);
|
void setDoubleClickToPlay(int _doubleClickToPlay);
|
||||||
|
@ -231,9 +221,7 @@ public slots:
|
||||||
void setIgnoreUnregisteredUsers(int _ignoreUnregisteredUsers);
|
void setIgnoreUnregisteredUsers(int _ignoreUnregisteredUsers);
|
||||||
void setIgnoreUnregisteredUserMessages(int _ignoreUnregisteredUserMessages);
|
void setIgnoreUnregisteredUserMessages(int _ignoreUnregisteredUserMessages);
|
||||||
void setPicUrl(const QString &_picUrl);
|
void setPicUrl(const QString &_picUrl);
|
||||||
void setPicUrlHq(const QString &_picUrlHq);
|
|
||||||
void setPicUrlFallback(const QString &_picUrlFallback);
|
void setPicUrlFallback(const QString &_picUrlFallback);
|
||||||
void setPicUrlHqFallback(const QString &_picUrlHqFallback);
|
|
||||||
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);
|
||||||
|
|
|
@ -89,7 +89,7 @@ void SoundEngine::playSound(QString fileName)
|
||||||
inputBuffer->setData(audioData[fileName]);
|
inputBuffer->setData(audioData[fileName]);
|
||||||
inputBuffer->open(QIODevice::ReadOnly);
|
inputBuffer->open(QIODevice::ReadOnly);
|
||||||
#if QT_VERSION >= 0x050000
|
#if QT_VERSION >= 0x050000
|
||||||
player->setVolume(settingsCache->getMasterVolume());
|
player->setVolume(settingsCache->getMasterVolume() / 100.0);
|
||||||
#endif
|
#endif
|
||||||
player->stop();
|
player->stop();
|
||||||
player->start(inputBuffer);
|
player->start(inputBuffer);
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "tab_deck_editor.h"
|
#include "tab_deck_editor.h"
|
||||||
#include "window_sets.h"
|
#include "window_sets.h"
|
||||||
#include "carddatabase.h"
|
#include "carddatabase.h"
|
||||||
|
#include "pictureloader.h"
|
||||||
#include "carddatabasemodel.h"
|
#include "carddatabasemodel.h"
|
||||||
#include "decklistmodel.h"
|
#include "decklistmodel.h"
|
||||||
#include "cardinfowidget.h"
|
#include "cardinfowidget.h"
|
||||||
|
@ -1058,7 +1059,7 @@ void TabDeckEditor::setDeck(DeckLoader *_deck)
|
||||||
deckView->expandAll();
|
deckView->expandAll();
|
||||||
setModified(false);
|
setModified(false);
|
||||||
|
|
||||||
db->cacheCardPixmaps(deckModel->getDeckList()->getCardList());
|
PictureLoader::cacheCardPixmaps(db->getCards(deckModel->getDeckList()->getCardList()));
|
||||||
deckView->expandAll();
|
deckView->expandAll();
|
||||||
setModified(false);
|
setModified(false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "settingscache.h"
|
#include "settingscache.h"
|
||||||
#include "carddatabase.h"
|
#include "carddatabase.h"
|
||||||
|
#include "pictureloader.h"
|
||||||
#include "replay_timeline_widget.h"
|
#include "replay_timeline_widget.h"
|
||||||
#include "lineeditcompleter.h"
|
#include "lineeditcompleter.h"
|
||||||
|
|
||||||
|
@ -242,7 +243,7 @@ void DeckViewContainer::deckSelectFinished(const Response &r)
|
||||||
{
|
{
|
||||||
const Response_DeckDownload &resp = r.GetExtension(Response_DeckDownload::ext);
|
const Response_DeckDownload &resp = r.GetExtension(Response_DeckDownload::ext);
|
||||||
DeckLoader newDeck(QString::fromStdString(resp.deck()));
|
DeckLoader newDeck(QString::fromStdString(resp.deck()));
|
||||||
db->cacheCardPixmaps(newDeck.getCardList());
|
PictureLoader::cacheCardPixmaps(db->getCards(newDeck.getCardList()));
|
||||||
setDeck(newDeck);
|
setDeck(newDeck);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -452,7 +453,6 @@ TabGame::TabGame(TabSupervisor *_tabSupervisor, QList<AbstractClient *> &_client
|
||||||
scene = new GameScene(phasesToolbar, this);
|
scene = new GameScene(phasesToolbar, this);
|
||||||
gameView = new GameView(scene);
|
gameView = new GameView(scene);
|
||||||
gameView->hide();
|
gameView->hide();
|
||||||
gameView->setFocusPolicy(Qt::ClickFocus);
|
|
||||||
|
|
||||||
cardInfo = new CardFrame();
|
cardInfo = new CardFrame();
|
||||||
playerListWidget = new PlayerListWidget(tabSupervisor, clients.first(), this);
|
playerListWidget = new PlayerListWidget(tabSupervisor, clients.first(), this);
|
||||||
|
@ -1044,7 +1044,7 @@ void TabGame::eventGameStateChanged(const Event_GameStateChanged &event, int /*e
|
||||||
DeckViewContainer *deckViewContainer = deckViewContainers.value(playerId);
|
DeckViewContainer *deckViewContainer = deckViewContainers.value(playerId);
|
||||||
if (playerInfo.has_deck_list()) {
|
if (playerInfo.has_deck_list()) {
|
||||||
DeckLoader newDeck(QString::fromStdString(playerInfo.deck_list()));
|
DeckLoader newDeck(QString::fromStdString(playerInfo.deck_list()));
|
||||||
db->cacheCardPixmaps(newDeck.getCardList());
|
PictureLoader::cacheCardPixmaps(db->getCards(newDeck.getCardList()));
|
||||||
deckViewContainer->setDeck(newDeck);
|
deckViewContainer->setDeck(newDeck);
|
||||||
player->setDeck(newDeck);
|
player->setDeck(newDeck);
|
||||||
}
|
}
|
||||||
|
|
|
@ -322,10 +322,10 @@ void TabLog::viewLogHistory_processResponse(const Response &resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
} else
|
} else
|
||||||
QMessageBox::information(static_cast<QWidget *>(parent()), tr("Message History"), tr("There is no messages for the selected iilters."));
|
QMessageBox::information(static_cast<QWidget *>(parent()), tr("Message History"), tr("There are no messages for the selected filters."));
|
||||||
|
|
||||||
} else
|
} else
|
||||||
QMessageBox::critical(static_cast<QWidget *>(parent()), tr("Message History"), tr("Failed to collecting message history information."));
|
QMessageBox::critical(static_cast<QWidget *>(parent()), tr("Message History"), tr("Failed to collect message history information."));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabLog::restartLayout()
|
void TabLog::restartLayout()
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "tab_server.h"
|
#include "tab_server.h"
|
||||||
#include "abstractclient.h"
|
#include "abstractclient.h"
|
||||||
#include "userlist.h"
|
#include "userlist.h"
|
||||||
|
#include "tab_supervisor.h"
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
#include "pending_command.h"
|
#include "pending_command.h"
|
||||||
|
@ -35,7 +36,6 @@ RoomSelector::RoomSelector(AbstractClient *_client, QWidget *parent)
|
||||||
#else
|
#else
|
||||||
roomList->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
|
roomList->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
|
||||||
roomList->header()->setSectionResizeMode(1, QHeaderView::Stretch);
|
roomList->header()->setSectionResizeMode(1, QHeaderView::Stretch);
|
||||||
roomList->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
|
|
||||||
roomList->header()->setSectionResizeMode(2, QHeaderView::ResizeToContents);
|
roomList->header()->setSectionResizeMode(2, QHeaderView::ResizeToContents);
|
||||||
roomList->header()->setSectionResizeMode(3, QHeaderView::ResizeToContents);
|
roomList->header()->setSectionResizeMode(3, QHeaderView::ResizeToContents);
|
||||||
#endif
|
#endif
|
||||||
|
@ -111,43 +111,19 @@ void RoomSelector::processListRoomsEvent(const Event_ListRooms &event)
|
||||||
roomList->addTopLevelItem(twi);
|
roomList->addTopLevelItem(twi);
|
||||||
if (room.has_auto_join())
|
if (room.has_auto_join())
|
||||||
if (room.auto_join())
|
if (room.auto_join())
|
||||||
joinRoom(room.room_id(), false);
|
emit joinRoomRequest(room.room_id(), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoomSelector::joinRoom(int id, bool setCurrent)
|
|
||||||
{
|
|
||||||
Command_JoinRoom cmd;
|
|
||||||
cmd.set_room_id(id);
|
|
||||||
|
|
||||||
PendingCommand *pend = client->prepareSessionCommand(cmd);
|
|
||||||
pend->setExtraData(setCurrent);
|
|
||||||
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(joinFinished(Response, CommandContainer, QVariant)));
|
|
||||||
|
|
||||||
client->sendCommand(pend);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RoomSelector::joinClicked()
|
void RoomSelector::joinClicked()
|
||||||
{
|
{
|
||||||
QTreeWidgetItem *twi = roomList->currentItem();
|
QTreeWidgetItem *twi = roomList->currentItem();
|
||||||
if (!twi)
|
if (!twi)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
joinRoom(twi->data(0, Qt::UserRole).toInt(), true);
|
int id = twi->data(0, Qt::UserRole).toInt();
|
||||||
}
|
|
||||||
|
|
||||||
void RoomSelector::joinFinished(const Response &r, const CommandContainer & /*commandContainer*/, const QVariant &extraData)
|
emit joinRoomRequest(id, true);
|
||||||
{
|
|
||||||
switch (r.response_code()) {
|
|
||||||
case Response::RespOk: break;
|
|
||||||
case Response::RespUserLevelTooLow: QMessageBox::critical(this, tr("Error"), tr("You do not have the proper permission to join this room.")); return;
|
|
||||||
default:
|
|
||||||
QMessageBox::critical(this, tr("Error"), tr("Failed to join the room due to an unknown error."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Response_JoinRoom &resp = r.GetExtension(Response_JoinRoom::ext);
|
|
||||||
emit roomJoined(resp.room_info(), extraData.toBool());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TabServer::TabServer(TabSupervisor *_tabSupervisor, AbstractClient *_client, QWidget *parent)
|
TabServer::TabServer(TabSupervisor *_tabSupervisor, AbstractClient *_client, QWidget *parent)
|
||||||
|
@ -157,7 +133,7 @@ TabServer::TabServer(TabSupervisor *_tabSupervisor, AbstractClient *_client, QWi
|
||||||
serverInfoBox = new QTextBrowser;
|
serverInfoBox = new QTextBrowser;
|
||||||
serverInfoBox->setOpenExternalLinks(true);
|
serverInfoBox->setOpenExternalLinks(true);
|
||||||
|
|
||||||
connect(roomSelector, SIGNAL(roomJoined(const ServerInfo_Room &, bool)), this, SIGNAL(roomJoined(const ServerInfo_Room &, bool)));
|
connect(roomSelector, SIGNAL(joinRoomRequest(int, bool)), this, SLOT(joinRoom(int, bool)));
|
||||||
|
|
||||||
connect(client, SIGNAL(serverMessageEventReceived(const Event_ServerMessage &)), this, SLOT(processServerMessageEvent(const Event_ServerMessage &)));
|
connect(client, SIGNAL(serverMessageEventReceived(const Event_ServerMessage &)), this, SLOT(processServerMessageEvent(const Event_ServerMessage &)));
|
||||||
|
|
||||||
|
@ -178,3 +154,47 @@ void TabServer::processServerMessageEvent(const Event_ServerMessage &event)
|
||||||
serverInfoBox->setHtml(QString::fromStdString(event.message()));
|
serverInfoBox->setHtml(QString::fromStdString(event.message()));
|
||||||
emit userEvent();
|
emit userEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TabServer::joinRoom(int id, bool setCurrent)
|
||||||
|
{
|
||||||
|
TabRoom *room = tabSupervisor->getRoomTabs().value(id);
|
||||||
|
if(!room)
|
||||||
|
{
|
||||||
|
Command_JoinRoom cmd;
|
||||||
|
cmd.set_room_id(id);
|
||||||
|
|
||||||
|
PendingCommand *pend = client->prepareSessionCommand(cmd);
|
||||||
|
pend->setExtraData(setCurrent);
|
||||||
|
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(joinRoomFinished(Response, CommandContainer, QVariant)));
|
||||||
|
|
||||||
|
client->sendCommand(pend);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(setCurrent)
|
||||||
|
tabSupervisor->setCurrentWidget((QWidget*)room);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TabServer::joinRoomFinished(const Response &r, const CommandContainer & /*commandContainer*/, const QVariant &extraData)
|
||||||
|
{
|
||||||
|
switch (r.response_code()) {
|
||||||
|
case Response::RespOk:
|
||||||
|
break;
|
||||||
|
case Response::RespNameNotFound:
|
||||||
|
QMessageBox::critical(this, tr("Error"), tr("Failed to join the room: it doesn't exists on the server."));
|
||||||
|
return;
|
||||||
|
case Response::RespContextError:
|
||||||
|
QMessageBox::critical(this, tr("Error"), tr("The server thinks you are in the room but Cockatrice is unable to display it. Try restarting Cockatrice."));
|
||||||
|
return;
|
||||||
|
case Response::RespUserLevelTooLow:
|
||||||
|
QMessageBox::critical(this, tr("Error"), tr("You do not have the required permission to join this room."));
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
QMessageBox::critical(this, tr("Error"), tr("Failed to join the room due to an unknown error: %1.").arg(r.response_code()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Response_JoinRoom &resp = r.GetExtension(Response_JoinRoom::ext);
|
||||||
|
emit roomJoined(resp.room_info(), extraData.toBool());
|
||||||
|
}
|
||||||
|
|
|
@ -24,14 +24,11 @@ private:
|
||||||
QTreeWidget *roomList;
|
QTreeWidget *roomList;
|
||||||
QPushButton *joinButton;
|
QPushButton *joinButton;
|
||||||
AbstractClient *client;
|
AbstractClient *client;
|
||||||
|
|
||||||
void joinRoom(int id, bool setCurrent);
|
|
||||||
private slots:
|
private slots:
|
||||||
void processListRoomsEvent(const Event_ListRooms &event);
|
void processListRoomsEvent(const Event_ListRooms &event);
|
||||||
void joinClicked();
|
void joinClicked();
|
||||||
void joinFinished(const Response &resp, const CommandContainer &commandContainer, const QVariant &extraData);
|
|
||||||
signals:
|
signals:
|
||||||
void roomJoined(const ServerInfo_Room &info, bool setCurrent);
|
void joinRoomRequest(int, bool setCurrent);
|
||||||
public:
|
public:
|
||||||
RoomSelector(AbstractClient *_client, QWidget *parent = 0);
|
RoomSelector(AbstractClient *_client, QWidget *parent = 0);
|
||||||
void retranslateUi();
|
void retranslateUi();
|
||||||
|
@ -43,6 +40,8 @@ signals:
|
||||||
void roomJoined(const ServerInfo_Room &info, bool setCurrent);
|
void roomJoined(const ServerInfo_Room &info, bool setCurrent);
|
||||||
private slots:
|
private slots:
|
||||||
void processServerMessageEvent(const Event_ServerMessage &event);
|
void processServerMessageEvent(const Event_ServerMessage &event);
|
||||||
|
void joinRoom(int id, bool setCurrent);
|
||||||
|
void joinRoomFinished(const Response &resp, const CommandContainer &commandContainer, const QVariant &extraData);
|
||||||
private:
|
private:
|
||||||
AbstractClient *client;
|
AbstractClient *client;
|
||||||
RoomSelector *roomSelector;
|
RoomSelector *roomSelector;
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
|
#include <QPixmapCache>
|
||||||
#include <QLibraryInfo>
|
#include <QLibraryInfo>
|
||||||
#if QT_VERSION < 0x050000
|
#if QT_VERSION < 0x050000
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
|
@ -115,6 +116,7 @@ void ThemeManager::themeChangedSlot()
|
||||||
playerBgBrush = loadBrush(PLAYERZONE_BG_NAME, QColor(200, 200, 200));
|
playerBgBrush = loadBrush(PLAYERZONE_BG_NAME, QColor(200, 200, 200));
|
||||||
stackBgBrush = loadBrush(STACKZONE_BG_NAME, QColor(113, 43, 43));
|
stackBgBrush = loadBrush(STACKZONE_BG_NAME, QColor(113, 43, 43));
|
||||||
|
|
||||||
|
QPixmapCache::clear();
|
||||||
|
|
||||||
emit themeChanged();
|
emit themeChanged();
|
||||||
}
|
}
|
||||||
|
|
|
@ -485,6 +485,7 @@ void MainWindow::retranslateUi()
|
||||||
aFullScreen->setText(tr("&Full screen"));
|
aFullScreen->setText(tr("&Full screen"));
|
||||||
aRegister->setText(tr("&Register to server..."));
|
aRegister->setText(tr("&Register to server..."));
|
||||||
aSettings->setText(tr("&Settings..."));
|
aSettings->setText(tr("&Settings..."));
|
||||||
|
aSettings->setIcon(QPixmap("theme:icons/settings"));
|
||||||
aExit->setText(tr("&Exit"));
|
aExit->setText(tr("&Exit"));
|
||||||
|
|
||||||
#if defined(__APPLE__) /* For OSX */
|
#if defined(__APPLE__) /* For OSX */
|
||||||
|
@ -797,6 +798,7 @@ void MainWindow::cardUpdateFinished(int, QProcess::ExitStatus)
|
||||||
|
|
||||||
// this will force a database reload
|
// this will force a database reload
|
||||||
settingsCache->setCardDatabasePath(settingsCache->getCardDatabasePath());
|
settingsCache->setCardDatabasePath(settingsCache->getCardDatabasePath());
|
||||||
|
settingsCache->setTokenDatabasePath(settingsCache->getTokenDatabasePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::refreshShortcuts()
|
void MainWindow::refreshShortcuts()
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include "window_sets.h"
|
#include "window_sets.h"
|
||||||
#include "setsmodel.h"
|
#include "setsmodel.h"
|
||||||
|
#include "pictureloader.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
#include <QTreeView>
|
#include <QTreeView>
|
||||||
#include <QGridLayout>
|
#include <QGridLayout>
|
||||||
#include <QHeaderView>
|
#include <QHeaderView>
|
||||||
|
@ -123,7 +125,7 @@ WndSets::~WndSets()
|
||||||
void WndSets::actSave()
|
void WndSets::actSave()
|
||||||
{
|
{
|
||||||
model->save(db);
|
model->save(db);
|
||||||
db->clearPixmapCache();
|
PictureLoader::clearPixmapCache();
|
||||||
QMessageBox::information(this, tr("Success"), tr("The sets database has been saved successfully."));
|
QMessageBox::information(this, tr("Success"), tr("The sets database has been saved successfully."));
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -86,6 +86,8 @@ void Server_AbstractUserInterface::joinPersistentGames(ResponseContainer &rc)
|
||||||
QMutexLocker gameLocker(&game->gameMutex);
|
QMutexLocker gameLocker(&game->gameMutex);
|
||||||
|
|
||||||
Server_Player *player = game->getPlayers().value(pr.getPlayerId());
|
Server_Player *player = game->getPlayers().value(pr.getPlayerId());
|
||||||
|
if (!player)
|
||||||
|
continue;
|
||||||
|
|
||||||
player->setUserInterface(this);
|
player->setUserInterface(this);
|
||||||
playerAddedToGame(game->getGameId(), room->getId(), player->getPlayerId());
|
playerAddedToGame(game->getGameId(), room->getId(), player->getPlayerId());
|
||||||
|
|
|
@ -147,7 +147,12 @@ int Server_CardZone::getFreeGridColumn(int x, int y, const QString &cardName, bo
|
||||||
if (x == -1) {
|
if (x == -1) {
|
||||||
if (!dontStackSameName && freePilesMap[y].contains(cardName)) {
|
if (!dontStackSameName && freePilesMap[y].contains(cardName)) {
|
||||||
x = (freePilesMap[y].value(cardName) / 3) * 3;
|
x = (freePilesMap[y].value(cardName) / 3) * 3;
|
||||||
if (!coordMap.contains(x))
|
|
||||||
|
if(coordMap.contains(x) &&
|
||||||
|
(coordMap[x]->getFaceDown() ||
|
||||||
|
!coordMap[x]->getAttachedCards().isEmpty())) {
|
||||||
|
// don't pile up on: 1. facedown cards 2. cards with attached cards
|
||||||
|
} else if (!coordMap.contains(x))
|
||||||
return x;
|
return x;
|
||||||
else if (!coordMap.contains(x + 1))
|
else if (!coordMap.contains(x + 1))
|
||||||
return x + 1;
|
return x + 1;
|
||||||
|
|
|
@ -387,7 +387,7 @@ Response::ResponseCode Server_ProtocolHandler::cmdLogin(const Command_Login &cmd
|
||||||
QString clientId = QString::fromStdString(cmd.clientid()).simplified();
|
QString clientId = QString::fromStdString(cmd.clientid()).simplified();
|
||||||
QString clientVersion = QString::fromStdString(cmd.clientver()).simplified();
|
QString clientVersion = QString::fromStdString(cmd.clientver()).simplified();
|
||||||
|
|
||||||
if (userName.isEmpty() || (userInfo != 0))
|
if (userInfo != 0)
|
||||||
return Response::RespContextError;
|
return Response::RespContextError;
|
||||||
|
|
||||||
// check client feature set against server feature set
|
// check client feature set against server feature set
|
||||||
|
@ -603,8 +603,11 @@ Response::ResponseCode Server_ProtocolHandler::cmdJoinRoom(const Command_JoinRoo
|
||||||
joinMessageEvent.set_message_type(Event_RoomSay::Welcome);
|
joinMessageEvent.set_message_type(Event_RoomSay::Welcome);
|
||||||
rc.enqueuePostResponseItem(ServerMessage::ROOM_EVENT, r->prepareRoomEvent(joinMessageEvent));
|
rc.enqueuePostResponseItem(ServerMessage::ROOM_EVENT, r->prepareRoomEvent(joinMessageEvent));
|
||||||
|
|
||||||
ServerInfo_ChatMessage chatMessage; for (int i = 0; i < r->chatHistory.size(); ++i) {
|
QReadLocker chatHistoryLocker(&r->historyLock);
|
||||||
chatMessage = r->chatHistory.at(i);
|
QList<ServerInfo_ChatMessage> chatHistory = r->getChatHistory();
|
||||||
|
ServerInfo_ChatMessage chatMessage;
|
||||||
|
for (int i = 0; i < chatHistory.size(); ++i) {
|
||||||
|
chatMessage = chatHistory.at(i);
|
||||||
qDebug() << QString::fromStdString(chatMessage.message()).simplified();
|
qDebug() << QString::fromStdString(chatMessage.message()).simplified();
|
||||||
Event_RoomSay roomChatHistory;
|
Event_RoomSay roomChatHistory;
|
||||||
roomChatHistory.set_message(chatMessage.sender_name() + ": " + chatMessage.message());
|
roomChatHistory.set_message(chatMessage.sender_name() + ": " + chatMessage.message());
|
||||||
|
|
|
@ -236,7 +236,6 @@ void Server_Room::say(const QString &userName, const QString &s, bool sendToIsl)
|
||||||
sendRoomEvent(prepareRoomEvent(event), sendToIsl);
|
sendRoomEvent(prepareRoomEvent(event), sendToIsl);
|
||||||
|
|
||||||
if (chatHistorySize != 0) {
|
if (chatHistorySize != 0) {
|
||||||
|
|
||||||
ServerInfo_ChatMessage chatMessage;
|
ServerInfo_ChatMessage chatMessage;
|
||||||
QDateTime dateTime = dateTime.currentDateTimeUtc();
|
QDateTime dateTime = dateTime.currentDateTimeUtc();
|
||||||
QString dateTimeString = dateTime.toString();
|
QString dateTimeString = dateTime.toString();
|
||||||
|
@ -244,10 +243,12 @@ void Server_Room::say(const QString &userName, const QString &s, bool sendToIsl)
|
||||||
chatMessage.set_sender_name(userName.toStdString());
|
chatMessage.set_sender_name(userName.toStdString());
|
||||||
chatMessage.set_message(s.simplified().toStdString());
|
chatMessage.set_message(s.simplified().toStdString());
|
||||||
|
|
||||||
|
historyLock.lockForWrite();
|
||||||
if (chatHistory.size() >= chatHistorySize)
|
if (chatHistory.size() >= chatHistorySize)
|
||||||
chatHistory.removeAt(0);
|
chatHistory.removeAt(0);
|
||||||
|
|
||||||
chatHistory << chatMessage;
|
chatHistory << chatMessage;
|
||||||
|
historyLock.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,12 +42,13 @@ private:
|
||||||
QMap<int, ServerInfo_Game> externalGames;
|
QMap<int, ServerInfo_Game> externalGames;
|
||||||
QMap<QString, Server_ProtocolHandler *> users;
|
QMap<QString, Server_ProtocolHandler *> users;
|
||||||
QMap<QString, ServerInfo_User_Container> externalUsers;
|
QMap<QString, ServerInfo_User_Container> externalUsers;
|
||||||
|
QList<ServerInfo_ChatMessage> chatHistory;
|
||||||
private slots:
|
private slots:
|
||||||
void broadcastGameListUpdate(const ServerInfo_Game &gameInfo, bool sendToIsl = true);
|
void broadcastGameListUpdate(const ServerInfo_Game &gameInfo, bool sendToIsl = true);
|
||||||
public:
|
public:
|
||||||
mutable QReadWriteLock usersLock;
|
mutable QReadWriteLock usersLock;
|
||||||
mutable QReadWriteLock gamesLock;
|
mutable QReadWriteLock gamesLock;
|
||||||
QList<ServerInfo_ChatMessage> chatHistory;
|
mutable QReadWriteLock historyLock;
|
||||||
Server_Room(int _id, int _chatHistorySize, const QString &_name, const QString &_description, const QString &_permissionLevel, bool _autoJoin, const QString &_joinMessage, const QStringList &_gameTypes, Server *parent );
|
Server_Room(int _id, int _chatHistorySize, const QString &_name, const QString &_description, const QString &_permissionLevel, bool _autoJoin, const QString &_joinMessage, const QStringList &_gameTypes, Server *parent );
|
||||||
~Server_Room();
|
~Server_Room();
|
||||||
int getId() const { return id; }
|
int getId() const { return id; }
|
||||||
|
@ -63,7 +64,7 @@ public:
|
||||||
const ServerInfo_Room &getInfo(ServerInfo_Room &result, bool complete, bool showGameTypes = false, bool includeExternalData = true) const;
|
const ServerInfo_Room &getInfo(ServerInfo_Room &result, bool complete, bool showGameTypes = false, bool includeExternalData = true) const;
|
||||||
int getGamesCreatedByUser(const QString &name) const;
|
int getGamesCreatedByUser(const QString &name) const;
|
||||||
QList<ServerInfo_Game> getGamesOfUser(const QString &name) const;
|
QList<ServerInfo_Game> getGamesOfUser(const QString &name) const;
|
||||||
QList<ServerInfo_ChatMessage> getChatHistory() { return chatHistory; }
|
QList<ServerInfo_ChatMessage> & getChatHistory() { return chatHistory; }
|
||||||
|
|
||||||
void addClient(Server_ProtocolHandler *client);
|
void addClient(Server_ProtocolHandler *client);
|
||||||
void removeClient(Server_ProtocolHandler *client);
|
void removeClient(Server_ProtocolHandler *client);
|
||||||
|
|
|
@ -29,12 +29,13 @@
|
||||||
<xs:extension base="xs:string">
|
<xs:extension base="xs:string">
|
||||||
<xs:attribute type="xs:int" name="muId" use="optional"/>
|
<xs:attribute type="xs:int" name="muId" use="optional"/>
|
||||||
<xs:attribute type="xs:anyURI" name="picUrl" use="optional"/>
|
<xs:attribute type="xs:anyURI" name="picUrl" use="optional"/>
|
||||||
<xs:attribute type="xs:anyURI" name="picUrlHq" use="optional"/>
|
|
||||||
</xs:extension>
|
</xs:extension>
|
||||||
</xs:simpleContent>
|
</xs:simpleContent>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
<xs:element type="xs:string" name="color" minOccurs="0" maxOccurs="unbounded"/>
|
<xs:element type="xs:string" name="color" minOccurs="0" maxOccurs="unbounded"/>
|
||||||
|
<xs:element type="xs:string" name="related" minOccurs="0" maxOccurs="unbounded"/>
|
||||||
|
<xs:element type="xs:string" name="reverse-related" minOccurs="0" maxOccurs="unbounded"/>
|
||||||
<xs:element type="xs:string" name="manacost"/>
|
<xs:element type="xs:string" name="manacost"/>
|
||||||
<xs:element type="xs:string" name="type"/>
|
<xs:element type="xs:string" name="type"/>
|
||||||
<xs:element type="xs:string" name="pt" minOccurs="0"/>
|
<xs:element type="xs:string" name="pt" minOccurs="0"/>
|
||||||
|
|
|
@ -12,6 +12,7 @@ SET(oracle_SOURCES
|
||||||
src/oraclewizard.cpp
|
src/oraclewizard.cpp
|
||||||
src/oracleimporter.cpp
|
src/oracleimporter.cpp
|
||||||
../cockatrice/src/carddatabase.cpp
|
../cockatrice/src/carddatabase.cpp
|
||||||
|
../cockatrice/src/pictureloader.cpp
|
||||||
../cockatrice/src/settingscache.cpp
|
../cockatrice/src/settingscache.cpp
|
||||||
../cockatrice/src/shortcutssettings.cpp
|
../cockatrice/src/shortcutssettings.cpp
|
||||||
../cockatrice/src/settings/carddatabasesettings.cpp
|
../cockatrice/src/settings/carddatabasesettings.cpp
|
||||||
|
@ -24,10 +25,6 @@ SET(oracle_SOURCES
|
||||||
../cockatrice/src/qt-json/json.cpp
|
../cockatrice/src/qt-json/json.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if (UNIX AND NOT APPLE)
|
|
||||||
set_source_files_properties(src/main.cpp PROPERTIES COMPILE_FLAGS -DTRANSLATION_PATH=\\"${CMAKE_INSTALL_PREFIX}/share/oracle/translations\\")
|
|
||||||
endif (UNIX AND NOT APPLE)
|
|
||||||
|
|
||||||
set(oracle_RESOURCES oracle.qrc)
|
set(oracle_RESOURCES oracle.qrc)
|
||||||
|
|
||||||
IF(UPDATE_TRANSLATIONS)
|
IF(UPDATE_TRANSLATIONS)
|
||||||
|
@ -185,6 +182,7 @@ if(APPLE)
|
||||||
# these needs to be relative to CMAKE_INSTALL_PREFIX
|
# these needs to be relative to CMAKE_INSTALL_PREFIX
|
||||||
set(plugin_dest_dir oracle.app/Contents/Plugins)
|
set(plugin_dest_dir oracle.app/Contents/Plugins)
|
||||||
set(qtconf_dest_dir oracle.app/Contents/Resources)
|
set(qtconf_dest_dir oracle.app/Contents/Resources)
|
||||||
|
get_filename_component(QT_LIBRARY_DIR "${QT_LIBRARY_DIR}/.." ABSOLUTE)
|
||||||
|
|
||||||
# qt4: codecs, iconengines, imageformats
|
# qt4: codecs, iconengines, imageformats
|
||||||
# qt5: iconengines, platforms
|
# qt5: iconengines, platforms
|
||||||
|
@ -214,10 +212,13 @@ IF(WIN32)
|
||||||
set(qtconf_dest_dir .)
|
set(qtconf_dest_dir .)
|
||||||
list(APPEND libSearchDirs ${QT_LIBRARY_DIR})
|
list(APPEND libSearchDirs ${QT_LIBRARY_DIR})
|
||||||
IF(ZLIB_FOUND)
|
IF(ZLIB_FOUND)
|
||||||
|
# look for dll in the bin/ directory (gnuwin32 package)
|
||||||
get_filename_component(ZLIB_DLL_DIR "${ZLIB_INCLUDE_DIRS}/../bin/" REALPATH)
|
get_filename_component(ZLIB_DLL_DIR "${ZLIB_INCLUDE_DIRS}/../bin/" REALPATH)
|
||||||
list(APPEND libSearchDirs ${ZLIB_DLL_DIR})
|
list(APPEND libSearchDirs ${ZLIB_DLL_DIR})
|
||||||
|
# look for dll in the lib/ directory (nuget package)
|
||||||
|
get_filename_component(ZLIB_DLL_DIR "${ZLIB_LIBRARY}" DIRECTORY)
|
||||||
|
list(APPEND libSearchDirs ${ZLIB_DLL_DIR})
|
||||||
ENDIF()
|
ENDIF()
|
||||||
MESSAGE(STATUS "Oracle: ZLIB dll found at ${ZLIB_DLL_DIR}")
|
|
||||||
|
|
||||||
# qt4: codecs, iconengines, imageformats
|
# qt4: codecs, iconengines, imageformats
|
||||||
# qt5: iconengines, imageformats, platforms
|
# qt5: iconengines, imageformats, platforms
|
||||||
|
|
|
@ -14,11 +14,7 @@ SettingsCache *settingsCache;
|
||||||
ThemeManager *themeManager;
|
ThemeManager *themeManager;
|
||||||
|
|
||||||
const QString translationPrefix = "oracle";
|
const QString translationPrefix = "oracle";
|
||||||
#ifdef TRANSLATION_PATH
|
QString translationPath;
|
||||||
QString translationPath = TRANSLATION_PATH;
|
|
||||||
#else
|
|
||||||
QString translationPath = QString();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void installNewTranslator()
|
void installNewTranslator()
|
||||||
{
|
{
|
||||||
|
@ -44,13 +40,13 @@ int main(int argc, char *argv[])
|
||||||
// this can't be changed, as it influences the default savepath for cards.xml
|
// this can't be changed, as it influences the default savepath for cards.xml
|
||||||
QCoreApplication::setApplicationName("Cockatrice");
|
QCoreApplication::setApplicationName("Cockatrice");
|
||||||
|
|
||||||
if (translationPath.isEmpty()) {
|
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
translationPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
|
translationPath = qApp->applicationDirPath() + "/../Resources/translations";
|
||||||
#elif defined(Q_OS_WIN)
|
#elif defined(Q_OS_WIN)
|
||||||
translationPath = app.applicationDirPath() + "/translations";
|
translationPath = qApp->applicationDirPath() + "/translations";
|
||||||
|
#else // linux
|
||||||
|
translationPath = qApp->applicationDirPath() + "/../share/cockatrice/translations";
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
settingsCache = new SettingsCache;
|
settingsCache = new SettingsCache;
|
||||||
themeManager = new ThemeManager;
|
themeManager = new ThemeManager;
|
||||||
|
|
|
@ -67,6 +67,7 @@ CardInfo *OracleImporter::addCard(const QString &setName,
|
||||||
const QString &cardText,
|
const QString &cardText,
|
||||||
const QStringList & colors,
|
const QStringList & colors,
|
||||||
const QStringList & relatedCards,
|
const QStringList & relatedCards,
|
||||||
|
const QStringList & reverseRelatedCards,
|
||||||
bool upsideDown
|
bool upsideDown
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
@ -95,7 +96,7 @@ CardInfo *OracleImporter::addCard(const QString &setName,
|
||||||
bool cipt = cardText.contains("Hideaway") || (cardText.contains(cardName + " enters the battlefield tapped") && !cardText.contains(cardName + " enters the battlefield tapped unless"));
|
bool cipt = cardText.contains("Hideaway") || (cardText.contains(cardName + " enters the battlefield tapped") && !cardText.contains(cardName + " enters the battlefield tapped unless"));
|
||||||
|
|
||||||
// insert the card and its properties
|
// insert the card and its properties
|
||||||
card = new CardInfo(this, cardName, isToken, cardCost, cmc, cardType, cardPT, cardText, colors, relatedCards, upsideDown, cardLoyalty, cipt);
|
card = new CardInfo(this, cardName, isToken, cardCost, cmc, cardType, cardPT, cardText, colors, relatedCards, reverseRelatedCards, upsideDown, cardLoyalty, cipt);
|
||||||
int tableRow = 1;
|
int tableRow = 1;
|
||||||
QString mainCardType = card->getMainCardType();
|
QString mainCardType = card->getMainCardType();
|
||||||
if ((mainCardType == "Land") || mArtifact)
|
if ((mainCardType == "Land") || mArtifact)
|
||||||
|
@ -146,6 +147,7 @@ int OracleImporter::importTextSpoiler(CardSet *set, const QVariant &data)
|
||||||
QString cardText;
|
QString cardText;
|
||||||
QStringList colors;
|
QStringList colors;
|
||||||
QStringList relatedCards;
|
QStringList relatedCards;
|
||||||
|
QStringList reverseRelatedCards; // dummy
|
||||||
int cardId;
|
int cardId;
|
||||||
int cardLoyalty;
|
int cardLoyalty;
|
||||||
bool upsideDown = false;
|
bool upsideDown = false;
|
||||||
|
@ -192,7 +194,7 @@ int OracleImporter::importTextSpoiler(CardSet *set, const QVariant &data)
|
||||||
colors.clear();
|
colors.clear();
|
||||||
extractColors(map.value("colors").toStringList(), colors);
|
extractColors(map.value("colors").toStringList(), colors);
|
||||||
|
|
||||||
CardInfo *card = addCard(set->getShortName(), cardName, false, cardId, cardCost, cmc, cardType, cardPT, cardLoyalty, cardText, colors, relatedCards, upsideDown);
|
CardInfo *card = addCard(set->getShortName(), cardName, false, cardId, cardCost, cmc, cardType, cardPT, cardLoyalty, cardText, colors, relatedCards, reverseRelatedCards, upsideDown);
|
||||||
|
|
||||||
if (!set->contains(card)) {
|
if (!set->contains(card)) {
|
||||||
card->addToSet(set);
|
card->addToSet(set);
|
||||||
|
@ -276,10 +278,11 @@ int OracleImporter::importTextSpoiler(CardSet *set, const QVariant &data)
|
||||||
|
|
||||||
colors.removeDuplicates();
|
colors.removeDuplicates();
|
||||||
relatedCards = QStringList();
|
relatedCards = QStringList();
|
||||||
|
reverseRelatedCards = QStringList();
|
||||||
upsideDown = false;
|
upsideDown = false;
|
||||||
|
|
||||||
// add the card
|
// add the card
|
||||||
CardInfo *card = addCard(set->getShortName(), cardName, false, muid, cardCost, cmc, cardType, cardPT, cardLoyalty, cardText, colors, relatedCards, upsideDown);
|
CardInfo *card = addCard(set->getShortName(), cardName, false, muid, cardCost, cmc, cardType, cardPT, cardLoyalty, cardText, colors, relatedCards, reverseRelatedCards, upsideDown);
|
||||||
|
|
||||||
if (!set->contains(card)) {
|
if (!set->contains(card)) {
|
||||||
card->addToSet(set);
|
card->addToSet(set);
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define ORACLEIMPORTER_H
|
#define ORACLEIMPORTER_H
|
||||||
|
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
#include <carddatabase.h>
|
#include <carddatabase.h>
|
||||||
|
|
||||||
|
@ -29,7 +30,7 @@ private:
|
||||||
QVariantMap setsMap;
|
QVariantMap setsMap;
|
||||||
QString dataDir;
|
QString dataDir;
|
||||||
|
|
||||||
CardInfo *addCard(const QString &setName, QString cardName, bool isToken, int cardId, QString &cardCost, QString &cmc, const QString &cardType, const QString &cardPT, int cardLoyalty, const QString &cardText, const QStringList & colors, const QStringList & relatedCards, bool upsideDown);
|
CardInfo *addCard(const QString &setName, QString cardName, bool isToken, int cardId, QString &cardCost, QString &cmc, const QString &cardType, const QString &cardPT, int cardLoyalty, const QString &cardText, const QStringList & colors, const QStringList & relatedCards, const QStringList & reverseRelatedCards, bool upsideDown);
|
||||||
signals:
|
signals:
|
||||||
void setIndexChanged(int cardsImported, int setIndex, const QString &setName);
|
void setIndexChanged(int cardsImported, int setIndex, const QString &setName);
|
||||||
void dataReadProgress(int bytesRead, int totalBytes);
|
void dataReadProgress(int bytesRead, int totalBytes);
|
||||||
|
|
|
@ -83,6 +83,28 @@ endif()
|
||||||
|
|
||||||
SET(QT_DONT_USE_QTGUI TRUE)
|
SET(QT_DONT_USE_QTGUI TRUE)
|
||||||
|
|
||||||
|
# Mysql connector
|
||||||
|
if(UNIX)
|
||||||
|
if(APPLE)
|
||||||
|
SET(MYSQLCLIENT_DEFAULT_PATHS "/usr/local/lib" "/opt/local/lib/mysql55/mysql/" "/opt/local/lib/mysql56/mysql/")
|
||||||
|
else()
|
||||||
|
SET(MYSQLCLIENT_DEFAULT_PATHS "/usr/lib" "/usr/local/lib")
|
||||||
|
endif()
|
||||||
|
elseif(WIN32)
|
||||||
|
SET(MYSQLCLIENT_DEFAULT_PATHS "C:\\Program Files\\MySQL\\MySQL Server 5.5\\lib" "C:\\Program Files\\MySQL\\MySQL Server 5.6\\lib")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_library(MYSQLCLIENT_LIBRARIES NAMES mysqlclient PATHS ${MYSQLCLIENT_DEFAULT_PATHS} PATH_SUFFIXES mysql mariadb)
|
||||||
|
if(${MYSQLCLIENT_LIBRARIES} MATCHES "NOTFOUND")
|
||||||
|
set(MYSQLCLIENT_FOUND FALSE CACHE INTERNAL "")
|
||||||
|
MESSAGE(STATUS "Mysql connector NOT FOUND: servatrice won't be able to connect to a mysql server")
|
||||||
|
unset(MYSQLCLIENT_LIBRARIES)
|
||||||
|
else()
|
||||||
|
set(MYSQLCLIENT_FOUND TRUE CACHE INTERNAL "")
|
||||||
|
get_filename_component(MYSQLCLIENT_LIBRARY_DIR ${MYSQLCLIENT_LIBRARIES} PATH)
|
||||||
|
MESSAGE(STATUS "Mysql connector found at: ${MYSQLCLIENT_LIBRARY_DIR}")
|
||||||
|
endif()
|
||||||
|
|
||||||
# Declare path variables
|
# Declare path variables
|
||||||
set(ICONDIR share/icons CACHE STRING "icon dir")
|
set(ICONDIR share/icons CACHE STRING "icon dir")
|
||||||
set(DESKTOPDIR share/applications CACHE STRING "desktop file destination")
|
set(DESKTOPDIR share/applications CACHE STRING "desktop file destination")
|
||||||
|
@ -146,12 +168,13 @@ if(APPLE)
|
||||||
# these needs to be relative to CMAKE_INSTALL_PREFIX
|
# these needs to be relative to CMAKE_INSTALL_PREFIX
|
||||||
set(plugin_dest_dir servatrice.app/Contents/Plugins)
|
set(plugin_dest_dir servatrice.app/Contents/Plugins)
|
||||||
set(qtconf_dest_dir servatrice.app/Contents/Resources)
|
set(qtconf_dest_dir servatrice.app/Contents/Resources)
|
||||||
|
get_filename_component(QT_LIBRARY_DIR "${QT_LIBRARY_DIR}/.." ABSOLUTE)
|
||||||
|
|
||||||
# qt4: codecs, sqldrivers
|
# qt4: codecs, sqldrivers
|
||||||
# qt5: platforms, sqldrivers
|
# qt5: platforms, sqldrivers
|
||||||
|
|
||||||
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 "(codecs|platforms|sqldrivers)/.*\\.dylib"
|
FILES_MATCHING REGEX "(codecs/.*|platforms/.*|sqldrivers/libqsqlmysql)\\.dylib"
|
||||||
REGEX ".*_debug\\.dylib" EXCLUDE)
|
REGEX ".*_debug\\.dylib" EXCLUDE)
|
||||||
|
|
||||||
install(CODE "
|
install(CODE "
|
||||||
|
@ -165,7 +188,7 @@ Translations = Resources/translations\")
|
||||||
\"\${CMAKE_INSTALL_PREFIX}/${plugin_dest_dir}/*.dylib\")
|
\"\${CMAKE_INSTALL_PREFIX}/${plugin_dest_dir}/*.dylib\")
|
||||||
set(BU_CHMOD_BUNDLE_ITEMS ON)
|
set(BU_CHMOD_BUNDLE_ITEMS ON)
|
||||||
include(BundleUtilities)
|
include(BundleUtilities)
|
||||||
fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/servatrice.app\" \"\${QTPLUGINS}\" \"${QT_LIBRARY_DIR}\")
|
fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/servatrice.app\" \"\${QTPLUGINS}\" \"${QT_LIBRARY_DIR};${MYSQLCLIENT_LIBRARY_DIR}\")
|
||||||
" COMPONENT Runtime)
|
" COMPONENT Runtime)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -178,7 +201,8 @@ if(WIN32)
|
||||||
# qt5: platforms, sqldrivers
|
# qt5: platforms, sqldrivers
|
||||||
|
|
||||||
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 "(codecs|platforms|sqldrivers)/.*[^d]\\.dll")
|
FILES_MATCHING REGEX "(codecs/.*|platforms/.*|sqldrivers/libqsqlmysql)\\.dll"
|
||||||
|
REGEX ".*d\\.dll" EXCLUDE)
|
||||||
|
|
||||||
install(CODE "
|
install(CODE "
|
||||||
file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf\" \"[Paths]
|
file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf\" \"[Paths]
|
||||||
|
@ -191,7 +215,7 @@ Translations = Resources/translations\")
|
||||||
\"\${CMAKE_INSTALL_PREFIX}/${plugin_dest_dir}/*.dll\")
|
\"\${CMAKE_INSTALL_PREFIX}/${plugin_dest_dir}/*.dll\")
|
||||||
set(BU_CHMOD_BUNDLE_ITEMS ON)
|
set(BU_CHMOD_BUNDLE_ITEMS ON)
|
||||||
include(BundleUtilities)
|
include(BundleUtilities)
|
||||||
fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/servatrice.exe\" \"\${QTPLUGINS}\" \"${QT_LIBRARY_DIR}\")
|
fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/servatrice.exe\" \"\${QTPLUGINS}\" \"${QT_LIBRARY_DIR};${MYSQLCLIENT_LIBRARY_DIR}\")
|
||||||
" COMPONENT Runtime)
|
" COMPONENT Runtime)
|
||||||
endif()
|
endif()
|
||||||
#Compile a portable version, default off
|
#Compile a portable version, default off
|
||||||
|
|
33
servatrice/check_schema_version.sh
Executable file
33
servatrice/check_schema_version.sh
Executable file
|
@ -0,0 +1,33 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
schema_ver="$(grep 'INSERT INTO cockatrice_schema_version' servatrice/servatrice.sql | sed 's/.*VALUES(//' | sed 's/).*//')"
|
||||||
|
|
||||||
|
latest_migration="$(ls -1 servatrice/migrations/ | tail -n1)"
|
||||||
|
xtoysql="${latest_migration#servatrice_}"
|
||||||
|
xtoy="${xtoysql%.sql}"
|
||||||
|
old_ver="$(echo ${xtoy%%_to_*} | bc)"
|
||||||
|
new_ver="$(echo ${xtoy##*_to_} | bc)"
|
||||||
|
|
||||||
|
if ((old_ver >= new_ver)); then
|
||||||
|
echo "New version $new_ver is not newer than $old_ver"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ((schema_ver != new_ver)); then
|
||||||
|
echo "Schema version $schema_ver does not equal new version $new_ver"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
expected_sql="^UPDATE cockatrice_schema_version SET version=${new_ver} WHERE version=${old_ver};$"
|
||||||
|
if ! grep -q "$expected_sql" servatrice/migrations/$latest_migration; then
|
||||||
|
echo "$latest_migration does not contain expected sql: $expected_sql"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
expected_define="^#define DATABASE_SCHEMA_VERSION $new_ver$"
|
||||||
|
if ! grep -q "$expected_define" servatrice/src/servatrice_database_interface.h; then
|
||||||
|
echo "servatrice_database_interface.h does not contain expected #define: $expected_define"
|
||||||
|
exit 1
|
||||||
|
fi
|
5
servatrice/migrations/servatrice_0011_to_0012.sql
Normal file
5
servatrice/migrations/servatrice_0011_to_0012.sql
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
-- Servatrice db migration from version 11 to version 12
|
||||||
|
|
||||||
|
alter table cockatrice_users modify token binary(16) NULL;
|
||||||
|
|
||||||
|
UPDATE cockatrice_schema_version SET version=12 WHERE version=11;
|
|
@ -20,7 +20,7 @@ CREATE TABLE IF NOT EXISTS `cockatrice_schema_version` (
|
||||||
PRIMARY KEY (`version`)
|
PRIMARY KEY (`version`)
|
||||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
INSERT INTO cockatrice_schema_version VALUES(11);
|
INSERT INTO cockatrice_schema_version VALUES(12);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `cockatrice_decklist_files` (
|
CREATE TABLE IF NOT EXISTS `cockatrice_decklist_files` (
|
||||||
`id` int(7) unsigned zerofill NOT NULL auto_increment,
|
`id` int(7) unsigned zerofill NOT NULL auto_increment,
|
||||||
|
@ -82,7 +82,7 @@ CREATE TABLE IF NOT EXISTS `cockatrice_users` (
|
||||||
`avatar_bmp` blob NOT NULL,
|
`avatar_bmp` blob NOT NULL,
|
||||||
`registrationDate` datetime NOT NULL,
|
`registrationDate` datetime NOT NULL,
|
||||||
`active` tinyint(1) NOT NULL,
|
`active` tinyint(1) NOT NULL,
|
||||||
`token` binary(16) NOT NULL,
|
`token` binary(16),
|
||||||
`clientid` varchar(15) NOT NULL,
|
`clientid` varchar(15) NOT NULL,
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
UNIQUE KEY `name` (`name`),
|
UNIQUE KEY `name` (`name`),
|
||||||
|
|
|
@ -176,7 +176,8 @@ bool Servatrice::initServer()
|
||||||
bool registrationEnabled = settingsCache->value("registration/enabled", false).toBool();
|
bool registrationEnabled = settingsCache->value("registration/enabled", false).toBool();
|
||||||
bool requireEmailForRegistration = settingsCache->value("registration/requireemail", true).toBool();
|
bool requireEmailForRegistration = settingsCache->value("registration/requireemail", true).toBool();
|
||||||
|
|
||||||
qDebug() << "Registration enabled: " << regServerOnly;
|
qDebug() << "Accept registered users only: " << regServerOnly;
|
||||||
|
qDebug() << "Registration enabled: " << registrationEnabled;
|
||||||
if (registrationEnabled)
|
if (registrationEnabled)
|
||||||
qDebug() << "Require email address to register: " << requireEmailForRegistration;
|
qDebug() << "Require email address to register: " << requireEmailForRegistration;
|
||||||
|
|
||||||
|
|
|
@ -124,6 +124,8 @@ bool Servatrice_DatabaseInterface::execSqlQuery(QSqlQuery *query)
|
||||||
bool Servatrice_DatabaseInterface::usernameIsValid(const QString &user, QString & error)
|
bool Servatrice_DatabaseInterface::usernameIsValid(const QString &user, QString & error)
|
||||||
{
|
{
|
||||||
int minNameLength = settingsCache->value("users/minnamelength", 6).toInt();
|
int minNameLength = settingsCache->value("users/minnamelength", 6).toInt();
|
||||||
|
if(minNameLength < 1)
|
||||||
|
minNameLength = 1;
|
||||||
int maxNameLength = settingsCache->value("users/maxnamelength", 12).toInt();
|
int maxNameLength = settingsCache->value("users/maxnamelength", 12).toInt();
|
||||||
bool allowLowercase = settingsCache->value("users/allowlowercase", true).toBool();
|
bool allowLowercase = settingsCache->value("users/allowlowercase", true).toBool();
|
||||||
bool allowUppercase = settingsCache->value("users/allowuppercase", true).toBool();
|
bool allowUppercase = settingsCache->value("users/allowuppercase", true).toBool();
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "server_database_interface.h"
|
#include "server_database_interface.h"
|
||||||
|
|
||||||
#define DATABASE_SCHEMA_VERSION 11
|
#define DATABASE_SCHEMA_VERSION 12
|
||||||
|
|
||||||
class Servatrice;
|
class Servatrice;
|
||||||
|
|
||||||
|
|
38
tests/CMakeLists.txt
Normal file
38
tests/CMakeLists.txt
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
enable_testing()
|
||||||
|
add_test(NAME dummy_test COMMAND dummy_test)
|
||||||
|
|
||||||
|
# Find GTest
|
||||||
|
|
||||||
|
add_executable(dummy_test dummy_test.cpp)
|
||||||
|
|
||||||
|
find_package(GTest)
|
||||||
|
|
||||||
|
if(NOT GTEST_FOUND)
|
||||||
|
IF(NOT EXISTS "${CMAKE_BINARY_DIR}/gtest-build")
|
||||||
|
message(STATUS "Downloading googletest")
|
||||||
|
configure_file("${CMAKE_SOURCE_DIR}/cmake/gtest-CMakeLists.txt.in" "${CMAKE_BINARY_DIR}/gtest-download/CMakeLists.txt")
|
||||||
|
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
|
||||||
|
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/gtest-download )
|
||||||
|
execute_process(COMMAND ${CMAKE_COMMAND} --build .
|
||||||
|
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/gtest-download )
|
||||||
|
ELSE()
|
||||||
|
message(STATUS "GoogleTest directory exists")
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
# Add gtest directly to our build
|
||||||
|
add_subdirectory(${CMAKE_BINARY_DIR}/gtest-src
|
||||||
|
${CMAKE_BINARY_DIR}/gtest-build
|
||||||
|
EXCLUDE_FROM_ALL )
|
||||||
|
|
||||||
|
# Add the gtest include directory, since gtest
|
||||||
|
# doesn't add that dependency to its gtest target
|
||||||
|
target_include_directories(gtest INTERFACE
|
||||||
|
"${CMAKE_BINARY_DIR}/gtest-src/include" )
|
||||||
|
|
||||||
|
SET(GTEST_INCLUDE_DIRS "${CMAKE_BINARY_DIR}/gtest-src/include")
|
||||||
|
SET(GTEST_BOTH_LIBRARIES gtest)
|
||||||
|
add_dependencies(dummy_test gtest)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include_directories(${GTEST_INCLUDE_DIRS})
|
||||||
|
target_link_libraries(dummy_test ${GTEST_BOTH_LIBRARIES})
|
16
tests/dummy_test.cpp
Normal file
16
tests/dummy_test.cpp
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
class FooTest : public ::testing::Test {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST(DummyTest, Works) {
|
||||||
|
ASSERT_EQ(1, 1) << "One is not equal to one";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
::testing::InitGoogleTest(&argc, argv);
|
||||||
|
return RUN_ALL_TESTS();
|
||||||
|
}
|
Binary file not shown.
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 41 KiB |
Binary file not shown.
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 110 KiB |
|
@ -2,14 +2,24 @@
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
./servatrice/check_schema_version.sh
|
||||||
|
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
prefix=""
|
prefix=""
|
||||||
if [[ $TRAVIS_OS_NAME == "osx" && $QT4 == 0 ]]; then
|
if [[ $TRAVIS_OS_NAME == "osx" && $QT4 == 0 ]]; then
|
||||||
prefix="-DCMAKE_PREFIX_PATH=`echo /usr/local/Cellar/qt5/5.*/`"
|
prefix="-DCMAKE_PREFIX_PATH=$(echo /usr/local/Cellar/qt5/5.*/)"
|
||||||
fi
|
fi
|
||||||
if [[ $TRAVIS_OS_NAME == "linux" && $QT4 == 0 ]]; then
|
if [[ $TRAVIS_OS_NAME == "linux" && $QT4 == 0 ]]; then
|
||||||
prefix="-DCMAKE_PREFIX_PATH=/opt/qt52/lib/cmake/"
|
prefix="-DCMAKE_PREFIX_PATH=$(echo /opt/qt5*/lib/cmake/)"
|
||||||
|
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$(echo /opt/qt5*/lib/)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $BUILDTYPE == "Debug" ]]; then
|
||||||
|
cmake .. -DWITH_SERVER=1 -DTEST=1 -DCMAKE_BUILD_TYPE=$BUILDTYPE -DWITH_QT4=$QT4 $prefix
|
||||||
|
make -j2
|
||||||
|
make test
|
||||||
|
else
|
||||||
|
cmake .. -DWITH_SERVER=1 -DCMAKE_BUILD_TYPE=$BUILDTYPE -DWITH_QT4=$QT4 $prefix
|
||||||
|
make package -j2
|
||||||
fi
|
fi
|
||||||
cmake .. -DWITH_SERVER=1 -DCMAKE_BUILD_TYPE=Debug -DWITH_QT4=$QT4 $prefix
|
|
||||||
make -j2
|
|
||||||
|
|
|
@ -1,21 +1,49 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
if [[ $TRAVIS_OS_NAME == "osx" ]] ; then
|
if [[ $TRAVIS_OS_NAME == "osx" ]] ; then
|
||||||
brew update
|
brew update > /dev/null
|
||||||
if (( QT4 )); then
|
if (( QT4 )); then
|
||||||
brew install qt protobuf libgcrypt
|
brew install qt protobuf libgcrypt > /dev/null
|
||||||
else
|
else
|
||||||
brew install qt5 protobuf libgcrypt
|
brew install qt5 protobuf libgcrypt > /dev/null
|
||||||
fi
|
fi
|
||||||
|
brew unlink cmake
|
||||||
|
brew upgrade cmake
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
|
# common prerequisites
|
||||||
|
sudo apt-get update -qq
|
||||||
|
sudo apt-get install -y libprotobuf-dev protobuf-compiler cmake bc
|
||||||
|
|
||||||
if (( QT4 )); then
|
if (( QT4 )); then
|
||||||
sudo apt-get update -qq
|
# qt4 prerequisites
|
||||||
sudo apt-get install -y qtmobility-dev libprotobuf-dev protobuf-compiler libqt4-dev
|
sudo apt-get install -y qtmobility-dev libqt4-dev
|
||||||
else
|
else
|
||||||
sudo add-apt-repository -y ppa:beineri/opt-qt521
|
# qt5 prerequisites
|
||||||
sudo add-apt-repository -y ppa:kalakris/cmake
|
sudo apt-get install -y libprotobuf-dev protobuf-compiler \
|
||||||
sudo apt-get update -qq
|
qt5-default qttools5-dev qttools5-dev-tools \
|
||||||
sudo apt-get install -y libprotobuf-dev protobuf-compiler cmake libsqlite3-dev\
|
qtmultimedia5-dev libqt5multimedia5-plugins libqt5svg5-dev libqt5sql5-mysql
|
||||||
qt52base qt52webkit qt52tools qt52svg qt52multimedia
|
fi
|
||||||
|
|
||||||
|
# prerequisites for tests
|
||||||
|
if [[ $BUILDTYPE == "Debug" ]]; then
|
||||||
|
if [[ $DIST == "precise" ]]; then
|
||||||
|
sudo add-apt-repository -y ppa:george-edison55/precise-backports
|
||||||
|
sudo apt-get update -qq
|
||||||
|
sudo apt-get install -y cmake cmake-data libgtest-dev
|
||||||
|
else
|
||||||
|
sudo add-apt-repository -y ppa:george-edison55/cmake-3.x
|
||||||
|
sudo apt-get update -qq
|
||||||
|
sudo apt-get install -y cmake cmake-extras libgtest-dev
|
||||||
|
fi
|
||||||
|
|
||||||
|
sudo mkdir /usr/src/gtest/build
|
||||||
|
cd /usr/src/gtest/build
|
||||||
|
sudo cmake .. -DBUILD_SHARED_LIBS=1
|
||||||
|
sudo make -j2
|
||||||
|
sudo ln -s /usr/src/gtest/build/libgtest.so /usr/lib/libgtest.so
|
||||||
|
sudo ln -s /usr/src/gtest/build/libgtest_main.so /usr/lib/libgtest_main.so
|
||||||
|
cd -
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
Loading…
Reference in a new issue