summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libcaja-private/caja-metadata.c1
-rw-r--r--libcaja-private/caja-metadata.h1
-rw-r--r--src/file-manager/fm-list-view.c199
3 files changed, 200 insertions, 1 deletions
diff --git a/libcaja-private/caja-metadata.c b/libcaja-private/caja-metadata.c
index c7c62e86..42d5763d 100644
--- a/libcaja-private/caja-metadata.c
+++ b/libcaja-private/caja-metadata.c
@@ -42,6 +42,7 @@ static char *used_metadata_names[] =
CAJA_METADATA_KEY_LIST_VIEW_SORT_REVERSED,
CAJA_METADATA_KEY_LIST_VIEW_VISIBLE_COLUMNS,
CAJA_METADATA_KEY_LIST_VIEW_COLUMN_ORDER,
+ CAJA_METADATA_KEY_LIST_VIEW_COLUMN_WIDTHS,
CAJA_METADATA_KEY_COMPACT_VIEW_ZOOM_LEVEL,
CAJA_METADATA_KEY_WINDOW_GEOMETRY,
CAJA_METADATA_KEY_WINDOW_SCROLL_POSITION,
diff --git a/libcaja-private/caja-metadata.h b/libcaja-private/caja-metadata.h
index e953b78e..060ac8ca 100644
--- a/libcaja-private/caja-metadata.h
+++ b/libcaja-private/caja-metadata.h
@@ -53,6 +53,7 @@
#define CAJA_METADATA_KEY_LIST_VIEW_SORT_REVERSED "caja-list-view-sort-reversed"
#define CAJA_METADATA_KEY_LIST_VIEW_VISIBLE_COLUMNS "caja-list-view-visible-columns"
#define CAJA_METADATA_KEY_LIST_VIEW_COLUMN_ORDER "caja-list-view-column-order"
+#define CAJA_METADATA_KEY_LIST_VIEW_COLUMN_WIDTHS "caja-list-view-column-widths"
#define CAJA_METADATA_KEY_COMPACT_VIEW_ZOOM_LEVEL "caja-compact-view-zoom-level"
diff --git a/src/file-manager/fm-list-view.c b/src/file-manager/fm-list-view.c
index 57b5862c..a5ccd675 100644
--- a/src/file-manager/fm-list-view.c
+++ b/src/file-manager/fm-list-view.c
@@ -115,6 +115,8 @@ struct FMListViewDetails
gulong clipboard_handler_id;
GQuark last_sort_attr;
+
+ guint column_width_save_id;
};
struct SelectionForeachData
@@ -149,6 +151,12 @@ static void fm_list_view_scale_font_size (FMListView *v
static void fm_list_view_scroll_to_file (FMListView *view,
CajaFile *file);
static void fm_list_view_iface_init (CajaViewIface *iface);
+static void column_width_changed_callback (GtkTreeViewColumn *column,
+ GParamSpec *pspec,
+ FMListView *view);
+static void block_column_width_signals (FMListView *list_view,
+ gboolean block);
+static void apply_column_widths (FMListView *list_view);
static void fm_list_view_rename_callback (CajaFile *file,
GFile *result_location,
GError *error,
@@ -1557,7 +1565,10 @@ apply_columns_settings (FMListView *list_view,
view_columns = g_list_reverse (view_columns);
- /* hide columns that are not present in the configuration */
+ block_column_width_signals (list_view, TRUE);
+
+ /* hide columns that are not present in the configuration and
+ * reset size so the columns auto-expand by default */
old_view_columns = gtk_tree_view_get_columns (list_view->details->tree_view);
for (l = old_view_columns; l != NULL; l = l->next)
{
@@ -1565,6 +1576,7 @@ apply_columns_settings (FMListView *list_view,
{
gtk_tree_view_column_set_visible (l->data, FALSE);
}
+ gtk_tree_view_column_set_fixed_width (l->data, -1);
}
g_list_free (old_view_columns);
@@ -1582,6 +1594,12 @@ apply_columns_settings (FMListView *list_view,
prev_view_column = l->data;
}
g_list_free (view_columns);
+
+ gtk_tree_view_column_set_expand (list_view->details->file_name_column, TRUE);
+
+ apply_column_widths (list_view);
+
+ block_column_width_signals (list_view, FALSE);
}
static void
@@ -1882,6 +1900,9 @@ create_and_set_up_tree_view (FMListView *view)
gtk_tree_view_column_set_cell_data_func (view->details->file_name_column, cell,
(GtkTreeCellDataFunc) filename_cell_data_func,
view, NULL);
+
+ g_signal_connect (view->details->file_name_column, "notify::fixed-width",
+ G_CALLBACK (column_width_changed_callback), view);
}
else
{
@@ -1900,6 +1921,9 @@ create_and_set_up_tree_view (FMListView *view)
column);
gtk_tree_view_column_set_resizable (column, TRUE);
+
+ g_signal_connect (column, "notify::fixed-width",
+ G_CALLBACK (column_width_changed_callback), view);
}
g_free (name);
g_free (label);
@@ -2011,6 +2035,161 @@ get_column_order (FMListView *list_view)
g_strdupv (default_column_order_auto_value);
}
+/* Column widths are stored as per-directory GIO metadata in a string list of
+ * "column-name:width" entries (e.g. ["name:300", "size:80"]). GIO metadata
+ * only supports string lists, so we encode the name-width pairs this way and
+ * parse them back into a hash table here. */
+static GHashTable *
+get_column_widths (FMListView *list_view)
+{
+ CajaFile *file;
+ GList *column_widths;
+ GHashTable *widths;
+
+ file = fm_directory_view_get_directory_as_file (FM_DIRECTORY_VIEW (list_view));
+
+ column_widths = caja_file_get_metadata_list
+ (file,
+ CAJA_METADATA_KEY_LIST_VIEW_COLUMN_WIDTHS);
+
+ widths = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+ if (column_widths)
+ {
+ GList *l;
+
+ for (l = column_widths; l != NULL; l = l->next)
+ {
+ char name[256];
+ int width;
+
+ /* Parse "column-name:width" entries */
+ if (sscanf (l->data, "%255[^:]:%d", name, &width) == 2 && width > 0)
+ {
+ g_hash_table_insert (widths,
+ g_strdup (name),
+ GINT_TO_POINTER (width));
+ }
+ g_free (l->data);
+ }
+ g_list_free (column_widths);
+ }
+
+ return widths;
+}
+
+static gboolean
+save_column_widths_idle (gpointer data)
+{
+ FMListView *list_view = FM_LIST_VIEW (data);
+ CajaFile *file;
+ GHashTableIter iter;
+ gpointer key, value;
+ GList *width_list;
+
+ list_view->details->column_width_save_id = 0;
+
+ file = fm_directory_view_get_directory_as_file (FM_DIRECTORY_VIEW (list_view));
+ if (file == NULL)
+ {
+ return G_SOURCE_REMOVE;
+ }
+
+ width_list = NULL;
+
+ g_hash_table_iter_init (&iter, list_view->details->columns);
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ {
+ GtkTreeViewColumn *column = value;
+ int width;
+
+ if (!gtk_tree_view_column_get_visible (column))
+ {
+ continue;
+ }
+
+ width = gtk_tree_view_column_get_width (column);
+ if (width > 0)
+ {
+ char *entry = g_strdup_printf ("%s:%d", (char *) key, width);
+ width_list = g_list_prepend (width_list, entry);
+ }
+ }
+
+ width_list = g_list_reverse (width_list);
+ caja_file_set_metadata_list (file,
+ CAJA_METADATA_KEY_LIST_VIEW_COLUMN_WIDTHS,
+ width_list);
+
+ g_list_free_full (width_list, g_free);
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+block_column_width_signals (FMListView *list_view,
+ gboolean block)
+{
+ GHashTableIter iter;
+ gpointer value;
+
+ g_hash_table_iter_init (&iter, list_view->details->columns);
+ while (g_hash_table_iter_next (&iter, NULL, &value))
+ {
+ if (block)
+ g_signal_handlers_block_by_func (value, column_width_changed_callback, list_view);
+ else
+ g_signal_handlers_unblock_by_func (value, column_width_changed_callback, list_view);
+ }
+}
+
+static void
+column_width_changed_callback (GtkTreeViewColumn *column,
+ GParamSpec *pspec,
+ FMListView *view)
+{
+ if (view->details->column_width_save_id == 0)
+ {
+ view->details->column_width_save_id =
+ g_idle_add (save_column_widths_idle, view);
+ }
+}
+
+static void
+apply_column_widths (FMListView *list_view)
+{
+ GHashTable *widths;
+ GHashTableIter iter;
+ gpointer key, value;
+
+ widths = get_column_widths (list_view);
+
+ if (g_hash_table_size (widths) == 0)
+ {
+ g_hash_table_destroy (widths);
+ return;
+ }
+
+ g_hash_table_iter_init (&iter, list_view->details->columns);
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ {
+ GtkTreeViewColumn *column = value;
+ gpointer width;
+
+ if (g_hash_table_lookup_extended (widths, key, NULL, &width))
+ {
+ gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
+ gtk_tree_view_column_set_fixed_width (column, GPOINTER_TO_INT (width));
+ }
+ }
+
+ /* When we have saved widths, disable expand on the name column
+ * so the saved widths are respected */
+ gtk_tree_view_column_set_expand (list_view->details->file_name_column, FALSE);
+
+ g_hash_table_destroy (widths);
+}
+
static void
set_columns_settings_from_metadata_and_preferences (FMListView *list_view)
{
@@ -2574,6 +2753,7 @@ column_chooser_use_default_callback (CajaColumnChooser *chooser,
caja_file_set_metadata_list (file, CAJA_METADATA_KEY_LIST_VIEW_COLUMN_ORDER, NULL);
caja_file_set_metadata_list (file, CAJA_METADATA_KEY_LIST_VIEW_VISIBLE_COLUMNS, NULL);
+ caja_file_set_metadata_list (file, CAJA_METADATA_KEY_LIST_VIEW_COLUMN_WIDTHS, NULL);
/* set view values ourselves, as new metadata could not have been
* updated yet.
@@ -2776,6 +2956,7 @@ fm_list_view_reset_to_defaults (FMDirectoryView *view)
caja_file_set_metadata (file, CAJA_METADATA_KEY_LIST_VIEW_ZOOM_LEVEL, NULL, NULL);
caja_file_set_metadata_list (file, CAJA_METADATA_KEY_LIST_VIEW_COLUMN_ORDER, NULL);
caja_file_set_metadata_list (file, CAJA_METADATA_KEY_LIST_VIEW_VISIBLE_COLUMNS, NULL);
+ caja_file_set_metadata_list (file, CAJA_METADATA_KEY_LIST_VIEW_COLUMN_WIDTHS, NULL);
default_sort_order = get_default_sort_order (file, &default_sort_reversed);
@@ -2787,6 +2968,12 @@ fm_list_view_reset_to_defaults (FMDirectoryView *view)
fm_list_view_set_zoom_level (FM_LIST_VIEW (view), get_default_zoom_level (), FALSE);
set_columns_settings_from_metadata_and_preferences (FM_LIST_VIEW (view));
+
+ /* FIXME: Column widths are not visually updated until the next directory
+ * reload. GTK's cell area context retains cached preferred widths and
+ * GtkTreeViewColumn's internal fixed_width (set during user resize)
+ * persists across layout passes, preventing columns from shrinking.
+ * Metadata is cleared anyway, so the next load will use default size. */
}
static void
@@ -2878,6 +3065,10 @@ fm_list_view_set_zoom_level (FMListView *view,
/* FIXME: https://bugzilla.gnome.org/show_bug.cgi?id=641518 */
gtk_tree_view_columns_autosize (view->details->tree_view);
+ block_column_width_signals (view, TRUE);
+ apply_column_widths (view);
+ block_column_width_signals (view, FALSE);
+
fm_directory_view_update_menus (FM_DIRECTORY_VIEW (view));
gtk_tree_model_foreach (GTK_TREE_MODEL (view->details->model), list_view_changed_foreach, NULL);
@@ -3156,6 +3347,12 @@ fm_list_view_dispose (GObject *object)
list_view->details->drag_dest = NULL;
}
+ if (list_view->details->column_width_save_id != 0)
+ {
+ g_source_remove (list_view->details->column_width_save_id);
+ list_view->details->column_width_save_id = 0;
+ }
+
if (list_view->details->renaming_file_activate_timeout != 0)
{
g_source_remove (list_view->details->renaming_file_activate_timeout);