[Xfce4-commits] <thunar:nick/multiple-file-properties> Some initial work to get things starting.

Nick Schermer noreply at xfce.org
Mon Sep 10 20:54:02 CEST 2012


Updating branch refs/heads/nick/multiple-file-properties
         to 8012573c62182c52550970360a526f3835e5366c (commit)
       from b8cc0567f7c35e10443c511aeed05686137ceb99 (commit)

commit 8012573c62182c52550970360a526f3835e5366c
Author: Nick Schermer <nick at xfce.org>
Date:   Mon Sep 10 20:52:24 2012 +0200

    Some initial work to get things starting.

 thunar/thunar-dbus-service.c      |    2 +-
 thunar/thunar-location-buttons.c  |    4 +-
 thunar/thunar-properties-dialog.c |  316 ++++++++++++++++++++++---------------
 thunar/thunar-properties-dialog.h |   11 +-
 thunar/thunar-renamer-dialog.c    |   18 +--
 thunar/thunar-size-label.c        |  161 ++++++-------------
 thunar/thunar-size-label.h        |    6 +-
 thunar/thunar-standard-view.c     |  119 +++++++-------
 thunar/thunar-tree-view.c         |    4 +-
 9 files changed, 316 insertions(+), 325 deletions(-)

diff --git a/thunar/thunar-dbus-service.c b/thunar/thunar-dbus-service.c
index 202b06c..ae8ad85 100644
--- a/thunar/thunar-dbus-service.c
+++ b/thunar/thunar-dbus-service.c
@@ -512,7 +512,7 @@ thunar_dbus_service_display_file_properties (ThunarDBusService *dbus_service,
     return FALSE;
 
   /* popup the file properties dialog */
-  dialog = thunar_properties_dialog_new ();
+  dialog = thunar_properties_dialog_new (NULL);
   gtk_window_set_screen (GTK_WINDOW (dialog), screen);
   gtk_window_set_startup_id (GTK_WINDOW (dialog), startup_id);
   thunar_properties_dialog_set_file (THUNAR_PROPERTIES_DIALOG (dialog), file);
diff --git a/thunar/thunar-location-buttons.c b/thunar/thunar-location-buttons.c
index f9a4310..148ce7d 100644
--- a/thunar/thunar-location-buttons.c
+++ b/thunar/thunar-location-buttons.c
@@ -1434,10 +1434,8 @@ thunar_location_buttons_action_properties (GtkAction             *action,
       if (G_LIKELY (toplevel != NULL && GTK_WIDGET_TOPLEVEL (toplevel)))
         {
           /* popup the properties dialog */
-          dialog = thunar_properties_dialog_new ();
-          gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
+          dialog = thunar_properties_dialog_new (GTK_WINDOW (toplevel));
           thunar_properties_dialog_set_file (THUNAR_PROPERTIES_DIALOG (dialog), directory);
-          gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (toplevel));
           gtk_widget_show (dialog);
         }
     }
diff --git a/thunar/thunar-properties-dialog.c b/thunar/thunar-properties-dialog.c
index 1e2de45..c04ed92 100644
--- a/thunar/thunar-properties-dialog.c
+++ b/thunar/thunar-properties-dialog.c
@@ -3,18 +3,18 @@
  * Copyright (c) 2005-2007 Benedikt Meurer <benny at xfce.org>
  * Copyright (c) 2009-2011 Jannis Pohlmann <jannis at xfce.org>
  *
