mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-07-15 06:52:15 -07:00
Visual Deck Editor.
This commit is contained in:
parent
13d18986b2
commit
0c73768c79
32 changed files with 3474 additions and 0 deletions
|
|
@ -25,6 +25,8 @@
|
|||
#include "tab_replays.h"
|
||||
#include "tab_room.h"
|
||||
#include "tab_server.h"
|
||||
#include "visual_deck_editor/tab_deck_editor_visual.h"
|
||||
#include "visual_deck_editor/tab_deck_editor_visual_tab_widget.h"
|
||||
#include "visual_deck_storage/tab_deck_storage_visual.h"
|
||||
|
||||
#include <QApplication>
|
||||
|
|
@ -804,6 +806,14 @@ TabDeckEditor *TabSupervisor::addDeckEditorTab(const DeckLoader *deckToOpen)
|
|||
return tab;
|
||||
}
|
||||
|
||||
TabDeckEditorVisual *TabSupervisor::addVisualDeckEditorTab()
|
||||
{
|
||||
TabDeckEditorVisual *tab = new TabDeckEditorVisual(this);
|
||||
myAddTab(tab);
|
||||
setCurrentWidget(tab);
|
||||
return tab;
|
||||
}
|
||||
|
||||
TabEdhRec *TabSupervisor::addEdhrecTab(const CardInfoPtr &cardToQuery, bool isCommander)
|
||||
{
|
||||
auto *tab = new TabEdhRec(this);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
#define TAB_SUPERVISOR_H
|
||||
|
||||
#include "../../deck/deck_loader.h"
|
||||
#include "visual_deck_editor/tab_deck_editor_visual.h"
|
||||
#include "visual_deck_editor/tab_deck_editor_visual_tab_widget.h"
|
||||
#include "../../server/user/user_list_proxy.h"
|
||||
#include "abstract_tab_deck_editor.h"
|
||||
#include "api/edhrec/tab_edhrec.h"
|
||||
|
|
@ -150,6 +152,8 @@ signals:
|
|||
public slots:
|
||||
TabDeckEditor *addDeckEditorTab(const DeckLoader *deckToOpen);
|
||||
TabEdhRec *addEdhrecTab(const CardInfoPtr &cardToQuery, bool isCommander = false);
|
||||
TabDeckStorageVisual *addVisualDeckStorageTab();
|
||||
TabDeckEditorVisual *addVisualDeckEditorTab();
|
||||
void openReplay(GameReplay *replay);
|
||||
void maximizeMainWindow();
|
||||
private slots:
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,151 @@
|
|||
#ifndef WINDOW_DECKEDITORVISUAL_H
|
||||
#define WINDOW_DECKEDITORVISUAL_H
|
||||
|
||||
#include "../../../deck/custom_line_edit.h"
|
||||
#include "../../game_logic/key_signals.h"
|
||||
#include "../tab.h"
|
||||
#include "../tab_deck_editor.h"
|
||||
#include "tab_deck_editor_visual_tab_widget.h"
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QDir>
|
||||
|
||||
class TabDeckEditorVisual : public Tab
|
||||
{
|
||||
Q_OBJECT
|
||||
private slots:
|
||||
void updateName(const QString &name);
|
||||
void updateComments();
|
||||
void updateHash();
|
||||
void updateCardInfoLeft(const QModelIndex ¤t, const QModelIndex &previous);
|
||||
void updateCardInfoRight(const QModelIndex ¤t, const QModelIndex &previous);
|
||||
void updateSearch(const QString &search);
|
||||
void databaseCustomMenu(QPoint point);
|
||||
|
||||
void actNewDeck();
|
||||
void actLoadDeck();
|
||||
bool actSaveDeck();
|
||||
bool actSaveDeckAs();
|
||||
void actLoadDeckFromClipboard();
|
||||
void actSaveDeckToClipboard();
|
||||
void actSaveDeckToClipboardRaw();
|
||||
void actPrintDeck();
|
||||
void actExportDeckDecklist();
|
||||
void actAnalyzeDeckDeckstats();
|
||||
void actAnalyzeDeckTappedout();
|
||||
|
||||
void actClearFilterAll();
|
||||
void actClearFilterOne();
|
||||
|
||||
void actSwapCard();
|
||||
void actAddCard();
|
||||
void actAddCardToSideboard();
|
||||
void actRemoveCard();
|
||||
void actIncrement();
|
||||
void actDecrement();
|
||||
void actDecrementCard();
|
||||
void actDecrementCardFromSideboard();
|
||||
void copyDatabaseCellContents();
|
||||
|
||||
void saveDeckRemoteFinished(const Response &r);
|
||||
void filterViewCustomContextMenu(const QPoint &point);
|
||||
void filterRemove(QAction *action);
|
||||
|
||||
void loadLayout();
|
||||
void restartLayout();
|
||||
void freeDocksSize();
|
||||
void refreshShortcuts();
|
||||
|
||||
bool eventFilter(QObject *o, QEvent *e) override;
|
||||
void dockVisibleTriggered();
|
||||
void dockFloatingTriggered();
|
||||
void dockTopLevelChanged(bool topLevel);
|
||||
void saveDbHeaderState();
|
||||
void setSaveStatus(bool newStatus);
|
||||
void showSearchSyntaxHelp();
|
||||
|
||||
private:
|
||||
CardInfoPtr currentCardInfo() const;
|
||||
void changeModelIndexToCard(CardInfoPtr activeCard);
|
||||
void addCardHelper(QString zoneName);
|
||||
void addCardInfo(CardInfoPtr info, QString zoneName);
|
||||
void offsetCountAtIndex(const QModelIndex &idx, int offset);
|
||||
void decrementCardHelper(QString zoneName);
|
||||
void recursiveExpand(const QModelIndex &index);
|
||||
|
||||
QWidget *parent;
|
||||
|
||||
CardDatabaseModel *databaseModel;
|
||||
CardDatabaseDisplayModel *databaseDisplayModel;
|
||||
DeckListModel *deckModel;
|
||||
QTreeView *databaseView;
|
||||
|
||||
TabDeckEditorVisualTabWidget *tabContainer;
|
||||
|
||||
QTreeView *deckView;
|
||||
KeySignals deckViewKeySignals;
|
||||
CardInfoFrameWidget *cardInfo;
|
||||
|
||||
SearchLineEdit *searchEdit;
|
||||
KeySignals searchKeySignals;
|
||||
|
||||
QLabel *nameLabel;
|
||||
LineEditUnfocusable *nameEdit;
|
||||
QLabel *commentsLabel;
|
||||
QTextEdit *commentsEdit;
|
||||
QLabel *hashLabel1;
|
||||
LineEditUnfocusable *hashLabel;
|
||||
FilterTreeModel *filterModel;
|
||||
QTreeView *filterView;
|
||||
KeySignals filterViewKeySignals;
|
||||
QWidget *filterBox;
|
||||
|
||||
QMenu *deckMenu, *viewMenu, *cardInfoDockMenu, *deckDockMenu, *deckAnalyticsMenu, *filterDockMenu, *analyzeDeckMenu,
|
||||
*saveDeckToClipboardMenu;
|
||||
QAction *aNewDeck, *aLoadDeck, *aSaveDeck, *aSaveDeckAs, *aLoadDeckFromClipboard, *aSaveDeckToClipboard,
|
||||
*aSaveDeckToClipboardRaw, *aPrintDeck, *aExportDeckDecklist, *aAnalyzeDeckDeckstats, *aAnalyzeDeckTappedout,
|
||||
*aClose;
|
||||
QAction *aClearFilterAll, *aClearFilterOne;
|
||||
QAction *aAddCard, *aAddCardToSideboard, *aRemoveCard, *aIncrement, *aDecrement;
|
||||
QAction *aResetLayout;
|
||||
QAction *aCardInfoDockVisible, *aCardInfoDockFloating, *aDeckDockVisible, *aDeckDockFloating,
|
||||
*aDeckAnalyticsDockFloating, *aDeckAnalyticsDockVisible, *aFilterDockVisible, *aFilterDockFloating;
|
||||
|
||||
bool modified;
|
||||
QVBoxLayout *centralFrame;
|
||||
QVBoxLayout *searchAndDatabaseFrame;
|
||||
QHBoxLayout *searchLayout;
|
||||
QDockWidget *searchAndDatabaseDock;
|
||||
QDockWidget *cardInfoDock;
|
||||
QDockWidget *deckAnalyticsDock;
|
||||
QDockWidget *deckDock;
|
||||
QDockWidget *filterDock;
|
||||
QWidget *centralWidget;
|
||||
|
||||
public:
|
||||
explicit TabDeckEditorVisual(TabSupervisor *_tabSupervisor, QWidget *parent = nullptr);
|
||||
~TabDeckEditorVisual() override;
|
||||
void retranslateUi() override;
|
||||
QString getTabText() const override;
|
||||
void setDeck(DeckLoader *_deckLoader);
|
||||
void setModified(bool _windowModified);
|
||||
bool confirmClose();
|
||||
void createDeckDock();
|
||||
void createCardInfoDock();
|
||||
void createDeckAnalyticsDock();
|
||||
void createFiltersDock();
|
||||
void createMenus();
|
||||
void createSearchAndDatabaseFrame();
|
||||
void createCentralFrame();
|
||||
|
||||
public slots:
|
||||
void setCurrentCardInfo(CardInfoPtr activeCard);
|
||||
void changeModelIndexAndCardInfo(CardInfoPtr activeCard);
|
||||
void processMainboardCardClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance);
|
||||
void processSideboardCardClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance);
|
||||
void processCardClickDatabaseDisplay(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance);
|
||||
signals:
|
||||
void deckEditorClosing(TabDeckEditorVisual *tab);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
#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 ¤t, const QModelIndex &previous)
|
||||
{
|
||||
(void)current;
|
||||
(void)previous;
|
||||
}
|
||||
void TabDeckEditorVisualDatabaseSearchTab::updateCardInfoRight(const QModelIndex ¤t, 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;
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
#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 ¤t, const QModelIndex &previous);
|
||||
void updateCardInfoRight(const QModelIndex ¤t, 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
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
//
|
||||
// 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
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
//
|
||||
// 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
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
#include "tab_deck_editor_visual_tab_widget.h"
|
||||
|
||||
#include "../../ui/widgets/visual_database_display/visual_database_display_widget.h"
|
||||
|
||||
TabDeckEditorVisualTabWidget::TabDeckEditorVisualTabWidget(QWidget *parent,
|
||||
DeckListModel *model,
|
||||
CardDatabaseModel *card_database_model,
|
||||
CardDatabaseDisplayModel *card_database_display_model)
|
||||
: QTabWidget(parent), deckModel(model), cardDatabaseModel(card_database_model),
|
||||
cardDatabaseDisplayModel(card_database_display_model)
|
||||
{
|
||||
this->setTabsClosable(true); // Enable tab closing
|
||||
connect(this, &QTabWidget::tabCloseRequested, this, &TabDeckEditorVisualTabWidget::handleTabClose);
|
||||
|
||||
// Set up the layout and add tab widget
|
||||
layout = new QVBoxLayout(this);
|
||||
setLayout(layout);
|
||||
|
||||
visualDeckView = new VisualDeckEditorWidget(this, this->deckModel);
|
||||
visualDeckView->setObjectName("visualDeckView");
|
||||
visualDeckView->updateDisplay();
|
||||
connect(visualDeckView, SIGNAL(activeCardChanged(CardInfoPtr)), this, SLOT(onCardChanged(CardInfoPtr)));
|
||||
connect(visualDeckView, SIGNAL(mainboardCardClicked(QMouseEvent *, CardInfoPictureWithTextOverlayWidget *)), this,
|
||||
SLOT(onMainboardCardClickedDeckEditor(QMouseEvent *, CardInfoPictureWithTextOverlayWidget *)));
|
||||
connect(visualDeckView, SIGNAL(sideboardCardClicked(QMouseEvent *, CardInfoPictureWithTextOverlayWidget *)), this,
|
||||
SLOT(onSideboardCardClickedDeckEditor(QMouseEvent *, CardInfoPictureWithTextOverlayWidget *)));
|
||||
|
||||
visualDatabaseDisplay =
|
||||
new VisualDatabaseDisplayWidget(this, this->cardDatabaseModel, this->cardDatabaseDisplayModel);
|
||||
visualDatabaseDisplay->setObjectName("visualDatabaseView");
|
||||
visualDatabaseDisplay->updateDisplay();
|
||||
connect(visualDatabaseDisplay, SIGNAL(cardHoveredDatabaseDisplay(CardInfoPtr)), this,
|
||||
SLOT(onCardChangedDatabaseDisplay(CardInfoPtr)));
|
||||
connect(visualDatabaseDisplay,
|
||||
SIGNAL(cardClickedDatabaseDisplay(QMouseEvent *, CardInfoPictureWithTextOverlayWidget *)), this,
|
||||
SLOT(onCardClickedDatabaseDisplay(QMouseEvent *, CardInfoPictureWithTextOverlayWidget *)));
|
||||
|
||||
deckAnalytics = new DeckAnalyticsWidget(this, this->deckModel);
|
||||
deckAnalytics->setObjectName("deckAnalytics");
|
||||
// deckAnalytics->analyzeManaCurve();
|
||||
|
||||
this->addNewTab(visualDeckView, "Visual Deck View");
|
||||
this->addNewTab(visualDatabaseDisplay, "Visual Database Display");
|
||||
this->addNewTab(deckAnalytics, "Deck Analytics");
|
||||
}
|
||||
|
||||
void TabDeckEditorVisualTabWidget::onCardChanged(CardInfoPtr activeCard)
|
||||
{
|
||||
emit cardChanged(activeCard);
|
||||
}
|
||||
|
||||
void TabDeckEditorVisualTabWidget::onCardChangedDatabaseDisplay(CardInfoPtr activeCard)
|
||||
{
|
||||
emit cardChangedDatabaseDisplay(activeCard);
|
||||
}
|
||||
|
||||
void TabDeckEditorVisualTabWidget::onMainboardCardClickedDeckEditor(QMouseEvent *event,
|
||||
CardInfoPictureWithTextOverlayWidget *instance)
|
||||
{
|
||||
emit mainboardCardClicked(event, instance);
|
||||
}
|
||||
|
||||
void TabDeckEditorVisualTabWidget::onSideboardCardClickedDeckEditor(QMouseEvent *event,
|
||||
CardInfoPictureWithTextOverlayWidget *instance)
|
||||
{
|
||||
emit sideboardCardClicked(event, instance);
|
||||
}
|
||||
|
||||
void TabDeckEditorVisualTabWidget::onCardClickedDatabaseDisplay(QMouseEvent *event,
|
||||
CardInfoPictureWithTextOverlayWidget *instance)
|
||||
{
|
||||
emit cardClickedDatabaseDisplay(event, instance);
|
||||
}
|
||||
|
||||
void TabDeckEditorVisualTabWidget::addNewTab(QWidget *widget, const QString &title)
|
||||
{
|
||||
// Add new tab to the tab widget
|
||||
this->addTab(widget, title);
|
||||
}
|
||||
|
||||
void TabDeckEditorVisualTabWidget::removeCurrentTab()
|
||||
{
|
||||
// Remove the currently selected tab
|
||||
int currentIndex = this->currentIndex();
|
||||
if (currentIndex != -1) {
|
||||
this->removeTab(currentIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void TabDeckEditorVisualTabWidget::setTabTitle(int index, const QString &title)
|
||||
{
|
||||
// Set the title of the tab at the given index
|
||||
if (index >= 0 && index < this->count()) {
|
||||
this->setTabText(index, title);
|
||||
}
|
||||
}
|
||||
|
||||
QWidget *TabDeckEditorVisualTabWidget::getCurrentTab() const
|
||||
{
|
||||
// Return the currently selected tab widget
|
||||
return this->currentWidget();
|
||||
}
|
||||
|
||||
int TabDeckEditorVisualTabWidget::getTabCount() const
|
||||
{
|
||||
// Return the number of tabs
|
||||
return this->count();
|
||||
}
|
||||
|
||||
void TabDeckEditorVisualTabWidget::handleTabClose(int index)
|
||||
{
|
||||
// Handle closing of the tab at the given index
|
||||
QWidget *tab = this->widget(index);
|
||||
this->removeTab(index);
|
||||
delete tab; // Delete the tab's widget to free memory
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
#ifndef TAB_DECK_EDITOR_VISUAL_TAB_WIDGET_H
|
||||
#define TAB_DECK_EDITOR_VISUAL_TAB_WIDGET_H
|
||||
|
||||
#include "../../ui/widgets/deck_analytics/deck_analytics_widget.h"
|
||||
#include "../../ui/widgets/visual_database_display/visual_database_display_widget.h"
|
||||
#include "../../ui/widgets/visual_deck_editor/visual_deck_editor_widget.h"
|
||||
|
||||
#include <QTabWidget>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
|
||||
class TabDeckEditorVisualTabWidget : public QTabWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TabDeckEditorVisualTabWidget(QWidget *parent = nullptr,
|
||||
DeckListModel *deckModel = nullptr,
|
||||
CardDatabaseModel *card_database_model = nullptr,
|
||||
CardDatabaseDisplayModel *card_database_display_model = nullptr);
|
||||
|
||||
// Utility functions
|
||||
void addNewTab(QWidget *widget, const QString &title);
|
||||
void removeCurrentTab();
|
||||
void setTabTitle(int index, const QString &title);
|
||||
QWidget *getCurrentTab() const;
|
||||
int getTabCount() const;
|
||||
|
||||
VisualDeckEditorWidget *visualDeckView;
|
||||
DeckAnalyticsWidget *deckAnalytics;
|
||||
VisualDatabaseDisplayWidget *visualDatabaseDisplay;
|
||||
|
||||
public slots:
|
||||
void onCardChanged(CardInfoPtr activeCard);
|
||||
void onCardChangedDatabaseDisplay(CardInfoPtr activeCard);
|
||||
void onMainboardCardClickedDeckEditor(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance);
|
||||
void onSideboardCardClickedDeckEditor(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance);
|
||||
void onCardClickedDatabaseDisplay(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance);
|
||||
|
||||
signals:
|
||||
void cardChanged(CardInfoPtr activeCard);
|
||||
void cardChangedDatabaseDisplay(CardInfoPtr activeCard);
|
||||
void mainboardCardClicked(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance);
|
||||
void sideboardCardClicked(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance);
|
||||
void cardClickedDatabaseDisplay(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance);
|
||||
|
||||
private:
|
||||
QVBoxLayout *layout; // Layout for the tab widget and other controls
|
||||
DeckListModel *deckModel;
|
||||
CardDatabaseModel *cardDatabaseModel;
|
||||
CardDatabaseDisplayModel *cardDatabaseDisplayModel;
|
||||
|
||||
private slots:
|
||||
void handleTabClose(int index); // Slot for closing a tab
|
||||
};
|
||||
|
||||
#endif // TAB_DECK_EDITOR_VISUAL_TAB_WIDGET_H
|
||||
|
|
@ -61,6 +61,7 @@ CardInfoFrameWidget::CardInfoFrameWidget(const QString &cardName, QWidget *paren
|
|||
|
||||
setViewMode(SettingsCache::instance().getCardInfoViewMode());
|
||||
|
||||
// TODO: Change this to be by UUID
|
||||
setCard(CardDatabaseManager::getInstance()->getCard(cardName));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
#include "deck_card_zone_display_widget.h"
|
||||
|
||||
#include "overlapped_card_group_display_widget.h"
|
||||
|
||||
#include <QResizeEvent>
|
||||
|
||||
DeckCardZoneDisplayWidget::DeckCardZoneDisplayWidget(QWidget *parent,
|
||||
QList<QPair<QString, QList<CardInfoPtr>>> cardLists,
|
||||
QString bannerText,
|
||||
int bannerOpacity,
|
||||
int subBannerOpacity)
|
||||
: QWidget(parent), cardLists(cardLists), bannerOpacity(bannerOpacity), subBannerOpacity(subBannerOpacity)
|
||||
{
|
||||
layout = new QVBoxLayout(this);
|
||||
setLayout(layout);
|
||||
|
||||
banner = new BannerWidget(bannerText, Qt::Orientation::Vertical, bannerOpacity, this);
|
||||
layout->addWidget(banner);
|
||||
|
||||
displayCards();
|
||||
}
|
||||
void DeckCardZoneDisplayWidget::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
QWidget::resizeEvent(event);
|
||||
for (QObject *child : layout->children()) {
|
||||
QWidget *widget = qobject_cast<QWidget *>(child);
|
||||
if (widget) {
|
||||
widget->resize(event->size());
|
||||
}
|
||||
}
|
||||
}
|
||||
void DeckCardZoneDisplayWidget::onClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *card)
|
||||
{
|
||||
emit cardClicked(event, card);
|
||||
}
|
||||
void DeckCardZoneDisplayWidget::onHover(CardInfoPtr card)
|
||||
{
|
||||
emit cardHovered(card);
|
||||
}
|
||||
|
||||
void DeckCardZoneDisplayWidget::displayCards()
|
||||
{
|
||||
for (QPair<QString, QList<CardInfoPtr>> &pair : cardLists) {
|
||||
QString criteriaValue = pair.first;
|
||||
QList<CardInfoPtr> cardList = pair.second;
|
||||
|
||||
OverlappedCardGroupDisplayWidget *display_widget =
|
||||
new OverlappedCardGroupDisplayWidget(this, &cardList, criteriaValue, subBannerOpacity);
|
||||
connect(display_widget, SIGNAL(cardClicked(QMouseEvent *, CardInfoPictureWithTextOverlayWidget *)), this,
|
||||
SLOT(onClick(QMouseEvent *, CardInfoPictureWithTextOverlayWidget *)));
|
||||
connect(display_widget, SIGNAL(cardHovered(CardInfoPtr)), this, SLOT(onHover(CardInfoPtr)));
|
||||
layout->addWidget(display_widget);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
#ifndef DECK_CARD_ZONE_DISPLAY_WIDGET_H
|
||||
#define DECK_CARD_ZONE_DISPLAY_WIDGET_H
|
||||
|
||||
#include "../../../../game/cards/card_database.h"
|
||||
#include "../general/display/banner_widget.h"
|
||||
#include "../general/layout_containers/overlap_widget.h"
|
||||
#include "card_info_picture_with_text_overlay_widget.h"
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
|
||||
class DeckCardZoneDisplayWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DeckCardZoneDisplayWidget(QWidget *parent,
|
||||
QList<QPair<QString, QList<CardInfoPtr>>> cardLists,
|
||||
QString bannerText,
|
||||
int bannerOpacity,
|
||||
int subBannerOpacity);
|
||||
void addCardsToOverlapWidget();
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
|
||||
public slots:
|
||||
void onClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *card);
|
||||
void onHover(CardInfoPtr card);
|
||||
void displayCards();
|
||||
|
||||
signals:
|
||||
void cardClicked(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *card);
|
||||
void cardHovered(CardInfoPtr card);
|
||||
|
||||
private:
|
||||
QList<QPair<QString, QList<CardInfoPtr>>> cardLists;
|
||||
QVBoxLayout *layout;
|
||||
BannerWidget *banner;
|
||||
int bannerOpacity = 20;
|
||||
int subBannerOpacity = 10;
|
||||
OverlapWidget *overlapWidget;
|
||||
};
|
||||
|
||||
#endif // DECK_CARD_ZONE_DISPLAY_WIDGET_H
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
#include "overlapped_card_group_display_widget.h"
|
||||
|
||||
#include "card_info_picture_with_text_overlay_widget.h"
|
||||
|
||||
#include <QResizeEvent>
|
||||
|
||||
OverlappedCardGroupDisplayWidget::OverlappedCardGroupDisplayWidget(QWidget *parent,
|
||||
QList<CardInfoPtr> *cards,
|
||||
QString bannerText,
|
||||
int bannerOpacity)
|
||||
: QWidget(parent), cardsToDisplay(cards)
|
||||
{
|
||||
layout = new QVBoxLayout(this);
|
||||
setLayout(layout);
|
||||
setMinimumSize(QSize(0, 0));
|
||||
|
||||
banner = new BannerWidget(bannerText, Qt::Orientation::Vertical, bannerOpacity, this);
|
||||
overlapWidget = new OverlapWidget(this, 80, 1, 1, Qt::Vertical, true);
|
||||
|
||||
layout->addWidget(banner);
|
||||
layout->addWidget(overlapWidget);
|
||||
addCardsToOverlapWidget();
|
||||
}
|
||||
|
||||
void OverlappedCardGroupDisplayWidget::addCardsToOverlapWidget()
|
||||
{
|
||||
for (int i = 0; i < cardsToDisplay->size(); i++) {
|
||||
CardInfoPtr card = cardsToDisplay->at(i);
|
||||
if (card) {
|
||||
CardInfoPictureWithTextOverlayWidget *display =
|
||||
new CardInfoPictureWithTextOverlayWidget(overlapWidget, true);
|
||||
display->setCard(card);
|
||||
|
||||
connect(display, SIGNAL(imageClicked(QMouseEvent *, CardInfoPictureWithTextOverlayWidget *)), this,
|
||||
SLOT(onClick(QMouseEvent *, CardInfoPictureWithTextOverlayWidget *)));
|
||||
connect(display, SIGNAL(hoveredOnCard(CardInfoPtr)), this, SLOT(onHover(CardInfoPtr)));
|
||||
overlapWidget->addWidget(display);
|
||||
}
|
||||
}
|
||||
overlapWidget->adjustMaxColumnsAndRows();
|
||||
}
|
||||
|
||||
void OverlappedCardGroupDisplayWidget::onClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *card)
|
||||
{
|
||||
emit cardClicked(event, card);
|
||||
}
|
||||
|
||||
void OverlappedCardGroupDisplayWidget::onHover(CardInfoPtr card)
|
||||
{
|
||||
emit cardHovered(card);
|
||||
}
|
||||
|
||||
void OverlappedCardGroupDisplayWidget::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
QWidget::resizeEvent(event);
|
||||
|
||||
overlapWidget->resize(event->size());
|
||||
overlapWidget->adjustMaxColumnsAndRows();
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
//
|
||||
// Created by ascor on 11/12/24.
|
||||
//
|
||||
|
||||
#ifndef OVERLAPPED_CARD_GROUP_DISPLAY_WIDGET_H
|
||||
#define OVERLAPPED_CARD_GROUP_DISPLAY_WIDGET_H
|
||||
|
||||
#include "../../../../game/cards/card_database.h"
|
||||
#include "../general/display/banner_widget.h"
|
||||
#include "../general/layout_containers/overlap_widget.h"
|
||||
#include "card_info_picture_with_text_overlay_widget.h"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
|
||||
class OverlappedCardGroupDisplayWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
OverlappedCardGroupDisplayWidget(QWidget *parent, QList<CardInfoPtr> *cards, QString bannerText, int bannerOpacity);
|
||||
void addCardsToOverlapWidget();
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
|
||||
public slots:
|
||||
void onClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *card);
|
||||
void onHover(CardInfoPtr card);
|
||||
|
||||
signals:
|
||||
void cardClicked(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *card);
|
||||
void cardHovered(CardInfoPtr card);
|
||||
|
||||
private:
|
||||
QList<CardInfoPtr> *cardsToDisplay;
|
||||
QVBoxLayout *layout;
|
||||
BannerWidget *banner;
|
||||
OverlapWidget *overlapWidget;
|
||||
};
|
||||
|
||||
#endif // OVERLAPPED_CARD_GROUP_DISPLAY_WIDGET_H
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
#include "deck_analytics_widget.h"
|
||||
|
||||
DeckAnalyticsWidget::DeckAnalyticsWidget(QWidget *parent, DeckListModel *deck_list_model)
|
||||
: QWidget(parent), deck_list_model(deck_list_model)
|
||||
{
|
||||
|
||||
this->setMinimumSize(0, 0);
|
||||
this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
this->setStyleSheet("border: 2px solid red;");
|
||||
main_layout = new QHBoxLayout();
|
||||
this->setLayout(main_layout);
|
||||
|
||||
flow_widget = new FlowWidget(this, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAlwaysOff);
|
||||
this->main_layout->addWidget(flow_widget);
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
#ifndef DECK_ANALYTICS_WIDGET_H
|
||||
#define DECK_ANALYTICS_WIDGET_H
|
||||
|
||||
#include "../../../../deck/deck_list_model.h"
|
||||
#include "../../../ui/widgets/general/layout_containers/flow_widget.h"
|
||||
#include "mana_base_widget.h"
|
||||
#include "mana_curve_widget.h"
|
||||
#include "mana_devotion_widget.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QWidget>
|
||||
#include <decklist.h>
|
||||
#include <qscrollarea.h>
|
||||
|
||||
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);
|
||||
std::map<int, int> analyzeManaCurve();
|
||||
|
||||
private:
|
||||
DeckListModel *deck_list_model;
|
||||
QHBoxLayout *main_layout;
|
||||
FlowWidget *flow_widget;
|
||||
|
||||
ManaCurveWidget *mana_curve_widget;
|
||||
ManaDevotionWidget *mana_devotion_widget;
|
||||
ManaBaseWidget *mana_base_widget;
|
||||
};
|
||||
|
||||
#endif // DECK_ANALYTICS_WIDGET_H
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
#include "mana_base_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/bar_widget.h"
|
||||
|
||||
#include <QRegularExpression>
|
||||
#include <decklist.h>
|
||||
#include <regex>
|
||||
#include <unordered_map>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
std::unordered_map<char, int> ManaBaseWidget::analyzeManaBase()
|
||||
{
|
||||
manaBaseMap = std::unordered_map<char, int>();
|
||||
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) {
|
||||
auto devotion = determineManaProduction(info->getText());
|
||||
mergeManaCounts(manaBaseMap, devotion);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update();
|
||||
// this->setCurve(ManaBaseMap);
|
||||
// mana_curve_widget->updateDisplay();
|
||||
this->updateDisplay();
|
||||
update();
|
||||
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);
|
||||
}
|
||||
|
||||
int totalSum = 0;
|
||||
for (auto entry : manaBaseMap) {
|
||||
totalSum += entry.second;
|
||||
}
|
||||
|
||||
// Add new widgets to the layout
|
||||
for (auto entry : manaBaseMap) {
|
||||
BarWidget *barWidget = new BarWidget(QString(entry.first), entry.second, totalSum, this);
|
||||
layout->addWidget(barWidget);
|
||||
}
|
||||
|
||||
update(); // Update the widget display
|
||||
}
|
||||
|
||||
std::unordered_map<char, int> ManaBaseWidget::determineManaProduction(const QString &rulesText)
|
||||
{
|
||||
// Initialize mana counts
|
||||
std::unordered_map<char, int> manaCounts = {{'W', 0}, {'U', 0}, {'B', 0}, {'R', 0}, {'G', 0}, {'C', 0}};
|
||||
|
||||
// Define regex patterns for different mana production rules
|
||||
QRegularExpression tapAddColorless(R"(\{T\}:\s*Add\s*\{C\}|Add\s*one\s*colorless\s*mana)");
|
||||
QRegularExpression tapAddAnyColor(
|
||||
R"(\{T\}:\s*Add\s*one\s*mana\s*of\s*any\s*color|Add\s*one\s*mana\s*of\s*any\s*color)");
|
||||
QRegularExpression tapAddSpecificColor(
|
||||
R"(\{T\}:\s*Add\s*\{(W|U|B|R|G)\}|Add\s*one\s*(white|blue|black|red|green)\s*mana)");
|
||||
|
||||
// Check for mana production rules in the text
|
||||
if (tapAddColorless.match(rulesText).hasMatch()) {
|
||||
manaCounts['C'] += 1; // Adds colorless mana
|
||||
}
|
||||
|
||||
if (tapAddAnyColor.match(rulesText).hasMatch()) {
|
||||
manaCounts['W'] += 1; // Assumes at least 1 of any color can be produced
|
||||
manaCounts['U'] += 1;
|
||||
manaCounts['B'] += 1;
|
||||
manaCounts['R'] += 1;
|
||||
manaCounts['G'] += 1;
|
||||
}
|
||||
|
||||
// Check for specific color production
|
||||
QRegularExpression specificColorRegex(R"(\{T\}:\s*Add\s*\{(W|U|B|R|G)\})");
|
||||
auto match = specificColorRegex.match(rulesText);
|
||||
if (match.hasMatch()) {
|
||||
QString color = match.captured(1);
|
||||
if (color == "W")
|
||||
manaCounts['W'] += 1;
|
||||
else if (color == "U")
|
||||
manaCounts['U'] += 1;
|
||||
else if (color == "B")
|
||||
manaCounts['B'] += 1;
|
||||
else if (color == "R")
|
||||
manaCounts['R'] += 1;
|
||||
else if (color == "G")
|
||||
manaCounts['G'] += 1;
|
||||
}
|
||||
|
||||
return manaCounts;
|
||||
}
|
||||
|
||||
void ManaBaseWidget::mergeManaCounts(std::unordered_map<char, int> &manaCounts1,
|
||||
const std::unordered_map<char, int> &manaCounts2)
|
||||
{
|
||||
for (const auto &pair : manaCounts2) {
|
||||
manaCounts1[pair.first] += pair.second; // Add values for matching keys
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
#include "../../../../deck/deck_list_model.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QWidget>
|
||||
#include <decklist.h>
|
||||
#include <utility>
|
||||
|
||||
#ifndef MANA_BASE_WIDGET_H
|
||||
#define MANA_BASE_WIDGET_H
|
||||
|
||||
class ManaBaseWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ManaBaseWidget(QWidget *parent = nullptr, DeckListModel *deck_list_model = nullptr);
|
||||
std::unordered_map<char, int> analyzeManaBase();
|
||||
void updateDisplay();
|
||||
|
||||
std::unordered_map<char, int> determineManaProduction(const QString &manaString);
|
||||
void mergeManaCounts(std::unordered_map<char, int> &manaCounts1, const std::unordered_map<char, int> &manaCounts2);
|
||||
|
||||
private:
|
||||
DeckListModel *deck_list_model;
|
||||
std::unordered_map<char, int> manaBaseMap;
|
||||
QHBoxLayout *layout;
|
||||
};
|
||||
|
||||
#endif // MANA_BASE_WIDGET_H
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
#include "mana_curve_widget.h"
|
||||
|
||||
#include "../general/display/bar_widget.h"
|
||||
|
||||
#include <QLabel>
|
||||
|
||||
ManaCurveWidget::ManaCurveWidget(QWidget *parent) : QWidget(parent)
|
||||
{
|
||||
layout = new QHBoxLayout(this);
|
||||
this->setLayout(layout);
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
setMinimumSize(0, 0);
|
||||
}
|
||||
|
||||
void ManaCurveWidget::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);
|
||||
}
|
||||
|
||||
int totalSum = 0;
|
||||
for (auto entry : curve) {
|
||||
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);
|
||||
}
|
||||
|
||||
update(); // Update the widget display
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#ifndef MANA_CURVE_WIDGET_H
|
||||
#define MANA_CURVE_WIDGET_H
|
||||
#include <QHBoxLayout>
|
||||
#include <QWidget>
|
||||
#include <utility>
|
||||
|
||||
class ManaCurveWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ManaCurveWidget(QWidget *parent = nullptr);
|
||||
void updateDisplay();
|
||||
|
||||
void setCurve(std::map<int, int> new_curve)
|
||||
{
|
||||
this->curve = std::move(new_curve);
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<int, int> curve;
|
||||
QHBoxLayout *layout;
|
||||
};
|
||||
|
||||
#endif // MANA_CURVE_WIDGET_H
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
#include "mana_devotion_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/bar_widget.h"
|
||||
|
||||
#include <decklist.h>
|
||||
#include <iostream>
|
||||
#include <regex>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
std::unordered_map<char, int> ManaDevotionWidget::analyzeManaDevotion()
|
||||
{
|
||||
manaDevotionMap = std::unordered_map<char, int>();
|
||||
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) {
|
||||
auto devotion = countManaSymbols(info->getManaCost());
|
||||
mergeManaCounts(manaDevotionMap, devotion);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update();
|
||||
// this->setCurve(manaDevotionMap);
|
||||
// mana_curve_widget->updateDisplay();
|
||||
this->updateDisplay();
|
||||
update();
|
||||
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);
|
||||
}
|
||||
|
||||
int totalSum = 0;
|
||||
for (auto entry : manaDevotionMap) {
|
||||
totalSum += entry.second;
|
||||
}
|
||||
|
||||
// Add new widgets to the layout
|
||||
for (auto entry : manaDevotionMap) {
|
||||
BarWidget *barWidget = new BarWidget(QString(entry.first), entry.second, totalSum, this);
|
||||
layout->addWidget(barWidget);
|
||||
}
|
||||
|
||||
update(); // Update the widget display
|
||||
}
|
||||
|
||||
// Function to count mana symbols W, U, B, R, G in the input string
|
||||
std::unordered_map<char, int> ManaDevotionWidget::countManaSymbols(const QString &manaString)
|
||||
{
|
||||
// Only track counts for W, U, B, R, G
|
||||
std::unordered_map<char, int> manaCounts = {{'W', 0}, {'U', 0}, {'B', 0}, {'R', 0}, {'G', 0}};
|
||||
|
||||
// Convert QString to std::string for regex processing
|
||||
std::string stdManaString = manaString.toStdString();
|
||||
std::regex regexPattern(R"(\{([WUBRG])\/([WUBRG])\})");
|
||||
std::string::const_iterator searchStart(stdManaString.cbegin());
|
||||
std::smatch match;
|
||||
|
||||
// Go through the string and find pairs within {}/ for W, U, B, R, G
|
||||
while (std::regex_search(searchStart, stdManaString.cend(), match, regexPattern)) {
|
||||
char mana1 = match[1].str()[0];
|
||||
char mana2 = match[2].str()[0];
|
||||
|
||||
// Increment the count for both mana symbols
|
||||
manaCounts[mana1]++;
|
||||
manaCounts[mana2]++;
|
||||
|
||||
// Move past the current match
|
||||
searchStart = match.suffix().first;
|
||||
}
|
||||
|
||||
// Now go through the string again but ignore the {}/ parts and non-WUBRG symbols
|
||||
for (int i = 0; i < manaString.size(); ++i) {
|
||||
if (manaString[i] == '{') {
|
||||
// Skip over the {X/Y} pattern
|
||||
while (manaString[i] != '}' && i < manaString.size()) {
|
||||
++i;
|
||||
}
|
||||
} else if (manaCounts.find(manaString[i].toLatin1()) != manaCounts.end()) {
|
||||
// If it's one of W, U, B, R, G, count it
|
||||
manaCounts[manaString[i].toLatin1()]++;
|
||||
}
|
||||
}
|
||||
|
||||
return manaCounts;
|
||||
}
|
||||
|
||||
void ManaDevotionWidget::mergeManaCounts(std::unordered_map<char, int> &manaCounts1,
|
||||
const std::unordered_map<char, int> &manaCounts2)
|
||||
{
|
||||
for (const auto &pair : manaCounts2) {
|
||||
manaCounts1[pair.first] += pair.second; // Add values for matching keys
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#ifndef MANA_DEVOTION_WIDGET_H
|
||||
#define MANA_DEVOTION_WIDGET_H
|
||||
#include "../../../../deck/deck_list_model.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QWidget>
|
||||
#include <decklist.h>
|
||||
#include <utility>
|
||||
|
||||
class ManaDevotionWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
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);
|
||||
|
||||
private:
|
||||
DeckListModel *deck_list_model;
|
||||
std::unordered_map<char, int> manaDevotionMap;
|
||||
QHBoxLayout *layout;
|
||||
};
|
||||
|
||||
#endif // MANA_DEVOTION_WIDGET_H
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
#include "bar_widget.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
BarWidget::BarWidget(QString label, int value, int total, QWidget *parent)
|
||||
: QWidget(parent), label(std::move(label)), value(value), total(total)
|
||||
{
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
}
|
||||
|
||||
QSize BarWidget::sizeHint() const
|
||||
{
|
||||
QFontMetrics metrics(font());
|
||||
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
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
// Draw the full bar background (gray)
|
||||
painter.setBrush(QColor(200, 200, 200)); // Gray background for full bar
|
||||
painter.drawRect(0, 10, 20, fullBarWidth);
|
||||
|
||||
// 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 the CMC label
|
||||
painter.setPen(Qt::white);
|
||||
QRect textRect(0, fullBarWidth + 10, 20, 30); // Define a rectangle for text
|
||||
painter.drawText(textRect, Qt::AlignCenter, label);
|
||||
|
||||
painter.setPen(Qt::black);
|
||||
QRect valueRect(0, 10, 20, fullBarWidth); // Define a rectangle for text
|
||||
painter.drawText(valueRect, Qt::AlignCenter, QString::number(value));
|
||||
|
||||
(void)event; // Suppress unused parameter warning
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#ifndef BAR_WIDGET_H
|
||||
#define BAR_WIDGET_H
|
||||
|
||||
#include <QPainter>
|
||||
#include <QWidget>
|
||||
|
||||
class BarWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
BarWidget(QString label, int value, int total, QWidget *parent = nullptr);
|
||||
|
||||
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)
|
||||
};
|
||||
|
||||
#endif // BAR_WIDGET_H
|
||||
|
|
@ -0,0 +1,273 @@
|
|||
#include "visual_database_display_widget.h"
|
||||
|
||||
#include "../../../../game/cards/card_database.h"
|
||||
#include "../../../../game/cards/card_database_manager.h"
|
||||
#include "../../../../main.h"
|
||||
#include "../../../../utility/card_info_comparator.h"
|
||||
#include "../cards/card_info_picture_with_text_overlay_widget.h"
|
||||
|
||||
#include <QPushButton>
|
||||
#include <qpropertyanimation.h>
|
||||
|
||||
VisualDatabaseDisplayWidget::VisualDatabaseDisplayWidget(QWidget *parent,
|
||||
CardDatabaseModel *database_model,
|
||||
CardDatabaseDisplayModel *database_display_model)
|
||||
: QWidget(parent), databaseModel(database_model), databaseDisplayModel(database_display_model)
|
||||
{
|
||||
cards = new QList<CardInfoPtr>;
|
||||
connect(databaseDisplayModel, &CardDatabaseDisplayModel::modelDirty, this,
|
||||
&VisualDatabaseDisplayWidget::modelDirty);
|
||||
|
||||
// Set up main layout and widgets
|
||||
setMinimumSize(0, 0);
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
main_layout = new QVBoxLayout();
|
||||
setLayout(main_layout);
|
||||
|
||||
flow_widget = new FlowWidget(this, Qt::ScrollBarAlwaysOff, Qt::ScrollBarPolicy::ScrollBarAsNeeded);
|
||||
main_layout->addWidget(flow_widget);
|
||||
|
||||
overlap_control_widget = new OverlapControlWidget(80, 10, 10, Qt::Vertical, flow_widget);
|
||||
main_layout->addWidget(overlap_control_widget);
|
||||
|
||||
debounce_timer = new QTimer(this);
|
||||
debounce_timer->setSingleShot(true); // Ensure it only fires once after the timeout
|
||||
|
||||
connect(debounce_timer, &QTimer::timeout, this, &VisualDatabaseDisplayWidget::searchModelChanged);
|
||||
setupPaginationControls();
|
||||
loadCurrentPage(); // Load the first page of cards
|
||||
}
|
||||
|
||||
void VisualDatabaseDisplayWidget::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
QWidget::resizeEvent(event);
|
||||
loadCurrentPage();
|
||||
}
|
||||
|
||||
void VisualDatabaseDisplayWidget::onClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance)
|
||||
{
|
||||
emit cardClickedDatabaseDisplay(event, instance);
|
||||
}
|
||||
|
||||
void VisualDatabaseDisplayWidget::onHover(CardInfoPtr hoveredCard)
|
||||
{
|
||||
emit cardHoveredDatabaseDisplay(hoveredCard);
|
||||
}
|
||||
|
||||
void VisualDatabaseDisplayWidget::populateCards()
|
||||
{
|
||||
this->cards->clear();
|
||||
int rowCount = databaseDisplayModel->rowCount();
|
||||
|
||||
// Calculate the start and end indices for the current page
|
||||
int start = currentPage * cardsPerPage;
|
||||
int end = qMin(start + cardsPerPage, rowCount);
|
||||
|
||||
// Load more cards if we are at the end of the current list and can fetch more
|
||||
if (end >= rowCount && databaseDisplayModel->canFetchMore(QModelIndex())) {
|
||||
databaseDisplayModel->fetchMore(QModelIndex());
|
||||
}
|
||||
|
||||
for (int row = start; row < end; ++row) {
|
||||
QModelIndex index = databaseDisplayModel->index(row, CardDatabaseModel::NameColumn);
|
||||
QVariant name = databaseDisplayModel->data(index, Qt::DisplayRole);
|
||||
CardInfoPtr info = CardDatabaseManager::getInstance()->getCard(name.toString());
|
||||
cards->append(info);
|
||||
}
|
||||
}
|
||||
|
||||
void VisualDatabaseDisplayWidget::searchModelChanged()
|
||||
{
|
||||
currentPage = 0;
|
||||
loadCurrentPage();
|
||||
}
|
||||
|
||||
void VisualDatabaseDisplayWidget::loadCurrentPage()
|
||||
{
|
||||
// If an animation is already in progress, don't start a new one
|
||||
if (isAnimating) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the flag indicating animation is in progress
|
||||
isAnimating = true;
|
||||
|
||||
// Store the original position of the widget
|
||||
QPoint originalPos = flow_widget->pos();
|
||||
|
||||
// Create the first animation to slide the flow_widget
|
||||
QPropertyAnimation *slideOutAnimation = new QPropertyAnimation(flow_widget, "pos");
|
||||
slideOutAnimation->setDuration(300); // Adjust for smoothness
|
||||
slideOutAnimation->setStartValue(originalPos); // Start from the current position
|
||||
|
||||
// Adjust the position (e.g., slide it up or down)
|
||||
QPoint slideOutPos = originalPos;
|
||||
slideOutPos.setY(originalPos.y() - flow_widget->height()); // Slide up (adjust direction as needed)
|
||||
slideOutAnimation->setEndValue(slideOutPos); // End at the new position
|
||||
|
||||
// Create the second animation to bring it back to its original position
|
||||
QPropertyAnimation *slideBackAnimation = new QPropertyAnimation(flow_widget, "pos");
|
||||
slideBackAnimation->setDuration(300); // Duration for smooth transition
|
||||
slideBackAnimation->setStartValue(slideOutPos); // Start from where the first animation ended
|
||||
slideBackAnimation->setEndValue(originalPos); // End at the original position
|
||||
|
||||
// Connect the end of the first animation to the start of the second
|
||||
connect(slideOutAnimation, &QPropertyAnimation::finished, [this, slideBackAnimation]() {
|
||||
// After sliding out, adjust the number of cards, load the new page, and start the slide back animation
|
||||
adjustCardsPerPage(); // Adjust the cards per page before loading
|
||||
populateCards(); // Load the new page of cards
|
||||
updateDisplay(); // Update the visual display
|
||||
|
||||
// Start sliding back to original position
|
||||
slideBackAnimation->start(QAbstractAnimation::DeleteWhenStopped);
|
||||
});
|
||||
|
||||
// Once the second animation finishes, allow new animations to start
|
||||
connect(slideBackAnimation, &QPropertyAnimation::finished, [this]() {
|
||||
isAnimating = false; // Reset the flag after animation finishes
|
||||
});
|
||||
|
||||
// Start the slide-out animation
|
||||
slideOutAnimation->start(QAbstractAnimation::DeleteWhenStopped);
|
||||
}
|
||||
|
||||
void VisualDatabaseDisplayWidget::updateDisplay()
|
||||
{
|
||||
// Clear the layout first
|
||||
flow_widget->clearLayout();
|
||||
|
||||
OverlapWidget *printings_group_widget = new OverlapWidget(flow_widget, 0, cardsPerRow, rowsPerColumn, Qt::Vertical);
|
||||
|
||||
// Create card widgets and store their sizes
|
||||
QList<CardInfoPictureWithTextOverlayWidget *> cardDisplays;
|
||||
for (const auto &info : *cards) {
|
||||
if (info) {
|
||||
CardInfoPictureWithTextOverlayWidget *display =
|
||||
new CardInfoPictureWithTextOverlayWidget(printings_group_widget, true);
|
||||
display->setCard(info);
|
||||
cardDisplays.append(display);
|
||||
printings_group_widget->addWidget(display);
|
||||
connect(display, SIGNAL(imageClicked(QMouseEvent *, CardInfoPictureWithTextOverlayWidget *)), this,
|
||||
SLOT(onClick(QMouseEvent *, CardInfoPictureWithTextOverlayWidget *)));
|
||||
connect(display, SIGNAL(hoveredOnCard(CardInfoPtr)), this, SLOT(onHover(CardInfoPtr)));
|
||||
} else {
|
||||
qDebug() << "Card not found in database!";
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the maximum size of the card widgets after they've been added to the layout
|
||||
// adjustCardsPerPage();
|
||||
|
||||
overlap_control_widget->connectOverlapWidget(printings_group_widget);
|
||||
flow_widget->addWidget(printings_group_widget);
|
||||
flow_widget->update();
|
||||
|
||||
update(); // Update the widget display
|
||||
}
|
||||
|
||||
void VisualDatabaseDisplayWidget::adjustCardsPerPage()
|
||||
{
|
||||
// Calculate available width and height in the OverlapWidget
|
||||
int availableWidth = flow_widget->width();
|
||||
int availableHeight = flow_widget->height();
|
||||
|
||||
QList<CardInfoPictureWithTextOverlayWidget *> cardDisplays;
|
||||
for (OverlapWidget *child : flow_widget->findChildren<OverlapWidget *>()) {
|
||||
for (CardInfoPictureWithTextOverlayWidget *overlapChild :
|
||||
child->findChildren<CardInfoPictureWithTextOverlayWidget *>()) {
|
||||
if (CardInfoPictureWithTextOverlayWidget *cardDisplay =
|
||||
qobject_cast<CardInfoPictureWithTextOverlayWidget *>(overlapChild)) {
|
||||
cardDisplays.append(cardDisplay);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Measure the size of the first card display to determine the size of cards
|
||||
if (!cardDisplays.isEmpty()) {
|
||||
int cardWidth = cardDisplays.first()->sizeHint().width();
|
||||
int cardHeight = cardDisplays.first()->sizeHint().height();
|
||||
const int overlapMargin = 10; // Margin between cards
|
||||
|
||||
// Calculate how many cards can fit horizontally and vertically
|
||||
cardsPerRow = availableWidth / (cardWidth + overlapMargin);
|
||||
rowsPerColumn = availableHeight / (cardHeight + overlapMargin);
|
||||
// qDebug() << "available width " << availableWidth << "available height: " << availableHeight;
|
||||
// qDebug() << "width: " << cardWidth << "height: " << cardHeight << "cardsPerRow: " << cardsPerRow <<
|
||||
// "rowsPerColumn: " << rowsPerColumn;
|
||||
|
||||
// Update cardsPerPage based on rows and columns
|
||||
cardsPerPage = cardsPerRow * rowsPerColumn;
|
||||
// qDebug() << "Adjusted cards per page to:" << cardsPerPage;
|
||||
}
|
||||
}
|
||||
|
||||
void VisualDatabaseDisplayWidget::modelDirty()
|
||||
{
|
||||
debounce_timer->start(debounce_time);
|
||||
}
|
||||
|
||||
void VisualDatabaseDisplayWidget::sortCardList(const QStringList properties, Qt::SortOrder order = Qt::AscendingOrder)
|
||||
{
|
||||
CardInfoComparator comparator(properties, order);
|
||||
std::sort(cards->begin(), cards->end(), comparator);
|
||||
}
|
||||
|
||||
void VisualDatabaseDisplayWidget::databaseDataChanged(QModelIndex topLeft, QModelIndex bottomRight)
|
||||
{
|
||||
(void)topLeft;
|
||||
(void)bottomRight;
|
||||
updateDisplay();
|
||||
}
|
||||
|
||||
void VisualDatabaseDisplayWidget::wheelEvent(QWheelEvent *event)
|
||||
{
|
||||
if (isAnimating) {
|
||||
return;
|
||||
}
|
||||
// Check scroll direction
|
||||
if (event->angleDelta().y() > 0) {
|
||||
// Scrolling up
|
||||
if (currentPage > 0) {
|
||||
currentPage--;
|
||||
loadCurrentPage(); // Load the previous page
|
||||
}
|
||||
} else if (event->angleDelta().y() < 0) {
|
||||
// Scrolling down
|
||||
if ((currentPage + 1) * cardsPerPage < databaseDisplayModel->rowCount()) {
|
||||
currentPage++;
|
||||
loadCurrentPage(); // Load the next page
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent overscrolling by stopping the event if needed
|
||||
if ((currentPage == 0 && event->angleDelta().y() > 0) ||
|
||||
((currentPage + 1) * cardsPerPage >= databaseDisplayModel->rowCount() && event->angleDelta().y() < 0)) {
|
||||
event->ignore(); // Ignore the event to prevent overscrolling
|
||||
} else {
|
||||
event->accept(); // Accept the event if scrolling is valid
|
||||
}
|
||||
}
|
||||
|
||||
void VisualDatabaseDisplayWidget::setupPaginationControls()
|
||||
{
|
||||
QPushButton *prevButton = new QPushButton("Previous", this);
|
||||
QPushButton *nextButton = new QPushButton("Next", this);
|
||||
|
||||
connect(prevButton, &QPushButton::clicked, this, [this]() {
|
||||
if (currentPage > 0) {
|
||||
currentPage--;
|
||||
loadCurrentPage();
|
||||
}
|
||||
});
|
||||
|
||||
connect(nextButton, &QPushButton::clicked, this, [this]() {
|
||||
if ((currentPage + 1) * cardsPerPage < databaseDisplayModel->rowCount()) {
|
||||
currentPage++;
|
||||
loadCurrentPage();
|
||||
}
|
||||
});
|
||||
|
||||
// Add buttons to layout (for example, at the bottom of the main layout)
|
||||
main_layout->addWidget(prevButton);
|
||||
main_layout->addWidget(nextButton);
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
#ifndef VISUAL_DATABASE_DISPLAY_WIDGET_H
|
||||
#define VISUAL_DATABASE_DISPLAY_WIDGET_H
|
||||
|
||||
#include "../../../../deck/deck_list_model.h"
|
||||
#include "../../../../game/cards/card_database.h"
|
||||
#include "../../../../game/cards/card_database_model.h"
|
||||
#include "../../layouts/flow_layout.h"
|
||||
#include "../cards/card_info_picture_with_text_overlay_widget.h"
|
||||
#include "../general/layout_containers/flow_widget.h"
|
||||
#include "../general/layout_containers/overlap_control_widget.h"
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QWheelEvent>
|
||||
#include <QWidget>
|
||||
#include <qscrollarea.h>
|
||||
|
||||
class VisualDatabaseDisplayWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit VisualDatabaseDisplayWidget(QWidget *parent,
|
||||
CardDatabaseModel *database_model,
|
||||
CardDatabaseDisplayModel *database_display_model);
|
||||
void updateDisplay();
|
||||
void adjustCardsPerPage();
|
||||
void populateCards();
|
||||
void searchModelChanged();
|
||||
void loadCurrentPage();
|
||||
void sortCardList(QStringList properties, Qt::SortOrder order);
|
||||
void setDeckList(const DeckList &new_deck_list_model);
|
||||
|
||||
signals:
|
||||
void cardClickedDatabaseDisplay(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance);
|
||||
void cardHoveredDatabaseDisplay(CardInfoPtr hoveredCard);
|
||||
|
||||
protected slots:
|
||||
void onClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance);
|
||||
void onHover(CardInfoPtr hoveredCard);
|
||||
void databaseDataChanged(QModelIndex topLeft, QModelIndex bottomRight);
|
||||
void wheelEvent(QWheelEvent *event) override;
|
||||
void setupPaginationControls();
|
||||
void modelDirty();
|
||||
|
||||
private:
|
||||
CardDatabaseModel *databaseModel;
|
||||
CardDatabaseDisplayModel *databaseDisplayModel;
|
||||
QList<CardInfoPtr> *cards;
|
||||
QVBoxLayout *main_layout;
|
||||
QScrollArea *scrollArea;
|
||||
FlowWidget *flow_widget;
|
||||
QWidget *overlap_categories;
|
||||
QVBoxLayout *overlap_categories_layout;
|
||||
OverlapControlWidget *overlap_control_widget;
|
||||
QWidget *container;
|
||||
QTimer *debounce_timer;
|
||||
|
||||
bool isAnimating = false;
|
||||
int debounce_time = 300;
|
||||
int currentPage = 0; // Current page index
|
||||
int cardsPerPage = 9; // Number of cards per page
|
||||
int cardsPerRow = 0;
|
||||
int rowsPerColumn = 0;
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
};
|
||||
|
||||
#endif // VISUAL_DATABASE_DISPLAY_WIDGET_H
|
||||
|
|
@ -0,0 +1,247 @@
|
|||
#include "visual_deck_editor_widget.h"
|
||||
|
||||
#include "../../../../deck/deck_list_model.h"
|
||||
#include "../../../../deck/deck_loader.h"
|
||||
#include "../../../../game/cards/card_database.h"
|
||||
#include "../../../../game/cards/card_database_manager.h"
|
||||
#include "../../../../main.h"
|
||||
#include "../../../../utility/card_info_comparator.h"
|
||||
#include "../../layouts/flow_layout.h"
|
||||
#include "../../layouts/overlap_layout.h"
|
||||
#include "../../layouts/vertical_flow_layout.h"
|
||||
#include "../cards/card_info_picture_with_text_overlay_widget.h"
|
||||
#include "../cards/deck_card_zone_display_widget.h"
|
||||
#include "../cards/overlapped_card_group_display_widget.h"
|
||||
#include "../general/layout_containers/flow_widget.h"
|
||||
#include "../general/layout_containers/overlap_control_widget.h"
|
||||
#include "../general/layout_containers/overlap_widget.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QResizeEvent>
|
||||
#include <qscrollarea.h>
|
||||
|
||||
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>;
|
||||
connect(deck_list_model, &DeckListModel::dataChanged, this, &VisualDeckEditorWidget::decklistDataChanged);
|
||||
|
||||
// The Main Widget and Main Layout, which contain a single Widget: The Scroll Area
|
||||
this->setMinimumSize(0, 0);
|
||||
this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
mainLayout = new QVBoxLayout();
|
||||
this->setLayout(mainLayout);
|
||||
|
||||
sortByComboBox = new QComboBox();
|
||||
QStringList sortProperties;
|
||||
sortProperties << "maintype"
|
||||
<< "colors"
|
||||
<< "cmc"
|
||||
<< "name";
|
||||
sortByComboBox->addItems(sortProperties);
|
||||
connect(sortByComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(activeSortCriteriaChanged()));
|
||||
|
||||
scrollArea = new QScrollArea();
|
||||
scrollArea->setWidgetResizable(true);
|
||||
scrollArea->setMinimumSize(0, 0);
|
||||
|
||||
// Set scrollbar policies
|
||||
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
|
||||
zoneContainer = new QWidget(scrollArea);
|
||||
zoneContainerLayout = new QVBoxLayout(zoneContainer);
|
||||
zoneContainer->setLayout(zoneContainerLayout);
|
||||
scrollArea->addScrollBarWidget(zoneContainer, Qt::AlignHCenter);
|
||||
scrollArea->setWidget(zoneContainer);
|
||||
|
||||
flowWidget = new FlowWidget(this, Qt::ScrollBarAlwaysOff, Qt::ScrollBarAsNeeded);
|
||||
|
||||
overlap_control_widget = new OverlapControlWidget(80, 1, 1, Qt::Vertical, this);
|
||||
|
||||
mainLayout->addWidget(sortByComboBox);
|
||||
mainLayout->addWidget(scrollArea);
|
||||
mainLayout->addWidget(overlap_control_widget);
|
||||
}
|
||||
|
||||
void VisualDeckEditorWidget::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
QWidget::resizeEvent(event);
|
||||
zoneContainer->setMaximumWidth(scrollArea->viewport()->width());
|
||||
}
|
||||
|
||||
void VisualDeckEditorWidget::activeSortCriteriaChanged()
|
||||
{
|
||||
activeSortCriteria = sortByComboBox->currentText();
|
||||
qDebug() << "activeSortCriteria changed: " << activeSortCriteria;
|
||||
updateDisplay();
|
||||
}
|
||||
|
||||
void VisualDeckEditorWidget::decklistDataChanged(QModelIndex topLeft, QModelIndex bottomRight)
|
||||
{
|
||||
// Might use these at some point.
|
||||
(void)topLeft;
|
||||
(void)bottomRight;
|
||||
// Necessary to delay this in this manner else the updateDisplay will nuke widgets while their onClick event
|
||||
// hasn't returned yet. Interval of 0 means QT will schedule this after the current event loop has finished.
|
||||
QTimer::singleShot(0, this, [this] { updateDisplay(); });
|
||||
}
|
||||
|
||||
void VisualDeckEditorWidget::updateDisplay()
|
||||
{
|
||||
// Clear the layout first
|
||||
populateCards();
|
||||
zoneContainer = new QWidget(scrollArea);
|
||||
zoneContainerLayout = new QVBoxLayout(zoneContainer);
|
||||
|
||||
DeckCardZoneDisplayWidget *mainBoardWidget =
|
||||
new DeckCardZoneDisplayWidget(zoneContainer, sortCards(mainDeckCards), "Mainboard", 20, 10);
|
||||
connect(mainBoardWidget, SIGNAL(cardHovered(CardInfoPtr)), this, SLOT(onHover(CardInfoPtr)));
|
||||
connect(mainBoardWidget, SIGNAL(cardClicked(QMouseEvent *, CardInfoPictureWithTextOverlayWidget *)), this,
|
||||
SLOT(onMainboardClick(QMouseEvent *, CardInfoPictureWithTextOverlayWidget *)));
|
||||
|
||||
DeckCardZoneDisplayWidget *sideBoardWidget =
|
||||
new DeckCardZoneDisplayWidget(zoneContainer, sortCards(sideboardCards), "Sideboard", 40, 30);
|
||||
connect(sideBoardWidget, SIGNAL(cardHovered(CardInfoPtr)), this, SLOT(onHover(CardInfoPtr)));
|
||||
connect(sideBoardWidget, SIGNAL(cardClicked(QMouseEvent *, CardInfoPictureWithTextOverlayWidget *)), this,
|
||||
SLOT(onSideboardClick(QMouseEvent *, CardInfoPictureWithTextOverlayWidget *)));
|
||||
|
||||
zoneContainerLayout->addWidget(mainBoardWidget);
|
||||
zoneContainerLayout->addWidget(sideBoardWidget);
|
||||
|
||||
scrollArea->setWidget(zoneContainer);
|
||||
update();
|
||||
}
|
||||
|
||||
QList<QPair<QString, QList<CardInfoPtr>>> VisualDeckEditorWidget::sortCards(QList<CardInfoPtr> *cardsToSort)
|
||||
{
|
||||
QList<QPair<QString, QList<CardInfoPtr>>> sortedCardGroups;
|
||||
QList<CardInfoPtr> activeList;
|
||||
|
||||
QStringList sortCriteria;
|
||||
sortCriteria.append(activeSortCriteria);
|
||||
sortCardList(sortCriteria, Qt::SortOrder::AscendingOrder);
|
||||
|
||||
QString lastSortCriteriaValue = cardsToSort->isEmpty() ? "" : cardsToSort->at(0)->getProperty(activeSortCriteria);
|
||||
|
||||
for (int i = 0; i < cardsToSort->size(); ++i) {
|
||||
CardInfoPtr info = cardsToSort->at(i);
|
||||
if (info) {
|
||||
QString currentCriteriaValue = info->getProperty(activeSortCriteria);
|
||||
if (currentCriteriaValue != lastSortCriteriaValue) {
|
||||
// Save the current tuple (criteriaValue, list) and start a new list
|
||||
sortedCardGroups.append(qMakePair(lastSortCriteriaValue, activeList));
|
||||
activeList.clear();
|
||||
lastSortCriteriaValue = currentCriteriaValue;
|
||||
}
|
||||
activeList.append(info);
|
||||
} else {
|
||||
qDebug() << "Card not found in database!";
|
||||
}
|
||||
}
|
||||
|
||||
// Add the last tuple to sortedCardGroups
|
||||
if (!activeList.isEmpty()) {
|
||||
sortedCardGroups.append(qMakePair(lastSortCriteriaValue, activeList));
|
||||
}
|
||||
|
||||
return sortedCardGroups;
|
||||
}
|
||||
|
||||
/*void VisualDeckEditorWidget::sortCards()
|
||||
{
|
||||
QStringList sortCriteria;
|
||||
sortCriteria.append(activeSortCriteria);
|
||||
this->sortCardList(sortCriteria, Qt::SortOrder::AscendingOrder);
|
||||
QString lastSortCriteriaValue = "";
|
||||
overlapCategories = new QWidget(scrollArea);
|
||||
overlapCategoriesLayout = new QVBoxLayout(overlapCategories);
|
||||
OverlapWidget *printings_group_widget = new OverlapWidget(80, 1, 1, Qt::Vertical, overlapCategories);
|
||||
overlap_control_widget->connectOverlapWidget(printings_group_widget);
|
||||
for (int i = 0; i < cards->size(); i++) {
|
||||
CardInfoPtr info = cards->at(i);
|
||||
if (info) {
|
||||
if (info->getProperty(activeSortCriteria) != lastSortCriteriaValue) {
|
||||
printings_group_widget->adjustMaxColumnsAndRows();
|
||||
lastSortCriteriaValue = info->getProperty(activeSortCriteria);
|
||||
printings_group_widget = new OverlapWidget(80, 1, 1, Qt::Vertical, overlapCategories);
|
||||
overlapCategoriesLayout->addWidget(printings_group_widget);
|
||||
overlap_control_widget->connectOverlapWidget(printings_group_widget);
|
||||
}
|
||||
CardInfoPictureWithTextOverlayWidget* display = new
|
||||
CardInfoPictureWithTextOverlayWidget(printings_group_widget, true);
|
||||
|
||||
display->setCard(info);
|
||||
printings_group_widget->addWidget(display);
|
||||
update();
|
||||
} else {
|
||||
qDebug() << "Card not found in database!";
|
||||
}
|
||||
}
|
||||
printings_group_widget->adjustMaxColumnsAndRows();
|
||||
|
||||
scrollArea->setWidget(overlapCategories);
|
||||
update();
|
||||
}*/
|
||||
|
||||
void VisualDeckEditorWidget::onHover(CardInfoPtr hoveredCard)
|
||||
{
|
||||
emit activeCardChanged(hoveredCard);
|
||||
}
|
||||
|
||||
void VisualDeckEditorWidget::onMainboardClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance)
|
||||
{
|
||||
emit mainboardCardClicked(event, instance);
|
||||
}
|
||||
|
||||
void VisualDeckEditorWidget::onSideboardClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance)
|
||||
{
|
||||
emit sideboardCardClicked(event, instance);
|
||||
}
|
||||
|
||||
void VisualDeckEditorWidget::populateCards()
|
||||
{
|
||||
mainDeckCards->clear();
|
||||
sideboardCards->clear();
|
||||
|
||||
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;
|
||||
for (int k = 0; k < currentCard->getNumber(); ++k) {
|
||||
CardInfoPtr info = CardDatabaseManager::getInstance()->getCardByNameAndProviderId(
|
||||
currentCard->getName(), currentCard->getCardProviderId());
|
||||
if (info) {
|
||||
if (currentZone->getName() == DECK_ZONE_MAIN) {
|
||||
mainDeckCards->append(info);
|
||||
} else if (currentZone->getName() == DECK_ZONE_SIDE) {
|
||||
sideboardCards->append(info);
|
||||
}
|
||||
} else {
|
||||
qDebug() << "Card not found in database!";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VisualDeckEditorWidget::sortCardList(const QStringList properties, Qt::SortOrder order = Qt::AscendingOrder)
|
||||
{
|
||||
CardInfoComparator comparator(properties, order);
|
||||
std::sort(mainDeckCards->begin(), mainDeckCards->end(), comparator);
|
||||
std::sort(sideboardCards->begin(), sideboardCards->end(), comparator);
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
#ifndef VISUAL_DECK_EDITOR_H
|
||||
#define VISUAL_DECK_EDITOR_H
|
||||
|
||||
#include "../../../../deck/deck_list_model.h"
|
||||
#include "../../../../game/cards/card_database.h"
|
||||
#include "../../layouts/flow_layout.h"
|
||||
#include "../../layouts/vertical_flow_layout.h"
|
||||
#include "../cards/card_info_picture_with_text_overlay_widget.h"
|
||||
#include "../general/layout_containers/flow_widget.h"
|
||||
#include "../general/layout_containers/overlap_control_widget.h"
|
||||
|
||||
#include <QWidget>
|
||||
#include <qscrollarea.h>
|
||||
|
||||
class VisualDeckEditorWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit VisualDeckEditorWidget(QWidget *parent = nullptr, DeckListModel *deck_list_model = nullptr);
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
void updateDisplay();
|
||||
QWidget *displayCards(QList<QPair<QString, QList<CardInfoPtr>>> cardLists, int bannerOpacity);
|
||||
QList<QPair<QString, QList<CardInfoPtr>>> sortCards(QList<CardInfoPtr> *cardsToSort);
|
||||
|
||||
OverlapWidget *getSortedCards();
|
||||
void populateCards();
|
||||
void sortCardList(QStringList properties, Qt::SortOrder order);
|
||||
void setDeckList(const DeckList &new_deck_list_model);
|
||||
|
||||
signals:
|
||||
void activeCardChanged(CardInfoPtr activeCard);
|
||||
void mainboardCardClicked(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance);
|
||||
void sideboardCardClicked(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance);
|
||||
|
||||
protected slots:
|
||||
void onHover(CardInfoPtr hoveredCard);
|
||||
void onMainboardClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance);
|
||||
void onSideboardClick(QMouseEvent *event, CardInfoPictureWithTextOverlayWidget *instance);
|
||||
void decklistDataChanged(QModelIndex topLeft, QModelIndex bottomRight);
|
||||
void activeSortCriteriaChanged();
|
||||
|
||||
private:
|
||||
DeckListModel *deck_list_model;
|
||||
QList<CardInfoPtr> *mainDeckCards;
|
||||
QList<CardInfoPtr> *sideboardCards;
|
||||
QVBoxLayout *mainLayout;
|
||||
QComboBox *sortByComboBox;
|
||||
QString activeSortCriteria = "maintype";
|
||||
FlowWidget *flowWidget;
|
||||
QScrollArea *scrollArea;
|
||||
QWidget *zoneContainer;
|
||||
QVBoxLayout *zoneContainerLayout;
|
||||
OverlapControlWidget *overlap_control_widget;
|
||||
QWidget *container;
|
||||
};
|
||||
|
||||
#endif // VISUAL_DECK_EDITOR_H
|
||||
|
|
@ -878,6 +878,8 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
connect(&SettingsCache::instance().shortcuts(), &ShortcutsSettings::shortCutChanged, this,
|
||||
&MainWindow::refreshShortcuts);
|
||||
refreshShortcuts();
|
||||
connect(CardDatabaseManager::getInstance(), SIGNAL(cardDatabaseLoadingFinished()), tabSupervisor,
|
||||
SLOT(addVisualDeckEditorTab()));
|
||||
|
||||
connect(CardDatabaseManager::getInstance(), &CardDatabase::cardDatabaseLoadingFailed, this,
|
||||
&MainWindow::cardDatabaseLoadingFailed);
|
||||
|
|
|
|||
75
cockatrice/src/utility/card_info_comparator.cpp
Normal file
75
cockatrice/src/utility/card_info_comparator.cpp
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
#include "card_info_comparator.h"
|
||||
|
||||
CardInfoComparator::CardInfoComparator(const QStringList &properties, Qt::SortOrder order)
|
||||
: m_properties(properties), m_order(order)
|
||||
{
|
||||
}
|
||||
|
||||
bool CardInfoComparator::operator()(const CardInfoPtr &a, const CardInfoPtr &b) const
|
||||
{
|
||||
// Iterate over each property in the list
|
||||
for (const QString &property : m_properties) {
|
||||
QVariant valueA = getProperty(a, property);
|
||||
QVariant valueB = getProperty(b, property);
|
||||
|
||||
// Compare the current property
|
||||
if (valueA != valueB) {
|
||||
// If values differ, perform comparison
|
||||
return compareVariants(valueA, valueB) ? (m_order == Qt::AscendingOrder) : (m_order == Qt::DescendingOrder);
|
||||
}
|
||||
}
|
||||
|
||||
// If all properties are equal, return false (indicating they are considered equal for sorting purposes)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CardInfoComparator::compareVariants(const QVariant &a, const QVariant &b) const
|
||||
{
|
||||
// Determine the type of QVariant based on Qt version
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
if (a.typeId() != b.typeId()) {
|
||||
#else
|
||||
if (a.type() != b.type()) {
|
||||
#endif
|
||||
// If they are not the same type, compare as strings
|
||||
return a.toString() < b.toString();
|
||||
}
|
||||
|
||||
// Perform type-specific comparison
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
switch (a.typeId()) {
|
||||
#else
|
||||
switch (a.type()) {
|
||||
#endif
|
||||
case QMetaType::Int:
|
||||
return a.toInt() < b.toInt();
|
||||
case QMetaType::Double:
|
||||
return a.toDouble() < b.toDouble();
|
||||
case QMetaType::QString:
|
||||
return a.toString() < b.toString();
|
||||
case QMetaType::Bool:
|
||||
return a.toBool() < b.toBool();
|
||||
default:
|
||||
// Default to comparing as strings
|
||||
return a.toString() < b.toString();
|
||||
}
|
||||
}
|
||||
|
||||
QVariant CardInfoComparator::getProperty(const CardInfoPtr &card, const QString &property) const
|
||||
{
|
||||
// Check if the property exists in the main fields of the class
|
||||
if (property == "name") {
|
||||
return card->getName();
|
||||
} else if (property == "text") {
|
||||
return card->getText();
|
||||
} else if (property == "isToken") {
|
||||
return card->getIsToken();
|
||||
}
|
||||
|
||||
// Otherwise, check if it's a custom property in the QVariantHash
|
||||
if (card->hasProperty(property)) {
|
||||
return card->getProperty(property);
|
||||
}
|
||||
|
||||
return QVariant(); // Return an invalid variant if the property does not exist
|
||||
}
|
||||
24
cockatrice/src/utility/card_info_comparator.h
Normal file
24
cockatrice/src/utility/card_info_comparator.h
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#ifndef CARD_INFO_COMPARATOR_H
|
||||
#define CARD_INFO_COMPARATOR_H
|
||||
|
||||
#include "../game/cards/card_database.h"
|
||||
|
||||
#include <QStringList>
|
||||
#include <QVariant>
|
||||
#include <Qt>
|
||||
|
||||
class CardInfoComparator
|
||||
{
|
||||
public:
|
||||
explicit CardInfoComparator(const QStringList &properties, Qt::SortOrder order = Qt::AscendingOrder);
|
||||
bool operator()(const CardInfoPtr &a, const CardInfoPtr &b) const;
|
||||
|
||||
private:
|
||||
QStringList m_properties; // List of properties to sort by
|
||||
Qt::SortOrder m_order;
|
||||
|
||||
QVariant getProperty(const CardInfoPtr &card, const QString &property) const;
|
||||
bool compareVariants(const QVariant &a, const QVariant &b) const;
|
||||
};
|
||||
|
||||
#endif // CARD_INFO_COMPARATOR_H
|
||||
Loading…
Add table
Add a link
Reference in a new issue