POSIX: Set the default screenshots path to the XDG Pictures directory

This commit is contained in:
Bastien Bouclet 2018-11-16 18:56:22 +01:00
parent e6dbdb880f
commit add9a0b49a
3 changed files with 101 additions and 0 deletions

2
README
View File

@ -2896,6 +2896,8 @@ The default location, when no screenshot path is defined in the config file,
depends on the OS:
Windows: In Users\username\My Pictures\ScummVM Screenshots.
macOS X: On the Desktop.
Other unices: In the XDG Pictures user directory,
e.g. ~/Pictures/ScummVM Screenshots.
Any other OS: In the current directory.

View File

@ -156,6 +156,101 @@ Common::String OSystem_POSIX::getDefaultConfigFileName() {
return configFile;
}
Common::String OSystem_POSIX::getXdgUserDir(const char *name) {
// The xdg-user-dirs configuration path is stored in the XDG config
// home directory. We start by retrieving this value.
Common::String configHome = getenv("XDG_CONFIG_HOME");
if (configHome.empty()) {
const char *home = getenv("HOME");
if (!home) {
return "";
}
configHome = Common::String::format("%s/.config", home);
}
// Find the requested directory line in the xdg-user-dirs configuration file
// Example line value: XDG_PICTURES_DIR="$HOME/Pictures"
Common::FSNode userDirsFile(configHome + "/user-dirs.dirs");
if (!userDirsFile.exists() || !userDirsFile.isReadable() || userDirsFile.isDirectory()) {
return "";
}
Common::SeekableReadStream *userDirsStream = userDirsFile.createReadStream();
if (!userDirsStream) {
return "";
}
Common::String dirLinePrefix = Common::String::format("XDG_%s_DIR=", name);
Common::String directoryValue;
while (!userDirsStream->eos() && !userDirsStream->err()) {
Common::String userDirsLine = userDirsStream->readLine();
userDirsLine.trim();
if (userDirsLine.hasPrefix(dirLinePrefix)) {
directoryValue = Common::String(userDirsLine.c_str() + dirLinePrefix.size());
break;
}
}
delete userDirsStream;
// Extract the path from the value
// Example value: "$HOME/Pictures"
if (directoryValue.empty() || directoryValue[0] != '"') {
return "";
}
if (directoryValue[directoryValue.size() - 1] != '"') {
return "";
}
// According to the spec the value is shell-escaped, and would need to be
// unescaped to be used, but neither the GTK+ nor the Qt implementation seem to
// properly perform that step, it's probably fine if we don't do it either.
Common::String directoryPath(directoryValue.c_str() + 1, directoryValue.size() - 2);
if (directoryPath.hasPrefix("$HOME/")) {
const char *home = getenv("HOME");
directoryPath = Common::String::format("%s%s", home, directoryPath.c_str() + 5);
}
// At this point, the path must be absolute
if (directoryPath.empty() || directoryPath[0] != '/') {
return "";
}
return directoryPath;
}
Common::String OSystem_POSIX::getScreenshotsPath() {
// If the user has configured a screenshots path, use it
const Common::String path = OSystem_SDL::getScreenshotsPath();
if (!path.empty()) {
return path;
}
// Otherwise, the default screenshots path is the "ScummVM Screenshots"
// directory in the XDG "Pictures" user directory, as defined in the
// xdg-user-dirs spec: https://www.freedesktop.org/wiki/Software/xdg-user-dirs/
Common::String picturesPath = getXdgUserDir("PICTURES");
if (picturesPath.empty()) {
return "";
}
if (!picturesPath.hasSuffix("/")) {
picturesPath += "/";
}
static const char *SCREENSHOTS_DIR_NAME = "ScummVM Screenshots";
if (!Posix::assureDirectoryExists(SCREENSHOTS_DIR_NAME, picturesPath.c_str())) {
return "";
}
return picturesPath + SCREENSHOTS_DIR_NAME + "/";
}
void OSystem_POSIX::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
#ifdef DATA_PATH
const char *snap = getenv("SNAP");

View File

@ -42,6 +42,8 @@ public:
virtual void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0);
Common::String getScreenshotsPath() override;
protected:
/**
* Base string for creating the default path and filename for the
@ -64,6 +66,8 @@ protected:
virtual Common::WriteStream *createLogFile();
Common::String getXdgUserDir(const char *name);
virtual AudioCDManager *createAudioCDManager();
bool launchBrowser(const Common::String& client, const Common::String &url);