added favorite directories

This commit is contained in:
Thomas Jentzsch 2021-12-02 23:27:02 +01:00
parent 3ee02e6958
commit f13862c19e
8 changed files with 550 additions and 467 deletions

View File

@ -55,7 +55,7 @@
<li><a href="#ROMInfo">ROM Launcher</a></li> <li><a href="#ROMInfo">ROM Launcher</a></li>
<ul> <ul>
<li><a href="#ROMInfoViewer">ROM Launcher Viewer</a></li> <li><a href="#ROMInfoViewer">ROM Launcher Viewer</a></li>
<li><a href="#FavoriteROMs">Favorite ROMs</a></li> <li><a href="#FavoriteROMs">Favorite ROMs and Directories</a></li>
<li><a href="#ROMLauncherContextMenu">ROM Launcher Context Menu</a></li> <li><a href="#ROMLauncherContextMenu">ROM Launcher Context Menu</a></li>
</ul> </ul>
<li><a href="#ROMAudit">ROM Audit Mode</a></li> <li><a href="#ROMAudit">ROM Audit Mode</a></li>
@ -4243,12 +4243,13 @@
</ul> </ul>
</br> </br>
<h3><b><a name="FavoriteROMs">Favorite ROMs</a></b></h3> <h3><b><a name="FavoriteROMs">Favorite ROMs and Directories</a></b></h3>
Stella allows to manually favor ROMs and also automatially tracks all played Stella allows to manually favor ROMs and directories and also automatially
ROMs. These ROMs are presented in three virtual directories: tracks all played ROMs. These ROMs are presented in three virtual directories:
<ul> <ul>
<li> <li>
<p><b>Favorites</b>: Lists all ROMs manually favored by the user (see <p><b>Favorites</b>: Lists all ROMs and directories manually favored by
the user (see
<b><a href="#ROMLauncherContextMenu">ROM Launcher Context Menu</a></b>). <b><a href="#ROMLauncherContextMenu">ROM Launcher Context Menu</a></b>).
</p> </p>
</li> </li>
@ -4281,7 +4282,7 @@
</li> </li>
<li> <li>
<p><b>Add to/remove from favorites</b> (or 'Control + F'): This option <p><b>Add to/remove from favorites</b> (or 'Control + F'): This option
toggles the favorite state of the selected ROM.</p> toggles the favorite state of the selected ROM or directory.</p>
</li> </li>
<li><p><b><a name="PowerOn">Power-on options</a></b> (or 'Control + P'): <li><p><b><a name="PowerOn">Power-on options</a></b> (or 'Control + P'):
Selecting this option shows a dialog whereby Selecting this option shows a dialog whereby

View File

@ -18,7 +18,7 @@
#ifndef VERSION_HXX #ifndef VERSION_HXX
#define VERSION_HXX #define VERSION_HXX
#define STELLA_VERSION "6.6" #define STELLA_VERSION "6.7pre"
#define STELLA_BUILD "7053" #define STELLA_BUILD "7053"
#endif #endif

View File

@ -43,8 +43,8 @@ void FavoritesManager::load()
for(const auto& u : jUser) for(const auto& u : jUser)
{ {
const string& path = u.get<string>(); const string& path = u.get<string>();
FilesystemNode node(path); //FilesystemNode node(path);
if(node.exists()) //if(node.exists())
addUser(path); addUser(path);
} }
} }
@ -60,8 +60,8 @@ void FavoritesManager::load()
for(const auto& r : jRecent) for(const auto& r : jRecent)
{ {
const string& path = r.get<string>(); const string& path = r.get<string>();
FilesystemNode node(path); //FilesystemNode node(path);
if(node.exists()) //if(node.exists())
addRecent(path); addRecent(path);
} }
} }
@ -77,8 +77,8 @@ void FavoritesManager::load()
{ {
const string& path = p[0].get<string>(); const string& path = p[0].get<string>();
const uInt32 count = p[1].get<uInt32>(); const uInt32 count = p[1].get<uInt32>();
FilesystemNode node(path); //FilesystemNode node(path);
if(node.exists()) //if(node.exists())
myPopularMap.emplace(path, count); myPopularMap.emplace(path, count);
} }
} }
@ -153,6 +153,10 @@ const FavoritesManager::UserList& FavoritesManager::userList() const
// Sort without path // Sort without path
FilesystemNode aNode(a); FilesystemNode aNode(a);
FilesystemNode bNode(b); FilesystemNode bNode(b);
bool realDir = aNode.isDirectory() && !BSPF::endsWithIgnoreCase(aNode.getPath(), ".zip");
if(realDir != (bNode.isDirectory() && !BSPF::endsWithIgnoreCase(bNode.getPath(), ".zip")))
return realDir;
return BSPF::compareIgnoreCase(aNode.getName(), bNode.getName()) < 0; return BSPF::compareIgnoreCase(aNode.getName(), bNode.getName()) < 0;
}); });
return sortedList; return sortedList;
@ -226,7 +230,6 @@ void FavoritesManager::incPopular(const string& path)
static constexpr uInt32 scale = 100; static constexpr uInt32 scale = 100;
static constexpr double factor = 0.7; static constexpr double factor = 0.7;
static constexpr uInt32 max_popular = scale; static constexpr uInt32 max_popular = scale;
//static constexpr uInt32 min_popular = max_popular * factor;
auto increased = myPopularMap.find(path); auto increased = myPopularMap.find(path);
if(increased != myPopularMap.end()) if(increased != myPopularMap.end())

View File

@ -97,33 +97,27 @@ void FileListWidget::setLocation(const FilesystemNode& node,
{ {
const string& path = file.getShortPath(); const string& path = file.getShortPath();
const string& name = file.getName(); const string& name = file.getName();
const string& displayName = _showFileExtensions ? name : file.getNameWithExt(EmptyString);
// display only relative path in tooltip // display only relative path in tooltip
if(path.length() >= orgLen && !fullPathToolTip()) if(path.length() >= orgLen && !fullPathToolTip())
_dirList.push_back(path.substr(orgLen)); _dirList.push_back(path.substr(orgLen));
else else
_dirList.push_back(path); _dirList.push_back(path);
if(file.isDirectory())
if(file.isDirectory() && !BSPF::endsWithIgnoreCase(name, ".zip"))
{ {
if(BSPF::endsWithIgnoreCase(name, ".zip")) list.push_back(name);
{ if(name == "..")
list.push_back(displayName); _iconTypeList.push_back(IconType::updir);
_iconTypeList.push_back(IconType::zip);
}
else else
{ _iconTypeList.push_back(getIconType(file.getPath()));
list.push_back(name);
if(name == "..")
_iconTypeList.push_back(IconType::updir);
else
_iconTypeList.push_back(IconType::directory);
}
} }
else else
{ {
const string& displayName = _showFileExtensions ? name : file.getNameWithExt(EmptyString);
list.push_back(displayName); list.push_back(displayName);
_iconTypeList.push_back(romIconType(file)); _iconTypeList.push_back(getIconType(file.getPath()));
} }
} }
extendLists(list); extendLists(list);
@ -157,13 +151,18 @@ void FileListWidget::getChildren(const FilesystemNode::CancelCheck& isCancelled)
} }
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - FileListWidget::IconType FileListWidget::getIconType(const string& path) const
FileListWidget::IconType FileListWidget::romIconType(const FilesystemNode& file) const
{ {
if(file.isFile() && Bankswitch::isValidRomName(file.getName())) const FilesystemNode node(path);
return IconType::rom;
if(node.isDirectory())
{
return BSPF::endsWithIgnoreCase(node.getName(), ".zip")
? IconType::zip : IconType::directory;
}
else else
return IconType::unknown; return node.isFile() && Bankswitch::isValidRomName(node.getName())
? IconType::rom : IconType::unknown;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -228,7 +227,7 @@ bool FileListWidget::handleText(char text)
// Select directories when the first character is uppercase // Select directories when the first character is uppercase
if((std::isupper(_quickSelectStr[0]) != 0) == if((std::isupper(_quickSelectStr[0]) != 0) ==
(_iconTypeList[selectedItem] == IconType::directory (_iconTypeList[selectedItem] == IconType::directory
|| _iconTypeList[selectedItem] == IconType::favdir || _iconTypeList[selectedItem] == IconType::userdir
|| _iconTypeList[selectedItem] == IconType::recentdir || _iconTypeList[selectedItem] == IconType::recentdir
|| _iconTypeList[selectedItem] == IconType::popdir)) || _iconTypeList[selectedItem] == IconType::popdir))
break; break;
@ -299,8 +298,8 @@ int FileListWidget::drawIcon(int i, int x, int y, ColorId color)
const int iconGap = smallIcon ? 2 : 3; const int iconGap = smallIcon ? 2 : 3;
FBSurface& s = _boss->dialog().surface(); FBSurface& s = _boss->dialog().surface();
s.drawBitmap(icon->data(), x + 1 + iconGap, s.drawBitmap(icon->data(), x + 2 + iconGap,
y + (_lineHeight - static_cast<int>(icon->size())) / 2, y + (_lineHeight - static_cast<int>(icon->size())) / 2 - 1,
color, iconWidth() - iconGap * 2, static_cast<int>(icon->size())); color, iconWidth() - iconGap * 2, static_cast<int>(icon->size()));
return iconWidth(); return iconWidth();
@ -309,229 +308,207 @@ int FileListWidget::drawIcon(int i, int x, int y, ColorId color)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const FileListWidget::Icon* FileListWidget::getIcon(int i) const const FileListWidget::Icon* FileListWidget::getIcon(int i) const
{ {
#if 1
static const Icon unknown_small = { static const Icon unknown_small = {
0b00111111'1100000, 0b00111111'11000000,
0b00100000'0110000, 0b00100000'01100000,
0b00100000'0111000, 0b00100000'01110000,
0b00100000'0111100, 0b00100000'01111000,
0b00100000'0000100, 0b00100000'00001000,
0b00100000'0000100, 0b00100000'00001000,
0b00100000'0000100, 0b00100000'00001000,
0b00100000'0000100, 0b00100000'00001000,
0b00100000'0000100, 0b00100000'00001000,
0b00100000'0000100, 0b00100000'00001000,
0b00100000'0000100, 0b00100000'00001000,
0b00100000'0000100, 0b00100000'00001000,
0b00100000'0000100, 0b00100000'00001000,
0b00111111'1111100 0b00111111'11111000
}; };
static const Icon rom_small = { static const Icon rom_small = {
0b00001111'1110000, 0b00000000000000000,
0b00001010'1010000, 0b00001111'11100000,
0b00001010'1010000, 0b00001010'10100000,
0b00001010'1010000, 0b00001010'10100000,
0b00001010'1010000, 0b00001010'10100000,
0b00001010'1010000, 0b00001010'10100000,
0b00011010'1011000, 0b00001010'10100000,
0b00110010'1001100, 0b00011010'10110000,
0b00100110'1100100, 0b00110010'10011000,
0b11101110'1110111, 0b00100110'11001000,
0b10001010'1010001, 0b11101110'11101110,
0b10011010'1011001, 0b10001010'10100010,
0b11110011'1001111 0b10011010'10110010,
0b11110011'10011110
}; };
static const Icon directory_small = { static const Icon directory_small = {
0b11111000'0000000, 0b00000000000000000,
0b11111100'0000000, 0b11111000'00000000,
0b11111111'1111111, 0b11111100'00000000,
0b10000000'0000001, 0b11111111'11111110,
0b10000000'0000001, 0b10000000'00000010,
0b10000000'0000001, 0b10000000'00000010,
0b10000000'0000001, 0b10000000'00000010,
0b10000000'0000001, 0b10000000'00000010,
0b10000000'0000001, 0b10000000'00000010,
0b10000000'0000001, 0b10000000'00000010,
0b10000000'0000001, 0b10000000'00000010,
0b10000000'0000001, 0b10000000'00000010,
0b11111111'1111111 0b10000000'00000010,
0b11111111'11111110
}; };
static const Icon zip_small = { static const Icon zip_small = {
//0b0011111'11111111, 0b00000000000000000,
//0b0110000'11000111, 0b11111000'00000000,
//0b1111111'11111101, 0b11111100'00000000,
//0b1000001'00000111, 0b11111111'11111110,
//0b1000001'00000101, 0b10000000'00000010,
//0b1000001'00000111, 0b10001111'11100010,
//0b1000001'00000111, 0b10000000'11100010,
//0b1111111'11111101, 0b10000001'11000010,
//0b1000001'00000111, 0b10000011'10000010,
//0b1000001'00000101, 0b10000111'00000010,
//0b1000001'00000111, 0b10001110'00000010,
//0b1000001'00000110, 0b10001111'11100010,
//0b1111111'11111100 0b10000000'00000010,
0b11111000'0000000, 0b11111111'11111110
0b11111100'0000000,
0b11111111'1111111,
0b10000000'0000001,
0b10001111'1110001,
0b10000000'1110001,
0b10000001'1100001,
0b10000011'1000001,
0b10000111'0000001,
0b10001110'0000001,
0b10001111'1110001,
0b10000000'0000001,
0b11111111'1111111
}; };
static const Icon up_small = { static const Icon up_small = {
//0b00000100'0000000, 0b00000000000000000,
//0b00001110'0000000, 0b11111000'00000000,
//0b00011111'0000000, 0b11111100'00000000,
//0b00111111'1000000, 0b11111111'11111110,
//0b01111111'1100000, 0b10000000'00000010,
//0b11111111'1110000, 0b10000011'10000010,
//0b00001110'0000000, 0b10000111'11000010,
//0b00001110'0000000, 0b10001111'11100010,
//0b00001110'0000000, 0b10011111'11110010,
//0b00001111'0000000, 0b10000011'10000010,
//0b00001111'1111111, 0b10000011'10000010,
//0b00000111'1111111, 0b10000011'10000010,
//0b00000011'1111111, 0b10000011'10000010,
//0b00000000'0000000, 0b11111111'11111110
0b11111000'0000000,
0b11111100'0000000,
0b11111111'1111111,
0b10000000'0000001,
0b10000011'1000001,
0b10000111'1100001,
0b10001111'1110001,
0b10011111'1111001,
0b10000011'1000001,
0b10000011'1000001,
0b10000011'1000001,
0b10000011'1000001,
0b11111111'1111111
}; };
static const Icon unknown_large = { static const Icon unknown_large = {
0b00111'11111111'11000000, 0b00000000000'00000000000,
0b00111'11111111'11100000, 0b00111111111'11110000000,
0b00110'00000000'01110000, 0b00111111111'11111000000,
0b00110'00000000'00111000, 0b00110000000'00011100000,
0b00110'00000000'00011100, 0b00110000000'00001110000,
0b00110'00000000'00001100, 0b00110000000'00000111000,
0b00110'00000000'00001100, 0b00110000000'00000011000,
0b00110'00000000'00001100, 0b00110000000'00000011000,
0b00110'00000000'00001100, 0b00110000000'00000011000,
0b00110'00000000'00001100, 0b00110000000'00000011000,
0b00110'00000000'00001100, 0b00110000000'00000011000,
0b00110'00000000'00001100, 0b00110000000'00000011000,
0b00110'00000000'00001100, 0b00110000000'00000011000,
0b00110'00000000'00001100, 0b00110000000'00000011000,
0b00110'00000000'00001100, 0b00110000000'00000011000,
0b00110'00000000'00001100, 0b00110000000'00000011000,
0b00110'00000000'00001100, 0b00110000000'00000011000,
0b00110'00000000'00001100, 0b00110000000'00000011000,
0b00110'00000000'00001100, 0b00110000000'00000011000,
0b00111'11111111'11111100, 0b00110000000'00000011000,
0b00111'11111111'11111100 0b00111111111'11111111000,
0b00111111111'11111111000
}; };
static const Icon rom_large = { static const Icon rom_large = {
0b00000'01111111'11000000, 0b00000000000'00000000000,
0b00000'01111111'11000000, 0b00000011111'11110000000,
0b00000'01101010'11000000, 0b00000011111'11110000000,
0b00000'01101010'11000000, 0b00000011010'10110000000,
0b00000'01101010'11000000, 0b00000011010'10110000000,
0b00000'01101010'11000000, 0b00000011010'10110000000,
0b00000'01101010'11000000, 0b00000011010'10110000000,
0b00000'01101010'11000000, 0b00000011010'10110000000,
0b00000'11101010'11100000, 0b00000011010'10110000000,
0b00000'11001010'01100000, 0b00000111010'10111000000,
0b00000'11001010'01100000, 0b00000110010'10011000000,
0b00001'11001010'01110000, 0b00000110010'10011000000,
0b00001'10001010'00110000, 0b00001110010'10011100000,
0b00011'10011011'00111000, 0b00001100010'10001100000,
0b00011'00011011'00011000, 0b00011100110'11001110000,
0b11111'00111011'10011111, 0b00011000110'11000110000,
0b11110'01111011'11001111, 0b11111001110'11100111110,
0b11000'01111011'11000011, 0b111100111101'1110011110,
0b11000'11111011'11100011, 0b110000111101'1110000110,
0b11111'11011111'01111111, 0b110001111101'1111000110,
0b11111'10011111'00111111 0b111111101111'1011111110,
0b111111001111'1001111110
}; };
static const Icon directory_large = { static const Icon directory_large = {
0b111111'10000000'0000000, 0b00000000000'00000000000,
0b111111'11000000'0000000, 0b11111110000'00000000000,
0b111111'11100000'0000000, 0b11111111000'00000000000,
0b111111'11111111'1111111, 0b11111111100'00000000000,
0b111111'11111111'1111111, 0b11111111111'11111111110,
0b110000'00000000'0000011, 0b11111111111'11111111110,
0b110000'00000000'0000011, 0b11000000000'00000000110,
0b110000'00000000'0000011, 0b11000000000'00000000110,
0b110000'00000000'0000011, 0b11000000000'00000000110,
0b110000'00000000'0000011, 0b11000000000'00000000110,
0b110000'00000000'0000011, 0b11000000000'00000000110,
0b110000'00000000'0000011, 0b11000000000'00000000110,
0b110000'00000000'0000011, 0b11000000000'00000000110,
0b110000'00000000'0000011, 0b11000000000'00000000110,
0b110000'00000000'0000011, 0b11000000000'00000000110,
0b110000'00000000'0000011, 0b11000000000'00000000110,
0b110000'00000000'0000011, 0b11000000000'00000000110,
0b110000'00000000'0000011, 0b11000000000'00000000110,
0b110000'00000000'0000011, 0b11000000000'00000000110,
0b111111'11111111'1111111, 0b11000000000'00000000110,
0b111111'11111111'1111111 0b11111111111'11111111110,
0b11111111111'11111111110
}; };
static const Icon zip_large = { static const Icon zip_large = {
0b111111'10000000'0000000, 0b00000000000'00000000000,
0b111111'11000000'0000000, 0b11111110000'00000000000,
0b111111'11100000'0000000, 0b11111111000'00000000000,
0b111111'11111111'1111111, 0b11111111100'00000000000,
0b111111'11111111'1111111, 0b11111111111'11111111110,
0b110000'00000000'0000011, 0b11111111111'11111111110,
0b110001'11111111'1100011, 0b11000000000'00000000110,
0b110001'11111111'1100011, 0b11000111111'11111000110,
0b110001'11111111'1100011, 0b11000111111'11111000110,
0b110000'00000111'1000011, 0b11000111111'11111000110,
0b110000'00001111'0000011, 0b11000000000'11110000110,
0b110000'00011110'0000011, 0b11000000001'11100000110,
0b110000'00111100'0000011, 0b11000000011'11000000110,
0b110000'01111000'0000011, 0b11000000111'10000000110,
0b110000'11110000'0000011, 0b11000001111'00000000110,
0b110001'11111111'1100011, 0b11000011110'00000000110,
0b110001'11111111'1100011, 0b11000111111'11111000110,
0b110001'11111111'1100011, 0b11000111111'11111000110,
0b110000'00000000'0000011, 0b11000111111'11111000110,
0b111111'11111111'1111111, 0b11000000000'00000000110,
0b111111'11111111'1111111 0b11111111111'11111111110,
0b11111111111'11111111110
}; };
static const Icon up_large = { static const Icon up_large = {
0b111111'10000000'0000000, 0b00000000000'00000000000,
0b111111'11000000'0000000, 0b11111110000'00000000000,
0b111111'11100000'0000000, 0b11111111000'00000000000,
0b111111'11111111'1111111, 0b11111111100'00000000000,
0b111111'11111111'1111111, 0b11111111111'11111111110,
0b110000'00000000'0000011, 0b11111111111'11111111110,
0b110000'00011100'0000011, 0b11000000000'00000000110,
0b110000'00111110'0000011, 0b11000000011'10000000110,
0b110000'01111111'0000011, 0b11000000111'11000000110,
0b110000'11111111'1000011, 0b11000001111'11100000110,
0b110001'11111111'1100011, 0b11000011111'11110000110,
0b110011'11111111'1110011, 0b11000111111'11111000110,
0b110011'11111111'1110011, 0b11001111111'11111100110,
0b110000'00111110'0000011, 0b11001111111'11111100110,
0b110000'00111110'0000011, 0b11000000111'11000000110,
0b110000'00111110'0000011, 0b11000000111'11000000110,
0b110000'00111110'0000011, 0b11000000111'11000000110,
0b110000'00111110'0000011, 0b11000000111'11000000110,
0b110000'00000000'0000011, 0b11000000111'11000000110,
0b111111'11111111'1111111, 0b11000000000'00000000110,
0b111111'11111111'1111111 0b11111111111'11111111110,
0b11111111111'11111111110
}; };
#endif
static const Icon* small_icons[int(IconType::numTypes)] = { static const Icon* small_icons[int(IconType::numTypes)] = {
&unknown_small, &rom_small, &directory_small, &zip_small, &up_small &unknown_small, &rom_small, &directory_small, &zip_small, &up_small
}; };
@ -541,7 +518,7 @@ const FileListWidget::Icon* FileListWidget::getIcon(int i) const
const bool smallIcon = iconWidth() < 24; const bool smallIcon = iconWidth() < 24;
const int iconType = int(_iconTypeList[i]); const int iconType = int(_iconTypeList[i]);
assert(iconType < 5); assert(iconType < int(IconType::numTypes));
return smallIcon ? small_icons[iconType] : large_icons[iconType]; return smallIcon ? small_icons[iconType] : large_icons[iconType];
} }

View File

@ -82,7 +82,7 @@ class FileListWidget : public StringListWidget
/** Select parent directory (if applicable) */ /** Select parent directory (if applicable) */
void selectParent(); void selectParent();
/** Descend into currently selected directory */ /** Descend into currently selected directory */
void selectDirectory(); virtual void selectDirectory();
/** Reload current location (file or directory) */ /** Reload current location (file or directory) */
void reload(); void reload();
@ -108,8 +108,10 @@ class FileListWidget : public StringListWidget
zip, zip,
updir, updir,
numTypes, numTypes,
favorite = numTypes, favrom = numTypes,
favdir, favdir,
favzip,
userdir,
recentdir, recentdir,
popdir, popdir,
numLauncherTypes = popdir - numTypes + 1 numLauncherTypes = popdir - numTypes + 1
@ -118,10 +120,12 @@ class FileListWidget : public StringListWidget
using Icon = uIntArray; using Icon = uIntArray;
protected: protected:
/** Very similar to setDirectory(), but also updates the history */
void setLocation(const FilesystemNode& node, const string& select);
virtual bool isDirectory(const FilesystemNode& node) const; virtual bool isDirectory(const FilesystemNode& node) const;
virtual void getChildren(const FilesystemNode::CancelCheck& isCancelled); virtual void getChildren(const FilesystemNode::CancelCheck& isCancelled);
virtual void extendLists(StringList& list) { } virtual void extendLists(StringList& list) { }
virtual IconType romIconType(const FilesystemNode& file) const; virtual IconType getIconType(const string& path) const;
virtual const Icon* getIcon(int i) const; virtual const Icon* getIcon(int i) const;
int iconWidth() const; int iconWidth() const;
virtual bool fullPathToolTip() const { return false; } virtual bool fullPathToolTip() const { return false; }
@ -130,13 +134,12 @@ class FileListWidget : public StringListWidget
FilesystemNode _node; FilesystemNode _node;
FSList _fileList; FSList _fileList;
FilesystemNode::NameFilter _filter; FilesystemNode::NameFilter _filter;
Common::FixedStack<string> _history;
string _selectedFile;
StringList _dirList; StringList _dirList;
IconTypeList _iconTypeList; IconTypeList _iconTypeList;
private: private:
/** Very similar to setDirectory(), but also updates the history */
void setLocation(const FilesystemNode& node, const string& select);
bool handleText(char text) override; bool handleText(char text) override;
void handleCommand(CommandSender* sender, int cmd, int data, int id) override; void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
int drawIcon(int i, int x, int y, ColorId color) override; int drawIcon(int i, int x, int y, ColorId color) override;
@ -146,9 +149,7 @@ class FileListWidget : public StringListWidget
bool _includeSubDirs{false}; bool _includeSubDirs{false};
bool _showFileExtensions{true}; bool _showFileExtensions{true};
Common::FixedStack<string> _history;
uInt32 _selected{0}; uInt32 _selected{0};
string _selectedFile;
string _quickSelectStr; string _quickSelectStr;
uInt64 _quickSelectTime{0}; uInt64 _quickSelectTime{0};

View File

@ -856,10 +856,6 @@ void LauncherDialog::handleCommand(CommandSender* sender, int cmd,
} }
[[fallthrough]]; [[fallthrough]];
case FileListWidget::ItemActivated: case FileListWidget::ItemActivated:
// Assumes that the ROM will be loaded successfully, has to be done
// before saving the config.
myList->updateFavorites();
saveConfig();
loadRom(); loadRom();
break; break;
@ -947,6 +943,11 @@ void LauncherDialog::handleCommand(CommandSender* sender, int cmd,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void LauncherDialog::loadRom() void LauncherDialog::loadRom()
{ {
// Assumes that the ROM will be loaded successfully, has to be done
// before saving the config.
myList->updateFavorites();
saveConfig();
const string& result = instance().createConsole(currentNode(), selectedRomMD5()); const string& result = instance().createConsole(currentNode(), selectedRomMD5());
if(result == EmptyString) if(result == EmptyString)
{ {
@ -1045,15 +1046,16 @@ void LauncherDialog::openContextMenu(int x, int y)
items.push_back(ContextItem("Remove from recently played", "Ctrl+X", "remove")); items.push_back(ContextItem("Remove from recently played", "Ctrl+X", "remove"));
if(myList->inPopularDir()) if(myList->inPopularDir())
items.push_back(ContextItem("Remove from most popular", "Ctrl+X", "remove")); items.push_back(ContextItem("Remove from most popular", "Ctrl+X", "remove"));
if(Bankswitch::isValidRomName(currentNode())) }
{ if(currentNode().isDirectory() || Bankswitch::isValidRomName(currentNode()))
items.push_back(ContextItem(myList->isUserFavorite(myList->selected().getPath()) items.push_back(ContextItem(myList->isUserFavorite(myList->selected().getPath())
? "Remove from favorites" ? "Remove from favorites"
: "Add to favorites", "Ctrl+F", "favorite")); : "Add to favorites", "Ctrl+F", "favorite"));
items.push_back(ContextItem("Power-on options" + ELLIPSIS, "Ctrl+P", "override")); if(!currentNode().isDirectory() && Bankswitch::isValidRomName(currentNode()))
if(instance().highScores().enabled()) {
items.push_back(ContextItem("High scores" + ELLIPSIS, "Ctrl+H", "highscores")); items.push_back(ContextItem("Power-on options" + ELLIPSIS, "Ctrl+P", "override"));
} if(instance().highScores().enabled())
items.push_back(ContextItem("High scores" + ELLIPSIS, "Ctrl+H", "highscores"));
} }
if(myUseMinimalUI) if(myUseMinimalUI)
{ {

View File

@ -34,6 +34,15 @@ LauncherFileListWidget::LauncherFileListWidget(GuiObject* boss, const GUI::Font&
myRomDir = instance().settings().getString("romdir"); myRomDir = instance().settings().getString("romdir");
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void LauncherFileListWidget::selectDirectory()
{
if(!myInVirtualDir && !_history.empty())
_history.pop();
_history.push(selected().getName());
setLocation(selected(), _selectedFile);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool LauncherFileListWidget::isDirectory(const FilesystemNode& node) const bool LauncherFileListWidget::isDirectory(const FilesystemNode& node) const
{ {
@ -71,6 +80,13 @@ void LauncherFileListWidget::getChildren(const FilesystemNode::CancelCheck& isCa
for(auto& item : myFavorites->userList()) for(auto& item : myFavorites->userList())
{ {
FilesystemNode node(item); FilesystemNode node(item);
string name = node.getName();
if(name.back() == FilesystemNode::PATH_SEPARATOR)
{
name.pop_back();
node.setName(name);
}
if(_filter(node)) if(_filter(node))
_fileList.emplace_back(node); _fileList.emplace_back(node);
} }
@ -124,7 +140,7 @@ void LauncherFileListWidget::extendLists(StringList& list)
int offset = _fileList.begin()->getName() == ".." ? 1 : 0; int offset = _fileList.begin()->getName() == ".." ? 1 : 0;
if(myFavorites->userList().size()) if(myFavorites->userList().size())
addFolder(list, offset, user_name, IconType::favdir); addFolder(list, offset, user_name, IconType::userdir);
if(myFavorites->popularList().size()) if(myFavorites->popularList().size())
addFolder(list, offset, popular_name, IconType::popdir); addFolder(list, offset, popular_name, IconType::popdir);
if(myFavorites->recentList().size()) if(myFavorites->recentList().size())
@ -162,13 +178,15 @@ bool LauncherFileListWidget::isUserFavorite(const string& path) const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void LauncherFileListWidget::toggleUserFavorite() void LauncherFileListWidget::toggleUserFavorite()
{ {
if(!selected().isDirectory() && Bankswitch::isValidRomName(selected())) if(selected().isDirectory() || Bankswitch::isValidRomName(selected()))
{ {
bool isUserFavorite = myFavorites->toggleUser(selected().getPath()); myFavorites->toggleUser(selected().getPath());
userFavor(selected().getPath());
userFavor(selected().getPath(), isUserFavorite);
// Redraw file list // Redraw file list
setDirty(); if(myVirtualDir == user_name)
reload();
else
setDirty();
} }
} }
@ -182,7 +200,7 @@ void LauncherFileListWidget::removeFavorite()
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void LauncherFileListWidget::userFavor(const string& path, bool isUserFavorite) void LauncherFileListWidget::userFavor(const string& path)
{ {
size_t pos = 0; size_t pos = 0;
@ -193,233 +211,311 @@ void LauncherFileListWidget::userFavor(const string& path, bool isUserFavorite)
pos++; pos++;
} }
if(pos < _iconTypeList.size()) if(pos < _iconTypeList.size())
_iconTypeList[pos] = isUserFavorite ? IconType::favorite : IconType::rom; _iconTypeList[pos] = getIconType(path);
} }
FileListWidget::IconType LauncherFileListWidget::romIconType(const FilesystemNode& file) const // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileListWidget::IconType LauncherFileListWidget::getIconType(const string& path) const
{ {
if(file.isFile() && Bankswitch::isValidRomName(file.getName())) if(!isUserFavorite(path))
return isUserFavorite(file.getPath()) ? IconType::favorite : IconType::rom; return FileListWidget::getIconType(path);
const FilesystemNode node(path);
if(node.isDirectory())
return BSPF::endsWithIgnoreCase(node.getName(), ".zip")
? IconType::favzip : IconType::favdir;
else else
return IconType::unknown; return IconType::favrom;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const FileListWidget::Icon* LauncherFileListWidget::getIcon(int i) const const FileListWidget::Icon* LauncherFileListWidget::getIcon(int i) const
{ {
static const Icon favorite_small = { static const Icon favrom_small = {
//0b0000001'11000000, //0b00000011'00000000,
//0b0000011'01100000, //0b00000111'10000000,
//0b0000010'00100000, //0b00000100'10000000,
//0b0000110'00110000, //0b00001100'11000000,
//0b0000100'00010000, //0b01111000'01111000,
//0b1111100'00011111, //0b11000000'00001100,
//0b1000000'00000001, //0b01100000'00011000,
//0b1100000'00000011, //0b00110000'00110000,
//0b0110000'00000110, //0b00011000'01100000,
//0b0011000'00001100, //0b00110000'00110000,
//0b0010000'00000100, //0b00100011'00010000,
//0b0110000'10000110, //0b01101111'11011000,
//0b0100011'01100010, //0b01111000'01111000,
//0b0101110'00111010, //0b00110000'00110000
//0b0111000'00001110,
0b0000001'10000000, 0b00000000'00001000,
0b0000011'11000000, 0b00001111'00011100,
0b0000010'01000000, 0b00001010'01111111,
0b0000110'01100000, 0b00001010'00111110,
0b0111100'00111100, 0b00001010'10011100,
0b1100000'00000110, 0b00001010'10110110,
0b0110000'00001100, 0b00001010'10100010,
0b0011000'00011000, 0b00011010'10000000,
0b0001100'00110000, 0b00110010'10011000,
0b0011000'00011000, 0b00100110'11001000,
0b0010001'10001000, 0b11101110'11101110,
0b0110111'11101100, 0b10001010'10100010,
0b0111100'00111100, 0b10011010'10110010,
0b0011000'00011000, 0b11110011'10011110
}; };
static const Icon favdir_small = { static const Icon favdir_small = {
//0b11111000'0000000, 0b00000000'00001000,
//0b11111100'0000000, 0b11111000'00011100,
//0b11111111'1111111, 0b11111100'01111111,
//0b10000000'0000001, 0b11111111'00111110,
//0b10000001'0000001, 0b10000000'00011100,
//0b10000011'1000001, 0b10000000'00110110,
//0b10001111'1110001, 0b10000000'00100010,
//0b10000111'1100001, 0b10000000'00000000,
//0b10000011'1000001, 0b10000000'00000010,
//0b10000111'1100001, 0b10000000'00000010,
//0b10001100'0110001, 0b10000000'00000010,
//0b10000000'0000001, 0b10000000'00000010,
//0b11111111'1111111 0b10000000'00000010,
0b11111111'11111110
0b11111000'0000000, };
0b11111100'0000000, static const Icon favzip_small = {
0b11111101'0111111, 0b00000000'00001000,
0b10000011'1000001, 0b11111000'00011100,
0b10000011'1000001, 0b11111100'01111111,
0b10000111'1100001, 0b11111111'00111110,
0b10111111'1111101, 0b10000000'00011100,
0b10011111'1111001, 0b10001111'10110110,
0b10001111'1110001, 0b10000000'00100010,
0b10000111'1100001, 0b10000001'10000000,
0b10001111'1110001, 0b10000011'10000010,
0b10011100'0111001, 0b10000111'00000010,
0b11011000'0011011 0b10001110'00000010,
0b10001111'11100010,
0b10000000'00000010,
0b11111111'11111110
};
static const Icon user_small = {
0b00000000'00000000,
0b11111000'00000000,
0b11111100'00000000,
0b11111001'00111110,
0b10000011'10000010,
0b10000011'10000010,
0b10000111'11000010,
0b10111111'11111010,
0b10011111'11110010,
0b10001111'11100010,
0b10000111'11000010,
0b10001111'11100010,
0b10011110'11110010,
0b11011000'00110110
}; };
static const Icon recent_small = { static const Icon recent_small = {
0b11111000'0000000, 0b00000000'00000000,
0b11111100'0000000, 0b11111000'00000000,
0b11111111'1111111, 0b11111100'00000000,
0b10000011'1000001, 0b11111111'11111110,
0b10001110'1110001, 0b10000011'10000010,
0b10001110'1110001, 0b10001110'11100010,
0b10011110'1111001, 0b10001110'11100010,
0b10011110'0111001, 0b10011110'11110010,
0b10011111'0011001, 0b10011110'01110010,
0b10001111'1110001, 0b10011111'00110010,
0b10001111'1110001, 0b10001111'11100010,
0b10000011'1000001, 0b10001111'11100010,
0b11111111'1111111 0b10000011'10000010,
0b11111111'11111110
}; };
static const Icon popular_small = { static const Icon popular_small = {
0b11111000'0000000, 0b00000000'00000000,
0b11111100'0000000, 0b11111000'00000000,
0b11111111'1111111, 0b11111100'00000000,
0b10000000'0000001, 0b11111111'11111110,
0b10001100'0110001, 0b10000000'00000010,
0b10011110'1111001, 0b10001100'01100010,
0b10011111'1111001, 0b10011110'11110010,
0b10011111'1111001, 0b10011111'11110010,
0b10001111'1110001, 0b10011111'11110010,
0b10000111'1100001, 0b10001111'11100010,
0b10000011'1000001, 0b10000111'11000010,
0b10000001'0000001, 0b10000011'10000010,
0b11111111'1111111 0b10000001'00000010,
0b11111111'11111110
}; };
static const Icon favorite_large = { static const Icon favrom_large = {
//0b0000000'0001000'0000000, //0b00000000000'00000000000,
//0b0000000'0011100'0000000, //0b00000000001'00000000000,
//0b0000000'0011100'0000000, //0b00000000011'10000000000,
//0b0000000'0110110'0000000, //0b00000000011'10000000000,
//0b0000000'0110110'0000000, //0b00000000111'11000000000,
//0b0000000'0110110'0000000, //0b00000000111'11000000000,
//0b0000000'1100011'0000000, //0b00000000110'11000000000,
//0b0111111'1000001'1111110, //0b00000001100'01100000000,
//0b1111111'0000000'1111111, //0b01111111100'01111111100,
//0b0110000'0000000'0000110, //0b11111111000'00111111110,
//0b0011000'0000000'0001100, //0b01110000000'00000011100,
//0b0001100'0000000'0011000, //0b00111000000'00000111000,
//0b0000110'0000000'0110000, //0b00011100000'00001110000,
//0b0000011'0000000'1100000, //0b00001110000'00011100000,
//0b0000111'0000000'1110000, //0b00000111000'00111000000,
//0b0000110'0001000'0110000, //0b00001110000'00011100000,
//0b0001100'0011100'0011000, //0b00001110011'10011100000,
//0b0001100'1110111'0011000, //0b00011100111'11001110000,
//0b0011001'1000001'1001100, //0b00011001110'11100110000,
//0b0011111'0000000'1111100, //0b00111111000'00111111000,
//0b0001100'0000000'0011000 //0b00111110000'00011111000,
//0b00011000000'00000110000
0b0000000'0001000'0000000,
0b0000000'0011100'0000000,
0b0000000'0011100'0000000,
0b0000000'0111110'0000000,
0b0000000'0111110'0000000,
0b0000000'0110110'0000000,
0b0000000'1100011'0000000,
0b0111111'1100011'1111110,
0b1111111'1000001'1111111,
0b0111000'0000000'0001110,
0b0011100'0000000'0011100,
0b0001110'0000000'0111000,
0b0000111'0000000'1110000,
0b0000011'1000001'1100000,
0b0000111'0000000'1110000,
0b0000111'0011100'1110000,
0b0001110'0111110'0111000,
0b0001100'1110111'0011000,
0b0011111'1000001'1111100,
0b0011111'0000000'1111100,
0b0001100'0000000'0011000
0b00000000000'00000100000,
0b00000011111'11101110000,
0b00000011111'11001110000,
0b00000011010'00011111000,
0b00000011010'11111111111,
0b00000011010'01111111110,
0b00000011010'00111111100,
0b00000011010'00011111000,
0b00000011010'00111111100,
0b00000111010'01111011110,
0b00000110010'01100000110,
0b00000110010'00001000000,
0b00001110010'10011100000,
0b00001100010'10001100000,
0b00011100110'11001110000,
0b00011000110'11000110000,
0b11111001110'11100111110,
0b11110011110'11110011110,
0b11000011110'11110000110,
0b11000111110'11111000110,
0b11111110111'11011111110,
0b11111100111'11001111110
}; };
static const Icon favdir_large = { static const Icon favdir_large = {
0b111111'10000000'0000000, 0b00000000000'00000100000,
0b111111'11000000'0000000, 0b11111110000'00001110000,
0b111111'11100000'0000000, 0b11111111000'00001110000,
0b111111'11111111'1111111, 0b11111111100'00011111000,
0b111111'11111111'1111111, 0b11111111110'11111111111,
0b110000'00001000'0000011, 0b11111111110'01111111110,
0b110000'00011100'0000011, 0b11000000000'00111111100,
0b110000'00011100'0000011, 0b11000000000'00011111000,
0b110000'00111110'0000011, 0b11000000000'00111111100,
0b110001'11111111'1100011, 0b11000000000'01111011110,
0b110011'11111111'1110011, 0b11000000000'01100000110,
0b110001'11111111'1100011, 0b11000000000'00000000000,
0b110000'11111111'1000011, 0b11000000000'00000000110,
0b110000'01111111'0000011, 0b11000000000'00000000110,
0b110000'11111111'1000011, 0b11000000000'00000000110,
0b110001'11110111'1100011, 0b11000000000'00000000110,
0b110001'11100011'1100011, 0b11000000000'00000000110,
0b110000'11000001'1000011, 0b11000000000'00000000110,
0b110000'00000000'0000011, 0b11000000000'00000000110,
0b111111'11111111'1111111, 0b11000000000'00000000110,
0b111111'11111111'1111111 0b11111111111'11111111110,
0b11111111111'11111111110
};
static const Icon favzip_large = {
0b00000000000'00000100000,
0b11111110000'00001110000,
0b11111111000'00001110000,
0b11111111100'00011111000,
0b11111111110'11111111111,
0b11111111110'01111111110,
0b11000000000'00111111100,
0b11000111111'10011111000,
0b11000111111'00111111100,
0b11000111111'01111011110,
0b11000000000'01100000110,
0b11000000001'00000000000,
0b11000000011'11000000110,
0b11000000111'10000000110,
0b11000001111'00000000110,
0b11000011110'00000000110,
0b11000111111'11111000110,
0b11000111111'11111000110,
0b11000111111'11111000110,
0b11000000000'00000000110,
0b11111111111'11111111110,
0b11111111111'11111111110
};
static const Icon user_large = {
0b00000000000'00000000000,
0b11111110000'00000000000,
0b11111111000'00000000000,
0b11111111100'00000000000,
0b11111111111'11111111110,
0b11111111111'11111111110,
0b11000000001'00000000110,
0b11000000011'10000000110,
0b11000000011'10000000110,
0b11000000111'11000000110,
0b11000111111'11111000110,
0b11001111111'11111100110,
0b11000111111'11111000110,
0b11000011111'11110000110,
0b11000001111'11100000110,
0b11000011111'11110000110,
0b11000111110'11111000110,
0b11000111100'01111000110,
0b11000011000'00110000110,
0b11000000000'00000000110,
0b11111111111'11111111110,
0b11111111111'11111111110
}; };
static const Icon recent_large = { static const Icon recent_large = {
0b111111'10000000'0000000, 0b00000000000'00000000000,
0b111111'11000000'0000000, 0b11111110000'00000000000,
0b111111'11100000'0000000, 0b11111111000'00000000000,
0b111111'11111111'1111111, 0b11111111100'00000000000,
0b111111'11111111'1111111, 0b11111111111'11111111110,
0b110000'00000000'0000011, 0b11111111111'11111111110,
0b110000'00111110'0000011, 0b11000000000'00000000110,
0b110000'11110111'1000011, 0b11000000111'11000000110,
0b110001'11110111'1100011, 0b11000011110'11110000110,
0b110001'11110111'1100011, 0b11000111110'11111000110,
0b110011'11110111'1110011, 0b11000111110'11111000110,
0b110011'11110111'1110011, 0b11001111110'11111100110,
0b110011'11110011'1110011, 0b11001111110'11111100110,
0b110011'11111001'1110011, 0b11001111110'01111100110,
0b110001'11111100'1100011, 0b11001111111'00111100110,
0b110001'11111111'1100011, 0b11000111111'10011000110,
0b110000'11111111'1000011, 0b11000111111'11111000110,
0b110000'00111110'0000011, 0b11000011111'11110000110,
0b110000'00000000'0000011, 0b11000000111'11000000110,
0b111111'11111111'1111111, 0b11000000000'00000000110,
0b111111'11111111'1111111 0b11111111111'11111111110,
0b11111111111'11111111110
}; };
static const Icon popular_large = { static const Icon popular_large = {
0b111111'10000000'0000000, 0b00000000000'00000000000,
0b111111'11000000'0000000, 0b11111110000'00000000000,
0b111111'11100000'0000000, 0b11111111000'00000000000,
0b111111'11111111'1111111, 0b11111111100'00000000000,
0b111111'11111111'1111111, 0b11111111111'11111111110,
0b110000'00000000'0000011, 0b11111111111'11111111110,
0b110000'00000000'0000011, 0b11000000000'00000000110,
0b110000'11100011'1000011, 0b11000000000'00000000110,
0b110001'11110111'1100011, 0b11000011100'01110000110,
0b110011'11111111'1110011, 0b11000111110'11111000110,
0b110011'11111111'1110011, 0b11001111111'11111100110,
0b110011'11111111'1110011, 0b11001111111'11111100110,
0b110001'11111111'1100011, 0b11001111111'11111100110,
0b110000'11111111'1000011, 0b11000111111'11111000110,
0b110000'01111111'0000011, 0b11000011111'11110000110,
0b110000'00111110'0000011, 0b11000001111'11100000110,
0b110000'00011100'0000011, 0b11000000111'11000000110,
0b110000'00001000'0000011, 0b11000000011'10000000110,
0b110000'00000000'0000011, 0b11000000001'00000000110,
0b111111'11111111'1111111, 0b11000000000'00000000110,
0b111111'11111111'1111111 0b11111111111'11111111110,
0b11111111111'11111111110
}; };
static const Icon* small_icons[int(IconType::numLauncherTypes)] = { static const Icon* small_icons[int(IconType::numLauncherTypes)] = {
&favorite_small, &favdir_small, &recent_small, &popular_small &favrom_small, &favdir_small, &favzip_small, &user_small, &recent_small, &popular_small
}; };
static const Icon* large_icons[int(IconType::numLauncherTypes)] = { static const Icon* large_icons[int(IconType::numLauncherTypes)] = {
&favorite_large, &favdir_large, &recent_large, &popular_large &favrom_large, &favdir_large, &favzip_large, &user_large, &recent_large, &popular_large
}; };
if(int(_iconTypeList[i]) < int(IconType::numTypes)) if(int(_iconTypeList[i]) < int(IconType::numTypes))

View File

@ -39,6 +39,9 @@ class LauncherFileListWidget : public FileListWidget
int x, int y, int w, int h); int x, int y, int w, int h);
~LauncherFileListWidget() override = default; ~LauncherFileListWidget() override = default;
/** Descend into currently selected directory */
void selectDirectory() override;
void loadFavorites(); void loadFavorites();
void saveFavorites(); void saveFavorites();
void updateFavorites(); void updateFavorites();
@ -64,10 +67,10 @@ class LauncherFileListWidget : public FileListWidget
private: private:
void getChildren(const FilesystemNode::CancelCheck& isCancelled) override; void getChildren(const FilesystemNode::CancelCheck& isCancelled) override;
void userFavor(const string& path, bool enable = true); void userFavor(const string& path);
void addFolder(StringList& list, int& offset, const string& name, IconType icon); void addFolder(StringList& list, int& offset, const string& name, IconType icon);
void extendLists(StringList& list) override; void extendLists(StringList& list) override;
IconType romIconType(const FilesystemNode& file) const override; IconType getIconType(const string& path) const override;
const Icon* getIcon(int i) const override; const Icon* getIcon(int i) const override;
bool fullPathToolTip() const override { return myInVirtualDir; } bool fullPathToolTip() const override { return myInVirtualDir; }
}; };