Compare commits

...

2 Commits

Author SHA1 Message Date
RickyRister
95c3434205 [TagDisplayWidget] Refactor to just store tags and use signals (#6395) 2025-12-04 10:26:39 -08:00
RickyRister
f0be6972cc [TagsDisplayWidget] cleanup refactor (#6394)
* Make fields private

* Move method to static

* clean up code

* move code
2025-12-04 09:40:24 -08:00
6 changed files with 143 additions and 106 deletions

View File

@@ -154,8 +154,10 @@ void DeckEditorDeckDockWidget::createDeckDock()
&DeckEditorDeckDockWidget::setBannerCard); &DeckEditorDeckDockWidget::setBannerCard);
bannerCardComboBox->setHidden(!SettingsCache::instance().getDeckEditorBannerCardComboBoxVisible()); bannerCardComboBox->setHidden(!SettingsCache::instance().getDeckEditorBannerCardComboBoxVisible());
deckTagsDisplayWidget = new DeckPreviewDeckTagsDisplayWidget(this, deckModel->getDeckList()); deckTagsDisplayWidget = new DeckPreviewDeckTagsDisplayWidget(this, deckModel->getDeckList()->getTags());
deckTagsDisplayWidget->setHidden(!SettingsCache::instance().getDeckEditorTagsWidgetVisible()); deckTagsDisplayWidget->setHidden(!SettingsCache::instance().getDeckEditorTagsWidgetVisible());
connect(deckTagsDisplayWidget, &DeckPreviewDeckTagsDisplayWidget::tagsChanged, this,
&DeckEditorDeckDockWidget::setTags);
activeGroupCriteriaLabel = new QLabel(this); activeGroupCriteriaLabel = new QLabel(this);
@@ -383,6 +385,13 @@ void DeckEditorDeckDockWidget::setBannerCard(int /* changedIndex */)
emit deckModified(); emit deckModified();
} }
void DeckEditorDeckDockWidget::setTags(const QStringList &tags)
{
deckModel->getDeckList()->setTags(tags);
deckEditor->setModified(true);
emit deckModified();
}
void DeckEditorDeckDockWidget::syncDeckListBannerCardWithComboBox() void DeckEditorDeckDockWidget::syncDeckListBannerCardWithComboBox()
{ {
auto [name, id] = bannerCardComboBox->currentData().value<QPair<QString, QString>>(); auto [name, id] = bannerCardComboBox->currentData().value<QPair<QString, QString>>();
@@ -451,7 +460,7 @@ void DeckEditorDeckDockWidget::syncDisplayWidgetsToModel()
sortDeckModelToDeckView(); sortDeckModelToDeckView();
expandAll(); expandAll();
deckTagsDisplayWidget->setDeckList(deckModel->getDeckList()); deckTagsDisplayWidget->setTags(deckModel->getDeckList()->getTags());
} }
void DeckEditorDeckDockWidget::sortDeckModelToDeckView() void DeckEditorDeckDockWidget::sortDeckModelToDeckView()
@@ -484,7 +493,7 @@ void DeckEditorDeckDockWidget::cleanDeck()
emit deckModified(); emit deckModified();
emit deckChanged(); emit deckChanged();
updateBannerCardComboBox(); updateBannerCardComboBox();
deckTagsDisplayWidget->setDeckList(deckModel->getDeckList()); deckTagsDisplayWidget->setTags(deckModel->getDeckList()->getTags());
} }
void DeckEditorDeckDockWidget::recursiveExpand(const QModelIndex &index) void DeckEditorDeckDockWidget::recursiveExpand(const QModelIndex &index)

View File

@@ -112,6 +112,7 @@ private slots:
void updateName(const QString &name); void updateName(const QString &name);
void updateComments(); void updateComments();
void setBannerCard(int); void setBannerCard(int);
void setTags(const QStringList &tags);
void syncDeckListBannerCardWithComboBox(); void syncDeckListBannerCardWithComboBox();
void updateHash(); void updateHash();
void refreshShortcuts(); void refreshShortcuts();

View File

@@ -13,8 +13,8 @@
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QMessageBox> #include <QMessageBox>
DeckPreviewDeckTagsDisplayWidget::DeckPreviewDeckTagsDisplayWidget(QWidget *_parent, DeckList *_deckList) DeckPreviewDeckTagsDisplayWidget::DeckPreviewDeckTagsDisplayWidget(QWidget *_parent, const QStringList &_tags)
: QWidget(_parent), deckList(nullptr) : QWidget(_parent), currentTags(_tags)
{ {
setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
@@ -27,16 +27,14 @@ DeckPreviewDeckTagsDisplayWidget::DeckPreviewDeckTagsDisplayWidget(QWidget *_par
flowWidget = new FlowWidget(this, Qt::Horizontal, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAsNeeded); flowWidget = new FlowWidget(this, Qt::Horizontal, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAsNeeded);
if (_deckList) {
setDeckList(_deckList);
}
layout->addWidget(flowWidget); layout->addWidget(flowWidget);
refreshTags();
} }
void DeckPreviewDeckTagsDisplayWidget::setDeckList(DeckList *_deckList) void DeckPreviewDeckTagsDisplayWidget::setTags(const QStringList &_tags)
{ {
deckList = _deckList; currentTags = _tags;
refreshTags(); refreshTags();
} }
@@ -44,7 +42,7 @@ void DeckPreviewDeckTagsDisplayWidget::refreshTags()
{ {
flowWidget->clearLayout(); flowWidget->clearLayout();
for (const QString &tag : deckList->getTags()) { for (const QString &tag : currentTags) {
flowWidget->addWidget(new DeckPreviewTagDisplayWidget(this, tag)); flowWidget->addWidget(new DeckPreviewTagDisplayWidget(this, tag));
} }
@@ -71,7 +69,45 @@ static QStringList getAllFiles(const QString &filePath)
return allFiles; return allFiles;
} }
bool confirmOverwriteIfExists(QWidget *parent, const QString &filePath) /**
* Gets all tags that appear in the deck folder
*/
static QStringList findAllKnownTags()
{
QStringList allFiles = getAllFiles(SettingsCache::instance().getDeckPath());
QStringList knownTags;
auto loader = DeckLoader(nullptr);
for (const QString &file : allFiles) {
loader.loadFromFile(file, DeckLoader::getFormatFromName(file), false);
QStringList tags = loader.getDeckList()->getTags();
knownTags.append(tags);
knownTags.removeDuplicates();
}
return knownTags;
}
void DeckPreviewDeckTagsDisplayWidget::openTagEditDlg()
{
if (qobject_cast<DeckPreviewWidget *>(parentWidget())) {
// If we're the child of a DeckPreviewWidget, then we need to handle conversion
auto *deckPreviewWidget = qobject_cast<DeckPreviewWidget *>(parentWidget());
bool canAddTags = promptFileConversionIfRequired(deckPreviewWidget);
if (canAddTags) {
QStringList knownTags = deckPreviewWidget->visualDeckStorageWidget->tagFilterWidget->getAllKnownTags();
execTagDialog(knownTags);
}
} else {
// If we're the child of an AbstractTabDeckEditor, then we don't bother with conversion
QStringList knownTags = findAllKnownTags();
execTagDialog(knownTags);
}
}
static bool confirmOverwriteIfExists(QWidget *parent, const QString &filePath)
{ {
QFileInfo fileInfo(filePath); QFileInfo fileInfo(filePath);
QString newFileName = QDir::toNativeSeparators(fileInfo.path() + "/" + fileInfo.completeBaseName() + ".cod"); QString newFileName = QDir::toNativeSeparators(fileInfo.path() + "/" + fileInfo.completeBaseName() + ".cod");
@@ -86,98 +122,70 @@ bool confirmOverwriteIfExists(QWidget *parent, const QString &filePath)
return true; // Safe to proceed return true; // Safe to proceed
} }
void DeckPreviewDeckTagsDisplayWidget::openTagEditDlg() static void convertFileToCockatriceFormat(DeckPreviewWidget *deckPreviewWidget)
{ {
if (qobject_cast<DeckPreviewWidget *>(parentWidget())) { deckPreviewWidget->deckLoader->convertToCockatriceFormat(deckPreviewWidget->filePath);
auto *deckPreviewWidget = qobject_cast<DeckPreviewWidget *>(parentWidget()); deckPreviewWidget->filePath = deckPreviewWidget->deckLoader->getLastLoadInfo().fileName;
QStringList knownTags = deckPreviewWidget->visualDeckStorageWidget->tagFilterWidget->getAllKnownTags(); deckPreviewWidget->refreshBannerCardText();
QStringList activeTags = deckList->getTags(); }
bool canAddTags = true; /**
* Checks if the deck's file format supports tags.
* If not, then prompt the user for file conversion.
* @return whether the resulting file can support adding tags
*/
bool DeckPreviewDeckTagsDisplayWidget::promptFileConversionIfRequired(DeckPreviewWidget *deckPreviewWidget)
{
if (DeckLoader::getFormatFromName(deckPreviewWidget->filePath) == DeckLoader::CockatriceFormat) {
return true;
}
if (DeckLoader::getFormatFromName(deckPreviewWidget->filePath) != DeckLoader::CockatriceFormat) { // Retrieve saved preference if the prompt is disabled
canAddTags = false; if (!SettingsCache::instance().getVisualDeckStoragePromptForConversion()) {
// Retrieve saved preference if the prompt is disabled if (!SettingsCache::instance().getVisualDeckStorageAlwaysConvert()) {
if (!SettingsCache::instance().getVisualDeckStoragePromptForConversion()) { return false;
if (SettingsCache::instance().getVisualDeckStorageAlwaysConvert()) {
if (!confirmOverwriteIfExists(this, deckPreviewWidget->filePath))
return;
deckPreviewWidget->deckLoader->convertToCockatriceFormat(deckPreviewWidget->filePath);
deckPreviewWidget->filePath = deckPreviewWidget->deckLoader->getLastLoadInfo().fileName;
deckPreviewWidget->refreshBannerCardText();
canAddTags = true;
}
} else {
// Show the dialog to the user
DialogConvertDeckToCodFormat conversionDialog(parentWidget());
if (conversionDialog.exec() == QDialog::Accepted) {
if (!confirmOverwriteIfExists(this, deckPreviewWidget->filePath))
return;
deckPreviewWidget->deckLoader->convertToCockatriceFormat(deckPreviewWidget->filePath);
deckPreviewWidget->filePath = deckPreviewWidget->deckLoader->getLastLoadInfo().fileName;
deckPreviewWidget->refreshBannerCardText();
canAddTags = true;
if (conversionDialog.dontAskAgain()) {
SettingsCache::instance().setVisualDeckStoragePromptForConversion(false);
SettingsCache::instance().setVisualDeckStorageAlwaysConvert(true);
}
} else {
SettingsCache::instance().setVisualDeckStorageAlwaysConvert(false);
if (conversionDialog.dontAskAgain()) {
SettingsCache::instance().setVisualDeckStoragePromptForConversion(false);
} else {
SettingsCache::instance().setVisualDeckStoragePromptForConversion(true);
}
}
}
} }
if (canAddTags) { if (!confirmOverwriteIfExists(this, deckPreviewWidget->filePath)) {
DeckPreviewTagDialog dialog(knownTags, activeTags); return false;
if (dialog.exec() == QDialog::Accepted) {
QStringList updatedTags = dialog.getActiveTags();
deckList->setTags(updatedTags);
deckPreviewWidget->deckLoader->saveToFile(deckPreviewWidget->filePath, DeckLoader::CockatriceFormat);
refreshTags();
}
} }
} else if (parentWidget()) {
// If we're the child of an AbstractTabDeckEditor, we are buried under a ton of childWidgets in the
// DeckInfoDock.
QWidget *currentParent = parentWidget();
while (currentParent) {
if (qobject_cast<AbstractTabDeckEditor *>(currentParent)) {
break;
}
currentParent = currentParent->parentWidget();
}
if (qobject_cast<AbstractTabDeckEditor *>(currentParent)) {
auto *deckEditor = qobject_cast<AbstractTabDeckEditor *>(currentParent);
QStringList knownTags;
QStringList allFiles = getAllFiles(SettingsCache::instance().getDeckPath());
DeckLoader loader(this);
for (const QString &file : allFiles) {
loader.loadFromFile(file, DeckLoader::getFormatFromName(file), false);
QStringList tags = loader.getDeckList()->getTags();
knownTags.append(tags);
knownTags.removeDuplicates();
}
QStringList activeTags = deckList->getTags(); convertFileToCockatriceFormat(deckPreviewWidget);
return true;
}
DeckPreviewTagDialog dialog(knownTags, activeTags); // Show the dialog to the user
if (dialog.exec() == QDialog::Accepted) { DialogConvertDeckToCodFormat conversionDialog(parentWidget());
QStringList updatedTags = dialog.getActiveTags(); if (conversionDialog.exec() != QDialog::Accepted) {
deckList->setTags(updatedTags); SettingsCache::instance().setVisualDeckStoragePromptForConversion(!conversionDialog.dontAskAgain());
deckEditor->setModified(true); SettingsCache::instance().setVisualDeckStorageAlwaysConvert(false);
refreshTags();
} return false;
}
// Try to convert file
if (!confirmOverwriteIfExists(this, deckPreviewWidget->filePath)) {
return false;
}
convertFileToCockatriceFormat(deckPreviewWidget);
if (conversionDialog.dontAskAgain()) {
SettingsCache::instance().setVisualDeckStoragePromptForConversion(false);
SettingsCache::instance().setVisualDeckStorageAlwaysConvert(true);
}
return true;
}
void DeckPreviewDeckTagsDisplayWidget::execTagDialog(const QStringList &knownTags)
{
DeckPreviewTagDialog dialog(knownTags, currentTags);
if (dialog.exec() == QDialog::Accepted) {
QStringList updatedTags = dialog.getActiveTags();
if (updatedTags != currentTags) {
setTags(updatedTags);
emit tagsChanged(updatedTags);
} }
} }
} }

View File

@@ -12,21 +12,31 @@
#include <QWidget> #include <QWidget>
inline bool confirmOverwriteIfExists(QWidget *parent, const QString &filePath);
class DeckPreviewWidget; class DeckPreviewWidget;
class DeckPreviewDeckTagsDisplayWidget : public QWidget class DeckPreviewDeckTagsDisplayWidget : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: QStringList currentTags;
explicit DeckPreviewDeckTagsDisplayWidget(QWidget *_parent, DeckList *_deckList);
void setDeckList(DeckList *_deckList);
void refreshTags();
DeckList *deckList;
FlowWidget *flowWidget; FlowWidget *flowWidget;
public:
explicit DeckPreviewDeckTagsDisplayWidget(QWidget *_parent, const QStringList &_tags);
void setTags(const QStringList &_tags);
void refreshTags();
public slots: public slots:
void openTagEditDlg(); void openTagEditDlg();
private:
bool promptFileConversionIfRequired(DeckPreviewWidget *deckPreviewWidget);
void execTagDialog(const QStringList &knownTags);
signals:
/**
* Emitted when the tags have changed due to user interaction.
* @param tags The new list of tags.
*/
void tagsChanged(const QStringList &tags);
}; };
#endif // DECK_PREVIEW_DECK_TAGS_DISPLAY_WIDGET_H #endif // DECK_PREVIEW_DECK_TAGS_DISPLAY_WIDGET_H

