mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-07-14 14:32:15 -07:00
Merge branch 'master' into valgrind
This commit is contained in:
commit
954489e6c0
105 changed files with 5903 additions and 4729 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -2,3 +2,4 @@ tags
|
||||||
build*
|
build*
|
||||||
*.qm
|
*.qm
|
||||||
.directory
|
.directory
|
||||||
|
mysql.cnf
|
||||||
|
|
|
||||||
|
|
@ -76,8 +76,19 @@ IF(MSVC)
|
||||||
#set(CMAKE_CXX_FLAGS_DEBUG "/Zi")
|
#set(CMAKE_CXX_FLAGS_DEBUG "/Zi")
|
||||||
ELSEIF (CMAKE_COMPILER_IS_GNUCXX)
|
ELSEIF (CMAKE_COMPILER_IS_GNUCXX)
|
||||||
# linux/gcc, bsd/gcc, windows/mingw
|
# linux/gcc, bsd/gcc, windows/mingw
|
||||||
|
include(CheckCXXCompilerFlag)
|
||||||
|
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "-s -O2")
|
set(CMAKE_CXX_FLAGS_RELEASE "-s -O2")
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -Wall -Wextra -pedantic -Werror -Wcast-align -Wmissing-declarations -Winline -Wno-long-long -Wno-error=extra -Wno-error=unused-parameter -Wno-inline -Wno-error=delete-non-virtual-dtor -Wno-error=sign-compare -Wno-error=reorder -Wno-error=missing-declarations")
|
set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -Wall -Wextra -pedantic -Werror")
|
||||||
|
|
||||||
|
set(ADDITIONAL_DEBUG_FLAGS -Wcast-align -Wmissing-declarations -Winline -Wno-long-long -Wno-error=extra -Wno-error=unused-parameter -Wno-inline -Wno-error=delete-non-virtual-dtor -Wno-error=sign-compare -Wno-error=reorder -Wno-error=missing-declarations)
|
||||||
|
|
||||||
|
FOREACH(FLAG ${ADDITIONAL_DEBUG_FLAGS})
|
||||||
|
CHECK_CXX_COMPILER_FLAG("${FLAG}" CXX_HAS_WARNING_${FLAG})
|
||||||
|
IF(CXX_HAS_WARNING_${FLAG})
|
||||||
|
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${FLAG}")
|
||||||
|
ENDIF()
|
||||||
|
ENDFOREACH()
|
||||||
ELSE()
|
ELSE()
|
||||||
# other: osx/llvm, bsd/llvm
|
# other: osx/llvm, bsd/llvm
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "-O2")
|
set(CMAKE_CXX_FLAGS_RELEASE "-O2")
|
||||||
|
|
@ -99,6 +110,11 @@ ENDIF()
|
||||||
|
|
||||||
IF(Qt5Widgets_FOUND)
|
IF(Qt5Widgets_FOUND)
|
||||||
MESSAGE(STATUS "Found Qt ${Qt5Widgets_VERSION_STRING}")
|
MESSAGE(STATUS "Found Qt ${Qt5Widgets_VERSION_STRING}")
|
||||||
|
|
||||||
|
if(UNIX AND NOT APPLE AND "${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64")
|
||||||
|
# FIX: Qt was built with -reduce-relocations
|
||||||
|
add_definitions(-fPIC)
|
||||||
|
endif()
|
||||||
ELSE()
|
ELSE()
|
||||||
FIND_PACKAGE(Qt4 4.8.0 REQUIRED)
|
FIND_PACKAGE(Qt4 4.8.0 REQUIRED)
|
||||||
IF(QT4_FOUND)
|
IF(QT4_FOUND)
|
||||||
|
|
|
||||||
134
CONTRIBUTING.md
Normal file
134
CONTRIBUTING.md
Normal 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`.
|
||||||
|
|
@ -33,8 +33,11 @@ To compile:
|
||||||
|
|
||||||
The following flags can be passed to `cmake`:
|
The following flags can be passed to `cmake`:
|
||||||
|
|
||||||
- `-DWITH_SERVER=1` build the server
|
- `-DWITH_SERVER=1` Build the server
|
||||||
- `-DWITHOUT_CLIENT=1` do not build the client
|
- `-DWITH_CLIENT=0` Do not build the client
|
||||||
|
- `-DWITH_ORACLE=0` Do not build Oracle
|
||||||
|
- `-DWITH_QT4=1` Force compilation to use Qt4 instead of Qt5.
|
||||||
|
- `-DCMAKE_BUILD_TYPE=Debug` Compile in debug mode. Enables extra logging output, debug symbols, and much more verbose compiler warnings.
|
||||||
|
|
||||||
# Running
|
# Running
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1 @@
|
||||||
!define NSIS_PROJECT_NAME "@PROJECT_NAME@"
|
|
||||||
!define NSIS_SOURCE_PATH "@PROJECT_SOURCE_DIR@"
|
!define NSIS_SOURCE_PATH "@PROJECT_SOURCE_DIR@"
|
||||||
!define NSIS_BINARY_PATH "@PROJECT_BINARY_DIR@"
|
|
||||||
|
|
@ -2,10 +2,11 @@
|
||||||
!include "MUI2.nsh"
|
!include "MUI2.nsh"
|
||||||
!include "FileFunc.nsh"
|
!include "FileFunc.nsh"
|
||||||
|
|
||||||
Name "${NSIS_PROJECT_NAME}"
|
Name "@CPACK_PACKAGE_NAME@"
|
||||||
OutFile "@CPACK_TOPLEVEL_DIRECTORY@/@CPACK_OUTPUT_FILE_NAME@"
|
OutFile "@CPACK_TOPLEVEL_DIRECTORY@/@CPACK_OUTPUT_FILE_NAME@"
|
||||||
SetCompressor /SOLID 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 "${NSIS_SOURCE_PATH}\cmake\leftimage.bmp"
|
!define MUI_WELCOMEFINISHPAGE_BITMAP "${NSIS_SOURCE_PATH}\cmake\leftimage.bmp"
|
||||||
|
|
@ -35,7 +36,8 @@ Section "Application" SecApplication
|
||||||
SetShellVarContext all
|
SetShellVarContext all
|
||||||
SetOutPath "$INSTDIR"
|
SetOutPath "$INSTDIR"
|
||||||
|
|
||||||
File /r "${NSIS_BINARY_PATH}\Release\*.*"
|
@CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS@
|
||||||
|
@CPACK_NSIS_FULL_INSTALL@
|
||||||
|
|
||||||
WriteUninstaller "$INSTDIR\uninstall.exe"
|
WriteUninstaller "$INSTDIR\uninstall.exe"
|
||||||
${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2
|
${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ find_package(Git)
|
||||||
if(GIT_FOUND)
|
if(GIT_FOUND)
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND ${GIT_EXECUTABLE} describe --long --always
|
COMMAND ${GIT_EXECUTABLE} describe --long --always
|
||||||
|
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||||
RESULT_VARIABLE res_var
|
RESULT_VARIABLE res_var
|
||||||
OUTPUT_VARIABLE GIT_COM_ID
|
OUTPUT_VARIABLE GIT_COM_ID
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QImageReader>
|
||||||
|
|
||||||
const int CardDatabase::versionNeeded = 3;
|
const int CardDatabase::versionNeeded = 3;
|
||||||
|
|
||||||
|
|
@ -92,6 +93,14 @@ bool PictureToLoad::nextSet()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString PictureToLoad::getSetName() const
|
||||||
|
{
|
||||||
|
if (setIndex < sortedSets.size())
|
||||||
|
return sortedSets[setIndex]->getCorrectedShortName();
|
||||||
|
else
|
||||||
|
return QString("");
|
||||||
|
}
|
||||||
|
|
||||||
PictureLoader::PictureLoader(const QString &__picsPath, bool _picDownload, bool _picDownloadHq, QObject *parent)
|
PictureLoader::PictureLoader(const QString &__picsPath, bool _picDownload, bool _picDownloadHq, QObject *parent)
|
||||||
: QObject(parent),
|
: QObject(parent),
|
||||||
_picsPath(__picsPath), picDownload(_picDownload), picDownloadHq(_picDownloadHq),
|
_picsPath(__picsPath), picDownload(_picDownload), picDownloadHq(_picDownloadHq),
|
||||||
|
|
@ -124,14 +133,33 @@ void PictureLoader::processLoadQueue()
|
||||||
}
|
}
|
||||||
PictureToLoad ptl = loadQueue.takeFirst();
|
PictureToLoad ptl = loadQueue.takeFirst();
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
QString correctedName = ptl.getCard()->getCorrectedName();
|
|
||||||
QString picsPath = _picsPath;
|
//The list of paths to the folders in which to search for images
|
||||||
|
QList<QString> picsPaths = QList<QString>() << _picsPath + "/CUSTOM/" + ptl.getCard()->getCorrectedName() + ".full";
|
||||||
|
|
||||||
|
|
||||||
QString setName=ptl.getSetName();
|
QString setName=ptl.getSetName();
|
||||||
|
if(!setName.isEmpty())
|
||||||
|
{
|
||||||
|
picsPaths << _picsPath + "/" + setName + "/" + ptl.getCard()->getCorrectedName() + ".full"
|
||||||
|
<< _picsPath + "/downloadedPics/" + setName + "/" + ptl.getCard()->getCorrectedName() + ".full";
|
||||||
|
}
|
||||||
|
|
||||||
QImage image;
|
QImage image;
|
||||||
if (!image.load(QString("%1/%2/%3.full.jpg").arg(picsPath).arg(setName).arg(correctedName)))
|
QImageReader imgReader;
|
||||||
if (!image.load(QString("%1/%2/%3%4.full.jpg").arg(picsPath).arg(setName).arg(correctedName).arg(1)))
|
imgReader.setDecideFormatFromContent(true);
|
||||||
if (!image.load(QString("%1/%2/%3/%4.full.jpg").arg(picsPath).arg("downloadedPics").arg(setName).arg(correctedName))) {
|
bool found = false;
|
||||||
|
|
||||||
|
//Iterates through the list of paths, searching for images with the desired name with any QImageReader-supported extension
|
||||||
|
for (int i = 0; i < picsPaths.length() && !found; i ++) {
|
||||||
|
imgReader.setFileName(picsPaths.at(i));
|
||||||
|
if (imgReader.read(&image)) {
|
||||||
|
emit imageLoaded(ptl.getCard(), image);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
if (picDownload) {
|
if (picDownload) {
|
||||||
cardsToDownload.append(ptl);
|
cardsToDownload.append(ptl);
|
||||||
if (!downloadRunning)
|
if (!downloadRunning)
|
||||||
|
|
@ -142,23 +170,53 @@ void PictureLoader::processLoadQueue()
|
||||||
else
|
else
|
||||||
emit imageLoaded(ptl.getCard(), QImage());
|
emit imageLoaded(ptl.getCard(), QImage());
|
||||||
}
|
}
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
emit imageLoaded(ptl.getCard(), image);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString PictureLoader::getPicUrl(CardInfo *card)
|
QString PictureLoader::getPicUrl(CardInfo *card)
|
||||||
{
|
{
|
||||||
if (!picDownload) return 0;
|
if (!picDownload) return QString("");
|
||||||
|
|
||||||
QString picUrl = picDownloadHq ? settingsCache->getPicUrlHq() : settingsCache->getPicUrl();
|
|
||||||
picUrl.replace("!name!", QUrl::toPercentEncoding(card->getCorrectedName()));
|
|
||||||
CardSet *set = card->getPreferredSet();
|
CardSet *set = card->getPreferredSet();
|
||||||
|
QString picUrl = QString("");
|
||||||
|
|
||||||
|
// if sets have been defined for the card, they can contain custom picUrls
|
||||||
|
if(set)
|
||||||
|
{
|
||||||
|
// first check if Hq is enabled and a custom Hq card url exists in cards.xml
|
||||||
|
if(picDownloadHq)
|
||||||
|
{
|
||||||
|
picUrl = card->getCustomPicURLHq(set->getShortName());
|
||||||
|
if (!picUrl.isEmpty())
|
||||||
|
return picUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// then, test for a custom, non-Hq card url in cards.xml
|
||||||
|
picUrl = card->getCustomPicURL(set->getShortName());
|
||||||
|
if (!picUrl.isEmpty())
|
||||||
|
return picUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise, fallback to the default url
|
||||||
|
picUrl = picDownloadHq ? settingsCache->getPicUrlHq() : settingsCache->getPicUrl();
|
||||||
|
picUrl.replace("!name!", QUrl::toPercentEncoding(card->getCorrectedName()));
|
||||||
|
|
||||||
|
if (set) {
|
||||||
picUrl.replace("!setcode!", QUrl::toPercentEncoding(set->getShortName()));
|
picUrl.replace("!setcode!", QUrl::toPercentEncoding(set->getShortName()));
|
||||||
picUrl.replace("!setname!", QUrl::toPercentEncoding(set->getLongName()));
|
picUrl.replace("!setname!", QUrl::toPercentEncoding(set->getLongName()));
|
||||||
picUrl.replace("!cardid!", QUrl::toPercentEncoding(QString::number(card->getPreferredMuId())));
|
}
|
||||||
|
int muid = card->getPreferredMuId();
|
||||||
|
if (muid)
|
||||||
|
picUrl.replace("!cardid!", QUrl::toPercentEncoding(QString::number(muid)));
|
||||||
|
|
||||||
|
if (picUrl.contains("!name!") ||
|
||||||
|
picUrl.contains("!setcode!") ||
|
||||||
|
picUrl.contains("!setname!") ||
|
||||||
|
picUrl.contains("!cardid!")) {
|
||||||
|
qDebug() << "Insufficient card data to download" << card->getName() << "Url:" << picUrl;
|
||||||
|
return QString("");
|
||||||
|
}
|
||||||
|
|
||||||
return picUrl;
|
return picUrl;
|
||||||
}
|
}
|
||||||
|
|
@ -175,8 +233,13 @@ void PictureLoader::startNextPicDownload()
|
||||||
|
|
||||||
cardBeingDownloaded = cardsToDownload.takeFirst();
|
cardBeingDownloaded = cardsToDownload.takeFirst();
|
||||||
|
|
||||||
// TODO: Do something useful when picUrl is 0 or empty, etc
|
|
||||||
QString picUrl = getPicUrl(cardBeingDownloaded.getCard());
|
QString picUrl = getPicUrl(cardBeingDownloaded.getCard());
|
||||||
|
if (picUrl.isEmpty()) {
|
||||||
|
qDebug() << "No url for" << cardBeingDownloaded.getCard()->getName();
|
||||||
|
cardBeingDownloaded = 0;
|
||||||
|
downloadRunning = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QUrl url(picUrl);
|
QUrl url(picUrl);
|
||||||
|
|
||||||
|
|
@ -192,29 +255,35 @@ void PictureLoader::picDownloadFinished(QNetworkReply *reply)
|
||||||
qDebug() << "Download failed:" << reply->errorString();
|
qDebug() << "Download failed:" << reply->errorString();
|
||||||
}
|
}
|
||||||
|
|
||||||
const QByteArray &picData = reply->readAll();
|
const QByteArray &picData = reply->peek(reply->size()); //peek is used to keep the data in the buffer for use by QImageReader
|
||||||
QImage testImage;
|
QImage testImage;
|
||||||
if (testImage.loadFromData(picData)) {
|
|
||||||
if (!QDir(QString(picsPath + "/downloadedPics/")).exists()) {
|
QImageReader imgReader;
|
||||||
QDir dir(picsPath);
|
imgReader.setDecideFormatFromContent(true);
|
||||||
if (!dir.exists())
|
imgReader.setDevice(reply);
|
||||||
|
QString extension = "." + imgReader.format(); //the format is determined prior to reading the QImageReader data into a QImage object, as that wipes the QImageReader buffer
|
||||||
|
if (extension == ".jpeg")
|
||||||
|
extension = ".jpg";
|
||||||
|
|
||||||
|
if (imgReader.read(&testImage)) {
|
||||||
|
QString setName = cardBeingDownloaded.getSetName();
|
||||||
|
if(!setName.isEmpty())
|
||||||
|
{
|
||||||
|
if (!QDir().mkpath(picsPath + "/downloadedPics/" + setName)) {
|
||||||
|
qDebug() << picsPath + "/downloadedPics/" + setName + " could not be created.";
|
||||||
return;
|
return;
|
||||||
dir.mkdir("downloadedPics");
|
|
||||||
}
|
|
||||||
if (!QDir(QString(picsPath + "/downloadedPics/" + cardBeingDownloaded.getSetName())).exists()) {
|
|
||||||
QDir dir(QString(picsPath + "/downloadedPics"));
|
|
||||||
dir.mkdir(cardBeingDownloaded.getSetName());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString suffix;
|
QString suffix;
|
||||||
if (!cardBeingDownloaded.getStripped())
|
if (!cardBeingDownloaded.getStripped())
|
||||||
suffix = ".full";
|
suffix = ".full";
|
||||||
|
|
||||||
QFile newPic(picsPath + "/downloadedPics/" + cardBeingDownloaded.getSetName() + "/" + cardBeingDownloaded.getCard()->getCorrectedName() + suffix + ".jpg");
|
QFile newPic(picsPath + "/downloadedPics/" + setName + "/" + cardBeingDownloaded.getCard()->getCorrectedName() + suffix + extension);
|
||||||
if (!newPic.open(QIODevice::WriteOnly))
|
if (!newPic.open(QIODevice::WriteOnly))
|
||||||
return;
|
return;
|
||||||
newPic.write(picData);
|
newPic.write(picData);
|
||||||
newPic.close();
|
newPic.close();
|
||||||
|
}
|
||||||
|
|
||||||
emit imageLoaded(cardBeingDownloaded.getCard(), testImage);
|
emit imageLoaded(cardBeingDownloaded.getCard(), testImage);
|
||||||
} else if (cardBeingDownloaded.getHq()) {
|
} else if (cardBeingDownloaded.getHq()) {
|
||||||
|
|
@ -275,6 +344,8 @@ CardInfo::CardInfo(CardDatabase *_db,
|
||||||
bool _cipt,
|
bool _cipt,
|
||||||
int _tableRow,
|
int _tableRow,
|
||||||
const SetList &_sets,
|
const SetList &_sets,
|
||||||
|
const QStringMap &_customPicURLs,
|
||||||
|
const QStringMap &_customPicURLsHq,
|
||||||
MuidMap _muIds)
|
MuidMap _muIds)
|
||||||
: db(_db),
|
: db(_db),
|
||||||
name(_name),
|
name(_name),
|
||||||
|
|
@ -286,6 +357,8 @@ CardInfo::CardInfo(CardDatabase *_db,
|
||||||
text(_text),
|
text(_text),
|
||||||
colors(_colors),
|
colors(_colors),
|
||||||
loyalty(_loyalty),
|
loyalty(_loyalty),
|
||||||
|
customPicURLs(_customPicURLs),
|
||||||
|
customPicURLsHq(_customPicURLsHq),
|
||||||
muIds(_muIds),
|
muIds(_muIds),
|
||||||
cipt(_cipt),
|
cipt(_cipt),
|
||||||
tableRow(_tableRow),
|
tableRow(_tableRow),
|
||||||
|
|
@ -424,6 +497,8 @@ void CardInfo::updatePixmapCache()
|
||||||
|
|
||||||
CardSet* CardInfo::getPreferredSet()
|
CardSet* CardInfo::getPreferredSet()
|
||||||
{
|
{
|
||||||
|
if(sets.isEmpty())
|
||||||
|
return 0;
|
||||||
SetList sortedSets = sets;
|
SetList sortedSets = sets;
|
||||||
sortedSets.sortByKey();
|
sortedSets.sortByKey();
|
||||||
return sortedSets.first();
|
return sortedSets.first();
|
||||||
|
|
@ -431,7 +506,28 @@ CardSet* CardInfo::getPreferredSet()
|
||||||
|
|
||||||
int CardInfo::getPreferredMuId()
|
int CardInfo::getPreferredMuId()
|
||||||
{
|
{
|
||||||
return muIds[getPreferredSet()->getShortName()];
|
CardSet *set = getPreferredSet();
|
||||||
|
return set ? muIds[set->getShortName()] : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CardInfo::simplifyName(const QString &name) {
|
||||||
|
QString simpleName(name);
|
||||||
|
|
||||||
|
// So Aetherling would work, but not Ætherling since 'Æ' would get replaced
|
||||||
|
// with nothing.
|
||||||
|
simpleName.replace("æ", "ae");
|
||||||
|
simpleName.replace("Æ", "AE");
|
||||||
|
|
||||||
|
// Replace Jötun Grunt with Jotun Grunt.
|
||||||
|
simpleName = simpleName.normalized(QString::NormalizationForm_KD);
|
||||||
|
|
||||||
|
// Replace dashes with spaces so that we can say "garruk the veil cursed"
|
||||||
|
// instead of the unintuitive "garruk the veilcursed".
|
||||||
|
simpleName = simpleName.replace("-", " ");
|
||||||
|
|
||||||
|
simpleName.remove(QRegExp("[^a-zA-Z0-9 ]"));
|
||||||
|
simpleName = simpleName.toLower();
|
||||||
|
return simpleName;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfo *info)
|
static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfo *info)
|
||||||
|
|
@ -448,6 +544,14 @@ static QXmlStreamWriter &operator<<(QXmlStreamWriter &xml, const CardInfo *info)
|
||||||
tmpSet=sets[i]->getShortName();
|
tmpSet=sets[i]->getShortName();
|
||||||
xml.writeAttribute("muId", QString::number(info->getMuId(tmpSet)));
|
xml.writeAttribute("muId", QString::number(info->getMuId(tmpSet)));
|
||||||
|
|
||||||
|
tmpString = info->getCustomPicURL(tmpSet);
|
||||||
|
if(!tmpString.isEmpty())
|
||||||
|
xml.writeAttribute("picURL", tmpString);
|
||||||
|
|
||||||
|
tmpString = info->getCustomPicURLHq(tmpSet);
|
||||||
|
if(!tmpString.isEmpty())
|
||||||
|
xml.writeAttribute("picURLHq", tmpString);
|
||||||
|
|
||||||
xml.writeCharacters(tmpSet);
|
xml.writeCharacters(tmpSet);
|
||||||
xml.writeEndElement();
|
xml.writeEndElement();
|
||||||
}
|
}
|
||||||
|
|
@ -507,55 +611,55 @@ CardDatabase::~CardDatabase()
|
||||||
|
|
||||||
void CardDatabase::clear()
|
void CardDatabase::clear()
|
||||||
{
|
{
|
||||||
QHashIterator<QString, CardSet *> setIt(setHash);
|
QHashIterator<QString, CardSet *> setIt(sets);
|
||||||
while (setIt.hasNext()) {
|
while (setIt.hasNext()) {
|
||||||
setIt.next();
|
setIt.next();
|
||||||
delete setIt.value();
|
delete setIt.value();
|
||||||
}
|
}
|
||||||
setHash.clear();
|
sets.clear();
|
||||||
|
|
||||||
QHashIterator<QString, CardInfo *> i(cardHash);
|
QHashIterator<QString, CardInfo *> i(cards);
|
||||||
while (i.hasNext()) {
|
while (i.hasNext()) {
|
||||||
i.next();
|
i.next();
|
||||||
delete i.value();
|
delete i.value();
|
||||||
}
|
}
|
||||||
cardHash.clear();
|
cards.clear();
|
||||||
|
|
||||||
|
// The pointers themselves were already deleted, so we don't delete them
|
||||||
|
// again.
|
||||||
|
simpleNameCards.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardDatabase::addCard(CardInfo *card)
|
void CardDatabase::addCard(CardInfo *card)
|
||||||
{
|
{
|
||||||
cardHash.insert(card->getName(), card);
|
cards.insert(card->getName(), card);
|
||||||
|
simpleNameCards.insert(CardInfo::simplifyName(card->getName()), card);
|
||||||
emit cardAdded(card);
|
emit cardAdded(card);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardDatabase::removeCard(CardInfo *card)
|
void CardDatabase::removeCard(CardInfo *card)
|
||||||
{
|
{
|
||||||
cardHash.remove(card->getName());
|
cards.remove(card->getName());
|
||||||
|
simpleNameCards.remove(CardInfo::simplifyName(card->getName()));
|
||||||
emit cardRemoved(card);
|
emit cardRemoved(card);
|
||||||
}
|
}
|
||||||
|
|
||||||
CardInfo *CardDatabase::getCard(const QString &cardName, bool createIfNotFound)
|
CardInfo *CardDatabase::getCard(const QString &cardName, bool createIfNotFound) {
|
||||||
{
|
return getCardFromMap(cards, cardName, createIfNotFound);
|
||||||
if (cardName.isEmpty())
|
}
|
||||||
return noCard;
|
|
||||||
else if (cardHash.contains(cardName))
|
CardInfo *CardDatabase::getCardBySimpleName(const QString &cardName, bool createIfNotFound) {
|
||||||
return cardHash.value(cardName);
|
QString simpleName = CardInfo::simplifyName(cardName);
|
||||||
else if (createIfNotFound) {
|
return getCardFromMap(simpleNameCards, simpleName, createIfNotFound);
|
||||||
CardInfo *newCard = new CardInfo(this, cardName, true);
|
|
||||||
newCard->addToSet(getSet("TK"));
|
|
||||||
cardHash.insert(cardName, newCard);
|
|
||||||
return newCard;
|
|
||||||
} else
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CardSet *CardDatabase::getSet(const QString &setName)
|
CardSet *CardDatabase::getSet(const QString &setName)
|
||||||
{
|
{
|
||||||
if (setHash.contains(setName))
|
if (sets.contains(setName))
|
||||||
return setHash.value(setName);
|
return sets.value(setName);
|
||||||
else {
|
else {
|
||||||
CardSet *newSet = new CardSet(setName);
|
CardSet *newSet = new CardSet(setName);
|
||||||
setHash.insert(setName, newSet);
|
sets.insert(setName, newSet);
|
||||||
return newSet;
|
return newSet;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -563,7 +667,7 @@ CardSet *CardDatabase::getSet(const QString &setName)
|
||||||
SetList CardDatabase::getSetList() const
|
SetList CardDatabase::getSetList() const
|
||||||
{
|
{
|
||||||
SetList result;
|
SetList result;
|
||||||
QHashIterator<QString, CardSet *> i(setHash);
|
QHashIterator<QString, CardSet *> i(sets);
|
||||||
while (i.hasNext()) {
|
while (i.hasNext()) {
|
||||||
i.next();
|
i.next();
|
||||||
result << i.value();
|
result << i.value();
|
||||||
|
|
@ -573,7 +677,9 @@ SetList CardDatabase::getSetList() const
|
||||||
|
|
||||||
void CardDatabase::clearPixmapCache()
|
void CardDatabase::clearPixmapCache()
|
||||||
{
|
{
|
||||||
QHashIterator<QString, CardInfo *> i(cardHash);
|
// This also clears the cards in simpleNameCards since they point to the
|
||||||
|
// same object.
|
||||||
|
QHashIterator<QString, CardInfo *> i(cards);
|
||||||
while (i.hasNext()) {
|
while (i.hasNext()) {
|
||||||
i.next();
|
i.next();
|
||||||
i.value()->clearPixmapCache();
|
i.value()->clearPixmapCache();
|
||||||
|
|
@ -597,7 +703,7 @@ void CardDatabase::loadSetsFromXml(QXmlStreamReader &xml)
|
||||||
else if (xml.name() == "longname")
|
else if (xml.name() == "longname")
|
||||||
longName = xml.readElementText();
|
longName = xml.readElementText();
|
||||||
}
|
}
|
||||||
setHash.insert(shortName, new CardSet(shortName, longName));
|
sets.insert(shortName, new CardSet(shortName, longName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -610,6 +716,7 @@ void CardDatabase::loadCardsFromXml(QXmlStreamReader &xml)
|
||||||
if (xml.name() == "card") {
|
if (xml.name() == "card") {
|
||||||
QString name, manacost, type, pt, text;
|
QString name, manacost, type, pt, text;
|
||||||
QStringList colors;
|
QStringList colors;
|
||||||
|
QStringMap customPicURLs, customPicURLsHq;
|
||||||
MuidMap muids;
|
MuidMap muids;
|
||||||
SetList sets;
|
SetList sets;
|
||||||
int tableRow = 0;
|
int tableRow = 0;
|
||||||
|
|
@ -636,6 +743,12 @@ void CardDatabase::loadCardsFromXml(QXmlStreamReader &xml)
|
||||||
if (attrs.hasAttribute("muId")) {
|
if (attrs.hasAttribute("muId")) {
|
||||||
muids[setName] = attrs.value("muId").toString().toInt();
|
muids[setName] = attrs.value("muId").toString().toInt();
|
||||||
}
|
}
|
||||||
|
if (attrs.hasAttribute("picURL")) {
|
||||||
|
customPicURLs[setName] = attrs.value("picURL").toString();
|
||||||
|
}
|
||||||
|
if (attrs.hasAttribute("picURLHq")) {
|
||||||
|
customPicURLsHq[setName] = attrs.value("picURLHq").toString();
|
||||||
|
}
|
||||||
} else if (xml.name() == "color")
|
} else if (xml.name() == "color")
|
||||||
colors << xml.readElementText();
|
colors << xml.readElementText();
|
||||||
else if (xml.name() == "tablerow")
|
else if (xml.name() == "tablerow")
|
||||||
|
|
@ -647,46 +760,32 @@ void CardDatabase::loadCardsFromXml(QXmlStreamReader &xml)
|
||||||
else if (xml.name() == "token")
|
else if (xml.name() == "token")
|
||||||
isToken = xml.readElementText().toInt();
|
isToken = xml.readElementText().toInt();
|
||||||
}
|
}
|
||||||
cardHash.insert(name, new CardInfo(this, name, isToken, manacost, type, pt, text, colors, loyalty, cipt, tableRow, sets, muids));
|
addCard(new CardInfo(this, name, isToken, manacost, type, pt, text, colors, loyalty, cipt, tableRow, sets, customPicURLs, customPicURLsHq, muids));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadStatus CardDatabase::loadFromFile(const QString &fileName, bool tokens)
|
CardInfo *CardDatabase::getCardFromMap(CardNameMap &cardMap, const QString &cardName, bool createIfNotFound) {
|
||||||
|
if (cardName.isEmpty())
|
||||||
|
return noCard;
|
||||||
|
else if (cardMap.contains(cardName))
|
||||||
|
return cardMap.value(cardName);
|
||||||
|
else if (createIfNotFound) {
|
||||||
|
CardInfo *newCard = new CardInfo(this, cardName, true);
|
||||||
|
newCard->addToSet(getSet("TK"));
|
||||||
|
cardMap.insert(cardName, newCard);
|
||||||
|
return newCard;
|
||||||
|
} else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LoadStatus CardDatabase::loadFromFile(const QString &fileName)
|
||||||
{
|
{
|
||||||
QFile file(fileName);
|
QFile file(fileName);
|
||||||
file.open(QIODevice::ReadOnly);
|
file.open(QIODevice::ReadOnly);
|
||||||
if (!file.isOpen())
|
if (!file.isOpen())
|
||||||
return FileError;
|
return FileError;
|
||||||
|
|
||||||
if (tokens) {
|
|
||||||
QMutableHashIterator<QString, CardInfo *> i(cardHash);
|
|
||||||
while (i.hasNext()) {
|
|
||||||
i.next();
|
|
||||||
if (i.value()->getIsToken()) {
|
|
||||||
delete i.value();
|
|
||||||
i.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
QHashIterator<QString, CardSet *> setIt(setHash);
|
|
||||||
while (setIt.hasNext()) {
|
|
||||||
setIt.next();
|
|
||||||
delete setIt.value();
|
|
||||||
}
|
|
||||||
setHash.clear();
|
|
||||||
|
|
||||||
QMutableHashIterator<QString, CardInfo *> i(cardHash);
|
|
||||||
while (i.hasNext()) {
|
|
||||||
i.next();
|
|
||||||
if (!i.value()->getIsToken()) {
|
|
||||||
delete i.value();
|
|
||||||
i.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cardHash.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
QXmlStreamReader xml(&file);
|
QXmlStreamReader xml(&file);
|
||||||
while (!xml.atEnd()) {
|
while (!xml.atEnd()) {
|
||||||
if (xml.readNext() == QXmlStreamReader::StartElement) {
|
if (xml.readNext() == QXmlStreamReader::StartElement) {
|
||||||
|
|
@ -707,9 +806,9 @@ LoadStatus CardDatabase::loadFromFile(const QString &fileName, bool tokens)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
qDebug() << cardHash.size() << "cards in" << setHash.size() << "sets loaded";
|
qDebug() << cards.size() << "cards in" << sets.size() << "sets loaded";
|
||||||
|
|
||||||
if (cardHash.isEmpty()) return NoCards;
|
if (cards.isEmpty()) return NoCards;
|
||||||
|
|
||||||
return Ok;
|
return Ok;
|
||||||
}
|
}
|
||||||
|
|
@ -728,17 +827,16 @@ bool CardDatabase::saveToFile(const QString &fileName, bool tokens)
|
||||||
|
|
||||||
if (!tokens) {
|
if (!tokens) {
|
||||||
xml.writeStartElement("sets");
|
xml.writeStartElement("sets");
|
||||||
QHashIterator<QString, CardSet *> setIterator(setHash);
|
QHashIterator<QString, CardSet *> setIterator(sets);
|
||||||
while (setIterator.hasNext())
|
while (setIterator.hasNext())
|
||||||
xml << setIterator.next().value();
|
xml << setIterator.next().value();
|
||||||
xml.writeEndElement(); // sets
|
xml.writeEndElement(); // sets
|
||||||
}
|
}
|
||||||
|
|
||||||
xml.writeStartElement("cards");
|
xml.writeStartElement("cards");
|
||||||
QHashIterator<QString, CardInfo *> cardIterator(cardHash);
|
QHashIterator<QString, CardInfo *> cardIterator(cards);
|
||||||
while (cardIterator.hasNext()) {
|
while (cardIterator.hasNext()) {
|
||||||
CardInfo *card = cardIterator.next().value();
|
CardInfo *card = cardIterator.next().value();
|
||||||
if (card->getIsToken() == tokens)
|
|
||||||
xml << card;
|
xml << card;
|
||||||
}
|
}
|
||||||
xml.writeEndElement(); // cards
|
xml.writeEndElement(); // cards
|
||||||
|
|
@ -753,7 +851,7 @@ void CardDatabase::picDownloadChanged()
|
||||||
{
|
{
|
||||||
pictureLoader->setPicDownload(settingsCache->getPicDownload());
|
pictureLoader->setPicDownload(settingsCache->getPicDownload());
|
||||||
if (settingsCache->getPicDownload()) {
|
if (settingsCache->getPicDownload()) {
|
||||||
QHashIterator<QString, CardInfo *> cardIterator(cardHash);
|
QHashIterator<QString, CardInfo *> cardIterator(cards);
|
||||||
while (cardIterator.hasNext())
|
while (cardIterator.hasNext())
|
||||||
cardIterator.next().value()->clearPixmapCacheMiss();
|
cardIterator.next().value()->clearPixmapCacheMiss();
|
||||||
}
|
}
|
||||||
|
|
@ -763,7 +861,7 @@ void CardDatabase::picDownloadHqChanged()
|
||||||
{
|
{
|
||||||
pictureLoader->setPicDownloadHq(settingsCache->getPicDownloadHq());
|
pictureLoader->setPicDownloadHq(settingsCache->getPicDownloadHq());
|
||||||
if (settingsCache->getPicDownloadHq()) {
|
if (settingsCache->getPicDownloadHq()) {
|
||||||
QHashIterator<QString, CardInfo *> cardIterator(cardHash);
|
QHashIterator<QString, CardInfo *> cardIterator(cards);
|
||||||
while (cardIterator.hasNext())
|
while (cardIterator.hasNext())
|
||||||
cardIterator.next().value()->clearPixmapCacheMiss();
|
cardIterator.next().value()->clearPixmapCacheMiss();
|
||||||
}
|
}
|
||||||
|
|
@ -773,11 +871,11 @@ LoadStatus CardDatabase::loadCardDatabase(const QString &path, bool tokens)
|
||||||
{
|
{
|
||||||
LoadStatus tempLoadStatus = NotLoaded;
|
LoadStatus tempLoadStatus = NotLoaded;
|
||||||
if (!path.isEmpty())
|
if (!path.isEmpty())
|
||||||
tempLoadStatus = loadFromFile(path, tokens);
|
tempLoadStatus = loadFromFile(path);
|
||||||
|
|
||||||
if (tempLoadStatus == Ok) {
|
if (tempLoadStatus == Ok) {
|
||||||
SetList allSets;
|
SetList allSets;
|
||||||
QHashIterator<QString, CardSet *> setsIterator(setHash);
|
QHashIterator<QString, CardSet *> setsIterator(sets);
|
||||||
while (setsIterator.hasNext())
|
while (setsIterator.hasNext())
|
||||||
allSets.append(setsIterator.next().value());
|
allSets.append(setsIterator.next().value());
|
||||||
allSets.sortByKey();
|
allSets.sortByKey();
|
||||||
|
|
@ -809,7 +907,7 @@ void CardDatabase::loadTokenDatabase()
|
||||||
QStringList CardDatabase::getAllColors() const
|
QStringList CardDatabase::getAllColors() const
|
||||||
{
|
{
|
||||||
QSet<QString> colors;
|
QSet<QString> colors;
|
||||||
QHashIterator<QString, CardInfo *> cardIterator(cardHash);
|
QHashIterator<QString, CardInfo *> cardIterator(cards);
|
||||||
while (cardIterator.hasNext()) {
|
while (cardIterator.hasNext()) {
|
||||||
const QStringList &cardColors = cardIterator.next().value()->getColors();
|
const QStringList &cardColors = cardIterator.next().value()->getColors();
|
||||||
if (cardColors.isEmpty())
|
if (cardColors.isEmpty())
|
||||||
|
|
@ -824,7 +922,7 @@ QStringList CardDatabase::getAllColors() const
|
||||||
QStringList CardDatabase::getAllMainCardTypes() const
|
QStringList CardDatabase::getAllMainCardTypes() const
|
||||||
{
|
{
|
||||||
QSet<QString> types;
|
QSet<QString> types;
|
||||||
QHashIterator<QString, CardInfo *> cardIterator(cardHash);
|
QHashIterator<QString, CardInfo *> cardIterator(cards);
|
||||||
while (cardIterator.hasNext())
|
while (cardIterator.hasNext())
|
||||||
types.insert(cardIterator.next().value()->getMainCardType());
|
types.insert(cardIterator.next().value()->getMainCardType());
|
||||||
return types.toList();
|
return types.toList();
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ public:
|
||||||
PictureToLoad(CardInfo *_card = 0, bool _stripped = false, bool _hq = true);
|
PictureToLoad(CardInfo *_card = 0, bool _stripped = false, bool _hq = true);
|
||||||
CardInfo *getCard() const { return card; }
|
CardInfo *getCard() const { return card; }
|
||||||
bool getStripped() const { return stripped; }
|
bool getStripped() const { return stripped; }
|
||||||
QString getSetName() const { return sortedSets[setIndex]->getCorrectedShortName(); }
|
QString getSetName() const;
|
||||||
bool nextSet();
|
bool nextSet();
|
||||||
bool getHq() const { return hq; }
|
bool getHq() const { return hq; }
|
||||||
void setHq(bool _hq) { hq = _hq; }
|
void setHq(bool _hq) { hq = _hq; }
|
||||||
|
|
@ -95,6 +95,13 @@ private:
|
||||||
CardDatabase *db;
|
CardDatabase *db;
|
||||||
|
|
||||||
QString name;
|
QString name;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The name without punctuation or capitalization, for better card tag name
|
||||||
|
* recognition.
|
||||||
|
*/
|
||||||
|
QString simpleName;
|
||||||
|
|
||||||
bool isToken;
|
bool isToken;
|
||||||
SetList sets;
|
SetList sets;
|
||||||
QString manacost;
|
QString manacost;
|
||||||
|
|
@ -103,6 +110,7 @@ private:
|
||||||
QString text;
|
QString text;
|
||||||
QStringList colors;
|
QStringList colors;
|
||||||
int loyalty;
|
int loyalty;
|
||||||
|
QStringMap customPicURLs, customPicURLsHq;
|
||||||
MuidMap muIds;
|
MuidMap muIds;
|
||||||
bool cipt;
|
bool cipt;
|
||||||
int tableRow;
|
int tableRow;
|
||||||
|
|
@ -121,6 +129,8 @@ public:
|
||||||
bool _cipt = false,
|
bool _cipt = false,
|
||||||
int _tableRow = 0,
|
int _tableRow = 0,
|
||||||
const SetList &_sets = SetList(),
|
const SetList &_sets = SetList(),
|
||||||
|
const QStringMap &_customPicURLs = QStringMap(),
|
||||||
|
const QStringMap &_customPicURLsHq = QStringMap(),
|
||||||
MuidMap muids = MuidMap());
|
MuidMap muids = MuidMap());
|
||||||
~CardInfo();
|
~CardInfo();
|
||||||
const QString &getName() const { return name; }
|
const QString &getName() const { return name; }
|
||||||
|
|
@ -138,12 +148,16 @@ public:
|
||||||
void setText(const QString &_text) { text = _text; emit cardInfoChanged(this); }
|
void setText(const QString &_text) { text = _text; emit cardInfoChanged(this); }
|
||||||
void setColors(const QStringList &_colors) { colors = _colors; emit cardInfoChanged(this); }
|
void setColors(const QStringList &_colors) { colors = _colors; emit cardInfoChanged(this); }
|
||||||
const QStringList &getColors() const { return colors; }
|
const QStringList &getColors() const { return colors; }
|
||||||
|
QString getCustomPicURL(const QString &set) const { return customPicURLs.value(set); }
|
||||||
|
QString getCustomPicURLHq(const QString &set) const { return customPicURLsHq.value(set); }
|
||||||
int getMuId(const QString &set) const { return muIds.value(set); }
|
int getMuId(const QString &set) const { return muIds.value(set); }
|
||||||
QString getMainCardType() const;
|
QString getMainCardType() const;
|
||||||
QString getCorrectedName() const;
|
QString getCorrectedName() const;
|
||||||
int getTableRow() const { return tableRow; }
|
int getTableRow() const { return tableRow; }
|
||||||
void setTableRow(int _tableRow) { tableRow = _tableRow; }
|
void setTableRow(int _tableRow) { tableRow = _tableRow; }
|
||||||
void setLoyalty(int _loyalty) { loyalty = _loyalty; emit cardInfoChanged(this); }
|
void setLoyalty(int _loyalty) { loyalty = _loyalty; emit cardInfoChanged(this); }
|
||||||
|
void setCustomPicURL(const QString &_set, const QString &_customPicURL) { customPicURLs.insert(_set, _customPicURL); }
|
||||||
|
void setCustomPicURLHq(const QString &_set, const QString &_customPicURL) { customPicURLsHq.insert(_set, _customPicURL); }
|
||||||
void setMuId(const QString &_set, const int &_muId) { muIds.insert(_set, _muId); }
|
void setMuId(const QString &_set, const int &_muId) { muIds.insert(_set, _muId); }
|
||||||
void addToSet(CardSet *set);
|
void addToSet(CardSet *set);
|
||||||
QPixmap *loadPixmap();
|
QPixmap *loadPixmap();
|
||||||
|
|
@ -153,6 +167,12 @@ public:
|
||||||
void imageLoaded(const QImage &image);
|
void imageLoaded(const QImage &image);
|
||||||
CardSet *getPreferredSet();
|
CardSet *getPreferredSet();
|
||||||
int getPreferredMuId();
|
int getPreferredMuId();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simplify a name to have no punctuation and lowercase all letters, for
|
||||||
|
* less strict name-matching.
|
||||||
|
*/
|
||||||
|
static QString simplifyName(const QString &name);
|
||||||
public slots:
|
public slots:
|
||||||
void updatePixmapCache();
|
void updatePixmapCache();
|
||||||
signals:
|
signals:
|
||||||
|
|
@ -162,11 +182,27 @@ signals:
|
||||||
|
|
||||||
enum LoadStatus { Ok, VersionTooOld, Invalid, NotLoaded, FileError, NoCards };
|
enum LoadStatus { Ok, VersionTooOld, Invalid, NotLoaded, FileError, NoCards };
|
||||||
|
|
||||||
|
typedef QHash<QString, CardInfo *> CardNameMap;
|
||||||
|
typedef QHash<QString, CardSet *> SetNameMap;
|
||||||
|
|
||||||
class CardDatabase : public QObject {
|
class CardDatabase : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
protected:
|
protected:
|
||||||
QHash<QString, CardInfo *> cardHash;
|
/*
|
||||||
QHash<QString, CardSet *> setHash;
|
* The cards, indexed by name.
|
||||||
|
*/
|
||||||
|
CardNameMap cards;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The cards, indexed by their simple name.
|
||||||
|
*/
|
||||||
|
CardNameMap simpleNameCards;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The sets, indexed by short name.
|
||||||
|
*/
|
||||||
|
SetNameMap sets;
|
||||||
|
|
||||||
CardInfo *noCard;
|
CardInfo *noCard;
|
||||||
|
|
||||||
QThread *pictureLoaderThread;
|
QThread *pictureLoaderThread;
|
||||||
|
|
@ -176,6 +212,8 @@ private:
|
||||||
static const int versionNeeded;
|
static const int versionNeeded;
|
||||||
void loadCardsFromXml(QXmlStreamReader &xml);
|
void loadCardsFromXml(QXmlStreamReader &xml);
|
||||||
void loadSetsFromXml(QXmlStreamReader &xml);
|
void loadSetsFromXml(QXmlStreamReader &xml);
|
||||||
|
|
||||||
|
CardInfo *getCardFromMap(CardNameMap &cardMap, const QString &cardName, bool createIfNotFound);
|
||||||
public:
|
public:
|
||||||
CardDatabase(QObject *parent = 0);
|
CardDatabase(QObject *parent = 0);
|
||||||
~CardDatabase();
|
~CardDatabase();
|
||||||
|
|
@ -183,10 +221,17 @@ public:
|
||||||
void addCard(CardInfo *card);
|
void addCard(CardInfo *card);
|
||||||
void removeCard(CardInfo *card);
|
void removeCard(CardInfo *card);
|
||||||
CardInfo *getCard(const QString &cardName = QString(), bool createIfNotFound = true);
|
CardInfo *getCard(const QString &cardName = QString(), bool createIfNotFound = true);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get a card by its simple name. The name will be simplified in this
|
||||||
|
* function, so you don't need to simplify it beforehand.
|
||||||
|
*/
|
||||||
|
CardInfo *getCardBySimpleName(const QString &cardName = QString(), bool createIfNotFound = true);
|
||||||
|
|
||||||
CardSet *getSet(const QString &setName);
|
CardSet *getSet(const QString &setName);
|
||||||
QList<CardInfo *> getCardList() const { return cardHash.values(); }
|
QList<CardInfo *> getCardList() const { return cards.values(); }
|
||||||
SetList getSetList() const;
|
SetList getSetList() const;
|
||||||
LoadStatus loadFromFile(const QString &fileName, bool tokens = false);
|
LoadStatus loadFromFile(const QString &fileName);
|
||||||
bool saveToFile(const QString &fileName, bool tokens = false);
|
bool saveToFile(const QString &fileName, bool tokens = false);
|
||||||
QStringList getAllColors() const;
|
QStringList getAllColors() const;
|
||||||
QStringList getAllMainCardTypes() const;
|
QStringList getAllMainCardTypes() const;
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ CardInfoWidget::CardInfoWidget(ResizeMode _mode, const QString &cardName, QWidge
|
||||||
} else
|
} else
|
||||||
setFixedWidth(250);
|
setFixedWidth(250);
|
||||||
|
|
||||||
setCard(db->getCard(cardName));
|
setCard(getCard(cardName));
|
||||||
setMinimized(settingsCache->getCardInfoMinimized());
|
setMinimized(settingsCache->getCardInfoMinimized());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -166,7 +166,7 @@ void CardInfoWidget::setCard(CardInfo *card)
|
||||||
|
|
||||||
void CardInfoWidget::setCard(const QString &cardName)
|
void CardInfoWidget::setCard(const QString &cardName)
|
||||||
{
|
{
|
||||||
setCard(db->getCard(cardName));
|
setCard(getCard(cardName));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardInfoWidget::setCard(AbstractCardItem *card)
|
void CardInfoWidget::setCard(AbstractCardItem *card)
|
||||||
|
|
@ -176,7 +176,11 @@ void CardInfoWidget::setCard(AbstractCardItem *card)
|
||||||
|
|
||||||
void CardInfoWidget::clear()
|
void CardInfoWidget::clear()
|
||||||
{
|
{
|
||||||
setCard(db->getCard());
|
setCard(getCard());
|
||||||
|
}
|
||||||
|
|
||||||
|
CardInfo *CardInfoWidget::getCard(const QString &cardName) {
|
||||||
|
return db->getCardBySimpleName(cardName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardInfoWidget::updatePixmap()
|
void CardInfoWidget::updatePixmap()
|
||||||
|
|
@ -188,7 +192,7 @@ void CardInfoWidget::updatePixmap()
|
||||||
if (resizedPixmap)
|
if (resizedPixmap)
|
||||||
cardPicture->setPixmap(*resizedPixmap);
|
cardPicture->setPixmap(*resizedPixmap);
|
||||||
else
|
else
|
||||||
cardPicture->setPixmap(*(db->getCard()->getPixmap(QSize(pixmapWidth, pixmapWidth * aspectRatio))));
|
cardPicture->setPixmap(*(getCard()->getPixmap(QSize(pixmapWidth, pixmapWidth * aspectRatio))));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardInfoWidget::retranslateUi()
|
void CardInfoWidget::retranslateUi()
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,11 @@ private:
|
||||||
CardInfo *info;
|
CardInfo *info;
|
||||||
void setMinimized(int _minimized);
|
void setMinimized(int _minimized);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wrapper around db->getCardBySimpleName.
|
||||||
|
*/
|
||||||
|
CardInfo *getCard(const QString &cardName = QString());
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CardInfoWidget(ResizeMode _mode, const QString &cardName = QString(), QWidget *parent = 0, Qt::WindowFlags f = 0);
|
CardInfoWidget(ResizeMode _mode, const QString &cardName = QString(), QWidget *parent = 0, Qt::WindowFlags f = 0);
|
||||||
void retranslateUi();
|
void retranslateUi();
|
||||||
|
|
|
||||||
|
|
@ -233,6 +233,7 @@ CardDragItem *CardItem::createDragItem(int _id, const QPointF &_pos, const QPoin
|
||||||
|
|
||||||
void CardItem::deleteDragItem()
|
void CardItem::deleteDragItem()
|
||||||
{
|
{
|
||||||
|
if(dragItem)
|
||||||
dragItem->deleteLater();
|
dragItem->deleteLater();
|
||||||
dragItem = NULL;
|
dragItem = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -472,13 +472,7 @@ void DeckListModel::printDeckList(QPrinter *printer)
|
||||||
doc.print(printer);
|
doc.print(printer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeckListModel::pricesUpdated(InnerDecklistNode *node)
|
void DeckListModel::pricesUpdated()
|
||||||
{
|
{
|
||||||
if (!node)
|
emit layoutChanged();
|
||||||
node = root;
|
|
||||||
|
|
||||||
if (node->isEmpty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
emit dataChanged(createIndex(0, 2, node->at(0)), createIndex(node->size() - 1, 2, node->last()));
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ public:
|
||||||
void cleanList();
|
void cleanList();
|
||||||
DeckLoader *getDeckList() const { return deckList; }
|
DeckLoader *getDeckList() const { return deckList; }
|
||||||
void setDeckList(DeckLoader *_deck);
|
void setDeckList(DeckLoader *_deck);
|
||||||
void pricesUpdated(InnerDecklistNode *node = 0);
|
void pricesUpdated();
|
||||||
private:
|
private:
|
||||||
DeckLoader *deckList;
|
DeckLoader *deckList;
|
||||||
InnerDecklistNode *root;
|
InnerDecklistNode *root;
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,10 @@
|
||||||
#include <QUrlQuery>
|
#include <QUrlQuery>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DeckStatsInterface::DeckStatsInterface(QObject *parent)
|
DeckStatsInterface::DeckStatsInterface(
|
||||||
: QObject(parent)
|
CardDatabase &_cardDatabase,
|
||||||
|
QObject *parent
|
||||||
|
) : QObject(parent), cardDatabase(_cardDatabase)
|
||||||
{
|
{
|
||||||
manager = new QNetworkAccessManager(this);
|
manager = new QNetworkAccessManager(this);
|
||||||
connect(manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(queryFinished(QNetworkReply *)));
|
connect(manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(queryFinished(QNetworkReply *)));
|
||||||
|
|
@ -43,24 +45,23 @@ void DeckStatsInterface::queryFinished(QNetworkReply *reply)
|
||||||
deleteLater();
|
deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DeckStatsInterface::getAnalyzeRequestData(DeckList *deck, QByteArray *data)
|
||||||
|
{
|
||||||
|
DeckList deckWithoutTokens;
|
||||||
|
copyDeckWithoutTokens(*deck, deckWithoutTokens);
|
||||||
|
|
||||||
#if QT_VERSION < 0x050000
|
#if QT_VERSION < 0x050000
|
||||||
void DeckStatsInterface::getAnalyzeRequestData(DeckList *deck, QByteArray *data)
|
|
||||||
{
|
|
||||||
QUrl params;
|
QUrl params;
|
||||||
params.addQueryItem("deck", deck->writeToString_Plain());
|
params.addQueryItem("deck", deckWithoutTokens.writeToString_Plain());
|
||||||
data->append(params.encodedQuery());
|
data->append(params.encodedQuery());
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
void DeckStatsInterface::getAnalyzeRequestData(DeckList *deck, QByteArray *data)
|
|
||||||
{
|
|
||||||
QUrl params;
|
QUrl params;
|
||||||
QUrlQuery urlQuery;
|
QUrlQuery urlQuery;
|
||||||
urlQuery.addQueryItem("deck", deck->writeToString_Plain());
|
urlQuery.addQueryItem("deck", deckWithoutTokens.writeToString_Plain());
|
||||||
params.setQuery(urlQuery);
|
params.setQuery(urlQuery);
|
||||||
data->append(params.query(QUrl::EncodeReserved));
|
data->append(params.query(QUrl::EncodeReserved));
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void DeckStatsInterface::analyzeDeck(DeckList *deck)
|
void DeckStatsInterface::analyzeDeck(DeckList *deck)
|
||||||
{
|
{
|
||||||
|
|
@ -72,3 +73,34 @@ void DeckStatsInterface::analyzeDeck(DeckList *deck)
|
||||||
|
|
||||||
manager->post(request, data);
|
manager->post(request, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct CopyIfNotAToken {
|
||||||
|
CardDatabase &cardDatabase;
|
||||||
|
DeckList &destination;
|
||||||
|
|
||||||
|
CopyIfNotAToken(
|
||||||
|
CardDatabase &_cardDatabase,
|
||||||
|
DeckList &_destination
|
||||||
|
) : cardDatabase(_cardDatabase), destination(_destination) {};
|
||||||
|
|
||||||
|
void operator()(
|
||||||
|
const InnerDecklistNode *node,
|
||||||
|
const DecklistCardNode *card
|
||||||
|
) const {
|
||||||
|
if (!cardDatabase.getCard(card->getName())->getIsToken()) {
|
||||||
|
DecklistCardNode *addedCard = destination.addCard(
|
||||||
|
card->getName(),
|
||||||
|
node->getName()
|
||||||
|
);
|
||||||
|
addedCard->setNumber(card->getNumber());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void DeckStatsInterface::copyDeckWithoutTokens(
|
||||||
|
const DeckList &source,
|
||||||
|
DeckList &destination
|
||||||
|
) {
|
||||||
|
CopyIfNotAToken copyIfNotAToken(cardDatabase, destination);
|
||||||
|
source.forEachCard(copyIfNotAToken);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef DECKSTATS_INTERFACE_H
|
#ifndef DECKSTATS_INTERFACE_H
|
||||||
#define DECKSTATS_INTERFACE_H
|
#define DECKSTATS_INTERFACE_H
|
||||||
|
|
||||||
|
#include "carddatabase.h"
|
||||||
|
#include "decklist.h"
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
class QByteArray;
|
class QByteArray;
|
||||||
|
|
@ -12,11 +14,21 @@ class DeckStatsInterface : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
private:
|
private:
|
||||||
QNetworkAccessManager *manager;
|
QNetworkAccessManager *manager;
|
||||||
|
|
||||||
|
CardDatabase &cardDatabase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deckstats doesn't recognize token cards, and instead tries to find the
|
||||||
|
* closest non-token card instead. So we construct a new deck which has no
|
||||||
|
* tokens.
|
||||||
|
*/
|
||||||
|
void copyDeckWithoutTokens(const DeckList &source, DeckList& destination);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void queryFinished(QNetworkReply *reply);
|
void queryFinished(QNetworkReply *reply);
|
||||||
void getAnalyzeRequestData(DeckList *deck, QByteArray *data);
|
void getAnalyzeRequestData(DeckList *deck, QByteArray *data);
|
||||||
public:
|
public:
|
||||||
DeckStatsInterface(QObject *parent = 0);
|
DeckStatsInterface(CardDatabase &_cardDatabase, QObject *parent = 0);
|
||||||
void analyzeDeck(DeckList *deck);
|
void analyzeDeck(DeckList *deck);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ DlgEditTokens::DlgEditTokens(CardDatabaseModel *_cardDatabaseModel, QWidget *par
|
||||||
setWindowTitle(tr("Edit tokens"));
|
setWindowTitle(tr("Edit tokens"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DlgEditTokens::tokenSelectionChanged(const QModelIndex ¤t, const QModelIndex &previous)
|
void DlgEditTokens::tokenSelectionChanged(const QModelIndex ¤t, const QModelIndex & /* previous */)
|
||||||
{
|
{
|
||||||
const QModelIndex realIndex = cardDatabaseDisplayModel->mapToSource(current);
|
const QModelIndex realIndex = cardDatabaseDisplayModel->mapToSource(current);
|
||||||
CardInfo *cardInfo = current.row() >= 0 ? cardDatabaseModel->getCard(realIndex.row()) : cardDatabaseModel->getDatabase()->getCard();
|
CardInfo *cardInfo = current.row() >= 0 ? cardDatabaseModel->getCard(realIndex.row()) : cardDatabaseModel->getDatabase()->getCard();
|
||||||
|
|
|
||||||
|
|
@ -9,26 +9,53 @@
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <QGridLayout>
|
#include <QGridLayout>
|
||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
|
#include <QSettings>
|
||||||
|
#include <QCryptographicHash>
|
||||||
|
|
||||||
DlgFilterGames::DlgFilterGames(const QMap<int, QString> &allGameTypes, QWidget *parent)
|
DlgFilterGames::DlgFilterGames(const QMap<int, QString> &_allGameTypes, QWidget *parent)
|
||||||
: QDialog(parent)
|
: QDialog(parent),
|
||||||
|
allGameTypes(_allGameTypes)
|
||||||
{
|
{
|
||||||
unavailableGamesVisibleCheckBox = new QCheckBox(tr("Show &unavailable games"));
|
QSettings settings;
|
||||||
passwordProtectedGamesVisibleCheckBox = new QCheckBox(tr("Show &password protected games"));
|
settings.beginGroup("filter_games");
|
||||||
|
|
||||||
|
unavailableGamesVisibleCheckBox = new QCheckBox(tr("Show &unavailable games"));
|
||||||
|
unavailableGamesVisibleCheckBox->setChecked(
|
||||||
|
settings.value("unavailable_games_visible", false).toBool()
|
||||||
|
);
|
||||||
|
|
||||||
|
passwordProtectedGamesVisibleCheckBox = new QCheckBox(tr("Show &password protected games"));
|
||||||
|
passwordProtectedGamesVisibleCheckBox->setChecked(
|
||||||
|
settings.value("password_protected_games_visible", false).toBool()
|
||||||
|
);
|
||||||
|
|
||||||
QLabel *gameNameFilterLabel = new QLabel(tr("Game &description:"));
|
|
||||||
gameNameFilterEdit = new QLineEdit;
|
gameNameFilterEdit = new QLineEdit;
|
||||||
|
gameNameFilterEdit->setText(
|
||||||
|
settings.value("game_name_filter", "").toString()
|
||||||
|
);
|
||||||
|
QLabel *gameNameFilterLabel = new QLabel(tr("Game &description:"));
|
||||||
gameNameFilterLabel->setBuddy(gameNameFilterEdit);
|
gameNameFilterLabel->setBuddy(gameNameFilterEdit);
|
||||||
|
|
||||||
QLabel *creatorNameFilterLabel = new QLabel(tr("&Creator name:"));
|
|
||||||
creatorNameFilterEdit = new QLineEdit;
|
creatorNameFilterEdit = new QLineEdit;
|
||||||
|
creatorNameFilterEdit->setText(
|
||||||
|
settings.value("creator_name_filter", "").toString()
|
||||||
|
);
|
||||||
|
QLabel *creatorNameFilterLabel = new QLabel(tr("&Creator name:"));
|
||||||
creatorNameFilterLabel->setBuddy(creatorNameFilterEdit);
|
creatorNameFilterLabel->setBuddy(creatorNameFilterEdit);
|
||||||
|
|
||||||
QVBoxLayout *gameTypeFilterLayout = new QVBoxLayout;
|
QVBoxLayout *gameTypeFilterLayout = new QVBoxLayout;
|
||||||
QMapIterator<int, QString> gameTypesIterator(allGameTypes);
|
QMapIterator<int, QString> gameTypesIterator(allGameTypes);
|
||||||
while (gameTypesIterator.hasNext()) {
|
while (gameTypesIterator.hasNext()) {
|
||||||
gameTypesIterator.next();
|
gameTypesIterator.next();
|
||||||
|
|
||||||
QCheckBox *temp = new QCheckBox(gameTypesIterator.value());
|
QCheckBox *temp = new QCheckBox(gameTypesIterator.value());
|
||||||
|
temp->setChecked(
|
||||||
|
settings.value(
|
||||||
|
"game_type/" + hashGameType(gameTypesIterator.value()),
|
||||||
|
false
|
||||||
|
).toBool()
|
||||||
|
);
|
||||||
|
|
||||||
gameTypeFilterCheckBoxes.insert(gameTypesIterator.key(), temp);
|
gameTypeFilterCheckBoxes.insert(gameTypesIterator.key(), temp);
|
||||||
gameTypeFilterLayout->addWidget(temp);
|
gameTypeFilterLayout->addWidget(temp);
|
||||||
}
|
}
|
||||||
|
|
@ -43,14 +70,18 @@ DlgFilterGames::DlgFilterGames(const QMap<int, QString> &allGameTypes, QWidget *
|
||||||
maxPlayersFilterMinSpinBox = new QSpinBox;
|
maxPlayersFilterMinSpinBox = new QSpinBox;
|
||||||
maxPlayersFilterMinSpinBox->setMinimum(1);
|
maxPlayersFilterMinSpinBox->setMinimum(1);
|
||||||
maxPlayersFilterMinSpinBox->setMaximum(99);
|
maxPlayersFilterMinSpinBox->setMaximum(99);
|
||||||
maxPlayersFilterMinSpinBox->setValue(1);
|
maxPlayersFilterMinSpinBox->setValue(
|
||||||
|
settings.value("min_players", 1).toInt()
|
||||||
|
);
|
||||||
maxPlayersFilterMinLabel->setBuddy(maxPlayersFilterMinSpinBox);
|
maxPlayersFilterMinLabel->setBuddy(maxPlayersFilterMinSpinBox);
|
||||||
|
|
||||||
QLabel *maxPlayersFilterMaxLabel = new QLabel(tr("at &most:"));
|
QLabel *maxPlayersFilterMaxLabel = new QLabel(tr("at &most:"));
|
||||||
maxPlayersFilterMaxSpinBox = new QSpinBox;
|
maxPlayersFilterMaxSpinBox = new QSpinBox;
|
||||||
maxPlayersFilterMaxSpinBox->setMinimum(1);
|
maxPlayersFilterMaxSpinBox->setMinimum(1);
|
||||||
maxPlayersFilterMaxSpinBox->setMaximum(99);
|
maxPlayersFilterMaxSpinBox->setMaximum(99);
|
||||||
maxPlayersFilterMaxSpinBox->setValue(99);
|
maxPlayersFilterMaxSpinBox->setValue(
|
||||||
|
settings.value("max_players", 99).toInt()
|
||||||
|
);
|
||||||
maxPlayersFilterMaxLabel->setBuddy(maxPlayersFilterMaxSpinBox);
|
maxPlayersFilterMaxLabel->setBuddy(maxPlayersFilterMaxSpinBox);
|
||||||
|
|
||||||
QGridLayout *maxPlayersFilterLayout = new QGridLayout;
|
QGridLayout *maxPlayersFilterLayout = new QGridLayout;
|
||||||
|
|
@ -83,7 +114,7 @@ DlgFilterGames::DlgFilterGames(const QMap<int, QString> &allGameTypes, QWidget *
|
||||||
hbox->addLayout(rightColumn);
|
hbox->addLayout(rightColumn);
|
||||||
|
|
||||||
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||||
connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
connect(buttonBox, SIGNAL(accepted()), this, SLOT(actOk()));
|
||||||
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
||||||
|
|
||||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||||
|
|
@ -94,6 +125,42 @@ DlgFilterGames::DlgFilterGames(const QMap<int, QString> &allGameTypes, QWidget *
|
||||||
setWindowTitle(tr("Filter games"));
|
setWindowTitle(tr("Filter games"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DlgFilterGames::actOk() {
|
||||||
|
QSettings settings;
|
||||||
|
settings.beginGroup("filter_games");
|
||||||
|
settings.setValue(
|
||||||
|
"unavailable_games_visible",
|
||||||
|
unavailableGamesVisibleCheckBox->isChecked()
|
||||||
|
);
|
||||||
|
settings.setValue(
|
||||||
|
"password_protected_games_visible",
|
||||||
|
passwordProtectedGamesVisibleCheckBox->isChecked()
|
||||||
|
);
|
||||||
|
settings.setValue("game_name_filter", gameNameFilterEdit->text());
|
||||||
|
settings.setValue("creator_name_filter", creatorNameFilterEdit->text());
|
||||||
|
|
||||||
|
QMapIterator<int, QString> gameTypeIterator(allGameTypes);
|
||||||
|
QMapIterator<int, QCheckBox *> checkboxIterator(gameTypeFilterCheckBoxes);
|
||||||
|
while (gameTypeIterator.hasNext()) {
|
||||||
|
gameTypeIterator.next();
|
||||||
|
checkboxIterator.next();
|
||||||
|
|
||||||
|
settings.setValue(
|
||||||
|
"game_type/" + hashGameType(gameTypeIterator.value()),
|
||||||
|
checkboxIterator.value()->isChecked()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.setValue("min_players", maxPlayersFilterMinSpinBox->value());
|
||||||
|
settings.setValue("max_players", maxPlayersFilterMaxSpinBox->value());
|
||||||
|
|
||||||
|
accept();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString DlgFilterGames::hashGameType(const QString &gameType) const {
|
||||||
|
return QCryptographicHash::hash(gameType.toUtf8(), QCryptographicHash::Md5).toHex();
|
||||||
|
}
|
||||||
|
|
||||||
bool DlgFilterGames::getUnavailableGamesVisible() const
|
bool DlgFilterGames::getUnavailableGamesVisible() const
|
||||||
{
|
{
|
||||||
return unavailableGamesVisibleCheckBox->isChecked();
|
return unavailableGamesVisibleCheckBox->isChecked();
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,16 @@ private:
|
||||||
QMap<int, QCheckBox *> gameTypeFilterCheckBoxes;
|
QMap<int, QCheckBox *> gameTypeFilterCheckBoxes;
|
||||||
QSpinBox *maxPlayersFilterMinSpinBox;
|
QSpinBox *maxPlayersFilterMinSpinBox;
|
||||||
QSpinBox *maxPlayersFilterMaxSpinBox;
|
QSpinBox *maxPlayersFilterMaxSpinBox;
|
||||||
|
|
||||||
|
const QMap<int, QString> &allGameTypes;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The game type might contain special characters, so to use it in
|
||||||
|
* QSettings we just hash it.
|
||||||
|
*/
|
||||||
|
QString hashGameType(const QString &gameType) const;
|
||||||
|
private slots:
|
||||||
|
void actOk();
|
||||||
public:
|
public:
|
||||||
DlgFilterGames(const QMap<int, QString> &allGameTypes, QWidget *parent = 0);
|
DlgFilterGames(const QMap<int, QString> &allGameTypes, QWidget *parent = 0);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,11 +18,13 @@
|
||||||
#include <QInputDialog>
|
#include <QInputDialog>
|
||||||
#include <QSpinBox>
|
#include <QSpinBox>
|
||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
|
#include <QRadioButton>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include "carddatabase.h"
|
#include "carddatabase.h"
|
||||||
#include "dlg_settings.h"
|
#include "dlg_settings.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "settingscache.h"
|
#include "settingscache.h"
|
||||||
|
#include "priceupdater.h"
|
||||||
|
|
||||||
GeneralSettingsPage::GeneralSettingsPage()
|
GeneralSettingsPage::GeneralSettingsPage()
|
||||||
{
|
{
|
||||||
|
|
@ -532,8 +534,29 @@ DeckEditorSettingsPage::DeckEditorSettingsPage()
|
||||||
priceTagsCheckBox->setChecked(settingsCache->getPriceTagFeature());
|
priceTagsCheckBox->setChecked(settingsCache->getPriceTagFeature());
|
||||||
connect(priceTagsCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setPriceTagFeature(int)));
|
connect(priceTagsCheckBox, SIGNAL(stateChanged(int)), settingsCache, SLOT(setPriceTagFeature(int)));
|
||||||
|
|
||||||
|
priceTagSource0 = new QRadioButton;
|
||||||
|
priceTagSource1 = new QRadioButton;
|
||||||
|
|
||||||
|
switch(settingsCache->getPriceTagSource())
|
||||||
|
{
|
||||||
|
case AbstractPriceUpdater::DBPriceSource:
|
||||||
|
priceTagSource1->setChecked(true);
|
||||||
|
break;
|
||||||
|
case AbstractPriceUpdater::BLPPriceSource:
|
||||||
|
default:
|
||||||
|
priceTagSource0->setChecked(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
connect(priceTagSource0, SIGNAL(toggled(bool)), this, SLOT(radioPriceTagSourceClicked(bool)));
|
||||||
|
connect(priceTagSource1, SIGNAL(toggled(bool)), this, SLOT(radioPriceTagSourceClicked(bool)));
|
||||||
|
|
||||||
|
connect(this, SIGNAL(priceTagSourceChanged(int)), settingsCache, SLOT(setPriceTagSource(int)));
|
||||||
|
|
||||||
QGridLayout *generalGrid = new QGridLayout;
|
QGridLayout *generalGrid = new QGridLayout;
|
||||||
generalGrid->addWidget(priceTagsCheckBox, 0, 0);
|
generalGrid->addWidget(priceTagsCheckBox, 0, 0);
|
||||||
|
generalGrid->addWidget(priceTagSource0, 1, 0);
|
||||||
|
generalGrid->addWidget(priceTagSource1, 2, 0);
|
||||||
|
|
||||||
generalGroupBox = new QGroupBox;
|
generalGroupBox = new QGroupBox;
|
||||||
generalGroupBox->setLayout(generalGrid);
|
generalGroupBox->setLayout(generalGrid);
|
||||||
|
|
@ -546,10 +569,26 @@ DeckEditorSettingsPage::DeckEditorSettingsPage()
|
||||||
|
|
||||||
void DeckEditorSettingsPage::retranslateUi()
|
void DeckEditorSettingsPage::retranslateUi()
|
||||||
{
|
{
|
||||||
priceTagsCheckBox->setText(tr("Enable &price tag feature (using data from blacklotusproject.com)"));
|
priceTagsCheckBox->setText(tr("Enable &price tag feature"));
|
||||||
|
priceTagSource0->setText(tr("using data from blacklotusproject.com"));
|
||||||
|
priceTagSource1->setText(tr("using data from deckbrew.com"));
|
||||||
generalGroupBox->setTitle(tr("General"));
|
generalGroupBox->setTitle(tr("General"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DeckEditorSettingsPage::radioPriceTagSourceClicked(bool checked)
|
||||||
|
{
|
||||||
|
if(!checked)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int source=AbstractPriceUpdater::BLPPriceSource;
|
||||||
|
if(priceTagSource0->isChecked())
|
||||||
|
source=AbstractPriceUpdater::BLPPriceSource;
|
||||||
|
if(priceTagSource1->isChecked())
|
||||||
|
source=AbstractPriceUpdater::DBPriceSource;
|
||||||
|
|
||||||
|
emit priceTagSourceChanged(source);
|
||||||
|
}
|
||||||
|
|
||||||
MessagesSettingsPage::MessagesSettingsPage()
|
MessagesSettingsPage::MessagesSettingsPage()
|
||||||
{
|
{
|
||||||
aAdd = new QAction(this);
|
aAdd = new QAction(this);
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ class QCheckBox;
|
||||||
class QLabel;
|
class QLabel;
|
||||||
class QCloseEvent;
|
class QCloseEvent;
|
||||||
class QSpinBox;
|
class QSpinBox;
|
||||||
|
class QRadioButton;
|
||||||
|
|
||||||
class AbstractSettingsPage : public QWidget {
|
class AbstractSettingsPage : public QWidget {
|
||||||
public:
|
public:
|
||||||
|
|
@ -100,8 +101,13 @@ class DeckEditorSettingsPage : public AbstractSettingsPage {
|
||||||
public:
|
public:
|
||||||
DeckEditorSettingsPage();
|
DeckEditorSettingsPage();
|
||||||
void retranslateUi();
|
void retranslateUi();
|
||||||
|
private slots:
|
||||||
|
void radioPriceTagSourceClicked(bool checked);
|
||||||
|
signals:
|
||||||
|
void priceTagSourceChanged(int _priceTagSource);
|
||||||
private:
|
private:
|
||||||
QCheckBox *priceTagsCheckBox;
|
QCheckBox *priceTagsCheckBox;
|
||||||
|
QRadioButton *priceTagSource0, *priceTagSource1;
|
||||||
QGroupBox *generalGroupBox;
|
QGroupBox *generalGroupBox;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,10 @@ public:
|
||||||
virtual void enable() { enabled = true; nodeChanged(); }
|
virtual void enable() { enabled = true; nodeChanged(); }
|
||||||
virtual void disable() { enabled = false; nodeChanged(); }
|
virtual void disable() { enabled = false; nodeChanged(); }
|
||||||
virtual FilterTreeNode *parent() const { return NULL; }
|
virtual FilterTreeNode *parent() const { return NULL; }
|
||||||
virtual FilterTreeNode *nodeAt(int i) const { return NULL; }
|
virtual FilterTreeNode *nodeAt(int /* i */) const { return NULL; }
|
||||||
virtual void deleteAt(int i) {}
|
virtual void deleteAt(int /* i */) {}
|
||||||
virtual int childCount() const { return 0; }
|
virtual int childCount() const { return 0; }
|
||||||
virtual int childIndex(const FilterTreeNode *node) const { return -1; }
|
virtual int childIndex(const FilterTreeNode * /* node */) const { return -1; }
|
||||||
virtual int index() const { return (parent() != NULL)? parent()->childIndex(this) : -1; }
|
virtual int index() const { return (parent() != NULL)? parent()->childIndex(this) : -1; }
|
||||||
virtual QString text() const { return QString(textCStr()); }
|
virtual QString text() const { return QString(textCStr()); }
|
||||||
virtual bool isLeaf() const { return false; }
|
virtual bool isLeaf() const { return false; }
|
||||||
|
|
@ -48,7 +48,7 @@ class FilterTreeBranch : public FilterTreeNode {
|
||||||
protected:
|
protected:
|
||||||
QList<T> childNodes;
|
QList<T> childNodes;
|
||||||
public:
|
public:
|
||||||
~FilterTreeBranch();
|
virtual ~FilterTreeBranch();
|
||||||
FilterTreeNode *nodeAt(int i) const;
|
FilterTreeNode *nodeAt(int i) const;
|
||||||
void deleteAt(int i);
|
void deleteAt(int i);
|
||||||
int childCount() const { return childNodes.size(); }
|
int childCount() const { return childNodes.size(); }
|
||||||
|
|
@ -102,6 +102,7 @@ public:
|
||||||
|
|
||||||
FilterItem(QString trm, FilterItemList *parent)
|
FilterItem(QString trm, FilterItemList *parent)
|
||||||
: p(parent), term(trm) {}
|
: p(parent), term(trm) {}
|
||||||
|
virtual ~FilterItem() {};
|
||||||
|
|
||||||
CardFilter::Attr attr() const { return p->attr(); }
|
CardFilter::Attr attr() const { return p->attr(); }
|
||||||
CardFilter::Type type() const { return p->type; }
|
CardFilter::Type type() const { return p->type; }
|
||||||
|
|
|
||||||
|
|
@ -84,12 +84,6 @@ void GameSelector::actSetFilter()
|
||||||
if (room)
|
if (room)
|
||||||
gameTypeMap = gameListModel->getGameTypes().value(room->getRoomId());
|
gameTypeMap = gameListModel->getGameTypes().value(room->getRoomId());
|
||||||
DlgFilterGames dlg(gameTypeMap, this);
|
DlgFilterGames dlg(gameTypeMap, this);
|
||||||
dlg.setUnavailableGamesVisible(gameListProxyModel->getUnavailableGamesVisible());
|
|
||||||
dlg.setPasswordProtectedGamesVisible(gameListProxyModel->getPasswordProtectedGamesVisible());
|
|
||||||
dlg.setGameNameFilter(gameListProxyModel->getGameNameFilter());
|
|
||||||
dlg.setCreatorNameFilter(gameListProxyModel->getCreatorNameFilter());
|
|
||||||
dlg.setGameTypeFilter(gameListProxyModel->getGameTypeFilter());
|
|
||||||
dlg.setMaxPlayersFilter(gameListProxyModel->getMaxPlayersFilterMin(), gameListProxyModel->getMaxPlayersFilterMax());
|
|
||||||
|
|
||||||
if (!dlg.exec())
|
if (!dlg.exec())
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ ServerInfo_User LocalServer_DatabaseInterface::getUserData(const QString &name,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
AuthenticationResult LocalServer_DatabaseInterface::checkUserPassword(Server_ProtocolHandler *handler, const QString &user, const QString &password, QString &reasonStr, int &secondsLeft)
|
AuthenticationResult LocalServer_DatabaseInterface::checkUserPassword(Server_ProtocolHandler * /* handler */, const QString & /* user */, const QString & /* password */, QString & /* reasonStr */, int & /* secondsLeft */)
|
||||||
{
|
{
|
||||||
return UnknownUser;
|
return UnknownUser;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "window_main.h"
|
#include "window_main.h"
|
||||||
|
|
@ -158,6 +159,8 @@ int main(int argc, char *argv[])
|
||||||
QDir().mkpath(dataDir + "/pics");
|
QDir().mkpath(dataDir + "/pics");
|
||||||
settingsCache->setPicsPath(dataDir + "/pics");
|
settingsCache->setPicsPath(dataDir + "/pics");
|
||||||
}
|
}
|
||||||
|
if (!QDir().mkpath(settingsCache->getPicsPath() + "/CUSTOM"))
|
||||||
|
qDebug() << "Could not create " + settingsCache->getPicsPath().toUtf8() + "/CUSTOM. Will fall back on default card images.";
|
||||||
|
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
if(settingsCache->getHandBgPath().isEmpty() &&
|
if(settingsCache->getHandBgPath().isEmpty() &&
|
||||||
|
|
|
||||||
|
|
@ -959,6 +959,10 @@ void Player::actCreateToken()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
lastTokenName = dlg.getName();
|
lastTokenName = dlg.getName();
|
||||||
|
if (CardInfo *correctedCard = db->getCardBySimpleName(lastTokenName, false)) {
|
||||||
|
lastTokenName = correctedCard->getName();
|
||||||
|
}
|
||||||
|
|
||||||
lastTokenColor = dlg.getColor();
|
lastTokenColor = dlg.getColor();
|
||||||
lastTokenPT = dlg.getPT();
|
lastTokenPT = dlg.getPT();
|
||||||
lastTokenAnnotation = dlg.getAnnotation();
|
lastTokenAnnotation = dlg.getAnnotation();
|
||||||
|
|
|
||||||
|
|
@ -178,5 +178,5 @@ void PlayerListWidget::showContextMenu(const QPoint &pos, const QModelIndex &ind
|
||||||
int playerId = index.sibling(index.row(), 4).data(Qt::UserRole + 1).toInt();
|
int playerId = index.sibling(index.row(), 4).data(Qt::UserRole + 1).toInt();
|
||||||
UserLevelFlags userLevel(index.sibling(index.row(), 3).data(Qt::UserRole).toInt());
|
UserLevelFlags userLevel(index.sibling(index.row(), 3).data(Qt::UserRole).toInt());
|
||||||
|
|
||||||
userContextMenu->showContextMenu(pos, userName, userLevel, playerId);
|
userContextMenu->showContextMenu(pos, userName, userLevel, true, playerId);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,25 +4,46 @@
|
||||||
*/
|
*/
|
||||||
#include <QNetworkAccessManager>
|
#include <QNetworkAccessManager>
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
#include "qt-json/json.h"
|
#include "qt-json/json.h"
|
||||||
#include "priceupdater.h"
|
#include "priceupdater.h"
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "carddatabase.h"
|
||||||
|
|
||||||
|
#if QT_VERSION < 0x050000
|
||||||
|
// for Qt::escape()
|
||||||
|
#include <QtGui/qtextdocument.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*
|
*
|
||||||
* @param _deck deck.
|
* @param _deck deck.
|
||||||
*/
|
*/
|
||||||
PriceUpdater::PriceUpdater(const DeckList *_deck)
|
AbstractPriceUpdater::AbstractPriceUpdater(const DeckList *_deck)
|
||||||
{
|
{
|
||||||
nam = new QNetworkAccessManager(this);
|
nam = new QNetworkAccessManager(this);
|
||||||
deck = _deck;
|
deck = _deck;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// blacklotusproject.com
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param _deck deck.
|
||||||
|
*/
|
||||||
|
BLPPriceUpdater::BLPPriceUpdater(const DeckList *_deck)
|
||||||
|
: AbstractPriceUpdater(_deck)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the prices of the cards in deckList.
|
* Update the prices of the cards in deckList.
|
||||||
*/
|
*/
|
||||||
void PriceUpdater::updatePrices()
|
void BLPPriceUpdater::updatePrices()
|
||||||
{
|
{
|
||||||
QString q = "http://blacklotusproject.com/json/?cards=";
|
QString q = "http://blacklotusproject.com/json/?cards=";
|
||||||
QStringList cards = deck->getCardList();
|
QStringList cards = deck->getCardList();
|
||||||
|
|
@ -38,7 +59,7 @@ void PriceUpdater::updatePrices()
|
||||||
/**
|
/**
|
||||||
* Called when the download of the json file with the prices is finished.
|
* Called when the download of the json file with the prices is finished.
|
||||||
*/
|
*/
|
||||||
void PriceUpdater::downloadFinished()
|
void BLPPriceUpdater::downloadFinished()
|
||||||
{
|
{
|
||||||
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
|
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
|
||||||
bool ok;
|
bool ok;
|
||||||
|
|
@ -82,3 +103,188 @@ void PriceUpdater::downloadFinished()
|
||||||
deleteLater();
|
deleteLater();
|
||||||
emit finishedUpdate();
|
emit finishedUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// deckbrew.com
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param _deck deck.
|
||||||
|
*/
|
||||||
|
DBPriceUpdater::DBPriceUpdater(const DeckList *_deck)
|
||||||
|
: AbstractPriceUpdater(_deck)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the prices of the cards in deckList.
|
||||||
|
*/
|
||||||
|
void DBPriceUpdater::updatePrices()
|
||||||
|
{
|
||||||
|
QString base = "https://api.deckbrew.com/mtg/cards", q = "";
|
||||||
|
QStringList cards = deck->getCardList();
|
||||||
|
muidMap.clear();
|
||||||
|
urls.clear();
|
||||||
|
CardInfo * card;
|
||||||
|
int muid;
|
||||||
|
SetList sets;
|
||||||
|
bool bNotFirst=false;
|
||||||
|
|
||||||
|
for (int i = 0; i < cards.size(); ++i) {
|
||||||
|
card = db->getCard(cards[i], false);
|
||||||
|
sets = card->getSets();
|
||||||
|
for(int j = 0; j < sets.size(); ++j)
|
||||||
|
{
|
||||||
|
muid=card->getMuId(sets[j]->getShortName());
|
||||||
|
|
||||||
|
if (!muid) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//qDebug() << "muid " << muid << " card: " << cards[i] << endl;
|
||||||
|
if(bNotFirst)
|
||||||
|
{
|
||||||
|
q += QString("&m=%1").arg(muid);
|
||||||
|
} else {
|
||||||
|
q += QString("?m=%1").arg(muid);
|
||||||
|
bNotFirst = true;
|
||||||
|
}
|
||||||
|
muidMap.insert(muid, cards[i]);
|
||||||
|
|
||||||
|
if(q.length() > 240)
|
||||||
|
{
|
||||||
|
urls.append(base + q);
|
||||||
|
bNotFirst=false;
|
||||||
|
q = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(q.length() > 0)
|
||||||
|
urls.append(base + q);
|
||||||
|
|
||||||
|
requestNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DBPriceUpdater::requestNext()
|
||||||
|
{
|
||||||
|
if(urls.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
QUrl url(urls.takeFirst(), QUrl::TolerantMode);
|
||||||
|
//qDebug() << "request prices from: " << url.toString() << endl;
|
||||||
|
QNetworkReply *reply = nam->get(QNetworkRequest(url));
|
||||||
|
connect(reply, SIGNAL(finished()), this, SLOT(downloadFinished()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the download of the json file with the prices is finished.
|
||||||
|
*/
|
||||||
|
void DBPriceUpdater::downloadFinished()
|
||||||
|
{
|
||||||
|
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
|
||||||
|
bool ok;
|
||||||
|
QString tmp = QString(reply->readAll());
|
||||||
|
|
||||||
|
// Errors are incapsulated in an object, check for them first
|
||||||
|
QVariantMap resultMap = QtJson::Json::parse(tmp, ok).toMap();
|
||||||
|
if (!ok) {
|
||||||
|
QMessageBox::critical(this, tr("Error"), tr("A problem has occured while fetching card prices."));
|
||||||
|
reply->deleteLater();
|
||||||
|
if(urls.isEmpty())
|
||||||
|
{
|
||||||
|
deleteLater();
|
||||||
|
emit finishedUpdate();
|
||||||
|
} else {
|
||||||
|
requestNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(resultMap.contains("errors"))
|
||||||
|
{
|
||||||
|
QMessageBox::critical(this, tr("Error"), tr("A problem has occured while fetching card prices:") +
|
||||||
|
"<br/>" +
|
||||||
|
#if QT_VERSION < 0x050000
|
||||||
|
Qt::escape(resultMap["errors"].toList().first().toString())
|
||||||
|
#else
|
||||||
|
resultMap["errors"].toList().first().toString().toHtmlEscaped()
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
reply->deleteLater();
|
||||||
|
if(urls.isEmpty())
|
||||||
|
{
|
||||||
|
deleteLater();
|
||||||
|
emit finishedUpdate();
|
||||||
|
} else {
|
||||||
|
requestNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Good results are a list
|
||||||
|
QVariantList resultList = QtJson::Json::parse(tmp, ok).toList();
|
||||||
|
if (!ok) {
|
||||||
|
QMessageBox::critical(this, tr("Error"), tr("A problem has occured while fetching card prices."));
|
||||||
|
reply->deleteLater();
|
||||||
|
if(urls.isEmpty())
|
||||||
|
{
|
||||||
|
deleteLater();
|
||||||
|
emit finishedUpdate();
|
||||||
|
} else {
|
||||||
|
requestNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QMap<QString, float> cardsPrice;
|
||||||
|
QListIterator<QVariant> it(resultList);
|
||||||
|
while (it.hasNext()) {
|
||||||
|
QVariantMap cardMap = it.next().toMap();
|
||||||
|
|
||||||
|
|
||||||
|
// get sets list
|
||||||
|
QList<QVariant> editions = cardMap.value("editions").toList();
|
||||||
|
foreach (QVariant ed, editions)
|
||||||
|
{
|
||||||
|
// retrieve card name "as we know it" from the muid
|
||||||
|
QVariantMap edition = ed.toMap();
|
||||||
|
QString set = edition.value("set_id").toString();
|
||||||
|
|
||||||
|
int muid = edition.value("multiverse_id").toString().toInt();
|
||||||
|
if(!muidMap.contains(muid))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
QString name=muidMap.value(muid);
|
||||||
|
// Prices are in USD cents
|
||||||
|
float price = edition.value("price").toMap().value("median").toString().toFloat() / 100;
|
||||||
|
//qDebug() << "card " << name << " set " << set << " price " << price << endl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make sure Masters Edition (MED) isn't the set, as it doesn't
|
||||||
|
* physically exist. Also check the price to see that the cheapest set
|
||||||
|
* ends up as the final price.
|
||||||
|
*/
|
||||||
|
if (set != "MED" && price > 0 && (!cardsPrice.contains(name) || cardsPrice.value(name) > price))
|
||||||
|
cardsPrice.insert(name, price);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InnerDecklistNode *listRoot = deck->getRoot();
|
||||||
|
for (int i = 0; i < listRoot->size(); i++) {
|
||||||
|
InnerDecklistNode *currentZone = dynamic_cast<InnerDecklistNode *>(listRoot->at(i));
|
||||||
|
for (int j = 0; j < currentZone->size(); j++) {
|
||||||
|
DecklistCardNode *currentCard = dynamic_cast<DecklistCardNode *>(currentZone->at(j));
|
||||||
|
if (!currentCard)
|
||||||
|
continue;
|
||||||
|
float price = cardsPrice[currentCard->getName()];
|
||||||
|
if(price > 0)
|
||||||
|
currentCard->setPrice(price);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reply->deleteLater();
|
||||||
|
if(urls.isEmpty())
|
||||||
|
{
|
||||||
|
deleteLater();
|
||||||
|
emit finishedUpdate();
|
||||||
|
} else {
|
||||||
|
requestNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,57 @@
|
||||||
#ifndef PRICEUPDATER_H
|
#ifndef PRICEUPDATER_H
|
||||||
#define PRICEUPDATER_H
|
#define PRICEUPDATER_H
|
||||||
|
|
||||||
#include <QNetworkReply>
|
#include <QNetworkAccessManager>
|
||||||
#include "decklist.h"
|
#include "decklist.h"
|
||||||
|
|
||||||
class QNetworkAccessManager;
|
class QNetworkAccessManager;
|
||||||
|
|
||||||
|
// If we don't typedef this, won't compile on OS X < 10.9
|
||||||
|
typedef QMap<int, QString> MuidStringMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Price Updater.
|
* Price Updater.
|
||||||
*
|
*
|
||||||
* @author Marcio Ribeiro <mmr@b1n.org>
|
* @author Marcio Ribeiro <mmr@b1n.org>
|
||||||
*/
|
*/
|
||||||
class PriceUpdater : public QObject
|
class AbstractPriceUpdater : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
private:
|
public:
|
||||||
|
enum PriceSource { BLPPriceSource, DBPriceSource };
|
||||||
|
protected:
|
||||||
const DeckList *deck;
|
const DeckList *deck;
|
||||||
QNetworkAccessManager *nam;
|
QNetworkAccessManager *nam;
|
||||||
signals:
|
signals:
|
||||||
void finishedUpdate();
|
void finishedUpdate();
|
||||||
private slots:
|
protected slots:
|
||||||
void downloadFinished();
|
virtual void downloadFinished() = 0;
|
||||||
public:
|
public:
|
||||||
PriceUpdater(const DeckList *deck);
|
AbstractPriceUpdater(const DeckList *deck);
|
||||||
void updatePrices();
|
virtual void updatePrices() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BLPPriceUpdater : public AbstractPriceUpdater
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
protected:
|
||||||
|
virtual void downloadFinished();
|
||||||
|
public:
|
||||||
|
BLPPriceUpdater(const DeckList *deck);
|
||||||
|
virtual void updatePrices();
|
||||||
|
};
|
||||||
|
|
||||||
|
class DBPriceUpdater : public AbstractPriceUpdater
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
protected:
|
||||||
|
MuidStringMap muidMap;
|
||||||
|
QList<QString> urls;
|
||||||
|
protected:
|
||||||
|
virtual void downloadFinished();
|
||||||
|
void requestNext();
|
||||||
|
public:
|
||||||
|
DBPriceUpdater(const DeckList *deck);
|
||||||
|
virtual void updatePrices();
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ void ReplayTimelineWidget::setTimeline(const QList<int> &_replayTimeline)
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReplayTimelineWidget::paintEvent(QPaintEvent *event)
|
void ReplayTimelineWidget::paintEvent(QPaintEvent * /* event */)
|
||||||
{
|
{
|
||||||
QPainter painter(this);
|
QPainter painter(this);
|
||||||
painter.drawRect(0, 0, width() - 1, height() - 1);
|
painter.drawRect(0, 0, width() - 1, height() - 1);
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ SettingsCache::SettingsCache()
|
||||||
soundPath = settings->value("sound/path").toString();
|
soundPath = settings->value("sound/path").toString();
|
||||||
|
|
||||||
priceTagFeature = settings->value("deckeditor/pricetags", false).toBool();
|
priceTagFeature = settings->value("deckeditor/pricetags", false).toBool();
|
||||||
|
priceTagSource = settings->value("deckeditor/pricetagsource", 0).toInt();
|
||||||
|
|
||||||
ignoreUnregisteredUsers = settings->value("chat/ignore_unregistered", false).toBool();
|
ignoreUnregisteredUsers = settings->value("chat/ignore_unregistered", false).toBool();
|
||||||
}
|
}
|
||||||
|
|
@ -247,6 +248,12 @@ void SettingsCache::setPriceTagFeature(int _priceTagFeature)
|
||||||
emit priceTagFeatureChanged(priceTagFeature);
|
emit priceTagFeatureChanged(priceTagFeature);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SettingsCache::setPriceTagSource(int _priceTagSource)
|
||||||
|
{
|
||||||
|
priceTagSource = _priceTagSource;
|
||||||
|
settings->setValue("deckeditor/pricetagsource", priceTagSource);
|
||||||
|
}
|
||||||
|
|
||||||
void SettingsCache::setIgnoreUnregisteredUsers(bool _ignoreUnregisteredUsers)
|
void SettingsCache::setIgnoreUnregisteredUsers(bool _ignoreUnregisteredUsers)
|
||||||
{
|
{
|
||||||
ignoreUnregisteredUsers = _ignoreUnregisteredUsers;
|
ignoreUnregisteredUsers = _ignoreUnregisteredUsers;
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@ private:
|
||||||
bool soundEnabled;
|
bool soundEnabled;
|
||||||
QString soundPath;
|
QString soundPath;
|
||||||
bool priceTagFeature;
|
bool priceTagFeature;
|
||||||
|
int priceTagSource;
|
||||||
bool ignoreUnregisteredUsers;
|
bool ignoreUnregisteredUsers;
|
||||||
QString picUrl;
|
QString picUrl;
|
||||||
QString picUrlHq;
|
QString picUrlHq;
|
||||||
|
|
@ -87,6 +88,7 @@ public:
|
||||||
bool getSoundEnabled() const { return soundEnabled; }
|
bool getSoundEnabled() const { return soundEnabled; }
|
||||||
QString getSoundPath() const { return soundPath; }
|
QString getSoundPath() const { return soundPath; }
|
||||||
bool getPriceTagFeature() const { return priceTagFeature; }
|
bool getPriceTagFeature() const { return priceTagFeature; }
|
||||||
|
int getPriceTagSource() const { return priceTagSource; }
|
||||||
bool getIgnoreUnregisteredUsers() const { return ignoreUnregisteredUsers; }
|
bool getIgnoreUnregisteredUsers() const { return ignoreUnregisteredUsers; }
|
||||||
QString getPicUrl() const { return picUrl; }
|
QString getPicUrl() const { return picUrl; }
|
||||||
QString getPicUrlHq() const { return picUrlHq; }
|
QString getPicUrlHq() const { return picUrlHq; }
|
||||||
|
|
@ -121,6 +123,7 @@ public slots:
|
||||||
void setSoundEnabled(int _soundEnabled);
|
void setSoundEnabled(int _soundEnabled);
|
||||||
void setSoundPath(const QString &_soundPath);
|
void setSoundPath(const QString &_soundPath);
|
||||||
void setPriceTagFeature(int _priceTagFeature);
|
void setPriceTagFeature(int _priceTagFeature);
|
||||||
|
void setPriceTagSource(int _priceTagSource);
|
||||||
void setIgnoreUnregisteredUsers(bool _ignoreUnregisteredUsers);
|
void setIgnoreUnregisteredUsers(bool _ignoreUnregisteredUsers);
|
||||||
void setPicUrl(const QString &_picUrl);
|
void setPicUrl(const QString &_picUrl);
|
||||||
void setPicUrlHq(const QString &_picUrlHq);
|
void setPicUrlHq(const QString &_picUrlHq);
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ public:
|
||||||
virtual QString getTabText() const = 0;
|
virtual QString getTabText() const = 0;
|
||||||
virtual void retranslateUi() = 0;
|
virtual void retranslateUi() = 0;
|
||||||
virtual void closeRequest() { }
|
virtual void closeRequest() { }
|
||||||
|
virtual void tabActivated() { }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -512,7 +512,10 @@ void TabDeckEditor::actPrintDeck()
|
||||||
|
|
||||||
void TabDeckEditor::actAnalyzeDeck()
|
void TabDeckEditor::actAnalyzeDeck()
|
||||||
{
|
{
|
||||||
DeckStatsInterface *interface = new DeckStatsInterface(this); // it deletes itself when done
|
DeckStatsInterface *interface = new DeckStatsInterface(
|
||||||
|
*databaseModel->getDatabase(),
|
||||||
|
this
|
||||||
|
); // it deletes itself when done
|
||||||
interface->analyzeDeck(deckModel->getDeckList());
|
interface->analyzeDeck(deckModel->getDeckList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -643,12 +646,25 @@ void TabDeckEditor::actDecrement()
|
||||||
void TabDeckEditor::setPriceTagFeatureEnabled(int enabled)
|
void TabDeckEditor::setPriceTagFeatureEnabled(int enabled)
|
||||||
{
|
{
|
||||||
aUpdatePrices->setVisible(enabled);
|
aUpdatePrices->setVisible(enabled);
|
||||||
|
deckModel->pricesUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabDeckEditor::actUpdatePrices()
|
void TabDeckEditor::actUpdatePrices()
|
||||||
{
|
{
|
||||||
aUpdatePrices->setDisabled(true);
|
aUpdatePrices->setDisabled(true);
|
||||||
PriceUpdater *up = new PriceUpdater(deckModel->getDeckList());
|
AbstractPriceUpdater *up;
|
||||||
|
|
||||||
|
switch(settingsCache->getPriceTagSource())
|
||||||
|
{
|
||||||
|
case AbstractPriceUpdater::DBPriceSource:
|
||||||
|
up = new DBPriceUpdater(deckModel->getDeckList());
|
||||||
|
break;
|
||||||
|
case AbstractPriceUpdater::BLPPriceSource:
|
||||||
|
default:
|
||||||
|
up = new BLPPriceUpdater(deckModel->getDeckList());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
connect(up, SIGNAL(finishedUpdate()), this, SLOT(finishedUpdatingPrices()));
|
connect(up, SIGNAL(finishedUpdate()), this, SLOT(finishedUpdatingPrices()));
|
||||||
up->updatePrices();
|
up->updatePrices();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -255,7 +255,7 @@ TabGame::TabGame(TabSupervisor *_tabSupervisor, GameReplay *_replay)
|
||||||
|
|
||||||
// Create list: event number -> time [ms]
|
// Create list: event number -> time [ms]
|
||||||
// Distribute simultaneous events evenly across 1 second.
|
// Distribute simultaneous events evenly across 1 second.
|
||||||
int lastEventTimestamp = -1;
|
unsigned int lastEventTimestamp = 0;
|
||||||
const int eventCount = replay->event_list_size();
|
const int eventCount = replay->event_list_size();
|
||||||
for (int i = 0; i < eventCount; ++i) {
|
for (int i = 0; i < eventCount; ++i) {
|
||||||
int j = i + 1;
|
int j = i + 1;
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,12 @@ void TabMessage::retranslateUi()
|
||||||
aLeave->setText(tr("&Leave"));
|
aLeave->setText(tr("&Leave"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TabMessage::tabActivated()
|
||||||
|
{
|
||||||
|
if(!sayEdit->hasFocus())
|
||||||
|
sayEdit->setFocus();
|
||||||
|
}
|
||||||
|
|
||||||
QString TabMessage::getUserName() const
|
QString TabMessage::getUserName() const
|
||||||
{
|
{
|
||||||
return QString::fromStdString(otherUserInfo->name());
|
return QString::fromStdString(otherUserInfo->name());
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ public:
|
||||||
~TabMessage();
|
~TabMessage();
|
||||||
void retranslateUi();
|
void retranslateUi();
|
||||||
void closeRequest();
|
void closeRequest();
|
||||||
|
void tabActivated();
|
||||||
QString getUserName() const;
|
QString getUserName() const;
|
||||||
QString getTabText() const;
|
QString getTabText() const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -202,7 +202,7 @@ void TabReplays::actDownload()
|
||||||
client->sendCommand(pend);
|
client->sendCommand(pend);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabReplays::downloadFinished(const Response &r, const CommandContainer &commandContainer, const QVariant &extraData)
|
void TabReplays::downloadFinished(const Response &r, const CommandContainer & /* commandContainer */, const QVariant &extraData)
|
||||||
{
|
{
|
||||||
if (r.response_code() != Response::RespOk)
|
if (r.response_code() != Response::RespOk)
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -121,6 +121,12 @@ void TabRoom::closeRequest()
|
||||||
actLeaveRoom();
|
actLeaveRoom();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TabRoom::tabActivated()
|
||||||
|
{
|
||||||
|
if(!sayEdit->hasFocus())
|
||||||
|
sayEdit->setFocus();
|
||||||
|
}
|
||||||
|
|
||||||
QString TabRoom::sanitizeHtml(QString dirty) const
|
QString TabRoom::sanitizeHtml(QString dirty) const
|
||||||
{
|
{
|
||||||
return dirty
|
return dirty
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,7 @@ public:
|
||||||
~TabRoom();
|
~TabRoom();
|
||||||
void retranslateUi();
|
void retranslateUi();
|
||||||
void closeRequest();
|
void closeRequest();
|
||||||
|
void tabActivated();
|
||||||
void processRoomEvent(const RoomEvent &event);
|
void processRoomEvent(const RoomEvent &event);
|
||||||
int getRoomId() const { return roomId; }
|
int getRoomId() const { return roomId; }
|
||||||
const QMap<int, QString> &getGameTypes() const { return gameTypes; }
|
const QMap<int, QString> &getGameTypes() const { return gameTypes; }
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ void CloseButton::paintEvent(QPaintEvent * /*event*/)
|
||||||
}
|
}
|
||||||
|
|
||||||
TabSupervisor::TabSupervisor(AbstractClient *_client, QWidget *parent)
|
TabSupervisor::TabSupervisor(AbstractClient *_client, QWidget *parent)
|
||||||
: QTabWidget(parent), userInfo(0), client(_client), tabUserLists(0), tabServer(0), tabDeckStorage(0), tabAdmin(0), tabReplays(0)
|
: QTabWidget(parent), userInfo(0), client(_client), tabServer(0), tabUserLists(0), tabDeckStorage(0), tabReplays(0), tabAdmin(0)
|
||||||
{
|
{
|
||||||
tabChangedIcon = new QIcon(":/resources/icon_tab_changed.svg");
|
tabChangedIcon = new QIcon(":/resources/icon_tab_changed.svg");
|
||||||
setElideMode(Qt::ElideRight);
|
setElideMode(Qt::ElideRight);
|
||||||
|
|
@ -479,6 +479,7 @@ void TabSupervisor::updateCurrent(int index)
|
||||||
tab->setContentsChanged(false);
|
tab->setContentsChanged(false);
|
||||||
}
|
}
|
||||||
emit setMenu(static_cast<Tab *>(widget(index))->getTabMenus());
|
emit setMenu(static_cast<Tab *>(widget(index))->getTabMenus());
|
||||||
|
tab->tabActivated();
|
||||||
} else
|
} else
|
||||||
emit setMenu();
|
emit setMenu();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ void UserContextMenu::banUser_dialogFinished()
|
||||||
client->sendCommand(client->prepareModeratorCommand(cmd));
|
client->sendCommand(client->prepareModeratorCommand(cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserContextMenu::showContextMenu(const QPoint &pos, const QString &userName, UserLevelFlags userLevel, int playerId)
|
void UserContextMenu::showContextMenu(const QPoint &pos, const QString &userName, UserLevelFlags userLevel, bool online, int playerId)
|
||||||
{
|
{
|
||||||
aUserName->setText(userName);
|
aUserName->setText(userName);
|
||||||
|
|
||||||
|
|
@ -132,7 +132,8 @@ void UserContextMenu::showContextMenu(const QPoint &pos, const QString &userName
|
||||||
menu->addAction(aBan);
|
menu->addAction(aBan);
|
||||||
}
|
}
|
||||||
bool anotherUser = userName != QString::fromStdString(tabSupervisor->getUserInfo()->name());
|
bool anotherUser = userName != QString::fromStdString(tabSupervisor->getUserInfo()->name());
|
||||||
aChat->setEnabled(anotherUser);
|
aDetails->setEnabled(online);
|
||||||
|
aChat->setEnabled(anotherUser && online);
|
||||||
aShowGames->setEnabled(anotherUser);
|
aShowGames->setEnabled(anotherUser);
|
||||||
aAddToBuddyList->setEnabled(anotherUser);
|
aAddToBuddyList->setEnabled(anotherUser);
|
||||||
aRemoveFromBuddyList->setEnabled(anotherUser);
|
aRemoveFromBuddyList->setEnabled(anotherUser);
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ private slots:
|
||||||
public:
|
public:
|
||||||
UserContextMenu(const TabSupervisor *_tabSupervisor, QWidget *_parent, TabGame *_game = 0);
|
UserContextMenu(const TabSupervisor *_tabSupervisor, QWidget *_parent, TabGame *_game = 0);
|
||||||
void retranslateUi();
|
void retranslateUi();
|
||||||
void showContextMenu(const QPoint &pos, const QString &userName, UserLevelFlags userLevel, int playerId = -1);
|
void showContextMenu(const QPoint &pos, const QString &userName, UserLevelFlags userLevel, bool online = true, int playerId = -1);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -311,8 +311,9 @@ void UserList::userClicked(QTreeWidgetItem *item, int /*column*/)
|
||||||
void UserList::showContextMenu(const QPoint &pos, const QModelIndex &index)
|
void UserList::showContextMenu(const QPoint &pos, const QModelIndex &index)
|
||||||
{
|
{
|
||||||
const ServerInfo_User &userInfo = static_cast<UserListTWI *>(userTree->topLevelItem(index.row()))->getUserInfo();
|
const ServerInfo_User &userInfo = static_cast<UserListTWI *>(userTree->topLevelItem(index.row()))->getUserInfo();
|
||||||
|
bool online = index.sibling(index.row(), 0).data(Qt::UserRole + 1).toBool();
|
||||||
|
|
||||||
userContextMenu->showContextMenu(pos, QString::fromStdString(userInfo.name()), UserLevelFlags(userInfo.user_level()));
|
userContextMenu->showContextMenu(pos, QString::fromStdString(userInfo.name()), UserLevelFlags(userInfo.user_level()), online);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserList::sortItems()
|
void UserList::sortItems()
|
||||||
|
|
|
||||||
|
|
@ -241,7 +241,7 @@ void MainWindow::loginError(Response::ResponseCode r, QString reasonStr, quint32
|
||||||
{
|
{
|
||||||
switch (r) {
|
switch (r) {
|
||||||
case Response::RespWrongPassword:
|
case Response::RespWrongPassword:
|
||||||
QMessageBox::critical(this, tr("Error"), tr("Invalid login data."));
|
QMessageBox::critical(this, tr("Error"), tr("Incorrect username or password. Please check your authentication information and try again."));
|
||||||
break;
|
break;
|
||||||
case Response::RespWouldOverwriteOldSession:
|
case Response::RespWouldOverwriteOldSession:
|
||||||
QMessageBox::critical(this, tr("Error"), tr("There is already an active session using this user name.\nPlease close that session first and re-login."));
|
QMessageBox::critical(this, tr("Error"), tr("There is already an active session using this user name.\nPlease close that session first and re-login."));
|
||||||
|
|
|
||||||
|
|
@ -355,7 +355,8 @@ DeckList::DeckList()
|
||||||
|
|
||||||
// TODO: http://qt-project.org/doc/qt-4.8/qobject.html#no-copy-constructor-or-assignment-operator
|
// TODO: http://qt-project.org/doc/qt-4.8/qobject.html#no-copy-constructor-or-assignment-operator
|
||||||
DeckList::DeckList(const DeckList &other)
|
DeckList::DeckList(const DeckList &other)
|
||||||
: name(other.name),
|
: QObject(),
|
||||||
|
name(other.name),
|
||||||
comments(other.comments),
|
comments(other.comments),
|
||||||
deckHash(other.deckHash)
|
deckHash(other.deckHash)
|
||||||
{
|
{
|
||||||
|
|
@ -547,14 +548,21 @@ bool DeckList::loadFromStream_Plain(QTextStream &in)
|
||||||
line.remove(rx);
|
line.remove(rx);
|
||||||
line = line.simplified();
|
line = line.simplified();
|
||||||
|
|
||||||
|
|
||||||
int i = line.indexOf(' ');
|
int i = line.indexOf(' ');
|
||||||
|
int cardNameStart = i + 1;
|
||||||
|
|
||||||
|
// If the count ends with an 'x', ignore it. For example,
|
||||||
|
// "4x Storm Crow" will count 4 correctly.
|
||||||
|
if (i > 0 && line[i - 1] == 'x') {
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
|
||||||
bool ok;
|
bool ok;
|
||||||
int number = line.left(i).toInt(&ok);
|
int number = line.left(i).toInt(&ok);
|
||||||
if (!ok)
|
if (!ok)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
QString cardName = line.mid(i + 1);
|
QString cardName = line.mid(cardNameStart);
|
||||||
// Common differences between cockatrice's card names
|
// Common differences between cockatrice's card names
|
||||||
// and what's commonly used in decklists
|
// and what's commonly used in decklists
|
||||||
rx.setPattern("’");
|
rx.setPattern("’");
|
||||||
|
|
@ -563,9 +571,20 @@ bool DeckList::loadFromStream_Plain(QTextStream &in)
|
||||||
cardName.replace(rx, "AE");
|
cardName.replace(rx, "AE");
|
||||||
rx.setPattern("^Aether");
|
rx.setPattern("^Aether");
|
||||||
cardName.replace(rx, "AEther");
|
cardName.replace(rx, "AEther");
|
||||||
rx.setPattern("\\s*[&|/]{1,2}\\s*");
|
rx.setPattern("\\s*[|/]{1,2}\\s*");
|
||||||
cardName.replace(rx, " // ");
|
cardName.replace(rx, " // ");
|
||||||
|
|
||||||
|
// Replace only if the ampersand is preceded by a non-capital letter,
|
||||||
|
// as would happen with acronyms. So 'Fire & Ice' is replaced but not
|
||||||
|
// 'R&D' or 'R & D'.
|
||||||
|
//
|
||||||
|
// Qt regexes don't support lookbehind so we capture and replace
|
||||||
|
// instead.
|
||||||
|
rx.setPattern("([^A-Z])\\s*&\\s*");
|
||||||
|
if (rx.indexIn(cardName) != -1) {
|
||||||
|
cardName.replace(rx, QString("%1 // ").arg(rx.cap(1)));
|
||||||
|
}
|
||||||
|
|
||||||
++okRows;
|
++okRows;
|
||||||
new DecklistCardNode(cardName, number, zone);
|
new DecklistCardNode(cardName, number, zone);
|
||||||
}
|
}
|
||||||
|
|
@ -579,16 +598,30 @@ bool DeckList::loadFromFile_Plain(QIODevice *device)
|
||||||
return loadFromStream_Plain(in);
|
return loadFromStream_Plain(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct WriteToStream {
|
||||||
|
QTextStream &stream;
|
||||||
|
|
||||||
|
WriteToStream(QTextStream &_stream) : stream(_stream) {}
|
||||||
|
|
||||||
|
void operator()(
|
||||||
|
const InnerDecklistNode *node,
|
||||||
|
const DecklistCardNode *card
|
||||||
|
) {
|
||||||
|
if (node->getName() == "side") {
|
||||||
|
stream << "SB: ";
|
||||||
|
}
|
||||||
|
stream << QString("%1 %2\n").arg(
|
||||||
|
card->getNumber()
|
||||||
|
).arg(
|
||||||
|
card->getName()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
bool DeckList::saveToStream_Plain(QTextStream &out)
|
bool DeckList::saveToStream_Plain(QTextStream &out)
|
||||||
{
|
{
|
||||||
// Support for this is only possible if the internal structure doesn't get more complicated.
|
WriteToStream writeToStream(out);
|
||||||
for (int i = 0; i < root->size(); i++) {
|
forEachCard(writeToStream);
|
||||||
InnerDecklistNode *node = dynamic_cast<InnerDecklistNode *>(root->at(i));
|
|
||||||
for (int j = 0; j < node->size(); j++) {
|
|
||||||
DecklistCardNode *card = dynamic_cast<DecklistCardNode *>(node->at(j));
|
|
||||||
out << QString("%1%2 %3\n").arg(node->getName() == "side" ? "SB: " : "").arg(card->getNumber()).arg(card->getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -117,6 +117,7 @@ public:
|
||||||
QString getName() const { return name; }
|
QString getName() const { return name; }
|
||||||
void setName(const QString &_name) { name = _name; }
|
void setName(const QString &_name) { name = _name; }
|
||||||
float getPrice() const { return price; }
|
float getPrice() const { return price; }
|
||||||
|
|
||||||
void setPrice(const float _price) { price = _price; }
|
void setPrice(const float _price) { price = _price; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -169,6 +170,28 @@ public:
|
||||||
InnerDecklistNode *getRoot() const { return root; }
|
InnerDecklistNode *getRoot() const { return root; }
|
||||||
DecklistCardNode *addCard(const QString &cardName, const QString &zoneName);
|
DecklistCardNode *addCard(const QString &cardName, const QString &zoneName);
|
||||||
bool deleteNode(AbstractDecklistNode *node, InnerDecklistNode *rootNode = 0);
|
bool deleteNode(AbstractDecklistNode *node, InnerDecklistNode *rootNode = 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls a given function object for each card in the deck. It must
|
||||||
|
* take a InnerDecklistNode* as its first argument and a
|
||||||
|
* DecklistCardNode* as its second.
|
||||||
|
*/
|
||||||
|
template <typename Callback>
|
||||||
|
void forEachCard(Callback &callback) const {
|
||||||
|
// Support for this is only possible if the internal structure
|
||||||
|
// doesn't get more complicated.
|
||||||
|
for (int i = 0; i < root->size(); i++) {
|
||||||
|
const InnerDecklistNode *node =
|
||||||
|
dynamic_cast<InnerDecklistNode *>(root->at(i));
|
||||||
|
for (int j = 0; j < node->size(); j++) {
|
||||||
|
const DecklistCardNode *card =
|
||||||
|
dynamic_cast<DecklistCardNode *>(
|
||||||
|
node->at(j)
|
||||||
|
);
|
||||||
|
callback(node, card);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ protected slots:
|
||||||
void externalGameEventContainerReceived(const GameEventContainer &cont, qint64 sessionId);
|
void externalGameEventContainerReceived(const GameEventContainer &cont, qint64 sessionId);
|
||||||
void externalResponseReceived(const Response &resp, qint64 sessionId);
|
void externalResponseReceived(const Response &resp, qint64 sessionId);
|
||||||
|
|
||||||
virtual void doSendIslMessage(const IslMessage &msg, int serverId) { }
|
virtual void doSendIslMessage(const IslMessage & /* msg */, int /* serverId */) { }
|
||||||
protected:
|
protected:
|
||||||
void prepareDestroy();
|
void prepareDestroy();
|
||||||
void setDatabaseInterface(Server_DatabaseInterface *_databaseInterface);
|
void setDatabaseInterface(Server_DatabaseInterface *_databaseInterface);
|
||||||
|
|
|
||||||
|
|
@ -12,18 +12,18 @@ public:
|
||||||
: QObject(parent) { }
|
: QObject(parent) { }
|
||||||
|
|
||||||
virtual AuthenticationResult checkUserPassword(Server_ProtocolHandler *handler, const QString &user, const QString &password, QString &reasonStr, int &secondsLeft) = 0;
|
virtual AuthenticationResult checkUserPassword(Server_ProtocolHandler *handler, const QString &user, const QString &password, QString &reasonStr, int &secondsLeft) = 0;
|
||||||
virtual bool userExists(const QString &user) { return false; }
|
virtual bool userExists(const QString & /* user */) { return false; }
|
||||||
virtual QMap<QString, ServerInfo_User> getBuddyList(const QString &name) { return QMap<QString, ServerInfo_User>(); }
|
virtual QMap<QString, ServerInfo_User> getBuddyList(const QString & /* name */) { return QMap<QString, ServerInfo_User>(); }
|
||||||
virtual QMap<QString, ServerInfo_User> getIgnoreList(const QString &name) { return QMap<QString, ServerInfo_User>(); }
|
virtual QMap<QString, ServerInfo_User> getIgnoreList(const QString & /* name */) { return QMap<QString, ServerInfo_User>(); }
|
||||||
virtual bool isInBuddyList(const QString &whoseList, const QString &who) { return false; }
|
virtual bool isInBuddyList(const QString & /* whoseList */, const QString & /* who */) { return false; }
|
||||||
virtual bool isInIgnoreList(const QString &whoseList, const QString &who) { return false; }
|
virtual bool isInIgnoreList(const QString & /* whoseList */, const QString & /* who */) { return false; }
|
||||||
virtual ServerInfo_User getUserData(const QString &name, bool withId = false) = 0;
|
virtual ServerInfo_User getUserData(const QString &name, bool withId = false) = 0;
|
||||||
virtual void storeGameInformation(const QString &roomName, const QStringList &roomGameTypes, const ServerInfo_Game &gameInfo, const QSet<QString> &allPlayersEver, const QSet<QString> &allSpectatorsEver, const QList<GameReplay *> &replayList) { }
|
virtual void storeGameInformation(const QString & /* roomName */, const QStringList & /* roomGameTypes */, const ServerInfo_Game & /* gameInfo */, const QSet<QString> & /* allPlayersEver */, const QSet<QString> & /* allSpectatorsEver */, const QList<GameReplay *> & /* replayList */) { }
|
||||||
virtual DeckList *getDeckFromDatabase(int deckId, int userId) { return 0; }
|
virtual DeckList *getDeckFromDatabase(int /* deckId */, int /* userId */) { return 0; }
|
||||||
|
|
||||||
virtual qint64 startSession(const QString &userName, const QString &address) { return 0; }
|
virtual qint64 startSession(const QString & /* userName */, const QString & /* address */) { return 0; }
|
||||||
public slots:
|
public slots:
|
||||||
virtual void endSession(qint64 sessionId) { }
|
virtual void endSession(qint64 /* sessionId */ ) { }
|
||||||
public:
|
public:
|
||||||
virtual int getNextGameId() = 0;
|
virtual int getNextGameId() = 0;
|
||||||
virtual int getNextReplayId() = 0;
|
virtual int getNextReplayId() = 0;
|
||||||
|
|
@ -31,7 +31,7 @@ public:
|
||||||
virtual void clearSessionTables() { }
|
virtual void clearSessionTables() { }
|
||||||
virtual void lockSessionTables() { }
|
virtual void lockSessionTables() { }
|
||||||
virtual void unlockSessionTables() { }
|
virtual void unlockSessionTables() { }
|
||||||
virtual bool userSessionExists(const QString &userName) { return false; }
|
virtual bool userSessionExists(const QString & /* userName */) { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1594,7 +1594,7 @@ Response::ResponseCode Server_Player::cmdRevealCards(const Command_RevealCards &
|
||||||
return Response::RespOk;
|
return Response::RespOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
Response::ResponseCode Server_Player::cmdChangeZoneProperties(const Command_ChangeZoneProperties &cmd, ResponseContainer &rc, GameEventStorage &ges)
|
Response::ResponseCode Server_Player::cmdChangeZoneProperties(const Command_ChangeZoneProperties &cmd, ResponseContainer & /* rc */, GameEventStorage &ges)
|
||||||
{
|
{
|
||||||
Server_CardZone *zone = zones.value(QString::fromStdString(cmd.zone_name()));
|
Server_CardZone *zone = zones.value(QString::fromStdString(cmd.zone_name()));
|
||||||
if (!zone)
|
if (!zone)
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ protected:
|
||||||
AuthenticationResult authState;
|
AuthenticationResult authState;
|
||||||
bool acceptsUserListChanges;
|
bool acceptsUserListChanges;
|
||||||
bool acceptsRoomListChanges;
|
bool acceptsRoomListChanges;
|
||||||
virtual void logDebugMessage(const QString &message) { }
|
virtual void logDebugMessage(const QString & /* message */) { }
|
||||||
private:
|
private:
|
||||||
QList<int> messageSizeOverTime, messageCountOverTime;
|
QList<int> messageSizeOverTime, messageCountOverTime;
|
||||||
int timeRunning, lastDataReceived;
|
int timeRunning, lastDataReceived;
|
||||||
|
|
@ -71,13 +71,13 @@ private:
|
||||||
Response::ResponseCode cmdJoinGame(const Command_JoinGame &cmd, Server_Room *room, ResponseContainer &rc);
|
Response::ResponseCode cmdJoinGame(const Command_JoinGame &cmd, Server_Room *room, ResponseContainer &rc);
|
||||||
|
|
||||||
Response::ResponseCode processSessionCommandContainer(const CommandContainer &cont, ResponseContainer &rc);
|
Response::ResponseCode processSessionCommandContainer(const CommandContainer &cont, ResponseContainer &rc);
|
||||||
virtual Response::ResponseCode processExtendedSessionCommand(int cmdType, const SessionCommand &cmd, ResponseContainer &rc) { return Response::RespFunctionNotAllowed; }
|
virtual Response::ResponseCode processExtendedSessionCommand(int /* cmdType */, const SessionCommand & /* cmd */, ResponseContainer & /* rc */) { return Response::RespFunctionNotAllowed; }
|
||||||
Response::ResponseCode processRoomCommandContainer(const CommandContainer &cont, ResponseContainer &rc);
|
Response::ResponseCode processRoomCommandContainer(const CommandContainer &cont, ResponseContainer &rc);
|
||||||
Response::ResponseCode processGameCommandContainer(const CommandContainer &cont, ResponseContainer &rc);
|
Response::ResponseCode processGameCommandContainer(const CommandContainer &cont, ResponseContainer &rc);
|
||||||
Response::ResponseCode processModeratorCommandContainer(const CommandContainer &cont, ResponseContainer &rc);
|
Response::ResponseCode processModeratorCommandContainer(const CommandContainer &cont, ResponseContainer &rc);
|
||||||
virtual Response::ResponseCode processExtendedModeratorCommand(int cmdType, const ModeratorCommand &cmd, ResponseContainer &rc) { return Response::RespFunctionNotAllowed; }
|
virtual Response::ResponseCode processExtendedModeratorCommand(int /* cmdType */, const ModeratorCommand & /* cmd */, ResponseContainer & /* rc */) { return Response::RespFunctionNotAllowed; }
|
||||||
Response::ResponseCode processAdminCommandContainer(const CommandContainer &cont, ResponseContainer &rc);
|
Response::ResponseCode processAdminCommandContainer(const CommandContainer &cont, ResponseContainer &rc);
|
||||||
virtual Response::ResponseCode processExtendedAdminCommand(int cmdType, const AdminCommand &cmd, ResponseContainer &rc) { return Response::RespFunctionNotAllowed; }
|
virtual Response::ResponseCode processExtendedAdminCommand(int /* cmdType */, const AdminCommand & /* cmd */, ResponseContainer & /* rc */) { return Response::RespFunctionNotAllowed; }
|
||||||
private slots:
|
private slots:
|
||||||
void pingClockTimeout();
|
void pingClockTimeout();
|
||||||
public slots:
|
public slots:
|
||||||
|
|
|
||||||
56
doc/cards.xsd
Normal file
56
doc/cards.xsd
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||||
|
<xs:element name="cockatrice_carddatabase">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="sets">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="set" maxOccurs="unbounded" minOccurs="0">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element type="xs:string" name="name"/>
|
||||||
|
<xs:element type="xs:string" name="longname"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element name="cards">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="card" maxOccurs="unbounded" minOccurs="0">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element type="xs:string" name="name"/>
|
||||||
|
<xs:element name="set" maxOccurs="unbounded" minOccurs="0">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:simpleContent>
|
||||||
|
<xs:extension base="xs:string">
|
||||||
|
<xs:attribute type="xs:int" name="muId" use="optional"/>
|
||||||
|
<xs:attribute type="xs:anyURI" name="picUrl" use="optional"/>
|
||||||
|
<xs:attribute type="xs:anyURI" name="picUrlHq" use="optional"/>
|
||||||
|
</xs:extension>
|
||||||
|
</xs:simpleContent>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element type="xs:string" name="color" minOccurs="0" maxOccurs="unbounded"/>
|
||||||
|
<xs:element type="xs:string" name="manacost"/>
|
||||||
|
<xs:element type="xs:string" name="type"/>
|
||||||
|
<xs:element type="xs:string" name="pt" minOccurs="0"/>
|
||||||
|
<xs:element type="xs:integer" name="tablerow"/>
|
||||||
|
<xs:element type="xs:string" name="text"/>
|
||||||
|
<xs:element type="xs:boolean" name="cipt" minOccurs="0"/>
|
||||||
|
<xs:element type="xs:integer" name="loyalty" minOccurs="0"/>
|
||||||
|
<xs:element type="xs:boolean" name="token" minOccurs="0"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
</xs:sequence>
|
||||||
|
<xs:attribute type="xs:integer" name="version"/>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
</xs:schema>
|
||||||
|
|
@ -16,6 +16,19 @@ SET(oracle_SOURCES
|
||||||
../cockatrice/src/qt-json/json.cpp
|
../cockatrice/src/qt-json/json.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set(oracle_RESOURCES oracle.qrc)
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
set(oracle_SOURCES ${oracle_SOURCES} oracle.rc)
|
||||||
|
endif(WIN32)
|
||||||
|
|
||||||
|
|
||||||
|
if(APPLE)
|
||||||
|
set(MACOSX_BUNDLE_ICON_FILE appicon.icns)
|
||||||
|
set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/resources/appicon.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
|
||||||
|
set(oracle_SOURCES ${oracle_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/resources/appicon.icns)
|
||||||
|
ENDIF(APPLE)
|
||||||
|
|
||||||
set(ORACLE_LIBS)
|
set(ORACLE_LIBS)
|
||||||
|
|
||||||
# Qt4 stuff
|
# Qt4 stuff
|
||||||
|
|
@ -29,6 +42,10 @@ if(Qt4_FOUND)
|
||||||
include_directories(${QT_INCLUDES})
|
include_directories(${QT_INCLUDES})
|
||||||
LIST(APPEND ORACLE_LIBS ${QT_QTMAIN_LIBRARY})
|
LIST(APPEND ORACLE_LIBS ${QT_QTMAIN_LIBRARY})
|
||||||
LIST(APPEND ORACLE_LIBS ${QT_LIBRARIES})
|
LIST(APPEND ORACLE_LIBS ${QT_LIBRARIES})
|
||||||
|
|
||||||
|
# Let cmake chew Qt4's translations and resource files
|
||||||
|
# Note: header files are MOC-ed automatically by cmake
|
||||||
|
QT4_ADD_RESOURCES(oracle_RESOURCES_RCC ${oracle_RESOURCES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# qt5 stuff
|
# qt5 stuff
|
||||||
|
|
@ -64,6 +81,10 @@ if(Qt5Widgets_FOUND)
|
||||||
list(APPEND ORACLE_LIBS Svg)
|
list(APPEND ORACLE_LIBS Svg)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Let cmake chew Qt5's translations and resource files
|
||||||
|
# Note: header files are MOC-ed automatically by cmake
|
||||||
|
QT5_ADD_RESOURCES(oracle_RESOURCES_RCC ${oracle_RESOURCES})
|
||||||
|
|
||||||
# guess plugins and libraries directory
|
# guess plugins and libraries directory
|
||||||
set(QT_PLUGINS_DIR "${Qt5Widgets_DIR}/../../../plugins")
|
set(QT_PLUGINS_DIR "${Qt5Widgets_DIR}/../../../plugins")
|
||||||
get_target_property(QT_LIBRARY_DIR Qt5::Core LOCATION)
|
get_target_property(QT_LIBRARY_DIR Qt5::Core LOCATION)
|
||||||
|
|
@ -73,7 +94,7 @@ endif()
|
||||||
INCLUDE_DIRECTORIES(../cockatrice/src)
|
INCLUDE_DIRECTORIES(../cockatrice/src)
|
||||||
|
|
||||||
# Build oracle binary and link it
|
# Build oracle binary and link it
|
||||||
ADD_EXECUTABLE(oracle WIN32 MACOSX_BUNDLE ${oracle_SOURCES} ${oracle_MOC_SRCS})
|
ADD_EXECUTABLE(oracle WIN32 MACOSX_BUNDLE ${oracle_SOURCES} ${oracle_RESOURCES_RCC} ${oracle_MOC_SRCS})
|
||||||
|
|
||||||
if(Qt4_FOUND)
|
if(Qt4_FOUND)
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
|
|
@ -94,6 +115,8 @@ if(UNIX)
|
||||||
else()
|
else()
|
||||||
# Assume linux
|
# Assume linux
|
||||||
INSTALL(TARGETS oracle RUNTIME DESTINATION bin/)
|
INSTALL(TARGETS oracle RUNTIME DESTINATION bin/)
|
||||||
|
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/oracle.png DESTINATION ${ICONDIR}/hicolor/48x48/apps)
|
||||||
|
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resources/oracle.svg DESTINATION ${ICONDIR}/hicolor/scalable/apps)
|
||||||
endif()
|
endif()
|
||||||
elseif(WIN32)
|
elseif(WIN32)
|
||||||
INSTALL(TARGETS oracle RUNTIME DESTINATION ./)
|
INSTALL(TARGETS oracle RUNTIME DESTINATION ./)
|
||||||
|
|
|
||||||
|
|
@ -4,5 +4,5 @@ Version=1.0
|
||||||
Type=Application
|
Type=Application
|
||||||
Name=Cockatrice Oracle downloader
|
Name=Cockatrice Oracle downloader
|
||||||
Exec=oracle
|
Exec=oracle
|
||||||
Icon=cockatrice
|
Icon=oracle
|
||||||
Categories=Game;CardGame;
|
Categories=Game;CardGame;
|
||||||
|
|
|
||||||
5
oracle/oracle.qrc
Normal file
5
oracle/oracle.qrc
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
<RCC>
|
||||||
|
<qresource prefix="/" >
|
||||||
|
<file alias="resources/appicon.svg">resources/oracle.svg</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
||||||
1
oracle/oracle.rc
Normal file
1
oracle/oracle.rc
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
ID1_ICON1 ICON DISCARDABLE "resources/appicon.ico"
|
||||||
BIN
oracle/resources/appicon.icns
Normal file
BIN
oracle/resources/appicon.icns
Normal file
Binary file not shown.
BIN
oracle/resources/appicon.ico
Normal file
BIN
oracle/resources/appicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 118 KiB |
BIN
oracle/resources/oracle.png
Normal file
BIN
oracle/resources/oracle.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
228
oracle/resources/oracle.svg
Normal file
228
oracle/resources/oracle.svg
Normal file
|
|
@ -0,0 +1,228 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="300.0036"
|
||||||
|
height="300"
|
||||||
|
id="svg2"
|
||||||
|
sodipodi:version="0.32"
|
||||||
|
inkscape:version="0.48.2 r9819"
|
||||||
|
sodipodi:docname="back.svg"
|
||||||
|
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
||||||
|
version="1.0"
|
||||||
|
inkscape:export-xdpi="96"
|
||||||
|
inkscape:export-ydpi="96">
|
||||||
|
<defs
|
||||||
|
id="defs4">
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient3169">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#0000ff;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop3171" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#000067;stop-opacity:1;"
|
||||||
|
offset="1"
|
||||||
|
id="stop3173" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient4766">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#784421;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop4768" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#3d2210;stop-opacity:0;"
|
||||||
|
offset="1"
|
||||||
|
id="stop4770" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient4758">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#a05a2c;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop4760" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#3d2210;stop-opacity:1;"
|
||||||
|
offset="1"
|
||||||
|
id="stop4762" />
|
||||||
|
</linearGradient>
|
||||||
|
<inkscape:perspective
|
||||||
|
sodipodi:type="inkscape:persp3d"
|
||||||
|
inkscape:vp_x="0 : 526.18109 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
||||||
|
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
||||||
|
id="perspective10" />
|
||||||
|
<inkscape:perspective
|
||||||
|
id="perspective2484"
|
||||||
|
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
||||||
|
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_x="0 : 526.18109 : 1"
|
||||||
|
sodipodi:type="inkscape:persp3d" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient4758"
|
||||||
|
id="linearGradient4764"
|
||||||
|
x1="466.09601"
|
||||||
|
y1="485.96021"
|
||||||
|
x2="715.14801"
|
||||||
|
y2="485.96021"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient4766"
|
||||||
|
id="linearGradient4772"
|
||||||
|
x1="496.548"
|
||||||
|
y1="485.26816"
|
||||||
|
x2="683.31201"
|
||||||
|
y2="485.26816"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient4766"
|
||||||
|
id="linearGradient2396"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="661.24402"
|
||||||
|
y1="602.90814"
|
||||||
|
x2="431.5"
|
||||||
|
y2="201.5482"
|
||||||
|
gradientTransform="matrix(0.9650128,0,0,0.9948433,-449.70565,-312.80927)" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient4758"
|
||||||
|
id="linearGradient2399"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="590.62201"
|
||||||
|
y1="434.7522"
|
||||||
|
x2="698.54004"
|
||||||
|
y2="517.79218"
|
||||||
|
gradientTransform="matrix(0.9650128,0,0,0.9948433,-449.70565,-312.80927)" />
|
||||||
|
<filter
|
||||||
|
inkscape:collect="always"
|
||||||
|
id="filter3287"
|
||||||
|
color-interpolation-filters="sRGB">
|
||||||
|
<feGaussianBlur
|
||||||
|
inkscape:collect="always"
|
||||||
|
stdDeviation="0.88403668"
|
||||||
|
id="feGaussianBlur3289" />
|
||||||
|
</filter>
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient4766"
|
||||||
|
id="linearGradient3057"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(0.84875138,0,0,0.874988,-395.5345,-274.89225)"
|
||||||
|
x1="661.24402"
|
||||||
|
y1="602.90814"
|
||||||
|
x2="431.5"
|
||||||
|
y2="201.5482" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient4758"
|
||||||
|
id="linearGradient3059"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(0.84875138,0,0,0.874988,-395.5345,-274.89225)"
|
||||||
|
x1="590.62201"
|
||||||
|
y1="434.7522"
|
||||||
|
x2="698.54004"
|
||||||
|
y2="517.79218" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="1.4911765"
|
||||||
|
inkscape:cx="164.24505"
|
||||||
|
inkscape:cy="113.77996"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:window-width="1280"
|
||||||
|
inkscape:window-height="725"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="25"
|
||||||
|
fit-margin-left="44.18"
|
||||||
|
fit-margin-right="44.18"
|
||||||
|
fit-margin-top="0"
|
||||||
|
fit-margin-bottom="0"
|
||||||
|
inkscape:window-maximized="0" />
|
||||||
|
<metadata
|
||||||
|
id="metadata7">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Ebene 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(44.245053,-0.31708717)">
|
||||||
|
<rect
|
||||||
|
style="fill:url(#linearGradient3059);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:17.23539734;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||||
|
id="rect2490"
|
||||||
|
width="194.4082"
|
||||||
|
height="282.76462"
|
||||||
|
x="8.5526457"
|
||||||
|
y="8.9347858"
|
||||||
|
inkscape:export-xdpi="969.46002"
|
||||||
|
inkscape:export-ydpi="969.46002" />
|
||||||
|
<rect
|
||||||
|
style="fill:url(#linearGradient3057);fill-opacity:1;stroke:#000000;stroke-width:1.72353971;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||||
|
id="rect3302"
|
||||||
|
width="156.81871"
|
||||||
|
height="244.01315"
|
||||||
|
x="26.760056"
|
||||||
|
y="27.704998" />
|
||||||
|
<path
|
||||||
|
sodipodi:type="arc"
|
||||||
|
style="opacity:0.39208954;fill:#a05a2c;stroke:#000000;stroke-width:2.00029755;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;filter:url(#filter3287)"
|
||||||
|
id="path3304"
|
||||||
|
sodipodi:cx="589.58398"
|
||||||
|
sodipodi:cy="489.76617"
|
||||||
|
sodipodi:rx="71.968002"
|
||||||
|
sodipodi:ry="128.71201"
|
||||||
|
d="m 661.55199,489.76617 c 0,71.08568 -32.22118,128.71201 -71.96801,128.71201 -39.74683,0 -71.968,-57.62633 -71.968,-128.71201 0,-71.08567 32.22117,-128.712 71.968,-128.712 39.74683,0 71.96801,57.62633 71.96801,128.712 z"
|
||||||
|
transform="matrix(1.0026379,0,0,0.89548037,-485.67617,-289.46994)" />
|
||||||
|
<flowRoot
|
||||||
|
xml:space="preserve"
|
||||||
|
id="flowRoot3021"
|
||||||
|
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><flowRegion
|
||||||
|
id="flowRegion3023"><rect
|
||||||
|
id="rect3025"
|
||||||
|
width="151.92514"
|
||||||
|
height="235.58012"
|
||||||
|
x="50.000679"
|
||||||
|
y="60.188515" /></flowRegion><flowPara
|
||||||
|
id="flowPara3027"></flowPara></flowRoot> <text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-size:35.18093872px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Songti SC;-inkscape-font-specification:Songti SC"
|
||||||
|
x="-14.38486"
|
||||||
|
y="244.29784"
|
||||||
|
id="text3029"
|
||||||
|
sodipodi:linespacing="125%"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan3031"
|
||||||
|
x="-14.38486"
|
||||||
|
y="244.29784"
|
||||||
|
style="font-size:390.50842285px;font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#ffffff;font-family:STKaiti;-inkscape-font-specification:STKaiti Bold Italic">o</tspan></text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 7.9 KiB |
|
|
@ -1,5 +1,6 @@
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QTextCodec>
|
#include <QTextCodec>
|
||||||
|
#include <QIcon>
|
||||||
#include "oraclewizard.h"
|
#include "oraclewizard.h"
|
||||||
#include "settingscache.h"
|
#include "settingscache.h"
|
||||||
|
|
||||||
|
|
@ -22,6 +23,10 @@ int main(int argc, char *argv[])
|
||||||
settingsCache = new SettingsCache;
|
settingsCache = new SettingsCache;
|
||||||
|
|
||||||
OracleWizard wizard;
|
OracleWizard wizard;
|
||||||
|
|
||||||
|
QIcon icon(":/resources/appicon.svg");
|
||||||
|
wizard.setWindowIcon(icon);
|
||||||
|
|
||||||
wizard.show();
|
wizard.show();
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
|
|
|
||||||
|
|
@ -80,8 +80,8 @@ CardInfo *OracleImporter::addCard(const QString &setName,
|
||||||
cardCost.remove(QChar('}'));
|
cardCost.remove(QChar('}'));
|
||||||
|
|
||||||
CardInfo *card;
|
CardInfo *card;
|
||||||
if (cardHash.contains(cardName)) {
|
if (cards.contains(cardName)) {
|
||||||
card = cardHash.value(cardName);
|
card = cards.value(cardName);
|
||||||
if (splitCard && !card->getText().contains(fullCardText))
|
if (splitCard && !card->getText().contains(fullCardText))
|
||||||
card->setText(card->getText() + "\n---\n" + fullCardText);
|
card->setText(card->getText() + "\n---\n" + fullCardText);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -121,7 +121,7 @@ CardInfo *OracleImporter::addCard(const QString &setName,
|
||||||
tableRow = 2;
|
tableRow = 2;
|
||||||
card->setTableRow(tableRow);
|
card->setTableRow(tableRow);
|
||||||
|
|
||||||
cardHash.insert(cardName, card);
|
cards.insert(cardName, card);
|
||||||
}
|
}
|
||||||
card->setMuId(setName, cardId);
|
card->setMuId(setName, cardId);
|
||||||
|
|
||||||
|
|
@ -141,6 +141,7 @@ int OracleImporter::importTextSpoiler(CardSet *set, const QVariant &data)
|
||||||
QString cardText;
|
QString cardText;
|
||||||
int cardId;
|
int cardId;
|
||||||
int cardLoyalty;
|
int cardLoyalty;
|
||||||
|
bool cardIsToken = false;
|
||||||
QMap<int, QVariantMap> splitCards;
|
QMap<int, QVariantMap> splitCards;
|
||||||
|
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
|
|
@ -201,9 +202,15 @@ int OracleImporter::importTextSpoiler(CardSet *set, const QVariant &data)
|
||||||
cardText = map.contains("text") ? map.value("text").toString() : QString("");
|
cardText = map.contains("text") ? map.value("text").toString() : QString("");
|
||||||
cardId = map.contains("multiverseid") ? map.value("multiverseid").toInt() : 0;
|
cardId = map.contains("multiverseid") ? map.value("multiverseid").toInt() : 0;
|
||||||
cardLoyalty = map.contains("loyalty") ? map.value("loyalty").toInt() : 0;
|
cardLoyalty = map.contains("loyalty") ? map.value("loyalty").toInt() : 0;
|
||||||
|
cardIsToken = map.value("layout") == "token";
|
||||||
|
|
||||||
|
// Distinguish Vanguard cards from regular cards of the same name.
|
||||||
|
if (map.value("layout") == "vanguard") {
|
||||||
|
cardName += " Avatar";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CardInfo *card = addCard(set->getShortName(), cardName, false, cardId, cardCost, cardType, cardPT, cardLoyalty, cardText.split("\n"));
|
CardInfo *card = addCard(set->getShortName(), cardName, cardIsToken, cardId, cardCost, cardType, cardPT, cardLoyalty, cardText.split("\n"));
|
||||||
|
|
||||||
if (!set->contains(card)) {
|
if (!set->contains(card)) {
|
||||||
card->addToSet(set);
|
card->addToSet(set);
|
||||||
|
|
@ -229,8 +236,8 @@ int OracleImporter::startImport()
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
CardSet *set = new CardSet(curSet->getShortName(), curSet->getLongName());
|
CardSet *set = new CardSet(curSet->getShortName(), curSet->getLongName());
|
||||||
if (!setHash.contains(set->getShortName()))
|
if (!sets.contains(set->getShortName()))
|
||||||
setHash.insert(set->getShortName(), set);
|
sets.insert(set->getShortName(), set);
|
||||||
|
|
||||||
int setCards = importTextSpoiler(set, curSet->getCards());
|
int setCards = importTextSpoiler(set, curSet->getCards());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -383,7 +383,7 @@ void SaveSetsPage::initializePage()
|
||||||
QMessageBox::critical(this, tr("Error"), tr("No set has been imported."));
|
QMessageBox::critical(this, tr("Error"), tr("No set has been imported."));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveSetsPage::updateTotalProgress(int cardsImported, int setIndex, const QString &setName)
|
void SaveSetsPage::updateTotalProgress(int cardsImported, int /* setIndex */, const QString &setName)
|
||||||
{
|
{
|
||||||
if (setName.isEmpty()) {
|
if (setName.isEmpty()) {
|
||||||
messageLog->append("<b>" + tr("Import finished: %1 cards.").arg(wizard()->importer->getCardList().size()) + "</b>");
|
messageLog->append("<b>" + tr("Import finished: %1 cards.").arg(wizard()->importer->getCardList().size()) + "</b>");
|
||||||
|
|
@ -418,9 +418,12 @@ bool SaveSetsPage::validatePage()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (wizard()->importer->saveToFile(fileName))
|
if (wizard()->importer->saveToFile(fileName))
|
||||||
|
{
|
||||||
ok = true;
|
ok = true;
|
||||||
else
|
QMessageBox::information(this, tr("Success"), tr("The card database has been saved successfully."));
|
||||||
|
} else {
|
||||||
QMessageBox::critical(this, tr("Error"), tr("The file could not be saved to the desired location."));
|
QMessageBox::critical(this, tr("Error"), tr("The file could not be saved to the desired location."));
|
||||||
|
}
|
||||||
} while (!ok);
|
} while (!ok);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
3
servatrice/scripts/maint_replays
Normal file
3
servatrice/scripts/maint_replays
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# SCHEDULE WITH CRONTAB BASED ON TIME PERIOD REPLAYS SHOULD BE SAVED UNTIL (EX: SCHEDULE ONCE A WEEK TO KEEP A WEEKS WORTH OF REPLAYS IN THE DB)
|
||||||
|
mysql --defaults-file=./mysql.cnf -h localhost -e 'truncate table servatrice.cockatrice_replays;truncate table servatrice.cockatrice_replays_access'
|
||||||
3
servatrice/scripts/maint_sessions
Normal file
3
servatrice/scripts/maint_sessions
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# SCHEDULE WITH CRONTAB TO RUN ONCE A MONTH
|
||||||
|
mysql --defaults-file=./mysql.cnf -h localhost -e "delete from servatrice.cockatrice_sessions where start_time < DATE_SUB(now(), INTERVAL 1 MONTH)"
|
||||||
3
servatrice/scripts/mysql.cnf.example
Normal file
3
servatrice/scripts/mysql.cnf.example
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
[client]
|
||||||
|
user={db_username}
|
||||||
|
password={db_password}
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
#include "server_logger.h"
|
#include "server_logger.h"
|
||||||
#include "rng_sfmt.h"
|
#include "rng_sfmt.h"
|
||||||
#include "version_string.h"
|
#include "version_string.h"
|
||||||
|
#include <google/protobuf/stubs/common.h>
|
||||||
#ifdef Q_OS_UNIX
|
#ifdef Q_OS_UNIX
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -37,6 +38,23 @@ RNG_Abstract *rng;
|
||||||
ServerLogger *logger;
|
ServerLogger *logger;
|
||||||
QThread *loggerThread;
|
QThread *loggerThread;
|
||||||
|
|
||||||
|
/* Prototypes */
|
||||||
|
|
||||||
|
void testRNG();
|
||||||
|
void testHash();
|
||||||
|
#if QT_VERSION < 0x050000
|
||||||
|
void myMessageOutput(QtMsgType type, const char *msg);
|
||||||
|
void myMessageOutput2(QtMsgType type, const char *msg);
|
||||||
|
#else
|
||||||
|
void myMessageOutput(QtMsgType type, const QMessageLogContext &, const QString &msg);
|
||||||
|
void myMessageOutput2(QtMsgType type, const QMessageLogContext &, const QString &msg);
|
||||||
|
#endif
|
||||||
|
#ifdef Q_OS_UNIX
|
||||||
|
void sigSegvHandler(int sig);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Implementations */
|
||||||
|
|
||||||
void testRNG()
|
void testRNG()
|
||||||
{
|
{
|
||||||
const int n = 500000;
|
const int n = 500000;
|
||||||
|
|
@ -216,5 +234,8 @@ int main(int argc, char *argv[])
|
||||||
loggerThread->wait();
|
loggerThread->wait();
|
||||||
delete loggerThread;
|
delete loggerThread;
|
||||||
|
|
||||||
|
// Delete all global objects allocated by libprotobuf.
|
||||||
|
google::protobuf::ShutdownProtobufLibrary();
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,15 @@ QString PasswordHasher::computeHash(const QString &password, const QString &salt
|
||||||
|
|
||||||
QByteArray passwordBuffer = (salt + password).toUtf8();
|
QByteArray passwordBuffer = (salt + password).toUtf8();
|
||||||
int hashLen = gcry_md_get_algo_dlen(algo);
|
int hashLen = gcry_md_get_algo_dlen(algo);
|
||||||
char hash[hashLen], tmp[hashLen];
|
char *hash = new char[hashLen], *tmp = new char[hashLen];
|
||||||
gcry_md_hash_buffer(algo, hash, passwordBuffer.data(), passwordBuffer.size());
|
gcry_md_hash_buffer(algo, hash, passwordBuffer.data(), passwordBuffer.size());
|
||||||
for (int i = 1; i < rounds; ++i) {
|
for (int i = 1; i < rounds; ++i) {
|
||||||
memcpy(tmp, hash, hashLen);
|
memcpy(tmp, hash, hashLen);
|
||||||
gcry_md_hash_buffer(algo, hash, tmp, hashLen);
|
gcry_md_hash_buffer(algo, hash, tmp, hashLen);
|
||||||
}
|
}
|
||||||
return salt + QString(QByteArray(hash, hashLen).toBase64());
|
QString hashedPass = salt + QString(QByteArray(hash, hashLen).toBase64());
|
||||||
|
delete[] tmp;
|
||||||
|
delete[] hash;
|
||||||
|
return hashedPass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,11 @@ Servatrice_GameServer::~Servatrice_GameServer()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if QT_VERSION < 0x050000
|
||||||
void Servatrice_GameServer::incomingConnection(int socketDescriptor)
|
void Servatrice_GameServer::incomingConnection(int socketDescriptor)
|
||||||
|
#else
|
||||||
|
void Servatrice_GameServer::incomingConnection(qintptr socketDescriptor)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
// Determine connection pool with smallest client count
|
// Determine connection pool with smallest client count
|
||||||
int minClientCount = -1;
|
int minClientCount = -1;
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,11 @@ public:
|
||||||
Servatrice_GameServer(Servatrice *_server, int _numberPools, const QSqlDatabase &_sqlDatabase, QObject *parent = 0);
|
Servatrice_GameServer(Servatrice *_server, int _numberPools, const QSqlDatabase &_sqlDatabase, QObject *parent = 0);
|
||||||
~Servatrice_GameServer();
|
~Servatrice_GameServer();
|
||||||
protected:
|
protected:
|
||||||
|
#if QT_VERSION < 0x050000
|
||||||
void incomingConnection(int socketDescriptor);
|
void incomingConnection(int socketDescriptor);
|
||||||
|
#else
|
||||||
|
void incomingConnection(qintptr socketDescriptor);
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
class Servatrice_IslServer : public QTcpServer {
|
class Servatrice_IslServer : public QTcpServer {
|
||||||
|
|
|
||||||
|
|
@ -50,9 +50,9 @@ void ServerLogger::logMessage(QString message, void *caller)
|
||||||
callerString = QString::number((qulonglong) caller, 16) + " ";
|
callerString = QString::number((qulonglong) caller, 16) + " ";
|
||||||
|
|
||||||
//filter out all log entries based on values in configuration file
|
//filter out all log entries based on values in configuration file
|
||||||
QSettings *settings = new QSettings("servatrice.ini", QSettings::IniFormat);
|
QSettings settings("servatrice.ini", QSettings::IniFormat);
|
||||||
bool shouldWeWriteLog = settings->value("server/writelog").toBool();
|
bool shouldWeWriteLog = settings.value("server/writelog").toBool();
|
||||||
QString logFilters = settings->value("server/logfilters").toString();
|
QString logFilters = settings.value("server/logfilters").toString();
|
||||||
QStringList listlogFilters = logFilters.split(",", QString::SkipEmptyParts);
|
QStringList listlogFilters = logFilters.split(",", QString::SkipEmptyParts);
|
||||||
bool shouldWeSkipLine = false;
|
bool shouldWeSkipLine = false;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
if [[ $TRAVIS_OS_NAME == "osx" ]] ; then
|
if [[ $TRAVIS_OS_NAME == "osx" ]] ; then
|
||||||
brew update
|
brew update
|
||||||
brew install qt cmake protobuf libgcrypt
|
brew install qt protobuf libgcrypt
|
||||||
else
|
else
|
||||||
sudo apt-get update -qq
|
sudo apt-get update -qq
|
||||||
sudo apt-get install -y qtmobility-dev libprotobuf-dev protobuf-compiler libqt4-dev
|
sudo apt-get install -y qtmobility-dev libprotobuf-dev protobuf-compiler libqt4-dev
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue