From 6a67d1c0a9922bfec2593593151952a45425f2db Mon Sep 17 00:00:00 2001 From: Thomas Jentzsch Date: Mon, 29 Nov 2021 09:27:41 +0100 Subject: [PATCH] add option for removing recent/popular files tried to fix the Linux compile problem renamed the (internal) Settings keys used to store the favorites further updated doc --- docs/index.html | 94 +++++++++++++++++++++++------- src/emucore/Settings.cxx | 6 +- src/gui/FavoritesManager.cxx | 36 ++++++++---- src/gui/FavoritesManager.hxx | 4 +- src/gui/LauncherDialog.cxx | 43 +++++++++----- src/gui/LauncherFileListWidget.cxx | 37 ++++++------ src/gui/LauncherFileListWidget.hxx | 5 ++ 7 files changed, 157 insertions(+), 68 deletions(-) diff --git a/docs/index.html b/docs/index.html index 805c130f5..64a15edcc 100644 --- a/docs/index.html +++ b/docs/index.html @@ -307,6 +307,7 @@ TIA sprites and collisions for each object separately
  • Full system state save/load functionality
  • Automatic save state creation ('Time Machine') which allows moving back and forth in the recorded timeline
  • +
  • Tracking of user favorites and popular or recently played ROMs.
  • High scores saving (internal or via PlusROM High Score Club)
  • Cross-platform UI including a built-in ROM launcher frontend
  • Built-in extensive debugger, including static analysis with the Distella disassembler @@ -2263,6 +2264,16 @@ Backspace Backspace + + Remove from 'Recently Played' or 'Most Popular' folder + Control + X + Control + X + + + Toggle favorite + Control + F + Control + F + Open Power-On options dialog Control + P @@ -2274,20 +2285,25 @@ Control + H - Toggle favorite - Control + F - Control + F + Toggle file extensions display + Control + E + Control + E + + + Toggle show all ROMs + Control + A + Control + A + + + Toggle search ROMs in subdirectories too + Control + D + Control + D Reload ROM listing Control + R Control + R - - Toggle file extensions display - Control + X - Control + X -

    UI Keys in Text Editing areas (cannot be remapped)

    @@ -3250,6 +3266,16 @@ directory only or all subdirectories too. + +
    -altsorting <1|0>
    + Alternative sorting in virtual folders. + + + +
    -maxrecentroms <1|0>
    + Number of ROMs tracked in 'Recently played' folder. + +
    -romviewer <float>
    Hide ROM Info Viewer in ROM launcher mode (0) or use the @@ -4210,12 +4236,21 @@

    ROM Launcher Context Menu

    -

    The ROM launcher also contains a context menu, selected by clicking the - right mouse button in the ROM list. This context menu - contains the following items:

    +

    The ROM launcher also contains a context menu, opened by clicking the + right mouse button in the ROM list or by a long controller button press. + This context menu can contain the following items:

    -

      -
    1. Power-on options: Selecting this option shows a dialog whereby +

        +
      • +

        Remove from recently played/most popular (or 'Control + X'): + This option removes the selected ROM from the current folder.

        +
      • +
      • +

        Add to/remove from favorites (or 'Control + F'): This option + toggles the favorite state of the selected ROM.

        +
      • +
      • Power-on options (or 'Control + P'): + Selecting this option shows a dialog whereby ROM properties can be temporarily overridden, and joystick/console buttons can be temporarily held down. Selecting options from this dialog will cause all ROMs launched after that to use those properties you specify. Clicking Defaults will disable @@ -4243,16 +4278,33 @@ -

        This dialog can also be opened by pressing 'Control + P'.

      • -
      • High scores: This option displays the - High Scores dialog for the selected ROM. Only available if high score - properties have been setup for the ROM. Also available via 'Control + H' keys combo.
      • +
      • +

        High scores (or 'Control + H'): This option displays the + High Scores dialog for the selected ROM. Only available if high score + properties have been setup for the ROM.

      • -
      • Reload listing: Selecting this performs a reload of the - current listing. It is an alternative to pressing the 'Control + R' - key combo.
      • -

    +
  • +

    Enable/disable file extensions (or 'Control + E'): Toggles the + display of the file extensions.

    +
  • +
  • +

    Toggle alternative sorting (or 'Control + S'): Toggles + alternative sorting in the virtual directories.

    +
  • +
  • +

    Show all files/only ROMs (or 'Control + A'): Toggles display of + non-ROM files.

    +
  • +
  • +

    Include/exclude subdirectories (or 'Control + D'): Toggles searching + of ROMs in current directory only or all subdirectories too.

    +
  • +
  • +

    Reload listing (or 'Control + R'): Selecting this performs a + reload of the current listing.

    +
  • +


    ROM Audit Mode

    diff --git a/src/emucore/Settings.cxx b/src/emucore/Settings.cxx index d3ee3583a..804502a00 100644 --- a/src/emucore/Settings.cxx +++ b/src/emucore/Settings.cxx @@ -157,10 +157,10 @@ Settings::Settings() setPermanent("launcherextensions", "false"); setPermanent("romviewer", "1"); setPermanent("lastrom", ""); - setPermanent("favoriteroms", ""); - setPermanent("recentroms", ""); + setPermanent("_favoriteroms", ""); // internal only + setPermanent("_recentroms", ""); // internal only setPermanent("maxrecentroms", "20"); - setPermanent("popularroms", ""); + setPermanent("_popularroms", ""); // internal only setPermanent("altsorting", "false"); // UI-related options diff --git a/src/gui/FavoritesManager.cxx b/src/gui/FavoritesManager.cxx index 36ba57581..13ffe88c0 100644 --- a/src/gui/FavoritesManager.cxx +++ b/src/gui/FavoritesManager.cxx @@ -36,7 +36,7 @@ void FavoritesManager::load() // User Favorites myUserSet.clear(); - const string& serializedUser = mySettings.getString("favoriteroms"); + const string& serializedUser = mySettings.getString("_favoriteroms"); if(!serializedUser.empty()) { const json& jUser = json::parse(serializedUser); @@ -49,7 +49,7 @@ void FavoritesManager::load() // Recently Played myRecentList.clear(); - const string& serializedRecent = mySettings.getString("recentroms"); + const string& serializedRecent = mySettings.getString("_recentroms"); if(!serializedRecent.empty()) { const json& jRecent = json::parse(serializedRecent); @@ -62,7 +62,7 @@ void FavoritesManager::load() // Most Popular myPopularMap.clear(); - const string& serializedPopular = mySettings.getString("popularroms"); + const string& serializedPopular = mySettings.getString("_popularroms"); if(!serializedPopular.empty()) { const json& jPopular = json::parse(serializedPopular); @@ -82,19 +82,19 @@ void FavoritesManager::save() json jUser = json::array(); for(const auto& path : myUserSet) jUser.push_back(path); - mySettings.setValue("favoriteroms", jUser.dump(2)); + mySettings.setValue("_favoriteroms", jUser.dump(2)); // Recently Played json jRecent = json::array(); for(const auto& path : myRecentList) jRecent.push_back(path); - mySettings.setValue("recentroms", jRecent.dump(2)); + mySettings.setValue("_recentroms", jRecent.dump(2)); // Most Popular json jPopular = json::array(); for(const auto& path : myPopularMap) - jPopular.push_back(path); - mySettings.setValue("popularroms", jPopular.dump(2)); + jPopular.emplace_back(path); + mySettings.setValue("_popularroms", jPopular.dump(2)); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -159,17 +159,25 @@ void FavoritesManager::update(const string& path) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void FavoritesManager::addRecent(const string& path) { - auto it = std::find(myRecentList.begin(), myRecentList.end(), path); - // Always remove existing before adding at the end again - if(it != myRecentList.end()) - myRecentList.erase(it); + removeRecent(path); myRecentList.emplace_back(path); + // Limit size while(myRecentList.size() > myMaxRecent) myRecentList.erase(myRecentList.begin()); } +bool FavoritesManager::removeRecent(const string& path) +{ + auto it = std::find(myRecentList.begin(), myRecentList.end(), path); + + if(it != myRecentList.end()) + myRecentList.erase(it); + + return it != myRecentList.end(); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - const FavoritesManager::RecentList& FavoritesManager::recentList() const { @@ -198,6 +206,11 @@ const FavoritesManager::RecentList& FavoritesManager::recentList() const return sortedList; } +bool FavoritesManager::removePopular(const string& path) +{ + return myPopularMap.erase(path); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void FavoritesManager::incPopular(const string& path) { @@ -220,7 +233,6 @@ void FavoritesManager::incPopular(const string& path) auto entry = myPopularMap.find(item->first); if(entry != myPopularMap.end()) { - //if(item - sortedList.cbegin() <= min_popular) if(entry->second >= scale * (1.0 - factor)) entry->second *= factor; // age data else diff --git a/src/gui/FavoritesManager.hxx b/src/gui/FavoritesManager.hxx index 13c020446..2658e032e 100644 --- a/src/gui/FavoritesManager.hxx +++ b/src/gui/FavoritesManager.hxx @@ -54,9 +54,11 @@ class FavoritesManager void update(const string& path); // Recently played + bool removeRecent(const string& path); const RecentList& recentList() const; // Most popular + bool removePopular(const string& path); const PopularList& popularList() const; @@ -67,7 +69,7 @@ class FavoritesManager UserSet myUserSet; RecentList myRecentList; PopularMap myPopularMap; - uInt32 myMaxRecent{10}; + uInt32 myMaxRecent{20}; Settings& mySettings; diff --git a/src/gui/LauncherDialog.cxx b/src/gui/LauncherDialog.cxx index 7aacad097..4006c643c 100644 --- a/src/gui/LauncherDialog.cxx +++ b/src/gui/LauncherDialog.cxx @@ -630,6 +630,11 @@ void LauncherDialog::handleContextMenu() if(cmd == "favorite") myList->toggleUserFavorite(); + else if(cmd == "remove") + { + myList->removeFavorite(); + reload(); + } else if(cmd == "override") openGlobalProps(); else if(cmd == "extensions") @@ -640,12 +645,12 @@ void LauncherDialog::handleContextMenu() toggleShowAll(); else if(cmd == "subdirs") toggleSubDirs(); - else if(cmd == "reload") - reload(); else if(cmd == "highscores") openHighScores(); else if(cmd == "options") openSettings(); + else if(cmd == "reload") + reload(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -686,6 +691,10 @@ void LauncherDialog::handleKeyDown(StellaKey key, StellaMod mod, bool repeated) toggleSubDirs(); break; + case KBDK_E: + toggleExtensions(); + break; + case KBDK_F: myList->toggleUserFavorite(); break; @@ -712,7 +721,8 @@ void LauncherDialog::handleKeyDown(StellaKey key, StellaMod mod, bool repeated) break; case KBDK_X: - toggleExtensions(); + myList->removeFavorite(); + reload(); break; default: @@ -1006,12 +1016,12 @@ void LauncherDialog::toggleSorting() void LauncherDialog::addContextItem(VariantList& items, const string& label, const string& shortcut, const string& key) { - const string pad = " "; + const string pad = " "; if(myUseMinimalUI) VarList::push_back(items, " " + label + " ", key); else - VarList::push_back(items, " " + label + pad.substr(0, 24 - label.length()) + VarList::push_back(items, " " + label + pad.substr(0, 29 - label.length()) + shortcut + " ", key); } @@ -1030,14 +1040,21 @@ void LauncherDialog::openContextMenu(int x, int y) // TODO: remove subdirs and show all from GUI - if(!currentNode().isDirectory() && Bankswitch::isValidRomName(currentNode())) + if(!currentNode().isDirectory()) { - addContextItem(items, myList->isUserFavorite(myList->selected().getPath()) - ? "Remove from favorites" - : "Add to favorites", "Ctrl+F", "favorite"); - addContextItem(items, "Power-on options" + ELLIPSIS, "Ctrl+P", "override"); - if(instance().highScores().enabled()) - addContextItem(items, "High scores" + ELLIPSIS, "Ctrl+H", "highscores"); + if(myList->inRecentDir()) + addContextItem(items, "Remove from recently played", "Ctrl+X", "remove"); + if(myList->inPopularDir()) + addContextItem(items, "Remove from most popular", "Ctrl+X", "remove"); + if(Bankswitch::isValidRomName(currentNode())) + { + addContextItem(items, myList->isUserFavorite(myList->selected().getPath()) + ? "Remove from favorites" + : "Add to favorites", "Ctrl+F", "favorite"); + addContextItem(items, "Power-on options" + ELLIPSIS, "Ctrl+P", "override"); + if(instance().highScores().enabled()) + addContextItem(items, "High scores" + ELLIPSIS, "Ctrl+H", "highscores"); + } } if(myUseMinimalUI) addContextItem(items, "Options" + ELLIPSIS, "Ctrl+O", "options"); @@ -1045,7 +1062,7 @@ void LauncherDialog::openContextMenu(int x, int y) { addContextItem(items, instance().settings().getBool("launcherextensions") ? "Disable file extensions" - : "Enable file extensions", "Ctrl+X", "extensions"); + : "Enable file extensions", "Ctrl+E", "extensions"); if(myList->inVirtualDir()) addContextItem(items, instance().settings().getBool("altsorting") ? "Normal sorting" diff --git a/src/gui/LauncherFileListWidget.cxx b/src/gui/LauncherFileListWidget.cxx index bed7ba0f6..5177435b1 100644 --- a/src/gui/LauncherFileListWidget.cxx +++ b/src/gui/LauncherFileListWidget.cxx @@ -52,36 +52,25 @@ bool LauncherFileListWidget::isDirectory(const FilesystemNode& node) const void LauncherFileListWidget::getChildren(const FilesystemNode::CancelCheck& isCancelled) { // TODO: - // + remove virtual folders in virtual folders - // + tooltips (incl. subdirs) - // + always add (after remove) recent ROMs - // + age recently played (e.g. reduce all regularly, WHEN? HOW MUCH?) - // + mark virtual dir when returning from it - // + "lastrom" - // + uppercase search - // + change sort order - // + move subdirs & all files into popup menu - // + no all files option in virtual folders - // + missing large icons - // + Settings.cxx doc - // + display only in ROM path folder // - remove subdirs & all files from GUI - // - doc (settings, hotkeys, popup, launcher, virtual folders) + // - doc (launcher, virtual directories) if(_node.exists() || !_node.hasParent()) { myInVirtualDir = false; + myVirtualDir = EmptyString; FileListWidget::getChildren(isCancelled); } else { myInVirtualDir = true; + myVirtualDir = _node.getName(); + FilesystemNode parent(_node.getParent()); parent.setName(".."); _fileList.emplace_back(parent); - const string& name = _node.getName(); - if(name == user_name) + if(myVirtualDir == user_name) { for(auto& item : myFavorites->userList()) { @@ -90,7 +79,7 @@ void LauncherFileListWidget::getChildren(const FilesystemNode::CancelCheck& isCa _fileList.emplace_back(node); } } - else if(name == popular_name) + else if(myVirtualDir == popular_name) { for(auto& item : myFavorites->popularList()) { @@ -99,7 +88,7 @@ void LauncherFileListWidget::getChildren(const FilesystemNode::CancelCheck& isCa _fileList.emplace_back(node); } } - else if(name == recent_name) + else if(myVirtualDir == recent_name) { for(auto& item : myFavorites->recentList()) { @@ -187,6 +176,18 @@ void LauncherFileListWidget::toggleUserFavorite() } } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void LauncherFileListWidget::removeFavorite() +{ + if(!selected().isDirectory()) + { + if((inRecentDir() && myFavorites->removeRecent(selected().getPath())) + || (inPopularDir() && myFavorites->removePopular(selected().getPath()))) + // Redraw file list + setDirty(); + } +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void LauncherFileListWidget::userFavor(const string& path, bool isUserFavorite) { diff --git a/src/gui/LauncherFileListWidget.hxx b/src/gui/LauncherFileListWidget.hxx index f8ecf35fd..bb8b636d4 100644 --- a/src/gui/LauncherFileListWidget.hxx +++ b/src/gui/LauncherFileListWidget.hxx @@ -44,9 +44,13 @@ class LauncherFileListWidget : public FileListWidget void updateFavorites(); bool isUserFavorite(const string& path) const; void toggleUserFavorite(); + void removeFavorite(); bool isDirectory(const FilesystemNode& node) const override; bool inVirtualDir() const { return myInVirtualDir; } + bool inUserDir() const { return myVirtualDir == user_name; } + bool inRecentDir() const { return myVirtualDir == recent_name; } + bool inPopularDir() const { return myVirtualDir == popular_name; } private: static const string user_name; @@ -55,6 +59,7 @@ class LauncherFileListWidget : public FileListWidget unique_ptr myFavorites; bool myInVirtualDir{false}; + string myVirtualDir; string myRomDir; private: