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
This commit is contained in:
Thomas Jentzsch 2021-11-29 09:27:41 +01:00
parent 00609a3a7a
commit 6a67d1c0a9
7 changed files with 157 additions and 68 deletions

View File

@ -307,6 +307,7 @@
TIA sprites and collisions for each object separately</li> TIA sprites and collisions for each object separately</li>
<li>Full system state save/load functionality</li> <li>Full system state save/load functionality</li>
<li>Automatic save state creation ('Time Machine') which allows moving back and forth in the recorded timeline</li> <li>Automatic save state creation ('Time Machine') which allows moving back and forth in the recorded timeline</li>
<li>Tracking of user favorites and popular or recently played ROMs.</li>
<li>High scores saving (internal or via PlusROM High Score Club)</li> <li>High scores saving (internal or via PlusROM High Score Club)</li>
<li>Cross-platform UI including a built-in ROM launcher frontend</li> <li>Cross-platform UI including a built-in ROM launcher frontend</li>
<li>Built-in extensive debugger, including static analysis with the Distella disassembler <li>Built-in extensive debugger, including static analysis with the Distella disassembler
@ -2263,6 +2264,16 @@
<td>Backspace</td> <td>Backspace</td>
<td>Backspace</td> <td>Backspace</td>
</tr> </tr>
<tr>
<td>Remove from 'Recently Played' or 'Most Popular' folder</td>
<td>Control + X</td>
<td>Control + X</td>
</tr>
<tr>
<td>Toggle favorite</td>
<td>Control + F</td>
<td>Control + F</td>
</tr>
<tr> <tr>
<td>Open Power-On options dialog</td> <td>Open Power-On options dialog</td>
<td>Control + P</td> <td>Control + P</td>
@ -2274,20 +2285,25 @@
<td>Control + H</td> <td>Control + H</td>
</tr> </tr>
<tr> <tr>
<td>Toggle favorite</td> <td>Toggle file extensions display</td>
<td>Control + F</td> <td>Control + E</td>
<td>Control + F</td> <td>Control + E</td>
</tr>
<tr>
<td>Toggle show all ROMs</td>
<td>Control + A</td>
<td>Control + A</td>
</tr>
<tr>
<td>Toggle search ROMs in subdirectories too</td>
<td>Control + D</td>
<td>Control + D</td>
</tr> </tr>
<tr> <tr>
<td>Reload ROM listing</td> <td>Reload ROM listing</td>
<td>Control + R</td> <td>Control + R</td>
<td>Control + R</td> <td>Control + R</td>
</tr> </tr>
<tr>
<td>Toggle file extensions display</td>
<td>Control + X</td>
<td>Control + X</td>
</tr>
</table> </table>
<p><b>UI Keys in Text Editing areas (cannot be remapped)</b></p> <p><b>UI Keys in Text Editing areas (cannot be remapped)</b></p>
@ -3250,6 +3266,16 @@
directory only or all subdirectories too.</td> directory only or all subdirectories too.</td>
</tr> </tr>
<tr>
<td><pre>-altsorting &lt;1|0&gt;</pre></td>
<td>Alternative sorting in virtual folders.</td>
</tr>
<tr>
<td><pre>-maxrecentroms &lt;1|0&gt;</pre></td>
<td>Number of ROMs tracked in 'Recently played' folder.</td>
</tr>
<tr> <tr>
<td><pre>-romviewer &lt;float&gt;</pre></td> <td><pre>-romviewer &lt;float&gt;</pre></td>
<td>Hide ROM Info Viewer in ROM launcher mode (0) or use the <td>Hide ROM Info Viewer in ROM launcher mode (0) or use the
@ -4210,12 +4236,21 @@
<h3><b><a name="ROMLauncherContextMenu">ROM Launcher Context Menu</a></b></h3> <h3><b><a name="ROMLauncherContextMenu">ROM Launcher Context Menu</a></b></h3>
<p>The ROM launcher also contains a context menu, selected by clicking the <p>The ROM launcher also contains a context menu, opened by clicking the
right mouse button in the ROM list. This context menu right mouse button in the ROM list or by a long controller button press.
contains the following items:</p> This context menu can contain the following items:</p>
<p><ol> <p><ul>
<li><p><b><a name="PowerOn">Power-on options</a></b>: Selecting this option shows a dialog whereby <li>
<p><b>Remove from recently played/most popular</b> (or 'Control + X'):
This option removes the selected ROM from the current folder.</p>
</li>
<li>
<p><b>Add to/remove from favorites</b> (or 'Control + F'): This option
toggles the favorite state of the selected ROM.</p>
</li>
<li><p><b><a name="PowerOn">Power-on options</a></b> (or 'Control + P'):
Selecting this option shows a dialog whereby
ROM properties can be temporarily overridden, and joystick/console buttons can be 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 temporarily held down. Selecting options from this dialog will cause all ROMs launched
after that to use those properties you specify. Clicking <b>Defaults</b> will disable after that to use those properties you specify. Clicking <b>Defaults</b> will disable
@ -4243,16 +4278,33 @@
</td> </td>
</tr> </tr>
</table> </table>
<p>This dialog can also be opened by pressing 'Control + P'.</p>
</li> </li>
<li><b>High scores</b>: This option displays the <a href="#HighScores"> <li>
High Scores</a> dialog for the selected ROM. Only available if high score <p><b>High scores</b> (or 'Control + H'): This option displays the <a href="#HighScores">
properties have been setup for the ROM. Also available via 'Control + H' keys combo.</li> High Scores</a> dialog for the selected ROM. Only available if high score
properties have been setup for the ROM.</p>
</li> </li>
<br><li><b>Reload listing</b>: Selecting this performs a reload of the <li>
current listing. It is an alternative to pressing the 'Control + R' <p><b>Enable/disable file extensions</b> (or 'Control + E'): Toggles the
key combo.</li> display of the file extensions.</p>
</ol></p> </li>
<li>
<p><b>Toggle alternative sorting</b> (or 'Control + S'): Toggles
alternative sorting in the virtual directories.</p>
</li>
<li>
<p><b>Show all files/only ROMs</b> (or 'Control + A'): Toggles display of
non-ROM files.</p>
</li>
<li>
<p><b>Include/exclude subdirectories</b> (or 'Control + D'): Toggles searching
of ROMs in current directory only or all subdirectories too.</p>
</li>
<li>
<p><b>Reload listing</b> (or 'Control + R'): Selecting this performs a
reload of the current listing. </p>
</li>
</ul></p>
</blockquote></br> </blockquote></br>
<h2><b><a name="ROMAudit">ROM Audit Mode</a></b></h2> <h2><b><a name="ROMAudit">ROM Audit Mode</a></b></h2>

