This commit is contained in:
satsukiyatoshi 2014-09-11 08:11:56 +00:00
commit 45266997f0
530 changed files with 83363 additions and 42300 deletions

5
.gitignore vendored Normal file
View file

@ -0,0 +1,5 @@
tags
build*
*.qm
.directory
mysql.cnf

10
.travis.yml Normal file
View file

@ -0,0 +1,10 @@
language: cpp
os:
- linux
- osx
compiler:
- gcc
- clang
script: mkdir build && cd build && cmake .. -DWITH_SERVER=1 && make
install: ./travis-dependencies.sh
cache: apt

222
CMakeLists.txt Normal file
View file

@ -0,0 +1,222 @@
# Cockatrice's main CMakeLists.txt
#
# This is basically a wrapper to enable/disable the compilation
# of the different projects: servatrice, cockatrice, test
# This file sets all the variables shared between the projects
# like the installation path, compilation flags etc..
cmake_minimum_required(VERSION 2.6)
if(POLICY CMP0020)
cmake_policy(SET CMP0020 OLD)
endif()
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
IF(DEFINED CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "Type of build")
ELSE()
SET(CMAKE_BUILD_TYPE Release CACHE STRING "Type of build")
ENDIF()
# A project name is needed for CPack
PROJECT("${PROJECT_NAME}")
# Set conventional loops
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
if(UNIX)
if(APPLE)
# MacOS X
# Due to the special bundle structure ignore
# the prefix eventually set by the user.
set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/release)
else()
# Linux / BSD
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
#fix package build
if(PREFIX)
set(CMAKE_INSTALL_PREFIX ${PREFIX})
else()
set(CMAKE_INSTALL_PREFIX /usr/local)
endif()
endif()
endif()
elseif(WIN32)
set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/release)
endif()
# Define proper compilation flags
IF(MSVC)
# Visual Studio:
# Maximum optimization
set(CMAKE_CXX_FLAGS_RELEASE "/Ox")
# Generate complete debugging information
#set(CMAKE_CXX_FLAGS_DEBUG "/Zi")
ELSEIF (CMAKE_COMPILER_IS_GNUCXX)
# linux/gcc, bsd/gcc, windows/mingw
include(CheckCXXCompilerFlag)
set(CMAKE_CXX_FLAGS_RELEASE "-s -O2")
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()
# other: osx/llvm, bsd/llvm
set(CMAKE_CXX_FLAGS_RELEASE "-O2")
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0")
ENDIF()
# GNU systems need to define the Mersenne exponent for the RNG to compile w/o warning
IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
ADD_DEFINITIONS("-DSFMT_MEXP=19937")
ENDIF()
# Find Qt and enable the needed features
# Default is Qt5 unless WITH_QT4 option is enabled
option(WITH_QT4 "Force the use of Qt4 libraries" OFF)
OPTION(UPDATE_TRANSLATIONS "Update translations on compile" OFF)
MESSAGE("UPDATE TRANSLATIONS: ${UPDATE_TRANSLATIONS}")
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()
FIND_PACKAGE(Qt5LinguistTools)
IF(UPDATE_TRANSLATIONS)
IF(NOT Qt5_LUPDATE_EXECUTABLE)
MESSAGE(WARNING "Qt's lupdate not found.")
ENDIF()
ENDIF()
IF(NOT Qt5_LRELEASE_EXECUTABLE)
MESSAGE(WARNING "Qt's lrelease not found.")
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}")
IF(UPDATE_TRANSLATIONS)
IF(NOT QT_LUPDATE_EXECUTABLE)
MESSAGE(WARNING "Qt's lupdate not found.")
ENDIF()
ENDIF()
IF(NOT QT_LRELEASE_EXECUTABLE)
MESSAGE(WARNING "Qt's lrelease not found.")
ENDIF()
ELSE()
MESSAGE(FATAL_ERROR "No Qt4 or Qt5 found!")
ENDIF()
ENDIF()
set(CMAKE_AUTOMOC TRUE)
# Find other needed libraries
FIND_PACKAGE(Protobuf REQUIRED)
# Package builder
set(CPACK_PACKAGE_CONTACT "Daenyth+github@gmail.com")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY ${PROJECT_NAME})
set(CPACK_PACKAGE_VENDOR "Cockatrice Development Team")
set(CPACK_PACKAGE_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/README.md")
set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/COPYING")
set(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}")
set(CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}")
set(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}")
if(UNIX)
if(APPLE)
set(CPACK_GENERATOR DragNDrop ${CPACK_GENERATOR})
set(CPACK_GENERATOR "DragNDrop")
set(CPACK_DMG_FORMAT "UDBZ")
set(CPACK_DMG_VOLUME_NAME "${PROJECT_NAME}")
set(CPACK_SYSTEM_NAME "OSX")
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-osx_git-${PROJECT_VERSION}")
set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/cockatrice/resources/appicon.icns")
else()
# linux
set(CPACK_GENERATOR DEB ${CPACK_GENERATOR})
set(CPACK_PACKAGE_INSTALL_DIRECTORY "${PROJECT_NAME}/${PROJECT_VERSION}")
set(CPACK_STRIP_FILES "bin/${PROJECT_NAME}")
set(CPACK_SOURCE_STRIP_FILES "")
endif()
elseif(WIN32)
set(CPACK_GENERATOR NSIS ${CPACK_GENERATOR})
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}_win32_git-${PROJECT_VERSION}")
# Configure file with custom definitions for NSIS.
configure_file(
${CMAKE_MODULE_PATH}/NSIS.definitions.nsh.in
${PROJECT_BINARY_DIR}/NSIS.definitions.nsh
)
endif()
include(CPack)
# Compile servatrice (default off)
option(WITH_SERVER "build servatrice" OFF)
add_subdirectory(common)
if(WITH_SERVER)
add_subdirectory(servatrice)
SET(CPACK_INSTALL_CMAKE_PROJECTS "servatrice;servatrice;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
endif()
# Compile cockatrice (default on)
option(WITH_CLIENT "build cockatrice" ON)
if(WITH_CLIENT)
add_subdirectory(cockatrice)
add_subdirectory(sounds)
add_subdirectory(zonebg)
SET(CPACK_INSTALL_CMAKE_PROJECTS "cockatrice;cockatrice;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
endif()
# Compile oracle (default on)
option(WITH_ORACLE "build oracle" ON)
if(WITH_ORACLE)
add_subdirectory(oracle)
SET(CPACK_INSTALL_CMAKE_PROJECTS "release/oracle.app;oracle;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})
endif()

134
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,134 @@
# 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.
### Memory Management ###
New code should be written using references over pointers and stack allocation
over heap allocation wherever possible.
// Good: uses stack allocation and references
void showCard(const Card &card);
int main()
{
Card card;
showCard(card);
}
// Bad: relies on manual memory management and doesn't give us much
// null-safety.
void showCard(const Card *card);
int main()
{
Card *card = new Card;
showCard(card);
delete card;
}
(Remember to pass by `const` reference wherever possible, to avoid accidentally
mutating objects.)
When pointers can't be avoided, try to use a smart pointer of some sort, such
as `QScopedPointer`, or, less preferably, `QSharedPointer`.

39
servatrice/copying → COPYING Executable file → Normal file
View file

@ -1,12 +1,12 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
@ -15,7 +15,7 @@ software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
@ -55,8 +55,8 @@ patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
@ -225,7 +225,7 @@ impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
@ -255,7 +255,7 @@ make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
@ -303,10 +303,9 @@ the "copyright" line and a pointer to where the full notice is found.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
@ -336,5 +335,5 @@ necessary. Here is a sample; alter the names:
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

53
README.md Normal file
View file

@ -0,0 +1,53 @@
# Cockatrice
Cockatrice is an open-source multiplatform software for playing card games,
such as Magic: The Gathering, over a network. It is fully client-server based
to prevent any kind of cheating, though it supports single-player games without
a network interface as well. Both client and server are written in Qt, supporting both Qt4 and Qt5.
# Get Involved
Chat with the Cockatrice developers on Gitter. Come here to talk about the application, features, or just to hang out. For support regarding specific servers, please contact that server's admin or forum for support rather than asking here.
[![Gitter chat](https://badges.gitter.im/Daenyth/Cockatrice.png)](https://gitter.im/Daenyth/Cockatrice)
# Building
[![Build Status](https://travis-ci.org/Daenyth/Cockatrice.svg?branch=master)](https://travis-ci.org/Daenyth/Cockatrice)
Dependencies:
- [Qt](http://qt-project.org/)
- [protobuf](http://code.google.com/p/protobuf/)
- [CMake](http://www.cmake.org/)
The server requires an additional dependency:
- [libgcrypt](http://www.gnu.org/software/libgcrypt/)
To compile:
mkdir build
cd build
cmake ..
make
make install
The following flags can be passed to `cmake`:
- `-DWITH_SERVER=1` Build the server
- `-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.
- `-DUPDATE_TRANSLATIONS=1` Configure `make` to update the translation .ts files for new strings in the source code. Note: Running `make clean` will remove the .ts files. You should run this when contributing code that changes user messages. Translation file updates should be added in the same commit as the string that was changed.
# Running
`oracle` fetches card data
`cockatrice` is the game client
`servatrice` is the server
# License
Cockatrice is free software, licensed under the GPLv2; see COPYING for details.

57
TODO.md Normal file
View file

@ -0,0 +1,57 @@
#TODOs
This is an unordered list of possible todo items for Cockatrice.
Note that "improve" and "write" always also means: "document and comment"
##Docs
* Improve README.md, it is very minimalistic and technical
##Improve packaging:
* Add SSL libraries to Windows build to support https links in oracle.exe
* Improve nsis file git hash extraction, it only works if the build directory is cleared as version_string.cpp does not seem to get updated by git pull/cmake
* Fix prepareMacRelease.sh to use default installation paths for Qt and protobuf
* Add Mac compile+package howto to the documentation
* Create script/... for creating Linux packages (deb, rpm, ebuild, ...) or at least an official tarball/git tags; package maintainers dislike using git snapshots so much that they rather ignore software without stable tarballs.
* Move everything package related into one directory
##Scripts
* Write example init script for servatrice.
##Webinterface
* Write a default cgi webinterface in some language for the servatrice database. Keep it simple and think about SQL-injections and other security risks - especially if you do it in PHP :-P
##Improve usermanual:
* Improve Layout, Text, Screenshots; nearly everything is still quick n dirty copy and paste.
* Add missing TODOs
* Translate the Documentation
* Include faq.txt and shortcuts.txt in usermanual, then remove them.
* Rename the picture filenames to something more meaningful.
* Create an index, lists of tables/figures/...
## Storage
* Find a better place for sets.xml than doc.
##Create developer documentation:
* Create developer manual
* Add comments to code
* Describe which components exist and how they work and interact
* Describe the *.proto files
* Comment and document servatrice.sql
* Document everything!1!!
* Coding guidelines
##Else
* Update SFMT library (http://www.math.sci.hiroshima-u.ac.jp/~m-mat@math.sci.hiroshima-u.ac.jp/MT/SFMT/) in common/sfmt and adapt common/rng_sfmt.cpp
* Prepare to update to Qt5, as Qt4 will die some day. See http://qt-project.org/wiki/Transition_from_Qt_4.x_to_Qt5 for relevant information.
* Move hardcoded URLs (especially from oracle and cockatrice) into a config file.
* Update the oracle to find all MtG extensions by itself, why the need for sets.xml when the oracle could ask the Gatherer or magiccards.info directly for this information?
* Update the oracle with some intelligence or improve it otherwise to deal with changes from the Gatherer.
* Remove cockatrice/resources/mtgforum.png as it is unused. Find other dead files or dead references to websites and files in the program code and documentation.
* Search git log for useful information/problems/bugs/...

46
cmake/FindLibgcrypt.cmake Normal file
View file

@ -0,0 +1,46 @@
# -*- cmake -*-
# Copied from http://code.google.com/p/emeraldviewer/
# - Find libgcrypt
# Find the libgcrypt includes and library
# This module defines
# LIBGCRYPT_INCLUDE_DIR, where to find gcrypt.h, etc.
# LIBGCRYPT_LIBRARIES, the libraries needed to use libgcrypt.
# LIBGCRYPT_FOUND, If false, do not try to use libgcrypt.
# also defined, but not for general use are
# LIBGCRYPT_LIBRARY, where to find the libgcrypt library.
FIND_PATH(LIBGCRYPT_INCLUDE_DIR gcrypt.h)
SET(LIBGCRYPT_NAMES ${LIBGCRYPT_NAMES} gcrypt)
FIND_LIBRARY(LIBGCRYPT_LIBRARY
NAMES ${LIBGCRYPT_NAMES}
)
IF (LIBGCRYPT_LIBRARY AND LIBGCRYPT_INCLUDE_DIR)
SET(LIBGCRYPT_LIBRARIES ${LIBGCRYPT_LIBRARY})
SET(LIBGCRYPT_FOUND "YES")
ELSE (LIBGCRYPT_LIBRARY AND LIBGCRYPT_INCLUDE_DIR)
SET(LIBGCRYPT_FOUND "NO")
ENDIF (LIBGCRYPT_LIBRARY AND LIBGCRYPT_INCLUDE_DIR)
IF (LIBGCRYPT_FOUND)
IF (NOT LIBGCRYPT_FIND_QUIETLY)
MESSAGE(STATUS "Found libgcrypt: '${LIBGCRYPT_LIBRARIES}' and header in '${LIBGCRYPT_INCLUDE_DIR}'")
ENDIF (NOT LIBGCRYPT_FIND_QUIETLY)
ELSE (LIBGCRYPT_FOUND)
IF (LIBGCRYPT_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find libgcrypt library")
ENDIF (LIBGCRYPT_FIND_REQUIRED)
ENDIF (LIBGCRYPT_FOUND)
# Deprecated declarations.
SET (NATIVE_LIBGCRYPT_INCLUDE_PATH ${LIBGCRYPT_INCLUDE_DIR} )
GET_FILENAME_COMPONENT (NATIVE_LIBGCRYPT_LIB_PATH ${LIBGCRYPT_LIBRARY} PATH)
MARK_AS_ADVANCED(
LIBGCRYPT_LIBRARY
LIBGCRYPT_INCLUDE_DIR
)

158
cmake/FindQtMobility.cmake Normal file
View file

@ -0,0 +1,158 @@
INCLUDE(FindQt4)
set(MOBILITY_CONFIG_MKSPECS_FILE "")
IF(EXISTS "${QT_MKSPECS_DIR}/features/mobilityconfig.prf")
set(MOBILITY_CONFIG_MKSPECS_FILE "${QT_MKSPECS_DIR}/features/mobilityconfig.prf")
ELSEIF(EXISTS "${QT_MKSPECS_DIR}/features/mobility.prf")
set(MOBILITY_CONFIG_MKSPECS_FILE "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/mobilityconfig.prf")
ENDIF()
macro(export_component component)
IF(NOT ${MOBILITY_CONFIG_MKSPECS_FILE} STREQUAL "")
FILE(READ ${MOBILITY_CONFIG_MKSPECS_FILE} MOBILITY_FILE_CONTENTS)
STRING(TOLOWER ${component} _COMPONENT)
IF(${MOBILITY_FILE_CONTENTS} MATCHES "MOBILITY_CONFIG=.*${_COMPONENT}.*")
STRING(TOUPPER ${component} _COMPONENT)
SET(QT_MOBILITY_${_COMPONENT}_FOUND 1)
SET(QT_MOBILITY_${_COMPONENT}_INCLUDE_DIR ${QT_MOBILITY_PARENT_INCLUDE_DIR}/Qt${component})
SET(QT_MOBILITY_${_COMPONENT}_LIBRARY Qt${component})
ENDIF()
ENDIF()
endmacro()
set(VERSION_INFO "")
set(FEATURE_FILE_PREFIX "${QT_MKSPECS_DIR}/features/mobility")
if(DEFINED MOBILITY_VERSION)
if(MOBILITY_VERSION STREQUAL "1.1" AND EXISTS "${FEATURE_FILE_PREFIX}11.prf")
set(MOBILITY_PRF_FILE "${FEATURE_FILE_PREFIX}11.prf")
set(VERSION_INFO "1.1")
elseif(MOBILITY_VERSION STREQUAL "1.2" AND EXISTS "${FEATURE_FILE_PREFIX}12.prf")
set(MOBILITY_PRF_FILE "${FEATURE_FILE_PREFIX}12.prf")
set(VERSION_INFO "1.2")
elseif(MOBILITY_VERSION STREQUAL "default" AND EXISTS "${FEATURE_FILE_PREFIX}.prf")
set(MOBILITY_PRF_FILE "${FEATURE_FILE_PREFIX}.prf")
set(VERSION_INFO "system's default")
else()
message(STATUS "Couldn't find QtMobility version: ${MOBILITY_VERSION}")
endif()
endif()
if(NOT DEFINED MOBILITY_PRF_FILE)
if(EXISTS "${FEATURE_FILE_PREFIX}.prf")
set(MOBILITY_PRF_FILE "${FEATURE_FILE_PREFIX}.prf")
set(VERSION_INFO "system's default")
elseif(EXISTS "${FEATURE_FILE_PREFIX}12.prf")
set(MOBILITY_PRF_FILE "${FEATURE_FILE_PREFIX}12.prf")
set(VERSION_INFO "1.2")
elseif(EXISTS "${FEATURE_FILE_PREFIX}11.prf")
set(MOBILITY_PRF_FILE "${FEATURE_FILE_PREFIX}11.prf")
set(VERSION_INFO "1.1")
else()
message(FATAL_ERROR "Couldn't find any version of QtMobility.")
endif()
endif()
message(STATUS "Using QtMobility version: ${VERSION_INFO}")
IF(DEFINED MOBILITY_PRF_FILE)
FILE(READ ${MOBILITY_PRF_FILE} MOBILITY_FILE_CONTENTS)
STRING(REGEX MATCH "MOBILITY_PREFIX=([^\n]+)" QT_MOBILITY_PREFIX "${MOBILITY_FILE_CONTENTS}")
SET(QT_MOBILITY_PREFIX ${CMAKE_MATCH_1})
STRING(REGEX MATCH "MOBILITY_INCLUDE=([^\n]+)" QT_MOBILITY_INCLUDE_DIR "${MOBILITY_FILE_CONTENTS}")
SET(QT_MOBILITY_INCLUDE_DIR ${CMAKE_MATCH_1})
STRING(REGEX MATCH "MOBILITY_LIB=([^\n]+)" "\\1" QT_MOBILITY_LIBRARY "${MOBILITY_FILE_CONTENTS}")
SET(QT_MOBILITY_LIBRARY_DIR ${CMAKE_MATCH_1})
#VERSION
IF(NOT ${MOBILITY_CONFIG_MKSPECS_FILE} STREQUAL "")
FILE(READ ${MOBILITY_CONFIG_MKSPECS_FILE} MOBILITY_CONFIG_FILE_CONTENTS)
STRING(REGEX MATCH "MOBILITY_VERSION = ([^\n]+)" QT_MOBILITY_VERSION "${MOBILITY_CONFIG_FILE_CONTENTS}")
SET(QT_MOBILITY_VERSION ${CMAKE_MATCH_1})
STRING(REGEX MATCH "MOBILITY_MAJOR_VERSION = ([^\n]+)" QT_MOBILITY_MAJOR_VERSION "${MOBILITY_CONFIG_FILE_CONTENTS}")
SET(QT_MOBILITY_MAJOR_VERSION ${CMAKE_MATCH_1})
STRING(REGEX MATCH "MOBILITY_MINOR_VERSION = ([^\n]+)" QT_MOBILITY_MINOR_VERSION "${MOBILITY_CONFIG_FILE_CONTENTS}")
SET(QT_MOBILITY_MINOR_VERSION ${CMAKE_MATCH_1})
STRING(REGEX MATCH "MOBILITY_PATCH_VERSION = ([^\n]+)" QT_MOBILITY_PATCH_VERSION "${MOBILITY_CONFIG_FILE_CONTENTS}")
SET(QT_MOBILITY_PATCH_VERSION ${CMAKE_MATCH_1})
ELSE()
SET(QT_MOBILITY_VERSION 1.0.0)
SET(QT_MOBILITY_MAJOR_VERSION 1)
SET(QT_MOBILITY_MINOR_VERSION 0)
SET(QT_MOBILITY_PATCH_VERSION 0)
ENDIF()
SET(QT_MOBILITY_PARENT_INCLUDE_DIR ${QT_MOBILITY_INCLUDE_DIR})
SET(QT_MOBILITY_INCLUDE_DIR ${QT_MOBILITY_INCLUDE_DIR}/QtMobility)
IF(QtMobility_FIND_VERSION_EXACT)
IF(QT_MOBILITY_VERSION VERSION_EQUAL QtMobility_FIND_VERSION)
SET(QT_MOBILITY_FOUND TRUE)
ELSE()
SET(QT_MOBILITY_FOUND FALSE)
IF(QT_MOBILITY_VERSION VERSION_LESS QtMobility_FIND_VERSION)
SET(QT_MOBILITY_TOO_OLD TRUE)
ELSE()
SET(QT_MOBILITY_TOO_NEW TRUE)
ENDIF()
ENDIF()
ELSE()
IF(QT_MOBILITY_VERSION VERSION_LESS QtMobility_FIND_VERSION)
SET(QT_MOBILITY_FOUND FALSE)
SET(QT_MOBILITY_TOO_OLD TRUE)
ELSE()
SET(QT_MOBILITY_FOUND TRUE)
ENDIF()
ENDIF()
ELSE()
SET(QT_MOBILITY_FOUND NOTFOUND)
SET(QT_MOBILITY_PREFIX NOTFOUND)
SET(QT_MOBILITY_INCLUDE NOTFOUND)
SET(QT_MOBILITY_LIB NOTFOUND)
ENDIF()
IF(NOT QT_MOBILITY_FOUND)
if(QT_MOBILITY_TOO_OLD)
MESSAGE(FATAL_ERROR "The installed QtMobility version ${QT_MOBILITY_VERSION} it too old, version ${QtMobility_FIND_VERSION} is required.")
ELSEIF(QT_MOBILITY_TOO_NEW)
MESSAGE(FATAL_ERROR "The installed QtMobility version ${QT_MOBILITY_VERSION} it too new, version ${QtMobility_FIND_VERSION} is required.")
ELSE()
MESSAGE(FATAL_ERROR "QtMobility not found.")
ENDIF()
ELSE()
export_component(Bearer)
export_component(Feedback)
export_component(Gallery)
export_component(PublishSubscribe)
export_component(Location)
export_component(Organizer)
export_component(ServiceFramework)
export_component(SystemInfo)
export_component(Contacts)
export_component(Messaging)
export_component(Versit)
export_component(Sensors)
# VersitOrganizer
if(${QT_MOBILITY_CONTACTS_FOUND} AND ${QT_MOBILITY_VERSIT_FOUND})
SET(QT_MOBILITY_VERSITORGANIZER_FOUND 1)
SET(QT_MOBILITY_VERSITORGANIZER_INCLUDE_DIR ${QT_MOBILITY_PARENT_INCLUDE_DIR}/QtVersitOrganizer)
SET(QT_MOBILITY_VERSITORGANIZER_LIBRARY QtVersitOrganizer)
endif()
# MultimediaKit - it's just 'multimedia' in the .prf file.
IF(NOT ${MOBILITY_CONFIG_MKSPECS_FILE} STREQUAL "")
FILE(READ ${MOBILITY_CONFIG_MKSPECS_FILE} MOBILITY_FILE_CONTENTS)
IF(${MOBILITY_FILE_CONTENTS} MATCHES "MOBILITY_CONFIG=.*multimedia.*")
SET(QT_MOBILITY_MULTIMEDIAKIT_FOUND 1)
SET(QT_MOBILITY_MULTIMEDIAKIT_INCLUDE_DIR ${QT_MOBILITY_PARENT_INCLUDE_DIR}/QtMultimediaKit)
SET(QT_MOBILITY_MULTIMEDIAKIT_LIBRARY QtMultimediaKit)
ENDIF()
ENDIF()
ENDIF()

View file

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

View file

@ -1,23 +1,26 @@
!include ..\..\..\NSIS.definitions.nsh
!include "MUI2.nsh"
!include "FileFunc.nsh"
Name "Cockatrice"
OutFile "cockatrice_win32.exe"
SetCompressor lzma
Name "@CPACK_PACKAGE_NAME@"
OutFile "@CPACK_TOPLEVEL_DIRECTORY@/@CPACK_OUTPUT_FILE_NAME@"
SetCompressor /SOLID lzma
InstallDir "$PROGRAMFILES\Cockatrice"
!define INST_DIR "@CPACK_TEMPORARY_DIRECTORY@"
!define MUI_ABORTWARNING
!define MUI_WELCOMEFINISHPAGE_BITMAP "leftimage.bmp"
!define MUI_UNWELCOMEFINISHPAGE_BITMAP "leftimage.bmp"
!define MUI_WELCOMEFINISHPAGE_BITMAP "${NSIS_SOURCE_PATH}\cmake\leftimage.bmp"
!define MUI_UNWELCOMEFINISHPAGE_BITMAP "${NSIS_SOURCE_PATH}\cmake\leftimage.bmp"
!define MUI_HEADERIMAGE
!define MUI_HEADERIMAGE_BITMAP "headerimage.bmp"
!define MUI_HEADERIMAGE_UNBITMAP "headerimage.bmp"
!define MUI_HEADERIMAGE_BITMAP "${NSIS_SOURCE_PATH}\cmake\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_FINISHPAGE_RUN "$INSTDIR/oracle.exe"
!define MUI_FINISHPAGE_RUN_TEXT "Run card database downloader now"
!define MUI_FINISHPAGE_RUN_PARAMETERS "-dlsets"
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE "${NSIS_SOURCE_PATH}\COPYING"
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
@ -30,34 +33,15 @@ InstallDir "$PROGRAMFILES\Cockatrice"
!insertmacro MUI_LANGUAGE "English"
Section "Application" SecApplication
SetShellVarContext all
SetOutPath "$INSTDIR"
File ..\cockatrice\release\cockatrice.exe
File ..\oracle\release\oracle.exe
File data\libgcc_s_dw2-1.dll
File data\mingwm10.dll
File data\QtCore4.dll
File data\QtGui4.dll
File data\QtNetwork4.dll
File data\QtSvg4.dll
File data\QtXml4.dll
File data\QtMultimedia4.dll
File data\QtScript4.dll
SetOutPath "$INSTDIR\zonebg"
File /r ..\zonebg\*.*
SetOutPath "$INSTDIR\plugins"
File /r data\plugins\*.*
@CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS@
@CPACK_NSIS_FULL_INSTALL@
SetOutPath "$INSTDIR\sounds"
File /r ..\sounds\*.*
SetOutPath "$INSTDIR\pics"
SetOutPath "$INSTDIR\decks"
WriteUninstaller "$INSTDIR\uninstall.exe"
${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2
IntFmt $0 "0x%08X" $0
WriteUninstaller "$INSTDIR\uninstall.exe"
${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2
IntFmt $0 "0x%08X" $0
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "DisplayName" "Cockatrice"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "UninstallString" "$\"$INSTDIR\uninstall.exe$\""
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S"
@ -67,50 +51,48 @@ Section "Application" SecApplication
SectionEnd
Section "Update configuration" SecUpdateConfig
WriteRegStr HKCU "Software\Cockatrice\Cockatrice\paths" "carddatabase" "$INSTDIR\cards.xml"
WriteRegStr HKCU "Software\Cockatrice\Cockatrice\paths" "decks" "$INSTDIR\decks"
WriteRegStr HKCU "Software\Cockatrice\Cockatrice\paths" "pics" "$INSTDIR\pics"
WriteRegStr HKCU "Software\Cockatrice\Cockatrice\sound" "path" "$INSTDIR\sounds"
WriteRegStr HKCU "Software\Cockatrice\Cockatrice\paths" "carddatabase" "$APPDATA\Cockatrice\cards.xml"
WriteRegStr HKCU "Software\Cockatrice\Cockatrice\paths" "decks" "$APPDATA\Cockatrice\decks"
WriteRegStr HKCU "Software\Cockatrice\Cockatrice\paths" "pics" "$APPDATA\Cockatrice\pics"
WriteRegStr HKCU "Software\Cockatrice\Cockatrice\sound" "path" "$APPDATA\Cockatrice\sounds"
SectionEnd
Section "Start menu item" SecStartMenu
createDirectory "$SMPROGRAMS\Cockatrice"
createShortCut "$SMPROGRAMS\Cockatrice\Cockatrice.lnk" "$INSTDIR\cockatrice.exe"
createShortCut "$SMPROGRAMS\Cockatrice\Cockatrice.lnk" "$INSTDIR\cockatrice.exe" '--debug-output'
createShortCut "$SMPROGRAMS\Cockatrice\Oracle.lnk" "$INSTDIR\oracle.exe"
createShortCut "$SMPROGRAMS\Cockatrice\Usermanual.lnk" "$INSTDIR\Usermanual.pdf"
SectionEnd
Section Uninstall
RMDir /r "$INSTDIR\zonebg"
RMDir /r "$INSTDIR\plugins"
RMDir /r "$INSTDIR\sounds"
RMDir "$INSTDIR\decks"
RMDir /r "$INSTDIR\pics\downloadedPics"
RMDir "$INSTDIR\pics"
Delete "$INSTDIR\uninstall.exe"
Delete "$INSTDIR\cockatrice.exe"
Delete "$INSTDIR\oracle.exe"
Delete "$INSTDIR\cards.xml"
Delete "$INSTDIR\libgcc_s_dw2-1.dll"
Delete "$INSTDIR\mingwm10.dll"
Delete "$INSTDIR\QtCore4.dll"
Delete "$INSTDIR\QtGui4.dll"
Delete "$INSTDIR\QtNetwork4.dll"
Delete "$INSTDIR\QtSvg4.dll"
Delete "$INSTDIR\QtXml4.dll"
RMDir "$INSTDIR"
SetShellVarContext all
RMDir /r "$INSTDIR\zonebg"
RMDir /r "$INSTDIR\plugins"
RMDir /r "$INSTDIR\sounds"
RMDir /r "$INSTDIR\translations"
Delete "$INSTDIR\uninstall.exe"
Delete "$INSTDIR\cockatrice.exe"
Delete "$INSTDIR\oracle.exe"
Delete "$INSTDIR\Usermanual.pdf"
Delete "$INSTDIR\libprotobuf.lib"
Delete "$INSTDIR\Qt*.dll"
Delete "$INSTDIR\icu*.dll"
Delete "$INSTDIR\qt.conf"
Delete "$INSTDIR\qdebug.txt"
RMDir "$INSTDIR"
RMDir /r "$SMPROGRAMS\Cockatrice"
DeleteRegKey HKCU "Software\Cockatrice"
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice"
RMDir "$SMPROGRAMS\Cockatrice"
DeleteRegKey HKCU "Software\Cockatrice"
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice"
SectionEnd
LangString DESC_SecApplication ${LANG_ENGLISH} "Cockatrice program files"
LangString DESC_SecUpdateConfig ${LANG_ENGLISH} "Update the paths in the application settings according to the installation paths."
LangString DESC_SecStartMenu ${LANG_ENGLISH} "Create start menu items for Cockatrice and Oracle."
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
!insertmacro MUI_DESCRIPTION_TEXT ${SecApplication} $(DESC_SecApplication)
!insertmacro MUI_DESCRIPTION_TEXT ${SecUpdateConfig} $(DESC_SecUpdateConfig)
!insertmacro MUI_DESCRIPTION_TEXT ${SecStartMenu} $(DESC_SecStartMenu)
!insertmacro MUI_DESCRIPTION_TEXT ${SecApplication} $(DESC_SecApplication)
!insertmacro MUI_DESCRIPTION_TEXT ${SecUpdateConfig} $(DESC_SecUpdateConfig)
!insertmacro MUI_DESCRIPTION_TEXT ${SecStartMenu} $(DESC_SecStartMenu)
!insertmacro MUI_FUNCTION_DESCRIPTION_END

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}
)

20
cmake/getversion.cmake Normal file
View file

@ -0,0 +1,20 @@
find_package(Git)
if(GIT_FOUND)
execute_process(
COMMAND ${GIT_EXECUTABLE} describe --long --always
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
RESULT_VARIABLE res_var
OUTPUT_VARIABLE GIT_COM_ID
)
if( NOT ${res_var} EQUAL 0 )
set( GIT_COMMIT_ID "git commit id unknown")
message( WARNING "Git failed (not a repo, or no tags). Build will not contain git revision info." )
endif()
string( REPLACE "\n" "" GIT_COMMIT_ID "${GIT_COM_ID}" )
else()
set( GIT_COMMIT_ID "unknown (git not found!)")
message( WARNING "Git not found. Build will not contain git revision info." )
endif()
set(PROJECT_VERSION_MAJOR ${GIT_COMMIT_ID})
set(PROJECT_VERSION ${GIT_COMMIT_ID} )

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

324
cockatrice/CMakeLists.txt Normal file
View file

@ -0,0 +1,324 @@
# CMakeLists for cockatrice directory
#
# provides the cockatrice binary
PROJECT(cockatrice)
SET(cockatrice_SOURCES
src/abstractcounter.cpp
src/counter_general.cpp
src/dlg_creategame.cpp
src/dlg_filter_games.cpp
src/dlg_connect.cpp
src/dlg_create_token.cpp
src/dlg_edit_tokens.cpp
src/abstractclient.cpp
src/remoteclient.cpp
src/main.cpp
src/window_main.cpp
src/gamesmodel.cpp
src/player.cpp
src/playertarget.cpp
src/cardzone.cpp
src/selectzone.cpp
src/cardlist.cpp
src/abstractcarditem.cpp
src/carditem.cpp
src/tablezone.cpp
src/handzone.cpp
src/handcounter.cpp
src/carddatabase.cpp
src/keysignals.cpp
src/gameview.cpp
src/gameselector.cpp
src/decklistmodel.cpp
src/deck_loader.cpp
src/dlg_load_deck_from_clipboard.cpp
src/dlg_load_remote_deck.cpp
src/cardinfowidget.cpp
src/cardframe.cpp
src/cardinfopicture.cpp
src/cardinfotext.cpp
src/filterbuilder.cpp
src/cardfilter.cpp
src/filtertreemodel.cpp
src/filtertree.cpp
src/messagelogwidget.cpp
src/zoneviewzone.cpp
src/zoneviewwidget.cpp
src/pilezone.cpp
src/stackzone.cpp
src/carddragitem.cpp
src/carddatabasemodel.cpp
src/setsmodel.cpp
src/window_sets.cpp
src/abstractgraphicsitem.cpp
src/abstractcarddragitem.cpp
src/dlg_settings.cpp
src/dlg_cardsearch.cpp
src/phasestoolbar.cpp
src/gamescene.cpp
src/arrowitem.cpp
src/arrowtarget.cpp
src/tab.cpp
src/tab_server.cpp
src/tab_room.cpp
src/tab_message.cpp
src/tab_game.cpp
src/tab_deck_storage.cpp
src/tab_replays.cpp
src/tab_supervisor.cpp
src/tab_admin.cpp
src/tab_userlists.cpp
src/tab_deck_editor.cpp
src/replay_timeline_widget.cpp
src/deckstats_interface.cpp
src/chatview.cpp
src/userlist.cpp
src/userinfobox.cpp
src/user_context_menu.cpp
src/remotedecklist_treewidget.cpp
src/remotereplaylist_treewidget.cpp
src/deckview.cpp
src/playerlistwidget.cpp
src/pixmapgenerator.cpp
src/settingscache.cpp
src/localserver.cpp
src/localserverinterface.cpp
src/localclient.cpp
src/priceupdater.cpp
src/qt-json/json.cpp
src/soundengine.cpp
src/pending_command.cpp
${VERSION_STRING_CPP}
)
if (UNIX AND NOT APPLE)
set_source_files_properties(src/main.cpp PROPERTIES COMPILE_FLAGS -DTRANSLATION_PATH=\\"${CMAKE_INSTALL_PREFIX}/share/cockatrice/translations\\")
endif (UNIX AND NOT APPLE)
set(cockatrice_RESOURCES cockatrice.qrc)
FILE(GLOB cockatrice_TS "${CMAKE_CURRENT_SOURCE_DIR}/translations/*.ts")
IF(UPDATE_TRANSLATIONS)
FILE(GLOB_RECURSE translate_cockatrice_SRCS ${CMAKE_SOURCE_DIR}/cockatrice/src/*.cpp)
FILE(GLOB_RECURSE translate_common_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/common/*.cpp)
SET(translate_SRCS ${translate_cockatrice_SRCS} ${translate_common_SRCS})
ENDIF(UPDATE_TRANSLATIONS)
if(WIN32)
set(cockatrice_SOURCES ${cockatrice_SOURCES} cockatrice.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(cockatrice_SOURCES ${cockatrice_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/resources/appicon.icns)
ENDIF(APPLE)
set(COCKATRICE_LIBS)
# Qt4 stuff
if(Qt4_FOUND)
if (NOT QT_QTMULTIMEDIA_FOUND)
FIND_PACKAGE(QtMobility REQUIRED)
endif()
SET(QT_USE_QTNETWORK TRUE)
SET(QT_USE_QTMULTIMEDIA TRUE)
SET(QT_USE_QTXML TRUE)
SET(QT_USE_QTSVG TRUE)
# Include directories
INCLUDE(${QT_USE_FILE})
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
# Note: header files are MOC-ed automatically by cmake
IF(UPDATE_TRANSLATIONS)
QT4_CREATE_TRANSLATION(cockatrice_QM ${translate_SRCS} ${cockatrice_TS})
ELSE(UPDATE_TRANSLATIONS)
QT4_ADD_TRANSLATION(cockatrice_QM ${cockatrice_TS})
ENDIF(UPDATE_TRANSLATIONS)
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
IF(UPDATE_TRANSLATIONS)
QT5_CREATE_TRANSLATION(cockatrice_QM ${translate_SRCS} ${cockatrice_TS})
ELSE()
QT5_ADD_TRANSLATION(cockatrice_QM ${cockatrice_TS})
ENDIF()
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(../common)
INCLUDE_DIRECTORIES(${PROTOBUF_INCLUDE_DIR})
INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/common)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
# Build cockatrice binary and link it
ADD_EXECUTABLE(cockatrice WIN32 MACOSX_BUNDLE ${cockatrice_SOURCES} ${cockatrice_QM} ${cockatrice_RESOURCES_RCC} ${cockatrice_MOC_SRCS})
if(Qt4_FOUND)
if(MSVC)
set(QT_USE_QTMAIN true)
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(APPLE)
INSTALL(TARGETS cockatrice BUNDLE DESTINATION ./)
INSTALL(FILES ${cockatrice_QM} DESTINATION ./cockatrice.app/Contents/Resources/translations)
else()
# Assume linux
INSTALL(TARGETS cockatrice RUNTIME DESTINATION bin/)
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/cockatrice.png DESTINATION ${ICONDIR}/hicolor/48x48/apps)
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/cockatrice.svg DESTINATION ${ICONDIR}/hicolor/scalable/apps)
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/cockatrice.desktop DESTINATION ${DESKTOPDIR})
INSTALL(FILES ${cockatrice_QM} DESTINATION share/cockatrice/translations)
endif()
elseif(WIN32)
INSTALL(TARGETS cockatrice RUNTIME DESTINATION ./)
INSTALL(FILES ${cockatrice_QM} DESTINATION ./translations)
endif()
if(APPLE)
# these needs to be relative to CMAKE_INSTALL_PREFIX
set(plugin_dest_dir cockatrice.app/Contents/Plugins)
set(qtconf_dest_dir cockatrice.app/Contents/Resources)
# 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)/.*_debug\\.dylib")
else()
install(DIRECTORY "${QT_PLUGINS_DIR}/" DESTINATION ${plugin_dest_dir} COMPONENT Runtime
FILES_MATCHING REGEX "(codecs|iconengines|imageformats|mediaservice|phonon_backend|platforms)/[^_]*\\.dylib")
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}/*.dylib\")
set(BU_CHMOD_BUNDLE_ITEMS ON)
include(BundleUtilities)
fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/cockatrice.app\" \"\${QTPLUGINS}\" \"${QT_LIBRARY_DIR}\")
" COMPONENT Runtime)
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

@ -1,311 +0,0 @@
# Doxyfile 1.5.5-KDevelop
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = clienttest
PROJECT_NUMBER = 0.1
OUTPUT_DIRECTORY =
CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ABBREVIATE_BRIEF = "The $name class" \
"The $name widget" \
"The $name file" \
is \
provides \
specifies \
contains \
represents \
a \
an \
the
ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
FULL_PATH_NAMES = YES
STRIP_FROM_PATH = /home/brukie/
STRIP_FROM_INC_PATH =
SHORT_NAMES = NO
JAVADOC_AUTOBRIEF = NO
QT_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
DETAILS_AT_TOP = NO
INHERIT_DOCS = YES
SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 8
ALIASES =
OPTIMIZE_OUTPUT_FOR_C = NO
OPTIMIZE_OUTPUT_JAVA = NO
OPTIMIZE_FOR_FORTRAN = NO
OPTIMIZE_OUTPUT_VHDL = NO
BUILTIN_STL_SUPPORT = NO
CPP_CLI_SUPPORT = NO
SIP_SUPPORT = NO
IDL_PROPERTY_SUPPORT = YES
DISTRIBUTE_GROUP_DOC = NO
SUBGROUPING = YES
TYPEDEF_HIDES_STRUCT = NO
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL = NO
EXTRACT_PRIVATE = NO
EXTRACT_STATIC = NO
EXTRACT_LOCAL_CLASSES = YES
EXTRACT_LOCAL_METHODS = NO
EXTRACT_ANON_NSPACES = NO
HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = NO
HIDE_FRIEND_COMPOUNDS = NO
HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
CASE_SENSE_NAMES = YES
HIDE_SCOPE_NAMES = NO
SHOW_INCLUDE_FILES = YES
INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
SORT_BRIEF_DOCS = NO
SORT_GROUP_NAMES = NO
SORT_BY_SCOPE_NAME = NO
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
SHOW_DIRECTORIES = NO
SHOW_FILES = YES
SHOW_NAMESPACES = YES
FILE_VERSION_FILTER =
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
QUIET = NO
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = NO
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = /home/brukie/clienttest
INPUT_ENCODING = UTF-8
FILE_PATTERNS = *.c \
*.cc \
*.cxx \
*.cpp \
*.c++ \
*.d \
*.java \
*.ii \
*.ixx \
*.ipp \
*.i++ \
*.inl \
*.h \
*.hh \
*.hxx \
*.hpp \
*.h++ \
*.idl \
*.odl \
*.cs \
*.php \
*.php3 \
*.inc \
*.m \
*.mm \
*.dox \
*.py \
*.f90 \
*.f \
*.vhd \
*.vhdl \
*.C \
*.CC \
*.C++ \
*.II \
*.I++ \
*.H \
*.HH \
*.H++ \
*.CS \
*.PHP \
*.PHP3 \
*.M \
*.MM \
*.PY \
*.F90 \
*.F \
*.VHD \
*.VHDL \
*.C \
*.H \
*.tlh \
*.diff \
*.patch \
*.moc \
*.xpm \
*.dox
RECURSIVE = yes
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS =
EXCLUDE_SYMBOLS =
EXAMPLE_PATH =
EXAMPLE_PATTERNS = *
EXAMPLE_RECURSIVE = NO
IMAGE_PATH =
INPUT_FILTER =
FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
#---------------------------------------------------------------------------
# configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER = NO
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = NO
REFERENCES_RELATION = NO
REFERENCES_LINK_SOURCE = YES
USE_HTAGS = NO
VERBATIM_HEADERS = YES
#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX = NO
COLS_IN_ALPHA_INDEX = 5
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML = YES
HTML_OUTPUT = html
HTML_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
HTML_STYLESHEET =
HTML_ALIGN_MEMBERS = YES
GENERATE_HTMLHELP = NO
GENERATE_DOCSET = NO
DOCSET_FEEDNAME = "Doxygen generated docs"
DOCSET_BUNDLE_ID = org.doxygen.Project
HTML_DYNAMIC_SECTIONS = NO
CHM_FILE =
HHC_LOCATION =
GENERATE_CHI = NO
BINARY_TOC = NO
TOC_EXPAND = NO
DISABLE_INDEX = NO
ENUM_VALUES_PER_LINE = 4
GENERATE_TREEVIEW = NONE
TREEVIEW_WIDTH = 250
FORMULA_FONTSIZE = 10
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
GENERATE_LATEX = YES
LATEX_OUTPUT = latex
LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex
COMPACT_LATEX = NO
PAPER_TYPE = a4wide
EXTRA_PACKAGES =
LATEX_HEADER =
PDF_HYPERLINKS = YES
USE_PDFLATEX = YES
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF = NO
RTF_OUTPUT = rtf
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------
GENERATE_MAN = NO
MAN_OUTPUT = man
MAN_EXTENSION = .3
MAN_LINKS = NO
#---------------------------------------------------------------------------
# configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = yes
XML_OUTPUT = xml
XML_SCHEMA =
XML_DTD =
XML_PROGRAMLISTING = YES
#---------------------------------------------------------------------------
# configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# configuration options related to the Perl module output
#---------------------------------------------------------------------------
GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
PERLMOD_PRETTY = YES
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED =
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration::additions related to external references
#---------------------------------------------------------------------------
TAGFILES =
GENERATE_TAGFILE = clienttest.tag
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = YES
MSCGEN_PATH =
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = NO
DOT_FONTNAME = FreeSans
DOT_FONTPATH =
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES
UML_LOOK = NO
TEMPLATE_RELATIONS = NO
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
CALL_GRAPH = NO
CALLER_GRAPH = NO
GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
DOT_IMAGE_FORMAT = png
DOT_PATH =
DOTFILE_DIRS =
DOT_GRAPH_MAX_NODES = 50
MAX_DOT_GRAPH_DEPTH = 1000
DOT_TRANSPARENT = YES
DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
DOT_CLEANUP = YES
#---------------------------------------------------------------------------
# Configuration::additions related to the search engine
#---------------------------------------------------------------------------
SEARCHENGINE = NO

View file

@ -1,207 +0,0 @@
TEMPLATE = app
TARGET = cockatrice
DEPENDPATH += . src ../common
INCLUDEPATH += . src ../common
MOC_DIR = build
OBJECTS_DIR = build
RESOURCES = cockatrice.qrc
QT += network script svg
unix:!macx {
CONFIG += mobility
MOBILITY = multimedia
} else {
QT += multimedia
}
HEADERS += src/abstractcounter.h \
src/counter_general.h \
src/dlg_creategame.h \
src/dlg_connect.h \
src/dlg_create_token.h \
src/gamesmodel.h \
src/abstractclient.h \
src/remoteclient.h \
src/window_main.h \
src/cardzone.h \
src/selectzone.h \
src/player.h \
src/playertarget.h \
src/cardlist.h \
src/abstractcarditem.h \
src/carditem.h \
src/tablezone.h \
src/handzone.h \
src/handcounter.h \
src/carddatabase.h \
src/gameview.h \
src/gameselector.h \
src/gametypemap.h \
src/decklistmodel.h \
src/dlg_load_deck_from_clipboard.h \
src/dlg_load_remote_deck.h \
src/cardinfowidget.h \
src/messagelogwidget.h \
src/zoneviewzone.h \
src/zoneviewwidget.h \
src/pilezone.h \
src/stackzone.h \
src/carddragitem.h \
src/carddatabasemodel.h \
src/window_deckeditor.h \
src/setsmodel.h \
src/window_sets.h \
src/abstractgraphicsitem.h \
src/abstractcarddragitem.h \
src/dlg_settings.h \
src/dlg_cardsearch.h \
src/phasestoolbar.h \
src/gamescene.h \
src/arrowitem.h \
src/arrowtarget.h \
src/tab.h \
src/tab_server.h \
src/tab_room.h \
src/tab_message.h \
src/tab_game.h \
src/tab_deck_storage.h \
src/tab_supervisor.h \
src/tab_admin.h \
src/tab_userlists.h \
src/chatview.h \
src/userlist.h \
src/userinfobox.h \
src/remotedecklist_treewidget.h \
src/deckview.h \
src/playerlistwidget.h \
src/pixmapgenerator.h \
src/settingscache.h \
src/localserver.h \
src/localserverinterface.h \
src/localclient.h \
src/translation.h \
src/priceupdater.h \
src/soundengine.h \
../common/color.h \
../common/serializable_item.h \
../common/decklist.h \
../common/protocol.h \
../common/protocol_items.h \
../common/protocol_datastructures.h \
../common/rng_abstract.h \
../common/rng_sfmt.h \
../common/server.h \
../common/server_arrow.h \
../common/server_card.h \
../common/server_cardzone.h \
../common/server_room.h \
../common/server_counter.h \
../common/server_game.h \
../common/server_player.h \
../common/server_protocolhandler.h \
../common/server_arrowtarget.h
SOURCES += src/abstractcounter.cpp \
src/counter_general.cpp \
src/dlg_creategame.cpp \
src/dlg_connect.cpp \
src/dlg_create_token.cpp \
src/abstractclient.cpp \
src/remoteclient.cpp \
src/main.cpp \
src/window_main.cpp \
src/gamesmodel.cpp \
src/player.cpp \
src/playertarget.cpp \
src/cardzone.cpp \
src/selectzone.cpp \
src/cardlist.cpp \
src/abstractcarditem.cpp \
src/carditem.cpp \
src/tablezone.cpp \
src/handzone.cpp \
src/handcounter.cpp \
src/carddatabase.cpp \
src/gameview.cpp \
src/gameselector.cpp \
src/decklistmodel.cpp \
src/dlg_load_deck_from_clipboard.cpp \
src/dlg_load_remote_deck.cpp \
src/cardinfowidget.cpp \
src/messagelogwidget.cpp \
src/zoneviewzone.cpp \
src/zoneviewwidget.cpp \
src/pilezone.cpp \
src/stackzone.cpp \
src/carddragitem.cpp \
src/carddatabasemodel.cpp \
src/window_deckeditor.cpp \
src/setsmodel.cpp \
src/window_sets.cpp \
src/abstractgraphicsitem.cpp \
src/abstractcarddragitem.cpp \
src/dlg_settings.cpp \
src/dlg_cardsearch.cpp \
src/phasestoolbar.cpp \
src/gamescene.cpp \
src/arrowitem.cpp \
src/arrowtarget.cpp \
src/tab.cpp \
src/tab_server.cpp \
src/tab_room.cpp \
src/tab_message.cpp \
src/tab_game.cpp \
src/tab_deck_storage.cpp \
src/tab_supervisor.cpp \
src/tab_admin.cpp \
src/tab_userlists.cpp \
src/chatview.cpp \
src/userlist.cpp \
src/userinfobox.cpp \
src/remotedecklist_treewidget.cpp \
src/deckview.cpp \
src/playerlistwidget.cpp \
src/pixmapgenerator.cpp \
src/settingscache.cpp \
src/localserver.cpp \
src/localserverinterface.cpp \
src/localclient.cpp \
src/priceupdater.cpp \
src/soundengine.cpp \
../common/serializable_item.cpp \
../common/decklist.cpp \
../common/protocol.cpp \
../common/protocol_items.cpp \
../common/protocol_datastructures.cpp \
../common/rng_abstract.cpp \
../common/rng_sfmt.cpp \
../common/sfmt/SFMT.c \
../common/server.cpp \
../common/server_card.cpp \
../common/server_cardzone.cpp \
../common/server_room.cpp \
../common/server_game.cpp \
../common/server_player.cpp \
../common/server_protocolhandler.cpp
TRANSLATIONS += \
translations/cockatrice_de.ts \
translations/cockatrice_en.ts \
translations/cockatrice_es.ts \
translations/cockatrice_pt.ts \
translations/cockatrice_pt-br.ts \
translations/cockatrice_fr.ts \
translations/cockatrice_it.ts \
translations/cockatrice_ja.ts \
translations/cockatrice_ru.ts \
translations/cockatrice_cs.ts \
translations/cockatrice_pl.ts \
translations/cockatrice_sk.ts
win32 {
RC_FILE = cockatrice.rc
}
macx {
ICON = resources/appicon.icns
CONFIG += x86 ppc x86_64 release
LIBS += -bind_at_load
}

View file

@ -1,6 +1,7 @@
<RCC>
<qresource prefix="/" >
<file alias="back.svg" >resources/back.svg</file>
<file>resources/lock.svg</file>
<file>resources/icon_delete.svg</file>
<file>resources/icon_tab_changed.svg</file>
<file>resources/icon_config_general.svg</file>
@ -20,13 +21,15 @@
<file>resources/phases/icon_phase_main2.svg</file>
<file>resources/phases/icon_phase_cleanup.svg</file>
<file>resources/phases/icon_phase_nextturn.svg</file>
<file>resources/icon_settings.svg</file>
<file>resources/hand.svg</file>
<file>resources/pencil.svg</file>
<file>resources/icon_search.svg</file>
<file>resources/icon_clearsearch.svg</file>
<file>resources/icon_update.png</file>
<file>resources/icon_view.svg</file>
<file>resources/hr.jpg</file>
<file>resources/appicon.svg</file>
<file alias="resources/appicon.svg">resources/cockatrice.svg</file>
<file>resources/add_to_sideboard.svg</file>
<file>resources/decrement.svg</file>
<file>resources/increment.svg</file>
@ -38,24 +41,19 @@
<file>resources/icon_conceded.svg</file>
<file>resources/icon_player.svg</file>
<file>resources/icon_spectator.svg</file>
<file>resources/replay_start.svg</file>
<file>resources/replay_stop.svg</file>
<file>resources/replay_fastforward.svg</file>
<file>resources/replay_rewind.svg</file>
<file>resources/replay_toend.svg</file>
<file>resources/replay_tostart.svg</file>
<file>resources/replay_pause.svg</file>
<file>resources/genders/male.svg</file>
<file>resources/genders/female.svg</file>
<file>resources/genders/unknown.svg</file>
<file>translations/cockatrice_de.qm</file>
<file>translations/cockatrice_en.qm</file>
<file>translations/cockatrice_es.qm</file>
<file>translations/cockatrice_it.qm</file>
<file>translations/cockatrice_pt.qm</file>
<!-- <file>translations/cockatrice_pt-br.qm</file>
--> <file>translations/cockatrice_fr.qm</file>
<file>translations/cockatrice_ja.qm</file>
<file>translations/cockatrice_ru.qm</file>
<!-- <file>translations/cockatrice_cs.qm</file>
<file>translations/cockatrice_pl.qm</file>
<file>translations/cockatrice_sk.qm</file>
-->
<file>resources/countries/ar.svg</file>
<file>resources/countries/at.svg</file>
<file>resources/countries/au.svg</file>
@ -63,16 +61,20 @@
<file>resources/countries/br.svg</file>
<file>resources/countries/by.svg</file>
<file>resources/countries/ca.svg</file>
<file>resources/countries/cl.svg</file>
<file>resources/countries/cz.svg</file>
<file>resources/countries/ch.svg</file>
<file>resources/countries/cn.svg</file>
<file>resources/countries/de.svg</file>
<file>resources/countries/dk.svg</file>
<file>resources/countries/do.svg</file>
<file>resources/countries/es.svg</file>
<file>resources/countries/fi.svg</file>
<file>resources/countries/fr.svg</file>
<file>resources/countries/ge.svg</file>
<file>resources/countries/gr.svg</file>
<file>resources/countries/gt.svg</file>
<file>resources/countries/hr.svg</file>
<file>resources/countries/hu.svg</file>
<file>resources/countries/ie.svg</file>
<file>resources/countries/il.svg</file>
@ -85,6 +87,7 @@
<file>resources/countries/my.svg</file>
<file>resources/countries/nl.svg</file>
<file>resources/countries/no.svg</file>
<file>resources/countries/nz.svg</file>
<file>resources/countries/pe.svg</file>
<file>resources/countries/ph.svg</file>
<file>resources/countries/pl.svg</file>
@ -99,6 +102,7 @@
<file>resources/countries/ua.svg</file>
<file>resources/countries/uk.svg</file>
<file>resources/countries/us.svg</file>
<file>resources/countries/ve.svg</file>
<file>resources/countries/za.svg</file>
<file>resources/counters/w.svg</file>

View file

@ -1,340 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View file

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Before After
Before After

View file

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="1500"
height="1000"
version="1.1">
<rect width="1500" height="1000" fill="#fff"/>
<rect
width="500"
height="1000"
fill="#0039A6"/>
<rect width="1500" height="500"
y="500" fill="#D52B1E"/><g id="star"
transform="translate(250,250) scale(125)"
fill="#fff">
<g id="cone">
<polygon
id="triangle"
points="0,0 0,1 .5,1" transform="translate(0,-1) rotate(18)"/><use
xlink:href="#triangle"
transform="scale(-1,1)" id="use12"/>
</g>
<use
xlink:href="#cone" transform="rotate(72)" id="use14"/>
<use xlink:href="#cone" transform="rotate(-72)"
id="use16"/>
<use xlink:href="#cone" transform="rotate(144)" id="use18"/>
<use
xlink:href="#cone"
transform="rotate(-144)"
id="use20"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 884 B

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 506 KiB

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="600" viewBox="0 0 300 200">
<defs>
<g id="smallcross"><clipPath id="vclip"><path d="M-109,104 a104,104 0 0,0 0,-208 H109 a104,104 0 0,0 0,208 z"/></clipPath><path id="varm" d="M-55,74 a55,55 0 0,1 110,0 V-74 a55,55 0 0,1 -110,0 z" clip-path="url(#vclip)"/>
<use xlink:href="#varm" transform="rotate(90)"/></g>
</defs>
<rect width="300" height="200" style="fill:#fff"/>
<path d="m 130,0 0,80 -130,0 L 0,120 l 130,0 0,80 40,0 0,-80 130,0 0,-40 -130,0 L 170,0 130,0 z" style="fill:#ff0000" />
<use xlink:href="#smallcross" transform="translate(64.45,39.45)" fill="#f00"/>
<use xlink:href="#smallcross" transform="translate(235.55,160.55)" fill="#f00"/>
<use xlink:href="#smallcross" transform="translate(235.55,39.45)" fill="#f00"/>
<use xlink:href="#smallcross" transform="translate(64.45,160.55)" fill="#f00"/>
</svg>

After

Width:  |  Height:  |  Size: 970 B

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 121 KiB

View file

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.0" xmlns:xlink="http://www.w3.org/1999/xlink" width="960" height="480" viewBox="0 0 240 120">
<title>Flag of New Zealand</title>
<rect fill="#00247d" width="240" height="120"/>
<svg width="120" height="60" viewBox="0 0 12 6">
<clipPath id="t">
<path d="M6,3 h6 v3 z v3 h-6 z h-6 v-3 z v-3 h6 z"/>
</clipPath>
<g stroke="#cf142b" stroke-width="1.2">
<path d="M0,0 L12,6 M12,0 L0,6" stroke="#fff"/>
<path d="M0,0 L12,6 M12,0 L0,6" clip-path="url(#t)" stroke-width="0.8"/>
<path d="M6,0 v6 M0,3 h12" stroke="#fff" stroke-width="2"/>
<path d="M6,0 v6 M0,3 h12"/>
</g>
</svg>
<polygon id="star" points="0,-513674 301930,415571 -488533,-158734 488533,-158734 -301930,415571" transform="scale(0.00000102347231405)"/>
<g transform="translate(180,24)">
<use xlink:href="#star" fill="#fff" transform="scale(18.472135955)"/>
<use xlink:href="#star" fill="#cc142b" transform="scale(12)"/>
</g>
<g transform="translate(180,96)">
<use xlink:href="#star" fill="#fff" transform="scale(20.472135955)"/>
<use xlink:href="#star" fill="#cc142b" transform="scale(14)"/>
</g>
<g transform="rotate(-8,180,48) translate(204,48) rotate(8)">
<use xlink:href="#star" fill="#fff" transform="scale(16.472135955)"/>
<use xlink:href="#star" fill="#cc142b" transform="scale(10)"/>
</g>
<g transform="rotate(-8,180,48) translate(152,48) rotate(8)">
<use xlink:href="#star" fill="#fff" transform="scale(18.472135955)"/>
<use xlink:href="#star" fill="#cc142b" transform="scale(12)"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="600">
<rect width="900" height="210" fill="#f7d117"/>
<rect y="200" width="900" height="210" fill="#0033ab"/>
<rect y="400" width="900" height="200" fill="#cf142b"/>
<g id="s" transform="rotate(-70 450,420) translate(450,240)" fill="#fff">
<g id="c">
<path id="t" d="M 0,-30 V 0 H 15" transform="rotate(18 0,-30)"/>
<use xlink:href="#t" transform="scale(-1,1)"/>
</g>
<use xlink:href="#c" transform="rotate(72)"/>
<use xlink:href="#c" transform="rotate(144)"/>
<use xlink:href="#c" transform="rotate(216)"/>
<use xlink:href="#c" transform="rotate(288)"/>
</g>
<use xlink:href="#s" transform="rotate(20 450,420)"/>
<use xlink:href="#s" transform="rotate(40 450,420)"/>
<use xlink:href="#s" transform="rotate(60 450,420)"/>
<use xlink:href="#s" transform="rotate(80 450,420)"/>
<use xlink:href="#s" transform="rotate(100 450,420)"/>
<use xlink:href="#s" transform="rotate(120 450,420)"/>
<use xlink:href="#s" transform="rotate(140 450,420)"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 12.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
<svg height="133.078" id="Layer_1" inkscape:version="0.42" sodipodi:docbase="F:\openclip\svg da inviare" sodipodi:docname="ruotadentata01.svg" sodipodi:version="0.32" space="preserve" style="overflow:visible;enable-background:new 0 0 132.882 133.078;" version="1.1" viewBox="0 0 132.882 133.078" width="132.882" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg">
<metadata>
<rdf:RDF xmlns:cc="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<cc:Work rdf:about="">
<dc:title>Ruota dentata grigia</dc:title>
<dc:description/>
<dc:subject>
<rdf:Bag>
<rdf:li>unsorted</rdf:li>
</rdf:Bag>
</dc:subject>
<dc:publisher>
<cc:Agent rdf:about="http://www.openclipart.org/">
<dc:title>Open Clip Art Library</dc:title>
</cc:Agent>
</dc:publisher>
<dc:creator>
<cc:Agent>
<dc:title>Architetto Francesco Rollandin</dc:title>
</cc:Agent>
</dc:creator>
<dc:rights>
<cc:Agent>
<dc:title>Architetto Francesco Rollandin</dc:title>
</cc:Agent>
</dc:rights>
<dc:date/>
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<cc:license rdf:resource="http://web.resource.org/cc/PublicDomain"/>
<dc:language>en</dc:language>
</cc:Work>
<cc:License rdf:about="http://web.resource.org/cc/PublicDomain">
<cc:permits rdf:resource="http://web.resource.org/cc/Reproduction"/>
<cc:permits rdf:resource="http://web.resource.org/cc/Distribution"/>
<cc:permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/>
</cc:License>
</rdf:RDF>
</metadata>
<defs id="defs88"/>
<sodipodi:namedview bordercolor="#666666" borderopacity="1.0" id="base" inkscape:current-layer="Layer_1" inkscape:cx="66.441002" inkscape:cy="66.539001" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:window-height="510" inkscape:window-width="787" inkscape:window-x="22" inkscape:window-y="29" inkscape:zoom="2.7051804" pagecolor="#ffffff"/>
<g id="g3">
<radialGradient cx="66.5674" cy="66.3169" gradientUnits="userSpaceOnUse" id="XMLID_5_" r="65.835">
<stop id="stop6" offset="0" style="stop-color:#F8F8F8"/>
<stop id="stop8" offset="1" style="stop-color:#7F7F7F"/>
</radialGradient>
<path d="M125.144,56.349c-3.771,0-7.545,0.045-11.314,0.186c-0.897-4.456-2.482-8.765-4.657-12.756 c-1.116-2.051-3.152-3.094-1.176-4.893c1.351-1.228,2.674-2.482,3.984-3.751c2.54-2.458,7.481-6.071,5.054-10.111 c-2.409-4.008-9.553-12.402-14.613-8.778c-3.259,2.332-6.025,5.805-8.753,8.728c-1.839,1.972-10.072-3.345-13.153-4.284 c-2.29-0.697-4.424-0.006-4.282-2.731c0.099-1.899,0.151-3.802,0.183-5.704c0.046-2.924,0.872-7.681-1.602-9.949 c-2.693-2.47-13.091-2.182-16.192-0.591c-2.902,1.487-2.505,5.529-2.49,8.222c0.011,2.005,0.038,4.011,0.09,6.017 c0.076,2.895,1.006,3.128-2.148,3.853c-4.414,1.016-8.685,2.631-12.661,4.795c-2.706,1.474-2.19,0.776-4.07-1.242 c-1.784-1.917-3.619-3.792-5.471-5.644c-5.942-5.942-11.491,1.433-15.473,6.153c-2.454,2.908-1.425,5.693,1.093,8.212 c1.554,1.552,3.121,3.095,4.703,4.618c3.003,2.895,2.475,2.563,0.439,6.089c-2.106,3.649-3.704,7.589-4.729,11.678 c-0.889,3.547-6.993,1.883-10.459,1.883c-8.083,0-6.575,7.183-6.646,13.097c-0.099,8.381,6.687,7.291,13.357,7.167 c3.019-0.057,3.419-1.006,4.392,2.141c0.679,2.203,1.527,4.354,2.533,6.43c0.999,2.063,2.151,4.05,3.442,5.944 c1.956,2.872-0.17,3.17-2.443,5.329c-2.402,2.283-7.031,5.432-7.215,9.075c-0.154,3.043,3.263,5.365,5.149,7.252 s4.212,5.316,7.26,5.158c3.995-0.206,7.724-5.77,10.257-8.424c1.112-1.164,2.211-2.339,3.291-3.532 c2.416,1.359,4.945,2.514,7.554,3.451c2.667,0.961,5.417,1.691,8.207,2.191c-0.196,2.286-0.295,4.58-0.357,6.873 c-0.093,3.384-1.316,9.583,1.551,12.215c2.403,2.205,7.079,1.192,10.013,1.252c2.549,0.054,6.151,0.456,7.717-2.1 c2.355-3.849,0.94-10.923,0.786-15.24c-0.107-2.931-1.017-3.003,2.18-3.832c3.045-0.79,6.019-1.861,8.864-3.205 c3.503-1.651,3.52-2.752,6.156,0.172c1.791,1.988,3.646,3.92,5.522,5.826c2.889,2.937,6.048,6.091,9.923,2.818 c2.688-2.271,7.617-6.12,8.636-9.61c1.223-4.195-4.952-8.343-7.479-10.767c-2.237-2.148-4.737-2.782-2.863-5.64 c1.603-2.441,2.973-5.036,4.082-7.737c0.839-2.045,1.528-4.15,2.061-6.296c2.411,0.156,4.826,0.234,7.239,0.275 c3.483,0.061,9.652,1.05,10.868-3.456C133.132,67.049,133.389,56.349,125.144,56.349 M65.631,84.78 c-10.628,0-20.194-8.436-20.194-19.325c0-10.889,9.565-19.324,20.194-19.324c10.627,0,20.195,8.435,20.195,19.324 C85.826,76.344,76.259,84.78,65.631,84.78" id="path10" style="fill:url(#XMLID_5_);"/>
<linearGradient gradientTransform="matrix(776.0099 550.007 550.007 -776.0099 -66856.1797 490158.2813)" gradientUnits="userSpaceOnUse" id="XMLID_6_" x1="-241.1641" x2="-239.5807" y1="461.063" y2="461.063">
<stop id="stop13" offset="0" style="stop-color:#FFFFFF"/>
<stop id="stop15" offset="1" style="stop-color:#000000"/>
</linearGradient>
<path d="M66.287,1.853c2.222-0.034,4.739-0.403,6.857,0.365c3.572,1.299,2.531,7.112,2.485,9.961 c-0.025,1.531-1.121,6.786-0.321,8.029c0.813,1.265,9.244,2.709,11.056,3.537c6.891,3.14,5.463,4.316,10.604-1.013 c2.665-2.76,6.867-9.078,11.128-5.777c2.658,2.06,9.874,8.281,8.585,11.593c-1.303,3.346-5.354,6.176-7.92,8.567 c-2.921,2.722-3.367,1.872-1.364,5.159c2.313,3.799,4.064,7.936,5.156,12.25c0.605,2.394-0.082,2.838,2.033,2.802 c4.069-0.069,10.315-1.296,14.178,0.4c3.522,1.548,2.268,9.16,2.229,12.543c-0.096,8.456-12.104,5.645-17.898,5.283 c0.156,0.011-6.795,14.843-7.944,16.447c-0.547,0.763,7.359,7.556,8.381,8.538c4.944,4.761,2.824,7.329-1.513,11.69 c-6.039,6.069-7.887,5.521-13.935-0.731c-2.149-2.219-4.261-4.48-6.246-6.85c-0.521-0.625-6.012,2.776-6.994,3.185 c-1.476,0.614-8.901,1.845-9.535,2.872c-1.004,1.622,0.309,8.013,0.33,9.982c0.096,8.526-0.896,10.481-9.352,10.481 c-2.232,0-4.709,0.411-6.843-0.365c-4-1.453-2.523-9.013-2.438-12.174c0.04-1.498,1.174-6.406,0.431-7.654 c-0.568-0.956-8.392-2.117-9.829-2.669c-0.787-0.303-6.762-3.507-7.049-3.207c-1.525,1.591-3.051,3.181-4.578,4.771 c-1.979,2.064-5.734,7.388-8.932,7.289c-2.806-0.048-9.959-7.553-11.098-10.111c-2.792-6.279,10.07-9.389,10.988-13.959 c0.043-0.212-9.882-17.351-8.595-17.368c-3.593,0.05-7.317,0.41-10.899,0.153c-6.971,0-5.875-6.05-5.83-11.202 c-0.16-7.395,3.619-7.569,9.824-7.444c2.137,0.043,4.276,0.086,6.414,0.128c0.444,0.01,2.333-7.586,2.722-8.551 c1.339-3.326,3.101-6.425,5.146-9.363c0.438-0.629-1.932-2.346-2.398-2.799c-3.363-3.273-10.421-7.872-5.851-12.794 c2.096-2.259,6.541-7.985,9.6-7.985c3.747,0,8.376,6.755,10.672,9.161c3.036,3.181,6.353-1.095,10.14-2.528 c3.945-1.491,9.292-0.362,9.213-4.943c-0.058-3.255-0.396-6.637-0.172-9.884C56.925,1.449,61.375,1.775,66.287,1.853 M69.694,0.223 c-3.688,0-9.813-1.099-12.571,1.586c-3.116,3.085-1.696,10.736-1.63,14.678c0.059,3.6-3.022,2.813-6.17,3.854 c-1.466,0.484-9.462,4.621-10.028,4.025c-2.892-3.043-6.707-8.735-10.962-9.909c-4.166-1.15-7.581,3.806-10.172,6.478 c-5.742,5.518-4.111,8.898,0.979,13.844c1.579,1.533,3.153,3.07,4.737,4.598c-2.533,3.705-4.533,7.768-5.897,12.042 c-1.361,4.257-0.689,4.336-4.944,4.254c-2.461-0.048-5.048-0.305-7.504,0.003c-6.472,0.811-5.456,7.242-5.495,12.174 c-0.062,8.137,3.169,9.687,10.582,9.567c2.239-0.035,4.479-0.076,6.717-0.105c1.116,4.185,2.831,8.202,5.067,11.91 c1.376,2.284,3.278,2.844,1.032,4.902c-1.601,1.465-3.171,2.964-4.72,4.482c-2.292,2.248-5.735,5.252-4.299,8.88 c1.176,2.967,7.935,9.732,10.902,10.908c4.637,1.839,8.851-4.352,11.594-7.205c1.362-1.417,2.717-2.845,4.093-4.25 c3.94,2.146,8.163,3.761,12.527,4.799c3.048,0.725,2.151,0.836,2.018,3.6c-0.091,1.868-0.145,3.736-0.175,5.606 c-0.057,3.465-0.923,9.161,2.917,11.094c3.094,1.558,9.554,0.977,13.091,0.706c8.238-0.634,5.907-11.882,5.715-17.565 c-0.093-2.766-0.968-2.98,2.009-3.78c2.121-0.57,4.206-1.277,6.235-2.116c2.025-0.838,3.997-1.808,5.898-2.898 c1.049,1.227,2.131,2.424,3.23,3.604c4.327,4.647,9.567,12.294,15.874,6.219c2.729-2.633,8.092-6.614,8.172-10.478 c0-4.122-5.587-7.971-8.271-10.553c-2.079-1.999-3.72-2.262-2.068-4.844c2.22-3.474,3.976-7.236,5.207-11.169 c1.902-6.08,17.526,3.361,19.05-6.681c0.542-3.585,1.057-12.592-1.447-15.135c-2.997-3.071-10.253-1.718-14.098-1.652 c-3.809,0.065-3-2.746-4.229-6.091c-1.123-3.054-5.727-8.679-3.43-10.785c6.34-5.817,12.979-10.456,5.196-17.885 c-2.6-2.681-6.001-7.617-10.181-6.482c-3.963,1.077-7.582,6.327-10.301,9.135c-2.466,2.545-4.07,0.031-7.078-1.328 c-2.639-1.192-9.949-2.184-9.821-4.885C77.38,10.375,79.38,0.223,69.694,0.223" id="path17" style="fill:url(#XMLID_6_);"/>
<linearGradient gradientTransform="matrix(0 -214.9991 -214.9991 0 102181.7813 -51529.3086)" gradientUnits="userSpaceOnUse" id="XMLID_7_" x1="-240.6104" x2="-239.069" y1="474.9624" y2="474.9624">
<stop id="stop20" offset="0" style="stop-color:#FFFFFF"/>
<stop id="stop22" offset="1" style="stop-color:#000000"/>
</linearGradient>
<path d="M44.65,65.457c0,26.066,41.962,26.066,41.962,0S44.65,39.39,44.65,65.457 M46.234,65.457 c0-24.025,38.794-24.025,38.794,0S46.234,89.482,46.234,65.457" id="path24" style="fill:url(#XMLID_7_);"/>
<radialGradient cx="65.6309" cy="65.4565" gradientUnits="userSpaceOnUse" id="XMLID_8_" r="34.9484">
<stop id="stop27" offset="0" style="stop-color:#F3F3F3"/>
<stop id="stop29" offset="0.4367" style="stop-color:#F1F1F1"/>
<stop id="stop31" offset="0.594" style="stop-color:#EAEAEA"/>
<stop id="stop33" offset="0.7061" style="stop-color:#DEDEDE"/>
<stop id="stop35" offset="0.7968" style="stop-color:#CDCDCD"/>
<stop id="stop37" offset="0.8745" style="stop-color:#B7B7B7"/>
<stop id="stop39" offset="0.9419" style="stop-color:#9D9D9D"/>
<stop id="stop41" offset="1" style="stop-color:#7F7F7F"/>
</radialGradient>
<path d="M65.631,31.895c-18.581,0-36.284,14.164-36.284,33.56c0,19.402,17.697,33.563,36.284,33.563 c18.586,0,36.283-14.16,36.283-33.563C101.914,46.058,84.212,31.895,65.631,31.895 M65.631,93.859 c-15.729,0-30.71-11.983-30.71-28.404c0-16.42,14.981-28.401,30.71-28.401c15.729,0,30.711,11.979,30.711,28.401 C96.343,81.877,81.362,93.859,65.631,93.859" id="path43" style="fill:url(#XMLID_8_);"/>
<path d="M24.022,47.759c1.389-2.133,2.794-4.254,4.284-6.319C26.071,40.979,24.669,46.14,24.022,47.759 M107.988,19.272c-1.503-5.967-10.331,4.207-11.839,5.825c-0.454,0.487-3.053,4-3.867,3.761c-4.902-3.622-10.62-6.063-16.557-7.381 c-1.076,3.631,8.287,4.644,11.055,6.028c2.139,1.068,4.24,4.338,6.308,2.435c3.427-3.154,6.553-6.757,10.268-9.576 c0.894-0.678,5.101-1.062,4.814,0.303C108.109,20.202,108.049,19.738,107.988,19.272 M40.692,28.996 c3.305-2.111,6.968-3.595,10.795-4.437c2.593-0.569,6.13,0.171,5.04-3.526C53.526,21.596,39.653,24.832,40.692,28.996" id="path45" style="fill:#E8E8E8;"/>
<path d="M73.152,3.636c0,2.344-14.251,2.344-14.251,0S73.152,1.292,73.152,3.636" id="path47" style="fill:#E8E8E8;"/>
<path d="M66.03,128.431c-0.671,0-7.125-0.13-7.125,1.282c0,1.931,14.251,1.933,14.251,0 C73.155,128.301,66.701,128.431,66.03,128.431" id="path49" style="fill:#616161;"/>
<path d="M11.008,72.88c-0.671,0-7.125-0.131-7.125,1.282c0,1.916,14.251,1.913,14.251,0 C18.134,72.75,11.679,72.88,11.008,72.88" id="path51" style="fill:#616161;"/>
<path d="M121.58,72.88c-0.671,0-7.125-0.13-7.125,1.282c0,1.914,14.251,1.914,14.251,0 C128.706,72.75,122.252,72.88,121.58,72.88" id="path53" style="fill:#616161;"/>
<path d="M17.557,106.256c-1.294,0,2.25,4.292,2.338,4.391c1.444,1.629,4.758,5.852,7.256,5.852 c0.034,0.022-1.976-3.976-2.431-4.485C23.285,110.405,20.025,106.251,17.557,106.256" id="path55" style="fill:#616161;"/>
<path d="M94.355,104.674c-0.578,0,7.519,12.467,9.826,10.159C105.671,113.348,96.25,104.674,94.355,104.674" id="path57" style="fill:#616161;"/>
<path d="M26.671,16.666c1.05,1.051-9.306,11.41-10.357,10.358C15.267,25.972,25.62,15.62,26.671,16.666" id="path59" style="fill:#E8E8E8;"/>
<path d="M115.199,27.97c-1.964,0-11.219,9.358-10.206,10.408C106.838,40.223,115.24,27.97,115.199,27.97" id="path61" style="fill:#616161;"/>
<path d="M115.726,106.081c-1.962,0-11.194,9.419-10.205,10.408 C107.472,118.347,115.713,106.081,115.726,106.081" id="path63" style="fill:#616161;"/>
<path d="M37.346,106.081c-1.842,0-4.608,3.414-5.731,4.537c-0.465,0.462-4.612,5.885-4.463,5.881 C29.433,118.323,37.092,106.081,37.346,106.081" id="path65" style="fill:#616161;"/>
<path d="M27.347,115.672c-0.07,0.271-0.138,0.545-0.207,0.816C27.825,117.173,26.743,114.15,27.347,115.672" id="path67" style="fill:#937342;"/>
<path d="M17.435,58.462c0,1.339-12.324-0.53-12.924,1.248c-0.368,1.084-0.489,11.103-1.228,11.024 c-1.711-0.183-0.224-10.043-0.08-11.327C3.558,56.244,17.435,57.476,17.435,58.462" id="path69" style="fill:#E8E8E8;"/>
<path d="M23.478,100.129c-0.358,0.358-4.58,4.749-5.319,4.013c-0.977-0.977,8.35-10.312,9.332-9.33 C28.226,95.548,23.835,99.773,23.478,100.129" id="path71" style="fill:#E8E8E8;"/>
<path d="M128.573,58.66c0,1.19-14.846,1.19-14.846,0S128.573,57.47,128.573,58.66" id="path73" style="fill:#E8E8E8;"/>
<path d="M101.119,74.258c-7.886,24.178-41.95,33.291-60.554,15.481c0,3.725,7.864,8.189,10.455,9.559 c9.041,4.776,19.717,4.771,29.24,1.414C92.282,96.476,99.202,86.506,101.119,74.258 M101.58,72.276 c-0.306,0.617-0.461,1.277-0.461,1.982C100.85,75.084,101.843,72.276,101.58,72.276" id="path75" style="fill:#666666;"/>
<path d="M90.129,90.213c-8.308,6.802-19.974,9.833-30.567,8.335C70.359,100.232,81.753,97.307,90.129,90.213 " id="path77" style="fill:#7F7F7F;"/>
<path d="M35.812,60.705c0-9.224,8.177-18.148,16.011-21.707c8.522-3.872,17.985-3.937,26.437,0.105 c1.084,0.518,13.452,7.704,11.891,9.714c0.415-0.534-7.813-6.607-8.427-6.956c-7.797-4.435-17.463-4.583-25.884-1.935 C48.108,42.359,35.812,51.58,35.812,60.705" id="path79" style="fill:#E8E8E8;"/>
<path d="M29.221,60.477c0-11.246,10.8-22.154,20.227-26.36c10.268-4.583,21.688-4.81,31.842,0.146 c3.762,1.836,7.336,4.222,10.343,7.144c0.161,0.158,3.231,3.874,2.678,3.895c-0.649,0.027-2.156-2.297-2.538-2.712 c-2.223-2.406-4.743-4.534-7.549-6.232c-9.406-5.692-21.297-5.859-31.503-2.277c-8.237,2.891-15.042,8.673-19.335,16.251 C31.957,52.851,29.221,57.912,29.221,60.477" id="path81" style="fill:#E8E8E8;"/>
<path d="M96.321,66.114c0.076-0.002-1.774,6.544-1.93,6.928c-2.031,5.045-5.354,9.536-9.722,12.801 c-14.182,10.598-33.677,7.999-44.948-5.131c15.231,22.079,55.698,13.75,56.604-14.6" id="path83" style="fill:#E8E8E8;"/>
<path d="M87.782,85.129c-0.864,0.83-1.773,1.606-2.729,2.329C86.015,86.743,86.926,85.967,87.782,85.129 M39.057,80.084c-0.394,0,5.06,5.707,5.491,6.023C43.611,85.29,40.002,80.084,39.057,80.084" id="path85" style="fill:#E8E8E8;"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

View file

@ -0,0 +1,29 @@
<?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="122.14841" height="72.055801" id="svg2" sodipodi:version="0.32" inkscape:version="0.46" sodipodi:docname="swerty_eye.svg" inkscape:output_extension="org.inkscape.output.svg.inkscape" version="1.0">
<defs id="defs4">
<linearGradient inkscape:collect="always" id="linearGradient3170">
<stop style="stop-color: rgb(255, 255, 255); stop-opacity: 1;" offset="0" id="stop3172"/>
<stop style="stop-color: rgb(255, 255, 255); stop-opacity: 0;" offset="1" id="stop3174"/>
</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"/>
<linearGradient inkscape:collect="always" xlink:href="#linearGradient3170" id="linearGradient3176" x1="348.1423" y1="241.25623" x2="362.82382" y2="226.27509" gradientUnits="userSpaceOnUse"/>
</defs>
<sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" gridtolerance="10000" guidetolerance="10" objecttolerance="10" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="1.9163562" inkscape:cx="296.89701" inkscape:cy="743.73197" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="false" showguides="true" inkscape:guide-bbox="true" inkscape:window-width="1024" inkscape:window-height="712" inkscape:window-x="-4" inkscape:window-y="-4"/>
<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"/>
</cc:Work>
</rdf:RDF>
</metadata>
<g inkscape:label="Layer 1" inkscape:groupmode="layer" id="layer1" transform="translate(-173.21257,-262.82673)">
<g id="g3178">
<path sodipodi:open="true" transform="matrix(1.7416,0,0,1.7416,-381.027,-111.162)" sodipodi:end="10.935153" sodipodi:start="4.6610829" d="M 352.96016,223.72064 A 11.219209,10.958297 0 1 1 352.85806,223.72622" sodipodi:ry="10.958297" sodipodi:rx="11.219209" sodipodi:cy="234.66452" sodipodi:cx="353.53552" id="path3166" style="opacity:1;fill:#0000de;fill-opacity:1;stroke:none;stroke-width:6.60500002;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" sodipodi:type="arc"/>
<path sodipodi:nodetypes="csssc" id="path3159" d="M 234.78774,331.58001 C 202.9109,331.61255 177.07055,300.49394 176.55697,298.91359 C 175.31289,295.08542 201.94514,266.1618 233.82197,266.12926 C 265.6988,266.09672 292.50969,296.17068 292.05273,298.79568 C 291.87369,299.82419 267.75558,331.00529 236.50341,331.5638" style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:6.60500002;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/>
<path sodipodi:open="true" transform="matrix(1.7416,0,0,1.7416,-380.897,-111.409)" sodipodi:end="10.935153" sodipodi:start="4.6610829" d="M 352.96016,223.72064 A 11.219209,10.958297 0 1 1 352.85806,223.72622" sodipodi:ry="10.958297" sodipodi:rx="11.219209" sodipodi:cy="234.66452" sodipodi:cx="353.53552" id="path3168" style="opacity:1;fill:url(#linearGradient3176);fill-opacity:1;stroke:none;stroke-width:6.60500002;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" sodipodi:type="arc"/>
<path sodipodi:open="true" transform="matrix(1.38447,0,0,1.38447,-254.533,-26.8231)" sodipodi:end="4.6519677" sodipodi:start="0.53396878" d="M 363.19295,240.24179 A 11.219209,10.958297 0 1 1 352.85806,223.72622" sodipodi:ry="10.958297" sodipodi:rx="11.219209" sodipodi:cy="234.66452" sodipodi:cx="353.53552" id="path3162" style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:6.60500002;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" sodipodi:type="arc"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.3 KiB

View file

@ -0,0 +1,173 @@
<?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://web.resource.org/cc/" 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" height="128.00000" id="svg1931" version="1.0" width="128.00000" x="0.00000000" y="0.00000000" sodipodi:version="0.32" inkscape:version="0.44.1" sodipodi:docname="Padlock-gold.svg" sodipodi:docbase="/home/azatoth/img">
<sodipodi:namedview inkscape:window-height="933" inkscape:window-width="1163" inkscape:pageshadow="2" inkscape:pageopacity="0.0" guidetolerance="10.0" gridtolerance="10.0" objecttolerance="10.0" borderopacity="1.0" bordercolor="#666666" pagecolor="#ffffff" id="base" inkscape:zoom="1" inkscape:cx="64.239444" inkscape:cy="87.686082" inkscape:window-x="204" inkscape:window-y="90" inkscape:current-layer="svg1931"/>
<metadata id="metadata3">
<rdf:RDF>
<cc:Work rdf:about="">
<dc:title>padlock</dc:title>
<dc:description/>
<dc:subject>
<rdf:Bag>
<rdf:li>icon</rdf:li>
<rdf:li/>
<rdf:li>lock</rdf:li>
<rdf:li>security</rdf:li>
<rdf:li>secure</rdf:li>
<rdf:li>padlock</rdf:li>
<rdf:li>signs_and_symbols</rdf:li>
</rdf:Bag>
</dc:subject>
<dc:publisher>
<cc:Agent rdf:about="http://www.openclipart.org">
<dc:title>AJ Ashton</dc:title>
</cc:Agent>
</dc:publisher>
<dc:creator>
<cc:Agent>
<dc:title>AJ Ashton</dc:title>
</cc:Agent>
</dc:creator>
<dc:rights>
<cc:Agent>
<dc:title>AJ Ashton</dc:title>
</cc:Agent>
</dc:rights>
<dc:date/>
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<cc:license rdf:resource="http://web.resource.org/cc/PublicDomain"/>
<dc:language>en</dc:language>
</cc:Work>
<cc:License rdf:about="http://web.resource.org/cc/PublicDomain">
<cc:permits rdf:resource="http://web.resource.org/cc/Reproduction"/>
<cc:permits rdf:resource="http://web.resource.org/cc/Distribution"/>
<cc:permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/>
</cc:License>
</rdf:RDF>
</metadata>
<defs id="defs3">
<linearGradient id="linearGradient3057">
<stop id="stop3059" offset="0.00000000" style="stop-color:#282828;stop-opacity:1.0000000;"/>
<stop id="stop3061" offset="1.0000000" style="stop-color:#282828;stop-opacity:0.00000000;"/>
</linearGradient>
<linearGradient id="linearGradient2834">
<stop id="stop2836" offset="0" style="stop-color:#e59a00;stop-opacity:1;"/>
<stop id="stop2838" offset="1" style="stop-color:#faff7d;stop-opacity:0.18367347;"/>
</linearGradient>
<linearGradient id="linearGradient2780">
<stop id="stop2782" offset="0.00000000" style="stop-color:#ffffff;stop-opacity:1.0000000;"/>
<stop id="stop2784" offset="1.0000000" style="stop-color:#ffffff;stop-opacity:0.00000000;"/>
</linearGradient>
<linearGradient id="linearGradient2713">
<stop id="stop2715" offset="0.00000000" style="stop-color:#000000;stop-opacity:1.0000000;"/>
<stop id="stop2717" offset="1.0000000" style="stop-color:#ffffff;stop-opacity:1.0000000;"/>
</linearGradient>
<linearGradient id="linearGradient2701">
<stop id="stop2703" offset="0" style="stop-color:#db9300;stop-opacity:1;"/>
<stop id="stop2770" offset="0.75" style="stop-color:#fac700;stop-opacity:1;"/>
<stop id="stop2705" offset="1" style="stop-color:#fff363;stop-opacity:1;"/>
</linearGradient>
<linearGradient gradientTransform="matrix(2.151801,0.000000,0.000000,1.770850,-5.130350e-2,4.351838)" gradientUnits="userSpaceOnUse" id="linearGradient2707" spreadMethod="reflect" x1="29.613848" x2="44.723549" xlink:href="#linearGradient2701" y1="52.608921" y2="52.608921"/>
<linearGradient gradientTransform="matrix(1.121224,0.000000,0.000000,0.891883,0.000000,4.000000)" gradientUnits="userSpaceOnUse" id="linearGradient2719" spreadMethod="reflect" x1="28.071486" x2="28.071486" xlink:href="#linearGradient2713" y1="40.272228" y2="42.645634"/>
<linearGradient gradientTransform="matrix(2.218790,0.000000,0.000000,1.825981,-5.130350e-2,-1.012826)" gradientUnits="userSpaceOnUse" id="linearGradient2732" spreadMethod="reflect" x1="29.093641" x2="29.093641" xlink:href="#linearGradient2713" y1="46.357063" y2="47.295517"/>
<linearGradient gradientTransform="matrix(2.218790,0.000000,0.000000,1.825981,-5.130350e-2,-1.012826)" gradientUnits="userSpaceOnUse" id="linearGradient2736" spreadMethod="reflect" x1="24.261463" x2="24.605862" xlink:href="#linearGradient2713" y1="44.011002" y2="45.887836"/>
<linearGradient gradientTransform="scale(1.102326,0.907173)" gradientUnits="userSpaceOnUse" id="linearGradient2740" spreadMethod="reflect" x1="17.681860" x2="17.425413" xlink:href="#linearGradient2713" y1="60.433849" y2="62.779984"/>
<radialGradient cx="20.360580" cy="22.546398" fx="20.360580" fy="22.546396" gradientTransform="matrix(0.433337,0.000000,0.000000,1.434961,6.409890,-0.113137)" gradientUnits="userSpaceOnUse" id="radialGradient2788" r="15.156592" xlink:href="#linearGradient2780"/>
<radialGradient cx="20.360580" cy="22.546398" fx="20.360580" fy="22.546396" gradientTransform="matrix(0.500069,0.000000,0.000000,1.675192,5.002970,-5.108149)" gradientUnits="userSpaceOnUse" id="radialGradient2792" r="15.156592" xlink:href="#linearGradient2780"/>
<radialGradient cx="20.360580" cy="22.546398" fx="20.360580" fy="22.546396" gradientTransform="matrix(0.621397,0.000000,0.000000,1.882058,2.388831,-9.409409)" gradientUnits="userSpaceOnUse" id="radialGradient2796" r="15.156592" xlink:href="#linearGradient2780"/>
<radialGradient cx="20.360580" cy="22.546398" fx="20.360580" fy="22.546396" gradientTransform="matrix(0.433337,0.000000,0.000000,1.434961,6.409890,-0.113137)" gradientUnits="userSpaceOnUse" id="radialGradient2811" r="15.156592" xlink:href="#linearGradient2780"/>
<radialGradient cx="20.360580" cy="22.546398" fx="20.360580" fy="22.546396" gradientTransform="matrix(0.500069,0.000000,0.000000,1.675192,5.002970,-5.108149)" gradientUnits="userSpaceOnUse" id="radialGradient2813" r="15.156592" xlink:href="#linearGradient2780"/>
<radialGradient cx="20.360580" cy="22.546398" fx="20.360580" fy="22.546396" gradientTransform="matrix(0.621397,0.000000,0.000000,1.882058,2.388831,-9.409409)" gradientUnits="userSpaceOnUse" id="radialGradient2815" r="15.156592" xlink:href="#linearGradient2780"/>
<radialGradient cx="20.360580" cy="22.546398" fx="20.360580" fy="22.546396" gradientTransform="matrix(0.433337,0.000000,0.000000,1.434961,6.409890,-0.113137)" gradientUnits="userSpaceOnUse" id="radialGradient2817" r="15.156592" xlink:href="#linearGradient2780"/>
<radialGradient cx="20.360580" cy="22.546398" fx="20.360580" fy="22.546396" gradientTransform="matrix(0.500069,0.000000,0.000000,1.675192,5.002970,-5.108149)" gradientUnits="userSpaceOnUse" id="radialGradient2819" r="15.156592" xlink:href="#linearGradient2780"/>
<radialGradient cx="20.360580" cy="22.546398" fx="20.360580" fy="22.546396" gradientTransform="matrix(0.621397,0.000000,0.000000,1.882058,2.388831,-9.409409)" gradientUnits="userSpaceOnUse" id="radialGradient2821" r="15.156592" xlink:href="#linearGradient2780"/>
<radialGradient cx="17.191872" cy="14.639010" fx="17.191872" fy="14.639010" gradientTransform="scale(1.896245,0.527358)" gradientUnits="userSpaceOnUse" id="radialGradient2840" r="3.5649405" xlink:href="#linearGradient2834"/>
<radialGradient cx="21.595108" cy="8.9813547" fx="21.595108" fy="8.9813547" gradientTransform="matrix(2.366562,0,0,1.726511,-0.404355,-1.2826e-2)" gradientUnits="userSpaceOnUse" id="radialGradient2869" r="6.0678878" xlink:href="#linearGradient2834"/>
<radialGradient cx="21.595108" cy="8.9813547" fx="21.595108" fy="8.9813547" gradientTransform="matrix(-2.366562,0,0,1.726511,129.1226,-0.112925)" gradientUnits="userSpaceOnUse" id="radialGradient2873" r="6.0678878" xlink:href="#linearGradient2834"/>
<linearGradient gradientTransform="matrix(2.161083,0,0,1.804543,-5.13035e-2,2.267068)" gradientUnits="userSpaceOnUse" id="linearGradient2895" x1="33.184048" x2="33.184048" xlink:href="#linearGradient2780" y1="24.384579" y2="-13.170087"/>
<radialGradient cx="27.270315" cy="16.278088" fx="27.270315" fy="16.278088" gradientTransform="scale(0.973329,1.027402)" gradientUnits="userSpaceOnUse" id="radialGradient2929" r="13.638700" xlink:href="#linearGradient2780"/>
<linearGradient gradientTransform="matrix(2.210222,0,0,1.964283,-1.515862,-2.171324)" gradientUnits="userSpaceOnUse" id="linearGradient2935" x1="33.184048" x2="33.184048" xlink:href="#linearGradient2780" y1="24.384579" y2="-13.170087"/>
<linearGradient gradientTransform="matrix(1.632005,0,0,2.482509,-5.13035e-2,-1.2826e-2)" gradientUnits="userSpaceOnUse" id="linearGradient2943" x1="38.781849" x2="38.781849" xlink:href="#linearGradient2780" y1="9.5745525" y2="7.5863166"/>
<linearGradient gradientTransform="matrix(1.63752,0,0,2.47415,-5.13035e-2,-1.2826e-2)" gradientUnits="userSpaceOnUse" id="linearGradient2951" x1="38.362892" x2="39.723621" xlink:href="#linearGradient2780" y1="11.170151" y2="6.0918369"/>
<radialGradient cx="21.595108" cy="8.9813547" fx="21.595108" fy="8.9813547" gradientTransform="matrix(3.085042,0,0,2.052895,-15.9848,-3.14928)" gradientUnits="userSpaceOnUse" id="radialGradient2955" r="6.0678878" xlink:href="#linearGradient2834"/>
<radialGradient cx="21.595108" cy="8.9813547" fx="21.595108" fy="8.9813547" gradientTransform="matrix(-2.846279,0,0,2.087943,139.5254,-3.586178)" gradientUnits="userSpaceOnUse" id="radialGradient2959" r="6.0678878" xlink:href="#linearGradient2834"/>
<radialGradient cx="8.0178375" cy="231.98276" fx="8.0178375" fy="231.98276" gradientTransform="scale(3.741657,0.267261)" gradientUnits="userSpaceOnUse" id="radialGradient3063" r="7.4833150" xlink:href="#linearGradient3057"/>
<radialGradient cx="8.0178375" cy="231.98276" fx="8.0178375" fy="231.98276" gradientTransform="scale(3.741657,0.267261)" gradientUnits="userSpaceOnUse" id="radialGradient3069" r="7.4833150" xlink:href="#linearGradient3057"/>
<radialGradient cx="8.0178375" cy="231.98276" fx="8.0178375" fy="231.98276" gradientTransform="scale(3.741657,0.267261)" gradientUnits="userSpaceOnUse" id="radialGradient3071" r="7.4833150" xlink:href="#linearGradient3057"/>
<linearGradient gradientTransform="matrix(2.136116,0.000000,0.000000,1.825981,2.348697,-1.012826)" gradientUnits="userSpaceOnUse" id="linearGradient3080" spreadMethod="pad" x1="26.974447" x2="26.974447" xlink:href="#linearGradient2780" y1="68.680031" y2="44.981197"/>
<linearGradient gradientTransform="matrix(1.632005,0,0,2.436073,-5.13035e-2,2.009678)" gradientUnits="userSpaceOnUse" id="linearGradient3084" x1="35.995708" x2="35.995708" xlink:href="#linearGradient2780" y1="1.6246380" y2="11.710631"/>
<linearGradient gradientTransform="matrix(2.218790,0.000000,0.000000,1.825981,-5.130350e-2,-1.012826)" gradientUnits="userSpaceOnUse" id="linearGradient3086" spreadMethod="reflect" x1="17.681860" x2="17.425413" xlink:href="#linearGradient2713" y1="60.433849" y2="62.779984"/>
<linearGradient inkscape:collect="always" xlink:href="#linearGradient2701" id="linearGradient3106" gradientUnits="userSpaceOnUse" gradientTransform="matrix(2.151801,0,0,1.77085,-5.13035e-2,4.351838)" spreadMethod="reflect" x1="29.613848" y1="52.608921" x2="44.723549" y2="52.608921"/>
<linearGradient inkscape:collect="always" xlink:href="#linearGradient2713" id="linearGradient3108" gradientUnits="userSpaceOnUse" gradientTransform="matrix(2.21879,0,0,1.825981,-5.13035e-2,-1.012826)" spreadMethod="reflect" x1="29.093641" y1="46.357063" x2="29.093641" y2="47.295517"/>
<linearGradient inkscape:collect="always" xlink:href="#linearGradient2713" id="linearGradient3110" gradientUnits="userSpaceOnUse" gradientTransform="matrix(2.21879,0,0,1.825981,-5.13035e-2,-1.012826)" spreadMethod="reflect" x1="24.261463" y1="44.011002" x2="24.605862" y2="45.887836"/>
<linearGradient inkscape:collect="always" xlink:href="#linearGradient2713" id="linearGradient3112" gradientUnits="userSpaceOnUse" gradientTransform="matrix(2.21879,0,0,1.825981,-5.13035e-2,-1.012826)" spreadMethod="reflect" x1="17.681860" y1="60.433849" x2="17.425413" y2="62.779984"/>
<radialGradient inkscape:collect="always" xlink:href="#linearGradient2780" id="radialGradient3114" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.433337,0,0,1.434961,6.40989,-0.113137)" cx="20.360580" cy="22.546398" fx="20.360580" fy="22.546396" r="15.156592"/>
<radialGradient inkscape:collect="always" xlink:href="#linearGradient2780" id="radialGradient3116" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.500069,0,0,1.675192,5.00297,-5.108149)" cx="20.360580" cy="22.546398" fx="20.360580" fy="22.546396" r="15.156592"/>
<radialGradient inkscape:collect="always" xlink:href="#linearGradient2780" id="radialGradient3118" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.621397,0,0,1.882058,2.388831,-9.409409)" cx="20.360580" cy="22.546398" fx="20.360580" fy="22.546396" r="15.156592"/>
<radialGradient inkscape:collect="always" xlink:href="#linearGradient2780" id="radialGradient3120" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.433337,0,0,1.434961,6.40989,-0.113137)" cx="20.360580" cy="22.546398" fx="20.360580" fy="22.546396" r="15.156592"/>
<radialGradient inkscape:collect="always" xlink:href="#linearGradient2780" id="radialGradient3122" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.500069,0,0,1.675192,5.00297,-5.108149)" cx="20.360580" cy="22.546398" fx="20.360580" fy="22.546396" r="15.156592"/>
<radialGradient inkscape:collect="always" xlink:href="#linearGradient2780" id="radialGradient3124" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.621397,0,0,1.882058,2.388831,-9.409409)" cx="20.360580" cy="22.546398" fx="20.360580" fy="22.546396" r="15.156592"/>
<linearGradient inkscape:collect="always" xlink:href="#linearGradient2780" id="linearGradient3126" gradientUnits="userSpaceOnUse" gradientTransform="matrix(2.136116,0,0,1.825981,2.348697,-1.012826)" spreadMethod="pad" x1="26.974447" y1="68.680031" x2="26.974447" y2="44.981197"/>
<linearGradient inkscape:collect="always" xlink:href="#linearGradient2780" id="linearGradient3130" gradientUnits="userSpaceOnUse" gradientTransform="matrix(2.136116,0,0,1.825981,2.348697,-1.012826)" spreadMethod="pad" x1="26.974447" y1="68.680031" x2="26.974447" y2="44.981197"/>
<linearGradient inkscape:collect="always" xlink:href="#linearGradient2713" id="linearGradient3142" gradientUnits="userSpaceOnUse" gradientTransform="matrix(2.21879,0,0,1.825981,-5.13035e-2,-1.012826)" spreadMethod="reflect" x1="17.681860" y1="60.433849" x2="17.425413" y2="62.779984"/>
<linearGradient inkscape:collect="always" xlink:href="#linearGradient2713" id="linearGradient3145" gradientUnits="userSpaceOnUse" gradientTransform="matrix(2.21879,0,0,1.825981,-5.13035e-2,-1.012826)" spreadMethod="reflect" x1="24.261463" y1="44.011002" x2="24.605862" y2="45.887836"/>
<linearGradient inkscape:collect="always" xlink:href="#linearGradient2713" id="linearGradient3148" gradientUnits="userSpaceOnUse" gradientTransform="matrix(2.21879,0,0,1.825981,-5.13035e-2,-1.012826)" spreadMethod="reflect" x1="29.093641" y1="46.357063" x2="29.093641" y2="47.295517"/>
<linearGradient inkscape:collect="always" xlink:href="#linearGradient2701" id="linearGradient3151" gradientUnits="userSpaceOnUse" gradientTransform="matrix(2.151801,0,0,1.77085,-5.13035e-2,4.351838)" spreadMethod="reflect" x1="29.613848" y1="52.608921" x2="44.723549" y2="52.608921"/>
<radialGradient inkscape:collect="always" xlink:href="#linearGradient3057" id="radialGradient4946" gradientUnits="userSpaceOnUse" gradientTransform="matrix(7.531304,0,0,0.53795,3.974348,-2.025652)" cx="8.0178375" cy="231.98276" fx="8.0178375" fy="231.98276" r="7.4833150"/>
<radialGradient inkscape:collect="always" xlink:href="#linearGradient3057" id="radialGradient4949" gradientUnits="userSpaceOnUse" gradientTransform="matrix(7.531304,0,0,0.672437,3.974348,-34.23087)" cx="8.0178375" cy="231.98276" fx="8.0178375" fy="231.98276" r="7.4833150"/>
<radialGradient inkscape:collect="always" xlink:href="#linearGradient3057" id="radialGradient4952" gradientUnits="userSpaceOnUse" gradientTransform="matrix(7.531304,0,0,0.53795,3.974348,-1.2826e-2)" cx="8.0178375" cy="231.98276" fx="8.0178375" fy="231.98276" r="7.4833150"/>
<radialGradient inkscape:collect="always" xlink:href="#linearGradient2834" id="radialGradient4955" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-2.846279,0,0,2.087943,139.5254,-3.586178)" cx="21.595108" cy="8.9813547" fx="21.595108" fy="8.9813547" r="6.0678878"/>
<radialGradient inkscape:collect="always" xlink:href="#linearGradient2834" id="radialGradient4958" gradientUnits="userSpaceOnUse" gradientTransform="matrix(3.085042,0,0,2.052895,-15.9848,-3.14928)" cx="21.595108" cy="8.9813547" fx="21.595108" fy="8.9813547" r="6.0678878"/>
<linearGradient inkscape:collect="always" xlink:href="#linearGradient2780" id="linearGradient4965" gradientUnits="userSpaceOnUse" gradientTransform="matrix(2.161083,0,0,1.804543,-5.13035e-2,2.267068)" x1="33.184048" y1="24.384579" x2="33.184048" y2="-13.170087"/>
<linearGradient inkscape:collect="always" xlink:href="#linearGradient2780" id="linearGradient4968" gradientUnits="userSpaceOnUse" gradientTransform="matrix(2.210222,0,0,1.964283,-1.515862,-2.171324)" x1="33.184048" y1="24.384579" x2="33.184048" y2="-13.170087"/>
<linearGradient inkscape:collect="always" xlink:href="#linearGradient2780" id="linearGradient4971" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1.632005,0,0,2.482509,-5.13035e-2,-1.2826e-2)" x1="38.781849" y1="9.5745525" x2="38.781849" y2="7.5863166"/>
<radialGradient inkscape:collect="always" xlink:href="#linearGradient2834" id="radialGradient4974" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-2.366562,0,0,1.726511,129.1226,-0.112925)" cx="21.595108" cy="8.9813547" fx="21.595108" fy="8.9813547" r="6.0678878"/>
<radialGradient inkscape:collect="always" xlink:href="#linearGradient2834" id="radialGradient4977" gradientUnits="userSpaceOnUse" gradientTransform="matrix(2.366562,0,0,1.726511,-0.404355,-1.2826e-2)" cx="21.595108" cy="8.9813547" fx="21.595108" fy="8.9813547" r="6.0678878"/>
<linearGradient inkscape:collect="always" xlink:href="#linearGradient2780" id="linearGradient4980" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1.63752,0,0,2.47415,-5.13035e-2,-1.2826e-2)" x1="38.362892" y1="11.170151" x2="39.723621" y2="6.0918369"/>
<linearGradient inkscape:collect="always" xlink:href="#linearGradient2780" id="linearGradient4983" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1.632005,0,0,2.436073,-5.13035e-2,2.009678)" x1="35.995708" y1="1.6246380" x2="35.995708" y2="11.710631"/>
<linearGradient inkscape:collect="always" xlink:href="#linearGradient2834" id="linearGradient6992" x1="-229" y1="36.5" x2="-134" y2="36.5" gradientUnits="userSpaceOnUse"/>
<radialGradient inkscape:collect="always" xlink:href="#linearGradient2834" id="radialGradient7002" cx="-118.5" cy="-41" fx="-118.5" fy="-41" r="30.5" gradientTransform="matrix(1,0,0,0.655738,0,-14.11475)" gradientUnits="userSpaceOnUse"/>
<radialGradient inkscape:collect="always" xlink:href="#linearGradient2834" id="radialGradient7014" cx="-35" cy="-163" fx="-35" fy="-163" r="59" gradientTransform="matrix(1,0,0,0.576271,0,-69.0678)" gradientUnits="userSpaceOnUse"/>
</defs>
<g id="g5908">
<g id="g5889">
<path style="fill:#282828;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.625;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1" id="rect2723" d="M 64.359126,2 C 44.287226,2 28.128259,18.158966 28.128259,38.230867 L 28.128259,78.487385 L 38.192389,78.487385 L 38.192389,38.230867 C 38.192389,23.734494 49.862754,12.06413 64.359126,12.06413 C 78.855498,12.06413 90.525863,23.734494 90.525863,38.230867 L 90.525863,78.487385 L 100.58999,78.487385 L 100.58999,38.230867 C 100.58999,18.158966 84.431026,2 64.359126,2 z "/>
<path style="opacity:0.65;fill:url(#linearGradient4983);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.625;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1" id="path3082" d="M 64.359126,4.6292539 C 45.402331,4.6292539 30.141085,20.935813 30.141085,39.538022 L 30.141085,77.066368 C 30.141085,91.15557 38.917475,103.11605 51.401559,108.11367 C 42.456647,104.04079 36.179563,95.313819 36.179563,84.967072 L 36.179563,37.562846 C 36.179563,23.337627 47.849928,10.941742 62.3463,10.941742 L 66.371952,10.941742 C 80.868324,10.941742 92.538689,23.337627 92.538689,37.562846 L 92.538689,84.967072 C 92.538689,95.313819 86.261604,104.04079 77.316693,108.11367 C 89.800776,103.11605 98.577166,91.15557 98.577166,77.066368 L 98.577166,39.538022 C 98.577166,20.935813 83.31592,4.6292539 64.359126,4.6292539 z "/>
<path style="opacity:0.5;fill:url(#linearGradient4980);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.625;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1" id="path2931" d="M 64.359126,2.8539414 C 44.8491,2.8539414 29.142472,18.454974 29.142472,37.833835 L 29.142472,76.929009 C 29.142472,91.606445 38.17499,104.06629 51.023407,109.27255 C 41.817448,105.02963 35.357175,95.938304 35.357175,85.159575 L 35.357175,35.776195 C 35.357175,20.957066 47.368128,6.6939225 62.287558,6.6939225 L 66.430694,6.6939225 C 81.350124,6.6939225 93.361077,20.957066 93.361077,35.776195 L 93.361077,85.159575 C 93.361077,95.938304 86.900804,105.02963 77.694844,109.27255 C 90.543262,104.06629 99.57578,91.606445 99.57578,76.929009 L 99.57578,37.833835 C 99.57578,18.454974 83.869152,2.8539414 64.359126,2.8539414 z "/>
<path style="opacity:0.8;fill:url(#radialGradient4977);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path2861" d="M 49.470641,12.003202 C 44.032247,15.40845 40.97192,21.213331 41.571128,23.148345 C 42.216771,25.233301 46.03779,15.914775 56.854306,13.028936 C 65.194873,10.80368 56.853813,7.380231 49.470641,12.003202 z "/>
<path style="opacity:0.8;fill:url(#radialGradient4974);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path2871" d="M 79.247611,11.903104 C 84.686005,15.308352 87.746331,21.113233 87.147123,23.048247 C 86.501481,25.133203 82.680461,15.814677 71.863945,12.928838 C 63.523378,10.703581 71.864438,7.280132 79.247611,11.903104 z "/>
<path style="opacity:0.5;fill:url(#linearGradient4971);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.625;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1" id="rect2875" d="M 64.359126,6.2794038 C 45.402331,6.2794038 30.141085,19.274072 30.141085,38.230867 L 30.141085,76.474559 C 30.141085,90.832324 38.917475,103.02079 51.401559,108.11367 C 42.456647,103.96315 36.179563,95.069836 36.179563,84.525863 L 36.179563,36.218041 C 36.179563,21.721668 47.849928,10.035751 62.3463,10.035751 L 66.371952,10.035751 C 80.868324,10.035751 92.538689,21.721668 92.538689,36.218041 L 92.538689,84.525863 C 92.538689,95.069836 86.261604,103.96315 77.316693,108.11367 C 89.800776,103.02079 98.577166,90.832324 98.577166,76.474559 L 98.577166,38.230867 C 98.577166,19.274072 83.31592,6.2794038 64.359126,6.2794038 z "/>
<path style="opacity:0.8;fill:url(#linearGradient4968);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.625;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1" id="path2933" d="M 64.359126,4.0389347 C 37.597412,4.0389347 31.421633,27.354187 31.421633,37.899012 C 31.421633,69.53349 33.480224,69.53349 33.480224,37.899012 C 33.480224,14.700396 49.942868,5.5442086 64.359126,5.5442086 C 78.775384,5.5442086 95.238027,15.646794 95.238027,37.899012 C 95.238027,69.53349 97.296619,69.53349 97.296619,37.899012 C 97.296619,27.354187 91.12084,4.0389347 64.359126,4.0389347 z "/>
<path style="opacity:0.6;fill:url(#linearGradient4965);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.625;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1" id="path2885" d="M 64.359126,7.091337 C 38.192389,7.091337 32.153911,29.391473 32.153911,39.078761 C 32.153911,68.140624 34.166737,68.140624 34.166737,39.078761 C 34.166737,17.766728 50.263376,8.474197 64.359126,8.474197 C 78.454875,8.474197 94.551515,18.636162 94.551515,39.078761 C 94.551515,68.140624 96.564341,68.140624 96.564341,39.078761 C 96.564341,29.391473 90.525863,7.091337 64.359126,7.091337 z "/>
<path style="opacity:0.8;fill:white;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path2897" d="M 36.979617,16.487555 C 34.10437,21.735798 40.00668,18.418682 41.377593,16.761368 C 45.231503,12.102333 51.745249,8.725083 57.462695,7.62284 C 62.257428,6.6984824 62.988478,4.847127 59.040233,4.5406553 C 51.168146,3.9296066 39.736027,11.456231 36.979617,16.487555 z "/>
<path style="opacity:0.6;fill:white;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path2901" d="M 32.623431,25.155638 C 32.928211,27.720405 37.886922,19.357836 41.791152,15.431911 C 46.559495,10.637072 53.787418,7.28111 57.264611,6.8376665 C 63.463032,6.0471897 60.520985,3.0096623 56.635935,3.7770922 C 42.515997,6.5662613 31.846251,18.615574 32.623431,25.155638 z "/>
<path style="opacity:0.8;fill:white;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path2909" d="M 91.579935,16.451601 C 94.474486,21.689224 88.560004,18.393859 87.183,16.741604 C 83.311963,12.096789 76.785826,8.743542 71.06436,7.662356 C 66.266258,6.7556569 64.915924,4.9102192 68.863013,4.5892139 C 76.732798,3.9491874 88.805023,11.430459 91.579935,16.451601 z "/>
<path style="opacity:0.6;fill:white;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path2911" d="M 95.798321,24.924688 C 95.502987,27.490558 90.51352,19.146303 86.594864,15.234779 C 81.808901,10.457527 74.568672,7.128199 71.089869,6.6975603 C 64.88858,5.9299082 67.797417,3.002405 71.706633,3.6353351 C 85.848263,5.9367719 96.551418,18.381806 95.798321,24.924688 z "/>
<path style="opacity:0.4;fill:url(#radialGradient4958);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path2953" d="M 49.032092,11.138281 C 41.942618,15.187263 37.953187,22.089508 38.734312,24.390321 C 39.575969,26.86942 44.557039,15.789305 58.657416,12.357921 C 69.530154,9.711999 58.656774,5.6413744 49.032092,11.138281 z "/>
<path style="opacity:0.4;fill:url(#radialGradient4955);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path2957" d="M 79.540422,10.945305 C 86.081213,15.063412 89.761889,22.083498 89.041216,24.423589 C 88.264698,26.945014 83.669133,15.675732 70.66004,12.185767 C 60.628786,9.494672 70.660632,5.3545529 79.540422,10.945305 z "/>
<path style="opacity:0.4;fill:url(#radialGradient4952);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.625;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1" id="path3055" d="M 120.71826,124.78239 C 120.71826,127.00569 95.485415,128.80804 64.359128,128.80804 C 33.232841,128.80804 8,127.00569 8,124.78239 C 8,122.55908 33.232841,120.75673 64.359128,120.75673 C 95.485415,120.75673 120.71826,122.55908 120.71826,124.78239 L 120.71826,124.78239 z "/>
<path style="opacity:0.4;fill:url(#radialGradient4949);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.625;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1" id="path3065" d="M 120.71826,121.76311 C 120.71826,124.54224 95.485415,126.79518 64.359128,126.79518 C 33.232841,126.79518 8,124.54224 8,121.76311 C 8,118.98398 33.232841,116.73105 64.359128,116.73105 C 95.485415,116.73105 120.71826,118.98398 120.71826,121.76311 L 120.71826,121.76311 z "/>
<path style="opacity:0.4;fill:url(#radialGradient4946);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.625;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1" id="path3067" d="M 120.71826,122.76956 C 120.71826,124.99287 95.485415,126.79521 64.359128,126.79521 C 33.232841,126.79521 8,124.99287 8,122.76956 C 8,120.54625 33.232841,118.74391 64.359128,118.74391 C 95.485415,118.74391 120.71826,120.54625 120.71826,122.76956 L 120.71826,122.76956 z "/>
</g>
<g id="g4928">
<rect y="57.359127" x="24.102608" width="80.513039" style="fill:url(#linearGradient3151);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.625;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1" ry="0.5" rx="0.49999997" id="rect1941" height="66.259109"/>
<rect y="57.359127" x="24.102608" width="80.513039" style="opacity:0.02999998;fill:url(#linearGradient3148);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.625;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1" ry="0.5" rx="0.49999997" id="rect2709" height="66.259109"/>
<rect y="57.359127" x="24.102608" width="80.513039" style="opacity:0.02999998;fill:url(#linearGradient3145);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.625;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1" ry="0.5" rx="0.49999997" id="rect2734" height="66.259109"/>
<rect y="57.359127" x="24.102608" width="80.513039" style="opacity:0.02999998;fill:url(#linearGradient3142);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.625;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1" ry="0.5" rx="0.49999997" id="rect2738" height="66.259109"/>
<path style="opacity:0.5;fill:white;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.625;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1" id="path2727" d="M 26.61864,57.359126 C 28.42873,59.480775 44.763964,61.14536 65.274048,61.14536 C 85.50262,61.14536 101.5673,59.498208 103.75791,57.418285 C 103.72708,57.415066 103.7324,57.359126 103.70072,57.359126 L 26.61864,57.359126 z "/>
<g transform="matrix(1.719497,0,0,1.981605,4.420926,1.487591)" id="g2798">
<path style="opacity:0.40277776;fill:url(#radialGradient3114);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path2778" d="M 13.971247,30.766863 C 13.531705,33.396386 13.04037,50.075728 14.667687,53.646863 C 16.25955,57.140196 16.060569,36.980196 19.940738,33.806863 C 23.861905,30.600002 14.385794,28.286863 13.971247,30.766863 z "/>
<path style="opacity:0.3;fill:url(#radialGradient3116);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path2790" d="M 13.728722,30.941568 C 13.221493,34.011307 12.654496,53.482989 14.53241,57.651979 C 16.36941,61.730142 16.139785,38.195094 20.617473,34.490503 C 25.142472,30.746772 14.207108,28.046383 13.728722,30.941568 z "/>
<path style="opacity:0.2;fill:url(#radialGradient3118);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path2794" d="M 13.231668,31.092008 C 12.601372,34.540822 11.896808,56.41702 14.23035,61.100829 C 16.513051,65.682595 16.227713,39.241256 21.791801,35.079193 C 27.414678,30.873157 13.826121,27.839303 13.231668,31.092008 z "/>
</g>
<g transform="matrix(-1.719497,0,0,1.981605,124.2973,1.487605)" id="g2803">
<path style="opacity:0.40277776;fill:url(#radialGradient3120);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path2805" d="M 13.971247,30.766863 C 13.531705,33.396386 13.04037,50.075728 14.667687,53.646863 C 16.25955,57.140196 16.060569,36.980196 19.940738,33.806863 C 23.861905,30.600002 14.385794,28.286863 13.971247,30.766863 z "/>
<path style="opacity:0.3;fill:url(#radialGradient3122);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path2807" d="M 13.728722,30.941568 C 13.221493,34.011307 12.654496,53.482989 14.53241,57.651979 C 16.36941,61.730142 16.139785,38.195094 20.617473,34.490503 C 25.142472,30.746772 14.207108,28.046383 13.728722,30.941568 z "/>
<path style="opacity:0.2;fill:url(#radialGradient3124);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path2809" d="M 13.231668,31.092008 C 12.601372,34.540822 11.896808,56.41702 14.23035,61.100829 C 16.513051,65.682595 16.227713,39.241256 21.791801,35.079193 C 27.414678,30.873157 13.826121,27.839303 13.231668,31.092008 z "/>
</g>
<path style="opacity:0.24999994;fill:url(#linearGradient3130);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.625;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1" id="rect3077" d="M 103.11564,114.72466 L 103.11564,122.61182 C 103.11564,123.16937 102.6835,123.61823 102.14673,123.61823 L 26.57152,123.61823 C 26.034743,123.61823 25.602607,123.16937 25.602607,122.61182 L 25.602607,94.596405 C 25.602607,124.11291 103.11564,73.717412 103.11564,114.72466 z "/>
<path style="opacity:0.5;fill:black;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.625;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1" id="path2768" d="M 25.646537,123.61824 C 27.456628,121.49659 43.791857,119.832 64.301941,119.832 C 84.530518,119.832 100.5952,121.47915 102.7858,123.55908 C 102.75497,123.5623 102.7603,123.61824 102.72862,123.61824 L 25.646537,123.61824 z "/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 34 KiB

View file

@ -0,0 +1,180 @@
<?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="32px"
height="32px"
id="svg3415"
version="1.1"
inkscape:version="0.48.2 r9819"
sodipodi:docname="New document 11">
<defs
id="defs3417">
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2237"
id="linearGradient7105"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.7509469,0,0,1,466.37866,-193.98279)"
x1="561.24646"
y1="416.94766"
x2="581.19086"
y2="451.85028" />
<linearGradient
id="linearGradient2237">
<stop
style="stop-color:#006000;stop-opacity:1;"
offset="0"
id="stop2239" />
<stop
style="stop-color:#48ff00;stop-opacity:1;"
offset="1"
id="stop2241" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3207"
id="linearGradient7107"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.7509469,0,0,0.7354122,466.90866,-81.0361)"
x1="561.24646"
y1="416.94766"
x2="581.19086"
y2="451.85028" />
<linearGradient
id="linearGradient3207">
<stop
id="stop3209"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop3211"
offset="1"
style="stop-color:#48ff00;stop-opacity:0;" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2237"
id="linearGradient7109"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.7509469,0,0,1,486.01576,-193.98279)"
x1="561.24646"
y1="416.94766"
x2="581.19086"
y2="451.85028" />
<linearGradient
id="linearGradient3395">
<stop
style="stop-color:#006000;stop-opacity:1;"
offset="0"
id="stop3397" />
<stop
style="stop-color:#48ff00;stop-opacity:1;"
offset="1"
id="stop3399" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3207"
id="linearGradient7111"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.7509469,0,0,0.734661,486.54576,-80.7033)"
x1="561.24646"
y1="416.94766"
x2="581.19086"
y2="451.85028" />
<linearGradient
id="linearGradient3402">
<stop
id="stop3404"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop3406"
offset="1"
style="stop-color:#48ff00;stop-opacity:0;" />
</linearGradient>
<linearGradient
y2="451.85028"
x2="581.19086"
y1="416.94766"
x1="561.24646"
gradientTransform="matrix(0.7509469,0,0,0.734661,486.54576,-80.7033)"
gradientUnits="userSpaceOnUse"
id="linearGradient3413"
xlink:href="#linearGradient3207"
inkscape:collect="always" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11.197802"
inkscape:cx="1.7561332"
inkscape:cy="16"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="800"
inkscape:window-height="628"
inkscape:window-x="946"
inkscape:window-y="0"
inkscape:window-maximized="0" />
<metadata
id="metadata3420">
<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
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<g
id="g7099"
transform="matrix(0.77034956,0,0,0.77034956,-682.67795,-169.99219)">
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc"
id="path6972"
d="m 888.47136,230.84445 -0.1313,21.48508 c -0.0519,2.75946 0.7649,3.42552 3.1952,2.65928 l 12.9804,-10.37119 c 1.9695,-1.71776 1.7878,-3.98642 0.1996,-5.31856 l -13.5794,-11.4349 c -2.2809,-0.95305 -2.6175,0.73817 -2.6645,2.98029 z"
style="fill:url(#linearGradient7105);fill-opacity:1;fill-rule:evenodd;stroke:#006100;stroke-width:0.8665719px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc"
id="path6974"
d="m 889.06306,231.14531 -0.1312,13.62502 c 6.5402,-8.90875 2.6913,1.16873 11.1093,-8.53132 l -8.7455,-7.28544 c -2.2809,-0.70088 -2.1856,0.54285 -2.2326,2.19174 z"
style="fill:url(#linearGradient7107);fill-opacity:1;fill-rule:evenodd;stroke:none" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc"
id="path7005"
d="m 908.10846,230.84445 -0.1313,21.48508 c -0.0519,2.75946 0.7649,3.42552 3.1952,2.65928 l 12.9804,-10.37119 c 1.9695,-1.71776 1.7878,-3.98642 0.1996,-5.31856 l -13.5794,-11.4349 c -2.2809,-0.95305 -2.6175,0.73817 -2.6645,2.98029 z"
style="fill:url(#linearGradient7109);fill-opacity:1;fill-rule:evenodd;stroke:#006100;stroke-width:0.8665719px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc"
id="path7007"
d="m 908.70016,231.15923 -0.1312,13.6111 c 6.5402,-8.89965 2.5318,0.85011 10.9498,-8.84003 l -8.586,-6.96057 c -2.2809,-0.70017 -2.1856,0.54229 -2.2326,2.1895 z"
style="fill:url(#linearGradient3413);fill-opacity:1;fill-rule:evenodd;stroke:none" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.3 KiB

View file

@ -0,0 +1,187 @@
<?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="32px"
height="32px"
id="svg3648"
version="1.1"
inkscape:version="0.48.2 r9819"
sodipodi:docname="New document 17">
<defs
id="defs3650">
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2237"
id="linearGradient5207"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.2215923,0,0,0.8996584,781.52213,-119.35192)"
x1="292.30838"
y1="419.81253"
x2="333.20709"
y2="475.94916" />
<linearGradient
id="linearGradient2237">
<stop
style="stop-color:#006000;stop-opacity:1;"
offset="0"
id="stop2239" />
<stop
style="stop-color:#48ff00;stop-opacity:1;"
offset="1"
id="stop2241" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3207"
id="linearGradient5209"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.1914392,0,0,0.8996584,791.32934,-118.70141)"
x1="297.8941"
y1="424.00873"
x2="333.20709"
y2="475.94916" />
<linearGradient
id="linearGradient3207">
<stop
id="stop3209"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop3211"
offset="1"
style="stop-color:#48ff00;stop-opacity:0;" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2237"
id="linearGradient5211"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.2215923,0,0,0.8996584,781.52213,-119.35192)"
x1="292.30838"
y1="419.81253"
x2="333.20709"
y2="475.94916" />
<linearGradient
id="linearGradient3627">
<stop
style="stop-color:#006000;stop-opacity:1;"
offset="0"
id="stop3629" />
<stop
style="stop-color:#48ff00;stop-opacity:1;"
offset="1"
id="stop3631" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3207"
id="linearGradient5213"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.1914392,0,0,0.8996584,791.32934,-118.70141)"
x1="297.8941"
y1="424.00873"
x2="333.20709"
y2="475.94916" />
<linearGradient
id="linearGradient3634">
<stop
id="stop3636"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop3638"
offset="1"
style="stop-color:#48ff00;stop-opacity:0;" />
</linearGradient>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11.197802"
inkscape:cx="16"
inkscape:cy="16"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="849"
inkscape:window-height="609"
inkscape:window-x="842"
inkscape:window-y="83"
inkscape:window-maximized="0" />
<metadata
id="metadata3653">
<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
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<g
id="g5246"
transform="matrix(0.76403568,0,0,0.76403568,-640.5195,-200.07815)">
<g
transform="translate(0.4951,0.288308)"
id="g5189">
<g
id="g5175">
<rect
ry="1.8429986"
y="268.62585"
x="847.34686"
height="27.794876"
width="6.8460755"
id="rect4006"
style="fill:url(#linearGradient5207);fill-opacity:1;fill-rule:evenodd;stroke:#006100;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
rx="1.5517035" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc"
id="rect4406"
d="m 849.53757,269.27635 3.23338,0 c 0.74268,0 0.69637,0.86122 0.69637,1.88224 l -0.10173,10.84392 c 0.20417,2.44168 -3.19894,3.13232 -5.23638,5.33738 l 0.0678,-16.22055 c 0,-1.02102 0.59787,-1.84299 1.34055,-1.84299 z"
style="fill:url(#linearGradient5209);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.44649449px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
</g>
</g>
<g
transform="translate(16.522255,0.288308)"
id="g5179">
<rect
rx="1.5517035"
style="fill:url(#linearGradient5211);fill-opacity:1;fill-rule:evenodd;stroke:#006100;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect5181"
width="6.8460755"
height="27.794876"
x="847.34686"
y="268.62585"
ry="1.8429986" />
<path
inkscape:connector-curvature="0"
style="fill:url(#linearGradient5213);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.44649449px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 849.53757,269.27635 3.23338,0 c 0.74268,0 0.69637,0.86122 0.69637,1.88224 l -0.10173,10.84392 c 0.20417,2.44168 -3.19894,3.13232 -5.23638,5.33738 l 0.0678,-16.22055 c 0,-1.02102 0.59787,-1.84299 1.34055,-1.84299 z"
id="path5183"
sodipodi:nodetypes="ccccccc" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.5 KiB

View file

@ -0,0 +1,178 @@
<?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="32px"
height="32px"
id="svg3530"
version="1.1"
inkscape:version="0.48.2 r9819"
sodipodi:docname="New document 14">
<defs
id="defs3532">
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2237"
id="linearGradient7125"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-0.7508448,0,0,1.0047463,1224.9887,-260.93318)"
x1="561.24646"
y1="416.94766"
x2="581.19086"
y2="451.85028" />
<linearGradient
id="linearGradient2237">
<stop
style="stop-color:#006000;stop-opacity:1;"
offset="0"
id="stop2239" />
<stop
style="stop-color:#48ff00;stop-opacity:1;"
offset="1"
id="stop2241" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3207"
id="linearGradient7127"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.7508448,0,0,1.0047463,356.20533,-226.06053)"
x1="574.19977"
y1="386.51755"
x2="602.19623"
y2="414.91589" />
<linearGradient
id="linearGradient3207">
<stop
id="stop3209"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop3211"
offset="1"
style="stop-color:#48ff00;stop-opacity:0;" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2237"
id="linearGradient7129"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-0.7508448,0,0,1.0047463,1224.9887,-260.93318)"
x1="561.24646"
y1="416.94766"
x2="581.19086"
y2="451.85028" />
<linearGradient
id="linearGradient3510">
<stop
style="stop-color:#006000;stop-opacity:1;"
offset="0"
id="stop3512" />
<stop
style="stop-color:#48ff00;stop-opacity:1;"
offset="1"
id="stop3514" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3207"
id="linearGradient7131"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.7508448,0,0,1.0047463,356.20533,-226.06053)"
x1="574.19977"
y1="386.51755"
x2="602.19623"
y2="414.91589" />
<linearGradient
id="linearGradient3517">
<stop
id="stop3519"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop3521"
offset="1"
style="stop-color:#48ff00;stop-opacity:0;" />
</linearGradient>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11.197802"
inkscape:cx="1.7561332"
inkscape:cy="16"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="721"
inkscape:window-height="582"
inkscape:window-x="1025"
inkscape:window-y="0"
inkscape:window-maximized="0" />
<metadata
id="metadata3535">
<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
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<g
id="g7117"
transform="matrix(0.76676112,0,0,0.76676112,-600.90663,-119.37546)">
<g
transform="translate(0.3991365,0)"
id="g7085">
<path
inkscape:connector-curvature="0"
style="fill:url(#linearGradient7125);fill-opacity:1;fill-rule:evenodd;stroke:#006100;stroke-width:0.86856693px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 802.95336,165.91041 0.13124,21.58705 c 0.0519,2.77256 -0.76484,3.44178 -3.19474,2.6719 l -12.97858,-10.42041 c -1.96927,-1.72591 -1.78765,-4.00534 -0.19967,-5.34381 l 13.5776,-11.48917 c 2.28061,-0.95757 2.61716,0.74168 2.66415,2.99444 z"
id="path7045"
sodipodi:nodetypes="ccccccc" />
<path
inkscape:connector-curvature="0"
style="fill:url(#linearGradient7127);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 802.33383,166.70719 0.0368,6.3298 c -6.54702,5.58043 -7.17964,0.0807 -10.96661,9.35453 l -3.24611,-2.72331 c -1.83699,-1.68228 -2.19329,-3.37644 -0.71199,-4.68107 l 12.66555,-11.19867 c 2.12742,-0.93337 2.17849,0.72292 2.22234,2.91872 z"
id="path7051"
sodipodi:nodetypes="ccccccc" />
</g>
<g
transform="translate(20.159898,-1.4678949e-6)"
id="g7089">
<path
inkscape:connector-curvature="0"
style="fill:url(#linearGradient7129);fill-opacity:1;fill-rule:evenodd;stroke:#006100;stroke-width:0.86856693px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 802.95336,165.91041 0.13124,21.58705 c 0.0519,2.77256 -0.76484,3.44178 -3.19474,2.6719 l -12.97858,-10.42041 c -1.96927,-1.72591 -1.78765,-4.00534 -0.19967,-5.34381 l 13.5776,-11.48917 c 2.28061,-0.95757 2.61716,0.74168 2.66415,2.99444 z"
id="path7091"
sodipodi:nodetypes="ccccccc" />
<path
inkscape:connector-curvature="0"
style="fill:url(#linearGradient7131);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 802.33383,166.70719 0.0368,6.3298 c -6.54702,5.58043 -7.17964,0.0807 -10.96661,9.35453 l -3.24611,-2.72331 c -1.83699,-1.68228 -2.19329,-3.37644 -0.71199,-4.68107 l 12.66555,-11.19867 c 2.12742,-0.93337 2.17849,0.72292 2.22234,2.91872 z"
id="path7093"
sodipodi:nodetypes="ccccccc" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.6 KiB

View file

@ -0,0 +1,130 @@
<?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="32px"
height="32px"
id="svg3239"
version="1.1"
inkscape:version="0.48.2 r9819"
sodipodi:docname="replay_start.svg">
<defs
id="defs3241">
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient12715"
id="linearGradient12804"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(636.02621,139.8406)"
x1="561.24646"
y1="416.94766"
x2="581.19086"
y2="451.85028" />
<linearGradient
id="linearGradient12715">
<stop
style="stop-color:#000080;stop-opacity:1;"
offset="0"
id="stop12717" />
<stop
id="stop12723"
offset="0.29885057"
style="stop-color:#0000a7;stop-opacity:1;" />
<stop
style="stop-color:#2828ff;stop-opacity:1;"
offset="1"
id="stop12719" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient13568"
id="linearGradient12801"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(636.73201,141.31112)"
x1="561.24646"
y1="416.94766"
x2="581.19086"
y2="451.85028" />
<linearGradient
id="linearGradient13568">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop13570" />
<stop
style="stop-color:#0600cf;stop-opacity:0;"
offset="1"
id="stop13572" />
</linearGradient>
<linearGradient
y2="451.85028"
x2="581.19086"
y1="416.94766"
x1="561.24646"
gradientTransform="translate(636.73201,141.31112)"
gradientUnits="userSpaceOnUse"
id="linearGradient3237"
xlink:href="#linearGradient13568"
inkscape:collect="always" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11.197802"
inkscape:cx="1.7561332"
inkscape:cy="16"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="907"
inkscape:window-height="665"
inkscape:window-x="839"
inkscape:window-y="0"
inkscape:window-maximized="0" />
<metadata
id="metadata3244">
<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
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<g
id="g13955"
transform="matrix(0.6981983,0,0,0.76802309,-828.57925,-425.81456)">
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc"
id="path12784"
d="m 1198.1068,564.66784 -0.1748,21.48508 c -0.069,2.75946 1.0186,3.42552 4.2549,2.65928 l 17.2853,-10.37119 c 2.6227,-1.71776 2.3808,-3.98642 0.2659,-5.31856 l -18.0831,-11.4349 c -3.0374,-0.95305 -3.4856,0.73817 -3.5482,2.98029 z"
style="fill:url(#linearGradient12804);fill-opacity:1;fill-rule:evenodd;stroke:#000061;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc"
id="path12786"
d="m 1198.8948,565.80969 -0.1748,18.52705 c 8.7093,-12.11394 4.4337,-0.58002 15.6435,-13.76997 l -12.4957,-7.73737 c -3.0374,-0.95305 -2.9104,0.73817 -2.973,2.98029 z"
style="fill:url(#linearGradient3237);fill-opacity:1;fill-rule:evenodd;stroke:none" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.2 KiB

View file

@ -0,0 +1,127 @@
<?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="32px"
height="32px"
id="svg3320"
version="1.1"
inkscape:version="0.48.2 r9819"
sodipodi:docname="replay_stop.svg">
<defs
id="defs3322">
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2237"
id="linearGradient3610"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.8996584,0,0,0.8996584,542.1675,-118.95505)"
x1="297.8941"
y1="424.00873"
x2="333.20709"
y2="475.94916" />
<linearGradient
id="linearGradient2237">
<stop
style="stop-color:#006000;stop-opacity:1;"
offset="0"
id="stop2239" />
<stop
style="stop-color:#48ff00;stop-opacity:1;"
offset="1"
id="stop2241" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3207"
id="linearGradient3998"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.8996584,0,0,0.8996584,543.08369,-117.97095)"
x1="293.33597"
y1="423.03891"
x2="330.00668"
y2="472.74878" />
<linearGradient
id="linearGradient3207">
<stop
id="stop3209"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop3211"
offset="1"
style="stop-color:#48ff00;stop-opacity:0;" />
</linearGradient>
<linearGradient
y2="472.74878"
x2="330.00668"
y1="423.03891"
x1="293.33597"
gradientTransform="matrix(0.8996584,0,0,0.8996584,543.08369,-117.97095)"
gradientUnits="userSpaceOnUse"
id="linearGradient3318"
xlink:href="#linearGradient3207"
inkscape:collect="always" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11.197802"
inkscape:cx="1.7561332"
inkscape:cy="16"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1075"
inkscape:window-height="703"
inkscape:window-x="841"
inkscape:window-y="315"
inkscape:window-maximized="0" />
<metadata
id="metadata3325">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<g
id="g4000"
transform="matrix(0.76669653,0,0,0.76669653,-615.23012,-200.91391)">
<rect
ry="3.588665"
y="269.02274"
x="809.41412"
height="27.794876"
width="27.794876"
id="rect3598"
style="fill:url(#linearGradient3610);fill-opacity:1;fill-rule:evenodd;stroke:#006100;stroke-width:0.89965838px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc"
id="rect3612"
d="m 813.91895,270.00686 20.0068,0 c 10.54509,7.32439 -17.45185,10.45989 -23.59547,24.20621 l 0,-20.61755 c 0,-1.98812 1.60055,-3.58866 3.58867,-3.58866 z"
style="fill:url(#linearGradient3318);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.2 KiB

View file

@ -0,0 +1,177 @@
<?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="32px"
height="32px"
id="svg3766"
version="1.1"
inkscape:version="0.48.2 r9819"
sodipodi:docname="New document 20">
<defs
id="defs3768">
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2237"
id="linearGradient9289"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(325.22401,-152.70392)"
x1="561.24646"
y1="416.94766"
x2="581.19086"
y2="451.85028" />
<linearGradient
id="linearGradient2237">
<stop
style="stop-color:#006000;stop-opacity:1;"
offset="0"
id="stop2239" />
<stop
style="stop-color:#48ff00;stop-opacity:1;"
offset="1"
id="stop2241" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3207"
id="linearGradient9291"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(325.92981,-151.2334)"
x1="561.24646"
y1="416.94766"
x2="581.19086"
y2="451.85028" />
<linearGradient
id="linearGradient3207">
<stop
id="stop3209"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop3211"
offset="1"
style="stop-color:#48ff00;stop-opacity:0;" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2237"
id="linearGradient9293"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.2215923,0,0,0.8996584,781.52213,-119.35192)"
x1="292.30838"
y1="419.81253"
x2="333.20709"
y2="475.94916" />
<linearGradient
id="linearGradient3747">
<stop
style="stop-color:#006000;stop-opacity:1;"
offset="0"
id="stop3749" />
<stop
style="stop-color:#48ff00;stop-opacity:1;"
offset="1"
id="stop3751" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3207"
id="linearGradient9295"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.1914392,0,0,0.8996584,791.32934,-118.70141)"
x1="297.8941"
y1="424.00873"
x2="333.20709"
y2="475.94916" />
<linearGradient
id="linearGradient3754">
<stop
id="stop3756"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop3758"
offset="1"
style="stop-color:#48ff00;stop-opacity:0;" />
</linearGradient>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11.197802"
inkscape:cx="16"
inkscape:cy="16"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="804"
inkscape:window-height="488"
inkscape:window-x="1089"
inkscape:window-y="0"
inkscape:window-maximized="0" />
<metadata
id="metadata3771">
<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
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<g
id="g9274"
transform="matrix(0.76402345,0,0,0.76402345,-674.86163,-200.00285)">
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc"
id="path5221"
d="m 887.3046,272.12332 -0.17478,21.48508 c -0.0691,2.75946 1.01863,3.42552 4.25485,2.65928 l 17.28531,-10.37119 c 2.62273,-1.71776 2.38085,-3.98642 0.26593,-5.31856 l -18.0831,-11.4349 c -3.0374,-0.95305 -3.48562,0.73817 -3.54821,2.98029 z"
style="fill:url(#linearGradient9289);fill-opacity:1;fill-rule:evenodd;stroke:#006100;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc"
id="path5223"
d="m 888.09257,273.26517 -0.17479,18.52705 c 8.70928,-12.11394 4.43369,-0.58002 15.64354,-13.76997 l -12.49571,-7.73737 c -3.0374,-0.95305 -2.91045,0.73817 -2.97304,2.98029 z"
style="fill:url(#linearGradient9291);fill-opacity:1;fill-rule:evenodd;stroke:none" />
<g
transform="translate(67.163097,0.1942719)"
id="g5236">
<rect
rx="1.5517035"
style="fill:url(#linearGradient9293);fill-opacity:1;fill-rule:evenodd;stroke:#006100;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect5238"
width="6.8460755"
height="27.794876"
x="847.34686"
y="268.62585"
ry="1.8429986" />
<path
inkscape:connector-curvature="0"
style="fill:url(#linearGradient9295);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.44649449px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 849.53757,269.27635 3.23338,0 c 0.74268,0 0.69637,0.86122 0.69637,1.88224 l -0.10173,10.84392 c 0.20417,2.44168 -3.19894,3.13232 -5.23638,5.33738 l 0.0678,-16.22055 c 0,-1.02102 0.59787,-1.84299 1.34055,-1.84299 z"
id="path5240"
sodipodi:nodetypes="ccccccc" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.2 KiB

View file

@ -0,0 +1,184 @@
<?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="32px"
height="32px"
id="svg3881"
version="1.1"
inkscape:version="0.48.2 r9819"
sodipodi:docname="New document 23">
<defs
id="defs3883">
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2237"
id="linearGradient5301"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-1,0,0,1,1457.2153,-101.44165)"
x1="561.24646"
y1="416.94766"
x2="581.19086"
y2="451.85028" />
<linearGradient
id="linearGradient2237">
<stop
style="stop-color:#006000;stop-opacity:1;"
offset="0"
id="stop2239" />
<stop
style="stop-color:#48ff00;stop-opacity:1;"
offset="1"
id="stop2241" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2237"
id="linearGradient5295"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.2215923,0,0,0.8996584,-933.75407,-67.895376)"
x1="292.30838"
y1="419.81253"
x2="333.20709"
y2="475.94916" />
<linearGradient
id="linearGradient3857">
<stop
style="stop-color:#006000;stop-opacity:1;"
offset="0"
id="stop3859" />
<stop
style="stop-color:#48ff00;stop-opacity:1;"
offset="1"
id="stop3861" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3207"
id="linearGradient5292"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.1914392,0,0,0.8996584,805.00844,-67.244866)"
x1="297.8941"
y1="424.00873"
x2="333.20709"
y2="475.94916" />
<linearGradient
id="linearGradient3207">
<stop
id="stop3209"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop3211"
offset="1"
style="stop-color:#48ff00;stop-opacity:0;" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3207"
id="linearGradient6073"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(300.14087,-66.733744)"
x1="574.19977"
y1="386.51755"
x2="602.19623"
y2="414.91589" />
<linearGradient
id="linearGradient3868">
<stop
id="stop3870"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop3872"
offset="1"
style="stop-color:#48ff00;stop-opacity:0;" />
</linearGradient>
<linearGradient
y2="414.91589"
x2="602.19623"
y1="386.51755"
x1="574.19977"
gradientTransform="translate(300.14087,-66.733744)"
gradientUnits="userSpaceOnUse"
id="linearGradient3879"
xlink:href="#linearGradient3207"
inkscape:collect="always" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11.197802"
inkscape:cx="16"
inkscape:cy="16"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="783"
inkscape:window-height="494"
inkscape:window-x="1110"
inkscape:window-y="0"
inkscape:window-maximized="0" />
<metadata
id="metadata3886">
<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
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<g
id="g6466"
transform="matrix(0.76402304,0,0,0.76402304,-654.96343,-239.16829)">
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc"
id="path5273"
d="m 895.1347,323.38559 0.17478,21.48508 c 0.0691,2.75946 -1.01863,3.42552 -4.25485,2.65928 l -17.28531,-10.37119 c -2.62273,-1.71776 -2.38085,-3.98642 -0.26593,-5.31856 l 18.0831,-11.4349 c 3.0374,-0.95305 3.48562,0.73817 3.54821,2.98029 z"
style="fill:url(#linearGradient5301);fill-opacity:1;fill-rule:evenodd;stroke:#006100;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<rect
transform="scale(-1,1)"
ry="1.8429986"
y="320.0824"
x="-867.92932"
height="27.794876"
width="6.8460755"
id="rect5279"
style="fill:url(#linearGradient5295);fill-opacity:1;fill-rule:evenodd;stroke:#006100;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
rx="1.5517035" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc"
id="path5281"
d="m 863.21667,320.73289 3.23338,0 c 0.74268,0 0.69637,0.86122 0.69637,1.88224 l -0.10173,10.84392 c 0.20417,2.44168 -3.19894,3.13232 -5.23638,5.33738 l 0.0678,-16.22055 c 0,-1.02102 0.59787,-1.84299 1.34055,-1.84299 z"
style="fill:url(#linearGradient5292);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.44649449px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<path
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc"
id="path5303"
d="m 894.30958,324.17861 0.049,6.2999 c -8.71954,5.55407 -9.56209,0.0803 -14.6057,9.31034 l -4.32328,-2.71045 c -2.44656,-1.67433 -2.9211,-3.36049 -0.94825,-4.65895 l 16.8684,-11.14577 c 2.83337,-0.92896 2.90139,0.7195 2.95978,2.90493 z"
style="fill:url(#linearGradient3879);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.6 KiB

View file

@ -5,47 +5,47 @@
#include <QDebug>
AbstractCardDragItem::AbstractCardDragItem(AbstractCardItem *_item, const QPointF &_hotSpot, AbstractCardDragItem *parentDrag)
: QGraphicsItem(), item(_item), hotSpot(_hotSpot)
: QGraphicsItem(), item(_item), hotSpot(_hotSpot)
{
if (parentDrag) {
parentDrag->addChildDrag(this);
setZValue(2000000007 + hotSpot.x() * 1000000 + hotSpot.y() * 1000 + 1000);
} else {
if ((hotSpot.x() < 0) || (hotSpot.y() < 0)) {
qDebug() << "CardDragItem: coordinate overflow: x =" << hotSpot.x() << ", y =" << hotSpot.y();
hotSpot = QPointF();
} else if ((hotSpot.x() > CARD_WIDTH) || (hotSpot.y() > CARD_HEIGHT)) {
qDebug() << "CardDragItem: coordinate overflow: x =" << hotSpot.x() << ", y =" << hotSpot.y();
hotSpot = QPointF(CARD_WIDTH, CARD_HEIGHT);
}
setCursor(Qt::ClosedHandCursor);
setZValue(2000000007);
}
if (item->getTapped())
setTransform(QTransform().translate((float) CARD_WIDTH / 2, (float) CARD_HEIGHT / 2).rotate(90).translate((float) -CARD_WIDTH / 2, (float) -CARD_HEIGHT / 2));
if (parentDrag) {
parentDrag->addChildDrag(this);
setZValue(2000000007 + hotSpot.x() * 1000000 + hotSpot.y() * 1000 + 1000);
} else {
if ((hotSpot.x() < 0) || (hotSpot.y() < 0)) {
qDebug() << "CardDragItem: coordinate overflow: x =" << hotSpot.x() << ", y =" << hotSpot.y();
hotSpot = QPointF();
} else if ((hotSpot.x() > CARD_WIDTH) || (hotSpot.y() > CARD_HEIGHT)) {
qDebug() << "CardDragItem: coordinate overflow: x =" << hotSpot.x() << ", y =" << hotSpot.y();
hotSpot = QPointF(CARD_WIDTH, CARD_HEIGHT);
}
setCursor(Qt::ClosedHandCursor);
setZValue(2000000007);
}
if (item->getTapped())
setTransform(QTransform().translate((float) CARD_WIDTH / 2, (float) CARD_HEIGHT / 2).rotate(90).translate((float) -CARD_WIDTH / 2, (float) -CARD_HEIGHT / 2));
setCacheMode(DeviceCoordinateCache);
setCacheMode(DeviceCoordinateCache);
}
AbstractCardDragItem::~AbstractCardDragItem()
{
qDebug("CardDragItem destructor");
for (int i = 0; i < childDrags.size(); i++)
delete childDrags[i];
qDebug("CardDragItem destructor");
for (int i = 0; i < childDrags.size(); i++)
delete childDrags[i];
}
void AbstractCardDragItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
item->paint(painter, option, widget);
item->paint(painter, option, widget);
}
void AbstractCardDragItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
event->accept();
updatePosition(event->scenePos());
event->accept();
updatePosition(event->scenePos());
}
void AbstractCardDragItem::addChildDrag(AbstractCardDragItem *child)
{
childDrags << child;
childDrags << child;
}

View file

@ -8,24 +8,25 @@ class CardZone;
class CardInfo;
class AbstractCardDragItem : public QObject, public QGraphicsItem {
Q_OBJECT
Q_OBJECT
Q_INTERFACES(QGraphicsItem)
protected:
AbstractCardItem *item;
QPointF hotSpot;
QList<AbstractCardDragItem *> childDrags;
AbstractCardItem *item;
QPointF hotSpot;
QList<AbstractCardDragItem *> childDrags;
public:
enum { Type = typeCardDrag };
int type() const { return Type; }
AbstractCardDragItem(AbstractCardItem *_item, const QPointF &_hotSpot, AbstractCardDragItem *parentDrag = 0);
~AbstractCardDragItem();
QRectF boundingRect() const { return QRectF(0, 0, CARD_WIDTH, CARD_HEIGHT); }
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
AbstractCardItem *getItem() const { return item; }
QPointF getHotSpot() const { return hotSpot; }
void addChildDrag(AbstractCardDragItem *child);
virtual void updatePosition(const QPointF &cursorScenePos) = 0;
enum { Type = typeCardDrag };
int type() const { return Type; }
AbstractCardDragItem(AbstractCardItem *_item, const QPointF &_hotSpot, AbstractCardDragItem *parentDrag = 0);
~AbstractCardDragItem();
QRectF boundingRect() const { return QRectF(0, 0, CARD_WIDTH, CARD_HEIGHT); }
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
AbstractCardItem *getItem() const { return item; }
QPointF getHotSpot() const { return hotSpot; }
void addChildDrag(AbstractCardDragItem *child);
virtual void updatePosition(const QPointF &cursorScenePos) = 0;
protected:
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
};
#endif

View file

@ -2,7 +2,10 @@
#include <QGraphicsScene>
#include <QCursor>
#include <QGraphicsSceneMouseEvent>
#include <math.h>
#include <cmath>
#ifdef _WIN32
#include "round.h"
#endif /* _WIN32 */
#include "carddatabase.h"
#include "cardinfowidget.h"
#include "abstractcarditem.h"
@ -11,233 +14,246 @@
#include "gamescene.h"
#include <QDebug>
AbstractCardItem::AbstractCardItem(const QString &_name, Player *_owner, QGraphicsItem *parent)
: ArrowTarget(_owner, parent), infoWidget(0), name(_name), tapped(false), tapAngle(0), isHovered(false), realZValue(0)
AbstractCardItem::AbstractCardItem(const QString &_name, Player *_owner, int _id, QGraphicsItem *parent)
: ArrowTarget(_owner, parent), infoWidget(0), id(_id), name(_name), tapped(false), facedown(false), tapAngle(0), isHovered(false), realZValue(0)
{
setCursor(Qt::OpenHandCursor);
setFlag(ItemIsSelectable);
setCacheMode(DeviceCoordinateCache);
connect(db, SIGNAL(cardListChanged()), this, SLOT(cardInfoUpdated()));
connect(settingsCache, SIGNAL(displayCardNamesChanged()), this, SLOT(callUpdate()));
cardInfoUpdated();
setCursor(Qt::OpenHandCursor);
setFlag(ItemIsSelectable);
setCacheMode(DeviceCoordinateCache);
connect(db, SIGNAL(cardListChanged()), this, SLOT(cardInfoUpdated()));
connect(settingsCache, SIGNAL(displayCardNamesChanged()), this, SLOT(callUpdate()));
cardInfoUpdated();
}
AbstractCardItem::~AbstractCardItem()
{
qDebug() << "AbstractCardItem destructor:" << name;
emit deleteCardInfoPopup(name);
emit deleteCardInfoPopup(name);
}
QRectF AbstractCardItem::boundingRect() const
{
return QRectF(0, 0, CARD_WIDTH, CARD_HEIGHT);
return QRectF(0, 0, CARD_WIDTH, CARD_HEIGHT);
}
void AbstractCardItem::pixmapUpdated()
{
update();
update();
emit sigPixmapUpdated();
}
void AbstractCardItem::cardInfoUpdated()
{
info = db->getCard(name);
connect(info, SIGNAL(pixmapUpdated()), this, SLOT(pixmapUpdated()));
info = db->getCard(name);
connect(info, SIGNAL(pixmapUpdated()), this, SLOT(pixmapUpdated()));
}
void AbstractCardItem::setRealZValue(qreal _zValue)
{
realZValue = _zValue;
setZValue(_zValue);
realZValue = _zValue;
setZValue(_zValue);
}
QSizeF AbstractCardItem::getTranslatedSize(QPainter *painter) const
{
return QSizeF(
painter->combinedTransform().map(QLineF(0, 0, boundingRect().width(), 0)).length(),
painter->combinedTransform().map(QLineF(0, 0, 0, boundingRect().height())).length()
);
return QSizeF(
painter->combinedTransform().map(QLineF(0, 0, boundingRect().width(), 0)).length(),
painter->combinedTransform().map(QLineF(0, 0, 0, boundingRect().height())).length()
);
}
void AbstractCardItem::transformPainter(QPainter *painter, const QSizeF &translatedSize, int angle)
{
QRectF totalBoundingRect = painter->combinedTransform().mapRect(boundingRect());
painter->resetTransform();
QTransform pixmapTransform;
pixmapTransform.translate(totalBoundingRect.width() / 2, totalBoundingRect.height() / 2);
pixmapTransform.rotate(angle);
pixmapTransform.translate(-translatedSize.width() / 2, -translatedSize.height() / 2);
painter->setTransform(pixmapTransform);
QRectF totalBoundingRect = painter->combinedTransform().mapRect(boundingRect());
painter->resetTransform();
QTransform pixmapTransform;
pixmapTransform.translate(totalBoundingRect.width() / 2, totalBoundingRect.height() / 2);
pixmapTransform.rotate(angle);
pixmapTransform.translate(-translatedSize.width() / 2, -translatedSize.height() / 2);
painter->setTransform(pixmapTransform);
QFont f;
int fontSize = round(translatedSize.height() / 8);
if (fontSize < 9)
fontSize = 9;
if (fontSize > 10)
fontSize = 10;
f.setPixelSize(fontSize);
QFont f;
int fontSize = round(translatedSize.height() / 8);
if (fontSize < 9)
fontSize = 9;
if (fontSize > 10)
fontSize = 10;
f.setPixelSize(fontSize);
painter->setFont(f);
painter->setFont(f);
}
void AbstractCardItem::paintPicture(QPainter *painter, const QSizeF &translatedSize, int angle)
{
qreal scaleFactor = translatedSize.width() / boundingRect().width();
QPixmap *translatedPixmap = info->getPixmap(translatedSize.toSize());
painter->save();
QColor bgColor = Qt::transparent;
if (translatedPixmap) {
painter->save();
transformPainter(painter, translatedSize, angle);
painter->drawPixmap(QPointF(0, 0), *translatedPixmap);
painter->restore();
} else {
QString colorStr;
if (!color.isEmpty())
colorStr = color;
else if (info->getColors().size() > 1)
colorStr = "m";
else if (!info->getColors().isEmpty())
colorStr = info->getColors().first().toLower();
if (colorStr == "b")
bgColor = QColor(0, 0, 0);
else if (colorStr == "u")
bgColor = QColor(0, 140, 180);
else if (colorStr == "w")
bgColor = QColor(255, 250, 140);
else if (colorStr == "r")
bgColor = QColor(230, 0, 0);
else if (colorStr == "g")
bgColor = QColor(0, 160, 0);
else if (colorStr == "m")
bgColor = QColor(250, 190, 30);
else
bgColor = QColor(230, 230, 230);
}
painter->setBrush(bgColor);
QPen pen(Qt::black);
pen.setWidth(2);
painter->setPen(pen);
painter->drawRect(QRectF(1, 1, CARD_WIDTH - 2, CARD_HEIGHT - 2));
if (!translatedPixmap || settingsCache->getDisplayCardNames()) {
painter->save();
transformPainter(painter, translatedSize, angle);
painter->setPen(Qt::white);
painter->setBackground(Qt::black);
painter->setBackgroundMode(Qt::OpaqueMode);
painter->drawText(QRectF(3 * scaleFactor, 3 * scaleFactor, translatedSize.width() - 6 * scaleFactor, translatedSize.height() - 6 * scaleFactor), Qt::AlignTop | Qt::AlignLeft | Qt::TextWrapAnywhere, name);
painter->restore();
}
painter->restore();
qreal scaleFactor = translatedSize.width() / boundingRect().width();
CardInfo *imageSource = facedown ? db->getCard() : info;
QPixmap *translatedPixmap = imageSource->getPixmap(translatedSize.toSize());
painter->save();
QColor bgColor = Qt::transparent;
if (translatedPixmap) {
painter->save();
transformPainter(painter, translatedSize, angle);
painter->drawPixmap(QPointF(0, 0), *translatedPixmap);
painter->restore();
} else {
QString colorStr;
if (!color.isEmpty())
colorStr = color;
else if (info->getColors().size() > 1)
colorStr = "m";
else if (!info->getColors().isEmpty())
colorStr = info->getColors().first().toLower();
if (colorStr == "b")
bgColor = QColor(0, 0, 0);
else if (colorStr == "u")
bgColor = QColor(0, 140, 180);
else if (colorStr == "w")
bgColor = QColor(255, 250, 140);
else if (colorStr == "r")
bgColor = QColor(230, 0, 0);
else if (colorStr == "g")
bgColor = QColor(0, 160, 0);
else if (colorStr == "m")
bgColor = QColor(250, 190, 30);
else
bgColor = QColor(230, 230, 230);
}
painter->setBrush(bgColor);
QPen pen(Qt::black);
pen.setWidth(2);
painter->setPen(pen);
painter->drawRect(QRectF(1, 1, CARD_WIDTH - 2, CARD_HEIGHT - 2));
if (!translatedPixmap || settingsCache->getDisplayCardNames() || facedown) {
painter->save();
transformPainter(painter, translatedSize, angle);
painter->setPen(Qt::white);
painter->setBackground(Qt::black);
painter->setBackgroundMode(Qt::OpaqueMode);
QString nameStr;
if (facedown)
nameStr = "# " + QString::number(id);
else
nameStr = name;
painter->drawText(QRectF(3 * scaleFactor, 3 * scaleFactor, translatedSize.width() - 6 * scaleFactor, translatedSize.height() - 6 * scaleFactor), Qt::AlignTop | Qt::AlignLeft | Qt::TextWrapAnywhere, nameStr);
painter->restore();
}
painter->restore();
}
void AbstractCardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem */*option*/, QWidget */*widget*/)
void AbstractCardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/)
{
painter->save();
painter->save();
QSizeF translatedSize = getTranslatedSize(painter);
paintPicture(painter, translatedSize, tapAngle);
painter->save();
painter->setRenderHint(QPainter::Antialiasing, false);
transformPainter(painter, translatedSize, tapAngle);
if (isSelected()) {
painter->setPen(Qt::red);
painter->drawRect(QRectF(0.5, 0.5, translatedSize.width() - 1, translatedSize.height() - 1));
} else if (isHovered) {
painter->setPen(Qt::yellow);
painter->drawRect(QRectF(0.5, 0.5, translatedSize.width() - 1, translatedSize.height() - 1));
}
painter->restore();
QSizeF translatedSize = getTranslatedSize(painter);
paintPicture(painter, translatedSize, tapAngle);
painter->save();
painter->setRenderHint(QPainter::Antialiasing, false);
transformPainter(painter, translatedSize, tapAngle);
if (isSelected()) {
painter->setPen(Qt::red);
painter->drawRect(QRectF(0.5, 0.5, translatedSize.width() - 1, translatedSize.height() - 1));
} else if (isHovered) {
painter->setPen(Qt::yellow);
painter->drawRect(QRectF(0.5, 0.5, translatedSize.width() - 1, translatedSize.height() - 1));
}
painter->restore();
painter->restore();
painter->restore();
}
void AbstractCardItem::setName(const QString &_name)
{
if (name == _name)
return;
emit deleteCardInfoPopup(name);
disconnect(info, 0, this, 0);
name = _name;
info = db->getCard(name);
connect(info, SIGNAL(pixmapUpdated()), this, SLOT(pixmapUpdated()));
update();
if (name == _name)
return;
emit deleteCardInfoPopup(name);
disconnect(info, 0, this, 0);
name = _name;
info = db->getCard(name);
connect(info, SIGNAL(pixmapUpdated()), this, SLOT(pixmapUpdated()));
update();
}
void AbstractCardItem::setHovered(bool _hovered)
{
if (isHovered == _hovered)
return;
if (_hovered)
processHoverEvent();
isHovered = _hovered;
setZValue(_hovered ? 2000000004 : realZValue);
update();
if (isHovered == _hovered)
return;
if (_hovered)
processHoverEvent();
isHovered = _hovered;
setZValue(_hovered ? 2000000004 : realZValue);
update();
}
void AbstractCardItem::setColor(const QString &_color)
{
color = _color;
update();
color = _color;
update();
}
void AbstractCardItem::setTapped(bool _tapped, bool canAnimate)
{
if (tapped == _tapped)
return;
tapped = _tapped;
if (settingsCache->getTapAnimation() && canAnimate)
static_cast<GameScene *>(scene())->registerAnimationItem(this);
else {
tapAngle = tapped ? 90 : 0;
setTransform(QTransform().translate((float) CARD_WIDTH / 2, (float) CARD_HEIGHT / 2).rotate(tapAngle).translate((float) -CARD_WIDTH / 2, (float) -CARD_HEIGHT / 2));
update();
}
if (tapped == _tapped)
return;
tapped = _tapped;
if (settingsCache->getTapAnimation() && canAnimate)
static_cast<GameScene *>(scene())->registerAnimationItem(this);
else {
tapAngle = tapped ? 90 : 0;
setTransform(QTransform().translate((float) CARD_WIDTH / 2, (float) CARD_HEIGHT / 2).rotate(tapAngle).translate((float) -CARD_WIDTH / 2, (float) -CARD_HEIGHT / 2));
update();
}
}
void AbstractCardItem::setFaceDown(bool _facedown)
{
facedown = _facedown;
update();
emit updateCardMenu(this);
}
void AbstractCardItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
if (!isSelected()) {
scene()->clearSelection();
setSelected(true);
}
if (event->button() == Qt::LeftButton)
setCursor(Qt::ClosedHandCursor);
else if (event->button() == Qt::MidButton)
emit showCardInfoPopup(event->screenPos(), name);
event->accept();
if (!isSelected()) {
scene()->clearSelection();
setSelected(true);
}
if (event->button() == Qt::LeftButton)
setCursor(Qt::ClosedHandCursor);
else if (event->button() == Qt::MidButton)
emit showCardInfoPopup(event->screenPos(), name);
event->accept();
}
void AbstractCardItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
if (event->button() == Qt::MidButton)
emit deleteCardInfoPopup(name);
// This function ensures the parent function doesn't mess around with our selection.
event->accept();
if (event->button() == Qt::MidButton)
emit deleteCardInfoPopup(name);
// This function ensures the parent function doesn't mess around with our selection.
event->accept();
}
void AbstractCardItem::processHoverEvent()
{
emit hovered(this);
emit hovered(this);
}
QVariant AbstractCardItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
{
if (change == ItemSelectedHasChanged) {
update();
return value;
} else
return QGraphicsItem::itemChange(change, value);
if (change == ItemSelectedHasChanged) {
update();
return value;
} else
return QGraphicsItem::itemChange(change, value);
}

View file

@ -12,51 +12,59 @@ const int CARD_WIDTH = 72;
const int CARD_HEIGHT = 102;
class AbstractCardItem : public ArrowTarget {
Q_OBJECT
Q_OBJECT
protected:
CardInfo *info;
CardInfoWidget *infoWidget;
QString name;
bool tapped;
int tapAngle;
QString color;
CardInfo *info;
CardInfoWidget *infoWidget;
int id;
QString name;
bool tapped;
bool facedown;
int tapAngle;
QString color;
private:
bool isHovered;
qreal realZValue;
bool isHovered;
qreal realZValue;
private slots:
void pixmapUpdated();
void cardInfoUpdated();
void callUpdate() { update(); }
void pixmapUpdated();
void cardInfoUpdated();
void callUpdate() { update(); }
signals:
void hovered(AbstractCardItem *card);
void showCardInfoPopup(QPoint pos, QString cardName);
void deleteCardInfoPopup(QString cardName);
void hovered(AbstractCardItem *card);
void showCardInfoPopup(QPoint pos, QString cardName);
void deleteCardInfoPopup(QString cardName);
void updateCardMenu(AbstractCardItem *card);
void sigPixmapUpdated();
public:
enum { Type = typeCard };
int type() const { return Type; }
AbstractCardItem(const QString &_name = QString(), Player *_owner = 0, QGraphicsItem *parent = 0);
~AbstractCardItem();
QRectF boundingRect() const;
QSizeF getTranslatedSize(QPainter *painter) const;
void paintPicture(QPainter *painter, const QSizeF &translatedSize, int angle);
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
CardInfo *getInfo() const { return info; }
QString getName() const { return name; }
void setName(const QString &_name = QString());
qreal getRealZValue() const { return realZValue; }
void setRealZValue(qreal _zValue);
void setHovered(bool _hovered);
QString getColor() const { return color; }
void setColor(const QString &_color);
bool getTapped() const { return tapped; }
void setTapped(bool _tapped, bool canAnimate = false);
void processHoverEvent();
void deleteCardInfoPopup() { emit deleteCardInfoPopup(name); }
enum { Type = typeCard };
int type() const { return Type; }
AbstractCardItem(const QString &_name = QString(), Player *_owner = 0, int _id = -1, QGraphicsItem *parent = 0);
~AbstractCardItem();
QRectF boundingRect() const;
QSizeF getTranslatedSize(QPainter *painter) const;
void paintPicture(QPainter *painter, const QSizeF &translatedSize, int angle);
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
CardInfo *getInfo() const { return info; }
int getId() const { return id; }
void setId(int _id) { id = _id; }
QString getName() const { return name; }
void setName(const QString &_name = QString());
qreal getRealZValue() const { return realZValue; }
void setRealZValue(qreal _zValue);
void setHovered(bool _hovered);
QString getColor() const { return color; }
void setColor(const QString &_color);
bool getTapped() const { return tapped; }
void setTapped(bool _tapped, bool canAnimate = false);
bool getFaceDown() const { return facedown; }
void setFaceDown(bool _facedown);
void processHoverEvent();
void deleteCardInfoPopup() { emit deleteCardInfoPopup(name); }
protected:
void transformPainter(QPainter *painter, const QSizeF &translatedSize, int angle);
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value);
void transformPainter(QPainter *painter, const QSizeF &translatedSize, int angle);
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value);
};
#endif

View file

@ -1,79 +1,162 @@
#include "abstractclient.h"
#include "protocol.h"
#include "protocol_items.h"
#include <QDebug>
#include "pending_command.h"
#include "pb/commands.pb.h"
#include "pb/server_message.pb.h"
#include "pb/event_server_identification.pb.h"
#include "pb/event_server_message.pb.h"
#include "pb/event_server_shutdown.pb.h"
#include "pb/event_connection_closed.pb.h"
#include "pb/event_user_message.pb.h"
#include "pb/event_list_rooms.pb.h"
#include "pb/event_add_to_list.pb.h"
#include "pb/event_remove_from_list.pb.h"
#include "pb/event_user_joined.pb.h"
#include "pb/event_user_left.pb.h"
#include "pb/event_game_joined.pb.h"
#include "pb/event_replay_added.pb.h"
#include "get_pb_extension.h"
#include <google/protobuf/descriptor.h>
#include "client_metatypes.h"
AbstractClient::AbstractClient(QObject *parent)
: QObject(parent), status(StatusDisconnected)
: QObject(parent), nextCmdId(0), status(StatusDisconnected)
{
qRegisterMetaType<QVariant>("QVariant");
qRegisterMetaType<CommandContainer>("CommandContainer");
qRegisterMetaType<Response>("Response");
qRegisterMetaType<Response::ResponseCode>("Response::ResponseCode");
qRegisterMetaType<ClientStatus>("ClientStatus");
qRegisterMetaType<RoomEvent>("RoomEvent");
qRegisterMetaType<GameEventContainer>("GameEventContainer");
qRegisterMetaType<Event_ServerIdentification>("Event_ServerIdentification");
qRegisterMetaType<Event_ConnectionClosed>("Event_ConnectionClosed");
qRegisterMetaType<Event_ServerShutdown>("Event_ServerShutdown");
qRegisterMetaType<Event_AddToList>("Event_AddToList");
qRegisterMetaType<Event_RemoveFromList>("Event_RemoveFromList");
qRegisterMetaType<Event_UserJoined>("Event_UserJoined");
qRegisterMetaType<Event_UserLeft>("Event_UserLeft");
qRegisterMetaType<Event_ServerMessage>("Event_ServerMessage");
qRegisterMetaType<Event_ListRooms>("Event_ListRooms");
qRegisterMetaType<Event_GameJoined>("Event_GameJoined");
qRegisterMetaType<Event_UserMessage>("Event_UserMessage");
qRegisterMetaType<ServerInfo_User>("ServerInfo_User");
qRegisterMetaType<QList<ServerInfo_User> >("QList<ServerInfo_User>");
qRegisterMetaType<Event_ReplayAdded>("Event_ReplayAdded");
connect(this, SIGNAL(sigQueuePendingCommand(PendingCommand *)), this, SLOT(queuePendingCommand(PendingCommand *)));
}
AbstractClient::~AbstractClient()
{
}
void AbstractClient::processProtocolItem(ProtocolItem *item)
void AbstractClient::processProtocolItem(const ServerMessage &item)
{
ProtocolResponse *response = qobject_cast<ProtocolResponse *>(item);
if (response) {
CommandContainer *cmdCont = pendingCommands.value(response->getCmdId(), 0);
if (!cmdCont)
return;
pendingCommands.remove(cmdCont->getCmdId());
cmdCont->processResponse(response);
if (response->getReceiverMayDelete())
delete response;
cmdCont->deleteLater();
return;
}
GenericEvent *genericEvent = qobject_cast<GenericEvent *>(item);
if (genericEvent) {
switch (genericEvent->getItemId()) {
case ItemId_Event_ConnectionClosed: emit connectionClosedEventReceived(static_cast<Event_ConnectionClosed *>(item)); break;
case ItemId_Event_ServerShutdown: emit serverShutdownEventReceived(static_cast<Event_ServerShutdown *>(item)); break;
case ItemId_Event_AddToList: emit addToListEventReceived(static_cast<Event_AddToList *>(item)); break;
case ItemId_Event_RemoveFromList: emit removeFromListEventReceived(static_cast<Event_RemoveFromList *>(item)); break;
case ItemId_Event_UserJoined: emit userJoinedEventReceived(static_cast<Event_UserJoined *>(item)); break;
case ItemId_Event_UserLeft: emit userLeftEventReceived(static_cast<Event_UserLeft *>(item)); break;
case ItemId_Event_ServerMessage: emit serverMessageEventReceived(static_cast<Event_ServerMessage *>(item)); break;
case ItemId_Event_ListRooms: emit listRoomsEventReceived(static_cast<Event_ListRooms *>(item)); break;
case ItemId_Event_GameJoined: emit gameJoinedEventReceived(static_cast<Event_GameJoined *>(item)); break;
case ItemId_Event_Message: emit messageEventReceived(static_cast<Event_Message *>(item)); break;
}
if (genericEvent->getReceiverMayDelete())
delete genericEvent;
return;
}
GameEventContainer *gameEventContainer = qobject_cast<GameEventContainer *>(item);
if (gameEventContainer) {
emit gameEventContainerReceived(gameEventContainer);
if (gameEventContainer->getReceiverMayDelete())
delete gameEventContainer;
return;
}
RoomEvent *roomEvent = qobject_cast<RoomEvent *>(item);
if (roomEvent) {
emit roomEventReceived(roomEvent);
if (roomEvent->getReceiverMayDelete())
delete roomEvent;
return;
}
switch (item.message_type()) {
case ServerMessage::RESPONSE: {
const Response &response = item.response();
const int cmdId = response.cmd_id();
PendingCommand *pend = pendingCommands.value(cmdId, 0);
if (!pend)
return;
pendingCommands.remove(cmdId);
pend->processResponse(response);
pend->deleteLater();
break;
}
case ServerMessage::SESSION_EVENT: {
const SessionEvent &event = item.session_event();
switch ((SessionEvent::SessionEventType) getPbExtension(event)) {
case SessionEvent::SERVER_IDENTIFICATION: emit serverIdentificationEventReceived(event.GetExtension(Event_ServerIdentification::ext)); break;
case SessionEvent::SERVER_MESSAGE: emit serverMessageEventReceived(event.GetExtension(Event_ServerMessage::ext)); break;
case SessionEvent::SERVER_SHUTDOWN: emit serverShutdownEventReceived(event.GetExtension(Event_ServerShutdown::ext)); break;
case SessionEvent::CONNECTION_CLOSED: emit connectionClosedEventReceived(event.GetExtension(Event_ConnectionClosed::ext)); break;
case SessionEvent::USER_MESSAGE: emit userMessageEventReceived(event.GetExtension(Event_UserMessage::ext)); break;
case SessionEvent::LIST_ROOMS: emit listRoomsEventReceived(event.GetExtension(Event_ListRooms::ext)); break;
case SessionEvent::ADD_TO_LIST: emit addToListEventReceived(event.GetExtension(Event_AddToList::ext)); break;
case SessionEvent::REMOVE_FROM_LIST: emit removeFromListEventReceived(event.GetExtension(Event_RemoveFromList::ext)); break;
case SessionEvent::USER_JOINED: emit userJoinedEventReceived(event.GetExtension(Event_UserJoined::ext)); break;
case SessionEvent::USER_LEFT: emit userLeftEventReceived(event.GetExtension(Event_UserLeft::ext)); break;
case SessionEvent::GAME_JOINED: emit gameJoinedEventReceived(event.GetExtension(Event_GameJoined::ext)); break;
case SessionEvent::REPLAY_ADDED: emit replayAddedEventReceived(event.GetExtension(Event_ReplayAdded::ext)); break;
default: break;
}
break;
}
case ServerMessage::GAME_EVENT_CONTAINER: {
emit gameEventContainerReceived(item.game_event_container());
break;
}
case ServerMessage::ROOM_EVENT: {
emit roomEventReceived(item.room_event());
break;
}
}
}
void AbstractClient::setStatus(const ClientStatus _status)
{
if (_status != status) {
status = _status;
emit statusChanged(_status);
}
QMutexLocker locker(&clientMutex);
if (_status != status) {
status = _status;
emit statusChanged(_status);
}
}
void AbstractClient::sendCommand(Command *cmd)
void AbstractClient::sendCommand(const CommandContainer &cont)
{
sendCommandContainer(new CommandContainer(QList<Command *>() << cmd));
sendCommand(new PendingCommand(cont));
}
void AbstractClient::sendCommand(PendingCommand *pend)
{
pend->moveToThread(thread());
emit sigQueuePendingCommand(pend);
}
void AbstractClient::queuePendingCommand(PendingCommand *pend)
{
// This function is always called from the client thread via signal/slot.
const int cmdId = getNewCmdId();
pend->getCommandContainer().set_cmd_id(cmdId);
pendingCommands.insert(cmdId, pend);
sendCommandContainer(pend->getCommandContainer());
}
PendingCommand *AbstractClient::prepareSessionCommand(const ::google::protobuf::Message &cmd)
{
CommandContainer cont;
SessionCommand *c = cont.add_session_command();
c->GetReflection()->MutableMessage(c, cmd.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(cmd);
return new PendingCommand(cont);
}
PendingCommand *AbstractClient::prepareRoomCommand(const ::google::protobuf::Message &cmd, int roomId)
{
CommandContainer cont;
RoomCommand *c = cont.add_room_command();
cont.set_room_id(roomId);
c->GetReflection()->MutableMessage(c, cmd.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(cmd);
return new PendingCommand(cont);
}
PendingCommand *AbstractClient::prepareModeratorCommand(const ::google::protobuf::Message &cmd)
{
CommandContainer cont;
ModeratorCommand *c = cont.add_moderator_command();
c->GetReflection()->MutableMessage(c, cmd.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(cmd);
return new PendingCommand(cont);
}
PendingCommand *AbstractClient::prepareAdminCommand(const ::google::protobuf::Message &cmd)
{
CommandContainer cont;
AdminCommand *c = cont.add_admin_command();
c->GetReflection()->MutableMessage(c, cmd.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(cmd);
return new PendingCommand(cont);
}

View file

@ -2,16 +2,17 @@
#define ABSTRACTCLIENT_H
#include <QObject>
#include "protocol_datastructures.h"
#include <QVariant>
#include <QMutex>
#include "pb/response.pb.h"
#include "pb/serverinfo_user.pb.h"
class Command;
class CommandContainer;
class ProtocolItem;
class ProtocolResponse;
class TopLevelProtocolItem;
class PendingCommand;
class CommandContainer;
class RoomEvent;
class GameEventContainer;
class ServerMessage;
class Event_ServerIdentification;
class Event_AddToList;
class Event_RemoveFromList;
class Event_UserJoined;
@ -19,57 +20,73 @@ class Event_UserLeft;
class Event_ServerMessage;
class Event_ListRooms;
class Event_GameJoined;
class Event_Message;
class Event_UserMessage;
class Event_ConnectionClosed;
class Event_ServerShutdown;
class Event_ReplayAdded;
enum ClientStatus {
StatusDisconnected,
StatusDisconnecting,
StatusConnecting,
StatusAwaitingWelcome,
StatusLoggingIn,
StatusLoggedIn,
StatusDisconnected,
StatusDisconnecting,
StatusConnecting,
StatusAwaitingWelcome,
StatusLoggingIn,
StatusLoggedIn
};
class AbstractClient : public QObject {
Q_OBJECT
Q_OBJECT
signals:
void statusChanged(ClientStatus _status);
void serverError(ResponseCode resp);
// Room events
void roomEventReceived(RoomEvent *event);
// Game events
void gameEventContainerReceived(GameEventContainer *event);
// Generic events
void connectionClosedEventReceived(Event_ConnectionClosed *event);
void serverShutdownEventReceived(Event_ServerShutdown *event);
void addToListEventReceived(Event_AddToList *event);
void removeFromListEventReceived(Event_RemoveFromList *event);
void userJoinedEventReceived(Event_UserJoined *event);
void userLeftEventReceived(Event_UserLeft *event);
void serverMessageEventReceived(Event_ServerMessage *event);
void listRoomsEventReceived(Event_ListRooms *event);
void gameJoinedEventReceived(Event_GameJoined *event);
void messageEventReceived(Event_Message *event);
void userInfoChanged(ServerInfo_User *userInfo);
void buddyListReceived(const QList<ServerInfo_User *> &buddyList);
void ignoreListReceived(const QList<ServerInfo_User *> &ignoreList);
void statusChanged(ClientStatus _status);
// Room events
void roomEventReceived(const RoomEvent &event);
// Game events
void gameEventContainerReceived(const GameEventContainer &event);
// Session events
void serverIdentificationEventReceived(const Event_ServerIdentification &event);
void connectionClosedEventReceived(const Event_ConnectionClosed &event);
void serverShutdownEventReceived(const Event_ServerShutdown &event);
void addToListEventReceived(const Event_AddToList &event);
void removeFromListEventReceived(const Event_RemoveFromList &event);
void userJoinedEventReceived(const Event_UserJoined &event);
void userLeftEventReceived(const Event_UserLeft &event);
void serverMessageEventReceived(const Event_ServerMessage &event);
void listRoomsEventReceived(const Event_ListRooms &event);
void gameJoinedEventReceived(const Event_GameJoined &event);
void userMessageEventReceived(const Event_UserMessage &event);
void userInfoChanged(const ServerInfo_User &userInfo);
void buddyListReceived(const QList<ServerInfo_User> &buddyList);
void ignoreListReceived(const QList<ServerInfo_User> &ignoreList);
void replayAddedEventReceived(const Event_ReplayAdded &event);
void sigQueuePendingCommand(PendingCommand *pend);
private:
int nextCmdId;
mutable QMutex clientMutex;
ClientStatus status;
private slots:
void queuePendingCommand(PendingCommand *pend);
protected slots:
void processProtocolItem(ProtocolItem *item);
void processProtocolItem(const ServerMessage &item);
protected:
QMap<int, CommandContainer *> pendingCommands;
ClientStatus status;
QString userName, password;
void setStatus(ClientStatus _status);
QMap<int, PendingCommand *> pendingCommands;
QString userName, password;
void setStatus(ClientStatus _status);
int getNewCmdId() { return nextCmdId++; }
virtual void sendCommandContainer(const CommandContainer &cont) = 0;
public:
AbstractClient(QObject *parent = 0);
~AbstractClient();
ClientStatus getStatus() const { return status; }
virtual void sendCommand(Command *cmd);
virtual void sendCommandContainer(CommandContainer *cont) = 0;
AbstractClient(QObject *parent = 0);
~AbstractClient();
ClientStatus getStatus() const { QMutexLocker locker(&clientMutex); return status; }
void sendCommand(const CommandContainer &cont);
void sendCommand(PendingCommand *pend);
static PendingCommand *prepareSessionCommand(const ::google::protobuf::Message &cmd);
static PendingCommand *prepareRoomCommand(const ::google::protobuf::Message &cmd, int roomId);
static PendingCommand *prepareModeratorCommand(const ::google::protobuf::Message &cmd);
static PendingCommand *prepareAdminCommand(const ::google::protobuf::Message &cmd);
};
#endif
#endif

View file

@ -1,130 +1,155 @@
#include "abstractcounter.h"
#include "player.h"
#include "protocol_items.h"
#include <QPainter>
#include <QMenu>
#include <QAction>
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsSceneHoverEvent>
#include "pb/command_inc_counter.pb.h"
#include "pb/command_set_counter.pb.h"
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)
{
setAcceptsHoverEvents(true);
if (player->getLocal()) {
menu = new QMenu(name);
aSet = new QAction(this);
connect(aSet, SIGNAL(triggered()), this, SLOT(setCounter()));
menu->addAction(aSet);
menu->addSeparator();
for (int i = -10; i <= 10; ++i)
if (i == 0)
menu->addSeparator();
else {
QAction *aIncrement = new QAction(QString(i < 0 ? "%1" : "+%1").arg(i), this);
if (i == -1)
aDec = aIncrement;
else if (i == 1)
aInc = aIncrement;
aIncrement->setData(i);
connect(aIncrement, SIGNAL(triggered()), this, SLOT(incrementCounter()));
menu->addAction(aIncrement);
}
} else
menu = 0;
retranslateUi();
#if QT_VERSION < 0x050000
setAcceptsHoverEvents(true);
#else
setAcceptHoverEvents(true);
#endif
if (player->getLocal()) {
menu = new QMenu(name);
aSet = new QAction(this);
connect(aSet, SIGNAL(triggered()), this, SLOT(setCounter()));
menu->addAction(aSet);
menu->addSeparator();
for (int i = -10; i <= 10; ++i)
if (i == 0)
menu->addSeparator();
else {
QAction *aIncrement = new QAction(QString(i < 0 ? "%1" : "+%1").arg(i), this);
if (i == -1)
aDec = aIncrement;
else if (i == 1)
aInc = aIncrement;
aIncrement->setData(i);
connect(aIncrement, SIGNAL(triggered()), this, SLOT(incrementCounter()));
menu->addAction(aIncrement);
}
} else
menu = 0;
retranslateUi();
}
AbstractCounter::~AbstractCounter()
{
delete menu;
delete menu;
}
void AbstractCounter::delCounter()
{
if (dialogSemaphore)
deleteAfterDialog = true;
else
deleteLater();
if (dialogSemaphore)
deleteAfterDialog = true;
else
deleteLater();
}
void AbstractCounter::retranslateUi()
{
if (menu) {
aSet->setText(tr("&Set counter..."));
}
if (menu) {
aSet->setText(tr("&Set counter..."));
}
}
void AbstractCounter::setShortcutsActive()
{
if (name == "life") {
aSet->setShortcut(tr("Ctrl+L"));
aDec->setShortcut(tr("F11"));
aInc->setShortcut(tr("F12"));
}
if (name == "life") {
aSet->setShortcut(tr("Ctrl+L"));
aDec->setShortcut(tr("F11"));
aInc->setShortcut(tr("F12"));
}
}
void AbstractCounter::setShortcutsInactive()
{
if (name == "life") {
aSet->setShortcut(QKeySequence());
aDec->setShortcut(QKeySequence());
aInc->setShortcut(QKeySequence());
}
if (name == "life") {
aSet->setShortcut(QKeySequence());
aDec->setShortcut(QKeySequence());
aInc->setShortcut(QKeySequence());
}
}
void AbstractCounter::setValue(int _value)
{
value = _value;
update();
value = _value;
update();
}
void AbstractCounter::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
player->sendGameCommand(new Command_IncCounter(-1, id, 1));
event->accept();
} else if (event->button() == Qt::RightButton) {
player->sendGameCommand(new Command_IncCounter(-1, id, -1));
event->accept();
} else if (event->button() == Qt::MidButton) {
if (menu)
menu->exec(event->screenPos());
event->accept();
} else
event->ignore();
if (event->button() == Qt::LeftButton) {
Command_IncCounter cmd;
cmd.set_counter_id(id);
cmd.set_delta(1);
player->sendGameCommand(cmd);
event->accept();
} else if (event->button() == Qt::RightButton) {
Command_IncCounter cmd;
cmd.set_counter_id(id);
cmd.set_delta(-1);
player->sendGameCommand(cmd);
event->accept();
} else if (event->button() == Qt::MidButton) {
if (menu)
menu->exec(event->screenPos());
event->accept();
} else
event->ignore();
}
void AbstractCounter::hoverEnterEvent(QGraphicsSceneHoverEvent * /*event*/)
{
hovered = true;
update();
hovered = true;
update();
}
void AbstractCounter::hoverLeaveEvent(QGraphicsSceneHoverEvent * /*event*/)
{
hovered = false;
update();
hovered = false;
update();
}
void AbstractCounter::incrementCounter()
{
int delta = static_cast<QAction *>(sender())->data().toInt();
player->sendGameCommand(new Command_IncCounter(-1, id, delta));
const int delta = static_cast<QAction *>(sender())->data().toInt();
Command_IncCounter cmd;
cmd.set_counter_id(id);
cmd.set_delta(delta);
player->sendGameCommand(cmd);
}
void AbstractCounter::setCounter()
{
bool ok;
dialogSemaphore = true;
int newValue = QInputDialog::getInteger(0, tr("Set counter"), tr("New value for counter '%1':").arg(name), value, -2000000000, 2000000000, 1, &ok);
if (deleteAfterDialog) {
deleteLater();
return;
}
dialogSemaphore = false;
if (ok)
player->sendGameCommand(new Command_SetCounter(-1, id, newValue));
bool ok;
dialogSemaphore = true;
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) {
deleteLater();
return;
}
dialogSemaphore = false;
if (!ok)
return;
Command_SetCounter cmd;
cmd.set_counter_id(id);
cmd.set_value(newValue);
player->sendGameCommand(cmd);
}

View file

@ -8,41 +8,42 @@ class QMenu;
class QAction;
class AbstractCounter : public QObject, public QGraphicsItem {
Q_OBJECT
Q_OBJECT
Q_INTERFACES(QGraphicsItem)
protected:
Player *player;
int id;
QString name;
int value;
bool hovered;
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
Player *player;
int id;
QString name;
int value;
bool hovered;
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
private:
QAction *aSet, *aDec, *aInc;
QMenu *menu;
bool dialogSemaphore, deleteAfterDialog;
bool shownInCounterArea;
QAction *aSet, *aDec, *aInc;
QMenu *menu;
bool dialogSemaphore, deleteAfterDialog;
bool shownInCounterArea;
private slots:
void incrementCounter();
void setCounter();
void incrementCounter();
void setCounter();
public:
AbstractCounter(Player *_player, int _id, const QString &_name, bool _shownInCounterArea, int _value, QGraphicsItem *parent = 0);
~AbstractCounter();
QMenu *getMenu() const { return menu; }
void retranslateUi();
int getId() const { return id; }
QString getName() const { return name; }
bool getShownInCounterArea() const { return shownInCounterArea; }
int getValue() const { return value; }
void setValue(int _value);
void delCounter();
void setShortcutsActive();
void setShortcutsInactive();
AbstractCounter(Player *_player, int _id, const QString &_name, bool _shownInCounterArea, int _value, QGraphicsItem *parent = 0);
~AbstractCounter();
QMenu *getMenu() const { return menu; }
void retranslateUi();
int getId() const { return id; }
QString getName() const { return name; }
bool getShownInCounterArea() const { return shownInCounterArea; }
int getValue() const { return value; }
void setValue(int _value);
void delCounter();
void setShortcutsActive();
void setShortcutsInactive();
};
#endif

View file

@ -3,48 +3,48 @@
void AbstractGraphicsItem::paintNumberEllipse(int number, int fontSize, const QColor &color, int position, int count, QPainter *painter)
{
painter->save();
painter->save();
QString numStr = QString::number(number);
QFont font("Serif");
font.setPixelSize(fontSize);
font.setWeight(QFont::Bold);
QFontMetrics fm(font);
double w = fm.width(numStr) * 1.3;
double h = fm.height() * 1.3;
if (w < h)
w = h;
QString numStr = QString::number(number);
QFont font("Serif");
font.setPixelSize(fontSize);
font.setWeight(QFont::Bold);
QFontMetrics fm(font);
double w = fm.width(numStr) * 1.3;
double h = fm.height() * 1.3;
if (w < h)
w = h;
painter->setPen(QColor(255, 255, 255, 0));
QRadialGradient grad(QPointF(0.5, 0.5), 0.5);
grad.setCoordinateMode(QGradient::ObjectBoundingMode);
QColor color1(color), color2(color);
color1.setAlpha(255);
color2.setAlpha(0);
grad.setColorAt(0, color1);
grad.setColorAt(0.8, color1);
grad.setColorAt(1, color2);
painter->setBrush(QBrush(grad));
QRectF textRect;
if (position == -1)
textRect = QRectF((boundingRect().width() - w) / 2.0, (boundingRect().height() - h) / 2.0, w, h);
else {
qreal xOffset = 10;
qreal yOffset = 20;
qreal spacing = 2;
if (position < 2)
textRect = QRectF(count == 1 ? ((boundingRect().width() - w) / 2.0) : (position % 2 == 0 ? xOffset : (boundingRect().width() - xOffset - w)), yOffset, w, h);
else
textRect = QRectF(count == 3 ? ((boundingRect().width() - w) / 2.0) : (position % 2 == 0 ? xOffset : (boundingRect().width() - xOffset - w)), yOffset + (spacing + h) * (position / 2), w, h);
}
painter->drawEllipse(textRect);
painter->setPen(QColor(255, 255, 255, 0));
QRadialGradient grad(QPointF(0.5, 0.5), 0.5);
grad.setCoordinateMode(QGradient::ObjectBoundingMode);
QColor color1(color), color2(color);
color1.setAlpha(255);
color2.setAlpha(0);
grad.setColorAt(0, color1);
grad.setColorAt(0.8, color1);
grad.setColorAt(1, color2);
painter->setBrush(QBrush(grad));
QRectF textRect;
if (position == -1)
textRect = QRectF((boundingRect().width() - w) / 2.0, (boundingRect().height() - h) / 2.0, w, h);
else {
qreal xOffset = 10;
qreal yOffset = 20;
qreal spacing = 2;
if (position < 2)
textRect = QRectF(count == 1 ? ((boundingRect().width() - w) / 2.0) : (position % 2 == 0 ? xOffset : (boundingRect().width() - xOffset - w)), yOffset, w, h);
else
textRect = QRectF(count == 3 ? ((boundingRect().width() - w) / 2.0) : (position % 2 == 0 ? xOffset : (boundingRect().width() - xOffset - w)), yOffset + (spacing + h) * (position / 2), w, h);
}
painter->drawEllipse(textRect);
painter->setPen(Qt::black);
painter->setFont(font);
painter->drawText(textRect, Qt::AlignCenter, numStr);
painter->setPen(Qt::black);
painter->setFont(font);
painter->drawText(textRect, Qt::AlignCenter, numStr);
painter->restore();
painter->restore();
}

View file

@ -4,20 +4,21 @@
#include <QGraphicsItem>
enum GraphicsItemType {
typeCard = QGraphicsItem::UserType + 1,
typeCardDrag = QGraphicsItem::UserType + 2,
typeZone = QGraphicsItem::UserType + 3,
typePlayerTarget = QGraphicsItem::UserType + 4,
typeDeckViewCardContainer = QGraphicsItem::UserType + 5,
typeOther = QGraphicsItem::UserType + 6
typeCard = QGraphicsItem::UserType + 1,
typeCardDrag = QGraphicsItem::UserType + 2,
typeZone = QGraphicsItem::UserType + 3,
typePlayerTarget = QGraphicsItem::UserType + 4,
typeDeckViewCardContainer = QGraphicsItem::UserType + 5,
typeOther = QGraphicsItem::UserType + 6
};
class AbstractGraphicsItem : public QObject, public QGraphicsItem {
Q_OBJECT
Q_OBJECT
Q_INTERFACES(QGraphicsItem)
protected:
void paintNumberEllipse(int number, int radius, const QColor &color, int position, int count, QPainter *painter);
void paintNumberEllipse(int number, int radius, const QColor &color, int position, int count, QPainter *painter);
public:
AbstractGraphicsItem(QGraphicsItem *parent = 0) : QObject(), QGraphicsItem(parent) { }
AbstractGraphicsItem(QGraphicsItem *parent = 0) : QObject(), QGraphicsItem(parent) { }
};
#endif

View file

@ -1,136 +1,145 @@
#define _USE_MATH_DEFINES
#include <cmath>
#include "arrowitem.h"
#include "playertarget.h"
#include "carditem.h"
#include "cardzone.h"
#include "player.h"
#include "math.h"
#include "protocol_items.h"
#include <QPainter>
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsScene>
#include <QDebug>
#include "color.h"
#include "pb/command_attach_card.pb.h"
#include "pb/command_create_arrow.pb.h"
#include "pb/command_delete_arrow.pb.h"
ArrowItem::ArrowItem(Player *_player, int _id, ArrowTarget *_startItem, ArrowTarget *_targetItem, const QColor &_color)
: QGraphicsItem(), player(_player), id(_id), startItem(_startItem), targetItem(_targetItem), color(_color), fullColor(true)
{
qDebug() << "ArrowItem constructor: startItem=" << static_cast<QGraphicsItem *>(startItem);
setZValue(2000000005);
if (startItem)
startItem->addArrowFrom(this);
if (targetItem)
targetItem->addArrowTo(this);
if (startItem && targetItem)
updatePath();
qDebug() << "ArrowItem constructor: startItem=" << static_cast<QGraphicsItem *>(startItem);
setZValue(2000000005);
if (startItem)
startItem->addArrowFrom(this);
if (targetItem)
targetItem->addArrowTo(this);
if (startItem && targetItem)
updatePath();
}
ArrowItem::~ArrowItem()
{
qDebug() << "ArrowItem destructor";
qDebug() << "ArrowItem destructor";
}
void ArrowItem::delArrow()
{
if (startItem) {
startItem->removeArrowFrom(this);
startItem = 0;
}
if (targetItem) {
targetItem->setBeingPointedAt(false);
targetItem->removeArrowTo(this);
targetItem = 0;
}
player->removeArrow(this);
deleteLater();
if (startItem) {
startItem->removeArrowFrom(this);
startItem = 0;
}
if (targetItem) {
targetItem->setBeingPointedAt(false);
targetItem->removeArrowTo(this);
targetItem = 0;
}
player->removeArrow(this);
deleteLater();
}
void ArrowItem::updatePath()
{
if (!targetItem)
return;
QPointF endPoint = targetItem->mapToScene(QPointF(targetItem->boundingRect().width() / 2, targetItem->boundingRect().height() / 2));
updatePath(endPoint);
if (!targetItem)
return;
QPointF endPoint = targetItem->mapToScene(QPointF(targetItem->boundingRect().width() / 2, targetItem->boundingRect().height() / 2));
updatePath(endPoint);
}
void ArrowItem::updatePath(const QPointF &endPoint)
{
const double arrowWidth = 15.0;
const double headWidth = 40.0;
const double headLength = headWidth / sqrt(2);
const double phi = 15;
if (!startItem)
return;
QPointF startPoint = startItem->mapToScene(QPointF(startItem->boundingRect().width() / 2, startItem->boundingRect().height() / 2));
QLineF line(startPoint, endPoint);
qreal lineLength = line.length();
prepareGeometryChange();
if (lineLength < 30)
path = QPainterPath();
else {
QPointF c(lineLength / 2, tan(phi * M_PI / 180) * lineLength);
QPainterPath centerLine;
centerLine.moveTo(0, 0);
centerLine.quadTo(c, QPointF(lineLength, 0));
double percentage = 1 - headLength / lineLength;
QPointF arrowBodyEndPoint = centerLine.pointAtPercent(percentage);
QLineF testLine(arrowBodyEndPoint, centerLine.pointAtPercent(percentage + 0.001));
qreal alpha = testLine.angle() - 90;
QPointF endPoint1 = arrowBodyEndPoint + arrowWidth / 2 * QPointF(cos(alpha * M_PI / 180), -sin(alpha * M_PI / 180));
QPointF endPoint2 = arrowBodyEndPoint + arrowWidth / 2 * QPointF(-cos(alpha * M_PI / 180), sin(alpha * M_PI / 180));
QPointF point1 = endPoint1 + (headWidth - arrowWidth) / 2 * QPointF(cos(alpha * M_PI / 180), -sin(alpha * M_PI / 180));
QPointF point2 = endPoint2 + (headWidth - arrowWidth) / 2 * QPointF(-cos(alpha * M_PI / 180), sin(alpha * M_PI / 180));
path = QPainterPath(-arrowWidth / 2 * QPointF(cos((phi - 90) * M_PI / 180), sin((phi - 90) * M_PI / 180)));
path.quadTo(c, endPoint1);
path.lineTo(point1);
path.lineTo(QPointF(lineLength, 0));
path.lineTo(point2);
path.lineTo(endPoint2);
path.quadTo(c, arrowWidth / 2 * QPointF(cos((phi - 90) * M_PI / 180), sin((phi - 90) * M_PI / 180)));
path.lineTo(-arrowWidth / 2 * QPointF(cos((phi - 90) * M_PI / 180), sin((phi - 90) * M_PI / 180)));
}
setPos(startPoint);
setTransform(QTransform().rotate(-line.angle()));
const double arrowWidth = 15.0;
const double headWidth = 40.0;
const double headLength = headWidth / pow(2, 0.5); // aka headWidth / sqrt (2) but this produces a compile error with MSVC++
const double phi = 15;
if (!startItem)
return;
QPointF startPoint = startItem->mapToScene(QPointF(startItem->boundingRect().width() / 2, startItem->boundingRect().height() / 2));
QLineF line(startPoint, endPoint);
qreal lineLength = line.length();
prepareGeometryChange();
if (lineLength < 30)
path = QPainterPath();
else {
QPointF c(lineLength / 2, tan(phi * M_PI / 180) * lineLength);
QPainterPath centerLine;
centerLine.moveTo(0, 0);
centerLine.quadTo(c, QPointF(lineLength, 0));
double percentage = 1 - headLength / lineLength;
QPointF arrowBodyEndPoint = centerLine.pointAtPercent(percentage);
QLineF testLine(arrowBodyEndPoint, centerLine.pointAtPercent(percentage + 0.001));
qreal alpha = testLine.angle() - 90;
QPointF endPoint1 = arrowBodyEndPoint + arrowWidth / 2 * QPointF(cos(alpha * M_PI / 180), -sin(alpha * M_PI / 180));
QPointF endPoint2 = arrowBodyEndPoint + arrowWidth / 2 * QPointF(-cos(alpha * M_PI / 180), sin(alpha * M_PI / 180));
QPointF point1 = endPoint1 + (headWidth - arrowWidth) / 2 * QPointF(cos(alpha * M_PI / 180), -sin(alpha * M_PI / 180));
QPointF point2 = endPoint2 + (headWidth - arrowWidth) / 2 * QPointF(-cos(alpha * M_PI / 180), sin(alpha * M_PI / 180));
path = QPainterPath(-arrowWidth / 2 * QPointF(cos((phi - 90) * M_PI / 180), sin((phi - 90) * M_PI / 180)));
path.quadTo(c, endPoint1);
path.lineTo(point1);
path.lineTo(QPointF(lineLength, 0));
path.lineTo(point2);
path.lineTo(endPoint2);
path.quadTo(c, arrowWidth / 2 * QPointF(cos((phi - 90) * M_PI / 180), sin((phi - 90) * M_PI / 180)));
path.lineTo(-arrowWidth / 2 * QPointF(cos((phi - 90) * M_PI / 180), sin((phi - 90) * M_PI / 180)));
}
setPos(startPoint);
setTransform(QTransform().rotate(-line.angle()));
}
void ArrowItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/)
{
QColor paintColor(color);
if (fullColor)
paintColor.setAlpha(200);
else
paintColor.setAlpha(150);
painter->setBrush(paintColor);
painter->drawPath(path);
QColor paintColor(color);
if (fullColor)
paintColor.setAlpha(200);
else
paintColor.setAlpha(150);
painter->setBrush(paintColor);
painter->drawPath(path);
}
void ArrowItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
if (!player->getLocal()) {
event->ignore();
return;
}
QList<QGraphicsItem *> colliding = scene()->items(event->scenePos());
for (int i = 0; i < colliding.size(); ++i)
if (qgraphicsitem_cast<CardItem *>(colliding[i])) {
event->ignore();
return;
}
event->accept();
if (event->button() == Qt::RightButton)
player->sendGameCommand(new Command_DeleteArrow(-1, id));
if (!player->getLocal()) {
event->ignore();
return;
}
QList<QGraphicsItem *> colliding = scene()->items(event->scenePos());
for (int i = 0; i < colliding.size(); ++i)
if (qgraphicsitem_cast<CardItem *>(colliding[i])) {
event->ignore();
return;
}
event->accept();
if (event->button() == Qt::RightButton) {
Command_DeleteArrow cmd;
cmd.set_arrow_id(id);
player->sendGameCommand(cmd);
}
}
ArrowDragItem::ArrowDragItem(Player *_owner, ArrowTarget *_startItem, const QColor &_color)
@ -140,93 +149,85 @@ ArrowDragItem::ArrowDragItem(Player *_owner, ArrowTarget *_startItem, const QCol
void ArrowDragItem::addChildArrow(ArrowDragItem *childArrow)
{
childArrows.append(childArrow);
childArrows.append(childArrow);
}
void ArrowDragItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
// This ensures that if a mouse move event happens after a call to delArrow(),
// the event will be discarded as it would create some stray pointers.
if (!startItem)
return;
QPointF endPos = event->scenePos();
QList<QGraphicsItem *> colliding = scene()->items(endPos);
ArrowTarget *cursorItem = 0;
qreal cursorItemZ = -1;
for (int i = colliding.size() - 1; i >= 0; i--)
if (qgraphicsitem_cast<PlayerTarget *>(colliding.at(i)) || qgraphicsitem_cast<CardItem *>(colliding.at(i)))
if (colliding.at(i)->zValue() > cursorItemZ) {
cursorItem = static_cast<ArrowTarget *>(colliding.at(i));
cursorItemZ = cursorItem->zValue();
}
if ((cursorItem != targetItem) && targetItem) {
targetItem->setBeingPointedAt(false);
targetItem->removeArrowTo(this);
}
// This ensures that if a mouse move event happens after a call to delArrow(),
// the event will be discarded as it would create some stray pointers.
if (!startItem)
return;
QPointF endPos = event->scenePos();
QList<QGraphicsItem *> colliding = scene()->items(endPos);
ArrowTarget *cursorItem = 0;
qreal cursorItemZ = -1;
for (int i = colliding.size() - 1; i >= 0; i--)
if (qgraphicsitem_cast<PlayerTarget *>(colliding.at(i)) || qgraphicsitem_cast<CardItem *>(colliding.at(i)))
if (colliding.at(i)->zValue() > cursorItemZ) {
cursorItem = static_cast<ArrowTarget *>(colliding.at(i));
cursorItemZ = cursorItem->zValue();
}
if ((cursorItem != targetItem) && targetItem) {
targetItem->setBeingPointedAt(false);
targetItem->removeArrowTo(this);
}
if (!cursorItem) {
fullColor = false;
targetItem = 0;
updatePath(endPos);
} else {
if (cursorItem != targetItem) {
fullColor = true;
if (cursorItem != startItem) {
cursorItem->setBeingPointedAt(true);
cursorItem->addArrowTo(this);
}
targetItem = cursorItem;
}
updatePath();
}
update();
for (int i = 0; i < childArrows.size(); ++i)
childArrows[i]->mouseMoveEvent(event);
fullColor = false;
targetItem = 0;
updatePath(endPos);
} else {
if (cursorItem != targetItem) {
fullColor = true;
if (cursorItem != startItem) {
cursorItem->setBeingPointedAt(true);
cursorItem->addArrowTo(this);
}
targetItem = cursorItem;
}
updatePath();
}
update();
for (int i = 0; i < childArrows.size(); ++i)
childArrows[i]->mouseMoveEvent(event);
}
void ArrowDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
if (!startItem)
return;
if (targetItem && (targetItem != startItem)) {
CardZone *startZone = static_cast<CardItem *>(startItem)->getZone();
// For now, we can safely assume that the start item is always a card.
// The target item can be a player as well.
CardItem *startCard = qgraphicsitem_cast<CardItem *>(startItem);
CardItem *targetCard = qgraphicsitem_cast<CardItem *>(targetItem);
if (targetCard) {
CardZone *targetZone = targetCard->getZone();
player->sendGameCommand(new Command_CreateArrow(
-1,
startZone->getPlayer()->getId(),
startZone->getName(),
startCard->getId(),
targetZone->getPlayer()->getId(),
targetZone->getName(),
targetCard->getId(),
color
));
} else {
PlayerTarget *targetPlayer = qgraphicsitem_cast<PlayerTarget *>(targetItem);
player->sendGameCommand(new Command_CreateArrow(
-1,
startZone->getPlayer()->getId(),
startZone->getName(),
startCard->getId(),
targetPlayer->getOwner()->getId(),
QString(),
-1,
color
));
}
}
delArrow();
if (!startItem)
return;
if (targetItem && (targetItem != startItem)) {
CardZone *startZone = static_cast<CardItem *>(startItem)->getZone();
// For now, we can safely assume that the start item is always a card.
// The target item can be a player as well.
CardItem *startCard = qgraphicsitem_cast<CardItem *>(startItem);
CardItem *targetCard = qgraphicsitem_cast<CardItem *>(targetItem);
for (int i = 0; i < childArrows.size(); ++i)
childArrows[i]->mouseReleaseEvent(event);
Command_CreateArrow cmd;
cmd.mutable_arrow_color()->CopyFrom(convertQColorToColor(color));
cmd.set_start_player_id(startZone->getPlayer()->getId());
cmd.set_start_zone(startZone->getName().toStdString());
cmd.set_start_card_id(startCard->getId());
if (targetCard) {
CardZone *targetZone = targetCard->getZone();
cmd.set_target_player_id(targetZone->getPlayer()->getId());
cmd.set_target_zone(targetZone->getName().toStdString());
cmd.set_target_card_id(targetCard->getId());
} else {
PlayerTarget *targetPlayer = qgraphicsitem_cast<PlayerTarget *>(targetItem);
cmd.set_target_player_id(targetPlayer->getOwner()->getId());
}
player->sendGameCommand(cmd);
}
delArrow();
for (int i = 0; i < childArrows.size(); ++i)
childArrows[i]->mouseReleaseEvent(event);
}
ArrowAttachItem::ArrowAttachItem(ArrowTarget *_startItem)
@ -236,57 +237,57 @@ ArrowAttachItem::ArrowAttachItem(ArrowTarget *_startItem)
void ArrowAttachItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if (!startItem)
return;
if (!startItem)
return;
QPointF endPos = event->scenePos();
QList<QGraphicsItem *> colliding = scene()->items(endPos);
QPointF endPos = event->scenePos();
QList<QGraphicsItem *> colliding = scene()->items(endPos);
ArrowTarget *cursorItem = 0;
qreal cursorItemZ = -1;
qreal cursorItemZ = -1;
for (int i = colliding.size() - 1; i >= 0; i--)
if (qgraphicsitem_cast<CardItem *>(colliding.at(i)))
if (colliding.at(i)->zValue() > cursorItemZ) {
cursorItem = static_cast<ArrowTarget *>(colliding.at(i));
cursorItemZ = cursorItem->zValue();
}
if ((cursorItem != targetItem) && targetItem)
targetItem->setBeingPointedAt(false);
if (colliding.at(i)->zValue() > cursorItemZ) {
cursorItem = static_cast<ArrowTarget *>(colliding.at(i));
cursorItemZ = cursorItem->zValue();
}
if ((cursorItem != targetItem) && targetItem)
targetItem->setBeingPointedAt(false);
if (!cursorItem) {
fullColor = false;
targetItem = 0;
updatePath(endPos);
} else {
fullColor = true;
if (cursorItem != startItem)
cursorItem->setBeingPointedAt(true);
targetItem = cursorItem;
updatePath();
}
update();
fullColor = false;
targetItem = 0;
updatePath(endPos);
} else {
fullColor = true;
if (cursorItem != startItem)
cursorItem->setBeingPointedAt(true);
targetItem = cursorItem;
updatePath();
}
update();
}
void ArrowAttachItem::mouseReleaseEvent(QGraphicsSceneMouseEvent * /*event*/)
{
if (!startItem)
return;
if (!startItem)
return;
if (targetItem && (targetItem != startItem)) {
CardItem *startCard = qgraphicsitem_cast<CardItem *>(startItem);
CardZone *startZone = startCard->getZone();
CardItem *targetCard = qgraphicsitem_cast<CardItem *>(targetItem);
CardZone *targetZone = targetCard->getZone();
if (targetItem && (targetItem != startItem)) {
CardItem *startCard = qgraphicsitem_cast<CardItem *>(startItem);
CardZone *startZone = startCard->getZone();
CardItem *targetCard = qgraphicsitem_cast<CardItem *>(targetItem);
CardZone *targetZone = targetCard->getZone();
Command_AttachCard cmd;
cmd.set_start_zone(startZone->getName().toStdString());
cmd.set_card_id(startCard->getId());
cmd.set_target_player_id(targetZone->getPlayer()->getId());
cmd.set_target_zone(targetZone->getName().toStdString());
cmd.set_target_card_id(targetCard->getId());
player->sendGameCommand(new Command_AttachCard(
-1,
startZone->getName(),
startCard->getId(),
targetZone->getPlayer()->getId(),
targetZone->getName(),
targetCard->getId()
));
}
delArrow();
player->sendGameCommand(cmd);
}
delArrow();
}

View file

@ -10,54 +10,55 @@ class Player;
class ArrowTarget;
class ArrowItem : public QObject, public QGraphicsItem {
Q_OBJECT
Q_OBJECT
Q_INTERFACES(QGraphicsItem)
private:
QPainterPath path;
QMenu *menu;
QPainterPath path;
QMenu *menu;
protected:
Player *player;
int id;
ArrowTarget *startItem, *targetItem;
QColor color;
bool fullColor;
void mousePressEvent(QGraphicsSceneMouseEvent *event);
Player *player;
int id;
ArrowTarget *startItem, *targetItem;
QColor color;
bool fullColor;
void mousePressEvent(QGraphicsSceneMouseEvent *event);
public:
ArrowItem(Player *_player, int _id, ArrowTarget *_startItem, ArrowTarget *_targetItem, const QColor &color);
~ArrowItem();
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
QRectF boundingRect() const { return path.boundingRect(); }
QPainterPath shape() const { return path; }
void updatePath();
void updatePath(const QPointF &endPoint);
int getId() const { return id; }
Player *getPlayer() const { return player; }
void setStartItem(ArrowTarget *_item) { startItem = _item; }
void setTargetItem(ArrowTarget *_item) { targetItem = _item; }
ArrowTarget *getStartItem() const { return startItem; }
ArrowTarget *getTargetItem() const { return targetItem; }
void delArrow();
ArrowItem(Player *_player, int _id, ArrowTarget *_startItem, ArrowTarget *_targetItem, const QColor &color);
~ArrowItem();
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
QRectF boundingRect() const { return path.boundingRect(); }
QPainterPath shape() const { return path; }
void updatePath();
void updatePath(const QPointF &endPoint);
int getId() const { return id; }
Player *getPlayer() const { return player; }
void setStartItem(ArrowTarget *_item) { startItem = _item; }
void setTargetItem(ArrowTarget *_item) { targetItem = _item; }
ArrowTarget *getStartItem() const { return startItem; }
ArrowTarget *getTargetItem() const { return targetItem; }
void delArrow();
};
class ArrowDragItem : public ArrowItem {
Q_OBJECT
Q_OBJECT
private:
QList<ArrowDragItem *> childArrows;
QList<ArrowDragItem *> childArrows;
public:
ArrowDragItem(Player *_owner, ArrowTarget *_startItem, const QColor &_color);
void addChildArrow(ArrowDragItem *childArrow);
ArrowDragItem(Player *_owner, ArrowTarget *_startItem, const QColor &_color);
void addChildArrow(ArrowDragItem *childArrow);
protected:
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
};
class ArrowAttachItem : public ArrowItem {
Q_OBJECT
Q_OBJECT
public:
ArrowAttachItem(ArrowTarget *_startItem);
ArrowAttachItem(ArrowTarget *_startItem);
protected:
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
};
#endif // ARROWITEM_H

View file

@ -3,24 +3,24 @@
#include "player.h"
ArrowTarget::ArrowTarget(Player *_owner, QGraphicsItem *parent)
: AbstractGraphicsItem(parent), owner(_owner), beingPointedAt(false)
: AbstractGraphicsItem(parent), owner(_owner), beingPointedAt(false)
{
}
ArrowTarget::~ArrowTarget()
{
for (int i = 0; i < arrowsFrom.size(); ++i) {
arrowsFrom[i]->setStartItem(0);
arrowsFrom[i]->delArrow();
}
for (int i = 0; i < arrowsTo.size(); ++i) {
arrowsTo[i]->setTargetItem(0);
arrowsTo[i]->delArrow();
}
for (int i = 0; i < arrowsFrom.size(); ++i) {
arrowsFrom[i]->setStartItem(0);
arrowsFrom[i]->delArrow();
}
for (int i = 0; i < arrowsTo.size(); ++i) {
arrowsTo[i]->setTargetItem(0);
arrowsTo[i]->delArrow();
}
}
void ArrowTarget::setBeingPointedAt(bool _beingPointedAt)
{
beingPointedAt = _beingPointedAt;
update();
beingPointedAt = _beingPointedAt;
update();
}

View file

@ -8,27 +8,28 @@ class Player;
class ArrowItem;
class ArrowTarget : public AbstractGraphicsItem {
Q_OBJECT
protected:
Player *owner;
Player *owner;
private:
bool beingPointedAt;
QList<ArrowItem *> arrowsFrom, arrowsTo;
bool beingPointedAt;
QList<ArrowItem *> arrowsFrom, arrowsTo;
public:
ArrowTarget(Player *_owner, QGraphicsItem *parent = 0);
~ArrowTarget();
Player *getOwner() const { return owner; }
void setBeingPointedAt(bool _beingPointedAt);
bool getBeingPointedAt() const { return beingPointedAt; }
const QList<ArrowItem *> &getArrowsFrom() const { return arrowsFrom; }
void addArrowFrom(ArrowItem *arrow) { arrowsFrom.append(arrow); }
void removeArrowFrom(ArrowItem *arrow) { arrowsFrom.removeAt(arrowsFrom.indexOf(arrow)); }
const QList<ArrowItem *> &getArrowsTo() const { return arrowsTo; }
void addArrowTo(ArrowItem *arrow) { arrowsTo.append(arrow); }
void removeArrowTo(ArrowItem *arrow) { arrowsTo.removeAt(arrowsTo.indexOf(arrow)); }
ArrowTarget(Player *_owner, QGraphicsItem *parent = 0);
~ArrowTarget();
Player *getOwner() const { return owner; }
void setBeingPointedAt(bool _beingPointedAt);
bool getBeingPointedAt() const { return beingPointedAt; }
const QList<ArrowItem *> &getArrowsFrom() const { return arrowsFrom; }
void addArrowFrom(ArrowItem *arrow) { arrowsFrom.append(arrow); }
void removeArrowFrom(ArrowItem *arrow) { arrowsFrom.removeAt(arrowsFrom.indexOf(arrow)); }
const QList<ArrowItem *> &getArrowsTo() const { return arrowsTo; }
void addArrowTo(ArrowItem *arrow) { arrowsTo.append(arrow); }
void removeArrowTo(ArrowItem *arrow) { arrowsTo.removeAt(arrowsTo.indexOf(arrow)); }
};
#endif
#endif

File diff suppressed because it is too large Load diff

View file

@ -20,193 +20,240 @@ class QNetworkRequest;
typedef QMap<QString, QString> QStringMap;
// If we don't typedef this, CardInfo::CardInfo will refuse to compile on OS X < 10.9
typedef QMap<QString, int> MuidMap;
class CardSet : public QList<CardInfo *> {
private:
QString shortName, longName;
unsigned int sortKey;
QString shortName, longName;
unsigned int sortKey;
public:
CardSet(const QString &_shortName = QString(), const QString &_longName = QString());
QString getShortName() const { return shortName; }
QString getLongName() const { return longName; }
int getSortKey() const { return sortKey; }
void setSortKey(unsigned int _sortKey);
void updateSortKey();
CardSet(const QString &_shortName = QString(), const QString &_longName = QString());
QString getCorrectedShortName() const;
QString getShortName() const { return shortName; }
QString getLongName() const { return longName; }
int getSortKey() const { return sortKey; }
void setSortKey(unsigned int _sortKey);
void updateSortKey();
};
class SetList : public QList<CardSet *> {
private:
class CompareFunctor;
class CompareFunctor;
public:
void sortByKey();
void sortByKey();
};
class PictureToLoad {
private:
CardInfo *card;
bool stripped;
SetList sortedSets;
int setIndex;
bool hq;
CardInfo *card;
bool stripped;
SetList sortedSets;
int setIndex;
bool hq;
public:
PictureToLoad(CardInfo *_card = 0, bool _stripped = false, bool _hq = true);
CardInfo *getCard() const { return card; }
bool getStripped() const { return stripped; }
QString getSetName() const { return sortedSets[setIndex]->getShortName(); }
bool nextSet();
bool getHq() const { return hq; }
void setHq(bool _hq) { hq = _hq; }
PictureToLoad(CardInfo *_card = 0, bool _stripped = false, bool _hq = true);
CardInfo *getCard() const { return card; }
bool getStripped() const { return stripped; }
QString getSetName() const;
bool nextSet();
bool getHq() const { return hq; }
void setHq(bool _hq) { hq = _hq; }
};
class PictureLoader : public QObject {
Q_OBJECT
Q_OBJECT
private:
QString _picsPath;
QList<PictureToLoad> loadQueue;
QMutex mutex;
QNetworkAccessManager *networkManager;
QList<PictureToLoad> cardsToDownload;
PictureToLoad cardBeingDownloaded;
bool picDownload, downloadRunning, loadQueueRunning;
void startNextPicDownload();
QString _picsPath;
QList<PictureToLoad> loadQueue;
QMutex mutex;
QNetworkAccessManager *networkManager;
QList<PictureToLoad> cardsToDownload;
PictureToLoad cardBeingDownloaded;
bool picDownload, picDownloadHq, downloadRunning, loadQueueRunning;
void startNextPicDownload();
QString getPicUrl(CardInfo* card);
public:
PictureLoader(QObject *parent = 0);
void setPicsPath(const QString &path);
void setPicDownload(bool _picDownload);
void loadImage(CardInfo *card, bool stripped);
PictureLoader(const QString &__picsPath, bool _picDownload, bool _picDownloadHq, QObject *parent = 0);
~PictureLoader();
void setPicsPath(const QString &path);
void setPicDownload(bool _picDownload);
void setPicDownloadHq(bool _picDownloadHq);
void loadImage(CardInfo *card, bool stripped);
private slots:
void picDownloadFinished(QNetworkReply *reply);
void picDownloadFinished(QNetworkReply *reply);
public slots:
void processLoadQueue();
void processLoadQueue();
signals:
void startLoadQueue();
void imageLoaded(CardInfo *card, const QImage &image);
};
class PictureLoadingThread : public QThread {
Q_OBJECT
private:
QString picsPath;
bool picDownload;
PictureLoader *pictureLoader;
QWaitCondition initWaitCondition;
protected:
void run();
public:
PictureLoadingThread(const QString &_picsPath, bool _picDownload, QObject *parent);
~PictureLoadingThread();
PictureLoader *getPictureLoader() const { return pictureLoader; }
void waitForInit();
signals:
void imageLoaded(CardInfo *card, const QImage &image);
void startLoadQueue();
void imageLoaded(CardInfo *card, const QImage &image);
};
class CardInfo : public QObject {
Q_OBJECT
Q_OBJECT
private:
CardDatabase *db;
CardDatabase *db;
QString name;
SetList sets;
QString manacost;
QString cardtype;
QString powtough;
QString text;
QStringList colors;
int loyalty;
QMap<QString, QString> picURLs, picURLsHq, picURLsSt;
bool cipt;
int tableRow;
QPixmap *pixmap;
QMap<int, QPixmap *> scaledPixmapCache;
QString name;
/*
* The name without punctuation or capitalization, for better card tag name
* recognition.
*/
QString simpleName;
bool isToken;
SetList sets;
QString manacost;
QString cardtype;
QString powtough;
QString text;
QStringList colors;
int loyalty;
QStringMap customPicURLs, customPicURLsHq;
MuidMap muIds;
bool cipt;
int tableRow;
QPixmap *pixmap;
QMap<int, QPixmap *> scaledPixmapCache;
public:
CardInfo(CardDatabase *_db,
const QString &_name = QString(),
const QString &_manacost = QString(),
const QString &_cardtype = QString(),
const QString &_powtough = QString(),
const QString &_text = QString(),
const QStringList &_colors = QStringList(),
int _loyalty = 0,
bool cipt = false,
int _tableRow = 0,
const SetList &_sets = SetList(),
const QStringMap &_picURLs = QStringMap(),
const QStringMap &_picURLsHq = QStringMap(),
const QStringMap &_picURLsSt = QStringMap());
~CardInfo();
const QString &getName() const { return name; }
const SetList &getSets() const { return sets; }
const QString &getManaCost() const { return manacost; }
const QString &getCardType() const { return cardtype; }
const QString &getPowTough() const { return powtough; }
const QString &getText() const { return text; }
const int &getLoyalty() const { return loyalty; }
bool getCipt() const { return cipt; }
void setText(const QString &_text) { text = _text; }
const QStringList &getColors() const { return colors; }
QString getPicURL(const QString &set) const { return picURLs.value(set); }
QString getPicURLHq(const QString &set) const { return picURLsHq.value(set); }
QString getPicURLSt(const QString &set) const { return picURLsSt.value(set); }
QString getPicURL() const;
const QMap<QString, QString> &getPicURLs() const { return picURLs; }
QString getMainCardType() const;
QString getCorrectedName() const;
int getTableRow() const { return tableRow; }
void setTableRow(int _tableRow) { tableRow = _tableRow; }
void setLoyalty(int _loyalty) { loyalty = _loyalty; }
void setPicURL(const QString &_set, const QString &_picURL) { picURLs.insert(_set, _picURL); }
void setPicURLHq(const QString &_set, const QString &_picURL) { picURLsHq.insert(_set, _picURL); }
void setPicURLSt(const QString &_set, const QString &_picURL) { picURLsSt.insert(_set, _picURL); }
void addToSet(CardSet *set);
QPixmap *loadPixmap();
QPixmap *getPixmap(QSize size);
void clearPixmapCache();
void clearPixmapCacheMiss();
void imageLoaded(const QImage &image);
CardInfo(CardDatabase *_db,
const QString &_name = QString(),
bool _isToken = false,
const QString &_manacost = QString(),
const QString &_cardtype = QString(),
const QString &_powtough = QString(),
const QString &_text = QString(),
const QStringList &_colors = QStringList(),
int _loyalty = 0,
bool _cipt = false,
int _tableRow = 0,
const SetList &_sets = SetList(),
const QStringMap &_customPicURLs = QStringMap(),
const QStringMap &_customPicURLsHq = QStringMap(),
MuidMap muids = MuidMap());
~CardInfo();
const QString &getName() const { return name; }
bool getIsToken() const { return isToken; }
const SetList &getSets() const { return sets; }
const QString &getManaCost() const { return manacost; }
const QString &getCardType() const { return cardtype; }
const QString &getPowTough() const { return powtough; }
const QString &getText() const { return text; }
const int &getLoyalty() const { return loyalty; }
bool getCipt() const { return cipt; }
void setManaCost(const QString &_manaCost) { manacost = _manaCost; emit cardInfoChanged(this); }
void setCardType(const QString &_cardType) { cardtype = _cardType; emit cardInfoChanged(this); }
void setPowTough(const QString &_powTough) { powtough = _powTough; emit cardInfoChanged(this); }
void setText(const QString &_text) { text = _text; emit cardInfoChanged(this); }
void setColors(const QStringList &_colors) { colors = _colors; emit cardInfoChanged(this); }
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); }
QString getMainCardType() const;
QString getCorrectedName() const;
int getTableRow() const { return tableRow; }
void setTableRow(int _tableRow) { tableRow = _tableRow; }
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 addToSet(CardSet *set);
QPixmap *loadPixmap();
QPixmap *getPixmap(QSize size);
void clearPixmapCache();
void clearPixmapCacheMiss();
void imageLoaded(const QImage &image);
CardSet *getPreferredSet();
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:
void updatePixmapCache();
void updatePixmapCache();
signals:
void pixmapUpdated();
void pixmapUpdated();
void cardInfoChanged(CardInfo *card);
};
enum LoadStatus { Ok, VersionTooOld, Invalid, NotLoaded, FileError, NoCards };
typedef QHash<QString, CardInfo *> CardNameMap;
typedef QHash<QString, CardSet *> SetNameMap;
class CardDatabase : public QObject {
Q_OBJECT
Q_OBJECT
protected:
QHash<QString, CardInfo *> cardHash;
QHash<QString, CardSet *> setHash;
bool loadSuccess;
CardInfo *noCard;
PictureLoadingThread *loadingThread;
/*
* 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;
QThread *pictureLoaderThread;
PictureLoader *pictureLoader;
LoadStatus loadStatus;
private:
void loadCardsFromXml(QXmlStreamReader &xml);
void loadSetsFromXml(QXmlStreamReader &xml);
static const int versionNeeded;
void loadCardsFromXml(QXmlStreamReader &xml);
void loadSetsFromXml(QXmlStreamReader &xml);
CardInfo *getCardFromMap(CardNameMap &cardMap, const QString &cardName, bool createIfNotFound);
public:
CardDatabase(QObject *parent = 0);
~CardDatabase();
void clear();
CardInfo *getCard(const QString &cardName = QString());
CardSet *getSet(const QString &setName);
QList<CardInfo *> getCardList() const { return cardHash.values(); }
SetList getSetList() const;
bool loadFromFile(const QString &fileName);
bool saveToFile(const QString &fileName);
QStringList getAllColors() const;
QStringList getAllMainCardTypes() const;
bool getLoadSuccess() const { return loadSuccess; }
void cacheCardPixmaps(const QStringList &cardNames);
void loadImage(CardInfo *card);
CardDatabase(QObject *parent = 0);
~CardDatabase();
void clear();
void addCard(CardInfo *card);
void removeCard(CardInfo *card);
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);
QList<CardInfo *> getCardList() const { return cards.values(); }
SetList getSetList() const;
LoadStatus loadFromFile(const QString &fileName);
bool saveToFile(const QString &fileName, bool tokens = false);
QStringList getAllColors() const;
QStringList getAllMainCardTypes() const;
LoadStatus getLoadStatus() const { return loadStatus; }
bool getLoadSuccess() const { return loadStatus == Ok; }
void cacheCardPixmaps(const QStringList &cardNames);
void loadImage(CardInfo *card);
public slots:
void clearPixmapCache();
bool loadCardDatabase(const QString &path);
bool loadCardDatabase();
void clearPixmapCache();
LoadStatus loadCardDatabase(const QString &path, bool tokens = false);
private slots:
void imageLoaded(CardInfo *card, QImage image);
void picDownloadChanged();
void picsPathChanged();
void imageLoaded(CardInfo *card, QImage image);
void picDownloadChanged();
void picDownloadHqChanged();
void picsPathChanged();
void loadCardDatabase();
void loadTokenDatabase();
signals:
void cardListChanged();
void cardListChanged();
void cardAdded(CardInfo *card);
void cardRemoved(CardInfo *card);
};
#endif

View file

@ -1,114 +1,180 @@
#include "carddatabasemodel.h"
#include "filtertree.h"
CardDatabaseModel::CardDatabaseModel(CardDatabase *_db, QObject *parent)
: QAbstractListModel(parent), db(_db)
: QAbstractListModel(parent), db(_db)
{
connect(db, SIGNAL(cardListChanged()), this, SLOT(updateCardList()));
cardList = db->getCardList();
connect(db, SIGNAL(cardListChanged()), this, SLOT(updateCardList()));
connect(db, SIGNAL(cardAdded(CardInfo *)), this, SLOT(cardAdded(CardInfo *)));
connect(db, SIGNAL(cardRemoved(CardInfo *)), this, SLOT(cardRemoved(CardInfo *)));
updateCardList();
}
CardDatabaseModel::~CardDatabaseModel()
{
}
int CardDatabaseModel::rowCount(const QModelIndex &/*parent*/) const
{
return cardList.size();
return cardList.size();
}
int CardDatabaseModel::columnCount(const QModelIndex &/*parent*/) const
{
return 5;
return 5;
}
QVariant CardDatabaseModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
if ((index.row() >= cardList.size()) || (index.column() >= 5))
return QVariant();
if (role != Qt::DisplayRole)
return QVariant();
if (!index.isValid())
return QVariant();
if ((index.row() >= cardList.size()) || (index.column() >= 5))
return QVariant();
if (role != Qt::DisplayRole)
return QVariant();
CardInfo *card = cardList.at(index.row());
switch (index.column()){
case 0: return card->getName();
case 1: {
QStringList setList;
const QList<CardSet *> &sets = card->getSets();
for (int i = 0; i < sets.size(); i++)
setList << sets[i]->getShortName();
return setList.join(", ");
}
case 2: return card->getManaCost();
case 3: return card->getCardType();
case 4: return card->getPowTough();
default: return QVariant();
}
CardInfo *card = cardList.at(index.row());
switch (index.column()){
case 0: return card->getName();
case 1: {
QStringList setList;
const QList<CardSet *> &sets = card->getSets();
for (int i = 0; i < sets.size(); i++)
setList << sets[i]->getShortName();
return setList.join(", ");
}
case 2: return card->getManaCost();
case 3: return card->getCardType();
case 4: return card->getPowTough();
default: return QVariant();
}
}
QVariant CardDatabaseModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role != Qt::DisplayRole)
return QVariant();
if (orientation != Qt::Horizontal)
return QVariant();
switch (section) {
case 0: return QString(tr("Name"));
case 1: return QString(tr("Sets"));
case 2: return QString(tr("Mana cost"));
case 3: return QString(tr("Card type"));
case 4: return QString(tr("P/T"));
default: return QVariant();
}
if (role != Qt::DisplayRole)
return QVariant();
if (orientation != Qt::Horizontal)
return QVariant();
switch (section) {
case 0: return QString(tr("Name"));
case 1: return QString(tr("Sets"));
case 2: return QString(tr("Mana cost"));
case 3: return QString(tr("Card type"));
case 4: return QString(tr("P/T"));
default: return QVariant();
}
}
void CardDatabaseModel::updateCardList()
{
cardList = db->getCardList();
reset();
beginResetModel();
for (int i = 0; i < cardList.size(); ++i)
disconnect(cardList[i], 0, this, 0);
cardList = db->getCardList();
for (int i = 0; i < cardList.size(); ++i)
connect(cardList[i], SIGNAL(cardInfoChanged(CardInfo *)), this, SLOT(cardInfoChanged(CardInfo *)));
endResetModel();
}
void CardDatabaseModel::cardInfoChanged(CardInfo *card)
{
const int row = cardList.indexOf(card);
if (row == -1)
return;
emit dataChanged(index(row, 0), index(row, 4));
}
void CardDatabaseModel::cardAdded(CardInfo *card)
{
beginInsertRows(QModelIndex(), cardList.size(), cardList.size());
cardList.append(card);
connect(card, SIGNAL(cardInfoChanged(CardInfo *)), this, SLOT(cardInfoChanged(CardInfo *)));
endInsertRows();
}
void CardDatabaseModel::cardRemoved(CardInfo *card)
{
const int row = cardList.indexOf(card);
if (row == -1)
return;
beginRemoveRows(QModelIndex(), row, row);
cardList.removeAt(row);
endRemoveRows();
}
CardDatabaseDisplayModel::CardDatabaseDisplayModel(QObject *parent)
: QSortFilterProxyModel(parent)
: QSortFilterProxyModel(parent),
isToken(ShowAll)
{
setFilterCaseSensitivity(Qt::CaseInsensitive);
setSortCaseSensitivity(Qt::CaseInsensitive);
filterTree = NULL;
setFilterCaseSensitivity(Qt::CaseInsensitive);
setSortCaseSensitivity(Qt::CaseInsensitive);
}
bool CardDatabaseDisplayModel::filterAcceptsRow(int sourceRow, const QModelIndex & /*sourceParent*/) const
{
CardInfo *info = static_cast<CardDatabaseModel *>(sourceModel())->getCard(sourceRow);
if (!cardNameBeginning.isEmpty())
if (!info->getName().startsWith(cardNameBeginning, Qt::CaseInsensitive))
return false;
if (!cardName.isEmpty())
if (!info->getName().contains(cardName, Qt::CaseInsensitive))
return false;
if (!cardText.isEmpty())
if (!info->getText().contains(cardText, Qt::CaseInsensitive))
return false;
if (!cardColors.isEmpty())
if (QSet<QString>::fromList(info->getColors()).intersect(cardColors).isEmpty() && !(info->getColors().isEmpty() && cardColors.contains("X")))
return false;
if (!cardTypes.isEmpty())
if (!cardTypes.contains(info->getMainCardType()))
return false;
CardInfo const *info = static_cast<CardDatabaseModel *>(sourceModel())->getCard(sourceRow);
if (((isToken == ShowTrue) && !info->getIsToken()) || ((isToken == ShowFalse) && info->getIsToken()))
return false;
if (!cardNameBeginning.isEmpty())
if (!info->getName().startsWith(cardNameBeginning, Qt::CaseInsensitive))
return false;
if (!cardName.isEmpty())
if (!info->getName().contains(cardName, Qt::CaseInsensitive))
return false;
if (!cardNameSet.isEmpty())
if (!cardNameSet.contains(info->getName()))
return false;
if (!cardText.isEmpty())
if (!info->getText().contains(cardText, Qt::CaseInsensitive))
return false;
if (!cardColors.isEmpty())
if (QSet<QString>::fromList(info->getColors()).intersect(cardColors).isEmpty() && !(info->getColors().isEmpty() && cardColors.contains("X")))
return false;
if (!cardTypes.isEmpty())
if (!cardTypes.contains(info->getMainCardType()))
return false;
return true;
if (filterTree != NULL)
return filterTree->acceptsCard(info);
return true;
}
void CardDatabaseDisplayModel::clearSearch()
{
cardName.clear();
cardText.clear();
cardTypes.clear();
cardColors.clear();
invalidateFilter();
cardName.clear();
cardText.clear();
cardTypes.clear();
cardColors.clear();
if (filterTree != NULL)
filterTree->clear();
invalidateFilter();
}
void CardDatabaseDisplayModel::setFilterTree(FilterTree *filterTree)
{
if (this->filterTree != NULL)
disconnect(this->filterTree, 0, this, 0);
this->filterTree = filterTree;
connect(this->filterTree, SIGNAL(changed()), this, SLOT(filterTreeChanged()));
invalidate();
}
void CardDatabaseDisplayModel::filterTreeChanged()
{
invalidate();
}

View file

@ -7,38 +7,53 @@
#include <QSet>
#include "carddatabase.h"
class FilterTree;
class CardDatabaseModel : public QAbstractListModel {
Q_OBJECT
Q_OBJECT
public:
CardDatabaseModel(CardDatabase *_db, QObject *parent = 0);
~CardDatabaseModel();
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
CardInfo *getCard(int index) const { return cardList[index]; }
CardDatabaseModel(CardDatabase *_db, QObject *parent = 0);
~CardDatabaseModel();
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
CardDatabase *getDatabase() const { return db; }
CardInfo *getCard(int index) const { return cardList[index]; }
private:
QList<CardInfo *> cardList;
CardDatabase *db;
QList<CardInfo *> cardList;
CardDatabase *db;
private slots:
void updateCardList();
void updateCardList();
void cardAdded(CardInfo *card);
void cardRemoved(CardInfo *card);
void cardInfoChanged(CardInfo *card);
};
class CardDatabaseDisplayModel : public QSortFilterProxyModel {
Q_OBJECT
private:
QString cardNameBeginning, cardName, cardText;
QSet<QString> cardTypes, cardColors;
Q_OBJECT
public:
CardDatabaseDisplayModel(QObject *parent = 0);
void setCardNameBeginning(const QString &_beginning) { cardNameBeginning = _beginning; invalidate(); }
void setCardName(const QString &_cardName) { cardName = _cardName; invalidate(); }
void setCardText(const QString &_cardText) { cardText = _cardText; invalidate(); }
void setCardTypes(const QSet<QString> &_cardTypes) { cardTypes = _cardTypes; invalidate(); }
void setCardColors(const QSet<QString> &_cardColors) { cardColors = _cardColors; invalidate(); }
void clearSearch();
enum FilterBool { ShowTrue, ShowFalse, ShowAll };
private:
FilterBool isToken;
QString cardNameBeginning, cardName, cardText;
QSet<QString> cardNameSet, cardTypes, cardColors;
FilterTree *filterTree;
public:
CardDatabaseDisplayModel(QObject *parent = 0);
void setFilterTree(FilterTree *filterTree);
void setIsToken(FilterBool _isToken) { isToken = _isToken; invalidate(); }
void setCardNameBeginning(const QString &_beginning) { cardNameBeginning = _beginning; invalidate(); }
void setCardName(const QString &_cardName) { cardName = _cardName; invalidate(); }
void setCardNameSet(const QSet<QString> &_cardNameSet) { cardNameSet = _cardNameSet; invalidate(); }
void setCardText(const QString &_cardText) { cardText = _cardText; invalidate(); }
void setCardTypes(const QSet<QString> &_cardTypes) { cardTypes = _cardTypes; invalidate(); }
void setCardColors(const QSet<QString> &_cardColors) { cardColors = _cardColors; invalidate(); }
void clearSearch();
protected:
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
private slots:
void filterTreeChanged();
};
#endif

View file

@ -1,4 +1,5 @@
#include "carddragitem.h"
#include "carditem.h"
#include "cardzone.h"
#include "tablezone.h"
#include "zoneviewzone.h"
@ -8,82 +9,82 @@
#include <QPainter>
CardDragItem::CardDragItem(CardItem *_item, int _id, const QPointF &_hotSpot, bool _faceDown, AbstractCardDragItem *parentDrag)
: AbstractCardDragItem(_item, _hotSpot, parentDrag), id(_id), faceDown(_faceDown), occupied(false), currentZone(0)
: AbstractCardDragItem(_item, _hotSpot, parentDrag), id(_id), faceDown(_faceDown), occupied(false), currentZone(0)
{
}
void CardDragItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
AbstractCardDragItem::paint(painter, option, widget);
if (occupied)
painter->fillRect(boundingRect(), QColor(200, 0, 0, 100));
AbstractCardDragItem::paint(painter, option, widget);
if (occupied)
painter->fillRect(boundingRect(), QColor(200, 0, 0, 100));
}
void CardDragItem::updatePosition(const QPointF &cursorScenePos)
{
QList<QGraphicsItem *> colliding = scene()->items(cursorScenePos, Qt::IntersectsItemBoundingRect, Qt::DescendingOrder, static_cast<GameScene *>(scene())->getViewTransform());
QList<QGraphicsItem *> colliding = scene()->items(cursorScenePos, Qt::IntersectsItemBoundingRect, Qt::DescendingOrder, static_cast<GameScene *>(scene())->getViewTransform());
CardZone *cardZone = 0;
ZoneViewZone *zoneViewZone = 0;
for (int i = colliding.size() - 1; i >= 0; i--) {
CardZone *temp = qgraphicsitem_cast<CardZone *>(colliding.at(i));
if (!cardZone)
cardZone = temp;
if (!zoneViewZone)
zoneViewZone = qobject_cast<ZoneViewZone *>(temp);
}
CardZone *cursorZone = 0;
if (zoneViewZone)
cursorZone = zoneViewZone;
else if (cardZone)
cursorZone = cardZone;
if (!cursorZone)
return;
currentZone = cursorZone;
QPointF zonePos = currentZone->scenePos();
QPointF cursorPosInZone = cursorScenePos - zonePos;
QPointF cardTopLeft = cursorPosInZone - hotSpot;
QPointF closestGridPoint = cursorZone->closestGridPoint(cardTopLeft);
QPointF newPos = zonePos + closestGridPoint;
if (newPos != pos()) {
for (int i = 0; i < childDrags.size(); i++)
childDrags[i]->setPos(newPos + childDrags[i]->getHotSpot());
setPos(newPos);
bool newOccupied = false;
TableZone *table = qobject_cast<TableZone *>(cursorZone);
if (table)
if (table->getCardFromCoords(closestGridPoint))
newOccupied = true;
if (newOccupied != occupied) {
occupied = newOccupied;
update();
}
}
CardZone *cardZone = 0;
ZoneViewZone *zoneViewZone = 0;
for (int i = colliding.size() - 1; i >= 0; i--) {
CardZone *temp = qgraphicsitem_cast<CardZone *>(colliding.at(i));
if (!cardZone)
cardZone = temp;
if (!zoneViewZone)
zoneViewZone = qobject_cast<ZoneViewZone *>(temp);
}
CardZone *cursorZone = 0;
if (zoneViewZone)
cursorZone = zoneViewZone;
else if (cardZone)
cursorZone = cardZone;
if (!cursorZone)
return;
currentZone = cursorZone;
QPointF zonePos = currentZone->scenePos();
QPointF cursorPosInZone = cursorScenePos - zonePos;
QPointF cardTopLeft = cursorPosInZone - hotSpot;
QPointF closestGridPoint = cursorZone->closestGridPoint(cardTopLeft);
QPointF newPos = zonePos + closestGridPoint;
if (newPos != pos()) {
for (int i = 0; i < childDrags.size(); i++)
childDrags[i]->setPos(newPos + childDrags[i]->getHotSpot());
setPos(newPos);
bool newOccupied = false;
TableZone *table = qobject_cast<TableZone *>(cursorZone);
if (table)
if (table->getCardFromCoords(closestGridPoint))
newOccupied = true;
if (newOccupied != occupied) {
occupied = newOccupied;
update();
}
}
}
void CardDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
setCursor(Qt::OpenHandCursor);
QGraphicsScene *sc = scene();
QPointF sp = pos();
sc->removeItem(this);
setCursor(Qt::OpenHandCursor);
QGraphicsScene *sc = scene();
QPointF sp = pos();
sc->removeItem(this);
QList<CardDragItem *> dragItemList;
CardZone *startZone = static_cast<CardItem *>(item)->getZone();
if (currentZone && !(static_cast<CardItem *>(item)->getAttachedTo() && (startZone == currentZone))) {
dragItemList.append(this);
for (int i = 0; i < childDrags.size(); i++) {
CardDragItem *c = static_cast<CardDragItem *>(childDrags[i]);
if (!(static_cast<CardItem *>(c->item)->getAttachedTo() && (startZone == currentZone)) && !c->occupied)
dragItemList.append(c);
sc->removeItem(c);
}
}
currentZone->handleDropEvent(dragItemList, startZone, (sp - currentZone->scenePos()).toPoint());
QList<CardDragItem *> dragItemList;
CardZone *startZone = static_cast<CardItem *>(item)->getZone();
if (currentZone && !(static_cast<CardItem *>(item)->getAttachedTo() && (startZone == currentZone))) {
dragItemList.append(this);
for (int i = 0; i < childDrags.size(); i++) {
CardDragItem *c = static_cast<CardDragItem *>(childDrags[i]);
if (!(static_cast<CardItem *>(c->item)->getAttachedTo() && (startZone == currentZone)) && !c->occupied)
dragItemList.append(c);
sc->removeItem(c);
}
}
currentZone->handleDropEvent(dragItemList, startZone, (sp - currentZone->scenePos()).toPoint());
event->accept();
event->accept();
}

View file

@ -6,19 +6,20 @@
class CardItem;
class CardDragItem : public AbstractCardDragItem {
Q_OBJECT
private:
int id;
bool faceDown;
bool occupied;
CardZone *currentZone;
int id;
bool faceDown;
bool occupied;
CardZone *currentZone;
public:
CardDragItem(CardItem *_item, int _id, const QPointF &_hotSpot, bool _faceDown, AbstractCardDragItem *parentDrag = 0);
int getId() const { return id; }
bool getFaceDown() const { return faceDown; }
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
void updatePosition(const QPointF &cursorScenePos);
CardDragItem(CardItem *_item, int _id, const QPointF &_hotSpot, bool _faceDown, AbstractCardDragItem *parentDrag = 0);
int getId() const { return id; }
bool getFaceDown() const { return faceDown; }
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
void updatePosition(const QPointF &cursorScenePos);
protected:
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
};
#endif

View file

@ -0,0 +1,37 @@
#include "cardfilter.h"
const char *CardFilter::typeName(Type t)
{
switch (t) {
case TypeAnd:
return "and";
case TypeOr:
return "or";
case TypeAndNot:
return "and not";
case TypeOrNot:
return "or not";
default:
return "";
}
}
const char *CardFilter::attrName(Attr a)
{
switch (a) {
case AttrName:
return "name";
case AttrType:
return "type";
case AttrColor:
return "color";
case AttrText:
return "text";
case AttrSet:
return "set";
case AttrManaCost:
return "mana cost";
default:
return "";
}
}

View file

@ -0,0 +1,44 @@
#ifndef CARDFILTER_H
#define CARDFILTER_H
#include <QString>
class CardFilter {
public:
enum Type {
TypeAnd = 0,
TypeOr,
TypeAndNot,
TypeOrNot,
TypeEnd
};
/* if you add an atribute here you also need to
* add its string representation in attrName */
enum Attr {
AttrName = 0,
AttrType,
AttrColor,
AttrText,
AttrSet,
AttrManaCost,
AttrEnd
};
private:
QString trm;
enum Type t;
enum Attr a;
public:
CardFilter(QString term, Type type, Attr attr) : trm(term), t(type), a(attr) {};
Type type() const { return t; }
const QString &term() const { return trm; }
Attr attr() const { return a; }
static const char *typeName(Type t);
static const char *attrName(Attr a);
};
#endif

View file

@ -0,0 +1,59 @@
#include "cardframe.h"
#include "carditem.h"
#include "carddatabase.h"
#include "main.h"
#include "cardinfopicture.h"
#include "cardinfotext.h"
CardFrame::CardFrame(int width, int height,
const QString &cardName, QWidget *parent)
: QStackedWidget(parent)
, info(0)
, cardTextOnly(false)
{
setFrameStyle(QFrame::Panel | QFrame::Raised);
setMaximumWidth(width);
setMinimumWidth(width);
setMaximumHeight(height);
setMinimumHeight(height);
pic = new CardInfoPicture(width);
addWidget(pic);
text = new CardInfoText();
addWidget(text);
connect(pic, SIGNAL(hasPictureChanged()), this, SLOT(hasPictureChanged()));
setCard(db->getCard(cardName));
}
void CardFrame::setCard(CardInfo *card)
{
if (info)
disconnect(info, 0, this, 0);
info = card;
connect(info, SIGNAL(destroyed()), this, SLOT(clear()));
text->setCard(info);
pic->setCard(info);
}
void CardFrame::setCard(const QString &cardName)
{
setCard(db->getCard(cardName));
}
void CardFrame::setCard(AbstractCardItem *card)
{
setCard(card->getInfo());
}
void CardFrame::clear()
{
setCard(db->getCard());
}
void CardFrame::hasPictureChanged()
{
if (pic->hasPicture() && !cardTextOnly)
setCurrentWidget(pic);
else
setCurrentWidget(text);
}

View file

@ -0,0 +1,36 @@
#ifndef CARDFRAME_H
#define CARDFRAME_H
#include <QStackedWidget>
class AbstractCardItem;
class CardInfo;
class CardInfoPicture;
class CardInfoText;
class CardFrame : public QStackedWidget {
Q_OBJECT
private:
CardInfo *info;
CardInfoPicture *pic;
CardInfoText *text;
bool cardTextOnly;
public:
CardFrame(int width, int height, const QString &cardName = QString(),
QWidget *parent = 0);
void setCardTextOnly(bool status) { cardTextOnly = status; hasPictureChanged(); }
public slots:
void setCard(CardInfo *card);
void setCard(const QString &cardName);
void setCard(AbstractCardItem *card);
void clear();
private slots:
void hasPictureChanged();
void toggleCardTextOnly() { setCardTextOnly(!cardTextOnly); }
};
#endif

View file

@ -0,0 +1,53 @@
#include "cardinfopicture.h"
#include <QLabel>
#include "carditem.h"
#include "carddatabase.h"
#include "main.h"
CardInfoPicture::CardInfoPicture(int maximumWidth, QWidget *parent)
: QLabel(parent)
, info(0)
, noPicture(true)
{
setMaximumWidth(maximumWidth);
}
void CardInfoPicture::setNoPicture(bool status)
{
if (noPicture != status) {
noPicture = status;
emit hasPictureChanged();
}
}
void CardInfoPicture::setCard(CardInfo *card)
{
if (info)
disconnect(info, 0, this, 0);
info = card;
connect(info, SIGNAL(pixmapUpdated()), this, SLOT(updatePixmap()));
updatePixmap();
}
void CardInfoPicture::updatePixmap()
{
qreal aspectRatio = (qreal) CARD_HEIGHT / (qreal) CARD_WIDTH;
qreal pixmapWidth = this->width();
if (pixmapWidth == 0) {
setNoPicture(true);
return;
}
QPixmap *resizedPixmap = info->getPixmap(QSize(pixmapWidth, pixmapWidth * aspectRatio));
if (resizedPixmap) {
setNoPicture(false);
this->setPixmap(*resizedPixmap);
}
else {
setNoPicture(true);
this->setPixmap(*(db->getCard()->getPixmap(QSize(pixmapWidth, pixmapWidth * aspectRatio))));
}
}

View file

@ -0,0 +1,34 @@
#ifndef CARDINFOPICTURE_H
#define CARDINFOPICTURE_H
#include <QLabel>
class AbstractCardItem;
class CardInfo;
class CardInfoPicture : public QLabel {
Q_OBJECT
signals:
void hasPictureChanged();
private:
CardInfo *info;
bool noPicture;
public:
CardInfoPicture(int maximumWidth, QWidget *parent = 0);
bool hasPicture() const { return !noPicture; }
private:
void setNoPicture(bool status);
public slots:
void setCard(CardInfo *card);
private slots:
void updatePixmap();
};
#endif

View file

@ -0,0 +1,67 @@
#include "cardinfotext.h"
#include <QLabel>
#include <QTextEdit>
#include <QGridLayout>
#include "carditem.h"
#include "carddatabase.h"
#include "main.h"
CardInfoText::CardInfoText(QWidget *parent)
: QFrame(parent)
, info(0)
{
nameLabel1 = new QLabel;
nameLabel2 = new QLabel;
nameLabel2->setWordWrap(true);
manacostLabel1 = new QLabel;
manacostLabel2 = new QLabel;
manacostLabel2->setWordWrap(true);
cardtypeLabel1 = new QLabel;
cardtypeLabel2 = new QLabel;
cardtypeLabel2->setWordWrap(true);
powtoughLabel1 = new QLabel;
powtoughLabel2 = new QLabel;
loyaltyLabel1 = new QLabel;
loyaltyLabel2 = new QLabel;
textLabel = new QTextEdit();
textLabel->setReadOnly(true);
QGridLayout *grid = new QGridLayout(this);
int row = 0;
grid->addWidget(nameLabel1, row, 0);
grid->addWidget(nameLabel2, row++, 1);
grid->addWidget(manacostLabel1, row, 0);
grid->addWidget(manacostLabel2, row++, 1);
grid->addWidget(cardtypeLabel1, row, 0);
grid->addWidget(cardtypeLabel2, row++, 1);
grid->addWidget(powtoughLabel1, row, 0);
grid->addWidget(powtoughLabel2, row++, 1);
grid->addWidget(loyaltyLabel1, row, 0);
grid->addWidget(loyaltyLabel2, row++, 1);
grid->addWidget(textLabel, row, 0, -1, 2);
grid->setRowStretch(row, 1);
grid->setColumnStretch(1, 1);
retranslateUi();
}
void CardInfoText::setCard(CardInfo *card)
{
nameLabel2->setText(card->getName());
manacostLabel2->setText(card->getManaCost());
cardtypeLabel2->setText(card->getCardType());
powtoughLabel2->setText(card->getPowTough());
loyaltyLabel2->setText(card->getLoyalty() > 0 ? QString::number(card->getLoyalty()) : QString());
textLabel->setText(card->getText());
}
void CardInfoText::retranslateUi()
{
nameLabel1->setText(tr("Name:"));
manacostLabel1->setText(tr("Mana cost:"));
cardtypeLabel1->setText(tr("Card type:"));
powtoughLabel1->setText(tr("P / T:"));
loyaltyLabel1->setText(tr("Loyalty:"));
}

View file

@ -0,0 +1,31 @@
#ifndef CARDINFOTEXT_H
#define CARDINFOTEXT_H
#include <QFrame>
class QLabel;
class QTextEdit;
class CardInfo;
class CardInfoText : public QFrame {
Q_OBJECT
private:
QLabel *nameLabel1, *nameLabel2;
QLabel *manacostLabel1, *manacostLabel2;
QLabel *cardtypeLabel1, *cardtypeLabel2;
QLabel *powtoughLabel1, *powtoughLabel2;
QLabel *loyaltyLabel1, *loyaltyLabel2;
QTextEdit *textLabel;
CardInfo *info;
public:
CardInfoText(QWidget *parent = 0);
void retranslateUi();
public slots:
void setCard(CardInfo *card);
};
#endif

View file

@ -4,180 +4,221 @@
#include <QPushButton>
#include <QStyle>
#include <QMouseEvent>
#include <QDesktopWidget>
#include "cardinfowidget.h"
#include "carditem.h"
#include "carddatabase.h"
#include "main.h"
#include "settingscache.h"
CardInfoWidget::CardInfoWidget(ResizeMode _mode, QWidget *parent, Qt::WindowFlags flags)
: QFrame(parent, flags)
, pixmapWidth(160)
, aspectRatio((qreal) CARD_HEIGHT / (qreal) CARD_WIDTH)
, minimized(settingsCache->getCardInfoMinimized()) // Initialize the cardinfo view status from cache.
, mode(_mode)
, info(0)
CardInfoWidget::CardInfoWidget(ResizeMode _mode, const QString &cardName, QWidget *parent, Qt::WindowFlags flags)
: QFrame(parent, flags)
, pixmapWidth(0)
, aspectRatio((qreal) CARD_HEIGHT / (qreal) CARD_WIDTH)
, minimized(settingsCache->getCardInfoMinimized()) // Initialize the cardinfo view status from cache.
, mode(_mode)
, info(0)
{
if (mode == ModeGameTab) {
// Create indexed list of status views for card.
const QStringList cardInfoStatus = QStringList() << tr("Show card only") << tr("Show text only") << tr("Show full info");
// Create droplist for cardinfo view selection, and set right current index.
dropList = new QComboBox();
dropList->addItems(cardInfoStatus);
dropList->setCurrentIndex(minimized);
connect(dropList, SIGNAL(currentIndexChanged(int)), this, SLOT(minimizeClicked(int)));
}
if (mode == ModeGameTab) {
// Create indexed list of status views for card.
const QStringList cardInfoStatus = QStringList() << tr("Show card only") << tr("Show text only") << tr("Show full info");
// Create droplist for cardinfo view selection, and set right current index.
dropList = new QComboBox();
dropList->addItems(cardInfoStatus);
dropList->setCurrentIndex(minimized);
connect(dropList, SIGNAL(currentIndexChanged(int)), this, SLOT(minimizeClicked(int)));
}
cardPicture = new QLabel;
cardPicture->setAlignment(Qt::AlignCenter);
cardPicture = new QLabel;
cardPicture->setAlignment(Qt::AlignCenter);
nameLabel1 = new QLabel;
nameLabel2 = new QLabel;
nameLabel2->setWordWrap(true);
manacostLabel1 = new QLabel;
manacostLabel2 = new QLabel;
manacostLabel2->setWordWrap(true);
cardtypeLabel1 = new QLabel;
cardtypeLabel2 = new QLabel;
cardtypeLabel2->setWordWrap(true);
powtoughLabel1 = new QLabel;
powtoughLabel2 = new QLabel;
nameLabel1 = new QLabel;
nameLabel2 = new QLabel;
nameLabel2->setWordWrap(true);
manacostLabel1 = new QLabel;
manacostLabel2 = new QLabel;
manacostLabel2->setWordWrap(true);
cardtypeLabel1 = new QLabel;
cardtypeLabel2 = new QLabel;
cardtypeLabel2->setWordWrap(true);
powtoughLabel1 = new QLabel;
powtoughLabel2 = new QLabel;
loyaltyLabel1 = new QLabel;
loyaltyLabel2 = new QLabel;
textLabel = new QTextEdit();
textLabel->setReadOnly(true);
textLabel = new QTextEdit();
textLabel->setReadOnly(true);
QGridLayout *grid = new QGridLayout(this);
int row = 0;
if (mode == ModeGameTab)
grid->addWidget(dropList, row++, 1, 1, 1, Qt::AlignRight);
grid->addWidget(cardPicture, row++, 0, 1, 2);
grid->addWidget(nameLabel1, row, 0);
grid->addWidget(nameLabel2, row++, 1);
grid->addWidget(manacostLabel1, row, 0);
grid->addWidget(manacostLabel2, row++, 1);
grid->addWidget(cardtypeLabel1, row, 0);
grid->addWidget(cardtypeLabel2, row++, 1);
grid->addWidget(powtoughLabel1, row, 0);
grid->addWidget(powtoughLabel2, row++, 1);
grid->addWidget(textLabel, row, 0, -1, 2);
grid->setRowStretch(row, 1);
grid->setColumnStretch(1, 1);
QGridLayout *grid = new QGridLayout(this);
int row = 0;
if (mode == ModeGameTab)
grid->addWidget(dropList, row++, 1, 1, 1, Qt::AlignRight);
grid->addWidget(cardPicture, row++, 0, 1, 2);
grid->addWidget(nameLabel1, row, 0);
grid->addWidget(nameLabel2, row++, 1);
grid->addWidget(manacostLabel1, row, 0);
grid->addWidget(manacostLabel2, row++, 1);
grid->addWidget(cardtypeLabel1, row, 0);
grid->addWidget(cardtypeLabel2, row++, 1);
grid->addWidget(powtoughLabel1, row, 0);
grid->addWidget(powtoughLabel2, row++, 1);
grid->addWidget(loyaltyLabel1, row, 0);
grid->addWidget(loyaltyLabel2, row++, 1);
grid->addWidget(textLabel, row, 0, -1, 2);
grid->setRowStretch(row, 1);
grid->setColumnStretch(1, 1);
CardInfo *cardBack = db->getCard();
setCard(cardBack);
retranslateUi();
setFrameStyle(QFrame::Panel | QFrame::Raised);
if (mode == ModeGameTab) {
textLabel->setMinimumHeight(100);
setFixedWidth(sizeHint().width());
} else if (mode == ModePopUp)
setFixedWidth(350);
else
setFixedWidth(250);
setMinimized(settingsCache->getCardInfoMinimized());
retranslateUi();
setFrameStyle(QFrame::Panel | QFrame::Raised);
if (mode == ModeGameTab) {
textLabel->setMinimumHeight(100);
setFixedWidth(sizeHint().width());
} else if (mode == ModePopUp) {
QDesktopWidget desktopWidget;
pixmapWidth = desktopWidget.screenGeometry().height() / 3 / aspectRatio;
setFixedWidth(pixmapWidth + 150);
} else
setFixedWidth(250);
setCard(getCard(cardName));
setMinimized(settingsCache->getCardInfoMinimized());
}
void CardInfoWidget::minimizeClicked(int newMinimized)
{
// Set new status, and store it in the settings cache.
setMinimized(newMinimized);
settingsCache->setCardInfoMinimized(newMinimized);
// Set new status, and store it in the settings cache.
setMinimized(newMinimized);
settingsCache->setCardInfoMinimized(newMinimized);
}
bool CardInfoWidget::shouldShowPowTough()
{
// return (!info->getPowTough().isEmpty() && (minimized != 0));
return (minimized != 0);
}
bool CardInfoWidget::shouldShowLoyalty()
{
// return ((info->getLoyalty() > 0) && (minimized != 0));
return (minimized != 0);
}
void CardInfoWidget::setMinimized(int _minimized)
{
minimized = _minimized;
minimized = _minimized;
// Toggle oracle fields according to selected view.
bool showAll = ((minimized == 1) || (minimized == 2));
if (mode == ModeGameTab) {
nameLabel1->setVisible(showAll);
nameLabel2->setVisible(showAll);
manacostLabel1->setVisible(showAll);
manacostLabel2->setVisible(showAll);
cardtypeLabel1->setVisible(showAll);
cardtypeLabel2->setVisible(showAll);
powtoughLabel1->setVisible(showAll);
powtoughLabel2->setVisible(showAll);
textLabel->setVisible(showAll);
}
// Toggle oracle fields according to selected view.
bool showAll = ((minimized == 1) || (minimized == 2));
bool showPowTough = info ? (showAll && shouldShowPowTough()) : true;
bool showLoyalty = info ? (showAll && shouldShowLoyalty()) : true;
if (mode == ModeGameTab) {
nameLabel1->setVisible(showAll);
nameLabel2->setVisible(showAll);
manacostLabel1->setVisible(showAll);
manacostLabel2->setVisible(showAll);
cardtypeLabel1->setVisible(showAll);
cardtypeLabel2->setVisible(showAll);
powtoughLabel1->setVisible(showPowTough);
powtoughLabel2->setVisible(showPowTough);
loyaltyLabel1->setVisible(showLoyalty);
loyaltyLabel2->setVisible(showLoyalty);
textLabel->setVisible(showAll);
}
cardPicture->hide();
cardHeightOffset = minimumSizeHint().height() + 10;
// Set the picture to be shown only at "card only" (0) and "full info" (2)
if (mode == ModeGameTab) {
cardPicture->setVisible((minimized == 0) || (minimized == 2));
cardPicture->hide();
cardHeightOffset = minimumSizeHint().height() + 10;
// Set the picture to be shown only at "card only" (0) and "full info" (2)
if (mode == ModeGameTab) {
cardPicture->setVisible((minimized == 0) || (minimized == 2));
if (minimized == 0)
setMaximumHeight(cardHeightOffset + width() * aspectRatio);
else
setMaximumHeight(1000000);
} else
cardPicture->show();
resize(width(), sizeHint().height());
if (minimized == 0)
setMaximumHeight(cardHeightOffset + width() * aspectRatio);
else
setMaximumHeight(1000000);
} else
cardPicture->show();
resize(width(), sizeHint().height());
}
void CardInfoWidget::setCard(CardInfo *card)
{
if (info)
disconnect(info, 0, this, 0);
info = card;
connect(info, SIGNAL(pixmapUpdated()), this, SLOT(updatePixmap()));
connect(info, SIGNAL(destroyed()), this, SLOT(clear()));
if (info)
disconnect(info, 0, this, 0);
info = card;
connect(info, SIGNAL(pixmapUpdated()), this, SLOT(updatePixmap()));
connect(info, SIGNAL(destroyed()), this, SLOT(clear()));
updatePixmap();
nameLabel2->setText(card->getName());
manacostLabel2->setText(card->getManaCost());
cardtypeLabel2->setText(card->getCardType());
powtoughLabel2->setText(card->getPowTough());
textLabel->setText(card->getText());
updatePixmap();
nameLabel2->setText(card->getName());
manacostLabel2->setText(card->getManaCost());
cardtypeLabel2->setText(card->getCardType());
powtoughLabel2->setText(card->getPowTough());
loyaltyLabel2->setText(card->getLoyalty() > 0 ? QString::number(card->getLoyalty()) : QString());
textLabel->setText(card->getText());
powtoughLabel1->setVisible(shouldShowPowTough());
powtoughLabel2->setVisible(shouldShowPowTough());
loyaltyLabel1->setVisible(shouldShowLoyalty());
loyaltyLabel2->setVisible(shouldShowLoyalty());
}
void CardInfoWidget::setCard(const QString &cardName)
{
setCard(db->getCard(cardName));
setCard(getCard(cardName));
}
void CardInfoWidget::setCard(AbstractCardItem *card)
{
setCard(card->getInfo());
setCard(card->getInfo());
}
void CardInfoWidget::clear()
{
setCard(db->getCard());
setCard(getCard());
}
CardInfo *CardInfoWidget::getCard(const QString &cardName) {
return db->getCardBySimpleName(cardName);
}
void CardInfoWidget::updatePixmap()
{
QPixmap *resizedPixmap = info->getPixmap(QSize(pixmapWidth, pixmapWidth * aspectRatio));
if (resizedPixmap)
cardPicture->setPixmap(*resizedPixmap);
else
cardPicture->setPixmap(*(db->getCard()->getPixmap(QSize(pixmapWidth, pixmapWidth * aspectRatio))));
if (pixmapWidth == 0)
return;
QPixmap *resizedPixmap = info->getPixmap(QSize(pixmapWidth, pixmapWidth * aspectRatio));
if (resizedPixmap)
cardPicture->setPixmap(*resizedPixmap);
else
cardPicture->setPixmap(*(getCard()->getPixmap(QSize(pixmapWidth, pixmapWidth * aspectRatio))));
}
void CardInfoWidget::retranslateUi()
{
nameLabel1->setText(tr("Name:"));
manacostLabel1->setText(tr("Mana cost:"));
cardtypeLabel1->setText(tr("Card type:"));
powtoughLabel1->setText(tr("P / T:"));
nameLabel1->setText(tr("Name:"));
manacostLabel1->setText(tr("Mana cost:"));
cardtypeLabel1->setText(tr("Card type:"));
powtoughLabel1->setText(tr("P / T:"));
loyaltyLabel1->setText(tr("Loyalty:"));
}
void CardInfoWidget::resizeEvent(QResizeEvent * /*event*/)
{
if ((mode == ModeGameTab) && (minimized == 1))
return;
pixmapWidth = qMax(100.0, qMin((qreal) cardPicture->width(), (height() - cardHeightOffset) / aspectRatio));
updatePixmap();
if (mode == ModePopUp)
return;
if ((minimized == 1) && (mode == ModeGameTab)) {
pixmapWidth = 0;
return;
}
qreal newPixmapWidth = qMax((qreal) 100.0, qMin((qreal) cardPicture->width(), (qreal) ((height() - cardHeightOffset) / aspectRatio)));
if (newPixmapWidth != pixmapWidth) {
pixmapWidth = newPixmapWidth;
updatePixmap();
}
}
QString CardInfoWidget::getCardName() const
{
return nameLabel2->text();
}
return nameLabel2->text();
}

View file

@ -14,46 +14,56 @@ class QResizeEvent;
class QMouseEvent;
class CardInfoWidget : public QFrame {
Q_OBJECT
Q_OBJECT
public:
enum ResizeMode { ModeDeckEditor, ModeGameTab, ModePopUp };
enum ResizeMode { ModeDeckEditor, ModeGameTab, ModePopUp };
private:
int pixmapWidth;
qreal cardHeightOffset;
qreal aspectRatio;
int minimized; // 0 - card, 1 - oracle only, 2 - full
ResizeMode mode;
int pixmapWidth;
qreal cardHeightOffset;
qreal aspectRatio;
// XXX: Why isn't this an eunm?
int minimized; // 0 - card, 1 - oracle only, 2 - full
ResizeMode mode;
QComboBox *dropList;
QLabel *cardPicture;
QLabel *nameLabel1, *nameLabel2;
QLabel *manacostLabel1, *manacostLabel2;
QLabel *cardtypeLabel1, *cardtypeLabel2;
QLabel *powtoughLabel1, *powtoughLabel2;
QTextEdit *textLabel;
QComboBox *dropList;
QLabel *cardPicture;
QLabel *nameLabel1, *nameLabel2;
QLabel *manacostLabel1, *manacostLabel2;
QLabel *cardtypeLabel1, *cardtypeLabel2;
QLabel *powtoughLabel1, *powtoughLabel2;
QLabel *loyaltyLabel1, *loyaltyLabel2;
QTextEdit *textLabel;
CardInfo *info;
void setMinimized(int _minimized);
bool shouldShowPowTough();
bool shouldShowLoyalty();
CardInfo *info;
void setMinimized(int _minimized);
/*
* Wrapper around db->getCardBySimpleName.
*/
CardInfo *getCard(const QString &cardName = QString());
public:
CardInfoWidget(ResizeMode _mode, QWidget *parent = 0, Qt::WindowFlags f = 0);
void retranslateUi();
QString getCardName() const;
CardInfoWidget(ResizeMode _mode, const QString &cardName = QString(), QWidget *parent = 0, Qt::WindowFlags f = 0);
void retranslateUi();
QString getCardName() const;
public slots:
void setCard(CardInfo *card);
void setCard(const QString &cardName);
void setCard(AbstractCardItem *card);
void setCard(CardInfo *card);
void setCard(const QString &cardName);
void setCard(AbstractCardItem *card);
private slots:
void clear();
void updatePixmap();
void minimizeClicked(int newMinimized);
void clear();
void updatePixmap();
void minimizeClicked(int newMinimized);
protected:
void resizeEvent(QResizeEvent *event);
void resizeEvent(QResizeEvent *event);
};
#endif

View file

@ -8,619 +8,385 @@
#include "carddragitem.h"
#include "carddatabase.h"
#include "cardzone.h"
#include "zoneviewzone.h"
#include "tablezone.h"
#include "player.h"
#include "arrowitem.h"
#include "main.h"
#include "protocol_datastructures.h"
#include "settingscache.h"
#include "tab_game.h"
#include "pb/serverinfo_card.pb.h"
CardItem::CardItem(Player *_owner, const QString &_name, int _cardid, bool _revealedCard, QGraphicsItem *parent)
: AbstractCardItem(_name, _owner, parent), zone(0), id(_cardid), revealedCard(_revealedCard), attacking(false), facedown(false), destroyOnZoneChange(false), doesntUntap(false), dragItem(0), attachedTo(0)
: AbstractCardItem(_name, _owner, _cardid, parent), zone(0), revealedCard(_revealedCard), attacking(false), destroyOnZoneChange(false), doesntUntap(false), dragItem(0), attachedTo(0)
{
owner->addCard(this);
aTap = new QAction(this);
aTap->setData(0);
connect(aTap, SIGNAL(triggered()), this, SLOT(cardMenuAction()));
aUntap = new QAction(this);
aUntap->setData(1);
connect(aUntap, SIGNAL(triggered()), this, SLOT(cardMenuAction()));
aDoesntUntap = new QAction(this);
aDoesntUntap->setData(2);
connect(aDoesntUntap, SIGNAL(triggered()), this, SLOT(cardMenuAction()));
aAttach = new QAction(this);
connect(aAttach, SIGNAL(triggered()), this, SLOT(actAttach()));
aUnattach = new QAction(this);
connect(aUnattach, SIGNAL(triggered()), this, SLOT(actUnattach()));
aDrawArrow = new QAction(this);
connect(aDrawArrow, SIGNAL(triggered()), this, SLOT(actDrawArrow()));
aIncP = new QAction(this);
connect(aIncP, SIGNAL(triggered()), this, SLOT(actIncP()));
aDecP = new QAction(this);
connect(aDecP, SIGNAL(triggered()), this, SLOT(actDecP()));
aIncT = new QAction(this);
connect(aIncT, SIGNAL(triggered()), this, SLOT(actIncT()));
aDecT = new QAction(this);
connect(aDecT, SIGNAL(triggered()), this, SLOT(actDecT()));
aIncPT = new QAction(this);
connect(aIncPT, SIGNAL(triggered()), this, SLOT(actIncPT()));
aDecPT = new QAction(this);
connect(aDecPT, SIGNAL(triggered()), this, SLOT(actDecPT()));
aSetPT = new QAction(this);
connect(aSetPT, SIGNAL(triggered()), this, SLOT(actSetPT()));
aSetAnnotation = new QAction(this);
connect(aSetAnnotation, SIGNAL(triggered()), this, SLOT(actSetAnnotation()));
aFlip = new QAction(this);
aFlip->setData(3);
connect(aFlip, SIGNAL(triggered()), this, SLOT(cardMenuAction()));
aClone = new QAction(this);
aClone->setData(4);
connect(aClone, SIGNAL(triggered()), this, SLOT(cardMenuAction()));
aMoveToTopLibrary = new QAction(this);
aMoveToTopLibrary->setData(5);
aMoveToBottomLibrary = new QAction(this);
aMoveToBottomLibrary->setData(6);
aMoveToGraveyard = new QAction(this);
aMoveToGraveyard->setData(7);
aMoveToExile = new QAction(this);
aMoveToExile->setData(8);
connect(aMoveToTopLibrary, SIGNAL(triggered()), this, SLOT(cardMenuAction()));
connect(aMoveToBottomLibrary, SIGNAL(triggered()), this, SLOT(cardMenuAction()));
connect(aMoveToGraveyard, SIGNAL(triggered()), this, SLOT(cardMenuAction()));
connect(aMoveToExile, SIGNAL(triggered()), this, SLOT(cardMenuAction()));
aPlay = new QAction(this);
connect(aPlay, SIGNAL(triggered()), this, SLOT(actPlay()));
aHide = new QAction(this);
connect(aHide, SIGNAL(triggered()), this, SLOT(actHide()));
for (int i = 0; i < 3; ++i) {
QAction *tempAddCounter = new QAction(this);
tempAddCounter->setData(9 + i * 1000);
QAction *tempRemoveCounter = new QAction(this);
tempRemoveCounter->setData(10 + i * 1000);
QAction *tempSetCounter = new QAction(this);
tempSetCounter->setData(11 + i * 1000);
aAddCounter.append(tempAddCounter);
aRemoveCounter.append(tempRemoveCounter);
aSetCounter.append(tempSetCounter);
connect(tempAddCounter, SIGNAL(triggered()), this, SLOT(actCardCounterTrigger()));
connect(tempRemoveCounter, SIGNAL(triggered()), this, SLOT(actCardCounterTrigger()));
connect(tempSetCounter, SIGNAL(triggered()), this, SLOT(actCardCounterTrigger()));
}
cardMenu = new QMenu;
ptMenu = new QMenu;
ptMenu->addAction(aIncP);
ptMenu->addAction(aDecP);
ptMenu->addSeparator();
ptMenu->addAction(aIncT);
ptMenu->addAction(aDecT);
ptMenu->addSeparator();
ptMenu->addAction(aIncPT);
ptMenu->addAction(aDecPT);
ptMenu->addSeparator();
ptMenu->addAction(aSetPT);
moveMenu = new QMenu;
retranslateUi();
updateCardMenu();
owner->addCard(this);
cardMenu = new QMenu;
ptMenu = new QMenu;
moveMenu = new QMenu;
retranslateUi();
emit updateCardMenu(this);
}
CardItem::~CardItem()
{
prepareDelete();
delete cardMenu;
cardMenu = 0;
delete moveMenu;
moveMenu = 0;
deleteDragItem();
prepareDelete();
if (scene())
static_cast<GameScene *>(scene())->unregisterAnimationItem(this);
delete cardMenu;
delete ptMenu;
delete moveMenu;
deleteDragItem();
}
void CardItem::prepareDelete()
{
if (owner) {
if (owner->getCardMenu() == cardMenu)
owner->setCardMenu(0);
owner = 0;
}
while (!attachedCards.isEmpty()) {
attachedCards.first()->setZone(0); // so that it won't try to call reorganizeCards()
attachedCards.first()->setAttachedTo(0);
}
if (attachedTo) {
attachedTo->removeAttachedCard(this);
attachedTo = 0;
}
if (owner) {
if (owner->getCardMenu() == cardMenu) {
owner->setCardMenu(0);
owner->getGame()->setActiveCard(0);
}
owner = 0;
}
while (!attachedCards.isEmpty()) {
attachedCards.first()->setZone(0); // so that it won't try to call reorganizeCards()
attachedCards.first()->setAttachedTo(0);
}
if (attachedTo) {
attachedTo->removeAttachedCard(this);
attachedTo = 0;
}
}
void CardItem::deleteLater()
{
prepareDelete();
AbstractCardItem::deleteLater();
prepareDelete();
AbstractCardItem::deleteLater();
}
void CardItem::setZone(CardZone *_zone)
{
zone = _zone;
updateCardMenu();
}
void CardItem::updateCardMenu()
{
cardMenu->clear();
if (revealedCard)
cardMenu->addAction(aHide);
else if (owner->getLocal()) {
moveMenu->clear();
moveMenu->addAction(aMoveToTopLibrary);
moveMenu->addAction(aMoveToBottomLibrary);
moveMenu->addAction(aMoveToGraveyard);
moveMenu->addAction(aMoveToExile);
if (zone) {
if (zone->getName() == "table") {
cardMenu->addAction(aTap);
cardMenu->addAction(aUntap);
cardMenu->addAction(aDoesntUntap);
cardMenu->addAction(aFlip);
cardMenu->addSeparator();
cardMenu->addAction(aAttach);
if (attachedTo)
cardMenu->addAction(aUnattach);
cardMenu->addAction(aDrawArrow);
cardMenu->addSeparator();
cardMenu->addMenu(ptMenu);
cardMenu->addAction(aSetAnnotation);
cardMenu->addSeparator();
cardMenu->addAction(aClone);
cardMenu->addMenu(moveMenu);
for (int i = 0; i < aAddCounter.size(); ++i) {
cardMenu->addSeparator();
cardMenu->addAction(aAddCounter[i]);
cardMenu->addAction(aRemoveCounter[i]);
cardMenu->addAction(aSetCounter[i]);
}
cardMenu->addSeparator();
} else if (zone->getName() == "stack") {
cardMenu->addAction(aDrawArrow);
cardMenu->addMenu(moveMenu);
} else {
cardMenu->addAction(aPlay);
cardMenu->addMenu(moveMenu);
}
} else
cardMenu->addMenu(moveMenu);
}
zone = _zone;
emit updateCardMenu(this);
}
void CardItem::retranslateUi()
{
aPlay->setText(tr("&Play"));
aHide->setText(tr("&Hide"));
aTap->setText(tr("&Tap"));
aUntap->setText(tr("&Untap"));
aDoesntUntap->setText(tr("Toggle &normal untapping"));
aFlip->setText(tr("&Flip"));
aClone->setText(tr("&Clone"));
aClone->setShortcut(tr("Ctrl+H"));
aAttach->setText(tr("&Attach to card..."));
aAttach->setShortcut(tr("Ctrl+A"));
aUnattach->setText(tr("Unattac&h"));
aDrawArrow->setText(tr("&Draw arrow..."));
ptMenu->setTitle(tr("&Power / toughness"));
aIncP->setText(tr("&Increase power"));
aIncP->setShortcut(tr("Ctrl++"));
aDecP->setText(tr("&Decrease power"));
aDecP->setShortcut(tr("Ctrl+-"));
aIncT->setText(tr("I&ncrease toughness"));
aIncT->setShortcut(tr("Alt++"));
aDecT->setText(tr("D&ecrease toughness"));
aDecT->setShortcut(tr("Alt+-"));
aIncPT->setText(tr("In&crease power and toughness"));
aIncPT->setShortcut(tr("Ctrl+Alt++"));
aDecPT->setText(tr("Dec&rease power and toughness"));
aDecPT->setShortcut(tr("Ctrl+Alt+-"));
aSetPT->setText(tr("Set &power and toughness..."));
aSetPT->setShortcut(tr("Ctrl+P"));
aSetAnnotation->setText(tr("&Set annotation..."));
QStringList counterColors;
counterColors.append(tr("red"));
counterColors.append(tr("yellow"));
counterColors.append(tr("green"));
for (int i = 0; i < aAddCounter.size(); ++i)
aAddCounter[i]->setText(tr("&Add counter (%1)").arg(counterColors[i]));
for (int i = 0; i < aRemoveCounter.size(); ++i)
aRemoveCounter[i]->setText(tr("&Remove counter (%1)").arg(counterColors[i]));
for (int i = 0; i < aSetCounter.size(); ++i)
aSetCounter[i]->setText(tr("&Set counters (%1)...").arg(counterColors[i]));
aMoveToTopLibrary->setText(tr("&top of library"));
aMoveToBottomLibrary->setText(tr("&bottom of library"));
aMoveToGraveyard->setText(tr("&graveyard"));
aMoveToGraveyard->setShortcut(tr("Ctrl+Del"));
aMoveToExile->setText(tr("&exile"));
moveMenu->setTitle(tr("&Move to"));
moveMenu->setTitle(tr("&Move to"));
ptMenu->setTitle(tr("&Power / toughness"));
}
void CardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
painter->save();
AbstractCardItem::paint(painter, option, widget);
int i = 0;
QMapIterator<int, int> counterIterator(counters);
while (counterIterator.hasNext()) {
counterIterator.next();
QColor color;
color.setHsv(counterIterator.key() * 60, 150, 255);
paintNumberEllipse(counterIterator.value(), 14, color, i, counters.size(), painter);
++i;
}
QSizeF translatedSize = getTranslatedSize(painter);
qreal scaleFactor = translatedSize.width() / boundingRect().width();
if (!pt.isEmpty()) {
painter->save();
transformPainter(painter, translatedSize, tapAngle);
painter->setBackground(Qt::black);
painter->setBackgroundMode(Qt::OpaqueMode);
painter->setPen(Qt::white);
painter->drawText(QRectF(4 * scaleFactor, 4 * scaleFactor, translatedSize.width() - 8 * scaleFactor, translatedSize.height() - 8 * scaleFactor), Qt::AlignRight | Qt::AlignBottom, pt);
painter->restore();
}
if (!annotation.isEmpty()) {
painter->save();
painter->save();
AbstractCardItem::paint(painter, option, widget);
int i = 0;
QMapIterator<int, int> counterIterator(counters);
while (counterIterator.hasNext()) {
counterIterator.next();
QColor color;
color.setHsv(counterIterator.key() * 60, 150, 255);
paintNumberEllipse(counterIterator.value(), 14, color, i, counters.size(), painter);
++i;
}
QSizeF translatedSize = getTranslatedSize(painter);
qreal scaleFactor = translatedSize.width() / boundingRect().width();
if (!pt.isEmpty()) {
painter->save();
transformPainter(painter, translatedSize, tapAngle);
painter->setBackground(Qt::black);
painter->setBackgroundMode(Qt::OpaqueMode);
painter->setPen(Qt::white);
painter->drawText(QRectF(4 * scaleFactor, 4 * scaleFactor, translatedSize.width() - 8 * scaleFactor, translatedSize.height() - 8 * scaleFactor), Qt::AlignRight | Qt::AlignBottom, pt);
painter->restore();
}
if (!annotation.isEmpty()) {
painter->save();
transformPainter(painter, translatedSize, tapAngle);
painter->setBackground(Qt::black);
painter->setBackgroundMode(Qt::OpaqueMode);
painter->setPen(Qt::white);
painter->drawText(QRectF(4 * scaleFactor, 4 * scaleFactor, translatedSize.width() - 8 * scaleFactor, translatedSize.height() - 8 * scaleFactor), Qt::AlignCenter | Qt::TextWrapAnywhere, annotation);
painter->restore();
}
if (getBeingPointedAt())
painter->fillRect(boundingRect(), QBrush(QColor(255, 0, 0, 100)));
painter->restore();
transformPainter(painter, translatedSize, tapAngle);
painter->setBackground(Qt::black);
painter->setBackgroundMode(Qt::OpaqueMode);
painter->setPen(Qt::white);
painter->drawText(QRectF(4 * scaleFactor, 4 * scaleFactor, translatedSize.width() - 8 * scaleFactor, translatedSize.height() - 8 * scaleFactor), Qt::AlignCenter | Qt::TextWrapAnywhere, annotation);
painter->restore();
}
if (getBeingPointedAt())
painter->fillRect(boundingRect(), QBrush(QColor(255, 0, 0, 100)));
painter->restore();
}
void CardItem::setAttacking(bool _attacking)
{
attacking = _attacking;
update();
}
void CardItem::setFaceDown(bool _facedown)
{
facedown = _facedown;
if (facedown)
setName(QString());
update();
attacking = _attacking;
update();
}
void CardItem::setCounter(int _id, int _value)
{
if (_value)
counters.insert(_id, _value);
else
counters.remove(_id);
update();
if (_value)
counters.insert(_id, _value);
else
counters.remove(_id);
update();
}
void CardItem::setAnnotation(const QString &_annotation)
{
annotation = _annotation;
update();
annotation = _annotation;
update();
}
void CardItem::setDoesntUntap(bool _doesntUntap)
{
doesntUntap = _doesntUntap;
doesntUntap = _doesntUntap;
}
void CardItem::setPT(const QString &_pt)
{
pt = _pt;
update();
pt = _pt;
update();
}
void CardItem::setAttachedTo(CardItem *_attachedTo)
{
if (attachedTo)
attachedTo->removeAttachedCard(this);
gridPoint.setX(-1);
attachedTo = _attachedTo;
if (attachedTo) {
setParentItem(attachedTo->getZone());
attachedTo->addAttachedCard(this);
if (zone != attachedTo->getZone())
attachedTo->getZone()->reorganizeCards();
} else
setParentItem(zone);
if (attachedTo)
attachedTo->removeAttachedCard(this);
gridPoint.setX(-1);
attachedTo = _attachedTo;
if (attachedTo) {
setParentItem(attachedTo->getZone());
attachedTo->addAttachedCard(this);
if (zone != attachedTo->getZone())
attachedTo->getZone()->reorganizeCards();
} else
setParentItem(zone);
if (zone)
zone->reorganizeCards();
updateCardMenu();
if (zone)
zone->reorganizeCards();
emit updateCardMenu(this);
}
void CardItem::resetState()
{
attacking = false;
facedown = false;
counters.clear();
pt.clear();
annotation.clear();
attachedTo = 0;
attachedCards.clear();
setTapped(false, false);
setDoesntUntap(false);
if (scene())
static_cast<GameScene *>(scene())->unregisterAnimationItem(this);
update();
attacking = false;
facedown = false;
counters.clear();
pt.clear();
annotation.clear();
attachedTo = 0;
attachedCards.clear();
setTapped(false, false);
setDoesntUntap(false);
if (scene())
static_cast<GameScene *>(scene())->unregisterAnimationItem(this);
update();
}
void CardItem::processCardInfo(ServerInfo_Card *info)
void CardItem::processCardInfo(const ServerInfo_Card &info)
{
counters.clear();
const QList<ServerInfo_CardCounter *> &_counterList = info->getCounters();
for (int i = 0; i < _counterList.size(); ++i)
counters.insert(_counterList[i]->getId(), _counterList[i]->getValue());
setId(info->getId());
setName(info->getName());
setAttacking(info->getAttacking());
setFaceDown(info->getFaceDown());
setPT(info->getPT());
setAnnotation(info->getAnnotation());
setColor(info->getColor());
setTapped(info->getTapped());
setDestroyOnZoneChange(info->getDestroyOnZoneChange());
setDoesntUntap(info->getDoesntUntap());
counters.clear();
const int counterListSize = info.counter_list_size();
for (int i = 0; i < counterListSize; ++i) {
const ServerInfo_CardCounter &counterInfo = info.counter_list(i);
counters.insert(counterInfo.id(), counterInfo.value());
}
setId(info.id());
setName(QString::fromStdString(info.name()));
setAttacking(info.attacking());
setFaceDown(info.face_down());
setPT(QString::fromStdString(info.pt()));
setAnnotation(QString::fromStdString(info.annotation()));
setColor(QString::fromStdString(info.color()));
setTapped(info.tapped());
setDestroyOnZoneChange(info.destroy_on_zone_change());
setDoesntUntap(info.doesnt_untap());
}
CardDragItem *CardItem::createDragItem(int _id, const QPointF &_pos, const QPointF &_scenePos, bool faceDown)
{
deleteDragItem();
dragItem = new CardDragItem(this, _id, _pos, faceDown);
dragItem->setVisible(false);
scene()->addItem(dragItem);
dragItem->updatePosition(_scenePos);
dragItem->setVisible(true);
deleteDragItem();
dragItem = new CardDragItem(this, _id, _pos, faceDown);
dragItem->setVisible(false);
scene()->addItem(dragItem);
dragItem->updatePosition(_scenePos);
dragItem->setVisible(true);
return dragItem;
return dragItem;
}
void CardItem::deleteDragItem()
{
dragItem->deleteLater();
dragItem = NULL;
if(dragItem)
dragItem->deleteLater();
dragItem = NULL;
}
void CardItem::drawArrow(const QColor &arrowColor)
{
if (static_cast<TabGame *>(owner->parent())->getSpectator())
return;
Player *arrowOwner = static_cast<TabGame *>(owner->parent())->getActiveLocalPlayer();
ArrowDragItem *arrow = new ArrowDragItem(arrowOwner, this, arrowColor);
scene()->addItem(arrow);
arrow->grabMouse();
QListIterator<QGraphicsItem *> itemIterator(scene()->selectedItems());
while (itemIterator.hasNext()) {
CardItem *c = qgraphicsitem_cast<CardItem *>(itemIterator.next());
if (!c || (c == this))
continue;
if (c->getZone() != zone)
continue;
ArrowDragItem *childArrow = new ArrowDragItem(arrowOwner, c, arrowColor);
scene()->addItem(childArrow);
arrow->addChildArrow(childArrow);
}
if (static_cast<TabGame *>(owner->parent())->getSpectator())
return;
Player *arrowOwner = static_cast<TabGame *>(owner->parent())->getActiveLocalPlayer();
ArrowDragItem *arrow = new ArrowDragItem(arrowOwner, this, arrowColor);
scene()->addItem(arrow);
arrow->grabMouse();
QListIterator<QGraphicsItem *> itemIterator(scene()->selectedItems());
while (itemIterator.hasNext()) {
CardItem *c = qgraphicsitem_cast<CardItem *>(itemIterator.next());
if (!c || (c == this))
continue;
if (c->getZone() != zone)
continue;
ArrowDragItem *childArrow = new ArrowDragItem(arrowOwner, c, arrowColor);
scene()->addItem(childArrow);
arrow->addChildArrow(childArrow);
}
}
void CardItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if (event->buttons().testFlag(Qt::RightButton)) {
if ((event->screenPos() - event->buttonDownScreenPos(Qt::RightButton)).manhattanLength() < 2 * QApplication::startDragDistance())
return;
QColor arrowColor = Qt::red;
if (event->modifiers().testFlag(Qt::ControlModifier))
arrowColor = Qt::yellow;
else if (event->modifiers().testFlag(Qt::AltModifier))
arrowColor = Qt::blue;
else if (event->modifiers().testFlag(Qt::ShiftModifier))
arrowColor = Qt::green;
drawArrow(arrowColor);
} else if (event->buttons().testFlag(Qt::LeftButton)) {
if ((event->screenPos() - event->buttonDownScreenPos(Qt::LeftButton)).manhattanLength() < 2 * QApplication::startDragDistance())
return;
if (!owner->getLocal())
return;
bool forceFaceDown = event->modifiers().testFlag(Qt::ShiftModifier);
createDragItem(id, event->pos(), event->scenePos(), facedown || forceFaceDown);
dragItem->grabMouse();
QList<QGraphicsItem *> sel = scene()->selectedItems();
int j = 0;
for (int i = 0; i < sel.size(); i++) {
CardItem *c = (CardItem *) sel.at(i);
if (c == this)
continue;
++j;
QPointF childPos;
if (zone->getHasCardAttr())
childPos = c->pos() - pos();
else
childPos = QPointF(j * CARD_WIDTH / 2, 0);
CardDragItem *drag = new CardDragItem(c, c->getId(), childPos, c->getFaceDown() || forceFaceDown, dragItem);
drag->setPos(dragItem->pos() + childPos);
scene()->addItem(drag);
}
}
setCursor(Qt::OpenHandCursor);
if (event->buttons().testFlag(Qt::RightButton)) {
if ((event->screenPos() - event->buttonDownScreenPos(Qt::RightButton)).manhattanLength() < 2 * QApplication::startDragDistance())
return;
QColor arrowColor = Qt::red;
if (event->modifiers().testFlag(Qt::ControlModifier))
arrowColor = Qt::yellow;
else if (event->modifiers().testFlag(Qt::AltModifier))
arrowColor = Qt::blue;
else if (event->modifiers().testFlag(Qt::ShiftModifier))
arrowColor = Qt::green;
drawArrow(arrowColor);
} else if (event->buttons().testFlag(Qt::LeftButton)) {
if ((event->screenPos() - event->buttonDownScreenPos(Qt::LeftButton)).manhattanLength() < 2 * QApplication::startDragDistance())
return;
if (zone->getIsView()) {
const ZoneViewZone *const view = static_cast<const ZoneViewZone *const>(zone);
if (view->getRevealZone() && !view->getWriteableRevealZone())
return;
} else if (!owner->getLocal())
return;
bool forceFaceDown = event->modifiers().testFlag(Qt::ShiftModifier);
createDragItem(id, event->pos(), event->scenePos(), facedown || forceFaceDown);
dragItem->grabMouse();
QList<QGraphicsItem *> sel = scene()->selectedItems();
int j = 0;
for (int i = 0; i < sel.size(); i++) {
CardItem *c = (CardItem *) sel.at(i);
if ((c == this) || (c->getZone() != zone))
continue;
++j;
QPointF childPos;
if (zone->getHasCardAttr())
childPos = c->pos() - pos();
else
childPos = QPointF(j * CARD_WIDTH / 2, 0);
CardDragItem *drag = new CardDragItem(c, c->getId(), childPos, c->getFaceDown() || forceFaceDown, dragItem);
drag->setPos(dragItem->pos() + childPos);
scene()->addItem(drag);
}
}
setCursor(Qt::OpenHandCursor);
}
void CardItem::playCard(bool faceDown)
{
// Do nothing if the card belongs to another player
if (!owner->getLocal())
return;
// Do nothing if the card belongs to another player
if (!owner->getLocal())
return;
TableZone *tz = qobject_cast<TableZone *>(zone);
if (tz)
tz->toggleTapped();
else
zone->getPlayer()->playCard(this, faceDown, info->getCipt());
TableZone *tz = qobject_cast<TableZone *>(zone);
if (tz)
tz->toggleTapped();
else
zone->getPlayer()->playCard(this, faceDown, info->getCipt());
}
void CardItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
if (event->button() == Qt::RightButton) {
if (cardMenu)
if (!cardMenu->isEmpty())
cardMenu->exec(event->screenPos());
} else if ((event->button() == Qt::LeftButton) && !settingsCache->getDoubleClickToPlay()) {
setCursor(Qt::OpenHandCursor);
if (revealedCard)
actHide();
else
playCard(event->modifiers().testFlag(Qt::ShiftModifier));
}
if (event->button() == Qt::RightButton) {
if (cardMenu)
if (!cardMenu->isEmpty())
cardMenu->exec(event->screenPos());
} else if ((event->button() == Qt::LeftButton) && !settingsCache->getDoubleClickToPlay()) {
bool hideCard = false;
if (zone->getIsView()) {
ZoneViewZone *view = static_cast<ZoneViewZone *>(zone);
if (view->getRevealZone() && !view->getWriteableRevealZone())
hideCard = true;
}
if (hideCard)
zone->removeCard(this);
else
playCard(event->modifiers().testFlag(Qt::ShiftModifier));
}
AbstractCardItem::mouseReleaseEvent(event);
setCursor(Qt::OpenHandCursor);
AbstractCardItem::mouseReleaseEvent(event);
}
void CardItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
{
if (settingsCache->getDoubleClickToPlay()) {
if (revealedCard)
actHide();
else
playCard(event->modifiers().testFlag(Qt::ShiftModifier));
}
event->accept();
if (settingsCache->getDoubleClickToPlay()) {
if (revealedCard)
zone->removeCard(this);
else
playCard(event->modifiers().testFlag(Qt::ShiftModifier));
}
event->accept();
}
bool CardItem::animationEvent()
{
int delta = 18;
if (!tapped)
delta *= -1;
tapAngle += delta;
setTransform(QTransform().translate((float) CARD_WIDTH / 2, (float) CARD_HEIGHT / 2).rotate(tapAngle).translate((float) -CARD_WIDTH / 2, (float) -CARD_HEIGHT / 2));
setHovered(false);
update();
int delta = 18;
if (!tapped)
delta *= -1;
tapAngle += delta;
setTransform(QTransform().translate((float) CARD_WIDTH / 2, (float) CARD_HEIGHT / 2).rotate(tapAngle).translate((float) -CARD_WIDTH / 2, (float) -CARD_HEIGHT / 2));
setHovered(false);
update();
if ((tapped && (tapAngle >= 90)) || (!tapped && (tapAngle <= 0)))
return false;
return true;
if ((tapped && (tapAngle >= 90)) || (!tapped && (tapAngle <= 0)))
return false;
return true;
}
QVariant CardItem::itemChange(GraphicsItemChange change, const QVariant &value)
{
if ((change == ItemSelectedHasChanged) && owner) {
if (value == true)
owner->setCardMenu(cardMenu);
else if (owner->getCardMenu() == cardMenu)
owner->setCardMenu(0);
}
return QGraphicsItem::itemChange(change, value);
}
void CardItem::cardMenuAction()
{
owner->cardMenuAction(static_cast<QAction *>(sender()));
}
void CardItem::actAttach()
{
owner->actAttach(static_cast<QAction *>(sender()));
}
void CardItem::actUnattach()
{
owner->actUnattach(static_cast<QAction *>(sender()));
}
void CardItem::actDrawArrow()
{
drawArrow(Qt::red);
}
void CardItem::actIncP()
{
owner->actIncPT(1, 0);
}
void CardItem::actDecP()
{
owner->actIncPT(-1, 0);
}
void CardItem::actIncT()
{
owner->actIncPT(0, 1);
}
void CardItem::actDecT()
{
owner->actIncPT(0, -1);
}
void CardItem::actIncPT()
{
owner->actIncPT(1, 1);
}
void CardItem::actDecPT()
{
owner->actIncPT(-1, -1);
}
void CardItem::actSetPT()
{
owner->actSetPT(static_cast<QAction *>(sender()));
}
void CardItem::actSetAnnotation()
{
owner->actSetAnnotation(static_cast<QAction *>(sender()));
}
void CardItem::actCardCounterTrigger()
{
owner->actCardCounterTrigger(static_cast<QAction *>(sender()));
}
void CardItem::actPlay()
{
playCard(false);
}
void CardItem::actHide()
{
zone->removeCard(this);
if ((change == ItemSelectedHasChanged) && owner) {
if (value == true) {
owner->setCardMenu(cardMenu);
owner->getGame()->setActiveCard(this);
} else if (owner->getCardMenu() == cardMenu) {
owner->setCardMenu(0);
owner->getGame()->setActiveCard(0);
}
}
return QGraphicsItem::itemChange(change, value);
}

View file

@ -14,99 +14,75 @@ class QColor;
const int MAX_COUNTERS_ON_CARD = 999;
class CardItem : public AbstractCardItem {
Q_OBJECT
Q_OBJECT
private:
CardZone *zone;
int id;
bool revealedCard;
bool attacking;
bool facedown;
QMap<int, int> counters;
QString annotation;
QString pt;
bool destroyOnZoneChange;
bool doesntUntap;
QPoint gridPoint;
CardDragItem *dragItem;
CardItem *attachedTo;
QList<CardItem *> attachedCards;
QList<QAction *> aAddCounter, aSetCounter, aRemoveCounter;
QAction *aPlay,
*aHide,
*aTap, *aUntap, *aDoesntUntap, *aAttach, *aUnattach, *aDrawArrow, *aSetPT, *aIncP, *aDecP, *aIncT, *aDecT, *aIncPT, *aDecPT, *aSetAnnotation, *aFlip, *aClone,
*aMoveToTopLibrary, *aMoveToBottomLibrary, *aMoveToGraveyard, *aMoveToExile;
QMenu *cardMenu, *ptMenu, *moveMenu;
CardZone *zone;
bool revealedCard;
bool attacking;
QMap<int, int> counters;
QString annotation;
QString pt;
bool destroyOnZoneChange;
bool doesntUntap;
QPoint gridPoint;
CardDragItem *dragItem;
CardItem *attachedTo;
QList<CardItem *> attachedCards;
QMenu *cardMenu, *ptMenu, *moveMenu;
void playCard(bool faceDown);
void drawArrow(const QColor &arrowColor);
void prepareDelete();
private slots:
void cardMenuAction();
void actCardCounterTrigger();
void actAttach();
void actUnattach();
void actDrawArrow();
void actSetPT();
void actIncP();
void actDecP();
void actIncT();
void actDecT();
void actIncPT();
void actDecPT();
void actSetAnnotation();
void actPlay();
void actHide();
void prepareDelete();
public slots:
void deleteLater();
void deleteLater();
public:
enum { Type = typeCard };
int type() const { return Type; }
CardItem(Player *_owner, const QString &_name = QString(), int _cardid = -1, bool revealedCard = false, QGraphicsItem *parent = 0);
~CardItem();
void retranslateUi();
CardZone *getZone() const { return zone; }
void setZone(CardZone *_zone);
QMenu *getCardMenu() const { return cardMenu; }
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
QPoint getGridPoint() const { return gridPoint; }
void setGridPoint(const QPoint &_gridPoint) { gridPoint = _gridPoint; }
QPoint getGridPos() const { return gridPoint; }
Player *getOwner() const { return owner; }
void setOwner(Player *_owner) { owner = _owner; }
int getId() const { return id; }
void setId(int _id) { id = _id; }
bool getAttacking() const { return attacking; }
void setAttacking(bool _attacking);
bool getFaceDown() const { return facedown; }
void setFaceDown(bool _facedown);
const QMap<int, int> &getCounters() const { return counters; }
void setCounter(int _id, int _value);
QString getAnnotation() const { return annotation; }
void setAnnotation(const QString &_annotation);
bool getDoesntUntap() const { return doesntUntap; }
void setDoesntUntap(bool _doesntUntap);
QString getPT() const { return pt; }
void setPT(const QString &_pt);
bool getDestroyOnZoneChange() const { return destroyOnZoneChange; }
void setDestroyOnZoneChange(bool _destroy) { destroyOnZoneChange = _destroy; }
CardItem *getAttachedTo() const { return attachedTo; }
void setAttachedTo(CardItem *_attachedTo);
void addAttachedCard(CardItem *card) { attachedCards.append(card); }
void removeAttachedCard(CardItem *card) { attachedCards.removeAt(attachedCards.indexOf(card)); }
const QList<CardItem *> &getAttachedCards() const { return attachedCards; }
void resetState();
void processCardInfo(ServerInfo_Card *info);
void updateCardMenu();
enum { Type = typeCard };
int type() const { return Type; }
CardItem(Player *_owner, const QString &_name = QString(), int _cardid = -1, bool revealedCard = false, QGraphicsItem *parent = 0);
~CardItem();
void retranslateUi();
CardZone *getZone() const { return zone; }
void setZone(CardZone *_zone);
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
QPoint getGridPoint() const { return gridPoint; }
void setGridPoint(const QPoint &_gridPoint) { gridPoint = _gridPoint; }
QPoint getGridPos() const { return gridPoint; }
Player *getOwner() const { return owner; }
void setOwner(Player *_owner) { owner = _owner; }
bool getRevealedCard() const { return revealedCard; }
bool getAttacking() const { return attacking; }
void setAttacking(bool _attacking);
const QMap<int, int> &getCounters() const { return counters; }
void setCounter(int _id, int _value);
QString getAnnotation() const { return annotation; }
void setAnnotation(const QString &_annotation);
bool getDoesntUntap() const { return doesntUntap; }
void setDoesntUntap(bool _doesntUntap);
QString getPT() const { return pt; }
void setPT(const QString &_pt);
bool getDestroyOnZoneChange() const { return destroyOnZoneChange; }
void setDestroyOnZoneChange(bool _destroy) { destroyOnZoneChange = _destroy; }
CardItem *getAttachedTo() const { return attachedTo; }
void setAttachedTo(CardItem *_attachedTo);
void addAttachedCard(CardItem *card) { attachedCards.append(card); }
void removeAttachedCard(CardItem *card) { attachedCards.removeAt(attachedCards.indexOf(card)); }
const QList<CardItem *> &getAttachedCards() const { return attachedCards; }
void resetState();
void processCardInfo(const ServerInfo_Card &info);
bool animationEvent();
CardDragItem *createDragItem(int _id, const QPointF &_pos, const QPointF &_scenePos, bool faceDown);
void deleteDragItem();
QMenu *getCardMenu() const { return cardMenu; }
QMenu *getPTMenu() const { return ptMenu; }
QMenu *getMoveMenu() const { return moveMenu; }
bool animationEvent();
CardDragItem *createDragItem(int _id, const QPointF &_pos, const QPointF &_scenePos, bool faceDown);
void deleteDragItem();
void drawArrow(const QColor &arrowColor);
void playCard(bool faceDown);
protected:
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
QVariant itemChange(GraphicsItemChange change, const QVariant &value);
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
QVariant itemChange(GraphicsItemChange change, const QVariant &value);
};
#endif

View file

@ -3,57 +3,57 @@
#include "carddatabase.h"
CardList::CardList(bool _contentsKnown)
: QList<CardItem *>(), contentsKnown(_contentsKnown)
: QList<CardItem *>(), contentsKnown(_contentsKnown)
{
}
CardItem *CardList::findCard(const int id, const bool remove, int *position)
{
if (!contentsKnown) {
if (empty())
return 0;
CardItem *temp = at(0);
if (remove)
removeAt(0);
if (position)
*position = id;
return temp;
} else
for (int i = 0; i < size(); i++) {
CardItem *temp = at(i);
if (temp->getId() == id) {
if (remove)
removeAt(i);
if (position)
*position = i;
return temp;
}
}
return 0;
if (!contentsKnown) {
if (empty())
return 0;
CardItem *temp = at(0);
if (remove)
removeAt(0);
if (position)
*position = id;
return temp;
} else
for (int i = 0; i < size(); i++) {
CardItem *temp = at(i);
if (temp->getId() == id) {
if (remove)
removeAt(i);
if (position)
*position = i;
return temp;
}
}
return 0;
}
class CardList::compareFunctor {
private:
int flags;
int flags;
public:
compareFunctor(int _flags) : flags(_flags)
{
}
inline bool operator()(CardItem *a, CardItem *b) const
{
if (flags & SortByType) {
QString t1 = a->getInfo()->getMainCardType();
QString t2 = b->getInfo()->getMainCardType();
if ((t1 == t2) && (flags & SortByName))
return a->getName() < b->getName();
return t1 < t2;
} else
return a->getName() < b->getName();
}
compareFunctor(int _flags) : flags(_flags)
{
}
inline bool operator()(CardItem *a, CardItem *b) const
{
if (flags & SortByType) {
QString t1 = a->getInfo()->getMainCardType();
QString t2 = b->getInfo()->getMainCardType();
if ((t1 == t2) && (flags & SortByName))
return a->getName() < b->getName();
return t1 < t2;
} else
return a->getName() < b->getName();
}
};
void CardList::sort(int flags)
{
compareFunctor cf(flags);
qSort(begin(), end(), cf);
compareFunctor cf(flags);
qSort(begin(), end(), cf);
}

View file

@ -7,15 +7,15 @@ class CardItem;
class CardList : public QList<CardItem *> {
private:
class compareFunctor;
class compareFunctor;
protected:
bool contentsKnown;
bool contentsKnown;
public:
enum SortFlags { SortByName = 1, SortByType = 2 };
CardList(bool _contentsKnown);
CardItem *findCard(const int id, const bool remove, int *position = NULL);
bool getContentsKnown() const { return contentsKnown; }
void sort(int flags = SortByName);
enum SortFlags { SortByName = 1, SortByType = 2 };
CardList(bool _contentsKnown);
CardItem *findCard(const int id, const bool remove, int *position = NULL);
bool getContentsKnown() const { return contentsKnown; }
void sort(int flags = SortByName);
};
#endif

View file

@ -6,188 +6,261 @@
#include "carditem.h"
#include "player.h"
#include "zoneviewzone.h"
#include "protocol_items.h"
#include "pb/command_move_card.pb.h"
#include "pb/serverinfo_user.pb.h"
CardZone::CardZone(Player *_p, const QString &_name, bool _hasCardAttr, bool _isShufflable, bool _contentsKnown, QGraphicsItem *parent, bool isView)
: AbstractGraphicsItem(parent), player(_p), name(_name), cards(_contentsKnown), view(NULL), menu(NULL), doubleClickAction(0), hasCardAttr(_hasCardAttr), isShufflable(_isShufflable)
CardZone::CardZone(Player *_p, const QString &_name, bool _hasCardAttr, bool _isShufflable, bool _contentsKnown, QGraphicsItem *parent, bool _isView)
: AbstractGraphicsItem(parent), player(_p), name(_name), cards(_contentsKnown), view(NULL), menu(NULL), doubleClickAction(0), hasCardAttr(_hasCardAttr), isShufflable(_isShufflable), isView(_isView)
{
if (!isView)
player->addZone(this);
if (!isView)
player->addZone(this);
}
CardZone::~CardZone()
{
qDebug() << "CardZone destructor: " << name;
delete view;
clearContents();
qDebug() << "CardZone destructor: " << name;
delete view;
clearContents();
}
void CardZone::retranslateUi()
{
for (int i = 0; i < cards.size(); ++i)
cards[i]->retranslateUi();
for (int i = 0; i < cards.size(); ++i)
cards[i]->retranslateUi();
}
void CardZone::clearContents()
{
for (int i = 0; i < cards.size(); i++) {
// If an incorrectly implemented server doesn't return attached cards to whom they belong before dropping a player,
// we have to return them to avoid a crash.
const QList<CardItem *> &attachedCards = cards[i]->getAttachedCards();
for (int j = 0; j < attachedCards.size(); ++j)
attachedCards[j]->setParentItem(attachedCards[j]->getZone());
player->deleteCard(cards.at(i));
}
cards.clear();
emit cardCountChanged();
for (int i = 0; i < cards.size(); i++) {
// If an incorrectly implemented server doesn't return attached cards to whom they belong before dropping a player,
// we have to return them to avoid a crash.
const QList<CardItem *> &attachedCards = cards[i]->getAttachedCards();
for (int j = 0; j < attachedCards.size(); ++j)
attachedCards[j]->setParentItem(attachedCards[j]->getZone());
player->deleteCard(cards.at(i));
}
cards.clear();
emit cardCountChanged();
}
QString CardZone::getTranslatedName(bool hisOwn, GrammaticalCase gc) const
{
QString ownerName = player->getName();
bool female = player->getUserInfo()->getGender() == ServerInfo_User::Female;
if (name == "hand")
switch (gc) {
case CaseNominative: return female ? (hisOwn ? tr("her hand", "nominative, female owner") : tr("%1's hand", "nominative, female owner").arg(ownerName)) : (hisOwn ? tr("his hand", "nominative, male owner") : tr("%1's hand", "nominative, male owner").arg(ownerName));
case CaseGenitive: return female ? (hisOwn ? tr("of her hand", "genitive, female owner") : tr("of %1's hand", "genitive, female owner").arg(ownerName)) : (hisOwn ? tr("of his hand", "genitive, male owner") : tr("of %1's hand", "genitive, male owner").arg(ownerName));
case CaseAccusative: return female ? (hisOwn ? tr("her hand", "accusative, female owner") : tr("%1's hand", "accusative, female owner").arg(ownerName)) : (hisOwn ? tr("his hand", "accusative, male owner") : tr("%1's hand", "accusative, male owner").arg(ownerName));
}
else if (name == "deck")
switch (gc) {
case CaseNominative: return female ? (hisOwn ? tr("her library", "nominative, female owner") : tr("%1's library", "nominative, female owner").arg(ownerName)) : (hisOwn ? tr("his library", "nominative, male owner") : tr("%1's library", "nominative, male owner").arg(ownerName));
case CaseGenitive: return female ? (hisOwn ? tr("of her library", "genitive, female owner") : tr("of %1's library", "genitive, female owner").arg(ownerName)) : (hisOwn ? tr("of his library", "genitive, male owner") : tr("of %1's library", "genitive, male owner").arg(ownerName));
case CaseAccusative: return female ? (hisOwn ? tr("her library", "accusative, female owner") : tr("%1's library", "accusative, female owner").arg(ownerName)) : (hisOwn ? tr("his library", "accusative, male owner") : tr("%1's library", "accusative, male owner").arg(ownerName));
}
else if (name == "grave")
switch (gc) {
case CaseNominative: return female ? (hisOwn ? tr("her graveyard", "nominative, female owner") : tr("%1's graveyard", "nominative, female owner").arg(ownerName)) : (hisOwn ? tr("his graveyard", "nominative, male owner") : tr("%1's graveyard", "nominative, male owner").arg(ownerName));
case CaseGenitive: return female ? (hisOwn ? tr("of her graveyard", "genitive, female owner") : tr("of %1's graveyard", "genitive, female owner").arg(ownerName)) : (hisOwn ? tr("of his graveyard", "genitive, male owner") : tr("of %1's graveyard", "genitive, male owner").arg(ownerName));
case CaseAccusative: return female ? (hisOwn ? tr("her graveyard", "accusative, female owner") : tr("%1's graveyard", "accusative, female owner").arg(ownerName)) : (hisOwn ? tr("his graveyard", "accusative, male owner") : tr("%1's graveyard", "accusative, male owner").arg(ownerName));
}
else if (name == "rfg")
switch (gc) {
case CaseNominative: return female ? (hisOwn ? tr("her exile", "nominative, female owner") : tr("%1's exile", "nominative, female owner").arg(ownerName)) : (hisOwn ? tr("his exile", "nominative, male owner") : tr("%1's exile", "nominative, male owner").arg(ownerName));
case CaseGenitive: return female ? (hisOwn ? tr("of her exile", "genitive, female owner") : tr("of %1's exile", "genitive, female owner").arg(ownerName)) : (hisOwn ? tr("of his exile", "genitive, male owner") : tr("of %1's exile", "genitive, male owner").arg(ownerName));
case CaseAccusative: return female ? (hisOwn ? tr("her exile", "accusative, female owner") : tr("%1's exile", "accusative, female owner").arg(ownerName)) : (hisOwn ? tr("his exile", "accusative, male owner") : tr("%1's exile", "accusative, male owner").arg(ownerName));
}
else if (name == "sb")
switch (gc) {
case CaseNominative: return female ? (hisOwn ? tr("her sideboard", "nominative, female owner") : tr("%1's sideboard", "nominative, female owner").arg(ownerName)) : (hisOwn ? tr("his sideboard", "nominative, male owner") : tr("%1's sideboard", "nominative, male owner").arg(ownerName));
case CaseGenitive: return female ? (hisOwn ? tr("of her sideboard", "genitive, female owner") : tr("of %1's sideboard", "genitive, female owner").arg(ownerName)) : (hisOwn ? tr("of his sideboard", "genitive, male owner") : tr("of %1's sideboard", "genitive, male owner").arg(ownerName));
case CaseAccusative: return female ? (hisOwn ? tr("her sideboard", "accusative, female owner") : tr("%1's sideboard", "accusative, female owner").arg(ownerName)) : (hisOwn ? tr("his sideboard", "accusative, male owner") : tr("%1's sideboard", "accusative, male owner").arg(ownerName));
}
return QString();
QString ownerName = player->getName();
bool female = player->getUserInfo()->gender() == ServerInfo_User::Female;
if (name == "hand")
return female
? (hisOwn
? tr("her hand", "nominative, female owner")
: tr("%1's hand", "nominative, female owner").arg(ownerName)
) : (hisOwn
? tr("his hand", "nominative, male owner")
: tr("%1's hand", "nominative, male owner").arg(ownerName)
);
else if (name == "deck")
switch (gc) {
case CaseLookAtZone:
return female
? (hisOwn
? tr("her library", "look at zone, female owner")
: tr("%1's library", "look at zone, female owner").arg(ownerName)
) : (hisOwn
? tr("his library", "look at zone, male owner")
: tr("%1's library", "look at zone, male owner").arg(ownerName)
);
case CaseTopCardsOfZone:
return female
? (hisOwn
? tr("of her library", "top cards of zone, female owner")
: tr("of %1's library", "top cards of zone, female owner").arg(ownerName)
) : (hisOwn
? tr("of his library", "top cards of zone, male owner")
: tr("of %1's library", "top cards of zone, male owner").arg(ownerName)
);
case CaseRevealZone:
return female
? (hisOwn
? tr("her library", "reveal zone, female owner")
: tr("%1's library", "reveal zone, female owner").arg(ownerName)
) : (hisOwn
? tr("his library", "reveal zone, male owner")
: tr("%1's library", "reveal zone, male owner").arg(ownerName)
);
case CaseShuffleZone:
return female
? (hisOwn
? tr("her library", "shuffle, female owner")
: tr("%1's library", "shuffle, female owner").arg(ownerName)
) : (hisOwn
? tr("his library", "shuffle, male owner")
: tr("%1's library", "shuffle, male owner").arg(ownerName)
);
default:
return female
? (hisOwn
? tr("her library", "nominative, female owner")
: tr("%1's library", "nominative, female owner").arg(ownerName)
) : (hisOwn
? tr("his library", "nominative, male owner")
: tr("%1's library", "nominative, male owner").arg(ownerName)
);
}
else if (name == "grave")
return female
? (hisOwn
? tr("her graveyard", "nominative, female owner")
: tr("%1's graveyard", "nominative, female owner").arg(ownerName)
) : (hisOwn
? tr("his graveyard", "nominative, male owner")
: tr("%1's graveyard", "nominative, male owner").arg(ownerName)
);
else if (name == "rfg")
return female
? (hisOwn
? tr("her exile", "nominative, female owner")
: tr("%1's exile", "nominative, female owner").arg(ownerName)
) : (hisOwn
? tr("his exile", "nominative, male owner")
: tr("%1's exile", "nominative, male owner").arg(ownerName)
);
else if (name == "sb")
switch (gc) {
case CaseLookAtZone:
return female
? (hisOwn
? tr("her sideboard", "look at zone, female owner")
: tr("%1's sideboard", "look at zone, female owner").arg(ownerName)
) : (hisOwn
? tr("his sideboard", "look at zone, male owner")
: tr("%1's sideboard", "look at zone, male owner").arg(ownerName)
);
case CaseNominative:
return female
? (hisOwn
? tr("her sideboard", "nominative, female owner")
: tr("%1's sideboard", "nominative, female owner").arg(ownerName)
) : (hisOwn
? tr("his sideboard", "nominative, male owner")
: tr("%1's sideboard", "nominative, male owner").arg(ownerName)
);
default: break;
}
return QString();
}
void CardZone::mouseDoubleClickEvent(QGraphicsSceneMouseEvent */*event*/)
void CardZone::mouseDoubleClickEvent(QGraphicsSceneMouseEvent * /*event*/)
{
if (doubleClickAction)
doubleClickAction->trigger();
if (doubleClickAction)
doubleClickAction->trigger();
}
bool CardZone::showContextMenu(const QPoint &screenPos)
{
if (menu) {
menu->exec(screenPos);
return true;
}
return false;
if (menu) {
menu->exec(screenPos);
return true;
}
return false;
}
void CardZone::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
if (event->button() == Qt::RightButton) {
if (showContextMenu(event->screenPos()))
event->accept();
else
event->ignore();
} else
event->ignore();
if (event->button() == Qt::RightButton) {
if (showContextMenu(event->screenPos()))
event->accept();
else
event->ignore();
} else
event->ignore();
}
void CardZone::addCard(CardItem *card, bool reorganize, int x, int y)
{
if (view)
if ((x <= view->getCards().size()) || (view->getNumberCards() == -1))
view->addCard(new CardItem(player, card->getName(), card->getId()), reorganize, x, y);
if (view)
if ((x <= view->getCards().size()) || (view->getNumberCards() == -1))
view->addCard(new CardItem(player, card->getName(), card->getId()), reorganize, x, y);
card->setZone(this);
addCardImpl(card, x, y);
card->setZone(this);
addCardImpl(card, x, y);
if (reorganize)
reorganizeCards();
emit cardCountChanged();
if (reorganize)
reorganizeCards();
emit cardCountChanged();
}
CardItem *CardZone::getCard(int cardId, const QString &cardName)
{
CardItem *c = cards.findCard(cardId, false);
if (!c) {
qDebug() << "CardZone::getCard: card id=" << cardId << "not found";
return 0;
}
// If the card's id is -1, this zone is invisible,
// so we need to give the card an id and a name as it comes out.
// It can be assumed that in an invisible zone, all cards are equal.
if ((c->getId() == -1) || (c->getName().isEmpty())) {
c->setId(cardId);
c->setName(cardName);
}
return c;
CardItem *c = cards.findCard(cardId, false);
if (!c) {
qDebug() << "CardZone::getCard: card id=" << cardId << "not found";
return 0;
}
// If the card's id is -1, this zone is invisible,
// so we need to give the card an id and a name as it comes out.
// It can be assumed that in an invisible zone, all cards are equal.
if ((c->getId() == -1) || (c->getName().isEmpty())) {
c->setId(cardId);
c->setName(cardName);
}
return c;
}
CardItem *CardZone::takeCard(int position, int cardId, bool /*canResize*/)
{
if (position == -1) {
// position == -1 means either that the zone is indexed by card id
// or that it doesn't matter which card you take.
for (int i = 0; i < cards.size(); ++i)
if (cards[i]->getId() == cardId) {
position = i;
break;
}
if (position == -1)
position = 0;
}
if (position >= cards.size())
return 0;
if (position == -1) {
// position == -1 means either that the zone is indexed by card id
// or that it doesn't matter which card you take.
for (int i = 0; i < cards.size(); ++i)
if (cards[i]->getId() == cardId) {
position = i;
break;
}
if (position == -1)
position = 0;
}
if (position >= cards.size())
return 0;
CardItem *c = cards.takeAt(position);
CardItem *c = cards.takeAt(position);
if (view)
view->removeCard(position);
if (view)
view->removeCard(position);
c->setId(cardId);
c->setId(cardId);
reorganizeCards();
emit cardCountChanged();
return c;
reorganizeCards();
emit cardCountChanged();
return c;
}
void CardZone::removeCard(CardItem *card)
{
cards.removeAt(cards.indexOf(card));
reorganizeCards();
emit cardCountChanged();
player->deleteCard(card);
cards.removeAt(cards.indexOf(card));
reorganizeCards();
emit cardCountChanged();
player->deleteCard(card);
}
void CardZone::moveAllToZone()
{
QList<QVariant> data = static_cast<QAction *>(sender())->data().toList();
QString targetZone = data[0].toString();
int targetX = data[1].toInt();
QList<CardToMove *> idList;
for (int i = 0; i < cards.size(); ++i)
idList.append(new CardToMove(cards[i]->getId()));
player->sendGameCommand(new Command_MoveCard(-1, getName(), idList, player->getId(), targetZone, targetX));
QList<QVariant> data = static_cast<QAction *>(sender())->data().toList();
QString targetZone = data[0].toString();
int targetX = data[1].toInt();
Command_MoveCard cmd;
cmd.set_start_zone(getName().toStdString());
cmd.set_target_player_id(player->getId());
cmd.set_target_zone(targetZone.toStdString());
cmd.set_x(targetX);
for (int i = 0; i < cards.size(); ++i)
cmd.mutable_cards_to_move()->add_card()->set_card_id(cards[i]->getId());
player->sendGameCommand(cmd);
}
QPointF CardZone::closestGridPoint(const QPointF &point)
{
return point;
return point;
}

View file

@ -3,7 +3,6 @@
#include <QString>
#include "cardlist.h"
#include "carditem.h"
#include "abstractgraphicsitem.h"
#include "translation.h"
@ -15,51 +14,56 @@ class QPainter;
class CardDragItem;
class CardZone : public AbstractGraphicsItem {
Q_OBJECT
Q_OBJECT
protected:
Player *player;
QString name;
CardList cards;
ZoneViewZone *view;
QMenu *menu;
QAction *doubleClickAction;
bool hasCardAttr;
bool isShufflable;
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
void mousePressEvent(QGraphicsSceneMouseEvent *event);
virtual void addCardImpl(CardItem *card, int x, int y) = 0;
Player *player;
QString name;
CardList cards;
ZoneViewZone *view;
QMenu *menu;
QAction *doubleClickAction;
bool hasCardAttr;
bool isShufflable;
bool isView;
bool alwaysRevealTopCard;
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
void mousePressEvent(QGraphicsSceneMouseEvent *event);
virtual void addCardImpl(CardItem *card, int x, int y) = 0;
signals:
void cardCountChanged();
void cardCountChanged();
public slots:
void moveAllToZone();
bool showContextMenu(const QPoint &screenPos);
void moveAllToZone();
bool showContextMenu(const QPoint &screenPos);
public:
enum { Type = typeZone };
int type() const { return Type; }
virtual void handleDropEvent(const QList<CardDragItem *> &dragItem, CardZone *startZone, const QPoint &dropPoint) = 0;
CardZone(Player *_player, const QString &_name, bool _hasCardAttr, bool _isShufflable, bool _contentsKnown, QGraphicsItem *parent = 0, bool isView = false);
~CardZone();
void retranslateUi();
void clearContents();
bool getHasCardAttr() const { return hasCardAttr; }
bool getIsShufflable() const { return isShufflable; }
QMenu *getMenu() const { return menu; }
void setMenu(QMenu *_menu, QAction *_doubleClickAction = 0) { menu = _menu; doubleClickAction = _doubleClickAction; }
QString getName() const { return name; }
QString getTranslatedName(bool hisOwn, GrammaticalCase gc) const;
Player *getPlayer() const { return player; }
bool contentsKnown() const { return cards.getContentsKnown(); }
const CardList &getCards() const { return cards; }
void addCard(CardItem *card, bool reorganize, int x, int y = -1);
// getCard() finds a card by id.
CardItem *getCard(int cardId, const QString &cardName);
// takeCard() finds a card by position and removes it from the zone and from all of its views.
virtual CardItem *takeCard(int position, int cardId, bool canResize = true);
void removeCard(CardItem *card);
ZoneViewZone *getView() const { return view; }
void setView(ZoneViewZone *_view) { view = _view; }
virtual void reorganizeCards() = 0;
virtual QPointF closestGridPoint(const QPointF &point);
enum { Type = typeZone };
int type() const { return Type; }
virtual void handleDropEvent(const QList<CardDragItem *> &dragItem, CardZone *startZone, const QPoint &dropPoint) = 0;
CardZone(Player *_player, const QString &_name, bool _hasCardAttr, bool _isShufflable, bool _contentsKnown, QGraphicsItem *parent = 0, bool _isView = false);
~CardZone();
void retranslateUi();
void clearContents();
bool getHasCardAttr() const { return hasCardAttr; }
bool getIsShufflable() const { return isShufflable; }
QMenu *getMenu() const { return menu; }
void setMenu(QMenu *_menu, QAction *_doubleClickAction = 0) { menu = _menu; doubleClickAction = _doubleClickAction; }
QString getName() const { return name; }
QString getTranslatedName(bool hisOwn, GrammaticalCase gc) const;
Player *getPlayer() const { return player; }
bool contentsKnown() const { return cards.getContentsKnown(); }
const CardList &getCards() const { return cards; }
void addCard(CardItem *card, bool reorganize, int x, int y = -1);
// getCard() finds a card by id.
CardItem *getCard(int cardId, const QString &cardName);
// takeCard() finds a card by position and removes it from the zone and from all of its views.
virtual CardItem *takeCard(int position, int cardId, bool canResize = true);
void removeCard(CardItem *card);
ZoneViewZone *getView() const { return view; }
void setView(ZoneViewZone *_view) { view = _view; }
virtual void reorganizeCards() = 0;
virtual QPointF closestGridPoint(const QPointF &point);
bool getIsView() const { return isView; }
bool getAlwaysRevealTopCard() const { return alwaysRevealTopCard; }
void setAlwaysRevealTopCard(bool _alwaysRevealTopCard) { alwaysRevealTopCard = _alwaysRevealTopCard; }
};
#endif

View file

@ -4,197 +4,262 @@
#include <QMouseEvent>
#include <QDesktopServices>
#include "chatview.h"
#include "user_level.h"
#include "user_context_menu.h"
#include "tab_supervisor.h"
#include "pixmapgenerator.h"
ChatView::ChatView(const QString &_ownName, bool _showTimestamps, QWidget *parent)
: QTextBrowser(parent), evenNumber(true), ownName(_ownName), showTimestamps(_showTimestamps)
ChatView::ChatView(const TabSupervisor *_tabSupervisor, TabGame *_game, bool _showTimestamps, QWidget *parent)
: QTextBrowser(parent), tabSupervisor(_tabSupervisor), game(_game), evenNumber(true), showTimestamps(_showTimestamps), hoveredItemType(HoveredNothing)
{
setReadOnly(true);
setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse);
setOpenLinks(false);
connect(this, SIGNAL(anchorClicked(const QUrl &)), this, SLOT(openLink(const QUrl &)));
document()->setDefaultStyleSheet("a { text-decoration: none; color: blue; }");
userContextMenu = new UserContextMenu(tabSupervisor, this, game);
connect(userContextMenu, SIGNAL(openMessageDialog(QString, bool)), this, SIGNAL(openMessageDialog(QString, bool)));
viewport()->setCursor(Qt::IBeamCursor);
setReadOnly(true);
setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse);
setOpenLinks(false);
connect(this, SIGNAL(anchorClicked(const QUrl &)), this, SLOT(openLink(const QUrl &)));
}
void ChatView::retranslateUi()
{
userContextMenu->retranslateUi();
}
QTextCursor ChatView::prepareBlock(bool same)
{
lastSender.clear();
QTextCursor cursor(document()->lastBlock());
cursor.movePosition(QTextCursor::End);
if (!same) {
QTextBlockFormat blockFormat;
if ((evenNumber = !evenNumber))
blockFormat.setBackground(palette().alternateBase());
blockFormat.setBottomMargin(2);
cursor.insertBlock(blockFormat);
} else
cursor.insertHtml("<br>");
return cursor;
lastSender.clear();
QTextCursor cursor(document()->lastBlock());
cursor.movePosition(QTextCursor::End);
if (!same) {
QTextBlockFormat blockFormat;
if ((evenNumber = !evenNumber))
blockFormat.setBackground(palette().alternateBase());
blockFormat.setBottomMargin(2);
cursor.insertBlock(blockFormat);
} else
cursor.insertHtml("<br>");
return cursor;
}
void ChatView::appendHtml(const QString &html)
{
bool atBottom = verticalScrollBar()->value() >= verticalScrollBar()->maximum();
prepareBlock().insertHtml(html);
if (atBottom)
verticalScrollBar()->setValue(verticalScrollBar()->maximum());
bool atBottom = verticalScrollBar()->value() >= verticalScrollBar()->maximum();
prepareBlock().insertHtml(html);
if (atBottom)
verticalScrollBar()->setValue(verticalScrollBar()->maximum());
}
void ChatView::appendMessage(QString sender, QString message, QColor playerColor, bool playerBold)
void ChatView::appendCardTag(QTextCursor &cursor, const QString &cardName)
{
bool atBottom = verticalScrollBar()->value() >= verticalScrollBar()->maximum();
bool sameSender = (sender == lastSender) && !lastSender.isEmpty();
QTextCursor cursor = prepareBlock(sameSender);
lastSender = sender;
if (showTimestamps && !sameSender) {
QTextCharFormat timeFormat;
timeFormat.setForeground(Qt::black);
cursor.setCharFormat(timeFormat);
cursor.insertText(QDateTime::currentDateTime().toString("[hh:mm] "));
}
QTextCharFormat senderFormat;
if (sender == ownName) {
senderFormat.setFontWeight(QFont::Bold);
senderFormat.setForeground(Qt::red);
} else {
if (playerColor == QColor())
senderFormat.setForeground(QColor(0, 0, 254));
else
senderFormat.setForeground(playerColor);
if (playerBold)
senderFormat.setFontWeight(QFont::Bold);
}
if (!sameSender) {
cursor.setCharFormat(senderFormat);
if (!sender.isEmpty())
sender.append(": ");
cursor.insertText(sender);
} else
cursor.insertText(" ");
QTextCharFormat messageFormat;
if (sender.isEmpty())
messageFormat.setForeground(Qt::darkGreen);
cursor.setCharFormat(messageFormat);
int from = 0, index = 0;
while ((index = message.indexOf('[', from)) != -1) {
cursor.insertText(message.left(index));
message = message.mid(index);
if (message.isEmpty())
break;
if (message.startsWith("[card]")) {
message = message.mid(6);
QTextCharFormat tempFormat = messageFormat;
tempFormat.setForeground(Qt::blue);
cursor.setCharFormat(tempFormat);
int closeTagIndex = message.indexOf("[/card]");
cursor.insertText(message.left(closeTagIndex));
cursor.setCharFormat(messageFormat);
if (closeTagIndex == -1)
message.clear();
else
message = message.mid(closeTagIndex + 7);
} else if (message.startsWith("[url]")) {
message = message.mid(5);
int closeTagIndex = message.indexOf("[/url]");
QString url = message.left(closeTagIndex);
if (!url.startsWith("http://"))
url.prepend("http://");
QTextCharFormat tempFormat = messageFormat;
tempFormat.setForeground(QColor(0, 0, 254));
tempFormat.setAnchor(true);
tempFormat.setAnchorHref(url);
cursor.setCharFormat(tempFormat);
cursor.insertText(url);
cursor.setCharFormat(messageFormat);
if (closeTagIndex == -1)
message.clear();
else
message = message.mid(closeTagIndex + 6);
} else
from = 1;
}
if (!message.isEmpty())
cursor.insertText(message);
if (atBottom)
verticalScrollBar()->setValue(verticalScrollBar()->maximum());
QTextCharFormat oldFormat = cursor.charFormat();
QTextCharFormat anchorFormat = oldFormat;
anchorFormat.setForeground(Qt::blue);
anchorFormat.setAnchor(true);
anchorFormat.setAnchorHref("card://" + cardName);
cursor.setCharFormat(anchorFormat);
cursor.insertText(cardName);
cursor.setCharFormat(oldFormat);
}
void ChatView::appendUrlTag(QTextCursor &cursor, QString url)
{
if (!url.contains("://"))
url.prepend("http://");
QTextCharFormat oldFormat = cursor.charFormat();
QTextCharFormat anchorFormat = oldFormat;
anchorFormat.setForeground(Qt::blue);
anchorFormat.setAnchor(true);
anchorFormat.setAnchorHref(url);
cursor.setCharFormat(anchorFormat);
cursor.insertText(url);
cursor.setCharFormat(oldFormat);
}
void ChatView::appendMessage(QString message, QString sender, UserLevelFlags userLevel, bool playerBold)
{
bool atBottom = verticalScrollBar()->value() >= verticalScrollBar()->maximum();
bool sameSender = (sender == lastSender) && !lastSender.isEmpty();
QTextCursor cursor = prepareBlock(sameSender);
lastSender = sender;
if (showTimestamps && !sameSender) {
QTextCharFormat timeFormat;
timeFormat.setForeground(Qt::black);
cursor.setCharFormat(timeFormat);
cursor.insertText(QDateTime::currentDateTime().toString("[hh:mm] "));
}
QTextCharFormat senderFormat;
if (tabSupervisor && tabSupervisor->getUserInfo() && (sender == QString::fromStdString(tabSupervisor->getUserInfo()->name()))) {
senderFormat.setFontWeight(QFont::Bold);
senderFormat.setForeground(Qt::red);
} else {
senderFormat.setForeground(Qt::blue);
if (playerBold)
senderFormat.setFontWeight(QFont::Bold);
}
senderFormat.setAnchor(true);
senderFormat.setAnchorHref("user://" + QString::number(userLevel) + "_" + sender);
if (!sameSender) {
if (!sender.isEmpty()) {
const int pixelSize = QFontInfo(cursor.charFormat().font()).pixelSize();
cursor.insertImage(UserLevelPixmapGenerator::generatePixmap(pixelSize, userLevel).toImage(), QString::number(pixelSize) + "_" + QString::number((int) userLevel));
cursor.insertText(" ");
}
cursor.setCharFormat(senderFormat);
if (!sender.isEmpty())
sender.append(": ");
cursor.insertText(sender);
} else
cursor.insertText(" ");
QTextCharFormat messageFormat;
if (sender.isEmpty())
messageFormat.setForeground(Qt::darkGreen);
cursor.setCharFormat(messageFormat);
int from = 0, index = 0;
while ((index = message.indexOf('[', from)) != -1) {
cursor.insertText(message.left(index));
message = message.mid(index);
if (message.isEmpty())
break;
if (message.startsWith("[card]")) {
message = message.mid(6);
int closeTagIndex = message.indexOf("[/card]");
QString cardName = message.left(closeTagIndex);
if (closeTagIndex == -1)
message.clear();
else
message = message.mid(closeTagIndex + 7);
appendCardTag(cursor, cardName);
} else if (message.startsWith("[[")) {
message = message.mid(2);
int closeTagIndex = message.indexOf("]]");
QString cardName = message.left(closeTagIndex);
if (closeTagIndex == -1)
message.clear();
else
message = message.mid(closeTagIndex + 2);
appendCardTag(cursor, cardName);
} else if (message.startsWith("[url]")) {
message = message.mid(5);
int closeTagIndex = message.indexOf("[/url]");
QString url = message.left(closeTagIndex);
if (closeTagIndex == -1)
message.clear();
else
message = message.mid(closeTagIndex + 6);
appendUrlTag(cursor, url);
} else
from = 1;
}
if (!message.isEmpty())
cursor.insertText(message);
if (atBottom)
verticalScrollBar()->setValue(verticalScrollBar()->maximum());
}
void ChatView::enterEvent(QEvent * /*event*/)
{
setMouseTracking(true);
setMouseTracking(true);
}
void ChatView::leaveEvent(QEvent * /*event*/)
{
setMouseTracking(false);
setMouseTracking(false);
}
QTextFragment ChatView::getFragmentUnderMouse(const QPoint &pos) const
{
QTextCursor cursor(cursorForPosition(pos));
QTextBlock block(cursor.block());
QTextBlock::iterator it;
for (it = block.begin(); !(it.atEnd()); ++it) {
QTextFragment frag = it.fragment();
if (frag.contains(cursor.position()))
return frag;
}
return QTextFragment();
}
QString ChatView::getCardNameUnderMouse(QTextFragment frag) const
{
if (frag.charFormat().foreground().color() == Qt::blue)
return frag.text();
return QString();
}
QString ChatView::getCardNameUnderMouse(const QPoint &pos) const
{
return getCardNameUnderMouse(getFragmentUnderMouse(pos));
QTextCursor cursor(cursorForPosition(pos));
QTextBlock block(cursor.block());
QTextBlock::iterator it;
for (it = block.begin(); !(it.atEnd()); ++it) {
QTextFragment frag = it.fragment();
if (frag.contains(cursor.position()))
return frag;
}
return QTextFragment();
}
void ChatView::mouseMoveEvent(QMouseEvent *event)
{
QTextFragment frag = getFragmentUnderMouse(event->pos());
QString cardName = getCardNameUnderMouse(frag);
if (!cardName.isEmpty()) {
viewport()->setCursor(Qt::PointingHandCursor);
emit cardNameHovered(cardName);
} else if (frag.charFormat().isAnchor())
viewport()->setCursor(Qt::PointingHandCursor);
else
viewport()->setCursor(Qt::IBeamCursor);
QTextBrowser::mouseMoveEvent(event);
QString anchorHref = getFragmentUnderMouse(event->pos()).charFormat().anchorHref();
if (!anchorHref.isEmpty()) {
const int delimiterIndex = anchorHref.indexOf("://");
if (delimiterIndex != -1) {
const QString scheme = anchorHref.left(delimiterIndex);
hoveredContent = anchorHref.mid(delimiterIndex + 3);
if (scheme == "card") {
hoveredItemType = HoveredCard;
emit cardNameHovered(hoveredContent);
} else if (scheme == "user")
hoveredItemType = HoveredUser;
else
hoveredItemType = HoveredUrl;
viewport()->setCursor(Qt::PointingHandCursor);
} else {
hoveredItemType = HoveredNothing;
viewport()->setCursor(Qt::IBeamCursor);
}
} else {
hoveredItemType = HoveredNothing;
viewport()->setCursor(Qt::IBeamCursor);
}
QTextBrowser::mouseMoveEvent(event);
}
void ChatView::mousePressEvent(QMouseEvent *event)
{
if ((event->button() == Qt::MidButton) || (event->button() == Qt::LeftButton)) {
QString cardName = getCardNameUnderMouse(event->pos());
if (!cardName.isEmpty())
emit showCardInfoPopup(event->globalPos(), cardName);
}
QTextBrowser::mousePressEvent(event);
switch (hoveredItemType) {
case HoveredCard: {
if ((event->button() == Qt::MidButton) || (event->button() == Qt::LeftButton))
emit showCardInfoPopup(event->globalPos(), hoveredContent);
break;
}
case HoveredUser: {
if (event->button() == Qt::RightButton) {
const int delimiterIndex = hoveredContent.indexOf("_");
UserLevelFlags userLevel(hoveredContent.left(delimiterIndex).toInt());
const QString userName = hoveredContent.mid(delimiterIndex + 1);
userContextMenu->showContextMenu(event->globalPos(), userName, userLevel);
}
break;
}
default: {
QTextBrowser::mousePressEvent(event);
}
}
}
void ChatView::mouseReleaseEvent(QMouseEvent *event)
{
if ((event->button() == Qt::MidButton) || (event->button() == Qt::LeftButton))
emit deleteCardInfoPopup(QString("_"));
QTextBrowser::mouseReleaseEvent(event);
if ((event->button() == Qt::MidButton) || (event->button() == Qt::LeftButton))
emit deleteCardInfoPopup(QString("_"));
QTextBrowser::mouseReleaseEvent(event);
}
void ChatView::openLink(const QUrl &link)
{
QDesktopServices::openUrl(link);
if ((link.scheme() == "card") || (link.scheme() == "user"))
return;
QDesktopServices::openUrl(link);
}

View file

@ -5,37 +5,49 @@
#include <QTextFragment>
#include <QTextCursor>
#include <QColor>
#include "user_level.h"
class QTextTable;
class QMouseEvent;
class UserContextMenu;
class TabSupervisor;
class TabGame;
class ChatView : public QTextBrowser {
Q_OBJECT;
private:
QString lastSender;
bool evenNumber;
QString ownName;
bool showTimestamps;
QTextFragment getFragmentUnderMouse(const QPoint &pos) const;
QString getCardNameUnderMouse(QTextFragment frag) const;
QString getCardNameUnderMouse(const QPoint &pos) const;
QTextCursor prepareBlock(bool same = false);
private slots:
void openLink(const QUrl &link);
public:
ChatView(const QString &_ownName, bool _showTimestamps, QWidget *parent = 0);
void appendHtml(const QString &html);
void appendMessage(QString sender, QString message, QColor playerColor = QColor(), bool playerBold = false);
Q_OBJECT
protected:
void enterEvent(QEvent *event);
void leaveEvent(QEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
const TabSupervisor * const tabSupervisor;
TabGame * const game;
private:
enum HoveredItemType { HoveredNothing, HoveredUrl, HoveredCard, HoveredUser };
UserContextMenu *userContextMenu;
QString lastSender;
bool evenNumber;
bool showTimestamps;
HoveredItemType hoveredItemType;
QString hoveredContent;
QTextFragment getFragmentUnderMouse(const QPoint &pos) const;
QTextCursor prepareBlock(bool same = false);
void appendCardTag(QTextCursor &cursor, const QString &cardName);
void appendUrlTag(QTextCursor &cursor, QString url);
private slots:
void openLink(const QUrl &link);
public:
ChatView(const TabSupervisor *_tabSupervisor, TabGame *_game, bool _showTimestamps, QWidget *parent = 0);
void retranslateUi();
void appendHtml(const QString &html);
void appendMessage(QString message, QString sender = QString(), UserLevelFlags userLevel = UserLevelFlags(), bool playerBold = false);
protected:
void enterEvent(QEvent *event);
void leaveEvent(QEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
signals:
void cardNameHovered(QString cardName);
void showCardInfoPopup(QPoint pos, QString cardName);
void deleteCardInfoPopup(QString cardName);
void openMessageDialog(const QString &userName, bool focus);
void cardNameHovered(QString cardName);
void showCardInfoPopup(QPoint pos, QString cardName);
void deleteCardInfoPopup(QString cardName);
};
#endif
#endif

View file

@ -0,0 +1,29 @@
#ifndef CLIENT_METATYPES_H
#define CLIENT_METATYPES_H
#include <QMetaType>
Q_DECLARE_METATYPE(QVariant)
Q_DECLARE_METATYPE(CommandContainer)
Q_DECLARE_METATYPE(Response)
Q_DECLARE_METATYPE(Response::ResponseCode)
Q_DECLARE_METATYPE(ClientStatus)
Q_DECLARE_METATYPE(RoomEvent)
Q_DECLARE_METATYPE(GameEventContainer)
Q_DECLARE_METATYPE(Event_ServerIdentification)
Q_DECLARE_METATYPE(Event_ConnectionClosed)
Q_DECLARE_METATYPE(Event_ServerShutdown)
Q_DECLARE_METATYPE(Event_AddToList)
Q_DECLARE_METATYPE(Event_RemoveFromList)
Q_DECLARE_METATYPE(Event_UserJoined)
Q_DECLARE_METATYPE(Event_UserLeft)
Q_DECLARE_METATYPE(Event_ServerMessage)
Q_DECLARE_METATYPE(Event_ListRooms)
Q_DECLARE_METATYPE(Event_GameJoined)
Q_DECLARE_METATYPE(Event_UserMessage)
Q_DECLARE_METATYPE(ServerInfo_User)
Q_DECLARE_METATYPE(QList<ServerInfo_User>)
Q_DECLARE_METATYPE(Event_ReplayAdded)
#endif

View file

@ -3,34 +3,34 @@
#include <QPainter>
GeneralCounter::GeneralCounter(Player *_player, int _id, const QString &_name, const QColor &_color, int _radius, int _value, QGraphicsItem *parent)
: AbstractCounter(_player, _id, _name, true, _value, parent), color(_color), radius(_radius)
: AbstractCounter(_player, _id, _name, true, _value, parent), color(_color), radius(_radius)
{
setCacheMode(DeviceCoordinateCache);
setCacheMode(DeviceCoordinateCache);
}
QRectF GeneralCounter::boundingRect() const
{
return QRectF(0, 0, radius * 2, radius * 2);
return QRectF(0, 0, radius * 2, radius * 2);
}
void GeneralCounter::paint(QPainter *painter, const QStyleOptionGraphicsItem */*option*/, QWidget */*widget*/)
void GeneralCounter::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/)
{
QRectF mapRect = painter->combinedTransform().mapRect(boundingRect());
int translatedHeight = mapRect.size().height();
qreal scaleFactor = translatedHeight / boundingRect().height();
QPixmap pixmap = CounterPixmapGenerator::generatePixmap(translatedHeight, name, hovered);
painter->save();
painter->resetTransform();
painter->drawPixmap(QPoint(0, 0), pixmap);
QRectF mapRect = painter->combinedTransform().mapRect(boundingRect());
int translatedHeight = mapRect.size().height();
qreal scaleFactor = translatedHeight / boundingRect().height();
QPixmap pixmap = CounterPixmapGenerator::generatePixmap(translatedHeight, name, hovered);
painter->save();
painter->resetTransform();
painter->drawPixmap(QPoint(0, 0), pixmap);
if (value) {
QFont f("Serif");
f.setPixelSize(qMax((int) (radius * scaleFactor), 10));
f.setWeight(QFont::Bold);
painter->setPen(Qt::black);
painter->setFont(f);
painter->drawText(mapRect, Qt::AlignCenter, QString::number(value));
}
painter->restore();
if (value) {
QFont f("Serif");
f.setPixelSize(qMax((int) (radius * scaleFactor), 10));
f.setWeight(QFont::Bold);
painter->setPen(Qt::black);
painter->setFont(f);
painter->drawText(mapRect, Qt::AlignCenter, QString::number(value));
}
painter->restore();
}

View file

@ -4,14 +4,14 @@
#include "abstractcounter.h"
class GeneralCounter : public AbstractCounter {
Q_OBJECT
Q_OBJECT
private:
QColor color;
int radius;
QColor color;
int radius;
public:
GeneralCounter(Player *_player, int _id, const QString &_name, const QColor &_color, int _radius, int _value, QGraphicsItem *parent = 0);
QRectF boundingRect() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
GeneralCounter(Player *_player, int _id, const QString &_name, const QColor &_color, int _radius, int _value, QGraphicsItem *parent = 0);
QRectF boundingRect() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
};
#endif
#endif

View file

@ -0,0 +1,110 @@
#include <QStringList>
#include <QFile>
#include <QDebug>
#include "deck_loader.h"
#include "decklist.h"
const QStringList DeckLoader::fileNameFilters = QStringList()
<< QObject::tr("Common deck formats (*.cod *.dec *.mwDeck)")
<< QObject::tr("All files (*.*)");
DeckLoader::DeckLoader()
: DeckList(),
lastFileName(QString()),
lastFileFormat(CockatriceFormat),
lastRemoteDeckId(-1)
{
}
DeckLoader::DeckLoader(const QString &nativeString)
: DeckList(nativeString),
lastFileName(QString()),
lastFileFormat(CockatriceFormat),
lastRemoteDeckId(-1)
{
}
DeckLoader::DeckLoader(const DeckList &other)
: DeckList(other),
lastFileName(QString()),
lastFileFormat(CockatriceFormat),
lastRemoteDeckId(-1)
{
}
DeckLoader::DeckLoader(const DeckLoader &other)
: DeckList(other),
lastFileName(other.lastFileName),
lastFileFormat(other.lastFileFormat),
lastRemoteDeckId(other.lastRemoteDeckId)
{
}
bool DeckLoader::loadFromFile(const QString &fileName, FileFormat fmt)
{
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
return false;
bool result = false;
switch (fmt) {
case PlainTextFormat: result = loadFromFile_Plain(&file); break;
case CockatriceFormat:
result = loadFromFile_Native(&file);
qDebug() << "Loaded from" << fileName << "-" << result;
if (!result) {
qDebug() << "Retying as plain format";
file.seek(0);
result = loadFromFile_Plain(&file);
fmt = PlainTextFormat;
}
break;
}
if (result) {
lastFileName = fileName;
lastFileFormat = fmt;
emit deckLoaded();
}
qDebug() << "Deck was loaded -" << result;
return result;
}
bool DeckLoader::loadFromRemote(const QString &nativeString, int remoteDeckId)
{
bool result = loadFromString_Native(nativeString);
if (result) {
lastFileName = QString();
lastFileFormat = CockatriceFormat;
lastRemoteDeckId = remoteDeckId;
emit deckLoaded();
}
return result;
}
bool DeckLoader::saveToFile(const QString &fileName, FileFormat fmt)
{
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
return false;
bool result = false;
switch (fmt) {
case PlainTextFormat: result = saveToFile_Plain(&file); break;
case CockatriceFormat: result = saveToFile_Native(&file); break;
}
if (result) {
lastFileName = fileName;
lastFileFormat = fmt;
}
return result;
}
DeckLoader::FileFormat DeckLoader::getFormatFromName(const QString &fileName)
{
if (fileName.endsWith(".cod", Qt::CaseInsensitive)) {
return CockatriceFormat;
}
return PlainTextFormat;
}

View file

@ -0,0 +1,33 @@
#ifndef DECK_LOADER_H
#define DECK_LOADER_H
#include "decklist.h"
class DeckLoader : public DeckList {
Q_OBJECT
signals:
void deckLoaded();
public:
enum FileFormat { PlainTextFormat, CockatriceFormat };
static const QStringList fileNameFilters;
private:
QString lastFileName;
FileFormat lastFileFormat;
int lastRemoteDeckId;
public:
DeckLoader();
DeckLoader(const QString &nativeString);
DeckLoader(const DeckList &other);
DeckLoader(const DeckLoader &other);
const QString &getLastFileName() const { return lastFileName; }
FileFormat getLastFileFormat() const { return lastFileFormat; }
int getLastRemoteDeckId() const { return lastRemoteDeckId; }
static FileFormat getFormatFromName(const QString &fileName);
bool loadFromFile(const QString &fileName, FileFormat fmt);
bool loadFromRemote(const QString &nativeString, int remoteDeckId);
bool saveToFile(const QString &fileName, FileFormat fmt);
};
#endif

View file

@ -11,427 +11,468 @@
#include "decklistmodel.h"
#include "carddatabase.h"
#include "settingscache.h"
#include "deck_loader.h"
DeckListModel::DeckListModel(QObject *parent)
: QAbstractItemModel(parent)
: QAbstractItemModel(parent), lastKnownColumn(1), lastKnownOrder(Qt::AscendingOrder)
{
deckList = new DeckList;
connect(deckList, SIGNAL(deckLoaded()), this, SLOT(rebuildTree()));
connect(deckList, SIGNAL(deckHashChanged()), this, SIGNAL(deckHashChanged()));
root = new InnerDecklistNode;
deckList = new DeckLoader;
connect(deckList, SIGNAL(deckLoaded()), this, SLOT(rebuildTree()));
connect(deckList, SIGNAL(deckHashChanged()), this, SIGNAL(deckHashChanged()));
root = new InnerDecklistNode;
}
DeckListModel::~DeckListModel()
{
delete root;
delete deckList;
delete root;
delete deckList;
}
void DeckListModel::rebuildTree()
{
root->clearTree();
InnerDecklistNode *listRoot = deckList->getRoot();
for (int i = 0; i < listRoot->size(); i++) {
InnerDecklistNode *currentZone = dynamic_cast<InnerDecklistNode *>(listRoot->at(i));
InnerDecklistNode *node = new InnerDecklistNode(currentZone->getName(), root);
for (int j = 0; j < currentZone->size(); j++) {
DecklistCardNode *currentCard = dynamic_cast<DecklistCardNode *>(currentZone->at(j));
// XXX better sanity checking
if (!currentCard)
continue;
beginResetModel();
CardInfo *info = db->getCard(currentCard->getName());
QString cardType;
if (!info)
cardType = "unknown";
else
cardType = info->getMainCardType();
InnerDecklistNode *cardTypeNode = dynamic_cast<InnerDecklistNode *>(node->findChild(cardType));
if (!cardTypeNode)
cardTypeNode = new InnerDecklistNode(cardType, node);
root->clearTree();
InnerDecklistNode *listRoot = deckList->getRoot();
for (int i = 0; i < listRoot->size(); i++) {
InnerDecklistNode *currentZone = dynamic_cast<InnerDecklistNode *>(listRoot->at(i));
InnerDecklistNode *node = new InnerDecklistNode(currentZone->getName(), root);
for (int j = 0; j < currentZone->size(); j++) {
DecklistCardNode *currentCard = dynamic_cast<DecklistCardNode *>(currentZone->at(j));
// XXX better sanity checking
if (!currentCard)
continue;
new DecklistModelCardNode(currentCard, cardTypeNode);
}
}
CardInfo *info = db->getCard(currentCard->getName());
QString cardType;
if (!info)
cardType = "unknown";
else
cardType = info->getMainCardType();
InnerDecklistNode *cardTypeNode = dynamic_cast<InnerDecklistNode *>(node->findChild(cardType));
if (!cardTypeNode)
cardTypeNode = new InnerDecklistNode(cardType, node);
reset();
new DecklistModelCardNode(currentCard, cardTypeNode);
}
}
endResetModel();
}
int DeckListModel::rowCount(const QModelIndex &parent) const
{
// debugIndexInfo("rowCount", parent);
InnerDecklistNode *node = getNode<InnerDecklistNode *>(parent);
if (node)
return node->size();
else
return 0;
// debugIndexInfo("rowCount", parent);
InnerDecklistNode *node = getNode<InnerDecklistNode *>(parent);
if (node)
return node->size();
else
return 0;
}
int DeckListModel::columnCount(const QModelIndex &/*parent*/) const
{
if (settingsCache->getPriceTagFeature())
return 3;
else
return 2;
if (settingsCache->getPriceTagFeature())
return 3;
else
return 2;
}
QVariant DeckListModel::data(const QModelIndex &index, int role) const
{
// debugIndexInfo("data", index);
if (!index.isValid())
return QVariant();
// debugIndexInfo("data", index);
if (!index.isValid())
return QVariant();
if (index.column() >= columnCount())
return QVariant();
return QVariant();
AbstractDecklistNode *temp = static_cast<AbstractDecklistNode *>(index.internalPointer());
DecklistModelCardNode *card = dynamic_cast<DecklistModelCardNode *>(temp);
if (!card) {
InnerDecklistNode *node = dynamic_cast<InnerDecklistNode *>(temp);
switch (role) {
case Qt::FontRole: {
QFont f;
f.setBold(true);
return f;
}
case Qt::DisplayRole:
case Qt::EditRole:
switch (index.column()) {
AbstractDecklistNode *temp = static_cast<AbstractDecklistNode *>(index.internalPointer());
DecklistModelCardNode *card = dynamic_cast<DecklistModelCardNode *>(temp);
if (!card) {
InnerDecklistNode *node = dynamic_cast<InnerDecklistNode *>(temp);
switch (role) {
case Qt::FontRole: {
QFont f;
f.setBold(true);
return f;
}
case Qt::DisplayRole:
case Qt::EditRole:
switch (index.column()) {
case 0: return node->recursiveCount(true);
case 1: return node->getVisibleName();
case 2: return QString().sprintf("$%.2f", node->recursivePrice(true));
default: return QVariant();
}
case Qt::BackgroundRole: {
int color = 90 + 60 * node->depth();
return QBrush(QColor(color, 255, color));
}
default: return QVariant();
}
} else {
switch (role) {
case Qt::DisplayRole:
case Qt::EditRole: {
switch (index.column()) {
default: return QVariant();
}
case Qt::BackgroundRole: {
int color = 90 + 60 * node->depth();
return QBrush(QColor(color, 255, color));
}
default: return QVariant();
}
} else {
switch (role) {
case Qt::DisplayRole:
case Qt::EditRole: {
switch (index.column()) {
case 0: return card->getNumber();
case 1: return card->getName();
case 2: return QString().sprintf("$%.2f", card->getTotalPrice());
default: return QVariant();
}
}
case Qt::BackgroundRole: {
int color = 255 - (index.row() % 2) * 30;
return QBrush(QColor(color, color, color));
}
default: return QVariant();
}
}
default: return QVariant();
}
}
case Qt::BackgroundRole: {
int color = 255 - (index.row() % 2) * 30;
return QBrush(QColor(color, color, color));
}
default: return QVariant();
}
}
}
QVariant DeckListModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if ((role != Qt::DisplayRole) || (orientation != Qt::Horizontal))
return QVariant();
if ((role != Qt::DisplayRole) || (orientation != Qt::Horizontal))
return QVariant();
if (section >= columnCount())
return QVariant();
switch (section) {
return QVariant();
switch (section) {
case 0: return tr("Number");
case 1: return tr("Card");
case 2: return tr("Price");
default: return QVariant();
}
default: return QVariant();
}
}
QModelIndex DeckListModel::index(int row, int column, const QModelIndex &parent) const
{
// debugIndexInfo("index", parent);
if (!hasIndex(row, column, parent))
return QModelIndex();
// debugIndexInfo("index", parent);
if (!hasIndex(row, column, parent))
return QModelIndex();
InnerDecklistNode *parentNode = getNode<InnerDecklistNode *>(parent);
if (row >= parentNode->size())
return QModelIndex();
InnerDecklistNode *parentNode = getNode<InnerDecklistNode *>(parent);
if (row >= parentNode->size())
return QModelIndex();
return createIndex(row, column, parentNode->at(row));
return createIndex(row, column, parentNode->at(row));
}
QModelIndex DeckListModel::parent(const QModelIndex &ind) const
{
if (!ind.isValid())
return QModelIndex();
if (!ind.isValid())
return QModelIndex();
return nodeToIndex(static_cast<AbstractDecklistNode *>(ind.internalPointer())->getParent());
return nodeToIndex(static_cast<AbstractDecklistNode *>(ind.internalPointer())->getParent());
}
Qt::ItemFlags DeckListModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return 0;
if (!index.isValid())
return 0;
Qt::ItemFlags result = Qt::ItemIsEnabled;
if (getNode<DecklistModelCardNode *>(index))
result |= Qt::ItemIsSelectable;
Qt::ItemFlags result = Qt::ItemIsEnabled;
result |= Qt::ItemIsSelectable;
return result;
return result;
}
void DeckListModel::emitRecursiveUpdates(const QModelIndex &index)
{
if (!index.isValid())
return;
emit dataChanged(index, index);
emitRecursiveUpdates(index.parent());
if (!index.isValid())
return;
emit dataChanged(index, index);
emitRecursiveUpdates(index.parent());
}
bool DeckListModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
DecklistModelCardNode *node = getNode<DecklistModelCardNode *>(index);
if (!node || (role != Qt::EditRole))
return false;
DecklistModelCardNode *node = getNode<DecklistModelCardNode *>(index);
if (!node || (role != Qt::EditRole))
return false;
switch (index.column()) {
switch (index.column()) {
case 0: node->setNumber(value.toInt()); break;
case 1: node->setName(value.toString()); break;
case 2: node->setPrice(value.toFloat()); break;
default: return false;
}
emitRecursiveUpdates(index);
deckList->updateDeckHash();
return true;
default: return false;
}
emitRecursiveUpdates(index);
deckList->updateDeckHash();
return true;
}
bool DeckListModel::removeRows(int row, int count, const QModelIndex &parent)
{
InnerDecklistNode *node = getNode<InnerDecklistNode *>(parent);
if (!node)
return false;
if (row + count > node->size())
return false;
InnerDecklistNode *node = getNode<InnerDecklistNode *>(parent);
if (!node)
return false;
if (row + count > node->size())
return false;
beginRemoveRows(parent, row, row + count - 1);
for (int i = 0; i < count; i++) {
AbstractDecklistNode *toDelete = node->takeAt(row);
if (DecklistModelCardNode *temp = dynamic_cast<DecklistModelCardNode *>(toDelete))
deckList->deleteNode(temp->getDataNode());
delete toDelete;
}
endRemoveRows();
beginRemoveRows(parent, row, row + count - 1);
for (int i = 0; i < count; i++) {
AbstractDecklistNode *toDelete = node->takeAt(row);
if (DecklistModelCardNode *temp = dynamic_cast<DecklistModelCardNode *>(toDelete))
deckList->deleteNode(temp->getDataNode());
delete toDelete;
}
endRemoveRows();
if (!node->size() && (node != root))
removeRows(parent.row(), 1, parent.parent());
else
emitRecursiveUpdates(parent);
if (!node->size() && (node != root))
removeRows(parent.row(), 1, parent.parent());
else
emitRecursiveUpdates(parent);
return true;
return true;
}
InnerDecklistNode *DeckListModel::createNodeIfNeeded(const QString &name, InnerDecklistNode *parent)
{
InnerDecklistNode *newNode = dynamic_cast<InnerDecklistNode *>(parent->findChild(name));
if (!newNode) {
beginInsertRows(nodeToIndex(parent), parent->size(), parent->size());
newNode = new InnerDecklistNode(name, parent);
endInsertRows();
}
return newNode;
InnerDecklistNode *newNode = dynamic_cast<InnerDecklistNode *>(parent->findChild(name));
if (!newNode) {
beginInsertRows(nodeToIndex(parent), parent->size(), parent->size());
newNode = new InnerDecklistNode(name, parent);
endInsertRows();
}
return newNode;
}
DecklistModelCardNode *DeckListModel::findCardNode(const QString &cardName, const QString &zoneName) const
{
InnerDecklistNode *zoneNode, *typeNode;
CardInfo *info;
QString cardType;
zoneNode = dynamic_cast<InnerDecklistNode *>(root->findChild(zoneName));
if(!zoneNode)
return NULL;
info = db->getCard(cardName);
if(!info)
return NULL;
cardType = info->getMainCardType();
typeNode = dynamic_cast<InnerDecklistNode *>(zoneNode->findChild(cardType));
if(!typeNode)
return NULL;
return dynamic_cast<DecklistModelCardNode *>(typeNode->findChild(cardName));
}
QModelIndex DeckListModel::findCard(const QString &cardName, const QString &zoneName) const
{
DecklistModelCardNode *cardNode;
cardNode = findCardNode(cardName, zoneName);
if(!cardNode)
return QModelIndex();
return nodeToIndex(cardNode);
}
QModelIndex DeckListModel::addCard(const QString &cardName, const QString &zoneName)
{
InnerDecklistNode *zoneNode = createNodeIfNeeded(zoneName, root);
InnerDecklistNode *zoneNode = createNodeIfNeeded(zoneName, root);
CardInfo *info = db->getCard(cardName);
QString cardType = info->getMainCardType();
InnerDecklistNode *cardTypeNode = createNodeIfNeeded(cardType, zoneNode);
CardInfo *info = db->getCard(cardName);
QString cardType = info->getMainCardType();
InnerDecklistNode *cardTypeNode = createNodeIfNeeded(cardType, zoneNode);
DecklistModelCardNode *cardNode = dynamic_cast<DecklistModelCardNode *>(cardTypeNode->findChild(cardName));
if (!cardNode) {
DecklistCardNode *decklistCard = deckList->addCard(cardName, zoneName);
QModelIndex parentIndex = nodeToIndex(cardTypeNode);
beginInsertRows(parentIndex, cardTypeNode->size(), cardTypeNode->size());
cardNode = new DecklistModelCardNode(decklistCard, cardTypeNode);
endInsertRows();
sort(1);
emitRecursiveUpdates(parentIndex);
return nodeToIndex(cardNode);
} else {
cardNode->setNumber(cardNode->getNumber() + 1);
QModelIndex ind = nodeToIndex(cardNode);
emitRecursiveUpdates(ind);
deckList->updateDeckHash();
return ind;
}
QModelIndex parentIndex = nodeToIndex(cardTypeNode);
DecklistModelCardNode *cardNode = dynamic_cast<DecklistModelCardNode *>(cardTypeNode->findChild(cardName));
if (!cardNode) {
DecklistCardNode *decklistCard = deckList->addCard(cardName, zoneName);
beginInsertRows(parentIndex, cardTypeNode->size(), cardTypeNode->size());
cardNode = new DecklistModelCardNode(decklistCard, cardTypeNode);
endInsertRows();
} else {
cardNode->setNumber(cardNode->getNumber() + 1);
deckList->updateDeckHash();
}
sort(lastKnownColumn, lastKnownOrder);
emitRecursiveUpdates(parentIndex);
return nodeToIndex(cardNode);
}
QModelIndex DeckListModel::nodeToIndex(AbstractDecklistNode *node) const
{
if (node == root)
return QModelIndex();
return createIndex(node->getParent()->indexOf(node), 0, node);
if (node == root)
return QModelIndex();
return createIndex(node->getParent()->indexOf(node), 0, node);
}
void DeckListModel::sortHelper(InnerDecklistNode *node, Qt::SortOrder order)
{
// Sort children of node and save the information needed to
// update the list of persistent indexes.
QVector<QPair<int, int> > sortResult = node->sort(order);
QModelIndexList from, to;
for (int i = sortResult.size() - 1; i >= 0; --i) {
const int fromRow = sortResult[i].first;
const int toRow = sortResult[i].second;
AbstractDecklistNode *temp = node->at(toRow);
for (int j = columnCount(); j; --j) {
from << createIndex(fromRow, 0, temp);
to << createIndex(toRow, 0, temp);
}
}
changePersistentIndexList(from, to);
// Recursion
for (int i = node->size() - 1; i >= 0; --i) {
InnerDecklistNode *subNode = dynamic_cast<InnerDecklistNode *>(node->at(i));
if (subNode)
sortHelper(subNode, order);
}
// Sort children of node and save the information needed to
// update the list of persistent indexes.
QVector<QPair<int, int> > sortResult = node->sort(order);
QModelIndexList from, to;
for (int i = sortResult.size() - 1; i >= 0; --i) {
const int fromRow = sortResult[i].first;
const int toRow = sortResult[i].second;
AbstractDecklistNode *temp = node->at(toRow);
for (int j = columnCount(); j; --j) {
from << createIndex(fromRow, 0, temp);
to << createIndex(toRow, 0, temp);
}
}
changePersistentIndexList(from, to);
// Recursion
for (int i = node->size() - 1; i >= 0; --i) {
InnerDecklistNode *subNode = dynamic_cast<InnerDecklistNode *>(node->at(i));
if (subNode)
sortHelper(subNode, order);
}
}
void DeckListModel::sort(int /*column*/, Qt::SortOrder order)
void DeckListModel::sort(int column, Qt::SortOrder order)
{
emit layoutAboutToBeChanged();
sortHelper(root, order);
emit layoutChanged();
lastKnownColumn = column;
lastKnownOrder = order;
emit layoutAboutToBeChanged();
DeckSortMethod sortMethod;
switch(column) {
case 0:
sortMethod = ByNumber;
break;
case 1:
sortMethod = ByName;
break;
case 2:
sortMethod = ByPrice;
break;
default:
sortMethod = ByName;
}
root->setSortMethod(sortMethod);
sortHelper(root, order);
emit layoutChanged();
}
void DeckListModel::cleanList()
{
root->clearTree();
deckList->cleanList();
reset();
setDeckList(new DeckLoader);
}
void DeckListModel::setDeckList(DeckList *_deck)
void DeckListModel::setDeckList(DeckLoader *_deck)
{
delete deckList;
deckList = _deck;
connect(deckList, SIGNAL(deckLoaded()), this, SLOT(rebuildTree()));
connect(deckList, SIGNAL(deckHashChanged()), this, SIGNAL(deckHashChanged()));
rebuildTree();
delete deckList;
deckList = _deck;
connect(deckList, SIGNAL(deckLoaded()), this, SLOT(rebuildTree()));
connect(deckList, SIGNAL(deckHashChanged()), this, SIGNAL(deckHashChanged()));
rebuildTree();
}
void DeckListModel::printDeckListNode(QTextCursor *cursor, InnerDecklistNode *node)
{
const int totalColumns = settingsCache->getPriceTagFeature() ? 3 : 2;
const int totalColumns = settingsCache->getPriceTagFeature() ? 3 : 2;
if (node->height() == 1) {
QTextBlockFormat blockFormat;
QTextCharFormat charFormat;
charFormat.setFontPointSize(11);
charFormat.setFontWeight(QFont::Bold);
cursor->insertBlock(blockFormat, charFormat);
QString priceStr;
if (settingsCache->getPriceTagFeature())
priceStr = QString().sprintf(": $%.2f", node->recursivePrice(true));
if (node->height() == 1) {
QTextBlockFormat blockFormat;
QTextCharFormat charFormat;
charFormat.setFontPointSize(11);
charFormat.setFontWeight(QFont::Bold);
cursor->insertBlock(blockFormat, charFormat);
QString priceStr;
if (settingsCache->getPriceTagFeature())
priceStr = QString().sprintf(": $%.2f", node->recursivePrice(true));
cursor->insertText(QString("%1: %2").arg(node->getVisibleName()).arg(node->recursiveCount(true)).append(priceStr));
QTextTableFormat tableFormat;
tableFormat.setCellPadding(0);
tableFormat.setCellSpacing(0);
tableFormat.setBorder(0);
QTextTableFormat tableFormat;
tableFormat.setCellPadding(0);
tableFormat.setCellSpacing(0);
tableFormat.setBorder(0);
QTextTable *table = cursor->insertTable(node->size() + 1, totalColumns, tableFormat);
for (int i = 0; i < node->size(); i++) {
AbstractDecklistCardNode *card = dynamic_cast<AbstractDecklistCardNode *>(node->at(i));
for (int i = 0; i < node->size(); i++) {
AbstractDecklistCardNode *card = dynamic_cast<AbstractDecklistCardNode *>(node->at(i));
QTextCharFormat cellCharFormat;
cellCharFormat.setFontPointSize(9);
QTextCharFormat cellCharFormat;
cellCharFormat.setFontPointSize(9);
QTextTableCell cell = table->cellAt(i, 0);
cell.setFormat(cellCharFormat);
QTextCursor cellCursor = cell.firstCursorPosition();
cellCursor.insertText(QString("%1 ").arg(card->getNumber()));
QTextTableCell cell = table->cellAt(i, 0);
cell.setFormat(cellCharFormat);
QTextCursor cellCursor = cell.firstCursorPosition();
cellCursor.insertText(QString("%1 ").arg(card->getNumber()));
cell = table->cellAt(i, 1);
cell.setFormat(cellCharFormat);
cellCursor = cell.firstCursorPosition();
cellCursor.insertText(card->getName());
cell = table->cellAt(i, 1);
cell.setFormat(cellCharFormat);
cellCursor = cell.firstCursorPosition();
cellCursor.insertText(card->getName());
if (settingsCache->getPriceTagFeature()) {
cell = table->cellAt(i, 2);
cell.setFormat(cellCharFormat);
cellCursor = cell.firstCursorPosition();
cellCursor.insertText(QString().sprintf("$%.2f ", card->getTotalPrice()));
}
}
} else if (node->height() == 2) {
QTextBlockFormat blockFormat;
QTextCharFormat charFormat;
charFormat.setFontPointSize(14);
charFormat.setFontWeight(QFont::Bold);
if (settingsCache->getPriceTagFeature()) {
cell = table->cellAt(i, 2);
cell.setFormat(cellCharFormat);
cellCursor = cell.firstCursorPosition();
cellCursor.insertText(QString().sprintf("$%.2f ", card->getTotalPrice()));
}
}
} else if (node->height() == 2) {
QTextBlockFormat blockFormat;
QTextCharFormat charFormat;
charFormat.setFontPointSize(14);
charFormat.setFontWeight(QFont::Bold);
cursor->insertBlock(blockFormat, charFormat);
QString priceStr;
if (settingsCache->getPriceTagFeature())
priceStr = QString().sprintf(": $%.2f", node->recursivePrice(true));
cursor->insertBlock(blockFormat, charFormat);
QString priceStr;
if (settingsCache->getPriceTagFeature())
priceStr = QString().sprintf(": $%.2f", node->recursivePrice(true));
cursor->insertText(QString("%1: %2").arg(node->getVisibleName()).arg(node->recursiveCount(true)).append(priceStr));
QTextTableFormat tableFormat;
tableFormat.setCellPadding(10);
tableFormat.setCellSpacing(0);
tableFormat.setBorder(0);
QVector<QTextLength> constraints;
for (int i = 0; i < totalColumns; i++)
constraints << QTextLength(QTextLength::PercentageLength, 100.0 / totalColumns);
tableFormat.setColumnWidthConstraints(constraints);
QTextTableFormat tableFormat;
tableFormat.setCellPadding(10);
tableFormat.setCellSpacing(0);
tableFormat.setBorder(0);
QVector<QTextLength> constraints;
for (int i = 0; i < totalColumns; i++)
constraints << QTextLength(QTextLength::PercentageLength, 100.0 / totalColumns);
tableFormat.setColumnWidthConstraints(constraints);
QTextTable *table = cursor->insertTable(1, totalColumns, tableFormat);
for (int i = 0; i < node->size(); i++) {
QTextCursor cellCursor = table->cellAt(0, (i * totalColumns) / node->size()).lastCursorPosition();
printDeckListNode(&cellCursor, dynamic_cast<InnerDecklistNode *>(node->at(i)));
}
}
cursor->movePosition(QTextCursor::End);
QTextTable *table = cursor->insertTable(1, totalColumns, tableFormat);
for (int i = 0; i < node->size(); i++) {
QTextCursor cellCursor = table->cellAt(0, (i * totalColumns) / node->size()).lastCursorPosition();
printDeckListNode(&cellCursor, dynamic_cast<InnerDecklistNode *>(node->at(i)));
}
}
cursor->movePosition(QTextCursor::End);
}
void DeckListModel::printDeckList(QPrinter *printer)
{
QTextDocument doc;
QTextDocument doc;
QFont font("Serif");
font.setStyleHint(QFont::Serif);
doc.setDefaultFont(font);
QFont font("Serif");
font.setStyleHint(QFont::Serif);
doc.setDefaultFont(font);
QTextCursor cursor(&doc);
QTextCursor cursor(&doc);
QTextBlockFormat headerBlockFormat;
QTextCharFormat headerCharFormat;
headerCharFormat.setFontPointSize(16);
headerCharFormat.setFontWeight(QFont::Bold);
QTextBlockFormat headerBlockFormat;
QTextCharFormat headerCharFormat;
headerCharFormat.setFontPointSize(16);
headerCharFormat.setFontWeight(QFont::Bold);
cursor.insertBlock(headerBlockFormat, headerCharFormat);
cursor.insertText(deckList->getName());
cursor.insertBlock(headerBlockFormat, headerCharFormat);
cursor.insertText(deckList->getName());
headerCharFormat.setFontPointSize(12);
cursor.insertBlock(headerBlockFormat, headerCharFormat);
cursor.insertText(deckList->getComments());
cursor.insertBlock(headerBlockFormat, headerCharFormat);
headerCharFormat.setFontPointSize(12);
cursor.insertBlock(headerBlockFormat, headerCharFormat);
cursor.insertText(deckList->getComments());
cursor.insertBlock(headerBlockFormat, headerCharFormat);
for (int i = 0; i < root->size(); i++) {
cursor.insertHtml("<br><img src=:/resources/hr.jpg>");
//cursor.insertHtml("<hr>");
cursor.insertBlock(headerBlockFormat, headerCharFormat);
for (int i = 0; i < root->size(); i++) {
cursor.insertHtml("<br><img src=:/resources/hr.jpg>");
//cursor.insertHtml("<hr>");
cursor.insertBlock(headerBlockFormat, headerCharFormat);
printDeckListNode(&cursor, dynamic_cast<InnerDecklistNode *>(root->at(i)));
}
printDeckListNode(&cursor, dynamic_cast<InnerDecklistNode *>(root->at(i)));
}
doc.print(printer);
doc.print(printer);
}
void DeckListModel::pricesUpdated(InnerDecklistNode *node)
void DeckListModel::pricesUpdated()
{
if (!node)
node = root;
if (node->isEmpty())
return;
emit dataChanged(createIndex(0, 2, node->at(0)), createIndex(node->size() - 1, 2, node->last()));
emit layoutChanged();
}

View file

@ -5,6 +5,7 @@
#include <QList>
#include "decklist.h"
class DeckLoader;
class CardDatabase;
class QProgressDialog;
class QPrinter;
@ -12,60 +13,64 @@ class QTextCursor;
class DecklistModelCardNode : public AbstractDecklistCardNode {
private:
DecklistCardNode *dataNode;
DecklistCardNode *dataNode;
public:
DecklistModelCardNode(DecklistCardNode *_dataNode, InnerDecklistNode *_parent) : AbstractDecklistCardNode(_parent), dataNode(_dataNode) { }
int getNumber() const { return dataNode->getNumber(); }
void setNumber(int _number) { dataNode->setNumber(_number); }
DecklistModelCardNode(DecklistCardNode *_dataNode, InnerDecklistNode *_parent) : AbstractDecklistCardNode(_parent), dataNode(_dataNode) { }
int getNumber() const { return dataNode->getNumber(); }
void setNumber(int _number) { dataNode->setNumber(_number); }
float getPrice() const { return dataNode->getPrice(); }
void setPrice(float _price) { dataNode->setPrice(_price); }
QString getName() const { return dataNode->getName(); }
void setName(const QString &_name) { dataNode->setName(_name); }
DecklistCardNode *getDataNode() const { return dataNode; }
void setPrice(const float _price) { dataNode->setPrice(_price); }
QString getName() const { return dataNode->getName(); }
void setName(const QString &_name) { dataNode->setName(_name); }
DecklistCardNode *getDataNode() const { return dataNode; }
};
class DeckListModel : public QAbstractItemModel {
Q_OBJECT
Q_OBJECT
private slots:
void rebuildTree();
void rebuildTree();
public slots:
void printDeckList(QPrinter *printer);
void printDeckList(QPrinter *printer);
signals:
void deckHashChanged();
void deckHashChanged();
public:
DeckListModel(QObject *parent = 0);
~DeckListModel();
int rowCount(const QModelIndex &parent = QModelIndex()) const;
DeckListModel(QObject *parent = 0);
~DeckListModel();
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &/*parent*/ = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
QModelIndex parent(const QModelIndex &index) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
bool setData(const QModelIndex &index, const QVariant &value, int role);
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
QModelIndex addCard(const QString &cardName, const QString &zoneName);
void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
void cleanList();
DeckList *getDeckList() const { return deckList; }
void setDeckList(DeckList *_deck);
void pricesUpdated(InnerDecklistNode *node = 0);
QVariant data(const QModelIndex &index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
QModelIndex parent(const QModelIndex &index) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
bool setData(const QModelIndex &index, const QVariant &value, int role);
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
QModelIndex findCard(const QString &cardName, const QString &zoneName) const;
QModelIndex addCard(const QString &cardName, const QString &zoneName);
void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
void cleanList();
DeckLoader *getDeckList() const { return deckList; }
void setDeckList(DeckLoader *_deck);
void pricesUpdated();
private:
DeckList *deckList;
InnerDecklistNode *root;
InnerDecklistNode *createNodeIfNeeded(const QString &name, InnerDecklistNode *parent);
QModelIndex nodeToIndex(AbstractDecklistNode *node) const;
void emitRecursiveUpdates(const QModelIndex &index);
void sortHelper(InnerDecklistNode *node, Qt::SortOrder order);
DeckLoader *deckList;
InnerDecklistNode *root;
int lastKnownColumn;
Qt::SortOrder lastKnownOrder;
InnerDecklistNode *createNodeIfNeeded(const QString &name, InnerDecklistNode *parent);
QModelIndex nodeToIndex(AbstractDecklistNode *node) const;
DecklistModelCardNode *findCardNode(const QString &cardName, const QString &zoneName) const;
void emitRecursiveUpdates(const QModelIndex &index);
void sortHelper(InnerDecklistNode *node, Qt::SortOrder order);
void printDeckListNode(QTextCursor *cursor, InnerDecklistNode *node);
void printDeckListNode(QTextCursor *cursor, InnerDecklistNode *node);
template<typename T> T getNode(const QModelIndex &index) const
{
if (!index.isValid())
return dynamic_cast<T>(root);
return dynamic_cast<T>(static_cast<AbstractDecklistNode *>(index.internalPointer()));
}
template<typename T> T getNode(const QModelIndex &index) const
{
if (!index.isValid())
return dynamic_cast<T>(root);
return dynamic_cast<T>(static_cast<AbstractDecklistNode *>(index.internalPointer()));
}
};
#endif

View file

@ -0,0 +1,106 @@
#include "deckstats_interface.h"
#include "decklist.h"
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QRegExp>
#include <QMessageBox>
#include <QDesktopServices>
#if QT_VERSION >= 0x050000
#include <QUrlQuery>
#endif
DeckStatsInterface::DeckStatsInterface(
CardDatabase &_cardDatabase,
QObject *parent
) : QObject(parent), cardDatabase(_cardDatabase)
{
manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(queryFinished(QNetworkReply *)));
}
void DeckStatsInterface::queryFinished(QNetworkReply *reply)
{
if (reply->error() != QNetworkReply::NoError) {
QMessageBox::critical(0, tr("Error"), reply->errorString());
reply->deleteLater();
deleteLater();
return;
}
QString data(reply->readAll());
reply->deleteLater();
QRegExp rx("id=\"deckstats_deck_url\" value=\"([^\"]+)\"");
if (!rx.indexIn(data)) {
QMessageBox::critical(0, tr("Error"), tr("The reply from the server could not be parsed."));
deleteLater();
return;
}
QString deckUrl = rx.cap(1);
QDesktopServices::openUrl(deckUrl);
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)
{
QByteArray data;
getAnalyzeRequestData(deck, &data);
QNetworkRequest request(QUrl("http://deckstats.net/index.php"));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
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

@ -0,0 +1,35 @@
#ifndef DECKSTATS_INTERFACE_H
#define DECKSTATS_INTERFACE_H
#include "carddatabase.h"
#include "decklist.h"
#include <QObject>
class QByteArray;
class QNetworkAccessManager;
class QNetworkReply;
class DeckList;
class DeckStatsInterface : public QObject {
Q_OBJECT
private:
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:
void queryFinished(QNetworkReply *reply);
void getAnalyzeRequestData(DeckList *deck, QByteArray *data);
public:
DeckStatsInterface(CardDatabase &_cardDatabase, QObject *parent = 0);
void analyzeDeck(DeckList *deck);
};
#endif

View file

@ -8,454 +8,483 @@
#include "main.h"
DeckViewCardDragItem::DeckViewCardDragItem(DeckViewCard *_item, const QPointF &_hotSpot, AbstractCardDragItem *parentDrag)
: AbstractCardDragItem(_item, _hotSpot, parentDrag), currentZone(0)
: AbstractCardDragItem(_item, _hotSpot, parentDrag), currentZone(0)
{
}
void DeckViewCardDragItem::updatePosition(const QPointF &cursorScenePos)
{
QList<QGraphicsItem *> colliding = scene()->items(cursorScenePos);
QList<QGraphicsItem *> colliding = scene()->items(cursorScenePos);
DeckViewCardContainer *cursorZone = 0;
for (int i = colliding.size() - 1; i >= 0; i--)
if ((cursorZone = qgraphicsitem_cast<DeckViewCardContainer *>(colliding.at(i))))
break;
if (!cursorZone)
return;
currentZone = cursorZone;
QPointF newPos = cursorScenePos;
if (newPos != pos()) {
for (int i = 0; i < childDrags.size(); i++)
childDrags[i]->setPos(newPos + childDrags[i]->getHotSpot());
setPos(newPos);
}
DeckViewCardContainer *cursorZone = 0;
for (int i = colliding.size() - 1; i >= 0; i--)
if ((cursorZone = qgraphicsitem_cast<DeckViewCardContainer *>(colliding.at(i))))
break;
if (!cursorZone)
return;
currentZone = cursorZone;
QPointF newPos = cursorScenePos;
if (newPos != pos()) {
for (int i = 0; i < childDrags.size(); i++)
childDrags[i]->setPos(newPos + childDrags[i]->getHotSpot());
setPos(newPos);
}
}
void DeckViewCardDragItem::handleDrop(DeckViewCardContainer *target)
{
DeckViewCard *card = static_cast<DeckViewCard *>(item);
DeckViewCardContainer *start = static_cast<DeckViewCardContainer *>(item->parentItem());
start->removeCard(card);
target->addCard(card);
card->setParentItem(target);
DeckViewCard *card = static_cast<DeckViewCard *>(item);
DeckViewCardContainer *start = static_cast<DeckViewCardContainer *>(item->parentItem());
start->removeCard(card);
target->addCard(card);
card->setParentItem(target);
}
void DeckViewCardDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
setCursor(Qt::OpenHandCursor);
DeckViewScene *sc = static_cast<DeckViewScene *>(scene());
sc->removeItem(this);
setCursor(Qt::OpenHandCursor);
DeckViewScene *sc = static_cast<DeckViewScene *>(scene());
sc->removeItem(this);
if (currentZone) {
handleDrop(currentZone);
for (int i = 0; i < childDrags.size(); i++) {
DeckViewCardDragItem *c = static_cast<DeckViewCardDragItem *>(childDrags[i]);
c->handleDrop(currentZone);
sc->removeItem(c);
}
sc->updateContents();
}
event->accept();
if (currentZone) {
handleDrop(currentZone);
for (int i = 0; i < childDrags.size(); i++) {
DeckViewCardDragItem *c = static_cast<DeckViewCardDragItem *>(childDrags[i]);
c->handleDrop(currentZone);
sc->removeItem(c);
}
sc->updateContents();
}
event->accept();
}
DeckViewCard::DeckViewCard(const QString &_name, const QString &_originZone, QGraphicsItem *parent)
: AbstractCardItem(_name, 0, parent), originZone(_originZone), dragItem(0)
: AbstractCardItem(_name, 0, -1, parent), originZone(_originZone), dragItem(0)
{
setAcceptsHoverEvents(true);
#if QT_VERSION < 0x050000
setAcceptsHoverEvents(true);
#else
setAcceptHoverEvents(true);
#endif
}
DeckViewCard::~DeckViewCard()
{
delete dragItem;
delete dragItem;
}
void DeckViewCard::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
AbstractCardItem::paint(painter, option, widget);
painter->save();
QPen pen;//(Qt::DotLine);
pen.setWidth(3);
if (originZone == "main")
pen.setColor(QColor(0, 255, 0));
else
pen.setColor(QColor(255, 0, 0));
painter->setPen(pen);
painter->drawRect(QRectF(1.5, 1.5, CARD_WIDTH - 3, CARD_HEIGHT - 3));
painter->restore();
AbstractCardItem::paint(painter, option, widget);
painter->save();
QPen pen;//(Qt::DotLine);
pen.setWidth(3);
if (originZone == "main")
pen.setColor(QColor(0, 255, 0));
else
pen.setColor(QColor(255, 0, 0));
painter->setPen(pen);
painter->drawRect(QRectF(1.5, 1.5, CARD_WIDTH - 3, CARD_HEIGHT - 3));
painter->restore();
}
void DeckViewCard::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if ((event->screenPos() - event->buttonDownScreenPos(Qt::LeftButton)).manhattanLength() < 2 * QApplication::startDragDistance())
return;
if (static_cast<DeckViewScene *>(scene())->getLocked())
return;
delete dragItem;
dragItem = new DeckViewCardDragItem(this, event->pos());
scene()->addItem(dragItem);
dragItem->updatePosition(event->scenePos());
dragItem->grabMouse();
QList<QGraphicsItem *> sel = scene()->selectedItems();
int j = 0;
for (int i = 0; i < sel.size(); i++) {
DeckViewCard *c = static_cast<DeckViewCard *>(sel.at(i));
if (c == this)
continue;
++j;
QPointF childPos = QPointF(j * CARD_WIDTH / 2, 0);
DeckViewCardDragItem *drag = new DeckViewCardDragItem(c, childPos, dragItem);
drag->setPos(dragItem->pos() + childPos);
scene()->addItem(drag);
}
setCursor(Qt::OpenHandCursor);
if ((event->screenPos() - event->buttonDownScreenPos(Qt::LeftButton)).manhattanLength() < 2 * QApplication::startDragDistance())
return;
if (static_cast<DeckViewScene *>(scene())->getLocked())
return;
delete dragItem;
dragItem = new DeckViewCardDragItem(this, event->pos());
scene()->addItem(dragItem);
dragItem->updatePosition(event->scenePos());
dragItem->grabMouse();
QList<QGraphicsItem *> sel = scene()->selectedItems();
int j = 0;
for (int i = 0; i < sel.size(); i++) {
DeckViewCard *c = static_cast<DeckViewCard *>(sel.at(i));
if (c == this)
continue;
++j;
QPointF childPos = QPointF(j * CARD_WIDTH / 2, 0);
DeckViewCardDragItem *drag = new DeckViewCardDragItem(c, childPos, dragItem);
drag->setPos(dragItem->pos() + childPos);
scene()->addItem(drag);
}
setCursor(Qt::OpenHandCursor);
}
void DeckViewCard::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
event->accept();
processHoverEvent();
event->accept();
processHoverEvent();
}
DeckViewCardContainer::DeckViewCardContainer(const QString &_name)
: QGraphicsItem(), name(_name), width(0), height(0)
: QGraphicsItem(), name(_name), width(0), height(0)
{
QString bgPath = settingsCache->getTableBgPath();
if (!bgPath.isEmpty())
bgPixmap.load(bgPath);
QString bgPath = settingsCache->getTableBgPath();
if (!bgPath.isEmpty())
bgPixmap.load(bgPath);
setCacheMode(DeviceCoordinateCache);
setCacheMode(DeviceCoordinateCache);
}
QRectF DeckViewCardContainer::boundingRect() const
{
return QRectF(0, 0, width, height);
return QRectF(0, 0, width, height);
}
void DeckViewCardContainer::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/)
{
qreal totalTextWidth = getCardTypeTextWidth();
if (bgPixmap.isNull())
painter->fillRect(boundingRect(), QColor(0, 0, 100));
else
painter->fillRect(boundingRect(), QBrush(bgPixmap));
painter->setPen(QColor(255, 255, 255, 100));
painter->drawLine(QPointF(0, separatorY), QPointF(width, separatorY));
painter->setPen(QColor(Qt::white));
QFont f("Serif");
f.setStyleHint(QFont::Serif);
f.setPixelSize(24);
f.setWeight(QFont::Bold);
painter->setFont(f);
painter->drawText(10, 0, width - 20, separatorY, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, InnerDecklistNode::visibleNameFromName(name) + QString(": %1").arg(cards.size()));
f.setPixelSize(16);
painter->setFont(f);
QList<QString> cardTypeList = cardsByType.uniqueKeys();
qreal yUntilNow = separatorY + paddingY;
for (int i = 0; i < cardTypeList.size(); ++i) {
if (i != 0) {
painter->setPen(QColor(255, 255, 255, 100));
painter->drawLine(QPointF(0, yUntilNow - paddingY / 2), QPointF(width, yUntilNow - paddingY / 2));
}
qreal thisRowHeight = CARD_HEIGHT * currentRowsAndCols[i].first;
QRectF textRect(0, yUntilNow, totalTextWidth, thisRowHeight);
yUntilNow += thisRowHeight + paddingY;
painter->setPen(Qt::white);
painter->drawText(textRect, Qt::AlignHCenter | Qt::AlignVCenter | Qt::TextSingleLine, cardTypeList[i]);
}
qreal totalTextWidth = getCardTypeTextWidth();
if (bgPixmap.isNull())
painter->fillRect(boundingRect(), QColor(0, 0, 100));
else
painter->fillRect(boundingRect(), QBrush(bgPixmap));
painter->setPen(QColor(255, 255, 255, 100));
painter->drawLine(QPointF(0, separatorY), QPointF(width, separatorY));
painter->setPen(QColor(Qt::white));
QFont f("Serif");
f.setStyleHint(QFont::Serif);
f.setPixelSize(24);
f.setWeight(QFont::Bold);
painter->setFont(f);
painter->drawText(10, 0, width - 20, separatorY, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, InnerDecklistNode::visibleNameFromName(name) + QString(": %1").arg(cards.size()));
f.setPixelSize(16);
painter->setFont(f);
QList<QString> cardTypeList = cardsByType.uniqueKeys();
qreal yUntilNow = separatorY + paddingY;
for (int i = 0; i < cardTypeList.size(); ++i) {
if (i != 0) {
painter->setPen(QColor(255, 255, 255, 100));
painter->drawLine(QPointF(0, yUntilNow - paddingY / 2), QPointF(width, yUntilNow - paddingY / 2));
}
qreal thisRowHeight = CARD_HEIGHT * currentRowsAndCols[i].first;
QRectF textRect(0, yUntilNow, totalTextWidth, thisRowHeight);
yUntilNow += thisRowHeight + paddingY;
painter->setPen(Qt::white);
painter->drawText(textRect, Qt::AlignHCenter | Qt::AlignVCenter | Qt::TextSingleLine, cardTypeList[i]);
}
}
void DeckViewCardContainer::addCard(DeckViewCard *card)
{
cards.append(card);
cardsByType.insert(card->getInfo()->getMainCardType(), card);
cards.append(card);
cardsByType.insert(card->getInfo()->getMainCardType(), card);
}
void DeckViewCardContainer::removeCard(DeckViewCard *card)
{
cards.removeAt(cards.indexOf(card));
cardsByType.remove(card->getInfo()->getMainCardType(), card);
cards.removeAt(cards.indexOf(card));
cardsByType.remove(card->getInfo()->getMainCardType(), card);
}
QList<QPair<int, int> > DeckViewCardContainer::getRowsAndCols() const
{
QList<QPair<int, int> > result;
QList<QString> cardTypeList = cardsByType.uniqueKeys();
for (int i = 0; i < cardTypeList.size(); ++i)
result.append(QPair<int, int>(1, cardsByType.count(cardTypeList[i])));
return result;
QList<QPair<int, int> > result;
QList<QString> cardTypeList = cardsByType.uniqueKeys();
for (int i = 0; i < cardTypeList.size(); ++i)
result.append(QPair<int, int>(1, cardsByType.count(cardTypeList[i])));
return result;
}
int DeckViewCardContainer::getCardTypeTextWidth() const
{
QFont f("Serif");
f.setStyleHint(QFont::Serif);
f.setPixelSize(16);
f.setWeight(QFont::Bold);
QFontMetrics fm(f);
int maxCardTypeWidth = 0;
QMapIterator<QString, DeckViewCard *> i(cardsByType);
while (i.hasNext()) {
int cardTypeWidth = fm.size(Qt::TextSingleLine, i.next().key()).width();
if (cardTypeWidth > maxCardTypeWidth)
maxCardTypeWidth = cardTypeWidth;
}
return maxCardTypeWidth + 15;
QFont f("Serif");
f.setStyleHint(QFont::Serif);
f.setPixelSize(16);
f.setWeight(QFont::Bold);
QFontMetrics fm(f);
int maxCardTypeWidth = 0;
QMapIterator<QString, DeckViewCard *> i(cardsByType);
while (i.hasNext()) {
int cardTypeWidth = fm.size(Qt::TextSingleLine, i.next().key()).width();
if (cardTypeWidth > maxCardTypeWidth)
maxCardTypeWidth = cardTypeWidth;
}
return maxCardTypeWidth + 15;
}
QSizeF DeckViewCardContainer::calculateBoundingRect(const QList<QPair<int, int> > &rowsAndCols) const
{
qreal totalHeight = 0;
qreal totalWidth = 0;
// Calculate space needed for cards
for (int i = 0; i < rowsAndCols.size(); ++i) {
totalHeight += CARD_HEIGHT * rowsAndCols[i].first + paddingY;
if (CARD_WIDTH * rowsAndCols[i].second > totalWidth)
totalWidth = CARD_WIDTH * rowsAndCols[i].second;
}
return QSizeF(getCardTypeTextWidth() + totalWidth, totalHeight + separatorY + paddingY);
qreal totalHeight = 0;
qreal totalWidth = 0;
// Calculate space needed for cards
for (int i = 0; i < rowsAndCols.size(); ++i) {
totalHeight += CARD_HEIGHT * rowsAndCols[i].first + paddingY;
if (CARD_WIDTH * rowsAndCols[i].second > totalWidth)
totalWidth = CARD_WIDTH * rowsAndCols[i].second;
}
return QSizeF(getCardTypeTextWidth() + totalWidth, totalHeight + separatorY + paddingY);
}
void DeckViewCardContainer::rearrangeItems(const QList<QPair<int, int> > &rowsAndCols)
{
currentRowsAndCols = rowsAndCols;
int totalCols = 0, totalRows = 0;
qreal yUntilNow = separatorY + paddingY;
qreal x = (qreal) getCardTypeTextWidth();
for (int i = 0; i < rowsAndCols.size(); ++i) {
const int tempRows = rowsAndCols[i].first;
const int tempCols = rowsAndCols[i].second;
totalRows += tempRows;
if (tempCols > totalCols)
totalCols = tempCols;
QList<QString> cardTypeList = cardsByType.uniqueKeys();
QList<DeckViewCard *> row = cardsByType.values(cardTypeList[i]);
for (int j = 0; j < row.size(); ++j) {
DeckViewCard *card = row[j];
card->setPos(x + (j % tempCols) * CARD_WIDTH, yUntilNow + (j / tempCols) * CARD_HEIGHT);
}
yUntilNow += tempRows * CARD_HEIGHT + paddingY;
}
prepareGeometryChange();
QSizeF bRect = calculateBoundingRect(rowsAndCols);
width = bRect.width();
height = bRect.height();
currentRowsAndCols = rowsAndCols;
int totalCols = 0, totalRows = 0;
qreal yUntilNow = separatorY + paddingY;
qreal x = (qreal) getCardTypeTextWidth();
for (int i = 0; i < rowsAndCols.size(); ++i) {
const int tempRows = rowsAndCols[i].first;
const int tempCols = rowsAndCols[i].second;
totalRows += tempRows;
if (tempCols > totalCols)
totalCols = tempCols;
QList<QString> cardTypeList = cardsByType.uniqueKeys();
QList<DeckViewCard *> row = cardsByType.values(cardTypeList[i]);
for (int j = 0; j < row.size(); ++j) {
DeckViewCard *card = row[j];
card->setPos(x + (j % tempCols) * CARD_WIDTH, yUntilNow + (j / tempCols) * CARD_HEIGHT);
}
yUntilNow += tempRows * CARD_HEIGHT + paddingY;
}
prepareGeometryChange();
QSizeF bRect = calculateBoundingRect(rowsAndCols);
width = bRect.width();
height = bRect.height();
}
void DeckViewCardContainer::setWidth(qreal _width)
{
prepareGeometryChange();
width = _width;
update();
prepareGeometryChange();
width = _width;
update();
}
DeckViewScene::DeckViewScene(QObject *parent)
: QGraphicsScene(parent), locked(false), deck(0), optimalAspectRatio(1.0)
: QGraphicsScene(parent), locked(true), deck(0), optimalAspectRatio(1.0)
{
}
DeckViewScene::~DeckViewScene()
{
clearContents();
delete deck;
}
void DeckViewScene::setDeck(DeckList *_deck)
void DeckViewScene::clearContents()
{
if (deck)
delete deck;
QMapIterator<QString, DeckViewCardContainer *> i(cardContainers);
while (i.hasNext())
delete i.next().value();
cardContainers.clear();
deck = _deck;
rebuildTree();
applySideboardPlan(deck->getCurrentSideboardPlan());
rearrangeItems();
QMapIterator<QString, DeckViewCardContainer *> i(cardContainers);
while (i.hasNext())
delete i.next().value();
cardContainers.clear();
}
void DeckViewScene::setDeck(const DeckList &_deck)
{
if (deck)
delete deck;
deck = new DeckList(_deck);
rebuildTree();
applySideboardPlan(deck->getCurrentSideboardPlan());
rearrangeItems();
}
void DeckViewScene::rebuildTree()
{
InnerDecklistNode *listRoot = deck->getRoot();
for (int i = 0; i < listRoot->size(); i++) {
InnerDecklistNode *currentZone = dynamic_cast<InnerDecklistNode *>(listRoot->at(i));
DeckViewCardContainer *container = cardContainers.value(currentZone->getName(), 0);
if (!container) {
container = new DeckViewCardContainer(currentZone->getName());
cardContainers.insert(currentZone->getName(), container);
addItem(container);
}
for (int j = 0; j < currentZone->size(); j++) {
DecklistCardNode *currentCard = dynamic_cast<DecklistCardNode *>(currentZone->at(j));
if (!currentCard)
continue;
clearContents();
if (!deck)
return;
InnerDecklistNode *listRoot = deck->getRoot();
for (int i = 0; i < listRoot->size(); i++) {
InnerDecklistNode *currentZone = dynamic_cast<InnerDecklistNode *>(listRoot->at(i));
DeckViewCardContainer *container = cardContainers.value(currentZone->getName(), 0);
if (!container) {
container = new DeckViewCardContainer(currentZone->getName());
cardContainers.insert(currentZone->getName(), container);
addItem(container);
}
for (int j = 0; j < currentZone->size(); j++) {
DecklistCardNode *currentCard = dynamic_cast<DecklistCardNode *>(currentZone->at(j));
if (!currentCard)
continue;
for (int k = 0; k < currentCard->getNumber(); ++k) {
DeckViewCard *newCard = new DeckViewCard(currentCard->getName(), currentZone->getName(), container);
container->addCard(newCard);
emit newCardAdded(newCard);
}
}
}
for (int k = 0; k < currentCard->getNumber(); ++k) {
DeckViewCard *newCard = new DeckViewCard(currentCard->getName(), currentZone->getName(), container);
container->addCard(newCard);
emit newCardAdded(newCard);
}
}
}
}
void DeckViewScene::applySideboardPlan(const QList<MoveCardToZone *> &plan)
void DeckViewScene::applySideboardPlan(const QList<MoveCard_ToZone> &plan)
{
for (int i = 0; i < plan.size(); ++i) {
MoveCardToZone *m = plan[i];
DeckViewCardContainer *start = cardContainers.value(m->getStartZone());
DeckViewCardContainer *target = cardContainers.value(m->getTargetZone());
if (!start || !target)
continue;
DeckViewCard *card = 0;
const QList<DeckViewCard *> &cardList = start->getCards();
for (int j = 0; j < cardList.size(); ++j)
if (cardList[j]->getName() == m->getCardName()) {
card = cardList[j];
break;
}
if (!card)
continue;
start->removeCard(card);
target->addCard(card);
card->setParentItem(target);
}
for (int i = 0; i < plan.size(); ++i) {
const MoveCard_ToZone &m = plan[i];
DeckViewCardContainer *start = cardContainers.value(QString::fromStdString(m.start_zone()));
DeckViewCardContainer *target = cardContainers.value(QString::fromStdString(m.target_zone()));
if (!start || !target)
continue;
DeckViewCard *card = 0;
const QList<DeckViewCard *> &cardList = start->getCards();
for (int j = 0; j < cardList.size(); ++j)
if (cardList[j]->getName() == QString::fromStdString(m.card_name())) {
card = cardList[j];
break;
}
if (!card)
continue;
start->removeCard(card);
target->addCard(card);
card->setParentItem(target);
}
}
void DeckViewScene::rearrangeItems()
{
const int spacing = CARD_HEIGHT / 3;
QList<DeckViewCardContainer *> contList = cardContainers.values();
// Initialize space requirements
QList<QList<QPair<int, int> > > rowsAndColsList;
QList<QList<int> > cardCountList;
for (int i = 0; i < contList.size(); ++i) {
QList<QPair<int, int> > rowsAndCols = contList[i]->getRowsAndCols();
rowsAndColsList.append(rowsAndCols);
cardCountList.append(QList<int>());
for (int j = 0; j < rowsAndCols.size(); ++j)
cardCountList[i].append(rowsAndCols[j].second);
}
qreal totalHeight, totalWidth;
for (;;) {
// Calculate total size before this iteration
totalHeight = -spacing;
totalWidth = 0;
for (int i = 0; i < contList.size(); ++i) {
QSizeF contSize = contList[i]->calculateBoundingRect(rowsAndColsList[i]);
totalHeight += contSize.height() + spacing;
if (contSize.width() > totalWidth)
totalWidth = contSize.width();
}
// We're done when the aspect ratio shifts from too high to too low.
if (totalWidth / totalHeight <= optimalAspectRatio)
break;
// Find category with highest column count
int maxIndex1 = -1, maxIndex2 = -1, maxCols = 0;
for (int i = 0; i < rowsAndColsList.size(); ++i)
for (int j = 0; j < rowsAndColsList[i].size(); ++j)
if (rowsAndColsList[i][j].second > maxCols) {
maxIndex1 = i;
maxIndex2 = j;
maxCols = rowsAndColsList[i][j].second;
}
// Add row to category
const int maxRows = rowsAndColsList[maxIndex1][maxIndex2].first;
const int maxCardCount = cardCountList[maxIndex1][maxIndex2];
rowsAndColsList[maxIndex1][maxIndex2] = QPair<int, int>(maxRows + 1, (int) ceil((qreal) maxCardCount / (qreal) (maxRows + 1)));
}
totalHeight = -spacing;
for (int i = 0; i < contList.size(); ++i) {
DeckViewCardContainer *c = contList[i];
c->rearrangeItems(rowsAndColsList[i]);
c->setPos(0, totalHeight + spacing);
totalHeight += c->boundingRect().height() + spacing;
}
totalWidth = totalHeight * optimalAspectRatio;
for (int i = 0; i < contList.size(); ++i)
contList[i]->setWidth(totalWidth);
setSceneRect(QRectF(0, 0, totalWidth, totalHeight));
const int spacing = CARD_HEIGHT / 3;
QList<DeckViewCardContainer *> contList = cardContainers.values();
// Initialize space requirements
QList<QList<QPair<int, int> > > rowsAndColsList;
QList<QList<int> > cardCountList;
for (int i = 0; i < contList.size(); ++i) {
QList<QPair<int, int> > rowsAndCols = contList[i]->getRowsAndCols();
rowsAndColsList.append(rowsAndCols);
cardCountList.append(QList<int>());
for (int j = 0; j < rowsAndCols.size(); ++j)
cardCountList[i].append(rowsAndCols[j].second);
}
qreal totalHeight, totalWidth;
for (;;) {
// Calculate total size before this iteration
totalHeight = -spacing;
totalWidth = 0;
for (int i = 0; i < contList.size(); ++i) {
QSizeF contSize = contList[i]->calculateBoundingRect(rowsAndColsList[i]);
totalHeight += contSize.height() + spacing;
if (contSize.width() > totalWidth)
totalWidth = contSize.width();
}
// We're done when the aspect ratio shifts from too high to too low.
if (totalWidth / totalHeight <= optimalAspectRatio)
break;
// Find category with highest column count
int maxIndex1 = -1, maxIndex2 = -1, maxCols = 0;
for (int i = 0; i < rowsAndColsList.size(); ++i)
for (int j = 0; j < rowsAndColsList[i].size(); ++j)
if (rowsAndColsList[i][j].second > maxCols) {
maxIndex1 = i;
maxIndex2 = j;
maxCols = rowsAndColsList[i][j].second;
}
// Add row to category
const int maxRows = rowsAndColsList[maxIndex1][maxIndex2].first;
const int maxCardCount = cardCountList[maxIndex1][maxIndex2];
rowsAndColsList[maxIndex1][maxIndex2] = QPair<int, int>(maxRows + 1, (int) ceil((qreal) maxCardCount / (qreal) (maxRows + 1)));
}
totalHeight = -spacing;
for (int i = 0; i < contList.size(); ++i) {
DeckViewCardContainer *c = contList[i];
c->rearrangeItems(rowsAndColsList[i]);
c->setPos(0, totalHeight + spacing);
totalHeight += c->boundingRect().height() + spacing;
}
totalWidth = totalHeight * optimalAspectRatio;
for (int i = 0; i < contList.size(); ++i)
contList[i]->setWidth(totalWidth);
setSceneRect(QRectF(0, 0, totalWidth, totalHeight));
}
void DeckViewScene::updateContents()
{
rearrangeItems();
emit sideboardPlanChanged();
rearrangeItems();
emit sideboardPlanChanged();
}
QList<MoveCardToZone *> DeckViewScene::getSideboardPlan() const
QList<MoveCard_ToZone> DeckViewScene::getSideboardPlan() const
{
QList<MoveCardToZone *> result;
QMapIterator<QString, DeckViewCardContainer *> containerIterator(cardContainers);
while (containerIterator.hasNext()) {
DeckViewCardContainer *cont = containerIterator.next().value();
const QList<DeckViewCard *> cardList = cont->getCards();
for (int i = 0; i < cardList.size(); ++i)
if (cardList[i]->getOriginZone() != cont->getName())
result.append(new MoveCardToZone(cardList[i]->getName(), cardList[i]->getOriginZone(), cont->getName()));
}
return result;
QList<MoveCard_ToZone> result;
QMapIterator<QString, DeckViewCardContainer *> containerIterator(cardContainers);
while (containerIterator.hasNext()) {
DeckViewCardContainer *cont = containerIterator.next().value();
const QList<DeckViewCard *> cardList = cont->getCards();
for (int i = 0; i < cardList.size(); ++i)
if (cardList[i]->getOriginZone() != cont->getName()) {
MoveCard_ToZone m;
m.set_card_name(cardList[i]->getName().toStdString());
m.set_start_zone(cardList[i]->getOriginZone().toStdString());
m.set_target_zone(cont->getName().toStdString());
result.append(m);
}
}
return result;
}
void DeckViewScene::resetSideboardPlan()
{
rebuildTree();
rearrangeItems();
}
DeckView::DeckView(QWidget *parent)
: QGraphicsView(parent)
: QGraphicsView(parent)
{
deckViewScene = new DeckViewScene(this);
setBackgroundBrush(QBrush(QColor(0, 0, 0)));
setDragMode(RubberBandDrag);
setRenderHints(QPainter::TextAntialiasing | QPainter::Antialiasing/* | QPainter::SmoothPixmapTransform*/);
setScene(deckViewScene);
deckViewScene = new DeckViewScene(this);
setBackgroundBrush(QBrush(QColor(0, 0, 0)));
setDragMode(RubberBandDrag);
setRenderHints(QPainter::TextAntialiasing | QPainter::Antialiasing/* | QPainter::SmoothPixmapTransform*/);
setScene(deckViewScene);
connect(deckViewScene, SIGNAL(sceneRectChanged(const QRectF &)), this, SLOT(updateSceneRect(const QRectF &)));
connect(deckViewScene, SIGNAL(newCardAdded(AbstractCardItem *)), this, SIGNAL(newCardAdded(AbstractCardItem *)));
connect(deckViewScene, SIGNAL(sideboardPlanChanged()), this, SIGNAL(sideboardPlanChanged()));
connect(deckViewScene, SIGNAL(sceneRectChanged(const QRectF &)), this, SLOT(updateSceneRect(const QRectF &)));
connect(deckViewScene, SIGNAL(newCardAdded(AbstractCardItem *)), this, SIGNAL(newCardAdded(AbstractCardItem *)));
connect(deckViewScene, SIGNAL(sideboardPlanChanged()), this, SIGNAL(sideboardPlanChanged()));
}
void DeckView::resizeEvent(QResizeEvent *event)
{
QGraphicsView::resizeEvent(event);
deckViewScene->setOptimalAspectRatio((qreal) width() / (qreal) height());
deckViewScene->rearrangeItems();
QGraphicsView::resizeEvent(event);
deckViewScene->setOptimalAspectRatio((qreal) width() / (qreal) height());
deckViewScene->rearrangeItems();
}
void DeckView::updateSceneRect(const QRectF &rect)
{
fitInView(rect, Qt::KeepAspectRatio);
fitInView(rect, Qt::KeepAspectRatio);
}
void DeckView::setDeck(DeckList *_deck)
void DeckView::setDeck(const DeckList &_deck)
{
deckViewScene->setDeck(_deck);
deckViewScene->setDeck(_deck);
}
void DeckView::resetSideboardPlan()
{
deckViewScene->resetSideboardPlan();
}

View file

@ -6,9 +6,10 @@
#include <QMap>
#include <QMultiMap>
#include <QPixmap>
#include "abstractcarditem.h"
#include "abstractcarddragitem.h"
#include "pb/move_card_to_zone.pb.h"
class DeckList;
class InnerDecklistNode;
class CardInfo;
@ -18,98 +19,101 @@ class MoveCardToZone;
class DeckViewCard : public AbstractCardItem {
private:
QString originZone;
DeckViewCardDragItem *dragItem;
QString originZone;
DeckViewCardDragItem *dragItem;
public:
DeckViewCard(const QString &_name = QString(), const QString &_originZone = QString(), QGraphicsItem *parent = 0);
~DeckViewCard();
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
const QString &getOriginZone() const { return originZone; }
DeckViewCard(const QString &_name = QString(), const QString &_originZone = QString(), QGraphicsItem *parent = 0);
~DeckViewCard();
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
const QString &getOriginZone() const { return originZone; }
protected:
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
};
class DeckViewCardDragItem : public AbstractCardDragItem {
private:
DeckViewCardContainer *currentZone;
void handleDrop(DeckViewCardContainer *target);
DeckViewCardContainer *currentZone;
void handleDrop(DeckViewCardContainer *target);
public:
DeckViewCardDragItem(DeckViewCard *_item, const QPointF &_hotSpot, AbstractCardDragItem *parentDrag = 0);
void updatePosition(const QPointF &cursorScenePos);
DeckViewCardDragItem(DeckViewCard *_item, const QPointF &_hotSpot, AbstractCardDragItem *parentDrag = 0);
void updatePosition(const QPointF &cursorScenePos);
protected:
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
};
class DeckViewCardContainer : public QGraphicsItem {
private:
static const int separatorY = 20;
static const int paddingY = 10;
QString name;
QList<DeckViewCard *> cards;
QMultiMap<QString, DeckViewCard *> cardsByType;
QList<QPair<int, int> > currentRowsAndCols;
qreal width, height;
QPixmap bgPixmap;
int getCardTypeTextWidth() const;
static const int separatorY = 20;
static const int paddingY = 10;
QString name;
QList<DeckViewCard *> cards;
QMultiMap<QString, DeckViewCard *> cardsByType;
QList<QPair<int, int> > currentRowsAndCols;
qreal width, height;
QPixmap bgPixmap;
int getCardTypeTextWidth() const;
public:
enum { Type = typeDeckViewCardContainer };
int type() const { return Type; }
DeckViewCardContainer(const QString &_name);
QRectF boundingRect() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
void addCard(DeckViewCard *card);
void removeCard(DeckViewCard *card);
const QList<DeckViewCard *> &getCards() const { return cards; }
const QString &getName() const { return name; }
void setWidth(qreal _width);
enum { Type = typeDeckViewCardContainer };
int type() const { return Type; }
DeckViewCardContainer(const QString &_name);
QRectF boundingRect() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
void addCard(DeckViewCard *card);
void removeCard(DeckViewCard *card);
const QList<DeckViewCard *> &getCards() const { return cards; }
const QString &getName() const { return name; }
void setWidth(qreal _width);
QList<QPair<int, int> > getRowsAndCols() const;
QSizeF calculateBoundingRect(const QList<QPair<int, int> > &rowsAndCols) const;
void rearrangeItems(const QList<QPair<int, int> > &rowsAndCols);
QList<QPair<int, int> > getRowsAndCols() const;
QSizeF calculateBoundingRect(const QList<QPair<int, int> > &rowsAndCols) const;
void rearrangeItems(const QList<QPair<int, int> > &rowsAndCols);
};
class DeckViewScene : public QGraphicsScene {
Q_OBJECT
Q_OBJECT
signals:
void newCardAdded(AbstractCardItem *card);
void sideboardPlanChanged();
void newCardAdded(AbstractCardItem *card);
void sideboardPlanChanged();
private:
bool locked;
DeckList *deck;
QMap<QString, DeckViewCardContainer *> cardContainers;
qreal optimalAspectRatio;
void rebuildTree();
void applySideboardPlan(const QList<MoveCardToZone *> &plan);
bool locked;
DeckList *deck;
QMap<QString, DeckViewCardContainer *> cardContainers;
qreal optimalAspectRatio;
void clearContents();
void rebuildTree();
void applySideboardPlan(const QList<MoveCard_ToZone> &plan);
public:
DeckViewScene(QObject *parent = 0);
~DeckViewScene();
void setLocked(bool _locked) { locked = _locked; }
bool getLocked() const { return locked; }
void setDeck(DeckList *_deck);
void setOptimalAspectRatio(qreal _optimalAspectRatio) { optimalAspectRatio = _optimalAspectRatio; }
void rearrangeItems();
void updateContents();
QList<MoveCardToZone *> getSideboardPlan() const;
DeckViewScene(QObject *parent = 0);
~DeckViewScene();
void setLocked(bool _locked) { locked = _locked; }
bool getLocked() const { return locked; }
void setDeck(const DeckList &_deck);
void setOptimalAspectRatio(qreal _optimalAspectRatio) { optimalAspectRatio = _optimalAspectRatio; }
void rearrangeItems();
void updateContents();
QList<MoveCard_ToZone> getSideboardPlan() const;
void resetSideboardPlan();
};
class DeckView : public QGraphicsView {
Q_OBJECT
Q_OBJECT
private:
DeckViewScene *deckViewScene;
DeckViewScene *deckViewScene;
protected:
void resizeEvent(QResizeEvent *event);
void resizeEvent(QResizeEvent *event);
public slots:
void updateSceneRect(const QRectF &rect);
void updateSceneRect(const QRectF &rect);
signals:
void newCardAdded(AbstractCardItem *card);
void sideboardPlanChanged();
void newCardAdded(AbstractCardItem *card);
void sideboardPlanChanged();
public:
DeckView(QWidget *parent = 0);
void setDeck(DeckList *_deck);
void setLocked(bool _locked) { deckViewScene->setLocked(_locked); }
QList<MoveCardToZone *> getSideboardPlan() const { return deckViewScene->getSideboardPlan(); }
DeckView(QWidget *parent = 0);
void setDeck(const DeckList &_deck);
void setLocked(bool _locked) { deckViewScene->setLocked(_locked); }
QList<MoveCard_ToZone> getSideboardPlan() const { return deckViewScene->getSideboardPlan(); }
void resetSideboardPlan();
};
#endif

View file

@ -10,86 +10,86 @@
#include "main.h"
DlgCardSearch::DlgCardSearch(QWidget *parent)
: QDialog(parent)
: QDialog(parent)
{
QLabel *cardNameLabel = new QLabel(tr("Card name:"));
cardNameEdit = new QLineEdit;
QLabel *cardTextLabel = new QLabel(tr("Card text:"));
cardTextEdit = new QLineEdit;
QLabel *cardTypesLabel = new QLabel(tr("Card type (OR):"));
const QStringList &cardTypes = db->getAllMainCardTypes();
QVBoxLayout *cardTypesLayout = new QVBoxLayout;
for (int i = 0; i < cardTypes.size(); ++i) {
QCheckBox *cardTypeCheckBox = new QCheckBox(cardTypes[i]);
cardTypeCheckBox->setChecked(true);
cardTypeCheckBoxes.append(cardTypeCheckBox);
cardTypesLayout->addWidget(cardTypeCheckBox);
}
QLabel *cardColorsLabel = new QLabel(tr("Color (OR):"));
const QStringList &cardColors = db->getAllColors();
QHBoxLayout *cardColorsLayout = new QHBoxLayout;
for (int i = 0; i < cardColors.size(); ++i) {
QCheckBox *cardColorCheckBox = new QCheckBox(cardColors[i]);
cardColorCheckBox->setChecked(true);
cardColorCheckBoxes.append(cardColorCheckBox);
cardColorsLayout->addWidget(cardColorCheckBox);
}
QPushButton *okButton = new QPushButton(tr("O&K"));
okButton->setDefault(true);
okButton->setAutoDefault(true);
QPushButton *cancelButton = new QPushButton(tr("&Cancel"));
connect(okButton, SIGNAL(clicked()), this, SLOT(accept()));
connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
QHBoxLayout *buttonHBox = new QHBoxLayout;
buttonHBox->addStretch();
buttonHBox->addWidget(okButton);
buttonHBox->addWidget(cancelButton);
QGridLayout *optionsLayout = new QGridLayout;
optionsLayout->addWidget(cardNameLabel, 0, 0);
optionsLayout->addWidget(cardNameEdit, 0, 1);
optionsLayout->addWidget(cardTextLabel, 1, 0);
optionsLayout->addWidget(cardTextEdit, 1, 1);
optionsLayout->addWidget(cardTypesLabel, 2, 0);
optionsLayout->addLayout(cardTypesLayout, 2, 1);
optionsLayout->addWidget(cardColorsLabel, 3, 0);
optionsLayout->addLayout(cardColorsLayout, 3, 1);
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addLayout(optionsLayout);
mainLayout->addLayout(buttonHBox);
setLayout(mainLayout);
setWindowTitle(tr("Card search"));
QLabel *cardNameLabel = new QLabel(tr("Card name:"));
cardNameEdit = new QLineEdit;
QLabel *cardTextLabel = new QLabel(tr("Card text:"));
cardTextEdit = new QLineEdit;
QLabel *cardTypesLabel = new QLabel(tr("Card type (OR):"));
const QStringList &cardTypes = db->getAllMainCardTypes();
QVBoxLayout *cardTypesLayout = new QVBoxLayout;
for (int i = 0; i < cardTypes.size(); ++i) {
QCheckBox *cardTypeCheckBox = new QCheckBox(cardTypes[i]);
cardTypeCheckBox->setChecked(true);
cardTypeCheckBoxes.append(cardTypeCheckBox);
cardTypesLayout->addWidget(cardTypeCheckBox);
}
QLabel *cardColorsLabel = new QLabel(tr("Color (OR):"));
const QStringList &cardColors = db->getAllColors();
QHBoxLayout *cardColorsLayout = new QHBoxLayout;
for (int i = 0; i < cardColors.size(); ++i) {
QCheckBox *cardColorCheckBox = new QCheckBox(cardColors[i]);
cardColorCheckBox->setChecked(true);
cardColorCheckBoxes.append(cardColorCheckBox);
cardColorsLayout->addWidget(cardColorCheckBox);
}
QPushButton *okButton = new QPushButton(tr("O&K"));
okButton->setDefault(true);
okButton->setAutoDefault(true);
QPushButton *cancelButton = new QPushButton(tr("&Cancel"));
connect(okButton, SIGNAL(clicked()), this, SLOT(accept()));
connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
QHBoxLayout *buttonHBox = new QHBoxLayout;
buttonHBox->addStretch();
buttonHBox->addWidget(okButton);
buttonHBox->addWidget(cancelButton);
QGridLayout *optionsLayout = new QGridLayout;
optionsLayout->addWidget(cardNameLabel, 0, 0);
optionsLayout->addWidget(cardNameEdit, 0, 1);
optionsLayout->addWidget(cardTextLabel, 1, 0);
optionsLayout->addWidget(cardTextEdit, 1, 1);
optionsLayout->addWidget(cardTypesLabel, 2, 0);
optionsLayout->addLayout(cardTypesLayout, 2, 1);
optionsLayout->addWidget(cardColorsLabel, 3, 0);
optionsLayout->addLayout(cardColorsLayout, 3, 1);
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addLayout(optionsLayout);
mainLayout->addLayout(buttonHBox);
setLayout(mainLayout);
setWindowTitle(tr("Card search"));
}
QString DlgCardSearch::getCardName() const
{
return cardNameEdit->text();
return cardNameEdit->text();
}
QString DlgCardSearch::getCardText() const
{
return cardTextEdit->text();
return cardTextEdit->text();
}
QSet<QString> DlgCardSearch::getCardTypes() const
{
QStringList result;
for (int i = 0; i < cardTypeCheckBoxes.size(); ++i)
if (cardTypeCheckBoxes[i]->isChecked())
result.append(cardTypeCheckBoxes[i]->text());
return QSet<QString>::fromList(result);
QStringList result;
for (int i = 0; i < cardTypeCheckBoxes.size(); ++i)
if (cardTypeCheckBoxes[i]->isChecked())
result.append(cardTypeCheckBoxes[i]->text());
return QSet<QString>::fromList(result);
}
QSet<QString> DlgCardSearch::getCardColors() const
{
QStringList result;
for (int i = 0; i < cardColorCheckBoxes.size(); ++i)
if (cardColorCheckBoxes[i]->isChecked())
result.append(cardColorCheckBoxes[i]->text());
return QSet<QString>::fromList(result);
QStringList result;
for (int i = 0; i < cardColorCheckBoxes.size(); ++i)
if (cardColorCheckBoxes[i]->isChecked())
result.append(cardColorCheckBoxes[i]->text());
return QSet<QString>::fromList(result);
}

View file

@ -9,16 +9,16 @@ class QLineEdit;
class QCheckBox;
class DlgCardSearch : public QDialog {
Q_OBJECT
Q_OBJECT
private:
QLineEdit *cardNameEdit, *cardTextEdit;
QList<QCheckBox *> cardTypeCheckBoxes, cardColorCheckBoxes;
QLineEdit *cardNameEdit, *cardTextEdit;
QList<QCheckBox *> cardTypeCheckBoxes, cardColorCheckBoxes;
public:
DlgCardSearch(QWidget *parent = 0);
QString getCardName() const;
QString getCardText() const;
QSet<QString> getCardTypes() const;
QSet<QString> getCardColors() const;
DlgCardSearch(QWidget *parent = 0);
QString getCardName() const;
QString getCardText() const;
QSet<QString> getCardTypes() const;
QSet<QString> getCardColors() const;
};
#endif
#endif

View file

@ -1,74 +1,72 @@
#include <QSettings>
#include <QLabel>
#include <QPushButton>
#include <QCheckBox>
#include <QGridLayout>
#include <QHBoxLayout>
#include <QDialogButtonBox>
#include "dlg_connect.h"
DlgConnect::DlgConnect(QWidget *parent)
: QDialog(parent)
: QDialog(parent)
{
QSettings settings;
settings.beginGroup("server");
QSettings settings;
settings.beginGroup("server");
hostLabel = new QLabel(tr("&Host:"));
hostEdit = new QLineEdit(settings.value("hostname", "play.cockatrice.de").toString());
hostLabel->setBuddy(hostEdit);
hostLabel = new QLabel(tr("&Host:"));
hostEdit = new QLineEdit(settings.value("hostname", "cockatrice.woogerworks.com").toString());
hostLabel->setBuddy(hostEdit);
portLabel = new QLabel(tr("&Port:"));
portEdit = new QLineEdit(settings.value("port", "4747").toString());
portLabel->setBuddy(portEdit);
portLabel = new QLabel(tr("&Port:"));
portEdit = new QLineEdit(settings.value("port", "4747").toString());
portLabel->setBuddy(portEdit);
playernameLabel = new QLabel(tr("Player &name:"));
playernameEdit = new QLineEdit(settings.value("playername", "Player").toString());
playernameLabel->setBuddy(playernameEdit);
playernameLabel = new QLabel(tr("Player &name:"));
playernameEdit = new QLineEdit(settings.value("playername", "Player").toString());
playernameLabel->setBuddy(playernameEdit);
passwordLabel = new QLabel(tr("P&assword:"));
passwordEdit = new QLineEdit(settings.value("password").toString());
passwordLabel->setBuddy(passwordEdit);
passwordEdit->setEchoMode(QLineEdit::Password);
passwordLabel = new QLabel(tr("P&assword:"));
passwordEdit = new QLineEdit(settings.value("password").toString());
passwordLabel->setBuddy(passwordEdit);
passwordEdit->setEchoMode(QLineEdit::Password);
savePasswordCheckBox = new QCheckBox(tr("&Save password"));
savePasswordCheckBox->setChecked(settings.value("save_password", 1).toInt());
okButton = new QPushButton(tr("&OK"));
okButton->setDefault(true);
cancelButton = new QPushButton(tr("&Cancel"));
QGridLayout *grid = new QGridLayout;
grid->addWidget(hostLabel, 0, 0);
grid->addWidget(hostEdit, 0, 1);
grid->addWidget(portLabel, 1, 0);
grid->addWidget(portEdit, 1, 1);
grid->addWidget(playernameLabel, 2, 0);
grid->addWidget(playernameEdit, 2, 1);
grid->addWidget(passwordLabel, 3, 0);
grid->addWidget(passwordEdit, 3, 1);
grid->addWidget(savePasswordCheckBox, 4, 0, 1, 2);
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(buttonBox, SIGNAL(accepted()), this, SLOT(actOk()));
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addLayout(grid);
mainLayout->addWidget(buttonBox);
setLayout(mainLayout);
QGridLayout *grid = new QGridLayout;
grid->addWidget(hostLabel, 0, 0);
grid->addWidget(hostEdit, 0, 1);
grid->addWidget(portLabel, 1, 0);
grid->addWidget(portEdit, 1, 1);
grid->addWidget(playernameLabel, 2, 0);
grid->addWidget(playernameEdit, 2, 1);
grid->addWidget(passwordLabel, 3, 0);
grid->addWidget(passwordEdit, 3, 1);
QHBoxLayout *buttonLayout = new QHBoxLayout;
buttonLayout->addStretch();
buttonLayout->addWidget(okButton);
buttonLayout->addWidget(cancelButton);
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addLayout(grid);
mainLayout->addLayout(buttonLayout);
setLayout(mainLayout);
setWindowTitle(tr("Connect to server"));
setFixedHeight(sizeHint().height());
setMinimumWidth(300);
connect(okButton, SIGNAL(clicked()), this, SLOT(actOk()));
connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
setWindowTitle(tr("Connect to server"));
setFixedHeight(sizeHint().height());
setMinimumWidth(300);
}
void DlgConnect::actOk()
{
QSettings settings;
settings.beginGroup("server");
settings.setValue("hostname", hostEdit->text());
settings.setValue("port", portEdit->text());
settings.setValue("playername", playernameEdit->text());
settings.setValue("password", passwordEdit->text());
settings.endGroup();
QSettings settings;
settings.beginGroup("server");
settings.setValue("hostname", hostEdit->text());
settings.setValue("port", portEdit->text());
settings.setValue("playername", playernameEdit->text());
settings.setValue("password", savePasswordCheckBox->isChecked() ? passwordEdit->text() : QString());
settings.setValue("save_password", savePasswordCheckBox->isChecked() ? 1 : 0);
settings.endGroup();
accept();
accept();
}

View file

@ -6,21 +6,22 @@
class QLabel;
class QPushButton;
class QCheckBox;
class DlgConnect : public QDialog {
Q_OBJECT
Q_OBJECT
public:
DlgConnect(QWidget *parent = 0);
QString getHost() const { return hostEdit->text(); }
int getPort() const { return portEdit->text().toInt(); }
QString getPlayerName() const { return playernameEdit->text(); }
QString getPassword() const { return passwordEdit->text(); }
DlgConnect(QWidget *parent = 0);
QString getHost() const { return hostEdit->text(); }
int getPort() const { return portEdit->text().toInt(); }
QString getPlayerName() const { return playernameEdit->text(); }
QString getPassword() const { return passwordEdit->text(); }
private slots:
void actOk();
void actOk();
private:
QLabel *hostLabel, *portLabel, *playernameLabel, *passwordLabel;
QLineEdit *hostEdit, *portEdit, *playernameEdit, *passwordEdit;
QPushButton *okButton, *cancelButton;
QLabel *hostLabel, *portLabel, *playernameLabel, *passwordLabel;
QLineEdit *hostEdit, *portEdit, *playernameEdit, *passwordEdit;
QCheckBox *savePasswordCheckBox;
};
#endif

View file

@ -1,102 +1,180 @@
#include <QLabel>
#include <QLineEdit>
#include <QComboBox>
#include <QPushButton>
#include <QCheckBox>
#include <QGridLayout>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QDialogButtonBox>
#include <QGroupBox>
#include <QTreeView>
#include <QRadioButton>
#include <QHeaderView>
#include "decklist.h"
#include "dlg_create_token.h"
#include "carddatabasemodel.h"
#include "main.h"
DlgCreateToken::DlgCreateToken(QWidget *parent)
: QDialog(parent)
DlgCreateToken::DlgCreateToken(const QStringList &_predefinedTokens, QWidget *parent)
: QDialog(parent), predefinedTokens(_predefinedTokens)
{
nameLabel = new QLabel(tr("&Name:"));
nameEdit = new QLineEdit(tr("Token"));
nameEdit->selectAll();
nameLabel->setBuddy(nameEdit);
nameLabel = new QLabel(tr("&Name:"));
nameEdit = new QLineEdit(tr("Token"));
nameEdit->selectAll();
nameLabel->setBuddy(nameEdit);
colorLabel = new QLabel(tr("C&olor:"));
colorEdit = new QComboBox;
colorEdit->addItem(tr("white"), "w");
colorEdit->addItem(tr("blue"), "u");
colorEdit->addItem(tr("black"), "b");
colorEdit->addItem(tr("red"), "r");
colorEdit->addItem(tr("green"), "g");
colorEdit->addItem(tr("multicolor"), "m");
colorEdit->addItem(tr("colorless"), "");
colorLabel->setBuddy(colorEdit);
colorLabel = new QLabel(tr("C&olor:"));
colorEdit = new QComboBox;
colorEdit->addItem(tr("white"), "w");
colorEdit->addItem(tr("blue"), "u");
colorEdit->addItem(tr("black"), "b");
colorEdit->addItem(tr("red"), "r");
colorEdit->addItem(tr("green"), "g");
colorEdit->addItem(tr("multicolor"), "m");
colorEdit->addItem(tr("colorless"), QString());
colorLabel->setBuddy(colorEdit);
ptLabel = new QLabel(tr("&P/T:"));
ptEdit = new QLineEdit;
ptLabel->setBuddy(ptEdit);
ptLabel = new QLabel(tr("&P/T:"));
ptEdit = new QLineEdit;
ptLabel->setBuddy(ptEdit);
annotationLabel = new QLabel(tr("&Annotation:"));
annotationEdit = new QLineEdit;
annotationLabel->setBuddy(annotationEdit);
destroyCheckBox = new QCheckBox(tr("&Destroy token when it leaves the table"));
destroyCheckBox->setChecked(true);
annotationLabel = new QLabel(tr("&Annotation:"));
annotationEdit = new QLineEdit;
annotationLabel->setBuddy(annotationEdit);
destroyCheckBox = new QCheckBox(tr("&Destroy token when it leaves the table"));
destroyCheckBox->setChecked(true);
okButton = new QPushButton(tr("&OK"));
okButton->setDefault(true);
cancelButton = new QPushButton(tr("&Cancel"));
QGridLayout *grid = new QGridLayout;
grid->addWidget(nameLabel, 0, 0);
grid->addWidget(nameEdit, 0, 1);
grid->addWidget(colorLabel, 1, 0);
grid->addWidget(colorEdit, 1, 1);
grid->addWidget(ptLabel, 2, 0);
grid->addWidget(ptEdit, 2, 1);
grid->addWidget(annotationLabel, 3, 0);
grid->addWidget(annotationEdit, 3, 1);
grid->addWidget(destroyCheckBox, 4, 0, 1, 2);
QGroupBox *tokenDataGroupBox = new QGroupBox(tr("Token data"));
tokenDataGroupBox->setLayout(grid);
cardDatabaseModel = new CardDatabaseModel(db, this);
cardDatabaseDisplayModel = new CardDatabaseDisplayModel(this);
cardDatabaseDisplayModel->setSourceModel(cardDatabaseModel);
cardDatabaseDisplayModel->setIsToken(CardDatabaseDisplayModel::ShowTrue);
chooseTokenFromAllRadioButton = new QRadioButton(tr("Show &all tokens"));
connect(chooseTokenFromAllRadioButton, SIGNAL(toggled(bool)), this, SLOT(actChooseTokenFromAll(bool)));
chooseTokenFromDeckRadioButton = new QRadioButton(tr("Show tokens from this &deck"));
connect(chooseTokenFromDeckRadioButton, SIGNAL(toggled(bool)), this, SLOT(actChooseTokenFromDeck(bool)));
QTreeView *chooseTokenView = new QTreeView;
chooseTokenView->setModel(cardDatabaseDisplayModel);
chooseTokenView->setUniformRowHeights(true);
chooseTokenView->setRootIsDecorated(false);
chooseTokenView->setAlternatingRowColors(true);
chooseTokenView->setSortingEnabled(true);
chooseTokenView->sortByColumn(0, Qt::AscendingOrder);
chooseTokenView->resizeColumnToContents(0);
chooseTokenView->header()->setStretchLastSection(false);
chooseTokenView->header()->hideSection(1);
chooseTokenView->header()->hideSection(2);
#if QT_VERSION < 0x050000
chooseTokenView->header()->setResizeMode(3, 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)));
if (predefinedTokens.isEmpty())
chooseTokenFromAllRadioButton->setChecked(true);
else {
chooseTokenFromDeckRadioButton->setChecked(true);
cardDatabaseDisplayModel->setCardNameSet(QSet<QString>::fromList(predefinedTokens));
}
QVBoxLayout *tokenChooseLayout = new QVBoxLayout;
tokenChooseLayout->addWidget(chooseTokenFromAllRadioButton);
tokenChooseLayout->addWidget(chooseTokenFromDeckRadioButton);
tokenChooseLayout->addWidget(chooseTokenView);
QGroupBox *tokenChooseGroupBox = new QGroupBox(tr("Choose token from list"));
tokenChooseGroupBox->setLayout(tokenChooseLayout);
QVBoxLayout *leftVBox = new QVBoxLayout;
leftVBox->addWidget(tokenDataGroupBox);
leftVBox->addStretch();
QHBoxLayout *hbox = new QHBoxLayout;
hbox->addLayout(leftVBox);
hbox->addWidget(tokenChooseGroupBox);
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(buttonBox, SIGNAL(accepted()), this, SLOT(actOk()));
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addLayout(hbox);
mainLayout->addWidget(buttonBox);
setLayout(mainLayout);
QGridLayout *grid = new QGridLayout;
grid->addWidget(nameLabel, 0, 0);
grid->addWidget(nameEdit, 0, 1);
grid->addWidget(colorLabel, 1, 0);
grid->addWidget(colorEdit, 1, 1);
grid->addWidget(ptLabel, 2, 0);
grid->addWidget(ptEdit, 2, 1);
grid->addWidget(annotationLabel, 3, 0);
grid->addWidget(annotationEdit, 3, 1);
grid->addWidget(destroyCheckBox, 4, 0, 1, 2);
setWindowTitle(tr("Create token"));
setFixedHeight(sizeHint().height());
setMinimumWidth(300);
}
QHBoxLayout *buttonLayout = new QHBoxLayout;
buttonLayout->addStretch();
buttonLayout->addWidget(okButton);
buttonLayout->addWidget(cancelButton);
void DlgCreateToken::tokenSelectionChanged(const QModelIndex &current, const QModelIndex & /*previous*/)
{
const QModelIndex realIndex = cardDatabaseDisplayModel->mapToSource(current);
const CardInfo *cardInfo = current.row() >= 0 ? cardDatabaseModel->getCard(realIndex.row()) : db->getCard();
nameEdit->setText(cardInfo->getName());
const QString cardColor = cardInfo->getColors().isEmpty() ? QString() : (cardInfo->getColors().size() > 1 ? QString("m") : cardInfo->getColors().first());
colorEdit->setCurrentIndex(colorEdit->findData(cardColor, Qt::UserRole, Qt::MatchFixedString));
ptEdit->setText(cardInfo->getPowTough());
annotationEdit->setText(cardInfo->getText());
}
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addLayout(grid);
mainLayout->addLayout(buttonLayout);
setLayout(mainLayout);
void DlgCreateToken::actChooseTokenFromAll(bool checked)
{
if (checked)
cardDatabaseDisplayModel->setCardNameSet(QSet<QString>());
}
setWindowTitle(tr("Create token"));
setFixedHeight(sizeHint().height());
setMinimumWidth(300);
connect(okButton, SIGNAL(clicked()), this, SLOT(actOk()));
connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
void DlgCreateToken::actChooseTokenFromDeck(bool checked)
{
if (checked)
cardDatabaseDisplayModel->setCardNameSet(QSet<QString>::fromList(predefinedTokens));
}
void DlgCreateToken::actOk()
{
accept();
accept();
}
QString DlgCreateToken::getName() const
{
return nameEdit->text();
return nameEdit->text();
}
QString DlgCreateToken::getColor() const
{
return colorEdit->itemData(colorEdit->currentIndex()).toString();
return colorEdit->itemData(colorEdit->currentIndex()).toString();
}
QString DlgCreateToken::getPT() const
{
return ptEdit->text();
return ptEdit->text();
}
QString DlgCreateToken::getAnnotation() const
{
return annotationEdit->text();
return annotationEdit->text();
}
bool DlgCreateToken::getDestroy() const
{
return destroyCheckBox->isChecked();
return destroyCheckBox->isChecked();
}

View file

@ -2,30 +2,41 @@
#define DLG_CREATETOKEN_H
#include <QDialog>
#include <QLineEdit>
#include <QModelIndex>
class QLabel;
class QLineEdit;
class QComboBox;
class QCheckBox;
class QPushButton;
class QRadioButton;
class DeckList;
class CardDatabaseModel;
class CardDatabaseDisplayModel;
class DlgCreateToken : public QDialog {
Q_OBJECT
Q_OBJECT
public:
DlgCreateToken(QWidget *parent = 0);
QString getName() const;
QString getColor() const;
QString getPT() const;
QString getAnnotation() const;
bool getDestroy() const;
DlgCreateToken(const QStringList &_predefinedTokens, QWidget *parent = 0);
QString getName() const;
QString getColor() const;
QString getPT() const;
QString getAnnotation() const;
bool getDestroy() const;
private slots:
void actOk();
void tokenSelectionChanged(const QModelIndex &current, const QModelIndex &previous);
void actChooseTokenFromAll(bool checked);
void actChooseTokenFromDeck(bool checked);
void actOk();
private:
QLabel *nameLabel, *colorLabel, *ptLabel, *annotationLabel;
QComboBox *colorEdit;
QLineEdit *nameEdit, *ptEdit, *annotationEdit;
QCheckBox *destroyCheckBox;
QPushButton *okButton, *cancelButton;
CardDatabaseModel *cardDatabaseModel;
CardDatabaseDisplayModel *cardDatabaseDisplayModel;
QStringList predefinedTokens;
QLabel *nameLabel, *colorLabel, *ptLabel, *annotationLabel;
QComboBox *colorEdit;
QLineEdit *nameEdit, *ptEdit, *annotationEdit;
QCheckBox *destroyCheckBox;
QRadioButton *chooseTokenFromAllRadioButton, *chooseTokenFromDeckRadioButton;
};
#endif

View file

@ -7,146 +7,193 @@
#include <QHBoxLayout>
#include <QSpinBox>
#include <QGroupBox>
#include <QDialogButtonBox>
#include <QMessageBox>
#include <QSet>
#include "dlg_creategame.h"
#include "protocol_items.h"
#include "tab_room.h"
DlgCreateGame::DlgCreateGame(AbstractClient *_client, int _roomId, const QMap<int, QString> &_gameTypes, QWidget *parent)
: QDialog(parent), client(_client), roomId(_roomId), gameTypes(_gameTypes)
#include "pending_command.h"
#include "pb/room_commands.pb.h"
#include "pb/serverinfo_game.pb.h"
#include "pb/response.pb.h"
void DlgCreateGame::sharedCtor()
{
descriptionLabel = new QLabel(tr("&Description:"));
descriptionEdit = new QLineEdit;
descriptionLabel->setBuddy(descriptionEdit);
descriptionEdit->setMaxLength(60);
descriptionLabel = new QLabel(tr("&Description:"));
descriptionEdit = new QLineEdit;
descriptionLabel->setBuddy(descriptionEdit);
descriptionEdit->setMaxLength(60);
maxPlayersLabel = new QLabel(tr("P&layers:"));
maxPlayersEdit = new QSpinBox();
maxPlayersEdit->setMinimum(1);
maxPlayersEdit->setMaximum(100);
maxPlayersEdit->setValue(2);
maxPlayersLabel->setBuddy(maxPlayersEdit);
QGridLayout *generalGrid = new QGridLayout;
generalGrid->addWidget(descriptionLabel, 0, 0);
generalGrid->addWidget(descriptionEdit, 0, 1);
generalGrid->addWidget(maxPlayersLabel, 1, 0);
generalGrid->addWidget(maxPlayersEdit, 1, 1);
QVBoxLayout *gameTypeLayout = new QVBoxLayout;
QMapIterator<int, QString> gameTypeIterator(gameTypes);
while (gameTypeIterator.hasNext()) {
gameTypeIterator.next();
QCheckBox *gameTypeCheckBox = new QCheckBox(gameTypeIterator.value());
gameTypeLayout->addWidget(gameTypeCheckBox);
gameTypeCheckBoxes.insert(gameTypeIterator.key(), gameTypeCheckBox);
}
QGroupBox *gameTypeGroupBox = new QGroupBox(tr("Game type"));
gameTypeGroupBox->setLayout(gameTypeLayout);
passwordLabel = new QLabel(tr("&Password:"));
passwordEdit = new QLineEdit;
passwordLabel->setBuddy(passwordEdit);
maxPlayersLabel = new QLabel(tr("P&layers:"));
maxPlayersEdit = new QSpinBox();
maxPlayersEdit->setMinimum(1);
maxPlayersEdit->setMaximum(100);
maxPlayersEdit->setValue(2);
maxPlayersLabel->setBuddy(maxPlayersEdit);
QGridLayout *generalGrid = new QGridLayout;
generalGrid->addWidget(descriptionLabel, 0, 0);
generalGrid->addWidget(descriptionEdit, 0, 1);
generalGrid->addWidget(maxPlayersLabel, 1, 0);
generalGrid->addWidget(maxPlayersEdit, 1, 1);
QVBoxLayout *gameTypeLayout = new QVBoxLayout;
QMapIterator<int, QString> gameTypeIterator(gameTypes);
while (gameTypeIterator.hasNext()) {
gameTypeIterator.next();
QCheckBox *gameTypeCheckBox = new QCheckBox(gameTypeIterator.value());
gameTypeLayout->addWidget(gameTypeCheckBox);
gameTypeCheckBoxes.insert(gameTypeIterator.key(), gameTypeCheckBox);
}
QGroupBox *gameTypeGroupBox = new QGroupBox(tr("Game type"));
gameTypeGroupBox->setLayout(gameTypeLayout);
passwordLabel = new QLabel(tr("&Password:"));
passwordEdit = new QLineEdit;
passwordLabel->setBuddy(passwordEdit);
onlyBuddiesCheckBox = new QCheckBox(tr("Only &buddies can join"));
onlyRegisteredCheckBox = new QCheckBox(tr("Only &registered users can join"));
QGridLayout *joinRestrictionsLayout = new QGridLayout;
joinRestrictionsLayout->addWidget(passwordLabel, 0, 0);
joinRestrictionsLayout->addWidget(passwordEdit, 0, 1);
joinRestrictionsLayout->addWidget(onlyBuddiesCheckBox, 1, 0, 1, 2);
joinRestrictionsLayout->addWidget(onlyRegisteredCheckBox, 2, 0, 1, 2);
QGroupBox *joinRestrictionsGroupBox = new QGroupBox(tr("Joining restrictions"));
joinRestrictionsGroupBox->setLayout(joinRestrictionsLayout);
spectatorsAllowedCheckBox = new QCheckBox(tr("&Spectators allowed"));
spectatorsAllowedCheckBox->setChecked(true);
connect(spectatorsAllowedCheckBox, SIGNAL(stateChanged(int)), this, SLOT(spectatorsAllowedChanged(int)));
spectatorsNeedPasswordCheckBox = new QCheckBox(tr("Spectators &need a password to join"));
spectatorsCanTalkCheckBox = new QCheckBox(tr("Spectators can &chat"));
spectatorsSeeEverythingCheckBox = new QCheckBox(tr("Spectators see &everything"));
QVBoxLayout *spectatorsLayout = new QVBoxLayout;
spectatorsLayout->addWidget(spectatorsAllowedCheckBox);
spectatorsLayout->addWidget(spectatorsNeedPasswordCheckBox);
spectatorsLayout->addWidget(spectatorsCanTalkCheckBox);
spectatorsLayout->addWidget(spectatorsSeeEverythingCheckBox);
spectatorsGroupBox = new QGroupBox(tr("Spectators"));
spectatorsGroupBox->setLayout(spectatorsLayout);
onlyBuddiesCheckBox = new QCheckBox(tr("Only &buddies can join"));
onlyRegisteredCheckBox = new QCheckBox(tr("Only &registered users can join"));
if (room && room->getUserInfo()->user_level() & ServerInfo_User::IsRegistered)
onlyRegisteredCheckBox->setChecked(true);
QGridLayout *joinRestrictionsLayout = new QGridLayout;
joinRestrictionsLayout->addWidget(passwordLabel, 0, 0);
joinRestrictionsLayout->addWidget(passwordEdit, 0, 1);
joinRestrictionsLayout->addWidget(onlyBuddiesCheckBox, 1, 0, 1, 2);
joinRestrictionsLayout->addWidget(onlyRegisteredCheckBox, 2, 0, 1, 2);
QGroupBox *joinRestrictionsGroupBox = new QGroupBox(tr("Joining restrictions"));
joinRestrictionsGroupBox->setLayout(joinRestrictionsLayout);
spectatorsAllowedCheckBox = new QCheckBox(tr("&Spectators allowed"));
spectatorsAllowedCheckBox->setChecked(true);
connect(spectatorsAllowedCheckBox, SIGNAL(stateChanged(int)), this, SLOT(spectatorsAllowedChanged(int)));
spectatorsNeedPasswordCheckBox = new QCheckBox(tr("Spectators &need a password to join"));
spectatorsCanTalkCheckBox = new QCheckBox(tr("Spectators can &chat"));
spectatorsSeeEverythingCheckBox = new QCheckBox(tr("Spectators see &everything"));
QVBoxLayout *spectatorsLayout = new QVBoxLayout;
spectatorsLayout->addWidget(spectatorsAllowedCheckBox);
spectatorsLayout->addWidget(spectatorsNeedPasswordCheckBox);
spectatorsLayout->addWidget(spectatorsCanTalkCheckBox);
spectatorsLayout->addWidget(spectatorsSeeEverythingCheckBox);
spectatorsGroupBox = new QGroupBox(tr("Spectators"));
spectatorsGroupBox->setLayout(spectatorsLayout);
QGridLayout *grid = new QGridLayout;
grid->addLayout(generalGrid, 0, 0);
grid->addWidget(spectatorsGroupBox, 1, 0);
grid->addWidget(joinRestrictionsGroupBox, 0, 1);
grid->addWidget(gameTypeGroupBox, 1, 1);
QGridLayout *grid = new QGridLayout;
grid->addLayout(generalGrid, 0, 0);
grid->addWidget(spectatorsGroupBox, 1, 0);
grid->addWidget(joinRestrictionsGroupBox, 0, 1);
grid->addWidget(gameTypeGroupBox, 1, 1);
okButton = new QPushButton(tr("&OK"));
okButton->setDefault(true);
cancelButton = new QPushButton(tr("&Cancel"));
buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok);
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addLayout(grid);
mainLayout->addWidget(buttonBox);
QHBoxLayout *buttonLayout = new QHBoxLayout;
buttonLayout->addStretch();
buttonLayout->addWidget(okButton);
buttonLayout->addWidget(cancelButton);
setLayout(mainLayout);
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addLayout(grid);
mainLayout->addLayout(buttonLayout);
setFixedHeight(sizeHint().height());
}
setLayout(mainLayout);
DlgCreateGame::DlgCreateGame(TabRoom *_room, const QMap<int, QString> &_gameTypes, QWidget *parent)
: QDialog(parent), room(_room), gameTypes(_gameTypes)
{
sharedCtor();
buttonBox->addButton(QDialogButtonBox::Cancel);
connect(buttonBox, SIGNAL(accepted()), this, SLOT(actOK()));
setWindowTitle(tr("Create game"));
}
setWindowTitle(tr("Create game"));
setFixedHeight(sizeHint().height());
connect(okButton, SIGNAL(clicked()), this, SLOT(actOK()));
connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
DlgCreateGame::DlgCreateGame(const ServerInfo_Game &gameInfo, const QMap<int, QString> &_gameTypes, QWidget *parent)
: QDialog(parent), room(0), gameTypes(_gameTypes)
{
sharedCtor();
descriptionEdit->setEnabled(false);
maxPlayersEdit->setEnabled(false);
passwordEdit->setEnabled(false);
onlyBuddiesCheckBox->setEnabled(false);
onlyRegisteredCheckBox->setEnabled(false);
spectatorsAllowedCheckBox->setEnabled(false);
spectatorsNeedPasswordCheckBox->setEnabled(false);
spectatorsCanTalkCheckBox->setEnabled(false);
spectatorsSeeEverythingCheckBox->setEnabled(false);
descriptionEdit->setText(QString::fromStdString(gameInfo.description()));
maxPlayersEdit->setValue(gameInfo.max_players());
onlyBuddiesCheckBox->setChecked(gameInfo.only_buddies());
onlyRegisteredCheckBox->setChecked(gameInfo.only_registered());
spectatorsAllowedCheckBox->setChecked(gameInfo.spectators_allowed());
spectatorsNeedPasswordCheckBox->setChecked(gameInfo.spectators_need_password());
spectatorsCanTalkCheckBox->setChecked(gameInfo.spectators_can_chat());
spectatorsSeeEverythingCheckBox->setChecked(gameInfo.spectators_omniscient());
QSet<int> types;
for (int i = 0; i < gameInfo.game_types_size(); ++i)
types.insert(gameInfo.game_types(i));
QMapIterator<int, QString> gameTypeIterator(gameTypes);
while (gameTypeIterator.hasNext()) {
gameTypeIterator.next();
QCheckBox *gameTypeCheckBox = gameTypeCheckBoxes.value(gameTypeIterator.key());
gameTypeCheckBox->setEnabled(false);
gameTypeCheckBox->setChecked(types.contains(gameTypeIterator.key()));
}
connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
setWindowTitle(tr("Game information"));
}
void DlgCreateGame::actOK()
{
QList<GameTypeId *> gameTypeList;
QMapIterator<int, QCheckBox *> gameTypeCheckBoxIterator(gameTypeCheckBoxes);
while (gameTypeCheckBoxIterator.hasNext()) {
gameTypeCheckBoxIterator.next();
if (gameTypeCheckBoxIterator.value()->isChecked())
gameTypeList.append(new GameTypeId(gameTypeCheckBoxIterator.key()));
}
Command_CreateGame *createCommand = new Command_CreateGame(
roomId,
descriptionEdit->text(),
passwordEdit->text(),
maxPlayersEdit->value(),
gameTypeList,
onlyBuddiesCheckBox->isChecked(),
onlyRegisteredCheckBox->isChecked(),
spectatorsAllowedCheckBox->isChecked(),
spectatorsNeedPasswordCheckBox->isChecked(),
spectatorsCanTalkCheckBox->isChecked(),
spectatorsSeeEverythingCheckBox->isChecked()
);
connect(createCommand, SIGNAL(finished(ResponseCode)), this, SLOT(checkResponse(ResponseCode)));
client->sendCommand(createCommand);
okButton->setEnabled(false);
cancelButton->setEnabled(false);
Command_CreateGame cmd;
cmd.set_description(descriptionEdit->text().toStdString());
cmd.set_password(passwordEdit->text().toStdString());
cmd.set_max_players(maxPlayersEdit->value());
cmd.set_only_buddies(onlyBuddiesCheckBox->isChecked());
cmd.set_only_registered(onlyRegisteredCheckBox->isChecked());
cmd.set_spectators_allowed(spectatorsAllowedCheckBox->isChecked());
cmd.set_spectators_need_password(spectatorsNeedPasswordCheckBox->isChecked());
cmd.set_spectators_can_talk(spectatorsCanTalkCheckBox->isChecked());
cmd.set_spectators_see_everything(spectatorsSeeEverythingCheckBox->isChecked());
QMapIterator<int, QCheckBox *> gameTypeCheckBoxIterator(gameTypeCheckBoxes);
while (gameTypeCheckBoxIterator.hasNext()) {
gameTypeCheckBoxIterator.next();
if (gameTypeCheckBoxIterator.value()->isChecked())
cmd.add_game_type_ids(gameTypeCheckBoxIterator.key());
}
PendingCommand *pend = room->prepareRoomCommand(cmd);
connect(pend, SIGNAL(finished(Response, CommandContainer, QVariant)), this, SLOT(checkResponse(Response)));
room->sendRoomCommand(pend);
buttonBox->setEnabled(false);
}
void DlgCreateGame::checkResponse(ResponseCode response)
void DlgCreateGame::checkResponse(const Response &response)
{
okButton->setEnabled(true);
cancelButton->setEnabled(true);
buttonBox->setEnabled(true);
if (response == RespOk)
accept();
else {
QMessageBox::critical(this, tr("Error"), tr("Server error."));
return;
}
if (response.response_code() == Response::RespOk)
accept();
else {
QMessageBox::critical(this, tr("Error"), tr("Server error."));
return;
}
}
void DlgCreateGame::spectatorsAllowedChanged(int state)
{
spectatorsNeedPasswordCheckBox->setEnabled(state);
spectatorsCanTalkCheckBox->setEnabled(state);
spectatorsSeeEverythingCheckBox->setEnabled(state);
spectatorsNeedPasswordCheckBox->setEnabled(state);
spectatorsCanTalkCheckBox->setEnabled(state);
spectatorsSeeEverythingCheckBox->setEnabled(state);
}

View file

@ -2,7 +2,7 @@
#define DLG_CREATEGAME_H
#include <QDialog>
#include "abstractclient.h"
#include <QMap>
class QLabel;
class QLineEdit;
@ -10,28 +10,35 @@ class QPushButton;
class QCheckBox;
class QGroupBox;
class QSpinBox;
class QDialogButtonBox;
class TabRoom;
class Response;
class ServerInfo_Game;
class DlgCreateGame : public QDialog {
Q_OBJECT
Q_OBJECT
public:
DlgCreateGame(AbstractClient *_client, int _roomId, const QMap<int, QString> &_gameTypes, QWidget *parent = 0);
DlgCreateGame(TabRoom *_room, const QMap<int, QString> &_gameTypes, QWidget *parent = 0);
DlgCreateGame(const ServerInfo_Game &game, const QMap<int, QString> &_gameTypes, QWidget *parent = 0);
private slots:
void actOK();
void checkResponse(ResponseCode response);
void spectatorsAllowedChanged(int state);
void actOK();
void checkResponse(const Response &response);
void spectatorsAllowedChanged(int state);
private:
AbstractClient *client;
int roomId;
QMap<int, QString> gameTypes;
QMap<int, QCheckBox *> gameTypeCheckBoxes;
TabRoom *room;
QMap<int, QString> gameTypes;
QMap<int, QCheckBox *> gameTypeCheckBoxes;
QGroupBox *spectatorsGroupBox;
QLabel *descriptionLabel, *passwordLabel, *maxPlayersLabel;
QLineEdit *descriptionEdit, *passwordEdit;
QSpinBox *maxPlayersEdit;
QCheckBox *onlyBuddiesCheckBox, *onlyRegisteredCheckBox;
QCheckBox *spectatorsAllowedCheckBox, *spectatorsNeedPasswordCheckBox, *spectatorsCanTalkCheckBox, *spectatorsSeeEverythingCheckBox;
QPushButton *okButton, *cancelButton;
QGroupBox *spectatorsGroupBox;
QLabel *descriptionLabel, *passwordLabel, *maxPlayersLabel;
QLineEdit *descriptionEdit, *passwordEdit;
QSpinBox *maxPlayersEdit;
QCheckBox *onlyBuddiesCheckBox, *onlyRegisteredCheckBox;
QCheckBox *spectatorsAllowedCheckBox, *spectatorsNeedPasswordCheckBox, *spectatorsCanTalkCheckBox, *spectatorsSeeEverythingCheckBox;
QDialogButtonBox *buttonBox;
void sharedCtor();
};
#endif

View file

@ -0,0 +1,180 @@
#include "dlg_edit_tokens.h"
#include "carddatabasemodel.h"
#include <QDialogButtonBox>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QGridLayout>
#include <QLabel>
#include <QComboBox>
#include <QLineEdit>
#include <QGroupBox>
#include <QTreeView>
#include <QHeaderView>
#include <QToolBar>
#include <QAction>
#include <QInputDialog>
#include <QMessageBox>
DlgEditTokens::DlgEditTokens(CardDatabaseModel *_cardDatabaseModel, QWidget *parent)
: QDialog(parent), currentCard(0), cardDatabaseModel(_cardDatabaseModel)
{
nameLabel = new QLabel(tr("&Name:"));
nameEdit = new QLineEdit;
nameEdit->setEnabled(false);
nameLabel->setBuddy(nameEdit);
colorLabel = new QLabel(tr("C&olor:"));
colorEdit = new QComboBox;
colorEdit->addItem(tr("white"), "w");
colorEdit->addItem(tr("blue"), "u");
colorEdit->addItem(tr("black"), "b");
colorEdit->addItem(tr("red"), "r");
colorEdit->addItem(tr("green"), "g");
colorEdit->addItem(tr("multicolor"), "m");
colorEdit->addItem(tr("colorless"), QString());
colorLabel->setBuddy(colorEdit);
connect(colorEdit, SIGNAL(currentIndexChanged(int)), this, SLOT(colorChanged(int)));
ptLabel = new QLabel(tr("&P/T:"));
ptEdit = new QLineEdit;
ptLabel->setBuddy(ptEdit);
connect(ptEdit, SIGNAL(textChanged(QString)), this, SLOT(ptChanged(QString)));
annotationLabel = new QLabel(tr("&Annotation:"));
annotationEdit = new QLineEdit;
annotationLabel->setBuddy(annotationEdit);
connect(annotationEdit, SIGNAL(textChanged(QString)), this, SLOT(annotationChanged(QString)));
QGridLayout *grid = new QGridLayout;
grid->addWidget(nameLabel, 0, 0);
grid->addWidget(nameEdit, 0, 1);
grid->addWidget(colorLabel, 1, 0);
grid->addWidget(colorEdit, 1, 1);
grid->addWidget(ptLabel, 2, 0);
grid->addWidget(ptEdit, 2, 1);
grid->addWidget(annotationLabel, 3, 0);
grid->addWidget(annotationEdit, 3, 1);
QGroupBox *tokenDataGroupBox = new QGroupBox(tr("Token data"));
tokenDataGroupBox->setLayout(grid);
cardDatabaseDisplayModel = new CardDatabaseDisplayModel(this);
cardDatabaseDisplayModel->setSourceModel(cardDatabaseModel);
cardDatabaseDisplayModel->setIsToken(CardDatabaseDisplayModel::ShowTrue);
chooseTokenView = new QTreeView;
chooseTokenView->setModel(cardDatabaseDisplayModel);
chooseTokenView->setUniformRowHeights(true);
chooseTokenView->setRootIsDecorated(false);
chooseTokenView->setAlternatingRowColors(true);
chooseTokenView->setSortingEnabled(true);
chooseTokenView->sortByColumn(0, Qt::AscendingOrder);
chooseTokenView->resizeColumnToContents(0);
chooseTokenView->header()->setStretchLastSection(false);
chooseTokenView->header()->hideSection(1);
chooseTokenView->header()->hideSection(2);
#if QT_VERSION < 0x050000
chooseTokenView->header()->setResizeMode(3, 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)));
QAction *aAddToken = new QAction(tr("Add token"), this);
aAddToken->setIcon(QIcon(":/resources/increment.svg"));
connect(aAddToken, SIGNAL(triggered()), this, SLOT(actAddToken()));
QAction *aRemoveToken = new QAction(tr("Remove token"), this);
aRemoveToken->setIcon(QIcon(":/resources/decrement.svg"));
connect(aRemoveToken, SIGNAL(triggered()), this, SLOT(actRemoveToken()));
QToolBar *databaseToolBar = new QToolBar;
databaseToolBar->addAction(aAddToken);
databaseToolBar->addAction(aRemoveToken);
QVBoxLayout *leftVBox = new QVBoxLayout;
leftVBox->addWidget(chooseTokenView);
leftVBox->addWidget(databaseToolBar);
QHBoxLayout *hbox = new QHBoxLayout;
hbox->addLayout(leftVBox);
hbox->addWidget(tokenDataGroupBox);
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Close);
connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addLayout(hbox);
mainLayout->addWidget(buttonBox);
setLayout(mainLayout);
setWindowTitle(tr("Edit tokens"));
}
void DlgEditTokens::tokenSelectionChanged(const QModelIndex &current, const QModelIndex & /* previous */)
{
const QModelIndex realIndex = cardDatabaseDisplayModel->mapToSource(current);
CardInfo *cardInfo = current.row() >= 0 ? cardDatabaseModel->getCard(realIndex.row()) : cardDatabaseModel->getDatabase()->getCard();
if (!cardInfo->getName().isEmpty())
currentCard = cardInfo;
else
currentCard = 0;
nameEdit->setText(cardInfo->getName());
const QString cardColor = cardInfo->getColors().isEmpty() ? QString() : (cardInfo->getColors().size() > 1 ? QString("m") : cardInfo->getColors().first());
colorEdit->setCurrentIndex(colorEdit->findData(cardColor, Qt::UserRole, Qt::MatchFixedString));
ptEdit->setText(cardInfo->getPowTough());
annotationEdit->setText(cardInfo->getText());
}
void DlgEditTokens::actAddToken()
{
QString name;
bool askAgain;
do {
name = QInputDialog::getText(this, tr("Add token"), tr("Please enter the name of the token:"));
if (!name.isEmpty() && cardDatabaseModel->getDatabase()->getCard(name, false)) {
QMessageBox::critical(this, tr("Error"), tr("The chosen name conflicts with an existing card or token."));
askAgain = true;
} else
askAgain = false;
} while (askAgain);
if (name.isEmpty())
return;
CardInfo *card = new CardInfo(cardDatabaseModel->getDatabase(), name, true);
card->addToSet(cardDatabaseModel->getDatabase()->getSet("TK"));
card->setCardType("Token");
cardDatabaseModel->getDatabase()->addCard(card);
}
void DlgEditTokens::actRemoveToken()
{
if (currentCard) {
CardInfo *cardToRemove = currentCard; // the currentCard property gets modified during db->removeCard()
currentCard = 0;
cardDatabaseModel->getDatabase()->removeCard(cardToRemove);
delete cardToRemove;
}
}
void DlgEditTokens::colorChanged(int colorIndex)
{
if (currentCard)
currentCard->setColors(QStringList() << colorEdit->itemData(colorIndex).toString());
}
void DlgEditTokens::ptChanged(const QString &_pt)
{
if (currentCard)
currentCard->setPowTough(_pt);
}
void DlgEditTokens::annotationChanged(const QString &_annotation)
{
if (currentCard)
currentCard->setText(_annotation);
}

View file

@ -0,0 +1,38 @@
#ifndef DLG_EDIT_TOKENS_H
#define DLG_EDIT_TOKENS_H
#include <QDialog>
class QModelIndex;
class CardDatabaseModel;
class CardDatabaseDisplayModel;
class QLabel;
class QComboBox;
class QLineEdit;
class QTreeView;
class CardInfo;
class DlgEditTokens : public QDialog {
Q_OBJECT
private slots:
void tokenSelectionChanged(const QModelIndex &current, const QModelIndex &previous);
void colorChanged(int _colorIndex);
void ptChanged(const QString &_pt);
void annotationChanged(const QString &_annotation);
void actAddToken();
void actRemoveToken();
private:
CardInfo *currentCard;
CardDatabaseModel *cardDatabaseModel;
CardDatabaseDisplayModel *cardDatabaseDisplayModel;
QStringList predefinedTokens;
QLabel *nameLabel, *colorLabel, *ptLabel, *annotationLabel;
QComboBox *colorEdit;
QLineEdit *nameEdit, *ptEdit, *annotationEdit;
QTreeView *chooseTokenView;
public:
DlgEditTokens(CardDatabaseModel *_cardDatabaseModel, QWidget *parent = 0);
};
#endif

View file

@ -0,0 +1,239 @@
#include "dlg_filter_games.h"
#include <QCheckBox>
#include <QPushButton>
#include <QLabel>
#include <QSpinBox>
#include <QLineEdit>
#include <QGroupBox>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QGridLayout>
#include <QDialogButtonBox>
#include <QSettings>
#include <QCryptographicHash>
DlgFilterGames::DlgFilterGames(const QMap<int, QString> &_allGameTypes, QWidget *parent)
: QDialog(parent),
allGameTypes(_allGameTypes)
{
QSettings settings;
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()
);
gameNameFilterEdit = new QLineEdit;
gameNameFilterEdit->setText(
settings.value("game_name_filter", "").toString()
);
QLabel *gameNameFilterLabel = new QLabel(tr("Game &description:"));
gameNameFilterLabel->setBuddy(gameNameFilterEdit);
creatorNameFilterEdit = new QLineEdit;
creatorNameFilterEdit->setText(
settings.value("creator_name_filter", "").toString()
);
QLabel *creatorNameFilterLabel = new QLabel(tr("&Creator name:"));
creatorNameFilterLabel->setBuddy(creatorNameFilterEdit);
QVBoxLayout *gameTypeFilterLayout = new QVBoxLayout;
QMapIterator<int, QString> gameTypesIterator(allGameTypes);
while (gameTypesIterator.hasNext()) {
gameTypesIterator.next();
QCheckBox *temp = new QCheckBox(gameTypesIterator.value());
temp->setChecked(
settings.value(
"game_type/" + hashGameType(gameTypesIterator.value()),
false
).toBool()
);
gameTypeFilterCheckBoxes.insert(gameTypesIterator.key(), temp);
gameTypeFilterLayout->addWidget(temp);
}
QGroupBox *gameTypeFilterGroupBox;
if (!allGameTypes.isEmpty()) {
gameTypeFilterGroupBox = new QGroupBox(tr("&Game types"));
gameTypeFilterGroupBox->setLayout(gameTypeFilterLayout);
} else
gameTypeFilterGroupBox = 0;
QLabel *maxPlayersFilterMinLabel = new QLabel(tr("at &least:"));
maxPlayersFilterMinSpinBox = new QSpinBox;
maxPlayersFilterMinSpinBox->setMinimum(1);
maxPlayersFilterMinSpinBox->setMaximum(99);
maxPlayersFilterMinSpinBox->setValue(
settings.value("min_players", 1).toInt()
);
maxPlayersFilterMinLabel->setBuddy(maxPlayersFilterMinSpinBox);
QLabel *maxPlayersFilterMaxLabel = new QLabel(tr("at &most:"));
maxPlayersFilterMaxSpinBox = new QSpinBox;
maxPlayersFilterMaxSpinBox->setMinimum(1);
maxPlayersFilterMaxSpinBox->setMaximum(99);
maxPlayersFilterMaxSpinBox->setValue(
settings.value("max_players", 99).toInt()
);
maxPlayersFilterMaxLabel->setBuddy(maxPlayersFilterMaxSpinBox);
QGridLayout *maxPlayersFilterLayout = new QGridLayout;
maxPlayersFilterLayout->addWidget(maxPlayersFilterMinLabel, 0, 0);
maxPlayersFilterLayout->addWidget(maxPlayersFilterMinSpinBox, 0, 1);
maxPlayersFilterLayout->addWidget(maxPlayersFilterMaxLabel, 1, 0);
maxPlayersFilterLayout->addWidget(maxPlayersFilterMaxSpinBox, 1, 1);
QGroupBox *maxPlayersGroupBox = new QGroupBox(tr("Maximum player count"));
maxPlayersGroupBox->setLayout(maxPlayersFilterLayout);
QGridLayout *leftGrid = new QGridLayout;
leftGrid->addWidget(gameNameFilterLabel, 0, 0);
leftGrid->addWidget(gameNameFilterEdit, 0, 1);
leftGrid->addWidget(creatorNameFilterLabel, 1, 0);
leftGrid->addWidget(creatorNameFilterEdit, 1, 1);
leftGrid->addWidget(maxPlayersGroupBox, 2, 0, 1, 2);
leftGrid->addWidget(unavailableGamesVisibleCheckBox, 3, 0, 1, 2);
leftGrid->addWidget(passwordProtectedGamesVisibleCheckBox, 4, 0, 1, 2);
QVBoxLayout *leftColumn = new QVBoxLayout;
leftColumn->addLayout(leftGrid);
leftColumn->addStretch();
QVBoxLayout *rightColumn = new QVBoxLayout;
rightColumn->addWidget(gameTypeFilterGroupBox);
QHBoxLayout *hbox = new QHBoxLayout;
hbox->addLayout(leftColumn);
hbox->addLayout(rightColumn);
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(buttonBox, SIGNAL(accepted()), this, SLOT(actOk()));
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addLayout(hbox);
mainLayout->addWidget(buttonBox);
setLayout(mainLayout);
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
{
return unavailableGamesVisibleCheckBox->isChecked();
}
void DlgFilterGames::setUnavailableGamesVisible(bool _unavailableGamesVisible)
{
unavailableGamesVisibleCheckBox->setChecked(_unavailableGamesVisible);
}
bool DlgFilterGames::getPasswordProtectedGamesVisible() const
{
return passwordProtectedGamesVisibleCheckBox->isChecked();
}
void DlgFilterGames::setPasswordProtectedGamesVisible(bool _passwordProtectedGamesVisible)
{
passwordProtectedGamesVisibleCheckBox->setChecked(_passwordProtectedGamesVisible);
}
QString DlgFilterGames::getGameNameFilter() const
{
return gameNameFilterEdit->text();
}
void DlgFilterGames::setGameNameFilter(const QString &_gameNameFilter)
{
gameNameFilterEdit->setText(_gameNameFilter);
}
QString DlgFilterGames::getCreatorNameFilter() const
{
return creatorNameFilterEdit->text();
}
void DlgFilterGames::setCreatorNameFilter(const QString &_creatorNameFilter)
{
creatorNameFilterEdit->setText(_creatorNameFilter);
}
QSet<int> DlgFilterGames::getGameTypeFilter() const
{
QSet<int> result;
QMapIterator<int, QCheckBox *> i(gameTypeFilterCheckBoxes);
while (i.hasNext()) {
i.next();
if (i.value()->isChecked())
result.insert(i.key());
}
return result;
}
void DlgFilterGames::setGameTypeFilter(const QSet<int> &_gameTypeFilter)
{
QMapIterator<int, QCheckBox *> i(gameTypeFilterCheckBoxes);
while (i.hasNext()) {
i.next();
i.value()->setChecked(_gameTypeFilter.contains(i.key()));
}
}
int DlgFilterGames::getMaxPlayersFilterMin() const
{
return maxPlayersFilterMinSpinBox->value();
}
int DlgFilterGames::getMaxPlayersFilterMax() const
{
return maxPlayersFilterMaxSpinBox->value();
}
void DlgFilterGames::setMaxPlayersFilter(int _maxPlayersFilterMin, int _maxPlayersFilterMax)
{
maxPlayersFilterMinSpinBox->setValue(_maxPlayersFilterMin);
maxPlayersFilterMaxSpinBox->setValue(_maxPlayersFilterMax == -1 ? maxPlayersFilterMaxSpinBox->maximum() : _maxPlayersFilterMax);
}

View file

@ -0,0 +1,50 @@
#ifndef DLG_FILTER_GAMES_H
#define DLG_FILTER_GAMES_H
#include <QDialog>
#include <QSet>
#include <QMap>
class QCheckBox;
class QLineEdit;
class QSpinBox;
class DlgFilterGames : public QDialog {
Q_OBJECT
private:
QCheckBox *unavailableGamesVisibleCheckBox;
QCheckBox *passwordProtectedGamesVisibleCheckBox;
QLineEdit *gameNameFilterEdit;
QLineEdit *creatorNameFilterEdit;
QMap<int, QCheckBox *> gameTypeFilterCheckBoxes;
QSpinBox *maxPlayersFilterMinSpinBox;
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:
DlgFilterGames(const QMap<int, QString> &allGameTypes, QWidget *parent = 0);
bool getUnavailableGamesVisible() const;
void setUnavailableGamesVisible(bool _unavailableGamesVisible);
bool getPasswordProtectedGamesVisible() const;
void setPasswordProtectedGamesVisible(bool _passwordProtectedGamesVisible);
QString getGameNameFilter() const;
void setGameNameFilter(const QString &_gameNameFilter);
QString getCreatorNameFilter() const;
void setCreatorNameFilter(const QString &_creatorNameFilter);
QSet<int> getGameTypeFilter() const;
void setGameTypeFilter(const QSet<int> &_gameTypeFilter);
int getMaxPlayersFilterMin() const;
int getMaxPlayersFilterMax() const;
void setMaxPlayersFilter(int _maxPlayersFilterMin, int _maxPlayersFilterMax);
};
#endif

View file

@ -6,59 +6,53 @@
#include <QKeySequence>
#include <QApplication>
#include <QTextStream>
#include <QDialogButtonBox>
#include <QMessageBox>
#include "dlg_load_deck_from_clipboard.h"
#include "decklist.h"
#include "deck_loader.h"
DlgLoadDeckFromClipboard::DlgLoadDeckFromClipboard(QWidget *parent)
: QDialog(parent), deckList(0)
: QDialog(parent), deckList(0)
{
contentsEdit = new QPlainTextEdit;
refreshButton = new QPushButton(tr("&Refresh"));
refreshButton->setShortcut(QKeySequence("F5"));
okButton = new QPushButton(tr("&OK"));
okButton->setDefault(true);
cancelButton = new QPushButton(tr("&Cancel"));
contentsEdit = new QPlainTextEdit;
refreshButton = new QPushButton(tr("&Refresh"));
refreshButton->setShortcut(QKeySequence("F5"));
connect(refreshButton, SIGNAL(clicked()), this, SLOT(actRefresh()));
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
buttonBox->addButton(refreshButton, QDialogButtonBox::ActionRole);
connect(buttonBox, SIGNAL(accepted()), this, SLOT(actOK()));
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(contentsEdit);
mainLayout->addWidget(buttonBox);
QHBoxLayout *buttonLayout = new QHBoxLayout;
buttonLayout->addWidget(refreshButton);
buttonLayout->addStretch();
buttonLayout->addWidget(okButton);
buttonLayout->addWidget(cancelButton);
setLayout(mainLayout);
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(contentsEdit);
mainLayout->addLayout(buttonLayout);
setLayout(mainLayout);
setWindowTitle(tr("Load deck from clipboard"));
resize(500, 500);
connect(refreshButton, SIGNAL(clicked()), this, SLOT(actRefresh()));
connect(okButton, SIGNAL(clicked()), this, SLOT(actOK()));
connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
actRefresh();
setWindowTitle(tr("Load deck from clipboard"));
resize(500, 500);
actRefresh();
}
void DlgLoadDeckFromClipboard::actRefresh()
{
contentsEdit->setPlainText(QApplication::clipboard()->text());
contentsEdit->setPlainText(QApplication::clipboard()->text());
}
void DlgLoadDeckFromClipboard::actOK()
{
QString buffer = contentsEdit->toPlainText();
QTextStream stream(&buffer);
DeckList *l = new DeckList;
if (l->loadFromStream_Plain(stream)) {
deckList = l;
accept();
} else {
QMessageBox::critical(this, tr("Error"), tr("Invalid deck list."));
delete l;
}
QString buffer = contentsEdit->toPlainText();
QTextStream stream(&buffer);
DeckLoader *l = new DeckLoader;
if (l->loadFromStream_Plain(stream)) {
deckList = l;
accept();
} else {
QMessageBox::critical(this, tr("Error"), tr("Invalid deck list."));
delete l;
}
}

Some files were not shown because too many files have changed in this diff Show more