View File

@@ -83,7 +83,8 @@ void DeckPreviewWidget::initializeUi(const bool deckLoadSuccess)
setFilePath(deckLoader->getLastLoadInfo().fileName); setFilePath(deckLoader->getLastLoadInfo().fileName);
colorIdentityWidget = new ColorIdentityWidget(this, getColorIdentity()); colorIdentityWidget = new ColorIdentityWidget(this, getColorIdentity());
deckTagsDisplayWidget = new DeckPreviewDeckTagsDisplayWidget(this, deckLoader->getDeckList()); deckTagsDisplayWidget = new DeckPreviewDeckTagsDisplayWidget(this, deckLoader->getDeckList()->getTags());
connect(deckTagsDisplayWidget, &DeckPreviewDeckTagsDisplayWidget::tagsChanged, this, &DeckPreviewWidget::setTags);
bannerCardLabel = new QLabel(this); bannerCardLabel = new QLabel(this);
bannerCardLabel->setObjectName("bannerCardLabel"); bannerCardLabel->setObjectName("bannerCardLabel");
@@ -307,6 +308,12 @@ void DeckPreviewWidget::imageDoubleClickedEvent(QMouseEvent *event, DeckPreviewC
emit deckLoadRequested(filePath); emit deckLoadRequested(filePath);
} }
void DeckPreviewWidget::setTags(const QStringList &tags)
{
deckLoader->getDeckList()->setTags(tags);
deckLoader->saveToFile(filePath, DeckLoader::CockatriceFormat);
}
QMenu *DeckPreviewWidget::createRightClickMenu() QMenu *DeckPreviewWidget::createRightClickMenu()
{ {
auto *menu = new QMenu(this); auto *menu = new QMenu(this);

View File

@@ -72,6 +72,8 @@ private:
void addSetBannerCardMenu(QMenu *menu); void addSetBannerCardMenu(QMenu *menu);
private slots: private slots:
void setTags(const QStringList &tags);
void actRenameDeck(); void actRenameDeck();
void actRenameFile(); void actRenameFile();
void actDeleteFile(); void actDeleteFile();