diff --git a/cockatrice/cockatrice.qrc b/cockatrice/cockatrice.qrc index 05846bbb7..7b42f69ca 100644 --- a/cockatrice/cockatrice.qrc +++ b/cockatrice/cockatrice.qrc @@ -25,6 +25,7 @@ resources/icons/pencil.svg resources/icons/player.svg resources/icons/ready_start.svg + resources/icons/reload.svg resources/icons/remove_row.svg resources/icons/scales.svg resources/icons/search.svg diff --git a/cockatrice/resources/icons/reload.svg b/cockatrice/resources/icons/reload.svg new file mode 100644 index 000000000..102995876 --- /dev/null +++ b/cockatrice/resources/icons/reload.svg @@ -0,0 +1,7 @@ + + + + Svg Vector Icons : http://www.onlinewebfonts.com/icon + + \ No newline at end of file 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..831bb00dd 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,17 @@ #include "../../../../../settings/cache_settings.h" #include "deck_preview_tag_dialog.h" +#include #include #include #include #include +#include -DeckPreviewTagAdditionWidget::DeckPreviewTagAdditionWidget(DeckPreviewDeckTagsDisplayWidget *_parent, - const QString &_tagName) - : QWidget(_parent), parent(_parent), tagName_(_tagName) +DeckPreviewTagAdditionWidget::DeckPreviewTagAdditionWidget(QWidget *_parent, + DeckPreviewDeckTagsDisplayWidget *_tagsDisplayWidget, + QString _tagName) + : QWidget(_parent), tagsDisplayWidget(_tagsDisplayWidget), tagName_(std::move(_tagName)) { // Create layout auto *layout = new QHBoxLayout(this); @@ -30,7 +33,23 @@ QSize DeckPreviewTagAdditionWidget::sizeHint() const int width = textWidth + 50; // Add extra padding int height = fm.height() + 10; // Height based on font size + padding - return QSize(width, height); + return {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) @@ -39,52 +58,86 @@ void DeckPreviewTagAdditionWidget::mousePressEvent(QMouseEvent *event) 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())) { + auto *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)) { + auto *deckEditor = qobject_cast(currentParent); + QStringList knownTags; + QStringList allFiles = getAllFiles(SettingsCache::instance().getDeckPath(), true); + auto *loader = new DeckLoader(); + for (const 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..4d288c95a 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,8 +12,10 @@ class DeckPreviewTagAdditionWidget : public QWidget Q_OBJECT public: - explicit DeckPreviewTagAdditionWidget(DeckPreviewDeckTagsDisplayWidget *_parent, const QString &tagName); - QSize sizeHint() const override; + explicit DeckPreviewTagAdditionWidget(QWidget *_parent, + DeckPreviewDeckTagsDisplayWidget *_tagsDisplayWidget, + QString _tagName); + [[nodiscard]] QSize sizeHint() const override; signals: void tagClicked(); // Emitted when the tag is clicked @@ -24,10 +26,8 @@ protected: void paintEvent(QPaintEvent *event) override; private: - DeckPreviewDeckTagsDisplayWidget *parent; + DeckPreviewDeckTagsDisplayWidget *tagsDisplayWidget; QString tagName_; - QLabel *tagLabel_; - QPushButton *closeButton_; }; #endif // DECK_PREVIEW_TAG_ADDITION_WIDGET_H diff --git a/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_widget.cpp b/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_widget.cpp index 27519c252..df8ab2641 100644 --- a/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_widget.cpp +++ b/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_widget.cpp @@ -34,10 +34,26 @@ DeckPreviewWidget::DeckPreviewWidget(QWidget *_parent, connect(&SettingsCache::instance(), &SettingsCache::visualDeckStorageShowTagsOnDeckPreviewsChanged, this, &DeckPreviewWidget::updateTagsVisibility); + connect(&SettingsCache::instance(), &SettingsCache::visualDeckStorageShowBannerCardComboBoxChanged, this, + &DeckPreviewWidget::updateBannerCardComboBoxVisibility); layout->addWidget(bannerCardDisplayWidget); } +void DeckPreviewWidget::retranslateUi() +{ + bannerCardLabel->setText(tr("Banner Card")); +} + +void DeckPreviewWidget::resizeEvent(QResizeEvent *event) +{ + QWidget::resizeEvent(event); + if (bannerCardDisplayWidget == nullptr || bannerCardComboBox == nullptr) { + return; + } + bannerCardComboBox->setMaximumWidth(bannerCardDisplayWidget->width()); +} + void DeckPreviewWidget::initializeUi(const bool deckLoadSuccess) { if (!deckLoadSuccess) { @@ -56,10 +72,27 @@ void DeckPreviewWidget::initializeUi(const bool deckLoadSuccess) colorIdentityWidget = new DeckPreviewColorIdentityWidget(this, getColorIdentity()); deckTagsDisplayWidget = new DeckPreviewDeckTagsDisplayWidget(this, deckLoader); + + bannerCardLabel = new QLabel(); + bannerCardLabel->setObjectName("bannerCardLabel"); + bannerCardComboBox = new QComboBox(this); + bannerCardComboBox->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + bannerCardComboBox->setObjectName("bannerCardComboBox"); + bannerCardComboBox->setCurrentText(deckLoader->getBannerCard().first); + bannerCardComboBox->installEventFilter(new NoScrollFilter()); + connect(bannerCardComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, + &DeckPreviewWidget::setBannerCard); + + updateBannerCardComboBox(); + updateBannerCardComboBoxVisibility(SettingsCache::instance().getVisualDeckStorageShowBannerCardComboBox()); updateTagsVisibility(SettingsCache::instance().getVisualDeckStorageShowTagsOnDeckPreviews()); layout->addWidget(colorIdentityWidget); layout->addWidget(deckTagsDisplayWidget); + layout->addWidget(bannerCardLabel); + layout->addWidget(bannerCardComboBox); + + retranslateUi(); } void DeckPreviewWidget::updateVisibility() @@ -78,9 +111,24 @@ bool DeckPreviewWidget::checkVisibility() const return true; } +void DeckPreviewWidget::updateBannerCardComboBoxVisibility(bool visible) +{ + if (bannerCardComboBox == nullptr) { + return; + } + + if (visible) { + bannerCardComboBox->setVisible(true); + bannerCardLabel->setVisible(true); + } else { + bannerCardComboBox->setHidden(true); + bannerCardLabel->setHidden(true); + } +} + void DeckPreviewWidget::updateTagsVisibility(bool visible) { - if (!deckTagsDisplayWidget) { + if (deckTagsDisplayWidget == nullptr) { return; } @@ -133,6 +181,81 @@ void DeckPreviewWidget::refreshBannerCardText() deckLoader->getName().isEmpty() ? QFileInfo(deckLoader->getLastFileName()).fileName() : deckLoader->getName()); } +void DeckPreviewWidget::updateBannerCardComboBox() +{ + // Store the current text of the combo box + QString currentText = bannerCardComboBox->currentText(); + + // Block signals temporarily + bool wasBlocked = bannerCardComboBox->blockSignals(true); + + // Clear the existing items in the combo box + bannerCardComboBox->clear(); + + // Prepare the new items with deduplication + QSet> bannerCardSet; + InnerDecklistNode *listRoot = deckLoader->getRoot(); + for (auto i : *listRoot) { + auto *currentZone = dynamic_cast(i); + for (auto j : *currentZone) { + auto *currentCard = dynamic_cast(j); + if (!currentCard) + continue; + + for (int k = 0; k < currentCard->getNumber(); ++k) { + CardInfoPtr info = CardDatabaseManager::getInstance()->getCardByNameAndProviderId( + currentCard->getName(), currentCard->getCardProviderId()); + if (info) { + bannerCardSet.insert( + QPair(currentCard->getName(), currentCard->getCardProviderId())); + } + } + } + } + + QList> pairList = bannerCardSet.values(); + + // Sort QList by the first() element of the QPair + std::sort(pairList.begin(), pairList.end(), [](const QPair &a, const QPair &b) { + return a.first.toLower() < b.first.toLower(); + }); + + for (const auto &pair : pairList) { + QVariantMap dataMap; + dataMap["name"] = pair.first; + dataMap["uuid"] = pair.second; + + bannerCardComboBox->addItem(pair.first, dataMap); + } + + // Try to restore the previous selection by finding the currentText + int restoredIndex = bannerCardComboBox->findText(currentText); + if (restoredIndex != -1) { + bannerCardComboBox->setCurrentIndex(restoredIndex); + } else { + // Add a placeholder "-" and set it as the current selection + int bannerIndex = bannerCardComboBox->findText(deckLoader->getBannerCard().first); + if (bannerIndex != -1) { + bannerCardComboBox->setCurrentIndex(bannerIndex); + } else { + bannerCardComboBox->insertItem(0, "-"); + bannerCardComboBox->setCurrentIndex(0); + } + } + + // Restore the previous signal blocking state + bannerCardComboBox->blockSignals(wasBlocked); +} + +void DeckPreviewWidget::setBannerCard(int /* changedIndex */) +{ + QVariantMap itemData = bannerCardComboBox->itemData(bannerCardComboBox->currentIndex()).toMap(); + deckLoader->setBannerCard(QPair(itemData["name"].toString(), itemData["uuid"].toString())); + deckLoader->saveToFile(filePath, DeckLoader::getFormatFromName(filePath)); + bannerCardDisplayWidget->setCard(CardDatabaseManager::getInstance()->getCardByNameAndProviderId( + itemData["name"].toString(), itemData["uuid"].toString())); +} + void DeckPreviewWidget::imageClickedEvent(QMouseEvent *event, DeckPreviewCardPictureWidget *instance) { Q_UNUSED(instance); diff --git a/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_widget.h b/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_widget.h index af5dd04b7..36228ab6e 100644 --- a/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_widget.h +++ b/cockatrice/src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_widget.h @@ -19,15 +19,18 @@ public: explicit DeckPreviewWidget(QWidget *_parent, VisualDeckStorageWidget *_visualDeckStorageWidget, const QString &_filePath); + void retranslateUi(); QString getColorIdentity(); VisualDeckStorageWidget *visualDeckStorageWidget; QVBoxLayout *layout; QString filePath; DeckLoader *deckLoader; - DeckPreviewCardPictureWidget *bannerCardDisplayWidget; - DeckPreviewColorIdentityWidget *colorIdentityWidget; - DeckPreviewDeckTagsDisplayWidget *deckTagsDisplayWidget; + DeckPreviewCardPictureWidget *bannerCardDisplayWidget = nullptr; + DeckPreviewColorIdentityWidget *colorIdentityWidget = nullptr; + DeckPreviewDeckTagsDisplayWidget *deckTagsDisplayWidget = nullptr; + QLabel *bannerCardLabel = nullptr; + QComboBox *bannerCardComboBox = nullptr; bool filteredBySearch = false; bool filteredByColor = false; bool filteredByTags = false; @@ -41,11 +44,28 @@ signals: public slots: void setFilePath(const QString &filePath); void refreshBannerCardText(); + void updateBannerCardComboBox(); + void setBannerCard(int); void imageClickedEvent(QMouseEvent *event, DeckPreviewCardPictureWidget *instance); void imageDoubleClickedEvent(QMouseEvent *event, DeckPreviewCardPictureWidget *instance); void initializeUi(bool deckLoadSuccess); void updateVisibility(); + void updateBannerCardComboBoxVisibility(bool visible); void updateTagsVisibility(bool visible); + void resizeEvent(QResizeEvent *event) override; +}; + +class NoScrollFilter : public QObject +{ + Q_OBJECT +protected: + bool eventFilter(QObject *obj, QEvent *event) override + { + if (event->type() == QEvent::Wheel) { + return true; // Blocks the event + } + return QObject::eventFilter(obj, event); + } }; #endif // DECK_PREVIEW_WIDGET_H diff --git a/cockatrice/src/client/ui/widgets/visual_deck_storage/visual_deck_storage_widget.cpp b/cockatrice/src/client/ui/widgets/visual_deck_storage/visual_deck_storage_widget.cpp index 8e43f703e..0e04f1dc6 100644 --- a/cockatrice/src/client/ui/widgets/visual_deck_storage/visual_deck_storage_widget.cpp +++ b/cockatrice/src/client/ui/widgets/visual_deck_storage/visual_deck_storage_widget.cpp @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -35,6 +36,11 @@ VisualDeckStorageWidget::VisualDeckStorageWidget(QWidget *parent) : QWidget(pare sortWidget = new VisualDeckStorageSortWidget(this); searchWidget = new VisualDeckStorageSearchWidget(this); + refreshButton = new QToolButton(this); + refreshButton->setIcon(QPixmap("theme:icons/reload")); + refreshButton->setFixedSize(32, 32); + connect(refreshButton, &QPushButton::clicked, this, &VisualDeckStorageWidget::refreshIfPossible); + showFoldersCheckBox = new QCheckBox(this); showFoldersCheckBox->setChecked(SettingsCache::instance().getVisualDeckStorageShowFolders()); connect(showFoldersCheckBox, &QCheckBox::QT_STATE_CHANGED, this, &VisualDeckStorageWidget::updateShowFolders); @@ -59,6 +65,12 @@ VisualDeckStorageWidget::VisualDeckStorageWidget(QWidget *parent) : QWidget(pare connect(drawUnusedColorIdentitiesCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), &SettingsCache::setVisualDeckStorageDrawUnusedColorIdentities); + bannerCardComboBoxVisibilityCheckBox = new QCheckBox(this); + bannerCardComboBoxVisibilityCheckBox->setChecked( + SettingsCache::instance().getVisualDeckStorageShowBannerCardComboBox()); + connect(bannerCardComboBoxVisibilityCheckBox, &QCheckBox::QT_STATE_CHANGED, &SettingsCache::instance(), + &SettingsCache::setVisualDeckStorageShowBannerCardComboBox); + // card size slider cardSizeWidget = new CardSizeWidget(this, nullptr, SettingsCache::instance().getVisualDeckStorageCardSize()); @@ -67,11 +79,13 @@ VisualDeckStorageWidget::VisualDeckStorageWidget(QWidget *parent) : QWidget(pare quickSettingsWidget->addSettingsWidget(tagFilterVisibilityCheckBox); quickSettingsWidget->addSettingsWidget(tagsOnWidgetsVisibilityCheckBox); quickSettingsWidget->addSettingsWidget(drawUnusedColorIdentitiesCheckBox); + quickSettingsWidget->addSettingsWidget(bannerCardComboBoxVisibilityCheckBox); quickSettingsWidget->addSettingsWidget(cardSizeWidget); searchAndSortLayout->addWidget(deckPreviewColorIdentityFilterWidget); searchAndSortLayout->addWidget(sortWidget); searchAndSortLayout->addWidget(searchWidget); + searchAndSortLayout->addWidget(refreshButton); searchAndSortLayout->addWidget(quickSettingsWidget); // tag filter box @@ -104,6 +118,29 @@ VisualDeckStorageWidget::VisualDeckStorageWidget(QWidget *parent) : QWidget(pare } else { scrollArea->setWidget(databaseLoadIndicator); } + + addRecursiveWatch(watcher, SettingsCache::instance().getDeckPath()); + + // Signals for changes + connect(&watcher, &QFileSystemWatcher::fileChanged, this, &VisualDeckStorageWidget::refreshIfPossible); + connect(&watcher, &QFileSystemWatcher::directoryChanged, this, &VisualDeckStorageWidget::refreshIfPossible); +} + +void VisualDeckStorageWidget::refreshIfPossible() +{ + if (scrollArea->widget() != databaseLoadIndicator) { + createRootFolderWidget(); + } +} + +void VisualDeckStorageWidget::addRecursiveWatch(QFileSystemWatcher &watcher, const QString &dirPath) +{ + QDir dir(dirPath); + watcher.addPath(dirPath); // Watch the root directory + + for (const QFileInfo &entry : dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot)) { + addRecursiveWatch(watcher, entry.absoluteFilePath()); + } } void VisualDeckStorageWidget::showEvent(QShowEvent *event) @@ -132,6 +169,7 @@ void VisualDeckStorageWidget::retranslateUi() tagFilterVisibilityCheckBox->setText(tr("Show Tag Filter")); tagsOnWidgetsVisibilityCheckBox->setText(tr("Show Tags On Deck Previews")); drawUnusedColorIdentitiesCheckBox->setText(tr("Draw not contained Color Identities")); + bannerCardComboBoxVisibilityCheckBox->setText(tr("Show Banner Card Selection Option")); } void VisualDeckStorageWidget::deckPreviewClickedEvent(QMouseEvent *event, DeckPreviewWidget *instance) diff --git a/cockatrice/src/client/ui/widgets/visual_deck_storage/visual_deck_storage_widget.h b/cockatrice/src/client/ui/widgets/visual_deck_storage/visual_deck_storage_widget.h index b6ced6375..b2eee6ab4 100644 --- a/cockatrice/src/client/ui/widgets/visual_deck_storage/visual_deck_storage_widget.h +++ b/cockatrice/src/client/ui/widgets/visual_deck_storage/visual_deck_storage_widget.h @@ -14,6 +14,7 @@ #include #include +#include class VisualDeckStorageSearchWidget; class VisualDeckStorageSortWidget; @@ -25,6 +26,8 @@ class VisualDeckStorageWidget final : public QWidget Q_OBJECT public: explicit VisualDeckStorageWidget(QWidget *parent); + void refreshIfPossible(); + void addRecursiveWatch(QFileSystemWatcher &watcher, const QString &dirPath); void retranslateUi(); CardSizeWidget *cardSizeWidget; @@ -61,13 +64,16 @@ private: VisualDeckStorageSortWidget *sortWidget; VisualDeckStorageSearchWidget *searchWidget; DeckPreviewColorIdentityFilterWidget *deckPreviewColorIdentityFilterWidget; + QToolButton *refreshButton; SettingsButtonWidget *quickSettingsWidget; QCheckBox *showFoldersCheckBox; QCheckBox *drawUnusedColorIdentitiesCheckBox; + QCheckBox *bannerCardComboBoxVisibilityCheckBox; QCheckBox *tagFilterVisibilityCheckBox; QCheckBox *tagsOnWidgetsVisibilityCheckBox; QScrollArea *scrollArea; VisualDeckStorageFolderDisplayWidget *folderWidget; + QFileSystemWatcher watcher; }; #endif // VISUAL_DECK_STORAGE_WIDGET_H diff --git a/cockatrice/src/deck/deck_loader.cpp b/cockatrice/src/deck/deck_loader.cpp index ed1d8fa71..5249f1bba 100644 --- a/cockatrice/src/deck/deck_loader.cpp +++ b/cockatrice/src/deck/deck_loader.cpp @@ -162,6 +162,10 @@ bool DeckLoader::saveToFile(const QString &fileName, FileFormat fmt) lastFileName = fileName; lastFileFormat = fmt; } + + file.flush(); + file.close(); + return result; } diff --git a/cockatrice/src/settings/cache_settings.cpp b/cockatrice/src/settings/cache_settings.cpp index c8f2aa737..58e16f24b 100644 --- a/cockatrice/src/settings/cache_settings.cpp +++ b/cockatrice/src/settings/cache_settings.cpp @@ -264,6 +264,8 @@ SettingsCache::SettingsCache() visualDeckStorageSortingOrder = settings->value("interface/visualdeckstoragesortingorder", 0).toInt(); visualDeckStorageShowFolders = settings->value("interface/visualdeckstorageshowfolders", true).toBool(); visualDeckStorageShowTagFilter = settings->value("interface/visualdeckstorageshowtagfilter", true).toBool(); + visualDeckStorageShowBannerCardComboBox = + settings->value("interface/visualdeckstorageshowbannercardcombobox", true).toBool(); visualDeckStorageShowTagsOnDeckPreviews = settings->value("interface/visualdeckstorageshowtagsondeckpreviews", true).toBool(); visualDeckStorageDrawUnusedColorIdentities = @@ -670,6 +672,13 @@ void SettingsCache::setVisualDeckStorageShowTagFilter(QT_STATE_CHANGED_T _showTa emit visualDeckStorageShowTagFilterChanged(visualDeckStorageShowTagFilter); } +void SettingsCache::setVisualDeckStorageShowBannerCardComboBox(QT_STATE_CHANGED_T _showBannerCardComboBox) +{ + visualDeckStorageShowBannerCardComboBox = _showBannerCardComboBox; + settings->setValue("interface/visualdeckstorageshowbannercardcombobox", visualDeckStorageShowBannerCardComboBox); + emit visualDeckStorageShowBannerCardComboBoxChanged(visualDeckStorageShowBannerCardComboBox); +} + void SettingsCache::setVisualDeckStorageShowTagsOnDeckPreviews(QT_STATE_CHANGED_T _showTags) { visualDeckStorageShowTagsOnDeckPreviews = _showTags; diff --git a/cockatrice/src/settings/cache_settings.h b/cockatrice/src/settings/cache_settings.h index ff89bb9e9..bb23394e0 100644 --- a/cockatrice/src/settings/cache_settings.h +++ b/cockatrice/src/settings/cache_settings.h @@ -60,6 +60,7 @@ signals: void printingSelectorCardSizeChanged(); void printingSelectorNavigationButtonsVisibleChanged(); void visualDeckStorageShowTagFilterChanged(bool _visible); + void visualDeckStorageShowBannerCardComboBoxChanged(bool _visible); void visualDeckStorageShowTagsOnDeckPreviewsChanged(bool _visible); void visualDeckStorageCardSizeChanged(); void visualDeckStorageDrawUnusedColorIdentitiesChanged(bool _visible); @@ -129,6 +130,7 @@ private: bool printingSelectorNavigationButtonsVisible; int visualDeckStorageSortingOrder; bool visualDeckStorageShowFolders; + bool visualDeckStorageShowBannerCardComboBox; bool visualDeckStorageShowTagsOnDeckPreviews; bool visualDeckStorageShowTagFilter; int visualDeckStorageCardSize; @@ -412,6 +414,10 @@ public: { return visualDeckStorageShowTagFilter; } + bool getVisualDeckStorageShowBannerCardComboBox() const + { + return visualDeckStorageShowBannerCardComboBox; + } bool getVisualDeckStorageShowTagsOnDeckPreviews() const { return visualDeckStorageShowTagsOnDeckPreviews; @@ -760,6 +766,7 @@ public slots: void setVisualDeckStorageSortingOrder(int _visualDeckStorageSortingOrder); void setVisualDeckStorageShowFolders(QT_STATE_CHANGED_T value); void setVisualDeckStorageShowTagFilter(QT_STATE_CHANGED_T _showTags); + void setVisualDeckStorageShowBannerCardComboBox(QT_STATE_CHANGED_T _showBannerCardComboBox); void setVisualDeckStorageShowTagsOnDeckPreviews(QT_STATE_CHANGED_T _showTags); void setVisualDeckStorageCardSize(int _visualDeckStorageCardSize); void setVisualDeckStorageDrawUnusedColorIdentities(QT_STATE_CHANGED_T _visualDeckStorageDrawUnusedColorIdentities); diff --git a/common/decklist.cpp b/common/decklist.cpp index 164ccdfc6..d395accff 100644 --- a/common/decklist.cpp +++ b/common/decklist.cpp @@ -369,7 +369,7 @@ DeckList::DeckList() // TODO: https://qt-project.org/doc/qt-4.8/qobject.html#no-copy-constructor-or-assignment-operator DeckList::DeckList(const DeckList &other) : QObject(), name(other.name), comments(other.comments), bannerCard(other.bannerCard), deckHash(other.deckHash), - lastLoadedTimestamp(other.lastLoadedTimestamp) + lastLoadedTimestamp(other.lastLoadedTimestamp), tags(other.tags) { root = new InnerDecklistNode(other.getRoot()); @@ -807,6 +807,7 @@ void DeckList::cleanList() root->clearTree(); setName(); setComments(); + setTags(); deckHash = QString(); emit deckHashChanged(); } diff --git a/dbconverter/src/mocks.cpp b/dbconverter/src/mocks.cpp index 21769a5d4..9a76edf84 100644 --- a/dbconverter/src/mocks.cpp +++ b/dbconverter/src/mocks.cpp @@ -208,6 +208,9 @@ void SettingsCache::setVisualDeckStorageShowFolders(QT_STATE_CHANGED_T /* value void SettingsCache::setVisualDeckStorageShowTagFilter(QT_STATE_CHANGED_T /* _showTags */) { } +void SettingsCache::setVisualDeckStorageShowBannerCardComboBox(QT_STATE_CHANGED_T /* _showBannerCardComboBox */) +{ +} void SettingsCache::setVisualDeckStorageShowTagsOnDeckPreviews(QT_STATE_CHANGED_T /* _showTags */) { } diff --git a/tests/carddatabase/mocks.cpp b/tests/carddatabase/mocks.cpp index db813a8f1..0383a81d2 100644 --- a/tests/carddatabase/mocks.cpp +++ b/tests/carddatabase/mocks.cpp @@ -212,6 +212,9 @@ void SettingsCache::setVisualDeckStorageShowFolders(QT_STATE_CHANGED_T /* value void SettingsCache::setVisualDeckStorageShowTagFilter(QT_STATE_CHANGED_T /* _showTags */) { } +void SettingsCache::setVisualDeckStorageShowBannerCardComboBox(QT_STATE_CHANGED_T /* _showBannerCardComboBox */) +{ +} void SettingsCache::setVisualDeckStorageShowTagsOnDeckPreviews(QT_STATE_CHANGED_T /* _showTags */) { }