]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkfilesystemunix.c
2.8.2
[~andy/gtk] / gtk / gtkfilesystemunix.c
index 54e02aa3ef0840d0c5901bead67a6563ac78fe92..403b52129f9bf9a6decdacded20911028b965f89 100644 (file)
@@ -43,6 +43,8 @@
 
 #define BOOKMARKS_FILENAME ".gtk-bookmarks"
 
+#define HIDDEN_FILENAME ".hidden"
+
 #define FOLDER_CACHE_LIFETIME 2 /* seconds */
 
 typedef struct _GtkFileSystemUnixClass GtkFileSystemUnixClass;
@@ -112,6 +114,7 @@ struct _GtkFileFolderUnix
   guint have_stat : 1;
   guint have_mime_type : 1;
   guint is_network_dir : 1;
+  guint have_hidden : 1;
   time_t asof;
 };
 
@@ -119,6 +122,7 @@ struct stat_info_entry {
   struct stat statbuf;
   char *mime_type;
   IconType icon_type;
+  gboolean hidden;
 };
 
 static const GtkFileInfoType STAT_NEEDED_MASK = (GTK_FILE_INFO_IS_FOLDER |
@@ -225,9 +229,13 @@ static GtkFilePath *filename_to_path   (const gchar       *filename);
 
 static gboolean     filename_is_root  (const char       *filename);
 
+static gboolean file_is_hidden (GtkFileFolderUnix *folder_unix,
+                               const char        *basename);
+
 static gboolean fill_in_names (GtkFileFolderUnix *folder_unix, GError **error);
 static void fill_in_stats (GtkFileFolderUnix *folder_unix);
 static void fill_in_mime_type (GtkFileFolderUnix *folder_unix);
+static void fill_in_hidden (GtkFileFolderUnix *folder_unix);
 
 static char *       get_parent_dir    (const char       *filename);
 
@@ -397,7 +405,7 @@ gtk_file_system_unix_get_folder (GtkFileSystem     *file_system,
   GtkFileFolderUnix *folder_unix;
   const char *filename;
   char *filename_copy;
-  time_t now = time (NULL);
+  gboolean set_asof = FALSE;
 
   system_unix = GTK_FILE_SYSTEM_UNIX (file_system);
 
@@ -411,8 +419,8 @@ gtk_file_system_unix_get_folder (GtkFileSystem     *file_system,
   if (folder_unix)
     {
       g_free (filename_copy);
-      if (now - folder_unix->asof >= FOLDER_CACHE_LIFETIME &&
-         folder_unix->stat_info)
+      if (folder_unix->stat_info &&
+         time (NULL) - folder_unix->asof >= FOLDER_CACHE_LIFETIME)
        {
 #if 0
          g_print ("Cleaning out cached directory %s\n", filename);
@@ -421,6 +429,8 @@ gtk_file_system_unix_get_folder (GtkFileSystem     *file_system,
          folder_unix->stat_info = NULL;
          folder_unix->have_mime_type = FALSE;
          folder_unix->have_stat = FALSE;
+         folder_unix->have_hidden = FALSE;
+         set_asof = TRUE;
        }
 
       g_object_ref (folder_unix);
@@ -477,10 +487,11 @@ gtk_file_system_unix_get_folder (GtkFileSystem     *file_system,
       folder_unix->filename = filename_copy;
       folder_unix->types = types;
       folder_unix->stat_info = NULL;
-      folder_unix->asof = now;
       folder_unix->have_mime_type = FALSE;
       folder_unix->have_stat = FALSE;
-
+      folder_unix->have_hidden = FALSE;
+      set_asof = TRUE;
+         
       if ((system_unix->have_afs &&
           system_unix->afs_statbuf.st_dev == statbuf.st_dev &&
           system_unix->afs_statbuf.st_ino == statbuf.st_ino) ||
@@ -502,6 +513,9 @@ gtk_file_system_unix_get_folder (GtkFileSystem     *file_system,
   if ((types & GTK_FILE_INFO_MIME_TYPE) != 0)
     fill_in_mime_type (folder_unix);
 
+  if (set_asof)
+    folder_unix->asof = time (NULL);
+
   return GTK_FILE_FOLDER (folder_unix);
 }
 
@@ -622,7 +636,7 @@ static gchar *
 gtk_file_system_unix_volume_get_display_name (GtkFileSystem       *file_system,
                                              GtkFileSystemVolume *volume)
 {
-  return g_strdup (_("Filesystem")); /* Same as Nautilus */
+  return g_strdup (_("File System")); /* Same as Nautilus */
 }
 
 static IconType
@@ -794,7 +808,7 @@ gtk_file_system_unix_volume_render_icon (GtkFileSystem        *file_system,
 {
   GdkPixbuf *pixbuf;
 
-  pixbuf = get_cached_icon (widget, "gnome-fs-blockdev", pixel_size);
+  pixbuf = get_cached_icon (widget, "gnome-dev-harddisk", pixel_size);
   if (pixbuf)
     return pixbuf;
 
@@ -1336,7 +1350,7 @@ gtk_file_system_unix_render_icon (GtkFileSystem     *file_system,
 }
 
 static void
-string_list_free (GSList *list)
+bookmark_list_free (GSList *list)
 {
   GSList *l;
 
@@ -1370,21 +1384,20 @@ bookmark_get_filename (void)
 {
   char *filename;
 
-  filename = g_build_filename (g_get_home_dir (), BOOKMARKS_FILENAME, NULL);
-
+  filename = g_build_filename (g_get_home_dir (), 
+                              BOOKMARKS_FILENAME, NULL);
   g_assert (filename != NULL);
-
   return filename;
 }
 
 static gboolean
-string_list_read (const gchar  *filename, 
-                 GSList      **bookmarks, 
-                 GError      **error)
+bookmark_list_read (GSList **bookmarks, GError **error)
 {
+  gchar *filename;
   gchar *contents;
   gboolean result = FALSE;
 
+  filename = bookmark_get_filename ();
   *bookmarks = NULL;
 
   if (g_file_get_contents (filename, &contents, NULL, error))
@@ -1412,110 +1425,47 @@ string_list_read (const gchar  *filename,
       result = TRUE;
     }
 
+  g_free (filename);
+
   return result;
 }
 
 static gboolean
-string_list_write (gchar   *filename,
-                  GSList  *bookmarks, 
-                  GError **error)
+bookmark_list_write (GSList  *bookmarks, 
+                    GError **error)
 {
-  char *tmp_filename;
-  gboolean result = TRUE;
-  FILE *file;
-  int fd;
-  int saved_errno;
+  GSList *l;
+  GString *string;
+  char *filename;
+  GError *tmp_error = NULL;
+  gboolean result;
 
-  /* First, write a temporary file */  
-  tmp_filename = g_strdup_printf ("%s-XXXXXX", filename);
+  string = g_string_new ("");
 
-  fd = g_mkstemp (tmp_filename);
-  if (fd == -1)
+  for (l = bookmarks; l; l = l->next)
     {
-      saved_errno = errno;
-      goto io_error;
+      g_string_append (string, l->data);
+      g_string_append_c (string, '\n');
     }
 
-  if ((file = fdopen (fd, "w")) != NULL)
-    {
-      GSList *l;
+  filename = bookmark_get_filename ();
 
-      for (l = bookmarks; l; l = l->next)
-       if (fputs (l->data, file) == EOF
-           || fputs ("\n", file) == EOF)
-         {
-           saved_errno = errno;
-           goto io_error;
-         }
+  result = g_file_set_contents (filename, string->str, -1, &tmp_error);
 
-      if (fclose (file) == EOF)
-       {
-         saved_errno = errno;
-         goto io_error;
-       }
-
-      if (rename (tmp_filename, filename) == -1)
-       {
-         saved_errno = errno;
-         goto io_error;
-       }
+  g_free (filename);
+  g_string_free (string, TRUE);
 
-      result = TRUE;
-      goto out;
-    }
-  else
+  if (!result)
     {
-      saved_errno = errno;
-
-      /* fdopen() failed, so we can't do much error checking here anyway */
-      close (fd);
+      g_set_error (error,
+                  GTK_FILE_SYSTEM_ERROR,
+                  GTK_FILE_SYSTEM_ERROR_FAILED,
+                  _("Bookmark saving failed: %s"),
+                  tmp_error->message);
+      
+      g_error_free (tmp_error);
     }
 
- io_error:
-
-  g_set_error (error,
-              GTK_FILE_SYSTEM_ERROR,
-              GTK_FILE_SYSTEM_ERROR_FAILED,
-              _("Writing %s failed: %s"),
-              filename,
-              g_strerror (saved_errno));
-  result = FALSE;
-
-  if (fd != -1)
-    unlink (tmp_filename); /* again, not much error checking we can do here */
-
- out:
-
-  g_free (tmp_filename);
-
-  return result;
-}
-
-static gboolean
-bookmark_list_read (GSList **bookmarks, 
-                   GError **error)
-{
-  gchar *filename;
-  gboolean result;
-
-  filename = bookmark_get_filename ();
-  result = string_list_read (filename, bookmarks, error);
-  g_free (filename);
-
-  return result;
-}
-
-static gboolean
-bookmark_list_write (GSList  *bookmarks, 
-                    GError **error)
-{
-  gchar *filename;
-  gboolean result;
-
-  filename = bookmark_get_filename ();
-  result = string_list_write (filename, bookmarks, error);
-  g_free (filename);
-  
   return result;
 }
 
@@ -1581,7 +1531,7 @@ gtk_file_system_unix_insert_bookmark (GtkFileSystem     *file_system,
  out:
 
   g_free (uri);
-  string_list_free (bookmarks);
+  bookmark_list_free (bookmarks);
 
   return result;
 }
@@ -1643,7 +1593,7 @@ gtk_file_system_unix_remove_bookmark (GtkFileSystem     *file_system,
  out:
 
   g_free (uri);
-  string_list_free (bookmarks);
+  bookmark_list_free (bookmarks);
 
   return result;
 }
@@ -1673,7 +1623,7 @@ gtk_file_system_unix_list_bookmarks (GtkFileSystem *file_system)
        result = g_slist_prepend (result, gtk_file_system_unix_uri_to_path (file_system, bookmark));
     }
 
-  string_list_free (bookmarks);
+  bookmark_list_free (bookmarks);
 
   result = g_slist_reverse (result);
   return result;
@@ -1707,7 +1657,7 @@ gtk_file_system_unix_get_bookmark_label (GtkFileSystem     *file_system,
        label = g_strdup (space + 1);
     }
 
-  string_list_free (labels);
+  bookmark_list_free (labels);
   g_free (uri);
 
   return label;
@@ -1761,7 +1711,7 @@ gtk_file_system_unix_set_bookmark_label (GtkFileSystem     *file_system,
        g_signal_emit_by_name (file_system, "bookmarks-changed", 0);
     }
   
-  string_list_free (labels);
+  bookmark_list_free (labels);
   g_free (uri);
 }
 
@@ -1918,11 +1868,12 @@ stat_with_error (const char   *filename,
 
 /* Creates a new GtkFileInfo from the specified data */
 static GtkFileInfo *
-create_file_info (const char     *filename,
-                 const char     *basename,
-                 GtkFileInfoType types,
-                 struct stat    *statbuf,
-                 const char     *mime_type)
+create_file_info (GtkFileFolderUnix *folder_unix,
+                  const char        *filename,
+                 const char        *basename,
+                 GtkFileInfoType    types,
+                 struct stat       *statbuf,
+                 const char        *mime_type)
 {
   GtkFileInfo *info;
 
@@ -1936,7 +1887,10 @@ create_file_info (const char     *filename,
     }
 
   if (types & GTK_FILE_INFO_IS_HIDDEN)
-    gtk_file_info_set_is_hidden (info, basename[0] == '.');
+    {
+      if (file_is_hidden (folder_unix, basename))
+       gtk_file_info_set_is_hidden (info, TRUE);
+    }
 
   if (types & GTK_FILE_INFO_IS_FOLDER)
     gtk_file_info_set_is_folder (info, S_ISDIR (statbuf->st_mode));
@@ -2035,7 +1989,7 @@ gtk_file_folder_unix_get_info (GtkFileFolder      *folder,
          entry = create_stat_info_entry_and_emit_add (folder_unix, filename, basename, &statbuf);
        }
 
-      info = create_file_info (filename, basename, types, &entry->statbuf, entry->mime_type);
+      info = create_file_info (folder_unix, filename, basename, types, &entry->statbuf, entry->mime_type);
       g_free (basename);
       return info;
     }
@@ -2052,7 +2006,7 @@ gtk_file_folder_unix_get_info (GtkFileFolder      *folder,
       else
        mime_type = NULL;
 
-      info = create_file_info (filename, basename, types, &statbuf, mime_type);
+      info = create_file_info (folder_unix, filename, basename, types, &statbuf, mime_type);
       g_free (basename);
       return info;
     }
@@ -2135,7 +2089,10 @@ fill_in_names (GtkFileFolderUnix *folder_unix, GError **error)
 
       entry = g_new0 (struct stat_info_entry, 1);
       if (folder_unix->is_network_dir)
-       entry->statbuf.st_mode = S_IFDIR;
+       {
+         entry->statbuf.st_mode = S_IFDIR;
+         entry->mime_type = g_strdup ("x-directory/normal");
+       }
 
       g_hash_table_insert (folder_unix->stat_info,
                           g_strdup (basename),
@@ -2214,13 +2171,51 @@ fill_in_mime_type (GtkFileFolderUnix *folder_unix)
 
   g_assert (folder_unix->stat_info != NULL);
 
-  g_hash_table_foreach_remove (folder_unix->stat_info,
-                              cb_fill_in_mime_type,
-                              folder_unix);
+  if (!folder_unix->is_network_dir)
+    g_hash_table_foreach_remove (folder_unix->stat_info,
+                                cb_fill_in_mime_type,
+                                folder_unix);
 
   folder_unix->have_mime_type = TRUE;
 }
 
+static void
+fill_in_hidden (GtkFileFolderUnix *folder_unix)
+{
+  gchar *hidden_file;
+  gchar *contents;
+  
+  if (folder_unix->have_hidden)
+    return;
+
+  hidden_file = g_build_filename (folder_unix->filename, HIDDEN_FILENAME, NULL);
+
+  if (g_file_get_contents (hidden_file, &contents, NULL, NULL))
+    {
+      gchar **lines; 
+      int i;
+      
+      lines = g_strsplit (contents, "\n", -1);
+      for (i = 0; lines[i]; i++)
+       {
+         if (lines[i][0])
+           {
+             struct stat_info_entry *entry;
+             
+             entry = g_hash_table_lookup (folder_unix->stat_info, lines[i]);
+             if (entry != NULL)
+               entry->hidden = TRUE;
+           }
+       }
+      
+      g_strfreev (lines);
+      g_free (contents);
+    }
+
+  g_free (hidden_file);
+  folder_unix->have_hidden = TRUE;
+}
+
 static GtkFilePath *
 filename_to_path (const char *filename)
 {
@@ -2240,5 +2235,27 @@ filename_is_root (const char *filename)
   return (after_root != NULL && *after_root == '\0');
 }
 
+static gboolean
+file_is_hidden (GtkFileFolderUnix *folder_unix,
+               const char        *basename)
+{
+ struct stat_info_entry *entry;
+
+  if (basename[0] == '.' || basename[strlen (basename) - 1] == '~')
+    return TRUE;
+  if (folder_unix->have_stat)
+    {
+      fill_in_hidden (folder_unix);
+      
+      entry = g_hash_table_lookup (folder_unix->stat_info, basename);
+  
+      if (entry)
+       return entry->hidden;
+    }
+
+  return FALSE;
+}
+
 #define __GTK_FILE_SYSTEM_UNIX_C__
 #include "gtkaliasdef.c"