1
0
mirror of git://projects.qi-hardware.com/gmenu2x.git synced 2024-11-25 15:56:15 +02:00

Deal gracefully with the selector being started on a non-existent dir

If directory browsing is enabled, fall back to the closest existing
parent directory. If directory browsing is disabled, show empty list.
This commit is contained in:
Maarten ter Huurne 2014-08-17 10:05:21 +02:00
parent 9e22b0328f
commit 0b0e278459
6 changed files with 40 additions and 11 deletions

View File

@ -63,7 +63,7 @@ static void moveNames(set<string, case_less>&& from, vector<string>& to)
to.shrink_to_fit(); to.shrink_to_fit();
} }
void FileLister::browse(const string& path, bool clean) bool FileLister::browse(const string& path, bool clean)
{ {
if (clean) { if (clean) {
directories.clear(); directories.clear();
@ -79,7 +79,7 @@ void FileLister::browse(const string& path, bool clean)
if (errno != ENOENT) { if (errno != ENOENT) {
ERROR("Unable to open directory: %s\n", slashedPath.c_str()); ERROR("Unable to open directory: %s\n", slashedPath.c_str());
} }
return; return false;
} }
set<string, case_less> directorySet; set<string, case_less> directorySet;
@ -157,6 +157,8 @@ void FileLister::browse(const string& path, bool clean)
files.clear(); files.clear();
moveNames(move(fileSet), files); moveNames(move(fileSet), files);
} }
return true;
} }
string FileLister::operator[](uint x) string FileLister::operator[](uint x)

View File

@ -33,7 +33,14 @@ private:
public: public:
FileLister(); FileLister();
void browse(const std::string& path, bool clean = true);
/**
* Scans the given directory.
* @param clean If true, start a new result set, if false add to the
* results from the previous scan.
* @return True iff the given directory could be opened.
*/
bool browse(const std::string& path, bool clean = true);
unsigned int size() { return files.size() + directories.size(); } unsigned int size() { return files.size() + directories.size(); }
unsigned int dirCount() { return directories.size(); } unsigned int dirCount() { return directories.size(); }

View File

@ -53,7 +53,10 @@ int Selector::exec(int startSelection) {
FileLister fl; FileLister fl;
fl.setShowDirectories(showDirectories); fl.setShowDirectories(showDirectories);
fl.setFilter(link.getSelectorFilter()); fl.setFilter(link.getSelectorFilter());
prepare(fl); while (!prepare(fl) && showDirectories && dir != "/") {
// The given directory could not be opened; try parent.
dir = parentDir(dir);
}
OffscreenSurface bg(*gmenu2x->bg); OffscreenSurface bg(*gmenu2x->bg);
drawTitleIcon(bg, link.getIconPath(), true); drawTitleIcon(bg, link.getIconPath(), true);
@ -185,15 +188,15 @@ int Selector::exec(int startSelection) {
result = false; result = false;
break; break;
} }
// ...fall through...
case InputManager::LEFT: case InputManager::LEFT:
if (showDirectories) { if (showDirectories) {
string::size_type p = dir.rfind("/", dir.size()-2); string oldDir = dir;
if (p==string::npos || dir.length() < 2 || dir[0] != '/') { dir = parentDir(dir);
if (dir == "/" && oldDir == "/") {
close = true; close = true;
result = false; result = false;
} else { } else {
dir = dir.substr(0,p+1);
selected = 0; selected = 0;
firstElement = 0; firstElement = 0;
prepare(fl); prepare(fl);
@ -227,12 +230,14 @@ int Selector::exec(int startSelection) {
return result ? (int)selected : -1; return result ? (int)selected : -1;
} }
void Selector::prepare(FileLister& fl) { bool Selector::prepare(FileLister& fl) {
fl.browse(dir); bool opened = fl.browse(dir);
screendir = dir; screendir = dir;
if (!screendir.empty() && screendir[screendir.length() - 1] != '/') { if (!screendir.empty() && screendir[screendir.length() - 1] != '/') {
screendir += "/"; screendir += "/";
} }
screendir += "previews/"; screendir += "previews/";
return opened;
} }

View File

@ -35,7 +35,7 @@ private:
LinkApp& link; LinkApp& link;
std::string file, dir, screendir; std::string file, dir, screendir;
void prepare(FileLister& fl); bool prepare(FileLister& fl);
public: public:
Selector(GMenu2X *gmenu2x, LinkApp& link, Selector(GMenu2X *gmenu2x, LinkApp& link,

View File

@ -81,6 +81,13 @@ string readFileAsString(const char *filename) {
} }
} }
string parentDir(string const& dir) {
// Note that size() is unsigned, so for short strings the '- 2' wraps
// around and as a result the entire string is searched, which is fine.
auto p = dir.rfind('/', dir.size() - 2);
return p == string::npos ? "/" : dir.substr(0, p + 1);
}
bool fileExists(const string &file) { bool fileExists(const string &file) {
fstream fin; fstream fin;
fin.open(file.c_str() ,ios::in); fin.open(file.c_str() ,ios::in);

View File

@ -52,6 +52,14 @@ std::string readFileAsString(const char *filename);
std::string strreplace(std::string orig, const std::string &search, const std::string &replace); std::string strreplace(std::string orig, const std::string &search, const std::string &replace);
std::string cmdclean(std::string cmdline); std::string cmdclean(std::string cmdline);
/**
* Returns the parent directory of the given directory path, or "/" if there is
* no parent.
* This function does not check the file system: it is only string manipulation.
* @return The parent directory path, including a trailing '/'.
*/
std::string parentDir(std::string const& dir);
inline std::string trimExtension(std::string const& filename) { inline std::string trimExtension(std::string const& filename) {
return filename.substr(0, filename.rfind('.')); return filename.substr(0, filename.rfind('.'));
} }