Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2020-02-26 10:07:05 +0300
committerCampbell Barton <ideasman42@gmail.com>2020-02-26 10:14:34 +0300
commit48816d462eedc254d439608431fde78d74f2f518 (patch)
tree2b3d019714e5996a8647ceb58bfb5db591376046 /source/blender/editors
parent5f83495e4c21d8c2297e9f15ac1a81657a992855 (diff)
UI: Linux platform support for 'user-dirs.dirs'
Originally D6826 by @a.monti with parsing rewritten.
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/space_file/fsmenu.c190
1 files changed, 130 insertions, 60 deletions
diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c
index eaabd907f23..80ea0c190e2 100644
--- a/source/blender/editors/space_file/fsmenu.c
+++ b/source/blender/editors/space_file/fsmenu.c
@@ -30,6 +30,7 @@
#include "BLI_utildefines.h"
#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
#include "BLT_translation.h"
@@ -102,6 +103,111 @@ struct FSMenuEntry *ED_fsmenu_get_category(struct FSMenu *fsmenu, FSMenuCategory
return fsm_head;
}
+/* -------------------------------------------------------------------- */
+/** \name XDG User Directory Support (Unix)
+ *
+ * Generic Unix, Use XDG when available, otherwise fallback to the home directory.
+ * \{ */
+
+/**
+ * Look for `user-dirs.dirs`, where localized or custom user folders are defined,
+ * and store their paths in a GHash.
+ */
+static GHash *fsmenu_xdg_user_dirs_parse(const char *home)
+{
+ size_t data_len;
+ char *data;
+
+ /* Check if the config file exists. */
+ {
+ char filepath[FILE_MAX];
+ const char *xdg_config_home = getenv("XDG_CONFIG_HOME");
+ if (xdg_config_home != NULL) {
+ BLI_path_join(filepath, sizeof(filepath), xdg_config_home, "user-dirs.dirs", NULL);
+ }
+ else {
+ BLI_path_join(filepath, sizeof(filepath), home, ".config", "user-dirs.dirs", NULL);
+ }
+ data = BLI_file_read_text_as_mem_with_newline_as_nil(filepath, true, 1, &data_len);
+ if (data == NULL) {
+ return NULL;
+ }
+ }
+ /* By default there are 8 paths. */
+ GHash *xdg_map = BLI_ghash_str_new_ex(__func__, 8);
+ char *data_end = data + data_len;
+ uint l_len;
+ for (char *l = data; l != data_end; l += l_len + 1) {
+ l_len = strlen(l);
+
+ /* Avoid inserting invalid values. */
+ if (STRPREFIX(l, "XDG_")) {
+ char *l_value = strchr(l, '=');
+ if (l_value != NULL) {
+ *l_value = '\0';
+ l_value++;
+ if (*l_value == '"' && l[l_len - 1] == '"') {
+ l_value++;
+ l[l_len - 1] = '\0';
+
+ char l_value_expanded[FILE_MAX];
+ char *l_value_final = l_value;
+
+ /* This is currently the only variable used.
+ * Based on the 'user-dirs.dirs' man page,
+ * there is no need to resolve arbitrary environment variables. */
+ if (STRPREFIX(l_value, "$HOME" SEP_STR)) {
+ BLI_path_join(l_value_expanded, sizeof(l_value_expanded), home, l_value + 6, NULL);
+ l_value_final = l_value_expanded;
+ }
+
+ BLI_ghash_insert(xdg_map, BLI_strdup(l), BLI_strdup(l_value_final));
+ printf("'%s' = '%s'\n", l, l_value_final);
+ }
+ }
+ }
+ }
+ MEM_freeN(data);
+ return xdg_map;
+}
+
+static void fsmenu_xdg_user_dirs_free(GHash *xdg_map)
+{
+ if (xdg_map != NULL) {
+ BLI_ghash_free(xdg_map, MEM_freeN, MEM_freeN);
+ }
+}
+
+/**
+ * Add fsmenu entry for system folders on linux.
+ * - Check if a path is stored in the GHash generated from user-dirs.dirs
+ * - If not, check for a default path in $HOME
+ *
+ * \param key: Use `user-dirs.dirs` format "XDG_EXAMPLE_DIR"
+ * \param default_path: Directory name to check in $HOME, also used for the menu entry name.
+ */
+static void fsmenu_xdg_insert_entry(GHash *xdg_map,
+ struct FSMenu *fsmenu,
+ const char *key,
+ const char *default_path,
+ int icon,
+ const char *home)
+{
+ char dirpath[FILE_MAXDIR];
+ char *xdg_path = xdg_map ? BLI_ghash_lookup(xdg_map, key) : NULL;
+ if (xdg_path == NULL) {
+ BLI_path_join(dirpath, sizeof(dirpath), home, default_path, NULL);
+ }
+ else {
+ BLI_snprintf(dirpath, sizeof(dirpath), xdg_path);
+ }
+
+ fsmenu_insert_entry(
+ fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, dirpath, IFACE_(default_path), icon, FS_INSERT_LAST);
+}
+
+/** \} */
+
void ED_fsmenu_set_category(struct FSMenu *fsmenu, FSMenuCategory category, FSMenuEntry *fsm_head)
{
switch (category) {
@@ -710,68 +816,27 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
}
/* Follow the XDG spec, check if these are available. */
-
- /* TODO: parse "$XDG_CONFIG_HOME/user-dirs.dirs" for localized paths. */
-
- BLI_snprintf(line, sizeof(line), "%s/Desktop/", home);
- if (BLI_exists(line)) {
- fsmenu_insert_entry(fsmenu,
- FS_CATEGORY_SYSTEM_BOOKMARKS,
- line,
- IFACE_("Desktop"),
- ICON_DESKTOP,
- FS_INSERT_LAST);
- }
-
- BLI_snprintf(line, sizeof(line), "%s/Documents/", home);
- if (BLI_exists(line)) {
- fsmenu_insert_entry(fsmenu,
- FS_CATEGORY_SYSTEM_BOOKMARKS,
- line,
- IFACE_("Documents"),
- ICON_DOCUMENTS,
- FS_INSERT_LAST);
+ GHash *xdg_map = fsmenu_xdg_user_dirs_parse(home);
+
+ struct {
+ const char *key;
+ const char *default_path;
+ BIFIconID icon;
+ } xdg_items[] = {
+ {"XDG_DESKTOP_DIR", "Desktop", ICON_DESKTOP},
+ {"XDG_DOCUMENTS_DIR", "Documents", ICON_DOCUMENTS},
+ {"XDG_DOWNLOAD_DIR", "Downloads", ICON_IMPORT},
+ {"XDG_VIDEOS_DIR", "Videos", ICON_FILE_MOVIE},
+ {"XDG_PICTURES_DIR", "Pictures", ICON_FILE_IMAGE},
+ {"XDG_MUSIC_DIR", "Music", ICON_FILE_SOUND},
+ };
+
+ for (int i = 0; i < ARRAY_SIZE(xdg_items); i++) {
+ fsmenu_xdg_insert_entry(
+ xdg_map, fsmenu, xdg_items[i].key, xdg_items[i].default_path, xdg_items[i].icon, home);
}
- BLI_snprintf(line, sizeof(line), "%s/Downloads/", home);
- if (BLI_exists(line)) {
- fsmenu_insert_entry(fsmenu,
- FS_CATEGORY_SYSTEM_BOOKMARKS,
- line,
- IFACE_("Downloads"),
- ICON_IMPORT,
- FS_INSERT_LAST);
- }
-
- BLI_snprintf(line, sizeof(line), "%s/Videos/", home);
- if (BLI_exists(line)) {
- fsmenu_insert_entry(fsmenu,
- FS_CATEGORY_SYSTEM_BOOKMARKS,
- line,
- IFACE_("Videos"),
- ICON_FILE_MOVIE,
- FS_INSERT_LAST);
- }
-
- BLI_snprintf(line, sizeof(line), "%s/Pictures/", home);
- if (BLI_exists(line)) {
- fsmenu_insert_entry(fsmenu,
- FS_CATEGORY_SYSTEM_BOOKMARKS,
- line,
- IFACE_("Pictures"),
- ICON_FILE_IMAGE,
- FS_INSERT_LAST);
- }
-
- BLI_snprintf(line, sizeof(line), "%s/Music/", home);
- if (BLI_exists(line)) {
- fsmenu_insert_entry(fsmenu,
- FS_CATEGORY_SYSTEM_BOOKMARKS,
- line,
- IFACE_("Music"),
- ICON_FILE_SOUND,
- FS_INSERT_LAST);
- }
+ fsmenu_xdg_user_dirs_free(xdg_map);
}
{
@@ -858,6 +923,11 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
}
# endif
#endif
+
+#if defined(WIN32) || defined(__APPLE__)
+ /* Quiet warnings. */
+ UNUSED_VARS(fsmenu_xdg_insert_entry, fsmenu_xdg_user_dirs_parse, fsmenu_xdg_user_dirs_free);
+#endif
}
static void fsmenu_free_category(struct FSMenu *fsmenu, FSMenuCategory category)