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 GNU GENERAL PUBLIC LICENSE
Version 2, June 1991 Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc. Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed. of this license document, but changing it is not allowed.
Preamble Preamble
The licenses for most software are designed to take away your The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public 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 General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by 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. your programs, too.
When we speak of free software, we are referring to freedom, not 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 The precise terms and conditions for copying, distribution and
modification follow. modification follow.
GNU GENERAL PUBLIC LICENSE GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains 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 License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on does not normally print such an announcement, your work based on
the Program is not required to print an announcement.) the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program, identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in 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 access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not distribution of the source code, even though third parties are not
compelled to copy the source along with the object code. compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program 4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is 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 This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License. be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in 8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License 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 preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally. 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 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 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 PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES. POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest 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 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 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License along
along with this program; if not, write to the Free Software with this program; if not, write to the Free Software Foundation, Inc.,
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail. 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 This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the 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. 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 "MUI2.nsh"
!include "FileFunc.nsh" !include "FileFunc.nsh"
Name "Cockatrice" Name "@CPACK_PACKAGE_NAME@"
OutFile "cockatrice_win32.exe" OutFile "@CPACK_TOPLEVEL_DIRECTORY@/@CPACK_OUTPUT_FILE_NAME@"
SetCompressor lzma SetCompressor /SOLID lzma
InstallDir "$PROGRAMFILES\Cockatrice" InstallDir "$PROGRAMFILES\Cockatrice"
!define INST_DIR "@CPACK_TEMPORARY_DIRECTORY@"
!define MUI_ABORTWARNING !define MUI_ABORTWARNING
!define MUI_WELCOMEFINISHPAGE_BITMAP "leftimage.bmp" !define MUI_WELCOMEFINISHPAGE_BITMAP "${NSIS_SOURCE_PATH}\cmake\leftimage.bmp"
!define MUI_UNWELCOMEFINISHPAGE_BITMAP "leftimage.bmp" !define MUI_UNWELCOMEFINISHPAGE_BITMAP "${NSIS_SOURCE_PATH}\cmake\leftimage.bmp"
!define MUI_HEADERIMAGE !define MUI_HEADERIMAGE
!define MUI_HEADERIMAGE_BITMAP "headerimage.bmp" !define MUI_HEADERIMAGE_BITMAP "${NSIS_SOURCE_PATH}\cmake\headerimage.bmp"
!define MUI_HEADERIMAGE_UNBITMAP "headerimage.bmp" !define MUI_HEADERIMAGE_UNBITMAP "${NSIS_SOURCE_PATH}\cmake\headerimage.bmp"
!define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the installation of Cockatrice.$\r$\n$\r$\nClick Next to continue." !define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the installation of Cockatrice.$\r$\n$\r$\nClick Next to continue."
!define MUI_FINISHPAGE_RUN "$INSTDIR/oracle.exe" !define MUI_FINISHPAGE_RUN "$INSTDIR/oracle.exe"
!define MUI_FINISHPAGE_RUN_TEXT "Run card database downloader now" !define MUI_FINISHPAGE_RUN_TEXT "Run card database downloader now"
!define MUI_FINISHPAGE_RUN_PARAMETERS "-dlsets" !define MUI_FINISHPAGE_RUN_PARAMETERS "-dlsets"
!insertmacro MUI_PAGE_WELCOME !insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE "${NSIS_SOURCE_PATH}\COPYING"
!insertmacro MUI_PAGE_COMPONENTS !insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_DIRECTORY !insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES !insertmacro MUI_PAGE_INSTFILES
@ -30,34 +33,15 @@ InstallDir "$PROGRAMFILES\Cockatrice"
!insertmacro MUI_LANGUAGE "English" !insertmacro MUI_LANGUAGE "English"
Section "Application" SecApplication Section "Application" SecApplication
SetShellVarContext all
SetOutPath "$INSTDIR" 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" @CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS@
File /r ..\zonebg\*.* @CPACK_NSIS_FULL_INSTALL@
SetOutPath "$INSTDIR\plugins"
File /r data\plugins\*.*
SetOutPath "$INSTDIR\sounds" WriteUninstaller "$INSTDIR\uninstall.exe"
File /r ..\sounds\*.* ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2
IntFmt $0 "0x%08X" $0
SetOutPath "$INSTDIR\pics"
SetOutPath "$INSTDIR\decks"
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" "DisplayName" "Cockatrice"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "UninstallString" "$\"$INSTDIR\uninstall.exe$\"" 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" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S"
@ -67,50 +51,48 @@ Section "Application" SecApplication
SectionEnd SectionEnd
Section "Update configuration" SecUpdateConfig Section "Update configuration" SecUpdateConfig
WriteRegStr HKCU "Software\Cockatrice\Cockatrice\paths" "carddatabase" "$INSTDIR\cards.xml" WriteRegStr HKCU "Software\Cockatrice\Cockatrice\paths" "carddatabase" "$APPDATA\Cockatrice\cards.xml"
WriteRegStr HKCU "Software\Cockatrice\Cockatrice\paths" "decks" "$INSTDIR\decks" WriteRegStr HKCU "Software\Cockatrice\Cockatrice\paths" "decks" "$APPDATA\Cockatrice\decks"
WriteRegStr HKCU "Software\Cockatrice\Cockatrice\paths" "pics" "$INSTDIR\pics" WriteRegStr HKCU "Software\Cockatrice\Cockatrice\paths" "pics" "$APPDATA\Cockatrice\pics"
WriteRegStr HKCU "Software\Cockatrice\Cockatrice\sound" "path" "$INSTDIR\sounds" WriteRegStr HKCU "Software\Cockatrice\Cockatrice\sound" "path" "$APPDATA\Cockatrice\sounds"
SectionEnd SectionEnd
Section "Start menu item" SecStartMenu Section "Start menu item" SecStartMenu
createDirectory "$SMPROGRAMS\Cockatrice" 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\Oracle.lnk" "$INSTDIR\oracle.exe"
createShortCut "$SMPROGRAMS\Cockatrice\Usermanual.lnk" "$INSTDIR\Usermanual.pdf"
SectionEnd SectionEnd
Section Uninstall Section Uninstall
RMDir /r "$INSTDIR\zonebg" SetShellVarContext all
RMDir /r "$INSTDIR\plugins" RMDir /r "$INSTDIR\zonebg"
RMDir /r "$INSTDIR\sounds" RMDir /r "$INSTDIR\plugins"
RMDir "$INSTDIR\decks" RMDir /r "$INSTDIR\sounds"
RMDir /r "$INSTDIR\pics\downloadedPics" RMDir /r "$INSTDIR\translations"
RMDir "$INSTDIR\pics" Delete "$INSTDIR\uninstall.exe"
Delete "$INSTDIR\uninstall.exe" Delete "$INSTDIR\cockatrice.exe"
Delete "$INSTDIR\cockatrice.exe" Delete "$INSTDIR\oracle.exe"
Delete "$INSTDIR\oracle.exe" Delete "$INSTDIR\Usermanual.pdf"
Delete "$INSTDIR\cards.xml" Delete "$INSTDIR\libprotobuf.lib"
Delete "$INSTDIR\libgcc_s_dw2-1.dll" Delete "$INSTDIR\Qt*.dll"
Delete "$INSTDIR\mingwm10.dll" Delete "$INSTDIR\icu*.dll"
Delete "$INSTDIR\QtCore4.dll" Delete "$INSTDIR\qt.conf"
Delete "$INSTDIR\QtGui4.dll" Delete "$INSTDIR\qdebug.txt"
Delete "$INSTDIR\QtNetwork4.dll" RMDir "$INSTDIR"
Delete "$INSTDIR\QtSvg4.dll"
Delete "$INSTDIR\QtXml4.dll"
RMDir "$INSTDIR"
RMDir /r "$SMPROGRAMS\Cockatrice" RMDir "$SMPROGRAMS\Cockatrice"
DeleteRegKey HKCU "Software\Cockatrice" DeleteRegKey HKCU "Software\Cockatrice"
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice" DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Cockatrice"
SectionEnd SectionEnd
LangString DESC_SecApplication ${LANG_ENGLISH} "Cockatrice program files" 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_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." LangString DESC_SecStartMenu ${LANG_ENGLISH} "Create start menu items for Cockatrice and Oracle."
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
!insertmacro MUI_DESCRIPTION_TEXT ${SecApplication} $(DESC_SecApplication) !insertmacro MUI_DESCRIPTION_TEXT ${SecApplication} $(DESC_SecApplication)
!insertmacro MUI_DESCRIPTION_TEXT ${SecUpdateConfig} $(DESC_SecUpdateConfig) !insertmacro MUI_DESCRIPTION_TEXT ${SecUpdateConfig} $(DESC_SecUpdateConfig)
!insertmacro MUI_DESCRIPTION_TEXT ${SecStartMenu} $(DESC_SecStartMenu) !insertmacro MUI_DESCRIPTION_TEXT ${SecStartMenu} $(DESC_SecStartMenu)
!insertmacro MUI_FUNCTION_DESCRIPTION_END !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> <RCC>
<qresource prefix="/" > <qresource prefix="/" >
<file alias="back.svg" >resources/back.svg</file> <file alias="back.svg" >resources/back.svg</file>
<file>resources/lock.svg</file>
<file>resources/icon_delete.svg</file> <file>resources/icon_delete.svg</file>
<file>resources/icon_tab_changed.svg</file> <file>resources/icon_tab_changed.svg</file>
<file>resources/icon_config_general.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_main2.svg</file>
<file>resources/phases/icon_phase_cleanup.svg</file> <file>resources/phases/icon_phase_cleanup.svg</file>
<file>resources/phases/icon_phase_nextturn.svg</file> <file>resources/phases/icon_phase_nextturn.svg</file>
<file>resources/icon_settings.svg</file>
<file>resources/hand.svg</file> <file>resources/hand.svg</file>
<file>resources/pencil.svg</file> <file>resources/pencil.svg</file>
<file>resources/icon_search.svg</file> <file>resources/icon_search.svg</file>
<file>resources/icon_clearsearch.svg</file> <file>resources/icon_clearsearch.svg</file>
<file>resources/icon_update.png</file> <file>resources/icon_update.png</file>
<file>resources/icon_view.svg</file>
<file>resources/hr.jpg</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/add_to_sideboard.svg</file>
<file>resources/decrement.svg</file> <file>resources/decrement.svg</file>
<file>resources/increment.svg</file> <file>resources/increment.svg</file>
@ -38,24 +41,19 @@
<file>resources/icon_conceded.svg</file> <file>resources/icon_conceded.svg</file>
<file>resources/icon_player.svg</file> <file>resources/icon_player.svg</file>
<file>resources/icon_spectator.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/male.svg</file>
<file>resources/genders/female.svg</file> <file>resources/genders/female.svg</file>
<file>resources/genders/unknown.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/ar.svg</file>
<file>resources/countries/at.svg</file> <file>resources/countries/at.svg</file>
<file>resources/countries/au.svg</file> <file>resources/countries/au.svg</file>
@ -63,16 +61,20 @@
<file>resources/countries/br.svg</file> <file>resources/countries/br.svg</file>
<file>resources/countries/by.svg</file> <file>resources/countries/by.svg</file>
<file>resources/countries/ca.svg</file> <file>resources/countries/ca.svg</file>
<file>resources/countries/cl.svg</file>
<file>resources/countries/cz.svg</file> <file>resources/countries/cz.svg</file>
<file>resources/countries/ch.svg</file> <file>resources/countries/ch.svg</file>
<file>resources/countries/cn.svg</file> <file>resources/countries/cn.svg</file>
<file>resources/countries/de.svg</file> <file>resources/countries/de.svg</file>
<file>resources/countries/dk.svg</file> <file>resources/countries/dk.svg</file>
<file>resources/countries/do.svg</file>
<file>resources/countries/es.svg</file> <file>resources/countries/es.svg</file>
<file>resources/countries/fi.svg</file> <file>resources/countries/fi.svg</file>
<file>resources/countries/fr.svg</file> <file>resources/countries/fr.svg</file>
<file>resources/countries/ge.svg</file>
<file>resources/countries/gr.svg</file> <file>resources/countries/gr.svg</file>
<file>resources/countries/gt.svg</file> <file>resources/countries/gt.svg</file>
<file>resources/countries/hr.svg</file>
<file>resources/countries/hu.svg</file> <file>resources/countries/hu.svg</file>
<file>resources/countries/ie.svg</file> <file>resources/countries/ie.svg</file>
<file>resources/countries/il.svg</file> <file>resources/countries/il.svg</file>
@ -85,6 +87,7 @@
<file>resources/countries/my.svg</file> <file>resources/countries/my.svg</file>
<file>resources/countries/nl.svg</file> <file>resources/countries/nl.svg</file>
<file>resources/countries/no.svg</file> <file>resources/countries/no.svg</file>
<file>resources/countries/nz.svg</file>
<file>resources/countries/pe.svg</file> <file>resources/countries/pe.svg</file>
<file>resources/countries/ph.svg</file> <file>resources/countries/ph.svg</file>
<file>resources/countries/pl.svg</file> <file>resources/countries/pl.svg</file>
@ -99,6 +102,7 @@
<file>resources/countries/ua.svg</file> <file>resources/countries/ua.svg</file>
<file>resources/countries/uk.svg</file> <file>resources/countries/uk.svg</file>
<file>resources/countries/us.svg</file> <file>resources/countries/us.svg</file>
<file>resources/countries/ve.svg</file>
<file>resources/countries/za.svg</file> <file>resources/countries/za.svg</file>
<file>resources/counters/w.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> #include <QDebug>
AbstractCardDragItem::AbstractCardDragItem(AbstractCardItem *_item, const QPointF &_hotSpot, AbstractCardDragItem *parentDrag) AbstractCardDragItem::AbstractCardDragItem(AbstractCardItem *_item, const QPointF &_hotSpot, AbstractCardDragItem *parentDrag)
: QGraphicsItem(), item(_item), hotSpot(_hotSpot) : QGraphicsItem(), item(_item), hotSpot(_hotSpot)
{ {
if (parentDrag) { if (parentDrag) {
parentDrag->addChildDrag(this); parentDrag->addChildDrag(this);
setZValue(2000000007 + hotSpot.x() * 1000000 + hotSpot.y() * 1000 + 1000); setZValue(2000000007 + hotSpot.x() * 1000000 + hotSpot.y() * 1000 + 1000);
} else { } else {
if ((hotSpot.x() < 0) || (hotSpot.y() < 0)) { if ((hotSpot.x() < 0) || (hotSpot.y() < 0)) {
qDebug() << "CardDragItem: coordinate overflow: x =" << hotSpot.x() << ", y =" << hotSpot.y(); qDebug() << "CardDragItem: coordinate overflow: x =" << hotSpot.x() << ", y =" << hotSpot.y();
hotSpot = QPointF(); hotSpot = QPointF();
} else if ((hotSpot.x() > CARD_WIDTH) || (hotSpot.y() > CARD_HEIGHT)) { } else if ((hotSpot.x() > CARD_WIDTH) || (hotSpot.y() > CARD_HEIGHT)) {
qDebug() << "CardDragItem: coordinate overflow: x =" << hotSpot.x() << ", y =" << hotSpot.y(); qDebug() << "CardDragItem: coordinate overflow: x =" << hotSpot.x() << ", y =" << hotSpot.y();
hotSpot = QPointF(CARD_WIDTH, CARD_HEIGHT); hotSpot = QPointF(CARD_WIDTH, CARD_HEIGHT);
} }
setCursor(Qt::ClosedHandCursor); setCursor(Qt::ClosedHandCursor);
setZValue(2000000007); setZValue(2000000007);
} }
if (item->getTapped()) 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)); 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() AbstractCardDragItem::~AbstractCardDragItem()
{ {
qDebug("CardDragItem destructor"); qDebug("CardDragItem destructor");
for (int i = 0; i < childDrags.size(); i++) for (int i = 0; i < childDrags.size(); i++)
delete childDrags[i]; delete childDrags[i];
} }
void AbstractCardDragItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) 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) void AbstractCardDragItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{ {
event->accept(); event->accept();
updatePosition(event->scenePos()); updatePosition(event->scenePos());
} }
void AbstractCardDragItem::addChildDrag(AbstractCardDragItem *child) void AbstractCardDragItem::addChildDrag(AbstractCardDragItem *child)
{ {
childDrags << child; childDrags << child;
} }

View file

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

View file

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

View file

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

View file

@ -1,79 +1,162 @@
#include "abstractclient.h" #include "abstractclient.h"
#include "protocol.h"
#include "protocol_items.h" #include "pending_command.h"
#include <QDebug> #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) 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() AbstractClient::~AbstractClient()
{ {
} }
void AbstractClient::processProtocolItem(ProtocolItem *item) void AbstractClient::processProtocolItem(const ServerMessage &item)
{ {
ProtocolResponse *response = qobject_cast<ProtocolResponse *>(item); switch (item.message_type()) {
if (response) { case ServerMessage::RESPONSE: {
CommandContainer *cmdCont = pendingCommands.value(response->getCmdId(), 0); const Response &response = item.response();
if (!cmdCont) const int cmdId = response.cmd_id();
return;
PendingCommand *pend = pendingCommands.value(cmdId, 0);
pendingCommands.remove(cmdCont->getCmdId()); if (!pend)
cmdCont->processResponse(response); return;
if (response->getReceiverMayDelete()) pendingCommands.remove(cmdId);
delete response;
cmdCont->deleteLater(); pend->processResponse(response);
pend->deleteLater();
return; break;
} }
case ServerMessage::SESSION_EVENT: {
GenericEvent *genericEvent = qobject_cast<GenericEvent *>(item); const SessionEvent &event = item.session_event();
if (genericEvent) { switch ((SessionEvent::SessionEventType) getPbExtension(event)) {
switch (genericEvent->getItemId()) { case SessionEvent::SERVER_IDENTIFICATION: emit serverIdentificationEventReceived(event.GetExtension(Event_ServerIdentification::ext)); break;
case ItemId_Event_ConnectionClosed: emit connectionClosedEventReceived(static_cast<Event_ConnectionClosed *>(item)); break; case SessionEvent::SERVER_MESSAGE: emit serverMessageEventReceived(event.GetExtension(Event_ServerMessage::ext)); break;
case ItemId_Event_ServerShutdown: emit serverShutdownEventReceived(static_cast<Event_ServerShutdown *>(item)); break; case SessionEvent::SERVER_SHUTDOWN: emit serverShutdownEventReceived(event.GetExtension(Event_ServerShutdown::ext)); break;
case ItemId_Event_AddToList: emit addToListEventReceived(static_cast<Event_AddToList *>(item)); break; case SessionEvent::CONNECTION_CLOSED: emit connectionClosedEventReceived(event.GetExtension(Event_ConnectionClosed::ext)); break;
case ItemId_Event_RemoveFromList: emit removeFromListEventReceived(static_cast<Event_RemoveFromList *>(item)); break; case SessionEvent::USER_MESSAGE: emit userMessageEventReceived(event.GetExtension(Event_UserMessage::ext)); break;
case ItemId_Event_UserJoined: emit userJoinedEventReceived(static_cast<Event_UserJoined *>(item)); break; case SessionEvent::LIST_ROOMS: emit listRoomsEventReceived(event.GetExtension(Event_ListRooms::ext)); break;
case ItemId_Event_UserLeft: emit userLeftEventReceived(static_cast<Event_UserLeft *>(item)); break; case SessionEvent::ADD_TO_LIST: emit addToListEventReceived(event.GetExtension(Event_AddToList::ext)); break;
case ItemId_Event_ServerMessage: emit serverMessageEventReceived(static_cast<Event_ServerMessage *>(item)); break; case SessionEvent::REMOVE_FROM_LIST: emit removeFromListEventReceived(event.GetExtension(Event_RemoveFromList::ext)); break;
case ItemId_Event_ListRooms: emit listRoomsEventReceived(static_cast<Event_ListRooms *>(item)); break; case SessionEvent::USER_JOINED: emit userJoinedEventReceived(event.GetExtension(Event_UserJoined::ext)); break;
case ItemId_Event_GameJoined: emit gameJoinedEventReceived(static_cast<Event_GameJoined *>(item)); break; case SessionEvent::USER_LEFT: emit userLeftEventReceived(event.GetExtension(Event_UserLeft::ext)); break;
case ItemId_Event_Message: emit messageEventReceived(static_cast<Event_Message *>(item)); 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;
if (genericEvent->getReceiverMayDelete()) default: break;
delete genericEvent; }
return; break;
} }
case ServerMessage::GAME_EVENT_CONTAINER: {
GameEventContainer *gameEventContainer = qobject_cast<GameEventContainer *>(item); emit gameEventContainerReceived(item.game_event_container());
if (gameEventContainer) { break;
emit gameEventContainerReceived(gameEventContainer); }
if (gameEventContainer->getReceiverMayDelete()) case ServerMessage::ROOM_EVENT: {
delete gameEventContainer; emit roomEventReceived(item.room_event());
return; break;
} }
}
RoomEvent *roomEvent = qobject_cast<RoomEvent *>(item);
if (roomEvent) {
emit roomEventReceived(roomEvent);
if (roomEvent->getReceiverMayDelete())
delete roomEvent;
return;
}
} }
void AbstractClient::setStatus(const ClientStatus _status) void AbstractClient::setStatus(const ClientStatus _status)
{ {
if (_status != status) { QMutexLocker locker(&clientMutex);
status = _status; if (_status != status) {
emit statusChanged(_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 #define ABSTRACTCLIENT_H
#include <QObject> #include <QObject>
#include "protocol_datastructures.h" #include <QVariant>
#include <QMutex>
#include "pb/response.pb.h"
#include "pb/serverinfo_user.pb.h"
class Command; class PendingCommand;
class CommandContainer;
class ProtocolItem;
class ProtocolResponse;
class TopLevelProtocolItem;
class CommandContainer; class CommandContainer;
class RoomEvent; class RoomEvent;
class GameEventContainer; class GameEventContainer;
class ServerMessage;
class Event_ServerIdentification;
class Event_AddToList; class Event_AddToList;
class Event_RemoveFromList; class Event_RemoveFromList;
class Event_UserJoined; class Event_UserJoined;
@ -19,57 +20,73 @@ class Event_UserLeft;
class Event_ServerMessage; class Event_ServerMessage;
class Event_ListRooms; class Event_ListRooms;
class Event_GameJoined; class Event_GameJoined;
class Event_Message; class Event_UserMessage;
class Event_ConnectionClosed; class Event_ConnectionClosed;
class Event_ServerShutdown; class Event_ServerShutdown;
class Event_ReplayAdded;
enum ClientStatus { enum ClientStatus {
StatusDisconnected, StatusDisconnected,
StatusDisconnecting, StatusDisconnecting,
StatusConnecting, StatusConnecting,
StatusAwaitingWelcome, StatusAwaitingWelcome,
StatusLoggingIn, StatusLoggingIn,
StatusLoggedIn, StatusLoggedIn
}; };
class AbstractClient : public QObject { class AbstractClient : public QObject {
Q_OBJECT Q_OBJECT
signals: signals:
void statusChanged(ClientStatus _status); void statusChanged(ClientStatus _status);
void serverError(ResponseCode resp);
// Room events
// Room events void roomEventReceived(const RoomEvent &event);
void roomEventReceived(RoomEvent *event); // Game events
// Game events void gameEventContainerReceived(const GameEventContainer &event);
void gameEventContainerReceived(GameEventContainer *event); // Session events
// Generic events void serverIdentificationEventReceived(const Event_ServerIdentification &event);
void connectionClosedEventReceived(Event_ConnectionClosed *event); void connectionClosedEventReceived(const Event_ConnectionClosed &event);
void serverShutdownEventReceived(Event_ServerShutdown *event); void serverShutdownEventReceived(const Event_ServerShutdown &event);
void addToListEventReceived(Event_AddToList *event); void addToListEventReceived(const Event_AddToList &event);
void removeFromListEventReceived(Event_RemoveFromList *event); void removeFromListEventReceived(const Event_RemoveFromList &event);
void userJoinedEventReceived(Event_UserJoined *event); void userJoinedEventReceived(const Event_UserJoined &event);
void userLeftEventReceived(Event_UserLeft *event); void userLeftEventReceived(const Event_UserLeft &event);
void serverMessageEventReceived(Event_ServerMessage *event); void serverMessageEventReceived(const Event_ServerMessage &event);
void listRoomsEventReceived(Event_ListRooms *event); void listRoomsEventReceived(const Event_ListRooms &event);
void gameJoinedEventReceived(Event_GameJoined *event); void gameJoinedEventReceived(const Event_GameJoined &event);
void messageEventReceived(Event_Message *event); void userMessageEventReceived(const Event_UserMessage &event);
void userInfoChanged(ServerInfo_User *userInfo); void userInfoChanged(const ServerInfo_User &userInfo);
void buddyListReceived(const QList<ServerInfo_User *> &buddyList); void buddyListReceived(const QList<ServerInfo_User> &buddyList);
void ignoreListReceived(const QList<ServerInfo_User *> &ignoreList); 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: protected slots:
void processProtocolItem(ProtocolItem *item); void processProtocolItem(const ServerMessage &item);
protected: protected:
QMap<int, CommandContainer *> pendingCommands; QMap<int, PendingCommand *> pendingCommands;
ClientStatus status; QString userName, password;
QString userName, password; void setStatus(ClientStatus _status);
void setStatus(ClientStatus _status); int getNewCmdId() { return nextCmdId++; }
virtual void sendCommandContainer(const CommandContainer &cont) = 0;
public: public:
AbstractClient(QObject *parent = 0); AbstractClient(QObject *parent = 0);
~AbstractClient(); ~AbstractClient();
ClientStatus getStatus() const { return status; } ClientStatus getStatus() const { QMutexLocker locker(&clientMutex); return status; }
virtual void sendCommand(Command *cmd); void sendCommand(const CommandContainer &cont);
virtual void sendCommandContainer(CommandContainer *cont) = 0; 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 "abstractcounter.h"
#include "player.h" #include "player.h"
#include "protocol_items.h"
#include <QPainter> #include <QPainter>
#include <QMenu> #include <QMenu>
#include <QAction> #include <QAction>
#include <QGraphicsSceneMouseEvent> #include <QGraphicsSceneMouseEvent>
#include <QGraphicsSceneHoverEvent> #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) 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 QT_VERSION < 0x050000
setAcceptsHoverEvents(true);
if (player->getLocal()) { #else
menu = new QMenu(name); setAcceptHoverEvents(true);
aSet = new QAction(this); #endif
connect(aSet, SIGNAL(triggered()), this, SLOT(setCounter()));
menu->addAction(aSet); if (player->getLocal()) {
menu->addSeparator(); menu = new QMenu(name);
for (int i = -10; i <= 10; ++i) aSet = new QAction(this);
if (i == 0) connect(aSet, SIGNAL(triggered()), this, SLOT(setCounter()));
menu->addSeparator(); menu->addAction(aSet);
else { menu->addSeparator();
QAction *aIncrement = new QAction(QString(i < 0 ? "%1" : "+%1").arg(i), this); for (int i = -10; i <= 10; ++i)
if (i == -1) if (i == 0)
aDec = aIncrement; menu->addSeparator();
else if (i == 1) else {
aInc = aIncrement; QAction *aIncrement = new QAction(QString(i < 0 ? "%1" : "+%1").arg(i), this);
aIncrement->setData(i); if (i == -1)
connect(aIncrement, SIGNAL(triggered()), this, SLOT(incrementCounter())); aDec = aIncrement;
menu->addAction(aIncrement); else if (i == 1)
} aInc = aIncrement;
} else aIncrement->setData(i);
menu = 0; connect(aIncrement, SIGNAL(triggered()), this, SLOT(incrementCounter()));
menu->addAction(aIncrement);
retranslateUi(); }
} else
menu = 0;
retranslateUi();
} }
AbstractCounter::~AbstractCounter() AbstractCounter::~AbstractCounter()
{ {
delete menu; delete menu;
} }
void AbstractCounter::delCounter() void AbstractCounter::delCounter()
{ {
if (dialogSemaphore) if (dialogSemaphore)
deleteAfterDialog = true; deleteAfterDialog = true;
else else
deleteLater(); deleteLater();
} }
void AbstractCounter::retranslateUi() void AbstractCounter::retranslateUi()
{ {
if (menu) { if (menu) {
aSet->setText(tr("&Set counter...")); aSet->setText(tr("&Set counter..."));
} }
} }
void AbstractCounter::setShortcutsActive() void AbstractCounter::setShortcutsActive()
{ {
if (name == "life") { if (name == "life") {
aSet->setShortcut(tr("Ctrl+L")); aSet->setShortcut(tr("Ctrl+L"));
aDec->setShortcut(tr("F11")); aDec->setShortcut(tr("F11"));
aInc->setShortcut(tr("F12")); aInc->setShortcut(tr("F12"));
} }
} }
void AbstractCounter::setShortcutsInactive() void AbstractCounter::setShortcutsInactive()
{ {
if (name == "life") { if (name == "life") {
aSet->setShortcut(QKeySequence()); aSet->setShortcut(QKeySequence());
aDec->setShortcut(QKeySequence()); aDec->setShortcut(QKeySequence());
aInc->setShortcut(QKeySequence()); aInc->setShortcut(QKeySequence());
} }
} }
void AbstractCounter::setValue(int _value) void AbstractCounter::setValue(int _value)
{ {
value = _value; value = _value;
update(); update();
} }
void AbstractCounter::mousePressEvent(QGraphicsSceneMouseEvent *event) void AbstractCounter::mousePressEvent(QGraphicsSceneMouseEvent *event)
{ {
if (event->button() == Qt::LeftButton) { if (event->button() == Qt::LeftButton) {
player->sendGameCommand(new Command_IncCounter(-1, id, 1)); Command_IncCounter cmd;
event->accept(); cmd.set_counter_id(id);
} else if (event->button() == Qt::RightButton) { cmd.set_delta(1);
player->sendGameCommand(new Command_IncCounter(-1, id, -1)); player->sendGameCommand(cmd);
event->accept(); event->accept();
} else if (event->button() == Qt::MidButton) { } else if (event->button() == Qt::RightButton) {
if (menu) Command_IncCounter cmd;
menu->exec(event->screenPos()); cmd.set_counter_id(id);
event->accept(); cmd.set_delta(-1);
} else player->sendGameCommand(cmd);
event->ignore(); event->accept();
} else if (event->button() == Qt::MidButton) {
if (menu)
menu->exec(event->screenPos());
event->accept();
} else
event->ignore();
} }
void AbstractCounter::hoverEnterEvent(QGraphicsSceneHoverEvent * /*event*/) void AbstractCounter::hoverEnterEvent(QGraphicsSceneHoverEvent * /*event*/)
{ {
hovered = true; hovered = true;
update(); update();
} }
void AbstractCounter::hoverLeaveEvent(QGraphicsSceneHoverEvent * /*event*/) void AbstractCounter::hoverLeaveEvent(QGraphicsSceneHoverEvent * /*event*/)
{ {
hovered = false; hovered = false;
update(); update();
} }
void AbstractCounter::incrementCounter() void AbstractCounter::incrementCounter()
{ {
int delta = static_cast<QAction *>(sender())->data().toInt(); const int delta = static_cast<QAction *>(sender())->data().toInt();
player->sendGameCommand(new Command_IncCounter(-1, id, delta)); Command_IncCounter cmd;
cmd.set_counter_id(id);
cmd.set_delta(delta);
player->sendGameCommand(cmd);
} }
void AbstractCounter::setCounter() void AbstractCounter::setCounter()
{ {
bool ok; bool ok;
dialogSemaphore = true; dialogSemaphore = true;
int newValue = QInputDialog::getInteger(0, tr("Set counter"), tr("New value for counter '%1':").arg(name), value, -2000000000, 2000000000, 1, &ok); int newValue =
if (deleteAfterDialog) { #if QT_VERSION < 0x050000
deleteLater(); QInputDialog::getInteger(
return; #else
} QInputDialog::getInt(
dialogSemaphore = false; #endif
if (ok) 0, tr("Set counter"), tr("New value for counter '%1':").arg(name), value, -2000000000, 2000000000, 1, &ok);
player->sendGameCommand(new Command_SetCounter(-1, id, newValue)); 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 QAction;
class AbstractCounter : public QObject, public QGraphicsItem { class AbstractCounter : public QObject, public QGraphicsItem {
Q_OBJECT Q_OBJECT
Q_INTERFACES(QGraphicsItem)
protected: protected:
Player *player; Player *player;
int id; int id;
QString name; QString name;
int value; int value;
bool hovered; bool hovered;
void mousePressEvent(QGraphicsSceneMouseEvent *event); void mousePressEvent(QGraphicsSceneMouseEvent *event);
void hoverEnterEvent(QGraphicsSceneHoverEvent *event); void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
private: private:
QAction *aSet, *aDec, *aInc; QAction *aSet, *aDec, *aInc;
QMenu *menu; QMenu *menu;
bool dialogSemaphore, deleteAfterDialog; bool dialogSemaphore, deleteAfterDialog;
bool shownInCounterArea; bool shownInCounterArea;
private slots: private slots:
void incrementCounter(); void incrementCounter();
void setCounter(); void setCounter();
public: public:
AbstractCounter(Player *_player, int _id, const QString &_name, bool _shownInCounterArea, int _value, QGraphicsItem *parent = 0); AbstractCounter(Player *_player, int _id, const QString &_name, bool _shownInCounterArea, int _value, QGraphicsItem *parent = 0);
~AbstractCounter(); ~AbstractCounter();
QMenu *getMenu() const { return menu; } QMenu *getMenu() const { return menu; }
void retranslateUi(); void retranslateUi();
int getId() const { return id; } int getId() const { return id; }
QString getName() const { return name; } QString getName() const { return name; }
bool getShownInCounterArea() const { return shownInCounterArea; } bool getShownInCounterArea() const { return shownInCounterArea; }
int getValue() const { return value; } int getValue() const { return value; }
void setValue(int _value); void setValue(int _value);
void delCounter(); void delCounter();
void setShortcutsActive(); void setShortcutsActive();
void setShortcutsInactive(); void setShortcutsInactive();
}; };
#endif #endif

View file

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

View file

@ -4,20 +4,21 @@
#include <QGraphicsItem> #include <QGraphicsItem>
enum GraphicsItemType { enum GraphicsItemType {
typeCard = QGraphicsItem::UserType + 1, typeCard = QGraphicsItem::UserType + 1,
typeCardDrag = QGraphicsItem::UserType + 2, typeCardDrag = QGraphicsItem::UserType + 2,
typeZone = QGraphicsItem::UserType + 3, typeZone = QGraphicsItem::UserType + 3,
typePlayerTarget = QGraphicsItem::UserType + 4, typePlayerTarget = QGraphicsItem::UserType + 4,
typeDeckViewCardContainer = QGraphicsItem::UserType + 5, typeDeckViewCardContainer = QGraphicsItem::UserType + 5,
typeOther = QGraphicsItem::UserType + 6 typeOther = QGraphicsItem::UserType + 6
}; };
class AbstractGraphicsItem : public QObject, public QGraphicsItem { class AbstractGraphicsItem : public QObject, public QGraphicsItem {
Q_OBJECT Q_OBJECT
Q_INTERFACES(QGraphicsItem)
protected: 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: public:
AbstractGraphicsItem(QGraphicsItem *parent = 0) : QObject(), QGraphicsItem(parent) { } AbstractGraphicsItem(QGraphicsItem *parent = 0) : QObject(), QGraphicsItem(parent) { }
}; };
#endif #endif

View file

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

View file

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

View file

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

View file

@ -8,27 +8,28 @@ class Player;
class ArrowItem; class ArrowItem;
class ArrowTarget : public AbstractGraphicsItem { class ArrowTarget : public AbstractGraphicsItem {
Q_OBJECT
protected: protected:
Player *owner; Player *owner;
private: private:
bool beingPointedAt; bool beingPointedAt;
QList<ArrowItem *> arrowsFrom, arrowsTo; QList<ArrowItem *> arrowsFrom, arrowsTo;
public: public:
ArrowTarget(Player *_owner, QGraphicsItem *parent = 0); ArrowTarget(Player *_owner, QGraphicsItem *parent = 0);
~ArrowTarget(); ~ArrowTarget();
Player *getOwner() const { return owner; } Player *getOwner() const { return owner; }
void setBeingPointedAt(bool _beingPointedAt); void setBeingPointedAt(bool _beingPointedAt);
bool getBeingPointedAt() const { return beingPointedAt; } bool getBeingPointedAt() const { return beingPointedAt; }
const QList<ArrowItem *> &getArrowsFrom() const { return arrowsFrom; } const QList<ArrowItem *> &getArrowsFrom() const { return arrowsFrom; }
void addArrowFrom(ArrowItem *arrow) { arrowsFrom.append(arrow); } void addArrowFrom(ArrowItem *arrow) { arrowsFrom.append(arrow); }
void removeArrowFrom(ArrowItem *arrow) { arrowsFrom.removeAt(arrowsFrom.indexOf(arrow)); } void removeArrowFrom(ArrowItem *arrow) { arrowsFrom.removeAt(arrowsFrom.indexOf(arrow)); }
const QList<ArrowItem *> &getArrowsTo() const { return arrowsTo; } const QList<ArrowItem *> &getArrowsTo() const { return arrowsTo; }
void addArrowTo(ArrowItem *arrow) { arrowsTo.append(arrow); } void addArrowTo(ArrowItem *arrow) { arrowsTo.append(arrow); }
void removeArrowTo(ArrowItem *arrow) { arrowsTo.removeAt(arrowsTo.indexOf(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; 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 *> { class CardSet : public QList<CardInfo *> {
private: private:
QString shortName, longName; QString shortName, longName;
unsigned int sortKey; unsigned int sortKey;
public: public:
CardSet(const QString &_shortName = QString(), const QString &_longName = QString()); CardSet(const QString &_shortName = QString(), const QString &_longName = QString());
QString getShortName() const { return shortName; } QString getCorrectedShortName() const;
QString getLongName() const { return longName; } QString getShortName() const { return shortName; }
int getSortKey() const { return sortKey; } QString getLongName() const { return longName; }
void setSortKey(unsigned int _sortKey); int getSortKey() const { return sortKey; }
void updateSortKey(); void setSortKey(unsigned int _sortKey);
void updateSortKey();
}; };
class SetList : public QList<CardSet *> { class SetList : public QList<CardSet *> {
private: private:
class CompareFunctor; class CompareFunctor;
public: public:
void sortByKey(); void sortByKey();
}; };
class PictureToLoad { class PictureToLoad {
private: private:
CardInfo *card; CardInfo *card;
bool stripped; bool stripped;
SetList sortedSets; SetList sortedSets;
int setIndex; int setIndex;
bool hq; bool hq;
public: public:
PictureToLoad(CardInfo *_card = 0, bool _stripped = false, bool _hq = true); PictureToLoad(CardInfo *_card = 0, bool _stripped = false, bool _hq = true);
CardInfo *getCard() const { return card; } CardInfo *getCard() const { return card; }
bool getStripped() const { return stripped; } bool getStripped() const { return stripped; }
QString getSetName() const { return sortedSets[setIndex]->getShortName(); } QString getSetName() const;
bool nextSet(); bool nextSet();
bool getHq() const { return hq; }
bool getHq() const { return hq; } void setHq(bool _hq) { hq = _hq; }
void setHq(bool _hq) { hq = _hq; }
}; };
class PictureLoader : public QObject { class PictureLoader : public QObject {
Q_OBJECT Q_OBJECT
private: private:
QString _picsPath; QString _picsPath;
QList<PictureToLoad> loadQueue; QList<PictureToLoad> loadQueue;
QMutex mutex; QMutex mutex;
QNetworkAccessManager *networkManager; QNetworkAccessManager *networkManager;
QList<PictureToLoad> cardsToDownload; QList<PictureToLoad> cardsToDownload;
PictureToLoad cardBeingDownloaded; PictureToLoad cardBeingDownloaded;
bool picDownload, downloadRunning, loadQueueRunning; bool picDownload, picDownloadHq, downloadRunning, loadQueueRunning;
void startNextPicDownload(); void startNextPicDownload();
QString getPicUrl(CardInfo* card);
public: public:
PictureLoader(QObject *parent = 0); PictureLoader(const QString &__picsPath, bool _picDownload, bool _picDownloadHq, QObject *parent = 0);
void setPicsPath(const QString &path); ~PictureLoader();
void setPicDownload(bool _picDownload); void setPicsPath(const QString &path);
void loadImage(CardInfo *card, bool stripped); void setPicDownload(bool _picDownload);
void setPicDownloadHq(bool _picDownloadHq);
void loadImage(CardInfo *card, bool stripped);
private slots: private slots:
void picDownloadFinished(QNetworkReply *reply); void picDownloadFinished(QNetworkReply *reply);
public slots: public slots:
void processLoadQueue(); void processLoadQueue();
signals: signals:
void startLoadQueue(); void startLoadQueue();
void imageLoaded(CardInfo *card, const QImage &image); 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);
}; };
class CardInfo : public QObject { class CardInfo : public QObject {
Q_OBJECT Q_OBJECT
private: private:
CardDatabase *db; CardDatabase *db;
QString name; QString name;
SetList sets;
QString manacost; /*
QString cardtype; * The name without punctuation or capitalization, for better card tag name
QString powtough; * recognition.
QString text; */
QStringList colors; QString simpleName;
int loyalty;
QMap<QString, QString> picURLs, picURLsHq, picURLsSt; bool isToken;
bool cipt; SetList sets;
int tableRow; QString manacost;
QPixmap *pixmap; QString cardtype;
QMap<int, QPixmap *> scaledPixmapCache; QString powtough;
QString text;
QStringList colors;
int loyalty;
QStringMap customPicURLs, customPicURLsHq;
MuidMap muIds;
bool cipt;
int tableRow;
QPixmap *pixmap;
QMap<int, QPixmap *> scaledPixmapCache;
public: public:
CardInfo(CardDatabase *_db, CardInfo(CardDatabase *_db,
const QString &_name = QString(), const QString &_name = QString(),
const QString &_manacost = QString(), bool _isToken = false,
const QString &_cardtype = QString(), const QString &_manacost = QString(),
const QString &_powtough = QString(), const QString &_cardtype = QString(),
const QString &_text = QString(), const QString &_powtough = QString(),
const QStringList &_colors = QStringList(), const QString &_text = QString(),
int _loyalty = 0, const QStringList &_colors = QStringList(),
bool cipt = false, int _loyalty = 0,
int _tableRow = 0, bool _cipt = false,
const SetList &_sets = SetList(), int _tableRow = 0,
const QStringMap &_picURLs = QStringMap(), const SetList &_sets = SetList(),
const QStringMap &_picURLsHq = QStringMap(), const QStringMap &_customPicURLs = QStringMap(),
const QStringMap &_picURLsSt = QStringMap()); const QStringMap &_customPicURLsHq = QStringMap(),
~CardInfo(); MuidMap muids = MuidMap());
const QString &getName() const { return name; } ~CardInfo();
const SetList &getSets() const { return sets; } const QString &getName() const { return name; }
const QString &getManaCost() const { return manacost; } bool getIsToken() const { return isToken; }
const QString &getCardType() const { return cardtype; } const SetList &getSets() const { return sets; }
const QString &getPowTough() const { return powtough; } const QString &getManaCost() const { return manacost; }
const QString &getText() const { return text; } const QString &getCardType() const { return cardtype; }
const int &getLoyalty() const { return loyalty; } const QString &getPowTough() const { return powtough; }
bool getCipt() const { return cipt; } const QString &getText() const { return text; }
void setText(const QString &_text) { text = _text; } const int &getLoyalty() const { return loyalty; }
const QStringList &getColors() const { return colors; } bool getCipt() const { return cipt; }
QString getPicURL(const QString &set) const { return picURLs.value(set); } void setManaCost(const QString &_manaCost) { manacost = _manaCost; emit cardInfoChanged(this); }
QString getPicURLHq(const QString &set) const { return picURLsHq.value(set); } void setCardType(const QString &_cardType) { cardtype = _cardType; emit cardInfoChanged(this); }
QString getPicURLSt(const QString &set) const { return picURLsSt.value(set); } void setPowTough(const QString &_powTough) { powtough = _powTough; emit cardInfoChanged(this); }
QString getPicURL() const; void setText(const QString &_text) { text = _text; emit cardInfoChanged(this); }
const QMap<QString, QString> &getPicURLs() const { return picURLs; } void setColors(const QStringList &_colors) { colors = _colors; emit cardInfoChanged(this); }
QString getMainCardType() const; const QStringList &getColors() const { return colors; }
QString getCorrectedName() const; QString getCustomPicURL(const QString &set) const { return customPicURLs.value(set); }
int getTableRow() const { return tableRow; } QString getCustomPicURLHq(const QString &set) const { return customPicURLsHq.value(set); }
void setTableRow(int _tableRow) { tableRow = _tableRow; } int getMuId(const QString &set) const { return muIds.value(set); }
void setLoyalty(int _loyalty) { loyalty = _loyalty; } QString getMainCardType() const;
void setPicURL(const QString &_set, const QString &_picURL) { picURLs.insert(_set, _picURL); } QString getCorrectedName() const;
void setPicURLHq(const QString &_set, const QString &_picURL) { picURLsHq.insert(_set, _picURL); } int getTableRow() const { return tableRow; }
void setPicURLSt(const QString &_set, const QString &_picURL) { picURLsSt.insert(_set, _picURL); } void setTableRow(int _tableRow) { tableRow = _tableRow; }
void addToSet(CardSet *set); void setLoyalty(int _loyalty) { loyalty = _loyalty; emit cardInfoChanged(this); }
QPixmap *loadPixmap(); void setCustomPicURL(const QString &_set, const QString &_customPicURL) { customPicURLs.insert(_set, _customPicURL); }
QPixmap *getPixmap(QSize size); void setCustomPicURLHq(const QString &_set, const QString &_customPicURL) { customPicURLsHq.insert(_set, _customPicURL); }
void clearPixmapCache(); void setMuId(const QString &_set, const int &_muId) { muIds.insert(_set, _muId); }
void clearPixmapCacheMiss(); void addToSet(CardSet *set);
void imageLoaded(const QImage &image); 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: public slots:
void updatePixmapCache(); void updatePixmapCache();
signals: 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 { class CardDatabase : public QObject {
Q_OBJECT Q_OBJECT
protected: protected:
QHash<QString, CardInfo *> cardHash; /*
QHash<QString, CardSet *> setHash; * The cards, indexed by name.
bool loadSuccess; */
CardInfo *noCard; CardNameMap cards;
PictureLoadingThread *loadingThread;
/**
* 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: private:
void loadCardsFromXml(QXmlStreamReader &xml); static const int versionNeeded;
void loadSetsFromXml(QXmlStreamReader &xml); void loadCardsFromXml(QXmlStreamReader &xml);
void loadSetsFromXml(QXmlStreamReader &xml);
CardInfo *getCardFromMap(CardNameMap &cardMap, const QString &cardName, bool createIfNotFound);
public: public:
CardDatabase(QObject *parent = 0); CardDatabase(QObject *parent = 0);
~CardDatabase(); ~CardDatabase();
void clear(); void clear();
CardInfo *getCard(const QString &cardName = QString()); void addCard(CardInfo *card);
CardSet *getSet(const QString &setName); void removeCard(CardInfo *card);
QList<CardInfo *> getCardList() const { return cardHash.values(); } CardInfo *getCard(const QString &cardName = QString(), bool createIfNotFound = true);
SetList getSetList() const;
bool loadFromFile(const QString &fileName); /*
bool saveToFile(const QString &fileName); * Get a card by its simple name. The name will be simplified in this
QStringList getAllColors() const; * function, so you don't need to simplify it beforehand.
QStringList getAllMainCardTypes() const; */
bool getLoadSuccess() const { return loadSuccess; } CardInfo *getCardBySimpleName(const QString &cardName = QString(), bool createIfNotFound = true);
void cacheCardPixmaps(const QStringList &cardNames);
void loadImage(CardInfo *card); 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: public slots:
void clearPixmapCache(); void clearPixmapCache();
bool loadCardDatabase(const QString &path); LoadStatus loadCardDatabase(const QString &path, bool tokens = false);
bool loadCardDatabase();
private slots: private slots:
void imageLoaded(CardInfo *card, QImage image); void imageLoaded(CardInfo *card, QImage image);
void picDownloadChanged(); void picDownloadChanged();
void picsPathChanged(); void picDownloadHqChanged();
void picsPathChanged();
void loadCardDatabase();
void loadTokenDatabase();
signals: signals:
void cardListChanged(); void cardListChanged();
void cardAdded(CardInfo *card);
void cardRemoved(CardInfo *card);
}; };
#endif #endif

View file

@ -1,114 +1,180 @@
#include "carddatabasemodel.h" #include "carddatabasemodel.h"
#include "filtertree.h"
CardDatabaseModel::CardDatabaseModel(CardDatabase *_db, QObject *parent) CardDatabaseModel::CardDatabaseModel(CardDatabase *_db, QObject *parent)
: QAbstractListModel(parent), db(_db) : QAbstractListModel(parent), db(_db)
{ {
connect(db, SIGNAL(cardListChanged()), this, SLOT(updateCardList())); connect(db, SIGNAL(cardListChanged()), this, SLOT(updateCardList()));
cardList = db->getCardList(); connect(db, SIGNAL(cardAdded(CardInfo *)), this, SLOT(cardAdded(CardInfo *)));
connect(db, SIGNAL(cardRemoved(CardInfo *)), this, SLOT(cardRemoved(CardInfo *)));
updateCardList();
} }
CardDatabaseModel::~CardDatabaseModel() CardDatabaseModel::~CardDatabaseModel()
{ {
} }
int CardDatabaseModel::rowCount(const QModelIndex &/*parent*/) const int CardDatabaseModel::rowCount(const QModelIndex &/*parent*/) const
{ {
return cardList.size(); return cardList.size();
} }
int CardDatabaseModel::columnCount(const QModelIndex &/*parent*/) const int CardDatabaseModel::columnCount(const QModelIndex &/*parent*/) const
{ {
return 5; return 5;
} }
QVariant CardDatabaseModel::data(const QModelIndex &index, int role) const QVariant CardDatabaseModel::data(const QModelIndex &index, int role) const
{ {
if (!index.isValid()) if (!index.isValid())
return QVariant(); return QVariant();
if ((index.row() >= cardList.size()) || (index.column() >= 5)) if ((index.row() >= cardList.size()) || (index.column() >= 5))
return QVariant(); return QVariant();
if (role != Qt::DisplayRole) if (role != Qt::DisplayRole)
return QVariant(); return QVariant();
CardInfo *card = cardList.at(index.row()); CardInfo *card = cardList.at(index.row());
switch (index.column()){ switch (index.column()){
case 0: return card->getName(); case 0: return card->getName();
case 1: { case 1: {
QStringList setList; QStringList setList;
const QList<CardSet *> &sets = card->getSets(); const QList<CardSet *> &sets = card->getSets();
for (int i = 0; i < sets.size(); i++) for (int i = 0; i < sets.size(); i++)
setList << sets[i]->getShortName(); setList << sets[i]->getShortName();
return setList.join(", "); return setList.join(", ");
} }
case 2: return card->getManaCost(); case 2: return card->getManaCost();
case 3: return card->getCardType(); case 3: return card->getCardType();
case 4: return card->getPowTough(); case 4: return card->getPowTough();
default: return QVariant(); default: return QVariant();
} }
} }
QVariant CardDatabaseModel::headerData(int section, Qt::Orientation orientation, int role) const QVariant CardDatabaseModel::headerData(int section, Qt::Orientation orientation, int role) const
{ {
if (role != Qt::DisplayRole) if (role != Qt::DisplayRole)
return QVariant(); return QVariant();
if (orientation != Qt::Horizontal) if (orientation != Qt::Horizontal)
return QVariant(); return QVariant();
switch (section) { switch (section) {
case 0: return QString(tr("Name")); case 0: return QString(tr("Name"));
case 1: return QString(tr("Sets")); case 1: return QString(tr("Sets"));
case 2: return QString(tr("Mana cost")); case 2: return QString(tr("Mana cost"));
case 3: return QString(tr("Card type")); case 3: return QString(tr("Card type"));
case 4: return QString(tr("P/T")); case 4: return QString(tr("P/T"));
default: return QVariant(); default: return QVariant();
} }
} }
void CardDatabaseModel::updateCardList() void CardDatabaseModel::updateCardList()
{ {
cardList = db->getCardList(); beginResetModel();
reset();
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) CardDatabaseDisplayModel::CardDatabaseDisplayModel(QObject *parent)
: QSortFilterProxyModel(parent) : QSortFilterProxyModel(parent),
isToken(ShowAll)
{ {
setFilterCaseSensitivity(Qt::CaseInsensitive); filterTree = NULL;
setSortCaseSensitivity(Qt::CaseInsensitive); setFilterCaseSensitivity(Qt::CaseInsensitive);
setSortCaseSensitivity(Qt::CaseInsensitive);
} }
bool CardDatabaseDisplayModel::filterAcceptsRow(int sourceRow, const QModelIndex & /*sourceParent*/) const bool CardDatabaseDisplayModel::filterAcceptsRow(int sourceRow, const QModelIndex & /*sourceParent*/) const
{ {
CardInfo *info = static_cast<CardDatabaseModel *>(sourceModel())->getCard(sourceRow); CardInfo const *info = static_cast<CardDatabaseModel *>(sourceModel())->getCard(sourceRow);
if (((isToken == ShowTrue) && !info->getIsToken()) || ((isToken == ShowFalse) && info->getIsToken()))
if (!cardNameBeginning.isEmpty()) return false;
if (!info->getName().startsWith(cardNameBeginning, Qt::CaseInsensitive))
return false; if (!cardNameBeginning.isEmpty())
if (!info->getName().startsWith(cardNameBeginning, Qt::CaseInsensitive))
if (!cardName.isEmpty()) return false;
if (!info->getName().contains(cardName, Qt::CaseInsensitive))
return false; if (!cardName.isEmpty())
if (!info->getName().contains(cardName, Qt::CaseInsensitive))
if (!cardText.isEmpty()) return false;
if (!info->getText().contains(cardText, Qt::CaseInsensitive))
return false; if (!cardNameSet.isEmpty())
if (!cardNameSet.contains(info->getName()))
if (!cardColors.isEmpty()) return false;
if (QSet<QString>::fromList(info->getColors()).intersect(cardColors).isEmpty() && !(info->getColors().isEmpty() && cardColors.contains("X")))
return false; if (!cardText.isEmpty())
if (!info->getText().contains(cardText, Qt::CaseInsensitive))
if (!cardTypes.isEmpty()) return false;
if (!cardTypes.contains(info->getMainCardType()))
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() void CardDatabaseDisplayModel::clearSearch()
{ {
cardName.clear(); cardName.clear();
cardText.clear(); cardText.clear();
cardTypes.clear(); cardTypes.clear();
cardColors.clear(); cardColors.clear();
invalidateFilter(); 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 <QSet>
#include "carddatabase.h" #include "carddatabase.h"
class FilterTree;
class CardDatabaseModel : public QAbstractListModel { class CardDatabaseModel : public QAbstractListModel {
Q_OBJECT Q_OBJECT
public: public:
CardDatabaseModel(CardDatabase *_db, QObject *parent = 0); CardDatabaseModel(CardDatabase *_db, QObject *parent = 0);
~CardDatabaseModel(); ~CardDatabaseModel();
int rowCount(const QModelIndex &parent = QModelIndex()) const; int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const; int columnCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role) const; QVariant data(const QModelIndex &index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
CardInfo *getCard(int index) const { return cardList[index]; } CardDatabase *getDatabase() const { return db; }
CardInfo *getCard(int index) const { return cardList[index]; }
private: private:
QList<CardInfo *> cardList; QList<CardInfo *> cardList;
CardDatabase *db; CardDatabase *db;
private slots: private slots:
void updateCardList(); void updateCardList();
void cardAdded(CardInfo *card);
void cardRemoved(CardInfo *card);
void cardInfoChanged(CardInfo *card);
}; };
class CardDatabaseDisplayModel : public QSortFilterProxyModel { class CardDatabaseDisplayModel : public QSortFilterProxyModel {
Q_OBJECT Q_OBJECT
private:
QString cardNameBeginning, cardName, cardText;
QSet<QString> cardTypes, cardColors;
public: public:
CardDatabaseDisplayModel(QObject *parent = 0); enum FilterBool { ShowTrue, ShowFalse, ShowAll };
void setCardNameBeginning(const QString &_beginning) { cardNameBeginning = _beginning; invalidate(); } private:
void setCardName(const QString &_cardName) { cardName = _cardName; invalidate(); } FilterBool isToken;
void setCardText(const QString &_cardText) { cardText = _cardText; invalidate(); } QString cardNameBeginning, cardName, cardText;
void setCardTypes(const QSet<QString> &_cardTypes) { cardTypes = _cardTypes; invalidate(); } QSet<QString> cardNameSet, cardTypes, cardColors;
void setCardColors(const QSet<QString> &_cardColors) { cardColors = _cardColors; invalidate(); } FilterTree *filterTree;
void clearSearch(); 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: protected:
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
private slots:
void filterTreeChanged();
}; };
#endif #endif

View file

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

View file

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

View file

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

View file

@ -8,619 +8,385 @@
#include "carddragitem.h" #include "carddragitem.h"
#include "carddatabase.h" #include "carddatabase.h"
#include "cardzone.h" #include "cardzone.h"
#include "zoneviewzone.h"
#include "tablezone.h" #include "tablezone.h"
#include "player.h" #include "player.h"
#include "arrowitem.h" #include "arrowitem.h"
#include "main.h" #include "main.h"
#include "protocol_datastructures.h"
#include "settingscache.h" #include "settingscache.h"
#include "tab_game.h" #include "tab_game.h"
#include "pb/serverinfo_card.pb.h"
CardItem::CardItem(Player *_owner, const QString &_name, int _cardid, bool _revealedCard, QGraphicsItem *parent) 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); owner->addCard(this);
aTap = new QAction(this); cardMenu = new QMenu;
aTap->setData(0); ptMenu = new QMenu;
connect(aTap, SIGNAL(triggered()), this, SLOT(cardMenuAction())); moveMenu = new QMenu;
aUntap = new QAction(this);
aUntap->setData(1); retranslateUi();
connect(aUntap, SIGNAL(triggered()), this, SLOT(cardMenuAction())); emit updateCardMenu(this);
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();
} }
CardItem::~CardItem() CardItem::~CardItem()
{ {
prepareDelete(); prepareDelete();
delete cardMenu; if (scene())
cardMenu = 0; static_cast<GameScene *>(scene())->unregisterAnimationItem(this);
delete moveMenu;
moveMenu = 0; delete cardMenu;
delete ptMenu;
deleteDragItem(); delete moveMenu;
deleteDragItem();
} }
void CardItem::prepareDelete() void CardItem::prepareDelete()
{ {
if (owner) { if (owner) {
if (owner->getCardMenu() == cardMenu) if (owner->getCardMenu() == cardMenu) {
owner->setCardMenu(0); owner->setCardMenu(0);
owner = 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); 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 (attachedTo) {
} attachedTo->removeAttachedCard(this);
attachedTo = 0;
}
} }
void CardItem::deleteLater() void CardItem::deleteLater()
{ {
prepareDelete(); prepareDelete();
AbstractCardItem::deleteLater(); AbstractCardItem::deleteLater();
} }
void CardItem::setZone(CardZone *_zone) void CardItem::setZone(CardZone *_zone)
{ {
zone = _zone; zone = _zone;
updateCardMenu(); emit updateCardMenu(this);
}
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);
}
} }
void CardItem::retranslateUi() void CardItem::retranslateUi()
{ {
aPlay->setText(tr("&Play")); moveMenu->setTitle(tr("&Move to"));
aHide->setText(tr("&Hide")); ptMenu->setTitle(tr("&Power / toughness"));
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"));
} }
void CardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) void CardItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{ {
painter->save(); painter->save();
AbstractCardItem::paint(painter, option, widget); AbstractCardItem::paint(painter, option, widget);
int i = 0; int i = 0;
QMapIterator<int, int> counterIterator(counters); QMapIterator<int, int> counterIterator(counters);
while (counterIterator.hasNext()) { while (counterIterator.hasNext()) {
counterIterator.next(); counterIterator.next();
QColor color; QColor color;
color.setHsv(counterIterator.key() * 60, 150, 255); color.setHsv(counterIterator.key() * 60, 150, 255);
paintNumberEllipse(counterIterator.value(), 14, color, i, counters.size(), painter); paintNumberEllipse(counterIterator.value(), 14, color, i, counters.size(), painter);
++i; ++i;
} }
QSizeF translatedSize = getTranslatedSize(painter); QSizeF translatedSize = getTranslatedSize(painter);
qreal scaleFactor = translatedSize.width() / boundingRect().width(); qreal scaleFactor = translatedSize.width() / boundingRect().width();
if (!pt.isEmpty()) { if (!pt.isEmpty()) {
painter->save(); painter->save();
transformPainter(painter, translatedSize, tapAngle); transformPainter(painter, translatedSize, tapAngle);
painter->setBackground(Qt::black); painter->setBackground(Qt::black);
painter->setBackgroundMode(Qt::OpaqueMode); painter->setBackgroundMode(Qt::OpaqueMode);
painter->setPen(Qt::white); 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->drawText(QRectF(4 * scaleFactor, 4 * scaleFactor, translatedSize.width() - 8 * scaleFactor, translatedSize.height() - 8 * scaleFactor), Qt::AlignRight | Qt::AlignBottom, pt);
painter->restore(); painter->restore();
} }
if (!annotation.isEmpty()) { if (!annotation.isEmpty()) {
painter->save(); painter->save();
transformPainter(painter, translatedSize, tapAngle); transformPainter(painter, translatedSize, tapAngle);
painter->setBackground(Qt::black); painter->setBackground(Qt::black);
painter->setBackgroundMode(Qt::OpaqueMode); painter->setBackgroundMode(Qt::OpaqueMode);
painter->setPen(Qt::white); 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->drawText(QRectF(4 * scaleFactor, 4 * scaleFactor, translatedSize.width() - 8 * scaleFactor, translatedSize.height() - 8 * scaleFactor), Qt::AlignCenter | Qt::TextWrapAnywhere, annotation);
painter->restore(); painter->restore();
} }
if (getBeingPointedAt()) if (getBeingPointedAt())
painter->fillRect(boundingRect(), QBrush(QColor(255, 0, 0, 100))); painter->fillRect(boundingRect(), QBrush(QColor(255, 0, 0, 100)));
painter->restore(); painter->restore();
} }
void CardItem::setAttacking(bool _attacking) void CardItem::setAttacking(bool _attacking)
{ {
attacking = _attacking; attacking = _attacking;
update(); update();
}
void CardItem::setFaceDown(bool _facedown)
{
facedown = _facedown;
if (facedown)
setName(QString());
update();
} }
void CardItem::setCounter(int _id, int _value) void CardItem::setCounter(int _id, int _value)
{ {
if (_value) if (_value)
counters.insert(_id, _value); counters.insert(_id, _value);
else else
counters.remove(_id); counters.remove(_id);
update(); update();
} }
void CardItem::setAnnotation(const QString &_annotation) void CardItem::setAnnotation(const QString &_annotation)
{ {
annotation = _annotation; annotation = _annotation;
update(); update();
} }
void CardItem::setDoesntUntap(bool _doesntUntap) void CardItem::setDoesntUntap(bool _doesntUntap)
{ {
doesntUntap = _doesntUntap; doesntUntap = _doesntUntap;
} }
void CardItem::setPT(const QString &_pt) void CardItem::setPT(const QString &_pt)
{ {
pt = _pt; pt = _pt;
update(); update();
} }
void CardItem::setAttachedTo(CardItem *_attachedTo) void CardItem::setAttachedTo(CardItem *_attachedTo)
{ {
if (attachedTo) if (attachedTo)
attachedTo->removeAttachedCard(this); attachedTo->removeAttachedCard(this);
gridPoint.setX(-1); gridPoint.setX(-1);
attachedTo = _attachedTo; attachedTo = _attachedTo;
if (attachedTo) { if (attachedTo) {
setParentItem(attachedTo->getZone()); setParentItem(attachedTo->getZone());
attachedTo->addAttachedCard(this); attachedTo->addAttachedCard(this);
if (zone != attachedTo->getZone()) if (zone != attachedTo->getZone())
attachedTo->getZone()->reorganizeCards(); attachedTo->getZone()->reorganizeCards();
} else } else
setParentItem(zone); setParentItem(zone);
if (zone) if (zone)
zone->reorganizeCards(); zone->reorganizeCards();
updateCardMenu(); emit updateCardMenu(this);
} }
void CardItem::resetState() void CardItem::resetState()
{ {
attacking = false; attacking = false;
facedown = false; facedown = false;
counters.clear(); counters.clear();
pt.clear(); pt.clear();
annotation.clear(); annotation.clear();
attachedTo = 0; attachedTo = 0;
attachedCards.clear(); attachedCards.clear();
setTapped(false, false); setTapped(false, false);
setDoesntUntap(false); setDoesntUntap(false);
if (scene()) if (scene())
static_cast<GameScene *>(scene())->unregisterAnimationItem(this); static_cast<GameScene *>(scene())->unregisterAnimationItem(this);
update(); update();
} }
void CardItem::processCardInfo(ServerInfo_Card *info) void CardItem::processCardInfo(const ServerInfo_Card &info)
{ {
counters.clear(); counters.clear();
const QList<ServerInfo_CardCounter *> &_counterList = info->getCounters(); const int counterListSize = info.counter_list_size();
for (int i = 0; i < _counterList.size(); ++i) for (int i = 0; i < counterListSize; ++i) {
counters.insert(_counterList[i]->getId(), _counterList[i]->getValue()); const ServerInfo_CardCounter &counterInfo = info.counter_list(i);
counters.insert(counterInfo.id(), counterInfo.value());
setId(info->getId()); }
setName(info->getName());
setAttacking(info->getAttacking()); setId(info.id());
setFaceDown(info->getFaceDown()); setName(QString::fromStdString(info.name()));
setPT(info->getPT()); setAttacking(info.attacking());
setAnnotation(info->getAnnotation()); setFaceDown(info.face_down());
setColor(info->getColor()); setPT(QString::fromStdString(info.pt()));
setTapped(info->getTapped()); setAnnotation(QString::fromStdString(info.annotation()));
setDestroyOnZoneChange(info->getDestroyOnZoneChange()); setColor(QString::fromStdString(info.color()));
setDoesntUntap(info->getDoesntUntap()); 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) CardDragItem *CardItem::createDragItem(int _id, const QPointF &_pos, const QPointF &_scenePos, bool faceDown)
{ {
deleteDragItem(); deleteDragItem();
dragItem = new CardDragItem(this, _id, _pos, faceDown); dragItem = new CardDragItem(this, _id, _pos, faceDown);
dragItem->setVisible(false); dragItem->setVisible(false);
scene()->addItem(dragItem); scene()->addItem(dragItem);
dragItem->updatePosition(_scenePos); dragItem->updatePosition(_scenePos);
dragItem->setVisible(true); dragItem->setVisible(true);
return dragItem; return dragItem;
} }
void CardItem::deleteDragItem() void CardItem::deleteDragItem()
{ {
dragItem->deleteLater(); if(dragItem)
dragItem = NULL; dragItem->deleteLater();
dragItem = NULL;
} }
void CardItem::drawArrow(const QColor &arrowColor) void CardItem::drawArrow(const QColor &arrowColor)
{ {
if (static_cast<TabGame *>(owner->parent())->getSpectator()) if (static_cast<TabGame *>(owner->parent())->getSpectator())
return; return;
Player *arrowOwner = static_cast<TabGame *>(owner->parent())->getActiveLocalPlayer(); Player *arrowOwner = static_cast<TabGame *>(owner->parent())->getActiveLocalPlayer();
ArrowDragItem *arrow = new ArrowDragItem(arrowOwner, this, arrowColor); ArrowDragItem *arrow = new ArrowDragItem(arrowOwner, this, arrowColor);
scene()->addItem(arrow); scene()->addItem(arrow);
arrow->grabMouse(); arrow->grabMouse();
QListIterator<QGraphicsItem *> itemIterator(scene()->selectedItems()); QListIterator<QGraphicsItem *> itemIterator(scene()->selectedItems());
while (itemIterator.hasNext()) { while (itemIterator.hasNext()) {
CardItem *c = qgraphicsitem_cast<CardItem *>(itemIterator.next()); CardItem *c = qgraphicsitem_cast<CardItem *>(itemIterator.next());
if (!c || (c == this)) if (!c || (c == this))
continue; continue;
if (c->getZone() != zone) if (c->getZone() != zone)
continue; continue;
ArrowDragItem *childArrow = new ArrowDragItem(arrowOwner, c, arrowColor); ArrowDragItem *childArrow = new ArrowDragItem(arrowOwner, c, arrowColor);
scene()->addItem(childArrow); scene()->addItem(childArrow);
arrow->addChildArrow(childArrow); arrow->addChildArrow(childArrow);
} }
} }
void CardItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) void CardItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{ {
if (event->buttons().testFlag(Qt::RightButton)) { if (event->buttons().testFlag(Qt::RightButton)) {
if ((event->screenPos() - event->buttonDownScreenPos(Qt::RightButton)).manhattanLength() < 2 * QApplication::startDragDistance()) if ((event->screenPos() - event->buttonDownScreenPos(Qt::RightButton)).manhattanLength() < 2 * QApplication::startDragDistance())
return; return;
QColor arrowColor = Qt::red; QColor arrowColor = Qt::red;
if (event->modifiers().testFlag(Qt::ControlModifier)) if (event->modifiers().testFlag(Qt::ControlModifier))
arrowColor = Qt::yellow; arrowColor = Qt::yellow;
else if (event->modifiers().testFlag(Qt::AltModifier)) else if (event->modifiers().testFlag(Qt::AltModifier))
arrowColor = Qt::blue; arrowColor = Qt::blue;
else if (event->modifiers().testFlag(Qt::ShiftModifier)) else if (event->modifiers().testFlag(Qt::ShiftModifier))
arrowColor = Qt::green; arrowColor = Qt::green;
drawArrow(arrowColor); drawArrow(arrowColor);
} else if (event->buttons().testFlag(Qt::LeftButton)) { } else if (event->buttons().testFlag(Qt::LeftButton)) {
if ((event->screenPos() - event->buttonDownScreenPos(Qt::LeftButton)).manhattanLength() < 2 * QApplication::startDragDistance()) if ((event->screenPos() - event->buttonDownScreenPos(Qt::LeftButton)).manhattanLength() < 2 * QApplication::startDragDistance())
return; return;
if (!owner->getLocal()) if (zone->getIsView()) {
return; const ZoneViewZone *const view = static_cast<const ZoneViewZone *const>(zone);
if (view->getRevealZone() && !view->getWriteableRevealZone())
bool forceFaceDown = event->modifiers().testFlag(Qt::ShiftModifier); return;
} else if (!owner->getLocal())
createDragItem(id, event->pos(), event->scenePos(), facedown || forceFaceDown); return;
dragItem->grabMouse();
bool forceFaceDown = event->modifiers().testFlag(Qt::ShiftModifier);
QList<QGraphicsItem *> sel = scene()->selectedItems();
int j = 0; createDragItem(id, event->pos(), event->scenePos(), facedown || forceFaceDown);
for (int i = 0; i < sel.size(); i++) { dragItem->grabMouse();
CardItem *c = (CardItem *) sel.at(i);
if (c == this) QList<QGraphicsItem *> sel = scene()->selectedItems();
continue; int j = 0;
++j; for (int i = 0; i < sel.size(); i++) {
QPointF childPos; CardItem *c = (CardItem *) sel.at(i);
if (zone->getHasCardAttr()) if ((c == this) || (c->getZone() != zone))
childPos = c->pos() - pos(); continue;
else ++j;
childPos = QPointF(j * CARD_WIDTH / 2, 0); QPointF childPos;
CardDragItem *drag = new CardDragItem(c, c->getId(), childPos, c->getFaceDown() || forceFaceDown, dragItem); if (zone->getHasCardAttr())
drag->setPos(dragItem->pos() + childPos); childPos = c->pos() - pos();
scene()->addItem(drag); else
} childPos = QPointF(j * CARD_WIDTH / 2, 0);
} CardDragItem *drag = new CardDragItem(c, c->getId(), childPos, c->getFaceDown() || forceFaceDown, dragItem);
setCursor(Qt::OpenHandCursor); drag->setPos(dragItem->pos() + childPos);
scene()->addItem(drag);
}
}
setCursor(Qt::OpenHandCursor);
} }
void CardItem::playCard(bool faceDown) void CardItem::playCard(bool faceDown)
{ {
// Do nothing if the card belongs to another player // Do nothing if the card belongs to another player
if (!owner->getLocal()) if (!owner->getLocal())
return; return;
TableZone *tz = qobject_cast<TableZone *>(zone); TableZone *tz = qobject_cast<TableZone *>(zone);
if (tz) if (tz)
tz->toggleTapped(); tz->toggleTapped();
else else
zone->getPlayer()->playCard(this, faceDown, info->getCipt()); zone->getPlayer()->playCard(this, faceDown, info->getCipt());
} }
void CardItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) void CardItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{ {
if (event->button() == Qt::RightButton) { if (event->button() == Qt::RightButton) {
if (cardMenu) if (cardMenu)
if (!cardMenu->isEmpty()) if (!cardMenu->isEmpty())
cardMenu->exec(event->screenPos()); cardMenu->exec(event->screenPos());
} else if ((event->button() == Qt::LeftButton) && !settingsCache->getDoubleClickToPlay()) { } else if ((event->button() == Qt::LeftButton) && !settingsCache->getDoubleClickToPlay()) {
setCursor(Qt::OpenHandCursor);
if (revealedCard) bool hideCard = false;
actHide(); if (zone->getIsView()) {
else ZoneViewZone *view = static_cast<ZoneViewZone *>(zone);
playCard(event->modifiers().testFlag(Qt::ShiftModifier)); 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) void CardItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
{ {
if (settingsCache->getDoubleClickToPlay()) { if (settingsCache->getDoubleClickToPlay()) {
if (revealedCard) if (revealedCard)
actHide(); zone->removeCard(this);
else else
playCard(event->modifiers().testFlag(Qt::ShiftModifier)); playCard(event->modifiers().testFlag(Qt::ShiftModifier));
} }
event->accept(); event->accept();
} }
bool CardItem::animationEvent() bool CardItem::animationEvent()
{ {
int delta = 18; int delta = 18;
if (!tapped) if (!tapped)
delta *= -1; delta *= -1;
tapAngle += delta; tapAngle += delta;
setTransform(QTransform().translate((float) CARD_WIDTH / 2, (float) CARD_HEIGHT / 2).rotate(tapAngle).translate((float) -CARD_WIDTH / 2, (float) -CARD_HEIGHT / 2)); setTransform(QTransform().translate((float) CARD_WIDTH / 2, (float) CARD_HEIGHT / 2).rotate(tapAngle).translate((float) -CARD_WIDTH / 2, (float) -CARD_HEIGHT / 2));
setHovered(false); setHovered(false);
update(); update();
if ((tapped && (tapAngle >= 90)) || (!tapped && (tapAngle <= 0))) if ((tapped && (tapAngle >= 90)) || (!tapped && (tapAngle <= 0)))
return false; return false;
return true; return true;
} }
QVariant CardItem::itemChange(GraphicsItemChange change, const QVariant &value) QVariant CardItem::itemChange(GraphicsItemChange change, const QVariant &value)
{ {
if ((change == ItemSelectedHasChanged) && owner) { if ((change == ItemSelectedHasChanged) && owner) {
if (value == true) if (value == true) {
owner->setCardMenu(cardMenu); owner->setCardMenu(cardMenu);
else if (owner->getCardMenu() == cardMenu) owner->getGame()->setActiveCard(this);
owner->setCardMenu(0); } else if (owner->getCardMenu() == cardMenu) {
} owner->setCardMenu(0);
return QGraphicsItem::itemChange(change, value); owner->getGame()->setActiveCard(0);
} }
}
void CardItem::cardMenuAction() return QGraphicsItem::itemChange(change, value);
{
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);
} }

View file

@ -14,99 +14,75 @@ class QColor;
const int MAX_COUNTERS_ON_CARD = 999; const int MAX_COUNTERS_ON_CARD = 999;
class CardItem : public AbstractCardItem { class CardItem : public AbstractCardItem {
Q_OBJECT Q_OBJECT
private: private:
CardZone *zone; CardZone *zone;
int id; bool revealedCard;
bool revealedCard; bool attacking;
bool attacking; QMap<int, int> counters;
bool facedown; QString annotation;
QMap<int, int> counters; QString pt;
QString annotation; bool destroyOnZoneChange;
QString pt; bool doesntUntap;
bool destroyOnZoneChange; QPoint gridPoint;
bool doesntUntap; CardDragItem *dragItem;
QPoint gridPoint; CardItem *attachedTo;
CardDragItem *dragItem; QList<CardItem *> attachedCards;
CardItem *attachedTo;
QList<CardItem *> attachedCards; QMenu *cardMenu, *ptMenu, *moveMenu;
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;
void playCard(bool faceDown); void prepareDelete();
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();
public slots: public slots:
void deleteLater(); void deleteLater();
public: public:
enum { Type = typeCard }; enum { Type = typeCard };
int type() const { return Type; } int type() const { return Type; }
CardItem(Player *_owner, const QString &_name = QString(), int _cardid = -1, bool revealedCard = false, QGraphicsItem *parent = 0); CardItem(Player *_owner, const QString &_name = QString(), int _cardid = -1, bool revealedCard = false, QGraphicsItem *parent = 0);
~CardItem(); ~CardItem();
void retranslateUi(); void retranslateUi();
CardZone *getZone() const { return zone; } CardZone *getZone() const { return zone; }
void setZone(CardZone *_zone); void setZone(CardZone *_zone);
QMenu *getCardMenu() const { return cardMenu; } void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); QPoint getGridPoint() const { return gridPoint; }
QPoint getGridPoint() const { return gridPoint; } void setGridPoint(const QPoint &_gridPoint) { gridPoint = _gridPoint; }
void setGridPoint(const QPoint &_gridPoint) { gridPoint = _gridPoint; } QPoint getGridPos() const { return gridPoint; }
QPoint getGridPos() const { return gridPoint; } Player *getOwner() const { return owner; }
Player *getOwner() const { return owner; } void setOwner(Player *_owner) { owner = _owner; }
void setOwner(Player *_owner) { owner = _owner; } bool getRevealedCard() const { return revealedCard; }
int getId() const { return id; } bool getAttacking() const { return attacking; }
void setId(int _id) { id = _id; } void setAttacking(bool _attacking);
bool getAttacking() const { return attacking; } const QMap<int, int> &getCounters() const { return counters; }
void setAttacking(bool _attacking); void setCounter(int _id, int _value);
bool getFaceDown() const { return facedown; } QString getAnnotation() const { return annotation; }
void setFaceDown(bool _facedown); void setAnnotation(const QString &_annotation);
const QMap<int, int> &getCounters() const { return counters; } bool getDoesntUntap() const { return doesntUntap; }
void setCounter(int _id, int _value); void setDoesntUntap(bool _doesntUntap);
QString getAnnotation() const { return annotation; } QString getPT() const { return pt; }
void setAnnotation(const QString &_annotation); void setPT(const QString &_pt);
bool getDoesntUntap() const { return doesntUntap; } bool getDestroyOnZoneChange() const { return destroyOnZoneChange; }
void setDoesntUntap(bool _doesntUntap); void setDestroyOnZoneChange(bool _destroy) { destroyOnZoneChange = _destroy; }
QString getPT() const { return pt; } CardItem *getAttachedTo() const { return attachedTo; }
void setPT(const QString &_pt); void setAttachedTo(CardItem *_attachedTo);
bool getDestroyOnZoneChange() const { return destroyOnZoneChange; } void addAttachedCard(CardItem *card) { attachedCards.append(card); }
void setDestroyOnZoneChange(bool _destroy) { destroyOnZoneChange = _destroy; } void removeAttachedCard(CardItem *card) { attachedCards.removeAt(attachedCards.indexOf(card)); }
CardItem *getAttachedTo() const { return attachedTo; } const QList<CardItem *> &getAttachedCards() const { return attachedCards; }
void setAttachedTo(CardItem *_attachedTo); void resetState();
void addAttachedCard(CardItem *card) { attachedCards.append(card); } void processCardInfo(const ServerInfo_Card &info);
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();
bool animationEvent(); QMenu *getCardMenu() const { return cardMenu; }
CardDragItem *createDragItem(int _id, const QPointF &_pos, const QPointF &_scenePos, bool faceDown); QMenu *getPTMenu() const { return ptMenu; }
void deleteDragItem(); 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: protected:
void mouseMoveEvent(QGraphicsSceneMouseEvent *event); void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event); void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
QVariant itemChange(GraphicsItemChange change, const QVariant &value); QVariant itemChange(GraphicsItemChange change, const QVariant &value);
}; };
#endif #endif

View file

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

View file

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

View file

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

View file

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

View file

@ -4,197 +4,262 @@
#include <QMouseEvent> #include <QMouseEvent>
#include <QDesktopServices> #include <QDesktopServices>
#include "chatview.h" #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) ChatView::ChatView(const TabSupervisor *_tabSupervisor, TabGame *_game, bool _showTimestamps, QWidget *parent)
: QTextBrowser(parent), evenNumber(true), ownName(_ownName), showTimestamps(_showTimestamps) : QTextBrowser(parent), tabSupervisor(_tabSupervisor), game(_game), evenNumber(true), showTimestamps(_showTimestamps), hoveredItemType(HoveredNothing)
{ {
setReadOnly(true); document()->setDefaultStyleSheet("a { text-decoration: none; color: blue; }");
setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse); userContextMenu = new UserContextMenu(tabSupervisor, this, game);
setOpenLinks(false); connect(userContextMenu, SIGNAL(openMessageDialog(QString, bool)), this, SIGNAL(openMessageDialog(QString, bool)));
connect(this, SIGNAL(anchorClicked(const QUrl &)), this, SLOT(openLink(const QUrl &)));
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) QTextCursor ChatView::prepareBlock(bool same)
{ {
lastSender.clear(); lastSender.clear();
QTextCursor cursor(document()->lastBlock()); QTextCursor cursor(document()->lastBlock());
cursor.movePosition(QTextCursor::End); cursor.movePosition(QTextCursor::End);
if (!same) { if (!same) {
QTextBlockFormat blockFormat; QTextBlockFormat blockFormat;
if ((evenNumber = !evenNumber)) if ((evenNumber = !evenNumber))
blockFormat.setBackground(palette().alternateBase()); blockFormat.setBackground(palette().alternateBase());
blockFormat.setBottomMargin(2); blockFormat.setBottomMargin(2);
cursor.insertBlock(blockFormat); cursor.insertBlock(blockFormat);
} else } else
cursor.insertHtml("<br>"); cursor.insertHtml("<br>");
return cursor; return cursor;
} }
void ChatView::appendHtml(const QString &html) void ChatView::appendHtml(const QString &html)
{ {
bool atBottom = verticalScrollBar()->value() >= verticalScrollBar()->maximum(); bool atBottom = verticalScrollBar()->value() >= verticalScrollBar()->maximum();
prepareBlock().insertHtml(html); prepareBlock().insertHtml(html);
if (atBottom) if (atBottom)
verticalScrollBar()->setValue(verticalScrollBar()->maximum()); 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(); QTextCharFormat oldFormat = cursor.charFormat();
bool sameSender = (sender == lastSender) && !lastSender.isEmpty(); QTextCharFormat anchorFormat = oldFormat;
QTextCursor cursor = prepareBlock(sameSender); anchorFormat.setForeground(Qt::blue);
lastSender = sender; anchorFormat.setAnchor(true);
anchorFormat.setAnchorHref("card://" + cardName);
if (showTimestamps && !sameSender) {
QTextCharFormat timeFormat; cursor.setCharFormat(anchorFormat);
timeFormat.setForeground(Qt::black); cursor.insertText(cardName);
cursor.setCharFormat(timeFormat); cursor.setCharFormat(oldFormat);
cursor.insertText(QDateTime::currentDateTime().toString("[hh:mm] ")); }
}
void ChatView::appendUrlTag(QTextCursor &cursor, QString url)
QTextCharFormat senderFormat; {
if (sender == ownName) { if (!url.contains("://"))
senderFormat.setFontWeight(QFont::Bold); url.prepend("http://");
senderFormat.setForeground(Qt::red);
} else { QTextCharFormat oldFormat = cursor.charFormat();
if (playerColor == QColor()) QTextCharFormat anchorFormat = oldFormat;
senderFormat.setForeground(QColor(0, 0, 254)); anchorFormat.setForeground(Qt::blue);
else anchorFormat.setAnchor(true);
senderFormat.setForeground(playerColor); anchorFormat.setAnchorHref(url);
if (playerBold)
senderFormat.setFontWeight(QFont::Bold); cursor.setCharFormat(anchorFormat);
} cursor.insertText(url);
if (!sameSender) { cursor.setCharFormat(oldFormat);
cursor.setCharFormat(senderFormat); }
if (!sender.isEmpty())
sender.append(": "); void ChatView::appendMessage(QString message, QString sender, UserLevelFlags userLevel, bool playerBold)
cursor.insertText(sender); {
} else bool atBottom = verticalScrollBar()->value() >= verticalScrollBar()->maximum();
cursor.insertText(" "); bool sameSender = (sender == lastSender) && !lastSender.isEmpty();
QTextCursor cursor = prepareBlock(sameSender);
QTextCharFormat messageFormat; lastSender = sender;
if (sender.isEmpty())
messageFormat.setForeground(Qt::darkGreen); if (showTimestamps && !sameSender) {
cursor.setCharFormat(messageFormat); QTextCharFormat timeFormat;
timeFormat.setForeground(Qt::black);
int from = 0, index = 0; cursor.setCharFormat(timeFormat);
while ((index = message.indexOf('[', from)) != -1) { cursor.insertText(QDateTime::currentDateTime().toString("[hh:mm] "));
cursor.insertText(message.left(index)); }
message = message.mid(index);
if (message.isEmpty()) QTextCharFormat senderFormat;
break; if (tabSupervisor && tabSupervisor->getUserInfo() && (sender == QString::fromStdString(tabSupervisor->getUserInfo()->name()))) {
senderFormat.setFontWeight(QFont::Bold);
if (message.startsWith("[card]")) { senderFormat.setForeground(Qt::red);
message = message.mid(6); } else {
QTextCharFormat tempFormat = messageFormat; senderFormat.setForeground(Qt::blue);
tempFormat.setForeground(Qt::blue); if (playerBold)
cursor.setCharFormat(tempFormat); senderFormat.setFontWeight(QFont::Bold);
int closeTagIndex = message.indexOf("[/card]"); }
cursor.insertText(message.left(closeTagIndex)); senderFormat.setAnchor(true);
cursor.setCharFormat(messageFormat); senderFormat.setAnchorHref("user://" + QString::number(userLevel) + "_" + sender);
if (closeTagIndex == -1) if (!sameSender) {
message.clear(); if (!sender.isEmpty()) {
else const int pixelSize = QFontInfo(cursor.charFormat().font()).pixelSize();
message = message.mid(closeTagIndex + 7); cursor.insertImage(UserLevelPixmapGenerator::generatePixmap(pixelSize, userLevel).toImage(), QString::number(pixelSize) + "_" + QString::number((int) userLevel));
} else if (message.startsWith("[url]")) { cursor.insertText(" ");
message = message.mid(5); }
int closeTagIndex = message.indexOf("[/url]"); cursor.setCharFormat(senderFormat);
QString url = message.left(closeTagIndex); if (!sender.isEmpty())
if (!url.startsWith("http://")) sender.append(": ");
url.prepend("http://"); cursor.insertText(sender);
QTextCharFormat tempFormat = messageFormat; } else
tempFormat.setForeground(QColor(0, 0, 254)); cursor.insertText(" ");
tempFormat.setAnchor(true);
tempFormat.setAnchorHref(url); QTextCharFormat messageFormat;
cursor.setCharFormat(tempFormat); if (sender.isEmpty())
cursor.insertText(url); messageFormat.setForeground(Qt::darkGreen);
cursor.setCharFormat(messageFormat); cursor.setCharFormat(messageFormat);
if (closeTagIndex == -1)
message.clear(); int from = 0, index = 0;
else while ((index = message.indexOf('[', from)) != -1) {
message = message.mid(closeTagIndex + 6); cursor.insertText(message.left(index));
} else message = message.mid(index);
from = 1; if (message.isEmpty())
} break;
if (!message.isEmpty())
cursor.insertText(message); if (message.startsWith("[card]")) {
message = message.mid(6);
if (atBottom) int closeTagIndex = message.indexOf("[/card]");
verticalScrollBar()->setValue(verticalScrollBar()->maximum()); 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*/) void ChatView::enterEvent(QEvent * /*event*/)
{ {
setMouseTracking(true); setMouseTracking(true);
} }
void ChatView::leaveEvent(QEvent * /*event*/) void ChatView::leaveEvent(QEvent * /*event*/)
{ {
setMouseTracking(false); setMouseTracking(false);
} }
QTextFragment ChatView::getFragmentUnderMouse(const QPoint &pos) const QTextFragment ChatView::getFragmentUnderMouse(const QPoint &pos) const
{ {
QTextCursor cursor(cursorForPosition(pos)); QTextCursor cursor(cursorForPosition(pos));
QTextBlock block(cursor.block()); QTextBlock block(cursor.block());
QTextBlock::iterator it; QTextBlock::iterator it;
for (it = block.begin(); !(it.atEnd()); ++it) { for (it = block.begin(); !(it.atEnd()); ++it) {
QTextFragment frag = it.fragment(); QTextFragment frag = it.fragment();
if (frag.contains(cursor.position())) if (frag.contains(cursor.position()))
return frag; return frag;
} }
return QTextFragment(); 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));
} }
void ChatView::mouseMoveEvent(QMouseEvent *event) void ChatView::mouseMoveEvent(QMouseEvent *event)
{ {
QTextFragment frag = getFragmentUnderMouse(event->pos()); QString anchorHref = getFragmentUnderMouse(event->pos()).charFormat().anchorHref();
QString cardName = getCardNameUnderMouse(frag); if (!anchorHref.isEmpty()) {
if (!cardName.isEmpty()) { const int delimiterIndex = anchorHref.indexOf("://");
viewport()->setCursor(Qt::PointingHandCursor); if (delimiterIndex != -1) {
emit cardNameHovered(cardName); const QString scheme = anchorHref.left(delimiterIndex);
} else if (frag.charFormat().isAnchor()) hoveredContent = anchorHref.mid(delimiterIndex + 3);
viewport()->setCursor(Qt::PointingHandCursor); if (scheme == "card") {
else hoveredItemType = HoveredCard;
viewport()->setCursor(Qt::IBeamCursor); emit cardNameHovered(hoveredContent);
} else if (scheme == "user")
QTextBrowser::mouseMoveEvent(event); 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) void ChatView::mousePressEvent(QMouseEvent *event)
{ {
if ((event->button() == Qt::MidButton) || (event->button() == Qt::LeftButton)) { switch (hoveredItemType) {
QString cardName = getCardNameUnderMouse(event->pos()); case HoveredCard: {
if (!cardName.isEmpty()) if ((event->button() == Qt::MidButton) || (event->button() == Qt::LeftButton))
emit showCardInfoPopup(event->globalPos(), cardName); emit showCardInfoPopup(event->globalPos(), hoveredContent);
} break;
}
QTextBrowser::mousePressEvent(event); 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) void ChatView::mouseReleaseEvent(QMouseEvent *event)
{ {
if ((event->button() == Qt::MidButton) || (event->button() == Qt::LeftButton)) if ((event->button() == Qt::MidButton) || (event->button() == Qt::LeftButton))
emit deleteCardInfoPopup(QString("_")); emit deleteCardInfoPopup(QString("_"));
QTextBrowser::mouseReleaseEvent(event); QTextBrowser::mouseReleaseEvent(event);
} }
void ChatView::openLink(const QUrl &link) 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 <QTextFragment>
#include <QTextCursor> #include <QTextCursor>
#include <QColor> #include <QColor>
#include "user_level.h"
class QTextTable; class QTextTable;
class QMouseEvent; class QMouseEvent;
class UserContextMenu;
class TabSupervisor;
class TabGame;
class ChatView : public QTextBrowser { class ChatView : public QTextBrowser {
Q_OBJECT; 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);
protected: protected:
void enterEvent(QEvent *event); const TabSupervisor * const tabSupervisor;
void leaveEvent(QEvent *event); TabGame * const game;
void mouseMoveEvent(QMouseEvent *event); private:
void mousePressEvent(QMouseEvent *event); enum HoveredItemType { HoveredNothing, HoveredUrl, HoveredCard, HoveredUser };
void mouseReleaseEvent(QMouseEvent *event); 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: signals:
void cardNameHovered(QString cardName); void openMessageDialog(const QString &userName, bool focus);
void showCardInfoPopup(QPoint pos, QString cardName); void cardNameHovered(QString cardName);
void deleteCardInfoPopup(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> #include <QPainter>
GeneralCounter::GeneralCounter(Player *_player, int _id, const QString &_name, const QColor &_color, int _radius, int _value, QGraphicsItem *parent) 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 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()); QRectF mapRect = painter->combinedTransform().mapRect(boundingRect());
int translatedHeight = mapRect.size().height(); int translatedHeight = mapRect.size().height();
qreal scaleFactor = translatedHeight / boundingRect().height(); qreal scaleFactor = translatedHeight / boundingRect().height();
QPixmap pixmap = CounterPixmapGenerator::generatePixmap(translatedHeight, name, hovered); QPixmap pixmap = CounterPixmapGenerator::generatePixmap(translatedHeight, name, hovered);
painter->save(); painter->save();
painter->resetTransform(); painter->resetTransform();
painter->drawPixmap(QPoint(0, 0), pixmap); painter->drawPixmap(QPoint(0, 0), pixmap);
if (value) { if (value) {
QFont f("Serif"); QFont f("Serif");
f.setPixelSize(qMax((int) (radius * scaleFactor), 10)); f.setPixelSize(qMax((int) (radius * scaleFactor), 10));
f.setWeight(QFont::Bold); f.setWeight(QFont::Bold);
painter->setPen(Qt::black); painter->setPen(Qt::black);
painter->setFont(f); painter->setFont(f);
painter->drawText(mapRect, Qt::AlignCenter, QString::number(value)); painter->drawText(mapRect, Qt::AlignCenter, QString::number(value));
} }
painter->restore(); painter->restore();
} }

View file

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

View file

@ -5,6 +5,7 @@
#include <QList> #include <QList>
#include "decklist.h" #include "decklist.h"
class DeckLoader;
class CardDatabase; class CardDatabase;
class QProgressDialog; class QProgressDialog;
class QPrinter; class QPrinter;
@ -12,60 +13,64 @@ class QTextCursor;
class DecklistModelCardNode : public AbstractDecklistCardNode { class DecklistModelCardNode : public AbstractDecklistCardNode {
private: private:
DecklistCardNode *dataNode; DecklistCardNode *dataNode;
public: public:
DecklistModelCardNode(DecklistCardNode *_dataNode, InnerDecklistNode *_parent) : AbstractDecklistCardNode(_parent), dataNode(_dataNode) { } DecklistModelCardNode(DecklistCardNode *_dataNode, InnerDecklistNode *_parent) : AbstractDecklistCardNode(_parent), dataNode(_dataNode) { }
int getNumber() const { return dataNode->getNumber(); } int getNumber() const { return dataNode->getNumber(); }
void setNumber(int _number) { dataNode->setNumber(_number); } void setNumber(int _number) { dataNode->setNumber(_number); }
float getPrice() const { return dataNode->getPrice(); } float getPrice() const { return dataNode->getPrice(); }
void setPrice(float _price) { dataNode->setPrice(_price); } void setPrice(const float _price) { dataNode->setPrice(_price); }
QString getName() const { return dataNode->getName(); } QString getName() const { return dataNode->getName(); }
void setName(const QString &_name) { dataNode->setName(_name); } void setName(const QString &_name) { dataNode->setName(_name); }
DecklistCardNode *getDataNode() const { return dataNode; } DecklistCardNode *getDataNode() const { return dataNode; }
}; };
class DeckListModel : public QAbstractItemModel { class DeckListModel : public QAbstractItemModel {
Q_OBJECT Q_OBJECT
private slots: private slots:
void rebuildTree(); void rebuildTree();
public slots: public slots:
void printDeckList(QPrinter *printer); void printDeckList(QPrinter *printer);
signals: signals:
void deckHashChanged(); void deckHashChanged();
public: public:
DeckListModel(QObject *parent = 0); DeckListModel(QObject *parent = 0);
~DeckListModel(); ~DeckListModel();
int rowCount(const QModelIndex &parent = QModelIndex()) const; int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &/*parent*/ = QModelIndex()) const; int columnCount(const QModelIndex &/*parent*/ = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role) const; QVariant data(const QModelIndex &index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) 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 index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
QModelIndex parent(const QModelIndex &index) const; QModelIndex parent(const QModelIndex &index) const;
Qt::ItemFlags flags(const QModelIndex &index) const; Qt::ItemFlags flags(const QModelIndex &index) const;
bool setData(const QModelIndex &index, const QVariant &value, int role); bool setData(const QModelIndex &index, const QVariant &value, int role);
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
QModelIndex addCard(const QString &cardName, const QString &zoneName); QModelIndex findCard(const QString &cardName, const QString &zoneName) const;
void sort(int column, Qt::SortOrder order = Qt::AscendingOrder); QModelIndex addCard(const QString &cardName, const QString &zoneName);
void cleanList(); void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
DeckList *getDeckList() const { return deckList; } void cleanList();
void setDeckList(DeckList *_deck); DeckLoader *getDeckList() const { return deckList; }
void pricesUpdated(InnerDecklistNode *node = 0); void setDeckList(DeckLoader *_deck);
void pricesUpdated();
private: private:
DeckList *deckList; DeckLoader *deckList;
InnerDecklistNode *root; InnerDecklistNode *root;
InnerDecklistNode *createNodeIfNeeded(const QString &name, InnerDecklistNode *parent); int lastKnownColumn;
QModelIndex nodeToIndex(AbstractDecklistNode *node) const; Qt::SortOrder lastKnownOrder;
void emitRecursiveUpdates(const QModelIndex &index); InnerDecklistNode *createNodeIfNeeded(const QString &name, InnerDecklistNode *parent);
void sortHelper(InnerDecklistNode *node, Qt::SortOrder order); 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 template<typename T> T getNode(const QModelIndex &index) const
{ {
if (!index.isValid()) if (!index.isValid())
return dynamic_cast<T>(root); return dynamic_cast<T>(root);
return dynamic_cast<T>(static_cast<AbstractDecklistNode *>(index.internalPointer())); return dynamic_cast<T>(static_cast<AbstractDecklistNode *>(index.internalPointer()));
} }
}; };
#endif #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" #include "main.h"
DeckViewCardDragItem::DeckViewCardDragItem(DeckViewCard *_item, const QPointF &_hotSpot, AbstractCardDragItem *parentDrag) 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) void DeckViewCardDragItem::updatePosition(const QPointF &cursorScenePos)
{ {
QList<QGraphicsItem *> colliding = scene()->items(cursorScenePos); QList<QGraphicsItem *> colliding = scene()->items(cursorScenePos);
DeckViewCardContainer *cursorZone = 0; DeckViewCardContainer *cursorZone = 0;
for (int i = colliding.size() - 1; i >= 0; i--) for (int i = colliding.size() - 1; i >= 0; i--)
if ((cursorZone = qgraphicsitem_cast<DeckViewCardContainer *>(colliding.at(i)))) if ((cursorZone = qgraphicsitem_cast<DeckViewCardContainer *>(colliding.at(i))))
break; break;
if (!cursorZone) if (!cursorZone)
return; return;
currentZone = cursorZone; currentZone = cursorZone;
QPointF newPos = cursorScenePos; QPointF newPos = cursorScenePos;
if (newPos != pos()) { if (newPos != pos()) {
for (int i = 0; i < childDrags.size(); i++) for (int i = 0; i < childDrags.size(); i++)
childDrags[i]->setPos(newPos + childDrags[i]->getHotSpot()); childDrags[i]->setPos(newPos + childDrags[i]->getHotSpot());
setPos(newPos); setPos(newPos);
} }
} }
void DeckViewCardDragItem::handleDrop(DeckViewCardContainer *target) void DeckViewCardDragItem::handleDrop(DeckViewCardContainer *target)
{ {
DeckViewCard *card = static_cast<DeckViewCard *>(item); DeckViewCard *card = static_cast<DeckViewCard *>(item);
DeckViewCardContainer *start = static_cast<DeckViewCardContainer *>(item->parentItem()); DeckViewCardContainer *start = static_cast<DeckViewCardContainer *>(item->parentItem());
start->removeCard(card); start->removeCard(card);
target->addCard(card); target->addCard(card);
card->setParentItem(target); card->setParentItem(target);
} }
void DeckViewCardDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) void DeckViewCardDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{ {
setCursor(Qt::OpenHandCursor); setCursor(Qt::OpenHandCursor);
DeckViewScene *sc = static_cast<DeckViewScene *>(scene()); DeckViewScene *sc = static_cast<DeckViewScene *>(scene());
sc->removeItem(this); sc->removeItem(this);
if (currentZone) { if (currentZone) {
handleDrop(currentZone); handleDrop(currentZone);
for (int i = 0; i < childDrags.size(); i++) { for (int i = 0; i < childDrags.size(); i++) {
DeckViewCardDragItem *c = static_cast<DeckViewCardDragItem *>(childDrags[i]); DeckViewCardDragItem *c = static_cast<DeckViewCardDragItem *>(childDrags[i]);
c->handleDrop(currentZone); c->handleDrop(currentZone);
sc->removeItem(c); sc->removeItem(c);
} }
sc->updateContents(); sc->updateContents();
} }
event->accept(); event->accept();
} }
DeckViewCard::DeckViewCard(const QString &_name, const QString &_originZone, QGraphicsItem *parent) 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() DeckViewCard::~DeckViewCard()
{ {
delete dragItem; delete dragItem;
} }
void DeckViewCard::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) void DeckViewCard::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{ {
AbstractCardItem::paint(painter, option, widget); AbstractCardItem::paint(painter, option, widget);
painter->save(); painter->save();
QPen pen;//(Qt::DotLine); QPen pen;//(Qt::DotLine);
pen.setWidth(3); pen.setWidth(3);
if (originZone == "main") if (originZone == "main")
pen.setColor(QColor(0, 255, 0)); pen.setColor(QColor(0, 255, 0));
else else
pen.setColor(QColor(255, 0, 0)); pen.setColor(QColor(255, 0, 0));
painter->setPen(pen); painter->setPen(pen);
painter->drawRect(QRectF(1.5, 1.5, CARD_WIDTH - 3, CARD_HEIGHT - 3)); painter->drawRect(QRectF(1.5, 1.5, CARD_WIDTH - 3, CARD_HEIGHT - 3));
painter->restore(); painter->restore();
} }
void DeckViewCard::mouseMoveEvent(QGraphicsSceneMouseEvent *event) void DeckViewCard::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{ {
if ((event->screenPos() - event->buttonDownScreenPos(Qt::LeftButton)).manhattanLength() < 2 * QApplication::startDragDistance()) if ((event->screenPos() - event->buttonDownScreenPos(Qt::LeftButton)).manhattanLength() < 2 * QApplication::startDragDistance())
return; return;
if (static_cast<DeckViewScene *>(scene())->getLocked()) if (static_cast<DeckViewScene *>(scene())->getLocked())
return; return;
delete dragItem; delete dragItem;
dragItem = new DeckViewCardDragItem(this, event->pos()); dragItem = new DeckViewCardDragItem(this, event->pos());
scene()->addItem(dragItem); scene()->addItem(dragItem);
dragItem->updatePosition(event->scenePos()); dragItem->updatePosition(event->scenePos());
dragItem->grabMouse(); dragItem->grabMouse();
QList<QGraphicsItem *> sel = scene()->selectedItems(); QList<QGraphicsItem *> sel = scene()->selectedItems();
int j = 0; int j = 0;
for (int i = 0; i < sel.size(); i++) { for (int i = 0; i < sel.size(); i++) {
DeckViewCard *c = static_cast<DeckViewCard *>(sel.at(i)); DeckViewCard *c = static_cast<DeckViewCard *>(sel.at(i));
if (c == this) if (c == this)
continue; continue;
++j; ++j;
QPointF childPos = QPointF(j * CARD_WIDTH / 2, 0); QPointF childPos = QPointF(j * CARD_WIDTH / 2, 0);
DeckViewCardDragItem *drag = new DeckViewCardDragItem(c, childPos, dragItem); DeckViewCardDragItem *drag = new DeckViewCardDragItem(c, childPos, dragItem);
drag->setPos(dragItem->pos() + childPos); drag->setPos(dragItem->pos() + childPos);
scene()->addItem(drag); scene()->addItem(drag);
} }
setCursor(Qt::OpenHandCursor); setCursor(Qt::OpenHandCursor);
} }
void DeckViewCard::hoverEnterEvent(QGraphicsSceneHoverEvent *event) void DeckViewCard::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{ {
event->accept(); event->accept();
processHoverEvent(); processHoverEvent();
} }
DeckViewCardContainer::DeckViewCardContainer(const QString &_name) DeckViewCardContainer::DeckViewCardContainer(const QString &_name)
: QGraphicsItem(), name(_name), width(0), height(0) : QGraphicsItem(), name(_name), width(0), height(0)
{ {
QString bgPath = settingsCache->getTableBgPath(); QString bgPath = settingsCache->getTableBgPath();
if (!bgPath.isEmpty()) if (!bgPath.isEmpty())
bgPixmap.load(bgPath); bgPixmap.load(bgPath);
setCacheMode(DeviceCoordinateCache); setCacheMode(DeviceCoordinateCache);
} }
QRectF DeckViewCardContainer::boundingRect() const 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*/) void DeckViewCardContainer::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/)
{ {
qreal totalTextWidth = getCardTypeTextWidth(); qreal totalTextWidth = getCardTypeTextWidth();
if (bgPixmap.isNull()) if (bgPixmap.isNull())
painter->fillRect(boundingRect(), QColor(0, 0, 100)); painter->fillRect(boundingRect(), QColor(0, 0, 100));
else else
painter->fillRect(boundingRect(), QBrush(bgPixmap)); painter->fillRect(boundingRect(), QBrush(bgPixmap));
painter->setPen(QColor(255, 255, 255, 100)); painter->setPen(QColor(255, 255, 255, 100));
painter->drawLine(QPointF(0, separatorY), QPointF(width, separatorY)); painter->drawLine(QPointF(0, separatorY), QPointF(width, separatorY));
painter->setPen(QColor(Qt::white)); painter->setPen(QColor(Qt::white));
QFont f("Serif"); QFont f("Serif");
f.setStyleHint(QFont::Serif); f.setStyleHint(QFont::Serif);
f.setPixelSize(24); f.setPixelSize(24);
f.setWeight(QFont::Bold); f.setWeight(QFont::Bold);
painter->setFont(f); painter->setFont(f);
painter->drawText(10, 0, width - 20, separatorY, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, InnerDecklistNode::visibleNameFromName(name) + QString(": %1").arg(cards.size())); painter->drawText(10, 0, width - 20, separatorY, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, InnerDecklistNode::visibleNameFromName(name) + QString(": %1").arg(cards.size()));
f.setPixelSize(16); f.setPixelSize(16);
painter->setFont(f); painter->setFont(f);
QList<QString> cardTypeList = cardsByType.uniqueKeys(); QList<QString> cardTypeList = cardsByType.uniqueKeys();
qreal yUntilNow = separatorY + paddingY; qreal yUntilNow = separatorY + paddingY;
for (int i = 0; i < cardTypeList.size(); ++i) { for (int i = 0; i < cardTypeList.size(); ++i) {
if (i != 0) { if (i != 0) {
painter->setPen(QColor(255, 255, 255, 100)); painter->setPen(QColor(255, 255, 255, 100));
painter->drawLine(QPointF(0, yUntilNow - paddingY / 2), QPointF(width, yUntilNow - paddingY / 2)); painter->drawLine(QPointF(0, yUntilNow - paddingY / 2), QPointF(width, yUntilNow - paddingY / 2));
} }
qreal thisRowHeight = CARD_HEIGHT * currentRowsAndCols[i].first;
qreal thisRowHeight = CARD_HEIGHT * currentRowsAndCols[i].first; QRectF textRect(0, yUntilNow, totalTextWidth, thisRowHeight);
QRectF textRect(0, yUntilNow, totalTextWidth, thisRowHeight); yUntilNow += thisRowHeight + paddingY;
yUntilNow += thisRowHeight + paddingY;
painter->setPen(Qt::white);
painter->setPen(Qt::white); painter->drawText(textRect, Qt::AlignHCenter | Qt::AlignVCenter | Qt::TextSingleLine, cardTypeList[i]);
painter->drawText(textRect, Qt::AlignHCenter | Qt::AlignVCenter | Qt::TextSingleLine, cardTypeList[i]); }
}
} }
void DeckViewCardContainer::addCard(DeckViewCard *card) void DeckViewCardContainer::addCard(DeckViewCard *card)
{ {
cards.append(card); cards.append(card);
cardsByType.insert(card->getInfo()->getMainCardType(), card); cardsByType.insert(card->getInfo()->getMainCardType(), card);
} }
void DeckViewCardContainer::removeCard(DeckViewCard *card) void DeckViewCardContainer::removeCard(DeckViewCard *card)
{ {
cards.removeAt(cards.indexOf(card)); cards.removeAt(cards.indexOf(card));
cardsByType.remove(card->getInfo()->getMainCardType(), card); cardsByType.remove(card->getInfo()->getMainCardType(), card);
} }
QList<QPair<int, int> > DeckViewCardContainer::getRowsAndCols() const QList<QPair<int, int> > DeckViewCardContainer::getRowsAndCols() const
{ {
QList<QPair<int, int> > result; QList<QPair<int, int> > result;
QList<QString> cardTypeList = cardsByType.uniqueKeys(); QList<QString> cardTypeList = cardsByType.uniqueKeys();
for (int i = 0; i < cardTypeList.size(); ++i) for (int i = 0; i < cardTypeList.size(); ++i)
result.append(QPair<int, int>(1, cardsByType.count(cardTypeList[i]))); result.append(QPair<int, int>(1, cardsByType.count(cardTypeList[i])));
return result; return result;
} }
int DeckViewCardContainer::getCardTypeTextWidth() const int DeckViewCardContainer::getCardTypeTextWidth() const
{ {
QFont f("Serif"); QFont f("Serif");
f.setStyleHint(QFont::Serif); f.setStyleHint(QFont::Serif);
f.setPixelSize(16); f.setPixelSize(16);
f.setWeight(QFont::Bold); f.setWeight(QFont::Bold);
QFontMetrics fm(f); QFontMetrics fm(f);
int maxCardTypeWidth = 0; int maxCardTypeWidth = 0;
QMapIterator<QString, DeckViewCard *> i(cardsByType); QMapIterator<QString, DeckViewCard *> i(cardsByType);
while (i.hasNext()) { while (i.hasNext()) {
int cardTypeWidth = fm.size(Qt::TextSingleLine, i.next().key()).width(); int cardTypeWidth = fm.size(Qt::TextSingleLine, i.next().key()).width();
if (cardTypeWidth > maxCardTypeWidth) if (cardTypeWidth > maxCardTypeWidth)
maxCardTypeWidth = cardTypeWidth; maxCardTypeWidth = cardTypeWidth;
} }
return maxCardTypeWidth + 15; return maxCardTypeWidth + 15;
} }
QSizeF DeckViewCardContainer::calculateBoundingRect(const QList<QPair<int, int> > &rowsAndCols) const QSizeF DeckViewCardContainer::calculateBoundingRect(const QList<QPair<int, int> > &rowsAndCols) const
{ {
qreal totalHeight = 0; qreal totalHeight = 0;
qreal totalWidth = 0; qreal totalWidth = 0;
// Calculate space needed for cards // Calculate space needed for cards
for (int i = 0; i < rowsAndCols.size(); ++i) { for (int i = 0; i < rowsAndCols.size(); ++i) {
totalHeight += CARD_HEIGHT * rowsAndCols[i].first + paddingY; totalHeight += CARD_HEIGHT * rowsAndCols[i].first + paddingY;
if (CARD_WIDTH * rowsAndCols[i].second > totalWidth) if (CARD_WIDTH * rowsAndCols[i].second > totalWidth)
totalWidth = CARD_WIDTH * rowsAndCols[i].second; totalWidth = CARD_WIDTH * rowsAndCols[i].second;
} }
return QSizeF(getCardTypeTextWidth() + totalWidth, totalHeight + separatorY + paddingY); return QSizeF(getCardTypeTextWidth() + totalWidth, totalHeight + separatorY + paddingY);
} }
void DeckViewCardContainer::rearrangeItems(const QList<QPair<int, int> > &rowsAndCols) void DeckViewCardContainer::rearrangeItems(const QList<QPair<int, int> > &rowsAndCols)
{ {
currentRowsAndCols = rowsAndCols; currentRowsAndCols = rowsAndCols;
int totalCols = 0, totalRows = 0; int totalCols = 0, totalRows = 0;
qreal yUntilNow = separatorY + paddingY; qreal yUntilNow = separatorY + paddingY;
qreal x = (qreal) getCardTypeTextWidth(); qreal x = (qreal) getCardTypeTextWidth();
for (int i = 0; i < rowsAndCols.size(); ++i) { for (int i = 0; i < rowsAndCols.size(); ++i) {
const int tempRows = rowsAndCols[i].first; const int tempRows = rowsAndCols[i].first;
const int tempCols = rowsAndCols[i].second; const int tempCols = rowsAndCols[i].second;
totalRows += tempRows; totalRows += tempRows;
if (tempCols > totalCols) if (tempCols > totalCols)
totalCols = tempCols; totalCols = tempCols;
QList<QString> cardTypeList = cardsByType.uniqueKeys(); QList<QString> cardTypeList = cardsByType.uniqueKeys();
QList<DeckViewCard *> row = cardsByType.values(cardTypeList[i]); QList<DeckViewCard *> row = cardsByType.values(cardTypeList[i]);
for (int j = 0; j < row.size(); ++j) { for (int j = 0; j < row.size(); ++j) {
DeckViewCard *card = row[j]; DeckViewCard *card = row[j];
card->setPos(x + (j % tempCols) * CARD_WIDTH, yUntilNow + (j / tempCols) * CARD_HEIGHT); card->setPos(x + (j % tempCols) * CARD_WIDTH, yUntilNow + (j / tempCols) * CARD_HEIGHT);
} }
yUntilNow += tempRows * CARD_HEIGHT + paddingY; yUntilNow += tempRows * CARD_HEIGHT + paddingY;
} }
prepareGeometryChange(); prepareGeometryChange();
QSizeF bRect = calculateBoundingRect(rowsAndCols); QSizeF bRect = calculateBoundingRect(rowsAndCols);
width = bRect.width(); width = bRect.width();
height = bRect.height(); height = bRect.height();
} }
void DeckViewCardContainer::setWidth(qreal _width) void DeckViewCardContainer::setWidth(qreal _width)
{ {
prepareGeometryChange(); prepareGeometryChange();
width = _width; width = _width;
update(); update();
} }
DeckViewScene::DeckViewScene(QObject *parent) DeckViewScene::DeckViewScene(QObject *parent)
: QGraphicsScene(parent), locked(false), deck(0), optimalAspectRatio(1.0) : QGraphicsScene(parent), locked(true), deck(0), optimalAspectRatio(1.0)
{ {
} }
DeckViewScene::~DeckViewScene() DeckViewScene::~DeckViewScene()
{ {
clearContents();
delete deck;
} }
void DeckViewScene::setDeck(DeckList *_deck) void DeckViewScene::clearContents()
{ {
if (deck) QMapIterator<QString, DeckViewCardContainer *> i(cardContainers);
delete deck; while (i.hasNext())
QMapIterator<QString, DeckViewCardContainer *> i(cardContainers); delete i.next().value();
while (i.hasNext()) cardContainers.clear();
delete i.next().value(); }
cardContainers.clear();
void DeckViewScene::setDeck(const DeckList &_deck)
deck = _deck; {
rebuildTree(); if (deck)
applySideboardPlan(deck->getCurrentSideboardPlan()); delete deck;
rearrangeItems();
deck = new DeckList(_deck);
rebuildTree();
applySideboardPlan(deck->getCurrentSideboardPlan());
rearrangeItems();
} }
void DeckViewScene::rebuildTree() void DeckViewScene::rebuildTree()
{ {
InnerDecklistNode *listRoot = deck->getRoot(); clearContents();
for (int i = 0; i < listRoot->size(); i++) {
InnerDecklistNode *currentZone = dynamic_cast<InnerDecklistNode *>(listRoot->at(i)); if (!deck)
return;
DeckViewCardContainer *container = cardContainers.value(currentZone->getName(), 0);
if (!container) { InnerDecklistNode *listRoot = deck->getRoot();
container = new DeckViewCardContainer(currentZone->getName()); for (int i = 0; i < listRoot->size(); i++) {
cardContainers.insert(currentZone->getName(), container); InnerDecklistNode *currentZone = dynamic_cast<InnerDecklistNode *>(listRoot->at(i));
addItem(container);
} DeckViewCardContainer *container = cardContainers.value(currentZone->getName(), 0);
if (!container) {
for (int j = 0; j < currentZone->size(); j++) { container = new DeckViewCardContainer(currentZone->getName());
DecklistCardNode *currentCard = dynamic_cast<DecklistCardNode *>(currentZone->at(j)); cardContainers.insert(currentZone->getName(), container);
if (!currentCard) addItem(container);
continue; }
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) { for (int k = 0; k < currentCard->getNumber(); ++k) {
DeckViewCard *newCard = new DeckViewCard(currentCard->getName(), currentZone->getName(), container); DeckViewCard *newCard = new DeckViewCard(currentCard->getName(), currentZone->getName(), container);
container->addCard(newCard); container->addCard(newCard);
emit newCardAdded(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) { for (int i = 0; i < plan.size(); ++i) {
MoveCardToZone *m = plan[i]; const MoveCard_ToZone &m = plan[i];
DeckViewCardContainer *start = cardContainers.value(QString::fromStdString(m.start_zone()));
DeckViewCardContainer *start = cardContainers.value(m->getStartZone()); DeckViewCardContainer *target = cardContainers.value(QString::fromStdString(m.target_zone()));
DeckViewCardContainer *target = cardContainers.value(m->getTargetZone()); if (!start || !target)
if (!start || !target) continue;
continue;
DeckViewCard *card = 0;
DeckViewCard *card = 0; const QList<DeckViewCard *> &cardList = start->getCards();
const QList<DeckViewCard *> &cardList = start->getCards(); for (int j = 0; j < cardList.size(); ++j)
for (int j = 0; j < cardList.size(); ++j) if (cardList[j]->getName() == QString::fromStdString(m.card_name())) {
if (cardList[j]->getName() == m->getCardName()) { card = cardList[j];
card = cardList[j]; break;
break; }
} if (!card)
if (!card) continue;
continue;
start->removeCard(card);
start->removeCard(card); target->addCard(card);
target->addCard(card); card->setParentItem(target);
card->setParentItem(target); }
}
} }
void DeckViewScene::rearrangeItems() void DeckViewScene::rearrangeItems()
{ {
const int spacing = CARD_HEIGHT / 3; const int spacing = CARD_HEIGHT / 3;
QList<DeckViewCardContainer *> contList = cardContainers.values(); QList<DeckViewCardContainer *> contList = cardContainers.values();
// Initialize space requirements // Initialize space requirements
QList<QList<QPair<int, int> > > rowsAndColsList; QList<QList<QPair<int, int> > > rowsAndColsList;
QList<QList<int> > cardCountList; QList<QList<int> > cardCountList;
for (int i = 0; i < contList.size(); ++i) { for (int i = 0; i < contList.size(); ++i) {
QList<QPair<int, int> > rowsAndCols = contList[i]->getRowsAndCols(); QList<QPair<int, int> > rowsAndCols = contList[i]->getRowsAndCols();
rowsAndColsList.append(rowsAndCols); rowsAndColsList.append(rowsAndCols);
cardCountList.append(QList<int>()); cardCountList.append(QList<int>());
for (int j = 0; j < rowsAndCols.size(); ++j) for (int j = 0; j < rowsAndCols.size(); ++j)
cardCountList[i].append(rowsAndCols[j].second); cardCountList[i].append(rowsAndCols[j].second);
} }
qreal totalHeight, totalWidth; qreal totalHeight, totalWidth;
for (;;) { for (;;) {
// Calculate total size before this iteration // Calculate total size before this iteration
totalHeight = -spacing; totalHeight = -spacing;
totalWidth = 0; totalWidth = 0;
for (int i = 0; i < contList.size(); ++i) { for (int i = 0; i < contList.size(); ++i) {
QSizeF contSize = contList[i]->calculateBoundingRect(rowsAndColsList[i]); QSizeF contSize = contList[i]->calculateBoundingRect(rowsAndColsList[i]);
totalHeight += contSize.height() + spacing; totalHeight += contSize.height() + spacing;
if (contSize.width() > totalWidth) if (contSize.width() > totalWidth)
totalWidth = contSize.width(); totalWidth = contSize.width();
} }
// We're done when the aspect ratio shifts from too high to too low. // We're done when the aspect ratio shifts from too high to too low.
if (totalWidth / totalHeight <= optimalAspectRatio) if (totalWidth / totalHeight <= optimalAspectRatio)
break; break;
// Find category with highest column count // Find category with highest column count
int maxIndex1 = -1, maxIndex2 = -1, maxCols = 0; int maxIndex1 = -1, maxIndex2 = -1, maxCols = 0;
for (int i = 0; i < rowsAndColsList.size(); ++i) for (int i = 0; i < rowsAndColsList.size(); ++i)
for (int j = 0; j < rowsAndColsList[i].size(); ++j) for (int j = 0; j < rowsAndColsList[i].size(); ++j)
if (rowsAndColsList[i][j].second > maxCols) { if (rowsAndColsList[i][j].second > maxCols) {
maxIndex1 = i; maxIndex1 = i;
maxIndex2 = j; maxIndex2 = j;
maxCols = rowsAndColsList[i][j].second; maxCols = rowsAndColsList[i][j].second;
} }
// Add row to category // Add row to category
const int maxRows = rowsAndColsList[maxIndex1][maxIndex2].first; const int maxRows = rowsAndColsList[maxIndex1][maxIndex2].first;
const int maxCardCount = cardCountList[maxIndex1][maxIndex2]; const int maxCardCount = cardCountList[maxIndex1][maxIndex2];
rowsAndColsList[maxIndex1][maxIndex2] = QPair<int, int>(maxRows + 1, (int) ceil((qreal) maxCardCount / (qreal) (maxRows + 1))); rowsAndColsList[maxIndex1][maxIndex2] = QPair<int, int>(maxRows + 1, (int) ceil((qreal) maxCardCount / (qreal) (maxRows + 1)));
} }
totalHeight = -spacing; totalHeight = -spacing;
for (int i = 0; i < contList.size(); ++i) { for (int i = 0; i < contList.size(); ++i) {
DeckViewCardContainer *c = contList[i]; DeckViewCardContainer *c = contList[i];
c->rearrangeItems(rowsAndColsList[i]); c->rearrangeItems(rowsAndColsList[i]);
c->setPos(0, totalHeight + spacing); c->setPos(0, totalHeight + spacing);
totalHeight += c->boundingRect().height() + spacing; totalHeight += c->boundingRect().height() + spacing;
} }
totalWidth = totalHeight * optimalAspectRatio; totalWidth = totalHeight * optimalAspectRatio;
for (int i = 0; i < contList.size(); ++i) for (int i = 0; i < contList.size(); ++i)
contList[i]->setWidth(totalWidth); contList[i]->setWidth(totalWidth);
setSceneRect(QRectF(0, 0, totalWidth, totalHeight)); setSceneRect(QRectF(0, 0, totalWidth, totalHeight));
} }
void DeckViewScene::updateContents() void DeckViewScene::updateContents()
{ {
rearrangeItems(); rearrangeItems();
emit sideboardPlanChanged(); emit sideboardPlanChanged();
} }
QList<MoveCardToZone *> DeckViewScene::getSideboardPlan() const QList<MoveCard_ToZone> DeckViewScene::getSideboardPlan() const
{ {
QList<MoveCardToZone *> result; QList<MoveCard_ToZone> result;
QMapIterator<QString, DeckViewCardContainer *> containerIterator(cardContainers); QMapIterator<QString, DeckViewCardContainer *> containerIterator(cardContainers);
while (containerIterator.hasNext()) { while (containerIterator.hasNext()) {
DeckViewCardContainer *cont = containerIterator.next().value(); DeckViewCardContainer *cont = containerIterator.next().value();
const QList<DeckViewCard *> cardList = cont->getCards(); const QList<DeckViewCard *> cardList = cont->getCards();
for (int i = 0; i < cardList.size(); ++i) for (int i = 0; i < cardList.size(); ++i)
if (cardList[i]->getOriginZone() != cont->getName()) if (cardList[i]->getOriginZone() != cont->getName()) {
result.append(new MoveCardToZone(cardList[i]->getName(), cardList[i]->getOriginZone(), cont->getName())); MoveCard_ToZone m;
} m.set_card_name(cardList[i]->getName().toStdString());
return result; 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) DeckView::DeckView(QWidget *parent)
: QGraphicsView(parent) : QGraphicsView(parent)
{ {
deckViewScene = new DeckViewScene(this); deckViewScene = new DeckViewScene(this);
setBackgroundBrush(QBrush(QColor(0, 0, 0))); setBackgroundBrush(QBrush(QColor(0, 0, 0)));
setDragMode(RubberBandDrag); setDragMode(RubberBandDrag);
setRenderHints(QPainter::TextAntialiasing | QPainter::Antialiasing/* | QPainter::SmoothPixmapTransform*/); setRenderHints(QPainter::TextAntialiasing | QPainter::Antialiasing/* | QPainter::SmoothPixmapTransform*/);
setScene(deckViewScene); setScene(deckViewScene);
connect(deckViewScene, SIGNAL(sceneRectChanged(const QRectF &)), this, SLOT(updateSceneRect(const QRectF &))); connect(deckViewScene, SIGNAL(sceneRectChanged(const QRectF &)), this, SLOT(updateSceneRect(const QRectF &)));
connect(deckViewScene, SIGNAL(newCardAdded(AbstractCardItem *)), this, SIGNAL(newCardAdded(AbstractCardItem *))); connect(deckViewScene, SIGNAL(newCardAdded(AbstractCardItem *)), this, SIGNAL(newCardAdded(AbstractCardItem *)));
connect(deckViewScene, SIGNAL(sideboardPlanChanged()), this, SIGNAL(sideboardPlanChanged())); connect(deckViewScene, SIGNAL(sideboardPlanChanged()), this, SIGNAL(sideboardPlanChanged()));
} }
void DeckView::resizeEvent(QResizeEvent *event) void DeckView::resizeEvent(QResizeEvent *event)
{ {
QGraphicsView::resizeEvent(event); QGraphicsView::resizeEvent(event);
deckViewScene->setOptimalAspectRatio((qreal) width() / (qreal) height()); deckViewScene->setOptimalAspectRatio((qreal) width() / (qreal) height());
deckViewScene->rearrangeItems(); deckViewScene->rearrangeItems();
} }
void DeckView::updateSceneRect(const QRectF &rect) 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 <QMap>
#include <QMultiMap> #include <QMultiMap>
#include <QPixmap> #include <QPixmap>
#include "abstractcarditem.h"
#include "abstractcarddragitem.h" #include "abstractcarddragitem.h"
#include "pb/move_card_to_zone.pb.h"
class DeckList; class DeckList;
class InnerDecklistNode; class InnerDecklistNode;
class CardInfo; class CardInfo;
@ -18,98 +19,101 @@ class MoveCardToZone;
class DeckViewCard : public AbstractCardItem { class DeckViewCard : public AbstractCardItem {
private: private:
QString originZone; QString originZone;
DeckViewCardDragItem *dragItem; DeckViewCardDragItem *dragItem;
public: public:
DeckViewCard(const QString &_name = QString(), const QString &_originZone = QString(), QGraphicsItem *parent = 0); DeckViewCard(const QString &_name = QString(), const QString &_originZone = QString(), QGraphicsItem *parent = 0);
~DeckViewCard(); ~DeckViewCard();
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
const QString &getOriginZone() const { return originZone; } const QString &getOriginZone() const { return originZone; }
protected: protected:
void mouseMoveEvent(QGraphicsSceneMouseEvent *event); void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
void hoverEnterEvent(QGraphicsSceneHoverEvent *event); void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
}; };
class DeckViewCardDragItem : public AbstractCardDragItem { class DeckViewCardDragItem : public AbstractCardDragItem {
private: private:
DeckViewCardContainer *currentZone; DeckViewCardContainer *currentZone;
void handleDrop(DeckViewCardContainer *target); void handleDrop(DeckViewCardContainer *target);
public: public:
DeckViewCardDragItem(DeckViewCard *_item, const QPointF &_hotSpot, AbstractCardDragItem *parentDrag = 0); DeckViewCardDragItem(DeckViewCard *_item, const QPointF &_hotSpot, AbstractCardDragItem *parentDrag = 0);
void updatePosition(const QPointF &cursorScenePos); void updatePosition(const QPointF &cursorScenePos);
protected: protected:
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
}; };
class DeckViewCardContainer : public QGraphicsItem { class DeckViewCardContainer : public QGraphicsItem {
private: private:
static const int separatorY = 20; static const int separatorY = 20;
static const int paddingY = 10; static const int paddingY = 10;
QString name; QString name;
QList<DeckViewCard *> cards; QList<DeckViewCard *> cards;
QMultiMap<QString, DeckViewCard *> cardsByType; QMultiMap<QString, DeckViewCard *> cardsByType;
QList<QPair<int, int> > currentRowsAndCols; QList<QPair<int, int> > currentRowsAndCols;
qreal width, height; qreal width, height;
QPixmap bgPixmap; QPixmap bgPixmap;
int getCardTypeTextWidth() const; int getCardTypeTextWidth() const;
public: public:
enum { Type = typeDeckViewCardContainer }; enum { Type = typeDeckViewCardContainer };
int type() const { return Type; } int type() const { return Type; }
DeckViewCardContainer(const QString &_name); DeckViewCardContainer(const QString &_name);
QRectF boundingRect() const; QRectF boundingRect() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
void addCard(DeckViewCard *card); void addCard(DeckViewCard *card);
void removeCard(DeckViewCard *card); void removeCard(DeckViewCard *card);
const QList<DeckViewCard *> &getCards() const { return cards; } const QList<DeckViewCard *> &getCards() const { return cards; }
const QString &getName() const { return name; } const QString &getName() const { return name; }
void setWidth(qreal _width); void setWidth(qreal _width);
QList<QPair<int, int> > getRowsAndCols() const; QList<QPair<int, int> > getRowsAndCols() const;
QSizeF calculateBoundingRect(const QList<QPair<int, int> > &rowsAndCols) const; QSizeF calculateBoundingRect(const QList<QPair<int, int> > &rowsAndCols) const;
void rearrangeItems(const QList<QPair<int, int> > &rowsAndCols); void rearrangeItems(const QList<QPair<int, int> > &rowsAndCols);
}; };
class DeckViewScene : public QGraphicsScene { class DeckViewScene : public QGraphicsScene {
Q_OBJECT Q_OBJECT
signals: signals:
void newCardAdded(AbstractCardItem *card); void newCardAdded(AbstractCardItem *card);
void sideboardPlanChanged(); void sideboardPlanChanged();
private: private:
bool locked; bool locked;
DeckList *deck; DeckList *deck;
QMap<QString, DeckViewCardContainer *> cardContainers; QMap<QString, DeckViewCardContainer *> cardContainers;
qreal optimalAspectRatio; qreal optimalAspectRatio;
void rebuildTree(); void clearContents();
void applySideboardPlan(const QList<MoveCardToZone *> &plan); void rebuildTree();
void applySideboardPlan(const QList<MoveCard_ToZone> &plan);
public: public:
DeckViewScene(QObject *parent = 0); DeckViewScene(QObject *parent = 0);
~DeckViewScene(); ~DeckViewScene();
void setLocked(bool _locked) { locked = _locked; } void setLocked(bool _locked) { locked = _locked; }
bool getLocked() const { return locked; } bool getLocked() const { return locked; }
void setDeck(DeckList *_deck); void setDeck(const DeckList &_deck);
void setOptimalAspectRatio(qreal _optimalAspectRatio) { optimalAspectRatio = _optimalAspectRatio; } void setOptimalAspectRatio(qreal _optimalAspectRatio) { optimalAspectRatio = _optimalAspectRatio; }
void rearrangeItems(); void rearrangeItems();
void updateContents(); void updateContents();
QList<MoveCardToZone *> getSideboardPlan() const; QList<MoveCard_ToZone> getSideboardPlan() const;
void resetSideboardPlan();
}; };
class DeckView : public QGraphicsView { class DeckView : public QGraphicsView {
Q_OBJECT Q_OBJECT
private: private:
DeckViewScene *deckViewScene; DeckViewScene *deckViewScene;
protected: protected:
void resizeEvent(QResizeEvent *event); void resizeEvent(QResizeEvent *event);
public slots: public slots:
void updateSceneRect(const QRectF &rect); void updateSceneRect(const QRectF &rect);
signals: signals:
void newCardAdded(AbstractCardItem *card); void newCardAdded(AbstractCardItem *card);
void sideboardPlanChanged(); void sideboardPlanChanged();
public: public:
DeckView(QWidget *parent = 0); DeckView(QWidget *parent = 0);
void setDeck(DeckList *_deck); void setDeck(const DeckList &_deck);
void setLocked(bool _locked) { deckViewScene->setLocked(_locked); } void setLocked(bool _locked) { deckViewScene->setLocked(_locked); }
QList<MoveCardToZone *> getSideboardPlan() const { return deckViewScene->getSideboardPlan(); } QList<MoveCard_ToZone> getSideboardPlan() const { return deckViewScene->getSideboardPlan(); }
void resetSideboardPlan();
}; };
#endif #endif

View file

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

View file

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

View file

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

View file

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

View file

@ -1,102 +1,180 @@
#include <QLabel> #include <QLabel>
#include <QLineEdit> #include <QLineEdit>
#include <QComboBox> #include <QComboBox>
#include <QPushButton>
#include <QCheckBox> #include <QCheckBox>
#include <QGridLayout> #include <QGridLayout>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QDialogButtonBox>
#include <QGroupBox>
#include <QTreeView>
#include <QRadioButton>
#include <QHeaderView>
#include "decklist.h"
#include "dlg_create_token.h" #include "dlg_create_token.h"
#include "carddatabasemodel.h"
#include "main.h"
DlgCreateToken::DlgCreateToken(QWidget *parent) DlgCreateToken::DlgCreateToken(const QStringList &_predefinedTokens, QWidget *parent)
: QDialog(parent) : QDialog(parent), predefinedTokens(_predefinedTokens)
{ {
nameLabel = new QLabel(tr("&Name:")); nameLabel = new QLabel(tr("&Name:"));
nameEdit = new QLineEdit(tr("Token")); nameEdit = new QLineEdit(tr("Token"));
nameEdit->selectAll(); nameEdit->selectAll();
nameLabel->setBuddy(nameEdit); nameLabel->setBuddy(nameEdit);
colorLabel = new QLabel(tr("C&olor:")); colorLabel = new QLabel(tr("C&olor:"));
colorEdit = new QComboBox; colorEdit = new QComboBox;
colorEdit->addItem(tr("white"), "w"); colorEdit->addItem(tr("white"), "w");
colorEdit->addItem(tr("blue"), "u"); colorEdit->addItem(tr("blue"), "u");
colorEdit->addItem(tr("black"), "b"); colorEdit->addItem(tr("black"), "b");
colorEdit->addItem(tr("red"), "r"); colorEdit->addItem(tr("red"), "r");
colorEdit->addItem(tr("green"), "g"); colorEdit->addItem(tr("green"), "g");
colorEdit->addItem(tr("multicolor"), "m"); colorEdit->addItem(tr("multicolor"), "m");
colorEdit->addItem(tr("colorless"), ""); colorEdit->addItem(tr("colorless"), QString());
colorLabel->setBuddy(colorEdit); colorLabel->setBuddy(colorEdit);
ptLabel = new QLabel(tr("&P/T:")); ptLabel = new QLabel(tr("&P/T:"));
ptEdit = new QLineEdit; ptEdit = new QLineEdit;
ptLabel->setBuddy(ptEdit); ptLabel->setBuddy(ptEdit);
annotationLabel = new QLabel(tr("&Annotation:")); annotationLabel = new QLabel(tr("&Annotation:"));
annotationEdit = new QLineEdit; annotationEdit = new QLineEdit;
annotationLabel->setBuddy(annotationEdit); annotationLabel->setBuddy(annotationEdit);
destroyCheckBox = new QCheckBox(tr("&Destroy token when it leaves the table")); destroyCheckBox = new QCheckBox(tr("&Destroy token when it leaves the table"));
destroyCheckBox->setChecked(true); destroyCheckBox->setChecked(true);
okButton = new QPushButton(tr("&OK")); QGridLayout *grid = new QGridLayout;
okButton->setDefault(true); grid->addWidget(nameLabel, 0, 0);
cancelButton = new QPushButton(tr("&Cancel")); 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; setWindowTitle(tr("Create token"));
grid->addWidget(nameLabel, 0, 0); setFixedHeight(sizeHint().height());
grid->addWidget(nameEdit, 0, 1); setMinimumWidth(300);
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);
QHBoxLayout *buttonLayout = new QHBoxLayout; void DlgCreateToken::tokenSelectionChanged(const QModelIndex &current, const QModelIndex & /*previous*/)
buttonLayout->addStretch(); {
buttonLayout->addWidget(okButton); const QModelIndex realIndex = cardDatabaseDisplayModel->mapToSource(current);
buttonLayout->addWidget(cancelButton); 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; void DlgCreateToken::actChooseTokenFromAll(bool checked)
mainLayout->addLayout(grid); {
mainLayout->addLayout(buttonLayout); if (checked)
setLayout(mainLayout); cardDatabaseDisplayModel->setCardNameSet(QSet<QString>());
}
setWindowTitle(tr("Create token")); void DlgCreateToken::actChooseTokenFromDeck(bool checked)
setFixedHeight(sizeHint().height()); {
setMinimumWidth(300); if (checked)
cardDatabaseDisplayModel->setCardNameSet(QSet<QString>::fromList(predefinedTokens));
connect(okButton, SIGNAL(clicked()), this, SLOT(actOk()));
connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()));
} }
void DlgCreateToken::actOk() void DlgCreateToken::actOk()
{ {
accept(); accept();
} }
QString DlgCreateToken::getName() const QString DlgCreateToken::getName() const
{ {
return nameEdit->text(); return nameEdit->text();
} }
QString DlgCreateToken::getColor() const QString DlgCreateToken::getColor() const
{ {
return colorEdit->itemData(colorEdit->currentIndex()).toString(); return colorEdit->itemData(colorEdit->currentIndex()).toString();
} }
QString DlgCreateToken::getPT() const QString DlgCreateToken::getPT() const
{ {
return ptEdit->text(); return ptEdit->text();
} }
QString DlgCreateToken::getAnnotation() const QString DlgCreateToken::getAnnotation() const
{ {
return annotationEdit->text(); return annotationEdit->text();
} }
bool DlgCreateToken::getDestroy() const bool DlgCreateToken::getDestroy() const
{ {
return destroyCheckBox->isChecked(); return destroyCheckBox->isChecked();
} }

View file

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

View file

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

View file

@ -2,7 +2,7 @@
#define DLG_CREATEGAME_H #define DLG_CREATEGAME_H
#include <QDialog> #include <QDialog>
#include "abstractclient.h" #include <QMap>
class QLabel; class QLabel;
class QLineEdit; class QLineEdit;
@ -10,28 +10,35 @@ class QPushButton;
class QCheckBox; class QCheckBox;
class QGroupBox; class QGroupBox;
class QSpinBox; class QSpinBox;
class QDialogButtonBox;
class TabRoom;
class Response;
class ServerInfo_Game;
class DlgCreateGame : public QDialog { class DlgCreateGame : public QDialog {
Q_OBJECT Q_OBJECT
public: 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: private slots:
void actOK(); void actOK();
void checkResponse(ResponseCode response); void checkResponse(const Response &response);
void spectatorsAllowedChanged(int state); void spectatorsAllowedChanged(int state);
private: private:
AbstractClient *client; TabRoom *room;
int roomId; QMap<int, QString> gameTypes;
QMap<int, QString> gameTypes; QMap<int, QCheckBox *> gameTypeCheckBoxes;
QMap<int, QCheckBox *> gameTypeCheckBoxes;
QGroupBox *spectatorsGroupBox; QGroupBox *spectatorsGroupBox;
QLabel *descriptionLabel, *passwordLabel, *maxPlayersLabel; QLabel *descriptionLabel, *passwordLabel, *maxPlayersLabel;
QLineEdit *descriptionEdit, *passwordEdit; QLineEdit *descriptionEdit, *passwordEdit;
QSpinBox *maxPlayersEdit; QSpinBox *maxPlayersEdit;
QCheckBox *onlyBuddiesCheckBox, *onlyRegisteredCheckBox; QCheckBox *onlyBuddiesCheckBox, *onlyRegisteredCheckBox;
QCheckBox *spectatorsAllowedCheckBox, *spectatorsNeedPasswordCheckBox, *spectatorsCanTalkCheckBox, *spectatorsSeeEverythingCheckBox; QCheckBox *spectatorsAllowedCheckBox, *spectatorsNeedPasswordCheckBox, *spectatorsCanTalkCheckBox, *spectatorsSeeEverythingCheckBox;
QPushButton *okButton, *cancelButton; QDialogButtonBox *buttonBox;
void sharedCtor();
}; };
#endif #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 <QKeySequence>
#include <QApplication> #include <QApplication>
#include <QTextStream> #include <QTextStream>
#include <QDialogButtonBox>
#include <QMessageBox> #include <QMessageBox>
#include "dlg_load_deck_from_clipboard.h" #include "dlg_load_deck_from_clipboard.h"
#include "decklist.h" #include "deck_loader.h"
DlgLoadDeckFromClipboard::DlgLoadDeckFromClipboard(QWidget *parent) DlgLoadDeckFromClipboard::DlgLoadDeckFromClipboard(QWidget *parent)
: QDialog(parent), deckList(0) : QDialog(parent), deckList(0)
{ {
contentsEdit = new QPlainTextEdit; contentsEdit = new QPlainTextEdit;
refreshButton = new QPushButton(tr("&Refresh")); refreshButton = new QPushButton(tr("&Refresh"));
refreshButton->setShortcut(QKeySequence("F5")); refreshButton->setShortcut(QKeySequence("F5"));
okButton = new QPushButton(tr("&OK")); connect(refreshButton, SIGNAL(clicked()), this, SLOT(actRefresh()));
okButton->setDefault(true);
cancelButton = new QPushButton(tr("&Cancel")); 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; setLayout(mainLayout);
buttonLayout->addWidget(refreshButton);
buttonLayout->addStretch();
buttonLayout->addWidget(okButton);
buttonLayout->addWidget(cancelButton);
QVBoxLayout *mainLayout = new QVBoxLayout; setWindowTitle(tr("Load deck from clipboard"));
mainLayout->addWidget(contentsEdit); resize(500, 500);
mainLayout->addLayout(buttonLayout);
actRefresh();
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();
} }
void DlgLoadDeckFromClipboard::actRefresh() void DlgLoadDeckFromClipboard::actRefresh()
{ {
contentsEdit->setPlainText(QApplication::clipboard()->text()); contentsEdit->setPlainText(QApplication::clipboard()->text());
} }
void DlgLoadDeckFromClipboard::actOK() void DlgLoadDeckFromClipboard::actOK()
{ {
QString buffer = contentsEdit->toPlainText(); QString buffer = contentsEdit->toPlainText();
QTextStream stream(&buffer); QTextStream stream(&buffer);
DeckList *l = new DeckList; DeckLoader *l = new DeckLoader;
if (l->loadFromStream_Plain(stream)) { if (l->loadFromStream_Plain(stream)) {
deckList = l; deckList = l;
accept(); accept();
} else { } else {
QMessageBox::critical(this, tr("Error"), tr("Invalid deck list.")); QMessageBox::critical(this, tr("Error"), tr("Invalid deck list."));
delete l; delete l;
} }
} }

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