diff -rupN Thunar-1.6.3.old/thunar/thunar-file.c Thunar-1.6.3.new/thunar/thunar-file.c --- Thunar-1.6.3.old/thunar/thunar-file.c 2015-05-24 18:12:21.504226485 +0200 +++ Thunar-1.6.3.new/thunar/thunar-file.c 2015-05-24 18:05:20.328238133 +0200 @@ -57,11 +57,13 @@ #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -69,7 +71,6 @@ #include - /* Dump the file cache every X second, set to 0 to disable */ #define DUMP_FILE_CACHE 0 @@ -114,8 +115,19 @@ static gboolean thunar_file_lo static gboolean thunar_file_is_readable (const ThunarFile *file); static gboolean thunar_file_same_filesystem (const ThunarFile *file_a, const ThunarFile *file_b); - - +static void thunar_file_calc_recursive_size_start (ThunarFile *file, + ThunarListModel *store); +static void thunar_file_calc_recursive_size_error (ExoJob *deep_count_job, + const GError *error, + ThunarFile *file); +static void thunar_file_calc_recursive_size_finished (ExoJob *deep_count_job, + ThunarFile *file); +static void thunar_file_calc_recursive_size_update (ThunarDeepCountJob *deep_count_job, + guint64 total_size, + guint file_count, + guint directory_count, + guint unreadable_directory_count, + ThunarFile *file); G_LOCK_DEFINE_STATIC (file_cache_mutex); G_LOCK_DEFINE_STATIC (file_content_type_mutex); @@ -148,6 +160,15 @@ typedef enum } ThunarFileFlags; +typedef enum +{ + JOB_STATUS_NOT_STARTED_YET, + JOB_STATUS_UNDEFINED, + JOB_STATUS_COUNTING, + JOB_STATUS_FINISHED +} +DeepCountJobStatus; + struct _ThunarFileClass { GObjectClass __parent__; @@ -172,6 +193,15 @@ struct _ThunarFile gchar *basename; gchar *thumbnail_path; + /* for size calculation if file is a folder */ + ThunarDeepCountJob *deep_count_job; + DeepCountJobStatus deep_count_status; + guint64 size_recursive; + gchar *size_recursive_string; + /* Each file needs to keep a list of which models did start jobs for the file (in order to trigger GUI-updates)*/ + /* TODO: - possibilitie to run all jobs in the same thread ? */ + GSList *stores_to_update; + /* sorting */ gchar *collate_key; gchar *collate_key_nocase; @@ -397,8 +427,6 @@ thunar_file_dispose (GObject *object) (*G_OBJECT_CLASS (thunar_file_parent_class)->dispose) (object); } - - static void thunar_file_finalize (GObject *object) { @@ -434,6 +462,9 @@ thunar_file_finalize (GObject *object) g_free (file->display_name); g_free (file->basename); + /* stop recursive-size job (if any) and free variables */ + thunar_file_calc_recursive_size_cancel(file); + /* free collate keys */ if (file->collate_key_nocase != file->collate_key) g_free (file->collate_key_nocase); @@ -792,6 +823,9 @@ thunar_file_info_clear (ThunarFile *file g_free (file->basename); file->basename = NULL; + /* stop recursive-size job (if any) and free variables */ + thunar_file_calc_recursive_size_cancel(file); + /* content type */ g_free (file->content_type); file->content_type = NULL; @@ -949,6 +983,10 @@ thunar_file_info_reload (ThunarFile *f else file->collate_key_nocase = file->collate_key; + /* init variables for recursive size-check */ + thunar_file_calc_recursive_size_cancel(file); + file->deep_count_status = JOB_STATUS_NOT_STARTED_YET; + /* cleanup */ g_free (casefold); } @@ -1079,7 +1117,181 @@ thunar_file_load (ThunarFile *file, } } +/** + * thunar_file_calc_recursive_size_start: + * @file : a #ThunarFile instance. + * + * Starts a job to recursively calculate the total size of a folder and all it's sub-items + **/ +static void +thunar_file_calc_recursive_size_start (ThunarFile *file, + ThunarListModel *store) +{ + _thunar_return_if_fail (THUNAR_IS_FILE (file)); + _thunar_return_if_fail (thunar_file_is_directory(file)); + + /* cancel the pending job (if any) */ + thunar_file_calc_recursive_size_cancel(file); + + /* register store which should be updated when the calculation finished */ + file->stores_to_update = g_slist_append (file->stores_to_update, store); + + /* schedule a new job to determine the total size of the directory (not following symlinks) */ + GList *files; + files = g_list_append (files, file); + file->deep_count_job = thunar_deep_count_job_new (files, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS); + g_list_free (files); + g_signal_connect (file->deep_count_job, "error", G_CALLBACK (thunar_file_calc_recursive_size_error), file); + g_signal_connect (file->deep_count_job, "finished", G_CALLBACK (thunar_file_calc_recursive_size_finished), file); + g_signal_connect (file->deep_count_job, "status-update", G_CALLBACK (thunar_file_calc_recursive_size_update), file); + + file->deep_count_status = JOB_STATUS_COUNTING; + + /* launch the job */ + exo_job_launch (EXO_JOB (file->deep_count_job)); +} + +/** + * thunar_file_calc_recursive_size_cancel: + * @file : a #ThunarFile instance. + * + * Cancel the deep_count_job, if active + **/ +void +thunar_file_calc_recursive_size_cancel (ThunarFile *file) +{ + _thunar_return_if_fail (THUNAR_IS_FILE (file)); + if (G_UNLIKELY (file->deep_count_job != NULL)) + { + g_signal_handlers_disconnect_matched (file->deep_count_job, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, file); + exo_job_cancel (EXO_JOB (file->deep_count_job)); + g_object_unref (file->deep_count_job); + file->deep_count_job = NULL; + } + g_free (file->size_recursive_string); + file->size_recursive_string = NULL; + file->size_recursive = 0; + g_slist_free (file->stores_to_update); + file->stores_to_update = NULL; + file->deep_count_status = JOB_STATUS_UNDEFINED; +} + +/** + * thunar_file_calc_recursive_size_error: + * @deep_count_job : The job which produced the error. + * @error : The error which appeared. + * @file : a #ThunarFile instance. + * + * If any error occurs during the deep_count_job, this callback will be executed. Instead of the folder-size, the error message will be displayed + **/ +static void +thunar_file_calc_recursive_size_error (ExoJob *deep_count_job, + const GError *error, + ThunarFile *file) +{ + _thunar_return_if_fail (THUNAR_IS_JOB (deep_count_job)); + _thunar_return_if_fail (THUNAR_IS_FILE (file)); + _thunar_return_if_fail (file->deep_count_job == THUNAR_DEEP_COUNT_JOB (deep_count_job)); + file->size_recursive_string = g_strdup(error->message); + file->deep_count_status = JOB_STATUS_UNDEFINED; + /* update all registered stores */ + g_slist_foreach (file->stores_to_update, (GFunc)thunar_list_model_update, NULL); +} + +/** + * thunar_file_calc_recursive_size_finished: + * @deep_count_job : The job which got finished + * @file : a #ThunarFile instance. + * + * This callback will be executed when the deep_count_job finished + **/ +static void +thunar_file_calc_recursive_size_finished (ExoJob *deep_count_job, + ThunarFile *file) +{ + _thunar_return_if_fail (THUNAR_IS_JOB (deep_count_job)); + _thunar_return_if_fail (THUNAR_IS_FILE (file)); + _thunar_return_if_fail (file->deep_count_job == THUNAR_DEEP_COUNT_JOB (deep_count_job)); + + file->deep_count_status = JOB_STATUS_FINISHED; + + /* disconnect from the job */ + g_signal_handlers_disconnect_matched (file->deep_count_job, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, file); + g_object_unref (file->deep_count_job); + file->deep_count_job = NULL; +} + +/** + * thunar_file_calc_recursive_size_update: + * @deep_count_job : The job which was updated + * @total_size : the total size in bytes. + * @file_count : the number of files. + * @directory_count : the number of directories. + * @unreadable_directory_count : the number of unreadable directories. + * @file : a #ThunarFile instance. + * + * This callback will be executed by the job to inform listeners about the number of files, + * directories and bytes counted so far. + **/ +static void +thunar_file_calc_recursive_size_update (ThunarDeepCountJob *deep_count_job, + guint64 total_size, + guint file_count, + guint directory_count, + guint unreadable_directory_count, + ThunarFile *file) +{ + //TODO : + // Update list-model if box in preferences is un-checked + // possibilitie to run all jobs in the same thread ? + // Usage of G_Likely / G_UNLikely + // mutex protection for critical variables + // Possibility to refresh / re-calculate ? ( react on "reload" STR+R" .. maybe even automatically, if the size of an sub-folder/file is changed ) + + // save folder-sizes in tree-model for all sub-folders if possible (So that calculation is done only once when browsing a tree ) + // Possible to use "thunar-folder" instead of "thunar-file" in order to save calculated size ? + // -- So we could launch only one job there .. different views would use the same folder --> no extra-jobs + + // move impl to separate file, if it makes sense + // Ensure that there are no memory-leaks + // - Usage of g_object_ref, etc ? + // alphabetic order for methods + // update documentation + // create patch 1.6.3 + // create patch for trunk (git ?) + + guint n; + + _thunar_return_if_fail (THUNAR_IS_DEEP_COUNT_JOB (deep_count_job)); + _thunar_return_if_fail (THUNAR_IS_FILE (file)); + _thunar_return_if_fail (file->deep_count_job == deep_count_job); + + /* determine the total number of items */ + n = file_count + directory_count + unreadable_directory_count; + + if (G_LIKELY (n > unreadable_directory_count)) + { + /* update the file-data */ + file->size_recursive = total_size; + file->size_recursive_string = g_format_size (total_size); + + if (unreadable_directory_count > 0) + { + /* TRANSLATORS: this is shows if during the deep count directories were not accessible */ + file->size_recursive_string = g_strconcat (file->size_recursive_string, _("(some contents unreadable)"), NULL); + } + + } + else + { + /* nothing was readable, so permission was denied */ + file->size_recursive_string = g_strdup(_("Permission denied")); + } + + /* update all registered stores */ + g_slist_foreach (file->stores_to_update, (GFunc)thunar_list_model_update, NULL); +} /** * thunar_file_get: @@ -2142,6 +2354,45 @@ thunar_file_get_size_string (const Thuna } +/** + * thunar_file_get_recursive_size_string: + * @file : a #ThunarFile instance. + * + * On the first call of each folder, the method starts a job to calculate the size of a folder and all it's sub-items. + * If the job already provided size information, it will be returned, as text in a human readable + * format. You'll need to free the result using g_free() if you're done with it. + * + * Return value: the size of @file in a human readable format. + **/ +gchar * +thunar_file_get_recursive_size_string (ThunarFile *file, + GtkTreeModel *store, + gboolean *newJobStarted ) +{ + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL); + _thunar_return_val_if_fail (thunar_file_is_directory(file),NULL); + + ThunarListModel *list_model_store = THUNAR_LIST_MODEL (store); + _thunar_return_if_fail (THUNAR_IS_LIST_MODEL (list_model_store)); + *newJobStarted = FALSE; + if( file->deep_count_status == JOB_STATUS_NOT_STARTED_YET || file->deep_count_status == JOB_STATUS_UNDEFINED ) + { + thunar_file_calc_recursive_size_start (file, list_model_store); + *newJobStarted = TRUE; + return g_strdup(_("..calculating")); + } + else /* JOB_STATUS_FINISHED or JOB_STATUS_CALCULATING */ + { + /* add the related list-model, if not yet added, to be updated whenever there is new data */ + if( g_slist_find (file->stores_to_update, (gconstpointer) list_model_store) == NULL ) + file->stores_to_update = g_slist_append (file->stores_to_update, list_model_store); + } + + if( file->deep_count_status == JOB_STATUS_FINISHED ) + return g_strdup(file->size_recursive_string); + + return g_strconcat (file->size_recursive_string,_("..calculating"),NULL); +} /** * thunar_file_get_volume: @@ -2172,8 +2423,6 @@ thunar_file_get_volume (const ThunarFile return volume; } - - /** * thunar_file_get_group: * @file : a #ThunarFile instance. @@ -2394,6 +2643,10 @@ thunar_file_get_size (const ThunarFile * { _thunar_return_val_if_fail (THUNAR_IS_FILE (file), 0); + /* if recursive size-counting is enabled */ + if( file->deep_count_status == JOB_STATUS_FINISHED ) + return file->size_recursive; + if (file->info == NULL) return 0; diff -rupN Thunar-1.6.3.old/thunar/thunar-file.h Thunar-1.6.3.new/thunar/thunar-file.h --- Thunar-1.6.3.old/thunar/thunar-file.h 2015-05-24 18:12:21.504226485 +0200 +++ Thunar-1.6.3.new/thunar/thunar-file.h 2015-05-24 18:05:24.680238013 +0200 @@ -29,6 +29,7 @@ #include #include + G_BEGIN_DECLS; typedef struct _ThunarFileClass ThunarFileClass; @@ -99,7 +100,6 @@ typedef enum /*< flags >*/ #define THUNAR_FILE_EMBLEM_NAME_DESKTOP "emblem-desktop" - /** * ThunarFileGetFunc: * @@ -167,6 +167,9 @@ gchar *thunar_file_get_date_s ThunarDateStyle date_style) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; gchar *thunar_file_get_mode_string (const ThunarFile *file) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; gchar *thunar_file_get_size_string (const ThunarFile *file) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; +gchar *thunar_file_get_recursive_size_string (ThunarFile *file, + GtkTreeModel *store, + gboolean *newJobStarted) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; GVolume *thunar_file_get_volume (const ThunarFile *file); @@ -253,6 +256,7 @@ GList *thunar_file_list_get_a GList *thunar_file_list_to_thunar_g_file_list (GList *file_list); gboolean thunar_file_is_desktop (const ThunarFile *file); +void thunar_file_calc_recursive_size_cancel (ThunarFile *file); /** * thunar_file_is_root: diff -rupN Thunar-1.6.3.old/thunar/thunar-list-model.c Thunar-1.6.3.new/thunar/thunar-list-model.c --- Thunar-1.6.3.old/thunar/thunar-list-model.c 2015-05-24 18:12:21.484226485 +0200 +++ Thunar-1.6.3.new/thunar/thunar-list-model.c 2015-05-24 18:05:36.088237697 +0200 @@ -50,6 +50,7 @@ enum PROP_FOLDERS_FIRST, PROP_NUM_FILES, PROP_SHOW_HIDDEN, + PROP_RECURSIVE_FILE_SIZE, N_PROPERTIES }; @@ -184,6 +185,10 @@ static void thunar_list_mo 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_recursive_file_size (ThunarListModel *store); +static void thunar_list_model_set_recursive_file_size (ThunarListModel *store, + gboolean recursive_file_size); +static void thunar_list_model_stop_pending_jobs (ThunarListModel *store); struct _ThunarListModelClass { @@ -210,6 +215,7 @@ struct _ThunarListModel GSList *hidden; ThunarFolder *folder; gboolean show_hidden : 1; + gboolean recursive_file_size : 1; ThunarDateStyle date_style; /* Use the shared ThunarFileMonitor instance, so we @@ -228,6 +234,12 @@ struct _ThunarListModel gboolean sort_folders_first : 1; gint sort_sign; /* 1 = ascending, -1 descending */ ThunarSortFunc sort_func; + + /* folders of this list-model which are running a deep-count-job + - for each folder one job is started. ( Improved performance if different list-models show the same folder ) + - the jobs are cancelled when the current directory is changed for the list-model (if no other list-models are subscribed to the job) + */ + GSList *folders_running_deep_count_job; }; @@ -328,6 +340,17 @@ thunar_list_model_class_init (ThunarList FALSE, EXO_PARAM_READWRITE); + /** + * ThunarListModel:recursive-file-size: + * In order to enable / disable recursive file-size display + **/ + list_model_props[PROP_RECURSIVE_FILE_SIZE] = + g_param_spec_boolean ("recursive-file-size", + "recursive-file-size", + "recursive-file-size", + TRUE, + EXO_PARAM_READWRITE); + /* install properties */ g_object_class_install_properties (gobject_class, N_PROPERTIES, list_model_props); @@ -398,7 +421,6 @@ thunar_list_model_init (ThunarListModel #ifndef NDEBUG store->stamp = g_random_int (); #endif - store->row_inserted_id = g_signal_lookup ("row-inserted", GTK_TYPE_TREE_MODEL); store->row_deleted_id = g_signal_lookup ("row-deleted", GTK_TYPE_TREE_MODEL); @@ -475,6 +497,10 @@ thunar_list_model_get_property (GObject g_value_set_uint (value, thunar_list_model_get_num_files (store)); break; + case PROP_RECURSIVE_FILE_SIZE: + g_value_set_boolean (value, thunar_list_model_get_recursive_file_size (store)); + break; + case PROP_SHOW_HIDDEN: g_value_set_boolean (value, thunar_list_model_get_show_hidden (store)); break; @@ -509,6 +535,10 @@ thunar_list_model_set_property (GObject thunar_list_model_set_folder (store, g_value_get_object (value)); break; + case PROP_RECURSIVE_FILE_SIZE: + thunar_list_model_set_recursive_file_size (store, g_value_get_boolean (value)); + break; + case PROP_FOLDERS_FIRST: thunar_list_model_set_folders_first (store, g_value_get_boolean (value)); break; @@ -716,7 +746,15 @@ thunar_list_model_get_value (GtkTreeMode 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)->recursive_file_size && thunar_file_is_directory(file) ) + { + gboolean newJobStarted; + g_value_take_string (value, thunar_file_get_recursive_size_string (file, model,&newJobStarted)); + if(newJobStarted) + THUNAR_LIST_MODEL(model)->folders_running_deep_count_job = g_slist_append (THUNAR_LIST_MODEL(model)->folders_running_deep_count_job, file); + } + else + g_value_take_string (value, thunar_file_get_size_string (file)); break; case THUNAR_COLUMN_TYPE: @@ -1775,6 +1813,11 @@ thunar_list_model_set_folder (ThunarList g_slist_free_full (store->hidden, g_object_unref); store->hidden = NULL; + /* cancel any pending size-calculation jobs on the folder */ + g_slist_foreach (store->folders_running_deep_count_job,(GFunc)thunar_file_calc_recursive_size_cancel,NULL); + g_slist_free (store->folders_running_deep_count_job); + store->folders_running_deep_count_job = NULL; + /* unregister signals and drop the reference */ g_signal_handlers_disconnect_matched (G_OBJECT (store->folder), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, store); g_object_unref (G_OBJECT (store->folder)); @@ -1963,7 +2006,50 @@ thunar_list_model_set_show_hidden (Thuna g_object_thaw_notify (G_OBJECT (store)); } +/** + * thunar_list_model_get_recursive_file_size: + * @store : a #ThunarListModel. + * + * Return value: %TRUE if the size of directories is calculated recursively, else %FALSE. + **/ +static gboolean +thunar_list_model_get_recursive_file_size (ThunarListModel *store) +{ + _thunar_return_val_if_fail (THUNAR_IS_LIST_MODEL (store), FALSE); + return store->recursive_file_size; +} +static void +thunar_list_model_stop_pending_jobs (ThunarListModel *store) +{ + _thunar_return_val_if_fail (THUNAR_IS_LIST_MODEL (store), FALSE); +} + + +/** + * thunar_list_model_set_recursive_file_size: + * @store : a #ThunarListModel. + * @recursive_file_size : %TRUE if the size of directories should be calculated recursively, else %FALSE. + **/ +void +thunar_list_model_set_recursive_file_size (ThunarListModel *store, + gboolean recursive_file_size) +{ + _thunar_return_if_fail (THUNAR_IS_LIST_MODEL (store)); + + /* check if the new setting differs */ + if (store->recursive_file_size == recursive_file_size) + return; + + store->recursive_file_size = recursive_file_size; + g_object_notify_by_pspec (G_OBJECT (store), list_model_props[PROP_RECURSIVE_FILE_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 ) + thunar_list_model_sort (store); +} /** * thunar_list_model_get_file: @@ -2111,6 +2197,16 @@ thunar_list_model_get_paths_for_pattern return paths; } +void +thunar_list_model_update (ThunarListModel *store) +{ + _thunar_return_if_fail (THUNAR_IS_LIST_MODEL (store)); + + gtk_tree_model_foreach (GTK_TREE_MODEL (store), (GtkTreeModelForeachFunc) gtk_tree_model_row_changed, NULL); + + /* re-sort the store */ + thunar_list_model_sort (store); +} /** diff -rupN Thunar-1.6.3.old/thunar/thunar-list-model.h Thunar-1.6.3.new/thunar/thunar-list-model.h --- Thunar-1.6.3.old/thunar/thunar-list-model.h 2015-05-24 18:12:21.484226485 +0200 +++ Thunar-1.6.3.new/thunar/thunar-list-model.h 2015-05-24 18:05:39.552237601 +0200 @@ -60,6 +60,7 @@ GList *thunar_list_model_get_p gchar *thunar_list_model_get_statusbar_text (ThunarListModel *store, GList *selected_items); +void thunar_list_model_update (ThunarListModel *store); G_END_DECLS; diff -rupN Thunar-1.6.3.old/thunar/thunar-preferences.c Thunar-1.6.3.new/thunar/thunar-preferences.c --- Thunar-1.6.3.old/thunar/thunar-preferences.c 2015-05-24 18:12:21.484226485 +0200 +++ Thunar-1.6.3.new/thunar/thunar-preferences.c 2015-05-24 18:05:52.400237246 +0200 @@ -76,6 +76,7 @@ enum PROP_MISC_CASE_SENSITIVE, PROP_MISC_DATE_STYLE, PROP_MISC_FOLDERS_FIRST, + PROP_MISC_RECURSIVE_FILE_SIZE, PROP_MISC_FULL_PATH_IN_TITLE, PROP_MISC_HORIZONTAL_WHEEL_NAVIGATES, PROP_MISC_IMAGE_SIZE_IN_STATUSBAR, @@ -501,6 +502,17 @@ thunar_preferences_class_init (ThunarPre NULL, TRUE, EXO_PARAM_READWRITE); + /** + * ThunarPreferences:misc-folders-first: + * + * Whether to sort folders before files. + **/ + preferences_props[PROP_MISC_RECURSIVE_FILE_SIZE] = + g_param_spec_boolean ("misc-recursive-file-size", + "MiscRecursiveFileSize", + NULL, + TRUE, + EXO_PARAM_READWRITE); /** * ThunarPreferences:misc-full-path-in-title: diff -rupN Thunar-1.6.3.old/thunar/thunar-preferences-dialog.c Thunar-1.6.3.new/thunar/thunar-preferences-dialog.c --- Thunar-1.6.3.old/thunar/thunar-preferences-dialog.c 2015-05-24 18:12:21.484226485 +0200 +++ Thunar-1.6.3.new/thunar/thunar-preferences-dialog.c 2015-05-24 18:06:11.416236720 +0200 @@ -254,7 +254,8 @@ thunar_preferences_dialog_init (ThunarPr gtk_frame_set_label_widget (GTK_FRAME (frame), label); gtk_widget_show (label); - table = gtk_table_new (3, 2, FALSE); + //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 +301,11 @@ thunar_preferences_dialog_init (ThunarPr 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 recursive file size for folders")); + exo_mutual_binding_new (G_OBJECT (dialog->preferences), "misc-recursive-file-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 -rupN Thunar-1.6.3.old/thunar/thunar-standard-view.c Thunar-1.6.3.new/thunar/thunar-standard-view.c --- Thunar-1.6.3.old/thunar/thunar-standard-view.c 2015-05-24 18:12:21.484226485 +0200 +++ Thunar-1.6.3.new/thunar/thunar-standard-view.c 2015-05-24 18:06:26.500236303 +0200 @@ -693,6 +693,7 @@ thunar_standard_view_init (ThunarStandar 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-recursive-file-size", G_OBJECT (standard_view->model), "recursive-file-size"); /* setup the icon renderer */ standard_view->icon_renderer = thunar_icon_renderer_new (); @@ -3707,8 +3708,6 @@ thunar_standard_view_restore_selection ( } } - - static void thunar_standard_view_error (ThunarListModel *model, const GError *error,