* PictureLoader: Replace downloadedPics cache with QNetworkCache Currently when the "Download card pictures on the fly" option is enabled, Cockatrice stores downloaded pictures into a downloadedPics sub-folder, keyed on set and card name. If a picture is found in that folder, we never try to download a picture for that card ever again (until it is reprinted in a more recent set, I guess). This has the unfortunate consequence that if you change the URLs for downloading card images, the changes are not applied to cards that already have their picture downloaded. In particular, if you use localized card pictures (through !sflang!), you get a mix of cards in different languages depending on the currently configured language at the time each card was downloaded. This patch removes that mechanism in favor of setting a QNetworkDiskCache on the QNetworkAccessManager used by the PictureLoader to download pictures. The QNetworkDiskCache caches the picture keyed on their URL: if the URL changes, a new request will be made. In particular, if you use picture URLs with !sflang! and change the language, pictures for the current language will be downloaded even for cards that already have a picture. The QNetworkDiskCache is configured with a maximum size of 4GB, which should be enough to hold one high-quality JPEG for each M:TG card in existence. Note that this does not affect the existing mechanism for defining custom card art, either through the CUSTOM directory or the set-based one. Cockatrice will still read existing cards in the downloadedPics directory as before, it will just no longer write into that directory (since pictures are cached by the QNetworkDiskCache instead). To fully switch to the new cache, users should use the "Delete Downloaded Images" button in the settings: it will clear the QNetworkDiskCache but also remove the downloadedPics directory. * Do not use system cache dir for portable installs * Add settings for network cache size * Delete corrupted cache entries * Use old-style connect() syntax (Qt5 build failure) * Add setNetworkCacheSizeInMB to test mocks * setTransferTimeout was added in Qt 5.15 * Improve logging messages We now have the following messages - "Trying to download picture from url: URL" before loading a picture when picture download is enabled - "Trying to load picture from cache: URL" before loading a picture when picture download is disabled (i.e. cache-only offline mode) - "Removing corrupted cache file for url URL and retrying (ERR)" when when we fail to load a picture from the cache. Usually, this should be due to the timeout, in which case ERR will be "Operation Canceled". - "Download failed for url URL (ERR)" when there was an error downloading a picture from the network (ERR is the error message) - "Following redirect to URL" and "Following cached redirect to URL" when following a redirect (from network/from cache) - "Image successfully downloaded from URL" and "Image successfully loaded from cached url at URL" on success - "Possible cached/downloaded picture at URL could not be loaded" on ImageReader error * Clarify that network cache is on disk Also migrate "Delete Downloaded Image" to a "Clear" button right next to the network cache size. * Remove qPrintable * Move pixmap cache settings to card sources * qDebug().nospace() * some formatting on debug messages * format * inverted condition --------- Co-authored-by: ebbit1q <ebbit1q@gmail.com>
298 lines
7.6 KiB
C++
298 lines
7.6 KiB
C++
#ifndef DLG_SETTINGS_H
|
|
#define DLG_SETTINGS_H
|
|
|
|
#include <QCheckBox>
|
|
#include <QComboBox>
|
|
#include <QDialog>
|
|
#include <QGroupBox>
|
|
#include <QLabel>
|
|
#include <QPushButton>
|
|
#include <QSpinBox>
|
|
|
|
class CardDatabase;
|
|
class QCloseEvent;
|
|
class QGridLayout;
|
|
class QHBoxLayout;
|
|
class QLineEdit;
|
|
class QListWidget;
|
|
class QListWidgetItem;
|
|
class QRadioButton;
|
|
class QSlider;
|
|
class QStackedWidget;
|
|
class QTreeWidget;
|
|
class QTreeWidgetItem;
|
|
class QVBoxLayout;
|
|
class SequenceEdit;
|
|
|
|
class AbstractSettingsPage : public QWidget
|
|
{
|
|
public:
|
|
virtual void retranslateUi() = 0;
|
|
};
|
|
|
|
class GeneralSettingsPage : public AbstractSettingsPage
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
GeneralSettingsPage();
|
|
void retranslateUi() override;
|
|
|
|
private slots:
|
|
void deckPathButtonClicked();
|
|
void replaysPathButtonClicked();
|
|
void picsPathButtonClicked();
|
|
void cardDatabasePathButtonClicked();
|
|
void customCardDatabaseButtonClicked();
|
|
void tokenDatabasePathButtonClicked();
|
|
void resetAllPathsClicked();
|
|
void languageBoxChanged(int index);
|
|
|
|
private:
|
|
QStringList findQmFiles();
|
|
QString languageName(const QString &lang);
|
|
QLineEdit *deckPathEdit;
|
|
QLineEdit *replaysPathEdit;
|
|
QLineEdit *picsPathEdit;
|
|
QLineEdit *cardDatabasePathEdit;
|
|
QLineEdit *customCardDatabasePathEdit;
|
|
QLineEdit *tokenDatabasePathEdit;
|
|
QPushButton *resetAllPathsButton;
|
|
QLabel *allPathsResetLabel;
|
|
QGroupBox *personalGroupBox;
|
|
QGroupBox *pathsGroupBox;
|
|
QComboBox languageBox;
|
|
QCheckBox updateNotificationCheckBox;
|
|
QCheckBox newVersionOracleCheckBox;
|
|
QComboBox updateReleaseChannelBox;
|
|
QLabel languageLabel;
|
|
QLabel deckPathLabel;
|
|
QLabel replaysPathLabel;
|
|
QLabel picsPathLabel;
|
|
QLabel cardDatabasePathLabel;
|
|
QLabel customCardDatabasePathLabel;
|
|
QLabel tokenDatabasePathLabel;
|
|
QLabel updateReleaseChannelLabel;
|
|
QCheckBox showTipsOnStartup;
|
|
};
|
|
|
|
class AppearanceSettingsPage : public AbstractSettingsPage
|
|
{
|
|
Q_OBJECT
|
|
private slots:
|
|
void themeBoxChanged(int index);
|
|
void openThemeLocation();
|
|
|
|
private:
|
|
QLabel themeLabel;
|
|
QComboBox themeBox;
|
|
QPushButton openThemeButton;
|
|
QLabel minPlayersForMultiColumnLayoutLabel;
|
|
QLabel maxFontSizeForCardsLabel;
|
|
QCheckBox displayCardNamesCheckBox;
|
|
QCheckBox cardScalingCheckBox;
|
|
QCheckBox horizontalHandCheckBox;
|
|
QCheckBox leftJustifiedHandCheckBox;
|
|
QCheckBox invertVerticalCoordinateCheckBox;
|
|
QGroupBox *themeGroupBox;
|
|
QGroupBox *cardsGroupBox;
|
|
QGroupBox *handGroupBox;
|
|
QGroupBox *tableGroupBox;
|
|
QSpinBox minPlayersForMultiColumnLayoutEdit;
|
|
QSpinBox maxFontSizeForCardsEdit;
|
|
|
|
public:
|
|
AppearanceSettingsPage();
|
|
void retranslateUi() override;
|
|
};
|
|
|
|
class UserInterfaceSettingsPage : public AbstractSettingsPage
|
|
{
|
|
Q_OBJECT
|
|
private slots:
|
|
void setNotificationEnabled(int);
|
|
|
|
private:
|
|
QCheckBox notificationsEnabledCheckBox;
|
|
QCheckBox specNotificationsEnabledCheckBox;
|
|
QCheckBox buddyConnectNotificationsEnabledCheckBox;
|
|
QCheckBox doubleClickToPlayCheckBox;
|
|
QCheckBox playToStackCheckBox;
|
|
QCheckBox annotateTokensCheckBox;
|
|
QCheckBox useTearOffMenusCheckBox;
|
|
QCheckBox tapAnimationCheckBox;
|
|
QGroupBox *generalGroupBox;
|
|
QGroupBox *notificationsGroupBox;
|
|
QGroupBox *animationGroupBox;
|
|
|
|
public:
|
|
UserInterfaceSettingsPage();
|
|
void retranslateUi() override;
|
|
};
|
|
|
|
class DeckEditorSettingsPage : public AbstractSettingsPage
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
DeckEditorSettingsPage();
|
|
void retranslateUi() override;
|
|
QString getLastUpdateTime();
|
|
|
|
private slots:
|
|
void storeSettings();
|
|
void urlListChanged(const QModelIndex &, int, int, const QModelIndex &, int);
|
|
void setSpoilersEnabled(bool);
|
|
void spoilerPathButtonClicked();
|
|
void updateSpoilers();
|
|
void unlockSettings();
|
|
void actAddURL();
|
|
void actRemoveURL();
|
|
void actEditURL();
|
|
void clearDownloadedPicsButtonClicked();
|
|
void resetDownloadedURLsButtonClicked();
|
|
|
|
private:
|
|
QPushButton clearDownloadedPicsButton;
|
|
QPushButton resetDownloadURLs;
|
|
QLabel urlLinkLabel;
|
|
QCheckBox picDownloadCheckBox;
|
|
QListWidget *urlList;
|
|
QCheckBox mcDownloadSpoilersCheckBox;
|
|
QLabel msDownloadSpoilersLabel;
|
|
QGroupBox *mpGeneralGroupBox;
|
|
QGroupBox *mpSpoilerGroupBox;
|
|
QLineEdit *mpSpoilerSavePathLineEdit;
|
|
QLabel mcSpoilerSaveLabel;
|
|
QLabel lastUpdatedLabel;
|
|
QLabel infoOnSpoilersLabel;
|
|
QPushButton *mpSpoilerPathButton;
|
|
QPushButton *updateNowButton;
|
|
QLabel networkCacheLabel;
|
|
QSpinBox networkCacheEdit;
|
|
QSpinBox pixmapCacheEdit;
|
|
QLabel pixmapCacheLabel;
|
|
};
|
|
|
|
class MessagesSettingsPage : public AbstractSettingsPage
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
MessagesSettingsPage();
|
|
void retranslateUi() override;
|
|
|
|
private slots:
|
|
void actAdd();
|
|
void actEdit();
|
|
void actRemove();
|
|
void updateColor(const QString &value);
|
|
void updateHighlightColor(const QString &value);
|
|
void updateTextColor(int value);
|
|
void updateTextHighlightColor(int value);
|
|
|
|
private:
|
|
QListWidget *messageList;
|
|
QAction *aAdd;
|
|
QAction *aEdit;
|
|
QAction *aRemove;
|
|
QCheckBox chatMentionCheckBox;
|
|
QCheckBox chatMentionCompleterCheckbox;
|
|
QCheckBox invertMentionForeground;
|
|
QCheckBox invertHighlightForeground;
|
|
QCheckBox ignoreUnregUsersMainChat;
|
|
QCheckBox ignoreUnregUserMessages;
|
|
QCheckBox messagePopups;
|
|
QCheckBox mentionPopups;
|
|
QCheckBox roomHistory;
|
|
QGroupBox *chatGroupBox;
|
|
QGroupBox *highlightGroupBox;
|
|
QGroupBox *messageGroupBox;
|
|
QLineEdit *mentionColor;
|
|
QLineEdit *highlightColor;
|
|
QLineEdit *customAlertString;
|
|
QLabel hexLabel;
|
|
QLabel hexHighlightLabel;
|
|
QLabel customAlertStringLabel;
|
|
QLabel explainMessagesLabel;
|
|
|
|
void storeSettings();
|
|
void updateMentionPreview();
|
|
void updateHighlightPreview();
|
|
};
|
|
|
|
class SoundSettingsPage : public AbstractSettingsPage
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
SoundSettingsPage();
|
|
void retranslateUi() override;
|
|
|
|
private:
|
|
QLabel themeLabel;
|
|
QComboBox themeBox;
|
|
QGroupBox *soundGroupBox;
|
|
QPushButton soundTestButton;
|
|
QCheckBox soundEnabledCheckBox;
|
|
QLabel masterVolumeLabel;
|
|
QSlider *masterVolumeSlider;
|
|
QSpinBox *masterVolumeSpinBox;
|
|
|
|
private slots:
|
|
void masterVolumeChanged(int value);
|
|
void themeBoxChanged(int index);
|
|
};
|
|
|
|
class ShortcutSettingsPage : public AbstractSettingsPage
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
ShortcutSettingsPage();
|
|
void retranslateUi() override;
|
|
|
|
private:
|
|
QTreeWidget *shortcutsTable;
|
|
QVBoxLayout *mainLayout;
|
|
QHBoxLayout *buttonsLayout;
|
|
QGroupBox *editShortcutGroupBox;
|
|
QGridLayout *editLayout;
|
|
QLabel *currentActionGroupLabel;
|
|
QLabel *currentActionGroupName;
|
|
QLabel *currentActionLabel;
|
|
QLabel *currentActionName;
|
|
QLabel *currentShortcutLabel;
|
|
SequenceEdit *editTextBox;
|
|
QLabel *faqLabel;
|
|
QPushButton *btnResetAll;
|
|
QPushButton *btnClearAll;
|
|
|
|
private slots:
|
|
void resetShortcuts();
|
|
void refreshShortcuts();
|
|
void createShortcuts();
|
|
void clearShortcuts();
|
|
void currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous);
|
|
};
|
|
|
|
class DlgSettings : public QDialog
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
explicit DlgSettings(QWidget *parent = nullptr);
|
|
void setTab(int index);
|
|
|
|
private slots:
|
|
void changePage(QListWidgetItem *current, QListWidgetItem *previous);
|
|
void updateLanguage();
|
|
|
|
private:
|
|
QListWidget *contentsWidget;
|
|
QStackedWidget *pagesWidget;
|
|
QListWidgetItem *generalButton, *appearanceButton, *userInterfaceButton, *deckEditorButton, *messagesButton,
|
|
*soundButton, *shortcutsButton;
|
|
void createIcons();
|
|
void retranslateUi();
|
|
|
|
protected:
|
|
void changeEvent(QEvent *event) override;
|
|
void closeEvent(QCloseEvent *event) override;
|
|
};
|
|
|
|
#endif
|