mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2025-01-29 19:55:37 +00:00
Improved handling and sorting of folders.
This commit is contained in:
parent
2b82770e43
commit
e56fdf3df6
|
@ -151,6 +151,17 @@ const std::vector<FileData*> FileData::getChildrenRecursive() const
|
||||||
return childrenRecursive;
|
return childrenRecursive;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FileData::viewHasOnlyFolders()
|
||||||
|
{
|
||||||
|
bool onlyFolders = true;
|
||||||
|
std::vector<FileData*> entrySiblings = this->getParent()->getChildren();
|
||||||
|
for (auto it = entrySiblings.cbegin(); it != entrySiblings.cend(); it++) {
|
||||||
|
if ((*it)->getType() != FOLDER)
|
||||||
|
onlyFolders = false;
|
||||||
|
}
|
||||||
|
return onlyFolders;
|
||||||
|
}
|
||||||
|
|
||||||
const std::string FileData::getROMDirectory()
|
const std::string FileData::getROMDirectory()
|
||||||
{
|
{
|
||||||
std::string romDirSetting = Settings::getInstance()->getString("ROMDirectory");
|
std::string romDirSetting = Settings::getInstance()->getString("ROMDirectory");
|
||||||
|
@ -463,6 +474,13 @@ void FileData::sort(ComparisonFunction& comparator, bool ascending)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If descending sorting is requested, always perform a ascending sort by filename first.
|
||||||
|
// This adds a slight (probably negligible) overhead but it will avoid strange sorting
|
||||||
|
// issues where the secondary sorting is reversed for some sort types.
|
||||||
|
if (!ascending)
|
||||||
|
std::stable_sort(mChildrenOthers.begin(), mChildrenOthers.end(),
|
||||||
|
getSortTypeFromString("filename, ascending").comparisonFunction);
|
||||||
|
|
||||||
if (foldersOnTop && mOnlyFolders)
|
if (foldersOnTop && mOnlyFolders)
|
||||||
std::stable_sort(mChildrenFolders.begin(), mChildrenFolders.end(), comparator);
|
std::stable_sort(mChildrenFolders.begin(), mChildrenFolders.end(), comparator);
|
||||||
std::stable_sort(mChildrenOthers.begin(), mChildrenOthers.end(), comparator);
|
std::stable_sort(mChildrenOthers.begin(), mChildrenOthers.end(), comparator);
|
||||||
|
@ -479,6 +497,10 @@ void FileData::sort(ComparisonFunction& comparator, bool ascending)
|
||||||
mChildren.insert(mChildren.end(), mChildrenOthers.begin(), mChildrenOthers.end());
|
mChildren.insert(mChildren.end(), mChildrenOthers.begin(), mChildrenOthers.end());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
if (!ascending)
|
||||||
|
std::stable_sort(mChildren.begin(), mChildren.end(),
|
||||||
|
getSortTypeFromString("filename, ascending").comparisonFunction);
|
||||||
|
|
||||||
std::stable_sort(mChildren.begin(), mChildren.end(), comparator);
|
std::stable_sort(mChildren.begin(), mChildren.end(), comparator);
|
||||||
if (!ascending)
|
if (!ascending)
|
||||||
std::reverse(mChildren.begin(), mChildren.end());
|
std::reverse(mChildren.begin(), mChildren.end());
|
||||||
|
@ -523,6 +545,7 @@ void FileData::sortFavoritesOnTop(ComparisonFunction& comparator, bool ascending
|
||||||
mFirstLetterIndex.clear();
|
mFirstLetterIndex.clear();
|
||||||
mOnlyFolders = true;
|
mOnlyFolders = true;
|
||||||
std::vector<FileData*> mChildrenFolders;
|
std::vector<FileData*> mChildrenFolders;
|
||||||
|
std::vector<FileData*> mChildrenFavoritesFolders;
|
||||||
std::vector<FileData*> mChildrenFavorites;
|
std::vector<FileData*> mChildrenFavorites;
|
||||||
std::vector<FileData*> mChildrenOthers;
|
std::vector<FileData*> mChildrenOthers;
|
||||||
bool showHiddenGames = Settings::getInstance()->getBool("ShowHiddenGames");
|
bool showHiddenGames = Settings::getInstance()->getBool("ShowHiddenGames");
|
||||||
|
@ -538,7 +561,11 @@ void FileData::sortFavoritesOnTop(ComparisonFunction& comparator, bool ascending
|
||||||
}
|
}
|
||||||
|
|
||||||
if (foldersOnTop && mChildren[i]->getType() == FOLDER) {
|
if (foldersOnTop && mChildren[i]->getType() == FOLDER) {
|
||||||
mChildrenFolders.push_back(mChildren[i]);
|
if (!mChildren[i]->getFavorite())
|
||||||
|
mChildrenFolders.push_back(mChildren[i]);
|
||||||
|
else
|
||||||
|
mChildrenFavoritesFolders.push_back(mChildren[i]);
|
||||||
|
|
||||||
hasFolders = true;
|
hasFolders = true;
|
||||||
}
|
}
|
||||||
else if (mChildren[i]->getFavorite()) {
|
else if (mChildren[i]->getFavorite()) {
|
||||||
|
@ -555,6 +582,19 @@ void FileData::sortFavoritesOnTop(ComparisonFunction& comparator, bool ascending
|
||||||
mOnlyFolders = false;
|
mOnlyFolders = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If there are favorite folders and this is a mixed list, then don't handle these
|
||||||
|
// separately but instead merge them into the same vector. This is a quite wasteful
|
||||||
|
// approach but the scenario where a user has a mixed folder and files list and marks
|
||||||
|
// some folders as favorites is probably a rare situation.
|
||||||
|
if (!mOnlyFolders && mChildrenFavoritesFolders.size() > 0) {
|
||||||
|
mChildrenFolders.insert(mChildrenFolders.end(), mChildrenFavoritesFolders.begin(),
|
||||||
|
mChildrenFavoritesFolders.end());
|
||||||
|
mChildrenFavoritesFolders.erase(mChildrenFavoritesFolders.begin(),
|
||||||
|
mChildrenFavoritesFolders.end());
|
||||||
|
std::stable_sort(mChildrenFolders.begin(), mChildrenFolders.end(),
|
||||||
|
getSortTypeFromString("filename, ascending").comparisonFunction);
|
||||||
|
}
|
||||||
|
|
||||||
// If there are only favorites in the gamelist, it makes sense to still generate
|
// If there are only favorites in the gamelist, it makes sense to still generate
|
||||||
// a letter index. For instance to be able to quick jump in the 'favorites'
|
// a letter index. For instance to be able to quick jump in the 'favorites'
|
||||||
// collection. Doing this additional work here only for the applicable gamelists is
|
// collection. Doing this additional work here only for the applicable gamelists is
|
||||||
|
@ -584,49 +624,70 @@ void FileData::sortFavoritesOnTop(ComparisonFunction& comparator, bool ascending
|
||||||
auto last = std::unique(mFirstLetterIndex.begin(), mFirstLetterIndex.end());
|
auto last = std::unique(mFirstLetterIndex.begin(), mFirstLetterIndex.end());
|
||||||
mFirstLetterIndex.erase(last, mFirstLetterIndex.end());
|
mFirstLetterIndex.erase(last, mFirstLetterIndex.end());
|
||||||
|
|
||||||
|
// If there were at least one favorite folder in the gamelist, insert the favorite
|
||||||
|
// unicode character in the first position.
|
||||||
|
if (foldersOnTop && mOnlyFolders && mChildrenFavoritesFolders.size() > 0)
|
||||||
|
mFirstLetterIndex.insert(mFirstLetterIndex.begin(), FAVORITE_CHAR);
|
||||||
// If there were at least one favorite in the gamelist, insert the favorite
|
// If there were at least one favorite in the gamelist, insert the favorite
|
||||||
// unicode character in the first position.
|
// unicode character in the first position.
|
||||||
if (mChildrenOthers.size() > 0 && mChildrenFavorites.size() > 0)
|
else if (mChildrenOthers.size() > 0 && mChildrenFavorites.size() > 0)
|
||||||
mFirstLetterIndex.insert(mFirstLetterIndex.begin(), FAVORITE_CHAR);
|
mFirstLetterIndex.insert(mFirstLetterIndex.begin(), FAVORITE_CHAR);
|
||||||
|
|
||||||
// If it's a mixed list and folders are sorted on top, add a folder icon to the index.
|
// If it's a mixed list and folders are sorted on top, add a folder icon to the index.
|
||||||
if (foldersOnTop && hasFolders && !mOnlyFolders)
|
if (foldersOnTop && hasFolders && !mOnlyFolders)
|
||||||
mFirstLetterIndex.insert(mFirstLetterIndex.begin(), FOLDER_CHAR);
|
mFirstLetterIndex.insert(mFirstLetterIndex.begin(), FOLDER_CHAR);
|
||||||
|
|
||||||
|
// If descending sorting is requested, always perform a ascending sort by filename first.
|
||||||
|
// This adds a slight (probably negligible) overhead but it will avoid strange sorting
|
||||||
|
// issues where the secondary sorting is reversed for some sort types.
|
||||||
|
if (!ascending) {
|
||||||
|
std::stable_sort(mChildrenFolders.begin(), mChildrenFolders.end(),
|
||||||
|
getSortTypeFromString("filename, ascending").comparisonFunction);
|
||||||
|
std::stable_sort(mChildrenFavoritesFolders.begin(), mChildrenFavoritesFolders.end(),
|
||||||
|
getSortTypeFromString("filename, ascending").comparisonFunction);
|
||||||
|
std::stable_sort(mChildrenFavorites.begin(), mChildrenFavorites.end(),
|
||||||
|
getSortTypeFromString("filename, ascending").comparisonFunction);
|
||||||
|
std::stable_sort(mChildrenOthers.begin(), mChildrenOthers.end(),
|
||||||
|
getSortTypeFromString("filename, ascending").comparisonFunction);
|
||||||
|
}
|
||||||
|
|
||||||
// Sort favorite games and the other games separately.
|
// Sort favorite games and the other games separately.
|
||||||
if (foldersOnTop && mOnlyFolders)
|
if (foldersOnTop && mOnlyFolders) {
|
||||||
|
std::stable_sort(mChildrenFavoritesFolders.begin(),
|
||||||
|
mChildrenFavoritesFolders.end(), comparator);
|
||||||
std::stable_sort(mChildrenFolders.begin(), mChildrenFolders.end(), comparator);
|
std::stable_sort(mChildrenFolders.begin(), mChildrenFolders.end(), comparator);
|
||||||
|
}
|
||||||
std::stable_sort(mChildrenFavorites.begin(), mChildrenFavorites.end(), comparator);
|
std::stable_sort(mChildrenFavorites.begin(), mChildrenFavorites.end(), comparator);
|
||||||
std::stable_sort(mChildrenOthers.begin(), mChildrenOthers.end(), comparator);
|
std::stable_sort(mChildrenOthers.begin(), mChildrenOthers.end(), comparator);
|
||||||
|
|
||||||
|
// Iterate through any child favorite folders.
|
||||||
|
for (auto it = mChildrenFavoritesFolders.cbegin(); it !=
|
||||||
|
mChildrenFavoritesFolders.cend(); it++) {
|
||||||
|
if ((*it)->getChildren().size() > 0)
|
||||||
|
(*it)->sortFavoritesOnTop(comparator, ascending);
|
||||||
|
}
|
||||||
|
|
||||||
// Iterate through any child folders.
|
// Iterate through any child folders.
|
||||||
for (auto it = mChildrenFolders.cbegin(); it != mChildrenFolders.cend(); it++) {
|
for (auto it = mChildrenFolders.cbegin(); it != mChildrenFolders.cend(); it++) {
|
||||||
if ((*it)->getChildren().size() > 0)
|
if ((*it)->getChildren().size() > 0)
|
||||||
(*it)->sortFavoritesOnTop(comparator, ascending);
|
(*it)->sortFavoritesOnTop(comparator, ascending);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate through any child folders.
|
|
||||||
for (auto it = mChildrenFavorites.cbegin(); it != mChildrenFavorites.cend(); it++) {
|
|
||||||
if ((*it)->getChildren().size() > 0)
|
|
||||||
(*it)->sortFavoritesOnTop(comparator, ascending);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iterate through any child folders.
|
|
||||||
for (auto it = mChildrenOthers.cbegin(); it != mChildrenOthers.cend(); it++) {
|
|
||||||
if ((*it)->getChildren().size() > 0)
|
|
||||||
(*it)->sortFavoritesOnTop(comparator, ascending);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ascending) {
|
if (!ascending) {
|
||||||
if (foldersOnTop && mOnlyFolders)
|
if (foldersOnTop && mOnlyFolders) {
|
||||||
|
std::reverse(mChildrenFavoritesFolders.begin(), mChildrenFavoritesFolders.end());
|
||||||
std::reverse(mChildrenFolders.begin(), mChildrenFolders.end());
|
std::reverse(mChildrenFolders.begin(), mChildrenFolders.end());
|
||||||
|
}
|
||||||
std::reverse(mChildrenFavorites.begin(), mChildrenFavorites.end());
|
std::reverse(mChildrenFavorites.begin(), mChildrenFavorites.end());
|
||||||
std::reverse(mChildrenOthers.begin(), mChildrenOthers.end());
|
std::reverse(mChildrenOthers.begin(), mChildrenOthers.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Combine the individually sorted favorite games and other games vectors.
|
// Combine the individually sorted favorite games and other games vectors.
|
||||||
mChildren.erase(mChildren.begin(), mChildren.end());
|
mChildren.erase(mChildren.begin(), mChildren.end());
|
||||||
mChildren.reserve(mChildrenFolders.size() + mChildrenFavorites.size() + mChildrenOthers.size());
|
mChildren.reserve(mChildrenFavoritesFolders.size() + mChildrenFolders.size() +
|
||||||
|
mChildrenFavorites.size() + mChildrenOthers.size());
|
||||||
|
mChildren.insert(mChildren.end(), mChildrenFavoritesFolders.begin(),
|
||||||
|
mChildrenFavoritesFolders.end());
|
||||||
mChildren.insert(mChildren.end(), mChildrenFolders.begin(), mChildrenFolders.end());
|
mChildren.insert(mChildren.end(), mChildrenFolders.begin(), mChildrenFolders.end());
|
||||||
mChildren.insert(mChildren.end(), mChildrenFavorites.begin(), mChildrenFavorites.end());
|
mChildren.insert(mChildren.end(), mChildrenFavorites.begin(), mChildrenFavorites.end());
|
||||||
mChildren.insert(mChildren.end(), mChildrenOthers.begin(), mChildrenOthers.end());
|
mChildren.insert(mChildren.end(), mChildrenOthers.begin(), mChildrenOthers.end());
|
||||||
|
|
|
@ -64,6 +64,7 @@ public:
|
||||||
const std::vector<std::string>& getFirstLetterIndex() const
|
const std::vector<std::string>& getFirstLetterIndex() const
|
||||||
{ return mFirstLetterIndex; };
|
{ return mFirstLetterIndex; };
|
||||||
const bool getOnlyFoldersFlag() { return mOnlyFolders; }
|
const bool getOnlyFoldersFlag() { return mOnlyFolders; }
|
||||||
|
bool viewHasOnlyFolders();
|
||||||
static const std::string getROMDirectory();
|
static const std::string getROMDirectory();
|
||||||
static const std::string getMediaDirectory();
|
static const std::string getMediaDirectory();
|
||||||
const std::string getMediafilePath(std::string subdirectory, std::string mediatype) const;
|
const std::string getMediafilePath(std::string subdirectory, std::string mediatype) const;
|
||||||
|
|
|
@ -339,7 +339,7 @@ void GuiGamelistOptions::jumpToLetter()
|
||||||
if (mFavoritesSorting && mFirstLetterIndex.front() == FAVORITE_CHAR) {
|
if (mFavoritesSorting && mFirstLetterIndex.front() == FAVORITE_CHAR) {
|
||||||
if ((char)toupper(files.at(i)->getSortName().front()) ==
|
if ((char)toupper(files.at(i)->getSortName().front()) ==
|
||||||
letter && !files.at(i)->getFavorite()) {
|
letter && !files.at(i)->getFavorite()) {
|
||||||
if (mFoldersOnTop && files.at(i)->getType() == FOLDER) {
|
if (!mOnlyHasFolders && mFoldersOnTop && files.at(i)->getType() == FOLDER) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -368,9 +368,13 @@ void GuiGamelistOptions::jumpToFirstRow()
|
||||||
// Get the gamelist.
|
// Get the gamelist.
|
||||||
const std::vector<FileData*>& files = getGamelist()->getCursor()->
|
const std::vector<FileData*>& files = getGamelist()->getCursor()->
|
||||||
getParent()->getChildrenListToDisplay();
|
getParent()->getChildrenListToDisplay();
|
||||||
// Select the first game that is not a folder.
|
// Select the first game that is not a folder, unless it's a folder-only list in
|
||||||
|
// which case the first line overall is selected.
|
||||||
for (auto it = files.cbegin(); it != files.cend(); it++) {
|
for (auto it = files.cbegin(); it != files.cend(); it++) {
|
||||||
if ((*it)->getType() == GAME) {
|
if (!mOnlyHasFolders && mFoldersOnTop && (*it)->getType() == FOLDER) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else {
|
||||||
getGamelist()->setCursor(*it);
|
getGamelist()->setCursor(*it);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -189,6 +189,11 @@ bool ISimpleGameListView::input(InputConfig* config, Input input)
|
||||||
bool favoritesSorting;
|
bool favoritesSorting;
|
||||||
bool removedLastFavorite = false;
|
bool removedLastFavorite = false;
|
||||||
bool foldersOnTop = Settings::getInstance()->getBool("FoldersOnTop");
|
bool foldersOnTop = Settings::getInstance()->getBool("FoldersOnTop");
|
||||||
|
// If the current list only contains folders, then treat it as if the folders
|
||||||
|
// are not sorted on top, this way the logic should work exactly as for mixed
|
||||||
|
// lists or files-only lists.
|
||||||
|
if (getCursor()->getType() == FOLDER && foldersOnTop == true)
|
||||||
|
foldersOnTop = !getCursor()->viewHasOnlyFolders();
|
||||||
|
|
||||||
if (CollectionSystemManager::get()->getIsCustomCollection(mRoot->getSystem()))
|
if (CollectionSystemManager::get()->getIsCustomCollection(mRoot->getSystem()))
|
||||||
favoritesSorting = Settings::getInstance()->getBool("FavFirstCustom");
|
favoritesSorting = Settings::getInstance()->getBool("FavFirstCustom");
|
||||||
|
@ -208,6 +213,11 @@ bool ISimpleGameListView::input(InputConfig* config, Input input)
|
||||||
// If we are on the favorite marking boundary, select the next entry.
|
// If we are on the favorite marking boundary, select the next entry.
|
||||||
else if (getCursor()->getFavorite() != getPreviousEntry()->getFavorite())
|
else if (getCursor()->getFavorite() != getPreviousEntry()->getFavorite())
|
||||||
entryToSelect = getNextEntry();
|
entryToSelect = getNextEntry();
|
||||||
|
// If we mark the second entry as favorite and the first entry is not a
|
||||||
|
// favorite, then select this entry if they are of the same type.
|
||||||
|
else if (getPreviousEntry() == getFirstEntry() &&
|
||||||
|
getCursor()->getType() == getPreviousEntry()->getType())
|
||||||
|
entryToSelect = getPreviousEntry();
|
||||||
// For all other scenarios try to select the next entry, and if it doesn't
|
// For all other scenarios try to select the next entry, and if it doesn't
|
||||||
// exist, select the previous entry.
|
// exist, select the previous entry.
|
||||||
else
|
else
|
||||||
|
@ -271,9 +281,9 @@ bool ISimpleGameListView::input(InputConfig* config, Input input)
|
||||||
mWindow->setInfoPopup(s);
|
mWindow->setInfoPopup(s);
|
||||||
entryToUpdate->getSourceFileData()->getSystem()->onMetaDataSavePoint();
|
entryToUpdate->getSourceFileData()->getSystem()->onMetaDataSavePoint();
|
||||||
|
|
||||||
if (!Settings::getInstance()->getBool("FoldersOnTop"))
|
getCursor()->getParent()->sort(
|
||||||
mRoot->sort(mRoot->getSortTypeFromString(mRoot->getSortTypeString()),
|
mRoot->getSortTypeFromString(mRoot->getSortTypeString()),
|
||||||
Settings::getInstance()->getBool("FavoritesFirst"));
|
Settings::getInstance()->getBool("FavoritesFirst"));
|
||||||
|
|
||||||
ViewController::get()->onFileChanged(getCursor(), FILE_METADATA_CHANGED);
|
ViewController::get()->onFileChanged(getCursor(), FILE_METADATA_CHANGED);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue