From d92b96b9adb5fb1beb4f65d84585c360da820f55 Mon Sep 17 00:00:00 2001
From: Pratyaksh Gautam <pratyakshgautam11@gmail.com>
Date: Tue, 25 Oct 2022 20:01:34 +0000
Subject: [PATCH] List View: Add file count to size column for directories
 (Issue #61)

- File count for each directory will be counted in a separate job
- Configurable in the 'Configure columns ..' menu
- Options are 'Never' / 'Only for local files' / 'Always'
---
 thunar/thunar-column-editor.c      |  48 +++
 thunar/thunar-enum-types.c         |  58 ++++
 thunar/thunar-enum-types.h         |  35 +++
 thunar/thunar-file.c               | 104 ++++++-
 thunar/thunar-file.h               |   7 +
 thunar/thunar-io-jobs.c            |  70 ++++-
 thunar/thunar-io-jobs.h            |  47 +--
 thunar/thunar-list-model.c         | 477 +++++++++++++++++++----------
 thunar/thunar-preferences-dialog.c |  39 ---
 thunar/thunar-preferences.c        |  14 +
 thunar/thunar-standard-view.c      |   1 +
 11 files changed, 670 insertions(+), 230 deletions(-)

diff --git a/thunar/thunar-column-editor.c b/thunar/thunar-column-editor.c
index d01e4ee50..e920f507a 100644
--- a/thunar/thunar-column-editor.c
+++ b/thunar/thunar-column-editor.c
@@ -128,12 +128,14 @@ thunar_column_editor_init (ThunarColumnEditor *column_editor)
   GtkTreeIter        iter;
   GtkWidget         *separator;
   GtkWidget         *button;
+  GtkWidget         *combo;
   GtkWidget         *frame;
   GtkWidget         *image;
   GtkWidget         *label;
   GtkWidget         *grid;
   GtkWidget         *vbox;
   GtkWidget         *swin;
+  GEnumClass        *enum_class;
   gint               row = 0;
 
   /* grab a reference on the preferences */
@@ -334,6 +336,52 @@ thunar_column_editor_init (ThunarColumnEditor *column_editor)
   thunar_gtk_label_set_a11y_relation (GTK_LABEL (label), button);
   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);
+
+  label = gtk_label_new (_("Size Column of Folders"));
+  gtk_label_set_attributes (GTK_LABEL (label), thunar_pango_attr_list_bold ());
+  gtk_frame_set_label_widget (GTK_FRAME (frame), label);
+  gtk_widget_show (label);
+
+  grid = gtk_grid_new ();
+  gtk_grid_set_column_spacing (GTK_GRID (grid), 6);
+  gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
+  gtk_container_set_border_width (GTK_CONTAINER (grid), 12);
+  gtk_container_add (GTK_CONTAINER (frame), grid);
+  gtk_widget_show (grid);
+
+  /* explain what it does */
+  label = gtk_label_new (_("Show number of containing items"));
+  gtk_label_set_xalign (GTK_LABEL (label), 0.0f);
+  gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
+  gtk_widget_show (label);
+
+  combo = gtk_combo_box_text_new ();
+  enum_class = g_type_class_ref (THUNAR_TYPE_FOLDER_ITEM_COUNT);
+
+  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo),
+                                  g_enum_get_value (enum_class, THUNAR_FOLDER_ITEM_COUNT_NEVER)->value_nick);
+  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo),
+                                  g_enum_get_value (enum_class, THUNAR_FOLDER_ITEM_COUNT_ONLY_LOCAL)->value_nick);
+  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo),
+                                  g_enum_get_value (enum_class, THUNAR_FOLDER_ITEM_COUNT_ALWAYS)->value_nick);
+  g_type_class_unref (enum_class);
+
+  g_object_bind_property_full (G_OBJECT (column_editor->preferences), "misc-folder-item-count",
+                               G_OBJECT (combo), "active",
+                               G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE,
+                               transform_enum_value_to_index,
+                               transform_index_to_enum_value,
+                               (gpointer) thunar_folder_item_count_get_type, NULL);
+
+  gtk_widget_set_hexpand (combo, TRUE);
+  gtk_grid_attach (GTK_GRID (grid), combo, 1, row - 1, 1, 1);
+  thunar_gtk_label_set_a11y_relation (GTK_LABEL (label), combo);
+  gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
+  gtk_widget_show (combo);
+
   /* setup the tree selection */
   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (column_editor->tree_view));
   g_signal_connect_swapped (G_OBJECT (selection), "changed", G_CALLBACK (thunar_column_editor_update_buttons), column_editor);
diff --git a/thunar/thunar-enum-types.c b/thunar/thunar-enum-types.c
index 9a7e2343c..5e989dee5 100644
--- a/thunar/thunar-enum-types.c
+++ b/thunar/thunar-enum-types.c
@@ -37,6 +37,45 @@ static ThunarThumbnailSize thunar_icon_size_to_thumbnail_size   (ThunarIconSize
 
 
 
+gboolean
+transform_enum_value_to_index (GBinding     *binding,
+                               const GValue *src_value,
+                               GValue       *dst_value,
+                               gpointer      user_data)
+{
+  GEnumClass *klass;
+  GType     (*type_func)() = user_data;
+  guint       n;
+
+  klass = g_type_class_ref (type_func ());
+  for (n = 0; n < klass->n_values; ++n)
+    if (klass->values[n].value == g_value_get_enum (src_value))
+      g_value_set_int (dst_value, n);
+  g_type_class_unref (klass);
+
+  return TRUE;
+}
+
+
+
+gboolean
+transform_index_to_enum_value (GBinding     *binding,
+                               const GValue *src_value,
+                               GValue       *dst_value,
+                               gpointer      user_data)
+{
+  GEnumClass *klass;
+  GType     (*type_func)() = user_data;
+
+  klass = g_type_class_ref (type_func ());
+  g_value_set_enum (dst_value, klass->values[g_value_get_int (src_value)].value);
+  g_type_class_unref (klass);
+
+  return TRUE;
+}
+
+
+
 GType
 thunar_renamer_mode_get_type (void)
 {
@@ -712,3 +751,22 @@ thunar_image_preview_mode_get_type (void)
   return type;
 }
 
+GType thunar_folder_item_count_get_type (void)
+{
+  static GType type = G_TYPE_INVALID;
+
+  if (G_UNLIKELY (type == G_TYPE_INVALID))
+    {
+      static const GEnumValue values[] =
+      {
+        { THUNAR_FOLDER_ITEM_COUNT_NEVER,       "THUNAR_FOLDER_ITEM_COUNT_NEVER",       N_("Never") },
+        { THUNAR_FOLDER_ITEM_COUNT_ONLY_LOCAL,  "THUNAR_FOLDER_ITEM_COUNT_ONLY_LOCAL",  N_("Only for local files") },
+        { THUNAR_FOLDER_ITEM_COUNT_ALWAYS,      "THUNAR_FOLDER_ITEM_COUNT_ALWAYS",      N_("Always") },
+        { 0,                                    NULL,                                   NULL }
+      };
+
+      type = g_enum_register_static ("ThunarFolderItemCount", values);
+    }
+
+  return type;
+}
diff --git a/thunar/thunar-enum-types.h b/thunar/thunar-enum-types.h
index f63092beb..528badeb1 100644
--- a/thunar/thunar-enum-types.h
+++ b/thunar/thunar-enum-types.h
@@ -25,6 +25,17 @@
 
 G_BEGIN_DECLS;
 
+
+gboolean transform_enum_value_to_index (GBinding     *binding,
+                                        const GValue *src_value,
+                                        GValue       *dst_value,
+                                        gpointer      user_data);
+
+gboolean transform_index_to_enum_value (GBinding     *binding,
+                                        const GValue *src_value,
+                                        GValue       *dst_value,
+                                        gpointer      user_data);
+
 #define THUNAR_TYPE_RENAMER_MODE (thunar_renamer_mode_get_type ())
 
 /**
@@ -480,6 +491,30 @@ typedef enum
 
 GType thunar_image_preview_mode_get_type (void) G_GNUC_CONST;
 
+/**
+ * ThunarFolderItemCount
+ *
+ * Specify when the size column on a folder
+ * should instead show the item count of the folder
+ **/
+
+#define THUNAR_TYPE_FOLDER_ITEM_COUNT (thunar_folder_item_count_get_type ())
+
+/**
+ * ThunarFolderItemCount:
+ * @THUNAR_FOLDER_ITEM_COUNT_NEVER,        : never show number of items as the size of the folder
+ * @THUNAR_FOLDER_ITEM_COUNT_ONLY_LOCAL,   : only show number of items as size of folder for local folders
+ * @THUNAR_FOLDER_ITEM_COUNT_ALWAYS,       : always show the number of items as the size of the folder
+ **/
+typedef enum
+{
+  THUNAR_FOLDER_ITEM_COUNT_NEVER,
+  THUNAR_FOLDER_ITEM_COUNT_ONLY_LOCAL,
+  THUNAR_FOLDER_ITEM_COUNT_ALWAYS,
+} ThunarFolderItemCount;
+
+GType thunar_folder_item_count_get_type (void) G_GNUC_CONST;
+
 G_END_DECLS;
 
 #endif /* !__THUNAR_ENUM_TYPES_H__ */
diff --git a/thunar/thunar-file.c b/thunar/thunar-file.c
index c2d598d9e..78aed85a6 100644
--- a/thunar/thunar-file.c
+++ b/thunar/thunar-file.c
@@ -58,16 +58,17 @@
 
 #include <thunar/thunar-application.h>
 #include <thunar/thunar-chooser-dialog.h>
-#include <thunar/thunar-file.h>
+#include <thunar/thunar-dialogs.h>
 #include <thunar/thunar-file-monitor.h>
+#include <thunar/thunar-file.h>
 #include <thunar/thunar-gio-extensions.h>
 #include <thunar/thunar-gobject-extensions.h>
-#include <thunar/thunar-private.h>
+#include <thunar/thunar-icon-factory.h>
+#include <thunar/thunar-io-jobs.h>
 #include <thunar/thunar-preferences.h>
+#include <thunar/thunar-private.h>
 #include <thunar/thunar-user.h>
 #include <thunar/thunar-util.h>
-#include <thunar/thunar-dialogs.h>
-#include <thunar/thunar-icon-factory.h>
 
 
 
@@ -186,6 +187,13 @@ struct _ThunarFile
 
   /* tells whether the file watch is not set */
   gboolean              no_file_watch;
+
+  /* Number of files in this directory (only used if this #Thunarfile is a directory) */
+  /* Note that this feature was added into #ThunarFile on purpose, because having inside #ThunarFolder caused lag when
+   * there were > 10.000 files in a folder (Creation of #ThunarFolder seems to be slow) */
+  guint                 file_count;
+  guint64               file_count_timestamp;
+
 };
 
 typedef struct
@@ -382,6 +390,8 @@ thunar_file_class_init (ThunarFileClass *klass)
 static void
 thunar_file_init (ThunarFile *file)
 {
+  file->file_count = 0;
+  file->file_count_timestamp = 0;
 }
 
 
@@ -3485,6 +3495,92 @@ thunar_file_can_be_trashed (const ThunarFile *file)
 
 
 
+/**
+ * thunar_file_get_file_count
+ * @file    : a #ThunarFile instance.
+ * @callback: a #GCallback to be executed after the file count
+ * @data    : a #gpointer containing user data to pass to the callback
+ *
+ * Returns the number of items in the directory
+ * Counts the number of files in the directory as fast as possible.
+ * Will use cached data to do calculations only when the file has
+ * been modified since the last time its contents were counted.
+ *
+ * Return value: Number of files in a folder
+ **/
+guint
+thunar_file_get_file_count (ThunarFile   *file,
+                            GCallback     callback,
+                            gpointer      data)
+{
+  GError                    *err = NULL;
+  ThunarJob                 *job;
+  GFileInfo                 *info;
+  guint64                    last_modified;
+
+  _thunar_return_val_if_fail (thunar_file_is_directory (file), 0);
+
+  /* Forcefully get cached values by passing NULL as the second argument */
+  if (file == NULL)
+    return file->file_count;
+
+  info = g_file_query_info (thunar_file_get_file (file),
+                            G_FILE_ATTRIBUTE_TIME_MODIFIED,
+                            G_FILE_QUERY_INFO_NONE,
+                            NULL,
+                            &err);
+
+  if (err != NULL)
+    {
+      g_warning ("An error occured while trying to get file counts.");
+      return file->file_count;
+    }
+
+  last_modified = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED);
+  g_object_unref (info);
+
+  /* return a cached value if last time that the file count was computed is later
+   * than the last time the file was modified */
+  if (G_LIKELY (last_modified < file->file_count_timestamp))
+    return file->file_count;
+
+  /* put the timestamp calculation at the *start* of the process to prevent another call to
+   * thunar_file_get_count starting another job on the same folder before one has ended.
+   * Divide by 1e6 to convert from microseconds to seconds */
+  file->file_count_timestamp = g_get_real_time () / (guint64) 1e6;
+
+  /* set up a job to actually enumerate over the folder's contents and get its file count */
+  job = thunar_io_jobs_count_files (file);
+
+  /* set up the signal on finish to call the callback */
+  if (callback != NULL)
+    g_signal_connect (job, "finished", G_CALLBACK (callback), data);
+
+  exo_job_launch (EXO_JOB (job));
+
+  return file->file_count;
+}
+
+
+
+/**
+ * thunar_file_set_file_count
+ * @file: A #ThunarFileInstance
+ * @count: The value to set the file's count to
+ *
+ * Set @file's count to the given number if it is a directory.
+ * Does *NOT* update the file's count timestamp.
+ **/
+void
+thunar_file_set_file_count (ThunarFile  *file,
+                            const guint  count)
+{
+  _thunar_return_if_fail (thunar_file_is_directory (file));
+
+  file->file_count = count;
+}
+
+
 /**
  * thunar_file_get_emblem_names:
  * @file : a #ThunarFile instance.
diff --git a/thunar/thunar-file.h b/thunar/thunar-file.h
index 7e163b16a..8b9a3e405 100644
--- a/thunar/thunar-file.h
+++ b/thunar/thunar-file.h
@@ -235,6 +235,13 @@ gboolean          thunar_file_is_chmodable               (const ThunarFile
 gboolean          thunar_file_is_renameable              (const ThunarFile       *file);
 gboolean          thunar_file_can_be_trashed             (const ThunarFile       *file);
 
+
+guint             thunar_file_get_file_count             (ThunarFile             *file,
+                                                          GCallback               callback,
+                                                          gpointer                data);
+void              thunar_file_set_file_count             (ThunarFile             *file,
+                                                          const guint             count);
+
 GList            *thunar_file_get_emblem_names           (ThunarFile              *file);
 void              thunar_file_set_emblem_names           (ThunarFile              *file,
                                                           GList                   *emblem_names);
diff --git a/thunar/thunar-io-jobs.c b/thunar/thunar-io-jobs.c
index 7d28833da..75a06f1d6 100644
--- a/thunar/thunar-io-jobs.c
+++ b/thunar/thunar-io-jobs.c
@@ -31,10 +31,11 @@
 
 #include <thunar/thunar-application.h>
 #include <thunar/thunar-enum-types.h>
+#include <thunar/thunar-file.h>
 #include <thunar/thunar-gio-extensions.h>
-#include <thunar/thunar-io-scan-directory.h>
-#include <thunar/thunar-io-jobs.h>
 #include <thunar/thunar-io-jobs-util.h>
+#include <thunar/thunar-io-jobs.h>
+#include <thunar/thunar-io-scan-directory.h>
 #include <thunar/thunar-job.h>
 #include <thunar/thunar-private.h>
 #include <thunar/thunar-simple-job.h>
@@ -1451,3 +1452,68 @@ thunar_io_jobs_rename_file (ThunarFile            *file,
                                 G_TYPE_STRING, display_name,
                                 THUNAR_TYPE_OPERATION_LOG_MODE, log_mode);
 }
+
+
+
+static gboolean
+_thunar_io_jobs_count (ThunarJob *job,
+                       GArray    *param_values,
+                       GError   **error)
+{
+  GError          *err = NULL;
+  ThunarFile      *file;
+  GFileEnumerator *enumerator;
+  guint            count;
+
+  _thunar_return_val_if_fail (THUNAR_IS_JOB (job), FALSE);
+  _thunar_return_val_if_fail (param_values != NULL, FALSE);
+  _thunar_return_val_if_fail (param_values->len == 1, FALSE);
+  _thunar_return_val_if_fail (G_VALUE_HOLDS (&g_array_index (param_values, GValue, 0), THUNAR_TYPE_FILE), FALSE);
+  _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+  file = THUNAR_FILE (g_value_get_object (&g_array_index (param_values, GValue, 0)));
+
+  if (file == NULL)
+    return FALSE;
+
+  enumerator = g_file_enumerate_children (thunar_file_get_file (file), NULL,
+                                          G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+                                          NULL, &err);
+  if (err != NULL)
+    {
+      g_propagate_error (error, err);
+      return FALSE;
+    }
+
+  count = 0;
+  for (GFileInfo *child_info = g_file_enumerator_next_file (enumerator, NULL, &err);
+       child_info != NULL;
+       child_info = g_file_enumerator_next_file (enumerator, NULL, &err))
+    {
+      if (err != NULL)
+        {
+          g_propagate_error (error, err);
+          return FALSE;
+        }
+
+      count++;
+      g_object_unref (child_info);
+    }
+
+  thunar_file_set_file_count (file, count);
+
+  g_object_unref (enumerator);
+
+  return TRUE;
+}
+
+
+
+ThunarJob *
+thunar_io_jobs_count_files (ThunarFile *file)
+{
+  _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL);
+
+  return thunar_simple_job_new (_thunar_io_jobs_count, 1,
+                                THUNAR_TYPE_FILE, file);
+}
diff --git a/thunar/thunar-io-jobs.h b/thunar/thunar-io-jobs.h
index da7955d8d..a377b8c61 100644
--- a/thunar/thunar-io-jobs.h
+++ b/thunar/thunar-io-jobs.h
@@ -26,32 +26,33 @@
 
 G_BEGIN_DECLS
 
-ThunarJob *thunar_io_jobs_create_files     (GList         *file_list,
-                                            GFile         *template_file) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
-ThunarJob *thunar_io_jobs_make_directories (GList         *file_list) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
-ThunarJob *thunar_io_jobs_unlink_files     (GList         *file_list) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
-ThunarJob *thunar_io_jobs_move_files       (GList         *source_file_list,
-                                            GList         *target_file_list) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
-ThunarJob *thunar_io_jobs_copy_files       (GList         *source_file_list,
-                                            GList         *target_file_list) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
-ThunarJob *thunar_io_jobs_link_files       (GList         *source_file_list,
-                                            GList         *target_file_list) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
-ThunarJob *thunar_io_jobs_trash_files      (GList         *file_list) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
-ThunarJob *thunar_io_jobs_restore_files    (GList         *source_file_list,
-                                            GList         *target_file_list) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
-ThunarJob *thunar_io_jobs_change_group     (GList         *files,
-                                            guint32        gid,
-                                            gboolean       recursive) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
-ThunarJob *thunar_io_jobs_change_mode      (GList         *files,
-                                            ThunarFileMode dir_mask,
-                                            ThunarFileMode dir_mode,
-                                            ThunarFileMode file_mask,
-                                            ThunarFileMode file_mode,
-                                            gboolean       recursive) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
-ThunarJob *thunar_io_jobs_list_directory   (GFile         *directory) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+ThunarJob *thunar_io_jobs_create_files     (GList                 *file_list,
+                                            GFile                 *template_file) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+ThunarJob *thunar_io_jobs_make_directories (GList                 *file_list) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+ThunarJob *thunar_io_jobs_unlink_files     (GList                 *file_list) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+ThunarJob *thunar_io_jobs_move_files       (GList                 *source_file_list,
+                                            GList                 *target_file_list) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+ThunarJob *thunar_io_jobs_copy_files       (GList                 *source_file_list,
+                                            GList                 *target_file_list) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+ThunarJob *thunar_io_jobs_link_files       (GList                 *source_file_list,
+                                            GList                 *target_file_list) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+ThunarJob *thunar_io_jobs_trash_files      (GList                 *file_list) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+ThunarJob *thunar_io_jobs_restore_files    (GList                 *source_file_list,
+                                            GList                 *target_file_list) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+ThunarJob *thunar_io_jobs_change_group     (GList                 *files,
+                                            guint32                gid,
+                                            gboolean               recursive) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+ThunarJob *thunar_io_jobs_change_mode      (GList                 *files,
+                                            ThunarFileMode         dir_mask,
+                                            ThunarFileMode         dir_mode,
+                                            ThunarFileMode         file_mask,
+                                            ThunarFileMode         file_mode,
+                                            gboolean               recursive) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+ThunarJob *thunar_io_jobs_list_directory   (GFile                 *directory) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
 ThunarJob *thunar_io_jobs_rename_file      (ThunarFile            *file,
                                             const gchar           *display_name,
                                             ThunarOperationLogMode log_mode) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+ThunarJob *thunar_io_jobs_count_files      (ThunarFile            *file);
 
 G_END_DECLS
 
diff --git a/thunar/thunar-list-model.c b/thunar/thunar-list-model.c
index 75aa77f1a..7c069f38e 100644
--- a/thunar/thunar-list-model.c
+++ b/thunar/thunar-list-model.c
@@ -33,6 +33,7 @@
 #include <libxfce4util/libxfce4util.h>
 
 #include <thunar/thunar-application.h>
+#include <thunar/thunar-file.h>
 #include <thunar/thunar-file-monitor.h>
 #include <thunar/thunar-gobject-extensions.h>
 #include <thunar/thunar-list-model.h>
@@ -55,6 +56,7 @@ enum
   PROP_FOLDERS_FIRST,
   PROP_NUM_FILES,
   PROP_SHOW_HIDDEN,
+  PROP_FOLDER_ITEM_COUNT,
   PROP_FILE_SIZE_BINARY,
   N_PROPERTIES
 };
@@ -73,155 +75,163 @@ typedef gint (*ThunarSortFunc) (const ThunarFile *a,
                                 const ThunarFile *b,
                                 gboolean          case_sensitive);
 
-static void               thunar_list_model_tree_model_init       (GtkTreeModelIface           *iface);
-static void               thunar_list_model_drag_dest_init        (GtkTreeDragDestIface        *iface);
-static void               thunar_list_model_sortable_init         (GtkTreeSortableIface        *iface);
-static void               thunar_list_model_dispose               (GObject                     *object);
-static void               thunar_list_model_finalize              (GObject                     *object);
-static void               thunar_list_model_get_property          (GObject                     *object,
-                                                                   guint                        prop_id,
-                                                                   GValue                      *value,
-                                                                   GParamSpec                  *pspec);
-static void               thunar_list_model_set_property          (GObject                     *object,
-                                                                   guint                        prop_id,
-                                                                   const GValue                *value,
-                                                                   GParamSpec                  *pspec);
-static GtkTreeModelFlags  thunar_list_model_get_flags             (GtkTreeModel                *model);
-static gint               thunar_list_model_get_n_columns         (GtkTreeModel                *model);
-static GType              thunar_list_model_get_column_type       (GtkTreeModel                *model,
-                                                                   gint                         idx);
-static gboolean           thunar_list_model_get_iter              (GtkTreeModel                *model,
-                                                                   GtkTreeIter                 *iter,
-                                                                   GtkTreePath                 *path);
-static GtkTreePath       *thunar_list_model_get_path              (GtkTreeModel                *model,
-                                                                   GtkTreeIter                 *iter);
-static void               thunar_list_model_get_value             (GtkTreeModel                *model,
-                                                                   GtkTreeIter                 *iter,
-                                                                   gint                         column,
-                                                                   GValue                      *value);
-static gboolean           thunar_list_model_iter_next             (GtkTreeModel                *model,
-                                                                   GtkTreeIter                 *iter);
-static gboolean           thunar_list_model_iter_children         (GtkTreeModel                *model,
-                                                                   GtkTreeIter                 *iter,
-                                                                   GtkTreeIter                 *parent);
-static gboolean           thunar_list_model_iter_has_child        (GtkTreeModel                *model,
-                                                                   GtkTreeIter                 *iter);
-static gint               thunar_list_model_iter_n_children       (GtkTreeModel                *model,
-                                                                   GtkTreeIter                 *iter);
-static gboolean           thunar_list_model_iter_nth_child        (GtkTreeModel                *model,
-                                                                   GtkTreeIter                 *iter,
-                                                                   GtkTreeIter                 *parent,
-                                                                   gint                         n);
-static gboolean           thunar_list_model_iter_parent           (GtkTreeModel                *model,
-                                                                   GtkTreeIter                 *iter,
-                                                                   GtkTreeIter                 *child);
-static gboolean           thunar_list_model_drag_data_received    (GtkTreeDragDest             *dest,
-                                                                   GtkTreePath                 *path,
-                                                                   GtkSelectionData            *data);
-static gboolean           thunar_list_model_row_drop_possible     (GtkTreeDragDest             *dest,
-                                                                   GtkTreePath                 *path,
-                                                                   GtkSelectionData            *data);
-static gboolean           thunar_list_model_get_sort_column_id    (GtkTreeSortable             *sortable,
-                                                                   gint                        *sort_column_id,
-                                                                   GtkSortType                 *order);
-static void               thunar_list_model_set_sort_column_id    (GtkTreeSortable             *sortable,
-                                                                   gint                         sort_column_id,
-                                                                   GtkSortType                  order);
-static void               thunar_list_model_set_default_sort_func (GtkTreeSortable             *sortable,
-                                                                   GtkTreeIterCompareFunc       func,
-                                                                   gpointer                     data,
-                                                                   GDestroyNotify               destroy);
-static void               thunar_list_model_set_sort_func         (GtkTreeSortable             *sortable,
-                                                                   gint                         sort_column_id,
-                                                                   GtkTreeIterCompareFunc       func,
-                                                                   gpointer                     data,
-                                                                   GDestroyNotify               destroy);
-static gboolean           thunar_list_model_has_default_sort_func (GtkTreeSortable             *sortable);
-static gint               thunar_list_model_cmp_func              (gconstpointer                a,
-                                                                   gconstpointer                b,
-                                                                   gpointer                     user_data);
-static void               thunar_list_model_sort                  (ThunarListModel             *store);
-static void               thunar_list_model_file_changed          (ThunarFileMonitor           *file_monitor,
-                                                                   ThunarFile                  *file,
-                                                                   ThunarListModel             *store);
-static void               thunar_list_model_folder_destroy        (ThunarFolder                *folder,
-                                                                   ThunarListModel             *store);
-static void               thunar_list_model_folder_error          (ThunarFolder                *folder,
-                                                                   const GError                *error,
-                                                                   ThunarListModel             *store);
-static void               thunar_list_model_files_added           (ThunarFolder                *folder,
-                                                                   GList                       *files,
-                                                                   ThunarListModel             *store);
-static void               thunar_list_model_files_removed         (ThunarFolder                *folder,
-                                                                   GList                       *files,
-                                                                   ThunarListModel             *store);
-static gint               sort_by_date                            (const ThunarFile            *a,
-                                                                   const ThunarFile            *b,
-                                                                   gboolean                     case_sensitive,
-                                                                   gint                         type);
-static gint               sort_by_date_created                    (const ThunarFile            *a,
-                                                                   const ThunarFile            *b,
-                                                                   gboolean                     case_sensitive);
-static gint               sort_by_date_accessed                   (const ThunarFile            *a,
-                                                                   const ThunarFile            *b,
-                                                                   gboolean                     case_sensitive);
-static gint               sort_by_date_modified                   (const ThunarFile            *a,
-                                                                   const ThunarFile            *b,
-                                                                   gboolean                     case_sensitive);
-static gint               sort_by_date_deleted                    (const ThunarFile            *a,
-                                                                   const ThunarFile            *b,
-                                                                   gboolean                     case_sensitive);
-static gint               sort_by_recency                         (const ThunarFile            *a,
-                                                                   const ThunarFile            *b,
-                                                                   gboolean                     case_sensitive);
-static gint               sort_by_location                        (const ThunarFile            *a,
-                                                                   const ThunarFile            *b,
-                                                                   gboolean                     case_sensitive);
-static gint               sort_by_group                           (const ThunarFile            *a,
-                                                                   const ThunarFile            *b,
-                                                                   gboolean                     case_sensitive);
-static gint               sort_by_mime_type                       (const ThunarFile            *a,
-                                                                   const ThunarFile            *b,
-                                                                   gboolean                     case_sensitive);
-static gint               sort_by_owner                           (const ThunarFile            *a,
-                                                                   const ThunarFile            *b,
-                                                                   gboolean                     case_sensitive);
-static gint               sort_by_permissions                     (const ThunarFile            *a,
-                                                                   const ThunarFile            *b,
-                                                                   gboolean                     case_sensitive);
-static gint               sort_by_size                            (const ThunarFile            *a,
-                                                                   const ThunarFile            *b,
-                                                                   gboolean                     case_sensitive);
-static gint               sort_by_size_in_bytes                   (const ThunarFile            *a,
-                                                                   const ThunarFile            *b,
-                                                                   gboolean                     case_sensitive);
-static gint               sort_by_type                            (const ThunarFile            *a,
-                                                                   const ThunarFile            *b,
-                                                                   gboolean                     case_sensitive);
-
-static gboolean           thunar_list_model_get_case_sensitive    (ThunarListModel             *store);
-static void               thunar_list_model_set_case_sensitive    (ThunarListModel             *store,
-                                                                   gboolean                     case_sensitive);
-static ThunarDateStyle    thunar_list_model_get_date_style        (ThunarListModel             *store);
-static void               thunar_list_model_set_date_style        (ThunarListModel             *store,
-                                                                   ThunarDateStyle              date_style);
-static const char*        thunar_list_model_get_date_custom_style (ThunarListModel             *store);
-static void               thunar_list_model_set_date_custom_style (ThunarListModel             *store,
-                                                                   const char                  *date_custom_style);
-static gint               thunar_list_model_get_num_files         (ThunarListModel             *store);
-static gboolean           thunar_list_model_get_folders_first     (ThunarListModel             *store);
-static ThunarJob*         thunar_list_model_job_search_directory  (ThunarListModel             *model,
-                                                                   const gchar                 *search_query_c,
-                                                                   ThunarFile                  *directory);
-static void               thunar_list_model_search_folder         (ThunarListModel             *model,
-                                                                   ThunarJob                   *job,
-                                                                   gchar                       *uri,
-                                                                   gchar                      **search_query_c_terms,
-                                                                   enum ThunarListModelSearch   search_type,
-                                                                   gboolean                     show_hidden);
-static void               thunar_list_model_cancel_search_job     (ThunarListModel             *model);
-
-
+static void               thunar_list_model_tree_model_init             (GtkTreeModelIface            *iface);
+static void               thunar_list_model_drag_dest_init              (GtkTreeDragDestIface         *iface);
+static void               thunar_list_model_sortable_init               (GtkTreeSortableIface         *iface);
+static void               thunar_list_model_dispose                     (GObject                      *object);
+static void               thunar_list_model_finalize                    (GObject                      *object);
+static void               thunar_list_model_get_property                (GObject                      *object,
+                                                                         guint                         prop_id,
+                                                                         GValue                       *value,
+                                                                         GParamSpec                   *pspec);
+static void               thunar_list_model_set_property                (GObject                      *object,
+                                                                         guint                         prop_id,
+                                                                         const GValue                 *value,
+                                                                         GParamSpec                   *pspec);
+static GtkTreeModelFlags  thunar_list_model_get_flags                   (GtkTreeModel                 *model);
+static gint               thunar_list_model_get_n_columns               (GtkTreeModel                 *model);
+static GType              thunar_list_model_get_column_type             (GtkTreeModel                 *model,
+                                                                         gint                          idx);
+static gboolean           thunar_list_model_get_iter                    (GtkTreeModel                 *model,
+                                                                         GtkTreeIter                  *iter,
+                                                                         GtkTreePath                  *path);
+static GtkTreePath       *thunar_list_model_get_path                    (GtkTreeModel                 *model,
+                                                                         GtkTreeIter                  *iter);
+static void               thunar_list_model_get_value                   (GtkTreeModel                 *model,
+                                                                         GtkTreeIter                  *iter,
+                                                                         gint                          column,
+                                                                         GValue                       *value);
+static gboolean           thunar_list_model_iter_next                   (GtkTreeModel                 *model,
+                                                                         GtkTreeIter                  *iter);
+static gboolean           thunar_list_model_iter_children               (GtkTreeModel                 *model,
+                                                                         GtkTreeIter                  *iter,
+                                                                         GtkTreeIter                  *parent);
+static gboolean           thunar_list_model_iter_has_child              (GtkTreeModel                 *model,
+                                                                         GtkTreeIter                  *iter);
+static gint               thunar_list_model_iter_n_children             (GtkTreeModel                 *model,
+                                                                         GtkTreeIter                  *iter);
+static gboolean           thunar_list_model_iter_nth_child              (GtkTreeModel                 *model,
+                                                                         GtkTreeIter                  *iter,
+                                                                         GtkTreeIter                  *parent,
+                                                                         gint                          n);
+static gboolean           thunar_list_model_iter_parent                 (GtkTreeModel                 *model,
+                                                                         GtkTreeIter                  *iter,
+                                                                         GtkTreeIter                  *child);
+static gboolean           thunar_list_model_drag_data_received          (GtkTreeDragDest              *dest,
+                                                                         GtkTreePath                  *path,
+                                                                         GtkSelectionData             *data);
+static gboolean           thunar_list_model_row_drop_possible           (GtkTreeDragDest              *dest,
+                                                                         GtkTreePath                  *path,
+                                                                         GtkSelectionData             *data);
+static gboolean           thunar_list_model_get_sort_column_id          (GtkTreeSortable              *sortable,
+                                                                         gint                         *sort_column_id,
+                                                                         GtkSortType                  *order);
+static void               thunar_list_model_set_sort_column_id          (GtkTreeSortable              *sortable,
+                                                                         gint                          sort_column_id,
+                                                                         GtkSortType                   order);
+static void               thunar_list_model_set_default_sort_func       (GtkTreeSortable              *sortable,
+                                                                         GtkTreeIterCompareFunc        func,
+                                                                         gpointer                      data,
+                                                                         GDestroyNotify                destroy);
+static void               thunar_list_model_set_sort_func               (GtkTreeSortable              *sortable,
+                                                                         gint                          sort_column_id,
+                                                                         GtkTreeIterCompareFunc        func,
+                                                                         gpointer                      data,
+                                                                         GDestroyNotify                destroy);
+static gboolean           thunar_list_model_has_default_sort_func       (GtkTreeSortable              *sortable);
+static gint               thunar_list_model_cmp_func                    (gconstpointer                 a,
+                                                                         gconstpointer                 b,
+                                                                         gpointer                      user_data);
+static void               thunar_list_model_sort                        (ThunarListModel              *store);
+static void               thunar_list_model_file_changed                (ThunarFileMonitor            *file_monitor,
+                                                                         ThunarFile                   *file,
+                                                                         ThunarListModel              *store);
+static void               thunar_list_model_folder_destroy              (ThunarFolder                 *folder,
+                                                                         ThunarListModel              *store);
+static void               thunar_list_model_folder_error                (ThunarFolder                 *folder,
+                                                                         const GError                 *error,
+                                                                         ThunarListModel              *store);
+static void               thunar_list_model_files_added                 (ThunarFolder                 *folder,
+                                                                         GList                        *files,
+                                                                         ThunarListModel              *store);
+static void               thunar_list_model_files_removed               (ThunarFolder                 *folder,
+                                                                         GList                        *files,
+                                                                         ThunarListModel              *store);
+static gint               sort_by_date                                  (const ThunarFile             *a,
+                                                                         const ThunarFile             *b,
+                                                                         gboolean                      case_sensitive,
+                                                                         gint                          type);
+static gint               sort_by_date_created                          (const ThunarFile             *a,
+                                                                         const ThunarFile             *b,
+                                                                         gboolean                      case_sensitive);
+static gint               sort_by_date_accessed                         (const ThunarFile             *a,
+                                                                         const ThunarFile             *b,
+                                                                         gboolean                      case_sensitive);
+static gint               sort_by_date_modified                         (const ThunarFile             *a,
+                                                                         const ThunarFile             *b,
+                                                                         gboolean                      case_sensitive);
+static gint               sort_by_date_deleted                          (const ThunarFile             *a,
+                                                                         const ThunarFile             *b,
+                                                                         gboolean                      case_sensitive);
+static gint               sort_by_recency                               (const ThunarFile             *a,
+                                                                         const ThunarFile             *b,
+                                                                         gboolean                      case_sensitive);
+static gint               sort_by_location                              (const ThunarFile             *a,
+                                                                         const ThunarFile             *b,
+                                                                         gboolean                      case_sensitive);
+static gint               sort_by_group                                 (const ThunarFile             *a,
+                                                                         const ThunarFile             *b,
+                                                                         gboolean                      case_sensitive);
+static gint               sort_by_mime_type                             (const ThunarFile             *a,
+                                                                         const ThunarFile             *b,
+                                                                         gboolean                      case_sensitive);
+static gint               sort_by_owner                                 (const ThunarFile             *a,
+                                                                         const ThunarFile             *b,
+                                                                         gboolean                      case_sensitive);
+static gint               sort_by_permissions                           (const ThunarFile             *a,
+                                                                         const ThunarFile             *b,
+                                                                         gboolean                      case_sensitive);
+static gint               sort_by_size                                  (const ThunarFile             *a,
+                                                                         const ThunarFile             *b,
+                                                                         gboolean                      case_sensitive);
+static gint               sort_by_size_in_bytes                         (const ThunarFile             *a,
+                                                                         const ThunarFile             *b,
+                                                                         gboolean                      case_sensitive);
+static gint               sort_by_size_and_items_count                  (ThunarFile                   *a,
+                                                                         ThunarFile                   *b,
+                                                                         gboolean                      case_sensitive);
+static gint               sort_by_type                                  (const ThunarFile             *a,
+                                                                         const ThunarFile             *b,
+                                                                         gboolean                      case_sensitive);
+
+static gboolean           thunar_list_model_get_case_sensitive          (ThunarListModel              *store);
+static void               thunar_list_model_set_case_sensitive          (ThunarListModel              *store,
+                                                                         gboolean                      case_sensitive);
+static ThunarDateStyle    thunar_list_model_get_date_style              (ThunarListModel              *store);
+static void               thunar_list_model_set_date_style              (ThunarListModel              *store,
+                                                                         ThunarDateStyle               date_style);
+static const char*        thunar_list_model_get_date_custom_style       (ThunarListModel              *store);
+static void               thunar_list_model_set_date_custom_style       (ThunarListModel              *store,
+                                                                         const char                   *date_custom_style);
+static gint               thunar_list_model_get_num_files               (ThunarListModel              *store);
+static gboolean           thunar_list_model_get_folders_first           (ThunarListModel              *store);
+static ThunarJob*         thunar_list_model_job_search_directory        (ThunarListModel              *model,
+                                                                         const gchar                  *search_query_c,
+                                                                         ThunarFile                   *directory);
+static void               thunar_list_model_search_folder               (ThunarListModel              *model,
+                                                                         ThunarJob                    *job,
+                                                                         gchar                        *uri,
+                                                                         gchar                       **search_query_c_terms,
+                                                                         enum ThunarListModelSearch    search_type,
+                                                                         gboolean                      show_hidden);
+static void               thunar_list_model_cancel_search_job           (ThunarListModel              *model);
+
+static gint               thunar_list_model_get_folder_item_count       (ThunarListModel              *store);
+static void               thunar_list_model_set_folder_item_count       (ThunarListModel              *store,
+                                                                         ThunarFolderItemCount         count_as_dir_size);
+
+static void               thunar_list_model_file_count_callback         (ExoJob                       *job,
+                                                                         gpointer                      model);
 
 struct _ThunarListModelClass
 {
@@ -245,13 +255,14 @@ struct _ThunarListModel
   gint           stamp;
 #endif
 
-  GSequence      *rows;
-  GSList         *hidden;
-  ThunarFolder   *folder;
-  gboolean        show_hidden : 1;
-  gboolean        file_size_binary : 1;
-  ThunarDateStyle date_style;
-  char           *date_custom_style;
+  GSequence               *rows;
+  GSList                  *hidden;
+  ThunarFolder            *folder;
+  gboolean                 show_hidden : 1;
+  ThunarFolderItemCount    folder_item_count;
+  gboolean                 file_size_binary : 1;
+  ThunarDateStyle          date_style;
+  char                    *date_custom_style;
 
   /* Use the shared ThunarFileMonitor instance, so we
    * do not need to connect "changed" handler to every
@@ -405,6 +416,19 @@ thunar_list_model_class_init (ThunarListModelClass *klass)
                             TRUE,
                             EXO_PARAM_READWRITE);
 
+  /**
+   * ThunarListModel:folder-item-count:
+   *
+   * Tells when the size column of folders should show the number of containing files
+   **/
+  list_model_props[PROP_FOLDER_ITEM_COUNT] =
+      g_param_spec_enum ("folder-item-count",
+                         "folder-item-count",
+                         "folder-item-count",
+                         THUNAR_TYPE_FOLDER_ITEM_COUNT,
+                         TRUE,
+                         EXO_PARAM_READWRITE);
+
   /* install properties */
   g_object_class_install_properties (gobject_class, N_PROPERTIES, list_model_props);
 
@@ -594,6 +618,10 @@ thunar_list_model_get_property (GObject    *object,
       g_value_set_boolean (value, thunar_list_model_get_file_size_binary (store));
       break;
 
+    case PROP_FOLDER_ITEM_COUNT:
+      g_value_set_enum (value, thunar_list_model_get_folder_item_count (store));
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -640,6 +668,10 @@ thunar_list_model_set_property (GObject      *object,
       thunar_list_model_set_file_size_binary (store, g_value_get_boolean (value));
       break;
 
+    case PROP_FOLDER_ITEM_COUNT:
+      thunar_list_model_set_folder_item_count (store, g_value_get_enum (value));
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -783,9 +815,10 @@ thunar_list_model_get_value (GtkTreeModel *model,
   ThunarUser   *user;
   ThunarFile   *file;
   ThunarFolder *folder;
+  gchar        *str;
+  guint32       item_count;
   GFile        *g_file;
   GFile        *g_file_parent;
-  gchar        *str;
 
   _thunar_return_if_fail (THUNAR_IS_LIST_MODEL (model));
   _thunar_return_if_fail (iter->stamp == (THUNAR_LIST_MODEL (model))->stamp);
@@ -930,6 +963,7 @@ thunar_list_model_get_value (GtkTreeModel *model,
 
     case THUNAR_COLUMN_SIZE:
       g_value_init (value, G_TYPE_STRING);
+
       if (thunar_file_is_mountable (file))
         {
           g_file = thunar_file_get_target_location (file);
@@ -939,8 +973,38 @@ thunar_list_model_get_value (GtkTreeModel *model,
           g_object_unref (g_file);
           break;
         }
-      if (!thunar_file_is_directory (file))
-        g_value_take_string (value, thunar_file_get_size_string_formatted (file, THUNAR_LIST_MODEL (model)->file_size_binary));
+      else if (thunar_file_is_directory (file))
+        {
+          /* If the option is set to never show folder sizes as item counts, then just give the folder's binary size */
+          if (THUNAR_LIST_MODEL (model)->folder_item_count == THUNAR_FOLDER_ITEM_COUNT_NEVER)
+            g_value_take_string (value, thunar_file_get_size_string_formatted (file, THUNAR_LIST_MODEL (model)->file_size_binary));
+
+          /* If the option is set to always show folder sizes as item counts, then give the folder's item count */
+          else if (THUNAR_LIST_MODEL (model)->folder_item_count == THUNAR_FOLDER_ITEM_COUNT_ALWAYS)
+            {
+              item_count = thunar_file_get_file_count (file, G_CALLBACK (thunar_list_model_file_count_callback), model);
+              g_value_take_string (value, g_strdup_printf (ngettext ("%u item", "%u items", item_count), item_count));
+            }
+
+          /* If the option is set to always show folder sizes as item counts only for local files,
+           * check if the files is local or not, and act accordingly */
+          else if (THUNAR_LIST_MODEL (model)->folder_item_count == THUNAR_FOLDER_ITEM_COUNT_ONLY_LOCAL)
+            {
+              if (thunar_file_is_local (file))
+                {
+                  item_count = thunar_file_get_file_count (file, G_CALLBACK (thunar_list_model_file_count_callback), model);
+                  g_value_take_string (value, g_strdup_printf (ngettext ("%u item", "%u items", item_count), item_count));
+                }
+              else
+                g_value_take_string (value, thunar_file_get_size_string_formatted (file, THUNAR_LIST_MODEL (model)->file_size_binary));
+            }
+          else
+              g_warning ("Error, unknown enum value for folder_item_count in the list model");
+        }
+      else
+        {
+          g_value_take_string (value, thunar_file_get_size_string_formatted (file, THUNAR_LIST_MODEL (model)->file_size_binary));
+        }
       break;
 
     case THUNAR_COLUMN_SIZE_IN_BYTES:
@@ -1104,7 +1168,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 == (ThunarSortFunc) sort_by_size_and_items_count)
     *sort_column_id = THUNAR_COLUMN_SIZE;
   else if (store->sort_func == sort_by_size_in_bytes)
     *sort_column_id = THUNAR_COLUMN_SIZE_IN_BYTES;
@@ -1199,7 +1263,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->folder_item_count != THUNAR_FOLDER_ITEM_COUNT_NEVER) ? (ThunarSortFunc) sort_by_size_and_items_count : sort_by_size;
       break;
 
     case THUNAR_COLUMN_SIZE_IN_BYTES:
@@ -1355,7 +1419,7 @@ thunar_list_model_file_changed (ThunarFileMonitor *file_monitor,
   GtkTreePath   *path;
   GtkTreeIter    iter;
 
-  _thunar_return_if_fail (THUNAR_IS_FILE_MONITOR (file_monitor));
+  _thunar_return_if_fail (THUNAR_IS_FILE_MONITOR (file_monitor) || file_monitor == NULL);
   _thunar_return_if_fail (THUNAR_IS_LIST_MODEL (store));
   _thunar_return_if_fail (THUNAR_IS_FILE (file));
 
@@ -1858,6 +1922,32 @@ sort_by_size_in_bytes (const ThunarFile *a,
 
 
 
+static gint
+sort_by_size_and_items_count (ThunarFile *a,
+                              ThunarFile *b,
+                              gboolean    case_sensitive)
+{
+  guint32       count_a;
+  guint32       count_b;
+
+  if (thunar_file_is_directory (a) && thunar_file_is_directory (b))
+  {
+    count_a = thunar_file_get_file_count (a, NULL, NULL);
+    count_b = thunar_file_get_file_count (b, NULL, NULL);
+
+    if (count_a < count_b)
+      return -1;
+    else if (count_a > count_b)
+      return 1;
+    else
+      return thunar_file_compare_by_name (a, b, case_sensitive);
+  }
+
+  return sort_by_size(a, b, case_sensitive);
+}
+
+
+
 static gint
 sort_by_type (const ThunarFile *a,
               const ThunarFile *b,
@@ -2691,6 +2781,51 @@ thunar_list_model_set_file_size_binary (ThunarListModel *store,
 
 
 
+/**
+ * thunar_list_model_get_folder_item_count:
+ * @store : a #ThunarListModel.
+ *
+ * Return value: A value of the enum #ThunarFolderItemCount
+ **/
+static gint
+thunar_list_model_get_folder_item_count (ThunarListModel *store)
+{
+  _thunar_return_val_if_fail (THUNAR_IS_LIST_MODEL (store), FALSE);
+  return store->folder_item_count;
+}
+
+
+
+/**
+ * thunar_list_model_set_folder_item_count:
+ * @store             : a #ThunarListModel.
+ * @count_as_dir_size : a value of the enum #ThunarFolderItemCount
+ **/
+static void
+thunar_list_model_set_folder_item_count (ThunarListModel         *store,
+                                         ThunarFolderItemCount    count_as_dir_size)
+{
+  _thunar_return_if_fail (THUNAR_IS_LIST_MODEL (store));
+
+  /* check if the new setting differs */
+  if (store->folder_item_count == count_as_dir_size)
+    return;
+
+  store->folder_item_count = count_as_dir_size;
+  g_object_notify_by_pspec (G_OBJECT (store), list_model_props[PROP_FOLDER_ITEM_COUNT]);
+
+  gtk_tree_model_foreach (GTK_TREE_MODEL (store), (GtkTreeModelForeachFunc) (void (*)(void)) gtk_tree_model_row_changed, NULL);
+
+  /* re-sorting the store if needed */
+  if (store->sort_func == sort_by_size || store->sort_func == (ThunarSortFunc) sort_by_size_and_items_count)
+  {
+    store->sort_func = (store->folder_item_count != THUNAR_FOLDER_ITEM_COUNT_NEVER) ? (ThunarSortFunc) sort_by_size_and_items_count : sort_by_size;
+    thunar_list_model_sort (store);
+  }
+}
+
+
+
 /**
  * thunar_list_model_get_file:
  * @store : a #ThunarListModel.
@@ -3156,3 +3291,21 @@ thunar_list_model_get_statusbar_text (ThunarListModel *store,
   g_object_unref (preferences);
   return text;
 }
+
+
+
+static void
+thunar_list_model_file_count_callback (ExoJob  *job,
+                                       gpointer model)
+{
+  GArray     *param_values;
+  ThunarFile *file;
+
+  param_values = thunar_simple_job_get_param_values (THUNAR_SIMPLE_JOB (job));
+  file = THUNAR_FILE (g_value_get_object (&g_array_index (param_values, GValue, 0)));
+
+  if (file == NULL)
+    return;
+
+  thunar_list_model_file_changed (NULL, file, THUNAR_LIST_MODEL (model));
+}
diff --git a/thunar/thunar-preferences-dialog.c b/thunar/thunar-preferences-dialog.c
index 04ffa239e..05f527235 100644
--- a/thunar/thunar-preferences-dialog.c
+++ b/thunar/thunar-preferences-dialog.c
@@ -164,45 +164,6 @@ transform_view_index_to_string (GBinding     *binding,
 
 
 
-static gboolean
-transform_enum_value_to_index (GBinding     *binding,
-                         const GValue *src_value,
-                         GValue       *dst_value,
-                         gpointer      user_data)
-{
-  GEnumClass *klass;
-  GType     (*type_func)() = user_data;
-  guint       n;
-
-  klass = g_type_class_ref (type_func ());
-  for (n = 0; n < klass->n_values; ++n)
-    if (klass->values[n].value == g_value_get_enum (src_value))
-      g_value_set_int (dst_value, n);
-  g_type_class_unref (klass);
-
-  return TRUE;
-}
-
-
-
-static gboolean
-transform_index_to_enum_value (GBinding     *binding,
-                         const GValue *src_value,
-                         GValue       *dst_value,
-                         gpointer      user_data)
-{
-  GEnumClass *klass;
-  GType     (*type_func)() = user_data;
-
-  klass = g_type_class_ref (type_func ());
-  g_value_set_enum (dst_value, klass->values[g_value_get_int (src_value)].value);
-  g_type_class_unref (klass);
-
-  return TRUE;
-}
-
-
-
 static gboolean
 transform_string_to_uint64 (GBinding     *binding,
                             const GValue *src_value,
diff --git a/thunar/thunar-preferences.c b/thunar/thunar-preferences.c
index 2a5d6d4b8..eb581a6c8 100644
--- a/thunar/thunar-preferences.c
+++ b/thunar/thunar-preferences.c
@@ -89,6 +89,7 @@ enum
   PROP_MISC_DATE_CUSTOM_STYLE,
   PROP_EXEC_SHELL_SCRIPTS_BY_DEFAULT,
   PROP_MISC_FOLDERS_FIRST,
+  PROP_MISC_FOLDER_ITEM_COUNT,
   PROP_MISC_FULL_PATH_IN_TAB_TITLE,
   PROP_MISC_FULL_PATH_IN_WINDOW_TITLE,
   PROP_MISC_HORIZONTAL_WHEEL_NAVIGATES,
@@ -687,6 +688,19 @@ thunar_preferences_class_init (ThunarPreferencesClass *klass)
                             TRUE,
                             EXO_PARAM_READWRITE);
 
+  /**
+   * ThunarPreferences:misc-folder-item-count
+   *
+   * Tells when the size column of folders should show the number of containing files
+   **/
+  preferences_props[PROP_MISC_FOLDER_ITEM_COUNT] =
+      g_param_spec_enum ("misc-folder-item-count",
+                         "MiscFolderItemCount",
+                         NULL,
+                         THUNAR_TYPE_FOLDER_ITEM_COUNT,
+                         THUNAR_FOLDER_ITEM_COUNT_NEVER,
+                         EXO_PARAM_READWRITE);
+
   /**
    * ThunarPreferences:misc-full-path-in-tab-title:
    *
diff --git a/thunar/thunar-standard-view.c b/thunar/thunar-standard-view.c
index 852dbaea4..d6ef4a2ba 100644
--- a/thunar/thunar-standard-view.c
+++ b/thunar/thunar-standard-view.c
@@ -831,6 +831,7 @@ thunar_standard_view_init (ThunarStandardView *standard_view)
   g_object_bind_property (G_OBJECT (standard_view->preferences), "misc-date-custom-style", G_OBJECT (standard_view->model), "date-custom-style", G_BINDING_SYNC_CREATE);
   g_object_bind_property (G_OBJECT (standard_view->preferences), "misc-folders-first", G_OBJECT (standard_view->model), "folders-first", G_BINDING_SYNC_CREATE);
   g_object_bind_property (G_OBJECT (standard_view->preferences), "misc-file-size-binary", G_OBJECT (standard_view->model), "file-size-binary", G_BINDING_SYNC_CREATE);
+  g_object_bind_property (G_OBJECT (standard_view->preferences), "misc-folder-item-count", G_OBJECT (standard_view->model), "folder-item-count", G_BINDING_SYNC_CREATE);
 
   /* setup the icon renderer */
   standard_view->icon_renderer = thunar_icon_renderer_new ();
-- 
GitLab