- * This program is free software; you can redistribute it and/or 
+ * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of 
+ * published by the Free Software Foundation; either version 2 of
  * the License, or (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public 
- * License along with this program; if not, write to the Free 
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the Free
  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301, USA.
  */
@@ -62,7 +62,7 @@
 enum
 {
   PROP_0,
-  PROP_FILE,
+  PROP_FILES,
 };
 
 /* Signal identifiers */
@@ -87,9 +87,9 @@ static void     thunar_properties_dialog_set_property         (GObject
 static void     thunar_properties_dialog_response             (GtkDialog                   *dialog,
                                                                gint                         response);
 static gboolean thunar_properties_dialog_reload               (ThunarPropertiesDialog      *dialog);
-static void     thunar_properties_dialog_activate             (GtkWidget                   *entry,
+static void     thunar_properties_dialog_name_activate        (GtkWidget                   *entry,
                                                                ThunarPropertiesDialog      *dialog);
-static gboolean thunar_properties_dialog_focus_out_event      (GtkWidget                   *entry,
+static gboolean thunar_properties_dialog_name_focus_out_event (GtkWidget                   *entry,
                                                                GdkEventFocus               *event,
                                                                ThunarPropertiesDialog      *dialog);
 static void     thunar_properties_dialog_icon_button_clicked  (GtkWidget                   *button,
@@ -116,7 +116,7 @@ struct _ThunarPropertiesDialog
 
   ThunarPreferences      *preferences;
 
-  ThunarFile             *file;
+  GList                  *files;
 
   ThunarThumbnailer      *thumbnailer;
   guint                   thumbnail_request;
@@ -164,16 +164,16 @@ thunar_properties_dialog_class_init (ThunarPropertiesDialogClass *klass)
   klass->reload = thunar_properties_dialog_reload;
 
   /**
-   * ThunarPropertiesDialog:file:
+   * ThunarPropertiesDialog:files:
    *
-   * The #ThunarFile whose properties are currently displayed by
+   * The list of currently selected files whose properties are displayed by
    * this #ThunarPropertiesDialog. This property may also be %NULL
    * in which case nothing is displayed.
    **/
   g_object_class_install_property (gobject_class,
-                                   PROP_FILE,
-                                   g_param_spec_object ("file", "file", "file",
-                                                        THUNAR_TYPE_FILE,
+                                   PROP_FILES,
+                                   g_param_spec_boxed ("files", "files", "files",
+                                                        THUNARX_TYPE_FILE_INFO_LIST,
                                                         EXO_PARAM_READWRITE));
 
   /**
@@ -265,8 +265,8 @@ thunar_properties_dialog_init (ThunarPropertiesDialog *dialog)
   gtk_widget_show (label);
 
   dialog->name_entry = g_object_new (GTK_TYPE_ENTRY, "editable", FALSE, NULL);
-  g_signal_connect (G_OBJECT (dialog->name_entry), "activate", G_CALLBACK (thunar_properties_dialog_activate), dialog);
-  g_signal_connect (G_OBJECT (dialog->name_entry), "focus-out-event", G_CALLBACK (thunar_properties_dialog_focus_out_event), dialog);
+  g_signal_connect (G_OBJECT (dialog->name_entry), "activate", G_CALLBACK (thunar_properties_dialog_name_activate), dialog);
+  g_signal_connect (G_OBJECT (dialog->name_entry), "focus-out-event", G_CALLBACK (thunar_properties_dialog_name_focus_out_event), dialog);
   gtk_table_attach (GTK_TABLE (table), dialog->name_entry, 1, 2, row, row + 1, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 3);
   gtk_widget_show (dialog->name_entry);
 
@@ -312,7 +312,7 @@ thunar_properties_dialog_init (ThunarPropertiesDialog *dialog)
   gtk_widget_show (label);
 
   dialog->openwith_chooser = thunar_chooser_button_new ();
-  exo_binding_new (G_OBJECT (dialog), "file", G_OBJECT (dialog->openwith_chooser), "file");
+  /*TODO exo_binding_new (G_OBJECT (dialog), "file", G_OBJECT (dialog->openwith_chooser), "file");*/
   exo_binding_new (G_OBJECT (dialog->openwith_chooser), "visible", G_OBJECT (label), "visible");
   gtk_table_attach (GTK_TABLE (table), dialog->openwith_chooser, 1, 2, row, row + 1, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 3);
   gtk_widget_show (dialog->openwith_chooser);
@@ -422,7 +422,7 @@ thunar_properties_dialog_init (ThunarPropertiesDialog *dialog)
   gtk_widget_show (label);
 
   label = thunar_size_label_new ();
-  exo_binding_new (G_OBJECT (dialog), "file", G_OBJECT (label), "file");
+  exo_binding_new (G_OBJECT (dialog), "files", G_OBJECT (label), "files");
   gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row + 1, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 3);
   gtk_widget_show (label);
 
@@ -479,18 +479,17 @@ thunar_properties_dialog_init (ThunarPropertiesDialog *dialog)
    */
   label = gtk_label_new (_("Emblems"));
   chooser = thunar_emblem_chooser_new ();
-  exo_binding_new (G_OBJECT (dialog), "file", G_OBJECT (chooser), "file");
+  /*TODOexo_binding_new (G_OBJECT (dialog), "file", G_OBJECT (chooser), "file");*/
   gtk_notebook_append_page (GTK_NOTEBOOK (dialog->notebook), chooser, label);
   gtk_widget_show (chooser);
   gtk_widget_show (label);
 
-
   /*
      Permissions chooser
    */
   label = gtk_label_new (_("Permissions"));
   dialog->permissions_chooser = thunar_permissions_chooser_new ();
-  exo_binding_new (G_OBJECT (dialog), "file", G_OBJECT (dialog->permissions_chooser), "file");
+  /*TODOexo_binding_new (G_OBJECT (dialog), "files", G_OBJECT (dialog->permissions_chooser), "files");*/
   gtk_notebook_append_page (GTK_NOTEBOOK (dialog->notebook), dialog->permissions_chooser, label);
   gtk_widget_show (dialog->permissions_chooser);
   gtk_widget_show (label);
@@ -508,7 +507,7 @@ thunar_properties_dialog_dispose (GObject *object)
   ThunarPropertiesDialog *dialog = THUNAR_PROPERTIES_DIALOG (object);
 
   /* reset the file displayed by the dialog */
-  thunar_properties_dialog_set_file (dialog, NULL);
+  thunar_properties_dialog_set_files (dialog, NULL);
 
   (*G_OBJECT_CLASS (thunar_properties_dialog_parent_class)->dispose) (object);
 }
@@ -520,6 +519,8 @@ thunar_properties_dialog_finalize (GObject *object)
 {
   ThunarPropertiesDialog *dialog = THUNAR_PROPERTIES_DIALOG (object);
 
+  _thunar_return_if_fail (dialog->files == NULL);
+
   /* disconnect from the preferences */
   g_signal_handlers_disconnect_by_func (dialog->preferences, thunar_properties_dialog_reload, dialog);
   g_object_unref (dialog->preferences);
@@ -556,8 +557,8 @@ thunar_properties_dialog_get_property (GObject    *object,
 
   switch (prop_id)
     {
-    case PROP_FILE:
-      g_value_set_object (value, thunar_properties_dialog_get_file (dialog));
+    case PROP_FILES:
+      g_value_set_boxed (value, thunar_properties_dialog_get_files (dialog));
       break;
 
     default:
@@ -578,8 +579,8 @@ thunar_properties_dialog_set_property (GObject      *object,
 
   switch (prop_id)
     {
-    case PROP_FILE:
-      thunar_properties_dialog_set_file (dialog, g_value_get_object (value));
+    case PROP_FILES:
+      thunar_properties_dialog_set_files (dialog, g_value_get_boxed (value));
       break;
 
     default:
@@ -615,20 +616,10 @@ thunar_properties_dialog_response (GtkDialog *dialog,
 static gboolean
 thunar_properties_dialog_reload (ThunarPropertiesDialog *dialog)
 {
-  /* verify that we still have a file */
-  if (G_LIKELY (dialog->file != NULL))
-    {
-      /* reload the file status */
-      thunar_file_reload (dialog->file);
+  /* reload the active files */
+  g_list_foreach (dialog->files, (GFunc) thunar_file_reload, NULL);
 
-      /* we handled the event */
-      return TRUE;
-    }
-  else
-    {
-      /* did not handle the event */
-      return FALSE;
-    }
+  return dialog->files != NULL;
 }
 
 
@@ -641,10 +632,11 @@ thunar_properties_dialog_rename_error (ExoJob                 *job,
   _thunar_return_if_fail (EXO_IS_JOB (job));
   _thunar_return_if_fail (error != NULL);
   _thunar_return_if_fail (THUNAR_IS_PROPERTIES_DIALOG (dialog));
+  _thunar_return_if_fail (g_list_length (dialog->files) == 1);
 
   /* display an error message */
   thunar_dialogs_show_error (GTK_WIDGET (dialog), error, _("Failed to rename \"%s\""),
-                             thunar_file_get_display_name (dialog->file));
+                             thunar_file_get_display_name (THUNAR_FILE (dialog->files->data)));
 }
 
 
@@ -657,9 +649,10 @@ thunar_properties_dialog_rename_finished (ExoJob                 *job,
 
   _thunar_return_if_fail (EXO_IS_JOB (job));
   _thunar_return_if_fail (THUNAR_IS_PROPERTIES_DIALOG (dialog));
+  _thunar_return_if_fail (g_list_length (dialog->files) == 1);
 
   /* determine the new display name */
-  new_name = thunar_file_get_display_name (dialog->file);
+  new_name = thunar_file_get_display_name (THUNAR_FILE (dialog->files->data));
 
   /* reset the entry widget to the new name */
   gtk_entry_set_text (GTK_ENTRY (dialog->name_entry), new_name);
@@ -671,23 +664,28 @@ thunar_properties_dialog_rename_finished (ExoJob                 *job,
 
 
 static void
-thunar_properties_dialog_activate (GtkWidget              *entry,
-                                   ThunarPropertiesDialog *dialog)
+thunar_properties_dialog_name_activate (GtkWidget              *entry,
+                                        ThunarPropertiesDialog *dialog)
 {
   const gchar *old_name;
   ThunarJob   *job;
   gchar       *new_name;
+  ThunarFile  *file;
+
+  _thunar_return_if_fail (THUNAR_IS_PROPERTIES_DIALOG (dialog));
 
   /* check if we still have a valid file and if the user is allowed to rename */
-  if (G_UNLIKELY (dialog->file == NULL || !GTK_WIDGET_SENSITIVE (dialog->name_entry)))
+  if (G_UNLIKELY (!GTK_WIDGET_SENSITIVE (dialog->name_entry)
+      || g_list_length (dialog->files) != 1))
     return;
 
   /* determine new and old name */
+  file = THUNAR_FILE (dialog->files->data);
   new_name = gtk_editable_get_chars (GTK_EDITABLE (dialog->name_entry), 0, -1);
-  old_name = thunar_file_get_display_name (dialog->file);
+  old_name = thunar_file_get_display_name (file);
   if (g_utf8_collate (new_name, old_name) != 0)
     {
-      job = thunar_io_jobs_rename_file (dialog->file, new_name);
+      job = thunar_io_jobs_rename_file (file, new_name);
       if (job != NULL)
         {
           g_signal_connect (job, "error", G_CALLBACK (thunar_properties_dialog_rename_error), dialog);
@@ -699,11 +697,11 @@ thunar_properties_dialog_activate (GtkWidget              *entry,
 
 
 static gboolean
-thunar_properties_dialog_focus_out_event (GtkWidget              *entry,
-                                          GdkEventFocus          *event,
-                                          ThunarPropertiesDialog *dialog)
+thunar_properties_dialog_name_focus_out_event (GtkWidget              *entry,
+                                               GdkEventFocus          *event,
+                                               ThunarPropertiesDialog *dialog)
 {
-  thunar_properties_dialog_activate (entry, dialog);
+  thunar_properties_dialog_name_activate (entry, dialog);
   return FALSE;
 }
 
@@ -713,21 +711,25 @@ static void
 thunar_properties_dialog_icon_button_clicked (GtkWidget              *button,
                                               ThunarPropertiesDialog *dialog)
 {
-  GtkWidget *chooser;
-  GError    *err = NULL;
-  gchar     *custom_icon;
-  gchar     *title;
-  gchar     *icon;
+  GtkWidget  *chooser;
+  GError     *err = NULL;
+  gchar      *custom_icon;
+  gchar      *title;
+  gchar      *icon;
+  ThunarFile *file;
 
   _thunar_return_if_fail (THUNAR_IS_PROPERTIES_DIALOG (dialog));
   _thunar_return_if_fail (GTK_IS_BUTTON (button));
+  _thunar_return_if_fail (g_list_length (dialog->files) == 1);
 
   /* make sure we still have a file */
-  if (G_UNLIKELY (dialog->file == NULL))
+  if (G_UNLIKELY (dialog->files == NULL))
     return;
 
+  file = THUNAR_FILE (dialog->files->data);
+
   /* allocate the icon chooser */
-  title = g_strdup_printf (_("Select an Icon for \"%s\""), thunar_file_get_display_name (dialog->file));
+  title = g_strdup_printf (_("Select an Icon for \"%s\""), thunar_file_get_display_name (file));
   chooser = exo_icon_chooser_dialog_new (title, GTK_WINDOW (dialog),
                                          GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                          GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
@@ -737,23 +739,25 @@ thunar_properties_dialog_icon_button_clicked (GtkWidget              *button,
   g_free (title);
 
   /* use the custom_icon of the file as default */
-  custom_icon = thunar_file_get_custom_icon (dialog->file);
+  custom_icon = thunar_file_get_custom_icon (file);
   if (G_LIKELY (custom_icon != NULL && *custom_icon != '\0'))
     exo_icon_chooser_dialog_set_icon (EXO_ICON_CHOOSER_DIALOG (chooser), custom_icon);
   g_free (custom_icon);
 
   /* run the icon chooser dialog and make sure the dialog still has a file */
-  if (gtk_dialog_run (GTK_DIALOG (chooser)) == GTK_RESPONSE_ACCEPT && dialog->file != NULL)
+  if (gtk_dialog_run (GTK_DIALOG (chooser)) == GTK_RESPONSE_ACCEPT && file != NULL)
     {
       /* determine the selected icon and use it for the file */
       icon = exo_icon_chooser_dialog_get_icon (EXO_ICON_CHOOSER_DIALOG (chooser));
-      if (!thunar_file_set_custom_icon (dialog->file, icon, &err))
+      if (!thunar_file_set_custom_icon (file, icon, &err))
         {
           /* hide the icon chooser dialog first */
           gtk_widget_hide (chooser);
 
           /* tell the user that we failed to change the icon of the .desktop file */
-          thunar_dialogs_show_error (GTK_WIDGET (dialog), err, _("Failed to change icon of \"%s\""), thunar_file_get_display_name (dialog->file));
+          thunar_dialogs_show_error (GTK_WIDGET (dialog), err,
+                                     _("Failed to change icon of \"%s\""),
+                                     thunar_file_get_display_name (file));
           g_error_free (err);
         }
       g_free (icon);
@@ -771,7 +775,6 @@ thunar_properties_dialog_update_providers (ThunarPropertiesDialog *dialog)
   GtkWidget *label_widget;
   GList     *providers;
   GList     *pages = NULL;
-  GList      files;
   GList     *tmp;
   GList     *lp;
 
@@ -779,13 +782,10 @@ thunar_properties_dialog_update_providers (ThunarPropertiesDialog *dialog)
   providers = thunarx_provider_factory_list_providers (dialog->provider_factory, THUNARX_TYPE_PROPERTY_PAGE_PROVIDER);
   if (G_LIKELY (providers != NULL))
     {
-      /* determine the (one-element) file list */
-      files.data = dialog->file; files.next = files.prev = NULL;
-
       /* load the pages offered by the menu providers */
       for (lp = providers; lp != NULL; lp = lp->next)
         {
-          tmp = thunarx_property_page_provider_get_pages (lp->data, &files);
+          tmp = thunarx_property_page_provider_get_pages (lp->data, dialog->files);
           pages = g_list_concat (pages, tmp);
           g_object_unref (G_OBJECT (lp->data));
         }
@@ -814,7 +814,7 @@ thunar_properties_dialog_update_providers (ThunarPropertiesDialog *dialog)
 
 
 static void
-thunar_properties_dialog_update (ThunarPropertiesDialog *dialog)
+thunar_properties_dialog_update_single (ThunarPropertiesDialog *dialog)
 {
   ThunarIconFactory *icon_factory;
   ThunarDateStyle    date_style;
@@ -831,9 +831,17 @@ thunar_properties_dialog_update (ThunarPropertiesDialog *dialog)
   gchar             *size_string;
   gchar             *str;
   gchar             *volume_name;
+  ThunarFile        *file;
 
   _thunar_return_if_fail (THUNAR_IS_PROPERTIES_DIALOG (dialog));
-  _thunar_return_if_fail (THUNAR_IS_FILE (dialog->file));
+  _thunar_return_if_fail (g_list_length (dialog->files) == 1);
+  _thunar_return_if_fail (THUNAR_IS_FILE (dialog->files->data));
+
+  /* whether the dialog shows a single file or a group of files */
+  file = THUNAR_FILE (dialog->files->data);
+
+  /* hide the permissions chooser for trashed files */
+  gtk_widget_set_visible (dialog->permissions_chooser, !thunar_file_is_trashed (file));
 
   /* cancel any pending thumbnail requests */
   if (dialog->thumbnail_request > 0)
@@ -842,12 +850,9 @@ thunar_properties_dialog_update (ThunarPropertiesDialog *dialog)
       dialog->thumbnail_request = 0;
     }
 
-  if (dialog->file != NULL)
-    {
-      /* queue a new thumbnail request */
-      thunar_thumbnailer_queue_file (dialog->thumbnailer, dialog->file, 
-                                     &dialog->thumbnail_request);
-    }
+  /* queue a new thumbnail request */
+  thunar_thumbnailer_queue_file (dialog->thumbnailer, file,
+                                 &dialog->thumbnail_request);
 
   icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (dialog)));
   icon_factory = thunar_icon_factory_get_for_icon_theme (icon_theme);
@@ -856,17 +861,18 @@ thunar_properties_dialog_update (ThunarPropertiesDialog *dialog)
   g_object_get (G_OBJECT (dialog->preferences), "misc-date-style", &date_style, NULL);
 
   /* update the properties dialog title */
-  str = g_strdup_printf (_("%s - Properties"), thunar_file_get_display_name (dialog->file));
+  str = g_strdup_printf (_("%s - Properties"), thunar_file_get_display_name (file));
   gtk_window_set_title (GTK_WINDOW (dialog), str);
   g_free (str);
 
   /* update the preview image */
-  thunar_image_set_file (THUNAR_IMAGE (dialog->icon_image), dialog->file);
+  thunar_image_set_file (THUNAR_IMAGE (dialog->icon_image), file);
 
   /* check if the icon may be changed (only for writable .desktop files) */
   g_object_ref (G_OBJECT (dialog->icon_image));
   gtk_container_remove (GTK_CONTAINER (gtk_widget_get_parent (dialog->icon_image)), dialog->icon_image);
-  if (thunar_file_is_writable (dialog->file) && thunar_file_is_desktop_file (dialog->file))
+  if (thunar_file_is_writable (file)
+      && thunar_file_is_desktop_file (file))
     {
       gtk_container_add (GTK_CONTAINER (dialog->icon_button), dialog->icon_image);
       gtk_widget_show (dialog->icon_button);
@@ -879,8 +885,8 @@ thunar_properties_dialog_update (ThunarPropertiesDialog *dialog)
   g_object_unref (G_OBJECT (dialog->icon_image));
 
   /* update the name (if it differs) */
-  gtk_editable_set_editable (GTK_EDITABLE (dialog->name_entry), thunar_file_is_renameable (dialog->file));
-  name = thunar_file_get_display_name (dialog->file);
+  gtk_editable_set_editable (GTK_EDITABLE (dialog->name_entry), thunar_file_is_renameable (file));
+  name = thunar_file_get_display_name (file);
   if (G_LIKELY (strcmp (name, gtk_entry_get_text (GTK_ENTRY (dialog->name_entry))) != 0))
     {
       gtk_entry_set_text (GTK_ENTRY (dialog->name_entry), name);
@@ -902,13 +908,13 @@ thunar_properties_dialog_update (ThunarPropertiesDialog *dialog)
     }
 
   /* update the content type */
-  content_type = thunar_file_get_content_type (dialog->file);
+  content_type = thunar_file_get_content_type (file);
   if (content_type != NULL)
     {
       if (G_UNLIKELY (g_content_type_equals (content_type, "inode/symlink")))
         str = g_strdup (_("broken link"));
-      else if (G_UNLIKELY (thunar_file_is_symlink (dialog->file)))
-        str = g_strdup_printf (_("link to %s"), thunar_file_get_symlink_target (dialog->file));
+      else if (G_UNLIKELY (thunar_file_is_symlink (file)))
+        str = g_strdup_printf (_("link to %s"), thunar_file_get_symlink_target (file));
       else
         str = g_content_type_get_description (content_type);
       gtk_widget_set_tooltip_text (dialog->kind_ebox, content_type);
@@ -922,11 +928,11 @@ thunar_properties_dialog_update (ThunarPropertiesDialog *dialog)
 
   /* update the application chooser (shown only for non-executable regular files!) */
   g_object_set (G_OBJECT (dialog->openwith_chooser),
-                "visible", (thunar_file_is_regular (dialog->file) && !thunar_file_is_executable (dialog->file)),
+                "visible", (thunar_file_is_regular (file) && !thunar_file_is_executable (file)),
                 NULL);
 
   /* update the link target */
-  path = thunar_file_is_symlink (dialog->file) ? thunar_file_get_symlink_target (dialog->file) : NULL;
+  path = thunar_file_is_symlink (file) ? thunar_file_get_symlink_target (file) : NULL;
   if (G_UNLIKELY (path != NULL))
     {
       display_name = g_filename_display_name (path);
@@ -940,7 +946,7 @@ thunar_properties_dialog_update (ThunarPropertiesDialog *dialog)
     }
 
   /* update the original path */
-  path = thunar_file_get_original_path (dialog->file);
+  path = thunar_file_get_original_path (file);
   if (G_UNLIKELY (path != NULL))
     {
       display_name = g_filename_display_name (path);
@@ -954,7 +960,7 @@ thunar_properties_dialog_update (ThunarPropertiesDialog *dialog)
     }
 
   /* update the deleted time */
-  date = thunar_file_get_deletion_date (dialog->file, date_style);
+  date = thunar_file_get_deletion_date (file, date_style);
   if (G_LIKELY (date != NULL))
     {
       gtk_label_set_text (GTK_LABEL (dialog->deleted_label), date);
@@ -967,7 +973,7 @@ thunar_properties_dialog_update (ThunarPropertiesDialog *dialog)
     }
 
   /* update the modified time */
-  date = thunar_file_get_date_string (dialog->file, THUNAR_FILE_DATE_MODIFIED, date_style);
+  date = thunar_file_get_date_string (file, THUNAR_FILE_DATE_MODIFIED, date_style);
   if (G_LIKELY (date != NULL))
     {
       gtk_label_set_text (GTK_LABEL (dialog->modified_label), date);
@@ -980,7 +986,7 @@ thunar_properties_dialog_update (ThunarPropertiesDialog *dialog)
     }
 
   /* update the accessed time */
-  date = thunar_file_get_date_string (dialog->file, THUNAR_FILE_DATE_ACCESSED, date_style);
+  date = thunar_file_get_date_string (file, THUNAR_FILE_DATE_ACCESSED, date_style);
   if (G_LIKELY (date != NULL))
     {
       gtk_label_set_text (GTK_LABEL (dialog->accessed_label), date);
@@ -993,8 +999,8 @@ thunar_properties_dialog_update (ThunarPropertiesDialog *dialog)
     }
 
   /* update the free space (only for folders) */
-  if (thunar_file_is_directory (dialog->file) 
-      && thunar_file_get_free_space (dialog->file, &size))
+  if (thunar_file_is_directory (file)
+      && thunar_file_get_free_space (file, &size))
     {
 #if GLIB_CHECK_VERSION (2, 30, 0)
       size_string = g_format_size (size);
@@ -1011,7 +1017,7 @@ thunar_properties_dialog_update (ThunarPropertiesDialog *dialog)
     }
 
   /* update the volume */
-  volume = thunar_file_get_volume (dialog->file);
+  volume = thunar_file_get_volume (file);
   if (G_LIKELY (volume != NULL))
     {
       gicon = g_volume_get_icon (volume);
@@ -1035,8 +1041,28 @@ thunar_properties_dialog_update (ThunarPropertiesDialog *dialog)
 
 
 
+static void
+thunar_properties_dialog_update (ThunarPropertiesDialog *dialog)
+{
+  _thunar_return_if_fail (THUNAR_IS_PROPERTIES_DIALOG (dialog));
+  _thunar_return_if_fail (dialog->files != NULL);
+
+  if (dialog->files->next == NULL)
+    {
+      /* update the properties for a dialog showing 1 file */
+      thunar_properties_dialog_update_single (dialog);
+    }
+  else
+    {
+
+    }
+}
+
+
+
 /**
  * thunar_properties_dialog_new:
+ * @parent: transient window or NULL;
  *
  * Allocates a new #ThunarPropertiesDialog instance,
  * that is not associated with any #ThunarFile.
@@ -1045,72 +1071,82 @@ thunar_properties_dialog_update (ThunarPropertiesDialog *dialog)
  *               instance.
  **/
 GtkWidget*
-thunar_properties_dialog_new (void)
+thunar_properties_dialog_new (GtkWindow *parent)
 {
-  return g_object_new (THUNAR_TYPE_PROPERTIES_DIALOG, NULL);
+  _thunar_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), NULL);
+  return g_object_new (THUNAR_TYPE_PROPERTIES_DIALOG,
+                       "transient-for", parent,
+                       "destroy-with-parent", parent != NULL,
+                       NULL);
 }
 
 
 
 /**
- * thunar_properties_dialog_get_file:
+ * thunar_properties_dialog_get_files:
  * @dialog : a #ThunarPropertiesDialog.
  *
  * Returns the #ThunarFile currently being displayed
  * by @dialog or %NULL if @dialog doesn't display
  * any file right now.
  *
- * Return value: the #ThunarFile displayed by @dialog
+ * Return value: list of #ThunarFile's displayed by @dialog
  *               or %NULL.
  **/
-ThunarFile*
-thunar_properties_dialog_get_file (ThunarPropertiesDialog *dialog)
+GList*
+thunar_properties_dialog_get_files (ThunarPropertiesDialog *dialog)
 {
   _thunar_return_val_if_fail (THUNAR_IS_PROPERTIES_DIALOG (dialog), NULL);
-  return dialog->file;
+  return dialog->files;
 }
 
 
 
 /**
- * thunar_properties_dialog_set_file:
+ * thunar_properties_dialog_set_files:
  * @dialog : a #ThunarPropertiesDialog.
- * @file   : a #ThunarFile or %NULL.
+ * @files  : a GList of #ThunarFile's or %NULL.
  *
  * Sets the #ThunarFile that is displayed by @dialog
- * to @file.
+ * to @files.
  **/
 void
-thunar_properties_dialog_set_file (ThunarPropertiesDialog *dialog,
-                                   ThunarFile             *file)
+thunar_properties_dialog_set_files (ThunarPropertiesDialog *dialog,
+                                    GList                  *files)
 {
+  GList      *lp;
+  ThunarFile *file;
+
   _thunar_return_if_fail (THUNAR_IS_PROPERTIES_DIALOG (dialog));
-  _thunar_return_if_fail (file == NULL || THUNAR_IS_FILE (file));
 
-  /* check if we already display that file */
-  if (G_UNLIKELY (dialog->file == file))
+  /* check if the same lists are used (or null) */
+  if (G_UNLIKELY (dialog->files == files))
     return;
 
-  /* disconnect from any previously set file */
-  if (dialog->file != NULL)
+  /* disconnect from any previously set files */
+  for (lp = dialog->files; lp != NULL; lp = lp->next)
     {
+      file = THUNAR_FILE (lp->data);
+
       /* unregister our file watch */
-      thunar_file_unwatch (dialog->file);
+      thunar_file_unwatch (file);
 
       /* unregister handlers */
-      g_signal_handlers_disconnect_by_func (G_OBJECT (dialog->file), thunar_properties_dialog_update, dialog);
-      g_signal_handlers_disconnect_by_func (G_OBJECT (dialog->file), gtk_widget_destroy, dialog);
+      g_signal_handlers_disconnect_by_func (G_OBJECT (file), thunar_properties_dialog_update, dialog);
+      g_signal_handlers_disconnect_by_func (G_OBJECT (file), gtk_widget_destroy, dialog);
 
-      g_object_unref (G_OBJECT (dialog->file));
+      g_object_unref (G_OBJECT (file));
     }
+  g_list_free (dialog->files);
 
-  /* activate the new file */
-  dialog->file = file;
+  /* activate the new list */
+  dialog->files = g_list_copy (files);
 
-  /* connect to the new file */
-  if (file != NULL)
+  /* connect to the new files */
+  for (lp = dialog->files; lp != NULL; lp = lp->next)
     {
-      g_object_ref (G_OBJECT (file));
+      _thunar_assert (THUNAR_IS_FILE (lp->data));
+      file = g_object_ref (G_OBJECT (lp->data));
 
       /* watch the file for changes */
       thunar_file_watch (file);
@@ -1118,22 +1154,54 @@ thunar_properties_dialog_set_file (ThunarPropertiesDialog *dialog,
       /* install signal handlers */
       g_signal_connect_swapped (G_OBJECT (file), "changed", G_CALLBACK (thunar_properties_dialog_update), dialog);
       g_signal_connect_swapped (G_OBJECT (file), "destroy", G_CALLBACK (gtk_widget_destroy), dialog);
+    }
 
+  /* update the dialog contents */
+  if (dialog->files != NULL)
+    {
       /* update the UI for the new file */
       thunar_properties_dialog_update (dialog);
 
       /* update the provider property pages */
       thunar_properties_dialog_update_providers (dialog);
-
-      /* hide the permissions chooser for trashed files */
-      if (thunar_file_is_trashed (file))
-        gtk_widget_hide (dialog->permissions_chooser);
-      else
-        gtk_widget_show (dialog->permissions_chooser);
     }
 
   /* tell everybody that we have a new file here */
-  g_object_notify (G_OBJECT (dialog), "file");
+  g_object_notify (G_OBJECT (dialog), "files");
+}
+
+
+
+/**
+ * thunar_properties_dialog_set_file:
+ * @dialog : a #ThunarPropertiesDialog.
+ * @file   : a #ThunarFile or %NULL.
+ *
+ * Sets the #ThunarFile that is displayed by @dialog
+ * to @file.
+ **/
+void
+thunar_properties_dialog_set_file (ThunarPropertiesDialog *dialog,
+                                   ThunarFile             *file)
+{
+  GList foo;
+
+  _thunar_return_if_fail (THUNAR_IS_PROPERTIES_DIALOG (dialog));
+  _thunar_return_if_fail (file == NULL || THUNAR_IS_FILE (file));
+
+  if (file == NULL)
+    {
+      thunar_properties_dialog_set_files (dialog, NULL);
+    }
+  else
+    {
+      /* create a fake list */
+      foo.next = NULL;
+      foo.prev = NULL;
+      foo.data = file;
+
+      thunar_properties_dialog_set_files (dialog, &foo);
+    }
 }
 
 
diff --git a/thunar/thunar-properties-dialog.h b/thunar/thunar-properties-dialog.h
index 616023b..3e8951f 100644
--- a/thunar/thunar-properties-dialog.h
+++ b/thunar/thunar-properties-dialog.h
@@ -36,11 +36,14 @@ typedef struct _ThunarPropertiesDialog      ThunarPropertiesDialog;
 
 GType       thunar_properties_dialog_get_type (void) G_GNUC_CONST;
 
-GtkWidget  *thunar_properties_dialog_new      (void);
+GtkWidget  *thunar_properties_dialog_new       (GtkWindow              *parent);
 
-ThunarFile *thunar_properties_dialog_get_file (ThunarPropertiesDialog *dialog);
-void        thunar_properties_dialog_set_file (ThunarPropertiesDialog *dialog,  
-                                               ThunarFile             *file);
+GList      *thunar_properties_dialog_get_files (ThunarPropertiesDialog *dialog);
+void        thunar_properties_dialog_set_files (ThunarPropertiesDialog *dialog,  
+                                                GList                  *files);
+
+void        thunar_properties_dialog_set_file  (ThunarPropertiesDialog *dialog,  
+                                                ThunarFile             *file);
 
 G_END_DECLS;
 
diff --git a/thunar/thunar-renamer-dialog.c b/thunar/thunar-renamer-dialog.c
index 66ea52f..a19639d 100644
--- a/thunar/thunar-renamer-dialog.c
+++ b/thunar/thunar-renamer-dialog.c
@@ -1217,17 +1217,11 @@ thunar_renamer_dialog_action_properties (GtkAction           *action,
   _thunar_return_if_fail (GTK_IS_ACTION (action));
   _thunar_return_if_fail (THUNAR_IS_RENAMER_DIALOG (renamer_dialog));
 
-  /* verify that we have exactly one file selected */
-  if (G_LIKELY (g_list_length (renamer_dialog->selected_files) == 1))
-    {
-      /* popup the properties dialog */
-      dialog = thunar_properties_dialog_new ();
-      gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
-      gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
-      gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (renamer_dialog));
-      thunar_properties_dialog_set_file (THUNAR_PROPERTIES_DIALOG (dialog), renamer_dialog->selected_files->data);
-      gtk_widget_show (dialog);
-    }
+  /* popup the properties dialog */
+  dialog = thunar_properties_dialog_new (GTK_WINDOW (renamer_dialog));
+  gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+  thunar_properties_dialog_set_files (THUNAR_PROPERTIES_DIALOG (dialog), renamer_dialog->selected_files);
+  gtk_widget_show (dialog);
 }
 
 
@@ -1651,7 +1645,7 @@ thunar_renamer_dialog_selection_changed (GtkTreeSelection    *selection,
 
   /* the "Properties" action is only sensitive if we have exactly one selected file */
   action = gtk_action_group_get_action (renamer_dialog->action_group, "properties");
-  gtk_action_set_sensitive (action, (n_selected_files == 1));
+  gtk_action_set_sensitive (action, n_selected_files > 0);
 
   /* notify listeners */
   g_object_notify (G_OBJECT (renamer_dialog), "selected-files");
diff --git a/thunar/thunar-size-label.c b/thunar/thunar-size-label.c
index c83758e..3e63625 100644
--- a/thunar/thunar-size-label.c
+++ b/thunar/thunar-size-label.c
@@ -41,7 +41,7 @@
 enum
 {
   PROP_0,
-  PROP_FILE,
+  PROP_FILES,
 };
 
 
@@ -87,13 +87,13 @@ struct _ThunarSizeLabel
 
   ThunarDeepCountJob *job;
 
-  ThunarFile         *file;
+  GList              *files;
 
   GtkWidget          *label;
   GtkWidget          *throbber;
 
   /* the throbber animation is started after a timeout */
-  gint                animate_timer_id;
+  guint               animate_timer_id;
 };
 
 
@@ -119,10 +119,10 @@ thunar_size_label_class_init (ThunarSizeLabelClass *klass)
    * by this #ThunarSizeLabel.
    **/
   g_object_class_install_property (gobject_class,
-                                   PROP_FILE,
-                                   g_param_spec_object ("file", "file", "file",
-                                                        THUNAR_TYPE_FILE,
-                                                        EXO_PARAM_READWRITE));
+                                   PROP_FILES,
+                                   g_param_spec_boxed ("files", "files", "files",
+                                                       THUNARX_TYPE_FILE_INFO_LIST,
+                                                       EXO_PARAM_READWRITE));
 }
 
 
@@ -132,8 +132,6 @@ thunar_size_label_init (ThunarSizeLabel *size_label)
 {
   GtkWidget *ebox;
 
-  size_label->animate_timer_id = -1;
-
   gtk_widget_push_composite_child ();
 
   /* configure the box */
@@ -180,10 +178,10 @@ thunar_size_label_finalize (GObject *object)
     }
 
   /* reset the file property */
-  thunar_size_label_set_file (size_label, NULL);
+  thunar_size_label_set_files (size_label, NULL);
 
   /* be sure to cancel any pending animate timer */
-  if (G_UNLIKELY (size_label->animate_timer_id >= 0))
+  if (G_UNLIKELY (size_label->animate_timer_id != 0))
     g_source_remove (size_label->animate_timer_id);
 
   (*G_OBJECT_CLASS (thunar_size_label_parent_class)->finalize) (object);
@@ -201,8 +199,8 @@ thunar_size_label_get_property (GObject    *object,
 
   switch (prop_id)
     {
-    case PROP_FILE:
-      g_value_set_object (value, thunar_size_label_get_file (size_label));
+    case PROP_FILES:
+      g_value_set_boxed (value, thunar_size_label_get_files (size_label));
       break;
 
     default:
@@ -223,8 +221,8 @@ thunar_size_label_set_property (GObject      *object,
 
   switch (prop_id)
     {
-    case PROP_FILE:
-      thunar_size_label_set_file (size_label, g_value_get_object (value));
+    case PROP_FILES:
+      thunar_size_label_set_files (size_label, g_value_get_boxed (value));
       break;
 
     default:
@@ -247,7 +245,7 @@ thunar_size_label_button_press_event (GtkWidget       *ebox,
   if (G_LIKELY (event->button == 1))
     {
       /* be sure to cancel the animate timer */
-      if (G_UNLIKELY (size_label->animate_timer_id >= 0))
+      if (G_UNLIKELY (size_label->animate_timer_id != 0))
         g_source_remove (size_label->animate_timer_id);
 
       /* cancel the pending job (if any) */
@@ -275,67 +273,19 @@ thunar_size_label_button_press_event (GtkWidget       *ebox,
 
 
 
-static gchar*
-tsl_format_size_string (guint64 size)
-{
-  GString *result;
-  gchar   *grouping;
-  gchar   *thousep;
-  gint     ndigits = 0;
-
-#ifdef HAVE_LOCALECONV
-  grouping = localeconv ()->grouping;
-  thousep = localeconv ()->thousands_sep;
-#else
-  grouping = "\3\0";
-  thousep = ",";
-#endif
-
-  result = g_string_sized_new (32);
-  do
-    {
-      /* prepend the next digit to the string */
-      g_string_prepend_c (result, '0' + (size % 10));
-      ++ndigits;
-      
-      /* check if we should add the thousands separator */
-      if (ndigits == *grouping && *grouping != CHAR_MAX && size > 9)
-        {
-          g_string_prepend (result, thousep);
-          ndigits = 0;
-
-          /* if *(grouping+1) == '\0' then we have to use the
-           * *grouping character (last grouping rule) for all
-           * following cases.
-           */
-          if (*(grouping + 1) != '\0')
-            ++grouping;
-        }
-
-      size /= 10;
-    }
-  while (size > 0);
-
-  return g_string_free (result, FALSE);
-}
-
-
-
 static void
 thunar_size_label_file_changed (ThunarFile      *file,
                                 ThunarSizeLabel *size_label)
 {
   guint64 size;
-  gchar  *size_humanized;
   gchar  *size_string;
-  gchar  *text;
 
   _thunar_return_if_fail (THUNAR_IS_SIZE_LABEL (size_label));
-  _thunar_return_if_fail (size_label->file == file);
+  _thunar_return_if_fail (g_list_find (size_label->files, file) != NULL);
   _thunar_return_if_fail (THUNAR_IS_FILE (file));
 
   /* be sure to cancel the animate timer */
-  if (G_UNLIKELY (size_label->animate_timer_id >= 0))
+  if (G_UNLIKELY (size_label->animate_timer_id != 0))
     g_source_remove (size_label->animate_timer_id);
 
   /* cancel the pending job (if any) */
@@ -371,30 +321,9 @@ thunar_size_label_file_changed (ThunarFile      *file,
       /* determine the size of the file */
       size = thunar_file_get_size (file);
 
-      /* determine the size in bytes */
-      text = tsl_format_size_string (size);
-      size_string = g_strdup_printf (_("%s Bytes"), text);
-      g_free (text);
-
-      /* check if the file is larger that 1kB */
-      if (G_LIKELY (size > 1024ul))
-        {
-          /* prepend the humanized size */
-#if GLIB_CHECK_VERSION (2, 30, 0)
-          size_humanized = g_format_size (size);
-#else
-          size_humanized = g_format_size_for_display (size);
-#endif
-          text = g_strdup_printf ("%s (%s)", size_humanized, size_string);
-          g_free (size_humanized);
-          g_free (size_string);
-          size_string = text;
-        }
-
       /* setup the new label */
+      size_string = g_format_size_full (size, G_FORMAT_SIZE_LONG_FORMAT);
       gtk_label_set_text (GTK_LABEL (size_label->label), size_string);
-
-      /* cleanup */
       g_free (size_string);
     }
 }
@@ -425,7 +354,7 @@ thunar_size_label_finished (ExoJob          *job,
   _thunar_return_if_fail (size_label->job == THUNAR_DEEP_COUNT_JOB (job));
 
   /* be sure to cancel the animate timer */
-  if (G_UNLIKELY (size_label->animate_timer_id >= 0))
+  if (G_UNLIKELY (size_label->animate_timer_id != 0))
     g_source_remove (size_label->animate_timer_id);
 
   /* stop and hide the throbber */
@@ -457,7 +386,7 @@ thunar_size_label_status_update (ThunarDeepCountJob *job,
   _thunar_return_if_fail (size_label->job == job);
 
   /* check if the animate timer is already running */
-  if (G_UNLIKELY (size_label->animate_timer_id < 0))
+  if (G_UNLIKELY (size_label->animate_timer_id == 0))
     {
       /* schedule the animate timer to animate and display the throbber after 1s */
       size_label->animate_timer_id = g_timeout_add_full (G_PRIORITY_LOW, 1000, thunar_size_label_animate_timer,
@@ -468,11 +397,7 @@ thunar_size_label_status_update (ThunarDeepCountJob *job,
   n = file_count + directory_count + unreadable_directory_count;
 
   /* update the label */
-#if GLIB_CHECK_VERSION (2, 30, 0)
   size_string = g_format_size (total_size);
-#else
-  size_string = g_format_size_for_display (total_size);
-#endif
   text = g_strdup_printf (ngettext ("%u item, totalling %s", "%u items, totalling %s", n), n, size_string);
   gtk_label_set_text (GTK_LABEL (size_label->label), text);
   g_free (size_string);
@@ -502,7 +427,7 @@ thunar_size_label_animate_timer (gpointer user_data)
 static void
 thunar_size_label_animate_timer_destroy (gpointer user_data)
 {
-  THUNAR_SIZE_LABEL (user_data)->animate_timer_id = -1;
+  THUNAR_SIZE_LABEL (user_data)->animate_timer_id = 0;
 }
 
 
@@ -523,60 +448,68 @@ thunar_size_label_new (void)
 
 
 /**
- * thunar_size_label_get_file:
+ * thunar_size_label_get_files:
  * @size_label : a #ThunarSizeLabel.
  *
- * Returns the #ThunarFile for the @size_label.
+ * Returns the list of #ThunarFile's for the @size_label.
  *
  * Return value: the file for @size_label.
  **/
-ThunarFile*
-thunar_size_label_get_file (ThunarSizeLabel *size_label)
+GList*
+thunar_size_label_get_files (ThunarSizeLabel *size_label)
 {
   _thunar_return_val_if_fail (THUNAR_IS_SIZE_LABEL (size_label), NULL);
-  return size_label->file;
+  return size_label->files;
 }
 
 
 
 /**
- * thunar_size_label_set_file:
+ * thunar_size_label_set_files:
  * @size_label : a #ThunarSizeLabel.
- * @file       : a #ThunarFile or %NULL.
+ * @files      : a list of #ThunarFile's or %NULL.
  *
  * Sets @file as the #ThunarFile displayed by the @size_label.
  **/
 void
-thunar_size_label_set_file (ThunarSizeLabel *size_label,
-                            ThunarFile      *file)
+thunar_size_label_set_files (ThunarSizeLabel *size_label,
+                             GList           *files)
 {
+  GList      *lp;
+  ThunarFile *file;
+
   _thunar_return_if_fail (THUNAR_IS_SIZE_LABEL (size_label));
-  _thunar_return_if_fail (file == NULL || THUNAR_IS_FILE (file));
+  _thunar_return_if_fail (files == NULL || THUNAR_IS_FILE (files->data));
 
   /* check if we already display that file */
-  if (G_UNLIKELY (size_label->file == file))
+  if (G_UNLIKELY (size_label->files == files))
     return;
 
-  /* disconnect from the previous file */
-  if (G_UNLIKELY (size_label->file != NULL))
+  /* disconnect from the previous files */
+  for (lp = size_label->files; lp != NULL; lp = lp->next)
     {
-      g_signal_handlers_disconnect_by_func (G_OBJECT (size_label->file), thunar_size_label_file_changed, size_label);
-      g_object_unref (G_OBJECT (size_label->file));
+      file = THUNAR_FILE (lp->data);
+
+      g_signal_handlers_disconnect_by_func (G_OBJECT (file), thunar_size_label_file_changed, size_label);
+      g_object_unref (G_OBJECT (file));
     }
+  g_list_free (size_label->files);
 
   /* activate the new file */
-  size_label->file = file;
+  size_label->files = g_list_copy (files);
 
   /* connect to the new file */
-  if (G_LIKELY (file != NULL))
+  for (lp = files; lp != NULL; lp = lp->next)
     {
-      g_object_ref (G_OBJECT (file));
+      _thunar_assert (THUNAR_IS_FILE (lp->data));
+      file = g_object_ref (G_OBJECT (lp->data));
+
       thunar_size_label_file_changed (file, size_label);
       g_signal_connect (G_OBJECT (file), "changed", G_CALLBACK (thunar_size_label_file_changed), size_label);
     }
 
   /* notify listeners */
-  g_object_notify (G_OBJECT (size_label), "file");
+  g_object_notify (G_OBJECT (size_label), "files");
 }
 
 
diff --git a/thunar/thunar-size-label.h b/thunar/thunar-size-label.h
index d334aa7..8fa4774 100644
--- a/thunar/thunar-size-label.h
+++ b/thunar/thunar-size-label.h
@@ -38,9 +38,9 @@ GType       thunar_size_label_get_type  (void) G_GNUC_CONST;
 
 GtkWidget  *thunar_size_label_new       (void) G_GNUC_MALLOC;
 
-ThunarFile *thunar_size_label_get_file  (ThunarSizeLabel *size_label);
-void        thunar_size_label_set_file  (ThunarSizeLabel *size_label,
-                                         ThunarFile      *file);
+GList      *thunar_size_label_get_files (ThunarSizeLabel *size_label);
+void        thunar_size_label_set_files (ThunarSizeLabel *size_label,
+                                         GList           *files);
 
 G_END_DECLS;
 
diff --git a/thunar/thunar-standard-view.c b/thunar/thunar-standard-view.c
index 1ac61ac..56e8eab 100644
--- a/thunar/thunar-standard-view.c
+++ b/thunar/thunar-standard-view.c
@@ -3,18 +3,18 @@
  * Copyright (c) 2005-2006 Benedikt Meurer <benny at xfce.org>
  * Copyright (c) 2009-2011 Jannis Pohlmann <jannis at xfce.org>
  *
- * This program is free software; you can redistribute it and/or 
+ * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of 
+ * published by the Free Software Foundation; either version 2 of
  * the License, or (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public 
- * License along with this program; if not, write to the Free 
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the Free
  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301, USA.
  */
@@ -316,7 +316,7 @@ struct _ThunarStandardViewPrivate
   guint                   drop_occurred : 1;   /* whether the data was dropped */
   GList                  *drop_file_list;      /* the list of URIs that are contained in the drop data */
 
-  /* the "new-files" closure, which is used to select files whenever 
+  /* the "new-files" closure, which is used to select files whenever
    * new files are created by a ThunarJob associated with this view
    */
   GClosure               *new_files_closure;
@@ -345,7 +345,7 @@ struct _ThunarStandardViewPrivate
   guint                   thumbnail_source_id;
   gboolean                thumbnailing_scheduled;
 
-  /* Tree path for restoring the selection after selecting and 
+  /* Tree path for restoring the selection after selecting and
    * deleting an item */
   GtkTreePath            *selection_before_delete;
 };
@@ -621,7 +621,7 @@ thunar_standard_view_init (ThunarStandardView *standard_view)
   g_signal_connect_swapped (G_OBJECT (standard_view->model), "notify::num-files", G_CALLBACK (thunar_standard_view_update_statusbar_text), standard_view);
 
   /* connect to size allocation signals for generating thumbnail requests */
-  g_signal_connect_after (G_OBJECT (standard_view), "size-allocate", 
+  g_signal_connect_after (G_OBJECT (standard_view), "size-allocate",
                           G_CALLBACK (thunar_standard_view_size_allocate), NULL);
 }
 
@@ -793,7 +793,7 @@ thunar_standard_view_finalize (GObject *object)
   /* disconnect from the list model */
   g_signal_handlers_disconnect_matched (G_OBJECT (standard_view->model), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, standard_view);
   g_object_unref (G_OBJECT (standard_view->model));
-  
+
   /* free the statusbar text (if any) */
   g_free (standard_view->statusbar_text);
 
@@ -864,7 +864,7 @@ thunar_standard_view_set_property (GObject      *object,
       thunar_standard_view_set_loading (standard_view, g_value_get_boolean (value));
       break;
       break;
-      
+
     case PROP_SELECTED_FILES:
       thunar_component_set_selected_files (THUNAR_COMPONENT (object), g_value_get_boxed (value));
       break;
@@ -1552,7 +1552,7 @@ thunar_standard_view_delete_selected_files (ThunarStandardView *standard_view)
   permanently = (gtk_get_current_event_state (&state) && (state & GDK_SHIFT_MASK) != 0);
 
   /* check if the user defined a custom accelerator and is not holding the
-   * shift button. if he or she has, we don't response to the predefined key 
+   * shift button. if he or she has, we don't response to the predefined key
    * bindings (bug #4173) */
   accel_path = gtk_action_get_accel_path (action);
   if (accel_path != NULL && gtk_accel_map_lookup_entry (accel_path, &key)
@@ -1834,9 +1834,9 @@ thunar_standard_view_action_create_empty_file (GtkAction          *action,
   _thunar_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view));
 
   /* ask the user to enter a name for the new empty file */
-  name = thunar_show_create_dialog (GTK_WIDGET (standard_view), 
-                                    "text/plain", 
-                                    _("New Empty File"), 
+  name = thunar_show_create_dialog (GTK_WIDGET (standard_view),
+                                    "text/plain",
+                                    _("New Empty File"),
                                     _("New Empty File..."));
   if (G_LIKELY (name != NULL))
     {
@@ -1878,9 +1878,9 @@ thunar_standard_view_action_create_folder (GtkAction          *action,
   _thunar_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view));
 
   /* ask the user to enter a name for the new folder */
-  name = thunar_show_create_dialog (GTK_WIDGET (standard_view), 
-                                    "inode/directory", 
-                                    _("New Folder"), 
+  name = thunar_show_create_dialog (GTK_WIDGET (standard_view),
+                                    "inode/directory",
+                                    _("New Folder"),
                                     _("Create New Folder"));
   if (G_LIKELY (name != NULL))
     {
@@ -1926,13 +1926,13 @@ thunar_standard_view_action_create_template (GtkAction           *action,
   _thunar_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view));
 
   /* generate a title for the create dialog */
-  title = g_strdup_printf (_("Create Document from template \"%s\""), 
+  title = g_strdup_printf (_("Create Document from template \"%s\""),
                            thunar_file_get_display_name (file));
 
   /* ask the user to enter a name for the new document */
-  name = thunar_show_create_dialog (GTK_WIDGET (standard_view), 
-                                    thunar_file_get_content_type (file), 
-                                    thunar_file_get_display_name (file), 
+  name = thunar_show_create_dialog (GTK_WIDGET (standard_view),
+                                    thunar_file_get_content_type (file),
+                                    thunar_file_get_display_name (file),
                                     title);
   if (G_LIKELY (name != NULL))
     {
@@ -1974,40 +1974,36 @@ static void
 thunar_standard_view_action_properties (GtkAction          *action,
                                         ThunarStandardView *standard_view)
 {
-  ThunarFile *file = NULL;
+  ThunarFile *directory;
   GtkWidget  *toplevel;
   GtkWidget  *dialog;
 
   _thunar_return_if_fail (GTK_IS_ACTION (action));
   _thunar_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view));
 
-  /* check if no files are currently selected */
-  if (standard_view->priv->selected_files == NULL)
-    {
-      /* if we don't have any files selected, we just popup
-       * the properties dialog for the current folder.
-       */
-      file = thunar_navigator_get_current_directory (THUNAR_NAVIGATOR (standard_view));
-    }
-  else if (g_list_length (standard_view->priv->selected_files) == 1)
+  /* popup the files dialog */
+  toplevel = gtk_widget_get_toplevel (GTK_WIDGET (standard_view));
+  if (G_LIKELY (toplevel != NULL))
     {
-      /* popup the properties dialog for the one and only selected file */
-      file = THUNAR_FILE (standard_view->priv->selected_files->data);
-    }
+      dialog = thunar_properties_dialog_new (GTK_WINDOW (toplevel));
 
-  /* popup the properties dialog if we have exactly one file */
-  if (G_LIKELY (file != NULL))
-    {
-      toplevel = gtk_widget_get_toplevel (GTK_WIDGET (standard_view));
-      if (G_LIKELY (toplevel != NULL))
+      /* check if no files are currently selected */
+      if (standard_view->priv->selected_files == NULL)
+        {
+          /* if we don't have any files selected, we just popup
+           * the properties dialog for the current folder.
+           */
+          directory = thunar_navigator_get_current_directory (THUNAR_NAVIGATOR (standard_view));
+          thunar_properties_dialog_set_file (THUNAR_PROPERTIES_DIALOG (dialog), directory);
+        }
+      else
         {
-          dialog = g_object_new (THUNAR_TYPE_PROPERTIES_DIALOG,
-                                 "destroy-with-parent", TRUE,
-                                 "file", file,
-                                 NULL);
-          gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (toplevel));
-          gtk_widget_show (dialog);
+          /* popup the properties dialog for all file(s) */
+          thunar_properties_dialog_set_files (THUNAR_PROPERTIES_DIALOG (dialog),
+                                              standard_view->priv->selected_files);
         }
+
+      gtk_widget_show (dialog);
     }
 }
 
@@ -2258,7 +2254,7 @@ thunar_standard_view_rename_error (ExoJob             *job,
   file = g_value_get_object (g_value_array_get_nth (param_values, 0));
 
   /* display an error message */
-  thunar_dialogs_show_error (GTK_WIDGET (standard_view), error, 
+  thunar_dialogs_show_error (GTK_WIDGET (standard_view), error,
                              _("Failed to rename \"%s\""),
                              thunar_file_get_display_name (file));
 }
@@ -2606,7 +2602,7 @@ thunar_standard_view_drag_drop (GtkWidget          *view,
               if (G_LIKELY (*prop_text != '\0' && strchr ((const gchar *) prop_text, G_DIR_SEPARATOR) == NULL))
                 {
                   /* allocate the relative path for the target */
-                  path = g_file_resolve_relative_path (thunar_file_get_file (file), 
+                  path = g_file_resolve_relative_path (thunar_file_get_file (file),
                                                        (const gchar *)prop_text);
 
                   /* determine the new URI */
@@ -2917,9 +2913,9 @@ thunar_standard_view_drag_motion (GtkWidget          *view,
           file = thunar_standard_view_get_drop_file (standard_view, x, y, &path);
 
           /* check if we can save here */
-          if (G_LIKELY (file != NULL 
-                        && thunar_file_is_local (file) 
-                        && thunar_file_is_directory (file) 
+          if (G_LIKELY (file != NULL
+                        && thunar_file_is_local (file)
+                        && thunar_file_is_directory (file)
                         && thunar_file_is_writable (file)))
             {
               action = context->suggested_action;
@@ -3086,7 +3082,7 @@ thunar_standard_view_row_deleted (ThunarListModel    *model,
   /* Create a copy the path (we're not allowed to modify it in this handler) */
   path_copy = gtk_tree_path_copy (path);
 
-  /* Remember the selected path so that it can be restored after the row has 
+  /* Remember the selected path so that it can be restored after the row has
    * been removed. If the first row is removed, select the first row after the
    * removal, if any other row is removed, select the row before that one */
   if (G_LIKELY (gtk_tree_path_prev (path_copy)))
@@ -3116,7 +3112,7 @@ thunar_standard_view_restore_selection (ThunarListModel    *model,
   _thunar_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view));
   _thunar_return_if_fail (standard_view->model == model);
 
-  /* Check if there was only one file selected before the row was deleted. The 
+  /* Check if there was only one file selected before the row was deleted. The
    * path is set by thunar_standard_view_row_deleted() if this is the case */
   if (G_LIKELY (standard_view->priv->selection_before_delete != NULL))
     {
@@ -3330,7 +3326,7 @@ static void
 thunar_standard_view_schedule_thumbnail_timeout (ThunarStandardView *standard_view)
 {
   _thunar_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view));
-  
+
   /* delay creating the idle until the view has finished loading.
    * this is done because we only can tell the visible range reliably after
    * all items have been added and we've perhaps scrolled to the file remember
@@ -3345,8 +3341,8 @@ thunar_standard_view_schedule_thumbnail_timeout (ThunarStandardView *standard_vi
   thunar_standard_view_cancel_thumbnailing (standard_view);
 
   /* schedule the timeout handler */
-  standard_view->priv->thumbnail_source_id = 
-    g_timeout_add (175, (GSourceFunc) thunar_standard_view_request_thumbnails, 
+  standard_view->priv->thumbnail_source_id =
+    g_timeout_add (175, (GSourceFunc) thunar_standard_view_request_thumbnails,
                    standard_view);
 }
 
@@ -3356,10 +3352,10 @@ static void
 thunar_standard_view_schedule_thumbnail_idle (ThunarStandardView *standard_view)
 {
   _thunar_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view));
-  
+
   /* delay creating the idle until the view has finished loading.
    * this is done because we only can tell the visible range reliably after
-   * all items have been added, layouting has finished and we've perhaps 
+   * all items have been added, layouting has finished and we've perhaps
    * scrolled to the file remembered the last time */
   if (thunar_view_get_loading (THUNAR_VIEW (standard_view)))
     {
@@ -3371,7 +3367,7 @@ thunar_standard_view_schedule_thumbnail_idle (ThunarStandardView *standard_view)
   thunar_standard_view_cancel_thumbnailing (standard_view);
 
   /* schedule the timeout or idle handler */
-  standard_view->priv->thumbnail_source_id = 
+  standard_view->priv->thumbnail_source_id =
     g_idle_add ((GSourceFunc) thunar_standard_view_request_thumbnails, standard_view);
 }
 
@@ -3422,7 +3418,7 @@ thunar_standard_view_request_thumbnails (ThunarStandardView *standard_view)
           if (gtk_tree_path_compare (path, end_path) != 0)
             {
               /* try to compute the next visible item */
-              valid_iter = 
+              valid_iter =
                 gtk_tree_model_iter_next (GTK_TREE_MODEL (standard_view->model), &iter);
             }
           else
@@ -3472,7 +3468,7 @@ thunar_standard_view_show_thumbnails_toggled (ThunarStandardView *standard_view,
   if (show_thumbnails)
     {
       /* get the vertical adjustment of the view */
-      vadjustment = 
+      vadjustment =
         gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (standard_view));
 
       /* fake a scroll event to generate thumbnail requests */
@@ -3689,7 +3685,8 @@ thunar_standard_view_selection_changed (ThunarStandardView *standard_view)
   gtk_action_set_sensitive (standard_view->priv->action_create_document, !trashed && writable);
 
   /* update the "Properties" action */
-  gtk_action_set_sensitive (standard_view->priv->action_properties, (n_selected_files == 1 || (n_selected_files == 0 && current_directory != NULL)));
+  gtk_action_set_sensitive (standard_view->priv->action_properties,
+                            current_directory != NULL || n_selected_files > 0);
 
   /* update the "Cut" action */
   g_object_set (G_OBJECT (standard_view->priv->action_cut),
diff --git a/thunar/thunar-tree-view.c b/thunar/thunar-tree-view.c
index bdbc367..5b01d35 100644
--- a/thunar/thunar-tree-view.c
+++ b/thunar/thunar-tree-view.c
@@ -2127,10 +2127,8 @@ thunar_tree_view_action_properties (ThunarTreeView *view)
       if (G_LIKELY (toplevel != NULL && GTK_WIDGET_TOPLEVEL (toplevel)))
         {
           /* popup the properties dialog */
-          dialog = thunar_properties_dialog_new ();
-          gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
+          dialog = thunar_properties_dialog_new (GTK_WINDOW (toplevel));
           thunar_properties_dialog_set_file (THUNAR_PROPERTIES_DIALOG (dialog), file);
-          gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (toplevel));
           gtk_widget_show (dialog);
         }
 


More information about the Xfce4-commits mailing list