Allow filters to be saved and restored.

This commit is contained in:
Lukas Brübach 2025-02-26 09:07:20 +01:00
parent 000f0c4b49
commit 1b65818cab
10 changed files with 247 additions and 7 deletions

View file

@ -368,6 +368,14 @@ void TabDeckEditorVisual::actLoadDeck()
deckDockWidget->updateBannerCardComboBox();
}
void TabDeckEditorVisual::actLoadDeckFromClipboard()
{
TabGenericDeckEditor::actLoadDeckFromClipboard();
tabContainer->visualDeckView->updateDisplay();
tabContainer->deckAnalytics->refreshDisplays(deckDockWidget->deckModel);
tabContainer->sampleHandWidget->setDeckModel(deckDockWidget->deckModel);
}
void TabDeckEditorVisual::openDeckFromFile(const QString &fileName, DeckOpenLocation deckOpenLocation)
{
DeckLoader::FileFormat fmt = DeckLoader::getFormatFromName(fileName);

View file

@ -12,6 +12,7 @@ class TabDeckEditorVisual : public TabGenericDeckEditor
protected slots:
void actNewDeck() override;
void actLoadDeck() override;
void actLoadDeckFromClipboard() override;
void loadLayout() override;
void restartLayout() override;

View file

@ -27,7 +27,8 @@ TabDeckEditorVisualTabWidget::TabDeckEditorVisualTabWidget(QWidget *parent,
connect(visualDeckView, SIGNAL(sideboardCardClicked(QMouseEvent *, CardInfoPictureWithTextOverlayWidget *)), this,
SLOT(onSideboardCardClickedDeckEditor(QMouseEvent *, CardInfoPictureWithTextOverlayWidget *)));
visualDatabaseDisplay = new VisualDatabaseDisplayWidget(this, cardDatabaseModel, cardDatabaseDisplayModel);
visualDatabaseDisplay =
new VisualDatabaseDisplayWidget(this, deckEditor, cardDatabaseModel, cardDatabaseDisplayModel);
visualDatabaseDisplay->setObjectName("visualDatabaseView");
connect(visualDatabaseDisplay, SIGNAL(cardHoveredDatabaseDisplay(CardInfoPtr)), this,
SLOT(onCardChangedDatabaseDisplay(CardInfoPtr)));

View file

@ -3,6 +3,7 @@
#include "../../../../game/filters/filter_card.h"
#include "../../../../game/filters/filter_tree_model.h"
#include <QJsonObject>
#include <QMouseEvent>
#include <QPainter>

View file

@ -0,0 +1,124 @@
#include "visual_database_display_filter_save_load_widget.h"
#include "../../../../game/filters/filter_tree.h"
#include <QHBoxLayout>
#include <QJsonArray>
#include <QJsonObject>
VisualDatabaseDisplayFilterSaveLoadWidget::VisualDatabaseDisplayFilterSaveLoadWidget(QWidget *parent,
FilterTreeModel *_filterModel,
const QString &savePath)
: QWidget(parent), filterModel(_filterModel), saveDirectory(savePath)
{
setMinimumWidth(300);
setMaximumHeight(300);
layout = new QVBoxLayout(this);
setLayout(layout);
// Input for filter filename
filenameInput = new QLineEdit(this);
filenameInput->setPlaceholderText(tr("Enter filename..."));
layout->addWidget(filenameInput);
// Save button
saveButton = new QPushButton(tr("Save Filter"), this);
layout->addWidget(saveButton);
connect(saveButton, &QPushButton::clicked, this, &VisualDatabaseDisplayFilterSaveLoadWidget::saveFilter);
// File list container
fileListWidget = new FlowWidget(this, Qt::Vertical, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAsNeeded);
layout->addWidget(fileListWidget);
refreshFilterList(); // Populate the file list on startup
}
void VisualDatabaseDisplayFilterSaveLoadWidget::saveFilter()
{
QString filename = filenameInput->text().trimmed();
if (filename.isEmpty())
return;
QString filePath = saveDirectory + "/" + filename + ".json";
// Serialize the filter model to JSON
QJsonArray filtersArray;
QList<const CardFilter *> cardFilters = filterModel->allFilters();
for (const CardFilter *filter : cardFilters) {
filtersArray.append(filter->toJson()); // Assuming toJson() returns a QJsonObject
}
QJsonObject root;
root["filters"] = filtersArray;
QFile file(filePath);
if (file.open(QIODevice::WriteOnly)) {
file.write(QJsonDocument(root).toJson(QJsonDocument::Indented));
file.close();
}
filenameInput->clear();
refreshFilterList(); // Update the file list
}
void VisualDatabaseDisplayFilterSaveLoadWidget::loadFilter(const QString &filename)
{
QString filePath = saveDirectory + "/" + filename;
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly))
return;
QByteArray jsonData = file.readAll();
file.close();
QJsonDocument doc = QJsonDocument::fromJson(jsonData);
if (!doc.isObject())
return;
QJsonObject root = doc.object();
if (!root.contains("filters") || !root["filters"].isArray())
return;
QJsonArray filtersArray = root["filters"].toArray();
filterModel->clear();
filterModel->blockSignals(true);
filterModel->filterTree()->blockSignals(true);
for (const QJsonValue &value : filtersArray) {
if (value.isObject()) {
QJsonObject filterObj = value.toObject();
CardFilter *filter = CardFilter::fromJson(filterObj);
if (filter)
filterModel->addFilter(filter);
}
}
filterModel->blockSignals(false);
filterModel->filterTree()->blockSignals(false);
filterModel->filterTree()->nodeAt(0)->nodeChanged();
emit filterModel->layoutChanged();
}
void VisualDatabaseDisplayFilterSaveLoadWidget::refreshFilterList()
{
// Clear existing file buttons
for (auto button : fileButtons) {
delete button;
}
fileButtons.clear();
QDir dir(saveDirectory);
QStringList filterFiles = dir.entryList(QStringList() << "*.json", QDir::Files, QDir::Time);
for (const QString &filename : filterFiles) {
auto *button = new QPushButton(filename, fileListWidget);
fileListWidget->addWidget(button);
fileButtons[filename] = button;
connect(button, &QPushButton::clicked, this, [this, filename]() { loadFilter(filename); });
}
}

View file

@ -0,0 +1,42 @@
#ifndef VISUAL_DATABASE_DISPLAY_FILTER_SAVE_LOAD_WIDGET_H
#define VISUAL_DATABASE_DISPLAY_FILTER_SAVE_LOAD_WIDGET_H
#include "../../../../game/filters/filter_tree_model.h"
#include "../general/layout_containers/flow_widget.h"
#include <QDir>
#include <QFile>
#include <QFileDialog>
#include <QJsonDocument>
#include <QJsonObject>
#include <QLineEdit>
#include <QMap>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>
class VisualDatabaseDisplayFilterSaveLoadWidget : public QWidget
{
Q_OBJECT
public:
explicit VisualDatabaseDisplayFilterSaveLoadWidget(QWidget *parent,
FilterTreeModel *filterModel,
const QString &savePath);
void saveFilter();
void loadFilter(const QString &filename);
void refreshFilterList();
private:
FilterTreeModel *filterModel;
QString saveDirectory;
QVBoxLayout *layout;
QLineEdit *filenameInput;
QPushButton *saveButton;
FlowWidget *fileListWidget;
QMap<QString, QPushButton *> fileButtons;
};
#endif // VISUAL_DATABASE_DISPLAY_FILTER_SAVE_LOAD_WIDGET_H

View file

@ -1,10 +1,13 @@
#include "visual_database_display_name_filter_widget.h"
#include "../../../tabs/tab_generic_deck_editor.h"
#include <QHBoxLayout>
VisualDatabaseDisplayNameFilterWidget::VisualDatabaseDisplayNameFilterWidget(QWidget *parent,
TabGenericDeckEditor *_deckEditor,
FilterTreeModel *_filterModel)
: QWidget(parent), filterModel(_filterModel)
: QWidget(parent), deckEditor(_deckEditor), filterModel(_filterModel)
{
setMinimumWidth(300);
setMaximumHeight(300);
@ -22,12 +25,46 @@ VisualDatabaseDisplayNameFilterWidget::VisualDatabaseDisplayNameFilterWidget(QWi
if (!text.isEmpty() && !activeFilters.contains(text)) {
createNameFilter(text);
searchBox->clear();
updateFilterModel();
}
});
// Create container for active filters
flowWidget = new FlowWidget(this, Qt::Horizontal, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAsNeeded);
layout->addWidget(flowWidget);
loadFromDeckButton = new QPushButton(this);
loadFromDeckButton->setText(tr("Load from Deck"));
layout->addWidget(loadFromDeckButton);
connect(loadFromDeckButton, &QPushButton::clicked, this, &VisualDatabaseDisplayNameFilterWidget::actLoadFromDeck);
}
void VisualDatabaseDisplayNameFilterWidget::actLoadFromDeck()
{
DeckListModel *deck_list_model = deckEditor->deckDockWidget->deckModel;
if (!deck_list_model)
return;
DeckList *decklist = deck_list_model->getDeckList();
if (!decklist)
return;
InnerDecklistNode *listRoot = decklist->getRoot();
if (!listRoot)
return;
for (int i = 0; i < listRoot->size(); i++) {
InnerDecklistNode *currentZone = dynamic_cast<InnerDecklistNode *>(listRoot->at(i));
if (!currentZone)
continue;
for (int j = 0; j < currentZone->size(); j++) {
DecklistCardNode *currentCard = dynamic_cast<DecklistCardNode *>(currentZone->at(j));
if (!currentCard)
continue;
createNameFilter(currentCard->getName());
}
}
updateFilterModel();
}
void VisualDatabaseDisplayNameFilterWidget::createNameFilter(const QString &name)
@ -44,8 +81,6 @@ void VisualDatabaseDisplayNameFilterWidget::createNameFilter(const QString &name
flowWidget->addWidget(button);
activeFilters[name] = button;
updateFilterModel();
}
void VisualDatabaseDisplayNameFilterWidget::removeNameFilter(const QString &name)
@ -60,10 +95,20 @@ void VisualDatabaseDisplayNameFilterWidget::removeNameFilter(const QString &name
void VisualDatabaseDisplayNameFilterWidget::updateFilterModel()
{
// Clear existing name filters
emit filterModel->layoutAboutToBeChanged();
filterModel->clearFiltersOfType(CardFilter::Attr::AttrName);
filterModel->blockSignals(true);
filterModel->filterTree()->blockSignals(true);
for (const auto &name : activeFilters.keys()) {
QString nameString = name;
filterModel->addFilter(new CardFilter(nameString, CardFilter::Type::TypeOr, CardFilter::Attr::AttrName));
}
filterModel->blockSignals(false);
filterModel->filterTree()->blockSignals(false);
filterModel->filterTree()->nodeAt(0)->nodeChanged();
emit filterModel->layoutChanged();
}

View file

@ -2,6 +2,7 @@
#define VISUAL_DATABASE_DISPLAY_NAME_FILTER_WIDGET_H
#include "../../../../game/filters/filter_tree_model.h"
#include "../../../tabs/tab_generic_deck_editor.h"
#include "../general/layout_containers/flow_widget.h"
#include <QLineEdit>
@ -14,7 +15,9 @@ class VisualDatabaseDisplayNameFilterWidget : public QWidget
{
Q_OBJECT
public:
explicit VisualDatabaseDisplayNameFilterWidget(QWidget *parent, FilterTreeModel *filterModel);
explicit VisualDatabaseDisplayNameFilterWidget(QWidget *parent,
TabGenericDeckEditor *deckEditor,
FilterTreeModel *filterModel);
void createNameFilter(const QString &name);
void removeNameFilter(const QString &name);
@ -22,12 +25,17 @@ public:
void updateFilterModel();
private:
TabGenericDeckEditor *deckEditor;
FilterTreeModel *filterModel;
QVBoxLayout *layout;
QLineEdit *searchBox;
FlowWidget *flowWidget;
QPushButton *loadFromDeckButton;
QMap<QString, QPushButton *> activeFilters; // Store active name filter buttons
private slots:
void actLoadFromDeck();
};
#endif // VISUAL_DATABASE_DISPLAY_NAME_FILTER_WIDGET_H

View file

@ -9,6 +9,7 @@
#include "../cards/card_info_picture_with_text_overlay_widget.h"
#include "../quick_settings/settings_button_widget.h"
#include "visual_database_display_color_filter_widget.h"
#include "visual_database_display_filter_save_load_widget.h"
#include "visual_database_display_main_type_filter_widget.h"
#include "visual_database_display_name_filter_widget.h"
#include "visual_database_display_set_filter_widget.h"
@ -19,9 +20,11 @@
#include <qpropertyanimation.h>
VisualDatabaseDisplayWidget::VisualDatabaseDisplayWidget(QWidget *parent,
TabGenericDeckEditor *_deckEditor,
CardDatabaseModel *database_model,
CardDatabaseDisplayModel *database_display_model)
: QWidget(parent), databaseModel(database_model), databaseDisplayModel(database_display_model)
: QWidget(parent), deckEditor(_deckEditor), databaseModel(database_model),
databaseDisplayModel(database_display_model)
{
cards = new QList<CardInfoPtr>;
connect(databaseDisplayModel, &CardDatabaseDisplayModel::modelDirty, this,
@ -53,7 +56,11 @@ VisualDatabaseDisplayWidget::VisualDatabaseDisplayWidget(QWidget *parent,
filterModel->setObjectName("filterModel");
databaseDisplayModel->setFilterTree(filterModel->filterTree());
auto nameFilterWidget = new VisualDatabaseDisplayNameFilterWidget(this, filterModel);
auto saveLoadWidget =
new VisualDatabaseDisplayFilterSaveLoadWidget(this, filterModel, "/home/ascor/Cockatrice_presets/");
quickFilterWidget->addSettingsWidget(saveLoadWidget);
auto nameFilterWidget = new VisualDatabaseDisplayNameFilterWidget(this, deckEditor, filterModel);
quickFilterWidget->addSettingsWidget(nameFilterWidget);
auto mainTypeFilterWidget = new VisualDatabaseDisplayMainTypeFilterWidget(this, filterModel);

View file

@ -7,6 +7,7 @@
#include "../../../../game/cards/card_database_model.h"
#include "../../../../game/filters/filter_tree_model.h"
#include "../../../game_logic/key_signals.h"
#include "../../../tabs/tab_generic_deck_editor.h"
#include "../../layouts/flow_layout.h"
#include "../cards/card_info_picture_with_text_overlay_widget.h"
#include "../cards/card_size_widget.h"
@ -29,6 +30,7 @@ class VisualDatabaseDisplayWidget : public QWidget
public:
explicit VisualDatabaseDisplayWidget(QWidget *parent,
TabGenericDeckEditor *deckEditor,
CardDatabaseModel *database_model,
CardDatabaseDisplayModel *database_display_model);
@ -61,6 +63,7 @@ protected slots:
private:
KeySignals searchKeySignals;
TabGenericDeckEditor *deckEditor;
CardDatabaseModel *databaseModel;
CardDatabaseDisplayModel *databaseDisplayModel;
QTreeView *databaseView;