[Doxygen] abstract_tab_deck_editor (#6286)

* Doxygen abstract_tab_deck_editor

Took 15 minutes

Took 15 minutes


Took 4 seconds

* Lint.

Took 28 minutes

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
This commit is contained in:
BruebachL 2025-11-08 23:25:33 +01:00 committed by GitHub
parent 757e9f3415
commit 7e6cad974f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 319 additions and 88 deletions

View file

@ -1,3 +1,12 @@
/**
* @file abstract_tab_deck_editor.cpp
* @brief Implementation of the AbstractTabDeckEditor class.
*
* Handles deck editor tab UI, deck management, card operations, clipboard
* operations, printing, deck export, remote uploads, and interactions with
* external services (DeckStats, TappedOut, etc.).
*/
#include "abstract_tab_deck_editor.h"
#include "../../../client/settings/cache_settings.h"
@ -40,6 +49,11 @@
#include <libcockatrice/protocol/pending_command.h>
#include <libcockatrice/utility/trice_limits.h>
/**
* @brief Constructs the AbstractTabDeckEditor.
* Initializes all dock widgets and connects signals/slots.
* @param _tabSupervisor The tab supervisor managing this tab.
*/
AbstractTabDeckEditor::AbstractTabDeckEditor(TabSupervisor *_tabSupervisor) : Tab(_tabSupervisor)
{
setDockOptions(QMainWindow::AnimatedDocks | QMainWindow::AllowNestedDocks | QMainWindow::AllowTabbedDocks);
@ -53,10 +67,13 @@ AbstractTabDeckEditor::AbstractTabDeckEditor(TabSupervisor *_tabSupervisor) : Ta
printingSelectorDockWidget->setHidden(SettingsCache::instance().getOverrideAllCardArtWithPersonalPreference());
});
// Connect deck signals to this tab
connect(deckDockWidget, &DeckEditorDeckDockWidget::deckChanged, this, &AbstractTabDeckEditor::onDeckChanged);
connect(deckDockWidget, &DeckEditorDeckDockWidget::deckModified, this, &AbstractTabDeckEditor::onDeckModified);
connect(deckDockWidget, &DeckEditorDeckDockWidget::cardChanged, this, &AbstractTabDeckEditor::updateCard);
connect(this, &AbstractTabDeckEditor::decrementCard, deckDockWidget, &DeckEditorDeckDockWidget::actDecrementCard);
// Connect database display signals to this tab
connect(databaseDisplayDockWidget, &DeckEditorDatabaseDisplayWidget::cardChanged, this,
&AbstractTabDeckEditor::updateCard);
connect(databaseDisplayDockWidget, &DeckEditorDatabaseDisplayWidget::addCardToMainDeck, this,
@ -68,69 +85,97 @@ AbstractTabDeckEditor::AbstractTabDeckEditor(TabSupervisor *_tabSupervisor) : Ta
connect(databaseDisplayDockWidget, &DeckEditorDatabaseDisplayWidget::decrementCardFromSideboard, this,
&AbstractTabDeckEditor::actDecrementCardFromSideboard);
// Connect filter signals
connect(filterDockWidget, &DeckEditorFilterDockWidget::clearAllDatabaseFilters, databaseDisplayDockWidget,
&DeckEditorDatabaseDisplayWidget::clearAllDatabaseFilters);
// Connect shortcut changes
connect(&SettingsCache::instance().shortcuts(), &ShortcutsSettings::shortCutChanged, this,
&AbstractTabDeckEditor::refreshShortcuts);
}
/**
* @brief Updates the card info dock and printing selector.
* @param card The card to display.
*/
void AbstractTabDeckEditor::updateCard(const ExactCard &card)
{
cardInfoDockWidget->updateCard(card);
printingSelectorDockWidget->printingSelector->setCard(card.getCardPtr(), DECK_ZONE_MAIN);
}
/** @brief Placeholder: called when the deck changes. */
void AbstractTabDeckEditor::onDeckChanged()
{
}
/**
* @brief Marks the tab as modified and updates the save menu status.
*/
void AbstractTabDeckEditor::onDeckModified()
{
setModified(!isBlankNewDeck());
deckMenu->setSaveStatus(!isBlankNewDeck());
}
/**
* @brief Helper for adding a card to a deck zone.
* @param card Card to add.
* @param zoneName Zone to add the card to.
*/
void AbstractTabDeckEditor::addCardHelper(const ExactCard &card, QString zoneName)
{
if (!card)
return;
if (card.getInfo().getIsToken())
zoneName = DECK_ZONE_TOKENS;
QModelIndex newCardIndex = deckDockWidget->deckModel->addCard(card, zoneName);
// recursiveExpand(newCardIndex);
deckDockWidget->deckView->clearSelection();
deckDockWidget->deckView->setCurrentIndex(newCardIndex);
setModified(true);
databaseDisplayDockWidget->searchEdit->setSelection(0, databaseDisplayDockWidget->searchEdit->text().length());
}
/**
* @brief Adds a card to the main deck or sideboard depending on Ctrl key.
*/
void AbstractTabDeckEditor::actAddCard(const ExactCard &card)
{
if (QApplication::keyboardModifiers() & Qt::ControlModifier)
actAddCardToSideboard(card);
else
addCardHelper(card, DECK_ZONE_MAIN);
deckMenu->setSaveStatus(true);
}
/** @brief Adds a card to the sideboard explicitly. */
void AbstractTabDeckEditor::actAddCardToSideboard(const ExactCard &card)
{
addCardHelper(card, DECK_ZONE_SIDE);
deckMenu->setSaveStatus(true);
}
/** @brief Decrements a card from the main deck. */
void AbstractTabDeckEditor::actDecrementCard(const ExactCard &card)
{
emit decrementCard(card, DECK_ZONE_MAIN);
}
/** @brief Decrements a card from the sideboard. */
void AbstractTabDeckEditor::actDecrementCardFromSideboard(const ExactCard &card)
{
emit decrementCard(card, DECK_ZONE_SIDE);
}
/**
* @brief Swaps a card in a deck zone.
* @param card Card to swap.
* @param zoneName Zone to swap in.
*/
void AbstractTabDeckEditor::actSwapCard(const ExactCard &card, const QString &zoneName)
{
QString providerId = card.getPrinting().getUuid();
@ -145,8 +190,8 @@ void AbstractTabDeckEditor::actSwapCard(const ExactCard &card, const QString &zo
}
/**
* Opens the deck in this tab.
* @param deck The deck. Takes ownership of the object
* @brief Opens a deck in this tab.
* @param deck DeckLoader object (takes ownership).
*/
void AbstractTabDeckEditor::openDeck(DeckLoader *deck)
{
@ -158,8 +203,8 @@ void AbstractTabDeckEditor::openDeck(DeckLoader *deck)
}
/**
* Sets the currently active deck for this tab
* @param _deck The deck. Takes ownership of the object
* @brief Sets the currently active deck.
* @param _deck DeckLoader object.
*/
void AbstractTabDeckEditor::setDeck(DeckLoader *_deck)
{
@ -167,16 +212,20 @@ void AbstractTabDeckEditor::setDeck(DeckLoader *_deck)
CardPictureLoader::cacheCardPixmaps(CardDatabaseManager::query()->getCards(getDeckList()->getCardRefList()));
setModified(false);
// If they load a deck, make the deck list appear
aDeckDockVisible->setChecked(true);
deckDockWidget->setVisible(aDeckDockVisible->isChecked());
}
/** @brief Returns the currently loaded deck. */
DeckLoader *AbstractTabDeckEditor::getDeckList() const
{
return deckDockWidget->getDeckList();
}
/**
* @brief Sets the modified state of the tab.
* @param _modified True if tab is modified, false otherwise.
*/
void AbstractTabDeckEditor::setModified(bool _modified)
{
modified = _modified;
@ -184,7 +233,7 @@ void AbstractTabDeckEditor::setModified(bool _modified)
}
/**
* @brief Returns true if this tab is a blank newly opened tab, as if it was just created with the `New Deck` action.
* @brief Returns true if the tab is a blank newly created deck.
*/
bool AbstractTabDeckEditor::isBlankNewDeck() const
{
@ -192,13 +241,12 @@ bool AbstractTabDeckEditor::isBlankNewDeck() const
return !modified && deck->isBlankDeck() && deck->hasNotBeenLoaded();
}
/** @brief Creates a new deck. Handles opening in new tab if needed. */
void AbstractTabDeckEditor::actNewDeck()
{
auto deckOpenLocation = confirmOpen(false);
if (deckOpenLocation == CANCELLED) {
if (deckOpenLocation == CANCELLED)
return;
}
if (deckOpenLocation == NEW_TAB) {
emit openDeckEditor(nullptr);
@ -208,6 +256,7 @@ void AbstractTabDeckEditor::actNewDeck()
cleanDeckAndResetModified();
}
/** @brief Clears the current deck and resets modified flag. */
void AbstractTabDeckEditor::cleanDeckAndResetModified()
{
deckMenu->setSaveStatus(false);
@ -216,43 +265,29 @@ void AbstractTabDeckEditor::cleanDeckAndResetModified()
}
/**
* @brief Displays the save confirmation dialogue that is shown before loading a deck, if required. Takes into
* account the `openDeckInNewTab` settting.
*
* @param openInSameTabIfBlank Open the deck in the same tab instead of a new tab if the current tab is completely
* blank. Only relevant when the `openDeckInNewTab` setting is enabled.
*
* @returns An enum that indicates if and where to load the deck
* @brief Displays the save confirmation dialog before loading a deck.
* @param openInSameTabIfBlank Open in same tab if current tab is blank.
* @return DeckOpenLocation enum indicating where to open the deck.
*/
AbstractTabDeckEditor::DeckOpenLocation AbstractTabDeckEditor::confirmOpen(const bool openInSameTabIfBlank)
{
// handle `openDeckInNewTab` setting
if (SettingsCache::instance().getOpenDeckInNewTab()) {
if (openInSameTabIfBlank && isBlankNewDeck()) {
if (openInSameTabIfBlank && isBlankNewDeck())
return SAME_TAB;
} else {
else
return NEW_TAB;
}
}
// early return if deck is unmodified
if (!modified) {
if (!modified)
return SAME_TAB;
}
// do the save confirmation dialogue
tabSupervisor->setCurrentWidget(this);
QMessageBox *msgBox = createSaveConfirmationWindow();
QPushButton *newTabButton = msgBox->addButton(tr("Open in new tab"), QMessageBox::ApplyRole);
int ret = msgBox->exec();
// `exec()` returns an opaque value if a non-standard button was clicked.
// Directly check if newTabButton was clicked before switching over the standard buttons.
if (msgBox->clickedButton() == newTabButton) {
if (msgBox->clickedButton() == newTabButton)
return NEW_TAB;
}
switch (ret) {
case QMessageBox::Save:
@ -265,9 +300,8 @@ AbstractTabDeckEditor::DeckOpenLocation AbstractTabDeckEditor::confirmOpen(const
}
/**
* @brief Creates the base save confirmation dialogue box.
*
* @returns A QMessageBox that can be further modified
* @brief Creates the base save confirmation dialog.
* @return Pointer to a QMessageBox.
*/
QMessageBox *AbstractTabDeckEditor::createSaveConfirmationWindow()
{
@ -279,13 +313,15 @@ QMessageBox *AbstractTabDeckEditor::createSaveConfirmationWindow()
return msgBox;
}
/**
* @brief Loads a deck from file using a dialog.
* Displays a save confirmation if needed.
*/
void AbstractTabDeckEditor::actLoadDeck()
{
auto deckOpenLocation = confirmOpen();
if (deckOpenLocation == CANCELLED) {
if (deckOpenLocation == CANCELLED)
return;
}
DlgLoadDeck dialog(this);
if (!dialog.exec())
@ -296,21 +332,23 @@ void AbstractTabDeckEditor::actLoadDeck()
deckDockWidget->updateBannerCardComboBox();
}
/**
* @brief Opens a recently used deck file.
* @param fileName Path to the deck file.
*/
void AbstractTabDeckEditor::actOpenRecent(const QString &fileName)
{
auto deckOpenLocation = confirmOpen();
if (deckOpenLocation == CANCELLED) {
if (deckOpenLocation == CANCELLED)
return;
}
openDeckFromFile(fileName, deckOpenLocation);
}
/**
* Actually opens the deck from file
* @param fileName The path of the deck to open
* @param deckOpenLocation Which tab to open the deck
* @brief Actually opens a deck from file.
* @param fileName Path to the deck file.
* @param deckOpenLocation Where to open the deck (same or new tab).
*/
void AbstractTabDeckEditor::openDeckFromFile(const QString &fileName, DeckOpenLocation deckOpenLocation)
{
@ -332,6 +370,11 @@ void AbstractTabDeckEditor::openDeckFromFile(const QString &fileName, DeckOpenLo
deckMenu->setSaveStatus(true);
}
/**
* @brief Saves the current deck.
* If remote deck, sends upload command.
* @return True if save succeeded, false otherwise.
*/
bool AbstractTabDeckEditor::actSaveDeck()
{
DeckLoader *const deck = getDeckList();
@ -357,12 +400,17 @@ bool AbstractTabDeckEditor::actSaveDeck()
setModified(false);
return true;
}
QMessageBox::critical(
this, tr("Error"),
tr("The deck could not be saved.\nPlease check that the directory is writable and try again."));
return false;
}
/**
* @brief Saves the deck to a user-selected file.
* @return True if save succeeded.
*/
bool AbstractTabDeckEditor::actSaveDeckAs()
{
QFileDialog dialog(this, tr("Save deck"));
@ -384,13 +432,16 @@ bool AbstractTabDeckEditor::actSaveDeckAs()
tr("The deck could not be saved.\nPlease check that the directory is writable and try again."));
return false;
}
setModified(false);
SettingsCache::instance().recents().updateRecentlyOpenedDeckPaths(fileName);
return true;
}
/**
* @brief Callback for remote deck save completion.
* @param response Server response.
*/
void AbstractTabDeckEditor::saveDeckRemoteFinished(const Response &response)
{
if (response.response_code() != Response::RespOk)
@ -399,13 +450,15 @@ void AbstractTabDeckEditor::saveDeckRemoteFinished(const Response &response)
setModified(false);
}
/**
* @brief Loads a deck from clipboard.
* Displays confirmation if the tab is modified.
*/
void AbstractTabDeckEditor::actLoadDeckFromClipboard()
{
auto deckOpenLocation = confirmOpen();
if (deckOpenLocation == CANCELLED) {
if (deckOpenLocation == CANCELLED)
return;
}
DlgLoadDeckFromClipboard dlg(this);
if (!dlg.exec())
@ -421,6 +474,10 @@ void AbstractTabDeckEditor::actLoadDeckFromClipboard()
deckMenu->setSaveStatus(true);
}
/**
* @brief Opens the deck editor to edit clipboard contents.
* @param annotated If true, edits with annotations.
*/
void AbstractTabDeckEditor::editDeckInClipboard(bool annotated)
{
DlgEditDeckInClipboard dlg(*getDeckList(), annotated, this);
@ -429,40 +486,46 @@ void AbstractTabDeckEditor::editDeckInClipboard(bool annotated)
setDeck(dlg.getDeckList());
setModified(true);
deckMenu->setSaveStatus(true);
}
/** @brief Slot for editing deck in clipboard with annotations. */
void AbstractTabDeckEditor::actEditDeckInClipboard()
{
editDeckInClipboard(true);
}
/** @brief Slot for editing deck in clipboard without annotations. */
void AbstractTabDeckEditor::actEditDeckInClipboardRaw()
{
editDeckInClipboard(false);
}
/** @brief Saves deck to clipboard with set info and annotation. */
void AbstractTabDeckEditor::actSaveDeckToClipboard()
{
getDeckList()->saveToClipboard(true, true);
}
/** @brief Saves deck to clipboard with annotation, without set info. */
void AbstractTabDeckEditor::actSaveDeckToClipboardNoSetInfo()
{
getDeckList()->saveToClipboard(true, false);
}
/** @brief Saves deck to clipboard without annotations, with set info. */
void AbstractTabDeckEditor::actSaveDeckToClipboardRaw()
{
getDeckList()->saveToClipboard(false, true);
}
/** @brief Saves deck to clipboard without annotations or set info. */
void AbstractTabDeckEditor::actSaveDeckToClipboardRawNoSetInfo()
{
getDeckList()->saveToClipboard(false, false);
}
/** @brief Prints the deck using a QPrintPreviewDialog. */
void AbstractTabDeckEditor::actPrintDeck()
{
auto *dlg = new QPrintPreviewDialog(this);
@ -470,13 +533,14 @@ void AbstractTabDeckEditor::actPrintDeck()
dlg->exec();
}
/**
* @brief Loads a deck from a website.
*/
void AbstractTabDeckEditor::actLoadDeckFromWebsite()
{
auto deckOpenLocation = confirmOpen();
if (deckOpenLocation == CANCELLED) {
if (deckOpenLocation == CANCELLED)
return;
}
DlgLoadDeckFromWebsite dlg(this);
if (!dlg.exec())
@ -492,18 +556,21 @@ void AbstractTabDeckEditor::actLoadDeckFromWebsite()
deckMenu->setSaveStatus(true);
}
/**
* @brief Exports the deck to a decklist website.
* @param website Website to export to.
*/
void AbstractTabDeckEditor::exportToDecklistWebsite(DeckLoader::DecklistWebsite website)
{
// check if deck is not null
if (DeckLoader *const deck = getDeckList()) {
// Get the decklist url string from the deck loader class.
QString decklistUrlString = deck->exportDeckToDecklist(website);
// Check to make sure the string isn't empty.
if (QString::compare(decklistUrlString, "", Qt::CaseInsensitive) == 0) {
if (decklistUrlString.isEmpty()) {
// Show an error if the deck is empty, and return.
QMessageBox::critical(this, tr("Error"), tr("There are no cards in your deck to be exported"));
return;
}
// Encode the string recieved from the model to make sure all characters are encoded.
// first we put it into a qurl object
QUrl decklistUrl = QUrl(decklistUrlString);
@ -517,48 +584,54 @@ void AbstractTabDeckEditor::exportToDecklistWebsite(DeckLoader::DecklistWebsite
}
}
/**
* Exports the deck to www.decklist.org (the old website)
*/
/** @brief Exports deck to www.decklist.org. */
void AbstractTabDeckEditor::actExportDeckDecklist()
{
exportToDecklistWebsite(DeckLoader::DecklistOrg);
}
/**
* Exports the deck to www.decklist.xyz (the new website)
*/
/** @brief Exports deck to www.decklist.xyz. */
void AbstractTabDeckEditor::actExportDeckDecklistXyz()
{
exportToDecklistWebsite(DeckLoader::DecklistXyz);
}
/** @brief Analyzes the deck using DeckStats. */
void AbstractTabDeckEditor::actAnalyzeDeckDeckstats()
{
auto *interface = new DeckStatsInterface(*databaseDisplayDockWidget->databaseModel->getDatabase(),
this); // it deletes itself when done
auto *interface = new DeckStatsInterface(*databaseDisplayDockWidget->databaseModel->getDatabase(), this);
interface->analyzeDeck(getDeckList());
}
/** @brief Analyzes the deck using TappedOut. */
void AbstractTabDeckEditor::actAnalyzeDeckTappedout()
{
auto *interface = new TappedOutInterface(*databaseDisplayDockWidget->databaseModel->getDatabase(),
this); // it deletes itself when done
auto *interface = new TappedOutInterface(*databaseDisplayDockWidget->databaseModel->getDatabase(), this);
interface->analyzeDeck(getDeckList());
}
/** @brief Applies a new filter tree to the database display. */
void AbstractTabDeckEditor::filterTreeChanged(FilterTree *filterTree)
{
databaseDisplayDockWidget->setFilterTree(filterTree);
}
/**
* @brief Handles the close event of the tab.
* @param event Close event.
*/
void AbstractTabDeckEditor::closeEvent(QCloseEvent *event)
{
emit deckEditorClosing(this);
event->accept();
}
// Method uses to sync docks state with menu items state
/**
* @brief Event filter for dock visibility and geometry changes.
* @param o Object sending the event.
* @param e Event.
* @return False always.
*/
bool AbstractTabDeckEditor::eventFilter(QObject *o, QEvent *e)
{
if (e->type() == QEvent::Close) {
@ -576,6 +649,7 @@ bool AbstractTabDeckEditor::eventFilter(QObject *o, QEvent *e)
aPrintingSelectorDockFloating->setEnabled(false);
}
}
if (o == this && e->type() == QEvent::Hide) {
LayoutsSettings &layouts = SettingsCache::instance().layouts();
layouts.setDeckEditorLayoutState(saveState());
@ -585,9 +659,11 @@ bool AbstractTabDeckEditor::eventFilter(QObject *o, QEvent *e)
layouts.setDeckEditorDeckSize(deckDockWidget->size());
layouts.setDeckEditorPrintingSelectorSize(printingSelectorDockWidget->size());
}
return false;
}
/** @brief Shows a confirmation dialog before closing. */
bool AbstractTabDeckEditor::confirmClose()
{
if (modified) {
@ -601,11 +677,10 @@ bool AbstractTabDeckEditor::confirmClose()
return true;
}
/** @brief Handles close requests from outside (tab manager). */
bool AbstractTabDeckEditor::closeRequest()
{
if (!confirmClose()) {
if (!confirmClose())
return false;
}
return close();
}
}

View file

@ -1,3 +1,10 @@
/**
* @file abstract_tab_deck_editor.h
* @brief Defines the AbstractTabDeckEditor class, which provides a base for
* deck editor tabs in the application.
*
*/
#ifndef TAB_GENERIC_DECK_EDITOR_H
#define TAB_GENERIC_DECK_EDITOR_H
@ -40,6 +47,45 @@ class QDockWidget;
class QMenu;
class QAction;
/**
* @class AbstractTabDeckEditor
* @ingroup DeckEditorTabs
* @brief AbstractTabDeckEditor is the base class for all deck editor tabs.
*
* **Description:**
* AbstractTabDeckEditor is the base class for all deck editor tabs. It provides core functionality such as deck model
* management, card addition/removal, and integration with dock widgets and tab supervisors.
*
* **Purpose:**
*
* - Acts as the foundation for deck editor tabs (TabDeckEditor and TabDeckEditorVisual).
* - Provides basic deck operations like adding, removing, swapping, and decrementing cards.
* - Integrates with DeckListModel and CardDatabaseModel to access deck and card data.
* - Handles saving, loading, and layout persistence at the tab level.
*
* **Dock Widgets (typically managed in derived classes):**
*
* - DeckEditorCardInfoDockWidget Displays detailed card info.
* - DeckEditorDeckDockWidget Displays mainboard/sideboard cards and zones.
* - DeckEditorFilterDockWidget Provides filtering options for card searches.
* - DeckEditorPrintingSelectorDockWidget Selector for different card printings.
* - DeckEditorDatabaseDisplayWidget Shows card database for adding cards to deck.
*
* **Key Methods:**
*
* - actAddCard(const ExactCard &card) Adds a card to the deck.
* - actDecrementCard(const ExactCard &card) Removes a single instance of a card from the deck.
* - actSwapCard(const ExactCard &card, const QString &zone) Swaps a card between zones.
* - actRemoveCard() Removes the currently selected card from the deck.
* - actSaveDeckAs() Performs a "Save As" action for the deck.
* - updateCard(const ExactCard &card) Updates the currently displayed card info in the dock.
* - onDeckModified() Called when the deck model is changed.
*
* Provides UI docks for the deck, database, card info, printing selector,
* and filters. Supports loading, saving, editing, exporting decks, and
* interactions with external services such as DeckStats, TappedOut, and
* remote deck uploads.
*/
class AbstractTabDeckEditor : public Tab
{
Q_OBJECT
@ -47,68 +93,150 @@ class AbstractTabDeckEditor : public Tab
friend class DeckEditorMenu;
public:
/**
* @brief Constructs an AbstractTabDeckEditor.
* @param _tabSupervisor Pointer to the TabSupervisor managing this tab.
*/
explicit AbstractTabDeckEditor(TabSupervisor *_tabSupervisor);
// UI and Navigation
/** @brief Creates the menus for this tab. Pure virtual. */
virtual void createMenus() = 0;
/** @brief Returns the display text for the tab. */
[[nodiscard]] virtual QString getTabText() const override = 0;
/** @brief Confirms whether the tab can be safely closed. */
bool confirmClose();
/** @brief Retranslates the UI text. Pure virtual. */
virtual void retranslateUi() override = 0;
// Deck Management
/** @brief Opens a deck in this tab.
* @param deck Pointer to a DeckLoader object.
*/
void openDeck(DeckLoader *deck);
/** @brief Returns the currently active deck. */
DeckLoader *getDeckList() const;
/** @brief Sets the modified state of the tab.
* @param _windowModified Whether the tab is modified.
*/
void setModified(bool _windowModified);
// UI Elements
DeckEditorMenu *deckMenu;
DeckEditorDatabaseDisplayWidget *databaseDisplayDockWidget;
DeckEditorCardInfoDockWidget *cardInfoDockWidget;
DeckEditorDeckDockWidget *deckDockWidget;
DeckEditorFilterDockWidget *filterDockWidget;
DeckEditorPrintingSelectorDockWidget *printingSelectorDockWidget;
DeckEditorMenu *deckMenu; ///< Menu for deck operations
DeckEditorDatabaseDisplayWidget *databaseDisplayDockWidget; ///< Database dock
DeckEditorCardInfoDockWidget *cardInfoDockWidget; ///< Card info dock
DeckEditorDeckDockWidget *deckDockWidget; ///< Deck dock
DeckEditorFilterDockWidget *filterDockWidget; ///< Filter dock
DeckEditorPrintingSelectorDockWidget *printingSelectorDockWidget; ///< Printing selector dock
public slots:
/** @brief Called when the deck changes. */
virtual void onDeckChanged();
/** @brief Called when the deck is modified. */
virtual void onDeckModified();
/** @brief Updates the card info panel.
* @param card The card to display.
*/
void updateCard(const ExactCard &card);
/** @brief Adds a card to the main deck or sideboard based on Ctrl key. */
void actAddCard(const ExactCard &card);
/** @brief Adds a card to the sideboard explicitly. */
void actAddCardToSideboard(const ExactCard &card);
/** @brief Decrements a card from the main deck. */
void actDecrementCard(const ExactCard &card);
/** @brief Decrements a card from the sideboard. */
void actDecrementCardFromSideboard(const ExactCard &card);
/** @brief Opens a recently opened deck file. */
void actOpenRecent(const QString &fileName);
/** @brief Called when the filter tree changes. */
void filterTreeChanged(FilterTree *filterTree);
/** @brief Requests closing the tab. */
bool closeRequest() override;
/** @brief Shows the printing selector dock. Pure virtual. */
virtual void showPrintingSelector() = 0;
/** @brief Slot for when a dock's top-level state changes. Pure virtual. */
virtual void dockTopLevelChanged(bool topLevel) = 0;
signals:
/** @brief Emitted when a deck should be opened in a new editor tab. */
void openDeckEditor(const DeckLoader *deckLoader);
/** @brief Emitted before the tab is closed. */
void deckEditorClosing(AbstractTabDeckEditor *tab);
/** @brief Emitted when a card should be decremented. */
void decrementCard(const ExactCard &card, QString zoneName);
protected slots:
// Deck Operations
/** @brief Starts a new deck in this tab. */
virtual void actNewDeck();
/** @brief Cleans the current deck and resets the modified state. */
void cleanDeckAndResetModified();
/** @brief Loads a deck from file. */
virtual void actLoadDeck();
/** @brief Saves the current deck. */
bool actSaveDeck();
/** @brief Saves the current deck under a new name. */
virtual bool actSaveDeckAs();
/** @brief Loads a deck from the clipboard. */
virtual void actLoadDeckFromClipboard();
/** @brief Opens a deck editor for clipboard contents. */
void actEditDeckInClipboard();
/** @brief Opens a raw clipboard deck editor. */
void actEditDeckInClipboardRaw();
/** @brief Saves deck to clipboard with full info. */
void actSaveDeckToClipboard();
/** @brief Saves deck to clipboard without set info. */
void actSaveDeckToClipboardNoSetInfo();
/** @brief Saves deck to clipboard in raw format. */
void actSaveDeckToClipboardRaw();
/** @brief Saves deck to clipboard in raw format without set info. */
void actSaveDeckToClipboardRawNoSetInfo();
/** @brief Prints the deck using a preview dialog. */
void actPrintDeck();
/** @brief Loads a deck from an online website. */
void actLoadDeckFromWebsite();
/** @brief Exports the deck to decklist.org. */
void actExportDeckDecklist();
/** @brief Exports the deck to decklist.xyz. */
void actExportDeckDecklistXyz();
/** @brief Analyzes the deck using deckstats.net. */
void actAnalyzeDeckDeckstats();
/** @brief Analyzes the deck using tappedout.net. */
void actAnalyzeDeckTappedout();
// Remote Save
/** @brief Callback when a remote deck save finishes. */
void saveDeckRemoteFinished(const Response &r);
// UI Layout Management
@ -117,34 +245,62 @@ protected slots:
virtual void freeDocksSize() = 0;
virtual void refreshShortcuts() = 0;
/** @brief Handles dock close events. */
void closeEvent(QCloseEvent *event) override;
/** @brief Event filter for dock state changes. */
bool eventFilter(QObject *o, QEvent *e) override;
/** @brief Slot triggered when a dock visibility changes. Pure virtual. */
virtual void dockVisibleTriggered() = 0;
/** @brief Slot triggered when a dock floating state changes. Pure virtual. */
virtual void dockFloatingTriggered() = 0;
private:
/** @brief Sets the deck for this tab.
* @param _deck The deck object.
*/
virtual void setDeck(DeckLoader *_deck);
/** @brief Helper for editing decks from the clipboard. */
void editDeckInClipboard(bool annotated);
/** @brief Helper for exporting decks to websites.
* @param website Target website.
*/
void exportToDecklistWebsite(DeckLoader::DecklistWebsite website);
protected:
/**
* @brief Enum for selecting deck open location
*/
/** @brief Enum describing deck open locations */
enum DeckOpenLocation
{
CANCELLED,
SAME_TAB,
NEW_TAB
CANCELLED, ///< Operation cancelled
SAME_TAB, ///< Open deck in the same tab
NEW_TAB ///< Open deck in a new tab
};
/** @brief Confirms deck open action based on settings and modified state.
* @param openInSameTabIfBlank Whether to reuse same tab if blank.
* @return Selected DeckOpenLocation.
*/
DeckOpenLocation confirmOpen(bool openInSameTabIfBlank = true);
/** @brief Creates a save confirmation message box.
* @return Pointer to a QMessageBox.
*/
QMessageBox *createSaveConfirmationWindow();
/** @brief Returns true if the tab is a blank newly created deck. */
bool isBlankNewDeck() const;
// Helper functions for card actions
/** @brief Helper function to add a card to a specific deck zone. */
void addCardHelper(const ExactCard &card, QString zoneName);
/** @brief Swaps a card in the deck view. */
void actSwapCard(const ExactCard &card, const QString &zoneName);
/** @brief Opens a deck from a file. */
virtual void openDeckFromFile(const QString &fileName, DeckOpenLocation deckOpenLocation);
// UI Menu Elements
@ -154,7 +310,7 @@ protected:
QAction *aCardInfoDockVisible, *aCardInfoDockFloating, *aDeckDockVisible, *aDeckDockFloating;
QAction *aFilterDockVisible, *aFilterDockFloating, *aPrintingSelectorDockVisible, *aPrintingSelectorDockFloating;
bool modified = false;
bool modified = false; ///< Whether the deck/tab has unsaved changes
};
#endif // TAB_GENERIC_DECK_EDITOR_H