mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-06-12 09:04:53 -07:00
Turn Card, Deck_List, Protocol, RNG, Network (Client, Server), Settings and Utility into libraries and remove cockatrice_common. (#6212)
--------- Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de> Co-authored-by: ebbit1q <ebbit1q@gmail.com>
This commit is contained in:
parent
be1403c920
commit
1ef07309d6
605 changed files with 3812 additions and 3408 deletions
|
|
@ -0,0 +1,242 @@
|
|||
#include "card_picture_loader.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QBuffer>
|
||||
#include <QDebug>
|
||||
#include <QDirIterator>
|
||||
#include <QFileInfo>
|
||||
#include <QMainWindow>
|
||||
#include <QMovie>
|
||||
#include <QNetworkDiskCache>
|
||||
#include <QNetworkRequest>
|
||||
#include <QPainter>
|
||||
#include <QPixmapCache>
|
||||
#include <QScreen>
|
||||
#include <QStatusBar>
|
||||
#include <QThread>
|
||||
#include <algorithm>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
#include <utility>
|
||||
|
||||
// never cache more than 300 cards at once for a single deck
|
||||
#define CACHED_CARD_PER_DECK_MAX 300
|
||||
|
||||
CardPictureLoader::CardPictureLoader() : QObject(nullptr)
|
||||
{
|
||||
worker = new CardPictureLoaderWorker;
|
||||
connect(&SettingsCache::instance(), &SettingsCache::picsPathChanged, this, &CardPictureLoader::picsPathChanged);
|
||||
connect(&SettingsCache::instance(), &SettingsCache::picDownloadChanged, this,
|
||||
&CardPictureLoader::picDownloadChanged);
|
||||
|
||||
connect(worker, &CardPictureLoaderWorker::imageLoaded, this, &CardPictureLoader::imageLoaded);
|
||||
|
||||
statusBar = new CardPictureLoaderStatusBar(nullptr);
|
||||
QMainWindow *mainWindow = qobject_cast<QMainWindow *>(QApplication::activeWindow());
|
||||
if (mainWindow) {
|
||||
mainWindow->statusBar()->addPermanentWidget(statusBar);
|
||||
}
|
||||
|
||||
connect(worker, &CardPictureLoaderWorker::imageRequestQueued, statusBar,
|
||||
&CardPictureLoaderStatusBar::addQueuedImageLoad);
|
||||
connect(worker, &CardPictureLoaderWorker::imageRequestSucceeded, statusBar,
|
||||
&CardPictureLoaderStatusBar::addSuccessfulImageLoad);
|
||||
}
|
||||
|
||||
CardPictureLoader::~CardPictureLoader()
|
||||
{
|
||||
worker->deleteLater();
|
||||
}
|
||||
|
||||
void CardPictureLoader::getCardBackPixmap(QPixmap &pixmap, QSize size)
|
||||
{
|
||||
QString backCacheKey = "_trice_card_back_" + QString::number(size.width()) + "x" + QString::number(size.height());
|
||||
if (!QPixmapCache::find(backCacheKey, &pixmap)) {
|
||||
qCDebug(CardPictureLoaderLog) << "PictureLoader: cache miss for" << backCacheKey;
|
||||
QPixmap tmpPixmap("theme:cardback");
|
||||
|
||||
if (tmpPixmap.isNull()) {
|
||||
qCWarning(CardPictureLoaderLog) << "Failed to load 'theme:cardback'! Using fallback pixmap.";
|
||||
tmpPixmap = QPixmap(size);
|
||||
tmpPixmap.fill(Qt::gray); // Fallback to a gray pixmap
|
||||
} else {
|
||||
qCDebug(CardPictureLoaderLog) << "Successfully loaded 'theme:cardback'.";
|
||||
}
|
||||
|
||||
pixmap = tmpPixmap.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
QPixmapCache::insert(backCacheKey, pixmap);
|
||||
}
|
||||
}
|
||||
|
||||
void CardPictureLoader::getCardBackLoadingInProgressPixmap(QPixmap &pixmap, QSize size)
|
||||
{
|
||||
QString backCacheKey =
|
||||
"_trice_card_back_inprogress_" + QString::number(size.width()) + "x" + QString::number(size.height());
|
||||
if (!QPixmapCache::find(backCacheKey, &pixmap)) {
|
||||
qCDebug(CardPictureLoaderCardBackCacheFailLog) << "PictureLoader: cache miss for" << backCacheKey;
|
||||
QPixmap tmpPixmap("theme:cardback");
|
||||
|
||||
if (tmpPixmap.isNull()) {
|
||||
qCWarning(CardPictureLoaderLog) << "Failed to load 'theme:cardback' for in-progress state! Using fallback.";
|
||||
tmpPixmap = QPixmap(size);
|
||||
tmpPixmap.fill(Qt::blue); // Fallback with blue color
|
||||
} else {
|
||||
qCDebug(CardPictureLoaderCardBackCacheFailLog)
|
||||
<< "Successfully loaded 'theme:cardback' for in-progress state.";
|
||||
}
|
||||
|
||||
pixmap = tmpPixmap.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
QPixmapCache::insert(backCacheKey, pixmap);
|
||||
}
|
||||
}
|
||||
|
||||
void CardPictureLoader::getCardBackLoadingFailedPixmap(QPixmap &pixmap, QSize size)
|
||||
{
|
||||
QString backCacheKey =
|
||||
"_trice_card_back_failed_" + QString::number(size.width()) + "x" + QString::number(size.height());
|
||||
if (!QPixmapCache::find(backCacheKey, &pixmap)) {
|
||||
qCDebug(CardPictureLoaderCardBackCacheFailLog) << "PictureLoader: cache miss for" << backCacheKey;
|
||||
QPixmap tmpPixmap("theme:cardback");
|
||||
|
||||
if (tmpPixmap.isNull()) {
|
||||
qCWarning(CardPictureLoaderLog) << "Failed to load 'theme:cardback' for failed state! Using fallback.";
|
||||
tmpPixmap = QPixmap(size);
|
||||
tmpPixmap.fill(Qt::red); // Fallback with red color
|
||||
} else {
|
||||
qCDebug(CardPictureLoaderCardBackCacheFailLog) << "Successfully loaded 'theme:cardback' for failed state.";
|
||||
}
|
||||
|
||||
pixmap = tmpPixmap.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
QPixmapCache::insert(backCacheKey, pixmap);
|
||||
}
|
||||
}
|
||||
|
||||
void CardPictureLoader::getPixmap(QPixmap &pixmap, const ExactCard &card, QSize size)
|
||||
{
|
||||
if (!card) {
|
||||
qCWarning(CardPictureLoaderLog) << "getPixmap called with null card!";
|
||||
return;
|
||||
}
|
||||
|
||||
QString key = card.getPixmapCacheKey();
|
||||
QString sizeKey = key + QLatin1Char('_') + QString::number(size.width()) + "x" + QString::number(size.height());
|
||||
|
||||
if (QPixmapCache::find(sizeKey, &pixmap)) {
|
||||
return; // Use cached version
|
||||
}
|
||||
|
||||
// load the image and create a copy of the correct size
|
||||
QPixmap bigPixmap;
|
||||
if (QPixmapCache::find(key, &bigPixmap)) {
|
||||
if (bigPixmap.isNull()) {
|
||||
qCDebug(CardPictureLoaderLog) << "Cached pixmap for key" << key << "is NULL!";
|
||||
return;
|
||||
}
|
||||
|
||||
QScreen *screen = qApp->primaryScreen();
|
||||
qreal dpr = screen ? screen->devicePixelRatio() : 1.0;
|
||||
qCDebug(CardPictureLoaderLog) << "Scaling cached image for" << card.getName();
|
||||
|
||||
pixmap = bigPixmap.scaled(size * dpr, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
pixmap.setDevicePixelRatio(dpr);
|
||||
QPixmapCache::insert(sizeKey, pixmap);
|
||||
return;
|
||||
}
|
||||
|
||||
// add the card to the load queue
|
||||
qCDebug(CardPictureLoaderLog) << "Enqueuing " << card.getName() << " for " << card.getPixmapCacheKey();
|
||||
getInstance().worker->enqueueImageLoad(card);
|
||||
}
|
||||
|
||||
void CardPictureLoader::imageLoaded(const ExactCard &card, const QImage &image)
|
||||
{
|
||||
if (image.isNull()) {
|
||||
qCDebug(CardPictureLoaderLog) << "Caching NULL pixmap for" << card.getName();
|
||||
QPixmapCache::insert(card.getPixmapCacheKey(), QPixmap());
|
||||
} else {
|
||||
if (card.getInfo().getUpsideDownArt()) {
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 9, 0))
|
||||
QImage mirrorImage = image.flipped(Qt::Horizontal | Qt::Vertical);
|
||||
#else
|
||||
QImage mirrorImage = image.mirrored(true, true);
|
||||
#endif
|
||||
QPixmapCache::insert(card.getPixmapCacheKey(), QPixmap::fromImage(mirrorImage));
|
||||
} else {
|
||||
QPixmapCache::insert(card.getPixmapCacheKey(), QPixmap::fromImage(image));
|
||||
}
|
||||
}
|
||||
|
||||
// imageLoaded should only be reached if the exactCard isn't already in cache.
|
||||
// (plus there's a deduplication mechanism in CardPictureLoaderWorker)
|
||||
// It should be safe to connect the CardInfo here without worrying about redundant connections.
|
||||
connect(card.getCardPtr().data(), &QObject::destroyed, this,
|
||||
[cacheKey = card.getPixmapCacheKey()] { QPixmapCache::remove(cacheKey); });
|
||||
|
||||
card.emitPixmapUpdated();
|
||||
}
|
||||
|
||||
void CardPictureLoader::clearPixmapCache()
|
||||
{
|
||||
QPixmapCache::clear();
|
||||
}
|
||||
|
||||
void CardPictureLoader::clearNetworkCache()
|
||||
{
|
||||
getInstance().worker->clearNetworkCache();
|
||||
}
|
||||
|
||||
void CardPictureLoader::cacheCardPixmaps(const QList<ExactCard> &cards)
|
||||
{
|
||||
QPixmap tmp;
|
||||
int max = qMin(cards.size(), CACHED_CARD_PER_DECK_MAX);
|
||||
for (int i = 0; i < max; ++i) {
|
||||
const ExactCard &card = cards.at(i);
|
||||
if (!card) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QString key = card.getPixmapCacheKey();
|
||||
if (QPixmapCache::find(key, &tmp)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
getInstance().worker->enqueueImageLoad(card);
|
||||
}
|
||||
}
|
||||
|
||||
void CardPictureLoader::picDownloadChanged()
|
||||
{
|
||||
QPixmapCache::clear();
|
||||
}
|
||||
|
||||
void CardPictureLoader::picsPathChanged()
|
||||
{
|
||||
QPixmapCache::clear();
|
||||
}
|
||||
|
||||
bool CardPictureLoader::hasCustomArt()
|
||||
{
|
||||
auto picsPath = SettingsCache::instance().getPicsPath();
|
||||
QDirIterator it(picsPath, QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
|
||||
// Check if there is at least one non-directory file in the pics path, other
|
||||
// than in the "downloadedPics" subdirectory.
|
||||
while (it.hasNext()) {
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 3, 0))
|
||||
QFileInfo dir(it.nextFileInfo());
|
||||
#else
|
||||
// nextFileInfo() is only available in Qt 6.3+, for previous versions, we build
|
||||
// the QFileInfo from a QString which requires more system calls.
|
||||
QFileInfo dir(it.next());
|
||||
#endif
|
||||
|
||||
if (it.fileName() == "downloadedPics")
|
||||
continue;
|
||||
|
||||
QDirIterator subIt(it.filePath(), QDir::Files, QDirIterator::Subdirectories | QDirIterator::FollowSymlinks);
|
||||
if (subIt.hasNext()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/**
|
||||
* @file card_picture_loader.h
|
||||
* @ingroup PictureLoader
|
||||
* @brief TODO: Document this.
|
||||
*/
|
||||
|
||||
#ifndef CARD_PICTURE_LOADER_H
|
||||
#define CARD_PICTURE_LOADER_H
|
||||
|
||||
#include "card_picture_loader_status_bar.h"
|
||||
#include "card_picture_loader_worker.h"
|
||||
|
||||
#include <QLoggingCategory>
|
||||
#include <libcockatrice/card/card_info.h>
|
||||
|
||||
inline Q_LOGGING_CATEGORY(CardPictureLoaderLog, "card_picture_loader");
|
||||
inline Q_LOGGING_CATEGORY(CardPictureLoaderCardBackCacheFailLog, "card_picture_loader.card_back_cache_fail");
|
||||
|
||||
class CardPictureLoader : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
static CardPictureLoader &getInstance()
|
||||
{
|
||||
static CardPictureLoader instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
private:
|
||||
explicit CardPictureLoader();
|
||||
~CardPictureLoader() override;
|
||||
// Singleton - Don't implement copy constructor and assign operator
|
||||
CardPictureLoader(CardPictureLoader const &);
|
||||
void operator=(CardPictureLoader const &);
|
||||
|
||||
CardPictureLoaderWorker *worker;
|
||||
CardPictureLoaderStatusBar *statusBar;
|
||||
|
||||
public:
|
||||
static void getPixmap(QPixmap &pixmap, const ExactCard &card, QSize size);
|
||||
static void getCardBackPixmap(QPixmap &pixmap, QSize size);
|
||||
static void getCardBackLoadingInProgressPixmap(QPixmap &pixmap, QSize size);
|
||||
static void getCardBackLoadingFailedPixmap(QPixmap &pixmap, QSize size);
|
||||
static void clearPixmapCache();
|
||||
static void cacheCardPixmaps(const QList<ExactCard> &cards);
|
||||
static bool hasCustomArt();
|
||||
|
||||
public slots:
|
||||
static void clearNetworkCache();
|
||||
|
||||
private slots:
|
||||
void picDownloadChanged();
|
||||
void picsPathChanged();
|
||||
|
||||
public slots:
|
||||
void imageLoaded(const ExactCard &card, const QImage &image);
|
||||
};
|
||||
#endif
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
#include "card_picture_loader_local.h"
|
||||
|
||||
#include "card_picture_to_load.h"
|
||||
|
||||
#include <QDirIterator>
|
||||
#include <QMovie>
|
||||
#include <libcockatrice/card/card_database/card_database_manager.h>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
|
||||
static constexpr int REFRESH_INTERVAL_MS = 10 * 1000;
|
||||
|
||||
CardPictureLoaderLocal::CardPictureLoaderLocal(QObject *parent)
|
||||
: QObject(parent), picsPath(SettingsCache::instance().getPicsPath()),
|
||||
customPicsPath(SettingsCache::instance().getCustomPicsPath())
|
||||
{
|
||||
// Hook up signals to settings
|
||||
connect(&SettingsCache::instance(), &SettingsCache::picsPathChanged, this,
|
||||
&CardPictureLoaderLocal::picsPathChanged);
|
||||
|
||||
refreshIndex();
|
||||
|
||||
refreshTimer = new QTimer(this);
|
||||
connect(refreshTimer, &QTimer::timeout, this, &CardPictureLoaderLocal::refreshIndex);
|
||||
refreshTimer->start(REFRESH_INTERVAL_MS);
|
||||
}
|
||||
|
||||
void CardPictureLoaderLocal::refreshIndex()
|
||||
{
|
||||
customFolderIndex.clear();
|
||||
|
||||
QDirIterator it(customPicsPath, QDirIterator::Subdirectories | QDirIterator::FollowSymlinks);
|
||||
|
||||
// Recursively check all subdirectories of the CUSTOM folder
|
||||
while (it.hasNext()) {
|
||||
QString thisPath(it.next());
|
||||
QFileInfo thisFileInfo(thisPath);
|
||||
|
||||
if (thisFileInfo.isFile()) {
|
||||
// We don't know which name is the correctedName because there might be '.'s in the cardName.
|
||||
// Just add all possibilities to be sure.
|
||||
customFolderIndex.insert(thisFileInfo.baseName(), thisFileInfo.absoluteFilePath());
|
||||
customFolderIndex.insert(thisFileInfo.completeBaseName(), thisFileInfo.absoluteFilePath());
|
||||
}
|
||||
}
|
||||
|
||||
qCDebug(CardPictureLoaderLocalLog) << "Finished indexing local image folder CUSTOM; map now has"
|
||||
<< customFolderIndex.size() << "entries.";
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to load the card image from the local images.
|
||||
*
|
||||
* @param toLoad The card to load
|
||||
* @return The loaded image, or an empty QImage if loading failed.
|
||||
*/
|
||||
QImage CardPictureLoaderLocal::tryLoad(const ExactCard &toLoad) const
|
||||
{
|
||||
PrintingInfo setInstance = toLoad.getPrinting();
|
||||
|
||||
QString cardName = toLoad.getName();
|
||||
QString correctedCardName = toLoad.getInfo().getCorrectedName();
|
||||
|
||||
QString setName, collectorNumber, providerId;
|
||||
|
||||
if (setInstance.getSet()) {
|
||||
setName = setInstance.getSet()->getCorrectedShortName();
|
||||
collectorNumber = setInstance.getProperty("num");
|
||||
providerId = setInstance.getUuid();
|
||||
}
|
||||
|
||||
qCDebug(CardPictureLoaderLocalLog).nospace()
|
||||
<< "[card: " << cardName << " set: " << setName << "]: Attempting to load picture from local";
|
||||
return tryLoadCardImageFromDisk(setName, correctedCardName, collectorNumber, providerId);
|
||||
}
|
||||
|
||||
QImage CardPictureLoaderLocal::tryLoadCardImageFromDisk(const QString &setName,
|
||||
const QString &correctedCardName,
|
||||
const QString &collectorNumber,
|
||||
const QString &providerId) const
|
||||
{
|
||||
QImage image;
|
||||
QImageReader imgReader;
|
||||
imgReader.setDecideFormatFromContent(true);
|
||||
|
||||
// Most-to-least specific, these will fall through in order.
|
||||
QStringList nameVariants;
|
||||
|
||||
// cardName_providerId
|
||||
if (!providerId.isEmpty()) {
|
||||
nameVariants << QString("%1-%2").arg(correctedCardName, providerId)
|
||||
<< QString("%1_%2").arg(correctedCardName, providerId);
|
||||
}
|
||||
// cardName_setName_collectorNumber & setName-collectorNumber-cardName
|
||||
if (!setName.isEmpty() && !collectorNumber.isEmpty()) {
|
||||
nameVariants << QString("%1_%2_%3").arg(correctedCardName, setName, collectorNumber)
|
||||
<< QString("%1-%2-%3").arg(setName, collectorNumber, correctedCardName);
|
||||
}
|
||||
// cardName_setName
|
||||
if (!setName.isEmpty()) {
|
||||
nameVariants << QString("%1_%2").arg(correctedCardName, setName)
|
||||
<< QString("%1-%2").arg(setName, correctedCardName);
|
||||
}
|
||||
|
||||
// cardName
|
||||
nameVariants << correctedCardName;
|
||||
|
||||
for (const QString &nameVariant : nameVariants) {
|
||||
if (nameVariant.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QStringList candidatePaths = customFolderIndex.values(nameVariant);
|
||||
|
||||
if (!setName.isEmpty()) {
|
||||
candidatePaths << picsPath + "/" + setName + "/" + nameVariant;
|
||||
candidatePaths << picsPath + "/downloadedPics/" + setName + "/" + nameVariant;
|
||||
}
|
||||
|
||||
for (const QString &path : candidatePaths) {
|
||||
QFileInfo fileInfo(path);
|
||||
QDir dir = fileInfo.dir();
|
||||
QString baseName = fileInfo.fileName();
|
||||
|
||||
if (!dir.exists()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QStringList files = dir.entryList(QDir::Files);
|
||||
for (const QString &file : files) {
|
||||
if (!file.startsWith(baseName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QString fullPath = dir.filePath(file);
|
||||
imgReader.setFileName(fullPath);
|
||||
|
||||
if (imgReader.read(&image)) {
|
||||
qCDebug(CardPictureLoaderLocalLog).nospace()
|
||||
<< "[card: " << correctedCardName << " set: " << setName << "] Found picture at: " << fullPath;
|
||||
return image;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qCDebug(CardPictureLoaderLocalLog).nospace()
|
||||
<< "[card: " << correctedCardName << " set: " << setName << "]: Picture NOT found on disk.";
|
||||
return QImage();
|
||||
}
|
||||
|
||||
void CardPictureLoaderLocal::picsPathChanged()
|
||||
{
|
||||
picsPath = SettingsCache::instance().getPicsPath();
|
||||
customPicsPath = SettingsCache::instance().getCustomPicsPath();
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
* @file card_picture_loader_local.h
|
||||
* @ingroup PictureLoader
|
||||
* @brief TODO: Document this.
|
||||
*/
|
||||
|
||||
#ifndef PICTURE_LOADER_LOCAL_H
|
||||
#define PICTURE_LOADER_LOCAL_H
|
||||
|
||||
#include <QLoggingCategory>
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
#include <libcockatrice/card/card_printing/exact_card.h>
|
||||
|
||||
inline Q_LOGGING_CATEGORY(CardPictureLoaderLocalLog, "card_picture_loader.local");
|
||||
|
||||
/**
|
||||
* Handles searching for and loading card images from the local pics and custom image folders.
|
||||
* This class maintains an index of the CUSTOM folder, to avoid repeatedly searching the entire directory.
|
||||
*/
|
||||
class CardPictureLoaderLocal : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CardPictureLoaderLocal(QObject *parent);
|
||||
|
||||
QImage tryLoad(const ExactCard &toLoad) const;
|
||||
|
||||
private:
|
||||
QString picsPath, customPicsPath;
|
||||
|
||||
QMultiHash<QString, QString> customFolderIndex; // multimap of cardName to picPaths
|
||||
QTimer *refreshTimer;
|
||||
|
||||
void refreshIndex();
|
||||
|
||||
QImage tryLoadCardImageFromDisk(const QString &setName,
|
||||
const QString &correctedCardName,
|
||||
const QString &collectorNumber,
|
||||
const QString &providerId) const;
|
||||
|
||||
private slots:
|
||||
void picsPathChanged();
|
||||
};
|
||||
|
||||
#endif // PICTURE_LOADER_LOCAL_H
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
#include "card_picture_loader_request_status_display_widget.h"
|
||||
|
||||
CardPictureLoaderRequestStatusDisplayWidget::CardPictureLoaderRequestStatusDisplayWidget(QWidget *parent,
|
||||
const QUrl &_url,
|
||||
const ExactCard &card,
|
||||
const QString &setName)
|
||||
: QWidget(parent)
|
||||
{
|
||||
layout = new QHBoxLayout(this);
|
||||
|
||||
name = new QLabel(this);
|
||||
name->setText(card.getName());
|
||||
setShortname = new QLabel(this);
|
||||
setShortname->setText(setName);
|
||||
providerId = new QLabel(this);
|
||||
providerId->setText(card.getPrinting().getUuid());
|
||||
|
||||
layout->addWidget(name);
|
||||
layout->addWidget(setShortname);
|
||||
layout->addWidget(providerId);
|
||||
|
||||
startTime = new QLabel(QDateTime::currentDateTime().toString(), this);
|
||||
elapsedTime = new QLabel("0", this);
|
||||
finished = new QLabel("False", this);
|
||||
url = new QLabel(_url.toString(), this);
|
||||
|
||||
layout->addWidget(startTime);
|
||||
layout->addWidget(elapsedTime);
|
||||
layout->addWidget(finished);
|
||||
layout->addWidget(url);
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
* @file card_picture_loader_request_status_display_widget.h
|
||||
* @ingroup PictureLoader
|
||||
* @brief TODO: Document this.
|
||||
*/
|
||||
|
||||
#ifndef PICTURE_LOADER_REQUEST_STATUS_DISPLAY_WIDGET_H
|
||||
#define PICTURE_LOADER_REQUEST_STATUS_DISPLAY_WIDGET_H
|
||||
#include "card_picture_loader_worker_work.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QWidget>
|
||||
|
||||
class CardPictureLoaderRequestStatusDisplayWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CardPictureLoaderRequestStatusDisplayWidget(QWidget *parent,
|
||||
const QUrl &url,
|
||||
const ExactCard &card,
|
||||
const QString &setName);
|
||||
|
||||
void setFinished()
|
||||
{
|
||||
finished->setText("True");
|
||||
update();
|
||||
repaint();
|
||||
}
|
||||
|
||||
bool getFinished() const
|
||||
{
|
||||
return finished->text() == "True";
|
||||
}
|
||||
|
||||
void setElapsedTime(const QString &_elapsedTime) const
|
||||
{
|
||||
elapsedTime->setText(_elapsedTime);
|
||||
}
|
||||
|
||||
int queryElapsedSeconds()
|
||||
{
|
||||
if (!finished) {
|
||||
int elapsedSeconds = QDateTime::fromString(startTime->text()).secsTo(QDateTime::currentDateTime());
|
||||
elapsedTime->setText(QString::number(elapsedSeconds));
|
||||
update();
|
||||
repaint();
|
||||
return elapsedSeconds;
|
||||
}
|
||||
return elapsedTime->text().toInt();
|
||||
}
|
||||
|
||||
QString getStartTime() const
|
||||
{
|
||||
return startTime->text();
|
||||
}
|
||||
|
||||
QString getUrl() const
|
||||
{
|
||||
return url->text();
|
||||
}
|
||||
|
||||
private:
|
||||
QHBoxLayout *layout;
|
||||
QLabel *name;
|
||||
QLabel *setShortname;
|
||||
QLabel *providerId;
|
||||
QLabel *startTime;
|
||||
QLabel *elapsedTime;
|
||||
QLabel *finished;
|
||||
QLabel *url;
|
||||
};
|
||||
|
||||
#endif // PICTURE_LOADER_REQUEST_STATUS_DISPLAY_WIDGET_H
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
#include "card_picture_loader_status_bar.h"
|
||||
|
||||
#include "card_picture_loader_request_status_display_widget.h"
|
||||
|
||||
CardPictureLoaderStatusBar::CardPictureLoaderStatusBar(QWidget *parent) : QWidget(parent)
|
||||
{
|
||||
layout = new QHBoxLayout(this);
|
||||
progressBar = new QProgressBar(this);
|
||||
progressBar->setMaximum(0);
|
||||
progressBar->setFormat("%v/%m");
|
||||
layout->addWidget(progressBar);
|
||||
|
||||
loadLog = new SettingsButtonWidget(this);
|
||||
layout->addWidget(loadLog);
|
||||
|
||||
cleaner = new QTimer(this);
|
||||
cleaner->setInterval(1000);
|
||||
connect(cleaner, &QTimer::timeout, this, &CardPictureLoaderStatusBar::cleanOldEntries);
|
||||
cleaner->start();
|
||||
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
void CardPictureLoaderStatusBar::cleanOldEntries()
|
||||
{
|
||||
if (!loadLog || !loadLog->popup) {
|
||||
return;
|
||||
}
|
||||
for (CardPictureLoaderRequestStatusDisplayWidget *statusDisplayWidget :
|
||||
loadLog->popup->findChildren<CardPictureLoaderRequestStatusDisplayWidget *>()) {
|
||||
statusDisplayWidget->queryElapsedSeconds();
|
||||
if (statusDisplayWidget->getFinished() &&
|
||||
QDateTime::fromString(statusDisplayWidget->getStartTime()).secsTo(QDateTime::currentDateTime()) > 10) {
|
||||
loadLog->removeSettingsWidget(statusDisplayWidget);
|
||||
progressBar->setMaximum(progressBar->maximum() - 1);
|
||||
progressBar->setValue(progressBar->value() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CardPictureLoaderStatusBar::addQueuedImageLoad(const QUrl &url, const ExactCard &card, const QString &setName)
|
||||
{
|
||||
loadLog->addSettingsWidget(new CardPictureLoaderRequestStatusDisplayWidget(loadLog, url, card, setName));
|
||||
progressBar->setMaximum(progressBar->maximum() + 1);
|
||||
}
|
||||
|
||||
void CardPictureLoaderStatusBar::addSuccessfulImageLoad(const QUrl &url)
|
||||
{
|
||||
progressBar->setValue(progressBar->value() + 1);
|
||||
for (CardPictureLoaderRequestStatusDisplayWidget *statusDisplayWidget :
|
||||
loadLog->popup->findChildren<CardPictureLoaderRequestStatusDisplayWidget *>()) {
|
||||
if (statusDisplayWidget->getUrl() == url.toString()) {
|
||||
statusDisplayWidget->queryElapsedSeconds();
|
||||
statusDisplayWidget->setFinished();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* @file card_picture_loader_status_bar.h
|
||||
* @ingroup PictureLoader
|
||||
* @brief TODO: Document this.
|
||||
*/
|
||||
|
||||
#ifndef PICTURE_LOADER_STATUS_BAR_H
|
||||
#define PICTURE_LOADER_STATUS_BAR_H
|
||||
|
||||
#include "../../interface/widgets/quick_settings/settings_button_widget.h"
|
||||
#include "card_picture_loader_worker_work.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QProgressBar>
|
||||
#include <QWidget>
|
||||
|
||||
class CardPictureLoaderStatusBar : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit CardPictureLoaderStatusBar(QWidget *parent);
|
||||
|
||||
public slots:
|
||||
void addQueuedImageLoad(const QUrl &url, const ExactCard &card, const QString &setName);
|
||||
void addSuccessfulImageLoad(const QUrl &url);
|
||||
void cleanOldEntries();
|
||||
|
||||
private:
|
||||
QHBoxLayout *layout;
|
||||
QProgressBar *progressBar;
|
||||
SettingsButtonWidget *loadLog;
|
||||
QTimer *cleaner;
|
||||
};
|
||||
|
||||
#endif // PICTURE_LOADER_STATUS_BAR_H
|
||||
|
|
@ -0,0 +1,238 @@
|
|||
#include "card_picture_loader_worker.h"
|
||||
|
||||
#include "card_picture_loader_local.h"
|
||||
#include "card_picture_loader_worker_work.h"
|
||||
|
||||
#include <QDirIterator>
|
||||
#include <QMovie>
|
||||
#include <QNetworkDiskCache>
|
||||
#include <QNetworkReply>
|
||||
#include <QThread>
|
||||
#include <libcockatrice/card/card_database/card_database_manager.h>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
#include <utility>
|
||||
|
||||
static constexpr int MAX_REQUESTS_PER_SEC = 10;
|
||||
|
||||
CardPictureLoaderWorker::CardPictureLoaderWorker()
|
||||
: QObject(nullptr), picDownload(SettingsCache::instance().getPicDownload()), requestQuota(MAX_REQUESTS_PER_SEC)
|
||||
{
|
||||
networkManager = new QNetworkAccessManager(this);
|
||||
// We need a timeout to ensure requests don't hang indefinitely in case of
|
||||
// cache corruption, see related Qt bug: https://bugreports.qt.io/browse/QTBUG-111397
|
||||
// Use Qt's default timeout (30s, as of 2023-02-22)
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
|
||||
networkManager->setTransferTimeout();
|
||||
#endif
|
||||
cache = new QNetworkDiskCache(this);
|
||||
cache->setCacheDirectory(SettingsCache::instance().getNetworkCachePath());
|
||||
cache->setMaximumCacheSize(1024L * 1024L *
|
||||
static_cast<qint64>(SettingsCache::instance().getNetworkCacheSizeInMB()));
|
||||
// Note: the settings is in MB, but QNetworkDiskCache uses bytes
|
||||
connect(&SettingsCache::instance(), &SettingsCache::networkCacheSizeChanged, this,
|
||||
[this](int newSizeInMB) { cache->setMaximumCacheSize(1024L * 1024L * static_cast<qint64>(newSizeInMB)); });
|
||||
networkManager->setCache(cache);
|
||||
// Use a ManualRedirectPolicy since we keep track of redirects in picDownloadFinished
|
||||
// We can't use NoLessSafeRedirectPolicy because it is not applied with AlwaysCache
|
||||
networkManager->setRedirectPolicy(QNetworkRequest::ManualRedirectPolicy);
|
||||
|
||||
cacheFilePath = SettingsCache::instance().getRedirectCachePath() + REDIRECT_CACHE_FILENAME;
|
||||
loadRedirectCache();
|
||||
cleanStaleEntries();
|
||||
|
||||
connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this,
|
||||
&CardPictureLoaderWorker::saveRedirectCache);
|
||||
|
||||
localLoader = new CardPictureLoaderLocal(this);
|
||||
|
||||
pictureLoaderThread = new QThread;
|
||||
pictureLoaderThread->start(QThread::LowPriority);
|
||||
moveToThread(pictureLoaderThread);
|
||||
|
||||
connect(this, &CardPictureLoaderWorker::imageLoadEnqueued, this, &CardPictureLoaderWorker::handleImageLoadEnqueued);
|
||||
|
||||
connect(&requestTimer, &QTimer::timeout, this, &CardPictureLoaderWorker::resetRequestQuota);
|
||||
requestTimer.setInterval(1000);
|
||||
requestTimer.start();
|
||||
}
|
||||
|
||||
CardPictureLoaderWorker::~CardPictureLoaderWorker()
|
||||
{
|
||||
saveRedirectCache();
|
||||
pictureLoaderThread->deleteLater();
|
||||
}
|
||||
|
||||
void CardPictureLoaderWorker::queueRequest(const QUrl &url, CardPictureLoaderWorkerWork *worker)
|
||||
{
|
||||
QUrl cachedRedirect = getCachedRedirect(url);
|
||||
if (!cachedRedirect.isEmpty()) {
|
||||
queueRequest(cachedRedirect, worker);
|
||||
} else if (cache->metaData(url).isValid()) {
|
||||
// If we hit a cached url, we get to make the request for free, since it won't contribute towards the rate-limit
|
||||
makeRequest(url, worker);
|
||||
} else {
|
||||
requestLoadQueue.append(qMakePair(url, worker));
|
||||
emit imageRequestQueued(url, worker->cardToDownload.getCard(), worker->cardToDownload.getSetName());
|
||||
processQueuedRequests();
|
||||
}
|
||||
}
|
||||
|
||||
QNetworkReply *CardPictureLoaderWorker::makeRequest(const QUrl &url, CardPictureLoaderWorkerWork *worker)
|
||||
{
|
||||
// Check for cached redirects
|
||||
QUrl cachedRedirect = getCachedRedirect(url);
|
||||
if (!cachedRedirect.isEmpty()) {
|
||||
emit imageRequestSucceeded(url);
|
||||
return makeRequest(cachedRedirect, worker);
|
||||
}
|
||||
|
||||
QNetworkRequest req(url);
|
||||
if (!picDownload) {
|
||||
req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysCache);
|
||||
}
|
||||
|
||||
QNetworkReply *reply = networkManager->get(req);
|
||||
|
||||
// Connect reply handling
|
||||
connect(reply, &QNetworkReply::finished, worker, [reply, worker] { worker->handleNetworkReply(reply); });
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
void CardPictureLoaderWorker::resetRequestQuota()
|
||||
{
|
||||
requestQuota = MAX_REQUESTS_PER_SEC;
|
||||
processQueuedRequests();
|
||||
}
|
||||
|
||||
/**
|
||||
* Keeps processing requests from the queue until it is empty or until the quota runs out.
|
||||
*/
|
||||
void CardPictureLoaderWorker::processQueuedRequests()
|
||||
{
|
||||
while (requestQuota > 0 && processSingleRequest()) {
|
||||
--requestQuota;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Immediately processes a single queued request. No-ops if the load queue is empty
|
||||
* @return If a request was processed
|
||||
*/
|
||||
bool CardPictureLoaderWorker::processSingleRequest()
|
||||
{
|
||||
if (!requestLoadQueue.isEmpty()) {
|
||||
auto request = requestLoadQueue.takeFirst();
|
||||
makeRequest(request.first, request.second);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CardPictureLoaderWorker::enqueueImageLoad(const ExactCard &card)
|
||||
{
|
||||
// Send call through a connection to ensure the handling is run on the pictureLoader thread
|
||||
emit imageLoadEnqueued(card);
|
||||
}
|
||||
|
||||
void CardPictureLoaderWorker::handleImageLoadEnqueued(const ExactCard &card)
|
||||
{
|
||||
// deduplicate loads for the same card
|
||||
if (currentlyLoading.contains(card.getPixmapCacheKey())) {
|
||||
qCDebug(CardPictureLoaderWorkerLog())
|
||||
<< "Skipping enqueued" << card.getName() << "because it's already being loaded";
|
||||
return;
|
||||
}
|
||||
currentlyLoading.insert(card.getPixmapCacheKey());
|
||||
|
||||
// try to load image from local first
|
||||
QImage image = localLoader->tryLoad(card);
|
||||
if (!image.isNull()) {
|
||||
handleImageLoaded(card, image);
|
||||
} else {
|
||||
// queue up to load image from remote only after local loading failed
|
||||
new CardPictureLoaderWorkerWork(this, card);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when image loading is done. Failures are indicated by an empty QImage.
|
||||
*/
|
||||
void CardPictureLoaderWorker::handleImageLoaded(const ExactCard &card, const QImage &image)
|
||||
{
|
||||
currentlyLoading.remove(card.getPixmapCacheKey());
|
||||
emit imageLoaded(card, image);
|
||||
}
|
||||
|
||||
void CardPictureLoaderWorker::cacheRedirect(const QUrl &originalUrl, const QUrl &redirectUrl)
|
||||
{
|
||||
redirectCache[originalUrl] = qMakePair(redirectUrl, QDateTime::currentDateTimeUtc());
|
||||
// saveRedirectCache();
|
||||
}
|
||||
|
||||
void CardPictureLoaderWorker::removedCachedUrl(const QUrl &url)
|
||||
{
|
||||
networkManager->cache()->remove(url);
|
||||
}
|
||||
|
||||
QUrl CardPictureLoaderWorker::getCachedRedirect(const QUrl &originalUrl) const
|
||||
{
|
||||
if (redirectCache.contains(originalUrl)) {
|
||||
return redirectCache[originalUrl].first;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void CardPictureLoaderWorker::loadRedirectCache()
|
||||
{
|
||||
QSettings settings(cacheFilePath, QSettings::IniFormat);
|
||||
|
||||
redirectCache.clear();
|
||||
int size = settings.beginReadArray(REDIRECT_HEADER_NAME);
|
||||
for (int i = 0; i < size; ++i) {
|
||||
settings.setArrayIndex(i);
|
||||
QUrl originalUrl = settings.value(REDIRECT_ORIGINAL_URL).toUrl();
|
||||
QUrl redirectUrl = settings.value(REDIRECT_URL).toUrl();
|
||||
QDateTime timestamp = settings.value(REDIRECT_TIMESTAMP).toDateTime();
|
||||
|
||||
if (originalUrl.isValid() && redirectUrl.isValid()) {
|
||||
redirectCache[originalUrl] = qMakePair(redirectUrl, timestamp);
|
||||
}
|
||||
}
|
||||
settings.endArray();
|
||||
}
|
||||
|
||||
void CardPictureLoaderWorker::saveRedirectCache() const
|
||||
{
|
||||
QSettings settings(cacheFilePath, QSettings::IniFormat);
|
||||
|
||||
settings.beginWriteArray(REDIRECT_HEADER_NAME, static_cast<int>(redirectCache.size()));
|
||||
int index = 0;
|
||||
for (auto it = redirectCache.cbegin(); it != redirectCache.cend(); ++it) {
|
||||
settings.setArrayIndex(index++);
|
||||
settings.setValue(REDIRECT_ORIGINAL_URL, it.key());
|
||||
settings.setValue(REDIRECT_URL, it.value().first);
|
||||
settings.setValue(REDIRECT_TIMESTAMP, it.value().second);
|
||||
}
|
||||
settings.endArray();
|
||||
}
|
||||
|
||||
void CardPictureLoaderWorker::cleanStaleEntries()
|
||||
{
|
||||
QDateTime now = QDateTime::currentDateTimeUtc();
|
||||
|
||||
auto it = redirectCache.begin();
|
||||
while (it != redirectCache.end()) {
|
||||
if (it.value().second.addDays(SettingsCache::instance().getRedirectCacheTtl()) < now) {
|
||||
it = redirectCache.erase(it); // Remove stale entry
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CardPictureLoaderWorker::clearNetworkCache()
|
||||
{
|
||||
networkManager->cache()->clear();
|
||||
redirectCache.clear();
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
/**
|
||||
* @file card_picture_loader_worker.h
|
||||
* @ingroup PictureLoader
|
||||
* @brief TODO: Document this.
|
||||
*/
|
||||
|
||||
#ifndef PICTURE_LOADER_WORKER_H
|
||||
#define PICTURE_LOADER_WORKER_H
|
||||
|
||||
#include "card_picture_loader_local.h"
|
||||
#include "card_picture_loader_worker_work.h"
|
||||
#include "card_picture_to_load.h"
|
||||
|
||||
#include <QLoggingCategory>
|
||||
#include <QMutex>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkDiskCache>
|
||||
#include <QObject>
|
||||
#include <QQueue>
|
||||
#include <QTimer>
|
||||
#include <libcockatrice/card/card_database/card_database.h>
|
||||
#include <libcockatrice/card/card_info.h>
|
||||
|
||||
#define REDIRECT_HEADER_NAME "redirects"
|
||||
#define REDIRECT_ORIGINAL_URL "original"
|
||||
#define REDIRECT_URL "redirect"
|
||||
#define REDIRECT_TIMESTAMP "timestamp"
|
||||
#define REDIRECT_CACHE_FILENAME "cache.ini"
|
||||
|
||||
inline Q_LOGGING_CATEGORY(CardPictureLoaderWorkerLog, "card_picture_loader.worker");
|
||||
|
||||
class CardPictureLoaderWorkerWork;
|
||||
class CardPictureLoaderWorker : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit CardPictureLoaderWorker();
|
||||
~CardPictureLoaderWorker() override;
|
||||
|
||||
void enqueueImageLoad(const ExactCard &card); // Starts a thread for the image to be loaded
|
||||
void queueRequest(const QUrl &url, CardPictureLoaderWorkerWork *worker); // Queues network requests for load threads
|
||||
void clearNetworkCache();
|
||||
|
||||
public slots:
|
||||
QNetworkReply *makeRequest(const QUrl &url, CardPictureLoaderWorkerWork *workThread);
|
||||
void processQueuedRequests();
|
||||
bool processSingleRequest();
|
||||
void handleImageLoaded(const ExactCard &card, const QImage &image);
|
||||
void cacheRedirect(const QUrl &originalUrl, const QUrl &redirectUrl);
|
||||
void removedCachedUrl(const QUrl &url);
|
||||
|
||||
private:
|
||||
QThread *pictureLoaderThread;
|
||||
QNetworkAccessManager *networkManager;
|
||||
QNetworkDiskCache *cache;
|
||||
QHash<QUrl, QPair<QUrl, QDateTime>> redirectCache; // Stores redirect and timestamp
|
||||
QString cacheFilePath; // Path to persistent storage
|
||||
static constexpr int CacheTTLInDays = 30; // TODO: Make user configurable
|
||||
bool picDownload;
|
||||
QQueue<QPair<QUrl, CardPictureLoaderWorkerWork *>> requestLoadQueue;
|
||||
|
||||
int requestQuota;
|
||||
QTimer requestTimer; // Timer for refreshing request quota
|
||||
|
||||
CardPictureLoaderLocal *localLoader;
|
||||
QSet<QString> currentlyLoading; // for deduplication purposes. Contains pixmapCacheKey
|
||||
|
||||
QUrl getCachedRedirect(const QUrl &originalUrl) const;
|
||||
void loadRedirectCache();
|
||||
void saveRedirectCache() const;
|
||||
void cleanStaleEntries();
|
||||
|
||||
private slots:
|
||||
void resetRequestQuota();
|
||||
void handleImageLoadEnqueued(const ExactCard &card);
|
||||
|
||||
signals:
|
||||
void imageLoadEnqueued(const ExactCard &card);
|
||||
void imageLoaded(const ExactCard &card, const QImage &image);
|
||||
void imageRequestQueued(const QUrl &url, const ExactCard &card, const QString &setName);
|
||||
void imageRequestSucceeded(const QUrl &url);
|
||||
};
|
||||
|
||||
#endif // PICTURE_LOADER_WORKER_H
|
||||
|
|
@ -0,0 +1,223 @@
|
|||
#include "card_picture_loader_worker_work.h"
|
||||
|
||||
#include "card_picture_loader_worker.h"
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QDirIterator>
|
||||
#include <QLoggingCategory>
|
||||
#include <QMovie>
|
||||
#include <QNetworkDiskCache>
|
||||
#include <QNetworkReply>
|
||||
#include <QThread>
|
||||
#include <QThreadPool>
|
||||
#include <libcockatrice/card/card_database/card_database_manager.h>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
|
||||
// Card back returned by gatherer when card is not found
|
||||
static const QStringList MD5_BLACKLIST = {"db0c48db407a907c16ade38de048a441"};
|
||||
|
||||
CardPictureLoaderWorkerWork::CardPictureLoaderWorkerWork(const CardPictureLoaderWorker *worker, const ExactCard &toLoad)
|
||||
: QObject(nullptr), cardToDownload(CardPictureToLoad(toLoad)),
|
||||
picDownload(SettingsCache::instance().getPicDownload())
|
||||
{
|
||||
// Hook up signals to the orchestrator
|
||||
connect(this, &CardPictureLoaderWorkerWork::requestImageDownload, worker, &CardPictureLoaderWorker::queueRequest);
|
||||
connect(this, &CardPictureLoaderWorkerWork::urlRedirected, worker, &CardPictureLoaderWorker::cacheRedirect);
|
||||
connect(this, &CardPictureLoaderWorkerWork::cachedUrlInvalidated, worker,
|
||||
&CardPictureLoaderWorker::removedCachedUrl);
|
||||
connect(this, &CardPictureLoaderWorkerWork::imageLoaded, worker, &CardPictureLoaderWorker::handleImageLoaded);
|
||||
connect(this, &CardPictureLoaderWorkerWork::requestSucceeded, worker,
|
||||
&CardPictureLoaderWorker::imageRequestSucceeded);
|
||||
|
||||
// Hook up signals to settings
|
||||
connect(&SettingsCache::instance(), SIGNAL(picDownloadChanged()), this, SLOT(picDownloadChanged()));
|
||||
|
||||
startNextPicDownload();
|
||||
}
|
||||
|
||||
void CardPictureLoaderWorkerWork::startNextPicDownload()
|
||||
{
|
||||
QString picUrl = cardToDownload.getCurrentUrl();
|
||||
|
||||
if (picUrl.isEmpty()) {
|
||||
picDownloadFailed();
|
||||
} else {
|
||||
QUrl url(picUrl);
|
||||
qCDebug(CardPictureLoaderWorkerWorkLog).nospace()
|
||||
<< "PictureLoader: [card: " << cardToDownload.getCard().getInfo().getCorrectedName()
|
||||
<< " set: " << cardToDownload.getSetName() << "]: Trying to fetch picture from url "
|
||||
<< url.toDisplayString();
|
||||
emit requestImageDownload(url, this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts another pic download using the next possible url combination for the card.
|
||||
* If all possibilities are exhausted, then concludes the image loading with an empty QImage.
|
||||
*/
|
||||
void CardPictureLoaderWorkerWork::picDownloadFailed()
|
||||
{
|
||||
/* Take advantage of short-circuiting here to call the nextUrl until one
|
||||
is not available. Only once nextUrl evaluates to false will this move
|
||||
on to nextSet. If the Urls for a particular card are empty, this will
|
||||
effectively go through the sets for that card. */
|
||||
if (cardToDownload.nextUrl() || cardToDownload.nextSet()) {
|
||||
startNextPicDownload();
|
||||
} else {
|
||||
qCWarning(CardPictureLoaderWorkerWorkLog).nospace()
|
||||
<< "PictureLoader: [card: " << cardToDownload.getCard().getInfo().getCorrectedName()
|
||||
<< " set: " << cardToDownload.getSetName() << "]: Picture NOT found, "
|
||||
<< (picDownload ? "download failed" : "downloads disabled")
|
||||
<< ", no more url combinations to try: BAILING OUT";
|
||||
concludeImageLoad(QImage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param reply The reply. Takes ownership of the object
|
||||
*/
|
||||
void CardPictureLoaderWorkerWork::handleNetworkReply(QNetworkReply *reply)
|
||||
{
|
||||
QVariant redirectTarget = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
|
||||
if (redirectTarget.isValid()) {
|
||||
QUrl url = reply->request().url();
|
||||
QUrl redirectUrl = redirectTarget.toUrl();
|
||||
if (redirectUrl.isRelative()) {
|
||||
redirectUrl = url.resolved(redirectUrl);
|
||||
}
|
||||
emit urlRedirected(url, redirectUrl);
|
||||
}
|
||||
|
||||
if (reply->error()) {
|
||||
handleFailedReply(reply);
|
||||
} else {
|
||||
handleSuccessfulReply(reply);
|
||||
emit requestSucceeded(reply->url());
|
||||
}
|
||||
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
static bool imageIsBlackListed(const QByteArray &picData)
|
||||
{
|
||||
QString md5sum = QCryptographicHash::hash(picData, QCryptographicHash::Md5).toHex();
|
||||
return MD5_BLACKLIST.contains(md5sum);
|
||||
}
|
||||
|
||||
void CardPictureLoaderWorkerWork::handleFailedReply(const QNetworkReply *reply)
|
||||
{
|
||||
if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 429) {
|
||||
qCWarning(CardPictureLoaderWorkerWorkLog) << "Too many requests.";
|
||||
} else {
|
||||
bool isFromCache = reply->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool();
|
||||
|
||||
if (isFromCache) {
|
||||
qCDebug(CardPictureLoaderWorkerWorkLog).nospace()
|
||||
<< "PictureLoader: [card: " << cardToDownload.getCard().getName()
|
||||
<< " set: " << cardToDownload.getSetName() << "]: Removing corrupted cache file for url "
|
||||
<< reply->url().toDisplayString() << " and retrying (" << reply->errorString() << ")";
|
||||
|
||||
emit cachedUrlInvalidated(reply->url());
|
||||
|
||||
emit requestImageDownload(reply->url(), this);
|
||||
} else {
|
||||
qCDebug(CardPictureLoaderWorkerWorkLog).nospace()
|
||||
<< "PictureLoader: [card: " << cardToDownload.getCard().getName()
|
||||
<< " set: " << cardToDownload.getSetName() << "]: " << (picDownload ? "Download" : "Cache search")
|
||||
<< " failed for url " << reply->url().toDisplayString() << " (" << reply->errorString() << ")";
|
||||
|
||||
picDownloadFailed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CardPictureLoaderWorkerWork::handleSuccessfulReply(QNetworkReply *reply)
|
||||
{
|
||||
bool isFromCache = reply->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool();
|
||||
|
||||
// List of status codes from https://doc.qt.io/qt-6/qnetworkreply.html#redirected
|
||||
int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
if (statusCode == 301 || statusCode == 302 || statusCode == 303 || statusCode == 305 || statusCode == 307 ||
|
||||
statusCode == 308) {
|
||||
QUrl redirectUrl = reply->header(QNetworkRequest::LocationHeader).toUrl();
|
||||
qCDebug(CardPictureLoaderWorkerWorkLog).nospace()
|
||||
<< "PictureLoader: [card: " << cardToDownload.getCard().getName() << " set: " << cardToDownload.getSetName()
|
||||
<< "]: following " << (isFromCache ? "cached redirect" : "redirect") << " to "
|
||||
<< redirectUrl.toDisplayString();
|
||||
emit requestImageDownload(redirectUrl, this);
|
||||
return;
|
||||
}
|
||||
|
||||
// peek is used to keep the data in the buffer for use by QImageReader
|
||||
const QByteArray &picData = reply->peek(reply->size());
|
||||
|
||||
if (imageIsBlackListed(picData)) {
|
||||
qCDebug(CardPictureLoaderWorkerWorkLog).nospace()
|
||||
<< "PictureLoader: [card: " << cardToDownload.getCard().getName() << " set: " << cardToDownload.getSetName()
|
||||
<< "]: Picture found, but blacklisted, will consider it as not found";
|
||||
|
||||
picDownloadFailed();
|
||||
return;
|
||||
}
|
||||
|
||||
QImage image = tryLoadImageFromReply(reply);
|
||||
|
||||
if (image.isNull()) {
|
||||
qCDebug(CardPictureLoaderWorkerWorkLog).nospace()
|
||||
<< "PictureLoader: [card: " << cardToDownload.getCard().getName() << " set: " << cardToDownload.getSetName()
|
||||
<< "]: Possible " << (isFromCache ? "cached" : "downloaded") << " picture at "
|
||||
<< reply->url().toDisplayString() << " could not be loaded: " << reply->errorString();
|
||||
|
||||
picDownloadFailed();
|
||||
} else {
|
||||
qCDebug(CardPictureLoaderWorkerWorkLog).nospace()
|
||||
<< "PictureLoader: [card: " << cardToDownload.getCard().getName() << " set: " << cardToDownload.getSetName()
|
||||
<< "]: Image successfully " << (isFromCache ? "loaded from cached" : "downloaded from") << " url "
|
||||
<< reply->url().toDisplayString();
|
||||
|
||||
concludeImageLoad(image);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param reply The reply to load the image from
|
||||
* @return The loaded image, or an empty QImage if loading failed
|
||||
*/
|
||||
QImage CardPictureLoaderWorkerWork::tryLoadImageFromReply(QNetworkReply *reply)
|
||||
{
|
||||
static constexpr int riffHeaderSize = 12; // RIFF_HEADER_SIZE from webp/format_constants.h
|
||||
auto replyHeader = reply->peek(riffHeaderSize);
|
||||
|
||||
if (replyHeader.startsWith("RIFF") && replyHeader.endsWith("WEBP")) {
|
||||
auto imgBuf = QBuffer(this);
|
||||
imgBuf.setData(reply->readAll());
|
||||
|
||||
auto movie = QMovie(&imgBuf);
|
||||
movie.start();
|
||||
movie.stop();
|
||||
|
||||
return movie.currentImage();
|
||||
}
|
||||
|
||||
QImageReader imgReader;
|
||||
imgReader.setDecideFormatFromContent(true);
|
||||
imgReader.setDevice(reply);
|
||||
|
||||
return imgReader.read();
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this method when the image has finished being loaded.
|
||||
* @param image The image that was loaded. Empty QImage indicates failure.
|
||||
*/
|
||||
void CardPictureLoaderWorkerWork::concludeImageLoad(const QImage &image)
|
||||
{
|
||||
emit imageLoaded(cardToDownload.getCard(), image);
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
void CardPictureLoaderWorkerWork::picDownloadChanged()
|
||||
{
|
||||
picDownload = SettingsCache::instance().getPicDownload();
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/**
|
||||
* @file picture_loader_worker_work.h
|
||||
* @ingroup PictureLoader
|
||||
* @brief TODO: Document this.
|
||||
*/
|
||||
|
||||
#ifndef PICTURE_LOADER_WORKER_WORK_H
|
||||
#define PICTURE_LOADER_WORKER_WORK_H
|
||||
|
||||
#include "card_picture_loader_worker.h"
|
||||
#include "card_picture_to_load.h"
|
||||
|
||||
#include <QLoggingCategory>
|
||||
#include <QMutex>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QObject>
|
||||
#include <QThread>
|
||||
#include <libcockatrice/card/card_database/card_database.h>
|
||||
|
||||
#define REDIRECT_HEADER_NAME "redirects"
|
||||
#define REDIRECT_ORIGINAL_URL "original"
|
||||
#define REDIRECT_URL "redirect"
|
||||
#define REDIRECT_TIMESTAMP "timestamp"
|
||||
#define REDIRECT_CACHE_FILENAME "cache.ini"
|
||||
|
||||
inline Q_LOGGING_CATEGORY(CardPictureLoaderWorkerWorkLog, "card_picture_loader.worker");
|
||||
|
||||
class CardPictureLoaderWorker;
|
||||
|
||||
class CardPictureLoaderWorkerWork : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit CardPictureLoaderWorkerWork(const CardPictureLoaderWorker *worker, const ExactCard &toLoad);
|
||||
|
||||
CardPictureToLoad cardToDownload;
|
||||
|
||||
public slots:
|
||||
void handleNetworkReply(QNetworkReply *reply);
|
||||
|
||||
private:
|
||||
bool picDownload;
|
||||
|
||||
void startNextPicDownload();
|
||||
void picDownloadFailed();
|
||||
void handleFailedReply(const QNetworkReply *reply);
|
||||
void handleSuccessfulReply(QNetworkReply *reply);
|
||||
QImage tryLoadImageFromReply(QNetworkReply *reply);
|
||||
void concludeImageLoad(const QImage &image);
|
||||
|
||||
private slots:
|
||||
void picDownloadChanged();
|
||||
|
||||
signals:
|
||||
/**
|
||||
* Emitted when this worker has successfully loaded the image or has exhausted all attempts at loading the image.
|
||||
* Failures are represented by an empty QImage.
|
||||
* Note that this object will delete itself as this signal is emitted.
|
||||
*/
|
||||
void imageLoaded(const ExactCard &card, const QImage &image);
|
||||
|
||||
/**
|
||||
* Emitted when a request did not return a 400 or 500 response
|
||||
*/
|
||||
void requestSucceeded(const QUrl &url);
|
||||
void requestImageDownload(const QUrl &url, CardPictureLoaderWorkerWork *instance);
|
||||
|
||||
void urlRedirected(const QUrl &originalUrl, const QUrl &redirectUrl);
|
||||
void cachedUrlInvalidated(const QUrl &url);
|
||||
};
|
||||
|
||||
#endif // PICTURE_LOADER_WORKER_WORK_H
|
||||
|
|
@ -0,0 +1,290 @@
|
|||
#include "card_picture_to_load.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDate>
|
||||
#include <QRegularExpression>
|
||||
#include <QUrl>
|
||||
#include <algorithm>
|
||||
#include <libcockatrice/card/card_set/card_set_comparator.h>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
|
||||
CardPictureToLoad::CardPictureToLoad(const ExactCard &_card)
|
||||
: card(_card), urlTemplates(SettingsCache::instance().downloads().getAllURLs())
|
||||
{
|
||||
if (card) {
|
||||
sortedSets = extractSetsSorted(card);
|
||||
// The first time called, nextSet will also populate the Urls for the first set.
|
||||
nextSet();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts a list of all the sets from the card, sorted in priority order.
|
||||
* If the card does not contain any sets, then a dummy set will be inserted into the list.
|
||||
*
|
||||
* @return A list of sets. Will not be empty.
|
||||
*/
|
||||
QList<CardSetPtr> CardPictureToLoad::extractSetsSorted(const ExactCard &card)
|
||||
{
|
||||
QList<CardSetPtr> sortedSets;
|
||||
for (const auto &printings : card.getInfo().getSets()) {
|
||||
for (const auto &printing : printings) {
|
||||
sortedSets << printing.getSet();
|
||||
}
|
||||
}
|
||||
if (sortedSets.empty()) {
|
||||
sortedSets << CardSet::newInstance("", "", "", QDate());
|
||||
}
|
||||
std::sort(sortedSets.begin(), sortedSets.end(), SetPriorityComparator());
|
||||
|
||||
// If the user hasn't disabled arts other than their personal preference...
|
||||
if (!SettingsCache::instance().getOverrideAllCardArtWithPersonalPreference()) {
|
||||
// If the pixmapCacheKey corresponds to a specific set, we have to try to load it first.
|
||||
qsizetype setIndex = sortedSets.indexOf(card.getPrinting().getSet());
|
||||
if (setIndex > 0) { // we don't need to move the set if it's already first
|
||||
CardSetPtr setForCardProviderID = sortedSets.takeAt(setIndex);
|
||||
sortedSets.prepend(setForCardProviderID);
|
||||
}
|
||||
}
|
||||
|
||||
return sortedSets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the PrintingInfo corresponding to the exactCards's card name that belongs to a given set and has the
|
||||
* exactCards's providerId.
|
||||
* If the set name is in the CardInfo, but no printings in that set match the card's providerId, then the first
|
||||
* PrintingInfo for the set is returned.
|
||||
*
|
||||
* This method only exists to maintain existing behavior.
|
||||
* TODO: check if going through all sets is still necessary after the ExactCard refactor.
|
||||
*
|
||||
* @param card The card to look in
|
||||
* @param setName The set's short name
|
||||
* @return A PrintingInfo, or a default-constructed PrintingInfo if the set name is not in the CardInfo.
|
||||
*/
|
||||
static PrintingInfo findPrintingForSet(const ExactCard &card, const QString &setName)
|
||||
{
|
||||
SetToPrintingsMap setsToPrintings = card.getInfo().getSets();
|
||||
|
||||
if (!setsToPrintings.contains(setName))
|
||||
return PrintingInfo();
|
||||
|
||||
for (const auto &printing : setsToPrintings[setName]) {
|
||||
if (printing.getUuid() == card.getPrinting().getUuid()) {
|
||||
return printing;
|
||||
}
|
||||
}
|
||||
|
||||
return setsToPrintings[setName][0];
|
||||
}
|
||||
|
||||
void CardPictureToLoad::populateSetUrls()
|
||||
{
|
||||
/* currentSetUrls is a list, populated each time a new set is requested for a particular card
|
||||
and Urls are removed from it as a download is attempted from each one. Custom Urls for
|
||||
a set are given higher priority, so should be placed first in the list. */
|
||||
currentSetUrls.clear();
|
||||
|
||||
if (card && currentSet) {
|
||||
QString setCustomURL = findPrintingForSet(card, currentSet->getShortName()).getProperty("picurl");
|
||||
|
||||
if (!setCustomURL.isEmpty()) {
|
||||
currentSetUrls.append(setCustomURL);
|
||||
}
|
||||
}
|
||||
|
||||
for (const QString &urlTemplate : urlTemplates) {
|
||||
QString transformedUrl = transformUrl(urlTemplate);
|
||||
|
||||
if (!transformedUrl.isEmpty()) {
|
||||
currentSetUrls.append(transformedUrl);
|
||||
}
|
||||
}
|
||||
|
||||
/* Call nextUrl to make sure currentUrl is up-to-date
|
||||
but we don't need the result here. */
|
||||
(void)nextUrl();
|
||||
}
|
||||
|
||||
/**
|
||||
* Advances the currentSet to the next set in the list. Then repopulates the url list with the urls from that set.
|
||||
* If we are already at the end of the list, then currentSet is set to empty.
|
||||
* @return If we are already at the end of the list
|
||||
*/
|
||||
bool CardPictureToLoad::nextSet()
|
||||
{
|
||||
if (!sortedSets.isEmpty()) {
|
||||
currentSet = sortedSets.takeFirst();
|
||||
populateSetUrls();
|
||||
return true;
|
||||
}
|
||||
currentSet = {};
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Advances the currentUrl to the next url in the list.
|
||||
* If we are already at the end of the list, then currentUrl is set to empty.
|
||||
* @return If we are already at the end of the list
|
||||
*/
|
||||
bool CardPictureToLoad::nextUrl()
|
||||
{
|
||||
if (!currentSetUrls.isEmpty()) {
|
||||
currentUrl = currentSetUrls.takeFirst();
|
||||
return true;
|
||||
}
|
||||
currentUrl = QString();
|
||||
return false;
|
||||
}
|
||||
|
||||
QString CardPictureToLoad::getSetName() const
|
||||
{
|
||||
if (currentSet) {
|
||||
return currentSet->getCorrectedShortName();
|
||||
} else {
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
|
||||
static int parse(const QString &urlTemplate,
|
||||
const QString &propType,
|
||||
const QString &cardName,
|
||||
const QString &setName,
|
||||
std::function<QString(const QString &)> getProperty,
|
||||
QMap<QString, QString> &transformMap)
|
||||
{
|
||||
static const QRegularExpression rxFillWith("^(.+)_fill_with_(.+)$");
|
||||
static const QRegularExpression rxSubStr("^(.+)_substr_(\\d+)_(\\d+)$");
|
||||
|
||||
const QRegularExpression rxCardProp("!" + propType + ":([^!]+)!");
|
||||
|
||||
auto matches = rxCardProp.globalMatch(urlTemplate);
|
||||
while (matches.hasNext()) {
|
||||
auto match = matches.next();
|
||||
QString templatePropertyName = match.captured(1);
|
||||
auto fillMatch = rxFillWith.match(templatePropertyName);
|
||||
QString cardPropertyName;
|
||||
QString fillWith;
|
||||
int subStrPos = 0;
|
||||
int subStrLen = -1;
|
||||
if (fillMatch.hasMatch()) {
|
||||
cardPropertyName = fillMatch.captured(1);
|
||||
fillWith = fillMatch.captured(2);
|
||||
} else {
|
||||
fillWith = QString();
|
||||
auto subStrMatch = rxSubStr.match(templatePropertyName);
|
||||
if (subStrMatch.hasMatch()) {
|
||||
cardPropertyName = subStrMatch.captured(1);
|
||||
subStrPos = subStrMatch.captured(2).toInt();
|
||||
subStrLen = subStrMatch.captured(3).toInt();
|
||||
} else {
|
||||
cardPropertyName = templatePropertyName;
|
||||
}
|
||||
}
|
||||
QString propertyValue = getProperty(cardPropertyName);
|
||||
if (propertyValue.isEmpty()) {
|
||||
qCDebug(CardPictureToLoadLog).nospace()
|
||||
<< "PictureLoader: [card: " << cardName << " set: " << setName << "]: Requested " << propType
|
||||
<< "property (" << cardPropertyName << ") for Url template (" << urlTemplate << ") is not available";
|
||||
return 1;
|
||||
} else {
|
||||
int propLength = propertyValue.length();
|
||||
if (subStrLen > 0) {
|
||||
if (subStrPos + subStrLen > propLength) {
|
||||
qCDebug(CardPictureToLoadLog).nospace()
|
||||
<< "PictureLoader: [card: " << cardName << " set: " << setName << "]: Requested " << propType
|
||||
<< " property (" << cardPropertyName << ") for Url template (" << urlTemplate
|
||||
<< ") is smaller than substr specification (" << subStrPos << " + " << subStrLen << " > "
|
||||
<< propLength << ")";
|
||||
return 1;
|
||||
} else {
|
||||
propertyValue = propertyValue.mid(subStrPos, subStrLen);
|
||||
propLength = subStrLen;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fillWith.isEmpty()) {
|
||||
int fillLength = fillWith.length();
|
||||
if (fillLength < propLength) {
|
||||
qCDebug(CardPictureToLoadLog).nospace()
|
||||
<< "PictureLoader: [card: " << cardName << " set: " << setName << "]: Requested " << propType
|
||||
<< " property (" << cardPropertyName << ") for Url template (" << urlTemplate
|
||||
<< ") is longer than fill specification (" << fillWith << ")";
|
||||
return 1;
|
||||
} else {
|
||||
|
||||
propertyValue = fillWith.left(fillLength - propLength) + propertyValue;
|
||||
}
|
||||
}
|
||||
|
||||
transformMap["!" + propType + ":" + templatePropertyName + "!"] = propertyValue;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
QString CardPictureToLoad::transformUrl(const QString &urlTemplate) const
|
||||
{
|
||||
/* This function takes Url templates and substitutes actual card details
|
||||
into the url. This is used for making Urls with follow a predictable format
|
||||
for downloading images. If information is requested by the template that is
|
||||
not populated for this specific card/set combination, an empty string is returned.*/
|
||||
|
||||
CardSetPtr set = getCurrentSet();
|
||||
|
||||
QMap<QString, QString> transformMap = QMap<QString, QString>();
|
||||
QString setName = getSetName();
|
||||
|
||||
// name
|
||||
QString cardName = card.getName();
|
||||
transformMap["!name!"] = cardName;
|
||||
transformMap["!name_lower!"] = card.getName().toLower();
|
||||
transformMap["!corrected_name!"] = card.getInfo().getCorrectedName();
|
||||
transformMap["!corrected_name_lower!"] = card.getInfo().getCorrectedName().toLower();
|
||||
|
||||
// card properties
|
||||
if (parse(
|
||||
urlTemplate, "prop", cardName, setName,
|
||||
[&](const QString &name) { return card.getInfo().getProperty(name); }, transformMap)) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
if (set) {
|
||||
transformMap["!setcode!"] = set->getShortName();
|
||||
transformMap["!setcode_lower!"] = set->getShortName().toLower();
|
||||
transformMap["!setname!"] = set->getLongName();
|
||||
transformMap["!setname_lower!"] = set->getLongName().toLower();
|
||||
|
||||
if (parse(
|
||||
urlTemplate, "set", cardName, setName,
|
||||
[&](const QString &name) { return findPrintingForSet(card, set->getShortName()).getProperty(name); },
|
||||
transformMap)) {
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
|
||||
// language setting
|
||||
transformMap["!sflang!"] = QString(QCoreApplication::translate(
|
||||
"PictureLoader", "en", "code for scryfall's language property, not available for all languages"));
|
||||
|
||||
QString transformedUrl = urlTemplate;
|
||||
for (const QString &prop : transformMap.keys()) {
|
||||
if (transformedUrl.contains(prop)) {
|
||||
if (!transformMap[prop].isEmpty()) {
|
||||
transformedUrl.replace(prop, QUrl::toPercentEncoding(transformMap[prop]));
|
||||
} else {
|
||||
/* This means the template is requesting information that is not
|
||||
* populated in this card, so it should return an empty string,
|
||||
* indicating an invalid Url.
|
||||
*/
|
||||
qCDebug(CardPictureToLoadLog).nospace()
|
||||
<< "PictureLoader: [card: " << cardName << " set: " << setName << "]: Requested information ("
|
||||
<< prop << ") for Url template (" << urlTemplate << ") is not available";
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return transformedUrl;
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
* @file card_picture_to_load.h
|
||||
* @ingroup PictureLoader
|
||||
* @brief TODO: Document this.
|
||||
*/
|
||||
|
||||
#ifndef PICTURE_TO_LOAD_H
|
||||
#define PICTURE_TO_LOAD_H
|
||||
|
||||
#include <QLoggingCategory>
|
||||
#include <libcockatrice/card/card_printing/exact_card.h>
|
||||
|
||||
inline Q_LOGGING_CATEGORY(CardPictureToLoadLog, "card_picture_loader.picture_to_load");
|
||||
|
||||
class CardPictureToLoad
|
||||
{
|
||||
private:
|
||||
ExactCard card;
|
||||
QList<CardSetPtr> sortedSets;
|
||||
QList<QString> urlTemplates;
|
||||
QList<QString> currentSetUrls;
|
||||
QString currentUrl;
|
||||
CardSetPtr currentSet;
|
||||
|
||||
public:
|
||||
explicit CardPictureToLoad(const ExactCard &_card);
|
||||
|
||||
const ExactCard &getCard() const
|
||||
{
|
||||
return card;
|
||||
}
|
||||
QString getCurrentUrl() const
|
||||
{
|
||||
return currentUrl;
|
||||
}
|
||||
CardSetPtr getCurrentSet() const
|
||||
{
|
||||
return currentSet;
|
||||
}
|
||||
QString getSetName() const;
|
||||
QString transformUrl(const QString &urlTemplate) const;
|
||||
bool nextSet();
|
||||
bool nextUrl();
|
||||
void populateSetUrls();
|
||||
|
||||
static QList<CardSetPtr> extractSetsSorted(const ExactCard &card);
|
||||
};
|
||||
|
||||
#endif // PICTURE_TO_LOAD_H
|
||||
|
|
@ -1,13 +1,12 @@
|
|||
#include "pixel_map_generator.h"
|
||||
|
||||
#include "pb/serverinfo_user.pb.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDomDocument>
|
||||
#include <QFile>
|
||||
#include <QPainter>
|
||||
#include <QPalette>
|
||||
#include <QSvgRenderer>
|
||||
#include <libcockatrice/protocol/pb/serverinfo_user.pb.h>
|
||||
|
||||
#define DEFAULT_COLOR_UNREGISTERED "#32c8ec";
|
||||
#define DEFAULT_COLOR_REGISTERED "#5ed900";
|
||||
|
|
|
|||
|
|
@ -7,12 +7,11 @@
|
|||
#ifndef PIXMAPGENERATOR_H
|
||||
#define PIXMAPGENERATOR_H
|
||||
|
||||
#include "user_level.h"
|
||||
|
||||
#include <QIcon>
|
||||
#include <QLoggingCategory>
|
||||
#include <QMap>
|
||||
#include <QPixmap>
|
||||
#include <libcockatrice/network/server/remote/user_level.h>
|
||||
|
||||
inline Q_LOGGING_CATEGORY(PixelMapGeneratorLog, "pixel_map_generator");
|
||||
|
||||
|
|
|
|||
|
|
@ -6,9 +6,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "../settings/cache_settings.h"
|
||||
|
||||
#include <QMenu>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
|
||||
class TearOffMenu : public QMenu
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
#include "theme_manager.h"
|
||||
|
||||
#include "../settings/cache_settings.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QColor>
|
||||
#include <QDebug>
|
||||
#include <QLibraryInfo>
|
||||
#include <QPixmapCache>
|
||||
#include <QStandardPaths>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
|
||||
#define NONE_THEME_NAME "Default"
|
||||
#define STYLE_CSS_NAME "style.css"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
#include "deck_list_sort_filter_proxy_model.h"
|
||||
|
||||
#include "../../deck/deck_list_model.h"
|
||||
|
||||
bool DeckListSortFilterProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
|
||||
{
|
||||
auto *src = sourceModel();
|
||||
|
||||
// Inner nodes? -> sort alphabetically by column 1
|
||||
bool leftIsCard = src->data(left, Qt::UserRole + 1).toBool();
|
||||
bool rightIsCard = src->data(right, Qt::UserRole + 1).toBool();
|
||||
|
||||
if (!leftIsCard || !rightIsCard) {
|
||||
QString lName = src->data(left.siblingAtColumn(1), Qt::EditRole).toString();
|
||||
QString rName = src->data(right.siblingAtColumn(1), Qt::EditRole).toString();
|
||||
return lName.localeAwareCompare(rName) < 0;
|
||||
}
|
||||
|
||||
// Both are cards -> apply sort criteria
|
||||
auto *lNode = static_cast<DecklistModelCardNode *>(left.internalPointer());
|
||||
auto *rNode = static_cast<DecklistModelCardNode *>(right.internalPointer());
|
||||
|
||||
CardInfoPtr lInfo = CardDatabaseManager::query()->guessCard({lNode->getName()}).getCardPtr();
|
||||
CardInfoPtr rInfo = CardDatabaseManager::query()->guessCard({rNode->getName()}).getCardPtr();
|
||||
|
||||
// Example: multiple tie-break criteria (colors > cmc > name)
|
||||
for (const QString &crit : sortCriteria) {
|
||||
if (crit == "name") {
|
||||
QString ln = lNode->getName();
|
||||
QString rn = rNode->getName();
|
||||
int cmp = ln.localeAwareCompare(rn);
|
||||
if (cmp != 0)
|
||||
return cmp < 0;
|
||||
} else if (crit == "cmc") {
|
||||
int lc = lInfo ? lInfo->getCmc().toInt() : 0;
|
||||
int rc = rInfo ? rInfo->getCmc().toInt() : 0;
|
||||
if (lc != rc)
|
||||
return lc < rc;
|
||||
} else if (crit == "colors") {
|
||||
QString lr = lInfo ? lInfo->getColors() : QString();
|
||||
QString rr = rInfo ? rInfo->getColors() : QString();
|
||||
int cmp = lr.localeAwareCompare(rr);
|
||||
if (cmp != 0)
|
||||
return cmp < 0;
|
||||
} else if (crit == "maintype") {
|
||||
QString lr = lInfo ? lInfo->getMainCardType() : QString();
|
||||
QString rr = rInfo ? rInfo->getMainCardType() : QString();
|
||||
int cmp = lr.localeAwareCompare(rr);
|
||||
if (cmp != 0)
|
||||
return cmp < 0;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/**
|
||||
* @file deck_list_sort_filter_proxy_model.h
|
||||
* @ingroup DeckEditorCardGroupWidgets
|
||||
* @brief TODO: Document this.
|
||||
*/
|
||||
|
||||
#ifndef COCKATRICE_DECK_LIST_SORT_FILTER_PROXY_MODEL_H
|
||||
#define COCKATRICE_DECK_LIST_SORT_FILTER_PROXY_MODEL_H
|
||||
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <libcockatrice/card/card_database/card_database_manager.h>
|
||||
|
||||
class DeckListSortFilterProxyModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DeckListSortFilterProxyModel(QObject *parent = nullptr) : QSortFilterProxyModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void setSortCriteria(const QStringList &criteria)
|
||||
{
|
||||
sortCriteria = criteria;
|
||||
invalidate(); // re-sort
|
||||
}
|
||||
|
||||
protected:
|
||||
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
|
||||
|
||||
private:
|
||||
QStringList sortCriteria;
|
||||
};
|
||||
|
||||
#endif // COCKATRICE_DECK_LIST_SORT_FILTER_PROXY_MODEL_H
|
||||
219
cockatrice/src/interface/utility/sequence_edit.cpp
Normal file
219
cockatrice/src/interface/utility/sequence_edit.cpp
Normal file
|
|
@ -0,0 +1,219 @@
|
|||
#include "sequence_edit.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QKeyEvent>
|
||||
#include <QToolTip>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
#include <utility>
|
||||
|
||||
SequenceEdit::SequenceEdit(const QString &_shortcutName, QWidget *parent) : QWidget(parent)
|
||||
{
|
||||
lineEdit = new QLineEdit(this);
|
||||
clearButton = new QPushButton("", this);
|
||||
defaultButton = new QPushButton("", this);
|
||||
|
||||
lineEdit->setMinimumWidth(70);
|
||||
clearButton->setIcon(QPixmap("theme:icons/clearsearch"));
|
||||
defaultButton->setIcon(QPixmap("theme:icons/update"));
|
||||
|
||||
auto *layout = new QHBoxLayout(this);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->setSpacing(1);
|
||||
layout->addWidget(lineEdit);
|
||||
layout->addWidget(clearButton);
|
||||
layout->addWidget(defaultButton);
|
||||
|
||||
connect(clearButton, &QPushButton::clicked, this, &SequenceEdit::removeLastShortcut);
|
||||
connect(defaultButton, &QPushButton::clicked, this, &SequenceEdit::restoreDefault);
|
||||
lineEdit->installEventFilter(this);
|
||||
|
||||
setShortcutName(_shortcutName);
|
||||
retranslateUi();
|
||||
}
|
||||
|
||||
void SequenceEdit::setShortcutName(const QString &_shortcutName)
|
||||
{
|
||||
shortcutName = _shortcutName;
|
||||
if (shortcutName.isEmpty()) {
|
||||
clearButton->setEnabled(false);
|
||||
defaultButton->setEnabled(false);
|
||||
lineEdit->setEnabled(false);
|
||||
lineEdit->setText("");
|
||||
// Correct as in-line translation
|
||||
lineEdit->setPlaceholderText(tr("Choose an action from the table"));
|
||||
} else {
|
||||
clearButton->setEnabled(true);
|
||||
defaultButton->setEnabled(true);
|
||||
lineEdit->setEnabled(true);
|
||||
lineEdit->setText(SettingsCache::instance().shortcuts().getShortcutString(shortcutName));
|
||||
// Correct as in-line translation
|
||||
lineEdit->setPlaceholderText(tr("Hit the key/combination of keys you want to set for this action"));
|
||||
}
|
||||
}
|
||||
|
||||
QString SequenceEdit::getSequence()
|
||||
{
|
||||
return lineEdit->text();
|
||||
}
|
||||
|
||||
void SequenceEdit::removeLastShortcut()
|
||||
{
|
||||
QString sequences = lineEdit->text();
|
||||
if (!sequences.isEmpty()) {
|
||||
if (sequences.lastIndexOf(";") > 0) {
|
||||
QString validText = sequences.left(sequences.lastIndexOf(";"));
|
||||
lineEdit->setText(validText);
|
||||
} else {
|
||||
lineEdit->clear();
|
||||
}
|
||||
|
||||
updateSettings();
|
||||
}
|
||||
}
|
||||
|
||||
void SequenceEdit::restoreDefault()
|
||||
{
|
||||
lineEdit->setText(SettingsCache::instance().shortcuts().getDefaultShortcutString(shortcutName));
|
||||
updateSettings();
|
||||
}
|
||||
|
||||
void SequenceEdit::refreshShortcut()
|
||||
{
|
||||
lineEdit->setText(SettingsCache::instance().shortcuts().getShortcutString(shortcutName));
|
||||
}
|
||||
|
||||
void SequenceEdit::clear()
|
||||
{
|
||||
lineEdit->setText("");
|
||||
}
|
||||
|
||||
bool SequenceEdit::eventFilter(QObject *obj, QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) {
|
||||
auto *keyEvent = reinterpret_cast<QKeyEvent *>(event);
|
||||
|
||||
// don't filter outside arrow key events
|
||||
if (obj != lineEdit) {
|
||||
switch (keyEvent->key()) {
|
||||
case Qt::Key_Up:
|
||||
case Qt::Key_Down:
|
||||
case Qt::Key_Left:
|
||||
case Qt::Key_Right:
|
||||
return false;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (event->type() == QEvent::KeyPress && !keyEvent->isAutoRepeat()) {
|
||||
processKey(keyEvent);
|
||||
} else if (event->type() == QEvent::KeyRelease && !keyEvent->isAutoRepeat()) {
|
||||
finishShortcut();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SequenceEdit::processKey(QKeyEvent *e)
|
||||
{
|
||||
int key = e->key();
|
||||
if (key != Qt::Key_Control && key != Qt::Key_Shift && key != Qt::Key_Meta && key != Qt::Key_Alt) {
|
||||
valid = true;
|
||||
key |= translateModifiers(e->modifiers(), e->text());
|
||||
}
|
||||
|
||||
keys = key;
|
||||
currentKey++;
|
||||
if (currentKey >= key) {
|
||||
finishShortcut();
|
||||
}
|
||||
}
|
||||
|
||||
int SequenceEdit::translateModifiers(Qt::KeyboardModifiers state, const QString &text)
|
||||
{
|
||||
int result = 0;
|
||||
// The shift modifier only counts when it is not used to type a symbol
|
||||
// that is only reachable using the shift key anyway
|
||||
if ((state & Qt::ShiftModifier) &&
|
||||
(text.isEmpty() || !text.at(0).isPrint() || text.at(0).isLetterOrNumber() || text.at(0).isSpace())) {
|
||||
result |= Qt::SHIFT;
|
||||
}
|
||||
|
||||
if (state & Qt::ControlModifier) {
|
||||
result |= Qt::CTRL;
|
||||
}
|
||||
|
||||
if (state & Qt::MetaModifier) {
|
||||
result |= Qt::META;
|
||||
}
|
||||
|
||||
if (state & Qt::AltModifier) {
|
||||
result |= Qt::ALT;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*Validates that shortcut is valid (is a valid shortcut key sequence and doesn't conflict with any other shortcuts).
|
||||
*Displays warning messages if it's not valid.
|
||||
*
|
||||
* @param sequence The shortcut key sequence
|
||||
* @return True if the sequence isn't already self-contained
|
||||
*/
|
||||
bool SequenceEdit::validateShortcut(const QKeySequence &sequence)
|
||||
{
|
||||
if (sequence.isEmpty() || !valid) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto &shortcutsSettings = SettingsCache::instance().shortcuts();
|
||||
const QString sequenceString = sequence.toString();
|
||||
|
||||
if (!shortcutsSettings.isKeyAllowed(shortcutName, sequenceString)) {
|
||||
QToolTip::showText(lineEdit->mapToGlobal(QPoint()), tr("Invalid key"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!shortcutsSettings.isValid(shortcutName, sequenceString)) {
|
||||
auto overlaps = shortcutsSettings.findOverlaps(shortcutName, sequenceString);
|
||||
QToolTip::showText(lineEdit->mapToGlobal(QPoint()),
|
||||
tr("Shortcut already in use by:") + " " + overlaps.join(", "));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!lineEdit->text().isEmpty()) {
|
||||
if (lineEdit->text().contains(sequenceString)) {
|
||||
return false;
|
||||
}
|
||||
lineEdit->setText(lineEdit->text() + ";");
|
||||
}
|
||||
lineEdit->setText(lineEdit->text() + sequenceString);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SequenceEdit::finishShortcut()
|
||||
{
|
||||
if (!validateShortcut(QKeySequence(keys))) {
|
||||
return;
|
||||
}
|
||||
|
||||
currentKey = 0;
|
||||
keys = 0;
|
||||
valid = false;
|
||||
updateSettings();
|
||||
}
|
||||
|
||||
void SequenceEdit::updateSettings()
|
||||
{
|
||||
SettingsCache::instance().shortcuts().setShortcuts(shortcutName, lineEdit->text());
|
||||
}
|
||||
|
||||
void SequenceEdit::retranslateUi()
|
||||
{
|
||||
clearButton->setText(tr("Clear"));
|
||||
defaultButton->setText(tr("Restore default"));
|
||||
setShortcutName(shortcutName);
|
||||
}
|
||||
50
cockatrice/src/interface/utility/sequence_edit.h
Normal file
50
cockatrice/src/interface/utility/sequence_edit.h
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
* @file sequence_edit.h
|
||||
* @ingroup UI
|
||||
* @brief TODO: Document this.
|
||||
*/
|
||||
|
||||
#ifndef SEQUENCEEDIT_H
|
||||
#define SEQUENCEEDIT_H
|
||||
|
||||
#include <QEvent>
|
||||
#include <QKeySequence>
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include <QWidget>
|
||||
|
||||
class SequenceEdit : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SequenceEdit(const QString &_shortcutName, QWidget *parent = nullptr);
|
||||
QString getSequence();
|
||||
void setShortcutName(const QString &_shortcutName);
|
||||
void refreshShortcut();
|
||||
void clear();
|
||||
void retranslateUi();
|
||||
|
||||
private slots:
|
||||
void removeLastShortcut();
|
||||
void restoreDefault();
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *, QEvent *event) override;
|
||||
|
||||
private:
|
||||
QString shortcutName;
|
||||
QLineEdit *lineEdit;
|
||||
QPushButton *clearButton;
|
||||
QPushButton *defaultButton;
|
||||
int keys = 0;
|
||||
int currentKey = 0;
|
||||
bool valid = false;
|
||||
|
||||
void processKey(QKeyEvent *e);
|
||||
int translateModifiers(Qt::KeyboardModifiers state, const QString &text);
|
||||
bool validateShortcut(const QKeySequence &sequence);
|
||||
void finishShortcut();
|
||||
void updateSettings();
|
||||
};
|
||||
|
||||
#endif // SEQUENCEEDIT_H
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
#include "color_identity_widget.h"
|
||||
|
||||
#include "../../../../settings/cache_settings.h"
|
||||
#include "mana_symbol_widget.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
|
|
@ -9,6 +8,7 @@
|
|||
#include <QRegularExpression>
|
||||
#include <QResizeEvent>
|
||||
#include <QSize>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
|
||||
ColorIdentityWidget::ColorIdentityWidget(QWidget *parent, CardInfoPtr _card) : QWidget(parent), card(_card)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,10 +7,9 @@
|
|||
#ifndef COLOR_IDENTITY_WIDGET_H
|
||||
#define COLOR_IDENTITY_WIDGET_H
|
||||
|
||||
#include "../../../../card/card_info.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QWidget>
|
||||
#include <libcockatrice/card/card_info.h>
|
||||
|
||||
class ColorIdentityWidget : public QWidget
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,10 +7,9 @@
|
|||
#ifndef MANA_COST_WIDGET_H
|
||||
#define MANA_COST_WIDGET_H
|
||||
|
||||
#include "../../../../card/card_info.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QWidget>
|
||||
#include <libcockatrice/card/card_info.h>
|
||||
|
||||
class ManaCostWidget : public QWidget
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
#include "mana_symbol_widget.h"
|
||||
|
||||
#include "../../../../settings/cache_settings.h"
|
||||
|
||||
#include <QResizeEvent>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
|
||||
ManaSymbolWidget::ManaSymbolWidget(QWidget *parent, QString _symbol, bool _isActive, bool _mayBeToggled)
|
||||
: QLabel(parent), symbol(_symbol), isActive(_isActive), mayBeToggled(_mayBeToggled)
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
#include "card_group_display_widget.h"
|
||||
|
||||
#include "../../../../database/card_database_manager.h"
|
||||
#include "../../../../deck/deck_list_model.h"
|
||||
#include "../../../../utility/card_info_comparator.h"
|
||||
#include "../../../../utility/deck_list_sort_filter_proxy_model.h"
|
||||
#include "../../../utility/deck_list_sort_filter_proxy_model.h"
|
||||
#include "../card_info_picture_with_text_overlay_widget.h"
|
||||
|
||||
#include <QResizeEvent>
|
||||
#include <libcockatrice/card/card_database/card_database_manager.h>
|
||||
#include <libcockatrice/card/card_info_comparator.h>
|
||||
|
||||
CardGroupDisplayWidget::CardGroupDisplayWidget(QWidget *parent,
|
||||
DeckListModel *_deckListModel,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
#ifndef CARD_GROUP_DISPLAY_WIDGET_H
|
||||
#define CARD_GROUP_DISPLAY_WIDGET_H
|
||||
|
||||
#include "../../../../card/card_info.h"
|
||||
#include "../../../../deck/deck_list_model.h"
|
||||
#include "../../general/display/banner_widget.h"
|
||||
#include "../card_info_picture_with_text_overlay_widget.h"
|
||||
|
|
@ -16,6 +15,7 @@
|
|||
#include <QLabel>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
#include <libcockatrice/card/card_info.h>
|
||||
|
||||
class CardGroupDisplayWidget : public QWidget
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
#include "flat_card_group_display_widget.h"
|
||||
|
||||
#include "../../../../database/card_database_manager.h"
|
||||
#include "../../../../deck/deck_list_model.h"
|
||||
#include "../../../../utility/card_info_comparator.h"
|
||||
#include "../card_info_picture_with_text_overlay_widget.h"
|
||||
|
||||
#include <QResizeEvent>
|
||||
#include <libcockatrice/card/card_database/card_database_manager.h>
|
||||
#include <libcockatrice/card/card_info_comparator.h>
|
||||
#include <utility>
|
||||
|
||||
FlatCardGroupDisplayWidget::FlatCardGroupDisplayWidget(QWidget *parent,
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
#include "overlapped_card_group_display_widget.h"
|
||||
|
||||
#include "../../../../database/card_database_manager.h"
|
||||
#include "../../../../deck/deck_list_model.h"
|
||||
#include "../../../../utility/card_info_comparator.h"
|
||||
#include "../card_info_picture_with_text_overlay_widget.h"
|
||||
|
||||
#include <QResizeEvent>
|
||||
#include <libcockatrice/card/card_database/card_database_manager.h>
|
||||
#include <libcockatrice/card/card_info_comparator.h>
|
||||
|
||||
OverlappedCardGroupDisplayWidget::OverlappedCardGroupDisplayWidget(QWidget *parent,
|
||||
DeckListModel *_deckListModel,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
#include "card_info_display_widget.h"
|
||||
|
||||
#include "../../../database/card_database_manager.h"
|
||||
#include "../../../game/board/card_item.h"
|
||||
#include "../../../main.h"
|
||||
#include "card_info_picture_widget.h"
|
||||
|
|
@ -9,6 +8,7 @@
|
|||
#include <QApplication>
|
||||
#include <QScreen>
|
||||
#include <QVBoxLayout>
|
||||
#include <libcockatrice/card/card_database/card_database_manager.h>
|
||||
#include <utility>
|
||||
|
||||
CardInfoDisplayWidget::CardInfoDisplayWidget(const CardRef &cardRef, QWidget *parent, Qt::WindowFlags flags)
|
||||
|
|
|
|||
|
|
@ -7,12 +7,11 @@
|
|||
#ifndef CARDINFOWIDGET_H
|
||||
#define CARDINFOWIDGET_H
|
||||
|
||||
#include "../../../card/exact_card.h"
|
||||
#include "card_ref.h"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QFrame>
|
||||
#include <QStringList>
|
||||
#include <libcockatrice/card/card_printing/exact_card.h>
|
||||
#include <libcockatrice/utility/card_ref.h>
|
||||
|
||||
class CardInfoPictureWidget;
|
||||
class CardInfoTextWidget;
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
#include "card_info_frame_widget.h"
|
||||
|
||||
#include "../../../card/card_relation.h"
|
||||
#include "../../../database/card_database_manager.h"
|
||||
#include "../../../game/board/card_item.h"
|
||||
#include "../../../settings/cache_settings.h"
|
||||
#include "card_info_display_widget.h"
|
||||
#include "card_info_picture_widget.h"
|
||||
#include "card_info_text_widget.h"
|
||||
|
||||
#include <QSplitter>
|
||||
#include <QVBoxLayout>
|
||||
#include <libcockatrice/card/card_database/card_database_manager.h>
|
||||
#include <libcockatrice/card/card_relation/card_relation.h>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
#include <utility>
|
||||
|
||||
CardInfoFrameWidget::CardInfoFrameWidget(QWidget *parent)
|
||||
|
|
|
|||
|
|
@ -7,11 +7,10 @@
|
|||
#ifndef CARDFRAME_H
|
||||
#define CARDFRAME_H
|
||||
|
||||
#include "../../../card/exact_card.h"
|
||||
#include "card_ref.h"
|
||||
|
||||
#include <QPushButton>
|
||||
#include <QTabWidget>
|
||||
#include <libcockatrice/card/card_printing/exact_card.h>
|
||||
#include <libcockatrice/utility/card_ref.h>
|
||||
|
||||
class AbstractCardItem;
|
||||
class CardInfoPictureWidget;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include "card_info_picture_art_crop_widget.h"
|
||||
|
||||
#include "../../../picture_loader/picture_loader.h"
|
||||
#include "../../../interface/card_picture_loader/card_picture_loader.h"
|
||||
|
||||
CardInfoPictureArtCropWidget::CardInfoPictureArtCropWidget(QWidget *parent)
|
||||
: CardInfoPictureWidget(parent, false, false)
|
||||
|
|
@ -13,9 +13,9 @@ QPixmap CardInfoPictureArtCropWidget::getProcessedBackground(const QSize &target
|
|||
// Load the full-resolution card image, not a pre-scaled one
|
||||
QPixmap fullResPixmap;
|
||||
if (getCard()) {
|
||||
PictureLoader::getPixmap(fullResPixmap, getCard(), QSize(745, 1040)); // or a high default size
|
||||
CardPictureLoader::getPixmap(fullResPixmap, getCard(), QSize(745, 1040)); // or a high default size
|
||||
} else {
|
||||
PictureLoader::getCardBackPixmap(fullResPixmap, QSize(745, 1040));
|
||||
CardPictureLoader::getCardBackPixmap(fullResPixmap, QSize(745, 1040));
|
||||
}
|
||||
|
||||
// Fail-safe if loading failed
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
#include "card_info_picture_enlarged_widget.h"
|
||||
|
||||
#include "../../../picture_loader/picture_loader.h"
|
||||
#include "../../../settings/cache_settings.h"
|
||||
#include "../../../interface/card_picture_loader/card_picture_loader.h"
|
||||
|
||||
#include <QPainterPath>
|
||||
#include <QStylePainter>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
#include <utility>
|
||||
|
||||
/**
|
||||
|
|
@ -35,9 +35,9 @@ CardInfoPictureEnlargedWidget::CardInfoPictureEnlargedWidget(QWidget *parent) :
|
|||
void CardInfoPictureEnlargedWidget::loadPixmap(const QSize &size)
|
||||
{
|
||||
if (card) {
|
||||
PictureLoader::getPixmap(enlargedPixmap, card, size);
|
||||
CardPictureLoader::getPixmap(enlargedPixmap, card, size);
|
||||
} else {
|
||||
PictureLoader::getCardBackPixmap(enlargedPixmap, size);
|
||||
CardPictureLoader::getCardBackPixmap(enlargedPixmap, size);
|
||||
}
|
||||
pixmapDirty = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,10 +8,9 @@
|
|||
#ifndef CARD_PICTURE_ENLARGED_WIDGET_H
|
||||
#define CARD_PICTURE_ENLARGED_WIDGET_H
|
||||
|
||||
#include "../../../card/exact_card.h"
|
||||
|
||||
#include <QPixmap>
|
||||
#include <QWidget>
|
||||
#include <libcockatrice/card/card_printing/exact_card.h>
|
||||
|
||||
class CardInfoPictureEnlargedWidget final : public QWidget
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
#include "card_info_picture_widget.h"
|
||||
|
||||
#include "../../../card/card_relation.h"
|
||||
#include "../../../database/card_database_manager.h"
|
||||
#include "../../../game/board/card_item.h"
|
||||
#include "../../../picture_loader/picture_loader.h"
|
||||
#include "../../../settings/cache_settings.h"
|
||||
#include "../../../interface/card_picture_loader/card_picture_loader.h"
|
||||
#include "../../../tabs/tab_supervisor.h"
|
||||
#include "../../window_main.h"
|
||||
|
||||
|
|
@ -13,6 +10,9 @@
|
|||
#include <QScreen>
|
||||
#include <QStylePainter>
|
||||
#include <QWidget>
|
||||
#include <libcockatrice/card/card_database/card_database_manager.h>
|
||||
#include <libcockatrice/card/card_relation/card_relation.h>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
#include <utility>
|
||||
|
||||
/**
|
||||
|
|
@ -152,11 +152,11 @@ void CardInfoPictureWidget::updatePixmap()
|
|||
*/
|
||||
void CardInfoPictureWidget::loadPixmap()
|
||||
{
|
||||
PictureLoader::getCardBackLoadingInProgressPixmap(resizedPixmap, size());
|
||||
CardPictureLoader::getCardBackLoadingInProgressPixmap(resizedPixmap, size());
|
||||
if (exactCard) {
|
||||
PictureLoader::getPixmap(resizedPixmap, exactCard, size());
|
||||
CardPictureLoader::getPixmap(resizedPixmap, exactCard, size());
|
||||
} else {
|
||||
PictureLoader::getCardBackLoadingFailedPixmap(resizedPixmap, size());
|
||||
CardPictureLoader::getCardBackLoadingFailedPixmap(resizedPixmap, size());
|
||||
}
|
||||
|
||||
pixmapDirty = false;
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@
|
|||
#ifndef CARD_INFO_PICTURE_H
|
||||
#define CARD_INFO_PICTURE_H
|
||||
|
||||
#include "../../../card/exact_card.h"
|
||||
#include "card_info_picture_enlarged_widget.h"
|
||||
|
||||
#include <QPropertyAnimation>
|
||||
#include <QTimer>
|
||||
#include <QWidget>
|
||||
#include <libcockatrice/card/card_printing/exact_card.h>
|
||||
|
||||
inline Q_LOGGING_CATEGORY(CardInfoPictureWidgetLog, "card_info_picture_widget");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
#include "card_info_text_widget.h"
|
||||
|
||||
#include "../../../card/card_relation.h"
|
||||
#include "../../../card/game_specific_terms.h"
|
||||
#include "../../../game/board/card_item.h"
|
||||
|
||||
#include <QGridLayout>
|
||||
|
|
@ -10,6 +8,8 @@
|
|||
#include <QScrollBar>
|
||||
#include <QSizePolicy>
|
||||
#include <QTextEdit>
|
||||
#include <libcockatrice/card/card_relation/card_relation.h>
|
||||
#include <libcockatrice/card/game_specific_terms.h>
|
||||
|
||||
CardInfoTextWidget::CardInfoTextWidget(QWidget *parent) : QFrame(parent), info(nullptr)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,9 +7,8 @@
|
|||
#ifndef CARDINFOTEXT_H
|
||||
#define CARDINFOTEXT_H
|
||||
|
||||
#include "../../../card/card_info.h"
|
||||
|
||||
#include <QFrame>
|
||||
#include <libcockatrice/card/card_info.h>
|
||||
class QLabel;
|
||||
class QScrollArea;
|
||||
class QTextEdit;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
#include "card_size_widget.h"
|
||||
|
||||
#include "../../../settings/cache_settings.h"
|
||||
#include "../printing_selector/printing_selector.h"
|
||||
#include "../visual_deck_storage/visual_deck_storage_widget.h"
|
||||
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
|
||||
/**
|
||||
* @class CardSizeWidget
|
||||
* @brief A widget for adjusting card sizes using a slider.
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
#include "deck_card_zone_display_widget.h"
|
||||
|
||||
#include "../../../deck/deck_list_model.h"
|
||||
#include "../../../utility/card_info_comparator.h"
|
||||
#include "card_group_display_widgets/flat_card_group_display_widget.h"
|
||||
#include "card_group_display_widgets/overlapped_card_group_display_widget.h"
|
||||
|
||||
#include <QResizeEvent>
|
||||
#include <libcockatrice/card/card_info_comparator.h>
|
||||
|
||||
DeckCardZoneDisplayWidget::DeckCardZoneDisplayWidget(QWidget *parent,
|
||||
DeckListModel *_deckListModel,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
#ifndef DECK_CARD_ZONE_DISPLAY_WIDGET_H
|
||||
#define DECK_CARD_ZONE_DISPLAY_WIDGET_H
|
||||
|
||||
#include "../../../card/card_info.h"
|
||||
#include "../../../deck/deck_list_model.h"
|
||||
#include "../general/display/banner_widget.h"
|
||||
#include "../general/layout_containers/overlap_widget.h"
|
||||
|
|
@ -18,6 +17,7 @@
|
|||
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
#include <libcockatrice/card/card_info.h>
|
||||
|
||||
class DeckCardZoneDisplayWidget : public QWidget
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
#include "deck_preview_card_picture_widget.h"
|
||||
|
||||
#include "../../../settings/cache_settings.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QFileInfo>
|
||||
#include <QFontMetrics>
|
||||
|
|
@ -9,6 +7,7 @@
|
|||
#include <QPainterPath>
|
||||
#include <QStylePainter>
|
||||
#include <QTextOption>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
|
||||
/**
|
||||
* @brief Constructs a CardPictureWithTextOverlay widget.
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
#include <QScrollArea>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
#include <deck_list.h>
|
||||
#include <libcockatrice/deck_list/deck_list.h>
|
||||
|
||||
class DeckAnalyticsWidget : public QWidget
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
#include "mana_base_widget.h"
|
||||
|
||||
#include "../../../database/card_database.h"
|
||||
#include "../../../database/card_database_manager.h"
|
||||
#include "../../../deck/deck_loader.h"
|
||||
#include "../general/display/banner_widget.h"
|
||||
#include "../general/display/bar_widget.h"
|
||||
|
||||
#include <QHash>
|
||||
#include <QRegularExpression>
|
||||
#include <deck_list.h>
|
||||
#include <libcockatrice/card/card_database/card_database.h>
|
||||
#include <libcockatrice/card/card_database/card_database_manager.h>
|
||||
#include <libcockatrice/deck_list/deck_list.h>
|
||||
|
||||
ManaBaseWidget::ManaBaseWidget(QWidget *parent, DeckListModel *_deckListModel)
|
||||
: QWidget(parent), deckListModel(_deckListModel)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
#include <QHBoxLayout>
|
||||
#include <QWidget>
|
||||
#include <deck_list.h>
|
||||
#include <libcockatrice/deck_list/deck_list.h>
|
||||
#include <utility>
|
||||
|
||||
class ManaBaseWidget : public QWidget
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
#include "mana_curve_widget.h"
|
||||
|
||||
#include "../../../database/card_database.h"
|
||||
#include "../../../database/card_database_manager.h"
|
||||
#include "../../../deck/deck_loader.h"
|
||||
#include "../../../main.h"
|
||||
#include "../general/display/banner_widget.h"
|
||||
#include "../general/display/bar_widget.h"
|
||||
|
||||
#include <deck_list.h>
|
||||
#include <libcockatrice/card/card_database/card_database.h>
|
||||
#include <libcockatrice/card/card_database/card_database_manager.h>
|
||||
#include <libcockatrice/deck_list/deck_list.h>
|
||||
#include <unordered_map>
|
||||
|
||||
ManaCurveWidget::ManaCurveWidget(QWidget *parent, DeckListModel *_deckListModel)
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
#include "mana_devotion_widget.h"
|
||||
|
||||
#include "../../../database/card_database.h"
|
||||
#include "../../../database/card_database_manager.h"
|
||||
#include "../../../deck/deck_loader.h"
|
||||
#include "../../../main.h"
|
||||
#include "../general/display/banner_widget.h"
|
||||
#include "../general/display/bar_widget.h"
|
||||
|
||||
#include <deck_list.h>
|
||||
#include <iostream>
|
||||
#include <libcockatrice/card/card_database/card_database.h>
|
||||
#include <libcockatrice/card/card_database/card_database_manager.h>
|
||||
#include <libcockatrice/deck_list/deck_list.h>
|
||||
#include <regex>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
#include <QHBoxLayout>
|
||||
#include <QWidget>
|
||||
#include <deck_list.h>
|
||||
#include <libcockatrice/deck_list/deck_list.h>
|
||||
#include <utility>
|
||||
|
||||
class ManaDevotionWidget : public QWidget
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
#include "deck_editor_database_display_widget.h"
|
||||
|
||||
#include "../../../card/card_relation.h"
|
||||
#include "../../../database/card_database_manager.h"
|
||||
#include "../../../filters/syntax_help.h"
|
||||
#include "../../../settings/cache_settings.h"
|
||||
#include "../../../tabs/abstract_tab_deck_editor.h"
|
||||
#include "../../../tabs/tab_supervisor.h"
|
||||
#include "../../pixel_map_generator.h"
|
||||
|
|
@ -15,6 +12,9 @@
|
|||
#include <QTextBrowser>
|
||||
#include <QToolButton>
|
||||
#include <QTreeView>
|
||||
#include <libcockatrice/card/card_database/card_database_manager.h>
|
||||
#include <libcockatrice/card/card_relation/card_relation.h>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
|
||||
static bool canBeCommander(const CardInfo &cardInfo)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,14 +8,14 @@
|
|||
#ifndef DECK_EDITOR_DATABASE_DISPLAY_WIDGET_H
|
||||
#define DECK_EDITOR_DATABASE_DISPLAY_WIDGET_H
|
||||
|
||||
#include "../../../database/model/card_database_display_model.h"
|
||||
#include "../../../database/model/card_database_model.h"
|
||||
#include "../../../deck/custom_line_edit.h"
|
||||
#include "../../../tabs/abstract_tab_deck_editor.h"
|
||||
#include "../../../utility/key_signals.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QWidget>
|
||||
#include <libcockatrice/card/card_database/model/card_database_display_model.h>
|
||||
#include <libcockatrice/card/card_database/model/card_database_model.h>
|
||||
#include <libcockatrice/utility/key_signals.h>
|
||||
|
||||
class AbstractTabDeckEditor;
|
||||
class DeckEditorDatabaseDisplayWidget : public QWidget
|
||||
|
|
|
|||
|
|
@ -1,15 +1,14 @@
|
|||
#include "deck_editor_deck_dock_widget.h"
|
||||
|
||||
#include "../../../database/card_database_manager.h"
|
||||
#include "../../../settings/cache_settings.h"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QDockWidget>
|
||||
#include <QHeaderView>
|
||||
#include <QLabel>
|
||||
#include <QSplitter>
|
||||
#include <QTextEdit>
|
||||
#include <trice_limits.h>
|
||||
#include <libcockatrice/card/card_database/card_database_manager.h>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
#include <libcockatrice/utility/trice_limits.h>
|
||||
|
||||
DeckEditorDeckDockWidget::DeckEditorDeckDockWidget(AbstractTabDeckEditor *parent)
|
||||
: QDockWidget(parent), deckEditor(parent)
|
||||
|
|
|
|||
|
|
@ -8,10 +8,8 @@
|
|||
#ifndef DECK_EDITOR_DECK_DOCK_WIDGET_H
|
||||
#define DECK_EDITOR_DECK_DOCK_WIDGET_H
|
||||
|
||||
#include "../../../card/card_info.h"
|
||||
#include "../../../deck/custom_line_edit.h"
|
||||
#include "../../../tabs/abstract_tab_deck_editor.h"
|
||||
#include "../../../utility/key_signals.h"
|
||||
#include "../visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.h"
|
||||
|
||||
#include <QComboBox>
|
||||
|
|
@ -19,6 +17,8 @@
|
|||
#include <QLabel>
|
||||
#include <QTextEdit>
|
||||
#include <QTreeView>
|
||||
#include <libcockatrice/card/card_info.h>
|
||||
#include <libcockatrice/utility/key_signals.h>
|
||||
|
||||
class DeckListModel;
|
||||
class AbstractTabDeckEditor;
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
#include "deck_editor_filter_dock_widget.h"
|
||||
|
||||
#include "../../../database/model/card_database_model.h"
|
||||
#include "../../../filters/filter_builder.h"
|
||||
#include "../../../filters/filter_tree_model.h"
|
||||
#include "../../../settings/cache_settings.h"
|
||||
|
||||
#include <QGridLayout>
|
||||
#include <QMenu>
|
||||
#include <QToolButton>
|
||||
#include <libcockatrice/card/card_database/model/card_database_model.h>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
|
||||
DeckEditorFilterDockWidget::DeckEditorFilterDockWidget(AbstractTabDeckEditor *parent)
|
||||
: QDockWidget(parent), deckEditor(parent)
|
||||
|
|
|
|||
|
|
@ -9,10 +9,10 @@
|
|||
#define DECK_EDITOR_FILTER_DOCK_WIDGET_H
|
||||
|
||||
#include "../../../tabs/abstract_tab_deck_editor.h"
|
||||
#include "../../../utility/key_signals.h"
|
||||
|
||||
#include <QDockWidget>
|
||||
#include <QTreeView>
|
||||
#include <libcockatrice/utility/key_signals.h>
|
||||
|
||||
class FilterTreeModel;
|
||||
class AbstractTabDeckEditor;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
#include "home_widget.h"
|
||||
|
||||
#include "../../../database/card_database_manager.h"
|
||||
#include "../../../server/remote/remote_client.h"
|
||||
#include "../../../settings/cache_settings.h"
|
||||
#include "../../../tabs/tab_supervisor.h"
|
||||
#include "../../window_main.h"
|
||||
#include "background_sources.h"
|
||||
|
|
@ -12,6 +9,9 @@
|
|||
#include <QPainterPath>
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
#include <libcockatrice/card/card_database/card_database_manager.h>
|
||||
#include <libcockatrice/network/client/remote/remote_client.h>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
|
||||
HomeWidget::HomeWidget(QWidget *parent, TabSupervisor *_tabSupervisor)
|
||||
: QWidget(parent), tabSupervisor(_tabSupervisor), background("theme:backgrounds/home"), overlay("theme:cockatrice")
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
#ifndef HOME_WIDGET_H
|
||||
#define HOME_WIDGET_H
|
||||
#include "../../../server/abstract_client.h"
|
||||
#include "../../../tabs/tab_supervisor.h"
|
||||
#include "../cards/card_info_picture_art_crop_widget.h"
|
||||
#include "home_styled_button.h"
|
||||
|
|
@ -15,6 +14,7 @@
|
|||
#include <QGridLayout>
|
||||
#include <QGroupBox>
|
||||
#include <QWidget>
|
||||
#include <libcockatrice/network/client/abstract/abstract_client.h>
|
||||
|
||||
class HomeWidget : public QWidget
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
#ifndef CARD_AMOUNT_WIDGET_H
|
||||
#define CARD_AMOUNT_WIDGET_H
|
||||
|
||||
#include "../../../card/card_info.h"
|
||||
#include "../../../deck/deck_list_model.h"
|
||||
#include "../../../deck/deck_loader.h"
|
||||
#include "../../../tabs/abstract_tab_deck_editor.h"
|
||||
|
|
@ -19,6 +18,7 @@
|
|||
#include <QPushButton>
|
||||
#include <QTreeView>
|
||||
#include <QWidget>
|
||||
#include <libcockatrice/card/card_info.h>
|
||||
|
||||
class CardAmountWidget : public QWidget
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
#include "printing_selector.h"
|
||||
|
||||
#include "../../../dialogs/dlg_select_set_for_cards.h"
|
||||
#include "../../../picture_loader/picture_loader.h"
|
||||
#include "../../../settings/cache_settings.h"
|
||||
#include "../../../interface/card_picture_loader/card_picture_loader.h"
|
||||
#include "printing_selector_card_display_widget.h"
|
||||
#include "printing_selector_card_search_widget.h"
|
||||
#include "printing_selector_card_selection_widget.h"
|
||||
|
|
@ -10,6 +9,7 @@
|
|||
|
||||
#include <QFrame>
|
||||
#include <QScrollBar>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
#include <qboxlayout.h>
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
#ifndef PRINTING_SELECTOR_H
|
||||
#define PRINTING_SELECTOR_H
|
||||
|
||||
#include "../../../card/card_info.h"
|
||||
#include "../../../deck/deck_list_model.h"
|
||||
#include "../cards/card_size_widget.h"
|
||||
#include "../general/layout_containers/flow_widget.h"
|
||||
|
|
@ -19,6 +18,7 @@
|
|||
#include <QTreeView>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
#include <libcockatrice/card/card_info.h>
|
||||
|
||||
#define BATCH_SIZE 10
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
#ifndef PRINTING_SELECTOR_CARD_DISPLAY_WIDGET_H
|
||||
#define PRINTING_SELECTOR_CARD_DISPLAY_WIDGET_H
|
||||
|
||||
#include "../../../card/card_info.h"
|
||||
#include "../../../deck/deck_list_model.h"
|
||||
#include "../../../tabs/abstract_tab_deck_editor.h"
|
||||
#include "printing_selector_card_overlay_widget.h"
|
||||
|
|
@ -15,6 +14,7 @@
|
|||
|
||||
#include <QPainter>
|
||||
#include <QWidget>
|
||||
#include <libcockatrice/card/card_info.h>
|
||||
|
||||
class PrintingSelectorCardDisplayWidget : public QWidget
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
#include "printing_selector_card_overlay_widget.h"
|
||||
|
||||
#include "../../../card/card_relation.h"
|
||||
#include "../../../database/card_database_manager.h"
|
||||
#include "../../../settings/cache_settings.h"
|
||||
#include "printing_selector_card_display_widget.h"
|
||||
|
||||
#include <QMenu>
|
||||
#include <QMouseEvent>
|
||||
#include <QVBoxLayout>
|
||||
#include <libcockatrice/card/card_database/card_database_manager.h>
|
||||
#include <libcockatrice/card/card_relation/card_relation.h>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
#include <utility>
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
#ifndef PRINTING_SELECTOR_CARD_OVERLAY_WIDGET_H
|
||||
#define PRINTING_SELECTOR_CARD_OVERLAY_WIDGET_H
|
||||
|
||||
#include "../../../card/card_info.h"
|
||||
#include "../../../deck/deck_list_model.h"
|
||||
#include "../../../tabs/abstract_tab_deck_editor.h"
|
||||
#include "../cards/card_info_picture_widget.h"
|
||||
|
|
@ -15,6 +14,8 @@
|
|||
#include "card_amount_widget.h"
|
||||
#include "set_name_and_collectors_number_display_widget.h"
|
||||
|
||||
#include <libcockatrice/card/card_info.h>
|
||||
|
||||
class PrintingSelectorCardOverlayWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#include "printing_selector_card_sorting_widget.h"
|
||||
|
||||
#include "../../../settings/cache_settings.h"
|
||||
#include "../../../utility/card_set_comparator.h"
|
||||
#include <libcockatrice/card/card_set/card_set_comparator.h>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
|
||||
const QString PrintingSelectorCardSortingWidget::SORT_OPTIONS_ALPHABETICAL = tr("Alphabetical");
|
||||
const QString PrintingSelectorCardSortingWidget::SORT_OPTIONS_PREFERENCE = tr("Preference");
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
#include "visual_database_display_filter_save_load_widget.h"
|
||||
|
||||
#include "../../../filters/filter_tree.h"
|
||||
#include "../../../settings/cache_settings.h"
|
||||
#include "visual_database_filter_display_widget.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <QMessageBox>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
|
||||
VisualDatabaseDisplayFilterSaveLoadWidget::VisualDatabaseDisplayFilterSaveLoadWidget(QWidget *parent,
|
||||
FilterTreeModel *_filterModel)
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
#include "visual_database_display_main_type_filter_widget.h"
|
||||
|
||||
#include "../../../database/card_database_manager.h"
|
||||
#include "../../../filters/filter_tree.h"
|
||||
#include "../../../filters/filter_tree_model.h"
|
||||
|
||||
#include <QPushButton>
|
||||
#include <QSpinBox>
|
||||
#include <QTimer>
|
||||
#include <libcockatrice/card/card_database/card_database_manager.h>
|
||||
|
||||
VisualDatabaseDisplayMainTypeFilterWidget::VisualDatabaseDisplayMainTypeFilterWidget(QWidget *parent,
|
||||
FilterTreeModel *_filterModel)
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
#include "visual_database_display_set_filter_widget.h"
|
||||
|
||||
#include "../../../database/card_database_manager.h"
|
||||
#include "../../../filters/filter_tree.h"
|
||||
#include "../../../filters/filter_tree_model.h"
|
||||
#include "../../../settings/cache_settings.h"
|
||||
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include <QTimer>
|
||||
#include <algorithm>
|
||||
#include <libcockatrice/card/card_database/card_database_manager.h>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
|
||||
VisualDatabaseDisplayRecentSetFilterSettingsWidget::VisualDatabaseDisplayRecentSetFilterSettingsWidget(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
#include "visual_database_display_sub_type_filter_widget.h"
|
||||
|
||||
#include "../../../database/card_database_manager.h"
|
||||
#include "../../../filters/filter_tree.h"
|
||||
#include "../../../filters/filter_tree_model.h"
|
||||
|
||||
|
|
@ -8,6 +7,7 @@
|
|||
#include <QPushButton>
|
||||
#include <QSpinBox>
|
||||
#include <QTimer>
|
||||
#include <libcockatrice/card/card_database/card_database_manager.h>
|
||||
|
||||
VisualDatabaseDisplaySubTypeFilterWidget::VisualDatabaseDisplaySubTypeFilterWidget(QWidget *parent,
|
||||
FilterTreeModel *_filterModel)
|
||||
|
|
|
|||
|
|
@ -1,12 +1,8 @@
|
|||
#include "visual_database_display_widget.h"
|
||||
|
||||
#include "../../../database/card_database.h"
|
||||
#include "../../../database/card_database_manager.h"
|
||||
#include "../../../deck/custom_line_edit.h"
|
||||
#include "../../../filters/filter_tree_model.h"
|
||||
#include "../../../filters/syntax_help.h"
|
||||
#include "../../../settings/cache_settings.h"
|
||||
#include "../../../utility/card_info_comparator.h"
|
||||
#include "../../pixel_map_generator.h"
|
||||
#include "../cards/card_info_picture_with_text_overlay_widget.h"
|
||||
#include "../quick_settings/settings_button_widget.h"
|
||||
|
|
@ -19,6 +15,10 @@
|
|||
|
||||
#include <QHeaderView>
|
||||
#include <QScrollBar>
|
||||
#include <libcockatrice/card/card_database/card_database.h>
|
||||
#include <libcockatrice/card/card_database/card_database_manager.h>
|
||||
#include <libcockatrice/card/card_info_comparator.h>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
#include <qpropertyanimation.h>
|
||||
#include <utility>
|
||||
|
||||
|
|
|
|||
|
|
@ -7,13 +7,10 @@
|
|||
#ifndef VISUAL_DATABASE_DISPLAY_WIDGET_H
|
||||
#define VISUAL_DATABASE_DISPLAY_WIDGET_H
|
||||
|
||||
#include "../../../database/card_database.h"
|
||||
#include "../../../database/model/card_database_model.h"
|
||||
#include "../../../deck/custom_line_edit.h"
|
||||
#include "../../../deck/deck_list_model.h"
|
||||
#include "../../../filters/filter_tree_model.h"
|
||||
#include "../../../tabs/abstract_tab_deck_editor.h"
|
||||
#include "../../../utility/key_signals.h"
|
||||
#include "../../layouts/flow_layout.h"
|
||||
#include "../cards/card_info_picture_with_text_overlay_widget.h"
|
||||
#include "../cards/card_size_widget.h"
|
||||
|
|
@ -31,6 +28,9 @@
|
|||
#include <QVBoxLayout>
|
||||
#include <QWheelEvent>
|
||||
#include <QWidget>
|
||||
#include <libcockatrice/card/card_database/card_database.h>
|
||||
#include <libcockatrice/card/card_database/model/card_database_model.h>
|
||||
#include <libcockatrice/utility/key_signals.h>
|
||||
#include <qscrollarea.h>
|
||||
|
||||
inline Q_LOGGING_CATEGORY(VisualDatabaseDisplayLog, "visual_database_display");
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
#include "visual_database_filter_display_widget.h"
|
||||
|
||||
#include "../../../settings/cache_settings.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFontMetrics>
|
||||
#include <QHBoxLayout>
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
|
||||
FilterDisplayWidget::FilterDisplayWidget(QWidget *parent, const QString &filename, FilterTreeModel *_filterModel)
|
||||
: QWidget(parent), filterFilename(filename), filterModel(_filterModel)
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
#include "visual_deck_editor_sample_hand_widget.h"
|
||||
|
||||
#include "../../../database/card_database_manager.h"
|
||||
#include "../../../deck/deck_loader.h"
|
||||
#include "../../../settings/cache_settings.h"
|
||||
#include "../cards/card_info_picture_widget.h"
|
||||
|
||||
#include <libcockatrice/card/card_database/card_database_manager.h>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
#include <random>
|
||||
|
||||
VisualDeckEditorSampleHandWidget::VisualDeckEditorSampleHandWidget(QWidget *parent, DeckListModel *_deckListModel)
|
||||
|
|
|
|||
|
|
@ -1,14 +1,8 @@
|
|||
#include "visual_deck_editor_widget.h"
|
||||
|
||||
#include "../../../database/card_database.h"
|
||||
#include "../../../database/card_database_manager.h"
|
||||
#include "../../../database/model/card/card_completer_proxy_model.h"
|
||||
#include "../../../database/model/card/card_search_model.h"
|
||||
#include "../../../database/model/card_database_model.h"
|
||||
#include "../../../deck/deck_list_model.h"
|
||||
#include "../../../deck/deck_loader.h"
|
||||
#include "../../../main.h"
|
||||
#include "../../../utility/card_info_comparator.h"
|
||||
#include "../../layouts/overlap_layout.h"
|
||||
#include "../cards/card_info_picture_with_text_overlay_widget.h"
|
||||
#include "../cards/deck_card_zone_display_widget.h"
|
||||
|
|
@ -21,6 +15,12 @@
|
|||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include <QResizeEvent>
|
||||
#include <libcockatrice/card/card_database/card_database.h>
|
||||
#include <libcockatrice/card/card_database/card_database_manager.h>
|
||||
#include <libcockatrice/card/card_database/model/card/card_completer_proxy_model.h>
|
||||
#include <libcockatrice/card/card_database/model/card/card_search_model.h>
|
||||
#include <libcockatrice/card/card_database/model/card_database_model.h>
|
||||
#include <libcockatrice/card/card_info_comparator.h>
|
||||
#include <qscrollarea.h>
|
||||
|
||||
VisualDeckEditorWidget::VisualDeckEditorWidget(QWidget *parent, DeckListModel *_deckListModel)
|
||||
|
|
|
|||
|
|
@ -7,10 +7,6 @@
|
|||
#ifndef VISUAL_DECK_EDITOR_H
|
||||
#define VISUAL_DECK_EDITOR_H
|
||||
|
||||
#include "../../../database/card_database.h"
|
||||
#include "../../../database/model/card/card_completer_proxy_model.h"
|
||||
#include "../../../database/model/card_database_display_model.h"
|
||||
#include "../../../database/model/card_database_model.h"
|
||||
#include "../../../deck/deck_list_model.h"
|
||||
#include "../cards/card_info_picture_with_text_overlay_widget.h"
|
||||
#include "../cards/card_size_widget.h"
|
||||
|
|
@ -22,6 +18,10 @@
|
|||
#include <QListWidget>
|
||||
#include <QPushButton>
|
||||
#include <QWidget>
|
||||
#include <libcockatrice/card/card_database/card_database.h>
|
||||
#include <libcockatrice/card/card_database/model/card/card_completer_proxy_model.h>
|
||||
#include <libcockatrice/card/card_database/model/card_database_display_model.h>
|
||||
#include <libcockatrice/card/card_database/model/card_database_model.h>
|
||||
#include <qscrollarea.h>
|
||||
|
||||
class DeckCardZoneDisplayWidget;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
#include "deck_preview_deck_tags_display_widget.h"
|
||||
|
||||
#include "../../../../dialogs/dlg_convert_deck_to_cod_format.h"
|
||||
#include "../../../../settings/cache_settings.h"
|
||||
#include "../../../../tabs/tab_deck_editor.h"
|
||||
#include "../../general/layout_containers/flow_widget.h"
|
||||
#include "deck_preview_tag_addition_widget.h"
|
||||
|
|
@ -13,6 +12,7 @@
|
|||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QMessageBox>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
|
||||
DeckPreviewDeckTagsDisplayWidget::DeckPreviewDeckTagsDisplayWidget(QWidget *_parent, DeckList *_deckList)
|
||||
: QWidget(_parent), deckList(nullptr)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
#include "deck_preview_tag_addition_widget.h"
|
||||
|
||||
#include "../../../../settings/cache_settings.h"
|
||||
#include "../../../../tabs/abstract_tab_deck_editor.h"
|
||||
#include "deck_preview_tag_dialog.h"
|
||||
|
||||
|
|
@ -8,6 +7,7 @@
|
|||
#include <QHBoxLayout>
|
||||
#include <QMouseEvent>
|
||||
#include <QPainter>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
#include <utility>
|
||||
|
||||
DeckPreviewTagAdditionWidget::DeckPreviewTagAdditionWidget(QWidget *_parent, QString _tagName)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
#include "deck_preview_tag_dialog.h"
|
||||
|
||||
#include "../../../../dialogs/dlg_default_tags_editor.h"
|
||||
#include "../../../../settings/cache_settings.h"
|
||||
#include "deck_preview_tag_item_widget.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
|
|
@ -12,6 +11,7 @@
|
|||
#include <QPushButton>
|
||||
#include <QTimer>
|
||||
#include <QVBoxLayout>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
|
||||
DeckPreviewTagDialog::DeckPreviewTagDialog(const QStringList &knownTags,
|
||||
const QStringList &_activeTags,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
#include "deck_preview_widget.h"
|
||||
|
||||
#include "../../../../database/card_database_manager.h"
|
||||
#include "../../../../settings/cache_settings.h"
|
||||
#include "../../cards/additional_info/color_identity_widget.h"
|
||||
#include "../../cards/deck_preview_card_picture_widget.h"
|
||||
#include "deck_preview_deck_tags_display_widget.h"
|
||||
|
|
@ -15,6 +13,8 @@
|
|||
#include <QSet>
|
||||
#include <QStandardItemModel>
|
||||
#include <QVBoxLayout>
|
||||
#include <libcockatrice/card/card_database/card_database_manager.h>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
|
||||
DeckPreviewWidget::DeckPreviewWidget(QWidget *_parent,
|
||||
VisualDeckStorageWidget *_visualDeckStorageWidget,
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
#include "visual_deck_storage_folder_display_widget.h"
|
||||
|
||||
#include "../../../settings/cache_settings.h"
|
||||
#include "deck_preview/deck_preview_widget.h"
|
||||
|
||||
#include <QDirIterator>
|
||||
#include <QMouseEvent>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
|
||||
VisualDeckStorageFolderDisplayWidget::VisualDeckStorageFolderDisplayWidget(
|
||||
QWidget *parent,
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
#include "visual_deck_storage_quick_settings_widget.h"
|
||||
|
||||
#include "../../../settings/cache_settings.h"
|
||||
#include "visual_deck_storage_widget.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QComboBox>
|
||||
#include <QSpinBox>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
|
||||
VisualDeckStorageQuickSettingsWidget::VisualDeckStorageQuickSettingsWidget(QWidget *parent)
|
||||
: SettingsButtonWidget(parent)
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
#include "../../../filters/deck_filter_string.h"
|
||||
#include "../../../filters/syntax_help.h"
|
||||
#include "../../../settings/cache_settings.h"
|
||||
#include "../../pixel_map_generator.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
|
||||
/**
|
||||
* @brief Constructs a PrintingSelectorCardSearchWidget for searching cards by set name or set code.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include "visual_deck_storage_sort_widget.h"
|
||||
|
||||
#include "../../../settings/cache_settings.h"
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
|
||||
/**
|
||||
* @brief Constructs a PrintingSelectorCardSortWidget for searching cards by set name or set code.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
#include "visual_deck_storage_widget.h"
|
||||
|
||||
#include "../../../database/card_database_manager.h"
|
||||
#include "../../../settings/cache_settings.h"
|
||||
#include "../quick_settings/settings_button_widget.h"
|
||||
#include "deck_preview/deck_preview_widget.h"
|
||||
#include "visual_deck_storage_folder_display_widget.h"
|
||||
|
|
@ -14,6 +12,8 @@
|
|||
#include <QMouseEvent>
|
||||
#include <QSpinBox>
|
||||
#include <QVBoxLayout>
|
||||
#include <libcockatrice/card/card_database/card_database_manager.h>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
|
||||
VisualDeckStorageWidget::VisualDeckStorageWidget(QWidget *parent) : QWidget(parent), folderWidget(nullptr)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -22,8 +22,6 @@
|
|||
#include "../client/get_text_with_max.h"
|
||||
#include "../client/network/client_update_checker.h"
|
||||
#include "../client/network/release_channel.h"
|
||||
#include "../database/card_database.h"
|
||||
#include "../database/card_database_manager.h"
|
||||
#include "../dialogs/dlg_connect.h"
|
||||
#include "../dialogs/dlg_edit_tokens.h"
|
||||
#include "../dialogs/dlg_forgot_password_challenge.h"
|
||||
|
|
@ -37,18 +35,8 @@
|
|||
#include "../dialogs/dlg_update.h"
|
||||
#include "../dialogs/dlg_view_log.h"
|
||||
#include "../main.h"
|
||||
#include "../server/local_client.h"
|
||||
#include "../server/local_server.h"
|
||||
#include "../server/local_server_interface.h"
|
||||
#include "../server/remote/remote_client.h"
|
||||
#include "../settings/cache_settings.h"
|
||||
#include "../tabs/tab_game.h"
|
||||
#include "../tabs/tab_supervisor.h"
|
||||
#include "../utility/logger.h"
|
||||
#include "pb/event_connection_closed.pb.h"
|
||||
#include "pb/event_server_shutdown.pb.h"
|
||||
#include "pb/game_replay.pb.h"
|
||||
#include "pb/room_commands.pb.h"
|
||||
#include "version_string.h"
|
||||
|
||||
#include <QAction>
|
||||
|
|
@ -72,6 +60,18 @@
|
|||
#include <QWindow>
|
||||
#include <QtConcurrent>
|
||||
#include <QtNetwork>
|
||||
#include <libcockatrice/card/card_database/card_database.h>
|
||||
#include <libcockatrice/card/card_database/card_database_manager.h>
|
||||
#include <libcockatrice/network/client/local/local_client.h>
|
||||
#include <libcockatrice/network/client/remote/remote_client.h>
|
||||
#include <libcockatrice/network/server/local/local_server.h>
|
||||
#include <libcockatrice/network/server/local/local_server_interface.h>
|
||||
#include <libcockatrice/protocol/pb/event_connection_closed.pb.h>
|
||||
#include <libcockatrice/protocol/pb/event_server_shutdown.pb.h>
|
||||
#include <libcockatrice/protocol/pb/game_replay.pb.h>
|
||||
#include <libcockatrice/protocol/pb/room_commands.pb.h>
|
||||
#include <libcockatrice/settings/cache_settings.h>
|
||||
#include <libcockatrice/utility/logger.h>
|
||||
|
||||
#define GITHUB_PAGES_URL "https://cockatrice.github.io"
|
||||
#define GITHUB_CONTRIBUTORS_URL "https://github.com/Cockatrice/Cockatrice/graphs/contributors?type=c"
|
||||
|
|
|
|||
|
|
@ -25,9 +25,6 @@
|
|||
#ifndef WINDOW_H
|
||||
#define WINDOW_H
|
||||
|
||||
#include "../server/abstract_client.h"
|
||||
#include "pb/response.pb.h"
|
||||
|
||||
#include <QList>
|
||||
#include <QLoggingCategory>
|
||||
#include <QMainWindow>
|
||||
|
|
@ -35,6 +32,8 @@
|
|||
#include <QProcess>
|
||||
#include <QSystemTrayIcon>
|
||||
#include <QtNetwork>
|
||||
#include <libcockatrice/network/client/abstract/abstract_client.h>
|
||||
#include <libcockatrice/protocol/pb/response.pb.h>
|
||||
|
||||
inline Q_LOGGING_CATEGORY(WindowMainLog, "window_main");
|
||||
inline Q_LOGGING_CATEGORY(WindowMainStartupLog, "window_main.startup");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue