mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-09-28 00:42:19 -07:00
Compare commits
4 commits
5a6db206ce
...
e3820c3f34
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e3820c3f34 | ||
|
|
1c6ee62393 | ||
|
|
fd82b140a8 | ||
|
|
5d025ca0bd |
17 changed files with 96 additions and 42 deletions
|
|
@ -94,7 +94,7 @@ QStringMap &SoundEngine::getAvailableThemes()
|
||||||
QDir dir;
|
QDir dir;
|
||||||
availableThemes.clear();
|
availableThemes.clear();
|
||||||
|
|
||||||
// load themes from user profile dir
|
// Load themes from user profile dir
|
||||||
|
|
||||||
dir.setPath(SettingsCache::instance().getDataPath() + "/sounds");
|
dir.setPath(SettingsCache::instance().getDataPath() + "/sounds");
|
||||||
|
|
||||||
|
|
@ -104,7 +104,7 @@ QStringMap &SoundEngine::getAvailableThemes()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// load themes from cockatrice system dir
|
// Load themes from Cockatrice system dir
|
||||||
dir.setPath(qApp->applicationDirPath() +
|
dir.setPath(qApp->applicationDirPath() +
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
"/../Resources/sounds"
|
"/../Resources/sounds"
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@
|
||||||
static constexpr int MAX_REQUESTS_PER_SEC = 10;
|
static constexpr int MAX_REQUESTS_PER_SEC = 10;
|
||||||
static constexpr int MIN_HOST_QUOTA = 1; ///< Floor for the per-host request allowance
|
static constexpr int MIN_HOST_QUOTA = 1; ///< Floor for the per-host request allowance
|
||||||
static constexpr qint64 QUOTA_RECOVER_MS = 60000; ///< Idle time before a reduced quota starts recovering
|
static constexpr qint64 QUOTA_RECOVER_MS = 60000; ///< Idle time before a reduced quota starts recovering
|
||||||
|
static constexpr int DISPATCH_INTERVAL_MS = 100; ///< Pacing between individual network requests
|
||||||
|
static constexpr qint64 QUOTA_RESET_INTERVAL_MS = 1000; ///< Interval at which the request quota resets
|
||||||
|
|
||||||
CardPictureLoaderWorker::CardPictureLoaderWorker()
|
CardPictureLoaderWorker::CardPictureLoaderWorker()
|
||||||
: QObject(nullptr), picDownload(SettingsCache::instance().downloads().getPicDownload()),
|
: QObject(nullptr), picDownload(SettingsCache::instance().downloads().getPicDownload()),
|
||||||
|
|
@ -60,11 +62,18 @@ CardPictureLoaderWorker::CardPictureLoaderWorker()
|
||||||
pictureLoaderThread->start(QThread::LowPriority);
|
pictureLoaderThread->start(QThread::LowPriority);
|
||||||
moveToThread(pictureLoaderThread);
|
moveToThread(pictureLoaderThread);
|
||||||
|
|
||||||
|
// QTimer value members are not QObject children, so moveToThread on the worker doesn't move
|
||||||
|
// them. They must live in the worker's thread to be started from the slot code that runs there.
|
||||||
|
requestTimer.moveToThread(pictureLoaderThread);
|
||||||
|
dispatchTimer.moveToThread(pictureLoaderThread);
|
||||||
|
|
||||||
connect(this, &CardPictureLoaderWorker::imageLoadEnqueued, this, &CardPictureLoaderWorker::handleImageLoadEnqueued);
|
connect(this, &CardPictureLoaderWorker::imageLoadEnqueued, this, &CardPictureLoaderWorker::handleImageLoadEnqueued);
|
||||||
|
|
||||||
connect(&requestTimer, &QTimer::timeout, this, &CardPictureLoaderWorker::resetRequestQuota);
|
connect(&requestTimer, &QTimer::timeout, this, &CardPictureLoaderWorker::resetRequestQuota);
|
||||||
requestTimer.setInterval(1000);
|
requestTimer.setInterval(static_cast<int>(QUOTA_RESET_INTERVAL_MS));
|
||||||
requestTimer.start();
|
|
||||||
|
connect(&dispatchTimer, &QTimer::timeout, this, &CardPictureLoaderWorker::dispatchQueuedRequest);
|
||||||
|
dispatchTimer.setInterval(DISPATCH_INTERVAL_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
CardPictureLoaderWorker::~CardPictureLoaderWorker()
|
CardPictureLoaderWorker::~CardPictureLoaderWorker()
|
||||||
|
|
@ -84,8 +93,8 @@ void CardPictureLoaderWorker::queueRequest(const QUrl &url, CardPictureLoaderWor
|
||||||
SettingsCache::instance().cacheStorage().getCardPictureLoaderCacheMethod()) ==
|
SettingsCache::instance().cacheStorage().getCardPictureLoaderCacheMethod()) ==
|
||||||
CardPictureLoaderCacheMethod::CacheMethod::NETWORK_CACHE &&
|
CardPictureLoaderCacheMethod::CacheMethod::NETWORK_CACHE &&
|
||||||
cache->metaData(url).isValid()) {
|
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
|
// A request that will be served from the disk cache never touches the network and therefore
|
||||||
// rate-limit
|
// doesn't use up any of the rate limit, so it gets to skip the queue.
|
||||||
makeRequest(url, worker);
|
makeRequest(url, worker);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -107,10 +116,13 @@ QNetworkReply *CardPictureLoaderWorker::makeRequest(const QUrl &url, CardPicture
|
||||||
req.setHeader(QNetworkRequest::UserAgentHeader, QString("Cockatrice %1").arg(VERSION_STRING));
|
req.setHeader(QNetworkRequest::UserAgentHeader, QString("Cockatrice %1").arg(VERSION_STRING));
|
||||||
req.setRawHeader("Accept", "image/avif,image/webp,image/apng,image/,/*;q=0.8");
|
req.setRawHeader("Accept", "image/avif,image/webp,image/apng,image/,/*;q=0.8");
|
||||||
|
|
||||||
bool useNetworkCache =
|
// Cached entries are served straight from the disk cache even when picture downloads are
|
||||||
!picDownload && static_cast<CardPictureLoaderCacheMethod::CacheMethod>(
|
// enabled: re-fetching an already-cached image would burn the rate limit for nothing. Only a
|
||||||
|
// genuine cache miss goes to the network, and only when downloads are enabled.
|
||||||
|
bool useNetworkCache = static_cast<CardPictureLoaderCacheMethod::CacheMethod>(
|
||||||
SettingsCache::instance().cacheStorage().getCardPictureLoaderCacheMethod()) ==
|
SettingsCache::instance().cacheStorage().getCardPictureLoaderCacheMethod()) ==
|
||||||
CardPictureLoaderCacheMethod::CacheMethod::NETWORK_CACHE;
|
CardPictureLoaderCacheMethod::CacheMethod::NETWORK_CACHE &&
|
||||||
|
(cache->metaData(url).isValid() || !picDownload);
|
||||||
|
|
||||||
req.setAttribute(QNetworkRequest::CacheLoadControlAttribute,
|
req.setAttribute(QNetworkRequest::CacheLoadControlAttribute,
|
||||||
useNetworkCache ? QNetworkRequest::AlwaysCache : QNetworkRequest::AlwaysNetwork);
|
useNetworkCache ? QNetworkRequest::AlwaysCache : QNetworkRequest::AlwaysNetwork);
|
||||||
|
|
@ -126,6 +138,9 @@ QNetworkReply *CardPictureLoaderWorker::makeRequest(const QUrl &url, CardPicture
|
||||||
void CardPictureLoaderWorker::resetRequestQuota()
|
void CardPictureLoaderWorker::resetRequestQuota()
|
||||||
{
|
{
|
||||||
requestQuota = MAX_REQUESTS_PER_SEC;
|
requestQuota = MAX_REQUESTS_PER_SEC;
|
||||||
|
// Allowances are seeded per host on demand in processSingleRequest(), so a
|
||||||
|
// rate-limited host never gets a fresh full quota mid-second.
|
||||||
|
hostQuotaRemaining.clear();
|
||||||
|
|
||||||
QDateTime now = QDateTime::currentDateTime();
|
QDateTime now = QDateTime::currentDateTime();
|
||||||
for (auto it = hostRequestQuota.begin(); it != hostRequestQuota.end(); ++it) {
|
for (auto it = hostRequestQuota.begin(); it != hostRequestQuota.end(); ++it) {
|
||||||
|
|
@ -134,27 +149,53 @@ void CardPictureLoaderWorker::resetRequestQuota()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto &request : requestLoadQueue) {
|
|
||||||
const QString host = request.first.host();
|
|
||||||
hostQuotaRemaining.insert(host, hostRequestQuota.value(host, MAX_REQUESTS_PER_SEC));
|
|
||||||
}
|
|
||||||
|
|
||||||
processQueuedRequests();
|
processQueuedRequests();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardPictureLoaderWorker::processQueuedRequests()
|
void CardPictureLoaderWorker::processQueuedRequests()
|
||||||
{
|
{
|
||||||
while (requestQuota > 0 && processSingleRequest()) {
|
if (requestLoadQueue.isEmpty()) {
|
||||||
|
dispatchTimer.stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Start lazily from the worker's own thread: QTimer must be started in the thread it lives in.
|
||||||
|
if (!requestTimer.isActive()) {
|
||||||
|
requestTimer.start();
|
||||||
|
}
|
||||||
|
dispatchTimer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CardPictureLoaderWorker::dispatchQueuedRequest()
|
||||||
|
{
|
||||||
|
if (requestLoadQueue.isEmpty() || requestQuota <= 0) {
|
||||||
|
dispatchTimer.stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (processSingleRequest()) {
|
||||||
--requestQuota;
|
--requestQuota;
|
||||||
|
} else {
|
||||||
|
// No queued host currently has allowance left in this second; wait for the quota reset.
|
||||||
|
dispatchTimer.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CardPictureLoaderWorker::processSingleRequest()
|
bool CardPictureLoaderWorker::processSingleRequest()
|
||||||
{
|
{
|
||||||
|
QDateTime now = QDateTime::currentDateTime();
|
||||||
for (int i = 0; i < requestLoadQueue.size(); ++i) {
|
for (int i = 0; i < requestLoadQueue.size(); ++i) {
|
||||||
const auto &request = requestLoadQueue.at(i);
|
const auto &request = requestLoadQueue.at(i);
|
||||||
QString host = request.first.host();
|
const QString host = request.first.host();
|
||||||
int allowance = hostQuotaRemaining.value(host, MAX_REQUESTS_PER_SEC);
|
// Don't dispatch requests to a host that is currently in its 429 backoff.
|
||||||
|
if (CardPictureLoaderWorkerWork::rateLimiter().isRateLimited(host, now)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Seed the allowance only now, so a host that was rate limited last second
|
||||||
|
// doesn't get a fresh full quota the moment it is queried mid-second.
|
||||||
|
if (!hostQuotaRemaining.contains(host)) {
|
||||||
|
hostQuotaRemaining.insert(host, hostRequestQuota.value(host, MAX_REQUESTS_PER_SEC));
|
||||||
|
}
|
||||||
|
int allowance = hostQuotaRemaining.value(host);
|
||||||
if (allowance > 0) {
|
if (allowance > 0) {
|
||||||
hostQuotaRemaining.insert(host, allowance - 1);
|
hostQuotaRemaining.insert(host, allowance - 1);
|
||||||
makeRequest(request.first, request.second);
|
makeRequest(request.first, request.second);
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,9 @@ public slots:
|
||||||
/** @brief Processes all queued requests respecting the request quota. */
|
/** @brief Processes all queued requests respecting the request quota. */
|
||||||
void processQueuedRequests();
|
void processQueuedRequests();
|
||||||
|
|
||||||
|
/** @brief Chooses a request from the queue and starts it, respecting the quota and pacing. */
|
||||||
|
void dispatchQueuedRequest();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Processes a single queued request.
|
* @brief Processes a single queued request.
|
||||||
* @return true if a request was processed, false if queue is empty.
|
* @return true if a request was processed, false if queue is empty.
|
||||||
|
|
@ -120,6 +123,7 @@ private:
|
||||||
|
|
||||||
int requestQuota; ///< Remaining requests allowed per second
|
int requestQuota; ///< Remaining requests allowed per second
|
||||||
QTimer requestTimer; ///< Timer to reset the request quota
|
QTimer requestTimer; ///< Timer to reset the request quota
|
||||||
|
QTimer dispatchTimer; ///< Timer pacing individual network requests
|
||||||
QHash<QString, int> hostRequestQuota; ///< Sustained per-host request allowance
|
QHash<QString, int> hostRequestQuota; ///< Sustained per-host request allowance
|
||||||
QHash<QString, int> hostQuotaRemaining; ///< Per-host allowance left in the current second
|
QHash<QString, int> hostQuotaRemaining; ///< Per-host allowance left in the current second
|
||||||
QHash<QString, QDateTime> hostLast429; ///< When each host was last rate limited
|
QHash<QString, QDateTime> hostLast429; ///< When each host was last rate limited
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,11 @@ static const QStringList MD5_BLACKLIST = {
|
||||||
"fbc7d763c08771c260b39e2115414eeb" // Current card back hash
|
"fbc7d763c08771c260b39e2115414eeb" // Current card back hash
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ServerRateLimiter &CardPictureLoaderWorkerWork::rateLimiter()
|
||||||
|
{
|
||||||
|
return s_rateLimiter;
|
||||||
|
}
|
||||||
|
|
||||||
CardPictureLoaderWorkerWork::CardPictureLoaderWorkerWork(const CardPictureLoaderWorker *worker, const ExactCard &toLoad)
|
CardPictureLoaderWorkerWork::CardPictureLoaderWorkerWork(const CardPictureLoaderWorker *worker, const ExactCard &toLoad)
|
||||||
: QObject(nullptr), cardToDownload(CardPictureToLoad(toLoad)),
|
: QObject(nullptr), cardToDownload(CardPictureToLoad(toLoad)),
|
||||||
picDownload(SettingsCache::instance().downloads().getPicDownload())
|
picDownload(SettingsCache::instance().downloads().getPicDownload())
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,9 @@ public:
|
||||||
|
|
||||||
CardPictureToLoad cardToDownload; ///< The card and associated URLs to try downloading
|
CardPictureToLoad cardToDownload; ///< The card and associated URLs to try downloading
|
||||||
|
|
||||||
|
/** @brief Shared per-server 429 backoff state. */
|
||||||
|
static ServerRateLimiter &rateLimiter();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
/**
|
/**
|
||||||
* @brief Handles a finished network reply for the card image.
|
* @brief Handles a finished network reply for the card image.
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ enum Format
|
||||||
PlainText,
|
PlainText,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is cockatrice's native deck file format, and supports deck metadata such as banner cards and tags.
|
* This is Cockatrice's native deck file format, and supports deck metadata such as banner cards and tags.
|
||||||
* Stored as .cod files.
|
* Stored as .cod files.
|
||||||
*/
|
*/
|
||||||
Cockatrice
|
Cockatrice
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ DeckLoader::loadFromFile(const QString &fileName, DeckFileFormat::Format fmt, bo
|
||||||
result = deckList.loadFromFile_Native(&file);
|
result = deckList.loadFromFile_Native(&file);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
qCInfo(DeckLoaderLog) << "Failed to load " << fileName
|
qCInfo(DeckLoaderLog) << "Failed to load " << fileName
|
||||||
<< "as cockatrice format; retrying as plain format";
|
<< "as Cockatrice format; retrying as plain format";
|
||||||
file.seek(0);
|
file.seek(0);
|
||||||
result = deckList.loadFromFile_Plain(&file, CardNameNormalizer());
|
result = deckList.loadFromFile_Plain(&file, CardNameNormalizer());
|
||||||
fmt = DeckFileFormat::PlainText;
|
fmt = DeckFileFormat::PlainText;
|
||||||
|
|
|
||||||
|
|
@ -131,7 +131,7 @@ public:
|
||||||
static void printDeckList(QPrinter *printer, const DeckList &deckList);
|
static void printDeckList(QPrinter *printer, const DeckList &deckList);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the given deck's file to the cockatrice file format.
|
* Converts the given deck's file to the Cockatrice file format.
|
||||||
* Uses the lastLoadInfo in the LoadedDeck to determine the current name of the file and where to save to.
|
* Uses the lastLoadInfo in the LoadedDeck to determine the current name of the file and where to save to.
|
||||||
* @param deck The deck to convert. Should have valid lastLoadInfo. Will update the lastLoadInfo.
|
* @param deck The deck to convert. Should have valid lastLoadInfo. Will update the lastLoadInfo.
|
||||||
* @return Whether the conversion succeeded.
|
* @return Whether the conversion succeeded.
|
||||||
|
|
|
||||||
|
|
@ -224,7 +224,7 @@ QStringMap &ThemeManager::getAvailableThemes()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// load themes from cockatrice system dir
|
// Load themes from Cockatrice system dir
|
||||||
dir.setPath(systemThemesBasePath());
|
dir.setPath(systemThemesBasePath());
|
||||||
|
|
||||||
for (QString themeName : dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name)) {
|
for (QString themeName : dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name)) {
|
||||||
|
|
|
||||||
|
|
@ -478,13 +478,13 @@ void DlgSettings::closeEvent(QCloseEvent *event)
|
||||||
case Invalid:
|
case Invalid:
|
||||||
loadErrorMessage = tr("Your card database is invalid.\n\n"
|
loadErrorMessage = tr("Your card database is invalid.\n\n"
|
||||||
"Cockatrice may not function correctly with an invalid database\n\n"
|
"Cockatrice may not function correctly with an invalid database\n\n"
|
||||||
"You may need to rerun oracle to update your card database.\n\n"
|
"You may need to rerun Oracle to update your card database.\n\n"
|
||||||
"Would you like to change your database location setting?");
|
"Would you like to change your database location setting?");
|
||||||
break;
|
break;
|
||||||
case VersionTooOld:
|
case VersionTooOld:
|
||||||
loadErrorMessage = tr("Your card database version is too old.\n\n"
|
loadErrorMessage = tr("Your card database version is too old.\n\n"
|
||||||
"This can cause problems loading card information or images\n\n"
|
"This can cause problems loading card information or images\n\n"
|
||||||
"Usually this can be fixed by rerunning oracle to to update your card database.\n\n"
|
"Usually this can be fixed by rerunning Oracle to to update your card database.\n\n"
|
||||||
"Would you like to change your database location setting?");
|
"Would you like to change your database location setting?");
|
||||||
break;
|
break;
|
||||||
case NotLoaded:
|
case NotLoaded:
|
||||||
|
|
|
||||||
|
|
@ -92,8 +92,8 @@
|
||||||
#include <libcockatrice/settings/updates_settings.h>
|
#include <libcockatrice/settings/updates_settings.h>
|
||||||
|
|
||||||
#define GITHUB_PAGES_URL "https://cockatrice.github.io"
|
#define GITHUB_PAGES_URL "https://cockatrice.github.io"
|
||||||
#define GITHUB_CONTRIBUTORS_URL "https://github.com/Cockatrice/Cockatrice/graphs/contributors?type=c"
|
#define GITHUB_CONTRIBUTORS_URL "https://github.com/Cockatrice/Cockatrice/graphs/contributors"
|
||||||
#define GITHUB_CONTRIBUTE_URL "https://github.com/Cockatrice/Cockatrice#cockatrice"
|
#define GITHUB_CONTRIBUTE_URL "https://github.com/Cockatrice/Cockatrice#"
|
||||||
#define GITHUB_TRANSIFEX_TRANSLATORS_URL "https://github.com/Cockatrice/Cockatrice/wiki/Translator-Hall-of-Fame"
|
#define GITHUB_TRANSIFEX_TRANSLATORS_URL "https://github.com/Cockatrice/Cockatrice/wiki/Translator-Hall-of-Fame"
|
||||||
#define GITHUB_TRANSLATOR_FAQ_URL "https://github.com/Cockatrice/Cockatrice/wiki/Translation-FAQ"
|
#define GITHUB_TRANSLATOR_FAQ_URL "https://github.com/Cockatrice/Cockatrice/wiki/Translation-FAQ"
|
||||||
#define GITHUB_ISSUES_URL "https://github.com/Cockatrice/Cockatrice/issues"
|
#define GITHUB_ISSUES_URL "https://github.com/Cockatrice/Cockatrice/issues"
|
||||||
|
|
@ -1050,7 +1050,7 @@ void MainWindow::createCardUpdateProcess(bool background)
|
||||||
|
|
||||||
if (dir.exists(binaryName)) {
|
if (dir.exists(binaryName)) {
|
||||||
updaterCmd = dir.absoluteFilePath(binaryName);
|
updaterCmd = dir.absoluteFilePath(binaryName);
|
||||||
} else { // try and find the directory oracle is stored in the build directory
|
} else { // try and find the directory Oracle is stored in the build directory
|
||||||
QDir findLocalDir(dir);
|
QDir findLocalDir(dir);
|
||||||
findLocalDir.cdUp();
|
findLocalDir.cdUp();
|
||||||
findLocalDir.cd(getCardUpdaterBinaryName());
|
findLocalDir.cd(getCardUpdaterBinaryName());
|
||||||
|
|
|
||||||
|
|
@ -231,7 +231,7 @@ int main(int argc, char *argv[])
|
||||||
// These values are only used by the settings loader/saver
|
// These values are only used by the settings loader/saver
|
||||||
// Wrong or outdated values are kept to not break things
|
// Wrong or outdated values are kept to not break things
|
||||||
QCoreApplication::setOrganizationName("Cockatrice");
|
QCoreApplication::setOrganizationName("Cockatrice");
|
||||||
QCoreApplication::setOrganizationDomain("cockatrice.de");
|
QCoreApplication::setOrganizationDomain("cockatrice.github.io");
|
||||||
QCoreApplication::setApplicationName("Cockatrice");
|
QCoreApplication::setApplicationName("Cockatrice");
|
||||||
QCoreApplication::setApplicationVersion(VERSION_STRING);
|
QCoreApplication::setApplicationVersion(VERSION_STRING);
|
||||||
|
|
||||||
|
|
@ -250,7 +250,7 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
// Command-line parser
|
// Command-line parser
|
||||||
QCommandLineParser parser;
|
QCommandLineParser parser;
|
||||||
parser.setApplicationDescription("Cockatrice");
|
parser.setApplicationDescription("Cockatrice Client");
|
||||||
parser.addHelpOption();
|
parser.addHelpOption();
|
||||||
parser.addVersionOption();
|
parser.addVersionOption();
|
||||||
|
|
||||||
|
|
@ -350,8 +350,8 @@ int main(int argc, char *argv[])
|
||||||
qCInfo(MainLog) << "MainWindow constructor finished";
|
qCInfo(MainLog) << "MainWindow constructor finished";
|
||||||
|
|
||||||
ui.setWindowIcon(themePixmap(QStringLiteral("cockatrice")));
|
ui.setWindowIcon(themePixmap(QStringLiteral("cockatrice")));
|
||||||
// set name of the app desktop file; used by wayland to load the window icon
|
// Set name of the app desktop file; used by wayland to load the window icon
|
||||||
QGuiApplication::setDesktopFileName("cockatrice");
|
QGuiApplication::setDesktopFileName("Cockatrice");
|
||||||
|
|
||||||
SettingsCache::instance().network().setClientID(generateClientID());
|
SettingsCache::instance().network().setClientID(generateClientID());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,8 +50,8 @@ int main(int argc, char *argv[])
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
QCoreApplication::setOrganizationName("Cockatrice");
|
QCoreApplication::setOrganizationName("Cockatrice");
|
||||||
QCoreApplication::setOrganizationDomain("cockatrice");
|
QCoreApplication::setOrganizationDomain("Cockatrice");
|
||||||
// this can't be changed, as it influences the default save path for cards.xml
|
// This can't be changed, as it influences the default save path for cards.xml
|
||||||
QCoreApplication::setApplicationName("Cockatrice");
|
QCoreApplication::setApplicationName("Cockatrice");
|
||||||
|
|
||||||
// If the program is opened with the -s flag, it will only do spoilers. Otherwise it will do MTGJSON/Tokens
|
// If the program is opened with the -s flag, it will only do spoilers. Otherwise it will do MTGJSON/Tokens
|
||||||
|
|
@ -83,7 +83,7 @@ int main(int argc, char *argv[])
|
||||||
QIcon icon("theme:appicon.svg");
|
QIcon icon("theme:appicon.svg");
|
||||||
wizard.setWindowIcon(icon);
|
wizard.setWindowIcon(icon);
|
||||||
// set name of the app desktop file; used by wayland to load the window icon
|
// set name of the app desktop file; used by wayland to load the window icon
|
||||||
QGuiApplication::setDesktopFileName("oracle");
|
QGuiApplication::setDesktopFileName("Oracle");
|
||||||
|
|
||||||
wizard.show();
|
wizard.show();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -796,7 +796,7 @@ void SaveSetsPage::retranslateUi()
|
||||||
{
|
{
|
||||||
setTitle(tr("Sets imported"));
|
setTitle(tr("Sets imported"));
|
||||||
if (wizard()->downloadedPlainXml) {
|
if (wizard()->downloadedPlainXml) {
|
||||||
setSubTitle(tr("A cockatrice database file of %1 MB has been downloaded.")
|
setSubTitle(tr("A Cockatrice card database file of %1 MB has been downloaded.")
|
||||||
.arg(qRound(wizard()->xmlData.size() / 1000000.0)));
|
.arg(qRound(wizard()->xmlData.size() / 1000000.0)));
|
||||||
} else {
|
} else {
|
||||||
setSubTitle(tr("The following sets have been found:"));
|
setSubTitle(tr("The following sets have been found:"));
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
* Note that "...enters tapped unless..." returns false.
|
* Note that "...enters tapped unless..." returns false.
|
||||||
*
|
*
|
||||||
* @param name The name of the card
|
* @param name The name of the card
|
||||||
* @param text The oracle text of the card
|
* @param text The Oracle text of the card
|
||||||
*/
|
*/
|
||||||
bool parseCipt(const QString &name, const QString &text)
|
bool parseCipt(const QString &name, const QString &text)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ using ScanProgressCallback = std::function<void(qsizetype bytesRead, qsizetype t
|
||||||
* @brief Scans a full MTGJSON document without materializing the JSON tree.
|
* @brief Scans a full MTGJSON document without materializing the JSON tree.
|
||||||
*
|
*
|
||||||
* Splits the top-level "data" object into per-set byte ranges and reads each
|
* Splits the top-level "data" object into per-set byte ranges and reads each
|
||||||
* set's metadata directly from the raw bytes. The oracle importer can then
|
* set's metadata directly from the raw bytes. The Oracle importer can then
|
||||||
* parse one set at a time during import, keeping peak memory far below a single
|
* parse one set at a time during import, keeping peak memory far below a single
|
||||||
* QJsonDocument::fromJson() over the whole file.
|
* QJsonDocument::fromJson() over the whole file.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -86,9 +86,10 @@ bool Servatrice_DatabaseInterface::openDatabase()
|
||||||
<< dbversion << "to version" << expectedversion;
|
<< dbversion << "to version" << expectedversion;
|
||||||
return false;
|
return false;
|
||||||
} else if (dbversion > expectedversion) {
|
} else if (dbversion > expectedversion) {
|
||||||
qCCritical(DatabaseInterfaceLog) << poolStr << "Error opening database: the database schema version"
|
qCCritical(DatabaseInterfaceLog)
|
||||||
<< dbversion << "is too new, you need to update servatrice"
|
<< poolStr << "Error opening database: the database schema version" << dbversion
|
||||||
<< "(this servatrice actually uses version" << expectedversion << ")";
|
<< "is too new, you need to update Servatrice" << "(Currently running Servatrice actually uses version"
|
||||||
|
<< expectedversion << ")";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue