From 92f6fd493cc9b33894607f758fa01fddf4cb73a7 Mon Sep 17 00:00:00 2001 From: Andrew Date: Sun, 13 Oct 2013 23:33:13 +0300 Subject: [PATCH] Option to display items count in directory instead its size --- thunar/thunar-file.c | 71 ++++++++++++++++++++- thunar/thunar-file.h | 3 + thunar/thunar-list-model.c | 122 ++++++++++++++++++++++++++++++++++++- thunar/thunar-preferences-dialog.c | 7 ++- thunar/thunar-preferences.c | 11 ++++ thunar/thunar-standard-view.c | 1 + 6 files changed, 210 insertions(+), 5 deletions(-) diff --git a/thunar/thunar-file.c b/thunar/thunar-file.c index 0878817..ba5bbaa 100644 --- a/thunar/thunar-file.c +++ b/thunar/thunar-file.c @@ -178,6 +178,10 @@ struct _ThunarFile /* flags for thumbnail state etc */ ThunarFileFlags flags; + + /* caching directory items count */ + guint32 item_count; + guint64 item_count_cached_date; }; typedef struct @@ -809,6 +813,9 @@ thunar_file_info_clear (ThunarFile *file) /* free thumbnail path */ g_free (file->thumbnail_path); file->thumbnail_path = NULL; + + /* reset time stamp for directory items count caching */ + file->item_count_cached_date = 0; /* assume the file is mounted by default */ FLAG_SET (file, THUNAR_FILE_FLAG_IS_MOUNTED); @@ -948,7 +955,10 @@ thunar_file_info_reload (ThunarFile *file, file->collate_key_nocase = g_utf8_collate_key_for_filename (casefold, -1); else file->collate_key_nocase = file->collate_key; - + + /* reset time stamp for directory items count caching */ + file->item_count_cached_date = 0; + /* cleanup */ g_free (casefold); } @@ -3031,6 +3041,65 @@ thunar_file_get_item_count (const ThunarFile *file) /** + * thunar_file_get_dir_item_count: + * @file : a #ThunarFile instance. + * @count : place to store directory items count. + * + * Returns the number of items in the directory, fails if @file is + * local file or symlink. + * + * Return value: %TRUE if operation was successful. + **/ +gboolean +thunar_file_get_dir_item_count(ThunarFile* file, + guint32* count) +{ + GFileInfo *info; + GFileEnumerator *enumerator; + GFileInfo *child_info; + guint64 date; + + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); + + if (!thunar_file_is_local (file)) + return FALSE; + if (thunar_file_is_symlink (file)) + return FALSE; + + info = g_file_query_info (file->gfile, G_FILE_ATTRIBUTE_TIME_CHANGED, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, NULL); + date = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_CHANGED); + g_object_unref (G_OBJECT(info)); + + if (date != file->item_count_cached_date) + { + enumerator = g_file_enumerate_children (file->gfile, NULL, + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, + NULL, NULL); + if(!enumerator) + return FALSE; + + *count = 0; + child_info = g_file_enumerator_next_file (enumerator, NULL, NULL); + while (child_info) + { + ++*count; + g_object_unref (child_info); + child_info = g_file_enumerator_next_file (enumerator, NULL, NULL); + } + g_file_enumerator_close (enumerator, NULL, NULL); + g_object_unref (enumerator); + + file->item_count = *count; + file->item_count_cached_date = date; + } + else + *count = file->item_count; + return TRUE; +} + + + +/** * thunar_file_is_chmodable: * @file : a #ThunarFile instance. * diff --git a/thunar/thunar-file.h b/thunar/thunar-file.h index 74ed6f8..17425a9 100644 --- a/thunar/thunar-file.h +++ b/thunar/thunar-file.h @@ -209,6 +209,9 @@ gchar *thunar_file_get_deletion_date (const ThunarFile *file ThunarDateStyle date_style) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; const gchar *thunar_file_get_original_path (const ThunarFile *file); guint32 thunar_file_get_item_count (const ThunarFile *file); +/* name 'thunar_file_get_item_count' is already taken */ +gboolean thunar_file_get_dir_item_count (ThunarFile* file, + guint32* count); gboolean thunar_file_is_chmodable (const ThunarFile *file); gboolean thunar_file_is_renameable (const ThunarFile *file); diff --git a/thunar/thunar-list-model.c b/thunar/thunar-list-model.c index 33b36fd..277b40a 100644 --- a/thunar/thunar-list-model.c +++ b/thunar/thunar-list-model.c @@ -31,6 +31,7 @@ #endif #include +#include #include #include #include @@ -50,6 +51,7 @@ enum PROP_FOLDERS_FIRST, PROP_NUM_FILES, PROP_SHOW_HIDDEN, + PROP_ITEMS_COUNT_AS_DIR_SIZE, N_PROPERTIES }; @@ -171,6 +173,9 @@ static gint sort_by_permissions (const ThunarF static gint sort_by_size (const ThunarFile *a, const ThunarFile *b, gboolean case_sensitive); +static gint sort_by_size_and_items_count (const ThunarFile *a, + const ThunarFile *b, + gboolean case_sensitive); static gint sort_by_type (const ThunarFile *a, const ThunarFile *b, gboolean case_sensitive); @@ -184,6 +189,9 @@ static void thunar_list_model_set_date_style (ThunarListMod static gint thunar_list_model_get_num_files (ThunarListModel *store); static gboolean thunar_list_model_get_folders_first (ThunarListModel *store); +static gboolean thunar_list_model_get_items_count_as_dir_size (ThunarListModel *store); +static void thunar_list_model_set_items_count_as_dir_size (ThunarListModel *store, + gboolean items_count); struct _ThunarListModelClass { @@ -210,6 +218,7 @@ struct _ThunarListModel GSList *hidden; ThunarFolder *folder; gboolean show_hidden : 1; + gboolean items_count_as_dir_size : 1; ThunarDateStyle date_style; /* Use the shared ThunarFileMonitor instance, so we @@ -327,6 +336,15 @@ thunar_list_model_class_init (ThunarListModelClass *klass) "show-hidden", FALSE, EXO_PARAM_READWRITE); + /** + * ThunarListModel:items-count-as-dir-size: + **/ + list_model_props[PROP_ITEMS_COUNT_AS_DIR_SIZE] = + g_param_spec_boolean ("items-count-as-dir-size", + "items-count-as-dir-size", + "items-count-as-dir-size", + TRUE, + EXO_PARAM_READWRITE); /* install properties */ g_object_class_install_properties (gobject_class, N_PROPERTIES, list_model_props); @@ -479,6 +497,10 @@ thunar_list_model_get_property (GObject *object, g_value_set_boolean (value, thunar_list_model_get_show_hidden (store)); break; + case PROP_ITEMS_COUNT_AS_DIR_SIZE: + g_value_set_boolean (value, thunar_list_model_get_items_count_as_dir_size (store)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -517,6 +539,10 @@ thunar_list_model_set_property (GObject *object, thunar_list_model_set_show_hidden (store, g_value_get_boolean (value)); break; + case PROP_ITEMS_COUNT_AS_DIR_SIZE: + thunar_list_model_set_items_count_as_dir_size (store, g_value_get_boolean (value)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -646,6 +672,7 @@ thunar_list_model_get_value (GtkTreeModel *model, ThunarUser *user; ThunarFile *file; gchar *str; + guint32 item_count; _thunar_return_if_fail (THUNAR_IS_LIST_MODEL (model)); _thunar_return_if_fail (iter->stamp == (THUNAR_LIST_MODEL (model))->stamp); @@ -716,7 +743,16 @@ thunar_list_model_get_value (GtkTreeModel *model, case THUNAR_COLUMN_SIZE: g_value_init (value, G_TYPE_STRING); - g_value_take_string (value, thunar_file_get_size_string (file)); + if (THUNAR_LIST_MODEL (model)->items_count_as_dir_size + && thunar_file_is_directory(file) && thunar_file_get_dir_item_count(file, &item_count)) + { + if (item_count > 0) + g_value_take_string (value, g_strdup_printf (ngettext ("%u item", "%u items", item_count), item_count)); + else + g_value_take_string (value, g_strdup (_("empty"))); + } + else + g_value_take_string (value, thunar_file_get_size_string (file)); break; case THUNAR_COLUMN_TYPE: @@ -876,7 +912,7 @@ thunar_list_model_get_sort_column_id (GtkTreeSortable *sortable, *sort_column_id = THUNAR_COLUMN_NAME; else if (store->sort_func == sort_by_permissions) *sort_column_id = THUNAR_COLUMN_PERMISSIONS; - else if (store->sort_func == sort_by_size) + else if (store->sort_func == sort_by_size || store->sort_func == sort_by_size_and_items_count) *sort_column_id = THUNAR_COLUMN_SIZE; else if (store->sort_func == sort_by_date_accessed) *sort_column_id = THUNAR_COLUMN_DATE_ACCESSED; @@ -945,7 +981,7 @@ thunar_list_model_set_sort_column_id (GtkTreeSortable *sortable, break; case THUNAR_COLUMN_SIZE: - store->sort_func = sort_by_size; + store->sort_func = store->items_count_as_dir_size ? sort_by_size_and_items_count : sort_by_size; break; case THUNAR_COLUMN_TYPE: @@ -1532,6 +1568,39 @@ sort_by_size (const ThunarFile *a, static gint +sort_by_size_and_items_count (const ThunarFile *a, + const ThunarFile *b, + gboolean case_sensitive) +{ + guint32 count_a, count_b; + gboolean succ_a, succ_b; + + if (thunar_file_is_directory(a) && thunar_file_is_directory(b)) + { + /* dirty cast */ + succ_a = thunar_file_get_dir_item_count ((ThunarFile*)a, &count_a); + succ_b = thunar_file_get_dir_item_count ((ThunarFile*)b, &count_b); + + if (succ_a && succ_b) + { + if (count_a < count_b) + return -1; + else if (count_a > count_b) + return 1; + return thunar_file_compare_by_name (a, b, case_sensitive); + } + else if (succ_a) + return 1; + else if (succ_b) + return -1; + } + + return sort_by_size(a, b, case_sensitive); +} + + + +static gint sort_by_type (const ThunarFile *a, const ThunarFile *b, gboolean case_sensitive) @@ -1966,6 +2035,53 @@ thunar_list_model_set_show_hidden (ThunarListModel *store, /** + * thunar_list_model_get_items_count_as_dir_size: + * @store : a #ThunarListModel. + * + * Return value: %TRUE if items count in directory will be shown as + * directory size, else %FALSE. + **/ +static gboolean +thunar_list_model_get_items_count_as_dir_size (ThunarListModel *store) +{ + _thunar_return_val_if_fail (THUNAR_IS_LIST_MODEL (store), FALSE); + return store->items_count_as_dir_size; +} + + + +/** + * thunar_list_model_set_items_count_as_dir_size: + * @store : a #ThunarListModel. + * @count_as_dir_size : %TRUE if items count in directory will be shown + * as directory size, else %FALSE. + **/ +void +thunar_list_model_set_items_count_as_dir_size (ThunarListModel *store, + gboolean count_as_dir_size) +{ + _thunar_return_if_fail (THUNAR_IS_LIST_MODEL (store)); + + /* check if the new setting differs */ + if (store->items_count_as_dir_size == count_as_dir_size) + return; + + store->items_count_as_dir_size = count_as_dir_size; + g_object_notify_by_pspec (G_OBJECT (store), list_model_props[PROP_ITEMS_COUNT_AS_DIR_SIZE]); + + gtk_tree_model_foreach (GTK_TREE_MODEL (store), (GtkTreeModelForeachFunc) gtk_tree_model_row_changed, NULL); + + /* re-sorting the store if needed */ + if (store->sort_func == sort_by_size || store->sort_func == sort_by_size_and_items_count) + { + store->sort_func = store->items_count_as_dir_size ? sort_by_size_and_items_count : sort_by_size; + thunar_list_model_sort (store); + } +} + + + +/** * thunar_list_model_get_file: * @store : a #ThunarListModel. * @iter : a valid #GtkTreeIter for @store. diff --git a/thunar/thunar-preferences-dialog.c b/thunar/thunar-preferences-dialog.c index 162b902..2da1c94 100644 --- a/thunar/thunar-preferences-dialog.c +++ b/thunar/thunar-preferences-dialog.c @@ -254,7 +254,7 @@ thunar_preferences_dialog_init (ThunarPreferencesDialog *dialog) gtk_frame_set_label_widget (GTK_FRAME (frame), label); gtk_widget_show (label); - table = gtk_table_new (3, 2, FALSE); + table = gtk_table_new (4, 2, FALSE); gtk_table_set_row_spacings (GTK_TABLE (table), 6); gtk_table_set_col_spacings (GTK_TABLE (table), 12); gtk_container_set_border_width (GTK_CONTAINER (table), 12); @@ -300,6 +300,11 @@ thunar_preferences_dialog_init (ThunarPreferencesDialog *dialog) gtk_table_attach (GTK_TABLE (table), button, 0, 2, 2, 3, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0); gtk_widget_show (button); + button = gtk_check_button_new_with_mnemonic (_("Display number of files in size column for folders")); + exo_mutual_binding_new (G_OBJECT (dialog->preferences), "misc-items-count-as-dir-size", G_OBJECT (button), "active"); + gtk_table_attach (GTK_TABLE (table), button, 0, 2, 3, 4, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0); + gtk_widget_show (button); + frame = g_object_new (GTK_TYPE_FRAME, "border-width", 0, "shadow-type", GTK_SHADOW_NONE, NULL); gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0); gtk_widget_show (frame); diff --git a/thunar/thunar-preferences.c b/thunar/thunar-preferences.c index 41c07d8..ce71fc9 100644 --- a/thunar/thunar-preferences.c +++ b/thunar/thunar-preferences.c @@ -76,6 +76,7 @@ enum PROP_MISC_CASE_SENSITIVE, PROP_MISC_DATE_STYLE, PROP_MISC_FOLDERS_FIRST, + PROP_MISC_ITEMS_COUNT_AS_DIR_SIZE, PROP_MISC_FULL_PATH_IN_TITLE, PROP_MISC_HORIZONTAL_WHEEL_NAVIGATES, PROP_MISC_IMAGE_SIZE_IN_STATUSBAR, @@ -503,6 +504,16 @@ thunar_preferences_class_init (ThunarPreferencesClass *klass) EXO_PARAM_READWRITE); /** + * ThunarPreferences:misc-folders-first: + **/ + preferences_props[PROP_MISC_ITEMS_COUNT_AS_DIR_SIZE] = + g_param_spec_boolean ("misc-items-count-as-dir-size", + "MiscItemsCountAsDirSize", + NULL, + TRUE, + EXO_PARAM_READWRITE); + + /** * ThunarPreferences:misc-full-path-in-title: * * Show the full directory path in the window title, instead of diff --git a/thunar/thunar-standard-view.c b/thunar/thunar-standard-view.c index ad4af3a..524c64e 100644 --- a/thunar/thunar-standard-view.c +++ b/thunar/thunar-standard-view.c @@ -693,6 +693,7 @@ thunar_standard_view_init (ThunarStandardView *standard_view) exo_binding_new (G_OBJECT (standard_view->preferences), "misc-case-sensitive", G_OBJECT (standard_view->model), "case-sensitive"); exo_binding_new (G_OBJECT (standard_view->preferences), "misc-date-style", G_OBJECT (standard_view->model), "date-style"); exo_binding_new (G_OBJECT (standard_view->preferences), "misc-folders-first", G_OBJECT (standard_view->model), "folders-first"); + exo_binding_new (G_OBJECT (standard_view->preferences), "misc-items-count-as-dir-size", G_OBJECT (standard_view->model), "items-count-as-dir-size"); /* setup the icon renderer */ standard_view->icon_renderer = thunar_icon_renderer_new (); -- 1.8.4