From 03d0bce8f27b1b60420b2e8e20c430211face5e2 Mon Sep 17 00:00:00 2001 From: Reuben Green Date: Sat, 11 Apr 2020 11:15:47 +0100 Subject: [PATCH] draft patch to implement per directory settings for view type --- thunar/thunar-file.c | 50 +++++++++ thunar/thunar-file.h | 11 ++ thunar/thunar-preferences.c | 13 +++ thunar/thunar-window-ui.xml | 1 + thunar/thunar-window.c | 216 +++++++++++++++++++++++++----------- thunar/thunar-window.h | 1 + 6 files changed, 226 insertions(+), 66 deletions(-) diff --git a/thunar/thunar-file.c b/thunar/thunar-file.c index c8ae011f..ce9d4c50 100644 --- a/thunar/thunar-file.c +++ b/thunar/thunar-file.c @@ -4507,3 +4507,53 @@ thunar_file_list_to_thunar_g_file_list (GList *file_list) return list; } + +/* + * The implementation of the following two functions is a hack to get this + * patch to work to demonstrate the concept. I have not used GFile attributes + * before, and I could not find any good example code to copy, so these functions + * are probably badly implemented. Also, in the final fix, these functions should + * be better integrated into the existing file attribute system in thunar and + * thunarx - any help or advice on how to do this would be most welcome! + */ + +void +thunar_file_get_view_settings (ThunarFile *file, + ThunarFileViewSettings *settings) +{ + GFileInfo *info; + + _thunar_return_if_fail (THUNAR_IS_FILE (file)); + + info = g_file_query_info (file->gfile, + "metadata::thunar::view-type", + G_FILE_QUERY_INFO_NONE, + NULL, NULL); + + if (g_file_info_has_attribute (info, "metadata::thunar::view-type")) + settings->view_type = g_file_info_get_attribute_string (info, + "metadata::thunar::view-type"); + else + settings->view_type = NULL; +} + + + +void +thunar_file_set_view_settings (ThunarFile *file, + ThunarFileViewSettings *settings) +{ + + _thunar_return_if_fail (THUNAR_IS_FILE (file)); + + if (settings->view_type != NULL) + { + g_file_info_set_attribute_string (file->info, + "metadata::thunar::view-type", + settings->view_type); + g_file_set_attributes_from_info (file->gfile, + file->info, + G_FILE_QUERY_INFO_NONE, + NULL, NULL); + } +} diff --git a/thunar/thunar-file.h b/thunar/thunar-file.h index c9488d22..4dd7d400 100644 --- a/thunar/thunar-file.h +++ b/thunar/thunar-file.h @@ -41,6 +41,12 @@ typedef struct _ThunarFile ThunarFile; #define THUNAR_IS_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_TYPE_FILE)) #define THUNAR_FILE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_TYPE_FILE, ThunarFileClass)) +typedef struct +{ + const gchar *view_type; +} +ThunarFileViewSettings; + /** * ThunarFileDateType: * @THUNAR_FILE_DATE_ACCESSED : date of last access to the file. @@ -267,6 +273,11 @@ GList *thunar_file_list_to_thunar_g_file_list (GList gboolean thunar_file_is_desktop (const ThunarFile *file); +void thunar_file_get_view_settings (ThunarFile *file, + ThunarFileViewSettings *settings); +void thunar_file_set_view_settings (ThunarFile *file, + ThunarFileViewSettings *settings); + /** * thunar_file_is_root: * @file : a #ThunarFile. diff --git a/thunar/thunar-preferences.c b/thunar/thunar-preferences.c index 732d9a2d..eeb6dcf9 100644 --- a/thunar/thunar-preferences.c +++ b/thunar/thunar-preferences.c @@ -64,6 +64,7 @@ enum PROP_LAST_MENUBAR_VISIBLE, PROP_LAST_SEPARATOR_POSITION, PROP_LAST_SHOW_HIDDEN, + PROP_LAST_SAVE_VIEW, PROP_LAST_SIDE_PANE, PROP_LAST_SORT_COLUMN, PROP_LAST_SORT_ORDER, @@ -346,6 +347,18 @@ thunar_preferences_class_init (ThunarPreferencesClass *klass) FALSE, EXO_PARAM_READWRITE); + /** + * ThunarPreferences:last-save-view: + * + * Whether to use per directory settings. + **/ + preferences_props[PROP_LAST_SAVE_VIEW] = + g_param_spec_boolean ("last-save-view", + "LastSaveView", + NULL, + FALSE, + EXO_PARAM_READWRITE); + /** * ThunarPreferences:last-side-pane: * diff --git a/thunar/thunar-window-ui.xml b/thunar/thunar-window-ui.xml index 457b82b2..6b54190f 100644 --- a/thunar/thunar-window-ui.xml +++ b/thunar/thunar-window-ui.xml @@ -68,6 +68,7 @@ + diff --git a/thunar/thunar-window.c b/thunar/thunar-window.c index 7bf933b0..4ee0e4e9 100644 --- a/thunar/thunar-window.c +++ b/thunar/thunar-window.c @@ -188,6 +188,7 @@ static void thunar_window_action_open_location (ThunarWindow static void thunar_window_action_contents (ThunarWindow *window); static void thunar_window_action_about (ThunarWindow *window); static void thunar_window_action_show_hidden (ThunarWindow *window); +static void thunar_window_action_save_view (ThunarWindow *window); static void thunar_window_current_directory_changed (ThunarFile *current_directory, ThunarWindow *window); static void thunar_window_menu_item_selected (ThunarWindow *window, @@ -290,6 +291,7 @@ struct _ThunarWindow GtkWidget *statusbar; GType view_type; + GType shared_view_type; GSList *view_bindings; /* support for two different styles of location bars */ @@ -313,6 +315,8 @@ struct _ThunarWindow gboolean show_hidden; + gboolean save_view; + /* support to remember window geometry */ guint save_geometry_timer_id; @@ -353,6 +357,7 @@ static XfceGtkActionEntry thunar_window_action_entries[] = { THUNAR_WINDOW_ACTION_VIEW_STATUSBAR, "/ThunarWindow/view-statusbar", "", XFCE_GTK_CHECK_MENU_ITEM, N_ ("St_atusbar"), N_ ("Change the visibility of this window's statusbar"), NULL, G_CALLBACK (thunar_window_action_statusbar_changed), }, { THUNAR_WINDOW_ACTION_VIEW_MENUBAR, "/ThunarWindow/view-menubar", "m", XFCE_GTK_CHECK_MENU_ITEM, N_ ("_Menubar"), N_ ("Change the visibility of this window's menubar"), NULL, G_CALLBACK (thunar_window_action_menubar_changed), }, { THUNAR_WINDOW_ACTION_SHOW_HIDDEN, "/ThunarWindow/show-hidden", "h", XFCE_GTK_CHECK_MENU_ITEM, N_ ("Show _Hidden Files"), N_ ("Toggles the display of hidden files in the current window"), NULL, G_CALLBACK (thunar_window_action_show_hidden), }, + { THUNAR_WINDOW_ACTION_SAVE_VIEW, "/ThunarWindow/save-view", "", XFCE_GTK_CHECK_MENU_ITEM, N_ ("_Per directory settings"),N_ ("Toggles the use of per directory settings"), NULL, G_CALLBACK (thunar_window_action_save_view), }, { THUNAR_WINDOW_ACTION_ZOOM_IN, "/ThunarWindow/zoom-in", "KP_Add", XFCE_GTK_IMAGE_MENU_ITEM, N_ ("Zoom I_n"), N_ ("Show the contents in more detail"), "zoom-in-symbolic", G_CALLBACK (thunar_window_zoom_in), }, { THUNAR_WINDOW_ACTION_ZOOM_OUT, "/ThunarWindow/zoom-out", "KP_Subtract", XFCE_GTK_IMAGE_MENU_ITEM, N_ ("Zoom _Out"), N_ ("Show the contents in less detail"), "zoom-out-symbolic", G_CALLBACK (thunar_window_zoom_out), }, { THUNAR_WINDOW_ACTION_ZOOM_RESET, "/ThunarWindow/zoom-reset", "KP_0", XFCE_GTK_IMAGE_MENU_ITEM, N_ ("Normal Si_ze"), N_ ("Show the contents at the normal size"), "zoom-original-symbolic", G_CALLBACK (thunar_window_zoom_reset), }, @@ -567,6 +572,7 @@ thunar_window_init (ThunarWindow *window) GtkToolItem *tool_item; gboolean small_icons; GtkStyleContext *context; + gchar *type_name; /* unset the view type */ window->view_type = G_TYPE_NONE; @@ -585,6 +591,7 @@ thunar_window_init (ThunarWindow *window) /* get all properties for init */ g_object_get (G_OBJECT (window->preferences), "last-show-hidden", &window->show_hidden, + "last-save-view", &window->save_view, "last-window-width", &last_window_width, "last-window-height", &last_window_height, "last-window-maximized", &last_window_maximized, @@ -593,7 +600,6 @@ thunar_window_init (ThunarWindow *window) "last-location-bar", &last_location_bar, "last-side-pane", &last_side_pane, "last-statusbar-visible", &last_statusbar_visible, - "last-view", &last_view, "misc-small-toolbar-icons", &small_icons, NULL); @@ -787,15 +793,33 @@ G_GNUC_END_IGNORE_DEPRECATIONS if (G_LIKELY (window->view != NULL)) thunar_window_binding_create (window, window->view, "statusbar-text", window->statusbar, "text", G_BINDING_SYNC_CREATE); - if (exo_str_is_equal (last_view, g_type_name (THUNAR_TYPE_ICON_VIEW))) - window->view_type = THUNAR_TYPE_ICON_VIEW; - else if (exo_str_is_equal (last_view, g_type_name (THUNAR_TYPE_DETAILS_VIEW))) - window->view_type = THUNAR_TYPE_DETAILS_VIEW; - else if (exo_str_is_equal (last_view, g_type_name (THUNAR_TYPE_COMPACT_VIEW))) - window->view_type = THUNAR_TYPE_COMPACT_VIEW; - else - window->view_type = THUNAR_TYPE_ICON_VIEW; //default - g_free (last_view); + /* determine the shared view type from the default-view preference */ + window->shared_view_type = G_TYPE_NONE; + g_object_get (G_OBJECT (window->preferences), "default-view", &type_name, NULL); + if (exo_str_is_equal (type_name, g_type_name (THUNAR_TYPE_ICON_VIEW))) + window->shared_view_type = THUNAR_TYPE_ICON_VIEW; + else if (exo_str_is_equal (type_name, g_type_name (THUNAR_TYPE_DETAILS_VIEW))) + window->shared_view_type = THUNAR_TYPE_DETAILS_VIEW; + else if (exo_str_is_equal (type_name, g_type_name (THUNAR_TYPE_COMPACT_VIEW))) + window->shared_view_type = THUNAR_TYPE_COMPACT_VIEW; + g_free (type_name); + + /* determine the shared view type if the default view is "Last Active View" */ + if (g_type_is_a (window->shared_view_type, G_TYPE_NONE)) + { + g_object_get (G_OBJECT (window->preferences), "last-view", &type_name, NULL); + if (exo_str_is_equal (type_name, g_type_name (THUNAR_TYPE_ICON_VIEW))) + window->shared_view_type = THUNAR_TYPE_ICON_VIEW; + else if (exo_str_is_equal (type_name, g_type_name (THUNAR_TYPE_DETAILS_VIEW))) + window->shared_view_type = THUNAR_TYPE_DETAILS_VIEW; + else if (exo_str_is_equal (type_name, g_type_name (THUNAR_TYPE_COMPACT_VIEW))) + window->shared_view_type = THUNAR_TYPE_COMPACT_VIEW; + g_free (type_name); + + /* fallback, in case nothing was set */ + if (g_type_is_a (window->shared_view_type, G_TYPE_NONE)) + window->shared_view_type = THUNAR_TYPE_ICON_VIEW; + } /* load the bookmarks file and monitor */ window->bookmark_file = thunar_g_file_new_for_bookmarks (); @@ -973,7 +997,6 @@ thunar_window_create_view_menu (ThunarWindow *window, GtkWidget *sub_items; gchar *last_location_bar; gchar *last_side_pane; - gchar *last_view; _thunar_return_val_if_fail (THUNAR_IS_WINDOW (window), FALSE); _thunar_return_val_if_fail (GTK_IS_MENU_ITEM (menu), FALSE); @@ -1016,15 +1039,17 @@ thunar_window_create_view_menu (ThunarWindow *window, xfce_gtk_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_ZOOM_OUT), G_OBJECT (window), GTK_MENU_SHELL (submenu)); xfce_gtk_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_ZOOM_RESET), G_OBJECT (window), GTK_MENU_SHELL (submenu)); xfce_gtk_menu_append_seperator (GTK_MENU_SHELL (submenu)); - - g_object_get (window->preferences, "last-view", &last_view, NULL); + xfce_gtk_toggle_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_SAVE_VIEW), G_OBJECT (window), + window->save_view, GTK_MENU_SHELL (submenu)); xfce_gtk_toggle_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_VIEW_AS_ICONS), - G_OBJECT (window), exo_str_is_equal (last_view, g_type_name (THUNAR_TYPE_ICON_VIEW)), GTK_MENU_SHELL (submenu)); + G_OBJECT (window), window->view_type == THUNAR_TYPE_ICON_VIEW, + GTK_MENU_SHELL (submenu)); xfce_gtk_toggle_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_VIEW_AS_DETAILED_LIST), - G_OBJECT (window), exo_str_is_equal (last_view, g_type_name (THUNAR_TYPE_DETAILS_VIEW)), GTK_MENU_SHELL (submenu)); + G_OBJECT (window), window->view_type == THUNAR_TYPE_DETAILS_VIEW, + GTK_MENU_SHELL (submenu)); xfce_gtk_toggle_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_VIEW_AS_COMPACT_LIST), - G_OBJECT (window), exo_str_is_equal (last_view, g_type_name (THUNAR_TYPE_COMPACT_VIEW)), GTK_MENU_SHELL (submenu)); - g_free (last_view); + G_OBJECT (window), window->view_type == THUNAR_TYPE_COMPACT_VIEW, + GTK_MENU_SHELL (submenu)); gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu), GTK_WIDGET (submenu)); gtk_widget_show_all (GTK_WIDGET (submenu)); @@ -1633,6 +1658,7 @@ thunar_window_notebook_switch_page (GtkWidget *notebook, /* activate new view */ window->view = page; + window->view_type = G_OBJECT_TYPE (page); /* connect to the new history */ history = thunar_standard_view_get_history (THUNAR_STANDARD_VIEW (window->view)); @@ -2599,40 +2625,42 @@ static void thunar_window_action_view_changed (ThunarWindow *window, GType view_type) { - ThunarFile *file = NULL; - ThunarFile *current_directory = NULL; - GtkWidget *old_view; - ThunarHistory *history; - GList *selected_files = NULL; + ThunarFile *file = NULL; + ThunarFile *current_directory = NULL; + GtkWidget *old_view; + ThunarHistory *history; + GList *selected_files = NULL; + ThunarFileViewSettings settings; - /* drop the previous view (if any) */ + _thunar_return_if_fail (window->view != NULL); + _thunar_return_if_fail (thunar_navigator_get_current_directory (THUNAR_NAVIGATOR (window->view)) + == window->current_directory); + + /* save the previous view */ old_view = window->view; - if (G_LIKELY (window->view != NULL)) + + /* save the history */ + if (window->signal_handler_id_history_changed != 0) { - if (window->signal_handler_id_history_changed != 0) - { - history = thunar_standard_view_get_history (THUNAR_STANDARD_VIEW (window->view)); - g_signal_handler_disconnect (history, window->signal_handler_id_history_changed); - window->signal_handler_id_history_changed = 0; - } + history = thunar_standard_view_get_history (THUNAR_STANDARD_VIEW (window->view)); + g_signal_handler_disconnect (history, window->signal_handler_id_history_changed); + window->signal_handler_id_history_changed = 0; + } - /* get first visible file in the previous view */ - if (!thunar_view_get_visible_range (THUNAR_VIEW (window->view), &file, NULL)) - file = NULL; + /* get first visible file in the previous view */ + if (!thunar_view_get_visible_range (THUNAR_VIEW (window->view), &file, NULL)) + file = NULL; - /* store the active directory */ - current_directory = thunar_navigator_get_current_directory (THUNAR_NAVIGATOR (window->view)); - if (current_directory != NULL) - g_object_ref (current_directory); + /* store the active directory */ + current_directory = window->current_directory; + if (current_directory != NULL) + g_object_ref (current_directory); - /* remember the file selection */ - selected_files = thunar_g_file_list_copy (thunar_component_get_selected_files (THUNAR_COMPONENT (old_view))); - } - window->view_type = view_type; + /* remember the file selection */ + selected_files = thunar_g_file_list_copy (thunar_component_get_selected_files (THUNAR_COMPONENT (old_view))); - /* always open a new directory */ - if (current_directory == NULL && window->current_directory != NULL) - current_directory = g_object_ref (window->current_directory); + /* set the new view type */ + window->view_type = view_type; /* allocate a new view of the requested type */ if (G_LIKELY (window->view_type != G_TYPE_NONE)) @@ -2652,16 +2680,25 @@ thunar_window_action_view_changed (ThunarWindow *window, } /* destroy the old view */ - if (old_view != NULL) + if (G_LIKELY (old_view != NULL)) gtk_widget_destroy (old_view); /* restore the file selection */ thunar_component_set_selected_files (THUNAR_COMPONENT (window->view), selected_files); thunar_g_file_list_free (selected_files); - /* remember the setting */ - if (gtk_widget_get_visible (GTK_WIDGET (window)) && window->view_type != G_TYPE_NONE) - g_object_set (G_OBJECT (window->preferences), "last-view", g_type_name (window->view_type), NULL); + /* remember the view type */ + if (window->save_view) + { + settings.view_type = g_type_name (view_type); + thunar_file_set_view_settings (window->current_directory, &settings); + } + else + { + window->shared_view_type = view_type; + if (gtk_widget_get_visible (GTK_WIDGET (window)) && view_type != G_TYPE_NONE) + g_object_set (G_OBJECT (window->preferences), "last-view", g_type_name (view_type), NULL); + } /* release the file references */ if (G_UNLIKELY (file != NULL)) @@ -3156,6 +3193,42 @@ thunar_window_action_show_hidden (ThunarWindow *window) +static void +thunar_window_action_save_view (ThunarWindow *window) +{ + GType type; + ThunarFileViewSettings settings; + + _thunar_return_if_fail (THUNAR_IS_WINDOW (window)); + + window->save_view = !window->save_view; + + /* find the correct view type */ + type = G_TYPE_NONE; + if (window->save_view) + { + thunar_file_get_view_settings (window->current_directory, &settings); + if (settings.view_type != NULL) + { + if (exo_str_is_equal (settings.view_type, g_type_name (THUNAR_TYPE_ICON_VIEW))) + type = THUNAR_TYPE_ICON_VIEW; + else if (exo_str_is_equal (settings.view_type, g_type_name (THUNAR_TYPE_DETAILS_VIEW))) + type = THUNAR_TYPE_DETAILS_VIEW; + else if (exo_str_is_equal (settings.view_type, g_type_name (THUNAR_TYPE_COMPACT_VIEW))) + type = THUNAR_TYPE_COMPACT_VIEW; + } + } + if (type == G_TYPE_NONE) + type = window->shared_view_type; + + /* switch to the selected view type */ + thunar_window_action_view_changed (window, type); + + g_object_set (G_OBJECT (window->preferences), "last-save-view", window->save_view, NULL); +} + + + static void thunar_window_current_directory_changed (ThunarFile *current_directory, ThunarWindow *window) @@ -3436,8 +3509,9 @@ void thunar_window_set_current_directory (ThunarWindow *window, ThunarFile *current_directory) { - GType type; - gchar *type_name; + GType type; + gchar *type_name; + ThunarFileViewSettings settings; _thunar_return_if_fail (THUNAR_IS_WINDOW (window)); _thunar_return_if_fail (current_directory == NULL || THUNAR_IS_FILE (current_directory)); @@ -3464,26 +3538,36 @@ thunar_window_set_current_directory (ThunarWindow *window, g_signal_connect (G_OBJECT (current_directory), "changed", G_CALLBACK (thunar_window_current_directory_changed), window); g_object_ref (G_OBJECT (current_directory)); - /* create a new view if the window is new */ - if (gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook)) == 0) + /* find the required view type */ + type = G_TYPE_NONE; + if (window->save_view) { - /* determine the default view */ - g_object_get (G_OBJECT (window->preferences), "default-view", &type_name, NULL); - type = g_type_from_name (type_name); - g_free (type_name); - - /* determine the last selected view if the last selected view preference is not selected */ - if (g_type_is_a (type, G_TYPE_NONE)) + thunar_file_get_view_settings (current_directory, &settings); + if (settings.view_type != NULL) { - g_object_get (G_OBJECT (window->preferences), "last-view", &type_name, NULL); - type = g_type_from_name (type_name); - g_free (type_name); - - /* fallback, in nothing was set */ - if (g_type_is_a (type, G_TYPE_NONE)) + if (exo_str_is_equal (settings.view_type, g_type_name (THUNAR_TYPE_ICON_VIEW))) type = THUNAR_TYPE_ICON_VIEW; + else if (exo_str_is_equal (settings.view_type, g_type_name (THUNAR_TYPE_DETAILS_VIEW))) + type = THUNAR_TYPE_DETAILS_VIEW; + else if (exo_str_is_equal (settings.view_type, g_type_name (THUNAR_TYPE_COMPACT_VIEW))) + type = THUNAR_TYPE_COMPACT_VIEW; } - thunar_window_action_view_changed (window, window->view_type); + } + if (type == G_TYPE_NONE) + type = window->shared_view_type; + + /* create a new view if the window is new */ + if (gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook)) == 0) + { + window->view_type = type; + thunar_window_notebook_insert (window, current_directory); + } + + /* if there is an active view, switch to the correct type of view */ + if (window->view != NULL && G_OBJECT_TYPE (window->view) != type) + { + thunar_navigator_set_current_directory (THUNAR_NAVIGATOR (window->view), current_directory); + thunar_window_action_view_changed (window, type); } /* update window icon and title */ diff --git a/thunar/thunar-window.h b/thunar/thunar-window.h index 5b595d6f..b4e9039f 100644 --- a/thunar/thunar-window.h +++ b/thunar/thunar-window.h @@ -63,6 +63,7 @@ typedef enum THUNAR_WINDOW_ACTION_VIEW_STATUSBAR, THUNAR_WINDOW_ACTION_VIEW_MENUBAR, THUNAR_WINDOW_ACTION_SHOW_HIDDEN, + THUNAR_WINDOW_ACTION_SAVE_VIEW, THUNAR_WINDOW_ACTION_ZOOM_IN, THUNAR_WINDOW_ACTION_ZOOM_IN_ALT, THUNAR_WINDOW_ACTION_ZOOM_OUT, -- 2.25.1