View File

@ -157,10 +157,10 @@ Settings::Settings()
setPermanent("launcherextensions", "false"); setPermanent("launcherextensions", "false");
setPermanent("romviewer", "1"); setPermanent("romviewer", "1");
setPermanent("lastrom", ""); setPermanent("lastrom", "");
setPermanent("favoriteroms", ""); setPermanent("_favoriteroms", ""); // internal only
setPermanent("recentroms", ""); setPermanent("_recentroms", ""); // internal only
setPermanent("maxrecentroms", "20"); setPermanent("maxrecentroms", "20");
setPermanent("popularroms", ""); setPermanent("_popularroms", ""); // internal only
setPermanent("altsorting", "false"); setPermanent("altsorting", "false");
// UI-related options // UI-related options

View File

@ -36,7 +36,7 @@ void FavoritesManager::load()
// User Favorites // User Favorites
myUserSet.clear(); myUserSet.clear();
const string& serializedUser = mySettings.getString("favoriteroms"); const string& serializedUser = mySettings.getString("_favoriteroms");
if(!serializedUser.empty()) if(!serializedUser.empty())
{ {
const json& jUser = json::parse(serializedUser); const json& jUser = json::parse(serializedUser);
@ -49,7 +49,7 @@ void FavoritesManager::load()
// Recently Played // Recently Played
myRecentList.clear(); myRecentList.clear();
const string& serializedRecent = mySettings.getString("recentroms"); const string& serializedRecent = mySettings.getString("_recentroms");
if(!serializedRecent.empty()) if(!serializedRecent.empty())
{ {
const json& jRecent = json::parse(serializedRecent); const json& jRecent = json::parse(serializedRecent);
@ -62,7 +62,7 @@ void FavoritesManager::load()
// Most Popular // Most Popular
myPopularMap.clear(); myPopularMap.clear();
const string& serializedPopular = mySettings.getString("popularroms"); const string& serializedPopular = mySettings.getString("_popularroms");
if(!serializedPopular.empty()) if(!serializedPopular.empty())
{ {
const json& jPopular = json::parse(serializedPopular); const json& jPopular = json::parse(serializedPopular);
@ -82,19 +82,19 @@ void FavoritesManager::save()
json jUser = json::array(); json jUser = json::array();
for(const auto& path : myUserSet) for(const auto& path : myUserSet)
jUser.push_back(path); jUser.push_back(path);
mySettings.setValue("favoriteroms", jUser.dump(2)); mySettings.setValue("_favoriteroms", jUser.dump(2));
// Recently Played // Recently Played
json jRecent = json::array(); json jRecent = json::array();
for(const auto& path : myRecentList) for(const auto& path : myRecentList)
jRecent.push_back(path); jRecent.push_back(path);
mySettings.setValue("recentroms", jRecent.dump(2)); mySettings.setValue("_recentroms", jRecent.dump(2));
// Most Popular // Most Popular
json jPopular = json::array(); json jPopular = json::array();
for(const auto& path : myPopularMap) for(const auto& path : myPopularMap)
jPopular.push_back(path); jPopular.emplace_back(path);
mySettings.setValue("popularroms", jPopular.dump(2)); mySettings.setValue("_popularroms", jPopular.dump(2));
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -159,17 +159,25 @@ void FavoritesManager::update(const string& path)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FavoritesManager::addRecent(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 // Always remove existing before adding at the end again
if(it != myRecentList.end()) removeRecent(path);
myRecentList.erase(it);
myRecentList.emplace_back(path); myRecentList.emplace_back(path);
// Limit size // Limit size
while(myRecentList.size() > myMaxRecent) while(myRecentList.size() > myMaxRecent)
myRecentList.erase(myRecentList.begin()); 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 const FavoritesManager::RecentList& FavoritesManager::recentList() const
{ {
@ -198,6 +206,11 @@ const FavoritesManager::RecentList& FavoritesManager::recentList() const
return sortedList; return sortedList;
} }
bool FavoritesManager::removePopular(const string& path)
{
return myPopularMap.erase(path);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FavoritesManager::incPopular(const string& path) void FavoritesManager::incPopular(const string& path)
{ {
@ -220,7 +233,6 @@ void FavoritesManager::incPopular(const string& path)
auto entry = myPopularMap.find(item->first); auto entry = myPopularMap.find(item->first);
if(entry != myPopularMap.end()) if(entry != myPopularMap.end())
{ {
//if(item - sortedList.cbegin() <= min_popular)
if(entry->second >= scale * (1.0 - factor)) if(entry->second >= scale * (1.0 - factor))
entry->second *= factor; // age data entry->second *= factor; // age data
else else

View File

@ -54,9 +54,11 @@ class FavoritesManager
void update(const string& path); void update(const string& path);
// Recently played // Recently played
bool removeRecent(const string& path);
const RecentList& recentList() const; const RecentList& recentList() const;
// Most popular // Most popular
bool removePopular(const string& path);
const PopularList& popularList() const; const PopularList& popularList() const;
@ -67,7 +69,7 @@ class FavoritesManager
UserSet myUserSet; UserSet myUserSet;
RecentList myRecentList; RecentList myRecentList;
PopularMap myPopularMap; PopularMap myPopularMap;
uInt32 myMaxRecent{10}; uInt32 myMaxRecent{20};
Settings& mySettings; Settings& mySettings;

View File

@ -630,6 +630,11 @@ void LauncherDialog::handleContextMenu()
if(cmd == "favorite") if(cmd == "favorite")
myList->toggleUserFavorite(); myList->toggleUserFavorite();
else if(cmd == "remove")
{
myList->removeFavorite();
reload();
}
else if(cmd == "override") else if(cmd == "override")
openGlobalProps(); openGlobalProps();
else if(cmd == "extensions") else if(cmd == "extensions")
@ -640,12 +645,12 @@ void LauncherDialog::handleContextMenu()
toggleShowAll(); toggleShowAll();
else if(cmd == "subdirs") else if(cmd == "subdirs")
toggleSubDirs(); toggleSubDirs();
else if(cmd == "reload")
reload();
else if(cmd == "highscores") else if(cmd == "highscores")
openHighScores(); openHighScores();
else if(cmd == "options") else if(cmd == "options")
openSettings(); openSettings();
else if(cmd == "reload")
reload();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -686,6 +691,10 @@ void LauncherDialog::handleKeyDown(StellaKey key, StellaMod mod, bool repeated)
toggleSubDirs(); toggleSubDirs();
break; break;
case KBDK_E:
toggleExtensions();
break;
case KBDK_F: case KBDK_F:
myList->toggleUserFavorite(); myList->toggleUserFavorite();
break; break;
@ -712,7 +721,8 @@ void LauncherDialog::handleKeyDown(StellaKey key, StellaMod mod, bool repeated)
break; break;
case KBDK_X: case KBDK_X:
toggleExtensions(); myList->removeFavorite();
reload();
break; break;
default: default:
@ -1006,12 +1016,12 @@ void LauncherDialog::toggleSorting()
void LauncherDialog::addContextItem(VariantList& items, const string& label, void LauncherDialog::addContextItem(VariantList& items, const string& label,
const string& shortcut, const string& key) const string& shortcut, const string& key)
{ {
const string pad = " "; const string pad = " ";
if(myUseMinimalUI) if(myUseMinimalUI)
VarList::push_back(items, " " + label + " ", key); VarList::push_back(items, " " + label + " ", key);
else 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); + shortcut + " ", key);
} }
@ -1030,14 +1040,21 @@ void LauncherDialog::openContextMenu(int x, int y)
// TODO: remove subdirs and show all from GUI // TODO: remove subdirs and show all from GUI
if(!currentNode().isDirectory() && Bankswitch::isValidRomName(currentNode())) if(!currentNode().isDirectory())
{ {
addContextItem(items, myList->isUserFavorite(myList->selected().getPath()) if(myList->inRecentDir())
? "Remove from favorites" addContextItem(items, "Remove from recently played", "Ctrl+X", "remove");
: "Add to favorites", "Ctrl+F", "favorite"); if(myList->inPopularDir())
addContextItem(items, "Power-on options" + ELLIPSIS, "Ctrl+P", "override"); addContextItem(items, "Remove from most popular", "Ctrl+X", "remove");
if(instance().highScores().enabled()) if(Bankswitch::isValidRomName(currentNode()))
addContextItem(items, "High scores" + ELLIPSIS, "Ctrl+H", "highscores"); {
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) if(myUseMinimalUI)
addContextItem(items, "Options" + ELLIPSIS, "Ctrl+O", "options"); addContextItem(items, "Options" + ELLIPSIS, "Ctrl+O", "options");
@ -1045,7 +1062,7 @@ void LauncherDialog::openContextMenu(int x, int y)
{ {
addContextItem(items, instance().settings().getBool("launcherextensions") addContextItem(items, instance().settings().getBool("launcherextensions")
? "Disable file extensions" ? "Disable file extensions"
: "Enable file extensions", "Ctrl+X", "extensions"); : "Enable file extensions", "Ctrl+E", "extensions");
if(myList->inVirtualDir()) if(myList->inVirtualDir())
addContextItem(items, instance().settings().getBool("altsorting") addContextItem(items, instance().settings().getBool("altsorting")
? "Normal sorting" ? "Normal sorting"

View File

@ -52,36 +52,25 @@ bool LauncherFileListWidget::isDirectory(const FilesystemNode& node) const
void LauncherFileListWidget::getChildren(const FilesystemNode::CancelCheck& isCancelled) void LauncherFileListWidget::getChildren(const FilesystemNode::CancelCheck& isCancelled)
{ {
// TODO: // 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 // - remove subdirs & all files from GUI
// - doc (settings, hotkeys, popup, launcher, virtual folders) // - doc (launcher, virtual directories)
if(_node.exists() || !_node.hasParent()) if(_node.exists() || !_node.hasParent())
{ {
myInVirtualDir = false; myInVirtualDir = false;
myVirtualDir = EmptyString;
FileListWidget::getChildren(isCancelled); FileListWidget::getChildren(isCancelled);
} }
else else
{ {
myInVirtualDir = true; myInVirtualDir = true;
myVirtualDir = _node.getName();
FilesystemNode parent(_node.getParent()); FilesystemNode parent(_node.getParent());
parent.setName(".."); parent.setName("..");
_fileList.emplace_back(parent); _fileList.emplace_back(parent);
const string& name = _node.getName(); if(myVirtualDir == user_name)
if(name == user_name)
{ {
for(auto& item : myFavorites->userList()) for(auto& item : myFavorites->userList())
{ {
@ -90,7 +79,7 @@ void LauncherFileListWidget::getChildren(const FilesystemNode::CancelCheck& isCa
_fileList.emplace_back(node); _fileList.emplace_back(node);
} }
} }
else if(name == popular_name) else if(myVirtualDir == popular_name)
{ {
for(auto& item : myFavorites->popularList()) for(auto& item : myFavorites->popularList())
{ {
@ -99,7 +88,7 @@ void LauncherFileListWidget::getChildren(const FilesystemNode::CancelCheck& isCa
_fileList.emplace_back(node); _fileList.emplace_back(node);
} }
} }
else if(name == recent_name) else if(myVirtualDir == recent_name)
{ {
for(auto& item : myFavorites->recentList()) 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) void LauncherFileListWidget::userFavor(const string& path, bool isUserFavorite)
{ {

View File

@ -44,9 +44,13 @@ class LauncherFileListWidget : public FileListWidget
void updateFavorites(); void updateFavorites();
bool isUserFavorite(const string& path) const; bool isUserFavorite(const string& path) const;
void toggleUserFavorite(); void toggleUserFavorite();
void removeFavorite();
bool isDirectory(const FilesystemNode& node) const override; bool isDirectory(const FilesystemNode& node) const override;
bool inVirtualDir() const { return myInVirtualDir; } 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: private:
static const string user_name; static const string user_name;
@ -55,6 +59,7 @@ class LauncherFileListWidget : public FileListWidget
unique_ptr<FavoritesManager> myFavorites; unique_ptr<FavoritesManager> myFavorites;
bool myInVirtualDir{false}; bool myInVirtualDir{false};
string myVirtualDir;
string myRomDir; string myRomDir;
private: private: