mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-09-23 01:55:10 -07:00
[Card] Add a Tags filter to the visual card database
This commit is contained in:
parent
0ea0e231bf
commit
ea38af774a
9 changed files with 288 additions and 2 deletions
|
|
@ -311,6 +311,7 @@ set(cockatrice_SOURCES
|
||||||
src/interface/widgets/visual_database_display/visual_database_display_name_filter_widget.cpp
|
src/interface/widgets/visual_database_display/visual_database_display_name_filter_widget.cpp
|
||||||
src/interface/widgets/visual_database_display/visual_database_display_set_filter_widget.cpp
|
src/interface/widgets/visual_database_display/visual_database_display_set_filter_widget.cpp
|
||||||
src/interface/widgets/visual_database_display/visual_database_display_sub_type_filter_widget.cpp
|
src/interface/widgets/visual_database_display/visual_database_display_sub_type_filter_widget.cpp
|
||||||
|
src/interface/widgets/visual_database_display/visual_database_display_tag_filter_widget.cpp
|
||||||
src/interface/widgets/visual_database_display/visual_database_display_widget.cpp
|
src/interface/widgets/visual_database_display/visual_database_display_widget.cpp
|
||||||
src/interface/widgets/visual_database_display/visual_database_filter_display_widget.cpp
|
src/interface/widgets/visual_database_display/visual_database_filter_display_widget.cpp
|
||||||
src/interface/widgets/visual_deck_editor/visual_deck_display_options_widget.cpp
|
src/interface/widgets/visual_deck_editor/visual_deck_display_options_widget.cpp
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@
|
||||||
<file>resources/icons/swap.svg</file>
|
<file>resources/icons/swap.svg</file>
|
||||||
<file>resources/icons/sync.svg</file>
|
<file>resources/icons/sync.svg</file>
|
||||||
<file>resources/icons/tab_changed.svg</file>
|
<file>resources/icons/tab_changed.svg</file>
|
||||||
|
<file>resources/icons/tags.svg</file>
|
||||||
<file>resources/icons/update.png</file>
|
<file>resources/icons/update.png</file>
|
||||||
<file>resources/icons/view.svg</file>
|
<file>resources/icons/view.svg</file>
|
||||||
|
|
||||||
|
|
|
||||||
1
cockatrice/resources/icons/tags.svg
Normal file
1
cockatrice/resources/icons/tags.svg
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--!Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path fill="#000000" d="M401.2 39.1L549.4 189.4c27.7 28.1 27.7 73.1 0 101.2L393 448.9c-9.3 9.4-24.5 9.5-33.9 .2s-9.5-24.5-.2-33.9L515.3 256.8c9.2-9.3 9.2-24.4 0-33.7L367 72.9c-9.3-9.4-9.2-24.6 .2-33.9s24.6-9.2 33.9 .2zM32.1 229.5L32.1 96c0-35.3 28.7-64 64-64l133.5 0c17 0 33.3 6.7 45.3 18.7l144 144c25 25 25 65.5 0 90.5L285.4 418.7c-25 25-65.5 25-90.5 0l-144-144c-12-12-18.7-28.3-18.7-45.3zm144-85.5a32 32 0 1 0 -64 0 32 32 0 1 0 64 0z"/></svg>
|
||||||
|
After Width: | Height: | Size: 658 B |
|
|
@ -78,6 +78,9 @@ VisualDatabaseDisplayFilterToolbarWidget::VisualDatabaseDisplayFilterToolbarWidg
|
||||||
quickFilterFormatLegalityWidget = new SettingsButtonWidget(this);
|
quickFilterFormatLegalityWidget = new SettingsButtonWidget(this);
|
||||||
quickFilterFormatLegalityWidget->setButtonIcon(themePixmap(QStringLiteral("icons/scale_balanced")));
|
quickFilterFormatLegalityWidget->setButtonIcon(themePixmap(QStringLiteral("icons/scale_balanced")));
|
||||||
|
|
||||||
|
quickFilterTagWidget = new SettingsButtonWidget(this);
|
||||||
|
quickFilterTagWidget->setButtonIcon(themePixmap(QStringLiteral("icons/tags")));
|
||||||
|
|
||||||
retranslateUi();
|
retranslateUi();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -102,6 +105,7 @@ void VisualDatabaseDisplayFilterToolbarWidget::initialize()
|
||||||
formatLegalityWidget = new VisualDatabaseDisplayFormatLegalityFilterWidget(this, filterModel);
|
formatLegalityWidget = new VisualDatabaseDisplayFormatLegalityFilterWidget(this, filterModel);
|
||||||
subTypeFilterWidget = new VisualDatabaseDisplaySubTypeFilterWidget(this, filterModel);
|
subTypeFilterWidget = new VisualDatabaseDisplaySubTypeFilterWidget(this, filterModel);
|
||||||
setFilterWidget = new VisualDatabaseDisplaySetFilterWidget(this, filterModel);
|
setFilterWidget = new VisualDatabaseDisplaySetFilterWidget(this, filterModel);
|
||||||
|
tagFilterWidget = new VisualDatabaseDisplayTagFilterWidget(this, filterModel);
|
||||||
|
|
||||||
quickFilterSaveLoadWidget->addSettingsWidget(saveLoadWidget);
|
quickFilterSaveLoadWidget->addSettingsWidget(saveLoadWidget);
|
||||||
quickFilterNameWidget->addSettingsWidget(nameFilterWidget);
|
quickFilterNameWidget->addSettingsWidget(nameFilterWidget);
|
||||||
|
|
@ -109,6 +113,7 @@ void VisualDatabaseDisplayFilterToolbarWidget::initialize()
|
||||||
quickFilterSubTypeWidget->addSettingsWidget(subTypeFilterWidget);
|
quickFilterSubTypeWidget->addSettingsWidget(subTypeFilterWidget);
|
||||||
quickFilterSetWidget->addSettingsWidget(setFilterWidget);
|
quickFilterSetWidget->addSettingsWidget(setFilterWidget);
|
||||||
quickFilterFormatLegalityWidget->addSettingsWidget(formatLegalityWidget);
|
quickFilterFormatLegalityWidget->addSettingsWidget(formatLegalityWidget);
|
||||||
|
quickFilterTagWidget->addSettingsWidget(tagFilterWidget);
|
||||||
|
|
||||||
// fill groupbox layouts
|
// fill groupbox layouts
|
||||||
sortLayout->addWidget(sortByLabel);
|
sortLayout->addWidget(sortByLabel);
|
||||||
|
|
@ -121,6 +126,7 @@ void VisualDatabaseDisplayFilterToolbarWidget::initialize()
|
||||||
filterLayout->addWidget(quickFilterSubTypeWidget);
|
filterLayout->addWidget(quickFilterSubTypeWidget);
|
||||||
filterLayout->addWidget(quickFilterSetWidget);
|
filterLayout->addWidget(quickFilterSetWidget);
|
||||||
filterLayout->addWidget(quickFilterFormatLegalityWidget);
|
filterLayout->addWidget(quickFilterFormatLegalityWidget);
|
||||||
|
filterLayout->addWidget(quickFilterTagWidget);
|
||||||
|
|
||||||
// put everything into main layout
|
// put everything into main layout
|
||||||
addWidget(sortGroupBox);
|
addWidget(sortGroupBox);
|
||||||
|
|
@ -148,6 +154,7 @@ void VisualDatabaseDisplayFilterToolbarWidget::retranslateUi()
|
||||||
quickFilterSubTypeWidget->setToolTip(tr("Filter by card sub-type"));
|
quickFilterSubTypeWidget->setToolTip(tr("Filter by card sub-type"));
|
||||||
quickFilterSetWidget->setToolTip(tr("Filter by set"));
|
quickFilterSetWidget->setToolTip(tr("Filter by set"));
|
||||||
quickFilterFormatLegalityWidget->setToolTip(tr("Filter by format legality"));
|
quickFilterFormatLegalityWidget->setToolTip(tr("Filter by format legality"));
|
||||||
|
quickFilterTagWidget->setToolTip(tr("Filter by Scryfall Tagger tag"));
|
||||||
|
|
||||||
quickFilterSaveLoadWidget->setButtonText(tr("Save/Load"));
|
quickFilterSaveLoadWidget->setButtonText(tr("Save/Load"));
|
||||||
quickFilterNameWidget->setButtonText(tr("Name"));
|
quickFilterNameWidget->setButtonText(tr("Name"));
|
||||||
|
|
@ -155,6 +162,7 @@ void VisualDatabaseDisplayFilterToolbarWidget::retranslateUi()
|
||||||
quickFilterSubTypeWidget->setButtonText(tr("Sub Type"));
|
quickFilterSubTypeWidget->setButtonText(tr("Sub Type"));
|
||||||
quickFilterSetWidget->setButtonText(tr("Sets"));
|
quickFilterSetWidget->setButtonText(tr("Sets"));
|
||||||
quickFilterFormatLegalityWidget->setButtonText(tr("Formats"));
|
quickFilterFormatLegalityWidget->setButtonText(tr("Formats"));
|
||||||
|
quickFilterTagWidget->setButtonText(tr("Tags"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void VisualDatabaseDisplayFilterToolbarWidget::resizeEvent(QResizeEvent *event)
|
void VisualDatabaseDisplayFilterToolbarWidget::resizeEvent(QResizeEvent *event)
|
||||||
|
|
@ -168,8 +176,8 @@ void VisualDatabaseDisplayFilterToolbarWidget::updateCompactMode(int availableWi
|
||||||
const bool compact = availableWidth < fullWidthHint;
|
const bool compact = availableWidth < fullWidthHint;
|
||||||
|
|
||||||
const QList<SettingsButtonWidget *> filterButtons = {
|
const QList<SettingsButtonWidget *> filterButtons = {
|
||||||
quickFilterSaveLoadWidget, quickFilterNameWidget, quickFilterMainTypeWidget,
|
quickFilterSaveLoadWidget, quickFilterNameWidget, quickFilterMainTypeWidget, quickFilterSubTypeWidget,
|
||||||
quickFilterSubTypeWidget, quickFilterSetWidget, quickFilterFormatLegalityWidget,
|
quickFilterSetWidget, quickFilterFormatLegalityWidget, quickFilterTagWidget,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (auto *btn : filterButtons) {
|
for (auto *btn : filterButtons) {
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#include "visual_database_display_name_filter_widget.h"
|
#include "visual_database_display_name_filter_widget.h"
|
||||||
#include "visual_database_display_set_filter_widget.h"
|
#include "visual_database_display_set_filter_widget.h"
|
||||||
#include "visual_database_display_sub_type_filter_widget.h"
|
#include "visual_database_display_sub_type_filter_widget.h"
|
||||||
|
#include "visual_database_display_tag_filter_widget.h"
|
||||||
|
|
||||||
class VisualDatabaseDisplayWidget;
|
class VisualDatabaseDisplayWidget;
|
||||||
|
|
||||||
|
|
@ -46,6 +47,8 @@ private:
|
||||||
VisualDatabaseDisplaySetFilterWidget *setFilterWidget;
|
VisualDatabaseDisplaySetFilterWidget *setFilterWidget;
|
||||||
SettingsButtonWidget *quickFilterFormatLegalityWidget;
|
SettingsButtonWidget *quickFilterFormatLegalityWidget;
|
||||||
VisualDatabaseDisplayFormatLegalityFilterWidget *formatLegalityWidget;
|
VisualDatabaseDisplayFormatLegalityFilterWidget *formatLegalityWidget;
|
||||||
|
SettingsButtonWidget *quickFilterTagWidget;
|
||||||
|
VisualDatabaseDisplayTagFilterWidget *tagFilterWidget;
|
||||||
|
|
||||||
int fullWidthHint = 0;
|
int fullWidthHint = 0;
|
||||||
void updateCompactMode(int availableWidth);
|
void updateCompactMode(int availableWidth);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,197 @@
|
||||||
|
#include "visual_database_display_tag_filter_widget.h"
|
||||||
|
|
||||||
|
#include "../../../filters/filter_tree_model.h"
|
||||||
|
#include "visual_database_display_filter_button.h"
|
||||||
|
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QSpinBox>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <libcockatrice/card/database/card_database_manager.h>
|
||||||
|
#include <libcockatrice/filters/filter_tree.h>
|
||||||
|
|
||||||
|
VisualDatabaseDisplayTagFilterWidget::VisualDatabaseDisplayTagFilterWidget(QWidget *parent,
|
||||||
|
FilterTreeModel *_filterModel)
|
||||||
|
: QWidget(parent), filterModel(_filterModel)
|
||||||
|
{
|
||||||
|
allTagsWithCount = CardDatabaseManager::query()->getAllTagsWithCount();
|
||||||
|
|
||||||
|
setMinimumWidth(300);
|
||||||
|
setMaximumHeight(300);
|
||||||
|
|
||||||
|
layout = new QVBoxLayout(this);
|
||||||
|
setLayout(layout);
|
||||||
|
layout->setContentsMargins(0, 1, 0, 1);
|
||||||
|
layout->setSpacing(1);
|
||||||
|
layout->setAlignment(Qt::AlignTop);
|
||||||
|
|
||||||
|
// Create search box
|
||||||
|
searchBox = new QLineEdit(this);
|
||||||
|
layout->addWidget(searchBox);
|
||||||
|
connect(searchBox, &QLineEdit::textChanged, this,
|
||||||
|
&VisualDatabaseDisplayTagFilterWidget::updateTagButtonsVisibility);
|
||||||
|
|
||||||
|
flowWidget = new FlowWidget(this, Qt::Horizontal, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAsNeeded);
|
||||||
|
layout->addWidget(flowWidget);
|
||||||
|
|
||||||
|
// Create a container for the threshold control
|
||||||
|
auto *thresholdLayout = new QHBoxLayout();
|
||||||
|
thresholdLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
|
||||||
|
thresholdLabel = new QLabel(this);
|
||||||
|
thresholdLayout->addWidget(thresholdLabel);
|
||||||
|
|
||||||
|
// Create the spinbox
|
||||||
|
spinBox = new QSpinBox(this);
|
||||||
|
spinBox->setMinimum(1);
|
||||||
|
spinBox->setMaximum(getMaxTagCount());
|
||||||
|
spinBox->setValue(150);
|
||||||
|
thresholdLayout->addWidget(spinBox);
|
||||||
|
thresholdLayout->addStretch();
|
||||||
|
|
||||||
|
layout->addLayout(thresholdLayout);
|
||||||
|
|
||||||
|
connect(spinBox, qOverload<int>(&QSpinBox::valueChanged), this,
|
||||||
|
&VisualDatabaseDisplayTagFilterWidget::updateTagButtonsVisibility);
|
||||||
|
|
||||||
|
// Create the toggle button for Exact Match/Includes mode
|
||||||
|
toggleButton = new QPushButton(this);
|
||||||
|
layout->addWidget(toggleButton);
|
||||||
|
connect(toggleButton, &QPushButton::clicked, this, &VisualDatabaseDisplayTagFilterWidget::updateFilterMode);
|
||||||
|
connect(filterModel, &FilterTreeModel::layoutChanged, this,
|
||||||
|
[this]() { QTimer::singleShot(100, this, &VisualDatabaseDisplayTagFilterWidget::syncWithFilterModel); });
|
||||||
|
|
||||||
|
createTagButtons(); // Populate buttons initially
|
||||||
|
updateFilterMode(); // Initialize toggle button text
|
||||||
|
|
||||||
|
retranslateUi();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VisualDatabaseDisplayTagFilterWidget::retranslateUi()
|
||||||
|
{
|
||||||
|
searchBox->setPlaceholderText(tr("Search tags..."));
|
||||||
|
thresholdLabel->setText(tr("Show tags with at least:"));
|
||||||
|
spinBox->setSuffix(tr(" cards"));
|
||||||
|
spinBox->setToolTip(tr("Do not display tags with less than this amount of cards in the database"));
|
||||||
|
toggleButton->setToolTip(tr("Filter mode (require all selected tags, or any of them)"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void VisualDatabaseDisplayTagFilterWidget::createTagButtons()
|
||||||
|
{
|
||||||
|
// Iterate through tags and create buttons
|
||||||
|
for (auto it = allTagsWithCount.begin(); it != allTagsWithCount.end(); ++it) {
|
||||||
|
auto *button = new QPushButton(it.key(), flowWidget);
|
||||||
|
button->setCheckable(true);
|
||||||
|
button->setStyleSheet(visualDatabaseDisplayFilterButtonStyle);
|
||||||
|
|
||||||
|
flowWidget->addWidget(button);
|
||||||
|
tagButtons[it.key()] = button;
|
||||||
|
|
||||||
|
// Connect toggle signal for each button
|
||||||
|
connect(button, &QPushButton::toggled, this,
|
||||||
|
[this, tag = it.key()](bool checked) { handleTagToggled(tag, checked); });
|
||||||
|
}
|
||||||
|
updateTagButtonsVisibility(); // Ensure visibility is updated initially
|
||||||
|
}
|
||||||
|
|
||||||
|
void VisualDatabaseDisplayTagFilterWidget::updateTagButtonsVisibility()
|
||||||
|
{
|
||||||
|
const int threshold = spinBox->value();
|
||||||
|
const QString filterText = searchBox->text().trimmed().toLower();
|
||||||
|
|
||||||
|
// Iterate through buttons and hide/disable those below the threshold. An
|
||||||
|
// active search overrides the threshold so rare tags stay reachable.
|
||||||
|
for (auto it = tagButtons.begin(); it != tagButtons.end(); ++it) {
|
||||||
|
const bool isActive = activeTags.value(it.key(), false);
|
||||||
|
const bool visible = isActive || (filterText.isEmpty() ? allTagsWithCount[it.key()] >= threshold
|
||||||
|
: it.key().toLower().contains(filterText));
|
||||||
|
|
||||||
|
it.value()->setVisible(visible);
|
||||||
|
it.value()->setEnabled(visible);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int VisualDatabaseDisplayTagFilterWidget::getMaxTagCount() const
|
||||||
|
{
|
||||||
|
int maxCount = 1;
|
||||||
|
for (auto it = allTagsWithCount.begin(); it != allTagsWithCount.end(); ++it) {
|
||||||
|
maxCount = qMax(maxCount, it.value());
|
||||||
|
}
|
||||||
|
return maxCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VisualDatabaseDisplayTagFilterWidget::handleTagToggled(const QString &tag, bool active)
|
||||||
|
{
|
||||||
|
activeTags[tag] = active;
|
||||||
|
|
||||||
|
if (tagButtons.contains(tag)) {
|
||||||
|
tagButtons[tag]->setChecked(active);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateTagFilter();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VisualDatabaseDisplayTagFilterWidget::updateTagFilter()
|
||||||
|
{
|
||||||
|
filterModel->blockSignals(true);
|
||||||
|
filterModel->filterTree()->blockSignals(true);
|
||||||
|
filterModel->clearFiltersOfType(CardFilter::Attr::AttrTag);
|
||||||
|
|
||||||
|
for (const auto &activeTag : activeTags.keys()) {
|
||||||
|
if (activeTags[activeTag]) {
|
||||||
|
QString tag = activeTag;
|
||||||
|
filterModel->addFilter(new CardFilter(
|
||||||
|
tag, exactMatchMode ? CardFilter::Type::TypeAnd : CardFilter::Type::TypeOr, CardFilter::Attr::AttrTag));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
filterModel->blockSignals(false);
|
||||||
|
filterModel->filterTree()->blockSignals(false);
|
||||||
|
|
||||||
|
emit filterModel->filterTree()->changed();
|
||||||
|
emit filterModel->layoutChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VisualDatabaseDisplayTagFilterWidget::updateFilterMode()
|
||||||
|
{
|
||||||
|
exactMatchMode = !exactMatchMode;
|
||||||
|
toggleButton->setText(exactMatchMode ? tr("Mode: Exact Match") : tr("Mode: Includes"));
|
||||||
|
updateTagFilter();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VisualDatabaseDisplayTagFilterWidget::syncWithFilterModel()
|
||||||
|
{
|
||||||
|
// Temporarily block signals for each button to prevent toggling while updating button states
|
||||||
|
for (auto it = tagButtons.begin(); it != tagButtons.end(); ++it) {
|
||||||
|
it.value()->blockSignals(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uncheck all buttons
|
||||||
|
for (auto it = tagButtons.begin(); it != tagButtons.end(); ++it) {
|
||||||
|
it.value()->setChecked(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get active filters for tags
|
||||||
|
QSet<QString> activeTypes;
|
||||||
|
for (const auto &filter : filterModel->getFiltersOfType(CardFilter::AttrTag)) {
|
||||||
|
if (filter->type() == CardFilter::Type::TypeAnd || filter->type() == CardFilter::Type::TypeOr) {
|
||||||
|
activeTypes.insert(filter->term());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the buttons for active tags
|
||||||
|
for (const auto &tag : activeTypes) {
|
||||||
|
activeTags[tag] = true;
|
||||||
|
if (tagButtons.contains(tag)) {
|
||||||
|
tagButtons[tag]->setChecked(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-enable signal emissions for each button
|
||||||
|
for (auto it = tagButtons.begin(); it != tagButtons.end(); ++it) {
|
||||||
|
it.value()->blockSignals(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the visibility of buttons
|
||||||
|
updateTagButtonsVisibility();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
#ifndef COCKATRICE_VISUAL_DATABASE_DISPLAY_TAG_FILTER_WIDGET_H
|
||||||
|
#define COCKATRICE_VISUAL_DATABASE_DISPLAY_TAG_FILTER_WIDGET_H
|
||||||
|
|
||||||
|
#include "../../../filters/filter_tree_model.h"
|
||||||
|
#include "../general/layout_containers/flow_widget.h"
|
||||||
|
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QSpinBox>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
class VisualDatabaseDisplayTagFilterWidget : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit VisualDatabaseDisplayTagFilterWidget(QWidget *parent, FilterTreeModel *filterModel);
|
||||||
|
void retranslateUi();
|
||||||
|
void createTagButtons();
|
||||||
|
void updateTagButtonsVisibility();
|
||||||
|
[[nodiscard]] int getMaxTagCount() const;
|
||||||
|
|
||||||
|
void handleTagToggled(const QString &tag, bool active);
|
||||||
|
void updateTagFilter();
|
||||||
|
void updateFilterMode();
|
||||||
|
void syncWithFilterModel();
|
||||||
|
|
||||||
|
private:
|
||||||
|
FilterTreeModel *filterModel;
|
||||||
|
QMap<QString, int> allTagsWithCount;
|
||||||
|
|
||||||
|
QVBoxLayout *layout;
|
||||||
|
QLineEdit *searchBox;
|
||||||
|
FlowWidget *flowWidget;
|
||||||
|
QLabel *thresholdLabel;
|
||||||
|
QSpinBox *spinBox;
|
||||||
|
QPushButton *toggleButton; // Mode switch button
|
||||||
|
|
||||||
|
QMap<QString, bool> activeTags; // Track active filters
|
||||||
|
QMap<QString, QPushButton *> tagButtons; // Store toggle buttons
|
||||||
|
|
||||||
|
bool exactMatchMode = true; // Toggle between "Exact Match" (all) and "Includes" (any)
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // COCKATRICE_VISUAL_DATABASE_DISPLAY_TAG_FILTER_WIDGET_H
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#include "card_database_querier.h"
|
#include "card_database_querier.h"
|
||||||
|
|
||||||
#include "../card_info.h"
|
#include "../card_info.h"
|
||||||
|
#include "../game_specific_terms.h"
|
||||||
#include "../printing/exact_card.h"
|
#include "../printing/exact_card.h"
|
||||||
#include "../set/card_set_comparator.h"
|
#include "../set/card_set_comparator.h"
|
||||||
#include "card_database.h"
|
#include "card_database.h"
|
||||||
|
|
@ -23,6 +24,7 @@ void CardDatabaseQuerier::invalidateCaches()
|
||||||
mainCardTypeCountsCache.clear();
|
mainCardTypeCountsCache.clear();
|
||||||
subCardTypeCountsCache.clear();
|
subCardTypeCountsCache.clear();
|
||||||
formatsCountCache.clear();
|
formatsCountCache.clear();
|
||||||
|
tagCountsCache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -359,6 +361,21 @@ FormatRulesPtr CardDatabaseQuerier::getFormat(const QString &formatName) const
|
||||||
return db->formats.value(formatName.toLower());
|
return db->formats.value(formatName.toLower());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QMap<QString, int> CardDatabaseQuerier::getAllTagsWithCount() const
|
||||||
|
{
|
||||||
|
if (tagCountsCache.isEmpty()) {
|
||||||
|
for (const auto &card : db->cards.values()) {
|
||||||
|
const QStringList tags = card->getProperty(Mtg::Tags).split(" ", Qt::SkipEmptyParts);
|
||||||
|
|
||||||
|
for (const QString &tag : tags) {
|
||||||
|
tagCountsCache[tag]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tagCountsCache;
|
||||||
|
}
|
||||||
|
|
||||||
QMap<QString, int> CardDatabaseQuerier::getAllFormatsWithCount() const
|
QMap<QString, int> CardDatabaseQuerier::getAllFormatsWithCount() const
|
||||||
{
|
{
|
||||||
if (formatsCountCache.isEmpty()) {
|
if (formatsCountCache.isEmpty()) {
|
||||||
|
|
|
||||||
|
|
@ -214,6 +214,16 @@ public:
|
||||||
* @return Map of subtype string to count.
|
* @return Map of subtype string to count.
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] QMap<QString, int> getAllSubCardTypesWithCount() const;
|
[[nodiscard]] QMap<QString, int> getAllSubCardTypesWithCount() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a mapping of Scryfall Tagger tag slugs to their occurrence counts.
|
||||||
|
*
|
||||||
|
* Tags are stored space-separated in the `tags` card property, so a card
|
||||||
|
* tagged "ramp" and "removal" contributes one to each slug's count.
|
||||||
|
*
|
||||||
|
* @return Map of tag slug to count.
|
||||||
|
*/
|
||||||
|
[[nodiscard]] QMap<QString, int> getAllTagsWithCount() const;
|
||||||
FormatRulesPtr getFormat(const QString &formatName) const;
|
FormatRulesPtr getFormat(const QString &formatName) const;
|
||||||
QMap<QString, int> getAllFormatsWithCount() const;
|
QMap<QString, int> getAllFormatsWithCount() const;
|
||||||
|
|
||||||
|
|
@ -227,6 +237,7 @@ private:
|
||||||
mutable QMap<QString, int> mainCardTypeCountsCache;
|
mutable QMap<QString, int> mainCardTypeCountsCache;
|
||||||
mutable QMap<QString, int> subCardTypeCountsCache;
|
mutable QMap<QString, int> subCardTypeCountsCache;
|
||||||
mutable QMap<QString, int> formatsCountCache;
|
mutable QMap<QString, int> formatsCountCache;
|
||||||
|
mutable QMap<QString, int> tagCountsCache;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void invalidateCaches();
|
void invalidateCaches();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue