From d174464325c991ab261c909b133f4f934cd68dc2 Mon Sep 17 00:00:00 2001 From: Nick Schermer <nick@xfce.org> Date: Thu, 8 Nov 2012 20:36:46 +0100 Subject: [PATCH] Remove user directories and add bookmarks in go menu. --- icons/16x16/Makefile.am | 3 +- icons/16x16/stock_thunar-templates.png | Bin 478 -> 0 bytes thunar/thunar-gio-extensions.c | 16 - thunar/thunar-gio-extensions.h | 3 +- thunar/thunar-misc-jobs.c | 21 +- thunar/thunar-private.h | 14 - thunar/thunar-shortcuts-model.c | 137 +++--- thunar/thunar-stock.c | 16 +- thunar/thunar-stock.h | 7 - thunar/thunar-util.c | 63 +++ thunar/thunar-util.h | 11 +- thunar/thunar-window-ui.xml | 13 +- thunar/thunar-window.c | 595 +++++++++++++------------ 13 files changed, 473 insertions(+), 426 deletions(-) delete mode 100644 icons/16x16/stock_thunar-templates.png diff --git a/icons/16x16/Makefile.am b/icons/16x16/Makefile.am index d91ac9e32..9a205ebde 100644 --- a/icons/16x16/Makefile.am +++ b/icons/16x16/Makefile.am @@ -8,8 +8,7 @@ stockdir = $(datadir)/icons/hicolor/16x16/stock/navigation stock_DATA = \ stock_folder-copy.png \ stock_folder-move.png \ - stock_thunar-shortcuts.png \ - stock_thunar-templates.png + stock_thunar-shortcuts.png EXTRA_DIST = \ $(apps_DATA) \ diff --git a/icons/16x16/stock_thunar-templates.png b/icons/16x16/stock_thunar-templates.png deleted file mode 100644 index 367f7615272aa553b9285fcc7a9e3c772f64bd2b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 478 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbMf)c~ImS0IfQh>3|gI5>EFd&b7b zmb6SQ1A_J$6<u>GyJlB{$hlSBbE|shRrk!V?ww!Tx1hDPb-{uKD^{#nyLRpF-Mjbf z*|T@=-hKP_?ccxuz<~n?4<0;x`0$Y<M~)sndg|1v>({T}ym|B1ty{Nm-@bF_&fU9r zA3S*Q@ZrNpj~+dK{P@X}Cr_U~efI3x^XJcBym;~Q<;z#EUcG+(`pug+Z{NOs_wL>M z_wPS^`0(-L$1h*LeEs_M`}glZe*F0P^XKp1zyJRI`|saB(eAfmKwq(!1o;IsSlfAd zhhMq*O6EIIh%w3A-GyB&vEwz6v&7TIF+}3B>#6HZO$s6niBfLW(|MO(S{C{6fMD9? zd;cc}x%}oge{Rjdz-6$SBjUs9E<Y}v!V9H;b=qE~vz@k_@WD3UG|QkpU{9>t*DN+E zzNT=8mu=0<N?*?CTldeZ^+my#c{w3`zqh^Tw=I95B~$jq@kVrE#;(50>POz`T0ZzO z>yLrBOwR31R?9LaI+|0D-Ih((S-QcM<K!k0^R+4p2kM!AFfQC6>!it8`W6&Rp00i_ I>zopr0O8~Ew*UYD diff --git a/thunar/thunar-gio-extensions.c b/thunar/thunar-gio-extensions.c index b4da6840c..939aa6da2 100644 --- a/thunar/thunar-gio-extensions.c +++ b/thunar/thunar-gio-extensions.c @@ -71,22 +71,6 @@ thunar_g_file_new_for_desktop (void) -GFile * -thunar_g_file_new_for_user_special_dir (GUserDirectory dir) -{ - const gchar *path; - - _thunar_return_val_if_fail (dir < G_USER_N_DIRECTORIES, NULL); - - path = g_get_user_special_dir (dir); - if (path == NULL) - path = xfce_get_homedir (); - - return g_file_new_for_path (path); -} - - - gboolean thunar_g_file_is_root (GFile *file) { diff --git a/thunar/thunar-gio-extensions.h b/thunar/thunar-gio-extensions.h index f27832ea7..4efbef03b 100644 --- a/thunar/thunar-gio-extensions.h +++ b/thunar/thunar-gio-extensions.h @@ -29,8 +29,7 @@ GFile *thunar_g_file_new_for_home (void); GFile *thunar_g_file_new_for_root (void); GFile *thunar_g_file_new_for_trash (void); GFile *thunar_g_file_new_for_desktop (void); -GFile *thunar_g_file_new_for_user_special_dir (GUserDirectory dir); - + gboolean thunar_g_file_is_root (GFile *file); gboolean thunar_g_file_is_trashed (GFile *file); gboolean thunar_g_file_is_home (GFile *file); diff --git a/thunar/thunar-misc-jobs.c b/thunar/thunar-misc-jobs.c index 1f1c98156..eddc2e1bf 100644 --- a/thunar/thunar-misc-jobs.c +++ b/thunar/thunar-misc-jobs.c @@ -37,13 +37,14 @@ _thunar_misc_jobs_load_templates (ThunarJob *job, GArray *param_values, GError **error) { - ThunarFile *file; - GtkWidget *menu; - GFile *home_dir; - GFile *templates_dir; - GList *files = NULL; - GList *lp; - GList *paths = NULL; + ThunarFile *file; + GtkWidget *menu; + GFile *home_dir; + GFile *templates_dir; + GList *files = NULL; + GList *lp; + GList *paths = NULL; + const gchar *path; _thunar_return_val_if_fail (THUNAR_IS_JOB (job), FALSE); _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE); @@ -53,7 +54,11 @@ _thunar_misc_jobs_load_templates (ThunarJob *job, g_object_set_data (G_OBJECT (job), "menu", menu); home_dir = thunar_g_file_new_for_home (); - templates_dir = thunar_g_file_new_for_user_special_dir (G_USER_DIRECTORY_TEMPLATES); + path = g_get_user_special_dir (G_USER_DIRECTORY_TEMPLATES); + if (G_LIKELY (path != NULL)) + templates_dir = g_file_new_for_path (path); + else + templates_dir = g_file_resolve_relative_path (home_dir, "Templates"); if (G_LIKELY (!g_file_equal (templates_dir, home_dir))) { diff --git a/thunar/thunar-private.h b/thunar/thunar-private.h index b6c58e20a..6fbe31a45 100644 --- a/thunar/thunar-private.h +++ b/thunar/thunar-private.h @@ -74,20 +74,6 @@ G_STMT_START{ \ }G_STMT_END #endif -#define XDG_USER_DIRS_PACKAGE "xdg-user-dirs" -#define LOCALE_FILE_NAME "user-dirs.locale" - -typedef GUserDirectory ThunarUserDirectory; -#define THUNAR_USER_DIRECTORY_DESKTOP G_USER_DIRECTORY_DESKTOP -#define THUNAR_USER_DIRECTORY_DOCUMENTS G_USER_DIRECTORY_DOCUMENTS -#define THUNAR_USER_DIRECTORY_DOWNLOAD G_USER_DIRECTORY_DOWNLOAD -#define THUNAR_USER_DIRECTORY_MUSIC G_USER_DIRECTORY_MUSIC -#define THUNAR_USER_DIRECTORY_PICTURES G_USER_DIRECTORY_PICTURES -#define THUNAR_USER_DIRECTORY_PUBLIC_SHARE G_USER_DIRECTORY_PUBLIC_SHARE -#define THUNAR_USER_DIRECTORY_TEMPLATES G_USER_DIRECTORY_TEMPLATES -#define THUNAR_USER_DIRECTORY_VIDEOS G_USER_DIRECTORY_VIDEOS -#define THUNAR_USER_N_DIRECTORIES (8) - G_END_DECLS; #endif /* !__THUNAR_PRIVATE_H__ */ diff --git a/thunar/thunar-shortcuts-model.c b/thunar/thunar-shortcuts-model.c index 804fdc101..51cce29ef 100644 --- a/thunar/thunar-shortcuts-model.c +++ b/thunar/thunar-shortcuts-model.c @@ -43,6 +43,7 @@ #include <thunar/thunar-shortcuts-model.h> #include <thunar/thunar-device-monitor.h> #include <thunar/thunar-preferences.h> +#include <thunar/thunar-util.h> #include <thunar/thunar-private.h> #define SPINNER_CYCLE_DURATION 1000 @@ -1094,103 +1095,79 @@ thunar_shortcuts_model_remove_shortcut (ThunarShortcutsModel *model, -static gboolean -thunar_shortcuts_model_load (gpointer data) +static void +thunar_shortcuts_model_load_line (GFile *file_path, + const gchar *name, + gint row_num, + gpointer user_data) { - ThunarShortcutsModel *model = THUNAR_SHORTCUTS_MODEL (data); + ThunarShortcutsModel *model = THUNAR_SHORTCUTS_MODEL (user_data); ThunarShortcut *shortcut; ThunarFile *file; - GFile *file_path; - gchar *bookmarks_path; - gchar line[2048]; - gchar *name; - FILE *fp; - gint sort_id; - - _thunar_return_val_if_fail (THUNAR_IS_SHORTCUTS_MODEL (model), FALSE); - /* determine the path to the GTK+ bookmarks file */ - bookmarks_path = g_file_get_path (model->bookmarks_file); + _thunar_return_if_fail (G_IS_FILE (file_path)); + _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_MODEL (model)); + _thunar_return_if_fail (name == NULL || g_utf8_validate (name, -1, NULL)); - /* append the GTK+ bookmarks (if any) */ - fp = fopen (bookmarks_path, "r"); - if (G_LIKELY (fp != NULL)) + /* handle local and remove files differently */ + if (g_file_has_uri_scheme (file_path, "file")) { - sort_id = 0; - - GDK_THREADS_ENTER (); + /* try to open the file corresponding to the uri */ + file = thunar_file_get (file_path, NULL); + if (G_UNLIKELY (file == NULL)) + return; - while (fgets (line, sizeof (line), fp) != NULL) + /* make sure the file refers to a directory */ + if (G_UNLIKELY (thunar_file_is_directory (file))) { - /* strip leading/trailing whitespace */ - g_strstrip (line); - - /* skip over the URI */ - for (name = line; *name != '\0' && !g_ascii_isspace (*name); ++name) - ; + /* create the shortcut entry */ + shortcut = g_slice_new0 (ThunarShortcut); + shortcut->group = THUNAR_SHORTCUT_GROUP_PLACES_BOOKMARKS; + shortcut->file = file; + shortcut->sort_id = row_num; + shortcut->hidden = thunar_shortcuts_model_get_hidden (model, shortcut); + shortcut->name = g_strdup (name); - /* zero-terminate the URI */ - *name++ = '\0'; + /* append the shortcut to the list */ + thunar_shortcuts_model_add_shortcut (model, shortcut); + } + else + { + g_object_unref (file); + } + } + else + { + /* create the shortcut entry */ + shortcut = g_slice_new0 (ThunarShortcut); + shortcut->group = THUNAR_SHORTCUT_GROUP_NETWORK_BOOKMARKS; + shortcut->gicon = g_themed_icon_new ("folder-remote"); + shortcut->location = g_object_ref (file_path); + shortcut->sort_id = row_num; + shortcut->name = g_strdup (name); - /* check if we have a name */ - for (; g_ascii_isspace (*name); ++name) - ; + /* append the shortcut to the list */ + thunar_shortcuts_model_add_shortcut (model, shortcut); + } +} - /* parse the URI */ - file_path = g_file_new_for_uri (line); - /* handle local and remove files differently */ - if (g_file_has_uri_scheme (file_path, "file")) - { - /* try to open the file corresponding to the uri */ - file = thunar_file_get (file_path, NULL); - g_object_unref (file_path); - if (G_UNLIKELY (file == NULL)) - continue; +static gboolean +thunar_shortcuts_model_load (gpointer data) +{ + ThunarShortcutsModel *model = THUNAR_SHORTCUTS_MODEL (data); - /* make sure the file refers to a directory */ - if (G_UNLIKELY (thunar_file_is_directory (file))) - { - /* create the shortcut entry */ - shortcut = g_slice_new0 (ThunarShortcut); - shortcut->group = THUNAR_SHORTCUT_GROUP_PLACES_BOOKMARKS; - shortcut->file = file; - shortcut->sort_id = ++sort_id; - shortcut->hidden = thunar_shortcuts_model_get_hidden (model, shortcut); - shortcut->name = (*name != '\0') ? g_strdup (name) : NULL; - - /* append the shortcut to the list */ - thunar_shortcuts_model_add_shortcut (model, shortcut); - } - else - { - g_object_unref (file); - } - } - else - { - /* create the shortcut entry */ - shortcut = g_slice_new0 (ThunarShortcut); - shortcut->group = THUNAR_SHORTCUT_GROUP_NETWORK_BOOKMARKS; - shortcut->gicon = g_themed_icon_new ("folder-remote"); - shortcut->location = file_path; - shortcut->sort_id = ++sort_id; - shortcut->name = (*name != '\0') ? g_strdup (name) : NULL; - - /* append the shortcut to the list */ - thunar_shortcuts_model_add_shortcut (model, shortcut); - } - } + _thunar_return_val_if_fail (THUNAR_IS_SHORTCUTS_MODEL (model), FALSE); - GDK_THREADS_LEAVE (); + GDK_THREADS_ENTER (); - /* clean up */ - fclose (fp); - } + /* parse the bookmarks */ + thunar_util_load_bookmarks (model->bookmarks_file, + thunar_shortcuts_model_load_line, + model); - /* clean up */ - g_free (bookmarks_path); + GDK_THREADS_LEAVE (); model->bookmarks_idle_id = 0; diff --git a/thunar/thunar-stock.c b/thunar/thunar-stock.c index 129771aeb..e6ad229ed 100644 --- a/thunar/thunar-stock.c +++ b/thunar/thunar-stock.c @@ -45,18 +45,12 @@ typedef struct /* keep in sync with thunar-stock.h */ static const ThunarStockIcon thunar_stock_icons[] = { - { THUNAR_STOCK_DESKTOP, "user-desktop", }, - { THUNAR_STOCK_HOME, "go-home", }, - { THUNAR_STOCK_SHORTCUTS, "stock_thunar-shortcuts", }, - { THUNAR_STOCK_TEMPLATES, "text-x-generic-template", }, + { THUNAR_STOCK_DESKTOP, "user-desktop" }, + { THUNAR_STOCK_HOME, "go-home" }, + { THUNAR_STOCK_SHORTCUTS, "stock_thunar-shortcuts" }, + { THUNAR_STOCK_TEMPLATES, "text-x-generic-template" }, { THUNAR_STOCK_TRASH_EMPTY, "user-trash", }, - { THUNAR_STOCK_TRASH_FULL, "user-trash-full", }, - { THUNAR_STOCK_DOWNLOADS, "emblem-downloads", }, - { THUNAR_STOCK_DOCUMENTS, "emblem-documents", }, - { THUNAR_STOCK_MUSIC, "audio-x-generic", }, - { THUNAR_STOCK_PICTURES, "emblem-photos", }, - { THUNAR_STOCK_VIDEOS, "video-x-generic", }, - { THUNAR_STOCK_PUBLIC, "emblem-shared", }, + { THUNAR_STOCK_TRASH_FULL, "user-trash-full" }, }; diff --git a/thunar/thunar-stock.h b/thunar/thunar-stock.h index 226f51da5..8a68dd180 100644 --- a/thunar/thunar-stock.h +++ b/thunar/thunar-stock.h @@ -28,13 +28,6 @@ G_BEGIN_DECLS; #define THUNAR_STOCK_TEMPLATES "thunar-templates" /* see ThunarWindow */ #define THUNAR_STOCK_TRASH_EMPTY "thunar-trash" /* see ThunarTrashAction */ #define THUNAR_STOCK_TRASH_FULL "thunar-trash-full" /* see ThunarTrashAction */ -#define THUNAR_STOCK_DIRECTORY GTK_STOCK_DIRECTORY -#define THUNAR_STOCK_DOWNLOADS "thunar-downloads" -#define THUNAR_STOCK_DOCUMENTS "thunar-documents" -#define THUNAR_STOCK_MUSIC "thunar-music" -#define THUNAR_STOCK_PICTURES "thunar-pictures" -#define THUNAR_STOCK_VIDEOS "thunar-videos" -#define THUNAR_STOCK_PUBLIC "thunar-public" void thunar_stock_init (void); diff --git a/thunar/thunar-util.c b/thunar/thunar-util.c index 9ab597ec2..7b8665f03 100644 --- a/thunar/thunar-util.c +++ b/thunar/thunar-util.c @@ -61,6 +61,69 @@ #include <glib/gstdio.h> + +void +thunar_util_load_bookmarks (GFile *bookmarks_file, + ThunarBookmarksFunc foreach_func, + gpointer user_data) +{ + gchar *bookmarks_path; + gchar line[1024]; + const gchar *name; + gchar *space; + FILE *fp; + gint row_num = 1; + GFile *file; + + _thunar_return_if_fail (G_IS_FILE (bookmarks_file)); + _thunar_return_if_fail (g_file_is_native (bookmarks_file)); + _thunar_return_if_fail (foreach_func != NULL); + + /* determine the path to the GTK+ bookmarks file */ + bookmarks_path = g_file_get_path (bookmarks_file); + + /* append the GTK+ bookmarks (if any) */ + fp = fopen (bookmarks_path, "r"); + if (G_LIKELY (fp != NULL)) + { + while (fgets (line, sizeof (line), fp) != NULL) + { + /* remove trailing spaces */ + g_strchomp (line); + + /* skip over empty lines */ + if (*line == '\0' || *line == ' ') + continue; + + /* check if there is a custom name in the line */ + name = NULL; + space = strchr (line, ' '); + if (space != NULL) + { + /* break line */ + *space++ = '\0'; + + /* get the custom name */ + if (G_LIKELY (*space != '\0')) + name = space; + } + + file = g_file_new_for_uri (line); + + /* callback */ + foreach_func (file, name, row_num++, user_data); + + g_object_unref (G_OBJECT (file)); + } + + fclose (fp); + } + + g_free (bookmarks_path); +} + + + /** * thunar_util_expand_filename: * @filename : a local filename. diff --git a/thunar/thunar-util.h b/thunar/thunar-util.h index 779f9363c..8170bdc3b 100644 --- a/thunar/thunar-util.h +++ b/thunar/thunar-util.h @@ -26,7 +26,16 @@ G_BEGIN_DECLS; -gboolean thunar_util_looks_like_an_uri (const gchar *string) G_GNUC_WARN_UNUSED_RESULT; +typedef void (*ThunarBookmarksFunc) (GFile *file, + const gchar *name, + gint row_num, + gpointer user_data); + +void thunar_util_load_bookmarks (GFile *bookmarks_file, + ThunarBookmarksFunc foreach_func, + gpointer user_data); + +gboolean thunar_util_looks_like_an_uri (const gchar *string) G_GNUC_WARN_UNUSED_RESULT; gchar *thunar_util_expand_filename (const gchar *filename, GFile *working_directory, diff --git a/thunar/thunar-window-ui.xml b/thunar/thunar-window-ui.xml index 465c8a80d..1e026c7e3 100644 --- a/thunar/thunar-window-ui.xml +++ b/thunar/thunar-window-ui.xml @@ -77,17 +77,18 @@ <menuitem action="open-parent" /> <placeholder name="placeholder-go-history-actions" /> <separator /> + <menuitem action="open-home" /> <menuitem action="open-desktop" /> <placeholder name="placeholder-go-items-actions" /> - <menuitem action="open-documents" /> - <menuitem action="open-downloads" /> - <menuitem action="open-music" /> - <menuitem action="open-pictures" /> - <menuitem action="open-videos" /> - <menuitem action="open-public" /> + <menuitem action="open-file-system" /> <menuitem action="open-templates" /> <separator /> + <placeholder name="placeholder-go-local-actions" /> + <separator /> + <menuitem action="open-network" /> + <placeholder name="placeholder-go-remote-actions" /> + <separator /> <menuitem action="open-location" /> </menu> diff --git a/thunar/thunar-window.c b/thunar/thunar-window.c index 1fcae61ec..04d3e41ef 100644 --- a/thunar/thunar-window.c +++ b/thunar/thunar-window.c @@ -53,6 +53,7 @@ #include <thunar/thunar-preferences-dialog.h> #include <thunar/thunar-preferences.h> #include <thunar/thunar-private.h> +#include <thunar/thunar-util.h> #include <thunar/thunar-statusbar.h> #include <thunar/thunar-stock.h> #include <thunar/thunar-trash-action.h> @@ -138,6 +139,7 @@ static gpointer thunar_window_notebook_create_window (GtkWidget static void thunar_window_notebook_insert (ThunarWindow *window, ThunarFile *directory); static void thunar_window_merge_custom_preferences (ThunarWindow *window); +static gboolean thunar_window_bookmark_merge (gpointer user_data); static void thunar_window_merge_go_actions (ThunarWindow *window); static void thunar_window_install_location_bar (ThunarWindow *window, GType type); @@ -190,26 +192,16 @@ static void thunar_window_action_open_home (GtkAction ThunarWindow *window); static void thunar_window_action_open_desktop (GtkAction *action, ThunarWindow *window); -static void thunar_window_action_open_documents (GtkAction *action, - ThunarWindow *window); -static void thunar_window_action_open_downloads (GtkAction *action, - ThunarWindow *window); -static void thunar_window_action_open_music (GtkAction *action, - ThunarWindow *window); -static void thunar_window_action_open_pictures (GtkAction *action, - ThunarWindow *window); -static void thunar_window_action_open_public (GtkAction *action, - ThunarWindow *window); static void thunar_window_action_open_templates (GtkAction *action, ThunarWindow *window); -static void thunar_window_action_open_videos (GtkAction *action, - ThunarWindow *window); static void thunar_window_action_open_file_system (GtkAction *action, ThunarWindow *window); static void thunar_window_action_open_trash (GtkAction *action, ThunarWindow *window); static void thunar_window_action_open_network (GtkAction *action, ThunarWindow *window); +static void thunar_window_action_open_bookmark (GtkAction *action, + ThunarWindow *window); static void thunar_window_action_open_location (GtkAction *action, ThunarWindow *window); static void thunar_window_action_contents (GtkAction *action, @@ -277,6 +269,13 @@ struct _ThunarWindow /* UI manager merge ID for go menu actions */ guint go_items_actions_merge_id; + /* UI manager merge ID for the bookmark actions */ + guint bookmark_items_actions_merge_id; + GtkActionGroup *bookmark_action_group; + GFile *bookmark_file; + GFileMonitor *bookmark_monitor; + guint bookmark_reload_idle_id; + ThunarClipboardManager *clipboard; ThunarPreferences *preferences; @@ -356,12 +355,7 @@ static GtkActionEntry action_entries[] = { "open-home", THUNAR_STOCK_HOME, N_ ("_Home"), "<alt>Home", N_ ("Go to the home folder"), G_CALLBACK (thunar_window_action_open_home), }, { "open-desktop", THUNAR_STOCK_DESKTOP, "Desktop", NULL, N_ ("Go to the desktop folder"), G_CALLBACK (thunar_window_action_open_desktop), }, { "open-file-system", GTK_STOCK_HARDDISK, N_ ("File System"), NULL, N_ ("Browse the file system"), G_CALLBACK (thunar_window_action_open_file_system), }, - { "open-documents", THUNAR_STOCK_DOCUMENTS, "Documents", NULL, N_ ("Go to the documents folder"), G_CALLBACK (thunar_window_action_open_documents), }, - { "open-downloads", THUNAR_STOCK_DOWNLOADS, "Download", NULL, N_ ("Go to the downloads folder"), G_CALLBACK (thunar_window_action_open_downloads), }, - { "open-music", THUNAR_STOCK_MUSIC, "Music", NULL, N_ ("Go to the music folder"), G_CALLBACK (thunar_window_action_open_music), }, - { "open-pictures", THUNAR_STOCK_PICTURES, "Pictures", NULL, N_ ("Go to the pictures folder"), G_CALLBACK (thunar_window_action_open_pictures), }, - { "open-videos", THUNAR_STOCK_VIDEOS, "Videos", NULL, N_ ("Go to the videos folder"), G_CALLBACK (thunar_window_action_open_videos), }, - { "open-public", THUNAR_STOCK_PUBLIC, "Public", NULL, N_ ("Go to the public folder"), G_CALLBACK (thunar_window_action_open_public), }, + { "open-network", GTK_STOCK_NETWORK, N_("B_rowse Network"), NULL, N_ ("Browse local network connections"), G_CALLBACK (thunar_window_action_open_network), }, { "open-templates", THUNAR_STOCK_TEMPLATES, N_("T_emplates"), NULL, N_ ("Go to the templates folder"), G_CALLBACK (thunar_window_action_open_templates), }, { "open-location", NULL, N_ ("_Open Location..."), "<control>L", N_ ("Specify a location to open"), G_CALLBACK (thunar_window_action_open_location), }, { "help-menu", NULL, N_ ("_Help"), NULL, }, @@ -382,13 +376,6 @@ static const GtkToggleActionEntry toggle_action_entries[] = -static const gchar *thunar_user_directory_names[9] = { - "Desktop", "Documents", "Download", "Music", "Pictures", "Public", - "Templates", "Videos", NULL, -}; - - - static guint window_signals[LAST_SIGNAL]; @@ -659,107 +646,6 @@ view_index2type (gint idx) } } -/* Reads the current xdg user dirs locale from ~/.config/xdg-user-dirs.locale - * Notice that the result shall be freed by using g_free (). */ -static gchar * -thunar_get_xdg_user_dirs_locale (void) -{ - gchar *file = NULL; - gchar *content = NULL; - gchar *locale = NULL; - - /* get the file pathname */ - file = g_build_filename (g_get_user_config_dir (), LOCALE_FILE_NAME, NULL); - - /* grab the contents and get ride of the surrounding spaces */ - if (g_file_get_contents (file, &content, NULL, NULL)) - locale = g_strdup (g_strstrip (content)); - - g_free (content); - g_free (file); - - /* if we got nothing, let's set the default locale as C */ - if (exo_str_is_equal (locale, "")) - { - g_free (locale); - locale = g_strdup ("C"); - } - - return locale; -} - -/* this function hides all the user directory menu entries in case of - * glib <= 2.12. Otherwise it hide the menu entries only for the directories - * that point to $HOME or to NULL. Then, it translates the labels. */ -static void -thunar_window_setup_user_dir_menu_entries (ThunarWindow *window) -{ - static const gchar *callback_names[] = { - "open-desktop", - "open-documents", - "open-downloads", - "open-music", - "open-pictures", - "open-public", - "open-templates", - "open-videos", - NULL - }; - GtkAction *action; - GFile *home_dir; - GFile *dir; - gchar *locale; - gchar *old_locale; - const gchar *path; - gchar *translation; - gint i; - - bindtextdomain (XDG_USER_DIRS_PACKAGE, PACKAGE_LOCALE_DIR); -#ifdef HAVE_BIND_TEXTDOMAIN_CODESET - bind_textdomain_codeset (XDG_USER_DIRS_PACKAGE, "UTF-8"); -#endif /* HAVE_BIND_TEXTDOMAIN_CODESET */ - - /* save the old locale */ - old_locale = g_strdup(setlocale (LC_MESSAGES, NULL)); - - /* set the new locale */ - locale = thunar_get_xdg_user_dirs_locale (); - setlocale (LC_MESSAGES, locale); - g_free (locale); - - home_dir = thunar_g_file_new_for_home (); - - for (i = 0; i < G_USER_N_DIRECTORIES; i++) - { - action = gtk_action_group_get_action (window->action_group, callback_names[i]); - path = g_get_user_special_dir (i); - - /* special case: got NULL for the templates dir. Force it to ~/Templates */ - if (G_UNLIKELY (path == NULL && i == G_USER_DIRECTORY_TEMPLATES)) - dir = g_file_resolve_relative_path (home_dir, thunar_user_directory_names[i]); - else if (path != NULL) - dir = g_file_new_for_path (path); - else - continue; - - /* xdg user dirs pointing to $HOME must be considered disabled */ - if (G_LIKELY (path != NULL && !g_file_equal (dir, home_dir))) - { - /* menu entry label translation */ - translation = dgettext (XDG_USER_DIRS_PACKAGE, (gchar *) thunar_user_directory_names[i]); - g_object_set (action, "label", translation, NULL); - } - else - gtk_action_set_visible (GTK_ACTION (action), FALSE); - - g_object_unref (dir); - } - - g_object_unref (home_dir); - - setlocale (LC_MESSAGES, old_locale); - g_free (old_locale); -} static void @@ -833,9 +719,6 @@ thunar_window_init (ThunarWindow *window) action = gtk_action_group_get_action (window->action_group, "show-hidden"); gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), last_show_hidden); - /* rename the user dir menu entries and hide the unexisting ones */ - thunar_window_setup_user_dir_menu_entries (window); - /* * add view options */ @@ -1030,6 +913,19 @@ thunar_window_dispose (GObject *object) window->go_items_actions_merge_id = 0; } + /* un-merge the bookmark actions */ + if (G_LIKELY (window->bookmark_items_actions_merge_id != 0)) + { + gtk_ui_manager_remove_ui (window->ui_manager, window->bookmark_items_actions_merge_id); + window->bookmark_items_actions_merge_id = 0; + } + + if (window->bookmark_reload_idle_id != 0) + { + g_source_remove (window->bookmark_reload_idle_id); + window->bookmark_reload_idle_id = 0; + } + /* disconnect from the current-directory */ thunar_window_set_current_directory (window, NULL); @@ -1059,6 +955,18 @@ thunar_window_finalize (GObject *object) g_object_unref (window->icon_factory); g_object_unref (window->launcher); + if (window->bookmark_action_group != NULL) + g_object_unref (window->bookmark_action_group); + + if (window->bookmark_file != NULL) + g_object_unref (window->bookmark_file); + + if (window->bookmark_monitor != NULL) + { + g_file_monitor_cancel (window->bookmark_monitor); + g_object_unref (window->bookmark_monitor); + } + /* release our reference on the provider factory */ g_object_unref (window->provider_factory); @@ -1974,57 +1882,196 @@ thunar_window_merge_custom_preferences (ThunarWindow *window) -void -thunar_window_merge_go_actions (ThunarWindow *window) +static void +thunar_window_bookmark_changed (GFileMonitor *monitor, + GFile *file, + GFile *other_file, + GFileMonitorEvent event_type, + ThunarWindow *window) { - GtkAction *action; + _thunar_return_if_fail (THUNAR_IS_WINDOW (window)); + _thunar_return_if_fail (window->bookmark_monitor == monitor); + + if (window->bookmark_reload_idle_id == 0) + window->bookmark_reload_idle_id = g_idle_add (thunar_window_bookmark_merge, window); +} + + +static void +thunar_window_bookmark_merge_line (GFile *file_path, + const gchar *name, + gint line_num, + gpointer user_data) +{ + ThunarWindow *window = THUNAR_WINDOW (user_data); + GtkAction *action = NULL; + GChecksum *checksum; + gchar *uri; + ThunarFile *file; + gchar *parse_name; + gchar *tooltip; + gchar *remote_name = NULL; + const gchar *unique_name; + const gchar *path; + + _thunar_return_if_fail (G_IS_FILE (file_path)); + _thunar_return_if_fail (name == NULL || g_utf8_validate (name, -1, NULL)); _thunar_return_if_fail (THUNAR_IS_WINDOW (window)); - _thunar_return_if_fail (window->go_items_actions_merge_id == 0); - /* allocate a new merge id from the UI manager */ - window->go_items_actions_merge_id = gtk_ui_manager_new_merge_id (window->ui_manager); + /* create unique id based on the uri */ + uri = g_file_get_uri (file_path); + checksum = g_checksum_new (G_CHECKSUM_MD5); + g_checksum_update (checksum, (const guchar *) uri, strlen (uri)); + unique_name = g_checksum_get_string (checksum); + g_free (uri); - /* setup the "open-trash" action */ - if (thunar_g_vfs_is_uri_scheme_supported ("trash")) + parse_name = g_file_get_parse_name (file_path); + tooltip = g_strdup_printf (_("Open the location \"%s\""), parse_name); + g_free (parse_name); + + if (g_file_has_uri_scheme (file_path, "file")) { - /* add the trash action to the action group */ - action = thunar_trash_action_new (); - g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (thunar_window_action_open_trash), window); - gtk_action_group_add_action (window->action_group, action); + /* try to open the file corresponding to the uri */ + file = thunar_file_get (file_path, NULL); + if (G_UNLIKELY (file == NULL)) + return; + + /* make sure the file refers to a directory */ + if (G_UNLIKELY (thunar_file_is_directory (file))) + { + if (name == NULL) + name = thunar_file_get_display_name (file); + + action = gtk_action_new (unique_name, name, tooltip, GTK_STOCK_DIRECTORY); + g_object_set_data_full (G_OBJECT (action), I_("thunar-file"), file, g_object_unref); + } + else + { + g_object_unref (file); + } + + /* add to the local bookmarks */ + path = "/main-menu/go-menu/placeholder-go-local-actions"; + } + else + { + if (name == NULL) + { + remote_name = thunar_g_file_get_display_name_remote (file_path); + name = remote_name; + } + + action = gtk_action_new (unique_name, name, tooltip, NULL); + gtk_action_set_icon_name (action, "folder-remote"); + g_object_set_data_full (G_OBJECT (action), I_("location-file"), + g_object_ref (file_path), g_object_unref); + + g_free (remote_name); + + /* add to the remote bookmarks */ + path = "/main-menu/go-menu/placeholder-go-remote-actions"; + } + + if (G_LIKELY (action != NULL)) + { + /* connect action */ + g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (thunar_window_action_open_bookmark), window); + + /* insert the bookmark in the group */ + gtk_action_group_add_action_with_accel (window->bookmark_action_group, action, NULL); /* add the action to the UI manager */ gtk_ui_manager_add_ui (window->ui_manager, - window->go_items_actions_merge_id, - "/main-menu/go-menu/placeholder-go-items-actions", - gtk_action_get_name (GTK_ACTION (action)), - gtk_action_get_name (GTK_ACTION (action)), + window->bookmark_items_actions_merge_id, + path, + unique_name, unique_name, GTK_UI_MANAGER_MENUITEM, FALSE); g_object_unref (action); } - /* add the file system action to the UI manager */ - { - action = gtk_action_group_get_action (window->action_group, "open-file-system"); - gtk_ui_manager_add_ui (window->ui_manager, - window->go_items_actions_merge_id, - "/main-menu/go-menu/placeholder-go-items-actions", - gtk_action_get_name (GTK_ACTION (action)), - gtk_action_get_name (GTK_ACTION (action)), - GTK_UI_MANAGER_MENUITEM, FALSE); - } + g_checksum_free (checksum); + g_free (tooltip); +} + + + +static gboolean +thunar_window_bookmark_merge (gpointer user_data) +{ + ThunarWindow *window = THUNAR_WINDOW (user_data); + GFile *home; - /* setup the "open-network" action */ - if (thunar_g_vfs_is_uri_scheme_supported ("network")) + _thunar_return_val_if_fail (THUNAR_IS_WINDOW (window), FALSE); + + GDK_THREADS_ENTER (); + + /* remove old actions */ + if (window->bookmark_items_actions_merge_id != 0) + gtk_ui_manager_remove_ui (window->ui_manager, window->bookmark_items_actions_merge_id); + + /* drop old bookmarks action group */ + if (window->bookmark_action_group != NULL) { - /* create the network action */ - action = gtk_action_new ("open-network", _("Network"), _("Browse the network"), - GTK_STOCK_NETWORK); - g_signal_connect (action, "activate", G_CALLBACK (thunar_window_action_open_network), window); + gtk_ui_manager_remove_action_group (window->ui_manager, window->bookmark_action_group); + g_object_unref (window->bookmark_action_group); + } - /* add the network action to the action group */ - gtk_action_group_add_action (window->action_group, action); + /* lazy initialize the bookmarks */ + if (window->bookmark_file == NULL) + { + home = thunar_g_file_new_for_home (); + window->bookmark_file = g_file_resolve_relative_path (home, ".gtk-bookmarks"); + g_object_unref (home); + + window->bookmark_monitor = g_file_monitor_file (window->bookmark_file, G_FILE_MONITOR_NONE, NULL, NULL); + if (G_LIKELY (window->bookmark_monitor != NULL)) + { + g_signal_connect (window->bookmark_monitor, "changed", + G_CALLBACK (thunar_window_bookmark_changed), window); + } + } + + /* generate a new merge id */ + window->bookmark_items_actions_merge_id = gtk_ui_manager_new_merge_id (window->ui_manager); + + /* create a new action group */ + window->bookmark_action_group = gtk_action_group_new ("ThunarBookmarks"); + gtk_ui_manager_insert_action_group (window->ui_manager, window->bookmark_action_group, -1); + + /* collect bookmarks */ + thunar_util_load_bookmarks (window->bookmark_file, + thunar_window_bookmark_merge_line, + window); + + window->bookmark_reload_idle_id = 0; + + GDK_THREADS_LEAVE (); + + return FALSE; +} + + + +static void +thunar_window_merge_go_actions (ThunarWindow *window) +{ + GtkAction *action; + + _thunar_return_if_fail (THUNAR_IS_WINDOW (window)); + _thunar_return_if_fail (window->go_items_actions_merge_id == 0); + + /* setup the "open-trash" action */ + if (thunar_g_vfs_is_uri_scheme_supported ("trash")) + { + /* allocate a new merge id from the UI manager */ + window->go_items_actions_merge_id = gtk_ui_manager_new_merge_id (window->ui_manager); + + /* add the trash action to the action group */ + action = thunar_trash_action_new (); + g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (thunar_window_action_open_trash), window); + gtk_action_group_add_action_with_accel (window->action_group, action, NULL); /* add the action to the UI manager */ gtk_ui_manager_add_ui (window->ui_manager, @@ -2036,6 +2083,10 @@ thunar_window_merge_go_actions (ThunarWindow *window) g_object_unref (action); } + + /* setup visibility of the "open-network" action */ + action = gtk_action_group_get_action (window->action_group, "open-network"); + gtk_action_set_visible (action, thunar_g_vfs_is_uri_scheme_supported ("network")); } @@ -2654,34 +2705,44 @@ thunar_window_action_open_home (GtkAction *action, static gboolean -thunar_window_open_user_folder (GtkAction *action, - ThunarWindow *window, - ThunarUserDirectory thunar_user_dir, - const gchar *default_name) -{ - ThunarFile *user_file = NULL; - gboolean result = FALSE; - GError *error = NULL; - GFile *home_dir; - GFile *user_dir; - gchar *path = NULL; +thunar_window_open_user_folder (GtkAction *action, + ThunarWindow *window, + GUserDirectory thunar_user_dir, + const gchar *default_name) +{ + ThunarFile *user_file = NULL; + gboolean result = FALSE; + GError *error = NULL; + GFile *home_dir; + GFile *user_dir; + const gchar *path; + gint response; + GtkWidget *dialog; + gchar *parse_name; + + path = g_get_user_special_dir (thunar_user_dir); + home_dir = thunar_g_file_new_for_home (); - path = g_strdup (g_get_user_special_dir (thunar_user_dir)); + /* check if there is an entry in user-dirs.dirs */ + path = g_get_user_special_dir (thunar_user_dir); + if (G_LIKELY (path != NULL)) + { + user_dir = g_file_new_for_path (path); - if (G_UNLIKELY (path == NULL)) + /* if equal to home, leave */ + if (g_file_equal (user_dir, home_dir)) + goto is_homedir; + } + else { - home_dir = thunar_g_file_new_for_home (); + /* build a name */ user_dir = g_file_resolve_relative_path (home_dir, default_name); - path = g_file_get_path (user_dir); - g_object_unref (home_dir); } - else - user_dir = g_file_new_for_path (path); /* try to load the user dir */ user_file = thunar_file_get (user_dir, NULL); - /* handle the case where the file does not exists */ + /* check if the directory exists */ if (G_UNLIKELY (user_file == NULL || !thunar_file_exists (user_file))) { /* release the instance if it does not exist */ @@ -2691,9 +2752,25 @@ thunar_window_open_user_folder (GtkAction *action, user_file = NULL; } - /* try to create the folder, then reload the file */ - if (G_LIKELY (xfce_mkdirhier (path, 0755, &error))) - user_file = thunar_file_get (user_dir, &error); + /* ask the user to create the directory */ + parse_name = g_file_get_parse_name (user_dir); + dialog = gtk_message_dialog_new (GTK_WINDOW (window), + GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_QUESTION, + GTK_BUTTONS_YES_NO, + _("The directory \"%s\" does not exist. Do you want to create it?"), + parse_name); + gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_YES); + response = gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + g_free (parse_name); + + if (response == GTK_RESPONSE_YES + && g_file_make_directory_with_parents (user_dir, NULL, &error)) + { + /* try again */ + user_file = thunar_file_get (user_dir, &error); + } } if (G_LIKELY (user_file != NULL)) @@ -2703,18 +2780,18 @@ thunar_window_open_user_folder (GtkAction *action, g_object_unref (G_OBJECT (user_file)); result = TRUE; } - else + else if (error != NULL) { - gchar *error_msg = g_strdup_printf (_("Failed to open folder \"%s\""), default_name); - - thunar_dialogs_show_error (GTK_WIDGET (window), error, "%s", error_msg); - g_free (error_msg); - if (error) - g_error_free (error); + parse_name = g_file_get_parse_name (user_dir); + thunar_dialogs_show_error (GTK_WIDGET (window), error, _("Failed to open directory \"%s\""), parse_name); + g_free (parse_name); + g_error_free (error); } + is_homedir: + g_object_unref (user_dir); - g_free (path); + g_object_unref (home_dir); return result; } @@ -2729,82 +2806,12 @@ thunar_window_action_open_desktop (GtkAction *action, _thunar_return_if_fail (THUNAR_IS_WINDOW (window)); thunar_window_open_user_folder (action, window, - THUNAR_USER_DIRECTORY_DESKTOP, + G_USER_DIRECTORY_DESKTOP, "Desktop"); } -static void -thunar_window_action_open_documents (GtkAction *action, - ThunarWindow *window) -{ - _thunar_return_if_fail (GTK_IS_ACTION (action)); - _thunar_return_if_fail (THUNAR_IS_WINDOW (window)); - - thunar_window_open_user_folder (action, window, - THUNAR_USER_DIRECTORY_DOCUMENTS, - "Documents"); -} - - - -static void -thunar_window_action_open_downloads (GtkAction *action, - ThunarWindow *window) -{ - _thunar_return_if_fail (GTK_IS_ACTION (action)); - _thunar_return_if_fail (THUNAR_IS_WINDOW (window)); - - thunar_window_open_user_folder (action, window, - THUNAR_USER_DIRECTORY_DOWNLOAD, - "Downloads"); -} - - - -static void -thunar_window_action_open_music (GtkAction *action, - ThunarWindow *window) -{ - _thunar_return_if_fail (GTK_IS_ACTION (action)); - _thunar_return_if_fail (THUNAR_IS_WINDOW (window)); - - thunar_window_open_user_folder (action, window, - THUNAR_USER_DIRECTORY_MUSIC, - "Music"); -} - - - -static void -thunar_window_action_open_pictures (GtkAction *action, - ThunarWindow *window) -{ - _thunar_return_if_fail (GTK_IS_ACTION (action)); - _thunar_return_if_fail (THUNAR_IS_WINDOW (window)); - - thunar_window_open_user_folder (action, window, - THUNAR_USER_DIRECTORY_PICTURES, - "Pictures"); -} - - - -static void -thunar_window_action_open_public (GtkAction *action, - ThunarWindow *window) -{ - _thunar_return_if_fail (GTK_IS_ACTION (action)); - _thunar_return_if_fail (THUNAR_IS_WINDOW (window)); - - thunar_window_open_user_folder (action, window, - THUNAR_USER_DIRECTORY_PUBLIC_SHARE, - "Public"); -} - - - static void thunar_window_action_open_templates (GtkAction *action, ThunarWindow *window) @@ -2822,7 +2829,7 @@ thunar_window_action_open_templates (GtkAction *action, _thunar_return_if_fail (THUNAR_IS_WINDOW (window)); success = thunar_window_open_user_folder (action,window, - THUNAR_USER_DIRECTORY_TEMPLATES, + G_USER_DIRECTORY_TEMPLATES, "Templates"); /* check whether we should display the "About Templates" dialog */ @@ -2886,20 +2893,6 @@ thunar_window_action_open_templates (GtkAction *action, -static void -thunar_window_action_open_videos (GtkAction *action, - ThunarWindow *window) -{ - _thunar_return_if_fail (GTK_IS_ACTION (action)); - _thunar_return_if_fail (THUNAR_IS_WINDOW (window)); - - thunar_window_open_user_folder (action, window, - THUNAR_USER_DIRECTORY_VIDEOS, - "Videos"); -} - - - static void thunar_window_action_open_file_system (GtkAction *action, ThunarWindow *window) @@ -3004,6 +2997,48 @@ thunar_window_action_open_network (GtkAction *action, +static void +thunar_window_poke_location_finish (ThunarBrowser *browser, + GFile *location, + ThunarFile *file, + ThunarFile *target_file, + GError *error, + gpointer ignored) +{ + _thunar_return_if_fail (THUNAR_IS_WINDOW (browser)); + _thunar_return_if_fail (THUNAR_IS_FILE (file)); + + thunar_window_poke_file_finish (browser, file, target_file, error, ignored); +} + + + +static void +thunar_window_action_open_bookmark (GtkAction *action, + ThunarWindow *window) +{ + ThunarFile *local_file; + GFile *remote_file; + + /* try to open the local file */ + local_file = g_object_get_data (G_OBJECT (action), I_("thunar-file")); + if (local_file != NULL) + { + thunar_window_set_current_directory (window, local_file); + return; + } + + /* try to the remote file */ + remote_file = g_object_get_data (G_OBJECT (action), I_("location-file")); + if (remote_file != NULL) + { + thunar_browser_poke_location (THUNAR_BROWSER (window), remote_file, window, + thunar_window_poke_location_finish, NULL); + } +} + + + static void thunar_window_action_open_location (GtkAction *action, ThunarWindow *window) @@ -3284,6 +3319,8 @@ thunar_window_merge_idle (gpointer user_data) thunar_window_merge_go_actions (window); GDK_THREADS_LEAVE (); + thunar_window_bookmark_merge (window); + return FALSE; } -- GitLab