diff --git a/cockatrice/src/client/tabs/tab_deck_editor.cpp b/cockatrice/src/client/tabs/tab_deck_editor.cpp index 8eee22cf5..a2ac824af 100644 --- a/cockatrice/src/client/tabs/tab_deck_editor.cpp +++ b/cockatrice/src/client/tabs/tab_deck_editor.cpp @@ -113,6 +113,8 @@ void TabDeckEditor::createDeckDock() connect(bannerCardComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &TabDeckEditor::setBannerCard); + deckTagsDisplayWidget = new DeckPreviewDeckTagsDisplayWidget(this, deckModel->getDeckList()); + aIncrement = new QAction(QString(), this); aIncrement->setIcon(QPixmap("theme:icons/increment")); connect(aIncrement, SIGNAL(triggered()), this, SLOT(actIncrement())); @@ -148,6 +150,8 @@ void TabDeckEditor::createDeckDock() upperLayout->addWidget(bannerCardLabel, 2, 0); upperLayout->addWidget(bannerCardComboBox, 2, 1); + upperLayout->addWidget(deckTagsDisplayWidget, 3, 1); + hashLabel1 = new QLabel(); hashLabel1->setObjectName("hashLabel1"); auto *hashSizePolicy = new QSizePolicy(); @@ -1608,6 +1612,8 @@ void TabDeckEditor::setDeck(DeckLoader *_deck) deckView->expandAll(); setModified(false); + deckTagsDisplayWidget->connectDeckList(deckModel->getDeckList()); + // If they load a deck, make the deck list appear aDeckDockVisible->setChecked(true); deckDock->setVisible(aDeckDockVisible->isChecked()); diff --git a/cockatrice/src/client/tabs/tab_deck_editor.h b/cockatrice/src/client/tabs/tab_deck_editor.h index ab0c0883e..9bb696e34 100644 --- a/cockatrice/src/client/tabs/tab_deck_editor.h +++ b/cockatrice/src/client/tabs/tab_deck_editor.h @@ -5,6 +5,7 @@ #include "../../game/cards/card_database.h" #include "../game_logic/key_signals.h" #include "../ui/widgets/printing_selector/printing_selector.h" +#include "../ui/widgets/visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.h" #include "tab.h" #include @@ -19,6 +20,7 @@ class CardInfoFrameWidget; class QTextEdit; class QLabel; class DeckLoader; +class DeckPreviewDeckTagsDisplayWidget; class Response; class FilterTreeModel; class FilterBuilder; @@ -136,6 +138,7 @@ private: QTextEdit *commentsEdit; QLabel *bannerCardLabel; QComboBox *bannerCardComboBox; + DeckPreviewDeckTagsDisplayWidget *deckTagsDisplayWidget; QLabel *hashLabel1; LineEditUnfocusable *hashLabel; FilterTreeModel *filterModel; diff --git a/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.cpp b/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.cpp index 7f2dfaab0..06b00c089 100644 --- a/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.cpp +++ b/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.cpp @@ -1,5 +1,6 @@ #include "deck_preview_deck_tags_display_widget.h" +#include "../../../../tabs/tab_deck_editor.h" #include "../../general/layout_containers/flow_widget.h" #include "deck_preview_tag_addition_widget.h" #include "deck_preview_tag_display_widget.h" @@ -8,8 +9,8 @@ #include #include -DeckPreviewDeckTagsDisplayWidget::DeckPreviewDeckTagsDisplayWidget(DeckPreviewWidget *_parent, DeckLoader *_deckLoader) - : QWidget(_parent), parent(_parent), deckLoader(_deckLoader) +DeckPreviewDeckTagsDisplayWidget::DeckPreviewDeckTagsDisplayWidget(QWidget *_parent, DeckList *_deckList) + : QWidget(_parent), deckList(_deckList) { setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); @@ -21,21 +22,33 @@ DeckPreviewDeckTagsDisplayWidget::DeckPreviewDeckTagsDisplayWidget(DeckPreviewWi setFixedHeight(100); - connect(deckLoader, &DeckList::deckTagsChanged, this, &DeckPreviewDeckTagsDisplayWidget::refreshTags); - flowWidget = new FlowWidget(this, Qt::Horizontal, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAsNeeded); - for (const QString &tag : this->deckLoader->getTags()) { + + if (deckList) { + connectDeckList(deckList); + } + + layout->addWidget(flowWidget); +} + +void DeckPreviewDeckTagsDisplayWidget::connectDeckList(DeckList *_deckList) +{ + flowWidget->clearLayout(); + deckList = _deckList; + connect(deckList, &DeckList::deckTagsChanged, this, &DeckPreviewDeckTagsDisplayWidget::refreshTags); + + for (const QString &tag : deckList->getTags()) { flowWidget->addWidget(new DeckPreviewTagDisplayWidget(this, tag)); } - flowWidget->addWidget(new DeckPreviewTagAdditionWidget(this, tr("Edit tags ..."))); - layout->addWidget(flowWidget); + flowWidget->addWidget(new DeckPreviewTagAdditionWidget(this, this, tr("Edit tags ..."))); } void DeckPreviewDeckTagsDisplayWidget::refreshTags() { flowWidget->clearLayout(); - for (const QString &tag : this->deckLoader->getTags()) { + QStringList tags = deckList->getTags(); + for (const QString &tag : tags) { flowWidget->addWidget(new DeckPreviewTagDisplayWidget(this, tag)); } - flowWidget->addWidget(new DeckPreviewTagAdditionWidget(this, tr("Edit tags ..."))); + flowWidget->addWidget(new DeckPreviewTagAdditionWidget(this, this, tr("Edit tags ..."))); } \ No newline at end of file diff --git a/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.h b/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.h index a6a1c8de4..4e821f796 100644 --- a/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.h +++ b/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.h @@ -2,6 +2,7 @@ #define DECK_PREVIEW_DECK_TAGS_DISPLAY_WIDGET_H #include "../../../../../deck/deck_loader.h" +#include "../../../../tabs/tab_deck_editor.h" #include "deck_preview_widget.h" #include @@ -12,10 +13,10 @@ class DeckPreviewDeckTagsDisplayWidget : public QWidget Q_OBJECT public: - explicit DeckPreviewDeckTagsDisplayWidget(DeckPreviewWidget *_parent, DeckLoader *_deckLoader); + explicit DeckPreviewDeckTagsDisplayWidget(QWidget *_parent, DeckList *_deckList); + void connectDeckList(DeckList *_deckList); void refreshTags(); - DeckPreviewWidget *parent; - DeckLoader *deckLoader; + DeckList *deckList; FlowWidget *flowWidget; }; #endif // DECK_PREVIEW_DECK_TAGS_DISPLAY_WIDGET_H diff --git a/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_tag_addition_widget.cpp b/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_tag_addition_widget.cpp index 16a87bc8d..32313117c 100644 --- a/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_tag_addition_widget.cpp +++ b/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_tag_addition_widget.cpp @@ -4,14 +4,16 @@ #include "../../../../../settings/cache_settings.h" #include "deck_preview_tag_dialog.h" +#include #include #include #include #include -DeckPreviewTagAdditionWidget::DeckPreviewTagAdditionWidget(DeckPreviewDeckTagsDisplayWidget *_parent, +DeckPreviewTagAdditionWidget::DeckPreviewTagAdditionWidget(QWidget *_parent, + DeckPreviewDeckTagsDisplayWidget *_tagsDisplayWidget, const QString &_tagName) - : QWidget(_parent), parent(_parent), tagName_(_tagName) + : QWidget(_parent), tagsDisplayWidget(_tagsDisplayWidget), tagName_(_tagName) { // Create layout auto *layout = new QHBoxLayout(this); @@ -33,58 +35,108 @@ QSize DeckPreviewTagAdditionWidget::sizeHint() const return QSize(width, height); } +static QStringList getAllFiles(const QString &filePath, bool recursive) +{ + QStringList allFiles; + + // QDirIterator with QDir::Files ensures only files are listed (no directories) + auto flags = + recursive ? QDirIterator::Subdirectories | QDirIterator::FollowSymlinks : QDirIterator::NoIteratorFlags; + QDirIterator it(filePath, QDir::Files, flags); + + while (it.hasNext()) { + allFiles << it.next(); // Add each file path to the list + } + + return allFiles; +} + void DeckPreviewTagAdditionWidget::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { emit tagClicked(); } QWidget::mousePressEvent(event); - QStringList knownTags = parent->parent->visualDeckStorageWidget->tagFilterWidget->getAllKnownTags(); - QStringList activeTags = parent->deckLoader->getTags(); - bool canAddTags = true; + if (qobject_cast(tagsDisplayWidget->parentWidget())) { + DeckPreviewWidget *deckPreviewWidget = qobject_cast(tagsDisplayWidget->parentWidget()); + QStringList knownTags = deckPreviewWidget->visualDeckStorageWidget->tagFilterWidget->getAllKnownTags(); + QStringList activeTags = tagsDisplayWidget->deckList->getTags(); - if (DeckLoader::getFormatFromName(parent->parent->filePath) != DeckLoader::CockatriceFormat) { - canAddTags = false; - // Retrieve saved preference if the prompt is disabled - if (!SettingsCache::instance().getVisualDeckStoragePromptForConversion()) { - if (SettingsCache::instance().getVisualDeckStorageAlwaysConvert()) { - parent->deckLoader->convertToCockatriceFormat(parent->parent->filePath); - parent->parent->filePath = parent->deckLoader->getLastFileName(); - parent->parent->refreshBannerCardText(); - canAddTags = true; - } - } else { - // Show the dialog to the user - DialogConvertDeckToCodFormat conversionDialog(parent); - if (conversionDialog.exec() == QDialog::Accepted) { - parent->deckLoader->convertToCockatriceFormat(parent->parent->filePath); - parent->parent->filePath = parent->deckLoader->getLastFileName(); - parent->parent->refreshBannerCardText(); - canAddTags = true; + bool canAddTags = true; - if (conversionDialog.dontAskAgain()) { - SettingsCache::instance().setVisualDeckStoragePromptForConversion(Qt::CheckState::Unchecked); - SettingsCache::instance().setVisualDeckStorageAlwaysConvert(Qt::CheckState::Checked); + if (DeckLoader::getFormatFromName(deckPreviewWidget->filePath) != DeckLoader::CockatriceFormat) { + canAddTags = false; + // Retrieve saved preference if the prompt is disabled + if (!SettingsCache::instance().getVisualDeckStoragePromptForConversion()) { + if (SettingsCache::instance().getVisualDeckStorageAlwaysConvert()) { + deckPreviewWidget->deckLoader->convertToCockatriceFormat(deckPreviewWidget->filePath); + deckPreviewWidget->filePath = deckPreviewWidget->deckLoader->getLastFileName(); + deckPreviewWidget->refreshBannerCardText(); + canAddTags = true; } } else { - SettingsCache::instance().setVisualDeckStorageAlwaysConvert(Qt::CheckState::Unchecked); + // Show the dialog to the user + DialogConvertDeckToCodFormat conversionDialog(parentWidget()); + if (conversionDialog.exec() == QDialog::Accepted) { + deckPreviewWidget->deckLoader->convertToCockatriceFormat(deckPreviewWidget->filePath); + deckPreviewWidget->filePath = deckPreviewWidget->deckLoader->getLastFileName(); + deckPreviewWidget->refreshBannerCardText(); + canAddTags = true; - if (conversionDialog.dontAskAgain()) { - SettingsCache::instance().setVisualDeckStoragePromptForConversion(Qt::CheckState::Unchecked); + if (conversionDialog.dontAskAgain()) { + SettingsCache::instance().setVisualDeckStoragePromptForConversion(Qt::CheckState::Unchecked); + SettingsCache::instance().setVisualDeckStorageAlwaysConvert(Qt::CheckState::Checked); + } } else { - SettingsCache::instance().setVisualDeckStoragePromptForConversion(Qt::CheckState::Checked); + SettingsCache::instance().setVisualDeckStorageAlwaysConvert(Qt::CheckState::Unchecked); + + if (conversionDialog.dontAskAgain()) { + SettingsCache::instance().setVisualDeckStoragePromptForConversion(Qt::CheckState::Unchecked); + } else { + SettingsCache::instance().setVisualDeckStoragePromptForConversion(Qt::CheckState::Checked); + } } } } - } - if (canAddTags) { - DeckPreviewTagDialog dialog(knownTags, activeTags); - if (dialog.exec() == QDialog::Accepted) { - QStringList updatedTags = dialog.getActiveTags(); - parent->deckLoader->setTags(updatedTags); - parent->deckLoader->saveToFile(parent->parent->filePath, DeckLoader::CockatriceFormat); + if (canAddTags) { + DeckPreviewTagDialog dialog(knownTags, activeTags); + if (dialog.exec() == QDialog::Accepted) { + QStringList updatedTags = dialog.getActiveTags(); + tagsDisplayWidget->deckList->setTags(updatedTags); + deckPreviewWidget->deckLoader->saveToFile(deckPreviewWidget->filePath, DeckLoader::CockatriceFormat); + } + } + } else if (tagsDisplayWidget->parentWidget()) { + // If we're the child of a TabDeckEditor, we are buried under a ton of childWidgets in the DeckInfoDock. + QWidget *currentParent = tagsDisplayWidget->parentWidget(); + while (currentParent) { + if (qobject_cast(currentParent)) { + break; + } + currentParent = currentParent->parentWidget(); + } + if (qobject_cast(currentParent)) { + TabDeckEditor *deckEditor = qobject_cast(currentParent); + QStringList knownTags; + QStringList allFiles = getAllFiles(SettingsCache::instance().getDeckPath(), true); + DeckLoader *loader = new DeckLoader(); + for (QString file : allFiles) { + loader->loadFromFile(file, DeckLoader::getFormatFromName(file), false); + QStringList tags = loader->getTags(); + knownTags.append(tags); + knownTags.removeDuplicates(); + } + + QStringList activeTags = tagsDisplayWidget->deckList->getTags(); + + DeckPreviewTagDialog dialog(knownTags, activeTags); + if (dialog.exec() == QDialog::Accepted) { + QStringList updatedTags = dialog.getActiveTags(); + tagsDisplayWidget->deckList->setTags(updatedTags); + deckEditor->setModified(true); + } } } } diff --git a/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_tag_addition_widget.h b/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_tag_addition_widget.h index 14d51a556..bbd70383f 100644 --- a/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_tag_addition_widget.h +++ b/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_tag_addition_widget.h @@ -12,7 +12,9 @@ class DeckPreviewTagAdditionWidget : public QWidget Q_OBJECT public: - explicit DeckPreviewTagAdditionWidget(DeckPreviewDeckTagsDisplayWidget *_parent, const QString &tagName); + explicit DeckPreviewTagAdditionWidget(QWidget *_parent, + DeckPreviewDeckTagsDisplayWidget *_tagsDisplayWidget, + const QString &_tagName); QSize sizeHint() const override; signals: @@ -24,7 +26,7 @@ protected: void paintEvent(QPaintEvent *event) override; private: - DeckPreviewDeckTagsDisplayWidget *parent; + DeckPreviewDeckTagsDisplayWidget *tagsDisplayWidget; QString tagName_; QLabel *tagLabel_; QPushButton *closeButton_;