Better filtering and analytics.

This commit is contained in:
Lukas Brübach 2025-02-24 15:13:56 +01:00
parent a7b9a86feb
commit 7fb09cd149
28 changed files with 999 additions and 537 deletions

View file

@ -54,11 +54,13 @@ cockatrice_xml.* = false
# card_info = false
# card_list = false
#flow_layout = false
#flow_widget = false
#flow_widget.size = false
visual_database_display = false
# card_info_picture_widget = false
# stack_zone = false
flow_layout.debug = false
flow_widget.debug = false
flow_widget.size.debug = false
overlap_layout.debug = false

View file

@ -58,14 +58,13 @@ TabDeckEditorVisual::TabDeckEditorVisual(TabSupervisor *_tabSupervisor) : TabGen
{
setObjectName("TabDeckEditorVisual");
createSearchAndDatabaseFrame();
databaseDisplayDockWidget = new DeckEditorDatabaseDisplayWidget(this, this);
deckDockWidget = new DeckEditorDeckDockWidget(this, this);
cardInfoDockWidget = new DeckEditorCardInfoDockWidget(this);
filterDockWidget = new DeckEditorFilterDockWidget(this, this);
printingSelectorDockWidget = new DeckEditorPrintingSelectorDockWidget(this, this);
TabDeckEditorVisual::createCentralFrame();
createCentralFrame();
TabDeckEditorVisual::createMenus();
@ -86,10 +85,13 @@ void TabDeckEditorVisual::createCentralFrame()
centralFrame = new QVBoxLayout;
centralWidget->setLayout(centralFrame);
tabContainer = new TabDeckEditorVisualTabWidget(centralWidget, this->deckDockWidget->deckModel, this->databaseModel,
this->databaseDisplayModel);
connect(tabContainer, SIGNAL(cardChanged(CardInfoPtr)), this, SLOT(changeModelIndexAndCardInfo(CardInfoPtr)));
connect(tabContainer, SIGNAL(cardChangedDatabaseDisplay(CardInfoPtr)), this, SLOT(setCurrentCardInfo(CardInfoPtr)));
tabContainer = new TabDeckEditorVisualTabWidget(centralWidget, this, this->deckDockWidget->deckModel,
this->databaseDisplayDockWidget->databaseModel,
this->databaseDisplayDockWidget->databaseDisplayModel);
connect(tabContainer, &TabDeckEditorVisualTabWidget::cardChanged, this,
&TabDeckEditorVisual::changeModelIndexAndCardInfo);
connect(tabContainer, &TabDeckEditorVisualTabWidget::cardChangedDatabaseDisplay, this,
&TabGenericDeckEditor::updateCardInfo);
connect(tabContainer, SIGNAL(mainboardCardClicked(QMouseEvent *, CardInfoPictureWithTextOverlayWidget *)), this,
SLOT(processMainboardCardClick(QMouseEvent *, CardInfoPictureWithTextOverlayWidget *)));
connect(tabContainer, SIGNAL(sideboardCardClicked(QMouseEvent *, CardInfoPictureWithTextOverlayWidget *)), this,
@ -103,100 +105,6 @@ void TabDeckEditorVisual::createCentralFrame()
setDockOptions(QMainWindow::AnimatedDocks | QMainWindow::AllowNestedDocks | QMainWindow::AllowTabbedDocks);
}
void TabDeckEditorVisual::createSearchAndDatabaseFrame()
{
searchEdit = new SearchLineEdit;
searchEdit->setObjectName("searchEdit");
searchEdit->setPlaceholderText(tr("Search by card name (or search expressions)"));
searchEdit->setClearButtonEnabled(true);
searchEdit->addAction(loadColorAdjustedPixmap("theme:icons/search"), QLineEdit::LeadingPosition);
auto help = searchEdit->addAction(QPixmap("theme:icons/info"), QLineEdit::TrailingPosition);
searchEdit->installEventFilter(&searchKeySignals);
setFocusProxy(searchEdit);
setFocusPolicy(Qt::ClickFocus);
searchKeySignals.setObjectName("searchKeySignals");
connect(searchEdit, SIGNAL(textChanged(const QString &)), this, SLOT(updateSearch(const QString &)));
connect(&searchKeySignals, SIGNAL(onEnter()), this, SLOT(actAddCard()));
connect(&searchKeySignals, SIGNAL(onCtrlAltEqual()), this, SLOT(actAddCard()));
connect(&searchKeySignals, SIGNAL(onCtrlAltRBracket()), this, SLOT(actAddCardToSideboard()));
connect(&searchKeySignals, SIGNAL(onCtrlAltMinus()), this, SLOT(actDecrementCard()));
connect(&searchKeySignals, SIGNAL(onCtrlAltLBracket()), this, SLOT(actDecrementCardFromSideboard()));
connect(&searchKeySignals, SIGNAL(onCtrlAltEnter()), this, SLOT(actAddCardToSideboard()));
connect(&searchKeySignals, SIGNAL(onCtrlEnter()), this, SLOT(actAddCardToSideboard()));
connect(&searchKeySignals, SIGNAL(onCtrlC()), this, SLOT(copyDatabaseCellContents()));
connect(help, &QAction::triggered, this, &TabDeckEditorVisual::showSearchSyntaxHelp);
databaseModel = new CardDatabaseModel(CardDatabaseManager::getInstance(), true, this);
databaseModel->setObjectName("databaseModel");
databaseDisplayModel = new CardDatabaseDisplayModel(this);
databaseDisplayModel->setSourceModel(databaseModel);
databaseDisplayModel->setFilterKeyColumn(0);
databaseView = new QTreeView();
databaseView->setObjectName("databaseView");
databaseView->setFocusProxy(searchEdit);
databaseView->setUniformRowHeights(true);
databaseView->setRootIsDecorated(false);
databaseView->setAlternatingRowColors(true);
databaseView->setSortingEnabled(true);
databaseView->sortByColumn(0, Qt::AscendingOrder);
databaseView->setModel(databaseDisplayModel);
databaseView->setContextMenuPolicy(Qt::CustomContextMenu);
connect(databaseView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(databaseCustomMenu(QPoint)));
connect(databaseView->selectionModel(), SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)), this,
SLOT(updateCardInfoLeft(const QModelIndex &, const QModelIndex &)));
connect(databaseView, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(actAddCard()));
QByteArray dbHeaderState = SettingsCache::instance().layouts().getDeckEditorDbHeaderState();
if (dbHeaderState.isNull()) {
// first run
databaseView->setColumnWidth(0, 200);
} else {
databaseView->header()->restoreState(dbHeaderState);
}
connect(databaseView->header(), SIGNAL(geometriesChanged()), this, SLOT(saveDbHeaderState()));
searchEdit->setTreeView(databaseView);
aAddCard = new QAction(QString(), this);
aAddCard->setIcon(QPixmap("theme:icons/arrow_right_green"));
connect(aAddCard, SIGNAL(triggered()), this, SLOT(actAddCard()));
auto *tbAddCard = new QToolButton(this);
tbAddCard->setDefaultAction(aAddCard);
aAddCardToSideboard = new QAction(QString(), this);
aAddCardToSideboard->setIcon(QPixmap("theme:icons/arrow_right_blue"));
connect(aAddCardToSideboard, SIGNAL(triggered()), this, SLOT(actAddCardToSideboard()));
auto *tbAddCardToSideboard = new QToolButton(this);
tbAddCardToSideboard->setDefaultAction(aAddCardToSideboard);
searchLayout = new QHBoxLayout;
searchLayout->setObjectName("searchLayout");
searchLayout->addWidget(searchEdit);
searchLayout->addWidget(tbAddCard);
searchLayout->addWidget(tbAddCardToSideboard);
searchAndDatabaseFrame = new QVBoxLayout;
searchAndDatabaseFrame->setObjectName("searchAndDatabaseFrame");
searchAndDatabaseFrame->addLayout(searchLayout);
searchAndDatabaseFrame->addWidget(databaseView);
searchAndDatabaseDock = new QDockWidget(this);
searchAndDatabaseDock->setObjectName("searchAndDatabaseDock");
searchAndDatabaseDock->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable |
QDockWidget::DockWidgetMovable);
auto *searchAndDatabaseDockContents = new QWidget(this);
searchAndDatabaseDockContents->setObjectName("filterDockContents");
searchAndDatabaseDockContents->setLayout(searchAndDatabaseFrame);
searchAndDatabaseDock->setWidget(searchAndDatabaseDockContents);
searchAndDatabaseDock->installEventFilter(this);
connect(searchAndDatabaseDock, SIGNAL(topLevelChanged(bool)), this, SLOT(dockTopLevelChanged(bool)));
}
void TabDeckEditorVisual::createMenus()
{
deckMenu = new DeckEditorMenu(this, this);
@ -274,11 +182,10 @@ void TabDeckEditorVisual::changeModelIndexToCard(CardInfoPtr activeCard)
void TabDeckEditorVisual::processMainboardCardClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance)
{
(void)instance;
if (event->button() == Qt::LeftButton) {
deckDockWidget->actSwapCard();
actSwapCard(instance->getInfo(), DECK_ZONE_MAIN);
} else if (event->button() == Qt::RightButton) {
deckDockWidget->actDecrement();
actDecrementCard(instance->getInfo());
} else if (event->button() == Qt::MiddleButton) {
deckDockWidget->actRemoveCard();
}
@ -286,11 +193,10 @@ void TabDeckEditorVisual::processMainboardCardClick(QMouseEvent *event, CardInfo
void TabDeckEditorVisual::processSideboardCardClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance)
{
(void)instance;
if (event->button() == Qt::LeftButton) {
deckDockWidget->actSwapCard();
actSwapCard(instance->getInfo(), DECK_ZONE_SIDE);
} else if (event->button() == Qt::RightButton) {
deckDockWidget->actDecrement();
actDecrementCardFromSideboard(instance->getInfo());
} else if (event->button() == Qt::MiddleButton) {
deckDockWidget->actRemoveCard();
}
@ -299,11 +205,10 @@ void TabDeckEditorVisual::processSideboardCardClick(QMouseEvent *event, CardInfo
void TabDeckEditorVisual::processCardClickDatabaseDisplay(QMouseEvent *event,
CardInfoPictureWithTextOverlayWidget *instance)
{
(void)instance;
if (event->button() == Qt::LeftButton) {
// addCardInfo(instance->getInfo(), DECK_ZONE_MAIN);
actAddCard(instance->getInfo());
} else if (event->button() == Qt::RightButton) {
deckDockWidget->actDecrement();
actDecrementCard(instance->getInfo());
} else if (event->button() == Qt::MiddleButton) {
deckDockWidget->actRemoveCard();
}
@ -354,6 +259,9 @@ void TabDeckEditorVisual::freeDocksSize()
filterDockWidget->setMinimumSize(100, 100);
filterDockWidget->setMaximumSize(5000, 5000);
databaseDisplayDockWidget->setMinimumSize(100, 100);
databaseDisplayDockWidget->setMaximumSize(1400, 5000);
}
void TabDeckEditorVisual::refreshShortcuts()
@ -394,14 +302,14 @@ void TabDeckEditorVisual::loadLayout()
deckDockWidget->setMinimumSize(layouts.getDeckEditorDeckSize());
deckDockWidget->setMaximumSize(layouts.getDeckEditorDeckSize());
databaseDisplayDockWidget->setMinimumSize(100, 100);
databaseDisplayDockWidget->setMaximumSize(1400, 5000);
QTimer::singleShot(100, this, SLOT(freeDocksSize()));
}
void TabDeckEditorVisual::retranslateUi()
{
aAddCard->setText(tr("Add card to &maindeck"));
aAddCardToSideboard->setText(tr("Add card to &sideboard"));
deckMenu->setTitle(tr("&Visual Deck Editor"));
cardInfoDockWidget->setWindowTitle(tr("Card Info"));
@ -476,7 +384,7 @@ void TabDeckEditorVisual::openDeckFromFile(const QString &fileName, DeckOpenLoca
emit openDeckEditor(l);
} else {
deckMenu->setSaveStatus(false);
setDeck(l);
TabDeckEditorVisual::setDeck(l);
}
} else {
delete l;
@ -484,6 +392,13 @@ void TabDeckEditorVisual::openDeckFromFile(const QString &fileName, DeckOpenLoca
}
deckMenu->setSaveStatus(true);
tabContainer->visualDeckView->updateDisplay();
tabContainer->deckAnalytics->refreshDisplays(deckDockWidget->deckModel);
}
void TabDeckEditorVisual::setDeck(DeckLoader *_deck)
{
TabGenericDeckEditor::setDeck(_deck);
qDebug() << "set the deck";
}
void TabDeckEditorVisual::showPrintingSelector()

View file

@ -38,6 +38,7 @@ protected:
public:
explicit TabDeckEditorVisual(TabSupervisor *_tabSupervisor);
void setDeck(DeckLoader *_deck) override;
void retranslateUi() override;
QString getTabText() const override;
void changeModelIndexAndCardInfo(CardInfoPtr activeCard);
@ -45,7 +46,7 @@ public:
void createDeckAnalyticsDock();
void createMenus() override;
void createSearchAndDatabaseFrame();
void createCentralFrame() override;
void createCentralFrame();
public slots:
void showPrintingSelector() override;

View file

@ -1,138 +0,0 @@
#include "tab_deck_editor_visual_database_search_tab.h"
#include "../../../game/cards/card_database_manager.h"
#include "../../../main.h"
TabDeckEditorVisualDatabaseSearchTab::TabDeckEditorVisualDatabaseSearchTab(TabSupervisor *_tabSupervisor,
QWidget *_parent)
: Tab(_tabSupervisor), parent(_parent)
{
// Set up the layout and add tab widget
layout = new QVBoxLayout(this);
this->setLayout(layout);
visualDeckView = new VisualDeckEditorWidget(this, this->deckModel);
visualDeckView->setObjectName("visualDeckView");
visualDeckView->updateDisplay();
layout->addWidget(visualDeckView);
}
TabDeckEditorVisualDatabaseSearchTab::~TabDeckEditorVisualDatabaseSearchTab()
{
}
void TabDeckEditorVisualDatabaseSearchTab::updateCardInfoLeft(const QModelIndex &current, const QModelIndex &previous)
{
(void)current;
(void)previous;
}
void TabDeckEditorVisualDatabaseSearchTab::updateCardInfoRight(const QModelIndex &current, const QModelIndex &previous)
{
(void)current;
(void)previous;
}
void TabDeckEditorVisualDatabaseSearchTab::updateSearch(const QString &search)
{
(void)search;
}
void TabDeckEditorVisualDatabaseSearchTab::databaseCustomMenu(QPoint point)
{
(void)point;
}
void TabDeckEditorVisualDatabaseSearchTab::actClearFilterAll()
{
}
void TabDeckEditorVisualDatabaseSearchTab::actClearFilterOne()
{
}
void TabDeckEditorVisualDatabaseSearchTab::actSwapCard()
{
}
void TabDeckEditorVisualDatabaseSearchTab::actAddCard()
{
}
void TabDeckEditorVisualDatabaseSearchTab::actAddCardToSideboard()
{
}
void TabDeckEditorVisualDatabaseSearchTab::actRemoveCard()
{
}
void TabDeckEditorVisualDatabaseSearchTab::actIncrement()
{
}
void TabDeckEditorVisualDatabaseSearchTab::actDecrement()
{
}
void TabDeckEditorVisualDatabaseSearchTab::actDecrementCard()
{
}
void TabDeckEditorVisualDatabaseSearchTab::actDecrementCardFromSideboard()
{
}
void TabDeckEditorVisualDatabaseSearchTab::copyDatabaseCellContents()
{
}
void TabDeckEditorVisualDatabaseSearchTab::filterViewCustomContextMenu(const QPoint &point)
{
(void)point;
}
void TabDeckEditorVisualDatabaseSearchTab::filterRemove(QAction *action)
{
(void)action;
}
void TabDeckEditorVisualDatabaseSearchTab::saveDbHeaderState()
{
}
void TabDeckEditorVisualDatabaseSearchTab::setSaveStatus(bool newStatus)
{
(void)newStatus;
}
void TabDeckEditorVisualDatabaseSearchTab::showSearchSyntaxHelp()
{
}
CardInfoPtr TabDeckEditorVisualDatabaseSearchTab::currentCardInfo() const
{
const QModelIndex currentIndex = databaseView->selectionModel()->currentIndex();
if (!currentIndex.isValid()) {
return {};
}
const QString cardName = currentIndex.sibling(currentIndex.row(), 0).data().toString();
return CardDatabaseManager::getInstance()->getCard(cardName);
}
void TabDeckEditorVisualDatabaseSearchTab::addCardHelper(QString zoneName)
{
(void)zoneName;
}
void TabDeckEditorVisualDatabaseSearchTab::offsetCountAtIndex(const QModelIndex &idx, int offset)
{
(void)idx;
(void)offset;
}
void TabDeckEditorVisualDatabaseSearchTab::decrementCardHelper(QString zoneName)
{
(void)zoneName;
}
void TabDeckEditorVisualDatabaseSearchTab::recursiveExpand(const QModelIndex &index)
{
(void)index;
}
void TabDeckEditorVisualDatabaseSearchTab::retranslateUi()
{
}
void TabDeckEditorVisualDatabaseSearchTab::setDeck(DeckLoader *_deckLoader)
{
(void)_deckLoader;
}
void TabDeckEditorVisualDatabaseSearchTab::setModified(bool _windowModified)
{
(void)_windowModified;
}
bool TabDeckEditorVisualDatabaseSearchTab::confirmClose()
{
return true;
}

View file

@ -1,97 +0,0 @@
#ifndef TAB_DECK_EDITOR_VISUAL_DATABASE_SEARCH_TAB_H
#define TAB_DECK_EDITOR_VISUAL_DATABASE_SEARCH_TAB_H
#include "../../../client/game_logic/key_signals.h"
#include "../../../deck/deck_list_model.h"
#include "../../../game/cards/card_database.h"
#include "../../../game/cards/card_database_model.h"
#include "../../ui/widgets/cards/card_info_frame_widget.h"
#include "../../ui/widgets/deck_analytics/deck_analytics_widget.h"
#include "../../ui/widgets/visual_deck_editor/visual_deck_editor_widget.h"
#include "../tab.h"
#include "../tab_deck_editor.h"
#include <QTreeView>
class TabDeckEditorVisualDatabaseSearchTab : public Tab
{
Q_OBJECT
private slots:
void updateCardInfoLeft(const QModelIndex &current, const QModelIndex &previous);
void updateCardInfoRight(const QModelIndex &current, const QModelIndex &previous);
void updateSearch(const QString &search);
void databaseCustomMenu(QPoint point);
void actClearFilterAll();
void actClearFilterOne();
void actSwapCard();
void actAddCard();
void actAddCardToSideboard();
void actRemoveCard();
void actIncrement();
void actDecrement();
void actDecrementCard();
void actDecrementCardFromSideboard();
void copyDatabaseCellContents();
void filterViewCustomContextMenu(const QPoint &point);
void filterRemove(QAction *action);
void saveDbHeaderState();
void setSaveStatus(bool newStatus);
void showSearchSyntaxHelp();
private:
QWidget *parent;
CardInfoPtr currentCardInfo() const;
void addCardHelper(QString zoneName);
void offsetCountAtIndex(const QModelIndex &idx, int offset);
void decrementCardHelper(QString zoneName);
void recursiveExpand(const QModelIndex &index);
CardDatabaseModel *databaseModel;
CardDatabaseDisplayModel *databaseDisplayModel;
DeckListModel *deckModel;
QTreeView *databaseView;
VisualDeckEditorWidget *visualDeckView;
CardInfoFrameWidget *cardInfo;
SearchLineEdit *searchEdit;
KeySignals searchKeySignals;
FilterTreeModel *filterModel;
QTreeView *filterView;
KeySignals filterViewKeySignals;
QWidget *filterBox;
QMenu *deckMenu, *viewMenu, *cardInfoDockMenu, *filterDockMenu;
QAction *aClose;
QAction *aClearFilterAll, *aClearFilterOne;
QAction *aAddCard, *aAddCardToSideboard, *aRemoveCard, *aIncrement, *aDecrement;
QAction *aResetLayout;
QAction *aCardInfoDockVisible, *aCardInfoDockFloating, *aDeckDockVisible, *aDeckDockFloating,
*aDeckAnalyticsDockFloating, *aDeckAnalyticsDockVisible, *aFilterDockVisible, *aFilterDockFloating;
bool modified;
QVBoxLayout *layout;
QVBoxLayout *searchAndDatabaseFrame;
QHBoxLayout *searchLayout;
QDockWidget *searchAndDatabaseDock;
QDockWidget *cardInfoDock;
QDockWidget *deckDock;
QDockWidget *filterDock;
QWidget *centralWidget;
public:
explicit TabDeckEditorVisualDatabaseSearchTab(TabSupervisor *_tabSupervisor, QWidget *_parent);
~TabDeckEditorVisualDatabaseSearchTab() override;
void retranslateUi() override;
void setDeck(DeckLoader *_deckLoader);
void setModified(bool _windowModified);
bool confirmClose();
signals:
void deckEditorClosing(TabDeckEditorVisualDatabaseSearchTab *tab);
};
#endif // TAB_DECK_EDITOR_VISUAL_DATABASE_SEARCH_TAB_H

View file

@ -1,8 +0,0 @@
//
// Created by ascor on 10/12/24.
//
#ifndef TAB_DECK_EDITOR_VISUAL_DECK_CARDS_TAB_H
#define TAB_DECK_EDITOR_VISUAL_DECK_CARDS_TAB_H
#endif // TAB_DECK_EDITOR_VISUAL_DECK_CARDS_TAB_H

View file

@ -1,8 +0,0 @@
//
// Created by ascor on 10/12/24.
//
#ifndef TAB_DECK_EDITOR_VISUAL_DECK_STATS_TAB_H
#define TAB_DECK_EDITOR_VISUAL_DECK_STATS_TAB_H
#endif // TAB_DECK_EDITOR_VISUAL_DECK_STATS_TAB_H

View file

@ -1,12 +1,14 @@
#include "tab_deck_editor_visual_tab_widget.h"
#include "../../ui/widgets/visual_database_display/visual_database_display_widget.h"
#include "../tab_generic_deck_editor.h"
TabDeckEditorVisualTabWidget::TabDeckEditorVisualTabWidget(QWidget *parent,
TabGenericDeckEditor *_deckEditor,
DeckListModel *model,
CardDatabaseModel *card_database_model,
CardDatabaseDisplayModel *card_database_display_model)
: QTabWidget(parent), deckModel(model), cardDatabaseModel(card_database_model),
: QTabWidget(parent), deckEditor(_deckEditor), deckModel(model), cardDatabaseModel(card_database_model),
cardDatabaseDisplayModel(card_database_display_model)
{
this->setTabsClosable(true); // Enable tab closing
@ -16,7 +18,7 @@ TabDeckEditorVisualTabWidget::TabDeckEditorVisualTabWidget(QWidget *parent,
layout = new QVBoxLayout(this);
setLayout(layout);
visualDeckView = new VisualDeckEditorWidget(this, this->deckModel);
visualDeckView = new VisualDeckEditorWidget(this, deckModel);
visualDeckView->setObjectName("visualDeckView");
visualDeckView->updateDisplay();
connect(visualDeckView, SIGNAL(activeCardChanged(CardInfoPtr)), this, SLOT(onCardChanged(CardInfoPtr)));
@ -25,8 +27,7 @@ TabDeckEditorVisualTabWidget::TabDeckEditorVisualTabWidget(QWidget *parent,
connect(visualDeckView, SIGNAL(sideboardCardClicked(QMouseEvent *, CardInfoPictureWithTextOverlayWidget *)), this,
SLOT(onSideboardCardClickedDeckEditor(QMouseEvent *, CardInfoPictureWithTextOverlayWidget *)));
visualDatabaseDisplay =
new VisualDatabaseDisplayWidget(this, this->cardDatabaseModel, this->cardDatabaseDisplayModel);
visualDatabaseDisplay = new VisualDatabaseDisplayWidget(this, cardDatabaseModel, cardDatabaseDisplayModel);
visualDatabaseDisplay->setObjectName("visualDatabaseView");
connect(visualDatabaseDisplay, SIGNAL(cardHoveredDatabaseDisplay(CardInfoPtr)), this,
SLOT(onCardChangedDatabaseDisplay(CardInfoPtr)));
@ -34,9 +35,8 @@ TabDeckEditorVisualTabWidget::TabDeckEditorVisualTabWidget(QWidget *parent,
SIGNAL(cardClickedDatabaseDisplay(QMouseEvent *, CardInfoPictureWithTextOverlayWidget *)), this,
SLOT(onCardClickedDatabaseDisplay(QMouseEvent *, CardInfoPictureWithTextOverlayWidget *)));
deckAnalytics = new DeckAnalyticsWidget(this, this->deckModel);
deckAnalytics = new DeckAnalyticsWidget(this, deckModel);
deckAnalytics->setObjectName("deckAnalytics");
// deckAnalytics->analyzeManaCurve();
// printingSelector = new PrintingSelector(this, this->deckModel);

View file

@ -5,6 +5,7 @@
#include "../../ui/widgets/printing_selector/printing_selector.h"
#include "../../ui/widgets/visual_database_display/visual_database_display_widget.h"
#include "../../ui/widgets/visual_deck_editor/visual_deck_editor_widget.h"
#include "../tab_generic_deck_editor.h"
#include <QTabWidget>
#include <QVBoxLayout>
@ -16,6 +17,7 @@ class TabDeckEditorVisualTabWidget : public QTabWidget
public:
explicit TabDeckEditorVisualTabWidget(QWidget *parent = nullptr,
TabGenericDeckEditor *deckEditor = nullptr,
DeckListModel *deckModel = nullptr,
CardDatabaseModel *card_database_model = nullptr,
CardDatabaseDisplayModel *card_database_display_model = nullptr);
@ -48,6 +50,7 @@ signals:
private:
QVBoxLayout *layout; // Layout for the tab widget and other controls
TabGenericDeckEditor *deckEditor;
DeckListModel *deckModel;
CardDatabaseModel *cardDatabaseModel;
CardDatabaseDisplayModel *cardDatabaseDisplayModel;

View file

@ -1,26 +1,25 @@
#include "deck_analytics_widget.h"
DeckAnalyticsWidget::DeckAnalyticsWidget(QWidget *parent, DeckListModel *deck_list_model)
: QWidget(parent), deck_list_model(deck_list_model)
DeckAnalyticsWidget::DeckAnalyticsWidget(QWidget *parent, DeckListModel *_deckListModel)
: QWidget(parent), deckListModel(_deckListModel)
{
mainLayout = new QVBoxLayout();
setLayout(mainLayout);
this->setMinimumSize(0, 0);
this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
this->setStyleSheet("border: 2px solid red;");
main_layout = new QHBoxLayout();
this->setLayout(main_layout);
manaCurveWidget = new ManaCurveWidget(this);
mainLayout->addWidget(manaCurveWidget);
flow_widget = new FlowWidget(this, Qt::Horizontal, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAlwaysOff);
this->main_layout->addWidget(flow_widget);
manaDevotionWidget = new ManaDevotionWidget(this, deckListModel);
mainLayout->addWidget(manaDevotionWidget);
mana_curve_widget = new ManaCurveWidget(flow_widget);
mana_curve_widget->setStyleSheet("border: 2px solid yellow;");
flow_widget->addWidget(mana_curve_widget);
mana_devotion_widget = new ManaDevotionWidget(flow_widget, this->deck_list_model);
flow_widget->addWidget(mana_devotion_widget);
mana_base_widget = new ManaBaseWidget(flow_widget, this->deck_list_model);
flow_widget->addWidget(mana_base_widget);
manaBaseWidget = new ManaBaseWidget(this, deckListModel);
mainLayout->addWidget(manaBaseWidget);
}
void DeckAnalyticsWidget::refreshDisplays(DeckListModel *_deckModel)
{
deckListModel = _deckModel;
manaCurveWidget->setDeckModel(_deckModel);
manaDevotionWidget->setDeckModel(_deckModel);
manaBaseWidget->setDeckModel(_deckModel);
}

View file

@ -17,18 +17,18 @@ class DeckAnalyticsWidget : public QWidget
Q_OBJECT
public:
explicit DeckAnalyticsWidget(QWidget *parent = nullptr, DeckListModel *deck_list_model = nullptr);
void setDeckList(const DeckList &new_deck_list_model);
explicit DeckAnalyticsWidget(QWidget *parent, DeckListModel *deckListModel);
void setDeckList(const DeckList &_deckListModel);
std::map<int, int> analyzeManaCurve();
void refreshDisplays(DeckListModel *_deckListModel);
private:
DeckListModel *deck_list_model;
QHBoxLayout *main_layout;
FlowWidget *flow_widget;
DeckListModel *deckListModel;
QVBoxLayout *mainLayout;
ManaCurveWidget *mana_curve_widget;
ManaDevotionWidget *mana_devotion_widget;
ManaBaseWidget *mana_base_widget;
ManaCurveWidget *manaCurveWidget;
ManaDevotionWidget *manaDevotionWidget;
ManaBaseWidget *manaBaseWidget;
};
#endif // DECK_ANALYTICS_WIDGET_H

View file

@ -4,6 +4,7 @@
#include "../../../../game/cards/card_database.h"
#include "../../../../game/cards/card_database_manager.h"
#include "../../../../main.h"
#include "../general/display/banner_widget.h"
#include "../general/display/bar_widget.h"
#include <QRegularExpression>
@ -11,18 +12,32 @@
#include <regex>
#include <unordered_map>
ManaBaseWidget::ManaBaseWidget(QWidget *parent, DeckListModel *deck_list_model)
: QWidget(parent), deck_list_model(deck_list_model)
ManaBaseWidget::ManaBaseWidget(QWidget *parent, DeckListModel *_deck_list_model)
: QWidget(parent), deck_list_model(_deck_list_model)
{
layout = new QHBoxLayout(this);
this->setLayout(layout);
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
setMinimumSize(0, 0);
layout = new QVBoxLayout(this);
setLayout(layout);
bannerWidget = new BannerWidget(this, "Mana Base", Qt::Vertical, 100);
bannerWidget->setMaximumHeight(100);
layout->addWidget(bannerWidget);
barLayout = new QHBoxLayout();
layout->addLayout(barLayout);
connect(deck_list_model, &DeckListModel::dataChanged, this, &ManaBaseWidget::analyzeManaBase);
}
void ManaBaseWidget::setDeckModel(DeckListModel *deckModel)
{
deck_list_model = deckModel;
connect(deck_list_model, &DeckListModel::dataChanged, this, &ManaBaseWidget::analyzeManaBase);
analyzeManaBase();
}
std::unordered_map<char, int> ManaBaseWidget::analyzeManaBase()
{
manaBaseMap = std::unordered_map<char, int>();
manaBaseMap.clear();
InnerDecklistNode *listRoot = deck_list_model->getDeckList()->getRoot();
for (int i = 0; i < listRoot->size(); i++) {
InnerDecklistNode *currentZone = dynamic_cast<InnerDecklistNode *>(listRoot->at(i));
@ -41,29 +56,17 @@ std::unordered_map<char, int> ManaBaseWidget::analyzeManaBase()
}
}
update();
// this->setCurve(ManaBaseMap);
// mana_curve_widget->updateDisplay();
this->updateDisplay();
update();
updateDisplay();
return manaBaseMap;
}
void ManaBaseWidget::updateDisplay()
{
// Clear the layout first
if (layout != nullptr) {
QLayoutItem *item;
while ((item = layout->takeAt(0)) != nullptr) {
delete item->widget(); // Delete the widget
delete item; // Delete the layout item
}
}
// If layout is null, create a new layout, otherwise reuse the existing one
if (layout == nullptr) {
layout = new QHBoxLayout(this);
this->setLayout(layout);
QLayoutItem *item;
while ((item = barLayout->takeAt(0)) != nullptr) {
delete item->widget();
delete item;
}
int totalSum = 0;
@ -71,13 +74,18 @@ void ManaBaseWidget::updateDisplay()
totalSum += entry.second;
}
// Add new widgets to the layout
// Define color mapping for mana types
std::unordered_map<char, QColor> manaColors = {{'W', QColor(248, 231, 185)}, {'U', QColor(14, 104, 171)},
{'B', QColor(21, 11, 0)}, {'R', QColor(211, 32, 42)},
{'G', QColor(0, 115, 62)}, {'C', QColor(150, 150, 150)}};
for (auto entry : manaBaseMap) {
BarWidget *barWidget = new BarWidget(QString(entry.first), entry.second, totalSum, this);
layout->addWidget(barWidget);
QColor barColor = manaColors.count(entry.first) ? manaColors[entry.first] : Qt::gray;
BarWidget *barWidget = new BarWidget(QString(entry.first), entry.second, totalSum, barColor, this);
barLayout->addWidget(barWidget);
}
update(); // Update the widget display
update();
}
std::unordered_map<char, int> ManaBaseWidget::determineManaProduction(const QString &rulesText)
@ -131,4 +139,4 @@ void ManaBaseWidget::mergeManaCounts(std::unordered_map<char, int> &manaCounts1,
for (const auto &pair : manaCounts2) {
manaCounts1[pair.first] += pair.second; // Add values for matching keys
}
}
}

View file

@ -1,4 +1,5 @@
#include "../../../../deck/deck_list_model.h"
#include "../general/display/banner_widget.h"
#include <QHBoxLayout>
#include <QWidget>
@ -20,10 +21,15 @@ public:
std::unordered_map<char, int> determineManaProduction(const QString &manaString);
void mergeManaCounts(std::unordered_map<char, int> &manaCounts1, const std::unordered_map<char, int> &manaCounts2);
public slots:
void setDeckModel(DeckListModel *deckModel);
private:
DeckListModel *deck_list_model;
BannerWidget *bannerWidget;
std::unordered_map<char, int> manaBaseMap;
QHBoxLayout *layout;
QVBoxLayout *layout;
QHBoxLayout *barLayout;
};
#endif // MANA_BASE_WIDGET_H

View file

@ -1,43 +1,89 @@
#include "mana_curve_widget.h"
#include "../../../../deck/deck_loader.h"
#include "../../../../game/cards/card_database.h"
#include "../../../../game/cards/card_database_manager.h"
#include "../../../../main.h"
#include "../general/display/banner_widget.h"
#include "../general/display/bar_widget.h"
#include <QLabel>
#include <decklist.h>
#include <unordered_map>
ManaCurveWidget::ManaCurveWidget(QWidget *parent) : QWidget(parent)
ManaCurveWidget::ManaCurveWidget(QWidget *parent, DeckListModel *_deck_list_model)
: QWidget(parent), deck_list_model(_deck_list_model)
{
layout = new QHBoxLayout(this);
this->setLayout(layout);
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
setMinimumSize(0, 0);
layout = new QVBoxLayout(this);
setLayout(layout);
bannerWidget = new BannerWidget(this, "Mana Curve", Qt::Vertical, 100);
bannerWidget->setMaximumHeight(100);
layout->addWidget(bannerWidget);
connect(deck_list_model, &DeckListModel::dataChanged, this, &ManaCurveWidget::analyzeManaCurve);
}
void ManaCurveWidget::setDeckModel(DeckListModel *deckModel)
{
deck_list_model = deckModel;
connect(deck_list_model, &DeckListModel::dataChanged, this, &ManaCurveWidget::analyzeManaCurve);
analyzeManaCurve();
}
std::unordered_map<int, int> ManaCurveWidget::analyzeManaCurve()
{
manaCurveMap.clear();
InnerDecklistNode *listRoot = deck_list_model->getDeckList()->getRoot();
for (int i = 0; i < listRoot->size(); i++) {
InnerDecklistNode *currentZone = dynamic_cast<InnerDecklistNode *>(listRoot->at(i));
for (int j = 0; j < currentZone->size(); j++) {
DecklistCardNode *currentCard = dynamic_cast<DecklistCardNode *>(currentZone->at(j));
if (!currentCard)
continue;
for (int k = 0; k < currentCard->getNumber(); ++k) {
CardInfoPtr info = CardDatabaseManager::getInstance()->getCard(currentCard->getName());
if (info) {
int cmc = info->getCmc().toInt();
manaCurveMap[cmc]++;
}
}
}
}
updateDisplay();
return manaCurveMap;
}
void ManaCurveWidget::updateDisplay()
{
// Clear the layout first
if (layout != nullptr) {
if (barLayout != nullptr) {
QLayoutItem *item;
while ((item = layout->takeAt(0)) != nullptr) {
delete item->widget(); // Delete the widget
delete item; // Delete the layout item
while ((item = barLayout->takeAt(0)) != nullptr) {
delete item->widget();
delete item;
}
}
// If layout is null, create a new layout, otherwise reuse the existing one
if (layout == nullptr) {
layout = new QHBoxLayout(this);
this->setLayout(layout);
// Ensure layout exists
if (barLayout == nullptr) {
barLayout = new QHBoxLayout(this);
layout->addLayout(barLayout);
}
int totalSum = 0;
for (auto entry : curve) {
for (const auto &entry : manaCurveMap) {
totalSum += entry.second;
}
// Add a bar for each CMC to the layout
for (auto entry : curve) {
BarWidget *barWidget = new BarWidget(QString::number(entry.first), entry.second, totalSum, this);
layout->addWidget(barWidget);
// Convert unordered_map to ordered map to ensure sorting by CMC
std::map<int, int> sortedManaCurve(manaCurveMap.begin(), manaCurveMap.end());
// Add new widgets to the layout in sorted order
for (const auto &entry : sortedManaCurve) {
BarWidget *barWidget =
new BarWidget(QString::number(entry.first), entry.second, totalSum, QColor(11, 11, 11), this);
barLayout->addWidget(barWidget);
}
update(); // Update the widget display

View file

@ -1,25 +1,31 @@
#ifndef MANA_CURVE_WIDGET_H
#define MANA_CURVE_WIDGET_H
#include "../../../../deck/deck_list_model.h"
#include "../general/display/banner_widget.h"
#include <QHBoxLayout>
#include <QWidget>
#include <utility>
#include <unordered_map>
class ManaCurveWidget : public QWidget
{
Q_OBJECT
public:
explicit ManaCurveWidget(QWidget *parent = nullptr);
explicit ManaCurveWidget(QWidget *parent = nullptr, DeckListModel *deck_list_model = nullptr);
void updateDisplay();
void setCurve(std::map<int, int> new_curve)
{
this->curve = std::move(new_curve);
}
public slots:
void setDeckModel(DeckListModel *deckModel);
std::unordered_map<int, int> analyzeManaCurve();
private:
std::map<int, int> curve;
QHBoxLayout *layout;
DeckListModel *deck_list_model = nullptr;
std::unordered_map<int, int> manaCurveMap;
QVBoxLayout *layout;
QHBoxLayout *barLayout;
BannerWidget *bannerWidget;
};
#endif // MANA_CURVE_WIDGET_H

View file

@ -4,6 +4,7 @@
#include "../../../../game/cards/card_database.h"
#include "../../../../game/cards/card_database_manager.h"
#include "../../../../main.h"
#include "../general/display/banner_widget.h"
#include "../general/display/bar_widget.h"
#include <decklist.h>
@ -12,18 +13,32 @@
#include <string>
#include <unordered_map>
ManaDevotionWidget::ManaDevotionWidget(QWidget *parent, DeckListModel *deck_list_model)
: QWidget(parent), deck_list_model(deck_list_model)
ManaDevotionWidget::ManaDevotionWidget(QWidget *parent, DeckListModel *_deck_list_model)
: QWidget(parent), deck_list_model(_deck_list_model)
{
layout = new QHBoxLayout(this);
this->setLayout(layout);
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
setMinimumSize(0, 0);
layout = new QVBoxLayout(this);
setLayout(layout);
bannerWidget = new BannerWidget(this, "Mana Devotion", Qt::Vertical, 100);
bannerWidget->setMaximumHeight(100);
layout->addWidget(bannerWidget);
barLayout = new QHBoxLayout();
layout->addLayout(barLayout);
connect(deck_list_model, &DeckListModel::dataChanged, this, &ManaDevotionWidget::analyzeManaDevotion);
}
void ManaDevotionWidget::setDeckModel(DeckListModel *deckModel)
{
deck_list_model = deckModel;
connect(deck_list_model, &DeckListModel::dataChanged, this, &ManaDevotionWidget::analyzeManaDevotion);
analyzeManaDevotion();
}
std::unordered_map<char, int> ManaDevotionWidget::analyzeManaDevotion()
{
manaDevotionMap = std::unordered_map<char, int>();
manaDevotionMap.clear();
InnerDecklistNode *listRoot = deck_list_model->getDeckList()->getRoot();
for (int i = 0; i < listRoot->size(); i++) {
InnerDecklistNode *currentZone = dynamic_cast<InnerDecklistNode *>(listRoot->at(i));
@ -42,30 +57,17 @@ std::unordered_map<char, int> ManaDevotionWidget::analyzeManaDevotion()
}
}
update();
// this->setCurve(manaDevotionMap);
// mana_curve_widget->updateDisplay();
this->updateDisplay();
update();
updateDisplay();
return manaDevotionMap;
}
void ManaDevotionWidget::updateDisplay()
{
// Clear the layout first
if (layout != nullptr) {
QLayoutItem *item;
while ((item = layout->takeAt(0)) != nullptr) {
delete item->widget(); // Delete the widget
delete item; // Delete the layout item
}
}
// If layout is null, create a new layout, otherwise reuse the existing one
if (layout == nullptr) {
layout = new QHBoxLayout(this);
this->setLayout(layout);
QLayoutItem *item;
while ((item = barLayout->takeAt(0)) != nullptr) {
delete item->widget();
delete item;
}
int totalSum = 0;
@ -73,10 +75,15 @@ void ManaDevotionWidget::updateDisplay()
totalSum += entry.second;
}
// Add new widgets to the layout
// Define color mapping for devotion bars
std::unordered_map<char, QColor> manaColors = {{'W', QColor(248, 231, 185)}, {'U', QColor(14, 104, 171)},
{'B', QColor(21, 11, 0)}, {'R', QColor(211, 32, 42)},
{'G', QColor(0, 115, 62)}, {'C', QColor(150, 150, 150)}};
for (auto entry : manaDevotionMap) {
BarWidget *barWidget = new BarWidget(QString(entry.first), entry.second, totalSum, this);
layout->addWidget(barWidget);
QColor barColor = manaColors.count(entry.first) ? manaColors[entry.first] : Qt::gray;
BarWidget *barWidget = new BarWidget(QString(entry.first), entry.second, totalSum, barColor, this);
barLayout->addWidget(barWidget);
}
update(); // Update the widget display

View file

@ -1,6 +1,7 @@
#ifndef MANA_DEVOTION_WIDGET_H
#define MANA_DEVOTION_WIDGET_H
#include "../../../../deck/deck_list_model.h"
#include "../general/display/banner_widget.h"
#include <QHBoxLayout>
#include <QWidget>
@ -13,16 +14,21 @@ class ManaDevotionWidget : public QWidget
public:
explicit ManaDevotionWidget(QWidget *parent = nullptr, DeckListModel *deck_list_model = nullptr);
std::unordered_map<char, int> analyzeManaDevotion();
void updateDisplay();
std::unordered_map<char, int> countManaSymbols(const QString &manaString);
void mergeManaCounts(std::unordered_map<char, int> &manaCounts1, const std::unordered_map<char, int> &manaCounts2);
public slots:
void setDeckModel(DeckListModel *deckModel);
std::unordered_map<char, int> analyzeManaDevotion();
private:
DeckListModel *deck_list_model;
BannerWidget *bannerWidget;
std::unordered_map<char, int> manaDevotionMap;
QHBoxLayout *layout;
QVBoxLayout *layout;
QHBoxLayout *barLayout;
};
#endif // MANA_DEVOTION_WIDGET_H

View file

@ -1,9 +1,10 @@
#include "bar_widget.h"
#include <utility>
#include <QFontMetrics>
#include <QPainter>
BarWidget::BarWidget(QString label, int value, int total, QWidget *parent)
: QWidget(parent), label(std::move(label)), value(value), total(total)
BarWidget::BarWidget(QString label, int value, int total, QColor barColor, QWidget *parent)
: QWidget(parent), label(std::move(label)), value(value), total(total), barColor(barColor)
{
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
}
@ -14,10 +15,10 @@ QSize BarWidget::sizeHint() const
int labelHeight = metrics.height();
int valueHeight = metrics.height();
// Calculate the height based on total and value
int barHeight = total > 0 ? total * 2 : 20; // Adjust factor as necessary for visual size
int totalHeight = barHeight + labelHeight + valueHeight + 30; // Extra space for padding
return QSize(40, totalHeight); // Width is fixed, height is calculated
// Calculate the height dynamically based on the total
int barHeight = (total > 0) ? (value * 200 / total) : 20; // Scale height proportionally
int totalHeight = barHeight + labelHeight + valueHeight + 30; // Extra space for text
return QSize(60, totalHeight); // Allow width to expand
}
void BarWidget::paintEvent(QPaintEvent *event)
@ -25,25 +26,30 @@ void BarWidget::paintEvent(QPaintEvent *event)
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
// Calculate the full bar width and value-specific bar width
int fullBarWidth = total; // Full bar (sum of all entries)
int valueBarWidth = (total > 0) ? (value * 100 / total) : 0;
int widgetWidth = width();
int widgetHeight = height();
// Draw the full bar background (gray)
painter.setBrush(QColor(200, 200, 200)); // Gray background for full bar
painter.drawRect(0, 10, 20, fullBarWidth);
// Calculate bar dimensions
int barWidth = widgetWidth * 0.8; // Use 80% of the available width
int fullBarHeight = widgetHeight - 40; // Leave space for labels
int valueBarHeight = (total > 0) ? (value * fullBarHeight / total) : 0;
// Draw the value-specific bar (blue)
painter.setBrush(QColor(100, 150, 255)); // Blue for the value bar
painter.drawRect(0, fullBarWidth + 10, 20, -valueBarWidth);
// Draw full bar background (gray)
painter.setBrush(QColor(200, 200, 200));
painter.drawRect((widgetWidth - barWidth) / 2, 10, barWidth, fullBarHeight);
// Draw the value-specific bar using the assigned color
painter.setBrush(barColor);
painter.drawRect((widgetWidth - barWidth) / 2, 10 + fullBarHeight - valueBarHeight, barWidth, valueBarHeight);
// Draw the CMC label
painter.setPen(Qt::white);
QRect textRect(0, fullBarWidth + 10, 20, 30); // Define a rectangle for text
QRect textRect(0, widgetHeight - 30, widgetWidth, 20);
painter.drawText(textRect, Qt::AlignCenter, label);
// Draw the value count
painter.setPen(Qt::black);
QRect valueRect(0, 10, 20, fullBarWidth); // Define a rectangle for text
QRect valueRect(0, 10, widgetWidth, 20);
painter.drawText(valueRect, Qt::AlignCenter, QString::number(value));
(void)event; // Suppress unused parameter warning

View file

@ -1,7 +1,8 @@
#ifndef BAR_WIDGET_H
#define BAR_WIDGET_H
#include <QPainter>
#include <QColor>
#include <QString>
#include <QWidget>
class BarWidget : public QWidget
@ -9,17 +10,18 @@ class BarWidget : public QWidget
Q_OBJECT
public:
BarWidget(QString label, int value, int total, QWidget *parent = nullptr);
explicit BarWidget(QString label, int value, int total, QColor barColor = Qt::blue, QWidget *parent = nullptr);
QSize sizeHint() const override;
protected:
void paintEvent(QPaintEvent *event) override;
QSize sizeHint() const override;
private:
QString label; // The CMC value (label for the bar)
int value; // The specific value for this CMC (the inner bar length)
int total; // Total value for calculating proportional bar length
static int totalSum; // The total sum of all entry.second values (shared across instances)
QString label;
int value;
int total;
QColor barColor; // Store the bar color
};
#endif // BAR_WIDGET_H

View file

@ -0,0 +1,186 @@
#include "visual_database_display_color_filter_widget.h"
#include "../../../../game/filters/filter_card.h"
#include "../../../../game/filters/filter_tree_model.h"
#include <QMouseEvent>
#include <QPainter>
VisualDatabaseDisplayColorFilterCircleWidget::VisualDatabaseDisplayColorFilterCircleWidget(QChar color, QWidget *parent)
: QWidget(parent), colorChar(color), isActive(false), circleDiameter(30)
{
setFixedSize(circleDiameter, circleDiameter);
}
void VisualDatabaseDisplayColorFilterCircleWidget::setColorActive(bool active)
{
if (isActive != active) {
isActive = active;
update();
}
}
bool VisualDatabaseDisplayColorFilterCircleWidget::isColorActive() const
{
return isActive;
}
QChar VisualDatabaseDisplayColorFilterCircleWidget::getColorChar() const
{
return colorChar;
}
void VisualDatabaseDisplayColorFilterCircleWidget::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
QColor circleColor;
switch (colorChar.unicode()) {
case 'W':
circleColor = Qt::white;
break;
case 'U':
circleColor = QColor(0, 115, 230);
break;
case 'B':
circleColor = QColor(50, 50, 50);
break;
case 'R':
circleColor = QColor(230, 30, 30);
break;
case 'G':
circleColor = QColor(30, 180, 30);
break;
default:
circleColor = Qt::transparent;
break;
}
if (!isActive) {
circleColor.setAlpha(100); // Dim inactive circles
}
painter.setBrush(circleColor);
painter.setPen(Qt::black);
painter.drawEllipse(rect());
if (isActive) {
QFont font = painter.font();
font.setBold(true);
font.setPointSize(circleDiameter / 3);
painter.setFont(font);
painter.setPen(colorChar.unicode() == 'B' ? Qt::white : Qt::black);
painter.drawText(rect(), Qt::AlignCenter, colorChar);
}
}
void VisualDatabaseDisplayColorFilterCircleWidget::mousePressEvent(QMouseEvent *event)
{
Q_UNUSED(event);
isActive = !isActive;
emit colorToggled(colorChar, isActive);
update();
}
VisualDatabaseDisplayColorFilterWidget::VisualDatabaseDisplayColorFilterWidget(QWidget *parent,
FilterTreeModel *_filterModel)
: QWidget(parent), filterModel(_filterModel), layout(new QHBoxLayout(this))
{
setLayout(layout);
layout->setSpacing(5);
layout->setContentsMargins(0, 0, 0, 0);
QString fullColorIdentity = "WUBRG";
for (const QChar &color : fullColorIdentity) {
auto *circle = new VisualDatabaseDisplayColorFilterCircleWidget(color, this);
layout->addWidget(circle);
// Initialize the activeColors map
activeColors[color] = false;
// Connect the color toggled signal
connect(circle, &VisualDatabaseDisplayColorFilterCircleWidget::colorToggled, this,
&VisualDatabaseDisplayColorFilterWidget::handleColorToggled);
}
toggleButton = new QPushButton(this);
toggleButton->setCheckable(true);
layout->addWidget(toggleButton);
// Connect the button's toggled signal
connect(toggleButton, &QPushButton::toggled, this, &VisualDatabaseDisplayColorFilterWidget::updateFilterMode);
connect(this, &VisualDatabaseDisplayColorFilterWidget::activeColorsChanged, this,
&VisualDatabaseDisplayColorFilterWidget::updateColorFilter);
connect(this, &VisualDatabaseDisplayColorFilterWidget::filterModeChanged, this,
&VisualDatabaseDisplayColorFilterWidget::updateColorFilter);
// Call retranslateUi to set the initial text
retranslateUi();
}
void VisualDatabaseDisplayColorFilterWidget::retranslateUi()
{
// Set the toggle button text based on the current mode
toggleButton->setText(exactMatchMode ? tr("Mode: Exact Match") : tr("Mode: Includes"));
}
void VisualDatabaseDisplayColorFilterWidget::handleColorToggled(QChar color, bool active)
{
activeColors[color] = active;
emit activeColorsChanged();
}
void VisualDatabaseDisplayColorFilterWidget::updateColorFilter()
{
// Clear existing filters related to color
filterModel->clearFiltersOfType(CardFilter::Attr::AttrColor);
if (exactMatchMode) {
// Exact match: card must have ONLY the selected colors
QSet<QString> selectedColors;
for (const auto &color : activeColors.keys()) {
if (activeColors[color]) {
selectedColors.insert(color);
}
}
if (!selectedColors.isEmpty()) {
// Require all selected colors (TypeAnd)
for (const auto &color : selectedColors) {
QString colorString = color;
filterModel->addFilter(
new CardFilter(colorString, CardFilter::Type::TypeAnd, CardFilter::Attr::AttrColor));
}
// Exclude any other colors (TypeAndNot)
QStringList allPossibleColors = {"W", "U", "B", "R", "G"};
for (const auto &color : allPossibleColors) {
if (!selectedColors.contains(color)) {
QString colorString = color;
filterModel->addFilter(
new CardFilter(colorString, CardFilter::Type::TypeAndNot, CardFilter::Attr::AttrColor));
}
}
}
} else {
// Default includes mode (TypeAnd) - match any selected colors
for (const auto &color : activeColors.keys()) {
if (activeColors[color]) { // If the color is active
QString colorString = color;
filterModel->addFilter(
new CardFilter(colorString, CardFilter::Type::TypeAnd, CardFilter::Attr::AttrColor));
}
}
}
}
void VisualDatabaseDisplayColorFilterWidget::updateFilterMode(bool checked)
{
exactMatchMode = checked; // Toggle between modes
retranslateUi(); // Update the button text
emit filterModeChanged(exactMatchMode);
}

View file

@ -0,0 +1,58 @@
#ifndef VISUAL_DATABASE_DISPLAY_COLOR_FILTER_WIDGET_H
#define VISUAL_DATABASE_DISPLAY_COLOR_FILTER_WIDGET_H
#include "../../../../game/filters/filter_tree_model.h"
#include <QHBoxLayout>
#include <QPushButton>
#include <QWidget>
class VisualDatabaseDisplayColorFilterCircleWidget : public QWidget
{
Q_OBJECT
public:
explicit VisualDatabaseDisplayColorFilterCircleWidget(QChar color, QWidget *parent = nullptr);
void setColorActive(bool active);
bool isColorActive() const;
QChar getColorChar() const;
protected:
void paintEvent(QPaintEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
signals:
void colorToggled(QChar color, bool active);
private:
QChar colorChar;
bool isActive;
int circleDiameter;
};
class VisualDatabaseDisplayColorFilterWidget : public QWidget
{
Q_OBJECT
public:
explicit VisualDatabaseDisplayColorFilterWidget(QWidget *parent, FilterTreeModel *filterModel);
void retranslateUi();
signals:
void filterModeChanged(bool exactMatchMode);
void activeColorsChanged();
private slots:
void handleColorToggled(QChar color, bool active);
void updateColorFilter();
void updateFilterMode(bool checked);
private:
FilterTreeModel *filterModel;
QHBoxLayout *layout;
QPushButton *toggleButton;
QMap<QChar, bool> activeColors;
bool exactMatchMode = false; // Default to "includes" mode
};
#endif // VISUAL_DATABASE_DISPLAY_COLOR_FILTER_WIDGET_H

View file

@ -0,0 +1,142 @@
#include "visual_database_display_main_type_filter_widget.h"
#include "../../../../game/cards/card_database_manager.h"
#include "../../../../game/filters/filter_tree_model.h"
#include <QPushButton>
#include <QSpinBox>
VisualDatabaseDisplayMainTypeFilterWidget::VisualDatabaseDisplayMainTypeFilterWidget(QWidget *parent,
FilterTreeModel *_filterModel)
: QWidget(parent), filterModel(_filterModel)
{
allMainCardTypesWithCount = CardDatabaseManager::getInstance()->getAllMainCardTypesWithCount();
// Get all main card types with their count
setMinimumWidth(300);
layout = new QVBoxLayout(this);
setLayout(layout);
// Create the spinbox
spinBox = new QSpinBox(this);
spinBox->setMinimum(1);
spinBox->setMaximum(getMaxMainTypeCount()); // Set the max value dynamically
spinBox->setValue(150);
layout->addWidget(spinBox);
connect(spinBox, QOverload<int>::of(&QSpinBox::valueChanged), this,
&VisualDatabaseDisplayMainTypeFilterWidget::updateMainTypeButtonsVisibility);
flowWidget = new FlowWidget(this, Qt::Horizontal, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAlwaysOff);
layout->addWidget(flowWidget);
// Create the toggle button for Exact Match/Includes mode
toggleButton = new QPushButton(this);
toggleButton->setCheckable(true);
layout->addWidget(toggleButton);
connect(toggleButton, &QPushButton::toggled, this, &VisualDatabaseDisplayMainTypeFilterWidget::updateFilterMode);
createMainTypeButtons(); // Populate buttons initially
updateFilterMode(false); // Initialize toggle button text
}
void VisualDatabaseDisplayMainTypeFilterWidget::createMainTypeButtons()
{
// Iterate through main types and create buttons
for (auto it = allMainCardTypesWithCount.begin(); it != allMainCardTypesWithCount.end(); ++it) {
auto *button = new QPushButton(it.key(), flowWidget);
button->setCheckable(true);
button->setStyleSheet("QPushButton { background-color: lightgray; border: 1px solid gray; padding: 5px; }"
"QPushButton:checked { background-color: green; color: white; }");
flowWidget->addWidget(button);
typeButtons[it.key()] = button;
// Connect toggle signal
connect(button, &QPushButton::toggled, this,
[this, mainType = it.key()](bool checked) { handleMainTypeToggled(mainType, checked); });
}
updateMainTypeButtonsVisibility(); // Ensure visibility is updated initially
}
void VisualDatabaseDisplayMainTypeFilterWidget::updateMainTypeButtonsVisibility()
{
int threshold = spinBox->value(); // Get the current spinbox value
// Iterate through buttons and hide/disable those below the threshold
for (auto it = typeButtons.begin(); it != typeButtons.end(); ++it) {
bool visible = allMainCardTypesWithCount[it.key()] >= threshold;
it.value()->setVisible(visible);
it.value()->setEnabled(visible);
}
}
int VisualDatabaseDisplayMainTypeFilterWidget::getMaxMainTypeCount() const
{
int maxCount = 1;
for (auto it = allMainCardTypesWithCount.begin(); it != allMainCardTypesWithCount.end(); ++it) {
maxCount = qMax(maxCount, it.value());
}
return maxCount;
}
void VisualDatabaseDisplayMainTypeFilterWidget::handleMainTypeToggled(const QString &mainType, bool active)
{
activeMainTypes[mainType] = active;
if (typeButtons.contains(mainType)) {
typeButtons[mainType]->setChecked(active);
}
updateMainTypeFilter();
}
void VisualDatabaseDisplayMainTypeFilterWidget::updateMainTypeFilter()
{
// Clear existing filters related to main type
filterModel->clearFiltersOfType(CardFilter::Attr::AttrType);
if (exactMatchMode) {
// Exact Match: Only selected main types are allowed
QSet<QString> selectedTypes;
for (const auto &type : activeMainTypes.keys()) {
if (activeMainTypes[type]) {
selectedTypes.insert(type);
}
}
if (!selectedTypes.isEmpty()) {
// Require all selected types (TypeAnd)
for (const auto &type : selectedTypes) {
QString typeString = type;
filterModel->addFilter(
new CardFilter(typeString, CardFilter::Type::TypeAnd, CardFilter::Attr::AttrType));
}
// Exclude any other types (TypeAndNot)
for (const auto &type : typeButtons.keys()) {
if (!selectedTypes.contains(type)) {
QString typeString = type;
filterModel->addFilter(
new CardFilter(typeString, CardFilter::Type::TypeAndNot, CardFilter::Attr::AttrType));
}
}
}
} else {
// Default Includes Mode (TypeOr) - match any selected main types
for (const auto &type : activeMainTypes.keys()) {
if (activeMainTypes[type]) {
QString typeString = type;
filterModel->addFilter(
new CardFilter(typeString, CardFilter::Type::TypeAnd, CardFilter::Attr::AttrType));
}
}
}
}
void VisualDatabaseDisplayMainTypeFilterWidget::updateFilterMode(bool checked)
{
exactMatchMode = checked;
toggleButton->setText(exactMatchMode ? tr("Mode: Exact Match") : tr("Mode: Includes"));
updateMainTypeFilter();
}

View file

@ -0,0 +1,41 @@
#ifndef VISUAL_DATABASE_DISPLAY_MAIN_TYPE_FILTER_WIDGET_H
#define VISUAL_DATABASE_DISPLAY_MAIN_TYPE_FILTER_WIDGET_H
#include "../../../../game/filters/filter_tree_model.h"
#include "../general/layout_containers/flow_widget.h"
#include <QMap>
#include <QPushButton>
#include <QSpinBox>
#include <QToolButton>
#include <QVBoxLayout>
#include <QWidget>
class VisualDatabaseDisplayMainTypeFilterWidget : public QWidget
{
Q_OBJECT
public:
explicit VisualDatabaseDisplayMainTypeFilterWidget(QWidget *parent, FilterTreeModel *filterModel);
void createMainTypeButtons();
void updateMainTypeButtonsVisibility();
int getMaxMainTypeCount() const;
void handleMainTypeToggled(const QString &mainType, bool active);
void updateMainTypeFilter();
void updateFilterMode(bool checked);
private:
FilterTreeModel *filterModel;
QMap<QString, int> allMainCardTypesWithCount;
QSpinBox *spinBox;
QVBoxLayout *layout;
FlowWidget *flowWidget;
QPushButton *toggleButton; // Mode switch button
QMap<QString, bool> activeMainTypes; // Track active filters
QMap<QString, QPushButton *> typeButtons; // Store toggle buttons
bool exactMatchMode = false; // Toggle between "Exact Match" and "Includes"
};
#endif // VISUAL_DATABASE_DISPLAY_MAIN_TYPE_FILTER_WIDGET_H

View file

@ -0,0 +1,138 @@
#include "visual_database_display_set_filter_widget.h"
#include "../../../../game/cards/card_database_manager.h"
#include "../../../../game/filters/filter_tree_model.h"
#include <QLineEdit>
#include <QPushButton>
#include <algorithm>
VisualDatabaseDisplaySetFilterWidget::VisualDatabaseDisplaySetFilterWidget(QWidget *parent,
FilterTreeModel *_filterModel)
: QWidget(parent), filterModel(_filterModel)
{
setMinimumWidth(300);
setMaximumHeight(300);
layout = new QVBoxLayout(this);
setLayout(layout);
// Create the search box
searchBox = new QLineEdit(this);
searchBox->setPlaceholderText(tr("Search sets..."));
layout->addWidget(searchBox);
connect(searchBox, &QLineEdit::textChanged, this,
&VisualDatabaseDisplaySetFilterWidget::updateSetButtonsVisibility);
flowWidget = new FlowWidget(this, Qt::Horizontal, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAsNeeded);
layout->addWidget(flowWidget);
// Create the toggle button for Exact Match/Includes mode
toggleButton = new QPushButton(this);
toggleButton->setCheckable(true);
layout->addWidget(toggleButton);
connect(toggleButton, &QPushButton::toggled, this, &VisualDatabaseDisplaySetFilterWidget::updateFilterMode);
createSetButtons(); // Populate buttons initially
updateFilterMode(false); // Initialize toggle button text
}
void VisualDatabaseDisplaySetFilterWidget::createSetButtons()
{
SetList shared_pointerses = CardDatabaseManager::getInstance()->getSetList();
// Sort by release date
std::sort(shared_pointerses.begin(), shared_pointerses.end(),
[](const auto &a, const auto &b) { return a->getReleaseDate() > b->getReleaseDate(); });
for (const auto &shared_pointer : shared_pointerses) {
QString shortName = shared_pointer->getShortName();
QString longName = shared_pointer->getLongName();
auto *button = new QPushButton(longName + " (" + shortName + ")", flowWidget);
button->setCheckable(true);
button->setStyleSheet("QPushButton { background-color: lightgray; border: 1px solid gray; padding: 5px; }"
"QPushButton:checked { background-color: green; color: white; }");
flowWidget->addWidget(button);
setButtons[shortName] = button;
// Connect toggle signal
connect(button, &QPushButton::toggled, this,
[this, shortName](bool checked) { handleSetToggled(shortName, checked); });
}
updateSetButtonsVisibility(); // Ensure visibility is updated initially
}
void VisualDatabaseDisplaySetFilterWidget::updateSetButtonsVisibility()
{
QString filterText = searchBox->text().trimmed().toLower();
for (auto it = setButtons.begin(); it != setButtons.end(); ++it) {
QString shortName = it.key().toLower();
QString longName = it.value()->text().toLower();
bool alwaysVisible = activeSets.contains(it.key()) && activeSets[it.key()];
bool visible =
alwaysVisible || filterText.isEmpty() || shortName.contains(filterText) || longName.contains(filterText);
it.value()->setVisible(visible);
}
}
void VisualDatabaseDisplaySetFilterWidget::handleSetToggled(const QString &setShortName, bool active)
{
activeSets[setShortName] = active;
if (setButtons.contains(setShortName)) {
setButtons[setShortName]->setChecked(active);
}
updateSetFilter();
}
void VisualDatabaseDisplaySetFilterWidget::updateSetFilter()
{
// Clear existing filters related to sets
filterModel->clearFiltersOfType(CardFilter::Attr::AttrSet);
if (exactMatchMode) {
// Exact Match: Only selected sets are allowed
QSet<QString> selectedSets;
for (const auto &set : activeSets.keys()) {
if (activeSets[set]) {
selectedSets.insert(set);
}
}
if (!selectedSets.isEmpty()) {
// Require all selected sets (TypeAnd)
for (const auto &set : selectedSets) {
QString setString = set;
filterModel->addFilter(new CardFilter(setString, CardFilter::Type::TypeAnd, CardFilter::Attr::AttrSet));
}
// Exclude any other sets (TypeAndNot)
for (const auto &set : setButtons.keys()) {
if (!selectedSets.contains(set)) {
QString setString = set;
filterModel->addFilter(
new CardFilter(setString, CardFilter::Type::TypeAndNot, CardFilter::Attr::AttrSet));
}
}
}
} else {
// Default Includes Mode (TypeOr) - match any selected sets
for (const auto &set : activeSets.keys()) {
if (activeSets[set]) {
QString setString = set;
filterModel->addFilter(new CardFilter(setString, CardFilter::Type::TypeOr, CardFilter::Attr::AttrSet));
}
}
}
}
void VisualDatabaseDisplaySetFilterWidget::updateFilterMode(bool checked)
{
exactMatchMode = checked;
toggleButton->setText(exactMatchMode ? tr("Mode: Exact Match") : tr("Mode: Includes"));
updateSetFilter();
}

View file

@ -0,0 +1,42 @@
#ifndef VISUAL_DATABASE_DISPLAY_SET_FILTER_WIDGET_H
#define VISUAL_DATABASE_DISPLAY_SET_FILTER_WIDGET_H
#include "../../../../game/filters/filter_tree_model.h"
#include "../general/layout_containers/flow_widget.h"
#include <QLineEdit>
#include <QMap>
#include <QPushButton>
#include <QToolButton>
#include <QVBoxLayout>
#include <QWidget>
class VisualDatabaseDisplaySetFilterWidget : public QWidget
{
Q_OBJECT
public:
explicit VisualDatabaseDisplaySetFilterWidget(QWidget *parent, FilterTreeModel *filterModel);
void createSetButtons();
void updateSetButtonsVisibility();
void handleSetToggled(const QString &setShortName, bool active);
void updateSetFilter();
void updateFilterMode(bool checked);
private:
FilterTreeModel *filterModel;
QMap<QString, int> allMainCardTypesWithCount;
QVBoxLayout *layout;
QLineEdit *searchBox;
FlowWidget *flowWidget;
QPushButton *toggleButton; // Mode switch button
QMap<QString, bool> activeMainTypes; // Track active filters
QMap<QString, QPushButton *> typeButtons; // Store toggle buttons
QMap<QString, QPushButton *> setButtons; // Store set filter buttons
QMap<QString, bool> activeSets; // Track active set filters
bool exactMatchMode = false; // Toggle between "Exact Match" and "Includes"
};
#endif // VISUAL_DATABASE_DISPLAY_SET_FILTER_WIDGET_H

View file

@ -1,12 +1,18 @@
#include "visual_database_display_widget.h"
#include "../../../../deck/custom_line_edit.h"
#include "../../../../game/cards/card_database.h"
#include "../../../../game/cards/card_database_manager.h"
#include "../../../../main.h"
#include "../../../../game/filters/filter_tree_model.h"
#include "../../../../settings/cache_settings.h"
#include "../../../../utility/card_info_comparator.h"
#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_main_type_filter_widget.h"
#include "visual_database_display_set_filter_widget.h"
#include <QPushButton>
#include <QHeaderView>
#include <QScrollBar>
#include <qpropertyanimation.h>
@ -23,9 +29,79 @@ VisualDatabaseDisplayWidget::VisualDatabaseDisplayWidget(QWidget *parent,
// Set up main layout and widgets
setMinimumSize(0, 0);
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
main_layout = new QVBoxLayout();
main_layout = new QVBoxLayout(this);
setLayout(main_layout);
auto quickFilterWidget = new SettingsButtonWidget(this);
auto searchLayout = new QHBoxLayout(this);
searchEdit = new SearchLineEdit();
searchEdit->setObjectName("searchEdit");
searchEdit->setPlaceholderText(tr("Search by card name (or search expressions)"));
searchEdit->setClearButtonEnabled(true);
// searchEdit->addAction(loadColorAdjustedPixmap("theme:icons/search"), QLineEdit::LeadingPosition);
// auto help = searchEdit->addAction(QPixmap("theme:icons/info"), QLineEdit::TrailingPosition);
searchEdit->installEventFilter(&searchKeySignals);
setFocusProxy(searchEdit);
setFocusPolicy(Qt::ClickFocus);
filterModel = new FilterTreeModel();
filterModel->setObjectName("filterModel");
databaseDisplayModel->setFilterTree(filterModel->filterTree());
auto mainTypeFilterWidget = new VisualDatabaseDisplayMainTypeFilterWidget(this, filterModel);
quickFilterWidget->addSettingsWidget(mainTypeFilterWidget);
auto setFilterWidget = new VisualDatabaseDisplaySetFilterWidget(this, filterModel);
quickFilterWidget->addSettingsWidget(setFilterWidget);
colorFilterWidget = new VisualDatabaseDisplayColorFilterWidget(this, filterModel);
connect(filterModel, &FilterTreeModel::layoutChanged, this, &VisualDatabaseDisplayWidget::searchModelChanged);
searchKeySignals.setObjectName("searchKeySignals");
connect(searchEdit, SIGNAL(textChanged(const QString &)), this, SLOT(updateSearch(const QString &)));
/*connect(&searchKeySignals, SIGNAL(onEnter()), this, SLOT(actAddCard()));
connect(&searchKeySignals, SIGNAL(onCtrlAltEqual()), this, SLOT(actAddCard()));
connect(&searchKeySignals, SIGNAL(onCtrlAltRBracket()), this, SLOT(actAddCardToSideboard()));
connect(&searchKeySignals, SIGNAL(onCtrlAltMinus()), this, SLOT(actDecrementCard()));
connect(&searchKeySignals, SIGNAL(onCtrlAltLBracket()), this, SLOT(actDecrementCardFromSideboard()));
connect(&searchKeySignals, SIGNAL(onCtrlAltEnter()), this, SLOT(actAddCardToSideboard()));
connect(&searchKeySignals, SIGNAL(onCtrlEnter()), this, SLOT(actAddCardToSideboard()));
connect(&searchKeySignals, SIGNAL(onCtrlC()), this, SLOT(copyDatabaseCellContents()));*/
// connect(help, &QAction::triggered, this, &DeckEditorDatabaseDisplayWidget::showSearchSyntaxHelp);
/*databaseModel = new CardDatabaseModel(CardDatabaseManager::getInstance(), true, this);
databaseModel->setObjectName("databaseModel");
databaseDisplayModel = new CardDatabaseDisplayModel(this);
databaseDisplayModel->setSourceModel(databaseModel);
databaseDisplayModel->setFilterKeyColumn(0);*/
databaseView = new QTreeView(this);
databaseView->setObjectName("databaseView");
databaseView->setFocusProxy(searchEdit);
databaseView->setRootIsDecorated(false);
databaseView->setItemDelegate(nullptr);
databaseView->setSortingEnabled(true);
databaseView->sortByColumn(0, Qt::AscendingOrder);
databaseView->setModel(databaseDisplayModel);
databaseView->setVisible(false);
/*connect(databaseView->selectionModel(), SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)),
deckEditor, SLOT(updateCardInfoLeft(const QModelIndex &, const QModelIndex &)));
connect(databaseView->selectionModel(), SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)),
deckEditor, SLOT(updatePrintingSelectorDatabase(const QModelIndex &, const QModelIndex &)));*/
searchEdit->setTreeView(databaseView);
searchLayout->addWidget(colorFilterWidget);
searchLayout->addWidget(quickFilterWidget);
searchLayout->addWidget(searchEdit);
main_layout->addLayout(searchLayout);
flow_widget = new FlowWidget(this, Qt::Horizontal, Qt::ScrollBarAlwaysOff, Qt::ScrollBarPolicy::ScrollBarAsNeeded);
main_layout->addWidget(flow_widget);
@ -40,10 +116,7 @@ VisualDatabaseDisplayWidget::VisualDatabaseDisplayWidget(QWidget *parent,
auto loadCardsTimer = new QTimer(this);
loadCardsTimer->setSingleShot(true); // Ensure it only fires once after the timeout
connect(loadCardsTimer, &QTimer::timeout, this, [this]() {
qDebug() << "timer timed out";
loadCurrentPage();
});
connect(loadCardsTimer, &QTimer::timeout, this, [this]() { loadCurrentPage(); });
loadCardsTimer->start(5000);
}
@ -85,28 +158,37 @@ void VisualDatabaseDisplayWidget::populateCards()
int start = currentPage * cardsPerPage;
int end = qMin(start + cardsPerPage, rowCount);
qDebug() << "Fetching from " << start << " to " << end << " cards";
qCDebug(VisualDatabaseDisplayLog) << "Fetching from " << start << " to " << end << " cards";
// Load more cards if we are at the end of the current list and can fetch more
if (end >= rowCount && databaseDisplayModel->canFetchMore(QModelIndex())) {
qDebug() << "We gotta load more";
qCDebug(VisualDatabaseDisplayLog) << "We gotta load more";
databaseDisplayModel->fetchMore(QModelIndex());
}
for (int row = start; row < end; ++row) {
qDebug() << "Adding " << row;
qCDebug(VisualDatabaseDisplayLog) << "Adding " << row;
QModelIndex index = databaseDisplayModel->index(row, CardDatabaseModel::NameColumn);
QVariant name = databaseDisplayModel->data(index, Qt::DisplayRole);
qDebug() << name.toString();
qCDebug(VisualDatabaseDisplayLog) << name.toString();
CardInfoPtr info = CardDatabaseManager::getInstance()->getCard(name.toString());
if (info) {
addCard(info);
} else {
qDebug() << "Card not found in database!";
qCDebug(VisualDatabaseDisplayLog) << "Card not found in database!";
}
}
currentPage++;
}
void VisualDatabaseDisplayWidget::updateSearch(const QString &search)
{
databaseDisplayModel->setStringFilter(search);
QModelIndexList sel = databaseView->selectionModel()->selectedRows();
if (sel.isEmpty() && databaseDisplayModel->rowCount())
databaseView->selectionModel()->setCurrentIndex(databaseDisplayModel->index(0, 0),
QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
}
void VisualDatabaseDisplayWidget::searchModelChanged()
{
// Clear the current page and prepare for new data
@ -120,7 +202,7 @@ void VisualDatabaseDisplayWidget::searchModelChanged()
currentPage = 0;
loadCurrentPage();
qDebug() << "Search model changed";
qCDebug(VisualDatabaseDisplayLog) << "Search model changed";
}
void VisualDatabaseDisplayWidget::loadNextPage()
@ -143,7 +225,7 @@ void VisualDatabaseDisplayWidget::loadNextPage()
if (info) {
addCard(info);
} else {
qDebug() << "Card not found in database!";
qCDebug(VisualDatabaseDisplayLog) << "Card not found in database!";
}
}
@ -156,7 +238,7 @@ void VisualDatabaseDisplayWidget::loadCurrentPage()
// Ensure only the initial page is loaded
if (currentPage == 0) {
// Only load the first page initially
qDebug() << "Loading the first page";
qCDebug(VisualDatabaseDisplayLog) << "Loading the first page";
populateCards();
} else {
// If not the first page, just load the next page and append to the flow widget
@ -179,7 +261,7 @@ void VisualDatabaseDisplayWidget::databaseDataChanged(QModelIndex topLeft, QMode
{
(void)topLeft;
(void)bottomRight;
qDebug() << "Database Data changed";
qCDebug(VisualDatabaseDisplayLog) << "Database Data changed";
}
void VisualDatabaseDisplayWidget::wheelEvent(QWheelEvent *event)
@ -195,7 +277,7 @@ void VisualDatabaseDisplayWidget::wheelEvent(QWheelEvent *event)
event->accept(); // Accept the event as valid
return;
}
qDebug() << nextPageStartIndex << ":" << totalRows;
qCDebug(VisualDatabaseDisplayLog) << nextPageStartIndex << ":" << totalRows;
}
// Prevent overscrolling when there's no more data to load

View file

@ -1,20 +1,28 @@
#ifndef VISUAL_DATABASE_DISPLAY_WIDGET_H
#define VISUAL_DATABASE_DISPLAY_WIDGET_H
#include "../../../../deck/custom_line_edit.h"
#include "../../../../deck/deck_list_model.h"
#include "../../../../game/cards/card_database.h"
#include "../../../../game/cards/card_database_model.h"
#include "../../../../game/filters/filter_tree_model.h"
#include "../../../game_logic/key_signals.h"
#include "../../layouts/flow_layout.h"
#include "../cards/card_info_picture_with_text_overlay_widget.h"
#include "../cards/card_size_widget.h"
#include "../general/layout_containers/flow_widget.h"
#include "../general/layout_containers/overlap_control_widget.h"
#include "visual_database_display_color_filter_widget.h"
#include <QLoggingCategory>
#include <QTreeView>
#include <QVBoxLayout>
#include <QWheelEvent>
#include <QWidget>
#include <qscrollarea.h>
inline Q_LOGGING_CATEGORY(VisualDatabaseDisplayLog, "visual_database_display");
class VisualDatabaseDisplayWidget : public QWidget
{
Q_OBJECT
@ -23,15 +31,21 @@ public:
explicit VisualDatabaseDisplayWidget(QWidget *parent,
CardDatabaseModel *database_model,
CardDatabaseDisplayModel *database_display_model);
void updateDisplay();
void adjustCardsPerPage();
void populateCards();
void searchModelChanged();
void loadNextPage();
void loadCurrentPage();
void sortCardList(QStringList properties, Qt::SortOrder order);
void setDeckList(const DeckList &new_deck_list_model);
SearchLineEdit *searchEdit;
FilterTreeModel *filterModel;
VisualDatabaseDisplayColorFilterWidget *colorFilterWidget;
public slots:
void searchModelChanged();
signals:
void cardClickedDatabaseDisplay(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance);
void cardHoveredDatabaseDisplay(CardInfoPtr hoveredCard);
@ -43,10 +57,13 @@ protected slots:
void databaseDataChanged(QModelIndex topLeft, QModelIndex bottomRight);
void wheelEvent(QWheelEvent *event) override;
void modelDirty();
void updateSearch(const QString &search);
private:
KeySignals searchKeySignals;
CardDatabaseModel *databaseModel;
CardDatabaseDisplayModel *databaseDisplayModel;
QTreeView *databaseView;
QList<CardInfoPtr> *cards;
QVBoxLayout *main_layout;
QScrollArea *scrollArea;
@ -60,7 +77,7 @@ private:
int debounce_time = 300;
int currentPage = 0; // Current page index
int cardsPerPage = 200; // Number of cards per page
int cardsPerPage = 100; // Number of cards per page
protected:
void resizeEvent(QResizeEvent *event) override;

View file

@ -16,8 +16,8 @@
#include <QResizeEvent>
#include <qscrollarea.h>
VisualDeckEditorWidget::VisualDeckEditorWidget(QWidget *parent, DeckListModel *deck_list_model)
: QWidget(parent), deck_list_model(deck_list_model)
VisualDeckEditorWidget::VisualDeckEditorWidget(QWidget *parent, DeckListModel *_deck_list_model)
: QWidget(parent), deck_list_model(_deck_list_model)
{
this->mainDeckCards = new QList<CardInfoPtr>;
this->sideboardCards = new QList<CardInfoPtr>;