From 7e6cad974f4ba85f09741e59e6a48b8bb11c0fbe Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Sat, 8 Nov 2025 23:25:33 +0100 Subject: [PATCH] [Doxygen] abstract_tab_deck_editor (#6286) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Doxygen abstract_tab_deck_editor Took 15 minutes Took 15 minutes Took 4 seconds * Lint. Took 28 minutes --------- Co-authored-by: Lukas Brübach --- .../widgets/tabs/abstract_tab_deck_editor.cpp | 215 ++++++++++++------ .../widgets/tabs/abstract_tab_deck_editor.h | 192 ++++++++++++++-- 2 files changed, 319 insertions(+), 88 deletions(-) diff --git a/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.cpp b/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.cpp index 4236c3858..a5406aa6c 100644 --- a/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.cpp +++ b/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.cpp @@ -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 #include +/** + * @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(); -} \ No newline at end of file +} diff --git a/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.h b/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.h index bdf35b3da..c28f15b52 100644 --- a/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.h +++ b/cockatrice/src/interface/widgets/tabs/abstract_tab_deck_editor.h @@ -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