Give people options from a dropdown.

Took 1 hour 6 minutes

Took 3 seconds
This commit is contained in:
Lukas Brübach 2026-04-12 08:19:41 +02:00
parent 64885f4c20
commit 37cb86f16a
7 changed files with 173 additions and 47 deletions

View file

@ -1,5 +1,6 @@
#include "cache_settings.h" #include "cache_settings.h"
#include "../../interface/card_picture_loader/card_picture_loader_local_schemes.h"
#include "../network/update/client/release_channel.h" #include "../network/update/client/release_channel.h"
#include "card_counter_settings.h" #include "card_counter_settings.h"
#include "version_string.h" #include "version_string.h"
@ -266,7 +267,10 @@ SettingsCache::SettingsCache()
redirectCacheTtl = settings->value("personal/redirectCacheTtl", NETWORK_REDIRECT_CACHE_TTL_DEFAULT).toInt(); redirectCacheTtl = settings->value("personal/redirectCacheTtl", NETWORK_REDIRECT_CACHE_TTL_DEFAULT).toInt();
saveCardImagesToLocalStorage = settings->value("personal/saveCardImagesToLocalStorage", true).toBool(); saveCardImagesToLocalStorage = settings->value("personal/saveCardImagesToLocalStorage", true).toBool();
localCardImageStorageNamingScheme = localCardImageStorageNamingScheme =
settings->value("personal/localCardImageStorageNamingScheme", "{set}/{name}_{collector}_{uuid}.png").toString(); settings
->value("personal/localCardImageStorageNamingScheme",
static_cast<int>(CardPictureLoaderLocalSchemes::NamingScheme::Set_Folder_Name_ProviderId))
.toInt();
picDownload = settings->value("personal/picturedownload", true).toBool(); picDownload = settings->value("personal/picturedownload", true).toBool();
showStatusBar = settings->value("personal/showStatusBar", false).toBool(); showStatusBar = settings->value("personal/showStatusBar", false).toBool();
@ -1121,9 +1125,10 @@ void SettingsCache::setSaveCardImagesToLocalStorage(QT_STATE_CHANGED_T _saveCard
emit saveCardImagesToLocalStorageChanged(saveCardImagesToLocalStorage); emit saveCardImagesToLocalStorageChanged(saveCardImagesToLocalStorage);
} }
void SettingsCache::setLocalCardImageStorageNamingScheme(const QString _localCardImageStorageNamingScheme) void SettingsCache::setLocalCardImageStorageNamingScheme(
const CardPictureLoaderLocalSchemes::NamingScheme _localCardImageStorageNamingScheme)
{ {
localCardImageStorageNamingScheme = _localCardImageStorageNamingScheme; localCardImageStorageNamingScheme = static_cast<int>(_localCardImageStorageNamingScheme);
settings->setValue("personal/localCardImageStorageNamingScheme", localCardImageStorageNamingScheme); settings->setValue("personal/localCardImageStorageNamingScheme", localCardImageStorageNamingScheme);
emit localCardImageStorageNamingSchemeChanged(localCardImageStorageNamingScheme); emit localCardImageStorageNamingSchemeChanged(localCardImageStorageNamingScheme);
} }

View file

