mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-07-01 02:53:56 -07:00
[Doxygen] Card Picture Loader (#6315)
* [Doxygen] Card Picture Loader Took 25 minutes Took 16 minutes # Commit time for manual adjustment: # Took 12 seconds Took 14 seconds * Remove placeholder file description. Took 1 minute * ... but do group PictureLoader again Took 28 seconds * Link to methods directly. Took 6 minutes * Forward declaration. Took 49 seconds * Remove redundant .cpp function documentation. Took 15 minutes * More fixes. Took 7 minutes --------- Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
This commit is contained in:
parent
ace4063371
commit
827f22ed37
11 changed files with 435 additions and 152 deletions
|
|
@ -1,9 +1,3 @@
|
||||||
/**
|
|
||||||
* @file card_picture_loader.h
|
|
||||||
* @ingroup PictureLoader
|
|
||||||
* @brief TODO: Document this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CARD_PICTURE_LOADER_H
|
#ifndef CARD_PICTURE_LOADER_H
|
||||||
#define CARD_PICTURE_LOADER_H
|
#define CARD_PICTURE_LOADER_H
|
||||||
|
|
||||||
|
|
@ -16,10 +10,37 @@
|
||||||
inline Q_LOGGING_CATEGORY(CardPictureLoaderLog, "card_picture_loader");
|
inline Q_LOGGING_CATEGORY(CardPictureLoaderLog, "card_picture_loader");
|
||||||
inline Q_LOGGING_CATEGORY(CardPictureLoaderCardBackCacheFailLog, "card_picture_loader.card_back_cache_fail");
|
inline Q_LOGGING_CATEGORY(CardPictureLoaderCardBackCacheFailLog, "card_picture_loader.card_back_cache_fail");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class CardPictureLoader
|
||||||
|
* @ingroup PictureLoader
|
||||||
|
* @brief Singleton class to manage card image loading and caching. Provides functionality to asynchronously load,
|
||||||
|
* cache, and manage card images for the client.
|
||||||
|
*
|
||||||
|
* This class is a singleton and handles:
|
||||||
|
* - Loading card images from disk or network.
|
||||||
|
* - Caching images in QPixmapCache for fast reuse.
|
||||||
|
* - Providing themed card backs, including fallback and in-progress/failed states.
|
||||||
|
* - Emitting updates when pixmaps are loaded.
|
||||||
|
*
|
||||||
|
* It interacts with CardPictureLoaderWorker for background loading and
|
||||||
|
* CardPictureLoaderStatusBar to display loading progress in the main window.
|
||||||
|
*
|
||||||
|
* Provides static accessors for:
|
||||||
|
* - Card images by ExactCard.
|
||||||
|
* - Card back images (normal, in-progress, failed).
|
||||||
|
* - Cache management (clearPixmapCache(), clearNetworkCache(), cacheCardPixmaps(const QList<ExactCard> &cards)).
|
||||||
|
*
|
||||||
|
* Uses a worker thread for asynchronous image loading and a status bar widget
|
||||||
|
* to track load progress.
|
||||||
|
*/
|
||||||
class CardPictureLoader : public QObject
|
class CardPictureLoader : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Access the singleton instance of CardPictureLoader.
|
||||||
|
* @return Reference to the singleton.
|
||||||
|
*/
|
||||||
static CardPictureLoader &getInstance()
|
static CardPictureLoader &getInstance()
|
||||||
{
|
{
|
||||||
static CardPictureLoader instance;
|
static CardPictureLoader instance;
|
||||||
|
|
@ -29,30 +50,87 @@ public:
|
||||||
private:
|
private:
|
||||||
explicit CardPictureLoader();
|
explicit CardPictureLoader();
|
||||||
~CardPictureLoader() override;
|
~CardPictureLoader() override;
|
||||||
// Singleton - Don't implement copy constructor and assign operator
|
|
||||||
CardPictureLoader(CardPictureLoader const &);
|
|
||||||
void operator=(CardPictureLoader const &);
|
|
||||||
|
|
||||||
CardPictureLoaderWorker *worker;
|
// Disable copy and assignment for singleton
|
||||||
CardPictureLoaderStatusBar *statusBar;
|
CardPictureLoader(CardPictureLoader const &) = delete;
|
||||||
|
void operator=(CardPictureLoader const &) = delete;
|
||||||
|
|
||||||
|
CardPictureLoaderWorker *worker; ///< Worker thread for async image loading
|
||||||
|
CardPictureLoaderStatusBar *statusBar; ///< Status bar widget showing load progress
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Retrieve a card pixmap, either from cache or enqueued for loading.
|
||||||
|
* @param pixmap Reference to QPixmap where result will be stored.
|
||||||
|
* @param card ExactCard to load.
|
||||||
|
* @param size Desired size of pixmap.
|
||||||
|
*/
|
||||||
static void getPixmap(QPixmap &pixmap, const ExactCard &card, QSize size);
|
static void getPixmap(QPixmap &pixmap, const ExactCard &card, QSize size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieve a generic card back pixmap.
|
||||||
|
* @param pixmap Reference to QPixmap where result will be stored.
|
||||||
|
* @param size Desired size of pixmap.
|
||||||
|
*/
|
||||||
static void getCardBackPixmap(QPixmap &pixmap, QSize size);
|
static void getCardBackPixmap(QPixmap &pixmap, QSize size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieve a card back pixmap for the loading-in-progress state.
|
||||||
|
* @param pixmap Reference to QPixmap where result will be stored.
|
||||||
|
* @param size Desired size of pixmap.
|
||||||
|
*/
|
||||||
static void getCardBackLoadingInProgressPixmap(QPixmap &pixmap, QSize size);
|
static void getCardBackLoadingInProgressPixmap(QPixmap &pixmap, QSize size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieve a card back pixmap for the loading-failed state.
|
||||||
|
* @param pixmap Reference to QPixmap where result will be stored.
|
||||||
|
* @param size Desired size of pixmap.
|
||||||
|
*/
|
||||||
static void getCardBackLoadingFailedPixmap(QPixmap &pixmap, QSize size);
|
static void getCardBackLoadingFailedPixmap(QPixmap &pixmap, QSize size);
|
||||||
static void clearPixmapCache();
|
|
||||||
|
/**
|
||||||
|
* @brief Preload a list of cards into the pixmap cache (limited to CACHED_CARD_PER_DECK_MAX).
|
||||||
|
* @param cards List of ExactCard objects to preload.
|
||||||
|
*/
|
||||||
static void cacheCardPixmaps(const QList<ExactCard> &cards);
|
static void cacheCardPixmaps(const QList<ExactCard> &cards);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if the user has custom card art in the picsPath directory.
|
||||||
|
* @return True if any custom art exists.
|
||||||
|
*/
|
||||||
static bool hasCustomArt();
|
static bool hasCustomArt();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clears the in-memory QPixmap cache for all cards.
|
||||||
|
*/
|
||||||
|
static void clearPixmapCache();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
/**
|
||||||
|
* @brief Clears the network disk cache of the worker.
|
||||||
|
*/
|
||||||
static void clearNetworkCache();
|
static void clearNetworkCache();
|
||||||
|
|
||||||
private slots:
|
/**
|
||||||
void picDownloadChanged();
|
* @brief Slot called by the worker when an image is loaded.
|
||||||
void picsPathChanged();
|
* Inserts the pixmap into the cache and emits pixmap updated signals.
|
||||||
|
* @param card ExactCard that was loaded.
|
||||||
public slots:
|
* @param image Loaded QImage.
|
||||||
|
*/
|
||||||
void imageLoaded(const ExactCard &card, const QImage &image);
|
void imageLoaded(const ExactCard &card, const QImage &image);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
/**
|
||||||
|
* @brief Triggered when the user changes the picture download settings.
|
||||||
|
* Clears the QPixmap cache to reload images.
|
||||||
|
*/
|
||||||
|
void picDownloadChanged();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Triggered when the pictures path changes.
|
||||||
|
* Clears the QPixmap cache to reload images.
|
||||||
|
*/
|
||||||
|
void picsPathChanged();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -47,12 +47,6 @@ void CardPictureLoaderLocal::refreshIndex()
|
||||||
<< customFolderIndex.size() << "entries.";
|
<< 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
|
QImage CardPictureLoaderLocal::tryLoad(const ExactCard &toLoad) const
|
||||||
{
|
{
|
||||||
PrintingInfo setInstance = toLoad.getPrinting();
|
PrintingInfo setInstance = toLoad.getPrinting();
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,3 @@
|
||||||
/**
|
|
||||||
* @file card_picture_loader_local.h
|
|
||||||
* @ingroup PictureLoader
|
|
||||||
* @brief TODO: Document this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef PICTURE_LOADER_LOCAL_H
|
#ifndef PICTURE_LOADER_LOCAL_H
|
||||||
#define PICTURE_LOADER_LOCAL_H
|
#define PICTURE_LOADER_LOCAL_H
|
||||||
|
|
||||||
|
|
@ -15,32 +9,80 @@
|
||||||
inline Q_LOGGING_CATEGORY(CardPictureLoaderLocalLog, "card_picture_loader.local");
|
inline Q_LOGGING_CATEGORY(CardPictureLoaderLocalLog, "card_picture_loader.local");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles searching for and loading card images from the local pics and custom image folders.
|
* @class CardPictureLoaderLocal
|
||||||
* This class maintains an index of the CUSTOM folder, to avoid repeatedly searching the entire directory.
|
* @ingroup PictureLoader
|
||||||
|
* @brief Handles searching for and loading card images from local and custom image folders.
|
||||||
|
*
|
||||||
|
* This class maintains an index of the CUSTOM folder to avoid repeatedly scanning
|
||||||
|
* directories, and supports periodic refreshes to update the index.
|
||||||
|
*
|
||||||
|
* Responsibilities:
|
||||||
|
* - Load images for ExactCard objects from local disk or custom folders.
|
||||||
|
* - Maintain an index for fast lookup of images in the CUSTOM folder.
|
||||||
|
* - Refresh the index periodically to account for changes in local image directories.
|
||||||
*/
|
*/
|
||||||
class CardPictureLoaderLocal : public QObject
|
class CardPictureLoaderLocal : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Constructs a CardPictureLoaderLocal object.
|
||||||
|
* @param parent Optional parent QObject.
|
||||||
|
*
|
||||||
|
* Initializes paths from SettingsCache, connects to settings change signals,
|
||||||
|
* builds the initial folder index, and starts a periodic refresh timer.
|
||||||
|
*/
|
||||||
explicit CardPictureLoaderLocal(QObject *parent);
|
explicit CardPictureLoaderLocal(QObject *parent);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Attempts to load a card image from local disk or custom folders.
|
||||||
|
* @param toLoad ExactCard object representing the card to load.
|
||||||
|
* @return Loaded QImage if found; otherwise, an empty QImage.
|
||||||
|
*
|
||||||
|
* Uses a set of name variants and folder paths to attempt to locate the correct image.
|
||||||
|
*/
|
||||||
QImage tryLoad(const ExactCard &toLoad) const;
|
QImage tryLoad(const ExactCard &toLoad) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString picsPath, customPicsPath;
|
QString picsPath; ///< Path to standard card image folder
|
||||||
|
QString customPicsPath; ///< Path to custom card image folder
|
||||||
|
|
||||||
QMultiHash<QString, QString> customFolderIndex; // multimap of cardName to picPaths
|
QMultiHash<QString, QString> customFolderIndex; ///< Multimap from cardName to file paths in CUSTOM folder
|
||||||
QTimer *refreshTimer;
|
QTimer *refreshTimer; ///< Timer for periodic folder index refresh
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Rebuilds the index of the custom image folder.
|
||||||
|
*
|
||||||
|
* Iterates through all subdirectories of the CUSTOM folder and populates
|
||||||
|
* `customFolderIndex` with all discovered image files keyed by base name
|
||||||
|
* and complete base name.
|
||||||
|
*/
|
||||||
void refreshIndex();
|
void refreshIndex();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Attempts to load a card image from disk given its set and name info.
|
||||||
|
* @param setName Corrected short name of the card's set.
|
||||||
|
* @param correctedCardName Corrected card name (e.g., normalized name).
|
||||||
|
* @param collectorNumber Collector number of the card.
|
||||||
|
* @param providerId Optional provider UUID of the card.
|
||||||
|
* @return Loaded QImage if found; otherwise, an empty QImage.
|
||||||
|
*
|
||||||
|
* Searches in both the custom folder index and standard pictures paths.
|
||||||
|
* Uses several filename patterns to match card images, in order from
|
||||||
|
* most-specific to least-specific.
|
||||||
|
*/
|
||||||
QImage tryLoadCardImageFromDisk(const QString &setName,
|
QImage tryLoadCardImageFromDisk(const QString &setName,
|
||||||
const QString &correctedCardName,
|
const QString &correctedCardName,
|
||||||
const QString &collectorNumber,
|
const QString &collectorNumber,
|
||||||
const QString &providerId) const;
|
const QString &providerId) const;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
/**
|
||||||
|
* @brief Updates internal paths when the user changes picture settings.
|
||||||
|
*
|
||||||
|
* Triggered by `SettingsCache::picsPathChanged`.
|
||||||
|
*/
|
||||||
void picsPathChanged();
|
void picsPathChanged();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,43 @@
|
||||||
/**
|
|
||||||
* @file card_picture_loader_request_status_display_widget.h
|
|
||||||
* @ingroup PictureLoader
|
|
||||||
* @brief TODO: Document this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef PICTURE_LOADER_REQUEST_STATUS_DISPLAY_WIDGET_H
|
#ifndef PICTURE_LOADER_REQUEST_STATUS_DISPLAY_WIDGET_H
|
||||||
#define PICTURE_LOADER_REQUEST_STATUS_DISPLAY_WIDGET_H
|
#define PICTURE_LOADER_REQUEST_STATUS_DISPLAY_WIDGET_H
|
||||||
|
|
||||||
#include "card_picture_loader_worker_work.h"
|
#include "card_picture_loader_worker_work.h"
|
||||||
|
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class CardPictureLoaderRequestStatusDisplayWidget
|
||||||
|
* @ingroup PictureLoader
|
||||||
|
* @brief A small widget to display the status of a single card image request.
|
||||||
|
*
|
||||||
|
* Displays:
|
||||||
|
* - Card name
|
||||||
|
* - Set short name
|
||||||
|
* - Provider ID
|
||||||
|
* - Start time of request
|
||||||
|
* - Elapsed time since start
|
||||||
|
* - Finished status
|
||||||
|
* - URL of the requested image
|
||||||
|
*/
|
||||||
class CardPictureLoaderRequestStatusDisplayWidget : public QWidget
|
class CardPictureLoaderRequestStatusDisplayWidget : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Constructs a new status widget for a specific card image request.
|
||||||
|
* @param parent Parent widget
|
||||||
|
* @param url URL of the image being requested
|
||||||
|
* @param card The ExactCard being downloaded
|
||||||
|
* @param setName Set name for the card
|
||||||
|
*/
|
||||||
CardPictureLoaderRequestStatusDisplayWidget(QWidget *parent,
|
CardPictureLoaderRequestStatusDisplayWidget(QWidget *parent,
|
||||||
const QUrl &url,
|
const QUrl &url,
|
||||||
const ExactCard &card,
|
const ExactCard &card,
|
||||||
const QString &setName);
|
const QString &setName);
|
||||||
|
|
||||||
|
/** Marks the request as finished */
|
||||||
void setFinished()
|
void setFinished()
|
||||||
{
|
{
|
||||||
finished->setText("True");
|
finished->setText("True");
|
||||||
|
|
@ -28,19 +45,25 @@ public:
|
||||||
repaint();
|
repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns whether the request has finished */
|
||||||
bool getFinished() const
|
bool getFinished() const
|
||||||
{
|
{
|
||||||
return finished->text() == "True";
|
return finished->text() == "True";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Updates the elapsed time display */
|
||||||
void setElapsedTime(const QString &_elapsedTime) const
|
void setElapsedTime(const QString &_elapsedTime) const
|
||||||
{
|
{
|
||||||
elapsedTime->setText(_elapsedTime);
|
elapsedTime->setText(_elapsedTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Queries the elapsed time in seconds since the request started
|
||||||
|
* @return Elapsed time in seconds
|
||||||
|
*/
|
||||||
int queryElapsedSeconds()
|
int queryElapsedSeconds()
|
||||||
{
|
{
|
||||||
if (!finished) {
|
if (!getFinished()) {
|
||||||
int elapsedSeconds = QDateTime::fromString(startTime->text()).secsTo(QDateTime::currentDateTime());
|
int elapsedSeconds = QDateTime::fromString(startTime->text()).secsTo(QDateTime::currentDateTime());
|
||||||
elapsedTime->setText(QString::number(elapsedSeconds));
|
elapsedTime->setText(QString::number(elapsedSeconds));
|
||||||
update();
|
update();
|
||||||
|
|
@ -50,25 +73,27 @@ public:
|
||||||
return elapsedTime->text().toInt();
|
return elapsedTime->text().toInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns the start time as a string */
|
||||||
QString getStartTime() const
|
QString getStartTime() const
|
||||||
{
|
{
|
||||||
return startTime->text();
|
return startTime->text();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns the URL of the request */
|
||||||
QString getUrl() const
|
QString getUrl() const
|
||||||
{
|
{
|
||||||
return url->text();
|
return url->text();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QHBoxLayout *layout;
|
QHBoxLayout *layout; ///< Horizontal layout for arranging labels
|
||||||
QLabel *name;
|
QLabel *name; ///< Card name
|
||||||
QLabel *setShortname;
|
QLabel *setShortname; ///< Set short name
|
||||||
QLabel *providerId;
|
QLabel *providerId; ///< Provider ID for the card
|
||||||
QLabel *startTime;
|
QLabel *startTime; ///< Start time of the request
|
||||||
QLabel *elapsedTime;
|
QLabel *elapsedTime; ///< Elapsed time since start
|
||||||
QLabel *finished;
|
QLabel *finished; ///< Whether the request has finished
|
||||||
QLabel *url;
|
QLabel *url; ///< URL of the requested image
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PICTURE_LOADER_REQUEST_STATUS_DISPLAY_WIDGET_H
|
#endif // PICTURE_LOADER_REQUEST_STATUS_DISPLAY_WIDGET_H
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,3 @@
|
||||||
/**
|
|
||||||
* @file card_picture_loader_status_bar.h
|
|
||||||
* @ingroup PictureLoader
|
|
||||||
* @brief TODO: Document this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef PICTURE_LOADER_STATUS_BAR_H
|
#ifndef PICTURE_LOADER_STATUS_BAR_H
|
||||||
#define PICTURE_LOADER_STATUS_BAR_H
|
#define PICTURE_LOADER_STATUS_BAR_H
|
||||||
|
|
||||||
|
|
@ -12,24 +6,56 @@
|
||||||
|
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QProgressBar>
|
#include <QProgressBar>
|
||||||
|
#include <QTimer>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class CardPictureLoaderStatusBar
|
||||||
|
* @ingroup PictureLoader
|
||||||
|
* @brief Displays the status of card image downloads in a horizontal progress bar with a log popup.
|
||||||
|
*
|
||||||
|
* Responsibilities:
|
||||||
|
* - Shows overall progress of image downloads.
|
||||||
|
* - Maintains a log of individual requests via a popup (SettingsButtonWidget).
|
||||||
|
* - Cleans up finished request entries automatically after a delay.
|
||||||
|
*/
|
||||||
class CardPictureLoaderStatusBar : public QWidget
|
class CardPictureLoaderStatusBar : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Constructs a status bar with progress bar and log button.
|
||||||
|
* @param parent Parent widget
|
||||||
|
*/
|
||||||
explicit CardPictureLoaderStatusBar(QWidget *parent);
|
explicit CardPictureLoaderStatusBar(QWidget *parent);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
/**
|
||||||
|
* @brief Adds a queued image download to the log and increments the progress bar maximum.
|
||||||
|
* @param url URL of the image
|
||||||
|
* @param card The card being loaded
|
||||||
|
* @param setName The set name of the card
|
||||||
|
*/
|
||||||
void addQueuedImageLoad(const QUrl &url, const ExactCard &card, const QString &setName);
|
void addQueuedImageLoad(const QUrl &url, const ExactCard &card, const QString &setName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Marks an image as successfully loaded.
|
||||||
|
* Updates the progress bar and marks the corresponding log entry as finished.
|
||||||
|
* @param url URL of the successfully loaded image
|
||||||
|
*/
|
||||||
void addSuccessfulImageLoad(const QUrl &url);
|
void addSuccessfulImageLoad(const QUrl &url);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Cleans up old entries from the log that have finished more than 10 seconds ago.
|
||||||
|
* Adjusts the progress bar accordingly.
|
||||||
|
*/
|
||||||
void cleanOldEntries();
|
void cleanOldEntries();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QHBoxLayout *layout;
|
QHBoxLayout *layout; ///< Horizontal layout containing progress bar and log button
|
||||||
QProgressBar *progressBar;
|
QProgressBar *progressBar; ///< Progress bar showing overall download progress
|
||||||
SettingsButtonWidget *loadLog;
|
SettingsButtonWidget *loadLog; ///< Popup log showing individual request statuses
|
||||||
QTimer *cleaner;
|
QTimer *cleaner; ///< Timer for periodically cleaning old log entries
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PICTURE_LOADER_STATUS_BAR_H
|
#endif // PICTURE_LOADER_STATUS_BAR_H
|
||||||
|
|
|
||||||
|
|
@ -105,9 +105,6 @@ void CardPictureLoaderWorker::resetRequestQuota()
|
||||||
processQueuedRequests();
|
processQueuedRequests();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Keeps processing requests from the queue until it is empty or until the quota runs out.
|
|
||||||
*/
|
|
||||||
void CardPictureLoaderWorker::processQueuedRequests()
|
void CardPictureLoaderWorker::processQueuedRequests()
|
||||||
{
|
{
|
||||||
while (requestQuota > 0 && processSingleRequest()) {
|
while (requestQuota > 0 && processSingleRequest()) {
|
||||||
|
|
@ -115,10 +112,6 @@ void CardPictureLoaderWorker::processQueuedRequests()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Immediately processes a single queued request. No-ops if the load queue is empty
|
|
||||||
* @return If a request was processed
|
|
||||||
*/
|
|
||||||
bool CardPictureLoaderWorker::processSingleRequest()
|
bool CardPictureLoaderWorker::processSingleRequest()
|
||||||
{
|
{
|
||||||
if (!requestLoadQueue.isEmpty()) {
|
if (!requestLoadQueue.isEmpty()) {
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,3 @@
|
||||||
/**
|
|
||||||
* @file card_picture_loader_worker.h
|
|
||||||
* @ingroup PictureLoader
|
|
||||||
* @brief TODO: Document this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef PICTURE_LOADER_WORKER_H
|
#ifndef PICTURE_LOADER_WORKER_H
|
||||||
#define PICTURE_LOADER_WORKER_H
|
#define PICTURE_LOADER_WORKER_H
|
||||||
|
|
||||||
|
|
@ -27,57 +21,131 @@
|
||||||
#define REDIRECT_TIMESTAMP "timestamp"
|
#define REDIRECT_TIMESTAMP "timestamp"
|
||||||
#define REDIRECT_CACHE_FILENAME "cache.ini"
|
#define REDIRECT_CACHE_FILENAME "cache.ini"
|
||||||
|
|
||||||
inline Q_LOGGING_CATEGORY(CardPictureLoaderWorkerLog, "card_picture_loader.worker");
|
inline Q_LOGGING_CATEGORY(CardPictureLoaderWorkerLog, "card_picture_loader.worker")
|
||||||
|
|
||||||
class CardPictureLoaderWorkerWork;
|
class CardPictureLoaderWorkerWork;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class CardPictureLoaderWorker
|
||||||
|
* @ingroup PictureLoader
|
||||||
|
* @brief Handles asynchronous loading of card images, both locally and via network.
|
||||||
|
*
|
||||||
|
* Responsibilities:
|
||||||
|
* - Maintain a queue of network image requests with rate-limiting.
|
||||||
|
* - Load images from local cache first via CardPictureLoaderLocal.
|
||||||
|
* - Handle network redirects and persistent caching of redirects.
|
||||||
|
* - Deduplicate simultaneous requests for the same card.
|
||||||
|
* - Emit signals for status updates and loaded images.
|
||||||
|
*/
|
||||||
class CardPictureLoaderWorker : public QObject
|
class CardPictureLoaderWorker : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Constructs a CardPictureLoaderWorker.
|
||||||
|
*
|
||||||
|
* Initializes network manager, cache, redirect cache, local loader, and request quota timer.
|
||||||
|
*/
|
||||||
explicit CardPictureLoaderWorker();
|
explicit CardPictureLoaderWorker();
|
||||||
|
|
||||||
~CardPictureLoaderWorker() override;
|
~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
|
* @brief Enqueues an ExactCard for loading.
|
||||||
|
* @param card ExactCard to load
|
||||||
|
*
|
||||||
|
* This will first try to load the image locally; if that fails, it will enqueue a network request.
|
||||||
|
*/
|
||||||
|
void enqueueImageLoad(const ExactCard &card);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Queues a network request for a given URL and worker thread.
|
||||||
|
* @param url URL to load
|
||||||
|
* @param worker Worker handling this request
|
||||||
|
*/
|
||||||
|
void queueRequest(const QUrl &url, CardPictureLoaderWorkerWork *worker);
|
||||||
|
|
||||||
|
/** @brief Clears the network cache and redirect cache. */
|
||||||
void clearNetworkCache();
|
void clearNetworkCache();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
/**
|
||||||
|
* @brief Makes a network request for the given URL using the specified worker.
|
||||||
|
* @param url URL to load
|
||||||
|
* @param workThread Worker handling the request
|
||||||
|
* @return The QNetworkReply object representing the request
|
||||||
|
*/
|
||||||
QNetworkReply *makeRequest(const QUrl &url, CardPictureLoaderWorkerWork *workThread);
|
QNetworkReply *makeRequest(const QUrl &url, CardPictureLoaderWorkerWork *workThread);
|
||||||
|
|
||||||
|
/** @brief Processes all queued requests respecting the request quota. */
|
||||||
void processQueuedRequests();
|
void processQueuedRequests();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Processes a single queued request.
|
||||||
|
* @return true if a request was processed, false if queue is empty.
|
||||||
|
*/
|
||||||
bool processSingleRequest();
|
bool processSingleRequest();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handles an image that has finished loading.
|
||||||
|
* @param card The ExactCard that was loaded
|
||||||
|
* @param image The loaded QImage; empty if loading failed
|
||||||
|
*/
|
||||||
void handleImageLoaded(const ExactCard &card, const QImage &image);
|
void handleImageLoaded(const ExactCard &card, const QImage &image);
|
||||||
|
|
||||||
|
/** @brief Caches a redirect mapping between original and redirected URL. */
|
||||||
void cacheRedirect(const QUrl &originalUrl, const QUrl &redirectUrl);
|
void cacheRedirect(const QUrl &originalUrl, const QUrl &redirectUrl);
|
||||||
|
|
||||||
|
/** @brief Removes a URL from the network cache. */
|
||||||
void removedCachedUrl(const QUrl &url);
|
void removedCachedUrl(const QUrl &url);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QThread *pictureLoaderThread;
|
QThread *pictureLoaderThread; ///< Thread for executing worker tasks
|
||||||
QNetworkAccessManager *networkManager;
|
QNetworkAccessManager *networkManager; ///< Network manager for HTTP requests
|
||||||
QNetworkDiskCache *cache;
|
QNetworkDiskCache *cache; ///< Disk cache for downloaded images
|
||||||
QHash<QUrl, QPair<QUrl, QDateTime>> redirectCache; // Stores redirect and timestamp
|
QHash<QUrl, QPair<QUrl, QDateTime>> redirectCache; ///< Maps original URLs to redirects with timestamp
|
||||||
QString cacheFilePath; // Path to persistent storage
|
QString cacheFilePath; ///< Path to persistent redirect cache file
|
||||||
static constexpr int CacheTTLInDays = 30; // TODO: Make user configurable
|
static constexpr int CacheTTLInDays = 30; ///< Time-to-live for redirect cache entries (days)
|
||||||
bool picDownload;
|
bool picDownload; ///< Whether downloading images from network is enabled
|
||||||
QQueue<QPair<QUrl, CardPictureLoaderWorkerWork *>> requestLoadQueue;
|
QQueue<QPair<QUrl, CardPictureLoaderWorkerWork *>> requestLoadQueue; ///< Queue of pending network requests
|
||||||
|
|
||||||
int requestQuota;
|
int requestQuota; ///< Remaining requests allowed per second
|
||||||
QTimer requestTimer; // Timer for refreshing request quota
|
QTimer requestTimer; ///< Timer to reset the request quota
|
||||||
|
|
||||||
CardPictureLoaderLocal *localLoader;
|
CardPictureLoaderLocal *localLoader; ///< Loader for local images
|
||||||
QSet<QString> currentlyLoading; // for deduplication purposes. Contains pixmapCacheKey
|
QSet<QString> currentlyLoading; ///< Deduplication: contains pixmapCacheKey currently being loaded
|
||||||
|
|
||||||
|
/** @brief Returns cached redirect URL for the given original URL, if available. */
|
||||||
QUrl getCachedRedirect(const QUrl &originalUrl) const;
|
QUrl getCachedRedirect(const QUrl &originalUrl) const;
|
||||||
|
|
||||||
|
/** @brief Loads redirect cache from disk. */
|
||||||
void loadRedirectCache();
|
void loadRedirectCache();
|
||||||
|
|
||||||
|
/** @brief Saves redirect cache to disk. */
|
||||||
void saveRedirectCache() const;
|
void saveRedirectCache() const;
|
||||||
|
|
||||||
|
/** @brief Removes stale redirect entries older than TTL. */
|
||||||
void cleanStaleEntries();
|
void cleanStaleEntries();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
/** @brief Resets the request quota for rate-limiting. */
|
||||||
void resetRequestQuota();
|
void resetRequestQuota();
|
||||||
|
|
||||||
|
/** @brief Handles image load requests enqueued on this worker. */
|
||||||
void handleImageLoadEnqueued(const ExactCard &card);
|
void handleImageLoadEnqueued(const ExactCard &card);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
/** @brief Emitted when an image load is enqueued. */
|
||||||
void imageLoadEnqueued(const ExactCard &card);
|
void imageLoadEnqueued(const ExactCard &card);
|
||||||
|
|
||||||
|
/** @brief Emitted when an image has finished loading. */
|
||||||
void imageLoaded(const ExactCard &card, const QImage &image);
|
void imageLoaded(const ExactCard &card, const QImage &image);
|
||||||
|
|
||||||
|
/** @brief Emitted when a request is added to the network queue. */
|
||||||
void imageRequestQueued(const QUrl &url, const ExactCard &card, const QString &setName);
|
void imageRequestQueued(const QUrl &url, const ExactCard &card, const QString &setName);
|
||||||
|
|
||||||
|
/** @brief Emitted when a network request successfully completes. */
|
||||||
void imageRequestSucceeded(const QUrl &url);
|
void imageRequestSucceeded(const QUrl &url);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,10 +51,6 @@ void CardPictureLoaderWorkerWork::startNextPicDownload()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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()
|
void CardPictureLoaderWorkerWork::picDownloadFailed()
|
||||||
{
|
{
|
||||||
/* Take advantage of short-circuiting here to call the nextUrl until one
|
/* Take advantage of short-circuiting here to call the nextUrl until one
|
||||||
|
|
@ -73,10 +69,6 @@ void CardPictureLoaderWorkerWork::picDownloadFailed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param reply The reply. Takes ownership of the object
|
|
||||||
*/
|
|
||||||
void CardPictureLoaderWorkerWork::handleNetworkReply(QNetworkReply *reply)
|
void CardPictureLoaderWorkerWork::handleNetworkReply(QNetworkReply *reply)
|
||||||
{
|
{
|
||||||
QVariant redirectTarget = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
|
QVariant redirectTarget = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
|
||||||
|
|
@ -180,10 +172,6 @@ void CardPictureLoaderWorkerWork::handleSuccessfulReply(QNetworkReply *reply)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @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)
|
QImage CardPictureLoaderWorkerWork::tryLoadImageFromReply(QNetworkReply *reply)
|
||||||
{
|
{
|
||||||
static constexpr int riffHeaderSize = 12; // RIFF_HEADER_SIZE from webp/format_constants.h
|
static constexpr int riffHeaderSize = 12; // RIFF_HEADER_SIZE from webp/format_constants.h
|
||||||
|
|
@ -207,10 +195,6 @@ QImage CardPictureLoaderWorkerWork::tryLoadImageFromReply(QNetworkReply *reply)
|
||||||
return imgReader.read();
|
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)
|
void CardPictureLoaderWorkerWork::concludeImageLoad(const QImage &image)
|
||||||
{
|
{
|
||||||
emit imageLoaded(cardToDownload.getCard(), image);
|
emit imageLoaded(cardToDownload.getCard(), image);
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,3 @@
|
||||||
/**
|
|
||||||
* @file picture_loader_worker_work.h
|
|
||||||
* @ingroup PictureLoader
|
|
||||||
* @brief TODO: Document this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef PICTURE_LOADER_WORKER_WORK_H
|
#ifndef PICTURE_LOADER_WORKER_WORK_H
|
||||||
#define PICTURE_LOADER_WORKER_WORK_H
|
#define PICTURE_LOADER_WORKER_WORK_H
|
||||||
|
|
||||||
|
|
@ -17,55 +11,96 @@
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <libcockatrice/card/database/card_database.h>
|
#include <libcockatrice/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");
|
inline Q_LOGGING_CATEGORY(CardPictureLoaderWorkerWorkLog, "card_picture_loader.worker");
|
||||||
|
|
||||||
class CardPictureLoaderWorker;
|
class CardPictureLoaderWorker;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class CardPictureLoaderWorkerWork
|
||||||
|
* @ingroup PictureLoader
|
||||||
|
* @brief Handles downloading a single card image from network or local sources.
|
||||||
|
*
|
||||||
|
* Responsibilities:
|
||||||
|
* - Try to load images from all possible URLs and sets for a given ExactCard.
|
||||||
|
* - Handle network redirects and cache invalidation.
|
||||||
|
* - Check for blacklisted images and discard them.
|
||||||
|
* - Emit signals when image is successfully loaded or all attempts fail.
|
||||||
|
* - Delete itself after loading completes.
|
||||||
|
*/
|
||||||
class CardPictureLoaderWorkerWork : public QObject
|
class CardPictureLoaderWorkerWork : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Constructs a worker for downloading a specific card image.
|
||||||
|
* @param worker The orchestrating CardPictureLoaderWorker
|
||||||
|
* @param toLoad The ExactCard to download
|
||||||
|
*/
|
||||||
explicit CardPictureLoaderWorkerWork(const CardPictureLoaderWorker *worker, const ExactCard &toLoad);
|
explicit CardPictureLoaderWorkerWork(const CardPictureLoaderWorker *worker, const ExactCard &toLoad);
|
||||||
|
|
||||||
CardPictureToLoad cardToDownload;
|
CardPictureToLoad cardToDownload; ///< The card and associated URLs to try downloading
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
/**
|
||||||
|
* @brief Handles a finished network reply for the card image.
|
||||||
|
* @param reply The QNetworkReply object to process. Ownership is transferred.
|
||||||
|
*/
|
||||||
void handleNetworkReply(QNetworkReply *reply);
|
void handleNetworkReply(QNetworkReply *reply);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool picDownload;
|
bool picDownload; ///< Whether network downloading is enabled
|
||||||
|
|
||||||
|
/** @brief Starts downloading the next URL for this card. */
|
||||||
void startNextPicDownload();
|
void startNextPicDownload();
|
||||||
|
|
||||||
|
/** @brief Called when all URLs have been exhausted or download failed. */
|
||||||
void picDownloadFailed();
|
void picDownloadFailed();
|
||||||
|
|
||||||
|
/** @brief Processes a failed network reply. */
|
||||||
void handleFailedReply(const QNetworkReply *reply);
|
void handleFailedReply(const QNetworkReply *reply);
|
||||||
|
|
||||||
|
/** @brief Processes a successful network reply. */
|
||||||
void handleSuccessfulReply(QNetworkReply *reply);
|
void handleSuccessfulReply(QNetworkReply *reply);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Attempts to read an image from a network reply.
|
||||||
|
* @param reply The network reply
|
||||||
|
* @return The loaded QImage or an empty image if reading failed
|
||||||
|
*/
|
||||||
QImage tryLoadImageFromReply(QNetworkReply *reply);
|
QImage tryLoadImageFromReply(QNetworkReply *reply);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Finalizes the image loading process.
|
||||||
|
* @param image The loaded image (empty if failed)
|
||||||
|
*
|
||||||
|
* Emits imageLoaded() and deletes this object.
|
||||||
|
*/
|
||||||
void concludeImageLoad(const QImage &image);
|
void concludeImageLoad(const QImage &image);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
/** @brief Updates the picDownload setting when it changes. */
|
||||||
void picDownloadChanged();
|
void picDownloadChanged();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
/**
|
/**
|
||||||
* Emitted when this worker has successfully loaded the image or has exhausted all attempts at loading the image.
|
* @brief Emitted when the image has been loaded or all attempts failed.
|
||||||
* Failures are represented by an empty QImage.
|
* @param card The card corresponding to the image
|
||||||
* Note that this object will delete itself as this signal is emitted.
|
* @param image The loaded image (empty if failed)
|
||||||
|
*
|
||||||
|
* The worker deletes itself after emitting this signal.
|
||||||
*/
|
*/
|
||||||
void imageLoaded(const ExactCard &card, const QImage &image);
|
void imageLoaded(const ExactCard &card, const QImage &image);
|
||||||
|
|
||||||
/**
|
/** @brief Emitted when a network request completes successfully. */
|
||||||
* Emitted when a request did not return a 400 or 500 response
|
|
||||||
*/
|
|
||||||
void requestSucceeded(const QUrl &url);
|
void requestSucceeded(const QUrl &url);
|
||||||
|
|
||||||
|
/** @brief Request that a URL be downloaded. */
|
||||||
void requestImageDownload(const QUrl &url, CardPictureLoaderWorkerWork *instance);
|
void requestImageDownload(const QUrl &url, CardPictureLoaderWorkerWork *instance);
|
||||||
|
|
||||||
|
/** @brief Emitted when a URL has been redirected. */
|
||||||
void urlRedirected(const QUrl &originalUrl, const QUrl &redirectUrl);
|
void urlRedirected(const QUrl &originalUrl, const QUrl &redirectUrl);
|
||||||
|
|
||||||
|
/** @brief Emitted when a cached URL is invalid and must be removed. */
|
||||||
void cachedUrlInvalidated(const QUrl &url);
|
void cachedUrlInvalidated(const QUrl &url);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,12 +20,6 @@ CardPictureToLoad::CardPictureToLoad(const ExactCard &_card)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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> CardPictureToLoad::extractSetsSorted(const ExactCard &card)
|
||||||
{
|
{
|
||||||
QList<CardSetPtr> sortedSets;
|
QList<CardSetPtr> sortedSets;
|
||||||
|
|
@ -109,11 +103,6 @@ void CardPictureToLoad::populateSetUrls()
|
||||||
(void)nextUrl();
|
(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()
|
bool CardPictureToLoad::nextSet()
|
||||||
{
|
{
|
||||||
if (!sortedSets.isEmpty()) {
|
if (!sortedSets.isEmpty()) {
|
||||||
|
|
@ -125,11 +114,6 @@ bool CardPictureToLoad::nextSet()
|
||||||
return false;
|
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()
|
bool CardPictureToLoad::nextUrl()
|
||||||
{
|
{
|
||||||
if (!currentSetUrls.isEmpty()) {
|
if (!currentSetUrls.isEmpty()) {
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,3 @@
|
||||||
/**
|
|
||||||
* @file card_picture_to_load.h
|
|
||||||
* @ingroup PictureLoader
|
|
||||||
* @brief TODO: Document this.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef PICTURE_TO_LOAD_H
|
#ifndef PICTURE_TO_LOAD_H
|
||||||
#define PICTURE_TO_LOAD_H
|
#define PICTURE_TO_LOAD_H
|
||||||
|
|
||||||
|
|
@ -12,37 +6,97 @@
|
||||||
|
|
||||||
inline Q_LOGGING_CATEGORY(CardPictureToLoadLog, "card_picture_loader.picture_to_load");
|
inline Q_LOGGING_CATEGORY(CardPictureToLoadLog, "card_picture_loader.picture_to_load");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class CardPictureToLoad
|
||||||
|
* @ingroup PictureLoader
|
||||||
|
* @brief Manages all URLs and sets for downloading a specific card image.
|
||||||
|
*
|
||||||
|
* Responsibilities:
|
||||||
|
* - Maintains a sorted list of sets for a card.
|
||||||
|
* - Generates URLs to download images from, including custom URLs and URL templates.
|
||||||
|
* - Tracks which URL and set is currently being attempted.
|
||||||
|
* - Provides helper methods to advance to next URL or set.
|
||||||
|
*/
|
||||||
class CardPictureToLoad
|
class CardPictureToLoad
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
ExactCard card;
|
ExactCard card; ///< The ExactCard being downloaded
|
||||||
QList<CardSetPtr> sortedSets;
|
QList<CardSetPtr> sortedSets; ///< All sets for this card, sorted by priority
|
||||||
QList<QString> urlTemplates;
|
QList<QString> urlTemplates; ///< URL templates from settings
|
||||||
QList<QString> currentSetUrls;
|
QList<QString> currentSetUrls; ///< URLs for the current set being attempted
|
||||||
QString currentUrl;
|
QString currentUrl; ///< Currently active URL to download
|
||||||
CardSetPtr currentSet;
|
CardSetPtr currentSet; ///< Currently active set
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Constructs a CardPictureToLoad for a given ExactCard.
|
||||||
|
* @param _card The card to download
|
||||||
|
*
|
||||||
|
* Initializes URL templates and pre-populates the first set URLs.
|
||||||
|
*/
|
||||||
explicit CardPictureToLoad(const ExactCard &_card);
|
explicit CardPictureToLoad(const ExactCard &_card);
|
||||||
|
|
||||||
|
/** @return The card being loaded. */
|
||||||
const ExactCard &getCard() const
|
const ExactCard &getCard() const
|
||||||
{
|
{
|
||||||
return card;
|
return card;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return The current URL being attempted. */
|
||||||
QString getCurrentUrl() const
|
QString getCurrentUrl() const
|
||||||
{
|
{
|
||||||
return currentUrl;
|
return currentUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return The current set being attempted. */
|
||||||
CardSetPtr getCurrentSet() const
|
CardSetPtr getCurrentSet() const
|
||||||
{
|
{
|
||||||
return currentSet;
|
return currentSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return The short name of the current set, or empty string if no set. */
|
||||||
QString getSetName() const;
|
QString getSetName() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Transforms a URL template into a concrete URL for this card/set.
|
||||||
|
* @param urlTemplate The URL template to transform
|
||||||
|
* @return The transformed URL or empty string if the template cannot be fulfilled
|
||||||
|
*/
|
||||||
QString transformUrl(const QString &urlTemplate) const;
|
QString transformUrl(const QString &urlTemplate) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Advance to the next set in the list.
|
||||||
|
* @return True if a next set exists and was selected, false if at the end.
|
||||||
|
*
|
||||||
|
* Updates currentSet and repopulates currentSetUrls.
|
||||||
|
* If we are already at the end of the list, then currentSet is set to empty.
|
||||||
|
*/
|
||||||
bool nextSet();
|
bool nextSet();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Advance to the next URL in the current set's list.
|
||||||
|
* @return True if a next URL exists, false if at the end.
|
||||||
|
*
|
||||||
|
* Updates currentUrl.
|
||||||
|
* If we are already at the end of the list, then currentUrl is set to empty.
|
||||||
|
*/
|
||||||
bool nextUrl();
|
bool nextUrl();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Populates the currentSetUrls list with URLs for the current set.
|
||||||
|
*
|
||||||
|
* Includes custom URLs first, followed by template-based URLs.
|
||||||
|
*/
|
||||||
void populateSetUrls();
|
void populateSetUrls();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Extract all sets from the card and sort them by priority.
|
||||||
|
* @param card The card to extract sets from
|
||||||
|
* @return A non-empty list of CardSetPtr, sorted by priority
|
||||||
|
*
|
||||||
|
* If the card has no sets, a dummy set is inserted. Also ensures
|
||||||
|
* the printing corresponding to the ExactCard is first in the list.
|
||||||
|
*/
|
||||||
static QList<CardSetPtr> extractSetsSorted(const ExactCard &card);
|
static QList<CardSetPtr> extractSetsSorted(const ExactCard &card);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue