This commit is contained in:
ctrlaltca 2014-08-07 21:03:42 +00:00
commit 176f42a7dd
119 changed files with 6502 additions and 4865 deletions

View file

@ -7,13 +7,21 @@
cmake_minimum_required(VERSION 2.6) cmake_minimum_required(VERSION 2.6)
set(PROJECT_NAME "Cockatrice") if(POLICY CMP0020)
set(PROJECT_VERSION_MAJOR 0) cmake_policy(SET CMP0020 OLD)
set(PROJECT_VERSION_MINOR 0) endif()
set(PROJECT_VERSION_PATCH 1)
set(PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH} )
# Defualt to "Release" build type if(POLICY CMP0043)
cmake_policy(SET CMP0043 OLD)
endif()
if(POLICY CMP0048)
cmake_policy(SET CMP0048 OLD)
endif()
set(PROJECT_NAME "Cockatrice")
# Default to "Release" build type
# User-provided value for CMAKE_BUILD_TYPE must be checked before the PROJECT() call # User-provided value for CMAKE_BUILD_TYPE must be checked before the PROJECT() call
IF(DEFINED CMAKE_BUILD_TYPE) IF(DEFINED CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "Type of build") SET(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "Type of build")
@ -24,9 +32,19 @@ ENDIF()
# A project name is needed for CPack # A project name is needed for CPack
PROJECT("${PROJECT_NAME}") PROJECT("${PROJECT_NAME}")
# Set conventional loops # Set conventional loops
set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true) set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true)
# Search path for cmake modules
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
# Retrieve git version hash
include(getversion)
# Create a header and a cpp file containing the version hash
include(createversionfile)
# Define a proper install path # Define a proper install path
if(UNIX) if(UNIX)
if(APPLE) if(APPLE)
@ -58,8 +76,19 @@ IF(MSVC)
#set(CMAKE_CXX_FLAGS_DEBUG "/Zi") #set(CMAKE_CXX_FLAGS_DEBUG "/Zi")
ELSEIF (CMAKE_COMPILER_IS_GNUCXX) ELSEIF (CMAKE_COMPILER_IS_GNUCXX)
# linux/gcc, bsd/gcc, windows/mingw # linux/gcc, bsd/gcc, windows/mingw
include(CheckCXXCompilerFlag)
set(CMAKE_CXX_FLAGS_RELEASE "-s -O2") set(CMAKE_CXX_FLAGS_RELEASE "-s -O2")
set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -Wall -Wextra -pedantic -Werror -Wcast-align -Wmissing-declarations -Winline -Wno-long-long -Wno-error=extra -Wno-error=unused-parameter -Wno-inline -Wno-error=delete-non-virtual-dtor -Wno-error=sign-compare -Wno-error=reorder -Wno-error=missing-declarations") set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -Wall -Wextra -pedantic -Werror")
set(ADDITIONAL_DEBUG_FLAGS -Wcast-align -Wmissing-declarations -Winline -Wno-long-long -Wno-error=extra -Wno-error=unused-parameter -Wno-inline -Wno-error=delete-non-virtual-dtor -Wno-error=sign-compare -Wno-error=reorder -Wno-error=missing-declarations)
FOREACH(FLAG ${ADDITIONAL_DEBUG_FLAGS})
CHECK_CXX_COMPILER_FLAG("${FLAG}" CXX_HAS_WARNING_${FLAG})
IF(CXX_HAS_WARNING_${FLAG})
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${FLAG}")
ENDIF()
ENDFOREACH()
ELSE() ELSE()
# other: osx/llvm, bsd/llvm # other: osx/llvm, bsd/llvm
set(CMAKE_CXX_FLAGS_RELEASE "-O2") set(CMAKE_CXX_FLAGS_RELEASE "-O2")
@ -71,8 +100,33 @@ IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
ADD_DEFINITIONS("-DSFMT_MEXP=19937") ADD_DEFINITIONS("-DSFMT_MEXP=19937")
ENDIF() ENDIF()
#Find Qt4 and enable the needed features # Find Qt and enable the needed features
FIND_PACKAGE(Qt4 REQUIRED) # Default is Qt5 unless WITH_QT4 option is enabled
option(WITH_QT4 "Force thr use of Qt4 libraries" OFF)
IF(NOT WITH_QT4)
FIND_PACKAGE(Qt5Widgets)
ENDIF()
IF(Qt5Widgets_FOUND)
MESSAGE(STATUS "Found Qt ${Qt5Widgets_VERSION_STRING}")
if(UNIX AND NOT APPLE AND "${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64")
# FIX: Qt was built with -reduce-relocations
add_definitions(-fPIC)
endif()
ELSE()
FIND_PACKAGE(Qt4 4.8.0 REQUIRED)
IF(QT4_FOUND)
# Old FindQt4.cmake modules used the same flag with different case
SET(Qt4_FOUND TRUE)
ENDIF()
IF(Qt4_FOUND)
MESSAGE(STATUS "Found Qt ${QT_VERSION_MAJOR}.${QT_VERSION_MINOR}.${QT_VERSION_PATCH}")
ELSE()
MESSAGE(FATAL_ERROR "No Qt4 or Qt5 found!")
ENDIF()
ENDIF()
set(CMAKE_AUTOMOC TRUE) set(CMAKE_AUTOMOC TRUE)
@ -83,8 +137,8 @@ FIND_PACKAGE(Protobuf REQUIRED)
set(CPACK_PACKAGE_CONTACT "Daenyth+github@gmail.com") set(CPACK_PACKAGE_CONTACT "Daenyth+github@gmail.com")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY ${PROJECT_NAME}) set(CPACK_PACKAGE_DESCRIPTION_SUMMARY ${PROJECT_NAME})
set(CPACK_PACKAGE_VENDOR "Cockatrice Development Team") set(CPACK_PACKAGE_VENDOR "Cockatrice Development Team")
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README.md") set(CPACK_PACKAGE_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/README.md")
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING") set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/COPYING")
set(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}") 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}")
@ -96,7 +150,7 @@ 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}-${PROJECT_VERSION}") set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-osx_git-${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
@ -107,13 +161,13 @@ if(UNIX)
endif() endif()
elseif(WIN32) elseif(WIN32)
set(CPACK_GENERATOR NSIS ${CPACK_GENERATOR}) set(CPACK_GENERATOR NSIS ${CPACK_GENERATOR})
set(CPACK_PACKAGE_INSTALL_DIRECTORY "${PROJECT_NAME}\\\\${PROJECT_VERSION}") set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}_win32_git-${PROJECT_VERSION}")
set(CPACK_NSIS_INSTALLED_ICON_NAME "bin\\\\${PROJECT_NAME}.exe")
set(CPACK_NSIS_DISPLAY_NAME "${CPACK_PACKAGE_INSTALL_DIRECTORY} ${PROJECT_NAME}") # Configure file with custom definitions for NSIS.
set(CPACK_NSIS_HELP_LINK "https://github.com/Daenyth/Cockatrice") configure_file(
set(CPACK_NSIS_URL_INFO_ABOUT "https://github.com/Daenyth/Cockatrice") ${CMAKE_MODULE_PATH}/NSIS.definitions.nsh.in
set(CPACK_NSIS_CONTACT "Daenyth+github@gmail.com") ${PROJECT_BINARY_DIR}/NSIS.definitions.nsh
set(CPACK_NSIS_MODIFY_PATH ON) )
endif() endif()
include(CPack) include(CPack)

105
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,105 @@
# Style Guide #
### Compatibility ###
Cockatrice is written in C++-03, so do not use C++11 constructs such as `auto`.
Cockatrice support both Qt 4 and Qt 5, so make sure that your code compiles
with both. If there have been breaking changes between Qt 4 and 5, use a
statement such as
#if QT_VERSION >= 0x500000
doSomethingWithQt5();
#else
doSomethingWithQt4();
#endif
For consistency, use Qt data structures where possible, such as `QString` over
`std::string` or `QList` over `std::vector`.
### Header files ###
Use header files with the extension `.h` and source files with the extension
`.cpp`.
Use header guards in the form of `FILE_NAME_H`.
Simple functions, such as getters, may be written inline in the header file,
but other functions should be written in the source file.
Keep library includes and project includes grouped together. So this is okay:
// Good:
#include <QList>
#include <QString>
#include "card.h"
#include "deck.h"
// Good:
#include "card.h"
#include "deck.h"
#include <QList>
#include <QString>
// Bad:
#include <QList>
#include "card.h"
#include <QString>
#include "deck.h"
### Naming ###
Use `UpperCamelCase` for classes, structs, enums, etc. and `lowerCamelCase` for
function and variable names.
Member variables aren't decorated in any way. Don't prefix or suffix with
underscores, etc.
For arguments to constructors which have the same names as member variables,
prefix those arguments with underscores:
MyClass::MyClass(int _myData)
: myData(_myData)
{}
Pointers and references should be denoted with the `*` or `&` going with the
variable name:
// Good:
Foo *foo1 = new Foo;
Foo &foo2 = *foo1;
// Bad:
Bar* bar1 = new Bar;
Bar& bar2 = *bar1;
Use `0` instead of `NULL` (or `nullptr`) for null pointers.
### Braces ###
Use K&R-style braces. Braces for function implementations go on their own
lines, but they go on the same line everywhere else:
int main()
{
if (someCondition) {
doSomething();
} else {
while (someOtherCondition) {
doSomethingElse();
}
}
}
Braces can be omitted for single-statement if's and the like, as long as it is
still legible.
### Tabs ###
Use only spaces. Four spaces per tab.
### Lines ###
Do not have trailing whitespace in your lines.
Lines should be 80 characters or less, as a soft limit.

View file

@ -33,8 +33,11 @@ To compile:
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` Build the server
- `-DWITHOUT_CLIENT=1` do not build the client - `-DWITH_CLIENT=0` Do not build the client
- `-DWITH_ORACLE=0` Do not build Oracle
- `-DWITH_QT4=1` Force compilation to use Qt4 instead of Qt5.
- `-DCMAKE_BUILD_TYPE=Debug` Compile in debug mode. Enables extra logging output, debug symbols, and much more verbose compiler warnings.
# Running # Running

View file

@ -0,0 +1 @@
!define NSIS_SOURCE_PATH "@PROJECT_SOURCE_DIR@"

View file

@ -1,30 +1,26 @@
!include ..\..\..\NSIS.definitions.nsh
!include "MUI2.nsh" !include "MUI2.nsh"
!include "FileFunc.nsh" !include "FileFunc.nsh"
!define /date TIMESTAMP "%Y%m%d" Name "@CPACK_PACKAGE_NAME@"
!searchparse /file ../build/cockatrice/version_string.cpp '= "' VERSION '";' OutFile "@CPACK_TOPLEVEL_DIRECTORY@/@CPACK_OUTPUT_FILE_NAME@"
Name "Cockatrice"
OutFile "cockatrice_win32_${TIMESTAMP}_git-${VERSION}.exe"
SetCompressor /SOLID lzma SetCompressor /SOLID lzma
InstallDir "$PROGRAMFILES\Cockatrice" InstallDir "$PROGRAMFILES\Cockatrice"
!define INST_DIR "@CPACK_TEMPORARY_DIRECTORY@"
; set the Qt install dir here (and make sure you use the latest 4.8 version for packaging)
!define QTDIR "C:\Qt\4.8.6"
!define MUI_ABORTWARNING !define MUI_ABORTWARNING
!define MUI_WELCOMEFINISHPAGE_BITMAP "leftimage.bmp" !define MUI_WELCOMEFINISHPAGE_BITMAP "${NSIS_SOURCE_PATH}\cmake\leftimage.bmp"
!define MUI_UNWELCOMEFINISHPAGE_BITMAP "leftimage.bmp" !define MUI_UNWELCOMEFINISHPAGE_BITMAP "${NSIS_SOURCE_PATH}\cmake\leftimage.bmp"
!define MUI_HEADERIMAGE !define MUI_HEADERIMAGE
!define MUI_HEADERIMAGE_BITMAP "headerimage.bmp" !define MUI_HEADERIMAGE_BITMAP "${NSIS_SOURCE_PATH}\cmake\headerimage.bmp"
!define MUI_HEADERIMAGE_UNBITMAP "headerimage.bmp" !define MUI_HEADERIMAGE_UNBITMAP "${NSIS_SOURCE_PATH}\cmake\headerimage.bmp"
!define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the installation of Cockatrice.$\r$\n$\r$\nClick Next to continue." !define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the installation of Cockatrice.$\r$\n$\r$\nClick Next to continue."
!define MUI_FINISHPAGE_RUN "$INSTDIR/oracle.exe" !define MUI_FINISHPAGE_RUN "$INSTDIR/oracle.exe"
!define MUI_FINISHPAGE_RUN_TEXT "Run card database downloader now" !define MUI_FINISHPAGE_RUN_TEXT "Run card database downloader now"
!define MUI_FINISHPAGE_RUN_PARAMETERS "-dlsets" !define MUI_FINISHPAGE_RUN_PARAMETERS "-dlsets"
!insertmacro MUI_PAGE_WELCOME !insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE "..\COPYING" !insertmacro MUI_PAGE_LICENSE "${NSIS_SOURCE_PATH}\COPYING"
!insertmacro MUI_PAGE_COMPONENTS !insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_DIRECTORY !insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES !insertmacro MUI_PAGE_INSTFILES
@ -39,37 +35,9 @@ InstallDir "$PROGRAMFILES\Cockatrice"
Section "Application" SecApplication Section "Application" SecApplication
SetShellVarContext all SetShellVarContext all
SetOutPath "$INSTDIR" SetOutPath "$INSTDIR"
File ..\build\cockatrice\Release\cockatrice.exe
File ..\build\oracle\Release\oracle.exe
File ..\doc\usermanual\Usermanual.pdf
File ..\build\protobuf-2.5.0\protobuf-2.5.0\vsprojects\Release\libprotobuf.lib
File "${QTDIR}\bin\QtCore4.dll"
File "${QTDIR}\bin\QtGui4.dll"
File "${QTDIR}\bin\QtNetwork4.dll"
File "${QTDIR}\bin\QtSvg4.dll"
File "${QTDIR}\bin\QtXml4.dll"
File "${QTDIR}\bin\QtMultimedia4.dll"
SetOutPath "$INSTDIR\zonebg" @CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS@
File /r ..\zonebg\*.* @CPACK_NSIS_FULL_INSTALL@
SetOutPath "$INSTDIR\plugins"
SetOutPath "$INSTDIR\plugins\codecs"
File "${QTDIR}\plugins\codecs\qcncodecs4.dll"
File "${QTDIR}\plugins\codecs\qjpcodecs4.dll"
File "${QTDIR}\plugins\codecs\qkrcodecs4.dll"
File "${QTDIR}\plugins\codecs\qtwcodecs4.dll"
SetOutPath "$INSTDIR\plugins\iconengines"
File "${QTDIR}\plugins\iconengines\qsvgicon4.dll"
SetOutPath "$INSTDIR\plugins\imageformats"
File "${QTDIR}\plugins\imageformats\qjpeg4.dll"
File "${QTDIR}\plugins\imageformats\qsvg4.dll"
SetOutPath "$INSTDIR\sounds"
File /r ..\sounds\*.*
SetOutPath "$INSTDIR\translations"
File /r ..\build\cockatrice\*.qm
WriteUninstaller "$INSTDIR\uninstall.exe" WriteUninstaller "$INSTDIR\uninstall.exe"
${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2 ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2
@ -107,12 +75,10 @@ SetShellVarContext all
Delete "$INSTDIR\oracle.exe" Delete "$INSTDIR\oracle.exe"
Delete "$INSTDIR\Usermanual.pdf" Delete "$INSTDIR\Usermanual.pdf"
Delete "$INSTDIR\libprotobuf.lib" Delete "$INSTDIR\libprotobuf.lib"
Delete "$INSTDIR\QtCore4.dll" Delete "$INSTDIR\Qt*.dll"
Delete "$INSTDIR\QtGui4.dll" Delete "$INSTDIR\icu*.dll"
Delete "$INSTDIR\QtNetwork4.dll" Delete "$INSTDIR\qt.conf"
Delete "$INSTDIR\QtSvg4.dll" Delete "$INSTDIR\qdebug.txt"
Delete "$INSTDIR\QtXml4.dll"
Delete "$INSTDIR\QtMultimedia4.dll"
RMDir "$INSTDIR" RMDir "$INSTDIR"
RMDir "$SMPROGRAMS\Cockatrice" RMDir "$SMPROGRAMS\Cockatrice"

View file

@ -0,0 +1,17 @@
set(VERSION_STRING_CPP "${PROJECT_BINARY_DIR}/version_string.cpp")
set(VERSION_STRING_H "${PROJECT_BINARY_DIR}/version_string.h")
INCLUDE_DIRECTORIES(${PROJECT_BINARY_DIR})
set( hstring "extern const char *VERSION_STRING\;\n" )
set( cppstring "const char * VERSION_STRING = \"${PROJECT_VERSION}\"\;\n")
file(WRITE ${PROJECT_BINARY_DIR}/version_string.cpp.txt ${cppstring} )
file(WRITE ${PROJECT_BINARY_DIR}/version_string.h.txt ${hstring} )
execute_process(
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PROJECT_BINARY_DIR}/version_string.h.txt ${VERSION_STRING_H}
)
execute_process(
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PROJECT_BINARY_DIR}/version_string.cpp.txt ${VERSION_STRING_CPP}
)

View file

@ -2,6 +2,7 @@ find_package(Git)
if(GIT_FOUND) if(GIT_FOUND)
execute_process( execute_process(
COMMAND ${GIT_EXECUTABLE} describe --long --always COMMAND ${GIT_EXECUTABLE} describe --long --always
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
RESULT_VARIABLE res_var RESULT_VARIABLE res_var
OUTPUT_VARIABLE GIT_COM_ID OUTPUT_VARIABLE GIT_COM_ID
) )
@ -15,15 +16,5 @@ else()
message( WARNING "Git not found. Build will not contain git revision info." ) message( WARNING "Git not found. Build will not contain git revision info." )
endif() endif()
set( hstring "extern const char *VERSION_STRING\;\n" ) set(PROJECT_VERSION_MAJOR ${GIT_COMMIT_ID})
set( cppstring "const char * VERSION_STRING = \"${GIT_COMMIT_ID}\"\;\n") set(PROJECT_VERSION ${GIT_COMMIT_ID} )
file(WRITE version_string.cpp.txt ${cppstring} )
file(WRITE version_string.h.txt ${hstring} )
execute_process(
COMMAND ${CMAKE_COMMAND} -E copy_if_different version_string.h.txt ${CMAKE_CURRENT_BINARY_DIR}/version_string.h
)
execute_process(
COMMAND ${CMAKE_COMMAND} -E copy_if_different version_string.cpp.txt ${CMAKE_CURRENT_BINARY_DIR}/version_string.cpp
)

View file

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 201 KiB

After

Width:  |  Height:  |  Size: 201 KiB

Before After
Before After

View file

@ -90,7 +90,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
${CMAKE_CURRENT_BINARY_DIR}/version_string.cpp ${VERSION_STRING_CPP}
) )
if (UNIX AND NOT APPLE) if (UNIX AND NOT APPLE)
@ -125,41 +125,119 @@ if(APPLE)
set(cockatrice_SOURCES ${cockatrice_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/resources/appicon.icns) set(cockatrice_SOURCES ${cockatrice_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/resources/appicon.icns)
ENDIF(APPLE) ENDIF(APPLE)
set(COCKATRICE_LIBS)
# Qt4 stuff
if(Qt4_FOUND)
if (NOT QT_QTMULTIMEDIA_FOUND) if (NOT QT_QTMULTIMEDIA_FOUND)
SET(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
FIND_PACKAGE(QtMobility REQUIRED) FIND_PACKAGE(QtMobility REQUIRED)
endif (NOT QT_QTMULTIMEDIA_FOUND) endif()
SET(QT_USE_QTNETWORK TRUE) SET(QT_USE_QTNETWORK TRUE)
SET(QT_USE_QTMULTIMEDIA TRUE) SET(QT_USE_QTMULTIMEDIA TRUE)
SET(QT_USE_QTXML TRUE) SET(QT_USE_QTXML TRUE)
SET(QT_USE_QTSVG TRUE) SET(QT_USE_QTSVG TRUE)
# Declare path variables # Include directories
set(ICONDIR share/icons CACHE STRING "icon dir") INCLUDE(${QT_USE_FILE})
set(DESKTOPDIR share/applications CACHE STRING "desktop file destination") INCLUDE_DIRECTORIES(${QT_INCLUDES})
INCLUDE_DIRECTORIES(${QT_MOBILITY_INCLUDE_DIR})
INCLUDE_DIRECTORIES(${QT_MOBILITY_MULTIMEDIAKIT_INCLUDE_DIR})
LIST(APPEND COCKATRICE_LIBS ${QT_LIBRARIES})
LIST(APPEND COCKATRICE_LIBS ${QT_QTMAIN_LIBRARY})
LIST(APPEND COCKATRICE_LIBS ${QT_MOBILITY_MULTIMEDIAKIT_LIBRARY})
# Let cmake chew Qt4's translations and resource files # Let cmake chew Qt4's translations and resource files
# Note: header files are MOC-ed automatically by cmake # Note: header files are MOC-ed automatically by cmake
QT4_ADD_TRANSLATION(cockatrice_QM ${cockatrice_TS}) QT4_ADD_TRANSLATION(cockatrice_QM ${cockatrice_TS})
QT4_ADD_RESOURCES(cockatrice_RESOURCES_RCC ${cockatrice_RESOURCES}) QT4_ADD_RESOURCES(cockatrice_RESOURCES_RCC ${cockatrice_RESOURCES})
endif()
# qt5 stuff
if(Qt5Widgets_FOUND)
include_directories(${Qt5Widgets_INCLUDE_DIRS})
list(APPEND COCKATRICE_LIBS Widgets)
# QtNetwork
find_package(Qt5Network)
if(Qt5Network_FOUND)
include_directories(${Qt5Network_INCLUDE_DIRS})
list(APPEND COCKATRICE_LIBS Network)
endif()
# QtMultimedia
find_package(Qt5Multimedia)
if(Qt5Multimedia_FOUND)
include_directories(${Qt5Multimedia_INCLUDE_DIRS})
list(APPEND COCKATRICE_LIBS Multimedia)
endif()
# QtPrinter
find_package(Qt5PrintSupport)
if(Qt5PrintSupport_FOUND)
include_directories(${Qt5PrintSupport_INCLUDE_DIRS})
list(APPEND COCKATRICE_LIBS PrintSupport)
endif()
# QtXml
find_package(Qt5Xml)
if(Qt5Xml_FOUND)
include_directories(${Qt5Xml_INCLUDE_DIRS})
list(APPEND COCKATRICE_LIBS Xml)
endif()
# QtSvg
find_package(Qt5Svg)
if(Qt5Svg_FOUND)
include_directories(${Qt5Svg_INCLUDE_DIRS})
list(APPEND COCKATRICE_LIBS Svg)
endif()
# Qt5LinguistTools
find_package(Qt5LinguistTools)
if(Qt5LinguistTools_FOUND)
include_directories(${Qt5LinguistTools_INCLUDE_DIRS})
list(APPEND COCKATRICE_LIBS LinguistTools)
endif()
# Let cmake chew Qt5's translations and resource files
# Note: header files are MOC-ed automatically by cmake
QT5_ADD_TRANSLATION(cockatrice_QM ${cockatrice_TS})
QT5_ADD_RESOURCES(cockatrice_RESOURCES_RCC ${cockatrice_RESOURCES})
# guess plugins and libraries directory
set(QT_PLUGINS_DIR "${Qt5Widgets_DIR}/../../../plugins")
get_target_property(QT_LIBRARY_DIR Qt5::Core LOCATION)
get_filename_component(QT_LIBRARY_DIR ${QT_LIBRARY_DIR} PATH)
endif()
# Declare path variables
set(ICONDIR share/icons CACHE STRING "icon dir")
set(DESKTOPDIR share/applications CACHE STRING "desktop file destination")
# Include directories # Include directories
INCLUDE(${QT_USE_FILE})
INCLUDE_DIRECTORIES(../common) INCLUDE_DIRECTORIES(../common)
INCLUDE_DIRECTORIES(${PROTOBUF_INCLUDE_DIR}) INCLUDE_DIRECTORIES(${PROTOBUF_INCLUDE_DIR})
INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/common) INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/common)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
INCLUDE_DIRECTORIES(${QT_MOBILITY_INCLUDE_DIR})
INCLUDE_DIRECTORIES(${QT_MOBILITY_MULTIMEDIAKIT_INCLUDE_DIR})
# Build cockatrice binary and link it # Build cockatrice binary and link it
ADD_EXECUTABLE(cockatrice WIN32 MACOSX_BUNDLE ${cockatrice_SOURCES} ${cockatrice_QM} ${cockatrice_RESOURCES_RCC} ${cockatrice_MOC_SRCS}) ADD_EXECUTABLE(cockatrice WIN32 MACOSX_BUNDLE ${cockatrice_SOURCES} ${cockatrice_QM} ${cockatrice_RESOURCES_RCC} ${cockatrice_MOC_SRCS})
TARGET_LINK_LIBRARIES(cockatrice cockatrice_common ${QT_QTMAIN_LIBRARY} ${QT_LIBRARIES} ${QT_MOBILITY_MULTIMEDIAKIT_LIBRARY})
if(Qt4_FOUND)
if(MSVC) if(MSVC)
set_target_properties(cockatrice PROPERTIES LINK_FLAGS "/SUBSYSTEM:WINDOWS") set(QT_USE_QTMAIN true)
endif(MSVC) endif()
TARGET_LINK_LIBRARIES(cockatrice cockatrice_common ${COCKATRICE_LIBS})
endif()
if(Qt5Widgets_FOUND)
if(MSVC)
TARGET_LINK_LIBRARIES(cockatrice cockatrice_common Qt5::WinMain)
else()
TARGET_LINK_LIBRARIES(cockatrice cockatrice_common)
endif()
qt5_use_modules(cockatrice ${COCKATRICE_LIBS})
endif()
if(UNIX) if(UNIX)
if(APPLE) if(APPLE)
@ -178,11 +256,6 @@ elseif(WIN32)
INSTALL(FILES ${cockatrice_QM} DESTINATION ./translations) INSTALL(FILES ${cockatrice_QM} DESTINATION ./translations)
endif() endif()
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/version_string.cpp ${CMAKE_CURRENT_BINARY_DIR}/version_string.h
COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR} -P ${CMAKE_CURRENT_SOURCE_DIR}/../common/getversion.cmake
)
if(APPLE) if(APPLE)
# these needs to be relative to CMAKE_INSTALL_PREFIX # these needs to be relative to CMAKE_INSTALL_PREFIX
set(plugin_dest_dir cockatrice.app/Contents/Plugins) set(plugin_dest_dir cockatrice.app/Contents/Plugins)
@ -215,3 +288,36 @@ Data = Resources\")
fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/cockatrice.app\" \"\${QTPLUGINS}\" \"${QT_LIBRARY_DIR}\") fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/cockatrice.app\" \"\${QTPLUGINS}\" \"${QT_LIBRARY_DIR}\")
" COMPONENT Runtime) " COMPONENT Runtime)
endif() endif()
if(WIN32)
# these needs to be relative to CMAKE_INSTALL_PREFIX
set(plugin_dest_dir Plugins)
set(qtconf_dest_dir .)
# note: no codecs in qt5
# note: phonon_backend => mediaservice
# note: needs platform on osx
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime
FILES_MATCHING REGEX "(codecs|iconengines|imageformats|mediaservice|phonon_backend|platforms)/.*d\\.dll")
else()
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime
FILES_MATCHING REGEX "(codecs|iconengines|imageformats|mediaservice|phonon_backend|platforms)/.*[^d]\\.dll")
endif()
install(CODE "
file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf\" \"[Paths]
Plugins = Plugins
Translations = Resources/translations
Data = Resources\")
" COMPONENT Runtime)
install(CODE "
file(GLOB_RECURSE QTPLUGINS
\"\${CMAKE_INSTALL_PREFIX}/${plugin_dest_dir}/*.dll\")
set(BU_CHMOD_BUNDLE_ITEMS ON)
include(BundleUtilities)
fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/cockatrice.exe\" \"\${QTPLUGINS}\" \"${QT_LIBRARY_DIR}\")
" COMPONENT Runtime)
endif()

View file

@ -11,7 +11,11 @@
AbstractCounter::AbstractCounter(Player *_player, int _id, const QString &_name, bool _shownInCounterArea, int _value, QGraphicsItem *parent) AbstractCounter::AbstractCounter(Player *_player, int _id, const QString &_name, bool _shownInCounterArea, int _value, QGraphicsItem *parent)
: QGraphicsItem(parent), player(_player), id(_id), name(_name), value(_value), hovered(false), aDec(0), aInc(0), dialogSemaphore(false), deleteAfterDialog(false), shownInCounterArea(_shownInCounterArea) : QGraphicsItem(parent), player(_player), id(_id), name(_name), value(_value), hovered(false), aDec(0), aInc(0), dialogSemaphore(false), deleteAfterDialog(false), shownInCounterArea(_shownInCounterArea)
{ {
#if QT_VERSION < 0x050000
setAcceptsHoverEvents(true); setAcceptsHoverEvents(true);
#else
setAcceptHoverEvents(true);
#endif
if (player->getLocal()) { if (player->getLocal()) {
menu = new QMenu(name); menu = new QMenu(name);
@ -129,7 +133,13 @@ void AbstractCounter::setCounter()
{ {
bool ok; bool ok;
dialogSemaphore = true; dialogSemaphore = true;
int newValue = QInputDialog::getInteger(0, tr("Set counter"), tr("New value for counter '%1':").arg(name), value, -2000000000, 2000000000, 1, &ok); int newValue =
#if QT_VERSION < 0x050000
QInputDialog::getInteger(
#else
QInputDialog::getInt(
#endif
0, tr("Set counter"), tr("New value for counter '%1':").arg(name), value, -2000000000, 2000000000, 1, &ok);
if (deleteAfterDialog) { if (deleteAfterDialog) {
deleteLater(); deleteLater();
return; return;

View file

@ -13,6 +13,7 @@
#include <QNetworkReply> #include <QNetworkReply>
#include <QNetworkRequest> #include <QNetworkRequest>
#include <QDebug> #include <QDebug>
#include <QImageReader>
const int CardDatabase::versionNeeded = 3; const int CardDatabase::versionNeeded = 3;
@ -92,6 +93,14 @@ bool PictureToLoad::nextSet()
return true; return true;
} }
QString PictureToLoad::getSetName() const
{
if (setIndex < sortedSets.size())
return sortedSets[setIndex]->getCorrectedShortName();
else
return QString("");
}
PictureLoader::PictureLoader(const QString &__picsPath, bool _picDownload, bool _picDownloadHq, QObject *parent) PictureLoader::PictureLoader(const QString &__picsPath, bool _picDownload, bool _picDownloadHq, QObject *parent)
: QObject(parent), : QObject(parent),
_picsPath(__picsPath), picDownload(_picDownload), picDownloadHq(_picDownloadHq), _picsPath(__picsPath), picDownload(_picDownload), picDownloadHq(_picDownloadHq),
@ -124,14 +133,33 @@ void PictureLoader::processLoadQueue()
} }
PictureToLoad ptl = loadQueue.takeFirst(); PictureToLoad ptl = loadQueue.takeFirst();
mutex.unlock(); mutex.unlock();
QString correctedName = ptl.getCard()->getCorrectedName();
QString picsPath = _picsPath; //The list of paths to the folders in which to search for images
QList<QString> picsPaths = QList<QString>() << _picsPath + "/CUSTOM/" + ptl.getCard()->getCorrectedName() + ".full";
QString setName=ptl.getSetName(); QString setName=ptl.getSetName();
if(!setName.isEmpty())
{
picsPaths << _picsPath + "/" + setName + "/" + ptl.getCard()->getCorrectedName() + ".full"
<< _picsPath + "/downloadedPics/" + setName + "/" + ptl.getCard()->getCorrectedName() + ".full";
}
QImage image; QImage image;
if (!image.load(QString("%1/%2/%3.full.jpg").arg(picsPath).arg(setName).arg(correctedName))) QImageReader imgReader;
if (!image.load(QString("%1/%2/%3%4.full.jpg").arg(picsPath).arg(setName).arg(correctedName).arg(1))) imgReader.setDecideFormatFromContent(true);
if (!image.load(QString("%1/%2/%3/%4.full.jpg").arg(picsPath).arg("downloadedPics").arg(setName).arg(correctedName))) { 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)) {
emit imageLoaded(ptl.getCard(), image);
found = true;
}
}
if (!found) {
if (picDownload) { if (picDownload) {
cardsToDownload.append(ptl); cardsToDownload.append(ptl);
if (!downloadRunning) if (!downloadRunning)
@ -142,10 +170,7 @@ void PictureLoader::processLoadQueue()
else else
emit imageLoaded(ptl.getCard(), QImage()); emit imageLoaded(ptl.getCard(), QImage());
} }
continue;
} }
emit imageLoaded(ptl.getCard(), image);
} }
} }
@ -153,11 +178,30 @@ QString PictureLoader::getPicUrl(CardInfo *card)
{ {
if (!picDownload) return QString(""); if (!picDownload) return QString("");
QString picUrl = picDownloadHq ? settingsCache->getPicUrlHq() : settingsCache->getPicUrl(); CardSet *set = card->getPreferredSet();
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;
}
// otherwise, fallback to the default url
picUrl = picDownloadHq ? settingsCache->getPicUrlHq() : settingsCache->getPicUrl();
picUrl.replace("!name!", QUrl::toPercentEncoding(card->getCorrectedName())); picUrl.replace("!name!", QUrl::toPercentEncoding(card->getCorrectedName()));
CardSet *set = card->getPreferredSet();
if (set) { if (set) {
picUrl.replace("!setcode!", QUrl::toPercentEncoding(set->getShortName())); picUrl.replace("!setcode!", QUrl::toPercentEncoding(set->getShortName()));
picUrl.replace("!setname!", QUrl::toPercentEncoding(set->getLongName())); picUrl.replace("!setname!", QUrl::toPercentEncoding(set->getLongName()));
@ -211,29 +255,35 @@ void PictureLoader::picDownloadFinished(QNetworkReply *reply)
qDebug() << "Download failed:" << reply->errorString(); qDebug() << "Download failed:" << reply->errorString();
} }
const QByteArray &picData = reply->readAll(); const QByteArray &picData = reply->peek(reply->size()); //peek is used to keep the data in the buffer for use by QImageReader
QImage testImage; QImage testImage;
if (testImage.loadFromData(picData)) {
if (!QDir(QString(picsPath + "/downloadedPics/")).exists()) { QImageReader imgReader;
QDir dir(picsPath); imgReader.setDecideFormatFromContent(true);
if (!dir.exists()) 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; return;
dir.mkdir("downloadedPics");
}
if (!QDir(QString(picsPath + "/downloadedPics/" + cardBeingDownloaded.getSetName())).exists()) {
QDir dir(QString(picsPath + "/downloadedPics"));
dir.mkdir(cardBeingDownloaded.getSetName());
} }
QString suffix; QString suffix;
if (!cardBeingDownloaded.getStripped()) if (!cardBeingDownloaded.getStripped())
suffix = ".full"; suffix = ".full";
QFile newPic(picsPath + "/downloadedPics/" + cardBeingDownloaded.getSetName() + "/" + cardBeingDownloaded.getCard()->getCorrectedName() + suffix + ".jpg"); QFile newPic(picsPath + "/downloadedPics/" + setName + "/" + cardBeingDownloaded.getCard()->getCorrectedName() + suffix + extension);
if (!newPic.open(QIODevice::WriteOnly)) if (!newPic.open(QIODevice::WriteOnly))
return; return;
newPic.write(picData); newPic.write(picData);
newPic.close(); newPic.close();
}
emit imageLoaded(cardBeingDownloaded.getCard(), testImage); emit imageLoaded(cardBeingDownloaded.getCard(), testImage);
} else if (cardBeingDownloaded.getHq()) { } else if (cardBeingDownloaded.getHq()) {
@ -294,6 +344,8 @@ CardInfo::CardInfo(CardDatabase *_db,
bool _cipt, bool _cipt,
int _tableRow, int _tableRow,
const SetList &_sets, const SetList &_sets,
const QStringMap &_customPicURLs,
const QStringMap &_customPicURLsHq,
MuidMap _muIds) MuidMap _muIds)
: db(_db), : db(_db),
name(_name), name(_name),
@ -305,6 +357,8 @@ CardInfo::CardInfo(CardDatabase *_db,
text(_text), text(_text),
colors(_colors), colors(_colors),
loyalty(_loyalty), loyalty(_loyalty),
customPicURLs(_customPicURLs),
customPicURLsHq(_customPicURLsHq),
muIds(_muIds), muIds(_muIds),
cipt(_cipt), cipt(_cipt),
tableRow(_tableRow), tableRow(_tableRow),
@ -443,6 +497,8 @@ void CardInfo::updatePixmapCache()
CardSet* CardInfo::getPreferredSet() CardSet* CardInfo::getPreferredSet()
{ {
if(sets.isEmpty())
return 0;
SetList sortedSets = sets; SetList sortedSets = sets;
sortedSets.sortByKey(); sortedSets.sortByKey();
return sortedSets.first(); return sortedSets.first();
@ -450,7 +506,28 @@ CardSet* CardInfo::getPreferredSet()
int CardInfo::getPreferredMuId() int CardInfo::getPreferredMuId()
{ {
return muIds[getPreferredSet()->getShortName()]; CardSet *set = getPreferredSet();
return set ? muIds[set->getShortName()] : 0;
}
QString CardInfo::simplifyName(const QString &name) {
QString simpleName(name);
// So Aetherling would work, but not Ætherling since 'Æ' would get replaced
// with nothing.
simpleName.replace("æ", "ae");
simpleName.replace("Æ", "AE");
// Replace Jötun Grunt with Jotun Grunt.
simpleName = simpleName.normalized(QString::NormalizationForm_KD);
// Replace dashes with spaces so that we can say "garruk the veil cursed"
// instead of the unintuitive "garruk the veilcursed".
simpleName = simpleName.replace("-", " ");
simpleName.remove(QRegExp("[^a-zA-Z0-9 ]"));
simpleName = simpleName.toLower();
return simpleName;
} }
static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfo *info) static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfo *info)
@ -467,6 +544,14 @@ static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfo *info)
tmpSet=sets[i]->getShortName(); tmpSet=sets[i]->getShortName();
xml.writeAttribute("muId", QString::number(info->getMuId(tmpSet))); xml.writeAttribute("muId", QString::number(info->getMuId(tmpSet)));
tmpString = info->getCustomPicURL(tmpSet);
if(!tmpString.isEmpty())
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();
} }
@ -526,55 +611,55 @@ CardDatabase::~CardDatabase()
void CardDatabase::clear() void CardDatabase::clear()
{ {
QHashIterator<QString, CardSet *> setIt(setHash); QHashIterator<QString, CardSet *> setIt(sets);
while (setIt.hasNext()) { while (setIt.hasNext()) {
setIt.next(); setIt.next();
delete setIt.value(); delete setIt.value();
} }
setHash.clear(); sets.clear();
QHashIterator<QString, CardInfo *> i(cardHash); QHashIterator<QString, CardInfo *> i(cards);
while (i.hasNext()) { while (i.hasNext()) {
i.next(); i.next();
delete i.value(); delete i.value();
} }
cardHash.clear(); cards.clear();
// The pointers themselves were already deleted, so we don't delete them
// again.
simpleNameCards.clear();
} }
void CardDatabase::addCard(CardInfo *card) void CardDatabase::addCard(CardInfo *card)
{ {
cardHash.insert(card->getName(), card); cards.insert(card->getName(), card);
simpleNameCards.insert(CardInfo::simplifyName(card->getName()), card);
emit cardAdded(card); emit cardAdded(card);
} }
void CardDatabase::removeCard(CardInfo *card) void CardDatabase::removeCard(CardInfo *card)
{ {
cardHash.remove(card->getName()); cards.remove(card->getName());
simpleNameCards.remove(CardInfo::simplifyName(card->getName()));
emit cardRemoved(card); emit cardRemoved(card);
} }
CardInfo *CardDatabase::getCard(const QString &cardName, bool createIfNotFound) CardInfo *CardDatabase::getCard(const QString &cardName, bool createIfNotFound) {
{ return getCardFromMap(cards, cardName, createIfNotFound);
if (cardName.isEmpty()) }
return noCard;
else if (cardHash.contains(cardName)) CardInfo *CardDatabase::getCardBySimpleName(const QString &cardName, bool createIfNotFound) {
return cardHash.value(cardName); QString simpleName = CardInfo::simplifyName(cardName);
else if (createIfNotFound) { return getCardFromMap(simpleNameCards, simpleName, createIfNotFound);
CardInfo *newCard = new CardInfo(this, cardName, true);
newCard->addToSet(getSet("TK"));
cardHash.insert(cardName, newCard);
return newCard;
} else
return 0;
} }
CardSet *CardDatabase::getSet(const QString &setName) CardSet *CardDatabase::getSet(const QString &setName)
{ {
if (setHash.contains(setName)) if (sets.contains(setName))
return setHash.value(setName); return sets.value(setName);
else { else {
CardSet *newSet = new CardSet(setName); CardSet *newSet = new CardSet(setName);
setHash.insert(setName, newSet); sets.insert(setName, newSet);
return newSet; return newSet;
} }
} }
@ -582,7 +667,7 @@ CardSet *CardDatabase::getSet(const QString &setName)
SetList CardDatabase::getSetList() const SetList CardDatabase::getSetList() const
{ {
SetList result; SetList result;
QHashIterator<QString, CardSet *> i(setHash); QHashIterator<QString, CardSet *> i(sets);
while (i.hasNext()) { while (i.hasNext()) {
i.next(); i.next();
result << i.value(); result << i.value();
@ -592,7 +677,9 @@ SetList CardDatabase::getSetList() const
void CardDatabase::clearPixmapCache() void CardDatabase::clearPixmapCache()
{ {
QHashIterator<QString, CardInfo *> i(cardHash); // This also clears the cards in simpleNameCards since they point to the
// same object.
QHashIterator<QString, CardInfo *> i(cards);
while (i.hasNext()) { while (i.hasNext()) {
i.next(); i.next();
i.value()->clearPixmapCache(); i.value()->clearPixmapCache();
@ -616,7 +703,7 @@ void CardDatabase::loadSetsFromXml(QXmlStreamReader &xml)
else if (xml.name() == "longname") else if (xml.name() == "longname")
longName = xml.readElementText(); longName = xml.readElementText();
} }
setHash.insert(shortName, new CardSet(shortName, longName)); sets.insert(shortName, new CardSet(shortName, longName));
} }
} }
} }
@ -629,6 +716,7 @@ void CardDatabase::loadCardsFromXml(QXmlStreamReader &xml)
if (xml.name() == "card") { if (xml.name() == "card") {
QString name, manacost, type, pt, text; QString name, manacost, type, pt, text;
QStringList colors; QStringList colors;
QStringMap customPicURLs, customPicURLsHq;
MuidMap muids; MuidMap muids;
SetList sets; SetList sets;
int tableRow = 0; int tableRow = 0;
@ -655,6 +743,12 @@ void CardDatabase::loadCardsFromXml(QXmlStreamReader &xml)
if (attrs.hasAttribute("muId")) { if (attrs.hasAttribute("muId")) {
muids[setName] = attrs.value("muId").toString().toInt(); muids[setName] = attrs.value("muId").toString().toInt();
} }
if (attrs.hasAttribute("picURL")) {
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() == "tablerow") else if (xml.name() == "tablerow")
@ -666,46 +760,32 @@ void CardDatabase::loadCardsFromXml(QXmlStreamReader &xml)
else if (xml.name() == "token") else if (xml.name() == "token")
isToken = xml.readElementText().toInt(); isToken = xml.readElementText().toInt();
} }
cardHash.insert(name, new CardInfo(this, name, isToken, manacost, type, pt, text, colors, loyalty, cipt, tableRow, sets, muids)); addCard(new CardInfo(this, name, isToken, manacost, type, pt, text, colors, loyalty, cipt, tableRow, sets, customPicURLs, customPicURLsHq, muids));
} }
} }
} }
LoadStatus CardDatabase::loadFromFile(const QString &fileName, bool tokens) CardInfo *CardDatabase::getCardFromMap(CardNameMap &cardMap, const QString &cardName, bool createIfNotFound) {
if (cardName.isEmpty())
return noCard;
else if (cardMap.contains(cardName))
return cardMap.value(cardName);
else if (createIfNotFound) {
CardInfo *newCard = new CardInfo(this, cardName, true);
newCard->addToSet(getSet("TK"));
cardMap.insert(cardName, newCard);
return newCard;
} else
return 0;
}
LoadStatus CardDatabase::loadFromFile(const QString &fileName)
{ {
QFile file(fileName); QFile file(fileName);
file.open(QIODevice::ReadOnly); file.open(QIODevice::ReadOnly);
if (!file.isOpen()) if (!file.isOpen())
return FileError; return FileError;
if (tokens) {
QMutableHashIterator<QString, CardInfo *> i(cardHash);
while (i.hasNext()) {
i.next();
if (i.value()->getIsToken()) {
delete i.value();
i.remove();
}
}
} else {
QHashIterator<QString, CardSet *> setIt(setHash);
while (setIt.hasNext()) {
setIt.next();
delete setIt.value();
}
setHash.clear();
QMutableHashIterator<QString, CardInfo *> i(cardHash);
while (i.hasNext()) {
i.next();
if (!i.value()->getIsToken()) {
delete i.value();
i.remove();
}
}
cardHash.clear();
}
QXmlStreamReader xml(&file); QXmlStreamReader xml(&file);
while (!xml.atEnd()) { while (!xml.atEnd()) {
if (xml.readNext() == QXmlStreamReader::StartElement) { if (xml.readNext() == QXmlStreamReader::StartElement) {
@ -726,9 +806,9 @@ LoadStatus CardDatabase::loadFromFile(const QString &fileName, bool tokens)
} }
} }
} }
qDebug() << cardHash.size() << "cards in" << setHash.size() << "sets loaded"; qDebug() << cards.size() << "cards in" << sets.size() << "sets loaded";
if (cardHash.isEmpty()) return NoCards; if (cards.isEmpty()) return NoCards;
return Ok; return Ok;
} }
@ -747,17 +827,16 @@ bool CardDatabase::saveToFile(const QString &fileName, bool tokens)
if (!tokens) { if (!tokens) {
xml.writeStartElement("sets"); xml.writeStartElement("sets");
QHashIterator<QString, CardSet *> setIterator(setHash); QHashIterator<QString, CardSet *> setIterator(sets);
while (setIterator.hasNext()) while (setIterator.hasNext())
xml << setIterator.next().value(); xml << setIterator.next().value();
xml.writeEndElement(); // sets xml.writeEndElement(); // sets
} }
xml.writeStartElement("cards"); xml.writeStartElement("cards");
QHashIterator<QString, CardInfo *> cardIterator(cardHash); QHashIterator<QString, CardInfo *> cardIterator(cards);
while (cardIterator.hasNext()) { while (cardIterator.hasNext()) {
CardInfo *card = cardIterator.next().value(); CardInfo *card = cardIterator.next().value();
if (card->getIsToken() == tokens)
xml << card; xml << card;
} }
xml.writeEndElement(); // cards xml.writeEndElement(); // cards
@ -772,7 +851,7 @@ void CardDatabase::picDownloadChanged()
{ {
pictureLoader->setPicDownload(settingsCache->getPicDownload()); pictureLoader->setPicDownload(settingsCache->getPicDownload());
if (settingsCache->getPicDownload()) { if (settingsCache->getPicDownload()) {
QHashIterator<QString, CardInfo *> cardIterator(cardHash); QHashIterator<QString, CardInfo *> cardIterator(cards);
while (cardIterator.hasNext()) while (cardIterator.hasNext())
cardIterator.next().value()->clearPixmapCacheMiss(); cardIterator.next().value()->clearPixmapCacheMiss();
} }
@ -782,7 +861,7 @@ void CardDatabase::picDownloadHqChanged()
{ {
pictureLoader->setPicDownloadHq(settingsCache->getPicDownloadHq()); pictureLoader->setPicDownloadHq(settingsCache->getPicDownloadHq());
if (settingsCache->getPicDownloadHq()) { if (settingsCache->getPicDownloadHq()) {
QHashIterator<QString, CardInfo *> cardIterator(cardHash); QHashIterator<QString, CardInfo *> cardIterator(cards);
while (cardIterator.hasNext()) while (cardIterator.hasNext())
cardIterator.next().value()->clearPixmapCacheMiss(); cardIterator.next().value()->clearPixmapCacheMiss();
} }
@ -792,11 +871,11 @@ LoadStatus CardDatabase::loadCardDatabase(const QString &path, bool tokens)
{ {
LoadStatus tempLoadStatus = NotLoaded; LoadStatus tempLoadStatus = NotLoaded;
if (!path.isEmpty()) if (!path.isEmpty())
tempLoadStatus = loadFromFile(path, tokens); tempLoadStatus = loadFromFile(path);
if (tempLoadStatus == Ok) { if (tempLoadStatus == Ok) {
SetList allSets; SetList allSets;
QHashIterator<QString, CardSet *> setsIterator(setHash); QHashIterator<QString, CardSet *> setsIterator(sets);
while (setsIterator.hasNext()) while (setsIterator.hasNext())
allSets.append(setsIterator.next().value()); allSets.append(setsIterator.next().value());
allSets.sortByKey(); allSets.sortByKey();
@ -828,7 +907,7 @@ void CardDatabase::loadTokenDatabase()
QStringList CardDatabase::getAllColors() const QStringList CardDatabase::getAllColors() const
{ {
QSet<QString> colors; QSet<QString> colors;
QHashIterator<QString, CardInfo *> cardIterator(cardHash); QHashIterator<QString, CardInfo *> cardIterator(cards);
while (cardIterator.hasNext()) { while (cardIterator.hasNext()) {
const QStringList &cardColors = cardIterator.next().value()->getColors(); const QStringList &cardColors = cardIterator.next().value()->getColors();
if (cardColors.isEmpty()) if (cardColors.isEmpty())
@ -843,7 +922,7 @@ QStringList CardDatabase::getAllColors() const
QStringList CardDatabase::getAllMainCardTypes() const QStringList CardDatabase::getAllMainCardTypes() const
{ {
QSet<QString> types; QSet<QString> types;
QHashIterator<QString, CardInfo *> cardIterator(cardHash); QHashIterator<QString, CardInfo *> cardIterator(cards);
while (cardIterator.hasNext()) while (cardIterator.hasNext())
types.insert(cardIterator.next().value()->getMainCardType()); types.insert(cardIterator.next().value()->getMainCardType());
return types.toList(); return types.toList();

View file

@ -55,7 +55,7 @@ public:
PictureToLoad(CardInfo *_card = 0, bool _stripped = false, bool _hq = true); PictureToLoad(CardInfo *_card = 0, bool _stripped = false, bool _hq = true);
CardInfo *getCard() const { return card; } CardInfo *getCard() const { return card; }
bool getStripped() const { return stripped; } bool getStripped() const { return stripped; }
QString getSetName() const { return sortedSets[setIndex]->getCorrectedShortName(); } QString getSetName() const;
bool nextSet(); bool nextSet();
bool getHq() const { return hq; } bool getHq() const { return hq; }
void setHq(bool _hq) { hq = _hq; } void setHq(bool _hq) { hq = _hq; }
@ -95,6 +95,13 @@ private:
CardDatabase *db; CardDatabase *db;
QString name; QString name;
/*
* The name without punctuation or capitalization, for better card tag name
* recognition.
*/
QString simpleName;
bool isToken; bool isToken;
SetList sets; SetList sets;
QString manacost; QString manacost;
@ -103,6 +110,7 @@ private:
QString text; QString text;
QStringList colors; QStringList colors;
int loyalty; int loyalty;
QStringMap customPicURLs, customPicURLsHq;
MuidMap muIds; MuidMap muIds;
bool cipt; bool cipt;
int tableRow; int tableRow;
@ -121,6 +129,8 @@ public:
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 &_customPicURLsHq = QStringMap(),
MuidMap muids = MuidMap()); MuidMap muids = MuidMap());
~CardInfo(); ~CardInfo();
const QString &getName() const { return name; } const QString &getName() const { return name; }
@ -138,12 +148,16 @@ public:
void setText(const QString &_text) { text = _text; emit cardInfoChanged(this); } void setText(const QString &_text) { text = _text; emit cardInfoChanged(this); }
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; }
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;
int getTableRow() const { return tableRow; } int getTableRow() const { return tableRow; }
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 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);
QPixmap *loadPixmap(); QPixmap *loadPixmap();
@ -153,6 +167,12 @@ public:
void imageLoaded(const QImage &image); void imageLoaded(const QImage &image);
CardSet *getPreferredSet(); CardSet *getPreferredSet();
int getPreferredMuId(); int getPreferredMuId();
/**
* Simplify a name to have no punctuation and lowercase all letters, for
* less strict name-matching.
*/
static QString simplifyName(const QString &name);
public slots: public slots:
void updatePixmapCache(); void updatePixmapCache();
signals: signals:
@ -162,11 +182,27 @@ signals:
enum LoadStatus { Ok, VersionTooOld, Invalid, NotLoaded, FileError, NoCards }; enum LoadStatus { Ok, VersionTooOld, Invalid, NotLoaded, FileError, NoCards };
typedef QHash<QString, CardInfo *> CardNameMap;
typedef QHash<QString, CardSet *> SetNameMap;
class CardDatabase : public QObject { class CardDatabase : public QObject {
Q_OBJECT Q_OBJECT
protected: protected:
QHash<QString, CardInfo *> cardHash; /*
QHash<QString, CardSet *> setHash; * The cards, indexed by name.
*/
CardNameMap cards;
/**
* The cards, indexed by their simple name.
*/
CardNameMap simpleNameCards;
/*
* The sets, indexed by short name.
*/
SetNameMap sets;
CardInfo *noCard; CardInfo *noCard;
QThread *pictureLoaderThread; QThread *pictureLoaderThread;
@ -176,6 +212,8 @@ private:
static const int versionNeeded; static const int versionNeeded;
void loadCardsFromXml(QXmlStreamReader &xml); void loadCardsFromXml(QXmlStreamReader &xml);
void loadSetsFromXml(QXmlStreamReader &xml); void loadSetsFromXml(QXmlStreamReader &xml);
CardInfo *getCardFromMap(CardNameMap &cardMap, const QString &cardName, bool createIfNotFound);
public: public:
CardDatabase(QObject *parent = 0); CardDatabase(QObject *parent = 0);
~CardDatabase(); ~CardDatabase();
@ -183,10 +221,17 @@ public:
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); CardInfo *getCard(const QString &cardName = QString(), bool createIfNotFound = true);
/*
* Get a card by its simple name. The name will be simplified in this
* function, so you don't need to simplify it beforehand.
*/
CardInfo *getCardBySimpleName(const QString &cardName = QString(), bool createIfNotFound = true);
CardSet *getSet(const QString &setName); CardSet *getSet(const QString &setName);
QList<CardInfo *> getCardList() const { return cardHash.values(); } QList<CardInfo *> getCardList() const { return cards.values(); }
SetList getSetList() const; SetList getSetList() const;
LoadStatus loadFromFile(const QString &fileName, bool tokens = false); LoadStatus loadFromFile(const QString &fileName);
bool saveToFile(const QString &fileName, bool tokens = false); bool saveToFile(const QString &fileName, bool tokens = false);
QStringList getAllColors() const; QStringList getAllColors() const;
QStringList getAllMainCardTypes() const; QStringList getAllMainCardTypes() const;

View file

@ -68,6 +68,8 @@ QVariant CardDatabaseModel::headerData(int section, Qt::Orientation orientation,
void CardDatabaseModel::updateCardList() void CardDatabaseModel::updateCardList()
{ {
beginResetModel();
for (int i = 0; i < cardList.size(); ++i) for (int i = 0; i < cardList.size(); ++i)
disconnect(cardList[i], 0, this, 0); disconnect(cardList[i], 0, this, 0);
@ -75,7 +77,7 @@ void CardDatabaseModel::updateCardList()
for (int i = 0; i < cardList.size(); ++i) for (int i = 0; i < cardList.size(); ++i)
connect(cardList[i], SIGNAL(cardInfoChanged(CardInfo *)), this, SLOT(cardInfoChanged(CardInfo *))); connect(cardList[i], SIGNAL(cardInfoChanged(CardInfo *)), this, SLOT(cardInfoChanged(CardInfo *)));
reset(); endResetModel();
} }
void CardDatabaseModel::cardInfoChanged(CardInfo *card) void CardDatabaseModel::cardInfoChanged(CardInfo *card)

View file

@ -81,7 +81,7 @@ CardInfoWidget::CardInfoWidget(ResizeMode _mode, const QString &cardName, QWidge
} else } else
setFixedWidth(250); setFixedWidth(250);
setCard(db->getCard(cardName)); setCard(getCard(cardName));
setMinimized(settingsCache->getCardInfoMinimized()); setMinimized(settingsCache->getCardInfoMinimized());
} }
@ -166,7 +166,7 @@ void CardInfoWidget::setCard(CardInfo *card)
void CardInfoWidget::setCard(const QString &cardName) void CardInfoWidget::setCard(const QString &cardName)
{ {
setCard(db->getCard(cardName)); setCard(getCard(cardName));
} }
void CardInfoWidget::setCard(AbstractCardItem *card) void CardInfoWidget::setCard(AbstractCardItem *card)
@ -176,7 +176,11 @@ void CardInfoWidget::setCard(AbstractCardItem *card)
void CardInfoWidget::clear() void CardInfoWidget::clear()
{ {
setCard(db->getCard()); setCard(getCard());
}
CardInfo *CardInfoWidget::getCard(const QString &cardName) {
return db->getCardBySimpleName(cardName);
} }
void CardInfoWidget::updatePixmap() void CardInfoWidget::updatePixmap()
@ -188,7 +192,7 @@ void CardInfoWidget::updatePixmap()
if (resizedPixmap) if (resizedPixmap)
cardPicture->setPixmap(*resizedPixmap); cardPicture->setPixmap(*resizedPixmap);
else else
cardPicture->setPixmap(*(db->getCard()->getPixmap(QSize(pixmapWidth, pixmapWidth * aspectRatio)))); cardPicture->setPixmap(*(getCard()->getPixmap(QSize(pixmapWidth, pixmapWidth * aspectRatio))));
} }
void CardInfoWidget::retranslateUi() void CardInfoWidget::retranslateUi()

View file

@ -42,6 +42,11 @@ private:
CardInfo *info; CardInfo *info;
void setMinimized(int _minimized); void setMinimized(int _minimized);
/*
* Wrapper around db->getCardBySimpleName.
*/
CardInfo *getCard(const QString &cardName = QString());
public: public:
CardInfoWidget(ResizeMode _mode, const QString &cardName = QString(), QWidget *parent = 0, Qt::WindowFlags f = 0); CardInfoWidget(ResizeMode _mode, const QString &cardName = QString(), QWidget *parent = 0, Qt::WindowFlags f = 0);
void retranslateUi(); void retranslateUi();

View file

@ -233,6 +233,7 @@ CardDragItem *CardItem::createDragItem(int _id, const QPointF &_pos, const QPoin
void CardItem::deleteDragItem() void CardItem::deleteDragItem()
{ {
if(dragItem)
dragItem->deleteLater(); dragItem->deleteLater();
dragItem = NULL; dragItem = NULL;
} }

View file

@ -30,6 +30,8 @@ DeckListModel::~DeckListModel()
void DeckListModel::rebuildTree() void DeckListModel::rebuildTree()
{ {
beginResetModel();
root->clearTree(); root->clearTree();
InnerDecklistNode *listRoot = deckList->getRoot(); InnerDecklistNode *listRoot = deckList->getRoot();
for (int i = 0; i < listRoot->size(); i++) { for (int i = 0; i < listRoot->size(); i++) {
@ -55,7 +57,7 @@ void DeckListModel::rebuildTree()
} }
} }
reset(); endResetModel();
} }
int DeckListModel::rowCount(const QModelIndex &parent) const int DeckListModel::rowCount(const QModelIndex &parent) const
@ -470,13 +472,7 @@ void DeckListModel::printDeckList(QPrinter *printer)
doc.print(printer); doc.print(printer);
} }
void DeckListModel::pricesUpdated(InnerDecklistNode *node) void DeckListModel::pricesUpdated()
{ {
if (!node) emit layoutChanged();
node = root;
if (node->isEmpty())
return;
emit dataChanged(createIndex(0, 2, node->at(0)), createIndex(node->size() - 1, 2, node->last()));
} }

View file

@ -51,7 +51,7 @@ public:
void cleanList(); void cleanList();
DeckLoader *getDeckList() const { return deckList; } DeckLoader *getDeckList() const { return deckList; }
void setDeckList(DeckLoader *_deck); void setDeckList(DeckLoader *_deck);
void pricesUpdated(InnerDecklistNode *node = 0); void pricesUpdated();
private: private:
DeckLoader *deckList; DeckLoader *deckList;
InnerDecklistNode *root; InnerDecklistNode *root;

View file

@ -7,8 +7,14 @@
#include <QMessageBox> #include <QMessageBox>
#include <QDesktopServices> #include <QDesktopServices>
DeckStatsInterface::DeckStatsInterface(QObject *parent) #if QT_VERSION >= 0x050000
: QObject(parent) #include <QUrlQuery>
#endif
DeckStatsInterface::DeckStatsInterface(
CardDatabase &_cardDatabase,
QObject *parent
) : QObject(parent), cardDatabase(_cardDatabase)
{ {
manager = new QNetworkAccessManager(this); manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(queryFinished(QNetworkReply *))); connect(manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(queryFinished(QNetworkReply *)));
@ -39,15 +45,62 @@ void DeckStatsInterface::queryFinished(QNetworkReply *reply)
deleteLater(); deleteLater();
} }
void DeckStatsInterface::getAnalyzeRequestData(DeckList *deck, QByteArray *data)
{
DeckList deckWithoutTokens;
copyDeckWithoutTokens(*deck, deckWithoutTokens);
#if QT_VERSION < 0x050000
QUrl params;
params.addQueryItem("deck", deckWithoutTokens.writeToString_Plain());
data->append(params.encodedQuery());
#else
QUrl params;
QUrlQuery urlQuery;
urlQuery.addQueryItem("deck", deckWithoutTokens.writeToString_Plain());
params.setQuery(urlQuery);
data->append(params.query(QUrl::EncodeReserved));
#endif
}
void DeckStatsInterface::analyzeDeck(DeckList *deck) void DeckStatsInterface::analyzeDeck(DeckList *deck)
{ {
QUrl params;
params.addQueryItem("deck", deck->writeToString_Plain());
QByteArray data; QByteArray data;
data.append(params.encodedQuery()); getAnalyzeRequestData(deck, &data);
QNetworkRequest request(QUrl("http://deckstats.net/index.php")); QNetworkRequest request(QUrl("http://deckstats.net/index.php"));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
manager->post(request, data); manager->post(request, data);
} }
struct CopyIfNotAToken {
CardDatabase &cardDatabase;
DeckList &destination;
CopyIfNotAToken(
CardDatabase &_cardDatabase,
DeckList &_destination
) : cardDatabase(_cardDatabase), destination(_destination) {};
void operator()(
const InnerDecklistNode *node,
const DecklistCardNode *card
) const {
if (!cardDatabase.getCard(card->getName())->getIsToken()) {
DecklistCardNode *addedCard = destination.addCard(
card->getName(),
node->getName()
);
addedCard->setNumber(card->getNumber());
}
}
};
void DeckStatsInterface::copyDeckWithoutTokens(
const DeckList &source,
DeckList &destination
) {
CopyIfNotAToken copyIfNotAToken(cardDatabase, destination);
source.forEachCard(copyIfNotAToken);
}

View file

@ -1,8 +1,11 @@
#ifndef DECKSTATS_INTERFACE_H #ifndef DECKSTATS_INTERFACE_H
#define DECKSTATS_INTERFACE_H #define DECKSTATS_INTERFACE_H
#include "carddatabase.h"
#include "decklist.h"
#include <QObject> #include <QObject>
class QByteArray;
class QNetworkAccessManager; class QNetworkAccessManager;
class QNetworkReply; class QNetworkReply;
class DeckList; class DeckList;
@ -11,10 +14,21 @@ class DeckStatsInterface : public QObject {
Q_OBJECT Q_OBJECT
private: private:
QNetworkAccessManager *manager; QNetworkAccessManager *manager;
CardDatabase &cardDatabase;
/**
* Deckstats doesn't recognize token cards, and instead tries to find the
* closest non-token card instead. So we construct a new deck which has no
* tokens.
*/
void copyDeckWithoutTokens(const DeckList &source, DeckList& destination);
private slots: private slots:
void queryFinished(QNetworkReply *reply); void queryFinished(QNetworkReply *reply);
void getAnalyzeRequestData(DeckList *deck, QByteArray *data);
public: public:
DeckStatsInterface(QObject *parent = 0); DeckStatsInterface(CardDatabase &_cardDatabase, QObject *parent = 0);
void analyzeDeck(DeckList *deck); void analyzeDeck(DeckList *deck);
}; };

View file

@ -64,7 +64,11 @@ void DeckViewCardDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
DeckViewCard::DeckViewCard(const QString &_name, const QString &_originZone, QGraphicsItem *parent) DeckViewCard::DeckViewCard(const QString &_name, const QString &_originZone, QGraphicsItem *parent)
: AbstractCardItem(_name, 0, -1, parent), originZone(_originZone), dragItem(0) : AbstractCardItem(_name, 0, -1, parent), originZone(_originZone), dragItem(0)
{ {
#if QT_VERSION < 0x050000
setAcceptsHoverEvents(true); setAcceptsHoverEvents(true);
#else
setAcceptHoverEvents(true);
#endif
} }
DeckViewCard::~DeckViewCard() DeckViewCard::~DeckViewCard()

View file

@ -79,8 +79,13 @@ DlgCreateToken::DlgCreateToken(const QStringList &_predefinedTokens, QWidget *pa
chooseTokenView->header()->setStretchLastSection(false); chooseTokenView->header()->setStretchLastSection(false);
chooseTokenView->header()->hideSection(1); chooseTokenView->header()->hideSection(1);
chooseTokenView->header()->hideSection(2); chooseTokenView->header()->hideSection(2);
#if QT_VERSION < 0x050000
chooseTokenView->header()->setResizeMode(3, QHeaderView::ResizeToContents); chooseTokenView->header()->setResizeMode(3, QHeaderView::ResizeToContents);
chooseTokenView->header()->setResizeMode(4, QHeaderView::ResizeToContents); chooseTokenView->header()->setResizeMode(4, QHeaderView::ResizeToContents);
#else
chooseTokenView->header()->setSectionResizeMode(3, QHeaderView::ResizeToContents);
chooseTokenView->header()->setSectionResizeMode(4, QHeaderView::ResizeToContents);
#endif
connect(chooseTokenView->selectionModel(), SIGNAL(currentRowChanged(QModelIndex, QModelIndex)), this, SLOT(tokenSelectionChanged(QModelIndex, QModelIndex))); connect(chooseTokenView->selectionModel(), SIGNAL(currentRowChanged(QModelIndex, QModelIndex)), this, SLOT(tokenSelectionChanged(QModelIndex, QModelIndex)));
if (predefinedTokens.isEmpty()) if (predefinedTokens.isEmpty())

View file

@ -73,8 +73,13 @@ DlgEditTokens::DlgEditTokens(CardDatabaseModel *_cardDatabaseModel, QWidget *par
chooseTokenView->header()->setStretchLastSection(false); chooseTokenView->header()->setStretchLastSection(false);
chooseTokenView->header()->hideSection(1); chooseTokenView->header()->hideSection(1);
chooseTokenView->header()->hideSection(2); chooseTokenView->header()->hideSection(2);
#if QT_VERSION < 0x050000
chooseTokenView->header()->setResizeMode(3, QHeaderView::ResizeToContents); chooseTokenView->header()->setResizeMode(3, QHeaderView::ResizeToContents);
chooseTokenView->header()->setResizeMode(4, QHeaderView::ResizeToContents); chooseTokenView->header()->setResizeMode(4, QHeaderView::ResizeToContents);
#else
chooseTokenView->header()->setSectionResizeMode(3, QHeaderView::ResizeToContents);
chooseTokenView->header()->setSectionResizeMode(4, QHeaderView::ResizeToContents);
#endif
connect(chooseTokenView->selectionModel(), SIGNAL(currentRowChanged(QModelIndex, QModelIndex)), this, SLOT(tokenSelectionChanged(QModelIndex, QModelIndex))); connect(chooseTokenView->selectionModel(), SIGNAL(currentRowChanged(QModelIndex, QModelIndex)), this, SLOT(tokenSelectionChanged(QModelIndex, QModelIndex)));
QAction *aAddToken = new QAction(tr("Add token"), this); QAction *aAddToken = new QAction(tr("Add token"), this);
@ -108,7 +113,7 @@ DlgEditTokens::DlgEditTokens(CardDatabaseModel *_cardDatabaseModel, QWidget *par
setWindowTitle(tr("Edit tokens")); setWindowTitle(tr("Edit tokens"));
} }
void DlgEditTokens::tokenSelectionChanged(const QModelIndex &current, const QModelIndex &previous) void DlgEditTokens::tokenSelectionChanged(const QModelIndex &current, const QModelIndex & /* previous */)
{ {
const QModelIndex realIndex = cardDatabaseDisplayModel->mapToSource(current); const QModelIndex realIndex = cardDatabaseDisplayModel->mapToSource(current);
CardInfo *cardInfo = current.row() >= 0 ? cardDatabaseModel->getCard(realIndex.row()) : cardDatabaseModel->getDatabase()->getCard(); CardInfo *cardInfo = current.row() >= 0 ? cardDatabaseModel->getCard(realIndex.row()) : cardDatabaseModel->getDatabase()->getCard();

View file

@ -9,26 +9,53 @@
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QGridLayout> #include <QGridLayout>
#include <QDialogButtonBox> #include <QDialogButtonBox>
#include <QSettings>
#include <QCryptographicHash>
DlgFilterGames::DlgFilterGames(const QMap<int, QString> &allGameTypes, QWidget *parent) DlgFilterGames::DlgFilterGames(const QMap<int, QString> &_allGameTypes, QWidget *parent)
: QDialog(parent) : QDialog(parent),
allGameTypes(_allGameTypes)
{ {
unavailableGamesVisibleCheckBox = new QCheckBox(tr("Show &unavailable games")); QSettings settings;
passwordProtectedGamesVisibleCheckBox = new QCheckBox(tr("Show &password protected games")); settings.beginGroup("filter_games");
unavailableGamesVisibleCheckBox = new QCheckBox(tr("Show &unavailable games"));
unavailableGamesVisibleCheckBox->setChecked(
settings.value("unavailable_games_visible", false).toBool()
);
passwordProtectedGamesVisibleCheckBox = new QCheckBox(tr("Show &password protected games"));
passwordProtectedGamesVisibleCheckBox->setChecked(
settings.value("password_protected_games_visible", false).toBool()
);
QLabel *gameNameFilterLabel = new QLabel(tr("Game &description:"));
gameNameFilterEdit = new QLineEdit; gameNameFilterEdit = new QLineEdit;
gameNameFilterEdit->setText(
settings.value("game_name_filter", "").toString()
);
QLabel *gameNameFilterLabel = new QLabel(tr("Game &description:"));
gameNameFilterLabel->setBuddy(gameNameFilterEdit); gameNameFilterLabel->setBuddy(gameNameFilterEdit);
QLabel *creatorNameFilterLabel = new QLabel(tr("&Creator name:"));
creatorNameFilterEdit = new QLineEdit; creatorNameFilterEdit = new QLineEdit;
creatorNameFilterEdit->setText(
settings.value("creator_name_filter", "").toString()
);
QLabel *creatorNameFilterLabel = new QLabel(tr("&Creator name:"));
creatorNameFilterLabel->setBuddy(creatorNameFilterEdit); creatorNameFilterLabel->setBuddy(creatorNameFilterEdit);
QVBoxLayout *gameTypeFilterLayout = new QVBoxLayout; QVBoxLayout *gameTypeFilterLayout = new QVBoxLayout;
QMapIterator<int, QString> gameTypesIterator(allGameTypes); QMapIterator<int, QString> gameTypesIterator(allGameTypes);
while (gameTypesIterator.hasNext()) { while (gameTypesIterator.hasNext()) {
gameTypesIterator.next(); gameTypesIterator.next();
QCheckBox *temp = new QCheckBox(gameTypesIterator.value()); QCheckBox *temp = new QCheckBox(gameTypesIterator.value());
temp->setChecked(
settings.value(
"game_type/" + hashGameType(gameTypesIterator.value()),
false
).toBool()
);
gameTypeFilterCheckBoxes.insert(gameTypesIterator.key(), temp); gameTypeFilterCheckBoxes.insert(gameTypesIterator.key(), temp);
gameTypeFilterLayout->addWidget(temp); gameTypeFilterLayout->addWidget(temp);
} }
@ -43,14 +70,18 @@ DlgFilterGames::DlgFilterGames(const QMap<int, QString> &allGameTypes, QWidget *
maxPlayersFilterMinSpinBox = new QSpinBox; maxPlayersFilterMinSpinBox = new QSpinBox;
maxPlayersFilterMinSpinBox->setMinimum(1); maxPlayersFilterMinSpinBox->setMinimum(1);
maxPlayersFilterMinSpinBox->setMaximum(99); maxPlayersFilterMinSpinBox->setMaximum(99);
maxPlayersFilterMinSpinBox->setValue(1); maxPlayersFilterMinSpinBox->setValue(
settings.value("min_players", 1).toInt()
);
maxPlayersFilterMinLabel->setBuddy(maxPlayersFilterMinSpinBox); maxPlayersFilterMinLabel->setBuddy(maxPlayersFilterMinSpinBox);
QLabel *maxPlayersFilterMaxLabel = new QLabel(tr("at &most:")); QLabel *maxPlayersFilterMaxLabel = new QLabel(tr("at &most:"));
maxPlayersFilterMaxSpinBox = new QSpinBox; maxPlayersFilterMaxSpinBox = new QSpinBox;
maxPlayersFilterMaxSpinBox->setMinimum(1); maxPlayersFilterMaxSpinBox->setMinimum(1);
maxPlayersFilterMaxSpinBox->setMaximum(99); maxPlayersFilterMaxSpinBox->setMaximum(99);
maxPlayersFilterMaxSpinBox->setValue(99); maxPlayersFilterMaxSpinBox->setValue(
settings.value("max_players", 99).toInt()
);
maxPlayersFilterMaxLabel->setBuddy(maxPlayersFilterMaxSpinBox); maxPlayersFilterMaxLabel->setBuddy(maxPlayersFilterMaxSpinBox);
QGridLayout *maxPlayersFilterLayout = new QGridLayout; QGridLayout *maxPlayersFilterLayout = new QGridLayout;
@ -83,7 +114,7 @@ DlgFilterGames::DlgFilterGames(const QMap<int, QString> &allGameTypes, QWidget *
hbox->addLayout(rightColumn); hbox->addLayout(rightColumn);
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(buttonBox, SIGNAL(accepted()), this, SLOT(actOk()));
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
QVBoxLayout *mainLayout = new QVBoxLayout; QVBoxLayout *mainLayout = new QVBoxLayout;
@ -94,6 +125,42 @@ DlgFilterGames::DlgFilterGames(const QMap<int, QString> &allGameTypes, QWidget *
setWindowTitle(tr("Filter games")); setWindowTitle(tr("Filter games"));
} }
void DlgFilterGames::actOk() {
QSettings settings;
settings.beginGroup("filter_games");
settings.setValue(
"unavailable_games_visible",
unavailableGamesVisibleCheckBox->isChecked()
);
settings.setValue(
"password_protected_games_visible",
passwordProtectedGamesVisibleCheckBox->isChecked()
);
settings.setValue("game_name_filter", gameNameFilterEdit->text());
settings.setValue("creator_name_filter", creatorNameFilterEdit->text());
QMapIterator<int, QString> gameTypeIterator(allGameTypes);
QMapIterator<int, QCheckBox *> checkboxIterator(gameTypeFilterCheckBoxes);
while (gameTypeIterator.hasNext()) {
gameTypeIterator.next();
checkboxIterator.next();
settings.setValue(
"game_type/" + hashGameType(gameTypeIterator.value()),
checkboxIterator.value()->isChecked()
);
}
settings.setValue("min_players", maxPlayersFilterMinSpinBox->value());
settings.setValue("max_players", maxPlayersFilterMaxSpinBox->value());
accept();
}
QString DlgFilterGames::hashGameType(const QString &gameType) const {
return QCryptographicHash::hash(gameType.toUtf8(), QCryptographicHash::Md5).toHex();
}
bool DlgFilterGames::getUnavailableGamesVisible() const bool DlgFilterGames::getUnavailableGamesVisible() const
{ {
return unavailableGamesVisibleCheckBox->isChecked(); return unavailableGamesVisibleCheckBox->isChecked();

View file

@ -19,6 +19,16 @@ private:
QMap<int, QCheckBox *> gameTypeFilterCheckBoxes; QMap<int, QCheckBox *> gameTypeFilterCheckBoxes;
QSpinBox *maxPlayersFilterMinSpinBox; QSpinBox *maxPlayersFilterMinSpinBox;
QSpinBox *maxPlayersFilterMaxSpinBox; QSpinBox *maxPlayersFilterMaxSpinBox;
const QMap<int, QString> &allGameTypes;
/*
* The game type might contain special characters, so to use it in
* QSettings we just hash it.
*/
QString hashGameType(const QString &gameType) const;
private slots:
void actOk();
public: public:
DlgFilterGames(const QMap<int, QString> &allGameTypes, QWidget *parent = 0); DlgFilterGames(const QMap<int, QString> &allGameTypes, QWidget *parent = 0);

View file

@ -18,11 +18,13 @@
#include <QInputDialog> #include <QInputDialog>
#include <QSpinBox> #include <QSpinBox>
#include <QDialogButtonBox> #include <QDialogButtonBox>
#include <QRadioButton>
#include <QDebug> #include <QDebug>
#include "carddatabase.h" #include "carddatabase.h"
#include "dlg_settings.h" #include "dlg_settings.h"
#include "main.h" #include "main.h"
#include "settingscache.h" #include "settingscache.h"
#include "priceupdater.h"
GeneralSettingsPage::GeneralSettingsPage() GeneralSettingsPage::GeneralSettingsPage()
{ {
@ -532,8 +534,29 @@ DeckEditorSettingsPage::DeckEditorSettingsPage()
priceTagsCheckBox->setChecked(settingsCache->getPriceTagFeature()); priceTagsCheckBox->setChecked(settingsCache->getPriceTagFeature());
connect(priceTagsCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setPriceTagFeature(int))); connect(priceTagsCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setPriceTagFeature(int)));
priceTagSource0 = new QRadioButton;
priceTagSource1 = new QRadioButton;
switch(settingsCache->getPriceTagSource())
{
case AbstractPriceUpdater::DBPriceSource:
priceTagSource1->setChecked(true);
break;
case AbstractPriceUpdater::BLPPriceSource:
default:
priceTagSource0->setChecked(true);
break;
}
connect(priceTagSource0, SIGNAL(toggled(bool)), this, SLOT(radioPriceTagSourceClicked(bool)));
connect(priceTagSource1, SIGNAL(toggled(bool)), this, SLOT(radioPriceTagSourceClicked(bool)));
connect(this, SIGNAL(priceTagSourceChanged(int)), settingsCache, SLOT(setPriceTagSource(int)));
QGridLayout *generalGrid = new QGridLayout; QGridLayout *generalGrid = new QGridLayout;
generalGrid->addWidget(priceTagsCheckBox, 0, 0); generalGrid->addWidget(priceTagsCheckBox, 0, 0);
generalGrid->addWidget(priceTagSource0, 1, 0);
generalGrid->addWidget(priceTagSource1, 2, 0);
generalGroupBox = new QGroupBox; generalGroupBox = new QGroupBox;
generalGroupBox->setLayout(generalGrid); generalGroupBox->setLayout(generalGrid);
@ -546,10 +569,26 @@ DeckEditorSettingsPage::DeckEditorSettingsPage()
void DeckEditorSettingsPage::retranslateUi() void DeckEditorSettingsPage::retranslateUi()
{ {
priceTagsCheckBox->setText(tr("Enable &price tag feature (using data from blacklotusproject.com)")); priceTagsCheckBox->setText(tr("Enable &price tag feature"));
priceTagSource0->setText(tr("using data from blacklotusproject.com"));
priceTagSource1->setText(tr("using data from deckbrew.com"));
generalGroupBox->setTitle(tr("General")); generalGroupBox->setTitle(tr("General"));
} }
void DeckEditorSettingsPage::radioPriceTagSourceClicked(bool checked)
{
if(!checked)
return;
int source=AbstractPriceUpdater::BLPPriceSource;
if(priceTagSource0->isChecked())
source=AbstractPriceUpdater::BLPPriceSource;
if(priceTagSource1->isChecked())
source=AbstractPriceUpdater::DBPriceSource;
emit priceTagSourceChanged(source);
}
MessagesSettingsPage::MessagesSettingsPage() MessagesSettingsPage::MessagesSettingsPage()
{ {
aAdd = new QAction(this); aAdd = new QAction(this);

View file

@ -15,6 +15,7 @@ class QCheckBox;
class QLabel; class QLabel;
class QCloseEvent; class QCloseEvent;
class QSpinBox; class QSpinBox;
class QRadioButton;
class AbstractSettingsPage : public QWidget { class AbstractSettingsPage : public QWidget {
public: public:
@ -100,8 +101,13 @@ class DeckEditorSettingsPage : public AbstractSettingsPage {
public: public:
DeckEditorSettingsPage(); DeckEditorSettingsPage();
void retranslateUi(); void retranslateUi();
private slots:
void radioPriceTagSourceClicked(bool checked);
signals:
void priceTagSourceChanged(int _priceTagSource);
private: private:
QCheckBox *priceTagsCheckBox; QCheckBox *priceTagsCheckBox;
QRadioButton *priceTagSource0, *priceTagSource1;
QGroupBox *generalGroupBox; QGroupBox *generalGroupBox;
}; };

View file

@ -18,10 +18,10 @@ public:
virtual void enable() { enabled = true; nodeChanged(); } virtual void enable() { enabled = true; nodeChanged(); }
virtual void disable() { enabled = false; nodeChanged(); } virtual void disable() { enabled = false; nodeChanged(); }
virtual FilterTreeNode *parent() const { return NULL; } virtual FilterTreeNode *parent() const { return NULL; }
virtual FilterTreeNode *nodeAt(int i) const { return NULL; } virtual FilterTreeNode *nodeAt(int /* i */) const { return NULL; }
virtual void deleteAt(int i) {} virtual void deleteAt(int /* i */) {}
virtual int childCount() const { return 0; } virtual int childCount() const { return 0; }
virtual int childIndex(const FilterTreeNode *node) const { return -1; } virtual int childIndex(const FilterTreeNode * /* node */) const { return -1; }
virtual int index() const { return (parent() != NULL)? parent()->childIndex(this) : -1; } virtual int index() const { return (parent() != NULL)? parent()->childIndex(this) : -1; }
virtual QString text() const { return QString(textCStr()); } virtual QString text() const { return QString(textCStr()); }
virtual bool isLeaf() const { return false; } virtual bool isLeaf() const { return false; }
@ -48,7 +48,7 @@ class FilterTreeBranch : public FilterTreeNode {
protected: protected:
QList<T> childNodes; QList<T> childNodes;
public: public:
~FilterTreeBranch(); virtual ~FilterTreeBranch();
FilterTreeNode *nodeAt(int i) const; FilterTreeNode *nodeAt(int i) const;
void deleteAt(int i); void deleteAt(int i);
int childCount() const { return childNodes.size(); } int childCount() const { return childNodes.size(); }
@ -102,6 +102,7 @@ public:
FilterItem(QString trm, FilterItemList *parent) FilterItem(QString trm, FilterItemList *parent)
: p(parent), term(trm) {} : p(parent), term(trm) {}
virtual ~FilterItem() {};
CardFilter::Attr attr() const { return p->attr(); } CardFilter::Attr attr() const { return p->attr(); }
CardFilter::Type type() const { return p->type; } CardFilter::Type type() const { return p->type; }

View file

@ -33,8 +33,11 @@ GameSelector::GameSelector(AbstractClient *_client, const TabSupervisor *_tabSup
gameListView->header()->hideSection(1); gameListView->header()->hideSection(1);
else else
gameListProxyModel->setUnavailableGamesVisible(true); gameListProxyModel->setUnavailableGamesVisible(true);
#if QT_VERSION < 0x050000
gameListView->header()->setResizeMode(1, QHeaderView::ResizeToContents); gameListView->header()->setResizeMode(1, QHeaderView::ResizeToContents);
#else
gameListView->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
#endif
filterButton = new QPushButton; filterButton = new QPushButton;
filterButton->setIcon(QIcon(":/resources/icon_search.svg")); filterButton->setIcon(QIcon(":/resources/icon_search.svg"));
connect(filterButton, SIGNAL(clicked()), this, SLOT(actSetFilter())); connect(filterButton, SIGNAL(clicked()), this, SLOT(actSetFilter()));
@ -81,12 +84,6 @@ void GameSelector::actSetFilter()
if (room) if (room)
gameTypeMap = gameListModel->getGameTypes().value(room->getRoomId()); gameTypeMap = gameListModel->getGameTypes().value(room->getRoomId());
DlgFilterGames dlg(gameTypeMap, this); DlgFilterGames dlg(gameTypeMap, this);
dlg.setUnavailableGamesVisible(gameListProxyModel->getUnavailableGamesVisible());
dlg.setPasswordProtectedGamesVisible(gameListProxyModel->getPasswordProtectedGamesVisible());
dlg.setGameNameFilter(gameListProxyModel->getGameNameFilter());
dlg.setCreatorNameFilter(gameListProxyModel->getCreatorNameFilter());
dlg.setGameTypeFilter(gameListProxyModel->getGameTypeFilter());
dlg.setMaxPlayersFilter(gameListProxyModel->getMaxPlayersFilterMin(), gameListProxyModel->getMaxPlayersFilterMax());
if (!dlg.exec()) if (!dlg.exec())
return; return;

View file

@ -33,7 +33,7 @@ ServerInfo_User LocalServer_DatabaseInterface::getUserData(const QString &name,
return result; return result;
} }
AuthenticationResult LocalServer_DatabaseInterface::checkUserPassword(Server_ProtocolHandler *handler, const QString &user, const QString &password, QString &reasonStr, int &secondsLeft) AuthenticationResult LocalServer_DatabaseInterface::checkUserPassword(Server_ProtocolHandler * /* handler */, const QString & /* user */, const QString & /* password */, QString & /* reasonStr */, int & /* secondsLeft */)
{ {
return UnknownUser; return UnknownUser;
} }

View file

@ -30,6 +30,7 @@
#include <QIcon> #include <QIcon>
#include <QDir> #include <QDir>
#include <QDesktopServices> #include <QDesktopServices>
#include <QDebug>
#include "main.h" #include "main.h"
#include "window_main.h" #include "window_main.h"
@ -55,6 +56,7 @@ QString translationPath = TRANSLATION_PATH;
QString translationPath = QString(); QString translationPath = QString();
#endif #endif
#if QT_VERSION < 0x050000
static void myMessageOutput(QtMsgType /*type*/, const char *msg) static void myMessageOutput(QtMsgType /*type*/, const char *msg)
{ {
QFile file("qdebug.txt"); QFile file("qdebug.txt");
@ -63,6 +65,16 @@ static void myMessageOutput(QtMsgType /*type*/, const char *msg)
out << msg << endl; out << msg << endl;
file.close(); file.close();
} }
#else
static void myMessageOutput(QtMsgType /*type*/, const QMessageLogContext &, const QString &msg)
{
QFile file("qdebug.txt");
file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text);
QTextStream out(&file);
out << msg << endl;
file.close();
}
#endif
void installNewTranslator() void installNewTranslator()
{ {
@ -87,11 +99,21 @@ int main(int argc, char *argv[])
QApplication app(argc, argv); QApplication app(argc, argv);
if (app.arguments().contains("--debug-output")) if (app.arguments().contains("--debug-output"))
{
#if QT_VERSION < 0x050000
qInstallMsgHandler(myMessageOutput); qInstallMsgHandler(myMessageOutput);
#else
qInstallMessageHandler(myMessageOutput);
#endif
}
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
app.addLibraryPath(app.applicationDirPath() + "/plugins"); app.addLibraryPath(app.applicationDirPath() + "/plugins");
#endif #endif
#if QT_VERSION < 0x050000
// gone in Qt5, all source files _MUST_ be utf8-encoded
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
#endif
QCoreApplication::setOrganizationName("Cockatrice"); QCoreApplication::setOrganizationName("Cockatrice");
QCoreApplication::setOrganizationDomain("cockatrice.de"); QCoreApplication::setOrganizationDomain("cockatrice.de");
@ -115,7 +137,11 @@ int main(int argc, char *argv[])
qsrand(QDateTime::currentDateTime().toTime_t()); qsrand(QDateTime::currentDateTime().toTime_t());
#if QT_VERSION < 0x050000
const QString dataDir = QDesktopServices::storageLocation(QDesktopServices::DataLocation); const QString dataDir = QDesktopServices::storageLocation(QDesktopServices::DataLocation);
#else
const QString dataDir = QStandardPaths::standardLocations(QStandardPaths::DataLocation).first();
#endif
if (!db->getLoadSuccess()) if (!db->getLoadSuccess())
if (db->loadCardDatabase(dataDir + "/cards.xml")) if (db->loadCardDatabase(dataDir + "/cards.xml"))
settingsCache->setCardDatabasePath(dataDir + "/cards.xml"); settingsCache->setCardDatabasePath(dataDir + "/cards.xml");
@ -133,6 +159,8 @@ int main(int argc, char *argv[])
QDir().mkpath(dataDir + "/pics"); QDir().mkpath(dataDir + "/pics");
settingsCache->setPicsPath(dataDir + "/pics"); settingsCache->setPicsPath(dataDir + "/pics");
} }
if (!QDir().mkpath(settingsCache->getPicsPath() + "/CUSTOM"))
qDebug() << "Could not create " + settingsCache->getPicsPath().toUtf8() + "/CUSTOM. Will fall back on default card images.";
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
if(settingsCache->getHandBgPath().isEmpty() && if(settingsCache->getHandBgPath().isEmpty() &&

View file

@ -13,7 +13,11 @@ PileZone::PileZone(Player *_p, const QString &_name, bool _isShufflable, bool _c
: CardZone(_p, _name, false, _isShufflable, _contentsKnown, parent) : CardZone(_p, _name, false, _isShufflable, _contentsKnown, parent)
{ {
setCacheMode(DeviceCoordinateCache); // Do not move this line to the parent constructor! setCacheMode(DeviceCoordinateCache); // Do not move this line to the parent constructor!
#if QT_VERSION < 0x050000
setAcceptsHoverEvents(true); setAcceptsHoverEvents(true);
#else
setAcceptHoverEvents(true);
#endif
setCursor(Qt::OpenHandCursor); setCursor(Qt::OpenHandCursor);
setTransform(QTransform().translate((float) CARD_WIDTH / 2, (float) CARD_HEIGHT / 2).rotate(90).translate((float) -CARD_WIDTH / 2, (float) -CARD_HEIGHT / 2)); setTransform(QTransform().translate((float) CARD_WIDTH / 2, (float) CARD_HEIGHT / 2).rotate(90).translate((float) -CARD_WIDTH / 2, (float) -CARD_HEIGHT / 2));

View file

@ -774,7 +774,13 @@ void Player::actViewLibrary()
void Player::actViewTopCards() void Player::actViewTopCards()
{ {
bool ok; bool ok;
int number = QInputDialog::getInteger(0, tr("View top cards of library"), tr("Number of cards:"), defaultNumberTopCards, 1, 2000000000, 1, &ok); int number =
#if QT_VERSION < 0x050000
QInputDialog::getInteger(
#else
QInputDialog::getInt(
#endif
0, tr("View top cards of library"), tr("Number of cards:"), defaultNumberTopCards, 1, 2000000000, 1, &ok);
if (ok) { if (ok) {
defaultNumberTopCards = number; defaultNumberTopCards = number;
static_cast<GameScene *>(scene())->toggleZoneView(this, "deck", number); static_cast<GameScene *>(scene())->toggleZoneView(this, "deck", number);
@ -829,7 +835,13 @@ void Player::actMulligan()
void Player::actDrawCards() void Player::actDrawCards()
{ {
int number = QInputDialog::getInteger(0, tr("Draw cards"), tr("Number:")); int number =
#if QT_VERSION < 0x050000
QInputDialog::getInteger(
#else
QInputDialog::getInt(
#endif
0, tr("Draw cards"), tr("Number:"));
if (number) { if (number) {
Command_DrawCards cmd; Command_DrawCards cmd;
cmd.set_number(number); cmd.set_number(number);
@ -844,7 +856,13 @@ void Player::actUndoDraw()
void Player::actMoveTopCardsToGrave() void Player::actMoveTopCardsToGrave()
{ {
int number = QInputDialog::getInteger(0, tr("Move top cards to grave"), tr("Number:")); int number =
#if QT_VERSION < 0x050000
QInputDialog::getInteger(
#else
QInputDialog::getInt(
#endif
0, tr("Move top cards to grave"), tr("Number:"));
if (!number) if (!number)
return; return;
@ -867,7 +885,13 @@ void Player::actMoveTopCardsToGrave()
void Player::actMoveTopCardsToExile() void Player::actMoveTopCardsToExile()
{ {
int number = QInputDialog::getInteger(0, tr("Move top cards to exile"), tr("Number:")); int number =
#if QT_VERSION < 0x050000
QInputDialog::getInteger(
#else
QInputDialog::getInt(
#endif
0, tr("Move top cards to exile"), tr("Number:"));
if (!number) if (!number)
return; return;
@ -914,7 +938,13 @@ void Player::actUntapAll()
void Player::actRollDie() void Player::actRollDie()
{ {
bool ok; bool ok;
int sides = QInputDialog::getInteger(0, tr("Roll die"), tr("Number of sides:"), 20, 2, 1000, 1, &ok); int sides =
#if QT_VERSION < 0x050000
QInputDialog::getInteger(
#else
QInputDialog::getInt(
#endif
0, tr("Roll die"), tr("Number of sides:"), 20, 2, 1000, 1, &ok);
if (ok) { if (ok) {
Command_RollDie cmd; Command_RollDie cmd;
cmd.set_sides(sides); cmd.set_sides(sides);
@ -929,6 +959,10 @@ void Player::actCreateToken()
return; return;
lastTokenName = dlg.getName(); lastTokenName = dlg.getName();
if (CardInfo *correctedCard = db->getCardBySimpleName(lastTokenName, false)) {
lastTokenName = correctedCard->getName();
}
lastTokenColor = dlg.getColor(); lastTokenColor = dlg.getColor();
lastTokenPT = dlg.getPT(); lastTokenPT = dlg.getPT();
lastTokenAnnotation = dlg.getAnnotation(); lastTokenAnnotation = dlg.getAnnotation();
@ -2022,7 +2056,13 @@ void Player::actCardCounterTrigger()
case 11: { case 11: {
bool ok; bool ok;
dialogSemaphore = true; dialogSemaphore = true;
int number = QInputDialog::getInteger(0, tr("Set counters"), tr("Number:"), 0, 0, MAX_COUNTERS_ON_CARD, 1, &ok); int number =
#if QT_VERSION < 0x050000
QInputDialog::getInteger(
#else
QInputDialog::getInt(
#endif
0, tr("Set counters"), tr("Number:"), 0, 0, MAX_COUNTERS_ON_CARD, 1, &ok);
dialogSemaphore = false; dialogSemaphore = false;
if (clearCardsToDelete()) if (clearCardsToDelete())
return; return;

View file

@ -72,7 +72,11 @@ PlayerListWidget::PlayerListWidget(TabSupervisor *_tabSupervisor, AbstractClient
setColumnCount(6); setColumnCount(6);
setHeaderHidden(true); setHeaderHidden(true);
setRootIsDecorated(false); setRootIsDecorated(false);
#if QT_VERSION < 0x050000
header()->setResizeMode(QHeaderView::ResizeToContents); header()->setResizeMode(QHeaderView::ResizeToContents);
#else
header()->setSectionResizeMode(QHeaderView::ResizeToContents);
#endif
retranslateUi(); retranslateUi();
} }
@ -174,5 +178,5 @@ void PlayerListWidget::showContextMenu(const QPoint &pos, const QModelIndex &ind
int playerId = index.sibling(index.row(), 4).data(Qt::UserRole + 1).toInt(); int playerId = index.sibling(index.row(), 4).data(Qt::UserRole + 1).toInt();
UserLevelFlags userLevel(index.sibling(index.row(), 3).data(Qt::UserRole).toInt()); UserLevelFlags userLevel(index.sibling(index.row(), 3).data(Qt::UserRole).toInt());
userContextMenu->showContextMenu(pos, userName, userLevel, playerId); userContextMenu->showContextMenu(pos, userName, userLevel, true, playerId);
} }

View file

@ -4,25 +4,46 @@
*/ */
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
#include <QNetworkReply> #include <QNetworkReply>
#include <QMessageBox>
#include "qt-json/json.h" #include "qt-json/json.h"
#include "priceupdater.h" #include "priceupdater.h"
#include "main.h"
#include "carddatabase.h"
#if QT_VERSION < 0x050000
// for Qt::escape()
#include <QtGui/qtextdocument.h>
#endif
/** /**
* Constructor. * Constructor.
* *
* @param _deck deck. * @param _deck deck.
*/ */
PriceUpdater::PriceUpdater(const DeckList *_deck) AbstractPriceUpdater::AbstractPriceUpdater(const DeckList *_deck)
{ {
nam = new QNetworkAccessManager(this); nam = new QNetworkAccessManager(this);
deck = _deck; deck = _deck;
} }
// blacklotusproject.com
/**
* Constructor.
*
* @param _deck deck.
*/
BLPPriceUpdater::BLPPriceUpdater(const DeckList *_deck)
: AbstractPriceUpdater(_deck)
{
}
/** /**
* Update the prices of the cards in deckList. * Update the prices of the cards in deckList.
*/ */
void PriceUpdater::updatePrices() void BLPPriceUpdater::updatePrices()
{ {
QString q = "http://blacklotusproject.com/json/?cards="; QString q = "http://blacklotusproject.com/json/?cards=";
QStringList cards = deck->getCardList(); QStringList cards = deck->getCardList();
@ -38,7 +59,7 @@ void PriceUpdater::updatePrices()
/** /**
* Called when the download of the json file with the prices is finished. * Called when the download of the json file with the prices is finished.
*/ */
void PriceUpdater::downloadFinished() void BLPPriceUpdater::downloadFinished()
{ {
QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
bool ok; bool ok;
@ -82,3 +103,188 @@ void PriceUpdater::downloadFinished()
deleteLater(); deleteLater();
emit finishedUpdate(); emit finishedUpdate();
} }
// deckbrew.com
/**
* Constructor.
*
* @param _deck deck.
*/
DBPriceUpdater::DBPriceUpdater(const DeckList *_deck)
: AbstractPriceUpdater(_deck)
{
}
/**
* Update the prices of the cards in deckList.
*/
void DBPriceUpdater::updatePrices()
{
QString base = "https://api.deckbrew.com/mtg/cards", q = "";
QStringList cards = deck->getCardList();
muidMap.clear();
urls.clear();
CardInfo * card;
int muid;
SetList sets;
bool bNotFirst=false;
for (int i = 0; i < cards.size(); ++i) {
card = db->getCard(cards[i], false);
sets = card->getSets();
for(int j = 0; j < sets.size(); ++j)
{
muid=card->getMuId(sets[j]->getShortName());
if (!muid) {
continue;
}
//qDebug() << "muid " << muid << " card: " << cards[i] << endl;
if(bNotFirst)
{
q += QString("&m=%1").arg(muid);
} else {
q += QString("?m=%1").arg(muid);
bNotFirst = true;
}
muidMap.insert(muid, cards[i]);
if(q.length() > 240)
{
urls.append(base + q);
bNotFirst=false;
q = "";
}
}
}
if(q.length() > 0)
urls.append(base + q);
requestNext();
}
void DBPriceUpdater::requestNext()
{
if(urls.empty())
return;
QUrl url(urls.takeFirst(), QUrl::TolerantMode);
//qDebug() << "request prices from: " << url.toString() << endl;
QNetworkReply *reply = nam->get(QNetworkRequest(url));
connect(reply, SIGNAL(finished()), this, SLOT(downloadFinished()));
}
/**
* Called when the download of the json file with the prices is finished.
*/
void DBPriceUpdater::downloadFinished()
{
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
bool ok;
QString tmp = QString(reply->readAll());
// Errors are incapsulated in an object, check for them first
QVariantMap resultMap = QtJson::Json::parse(tmp, ok).toMap();
if (!ok) {
QMessageBox::critical(this, tr("Error"), tr("A problem has occured while fetching card prices."));
reply->deleteLater();
if(urls.isEmpty())
{
deleteLater();
emit finishedUpdate();
} else {
requestNext();
}
}
if(resultMap.contains("errors"))
{
QMessageBox::critical(this, tr("Error"), tr("A problem has occured while fetching card prices:") +
"<br/>" +
#if QT_VERSION < 0x050000
Qt::escape(resultMap["errors"].toList().first().toString())
#else
resultMap["errors"].toList().first().toString().toHtmlEscaped()
#endif
);
reply->deleteLater();
if(urls.isEmpty())
{
deleteLater();
emit finishedUpdate();
} else {
requestNext();
}
}
// Good results are a list
QVariantList resultList = QtJson::Json::parse(tmp, ok).toList();
if (!ok) {
QMessageBox::critical(this, tr("Error"), tr("A problem has occured while fetching card prices."));
reply->deleteLater();
if(urls.isEmpty())
{
deleteLater();
emit finishedUpdate();
} else {
requestNext();
}
}
QMap<QString, float> cardsPrice;
QListIterator<QVariant> it(resultList);
while (it.hasNext()) {
QVariantMap cardMap = it.next().toMap();
// get sets list
QList<QVariant> editions = cardMap.value("editions").toList();
foreach (QVariant ed, editions)
{
// retrieve card name "as we know it" from the muid
QVariantMap edition = ed.toMap();
QString set = edition.value("set_id").toString();
int muid = edition.value("multiverse_id").toString().toInt();
if(!muidMap.contains(muid))
continue;
QString name=muidMap.value(muid);
// Prices are in USD cents
float price = edition.value("price").toMap().value("median").toString().toFloat() / 100;
//qDebug() << "card " << name << " set " << set << " price " << price << endl;
/**
* Make sure Masters Edition (MED) isn't the set, as it doesn't
* physically exist. Also check the price to see that the cheapest set
* ends up as the final price.
*/
if (set != "MED" && price > 0 && (!cardsPrice.contains(name) || cardsPrice.value(name) > price))
cardsPrice.insert(name, price);
}
}
InnerDecklistNode *listRoot = deck->getRoot();
for (int i = 0; i < listRoot->size(); i++) {
InnerDecklistNode *currentZone = dynamic_cast<InnerDecklistNode *>(listRoot->at(i));
for (int j = 0; j < currentZone->size(); j++) {
DecklistCardNode *currentCard = dynamic_cast<DecklistCardNode *>(currentZone->at(j));
if (!currentCard)
continue;
float price = cardsPrice[currentCard->getName()];
if(price > 0)
currentCard->setPrice(price);
}
}
reply->deleteLater();
if(urls.isEmpty())
{
deleteLater();
emit finishedUpdate();
} else {
requestNext();
}
}

View file

@ -1,28 +1,57 @@
#ifndef PRICEUPDATER_H #ifndef PRICEUPDATER_H
#define PRICEUPDATER_H #define PRICEUPDATER_H
#include <QNetworkReply> #include <QNetworkAccessManager>
#include "decklist.h" #include "decklist.h"
class QNetworkAccessManager; class QNetworkAccessManager;
// If we don't typedef this, won't compile on OS X < 10.9
typedef QMap<int, QString> MuidStringMap;
/** /**
* Price Updater. * Price Updater.
* *
* @author Marcio Ribeiro <mmr@b1n.org> * @author Marcio Ribeiro <mmr@b1n.org>
*/ */
class PriceUpdater : public QObject class AbstractPriceUpdater : public QWidget
{ {
Q_OBJECT Q_OBJECT
private: public:
enum PriceSource { BLPPriceSource, DBPriceSource };
protected:
const DeckList *deck; const DeckList *deck;
QNetworkAccessManager *nam; QNetworkAccessManager *nam;
signals: signals:
void finishedUpdate(); void finishedUpdate();
private slots: protected slots:
void downloadFinished(); virtual void downloadFinished() = 0;
public: public:
PriceUpdater(const DeckList *deck); AbstractPriceUpdater(const DeckList *deck);
void updatePrices(); virtual void updatePrices() = 0;
};
class BLPPriceUpdater : public AbstractPriceUpdater
{
Q_OBJECT
protected:
virtual void downloadFinished();
public:
BLPPriceUpdater(const DeckList *deck);
virtual void updatePrices();
};
class DBPriceUpdater : public AbstractPriceUpdater
{
Q_OBJECT
protected:
MuidStringMap muidMap;
QList<QString> urls;
protected:
virtual void downloadFinished();
void requestNext();
public:
DBPriceUpdater(const DeckList *deck);
virtual void updatePrices();
}; };
#endif #endif

View file

@ -553,7 +553,7 @@ int Json::nextToken(const QString &json, int &index)
QChar c = json[index]; QChar c = json[index];
index++; index++;
switch(c.toAscii()) switch(c.toLatin1())
{ {
case '{': return JsonTokenCurlyOpen; case '{': return JsonTokenCurlyOpen;
case '}': return JsonTokenCurlyClose; case '}': return JsonTokenCurlyClose;

View file

@ -15,7 +15,7 @@ RemoteClient::RemoteClient(QObject *parent)
: AbstractClient(parent), timeRunning(0), lastDataReceived(0), messageInProgress(false), handshakeStarted(false), messageLength(0) : AbstractClient(parent), timeRunning(0), lastDataReceived(0), messageInProgress(false), handshakeStarted(false), messageLength(0)
{ {
timer = new QTimer(this); timer = new QTimer(this);
timer->setInterval(9000); timer->setInterval(1000);
connect(timer, SIGNAL(timeout()), this, SLOT(ping())); connect(timer, SIGNAL(timeout()), this, SLOT(ping()));
socket = new QTcpSocket(this); socket = new QTcpSocket(this);

View file

@ -258,8 +258,11 @@ void RemoteDeckList_TreeModel::deckListFinished(const Response &r)
{ {
const Response_DeckList &resp = r.GetExtension(Response_DeckList::ext); const Response_DeckList &resp = r.GetExtension(Response_DeckList::ext);
beginResetModel();
root->clearTree(); root->clearTree();
reset();
endResetModel();
ServerInfo_DeckStorage_TreeItem tempRoot; ServerInfo_DeckStorage_TreeItem tempRoot;
tempRoot.set_id(0); tempRoot.set_id(0);
@ -280,7 +283,11 @@ RemoteDeckList_TreeWidget::RemoteDeckList_TreeWidget(AbstractClient *_client, QW
setModel(proxyModel); setModel(proxyModel);
connect(treeModel, SIGNAL(treeRefreshed()), this, SLOT(expandAll())); connect(treeModel, SIGNAL(treeRefreshed()), this, SLOT(expandAll()));
#if QT_VERSION < 0x050000
header()->setResizeMode(QHeaderView::ResizeToContents); header()->setResizeMode(QHeaderView::ResizeToContents);
#else
header()->setSectionResizeMode(QHeaderView::ResizeToContents);
#endif
setUniformRowHeights(true); setUniformRowHeights(true);
setSortingEnabled(true); setSortingEnabled(true);
proxyModel->sort(0, Qt::AscendingOrder); proxyModel->sort(0, Qt::AscendingOrder);

View file

@ -278,7 +278,11 @@ RemoteReplayList_TreeWidget::RemoteReplayList_TreeWidget(AbstractClient *_client
proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
setModel(proxyModel); setModel(proxyModel);
#if QT_VERSION < 0x050000
header()->setResizeMode(QHeaderView::ResizeToContents); header()->setResizeMode(QHeaderView::ResizeToContents);
#else
header()->setSectionResizeMode(QHeaderView::ResizeToContents);
#endif
header()->setStretchLastSection(false); header()->setStretchLastSection(false);
setUniformRowHeights(true); setUniformRowHeights(true);
setSortingEnabled(true); setSortingEnabled(true);

View file

@ -43,7 +43,7 @@ void ReplayTimelineWidget::setTimeline(const QList<int> &_replayTimeline)
update(); update();
} }
void ReplayTimelineWidget::paintEvent(QPaintEvent *event) void ReplayTimelineWidget::paintEvent(QPaintEvent * /* event */)
{ {
QPainter painter(this); QPainter painter(this);
painter.drawRect(0, 0, width() - 1, height() - 1); painter.drawRect(0, 0, width() - 1, height() - 1);

View file

@ -45,6 +45,7 @@ SettingsCache::SettingsCache()
soundPath = settings->value("sound/path").toString(); soundPath = settings->value("sound/path").toString();
priceTagFeature = settings->value("deckeditor/pricetags", false).toBool(); priceTagFeature = settings->value("deckeditor/pricetags", false).toBool();
priceTagSource = settings->value("deckeditor/pricetagsource", 0).toInt();
ignoreUnregisteredUsers = settings->value("chat/ignore_unregistered", false).toBool(); ignoreUnregisteredUsers = settings->value("chat/ignore_unregistered", false).toBool();
} }
@ -247,6 +248,12 @@ void SettingsCache::setPriceTagFeature(int _priceTagFeature)
emit priceTagFeatureChanged(priceTagFeature); emit priceTagFeatureChanged(priceTagFeature);
} }
void SettingsCache::setPriceTagSource(int _priceTagSource)
{
priceTagSource = _priceTagSource;
settings->setValue("deckeditor/pricetagsource", priceTagSource);
}
void SettingsCache::setIgnoreUnregisteredUsers(bool _ignoreUnregisteredUsers) void SettingsCache::setIgnoreUnregisteredUsers(bool _ignoreUnregisteredUsers)
{ {
ignoreUnregisteredUsers = _ignoreUnregisteredUsers; ignoreUnregisteredUsers = _ignoreUnregisteredUsers;

View file

@ -53,6 +53,7 @@ private:
bool soundEnabled; bool soundEnabled;
QString soundPath; QString soundPath;
bool priceTagFeature; bool priceTagFeature;
int priceTagSource;
bool ignoreUnregisteredUsers; bool ignoreUnregisteredUsers;
QString picUrl; QString picUrl;
QString picUrlHq; QString picUrlHq;
@ -87,6 +88,7 @@ public:
bool getSoundEnabled() const { return soundEnabled; } bool getSoundEnabled() const { return soundEnabled; }
QString getSoundPath() const { return soundPath; } QString getSoundPath() const { return soundPath; }
bool getPriceTagFeature() const { return priceTagFeature; } bool getPriceTagFeature() const { return priceTagFeature; }
int getPriceTagSource() const { return priceTagSource; }
bool getIgnoreUnregisteredUsers() const { return ignoreUnregisteredUsers; } bool getIgnoreUnregisteredUsers() const { return ignoreUnregisteredUsers; }
QString getPicUrl() const { return picUrl; } QString getPicUrl() const { return picUrl; }
QString getPicUrlHq() const { return picUrlHq; } QString getPicUrlHq() const { return picUrlHq; }
@ -121,6 +123,7 @@ public slots:
void setSoundEnabled(int _soundEnabled); void setSoundEnabled(int _soundEnabled);
void setSoundPath(const QString &_soundPath); void setSoundPath(const QString &_soundPath);
void setPriceTagFeature(int _priceTagFeature); void setPriceTagFeature(int _priceTagFeature);
void setPriceTagSource(int _priceTagSource);
void setIgnoreUnregisteredUsers(bool _ignoreUnregisteredUsers); void setIgnoreUnregisteredUsers(bool _ignoreUnregisteredUsers);
void setPicUrl(const QString &_picUrl); void setPicUrl(const QString &_picUrl);
void setPicUrlHq(const QString &_picUrlHq); void setPicUrlHq(const QString &_picUrlHq);

View file

@ -33,8 +33,13 @@ void SoundEngine::soundEnabledChanged()
if (settingsCache->getSoundEnabled()) { if (settingsCache->getSoundEnabled()) {
qDebug("SoundEngine: enabling sound"); qDebug("SoundEngine: enabling sound");
QAudioFormat format; QAudioFormat format;
#if QT_VERSION < 0x050000
format.setFrequency(44100); format.setFrequency(44100);
format.setChannels(1); format.setChannels(1);
#else
format.setSampleRate(44100);
format.setChannelCount(1);
#endif
format.setSampleSize(16); format.setSampleSize(16);
format.setCodec("audio/pcm"); format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian); format.setByteOrder(QAudioFormat::LittleEndian);

View file

@ -31,6 +31,7 @@ public:
virtual QString getTabText() const = 0; virtual QString getTabText() const = 0;
virtual void retranslateUi() = 0; virtual void retranslateUi() = 0;
virtual void closeRequest() { } virtual void closeRequest() { }
virtual void tabActivated() { }
}; };
#endif #endif

View file

@ -134,7 +134,11 @@ TabDeckEditor::TabDeckEditor(TabSupervisor *_tabSupervisor, QWidget *parent)
deckView->setUniformRowHeights(true); deckView->setUniformRowHeights(true);
deckView->setSortingEnabled(true); deckView->setSortingEnabled(true);
deckView->sortByColumn(1, Qt::AscendingOrder); deckView->sortByColumn(1, Qt::AscendingOrder);
#if QT_VERSION < 0x050000
deckView->header()->setResizeMode(QHeaderView::ResizeToContents); deckView->header()->setResizeMode(QHeaderView::ResizeToContents);
#else
deckView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
#endif
deckView->installEventFilter(&deckViewKeySignals); deckView->installEventFilter(&deckViewKeySignals);
connect(deckView->selectionModel(), SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(updateCardInfoRight(const QModelIndex &, const QModelIndex &))); connect(deckView->selectionModel(), SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(updateCardInfoRight(const QModelIndex &, const QModelIndex &)));
connect(&deckViewKeySignals, SIGNAL(onEnter()), this, SLOT(actIncrement())); connect(&deckViewKeySignals, SIGNAL(onEnter()), this, SLOT(actIncrement()));
@ -508,7 +512,10 @@ void TabDeckEditor::actPrintDeck()
void TabDeckEditor::actAnalyzeDeck() void TabDeckEditor::actAnalyzeDeck()
{ {
DeckStatsInterface *interface = new DeckStatsInterface(this); // it deletes itself when done DeckStatsInterface *interface = new DeckStatsInterface(
*databaseModel->getDatabase(),
this
); // it deletes itself when done
interface->analyzeDeck(deckModel->getDeckList()); interface->analyzeDeck(deckModel->getDeckList());
} }
@ -639,12 +646,25 @@ void TabDeckEditor::actDecrement()
void TabDeckEditor::setPriceTagFeatureEnabled(int enabled) void TabDeckEditor::setPriceTagFeatureEnabled(int enabled)
{ {
aUpdatePrices->setVisible(enabled); aUpdatePrices->setVisible(enabled);
deckModel->pricesUpdated();
} }
void TabDeckEditor::actUpdatePrices() void TabDeckEditor::actUpdatePrices()
{ {
aUpdatePrices->setDisabled(true); aUpdatePrices->setDisabled(true);
PriceUpdater *up = new PriceUpdater(deckModel->getDeckList()); AbstractPriceUpdater *up;
switch(settingsCache->getPriceTagSource())
{
case AbstractPriceUpdater::DBPriceSource:
up = new DBPriceUpdater(deckModel->getDeckList());
break;
case AbstractPriceUpdater::BLPPriceSource:
default:
up = new BLPPriceUpdater(deckModel->getDeckList());
break;
}
connect(up, SIGNAL(finishedUpdate()), this, SLOT(finishedUpdatingPrices())); connect(up, SIGNAL(finishedUpdate()), this, SLOT(finishedUpdatingPrices()));
up->updatePrices(); up->updatePrices();
} }

View file

@ -38,7 +38,11 @@ TabDeckStorage::TabDeckStorage(TabSupervisor *_tabSupervisor, AbstractClient *_c
localDirView->setColumnHidden(1, true); localDirView->setColumnHidden(1, true);
localDirView->setRootIndex(localDirModel->index(localDirModel->rootPath(), 0)); localDirView->setRootIndex(localDirModel->index(localDirModel->rootPath(), 0));
localDirView->setSortingEnabled(true); localDirView->setSortingEnabled(true);
#if QT_VERSION < 0x050000
localDirView->header()->setResizeMode(QHeaderView::ResizeToContents); localDirView->header()->setResizeMode(QHeaderView::ResizeToContents);
#else
localDirView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
#endif
localDirView->header()->setSortIndicator(0, Qt::AscendingOrder); localDirView->header()->setSortIndicator(0, Qt::AscendingOrder);
leftToolBar = new QToolBar; leftToolBar = new QToolBar;

View file

@ -254,7 +254,7 @@ TabGame::TabGame(TabSupervisor *_tabSupervisor, GameReplay *_replay)
// Create list: event number -> time [ms] // Create list: event number -> time [ms]
// Distribute simultaneous events evenly across 1 second. // Distribute simultaneous events evenly across 1 second.
int lastEventTimestamp = -1; unsigned int lastEventTimestamp = 0;
const int eventCount = replay->event_list_size(); const int eventCount = replay->event_list_size();
for (int i = 0; i < eventCount; ++i) { for (int i = 0; i < eventCount; ++i) {
int j = i + 1; int j = i + 1;

View file

@ -49,6 +49,12 @@ void TabMessage::retranslateUi()
aLeave->setText(tr("&Leave")); aLeave->setText(tr("&Leave"));
} }
void TabMessage::tabActivated()
{
if(!sayEdit->hasFocus())
sayEdit->setFocus();
}
QString TabMessage::getUserName() const QString TabMessage::getUserName() const
{ {
return QString::fromStdString(otherUserInfo->name()); return QString::fromStdString(otherUserInfo->name());

View file

@ -34,6 +34,7 @@ public:
~TabMessage(); ~TabMessage();
void retranslateUi(); void retranslateUi();
void closeRequest(); void closeRequest();
void tabActivated();
QString getUserName() const; QString getUserName() const;
QString getTabText() const; QString getTabText() const;

View file

@ -36,7 +36,11 @@ TabReplays::TabReplays(TabSupervisor *_tabSupervisor, AbstractClient *_client)
localDirView->setColumnHidden(1, true); localDirView->setColumnHidden(1, true);
localDirView->setRootIndex(localDirModel->index(localDirModel->rootPath(), 0)); localDirView->setRootIndex(localDirModel->index(localDirModel->rootPath(), 0));
localDirView->setSortingEnabled(true); localDirView->setSortingEnabled(true);
#if QT_VERSION < 0x050000
localDirView->header()->setResizeMode(QHeaderView::ResizeToContents); localDirView->header()->setResizeMode(QHeaderView::ResizeToContents);
#else
localDirView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
#endif
localDirView->header()->setSortIndicator(0, Qt::AscendingOrder); localDirView->header()->setSortIndicator(0, Qt::AscendingOrder);
leftToolBar = new QToolBar; leftToolBar = new QToolBar;
@ -198,7 +202,7 @@ void TabReplays::actDownload()
client->sendCommand(pend); client->sendCommand(pend);
} }
void TabReplays::downloadFinished(const Response &r, const CommandContainer &commandContainer, const QVariant &extraData) void TabReplays::downloadFinished(const Response &r, const CommandContainer & /* commandContainer */, const QVariant &extraData)
{ {
if (r.response_code() != Response::RespOk) if (r.response_code() != Response::RespOk)
return; return;

View file

@ -121,6 +121,12 @@ void TabRoom::closeRequest()
actLeaveRoom(); actLeaveRoom();
} }
void TabRoom::tabActivated()
{
if(!sayEdit->hasFocus())
sayEdit->setFocus();
}
QString TabRoom::sanitizeHtml(QString dirty) const QString TabRoom::sanitizeHtml(QString dirty) const
{ {
return dirty return dirty

View file

@ -64,6 +64,7 @@ public:
~TabRoom(); ~TabRoom();
void retranslateUi(); void retranslateUi();
void closeRequest(); void closeRequest();
void tabActivated();
void processRoomEvent(const RoomEvent &event); void processRoomEvent(const RoomEvent &event);
int getRoomId() const { return roomId; } int getRoomId() const { return roomId; }
const QMap<int, QString> &getGameTypes() const { return gameTypes; } const QMap<int, QString> &getGameTypes() const { return gameTypes; }

View file

@ -28,11 +28,17 @@ RoomSelector::RoomSelector(AbstractClient *_client, QWidget *parent)
roomList->setRootIsDecorated(false); roomList->setRootIsDecorated(false);
roomList->setColumnCount(4); roomList->setColumnCount(4);
roomList->header()->setStretchLastSection(false); roomList->header()->setStretchLastSection(false);
#if QT_VERSION < 0x050000
roomList->header()->setResizeMode(0, QHeaderView::ResizeToContents); roomList->header()->setResizeMode(0, QHeaderView::ResizeToContents);
roomList->header()->setResizeMode(1, QHeaderView::Stretch); roomList->header()->setResizeMode(1, QHeaderView::Stretch);
roomList->header()->setResizeMode(2, QHeaderView::ResizeToContents); roomList->header()->setResizeMode(2, QHeaderView::ResizeToContents);
roomList->header()->setResizeMode(3, QHeaderView::ResizeToContents); roomList->header()->setResizeMode(3, QHeaderView::ResizeToContents);
#else
roomList->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
roomList->header()->setSectionResizeMode(1, QHeaderView::Stretch);
roomList->header()->setSectionResizeMode(2, QHeaderView::ResizeToContents);
roomList->header()->setSectionResizeMode(3, QHeaderView::ResizeToContents);
#endif
joinButton = new QPushButton; joinButton = new QPushButton;
connect(joinButton, SIGNAL(clicked()), this, SLOT(joinClicked())); connect(joinButton, SIGNAL(clicked()), this, SLOT(joinClicked()));
QHBoxLayout *buttonLayout = new QHBoxLayout; QHBoxLayout *buttonLayout = new QHBoxLayout;

View file

@ -76,7 +76,7 @@ void CloseButton::paintEvent(QPaintEvent * /*event*/)
} }
TabSupervisor::TabSupervisor(AbstractClient *_client, QWidget *parent) TabSupervisor::TabSupervisor(AbstractClient *_client, QWidget *parent)
: QTabWidget(parent), userInfo(0), client(_client), tabUserLists(0), tabServer(0), tabDeckStorage(0), tabAdmin(0), tabReplays(0) : QTabWidget(parent), userInfo(0), client(_client), tabServer(0), tabUserLists(0), tabDeckStorage(0), tabReplays(0), tabAdmin(0)
{ {
tabChangedIcon = new QIcon(":/resources/icon_tab_changed.svg"); tabChangedIcon = new QIcon(":/resources/icon_tab_changed.svg");
setElideMode(Qt::ElideRight); setElideMode(Qt::ElideRight);
@ -479,6 +479,7 @@ void TabSupervisor::updateCurrent(int index)
tab->setContentsChanged(false); tab->setContentsChanged(false);
} }
emit setMenu(static_cast<Tab *>(widget(index))->getTabMenus()); emit setMenu(static_cast<Tab *>(widget(index))->getTabMenus());
tab->tabActivated();
} else } else
emit setMenu(); emit setMenu();
} }

View file

@ -28,7 +28,11 @@ TableZone::TableZone(Player *_p, QGraphicsItem *parent)
currentMinimumWidth = minWidth; currentMinimumWidth = minWidth;
setCacheMode(DeviceCoordinateCache); setCacheMode(DeviceCoordinateCache);
#if QT_VERSION < 0x050000
setAcceptsHoverEvents(true); setAcceptsHoverEvents(true);
#else
setAcceptHoverEvents(true);
#endif
} }
void TableZone::updateBgPixmap() void TableZone::updateBgPixmap()

View file

@ -102,7 +102,7 @@ void UserContextMenu::banUser_dialogFinished()
client->sendCommand(client->prepareModeratorCommand(cmd)); client->sendCommand(client->prepareModeratorCommand(cmd));
} }
void UserContextMenu::showContextMenu(const QPoint &pos, const QString &userName, UserLevelFlags userLevel, int playerId) void UserContextMenu::showContextMenu(const QPoint &pos, const QString &userName, UserLevelFlags userLevel, bool online, int playerId)
{ {
aUserName->setText(userName); aUserName->setText(userName);
@ -132,7 +132,8 @@ void UserContextMenu::showContextMenu(const QPoint &pos, const QString &userName
menu->addAction(aBan); menu->addAction(aBan);
} }
bool anotherUser = userName != QString::fromStdString(tabSupervisor->getUserInfo()->name()); bool anotherUser = userName != QString::fromStdString(tabSupervisor->getUserInfo()->name());
aChat->setEnabled(anotherUser); aDetails->setEnabled(online);
aChat->setEnabled(anotherUser && online);
aShowGames->setEnabled(anotherUser); aShowGames->setEnabled(anotherUser);
aAddToBuddyList->setEnabled(anotherUser); aAddToBuddyList->setEnabled(anotherUser);
aRemoveFromBuddyList->setEnabled(anotherUser); aRemoveFromBuddyList->setEnabled(anotherUser);

View file

@ -36,7 +36,7 @@ private slots:
public: public:
UserContextMenu(const TabSupervisor *_tabSupervisor, QWidget *_parent, TabGame *_game = 0); UserContextMenu(const TabSupervisor *_tabSupervisor, QWidget *_parent, TabGame *_game = 0);
void retranslateUi(); void retranslateUi();
void showContextMenu(const QPoint &pos, const QString &userName, UserLevelFlags userLevel, int playerId = -1); void showContextMenu(const QPoint &pos, const QString &userName, UserLevelFlags userLevel, bool online = true, int playerId = -1);
}; };
#endif #endif

View file

@ -216,7 +216,11 @@ UserList::UserList(TabSupervisor *_tabSupervisor, AbstractClient *_client, UserL
userTree = new QTreeWidget; userTree = new QTreeWidget;
userTree->setColumnCount(3); userTree->setColumnCount(3);
#if QT_VERSION < 0x050000
userTree->header()->setResizeMode(QHeaderView::ResizeToContents); userTree->header()->setResizeMode(QHeaderView::ResizeToContents);
#else
userTree->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
#endif
userTree->setHeaderHidden(true); userTree->setHeaderHidden(true);
userTree->setRootIsDecorated(false); userTree->setRootIsDecorated(false);
userTree->setIconSize(QSize(20, 12)); userTree->setIconSize(QSize(20, 12));
@ -307,8 +311,9 @@ void UserList::userClicked(QTreeWidgetItem *item, int /*column*/)
void UserList::showContextMenu(const QPoint &pos, const QModelIndex &index) void UserList::showContextMenu(const QPoint &pos, const QModelIndex &index)
{ {
const ServerInfo_User &userInfo = static_cast<UserListTWI *>(userTree->topLevelItem(index.row()))->getUserInfo(); const ServerInfo_User &userInfo = static_cast<UserListTWI *>(userTree->topLevelItem(index.row()))->getUserInfo();
bool online = index.sibling(index.row(), 0).data(Qt::UserRole + 1).toBool();
userContextMenu->showContextMenu(pos, QString::fromStdString(userInfo.name()), UserLevelFlags(userInfo.user_level())); userContextMenu->showContextMenu(pos, QString::fromStdString(userInfo.name()), UserLevelFlags(userInfo.user_level()), online);
} }
void UserList::sortItems() void UserList::sortItems()

View file

@ -28,7 +28,20 @@ SET(common_SOURCES
sfmt/SFMT.c sfmt/SFMT.c
) )
set(ORACLE_LIBS)
# Qt4 stuff
if(Qt4_FOUND)
# Include directories
INCLUDE(${QT_USE_FILE}) INCLUDE(${QT_USE_FILE})
include_directories(${QT_INCLUDES})
endif()
# qt5 stuff
if(Qt5Widgets_FOUND)
include_directories(${Qt5Widgets_INCLUDE_DIRS})
endif()
INCLUDE_DIRECTORIES(pb) INCLUDE_DIRECTORIES(pb)
INCLUDE_DIRECTORIES(sfmt) INCLUDE_DIRECTORIES(sfmt)
INCLUDE_DIRECTORIES(${PROTOBUF_INCLUDE_DIR}) INCLUDE_DIRECTORIES(${PROTOBUF_INCLUDE_DIR})

View file

@ -355,7 +355,8 @@ DeckList::DeckList()
// TODO: http://qt-project.org/doc/qt-4.8/qobject.html#no-copy-constructor-or-assignment-operator // TODO: http://qt-project.org/doc/qt-4.8/qobject.html#no-copy-constructor-or-assignment-operator
DeckList::DeckList(const DeckList &other) DeckList::DeckList(const DeckList &other)
: name(other.name), : QObject(),
name(other.name),
comments(other.comments), comments(other.comments),
deckHash(other.deckHash) deckHash(other.deckHash)
{ {
@ -547,14 +548,21 @@ bool DeckList::loadFromStream_Plain(QTextStream &in)
line.remove(rx); line.remove(rx);
line = line.simplified(); line = line.simplified();
int i = line.indexOf(' '); int i = line.indexOf(' ');
int cardNameStart = i + 1;
// If the count ends with an 'x', ignore it. For example,
// "4x Storm Crow" will count 4 correctly.
if (i > 0 && line[i - 1] == 'x') {
i--;
}
bool ok; bool ok;
int number = line.left(i).toInt(&ok); int number = line.left(i).toInt(&ok);
if (!ok) if (!ok)
continue; continue;
QString cardName = line.mid(i + 1); QString cardName = line.mid(cardNameStart);
// Common differences between cockatrice's card names // Common differences between cockatrice's card names
// and what's commonly used in decklists // and what's commonly used in decklists
rx.setPattern("’"); rx.setPattern("’");
@ -563,9 +571,20 @@ bool DeckList::loadFromStream_Plain(QTextStream &in)
cardName.replace(rx, "AE"); cardName.replace(rx, "AE");
rx.setPattern("^Aether"); rx.setPattern("^Aether");
cardName.replace(rx, "AEther"); cardName.replace(rx, "AEther");
rx.setPattern("\\s*[&|/]{1,2}\\s*"); rx.setPattern("\\s*[|/]{1,2}\\s*");
cardName.replace(rx, " // "); cardName.replace(rx, " // ");
// Replace only if the ampersand is preceded by a non-capital letter,
// as would happen with acronyms. So 'Fire & Ice' is replaced but not
// 'R&D' or 'R & D'.
//
// Qt regexes don't support lookbehind so we capture and replace
// instead.
rx.setPattern("([^A-Z])\\s*&\\s*");
if (rx.indexIn(cardName) != -1) {
cardName.replace(rx, QString("%1 // ").arg(rx.cap(1)));
}
++okRows; ++okRows;
new DecklistCardNode(cardName, number, zone); new DecklistCardNode(cardName, number, zone);
} }
@ -579,16 +598,30 @@ bool DeckList::loadFromFile_Plain(QIODevice *device)
return loadFromStream_Plain(in); return loadFromStream_Plain(in);
} }
struct WriteToStream {
QTextStream &stream;
WriteToStream(QTextStream &_stream) : stream(_stream) {}
void operator()(
const InnerDecklistNode *node,
const DecklistCardNode *card
) {
if (node->getName() == "side") {
stream << "SB: ";
}
stream << QString("%1 %2\n").arg(
card->getNumber()
).arg(
card->getName()
);
}
};
bool DeckList::saveToStream_Plain(QTextStream &out) bool DeckList::saveToStream_Plain(QTextStream &out)
{ {
// Support for this is only possible if the internal structure doesn't get more complicated. WriteToStream writeToStream(out);
for (int i = 0; i < root->size(); i++) { forEachCard(writeToStream);
InnerDecklistNode *node = dynamic_cast<InnerDecklistNode *>(root->at(i));
for (int j = 0; j < node->size(); j++) {
DecklistCardNode *card = dynamic_cast<DecklistCardNode *>(node->at(j));
out << QString("%1%2 %3\n").arg(node->getName() == "side" ? "SB: " : "").arg(card->getNumber()).arg(card->getName());
}
}
return true; return true;
} }

View file

@ -117,6 +117,7 @@ public:
QString getName() const { return name; } QString getName() const { return name; }
void setName(const QString &_name) { name = _name; } void setName(const QString &_name) { name = _name; }
float getPrice() const { return price; } float getPrice() const { return price; }
void setPrice(const float _price) { price = _price; } void setPrice(const float _price) { price = _price; }
}; };
@ -169,6 +170,28 @@ public:
InnerDecklistNode *getRoot() const { return root; } InnerDecklistNode *getRoot() const { return root; }
DecklistCardNode *addCard(const QString &cardName, const QString &zoneName); DecklistCardNode *addCard(const QString &cardName, const QString &zoneName);
bool deleteNode(AbstractDecklistNode *node, InnerDecklistNode *rootNode = 0); bool deleteNode(AbstractDecklistNode *node, InnerDecklistNode *rootNode = 0);
/**
* Calls a given function object for each card in the deck. It must
* take a InnerDecklistNode* as its first argument and a
* DecklistCardNode* as its second.
*/
template <typename Callback>
void forEachCard(Callback &callback) const {
// Support for this is only possible if the internal structure
// doesn't get more complicated.
for (int i = 0; i < root->size(); i++) {
const InnerDecklistNode *node =
dynamic_cast<InnerDecklistNode *>(root->at(i));
for (int j = 0; j < node->size(); j++) {
const DecklistCardNode *card =
dynamic_cast<DecklistCardNode *>(
node->at(j)
);
callback(node, card);
}
}
}
}; };
#endif #endif

View file

@ -97,7 +97,7 @@ protected slots:
void externalGameEventContainerReceived(const GameEventContainer &cont, qint64 sessionId); void externalGameEventContainerReceived(const GameEventContainer &cont, qint64 sessionId);
void externalResponseReceived(const Response &resp, qint64 sessionId); void externalResponseReceived(const Response &resp, qint64 sessionId);
virtual void doSendIslMessage(const IslMessage &msg, int serverId) { } virtual void doSendIslMessage(const IslMessage & /* msg */, int /* serverId */) { }
protected: protected:
void prepareDestroy(); void prepareDestroy();
void setDatabaseInterface(Server_DatabaseInterface *_databaseInterface); void setDatabaseInterface(Server_DatabaseInterface *_databaseInterface);

View file

@ -12,18 +12,18 @@ public:
: QObject(parent) { } : QObject(parent) { }
virtual AuthenticationResult checkUserPassword(Server_ProtocolHandler *handler, const QString &user, const QString &password, QString &reasonStr, int &secondsLeft) = 0; virtual AuthenticationResult checkUserPassword(Server_ProtocolHandler *handler, const QString &user, const QString &password, QString &reasonStr, int &secondsLeft) = 0;
virtual bool userExists(const QString &user) { return false; } virtual bool userExists(const QString & /* user */) { return false; }
virtual QMap<QString, ServerInfo_User> getBuddyList(const QString &name) { return QMap<QString, ServerInfo_User>(); } virtual QMap<QString, ServerInfo_User> getBuddyList(const QString & /* name */) { return QMap<QString, ServerInfo_User>(); }
virtual QMap<QString, ServerInfo_User> getIgnoreList(const QString &name) { return QMap<QString, ServerInfo_User>(); } virtual QMap<QString, ServerInfo_User> getIgnoreList(const QString & /* name */) { return QMap<QString, ServerInfo_User>(); }
virtual bool isInBuddyList(const QString &whoseList, const QString &who) { return false; } virtual bool isInBuddyList(const QString & /* whoseList */, const QString & /* who */) { return false; }
virtual bool isInIgnoreList(const QString &whoseList, const QString &who) { return false; } virtual bool isInIgnoreList(const QString & /* whoseList */, const QString & /* who */) { return false; }
virtual ServerInfo_User getUserData(const QString &name, bool withId = false) = 0; virtual ServerInfo_User getUserData(const QString &name, bool withId = false) = 0;
virtual void storeGameInformation(const QString &roomName, const QStringList &roomGameTypes, const ServerInfo_Game &gameInfo, const QSet<QString> &allPlayersEver, const QSet<QString> &allSpectatorsEver, const QList<GameReplay *> &replayList) { } virtual void storeGameInformation(const QString & /* roomName */, const QStringList & /* roomGameTypes */, const ServerInfo_Game & /* gameInfo */, const QSet<QString> & /* allPlayersEver */, const QSet<QString> & /* allSpectatorsEver */, const QList<GameReplay *> & /* replayList */) { }
virtual DeckList *getDeckFromDatabase(int deckId, int userId) { return 0; } virtual DeckList *getDeckFromDatabase(int /* deckId */, int /* userId */) { return 0; }
virtual qint64 startSession(const QString &userName, const QString &address) { return 0; } virtual qint64 startSession(const QString & /* userName */, const QString & /* address */) { return 0; }
public slots: public slots:
virtual void endSession(qint64 sessionId) { } virtual void endSession(qint64 /* sessionId */ ) { }
public: public:
virtual int getNextGameId() = 0; virtual int getNextGameId() = 0;
virtual int getNextReplayId() = 0; virtual int getNextReplayId() = 0;
@ -31,7 +31,7 @@ public:
virtual void clearSessionTables() { } virtual void clearSessionTables() { }
virtual void lockSessionTables() { } virtual void lockSessionTables() { }
virtual void unlockSessionTables() { } virtual void unlockSessionTables() { }
virtual bool userSessionExists(const QString &userName) { return false; } virtual bool userSessionExists(const QString & /* userName */) { return false; }
}; };
#endif #endif

View file

@ -1594,7 +1594,7 @@ Response::ResponseCode Server_Player::cmdRevealCards(const Command_RevealCards &
return Response::RespOk; return Response::RespOk;
} }
Response::ResponseCode Server_Player::cmdChangeZoneProperties(const Command_ChangeZoneProperties &cmd, ResponseContainer &rc, GameEventStorage &ges) Response::ResponseCode Server_Player::cmdChangeZoneProperties(const Command_ChangeZoneProperties &cmd, ResponseContainer & /* rc */, GameEventStorage &ges)
{ {
Server_CardZone *zone = zones.value(QString::fromStdString(cmd.zone_name())); Server_CardZone *zone = zones.value(QString::fromStdString(cmd.zone_name()));
if (!zone) if (!zone)

View file

@ -49,7 +49,7 @@ protected:
AuthenticationResult authState; AuthenticationResult authState;
bool acceptsUserListChanges; bool acceptsUserListChanges;
bool acceptsRoomListChanges; bool acceptsRoomListChanges;
virtual void logDebugMessage(const QString &message) { } virtual void logDebugMessage(const QString & /* message */) { }
private: private:
QList<int> messageSizeOverTime, messageCountOverTime; QList<int> messageSizeOverTime, messageCountOverTime;
int timeRunning, lastDataReceived; int timeRunning, lastDataReceived;
@ -71,13 +71,13 @@ private:
Response::ResponseCode cmdJoinGame(const Command_JoinGame &cmd, Server_Room *room, ResponseContainer &rc); Response::ResponseCode cmdJoinGame(const Command_JoinGame &cmd, Server_Room *room, ResponseContainer &rc);
Response::ResponseCode processSessionCommandContainer(const CommandContainer &cont, ResponseContainer &rc); Response::ResponseCode processSessionCommandContainer(const CommandContainer &cont, ResponseContainer &rc);
virtual Response::ResponseCode processExtendedSessionCommand(int cmdType, const SessionCommand &cmd, ResponseContainer &rc) { return Response::RespFunctionNotAllowed; } virtual Response::ResponseCode processExtendedSessionCommand(int /* cmdType */, const SessionCommand & /* cmd */, ResponseContainer & /* rc */) { return Response::RespFunctionNotAllowed; }
Response::ResponseCode processRoomCommandContainer(const CommandContainer &cont, ResponseContainer &rc); Response::ResponseCode processRoomCommandContainer(const CommandContainer &cont, ResponseContainer &rc);
Response::ResponseCode processGameCommandContainer(const CommandContainer &cont, ResponseContainer &rc); Response::ResponseCode processGameCommandContainer(const CommandContainer &cont, ResponseContainer &rc);
Response::ResponseCode processModeratorCommandContainer(const CommandContainer &cont, ResponseContainer &rc); Response::ResponseCode processModeratorCommandContainer(const CommandContainer &cont, ResponseContainer &rc);
virtual Response::ResponseCode processExtendedModeratorCommand(int cmdType, const ModeratorCommand &cmd, ResponseContainer &rc) { return Response::RespFunctionNotAllowed; } virtual Response::ResponseCode processExtendedModeratorCommand(int /* cmdType */, const ModeratorCommand & /* cmd */, ResponseContainer & /* rc */) { return Response::RespFunctionNotAllowed; }
Response::ResponseCode processAdminCommandContainer(const CommandContainer &cont, ResponseContainer &rc); Response::ResponseCode processAdminCommandContainer(const CommandContainer &cont, ResponseContainer &rc);
virtual Response::ResponseCode processExtendedAdminCommand(int cmdType, const AdminCommand &cmd, ResponseContainer &rc) { return Response::RespFunctionNotAllowed; } virtual Response::ResponseCode processExtendedAdminCommand(int /* cmdType */, const AdminCommand & /* cmd */, ResponseContainer & /* rc */) { return Response::RespFunctionNotAllowed; }
private slots: private slots:
void pingClockTimeout(); void pingClockTimeout();
public slots: public slots:

View file

@ -2,6 +2,7 @@
#define SERVER_RESPONSE_CONTAINERS_H #define SERVER_RESPONSE_CONTAINERS_H
#include <QPair> #include <QPair>
#include <QList>
#include "pb/server_message.pb.h" #include "pb/server_message.pb.h"
namespace google { namespace protobuf { class Message; } } namespace google { namespace protobuf { class Message; } }

56
doc/cards.xsd Normal file
View file

@ -0,0 +1,56 @@
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="cockatrice_carddatabase">
<xs:complexType>
<xs:sequence>
<xs:element name="sets">
<xs:complexType>
<xs:sequence>
<xs:element name="set" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="name"/>
<xs:element type="xs:string" name="longname"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="cards">
<xs:complexType>
<xs:sequence>
<xs:element name="card" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="name"/>
<xs:element name="set" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:int" name="muId" use="optional"/>
<xs:attribute type="xs:anyURI" name="picUrl" use="optional"/>
<xs:attribute type="xs:anyURI" name="picUrlHq" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element type="xs:string" name="color" minOccurs="0" maxOccurs="unbounded"/>
<xs:element type="xs:string" name="manacost"/>
<xs:element type="xs:string" name="type"/>
<xs:element type="xs:string" name="pt" minOccurs="0"/>
<xs:element type="xs:integer" name="tablerow"/>
<xs:element type="xs:string" name="text"/>
<xs:element type="xs:boolean" name="cipt" minOccurs="0"/>
<xs:element type="xs:integer" name="loyalty" minOccurs="0"/>
<xs:element type="xs:boolean" name="token" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:integer" name="version"/>
</xs:complexType>
</xs:element>
</xs:schema>

View file

@ -16,21 +16,98 @@ SET(oracle_SOURCES
../cockatrice/src/qt-json/json.cpp ../cockatrice/src/qt-json/json.cpp
) )
set(oracle_RESOURCES oracle.qrc)
if(WIN32)
set(oracle_SOURCES ${oracle_SOURCES} oracle.rc)
endif(WIN32)
if(APPLE)
set(MACOSX_BUNDLE_ICON_FILE appicon.icns)
set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/resources/appicon.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
set(oracle_SOURCES ${oracle_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/resources/appicon.icns)
ENDIF(APPLE)
set(ORACLE_LIBS)
# Qt4 stuff
if(Qt4_FOUND)
SET(QT_USE_QTNETWORK TRUE) SET(QT_USE_QTNETWORK TRUE)
SET(QT_USE_QTXML TRUE) SET(QT_USE_QTXML TRUE)
SET(QT_USE_QTSVG TRUE) SET(QT_USE_QTSVG TRUE)
# Include directories # Include directories
INCLUDE(${QT_USE_FILE}) INCLUDE(${QT_USE_FILE})
include_directories(${QT_INCLUDES})
LIST(APPEND ORACLE_LIBS ${QT_QTMAIN_LIBRARY})
LIST(APPEND ORACLE_LIBS ${QT_LIBRARIES})
# Let cmake chew Qt4's translations and resource files
# Note: header files are MOC-ed automatically by cmake
QT4_ADD_RESOURCES(oracle_RESOURCES_RCC ${oracle_RESOURCES})
endif()
# qt5 stuff
if(Qt5Widgets_FOUND)
include_directories(${Qt5Widgets_INCLUDE_DIRS})
list(APPEND ORACLE_LIBS Widgets)
# QtConcurrent
find_package(Qt5Concurrent)
if(Qt5Concurrent_FOUND)
include_directories(${Qt5Concurrent_INCLUDE_DIRS})
list(APPEND ORACLE_LIBS Concurrent)
endif()
# QtNetwork
find_package(Qt5Network)
if(Qt5Network_FOUND)
include_directories(${Qt5Network_INCLUDE_DIRS})
list(APPEND ORACLE_LIBS Network)
endif()
# QtXml
find_package(Qt5Xml)
if(Qt5Xml_FOUND)
include_directories(${Qt5Xml_INCLUDE_DIRS})
list(APPEND ORACLE_LIBS Xml)
endif()
# QtSvg
find_package(Qt5Svg)
if(Qt5Svg_FOUND)
include_directories(${Qt5Svg_INCLUDE_DIRS})
list(APPEND ORACLE_LIBS Svg)
endif()
# Let cmake chew Qt5's translations and resource files
# Note: header files are MOC-ed automatically by cmake
QT5_ADD_RESOURCES(oracle_RESOURCES_RCC ${oracle_RESOURCES})
# guess plugins and libraries directory
set(QT_PLUGINS_DIR "${Qt5Widgets_DIR}/../../../plugins")
get_target_property(QT_LIBRARY_DIR Qt5::Core LOCATION)
get_filename_component(QT_LIBRARY_DIR ${QT_LIBRARY_DIR} PATH)
endif()
INCLUDE_DIRECTORIES(../cockatrice/src) INCLUDE_DIRECTORIES(../cockatrice/src)
# Build oracle binary and link it # Build oracle binary and link it
ADD_EXECUTABLE(oracle WIN32 MACOSX_BUNDLE ${oracle_SOURCES} ${oracle_MOC_SRCS}) ADD_EXECUTABLE(oracle WIN32 MACOSX_BUNDLE ${oracle_SOURCES} ${oracle_RESOURCES_RCC} ${oracle_MOC_SRCS})
TARGET_LINK_LIBRARIES(oracle ${QT_QTMAIN_LIBRARY} ${QT_LIBRARIES})
if(Qt4_FOUND)
if(MSVC) if(MSVC)
set_target_properties(oracle PROPERTIES LINK_FLAGS "/SUBSYSTEM:WINDOWS") set(QT_USE_QTMAIN true)
endif(MSVC) endif()
TARGET_LINK_LIBRARIES(oracle ${ORACLE_LIBS})
endif()
if(Qt5Widgets_FOUND)
if(MSVC)
TARGET_LINK_LIBRARIES(oracle Qt5::WinMain)
endif()
qt5_use_modules(oracle ${ORACLE_LIBS})
endif()
if(UNIX) if(UNIX)
if(APPLE) if(APPLE)
@ -38,6 +115,8 @@ if(UNIX)
else() else()
# Assume linux # Assume linux
INSTALL(TARGETS oracle RUNTIME DESTINATION bin/) INSTALL(TARGETS oracle RUNTIME DESTINATION bin/)
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/oracle.png DESTINATION ${ICONDIR}/hicolor/48x48/apps)
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/oracle.svg DESTINATION ${ICONDIR}/hicolor/scalable/apps)
endif() endif()
elseif(WIN32) elseif(WIN32)
INSTALL(TARGETS oracle RUNTIME DESTINATION ./) INSTALL(TARGETS oracle RUNTIME DESTINATION ./)
@ -78,3 +157,35 @@ Translations = Resources/translations\")
fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/oracle.app\" \"\${QTPLUGINS}\" \"${QT_LIBRARY_DIR}\") fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/oracle.app\" \"\${QTPLUGINS}\" \"${QT_LIBRARY_DIR}\")
" COMPONENT Runtime) " COMPONENT Runtime)
endif() endif()
IF(WIN32)
# these needs to be relative to CMAKE_INSTALL_PREFIX
set(plugin_dest_dir Plugins)
set(qtconf_dest_dir .)
# note: no codecs in qt5
# note: phonon_backend => mediaservice
# note: needs platform on osx
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime
FILES_MATCHING REGEX "(codecs|iconengines|imageformats|mediaservice|phonon_backend|platforms)/.*d\\.dll")
else()
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime
FILES_MATCHING REGEX "(codecs|iconengines|imageformats|mediaservice|phonon_backend|platforms)/.*[^d]\\.dll")
endif()
install(CODE "
file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf\" \"[Paths]
Plugins = Plugins
Translations = Resources/translations\")
" COMPONENT Runtime)
install(CODE "
file(GLOB_RECURSE QTPLUGINS
\"\${CMAKE_INSTALL_PREFIX}/${plugin_dest_dir}/*.dll\")
set(BU_CHMOD_BUNDLE_ITEMS ON)
include(BundleUtilities)
fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/oracle.exe\" \"\${QTPLUGINS}\" \"${QT_LIBRARY_DIR}\")
" COMPONENT Runtime)
endif()

View file

@ -4,5 +4,5 @@ Version=1.0
Type=Application Type=Application
Name=Cockatrice Oracle downloader Name=Cockatrice Oracle downloader
Exec=oracle Exec=oracle
Icon=cockatrice Icon=oracle
Categories=Game;CardGame; Categories=Game;CardGame;

5
oracle/oracle.qrc Normal file
View file

@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/" >
<file alias="resources/appicon.svg">resources/oracle.svg</file>
</qresource>
</RCC>

1
oracle/oracle.rc Normal file
View file

@ -0,0 +1 @@
ID1_ICON1 ICON DISCARDABLE "resources/appicon.ico"

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

BIN
oracle/resources/oracle.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

228
oracle/resources/oracle.svg Normal file
View file

@ -0,0 +1,228 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="300.0036"
height="300"
id="svg2"
sodipodi:version="0.32"
inkscape:version="0.48.2 r9819"
sodipodi:docname="back.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.0"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96">
<defs
id="defs4">
<linearGradient
id="linearGradient3169">
<stop
style="stop-color:#0000ff;stop-opacity:1;"
offset="0"
id="stop3171" />
<stop
style="stop-color:#000067;stop-opacity:1;"
offset="1"
id="stop3173" />
</linearGradient>
<linearGradient
id="linearGradient4766">
<stop
style="stop-color:#784421;stop-opacity:1;"
offset="0"
id="stop4768" />
<stop
style="stop-color:#3d2210;stop-opacity:0;"
offset="1"
id="stop4770" />
</linearGradient>
<linearGradient
id="linearGradient4758">
<stop
style="stop-color:#a05a2c;stop-opacity:1;"
offset="0"
id="stop4760" />
<stop
style="stop-color:#3d2210;stop-opacity:1;"
offset="1"
id="stop4762" />
</linearGradient>
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective10" />
<inkscape:perspective
id="perspective2484"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 526.18109 : 1"
sodipodi:type="inkscape:persp3d" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4758"
id="linearGradient4764"
x1="466.09601"
y1="485.96021"
x2="715.14801"
y2="485.96021"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4766"
id="linearGradient4772"
x1="496.548"
y1="485.26816"
x2="683.31201"
y2="485.26816"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4766"
id="linearGradient2396"
gradientUnits="userSpaceOnUse"
x1="661.24402"
y1="602.90814"
x2="431.5"
y2="201.5482"
gradientTransform="matrix(0.9650128,0,0,0.9948433,-449.70565,-312.80927)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4758"
id="linearGradient2399"
gradientUnits="userSpaceOnUse"
x1="590.62201"
y1="434.7522"
x2="698.54004"
y2="517.79218"
gradientTransform="matrix(0.9650128,0,0,0.9948433,-449.70565,-312.80927)" />
<filter
inkscape:collect="always"
id="filter3287"
color-interpolation-filters="sRGB">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="0.88403668"
id="feGaussianBlur3289" />
</filter>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4766"
id="linearGradient3057"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.84875138,0,0,0.874988,-395.5345,-274.89225)"
x1="661.24402"
y1="602.90814"
x2="431.5"
y2="201.5482" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4758"
id="linearGradient3059"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.84875138,0,0,0.874988,-395.5345,-274.89225)"
x1="590.62201"
y1="434.7522"
x2="698.54004"
y2="517.79218" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.4911765"
inkscape:cx="164.24505"
inkscape:cy="113.77996"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1280"
inkscape:window-height="725"
inkscape:window-x="0"
inkscape:window-y="25"
fit-margin-left="44.18"
fit-margin-right="44.18"
fit-margin-top="0"
fit-margin-bottom="0"
inkscape:window-maximized="0" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(44.245053,-0.31708717)">
<rect
style="fill:url(#linearGradient3059);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:17.23539734;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="rect2490"
width="194.4082"
height="282.76462"
x="8.5526457"
y="8.9347858"
inkscape:export-xdpi="969.46002"
inkscape:export-ydpi="969.46002" />
<rect
style="fill:url(#linearGradient3057);fill-opacity:1;stroke:#000000;stroke-width:1.72353971;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="rect3302"
width="156.81871"
height="244.01315"
x="26.760056"
y="27.704998" />
<path
sodipodi:type="arc"
style="opacity:0.39208954;fill:#a05a2c;stroke:#000000;stroke-width:2.00029755;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;filter:url(#filter3287)"
id="path3304"
sodipodi:cx="589.58398"
sodipodi:cy="489.76617"
sodipodi:rx="71.968002"
sodipodi:ry="128.71201"
d="m 661.55199,489.76617 c 0,71.08568 -32.22118,128.71201 -71.96801,128.71201 -39.74683,0 -71.968,-57.62633 -71.968,-128.71201 0,-71.08567 32.22117,-128.712 71.968,-128.712 39.74683,0 71.96801,57.62633 71.96801,128.712 z"
transform="matrix(1.0026379,0,0,0.89548037,-485.67617,-289.46994)" />
<flowRoot
xml:space="preserve"
id="flowRoot3021"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><flowRegion
id="flowRegion3023"><rect
id="rect3025"
width="151.92514"
height="235.58012"
x="50.000679"
y="60.188515" /></flowRegion><flowPara
id="flowPara3027"></flowPara></flowRoot> <text
xml:space="preserve"
style="font-size:35.18093872px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Songti SC;-inkscape-font-specification:Songti SC"
x="-14.38486"
y="244.29784"
id="text3029"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3031"
x="-14.38486"
y="244.29784"
style="font-size:390.50842285px;font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#ffffff;font-family:STKaiti;-inkscape-font-specification:STKaiti Bold Italic">o</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.9 KiB

View file

@ -1,5 +1,6 @@
#include <QApplication> #include <QApplication>
#include <QTextCodec> #include <QTextCodec>
#include <QIcon>
#include "oraclewizard.h" #include "oraclewizard.h"
#include "settingscache.h" #include "settingscache.h"
@ -9,7 +10,10 @@ int main(int argc, char *argv[])
{ {
QApplication app(argc, argv); QApplication app(argc, argv);
#if QT_VERSION < 0x050000
// gone in Qt5, all source files _MUST_ be utf8-encoded
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
#endif
QCoreApplication::setOrganizationName("Cockatrice"); QCoreApplication::setOrganizationName("Cockatrice");
QCoreApplication::setOrganizationDomain("cockatrice"); QCoreApplication::setOrganizationDomain("cockatrice");
@ -19,6 +23,10 @@ int main(int argc, char *argv[])
settingsCache = new SettingsCache; settingsCache = new SettingsCache;
OracleWizard wizard; OracleWizard wizard;
QIcon icon(":/resources/appicon.svg");
wizard.setWindowIcon(icon);
wizard.show(); wizard.show();
return app.exec(); return app.exec();

View file

@ -1,5 +1,9 @@
#include "oracleimporter.h" #include "oracleimporter.h"
#if QT_VERSION < 0x050000
#include <QtGui> #include <QtGui>
#else
#include <QtWidgets>
#endif
#include <QDebug> #include <QDebug>
#include "qt-json/json.h" #include "qt-json/json.h"
@ -76,8 +80,8 @@ CardInfo *OracleImporter::addCard(const QString &setName,
cardCost.remove(QChar('}')); cardCost.remove(QChar('}'));
CardInfo *card; CardInfo *card;
if (cardHash.contains(cardName)) { if (cards.contains(cardName)) {
card = cardHash.value(cardName); card = cards.value(cardName);
if (splitCard && !card->getText().contains(fullCardText)) if (splitCard && !card->getText().contains(fullCardText))
card->setText(card->getText() + "\n---\n" + fullCardText); card->setText(card->getText() + "\n---\n" + fullCardText);
} else { } else {
@ -117,7 +121,7 @@ CardInfo *OracleImporter::addCard(const QString &setName,
tableRow = 2; tableRow = 2;
card->setTableRow(tableRow); card->setTableRow(tableRow);
cardHash.insert(cardName, card); cards.insert(cardName, card);
} }
card->setMuId(setName, cardId); card->setMuId(setName, cardId);
@ -137,6 +141,7 @@ int OracleImporter::importTextSpoiler(CardSet *set, const QVariant &data)
QString cardText; QString cardText;
int cardId; int cardId;
int cardLoyalty; int cardLoyalty;
bool cardIsToken = false;
QMap<int, QVariantMap> splitCards; QMap<int, QVariantMap> splitCards;
while (it.hasNext()) { while (it.hasNext()) {
@ -197,6 +202,7 @@ int OracleImporter::importTextSpoiler(CardSet *set, const QVariant &data)
cardText = map.contains("text") ? map.value("text").toString() : QString(""); cardText = map.contains("text") ? map.value("text").toString() : QString("");
cardId = map.contains("multiverseid") ? map.value("multiverseid").toInt() : 0; cardId = map.contains("multiverseid") ? map.value("multiverseid").toInt() : 0;
cardLoyalty = map.contains("loyalty") ? map.value("loyalty").toInt() : 0; cardLoyalty = map.contains("loyalty") ? map.value("loyalty").toInt() : 0;
cardIsToken = map.value("layout") == "token";
// Distinguish Vanguard cards from regular cards of the same name. // Distinguish Vanguard cards from regular cards of the same name.
if (map.value("layout") == "vanguard") { if (map.value("layout") == "vanguard") {
@ -204,7 +210,7 @@ int OracleImporter::importTextSpoiler(CardSet *set, const QVariant &data)
} }
} }
CardInfo *card = addCard(set->getShortName(), cardName, false, cardId, cardCost, cardType, cardPT, cardLoyalty, cardText.split("\n")); CardInfo *card = addCard(set->getShortName(), cardName, cardIsToken, cardId, cardCost, cardType, cardPT, cardLoyalty, cardText.split("\n"));
if (!set->contains(card)) { if (!set->contains(card)) {
card->addToSet(set); card->addToSet(set);
@ -230,8 +236,8 @@ int OracleImporter::startImport()
continue; continue;
CardSet *set = new CardSet(curSet->getShortName(), curSet->getLongName()); CardSet *set = new CardSet(curSet->getShortName(), curSet->getLongName());
if (!setHash.contains(set->getShortName())) if (!sets.contains(set->getShortName()))
setHash.insert(set->getShortName(), set); sets.insert(set->getShortName(), set);
int setCards = importTextSpoiler(set, curSet->getCards()); int setCards = importTextSpoiler(set, curSet->getCards());

View file

@ -1,8 +1,25 @@
#include <QtGui> #include <QtGui>
#include <QGridLayout> #if QT_VERSION < 0x050000
#include <QDesktopServices> #include <QDesktopServices>
#else
#include <QStandardPaths>
#include <QtConcurrent>
#endif
#include <QAbstractButton>
#include <QCheckBox>
#include <QFileDialog>
#include <QGridLayout>
#include <QLabel>
#include <QLineEdit>
#include <QMessageBox>
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
#include <QNetworkReply> #include <QNetworkReply>
#include <QProgressBar>
#include <QPushButton>
#include <QRadioButton>
#include <QScrollArea>
#include <QScrollBar>
#include <QTextEdit>
#include "oraclewizard.h" #include "oraclewizard.h"
#include "oracleimporter.h" #include "oracleimporter.h"
@ -13,7 +30,14 @@ OracleWizard::OracleWizard(QWidget *parent)
: QWizard(parent) : QWizard(parent)
{ {
settings = new QSettings(this); settings = new QSettings(this);
importer = new OracleImporter(QDesktopServices::storageLocation(QDesktopServices::DataLocation), this);
importer = new OracleImporter(
#if QT_VERSION < 0x050000
QDesktopServices::storageLocation(QDesktopServices::DataLocation)
#else
QStandardPaths::standardLocations(QStandardPaths::DataLocation).first()
#endif
, this);
addPage(new IntroPage); addPage(new IntroPage);
addPage(new LoadSetsPage); addPage(new LoadSetsPage);
@ -359,7 +383,7 @@ void SaveSetsPage::initializePage()
QMessageBox::critical(this, tr("Error"), tr("No set has been imported.")); QMessageBox::critical(this, tr("Error"), tr("No set has been imported."));
} }
void SaveSetsPage::updateTotalProgress(int cardsImported, int setIndex, const QString &setName) void SaveSetsPage::updateTotalProgress(int cardsImported, int /* setIndex */, const QString &setName)
{ {
if (setName.isEmpty()) { if (setName.isEmpty()) {
messageLog->append("<b>" + tr("Import finished: %1 cards.").arg(wizard()->importer->getCardList().size()) + "</b>"); messageLog->append("<b>" + tr("Import finished: %1 cards.").arg(wizard()->importer->getCardList().size()) + "</b>");
@ -372,7 +396,12 @@ void SaveSetsPage::updateTotalProgress(int cardsImported, int setIndex, const QS
bool SaveSetsPage::validatePage() bool SaveSetsPage::validatePage()
{ {
bool ok = false; bool ok = false;
const QString dataDir = QDesktopServices::storageLocation(QDesktopServices::DataLocation); const QString dataDir =
#if QT_VERSION < 0x050000
QDesktopServices::storageLocation(QDesktopServices::DataLocation);
#else
QStandardPaths::standardLocations(QStandardPaths::DataLocation).first();
#endif
QDir dir(dataDir); QDir dir(dataDir);
if (!dir.exists()) if (!dir.exists())
dir.mkpath(dataDir); dir.mkpath(dataDir);
@ -389,9 +418,12 @@ bool SaveSetsPage::validatePage()
return false; return false;
} }
if (wizard()->importer->saveToFile(fileName)) if (wizard()->importer->saveToFile(fileName))
{
ok = true; ok = true;
else QMessageBox::information(this, tr("Success"), tr("The card database has been saved successfully."));
} else {
QMessageBox::critical(this, tr("Error"), tr("The file could not be saved to the desired location.")); QMessageBox::critical(this, tr("Error"), tr("The file could not be saved to the desired location."));
}
} while (!ok); } while (!ok);
return true; return true;

View file

@ -4,8 +4,6 @@
PROJECT(servatrice) PROJECT(servatrice)
# cmake module for libgcrypt is included in current directory
SET(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
FIND_PACKAGE(Libgcrypt REQUIRED) FIND_PACKAGE(Libgcrypt REQUIRED)
SET(servatrice_SOURCES SET(servatrice_SOURCES
@ -17,15 +15,50 @@ SET(servatrice_SOURCES
src/server_logger.cpp src/server_logger.cpp
src/serversocketinterface.cpp src/serversocketinterface.cpp
src/isl_interface.cpp src/isl_interface.cpp
${CMAKE_CURRENT_BINARY_DIR}/version_string.cpp ${VERSION_STRING_CPP}
) )
SET(QT_DONTUSE_QTGUI) set(SERVATRICE_LIBS)
# Qt4 stuff
if(Qt4_FOUND)
SET(QT_USE_QTNETWORK TRUE) SET(QT_USE_QTNETWORK TRUE)
SET(QT_USE_QTSQL TRUE) SET(QT_USE_QTSQL TRUE)
# Include directories # Include directories
INCLUDE(${QT_USE_FILE}) INCLUDE(${QT_USE_FILE})
include_directories(${QT_INCLUDES})
LIST(APPEND SERVATRICE_LIBS ${QT_LIBRARIES})
endif()
# qt5 stuff
if(Qt5Widgets_FOUND)
include_directories(${Qt5Widgets_INCLUDE_DIRS})
list(APPEND SERVATRICE_LIBS Widgets)
# QtNetwork
find_package(Qt5Network)
if(Qt5Network_FOUND)
include_directories(${Qt5Network_INCLUDE_DIRS})
list(APPEND SERVATRICE_LIBS Network)
endif()
# QtSql
find_package(Qt5Sql)
if(Qt5Sql_FOUND)
include_directories(${Qt5Sql_INCLUDE_DIRS})
list(APPEND SERVATRICE_LIBS Sql)
endif()
# guess plugins and libraries directory
set(QT_PLUGINS_DIR "${Qt5Widgets_DIR}/../../../plugins")
get_target_property(QT_LIBRARY_DIR Qt5::Core LOCATION)
get_filename_component(QT_LIBRARY_DIR ${QT_LIBRARY_DIR} PATH)
endif()
SET(QT_DONT_USE_QTGUI TRUE)
# Include directories
INCLUDE_DIRECTORIES(../common) INCLUDE_DIRECTORIES(../common)
INCLUDE_DIRECTORIES(${LIBGCRYPT_INCLUDE_DIR}) INCLUDE_DIRECTORIES(${LIBGCRYPT_INCLUDE_DIR})
INCLUDE_DIRECTORIES(${PROTOBUF_INCLUDE_DIR}) INCLUDE_DIRECTORIES(${PROTOBUF_INCLUDE_DIR})
@ -34,13 +67,21 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
# Build servatrice binary and link it # Build servatrice binary and link it
ADD_EXECUTABLE(servatrice MACOSX_BUNDLE ${servatrice_SOURCES} ${servatrice_MOC_SRCS}) ADD_EXECUTABLE(servatrice MACOSX_BUNDLE ${servatrice_SOURCES} ${servatrice_MOC_SRCS})
TARGET_LINK_LIBRARIES(servatrice cockatrice_common ${QT_LIBRARIES} ${LIBGCRYPT_LIBRARY} ${CMAKE_THREAD_LIBS_INIT})
#add_custom_target(versionheader ALL DEPENDS version_header) if(Qt4_FOUND)
add_custom_command( if(MSVC)
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/version_string.h ${CMAKE_CURRENT_BINARY_DIR}/version_string.cpp set(QT_USE_QTMAIN true)
COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR} -P ${CMAKE_CURRENT_SOURCE_DIR}/../common/getversion.cmake endif()
) TARGET_LINK_LIBRARIES(servatrice cockatrice_common ${SERVATRICE_LIBS} ${LIBGCRYPT_LIBRARY} ${CMAKE_THREAD_LIBS_INIT})
endif()
if(Qt5Widgets_FOUND)
if(MSVC)
TARGET_LINK_LIBRARIES(servatrice cockatrice_common ${LIBGCRYPT_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} Qt5::WinMain)
else()
TARGET_LINK_LIBRARIES(servatrice cockatrice_common ${LIBGCRYPT_LIBRARY} ${CMAKE_THREAD_LIBS_INIT})
endif()
qt5_use_modules(servatrice ${SERVATRICE_LIBS})
endif()
# install rules # install rules
if(UNIX) if(UNIX)
@ -85,3 +126,35 @@ Translations = Resources/translations\")
fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/servatrice.app\" \"\${QTPLUGINS}\" \"${QT_LIBRARY_DIR}\") fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/servatrice.app\" \"\${QTPLUGINS}\" \"${QT_LIBRARY_DIR}\")
" COMPONENT Runtime) " COMPONENT Runtime)
endif() endif()
if(WIN32)
# these needs to be relative to CMAKE_INSTALL_PREFIX
set(plugin_dest_dir Plugins)
set(qtconf_dest_dir .)
# note: no codecs in qt5
# note: phonon_backend => mediaservice
# note: needs platform on osx
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime
FILES_MATCHING REGEX "(codecs|iconengines|imageformats|mediaservice|phonon_backend|platforms)/.*d\\.dll")
else()
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime
FILES_MATCHING REGEX "(codecs|iconengines|imageformats|mediaservice|phonon_backend|platforms)/.*[^d]\\.dll")
endif()
install(CODE "
file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf\" \"[Paths]
Plugins = Plugins
Translations = Resources/translations\")
" COMPONENT Runtime)
install(CODE "
file(GLOB_RECURSE QTPLUGINS
\"\${CMAKE_INSTALL_PREFIX}/${plugin_dest_dir}/*.dll\")
set(BU_CHMOD_BUNDLE_ITEMS ON)
include(BundleUtilities)
fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/servatrice.exe\" \"\${QTPLUGINS}\" \"${QT_LIBRARY_DIR}\")
" COMPONENT Runtime)
endif()

View file

@ -37,6 +37,23 @@ RNG_Abstract *rng;
ServerLogger *logger; ServerLogger *logger;
QThread *loggerThread; QThread *loggerThread;
/* Prototypes */
void testRNG();
void testHash();
#if QT_VERSION < 0x050000
void myMessageOutput(QtMsgType type, const char *msg);
void myMessageOutput2(QtMsgType type, const char *msg);
#else
void myMessageOutput(QtMsgType type, const QMessageLogContext &, const QString &msg);
void myMessageOutput2(QtMsgType type, const QMessageLogContext &, const QString &msg);
#endif
#ifdef Q_OS_UNIX
void sigSegvHandler(int sig);
#endif
/* Implementations */
void testRNG() void testRNG()
{ {
const int n = 500000; const int n = 500000;
@ -82,6 +99,7 @@ void testHash()
std::cerr << startTime.secsTo(endTime) << "secs" << std::endl; std::cerr << startTime.secsTo(endTime) << "secs" << std::endl;
} }
#if QT_VERSION < 0x050000
void myMessageOutput(QtMsgType /*type*/, const char *msg) void myMessageOutput(QtMsgType /*type*/, const char *msg)
{ {
logger->logMessage(msg); logger->logMessage(msg);
@ -92,6 +110,18 @@ void myMessageOutput2(QtMsgType /*type*/, const char *msg)
logger->logMessage(msg); logger->logMessage(msg);
std::cerr << msg << std::endl; std::cerr << msg << std::endl;
} }
#else
void myMessageOutput(QtMsgType /*type*/, const QMessageLogContext &, const QString &msg)
{
logger->logMessage(msg);
}
void myMessageOutput2(QtMsgType /*type*/, const QMessageLogContext &, const QString &msg)
{
logger->logMessage(msg);
std::cerr << msg.toStdString() << std::endl;
}
#endif
#ifdef Q_OS_UNIX #ifdef Q_OS_UNIX
void sigSegvHandler(int sig) void sigSegvHandler(int sig)
@ -122,7 +152,10 @@ int main(int argc, char *argv[])
qRegisterMetaType<QList<int> >("QList<int>"); qRegisterMetaType<QList<int> >("QList<int>");
#if QT_VERSION < 0x050000
// gone in Qt5, all source files _MUST_ be utf8-encoded
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
#endif
QSettings *settings = new QSettings("servatrice.ini", QSettings::IniFormat); QSettings *settings = new QSettings("servatrice.ini", QSettings::IniFormat);
@ -134,10 +167,18 @@ int main(int argc, char *argv[])
loggerThread->start(); loggerThread->start();
QMetaObject::invokeMethod(logger, "startLog", Qt::BlockingQueuedConnection, Q_ARG(QString, settings->value("server/logfile").toString())); QMetaObject::invokeMethod(logger, "startLog", Qt::BlockingQueuedConnection, Q_ARG(QString, settings->value("server/logfile").toString()));
#if QT_VERSION < 0x050000
if (logToConsole) if (logToConsole)
qInstallMsgHandler(myMessageOutput); qInstallMsgHandler(myMessageOutput);
else else
qInstallMsgHandler(myMessageOutput2); qInstallMsgHandler(myMessageOutput2);
#else
if (logToConsole)
qInstallMessageHandler(myMessageOutput);
else
qInstallMessageHandler(myMessageOutput2);
#endif
#ifdef Q_OS_UNIX #ifdef Q_OS_UNIX
struct sigaction hup; struct sigaction hup;
hup.sa_handler = ServerLogger::hupSignalHandler; hup.sa_handler = ServerLogger::hupSignalHandler;
@ -174,7 +215,11 @@ int main(int argc, char *argv[])
std::cerr << "-------------------------" << std::endl; std::cerr << "-------------------------" << std::endl;
std::cerr << "Server initialized." << std::endl; std::cerr << "Server initialized." << std::endl;
#if QT_VERSION < 0x050000
qInstallMsgHandler(myMessageOutput); qInstallMsgHandler(myMessageOutput);
#else
qInstallMessageHandler(myMessageOutput);
#endif
retval = app.exec(); retval = app.exec();
std::cerr << "Server quit." << std::endl; std::cerr << "Server quit." << std::endl;

View file

@ -16,14 +16,17 @@ QString PasswordHasher::computeHash(const QString &password, const QString &salt
const int algo = GCRY_MD_SHA512; const int algo = GCRY_MD_SHA512;
const int rounds = 1000; const int rounds = 1000;
QByteArray passwordBuffer = (salt + password).toAscii(); QByteArray passwordBuffer = (salt + password).toUtf8();
int hashLen = gcry_md_get_algo_dlen(algo); int hashLen = gcry_md_get_algo_dlen(algo);
char hash[hashLen], tmp[hashLen]; char *hash = new char[hashLen], *tmp = new char[hashLen];
gcry_md_hash_buffer(algo, hash, passwordBuffer.data(), passwordBuffer.size()); gcry_md_hash_buffer(algo, hash, passwordBuffer.data(), passwordBuffer.size());
for (int i = 1; i < rounds; ++i) { for (int i = 1; i < rounds; ++i) {
memcpy(tmp, hash, hashLen); memcpy(tmp, hash, hashLen);
gcry_md_hash_buffer(algo, hash, tmp, hashLen); gcry_md_hash_buffer(algo, hash, tmp, hashLen);
} }
return salt + QString(QByteArray(hash, hashLen).toBase64()); QString hashedPass = salt + QString(QByteArray(hash, hashLen).toBase64());
delete[] tmp;
delete[] hash;
return hashedPass;
} }

View file

@ -78,7 +78,11 @@ Servatrice_GameServer::~Servatrice_GameServer()
} }
} }
#if QT_VERSION < 0x050000
void Servatrice_GameServer::incomingConnection(int socketDescriptor) void Servatrice_GameServer::incomingConnection(int socketDescriptor)
#else
void Servatrice_GameServer::incomingConnection(qintptr socketDescriptor)
#endif
{ {
// Determine connection pool with smallest client count // Determine connection pool with smallest client count
int minClientCount = -1; int minClientCount = -1;
@ -234,8 +238,16 @@ bool Servatrice::initServer()
if (!certFile.open(QIODevice::ReadOnly)) if (!certFile.open(QIODevice::ReadOnly))
throw QString("Error opening certificate file: %1").arg(certFileName); throw QString("Error opening certificate file: %1").arg(certFileName);
QSslCertificate cert(&certFile); QSslCertificate cert(&certFile);
#if QT_VERSION < 0x050000
if (!cert.isValid()) if (!cert.isValid())
throw(QString("Invalid certificate.")); throw(QString("Invalid certificate."));
#else
const QDateTime currentTime = QDateTime::currentDateTime();
if(currentTime < cert.effectiveDate() ||
currentTime > cert.expiryDate() ||
cert.isBlacklisted())
throw(QString("Invalid certificate."));
#endif
qDebug() << "Loading private key..."; qDebug() << "Loading private key...";
QFile keyFile(keyFileName); QFile keyFile(keyFileName);
if (!keyFile.open(QIODevice::ReadOnly)) if (!keyFile.open(QIODevice::ReadOnly))
@ -319,7 +331,7 @@ void Servatrice::updateServerList()
query.prepare("select id, ssl_cert, hostname, address, game_port, control_port from " + dbPrefix + "_servers order by id asc"); query.prepare("select id, ssl_cert, hostname, address, game_port, control_port from " + dbPrefix + "_servers order by id asc");
servatriceDatabaseInterface->execSqlQuery(query); servatriceDatabaseInterface->execSqlQuery(query);
while (query.next()) { while (query.next()) {
ServerProperties prop(query.value(0).toInt(), QSslCertificate(query.value(1).toString().toAscii()), query.value(2).toString(), QHostAddress(query.value(3).toString()), query.value(4).toInt(), query.value(5).toInt()); ServerProperties prop(query.value(0).toInt(), QSslCertificate(query.value(1).toString().toUtf8()), query.value(2).toString(), QHostAddress(query.value(3).toString()), query.value(4).toInt(), query.value(5).toInt());
serverList.append(prop); serverList.append(prop);
qDebug() << QString("#%1 CERT=%2 NAME=%3 IP=%4:%5 CPORT=%6").arg(prop.id).arg(QString(prop.cert.digest().toHex())).arg(prop.hostname).arg(prop.address.toString()).arg(prop.gamePort).arg(prop.controlPort); qDebug() << QString("#%1 CERT=%2 NAME=%3 IP=%4:%5 CPORT=%6").arg(prop.id).arg(QString(prop.cert.digest().toHex())).arg(prop.hostname).arg(prop.address.toString()).arg(prop.gamePort).arg(prop.controlPort);
} }

View file

@ -52,7 +52,11 @@ public:
Servatrice_GameServer(Servatrice *_server, int _numberPools, const QSqlDatabase &_sqlDatabase, QObject *parent = 0); Servatrice_GameServer(Servatrice *_server, int _numberPools, const QSqlDatabase &_sqlDatabase, QObject *parent = 0);
~Servatrice_GameServer(); ~Servatrice_GameServer();
protected: protected:
#if QT_VERSION < 0x050000
void incomingConnection(int socketDescriptor); void incomingConnection(int socketDescriptor);
#else
void incomingConnection(qintptr socketDescriptor);
#endif
}; };
class Servatrice_IslServer : public QTcpServer { class Servatrice_IslServer : public QTcpServer {

View file

@ -2,7 +2,7 @@
if [[ $TRAVIS_OS_NAME == "osx" ]] ; then if [[ $TRAVIS_OS_NAME == "osx" ]] ; then
brew update brew update
brew install qt cmake protobuf libgcrypt brew install qt protobuf libgcrypt
else else
sudo apt-get update -qq sudo apt-get update -qq
sudo apt-get install -y qtmobility-dev libprotobuf-dev protobuf-compiler libqt4-dev sudo apt-get install -y qtmobility-dev libprotobuf-dev protobuf-compiler libqt4-dev