From 4ca1fc083d7bf9bc8d83432c7c16f25815654eb4 Mon Sep 17 00:00:00 2001 From: RickyRister <42636155+RickyRister@users.noreply.github.com> Date: Tue, 24 Dec 2024 16:55:04 -0800 Subject: [PATCH] add "open recent" menu option to deck editor tab (#5319) * add "open recent" menu option to deck editor tab * change texts * also get it to work with loading from deck storage tab * add error message when fail to open * only update recents on successful open * only update recents on successful open * reword to "Clear" --- cockatrice/CMakeLists.txt | 1 + .../src/client/tabs/tab_deck_editor.cpp | 57 ++++++++++++++++++- cockatrice/src/client/tabs/tab_deck_editor.h | 12 ++-- .../src/client/tabs/tab_deck_storage.cpp | 2 + cockatrice/src/settings/cache_settings.cpp | 1 + cockatrice/src/settings/cache_settings.h | 6 ++ cockatrice/src/settings/recents_settings.cpp | 32 +++++++++++ cockatrice/src/settings/recents_settings.h | 23 ++++++++ oracle/CMakeLists.txt | 1 + 9 files changed, 130 insertions(+), 5 deletions(-) create mode 100644 cockatrice/src/settings/recents_settings.cpp create mode 100644 cockatrice/src/settings/recents_settings.h diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index db81b3d0a..53ff29d26 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -122,6 +122,7 @@ set(cockatrice_SOURCES src/settings/game_filters_settings.cpp src/settings/layouts_settings.cpp src/settings/message_settings.cpp + src/settings/recents_settings.cpp src/settings/servers_settings.cpp src/settings/settings_manager.cpp src/settings/cache_settings.cpp diff --git a/cockatrice/src/client/tabs/tab_deck_editor.cpp b/cockatrice/src/client/tabs/tab_deck_editor.cpp index b9caf04d9..404bdb31f 100644 --- a/cockatrice/src/client/tabs/tab_deck_editor.cpp +++ b/cockatrice/src/client/tabs/tab_deck_editor.cpp @@ -292,6 +292,15 @@ void TabDeckEditor::createMenus() aLoadDeck = new QAction(QString(), this); connect(aLoadDeck, SIGNAL(triggered()), this, SLOT(actLoadDeck())); + loadRecentDeckMenu = new QMenu(this); + connect(&SettingsCache::instance().recents(), &RecentsSettings::recentlyOpenedDeckPathsChanged, this, + &TabDeckEditor::updateRecentlyOpened); + + aClearRecents = new QAction(QString(), this); + connect(aClearRecents, &QAction::triggered, this, &TabDeckEditor::actClearRecents); + + updateRecentlyOpened(); + aSaveDeck = new QAction(QString(), this); connect(aSaveDeck, SIGNAL(triggered()), this, SLOT(actSaveDeck())); @@ -342,6 +351,7 @@ void TabDeckEditor::createMenus() deckMenu = new QMenu(this); deckMenu->addAction(aNewDeck); deckMenu->addAction(aLoadDeck); + deckMenu->addMenu(loadRecentDeckMenu); deckMenu->addAction(aSaveDeck); deckMenu->addAction(aSaveDeckAs); deckMenu->addSeparator(); @@ -705,6 +715,8 @@ void TabDeckEditor::retranslateUi() aNewDeck->setText(tr("&New deck")); aLoadDeck->setText(tr("&Load deck...")); + loadRecentDeckMenu->setTitle(tr("Load recent deck...")); + aClearRecents->setText(tr("Clear")); aSaveDeck->setText(tr("&Save deck")); aSaveDeckAs->setText(tr("Save deck &as...")); aLoadDeckFromClipboard->setText(tr("Load deck from cl&ipboard...")); @@ -852,6 +864,20 @@ void TabDeckEditor::updateHash() hashLabel->setText(deckModel->getDeckList()->getDeckHash()); } +void TabDeckEditor::updateRecentlyOpened() +{ + loadRecentDeckMenu->clear(); + for (const auto &deckPath : SettingsCache::instance().recents().getRecentlyOpenedDeckPaths()) { + QAction *aRecentlyOpenedDeck = new QAction(deckPath, this); + loadRecentDeckMenu->addAction(aRecentlyOpenedDeck); + connect(aRecentlyOpenedDeck, &QAction::triggered, this, + [=, this] { actOpenRecent(aRecentlyOpenedDeck->text()); }); + } + loadRecentDeckMenu->addSeparator(); + loadRecentDeckMenu->addAction(aClearRecents); + aClearRecents->setEnabled(SettingsCache::instance().recents().getRecentlyOpenedDeckPaths().length() > 0); +} + bool TabDeckEditor::confirmClose() { if (modified) { @@ -907,21 +933,50 @@ void TabDeckEditor::actLoadDeck() return; QString fileName = dialog.selectedFiles().at(0); + openDeckFromFile(fileName, deckOpenLocation); +} + +void TabDeckEditor::actOpenRecent(const QString &fileName) +{ + auto deckOpenLocation = confirmOpen(); + + 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 + */ +void TabDeckEditor::openDeckFromFile(const QString &fileName, DeckOpenLocation deckOpenLocation) +{ DeckLoader::FileFormat fmt = DeckLoader::getFormatFromName(fileName); auto *l = new DeckLoader; if (l->loadFromFile(fileName, fmt)) { + SettingsCache::instance().recents().updateRecentlyOpenedDeckPaths(fileName); if (deckOpenLocation == NEW_TAB) { emit openDeckEditor(l); } else { setSaveStatus(false); setDeck(l); } - } else + } else { delete l; + QMessageBox::critical(this, tr("Error"), tr("Could not open deck at %1").arg(fileName)); + } setSaveStatus(true); } +void TabDeckEditor::actClearRecents() +{ + SettingsCache::instance().recents().clearRecentlyOpenedDeckPaths(); +} + void TabDeckEditor::saveDeckRemoteFinished(const Response &response) { if (response.response_code() != Response::RespOk) diff --git a/cockatrice/src/client/tabs/tab_deck_editor.h b/cockatrice/src/client/tabs/tab_deck_editor.h index 9b515a242..1501e5c4b 100644 --- a/cockatrice/src/client/tabs/tab_deck_editor.h +++ b/cockatrice/src/client/tabs/tab_deck_editor.h @@ -43,9 +43,12 @@ private slots: void updateSearch(const QString &search); void databaseCustomMenu(QPoint point); void decklistCustomMenu(QPoint point); + void updateRecentlyOpened(); void actNewDeck(); void actLoadDeck(); + void actOpenRecent(const QString &fileName); + void actClearRecents(); bool actSaveDeck(); bool actSaveDeckAs(); void actLoadDeckFromClipboard(); @@ -106,6 +109,7 @@ private: void offsetCountAtIndex(const QModelIndex &idx, int offset); void decrementCardHelper(QString zoneName); void recursiveExpand(const QModelIndex &index); + void openDeckFromFile(const QString &fileName, DeckOpenLocation deckOpenLocation); CardDatabaseModel *databaseModel; CardDatabaseDisplayModel *databaseDisplayModel; @@ -131,10 +135,10 @@ private: QWidget *filterBox; QMenu *deckMenu, *viewMenu, *cardInfoDockMenu, *deckDockMenu, *filterDockMenu, *printingSelectorDockMenu, - *analyzeDeckMenu, *saveDeckToClipboardMenu; - QAction *aNewDeck, *aLoadDeck, *aSaveDeck, *aSaveDeckAs, *aLoadDeckFromClipboard, *aSaveDeckToClipboard, - *aSaveDeckToClipboardRaw, *aPrintDeck, *aExportDeckDecklist, *aAnalyzeDeckDeckstats, *aAnalyzeDeckTappedout, - *aClose; + *analyzeDeckMenu, *saveDeckToClipboardMenu, *loadRecentDeckMenu; + QAction *aNewDeck, *aLoadDeck, *aClearRecents, *aSaveDeck, *aSaveDeckAs, *aLoadDeckFromClipboard, + *aSaveDeckToClipboard, *aSaveDeckToClipboardRaw, *aPrintDeck, *aExportDeckDecklist, *aAnalyzeDeckDeckstats, + *aAnalyzeDeckTappedout, *aClose; QAction *aClearFilterAll, *aClearFilterOne; QAction *aAddCard, *aAddCardToSideboard, *aRemoveCard, *aIncrement, *aDecrement; QAction *aResetLayout; diff --git a/cockatrice/src/client/tabs/tab_deck_storage.cpp b/cockatrice/src/client/tabs/tab_deck_storage.cpp index eca1b7b1f..7b2253b5f 100644 --- a/cockatrice/src/client/tabs/tab_deck_storage.cpp +++ b/cockatrice/src/client/tabs/tab_deck_storage.cpp @@ -166,6 +166,8 @@ void TabDeckStorage::actOpenLocalDeck() if (!deckLoader.loadFromFile(filePath, DeckLoader::CockatriceFormat)) return; + SettingsCache::instance().recents().updateRecentlyOpenedDeckPaths(filePath); + emit openDeckEditor(&deckLoader); } } diff --git a/cockatrice/src/settings/cache_settings.cpp b/cockatrice/src/settings/cache_settings.cpp index 683b2d721..36259977d 100644 --- a/cockatrice/src/settings/cache_settings.cpp +++ b/cockatrice/src/settings/cache_settings.cpp @@ -178,6 +178,7 @@ SettingsCache::SettingsCache() gameFiltersSettings = new GameFiltersSettings(settingsPath, this); layoutsSettings = new LayoutsSettings(settingsPath, this); downloadSettings = new DownloadSettings(settingsPath, this); + recentsSettings = new RecentsSettings(settingsPath, this); if (!QFile(settingsPath + "global.ini").exists()) translateLegacySettings(); diff --git a/cockatrice/src/settings/cache_settings.h b/cockatrice/src/settings/cache_settings.h index 59373b890..31676ac2f 100644 --- a/cockatrice/src/settings/cache_settings.h +++ b/cockatrice/src/settings/cache_settings.h @@ -7,6 +7,7 @@ #include "game_filters_settings.h" #include "layouts_settings.h" #include "message_settings.h" +#include "recents_settings.h" #include "servers_settings.h" #include "shortcuts_settings.h" @@ -82,6 +83,7 @@ private: GameFiltersSettings *gameFiltersSettings; LayoutsSettings *layoutsSettings; DownloadSettings *downloadSettings; + RecentsSettings *recentsSettings; QByteArray mainWindowGeometry; QByteArray tokenDialogGeometry; @@ -598,6 +600,10 @@ public: { return *downloadSettings; } + RecentsSettings &recents() const + { + return *recentsSettings; + } bool getIsPortableBuild() const { return isPortableBuild; diff --git a/cockatrice/src/settings/recents_settings.cpp b/cockatrice/src/settings/recents_settings.cpp new file mode 100644 index 000000000..a9250ecf6 --- /dev/null +++ b/cockatrice/src/settings/recents_settings.cpp @@ -0,0 +1,32 @@ +#include "recents_settings.h" + +#define MAX_RECENT_DECK_COUNT 10 + +RecentsSettings::RecentsSettings(QString settingPath, QObject *parent) + : SettingsManager(settingPath + "recents.ini", parent) +{ +} + +QStringList RecentsSettings::getRecentlyOpenedDeckPaths() +{ + return getValue("deckpaths", "deckbuilder").toStringList(); +} +void RecentsSettings::clearRecentlyOpenedDeckPaths() +{ + deleteValue("deckpaths", "deckbuilder"); + emit recentlyOpenedDeckPathsChanged(); +} +void RecentsSettings::updateRecentlyOpenedDeckPaths(const QString &deckPath) +{ + auto deckPaths = getValue("deckpaths", "deckbuilder").toStringList(); + deckPaths.removeAll(deckPath); + + deckPaths.prepend(deckPath); + + while (deckPaths.size() > MAX_RECENT_DECK_COUNT) { + deckPaths.removeLast(); + } + + setValue(deckPaths, "deckpaths", "deckbuilder"); + emit recentlyOpenedDeckPathsChanged(); +} \ No newline at end of file diff --git a/cockatrice/src/settings/recents_settings.h b/cockatrice/src/settings/recents_settings.h new file mode 100644 index 000000000..ce66d5ccc --- /dev/null +++ b/cockatrice/src/settings/recents_settings.h @@ -0,0 +1,23 @@ +#ifndef RECENTS_SETTINGS_H +#define RECENTS_SETTINGS_H + +#include "settings_manager.h" + +class RecentsSettings : public SettingsManager +{ + Q_OBJECT + friend class SettingsCache; + + explicit RecentsSettings(QString settingPath, QObject *parent = nullptr); + RecentsSettings(const RecentsSettings & /*other*/); + +public: + QStringList getRecentlyOpenedDeckPaths(); + void clearRecentlyOpenedDeckPaths(); + void updateRecentlyOpenedDeckPaths(const QString &deckPath); + +signals: + void recentlyOpenedDeckPathsChanged(); +}; + +#endif // RECENTS_SETTINGS_H diff --git a/oracle/CMakeLists.txt b/oracle/CMakeLists.txt index 218621317..27baf6014 100644 --- a/oracle/CMakeLists.txt +++ b/oracle/CMakeLists.txt @@ -28,6 +28,7 @@ set(oracle_SOURCES ../cockatrice/src/settings/servers_settings.cpp ../cockatrice/src/settings/settings_manager.cpp ../cockatrice/src/settings/message_settings.cpp + ../cockatrice/src/settings/recents_settings.cpp ../cockatrice/src/settings/game_filters_settings.cpp ../cockatrice/src/settings/layouts_settings.cpp ../cockatrice/src/settings/download_settings.cpp