@ -7,6 +7,7 @@
#ifndef SETTINGSCACHE_H #ifndef SETTINGSCACHE_H
#define SETTINGSCACHE_H #define SETTINGSCACHE_H
#include "../../interface/card_picture_loader/card_picture_loader_local_schemes.h"
#include "shortcuts_settings.h" #include "shortcuts_settings.h"
#include <QDate> #include <QDate>
@ -185,7 +186,7 @@ signals:
void networkCacheSizeChanged(int newSizeInMBs); void networkCacheSizeChanged(int newSizeInMBs);
void redirectCacheTtlChanged(int newTtl); void redirectCacheTtlChanged(int newTtl);
void saveCardImagesToLocalStorageChanged(bool saveCardImagesToLocalStorage); void saveCardImagesToLocalStorageChanged(bool saveCardImagesToLocalStorage);
void localCardImageStorageNamingSchemeChanged(QString localCardImageStorageNamingScheme); void localCardImageStorageNamingSchemeChanged(int localCardImageStorageNamingScheme);
void masterVolumeChanged(int value); void masterVolumeChanged(int value);
void chatMentionCompleterChanged(); void chatMentionCompleterChanged();
void downloadSpoilerTimeIndexChanged(); void downloadSpoilerTimeIndexChanged();
@ -305,7 +306,7 @@ private:
int networkCacheSize; int networkCacheSize;
int redirectCacheTtl; int redirectCacheTtl;
bool saveCardImagesToLocalStorage; bool saveCardImagesToLocalStorage;
QString localCardImageStorageNamingScheme; int localCardImageStorageNamingScheme;
bool scaleCards; bool scaleCards;
int verticalCardOverlapPercent; int verticalCardOverlapPercent;
bool showMessagePopups; bool showMessagePopups;
@ -797,9 +798,9 @@ public:
{ {
return saveCardImagesToLocalStorage; return saveCardImagesToLocalStorage;
} }
[[nodiscard]] QString getLocalCardImageStorageNamingScheme() const [[nodiscard]] CardPictureLoaderLocalSchemes::NamingScheme getLocalCardImageStorageNamingScheme() const
{ {
return localCardImageStorageNamingScheme; return static_cast<CardPictureLoaderLocalSchemes::NamingScheme>(localCardImageStorageNamingScheme);
} }
[[nodiscard]] bool getScaleCards() const [[nodiscard]] bool getScaleCards() const
{ {
@ -1108,7 +1109,8 @@ public slots:
void setNetworkCacheSizeInMB(const int _networkCacheSize); void setNetworkCacheSizeInMB(const int _networkCacheSize);
void setNetworkRedirectCacheTtl(const int _redirectCacheTtl); void setNetworkRedirectCacheTtl(const int _redirectCacheTtl);
void setSaveCardImagesToLocalStorage(QT_STATE_CHANGED_T _saveCardImagesToLocalStorage); void setSaveCardImagesToLocalStorage(QT_STATE_CHANGED_T _saveCardImagesToLocalStorage);
void setLocalCardImageStorageNamingScheme(const QString _localCardImageStorageNamingScheme); void setLocalCardImageStorageNamingScheme(
const CardPictureLoaderLocalSchemes::NamingScheme _localCardImageStorageNamingScheme);
void setCardScaling(const QT_STATE_CHANGED_T _scaleCards); void setCardScaling(const QT_STATE_CHANGED_T _scaleCards);
void setStackCardOverlapPercent(const int _verticalCardOverlapPercent); void setStackCardOverlapPercent(const int _verticalCardOverlapPercent);
void setShowMessagePopups(const QT_STATE_CHANGED_T _showMessagePopups); void setShowMessagePopups(const QT_STATE_CHANGED_T _showMessagePopups);

View file

@ -189,9 +189,19 @@ void CardPictureLoader::saveCardImageToLocalStorage(const ExactCard &card, const
} }
const QString picsRoot = SettingsCache::instance().getPicsPath(); const QString picsRoot = SettingsCache::instance().getPicsPath();
const QString scheme = SettingsCache::instance().getLocalCardImageStorageNamingScheme(); CardPictureLoaderLocalSchemes::NamingScheme scheme =
SettingsCache::instance().getLocalCardImageStorageNamingScheme();
if (picsRoot.isEmpty() || scheme.isEmpty()) { QString pattern;
for (const auto &s : CardPictureLoaderLocalSchemes::exportSchemes()) {
if (s.id == scheme) {
pattern = s.pattern;
break;
}
}
if (picsRoot.isEmpty() || pattern.isEmpty()) {
return; return;
} }
@ -217,18 +227,26 @@ void CardPictureLoader::saveCardImageToLocalStorage(const ExactCard &card, const
} }
// Build path from scheme // Build path from scheme
QString relativePath = scheme; QString relativePath =
CardPictureLoaderLocalSchemes::expandPattern(pattern, cardName, setName, collectorNumber, uuid);
relativePath.replace("{name}", cardName); if (relativePath.isEmpty()) {
relativePath.replace("{set}", setName); return;
relativePath.replace("{collector}", collectorNumber); }
relativePath.replace("{uuid}", uuid);
relativePath.replace("{ext}", "png"); // append extension
relativePath += ".png";
// Normalize slashes // Normalize slashes
relativePath = QDir::cleanPath(relativePath); relativePath = QDir::cleanPath(relativePath);
QFileInfo outInfo(baseDir.filePath(relativePath)); QFileInfo outInfo(baseDir.filePath(relativePath));
// Do not overwrite existing files
if (outInfo.exists()) {
return;
}
QDir outDir = outInfo.dir(); QDir outDir = outInfo.dir();
// Ensure directory exists // Ensure directory exists
@ -239,11 +257,6 @@ void CardPictureLoader::saveCardImageToLocalStorage(const ExactCard &card, const
} }
} }
// Do not overwrite existing files
if (outInfo.exists()) {
return;
}
// Save image // Save image
QImage image = pixmap.toImage(); QImage image = pixmap.toImage();
if (!image.save(outInfo.absoluteFilePath(), "PNG")) { if (!image.save(outInfo.absoluteFilePath(), "PNG")) {

View file

@ -1,6 +1,7 @@
#include "card_picture_loader_local.h" #include "card_picture_loader_local.h"
#include "../../client/settings/cache_settings.h" #include "../../client/settings/cache_settings.h"
#include "card_picture_loader_local_schemes.h"
#include "card_picture_to_load.h" #include "card_picture_to_load.h"
#include <QDirIterator> #include <QDirIterator>
@ -77,26 +78,8 @@ QImage CardPictureLoaderLocal::tryLoadCardImageFromDisk(const QString &setName,
imgReader.setDecideFormatFromContent(true); imgReader.setDecideFormatFromContent(true);
// Most-to-least specific, these will fall through in order. // Most-to-least specific, these will fall through in order.
QStringList nameVariants; QStringList nameVariants =
CardPictureLoaderLocalSchemes::generateImportVariants(correctedCardName, setName, collectorNumber, providerId);
// 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) { for (const QString &nameVariant : nameVariants) {
if (nameVariant.isEmpty()) { if (nameVariant.isEmpty()) {

View file

@ -0,0 +1,109 @@
#ifndef COCKATRICE_CARD_PICTURE_LOADER_LOCAL_SCHEMES_H
#define COCKATRICE_CARD_PICTURE_LOADER_LOCAL_SCHEMES_H
#include <QList>
#include <QRegularExpression>
#include <QString>
#include <QStringList>
namespace CardPictureLoaderLocalSchemes
{
enum class NamingScheme
{
NameOnly,
Name_Set,
Name_Set_Collector,
Set_Collector_Name,
Name_ProviderId,
Set_Folder_Name_ProviderId,
Set_Folder_Name_Set_Collector
};
struct NamingSchemeInfo
{
NamingScheme id;
QString displayName;
QString pattern;
};
inline const QList<NamingSchemeInfo> &importSchemes()
{
static QList<NamingSchemeInfo> list = {
{NamingScheme::Name_ProviderId, "Card Name + Provider ID", "{name}_{providerId}"},
{NamingScheme::Name_Set_Collector, "Card Name + Set + Collector", "{name}_{set}_{collector}"},
{NamingScheme::Set_Collector_Name, "Set + Collector + Card Name", "{set}_{collector}_{name}"},
{NamingScheme::Name_Set, "Card Name + Set", "{name}_{set}"},
{NamingScheme::NameOnly, "Card Name", "{name}"},
};
return list;
}
inline const QList<NamingSchemeInfo> &exportSchemes()
{
static QList<NamingSchemeInfo> list = {
{NamingScheme::Set_Folder_Name_ProviderId, "Set Folder / Name + Provider ID", "{set}/{name}_{providerId}"},
{NamingScheme::Set_Folder_Name_Set_Collector, "Set Folder / Name + Set Name + Collector",
"{set}/{name}_{set}_{collector}"},
{NamingScheme::Name_ProviderId, "Card Name + Provider ID", "{name}_{providerId}"},
{NamingScheme::Name_Set_Collector, "Card Name + Set + Collector", "{name}_{set}_{collector}"},
{NamingScheme::Set_Collector_Name, "Set + Collector + Card Name", "{set}_{collector}_{name}"},
};
return list;
}
inline QString expandPattern(const QString &pattern,
const QString &name,
const QString &set,
const QString &collector,
const QString &providerId)
{
QString result = pattern;
auto replaceIfPresent = [&](const QString &token, const QString &value) -> bool {
if (!result.contains(token))
return true;
if (value.isEmpty())
return false;
result.replace(token, value);
return true;
};
if (!replaceIfPresent("{name}", name))
return {};
if (!replaceIfPresent("{set}", set))
return {};
if (!replaceIfPresent("{collector}", collector))
return {};
if (!replaceIfPresent("{providerId}", providerId))
return {};
return result;
}
inline QStringList
generateImportVariants(const QString &name, const QString &set, const QString &collector, const QString &providerId)
{
QStringList variants;
const QStringList separators = {"_", "-"};
for (const auto &scheme : importSchemes()) {
for (const QString &sep : separators) {
QString pattern = scheme.pattern;
pattern.replace("_", sep);
QString v = expandPattern(pattern, name, set, collector, providerId);
if (!v.isEmpty())
variants << v;
}
}
return variants;
}
} // namespace CardPictureLoaderLocalSchemes
#endif // COCKATRICE_CARD_PICTURE_LOADER_LOCAL_SCHEMES_H

View file

@ -1079,10 +1079,24 @@ DeckEditorSettingsPage::DeckEditorSettingsPage()
connect(&saveCardImagesToLocalStorageCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), connect(&saveCardImagesToLocalStorageCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(),
&SettingsCache::setSaveCardImagesToLocalStorage); &SettingsCache::setSaveCardImagesToLocalStorage);
localCardImageStorageNamingSchemeLineEdit = localCardImageStorageNamingSchemeComboBox = new QComboBox;
new QLineEdit(SettingsCache::instance().getLocalCardImageStorageNamingScheme()); for (const auto &scheme : CardPictureLoaderLocalSchemes::exportSchemes()) {
connect(localCardImageStorageNamingSchemeLineEdit, &QLineEdit::textChanged, &SettingsCache::instance(), localCardImageStorageNamingSchemeComboBox->addItem(scheme.displayName, static_cast<int>(scheme.id));
&SettingsCache::setLocalCardImageStorageNamingScheme); }
int current = static_cast<int>(SettingsCache::instance().getLocalCardImageStorageNamingScheme());
int index = localCardImageStorageNamingSchemeComboBox->findData(current);
if (index >= 0) {
localCardImageStorageNamingSchemeComboBox->setCurrentIndex(index);
}
connect(localCardImageStorageNamingSchemeComboBox, qOverload<int>(&QComboBox::currentIndexChanged), this,
[this](int index) {
auto scheme = static_cast<CardPictureLoaderLocalSchemes::NamingScheme>(
localCardImageStorageNamingSchemeComboBox->itemData(index).toInt());
SettingsCache::instance().setLocalCardImageStorageNamingScheme(scheme);
});
auto networkCacheLayout = new QHBoxLayout; auto networkCacheLayout = new QHBoxLayout;
networkCacheLayout->addStretch(); networkCacheLayout->addStretch();
@ -1105,7 +1119,7 @@ DeckEditorSettingsPage::DeckEditorSettingsPage()
auto localCardImageStorageNamingSchemeLayout = new QHBoxLayout; auto localCardImageStorageNamingSchemeLayout = new QHBoxLayout;
localCardImageStorageNamingSchemeLayout->addWidget(&localCardImageStorageNamingSchemeLabel); localCardImageStorageNamingSchemeLayout->addWidget(&localCardImageStorageNamingSchemeLabel);
localCardImageStorageNamingSchemeLayout->addWidget(localCardImageStorageNamingSchemeLineEdit); localCardImageStorageNamingSchemeLayout->addWidget(localCardImageStorageNamingSchemeComboBox);
// Top Layout // Top Layout
lpGeneralGrid->addWidget(&picDownloadCheckBox, 0, 0); lpGeneralGrid->addWidget(&picDownloadCheckBox, 0, 0);

View file

@ -242,7 +242,7 @@ private:
QCheckBox saveCardImagesToLocalStorageCheckBox; QCheckBox saveCardImagesToLocalStorageCheckBox;
QLabel saveCardImagesToLocalStorageLabel; QLabel saveCardImagesToLocalStorageLabel;
QLabel localCardImageStorageNamingSchemeLabel; QLabel localCardImageStorageNamingSchemeLabel;
QLineEdit *localCardImageStorageNamingSchemeLineEdit; QComboBox *localCardImageStorageNamingSchemeComboBox;
}; };
class MessagesSettingsPage : public AbstractSettingsPage class MessagesSettingsPage : public AbstractSettingsPage