Git Repositories

2006-01-10 Benedikt Meurer <benny@xfce.org>
authorBenedikt Meurer <benny@xfce.org>
Tue, 10 Jan 2006 15:44:35 +0000 (15:44 +0000)
committerBenedikt Meurer <benny@xfce.org>
Tue, 10 Jan 2006 15:44:35 +0000 (15:44 +0000)
* thunar/thunar-path-entry.c(thunar_path_entry_activate): If we have
  a pending completion, accept the completion first, without activating
  the entry. This makes it more consistent with the behaviour when
  completing from the popup window.
* thunar/thunar-path-entry.c(thunar_path_entry_parse): Properly
  transform all parts of the filename to the local encoding.
* thunar/thunar-text-renderer.c(thunar_text_renderer_set_widget):
  Calculate the approx. character dimensions based on the font metrics
  for the active widget font.
* thunar/thunar-window.c(thunar_window_action_go_up): Handle errors
  properly.
* thunar/thunar-standard-view-ui.xml, thunar/thunar-standard-view.c:
  Add support to view the properties of the current folder.
* thunar/thunar-file.{c,h}, thunar/thunar-location-buttons.c,
  thunar/thunar-shortcuts-model.c, thunar/thunar-window.c: Change
  special file naming (home and root folder) to be consistent with
  what GtkFileChooser does.
* thunar/thunar-properties-dialog.c(thunar_properties_dialog_update):
  Display only the name of the file in the dialog title.
* thunar/thunar-standard-view.c: Add support for the XDS protocol.
* README: Add notes about supported standards.

(Old svn revision: 19378)

12 files changed:
ChangeLog
README
thunar/thunar-file.c
thunar/thunar-file.h
thunar/thunar-location-buttons.c
thunar/thunar-path-entry.c
thunar/thunar-properties-dialog.c
thunar/thunar-shortcuts-model.c
thunar/thunar-standard-view-ui.xml
thunar/thunar-standard-view.c
thunar/thunar-text-renderer.c
thunar/thunar-window.c

index 382fa7f..e5c2e81 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,27 @@
+2006-01-10     Benedikt Meurer <benny@xfce.org>
+
+       * thunar/thunar-path-entry.c(thunar_path_entry_activate): If we have
+         a pending completion, accept the completion first, without activating
+         the entry. This makes it more consistent with the behaviour when
+         completing from the popup window.
+       * thunar/thunar-path-entry.c(thunar_path_entry_parse): Properly
+         transform all parts of the filename to the local encoding.
+       * thunar/thunar-text-renderer.c(thunar_text_renderer_set_widget):
+         Calculate the approx. character dimensions based on the font metrics
+         for the active widget font.
+       * thunar/thunar-window.c(thunar_window_action_go_up): Handle errors
+         properly.
+       * thunar/thunar-standard-view-ui.xml, thunar/thunar-standard-view.c:
+         Add support to view the properties of the current folder.
+       * thunar/thunar-file.{c,h}, thunar/thunar-location-buttons.c, 
+         thunar/thunar-shortcuts-model.c, thunar/thunar-window.c: Change
+         special file naming (home and root folder) to be consistent with
+         what GtkFileChooser does.
+       * thunar/thunar-properties-dialog.c(thunar_properties_dialog_update):
+         Display only the name of the file in the dialog title.
+       * thunar/thunar-standard-view.c: Add support for the XDS protocol.
+       * README: Add notes about supported standards.
+
 2006-01-09     Benedikt Meurer <benny@xfce.org>
 
        * thunar-vfs/thunar-vfs-util.{c,h}: Add thunar_vfs_expand_filename(),
diff --git a/README b/README
index f783d62..50c50a8 100644 (file)
--- a/README
+++ b/README
@@ -57,6 +57,30 @@ can be setup using the configure flag `--enable-debug' (check the output of
                exactly what you do.
 
 
+Standards compliance
+====================
+
+Thunar supports the following standards/specifications:
+
+  * XDG Base Directory Specification
+    http://freedesktop.org/wiki/Standards_2fbasedir_2dspec
+
+  * Shared MIME Database Specification
+    http://freedesktop.org/wiki/Standards_2fshared_2dmime_2dinfo_2dspec
+
+  * X Direct Save (XDS) Protocol for the X Window System
+    http://freedesktop.org/wiki/Standards_2fdirect_2dsave
+
+  * Icon Theme Specification
+    http://freedesktop.org/wiki/Standards_2ficon_2dtheme_2dspec
+
+  * Thumbnail Managing Standard
+    http://jens.triq.net/thumbnail-spec/index.html
+
+  * File URI Specification
+    http://freedesktop.org/wiki/Standards_2ffile_2duri_2dspec
+
+
 How to report bugs?
 ===================
 
index bef5364..d60b270 100644 (file)
@@ -247,20 +247,6 @@ thunar_file_class_init (ThunarFileClass *klass)
                                                         EXO_PARAM_READABLE));
 
   /**
-   * ThunarFile::special-name:
-   *
-   * The file's special name, see thunar_file_get_special_name()
-   * for details.
-   **/
-  g_object_class_install_property (gobject_class,
-                                   PROP_SPECIAL_NAME,
-                                   g_param_spec_string ("special-name",
-                                                        "Special Name",
-                                                        "Special Name",
-                                                        NULL,
-                                                        EXO_PARAM_READABLE));
-
-  /**
    * ThunarFile::changed:
    * @file : the #ThunarFile instance.
    *
@@ -388,10 +374,6 @@ thunar_file_get_property (GObject    *object,
       g_value_set_static_string (value, thunar_file_get_display_name (file));
       break;
 
-    case PROP_SPECIAL_NAME:
-      g_value_set_static_string (value, thunar_file_get_special_name (file));
-      break;
-
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -506,11 +488,8 @@ thunar_file_real_changed (ThunarFile *file)
    */
   thunar_file_set_thumb_state (file, THUNAR_FILE_THUMB_STATE_UNKNOWN);
 
-  /* notify about changes of the display-name and special-name properties */
-  g_object_freeze_notify (G_OBJECT (file));
+  /* notify about changes of the display-name property */
   g_object_notify (G_OBJECT (file), "display-name");
-  g_object_notify (G_OBJECT (file), "special-name");
-  g_object_thaw_notify (G_OBJECT (file));
 }
 
 
@@ -1042,7 +1021,7 @@ thunar_file_get_display_name (const ThunarFile *file)
 
   /* root directory is always displayed as 'Filesystem' */
   if (thunar_file_is_root (file))
-    return _("Filesystem");
+    return _("File System");
 
   return file->info->display_name;
 }
@@ -1050,30 +1029,6 @@ thunar_file_get_display_name (const ThunarFile *file)
 
 
 /**
- * thunar_file_get_special_name:
- * @file : a #ThunarFile instance.
- *
- * Returns the special name for the @file, e.g. "Filesystem" for the #ThunarFile
- * referring to "/" and so on. If there's no special name for this @file, the
- * value of the "display-name" property will be returned instead.
- *
- * Return value: the special name of @file.
- **/
-const gchar*
-thunar_file_get_special_name (const ThunarFile *file)
-{
-  g_return_val_if_fail (THUNAR_IS_FILE (file), NULL);
-
-  /* home dir has special name, root dir is handled in get_display_name() */
-  if (thunar_file_is_home (file))
-    return _("Home");
-
-  return thunar_file_get_display_name (file);
-}
-
-
-
-/**
  * thunar_file_get_date:
  * @file        : a #ThunarFile instance.
  * @date_type   : the kind of date you are interested in.
index 3a98851..eafcc7a 100644 (file)
@@ -137,7 +137,6 @@ GdkDragAction                    thunar_file_accepts_drop         (ThunarFile
                                                                    GdkDragAction           actions);
 
 const gchar                     *thunar_file_get_display_name     (const ThunarFile       *file);
-const gchar                     *thunar_file_get_special_name     (const ThunarFile       *file);
 
 static inline ThunarVfsInfo     *thunar_file_get_info             (const ThunarFile       *file);
 static inline ThunarVfsPath     *thunar_file_get_path             (const ThunarFile       *file);
index f48a4b6..a63316c 100644 (file)
@@ -890,7 +890,7 @@ thunar_location_buttons_make_button (ThunarLocationButtons *buttons,
     {
       /* only non-root nodes have a label */
       label = g_object_new (GTK_TYPE_LABEL, NULL);
-      exo_binding_new (G_OBJECT (file), "special-name", G_OBJECT (label), "label");
+      exo_binding_new (G_OBJECT (file), "display-name", G_OBJECT (label), "label");
       g_object_set_qdata (G_OBJECT (button), gtk_label_quark, label);
       gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
       gtk_widget_show (label);
index e8e2a4f..ab4b093 100644 (file)
@@ -730,11 +730,16 @@ thunar_path_entry_activate (GtkEntry *entry)
 {
   ThunarPathEntry *path_entry = THUNAR_PATH_ENTRY (entry);
 
-  /* place cursor at the end of the text if we have completion set */
   if (G_LIKELY (path_entry->has_completion))
-    gtk_editable_set_position (GTK_EDITABLE (path_entry), -1);
-
-  (*GTK_ENTRY_CLASS (thunar_path_entry_parent_class)->activate) (entry);
+    {
+      /* place cursor at the end of the text if we have completion set */
+      gtk_editable_set_position (GTK_EDITABLE (path_entry), -1);
+    }
+  else
+    {
+      /* emit the "activate" signal */
+      (*GTK_ENTRY_CLASS (thunar_path_entry_parent_class)->activate) (entry);
+    }
 }
 
 
@@ -1179,32 +1184,39 @@ thunar_path_entry_parse (ThunarPathEntry *path_entry,
   if (G_UNLIKELY (last_slash == NULL))
     {
       /* no slash character, it's relative to the home dir */
-      *folder_part = g_strdup (xfce_get_homedir ());
-      *file_part = filename;
-      return TRUE;
+      *file_part = g_filename_from_utf8 (filename, -1, NULL, NULL, error);
+      if (G_LIKELY (*file_part != NULL))
+        *folder_part = g_strdup (xfce_get_homedir ());
     }
-
-  if (G_LIKELY (last_slash != filename))
-    *folder_part = g_filename_from_utf8 (filename, last_slash - filename, NULL, NULL, error);
   else
-    *folder_part = g_strdup ("/");
-
-  if (G_LIKELY (*folder_part != NULL))
     {
-      /* if folder_part doesn't start with '/', it's relative to the home dir */
-      if (G_UNLIKELY (**folder_part != G_DIR_SEPARATOR))
+      if (G_LIKELY (last_slash != filename))
+        *folder_part = g_filename_from_utf8 (filename, last_slash - filename, NULL, NULL, error);
+      else
+        *folder_part = g_strdup ("/");
+
+      if (G_LIKELY (*folder_part != NULL))
         {
-          path = xfce_get_homefile (*folder_part, NULL);
-          g_free (*folder_part);
-          *folder_part = path;
-        }
+          /* if folder_part doesn't start with '/', it's relative to the home dir */
+          if (G_UNLIKELY (**folder_part != G_DIR_SEPARATOR))
+            {
+              path = xfce_get_homefile (*folder_part, NULL);
+              g_free (*folder_part);
+              *folder_part = path;
+            }
 
-      /* determine the file part */
-      *file_part = g_strdup (last_slash + 1);
-    }
-  else
-    {
-      g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, _("Invalid path"));
+          /* determine the file part */
+          *file_part = g_filename_from_utf8 (last_slash + 1, -1, NULL, NULL, error);
+          if (G_UNLIKELY (*file_part == NULL))
+            {
+              g_free (*folder_part);
+              *folder_part = NULL;
+            }
+        }
+      else
+        {
+          g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, _("Invalid path"));
+        }
     }
 
   /* release the filename */
index af9414e..734e5f7 100644 (file)
@@ -1,6 +1,6 @@
 /* $Id$ */
 /*-
- * Copyright (c) 2005 Benedikt Meurer <benny@xfce.org>
+ * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org>
  *
  * 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
@@ -603,9 +603,7 @@ thunar_properties_dialog_update (ThunarPropertiesDialog *dialog)
   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);
-      str = g_strdup_printf (_("%s Info"), name);
-      gtk_window_set_title (GTK_WINDOW (dialog), str);
-      g_free (str);
+      gtk_window_set_title (GTK_WINDOW (dialog), name);
 
       /* grab the input focus to the name entry */
       gtk_widget_grab_focus (dialog->name_entry);
index 359dad7..562ff84 100644 (file)
@@ -1,6 +1,6 @@
 /* $Id$ */
 /*-
- * Copyright (c) 2005 Benedikt Meurer <benny@xfce.org>
+ * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org>
  *
  * 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
@@ -493,7 +493,7 @@ thunar_shortcuts_model_get_value (GtkTreeModel *tree_model,
       else if (shortcut->name != NULL)
         g_value_set_static_string (value, shortcut->name);
       else if (shortcut->file != NULL)
-        g_value_set_static_string (value, thunar_file_get_special_name (shortcut->file));
+        g_value_set_static_string (value, thunar_file_get_display_name (shortcut->file));
       else
         g_value_set_static_string (value, "");
       break;
index 2184d7d..f7a2031 100644 (file)
@@ -3,7 +3,7 @@
   <!--
     $Id$
 
-    Copyright (c) 2005 Benedikt Meurer <benny@xfce.org>
+    Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org>
 
     Thunar standard view user interface description file. Do NOT
     simply edit this file if you don't know how the whole system
@@ -69,6 +69,8 @@
     <menuitem action="paste" name="paste" />
     <separator />
     <placeholder name="placeholder-custom-actions" />
+    <separator />
+    <menuitem action="properties" name="properties" />
   </popup>
 
 </ui>
index f6da3cc..e3a1a87 100644 (file)
@@ -70,6 +70,7 @@ enum
 enum
 {
   TEXT_URI_LIST,
+  XDND_DIRECT_SAVE0,
 };
 
 
@@ -114,6 +115,10 @@ static GdkDragAction thunar_standard_view_get_dest_actions          (ThunarStand
                                                                      gint                      y,
                                                                      guint                     time,
                                                                      ThunarFile              **file_return);
+static ThunarFile   *thunar_standard_view_get_drop_file             (ThunarStandardView       *standard_view,
+                                                                     gint                      x,
+                                                                     gint                      y,
+                                                                     GtkTreePath             **path_return);
 static GList        *thunar_standard_view_get_selected_files        (ThunarStandardView       *standard_view);
 static GList        *thunar_standard_view_get_selected_paths        (ThunarStandardView       *standard_view);
 static void          thunar_standard_view_merge_custom_actions      (ThunarStandardView       *standard_view,
@@ -256,7 +261,7 @@ static const GtkActionEntry action_entries[] =
   { "file-context-menu", NULL, N_ ("File Context Menu"), NULL, NULL, NULL, },
   { "folder-context-menu", NULL, N_ ("Folder Context Menu"), NULL, NULL, NULL, },
   { "create-folder", NULL, N_ ("Create _Folder..."), "<control><shift>N", N_ ("Create an empty folder within the current folder"), G_CALLBACK (thunar_standard_view_action_create_folder), },
-  { "properties", GTK_STOCK_PROPERTIES, N_ ("_Properties"), "<alt>Return", N_ ("View the properties of the selected file"), G_CALLBACK (thunar_standard_view_action_properties), },
+  { "properties", GTK_STOCK_PROPERTIES, N_ ("_Properties..."), "<alt>Return", N_ ("View the properties of the selected file"), G_CALLBACK (thunar_standard_view_action_properties), },
   { "copy", GTK_STOCK_COPY, N_ ("_Copy Files"), NULL, N_ ("Copy the selected files"), G_CALLBACK (thunar_standard_view_action_copy), },
   { "cut", GTK_STOCK_CUT, N_ ("Cu_t Files"), NULL, N_ ("Cut the selected files"), G_CALLBACK (thunar_standard_view_action_cut), },
   { "paste", GTK_STOCK_PASTE, N_ ("_Paste Files"), NULL, NULL, G_CALLBACK (thunar_standard_view_action_paste), },
@@ -279,6 +284,7 @@ static const GtkTargetEntry drag_targets[] =
 static const GtkTargetEntry drop_targets[] =
 {
   { "text/uri-list", 0, TEXT_URI_LIST, },
+  { "XdndDirectSave0", 0, XDND_DIRECT_SAVE0, },
 };
 
 
@@ -1022,24 +1028,10 @@ thunar_standard_view_get_dest_actions (ThunarStandardView *standard_view,
   GdkDragAction actions = 0;
   GdkDragAction action = 0;
   GtkTreePath  *path;
-  GtkTreeIter   iter;
   ThunarFile   *file;
 
-  /* determine the path for the given coordinates */
-  path = (*THUNAR_STANDARD_VIEW_GET_CLASS (standard_view)->get_path_at_pos) (standard_view, x, y);
-  if (G_LIKELY (path != NULL))
-    {
-      /* determine the file for the path */
-      gtk_tree_model_get_iter (GTK_TREE_MODEL (standard_view->model), &iter, path);
-      file = thunar_list_model_get_file (standard_view->model, &iter);
-    }
-  else
-    {
-      /* determine the current directory */
-      file = thunar_navigator_get_current_directory (THUNAR_NAVIGATOR (standard_view));
-      if (G_LIKELY (file != NULL))
-        g_object_ref (G_OBJECT (file));
-    }
+  /* determine the file and path for the given coordinates */
+  file = thunar_standard_view_get_drop_file (standard_view, x, y, &path);
 
   /* check if we can drop there */
   if (G_LIKELY (file != NULL))
@@ -1065,9 +1057,6 @@ thunar_standard_view_get_dest_actions (ThunarStandardView *standard_view,
           if (G_UNLIKELY (file_return != NULL))
             *file_return = g_object_ref (G_OBJECT (file));
         }
-
-      /* release the file reference */
-      g_object_unref (G_OBJECT (file));
     }
 
   /* reset path if we cannot drop */
@@ -1096,6 +1085,8 @@ thunar_standard_view_get_dest_actions (ThunarStandardView *standard_view,
   gdk_drag_status (context, action, time);
 
   /* clean up */
+  if (G_LIKELY (file != NULL))
+    g_object_unref (G_OBJECT (file));
   if (G_LIKELY (path != NULL))
     gtk_tree_path_free (path);
 
@@ -1104,6 +1095,43 @@ thunar_standard_view_get_dest_actions (ThunarStandardView *standard_view,
 
 
 
+static ThunarFile*
+thunar_standard_view_get_drop_file (ThunarStandardView *standard_view,
+                                    gint                x,
+                                    gint                y,
+                                    GtkTreePath       **path_return)
+{
+  GtkTreePath *path = NULL;
+  GtkTreeIter  iter;
+  ThunarFile  *file = NULL;
+
+  /* determine the path for the given coordinates */
+  path = (*THUNAR_STANDARD_VIEW_GET_CLASS (standard_view)->get_path_at_pos) (standard_view, x, y);
+  if (G_LIKELY (path != NULL))
+    {
+      /* determine the file for the path */
+      gtk_tree_model_get_iter (GTK_TREE_MODEL (standard_view->model), &iter, path);
+      file = thunar_list_model_get_file (standard_view->model, &iter);
+    }
+  else
+    {
+      /* determine the current directory */
+      file = thunar_navigator_get_current_directory (THUNAR_NAVIGATOR (standard_view));
+      if (G_LIKELY (file != NULL))
+        g_object_ref (G_OBJECT (file));
+    }
+
+  /* return the path (if any) */
+  if (G_LIKELY (path_return != NULL))
+    *path_return = path;
+  else if (G_LIKELY (path != NULL))
+    gtk_tree_path_free (path);
+
+  return file;
+}
+
+
+
 static GList*
 thunar_standard_view_get_selected_files (ThunarStandardView *standard_view)
 {
@@ -1405,14 +1433,27 @@ static void
 thunar_standard_view_action_properties (GtkAction          *action,
                                         ThunarStandardView *standard_view)
 {
-  GtkWidget *toplevel;
-  GtkWidget *dialog;
-  GList     *files;
+  ThunarFile *current_directory;
+  GtkWidget  *toplevel;
+  GtkWidget  *dialog;
+  GList      *files;
 
   g_return_if_fail (GTK_IS_ACTION (action));
   g_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view));
 
+  /* determine the currently selected files */
   files = thunar_standard_view_get_selected_files (standard_view);
+  if (G_UNLIKELY (files == NULL))
+    {
+      /* if we don't have any files selected, we just popup
+       * the properties dialog for the current folder.
+       */
+      current_directory = thunar_navigator_get_current_directory (THUNAR_NAVIGATOR (standard_view));
+      if (G_LIKELY (current_directory != NULL))
+        files = g_list_prepend (files, g_object_ref (G_OBJECT (current_directory)));
+    }
+
+  /* popup the properties dialog if we have exactly one file */
   if (G_LIKELY (g_list_length (files) == 1))
     {
       toplevel = gtk_widget_get_toplevel (GTK_WIDGET (standard_view));
@@ -1426,6 +1467,8 @@ thunar_standard_view_action_properties (GtkAction          *action,
           gtk_widget_show (dialog);
         }
     }
+
+  /* cleanup */
   thunar_file_list_free (files);
 }
 
@@ -1908,27 +1951,73 @@ thunar_standard_view_drag_drop (GtkWidget          *view,
                                 guint               time,
                                 ThunarStandardView *standard_view)
 {
-  GdkAtom target;
+  ThunarVfsPath *path;
+  ThunarFile    *file = NULL;
+  GdkAtom        target;
+  guchar        *prop_text;
+  gint           prop_len;
+  gchar         *uri = NULL;
 
   target = gtk_drag_dest_find_target (view, context, NULL);
-  if (G_LIKELY (target != GDK_NONE))
-    {
-      /* set state so the drag-data-received knows that
-       * this is really a drop this time.
-       */
-      standard_view->priv->drop_occurred = TRUE;
-
-      /* request the drag data from the source */
-      gtk_drag_get_data (view, context, target, time);
-  
-      /* we'll call gtk_drag_finish() later */
-      return TRUE;
-    }
-  else
+  if (G_UNLIKELY (target == GDK_NONE))
     {
       /* we cannot handle the drag data */
       return FALSE;
     }
+  else if (G_UNLIKELY (target == gdk_atom_intern ("XdndDirectSave0", FALSE)))
+    {
+      /* determine the file for the drop position */
+      file = thunar_standard_view_get_drop_file (standard_view, x, y, NULL);
+      if (G_LIKELY (file != NULL))
+        {
+          /* determine the file name from the DnD source window */
+          if (gdk_property_get (context->source_window, gdk_atom_intern ("XdndDirectSave0", FALSE),
+                                gdk_atom_intern ("text/plain", FALSE), 0, 1024, FALSE, NULL, NULL,
+                                &prop_len, &prop_text) && prop_text != NULL)
+            {
+              /* zero-terminate the string */
+              prop_text = g_realloc (prop_text, prop_len + 1);
+              prop_text[prop_len] = '\0';
+
+              /* allocate the relative path for the target */
+              path = thunar_vfs_path_relative (thunar_file_get_path (file), (const gchar *) prop_text);
+
+              /* determine the new URI */
+              uri = thunar_vfs_path_dup_uri (path);
+
+              /* setup the property */
+              gdk_property_change (GDK_DRAWABLE (context->source_window),
+                                   gdk_atom_intern ("XdndDirectSave0", FALSE),
+                                   gdk_atom_intern ("text/plain", FALSE), 8,
+                                   GDK_PROP_MODE_REPLACE, uri, strlen (uri));
+
+              /* cleanup */
+              thunar_vfs_path_unref (path);
+              g_free (prop_text);
+              g_free (uri);
+            }
+
+          /* release the file reference */
+          g_object_unref (G_OBJECT (file));
+        }
+
+      /* if uri == NULL, we didn't set the property */
+      if (G_UNLIKELY (uri == NULL))
+        return FALSE;
+    }
+
+  /* set state so the drag-data-received knows that
+   * this is really a drop this time.
+   */
+  standard_view->priv->drop_occurred = TRUE;
+
+  /* request the drag data from the source (initiates
+   * saving in case of XdndDirectSave).
+   */
+  gtk_drag_get_data (view, context, target, time);
+
+  /* we'll call gtk_drag_finish() later */
+  return TRUE;
 }
 
 
@@ -1965,30 +2054,53 @@ thunar_standard_view_drag_data_received (GtkWidget          *view,
       /* reset the state */
       standard_view->priv->drop_occurred = FALSE;
 
-      /* determine the drop position */
-      actions = thunar_standard_view_get_dest_actions (standard_view, context, x, y, time, &file);
-      if (G_LIKELY ((actions & (GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK)) != 0))
+      /* check if we're doing XdndDirectSave */
+      if (G_UNLIKELY (info == XDND_DIRECT_SAVE0))
         {
-          /* ask the user what to do with the drop data */
-          action = (context->action == GDK_ACTION_ASK) ? thunar_dnd_ask (GTK_WIDGET (standard_view), time, actions) : context->action;
+          /* we don't handle XdndDirectSave stage (3), result "F" yet */
+          if (G_UNLIKELY (selection_data->format == 8 && selection_data->length == 1 && selection_data->data[0] == 'F'))
+            {
+              /* indicate that we don't provide "F" fallback */
+              gdk_property_change (GDK_DRAWABLE (context->source_window),
+                                   gdk_atom_intern ("XdndDirectSave0", FALSE),
+                                   gdk_atom_intern ("text/plain", FALSE), 8,
+                                   GDK_PROP_MODE_REPLACE, "", 0);
+            }
+          else if (G_LIKELY (selection_data->format == 8 && selection_data->length == 1 && selection_data->data[0] == 'S'))
+            {
+              // FIXME: Reload the folder contents!
+            }
 
-          /* perform the requested action */
-          if (G_LIKELY (action != 0))
+          /* in either case, we succeed! */
+          succeed = TRUE;
+        }
+      else if (G_LIKELY (info == TEXT_URI_LIST))
+        {
+          /* determine the drop position */
+          actions = thunar_standard_view_get_dest_actions (standard_view, context, x, y, time, &file);
+          if (G_LIKELY ((actions & (GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK)) != 0))
             {
-              succeed = thunar_dnd_perform (GTK_WIDGET (standard_view), file, standard_view->priv->drop_path_list,
-                                            action, thunar_standard_view_new_files_closure (standard_view));
+              /* ask the user what to do with the drop data */
+              action = (context->action == GDK_ACTION_ASK) ? thunar_dnd_ask (GTK_WIDGET (standard_view), time, actions) : context->action;
+
+              /* perform the requested action */
+              if (G_LIKELY (action != 0))
+                {
+                  succeed = thunar_dnd_perform (GTK_WIDGET (standard_view), file, standard_view->priv->drop_path_list,
+                                                action, thunar_standard_view_new_files_closure (standard_view));
+                }
             }
+
+          /* release the file reference */
+          if (G_LIKELY (file != NULL))
+            g_object_unref (G_OBJECT (file));
         }
 
-      /* release the file reference */
-      if (G_LIKELY (file != NULL))
-        g_object_unref (G_OBJECT (file));
+      /* tell the peer that we handled the drop */
+      gtk_drag_finish (context, succeed, FALSE, time);
 
       /* disable the highlighting and release the drag data */
       thunar_standard_view_drag_leave (view, context, time, standard_view);
-
-      /* tell the peer that we handled the drop */
-      gtk_drag_finish (context, succeed, FALSE, time);
     }
 }
 
@@ -2032,26 +2144,59 @@ thunar_standard_view_drag_motion (GtkWidget          *view,
                                   guint               time,
                                   ThunarStandardView *standard_view)
 {
-  GdkAtom target;
+  GdkDragAction action = 0;
+  GtkTreePath  *path;
+  ThunarFile   *file = NULL;
+  GdkAtom       target;
 
   /* request the drop data on-demand (if we don't have it already) */
   if (G_UNLIKELY (!standard_view->priv->drop_data_ready))
     {
       /* check if we can handle that drag data (yet?) */
       target = gtk_drag_dest_find_target (view, context, NULL);
-      if (G_UNLIKELY (target == GDK_NONE))
+      if (G_UNLIKELY (target == gdk_atom_intern ("XdndDirectSave0", FALSE)))
         {
-          /* we cannot handle the drag data */
-          gdk_drag_status (context, 0, time);
+          /* determine the file for the given coordinates */
+          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_directory (file) && thunar_file_is_writable (file)))
+            action = context->suggested_action;
+
+          /* reset path if we cannot drop */
+          if (G_UNLIKELY (action == 0 && path != NULL))
+            {
+              gtk_tree_path_free (path);
+              path = NULL;
+            }
+
+          /* do the view highlighting */
+          if (standard_view->priv->drop_highlight != (path == NULL && action != 0))
+            {
+              standard_view->priv->drop_highlight = (path == NULL && action != 0);
+              gtk_widget_queue_draw (GTK_WIDGET (standard_view));
+            }
+
+          /* setup drop-file for the icon renderer to highlight the target */
+          g_object_set (G_OBJECT (standard_view->icon_renderer), "drop-file", (action != 0) ? file : NULL, NULL);
+
+          /* do the item highlighting */
+          (*THUNAR_STANDARD_VIEW_GET_CLASS (standard_view)->highlight_path) (standard_view, path);
+
+          /* cleanup */
+          if (G_LIKELY (file != NULL))
+            g_object_unref (G_OBJECT (file));
+          if (G_LIKELY (path != NULL))
+            gtk_tree_path_free (path);
         }
       else
         {
           /* request the drag data from the source */
           gtk_drag_get_data (view, context, target, time);
-
-          /* and deny the drop so far */
-          gdk_drag_status (context, 0, time);
         }
+
+      /* tell Gdk whether we can drop here */
+      gdk_drag_status (context, action, time);
     }
   else
     {
@@ -2452,7 +2597,7 @@ thunar_standard_view_selection_changed (ThunarStandardView *standard_view)
   gtk_action_set_sensitive (standard_view->priv->action_create_folder, writable);
 
   /* update the "Properties" action */
-  gtk_action_set_sensitive (standard_view->priv->action_properties, (n_selected_files == 1));
+  gtk_action_set_sensitive (standard_view->priv->action_properties, (n_selected_files == 1 || (n_selected_files == 0 && current_directory != NULL)));
 
   /* update the "Copy File(s)" action */
   g_object_set (G_OBJECT (standard_view->priv->action_copy),
index 42d3bc2..cf41b30 100644 (file)
@@ -1,6 +1,6 @@
 /* $Id$ */
 /*-
- * Copyright (c) 2005 Benedikt Meurer <benny@xfce.org>
+ * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org>
  *
  * 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
@@ -634,11 +634,10 @@ static void
 thunar_text_renderer_set_widget (ThunarTextRenderer *text_renderer,
                                  GtkWidget          *widget)
 {
-  // FIXME: The sample text should be translatable with a hint to translators!
-  static const gchar SAMPLE_TEXT[] = "The Quick Brown Fox Jumps Over the Lazy Dog";
-  PangoRectangle     extents;
-  gint               focus_padding;
-  gint               focus_line_width;
+  PangoFontMetrics *metrics;
+  PangoContext     *context;
+  gint              focus_padding;
+  gint              focus_line_width;
 
   if (G_LIKELY (widget == text_renderer->widget))
     return;
@@ -664,12 +663,15 @@ thunar_text_renderer_set_widget (ThunarTextRenderer *text_renderer,
       g_signal_connect_swapped (G_OBJECT (text_renderer->widget), "destroy", G_CALLBACK (thunar_text_renderer_invalidate), text_renderer);
       g_signal_connect_swapped (G_OBJECT (text_renderer->widget), "style-set", G_CALLBACK (thunar_text_renderer_invalidate), text_renderer);
 
+      /* allocate a new pango layout for this widget */
+      context = gtk_widget_get_pango_context (widget);
+      text_renderer->layout = pango_layout_new (context);
+
       /* calculate the average character dimensions */
-      text_renderer->layout = gtk_widget_create_pango_layout (widget, SAMPLE_TEXT);
-      pango_layout_get_pixel_extents (text_renderer->layout, NULL, &extents);
-      pango_layout_set_width (text_renderer->layout, -1);
-      text_renderer->char_width = extents.width / g_utf8_strlen (SAMPLE_TEXT, sizeof (SAMPLE_TEXT) - 1);
-      text_renderer->char_height = extents.height;
+      metrics = pango_context_get_metrics (context, widget->style->font_desc, pango_context_get_language (context));
+      text_renderer->char_width = PANGO_PIXELS (pango_font_metrics_get_approximate_char_width (metrics));
+      text_renderer->char_height = PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) + pango_font_metrics_get_descent (metrics));
+      pango_font_metrics_unref (metrics);
 
       /* determine the focus-padding and focus-line-width style properties from the widget */
       gtk_widget_style_get (widget, "focus-padding", &focus_padding, "focus-line-width", &focus_line_width, NULL);
index b0d13b0..a55fc89 100644 (file)
@@ -920,11 +920,19 @@ thunar_window_action_go_up (GtkAction    *action,
                             ThunarWindow *window)
 {
   ThunarFile *parent;
+  GError     *error = NULL;
 
-  // FIXME: error handling
-  parent = thunar_file_get_parent (window->current_directory, NULL);
-  thunar_window_set_current_directory (window, parent);
-  g_object_unref (G_OBJECT (parent));
+  parent = thunar_file_get_parent (window->current_directory, &error);
+  if (G_LIKELY (parent != NULL))
+    {
+      thunar_window_set_current_directory (window, parent);
+      g_object_unref (G_OBJECT (parent));
+    }
+  else
+    {
+      thunar_dialogs_show_error (GTK_WIDGET (window), error, _("Failed to open parent folder"));
+      g_error_free (error);
+    }
 }
 
 
@@ -1089,7 +1097,7 @@ thunar_window_current_directory_changed (ThunarFile   *current_directory,
 
   /* set window title and icon */
   icon = thunar_icon_factory_load_file_icon (window->icon_factory, current_directory, THUNAR_FILE_ICON_STATE_DEFAULT, 48);
-  gtk_window_set_title (GTK_WINDOW (window), thunar_file_get_special_name (current_directory));
+  gtk_window_set_title (GTK_WINDOW (window), thunar_file_get_display_name (current_directory));
   gtk_window_set_icon (GTK_WINDOW (window), icon);
   g_object_unref (G_OBJECT (icon));
 }