summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarin Adler <darin@src.gnome.org>2000-03-08 21:16:21 +0000
committerDarin Adler <darin@src.gnome.org>2000-03-08 21:16:21 +0000
commit6ba4e1e5e3adce6604d0d09563c99923bc9cc97a (patch)
tree2f253460141e3b059b81134004e932a410d6c23b
parent886358c4f74f0843ee5d235218e0745c3ea2a64a (diff)
downloadnautilus-6ba4e1e5e3adce6604d0d09563c99923bc9cc97a.tar.gz
Broke the file part of nautilus-directory.[ch] into nautilus-file.[ch].
* components/music/nautilus-music-view.c, components/notes/ntl-notes.c, libnautilus/Makefile.am, libnautilus/nautilus-directory-private.h, libnautilus/nautilus-directory.h, libnautilus/nautilus-directory.c, libnautilus/nautilus-file-private.h, libnautilus/nautilus-file.h, libnautilus/nautilus-file.c, libnautilus/nautilus-icon-factory.h, src/ntl-index-panel.c, src/file-manager/fm-directory-view.h: Broke the file part of nautilus-directory.[ch] into nautilus-file.[ch]. * libnautilus/nautilus-string.c (nautilus_strstrip): Added more tests. Changed algorithm on strstrip so it's linear instead of n^2. * libnautilus/gnome-icon-container.c (gnome_icon_container_initialize): Fixed font for "larger" zoom level. Also made it assert if the font can't be loaded. * components/help/hyperbola-nav-index.c (despace): Fixed warning. * libnautilus/gnome-icon-container-dnd.c, libnautilus/nautilus-string.h: Whitespace. * src/file-manager/Makefile.am, src/file-manager/fm-directory-view.c, src/file-manager/fm-properties-window.h, src/file-manager/fm-properties-window.c: Added properties window hook, but no window yet. The menu item still needs to be added to the main menus as well as the context menus. * src/file-manager/fm-directory-view.c, src/file-manager/fm-directory-view-icons.c, src/file-manager/fm-icon-text-window.h, src/file-manager/fm-icon-text-window.c: A little cleanup. Shorter names.
-rw-r--r--ChangeLog-2000041455
-rw-r--r--components/help/hyperbola-nav-index.c2
-rw-r--r--components/music/nautilus-music-view.c1
-rw-r--r--components/notes/nautilus-notes.c6
-rw-r--r--components/notes/ntl-notes.c6
-rw-r--r--libnautilus-extensions/Makefile.am5
-rw-r--r--libnautilus-extensions/gnome-icon-container-dnd.c4
-rw-r--r--libnautilus-extensions/gnome-icon-container.c37
-rw-r--r--libnautilus-extensions/nautilus-directory-private.h72
-rw-r--r--libnautilus-extensions/nautilus-directory.c1093
-rw-r--r--libnautilus-extensions/nautilus-directory.h79
-rw-r--r--libnautilus-extensions/nautilus-file-private.h37
-rw-r--r--libnautilus-extensions/nautilus-file.c1014
-rw-r--r--libnautilus-extensions/nautilus-file.h106
-rw-r--r--libnautilus-extensions/nautilus-icon-factory.h9
-rw-r--r--libnautilus-extensions/nautilus-string.c83
-rw-r--r--libnautilus-extensions/nautilus-string.h4
-rw-r--r--libnautilus-private/Makefile.am5
-rw-r--r--libnautilus-private/gnome-icon-container-dnd.c4
-rw-r--r--libnautilus-private/gnome-icon-container.c37
-rw-r--r--libnautilus-private/nautilus-directory-private.h72
-rw-r--r--libnautilus-private/nautilus-directory.c1093
-rw-r--r--libnautilus-private/nautilus-directory.h79
-rw-r--r--libnautilus-private/nautilus-file-private.h37
-rw-r--r--libnautilus-private/nautilus-file.c1014
-rw-r--r--libnautilus-private/nautilus-file.h106
-rw-r--r--libnautilus-private/nautilus-icon-factory.h9
-rw-r--r--libnautilus-private/nautilus-string.c83
-rw-r--r--libnautilus-private/nautilus-string.h4
-rw-r--r--libnautilus/Makefile.am5
-rw-r--r--libnautilus/gnome-icon-container-dnd.c4
-rw-r--r--libnautilus/gnome-icon-container.c37
-rw-r--r--libnautilus/nautilus-directory-private.h72
-rw-r--r--libnautilus/nautilus-directory.c1093
-rw-r--r--libnautilus/nautilus-directory.h79
-rw-r--r--libnautilus/nautilus-file-private.h37
-rw-r--r--libnautilus/nautilus-file.c1014
-rw-r--r--libnautilus/nautilus-file.h106
-rw-r--r--libnautilus/nautilus-icon-factory.h9
-rw-r--r--libnautilus/nautilus-string.c83
-rw-r--r--libnautilus/nautilus-string.h4
-rw-r--r--src/file-manager/Makefile.am2
-rw-r--r--src/file-manager/fm-directory-view-icons.c54
-rw-r--r--src/file-manager/fm-directory-view.c248
-rw-r--r--src/file-manager/fm-directory-view.h1
-rw-r--r--src/file-manager/fm-icon-text-window.c10
-rw-r--r--src/file-manager/fm-icon-text-window.h3
-rw-r--r--src/file-manager/fm-properties-window.c34
-rw-r--r--src/file-manager/fm-properties-window.h34
-rw-r--r--src/nautilus-information-panel.c1
-rw-r--r--src/nautilus-sidebar.c1
-rw-r--r--src/ntl-index-panel.c1
52 files changed, 4341 insertions, 3747 deletions
diff --git a/ChangeLog-20000414 b/ChangeLog-20000414
index 2a22185dc..9ab27f408 100644
--- a/ChangeLog-20000414
+++ b/ChangeLog-20000414
@@ -1,13 +1,53 @@
+2000-03-07 Darin Adler <darin@eazel.com>
+
+ * components/music/nautilus-music-view.c,
+ components/notes/ntl-notes.c, libnautilus/Makefile.am,
+ libnautilus/nautilus-directory-private.h,
+ libnautilus/nautilus-directory.h,
+ libnautilus/nautilus-directory.c,
+ libnautilus/nautilus-file-private.h, libnautilus/nautilus-file.h,
+ libnautilus/nautilus-file.c, libnautilus/nautilus-icon-factory.h,
+ src/ntl-index-panel.c, src/file-manager/fm-directory-view.h:
+ Broke the file part of nautilus-directory.[ch] into
+ nautilus-file.[ch].
+
+ * libnautilus/nautilus-string.c (nautilus_strstrip): Added more
+ tests. Changed algorithm on strstrip so it's linear instead of
+ n^2.
+
+ * libnautilus/gnome-icon-container.c
+ (gnome_icon_container_initialize): Fixed font for "larger" zoom
+ level. Also made it assert if the font can't be loaded.
+
+ * components/help/hyperbola-nav-index.c (despace):
+ Fixed warning.
+
+ * libnautilus/gnome-icon-container-dnd.c,
+ libnautilus/nautilus-string.h: Whitespace.
+
+ * src/file-manager/Makefile.am,
+ src/file-manager/fm-directory-view.c,
+ src/file-manager/fm-properties-window.h,
+ src/file-manager/fm-properties-window.c: Added properties window
+ hook, but no window yet. The menu item still needs to be added to
+ the main menus as well as the context menus.
+
+ * src/file-manager/fm-directory-view.c,
+ src/file-manager/fm-directory-view-icons.c,
+ src/file-manager/fm-icon-text-window.h,
+ src/file-manager/fm-icon-text-window.c: A little cleanup. Shorter
+ names.
+
2000-03-08 Ramiro Estrugo <ramiro@eazel.com>
* src/nautilus-prefs-group-radio.h,
src/nautilus-prefs-group-radio.h: Make the radio group emit proper
- signals on changes.
+ signals on changes.
+
+ * src/nautilus-prefs-pane.c, src/nautilus-prefs-group.c
+ src/nautilus-prefs-box.c: Make everything prettier by using nice
+ offsets.
- * src/nautilus-prefs-pane.c,
- src/nautilus-prefs-group.c
- src/nautilus-prefs-box.c: Make everything prettier by using nice offsets.
-
2000-03-08 Ramiro Estrugo <ramiro@eazel.com>
Added macros to check, assert and invoke class methods
@@ -17,9 +57,10 @@
(NAUTILUS_KLASS) Access the class for a given object
(NAUTILUS_INVOKE_METHOD) Invoke a method for a given object
(NAUTILUS_ACCESS_METHOD) Access a method.
- (NAUTILUS_ASSERT_METHOD) Assert the non-nullness of a method for a given object
+ (NAUTILUS_ASSERT_METHOD) Assert the non-nullness of a method
+ for a given object
(NAUTILUS_INVOKE_METHOD_IF) Invoke a method if it aint null.
-
+
2000-03-08 Ramiro Estrugo <ramiro@eazel.com>
First whack at having a better preferences ui.
diff --git a/components/help/hyperbola-nav-index.c b/components/help/hyperbola-nav-index.c
index 6df6a109e..33535de9b 100644
--- a/components/help/hyperbola-nav-index.c
+++ b/components/help/hyperbola-nav-index.c
@@ -366,7 +366,7 @@ despace(GString *s)
ctmp = ctmp_s + 2;
i--;
if(i != strlen(ctmp))
- g_error("i (%d) != strlen(ctmp) (%ld)", i, strlen(ctmp));
+ g_error("i (%d) != strlen(ctmp) (%ld)", i, (long)strlen(ctmp));
}
ctmp_s = NULL;
}
diff --git a/components/music/nautilus-music-view.c b/components/music/nautilus-music-view.c
index 00cf191f1..11ce76912 100644
--- a/components/music/nautilus-music-view.c
+++ b/components/music/nautilus-music-view.c
@@ -33,6 +33,7 @@
#include <libnautilus/libnautilus.h>
#include <libnautilus/nautilus-background.h>
+#include <libnautilus/nautilus-file.h>
#include <libnautilus/nautilus-file-utilities.h>
#include <libnautilus/nautilus-glib-extensions.h>
#include <libnautilus/nautilus-gtk-macros.h>
diff --git a/components/notes/nautilus-notes.c b/components/notes/nautilus-notes.c
index 165def4b0..d89412230 100644
--- a/components/notes/nautilus-notes.c
+++ b/components/notes/nautilus-notes.c
@@ -24,7 +24,8 @@
*/
/* annotation metaview - allows you to annotate a directory or file */
-#include "config.h"
+
+#include <config.h>
#include <libnautilus/libnautilus.h>
#include <libnautilus/nautilus-metadata.h>
@@ -34,8 +35,9 @@
#include <limits.h>
#include <ctype.h>
#include <libnautilus/nautilus-background.h>
+#include <libnautilus/nautilus-file.h>
-#define NOTES_DEFAULT_BACKGROUND_COLOR "rgb:FFFF/FFFF/BBBB"
+#define NOTES_DEFAULT_BACKGROUND_COLOR "rgb:FFFF/FFFF/BBBB"
typedef struct {
diff --git a/components/notes/ntl-notes.c b/components/notes/ntl-notes.c
index 165def4b0..d89412230 100644
--- a/components/notes/ntl-notes.c
+++ b/components/notes/ntl-notes.c
@@ -24,7 +24,8 @@
*/
/* annotation metaview - allows you to annotate a directory or file */
-#include "config.h"
+
+#include <config.h>
#include <libnautilus/libnautilus.h>
#include <libnautilus/nautilus-metadata.h>
@@ -34,8 +35,9 @@
#include <limits.h>
#include <ctype.h>
#include <libnautilus/nautilus-background.h>
+#include <libnautilus/nautilus-file.h>
-#define NOTES_DEFAULT_BACKGROUND_COLOR "rgb:FFFF/FFFF/BBBB"
+#define NOTES_DEFAULT_BACKGROUND_COLOR "rgb:FFFF/FFFF/BBBB"
typedef struct {
diff --git a/libnautilus-extensions/Makefile.am b/libnautilus-extensions/Makefile.am
index 4e65cefad..002601a80 100644
--- a/libnautilus-extensions/Makefile.am
+++ b/libnautilus-extensions/Makefile.am
@@ -27,8 +27,6 @@ libnautilusincludedir=$(includedir)/libnautilus
libnautilusinclude_HEADERS= \
bonobo-stream-vfs.h \
gdk-extensions.h \
- gnome-icon-container-dnd.h \
- gnome-icon-container-private.h \
gnome-icon-container.h \
gtkflist.h \
gtkscrollframe.h \
@@ -38,13 +36,13 @@ libnautilusinclude_HEADERS= \
nautilus-bookmark.h \
nautilus-debug.h \
nautilus-directory.h \
+ nautilus-file.h \
nautilus-file-utilities.h \
nautilus-glib-extensions.h \
nautilus-gtk-extensions.h \
nautilus-icon-factory.h \
nautilus-icons-controller.h \
nautilus-icons-view-icon-item.h \
- nautilus-lib-self-check-functions.h \
nautilus-metadata.h \
nautilus-mime-type.h \
nautilus-self-checks.h \
@@ -68,6 +66,7 @@ libnautilus_la_SOURCES=$(nautilus_idl_sources) \
nautilus-default-file-icon.c \
nautilus-default-file-icon.h \
nautilus-directory.c \
+ nautilus-file.c \
nautilus-file-utilities.c \
nautilus-glib-extensions.c \
nautilus-gtk-extensions.c \
diff --git a/libnautilus-extensions/gnome-icon-container-dnd.c b/libnautilus-extensions/gnome-icon-container-dnd.c
index 987556da1..1057c984d 100644
--- a/libnautilus-extensions/gnome-icon-container-dnd.c
+++ b/libnautilus-extensions/gnome-icon-container-dnd.c
@@ -816,12 +816,12 @@ gnome_icon_container_dnd_begin_drag (GnomeIconContainer *container,
gtk_object_getv (GTK_OBJECT (item), 1, &pixbuf_arg);
pixbuf = GTK_VALUE_BOXED (pixbuf_arg);
- transparent_pixbuf = make_semi_transparent(pixbuf);
+ transparent_pixbuf = make_semi_transparent (pixbuf);
gdk_pixbuf_render_pixmap_and_mask (transparent_pixbuf,
&pixmap_for_dragged_file,
&mask_for_dragged_file,
128);
- gdk_pixbuf_unref(transparent_pixbuf);
+ gdk_pixbuf_unref (transparent_pixbuf);
/* compute the image's offset */
nautilus_icons_view_icon_item_get_icon_window_rectangle
diff --git a/libnautilus-extensions/gnome-icon-container.c b/libnautilus-extensions/gnome-icon-container.c
index 20ada54d2..ddf28423e 100644
--- a/libnautilus-extensions/gnome-icon-container.c
+++ b/libnautilus-extensions/gnome-icon-container.c
@@ -724,15 +724,17 @@ make_icon_visible (GnomeIconContainer *container,
icon_get_bounding_box (icon, &x1, &y1, &x2, &y2);
- if (y1 < vadj->value)
+ if (y1 < vadj->value) {
gtk_adjustment_set_value (vadj, y1);
- else if (y2 > vadj->value + allocation->height)
+ } else if (y2 > vadj->value + allocation->height) {
gtk_adjustment_set_value (vadj, y2 - allocation->height);
+ }
- if (x1 < hadj->value)
+ if (x1 < hadj->value) {
gtk_adjustment_set_value (hadj, x1);
- else if (x2 > hadj->value + allocation->width)
+ } else if (x2 > hadj->value + allocation->width) {
gtk_adjustment_set_value (hadj, x2 - allocation->width);
+ }
}
static gboolean
@@ -2145,6 +2147,17 @@ gnome_icon_container_initialize_class (GnomeIconContainerClass *class)
stipple = gdk_bitmap_create_from_data (NULL, stipple_bits, 2, 2);
}
+static GdkFont *
+load_font (const char *name)
+{
+ GdkFont *font;
+
+ /* FIXME: Eventually we need a runtime check, but an assert is better than nothing. */
+ font = gdk_font_load (name);
+ g_assert (font != NULL);
+ return font;
+}
+
static void
gnome_icon_container_initialize (GnomeIconContainer *container)
{
@@ -2159,15 +2172,15 @@ gnome_icon_container_initialize (GnomeIconContainer *container)
details->zoom_level = NAUTILUS_ZOOM_LEVEL_STANDARD;
- /* font table - this isnt exactly proportional, but it looks better than computed */
+ /* font table - this isn't exactly proportional, but it looks better than computed */
/* FIXME: read font from metadata and/or preferences */
- details->label_font[NAUTILUS_ZOOM_LEVEL_SMALLEST] = gdk_font_load("-*-helvetica-medium-r-normal-*-8-*-*-*-*-*-*-*");
- details->label_font[NAUTILUS_ZOOM_LEVEL_SMALLER] = gdk_font_load("-*-helvetica-medium-r-normal-*-8-*-*-*-*-*-*-*");
- details->label_font[NAUTILUS_ZOOM_LEVEL_SMALL] = gdk_font_load("-*-helvetica-medium-r-normal-*-10-*-*-*-*-*-*-*");
- details->label_font[NAUTILUS_ZOOM_LEVEL_STANDARD] = gdk_font_load("-*-helvetica-medium-r-normal-*-12-*-*-*-*-*-*-*");
- details->label_font[NAUTILUS_ZOOM_LEVEL_LARGE] = gdk_font_load("-*-helvetica-medium-r-normal-*-14-*-*-*-*-*-*-*");
- details->label_font[NAUTILUS_ZOOM_LEVEL_LARGER] = gdk_font_load("-*-helveticar-medium-r-normal-*-18-*-*-*-*-*-*-*");
- details->label_font[NAUTILUS_ZOOM_LEVEL_LARGEST] = gdk_font_load("-*-helvetica-medium-r-normal-*-18-*-*-*-*-*-*-*");
+ details->label_font[NAUTILUS_ZOOM_LEVEL_SMALLEST] = load_font ("-*-helvetica-medium-r-normal-*-8-*-*-*-*-*-*-*");
+ details->label_font[NAUTILUS_ZOOM_LEVEL_SMALLER] = load_font ("-*-helvetica-medium-r-normal-*-8-*-*-*-*-*-*-*");
+ details->label_font[NAUTILUS_ZOOM_LEVEL_SMALL] = load_font ("-*-helvetica-medium-r-normal-*-10-*-*-*-*-*-*-*");
+ details->label_font[NAUTILUS_ZOOM_LEVEL_STANDARD] = load_font ("-*-helvetica-medium-r-normal-*-12-*-*-*-*-*-*-*");
+ details->label_font[NAUTILUS_ZOOM_LEVEL_LARGE] = load_font ("-*-helvetica-medium-r-normal-*-14-*-*-*-*-*-*-*");
+ details->label_font[NAUTILUS_ZOOM_LEVEL_LARGER] = load_font ("-*-helvetica-medium-r-normal-*-18-*-*-*-*-*-*-*");
+ details->label_font[NAUTILUS_ZOOM_LEVEL_LARGEST] = load_font ("-*-helvetica-medium-r-normal-*-18-*-*-*-*-*-*-*");
/* FIXME: Read these from preferences. */
details->linger_selection_mode = FALSE;
diff --git a/libnautilus-extensions/nautilus-directory-private.h b/libnautilus-extensions/nautilus-directory-private.h
new file mode 100644
index 000000000..12496a3f6
--- /dev/null
+++ b/libnautilus-extensions/nautilus-directory-private.h
@@ -0,0 +1,72 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+
+ nautilus-directory.c: Nautilus directory model.
+
+ Copyright (C) 1999, 2000 Eazel, Inc.
+
+ 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 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 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 Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Darin Adler <darin@eazel.com>
+*/
+
+#include "nautilus-directory.h"
+
+#include <libgnomevfs/gnome-vfs-types.h>
+#include <libgnomevfs/gnome-vfs-uri.h>
+#include <libgnomevfs/gnome-vfs-file-info.h>
+
+#include <gnome-xml/tree.h>
+
+#include "nautilus-file.h"
+
+struct NautilusDirectoryDetails
+{
+ char *uri_text;
+ GnomeVFSURI *uri;
+
+ GnomeVFSURI *metafile_uri;
+ GnomeVFSURI *alternate_metafile_uri;
+ gboolean use_alternate_metafile;
+
+ xmlDoc *metafile_tree;
+ guint write_metafile_idle_id;
+
+ GnomeVFSAsyncHandle *directory_load_in_progress;
+ GnomeVFSDirectoryListPosition directory_load_list_last_handled;
+
+ GList *pending_file_info;
+ guint dequeue_pending_idle_id;
+
+ gboolean directory_loaded;
+
+ GList *files;
+};
+
+NautilusFile *nautilus_directory_new_file (NautilusDirectory *directory,
+ GnomeVFSFileInfo *info);
+char * nautilus_directory_get_file_metadata (NautilusDirectory *directory,
+ const char *file_name,
+ const char *tag,
+ const char *default_metadata);
+void nautilus_directory_set_file_metadata (NautilusDirectory *directory,
+ const char *file_name,
+ const char *tag,
+ const char *default_metadata,
+ const char *metadata);
+xmlNode * nautilus_directory_get_file_metadata_node (NautilusDirectory *directory,
+ const char *file_name);
+void nautilus_directory_files_removed (NautilusDirectory *directory,
+ GList *removed_files);
diff --git a/libnautilus-extensions/nautilus-directory.c b/libnautilus-extensions/nautilus-directory.c
index 643c290db..eaa37ac68 100644
--- a/libnautilus-extensions/nautilus-directory.c
+++ b/libnautilus-extensions/nautilus-directory.c
@@ -1,6 +1,6 @@
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
- nautilus-directory.c: Mautilus directory model.
+ nautilus-directory.c: Nautilus directory model.
Copyright (C) 1999, 2000 Eazel, Inc.
@@ -23,33 +23,20 @@
*/
#include <config.h>
-#include "nautilus-directory.h"
+#include "nautilus-directory-private.h"
-#include <grp.h>
-#include <pwd.h>
#include <stdlib.h>
#include <gtk/gtksignal.h>
#include <gtk/gtkmain.h>
-#include <libgnome/gnome-defs.h>
-#include <libgnome/gnome-i18n.h>
-
-#include <libgnomevfs/gnome-vfs-types.h>
-#include <libgnomevfs/gnome-vfs-uri.h>
-#include <libgnomevfs/gnome-vfs-file-info.h>
-#include <libgnomevfs/gnome-vfs-ops.h>
-#include <libgnomevfs/gnome-vfs-async-ops.h>
-
#include <gnome-xml/parser.h>
-#include <gnome-xml/tree.h>
#include <gnome-xml/xmlmemory.h>
-#include "nautilus-alloc.h"
-#include "nautilus-glib-extensions.h"
#include "nautilus-gtk-macros.h"
-#include "nautilus-lib-self-check-functions.h"
#include "nautilus-string.h"
+#include "nautilus-lib-self-check-functions.h"
+#include "nautilus-file-private.h"
#define METAFILE_NAME ".nautilus-metafile.xml"
#define METAFILE_PERMISSIONS (GNOME_VFS_PERM_USER_READ | GNOME_VFS_PERM_USER_WRITE \
@@ -67,12 +54,6 @@
#define DIRECTORY_LOAD_ITEMS_PER_CB 1
-typedef enum {
- NAUTILUS_DATE_TYPE_MODIFIED,
- NAUTILUS_DATE_TYPE_CHANGED,
- NAUTILUS_DATE_TYPE_ACCESSED
-} NautilusDateType;
-
enum
{
FILES_ADDED,
@@ -80,79 +61,25 @@ enum
LAST_SIGNAL
};
-/* FIXME: This hack needs to die eventually. See comments with function */
-static int get_directory_item_count_hack (NautilusFile *file, gboolean ignore_invisible_items);
-
-
static guint nautilus_directory_signals[LAST_SIGNAL];
-static void nautilus_directory_initialize_class (gpointer klass);
-static void nautilus_directory_initialize (gpointer object, gpointer klass);
-static void nautilus_directory_finalize (GtkObject *object);
-
-static NautilusDirectory *nautilus_directory_new (const char* uri);
-
-static void nautilus_directory_read_metafile (NautilusDirectory *directory);
-static void nautilus_directory_write_metafile (NautilusDirectory *directory);
-static void nautilus_directory_request_write_metafile (NautilusDirectory *directory);
-static void nautilus_directory_remove_write_metafile_idle (NautilusDirectory *directory);
-
-static void nautilus_file_free (NautilusFile *file);
-static int nautilus_file_compare_by_type (NautilusFile *file_1, NautilusFile *file_2);
-static int nautilus_file_compare_for_sort_internal (NautilusFile *file_1,
- NautilusFile *file_2,
- NautilusFileSortType sort_type,
- gboolean reversed);
-
-static char * nautilus_file_get_date_as_string (NautilusFile *file,
- NautilusDateType date_type);
-static char *nautilus_file_get_owner_as_string (NautilusFile *file);
-static char *nautilus_file_get_group_as_string (NautilusFile *file);
-static char *nautilus_file_get_permissions_as_string (NautilusFile *file);
-static char * nautilus_file_get_size_as_string (NautilusFile *file);
-static char * nautilus_file_get_type_as_string (NautilusFile *file);
-static void nautilus_directory_load_cb (GnomeVFSAsyncHandle *handle,
- GnomeVFSResult result,
- GnomeVFSDirectoryList *list,
- guint entries_read,
- gpointer callback_data);
-static NautilusFile *nautilus_directory_new_file (NautilusDirectory *directory,
- GnomeVFSFileInfo *info);
+static void nautilus_directory_initialize_class (gpointer klass);
+static void nautilus_directory_initialize (gpointer object,
+ gpointer klass);
+static void nautilus_directory_finalize (GtkObject *object);
+static NautilusDirectory *nautilus_directory_new (const char *uri);
+static void nautilus_directory_read_metafile (NautilusDirectory *directory);
+static void nautilus_directory_write_metafile (NautilusDirectory *directory);
+static void nautilus_directory_request_write_metafile (NautilusDirectory *directory);
+static void nautilus_directory_remove_write_metafile_idle (NautilusDirectory *directory);
+static void nautilus_directory_load_cb (GnomeVFSAsyncHandle *handle,
+ GnomeVFSResult result,
+ GnomeVFSDirectoryList *list,
+ guint entries_read,
+ gpointer callback_data);
NAUTILUS_DEFINE_CLASS_BOILERPLATE (NautilusDirectory, nautilus_directory, GTK_TYPE_OBJECT)
-struct NautilusDirectoryDetails
-{
- char *uri_text;
- GnomeVFSURI *uri;
-
- GnomeVFSURI *metafile_uri;
- GnomeVFSURI *alternate_metafile_uri;
- gboolean use_alternate_metafile;
-
- xmlDoc *metafile_tree;
- guint write_metafile_idle_id;
-
- GnomeVFSAsyncHandle *directory_load_in_progress;
- GnomeVFSDirectoryListPosition directory_load_list_last_handled;
-
- GList *pending_file_info;
- guint dequeue_pending_idle_id;
-
- gboolean directory_loaded;
-
- GList *files;
-};
-
-struct NautilusFile
-{
- guint ref_count;
-
- NautilusDirectory *directory;
- GnomeVFSFileInfo *info;
- gboolean is_gone;
-};
-
static GHashTable* directory_objects;
static void
@@ -1005,9 +932,9 @@ nautilus_directory_set_integer_metadata (NautilusDirectory *directory,
g_free (default_as_string);
}
-static xmlNode *
-get_file_metadata_node (NautilusDirectory *directory,
- const char *file_name)
+xmlNode *
+nautilus_directory_get_file_metadata_node (NautilusDirectory *directory,
+ const char *file_name)
{
xmlNode *root, *child;
xmlChar *property;
@@ -1038,18 +965,18 @@ get_file_metadata_node (NautilusDirectory *directory,
return NULL;
}
-static char *
+char *
nautilus_directory_get_file_metadata (NautilusDirectory *directory,
const char *file_name,
const char *tag,
const char *default_metadata)
{
return nautilus_directory_get_metadata_from_node
- (get_file_metadata_node (directory, file_name),
+ (nautilus_directory_get_file_metadata_node (directory, file_name),
tag, default_metadata);
}
-static void
+void
nautilus_directory_set_file_metadata (NautilusDirectory *directory,
const char *file_name,
const char *tag,
@@ -1118,7 +1045,7 @@ nautilus_directory_set_file_metadata (NautilusDirectory *directory,
nautilus_directory_request_write_metafile (directory);
}
-static NautilusFile *
+NautilusFile *
nautilus_directory_new_file (NautilusDirectory *directory, GnomeVFSFileInfo *info)
{
NautilusFile *file;
@@ -1135,973 +1062,13 @@ nautilus_directory_new_file (NautilusDirectory *directory, GnomeVFSFileInfo *inf
return file;
}
-/**
- * nautilus_file_get:
- * @uri: URI of file to get.
- *
- * Get a file given a uri.
- * Returns a referenced object. Unref when finished.
- * If two windows are viewing the same uri, the file object is shared.
- */
-NautilusFile *
-nautilus_file_get (const char *uri)
-{
- GnomeVFSResult result;
- GnomeVFSFileInfo *file_info;
- GnomeVFSURI *vfs_uri, *directory_vfs_uri;
- char *directory_uri;
- NautilusDirectory *directory;
- NautilusFile *file;
-
- /* Get info on the file. */
- file_info = gnome_vfs_file_info_new ();
- result = gnome_vfs_get_file_info (uri, file_info,
- GNOME_VFS_FILE_INFO_GETMIMETYPE
- | GNOME_VFS_FILE_INFO_FASTMIMETYPE
- | GNOME_VFS_FILE_INFO_FOLLOWLINKS, NULL);
- if (result != GNOME_VFS_OK)
- return NULL;
-
- /* Make VFS version of URI. */
- vfs_uri = gnome_vfs_uri_new (uri);
- if (vfs_uri == NULL)
- return NULL;
-
- /* Make VFS version of directory URI. */
- directory_vfs_uri = gnome_vfs_uri_get_parent (vfs_uri);
- gnome_vfs_uri_unref (vfs_uri);
- if (directory_vfs_uri == NULL)
- return NULL;
-
- /* Make text version of directory URI. */
- directory_uri = gnome_vfs_uri_to_string (directory_vfs_uri,
- GNOME_VFS_URI_HIDE_NONE);
- gnome_vfs_uri_unref (directory_vfs_uri);
-
- /* Get object that represents the directory. */
- directory = nautilus_directory_get (directory_uri);
- g_free (directory_uri);
- if (directory == NULL)
- return NULL;
-
- file = nautilus_directory_new_file (directory, file_info);
-
- gnome_vfs_file_info_unref (file_info);
- nautilus_file_ref (file);
- gtk_object_unref (GTK_OBJECT (directory));
-
- return file;
-}
-
-void
-nautilus_file_ref (NautilusFile *file)
-{
- g_return_if_fail (file != NULL);
-
- g_assert (file->ref_count < G_MAXINT);
- g_assert (file->directory != NULL);
-
- /* Increment the ref count. */
- if (file->ref_count++ != 0) {
- return;
- }
-
- /* As soon as someone other than the directory holds a ref,
- * we need to hold the directory too. */
- gtk_object_ref (GTK_OBJECT (file->directory));
-}
-
-void
-nautilus_file_unref (NautilusFile *file)
-{
- g_return_if_fail (file != NULL);
-
- g_assert (file->ref_count != 0);
- g_assert (file->directory != NULL);
-
- /* Decrement the ref count. */
- if (--file->ref_count != 0) {
- return;
- }
-
- /* No references left, so it's time to release our hold on the directory. */
- gtk_object_unref (GTK_OBJECT (file->directory));
- if (file->is_gone) {
- nautilus_file_free (file);
- }
-}
-
-static void
-nautilus_file_free (NautilusFile *file)
-{
- g_assert (file->ref_count == 0);
-
- /* Destroy the file object. */
- gnome_vfs_file_info_unref (file->info);
- g_free (file);
-}
-
-static int
-nautilus_file_compare_by_size_with_directories (NautilusFile *file_1, NautilusFile *file_2)
-{
- gboolean is_directory_1;
- gboolean is_directory_2;
- int item_count_1;
- int item_count_2;
-
- is_directory_1 = nautilus_file_is_directory (file_1);
- is_directory_2 = nautilus_file_is_directory (file_2);
-
- if (is_directory_1 && !is_directory_2)
- return -1;
-
- if (is_directory_2 && !is_directory_1)
- return +1;
-
- if (!is_directory_1 && !is_directory_2)
- return 0;
-
- /* Both are directories, compare by item count. */
- /* FIXME: get_directory_item_count_hack is slow, and calling
- * it for every pairwise comparison here is nasty. Need to
- * change this to (not-yet-existent) architecture where the
- * item count can be calculated once in a deferred way, and
- * then stored or cached.
- */
- item_count_1 = get_directory_item_count_hack (file_1, FALSE);
- item_count_2 = get_directory_item_count_hack (file_2, FALSE);
-
- if (item_count_1 < item_count_2)
- return -1;
-
- if (item_count_2 < item_count_1)
- return +1;
-
- return 0;
-}
-
-static int
-nautilus_file_compare_by_type (NautilusFile *file_1, NautilusFile *file_2)
-{
- gboolean is_directory_1;
- gboolean is_directory_2;
- char * type_string_1;
- char * type_string_2;
- int result;
-
- /* Directories go first. Then, if mime types are identical,
- * don't bother getting strings (for speed). This assumes
- * that the string is dependent entirely on the mime type,
- * which is true now but might not be later.
- */
- is_directory_1 = nautilus_file_is_directory (file_1);
- is_directory_2 = nautilus_file_is_directory (file_2);
-
- if (is_directory_1 && is_directory_2)
- return 0;
-
- if (is_directory_1)
- return -1;
-
- if (is_directory_2)
- return +1;
-
- if (nautilus_strcmp (file_1->info->mime_type, file_2->info->mime_type) == 0)
- return 0;
-
- type_string_1 = nautilus_file_get_type_as_string (file_1);
- type_string_2 = nautilus_file_get_type_as_string (file_2);
-
- result = nautilus_strcmp (type_string_1, type_string_2);
-
- g_free (type_string_1);
- g_free (type_string_2);
-
- return result;
-}
-
-static int
-nautilus_file_compare_for_sort_internal (NautilusFile *file_1,
- NautilusFile *file_2,
- NautilusFileSortType sort_type,
- gboolean reversed)
-{
- GnomeVFSDirectorySortRule *rules;
-
- g_return_val_if_fail (file_1 != NULL, 0);
- g_return_val_if_fail (file_2 != NULL, 0);
- g_return_val_if_fail (sort_type != NAUTILUS_FILE_SORT_NONE, 0);
-
-#define ALLOC_RULES(n) alloca ((n) * sizeof (GnomeVFSDirectorySortRule))
-
- switch (sort_type) {
- case NAUTILUS_FILE_SORT_BY_NAME:
- rules = ALLOC_RULES (2);
- /* Note: This used to put directories first. I
- * thought that was counterintuitive and removed it,
- * but I can imagine discussing this further.
- * John Sullivan <sullivan@eazel.com>
- */
- rules[0] = GNOME_VFS_DIRECTORY_SORT_BYNAME_IGNORECASE;
- rules[1] = GNOME_VFS_DIRECTORY_SORT_NONE;
- break;
- case NAUTILUS_FILE_SORT_BY_SIZE:
- /* Compare directory sizes ourselves, then if necessary
- * use GnomeVFS to compare file sizes.
- */
- {
- int size_compare;
-
- size_compare = nautilus_file_compare_by_size_with_directories (file_1, file_2);
- if (size_compare != 0)
- return size_compare;
- }
- rules = ALLOC_RULES (3);
- rules[0] = GNOME_VFS_DIRECTORY_SORT_BYSIZE;
- rules[1] = GNOME_VFS_DIRECTORY_SORT_BYNAME_IGNORECASE;
- rules[2] = GNOME_VFS_DIRECTORY_SORT_NONE;
- break;
- case NAUTILUS_FILE_SORT_BY_TYPE:
- /* GnomeVFS doesn't know about our special text for certain
- * mime types, so we handle the mime-type sorting ourselves.
- */
- {
- int type_compare;
-
- type_compare = nautilus_file_compare_by_type (file_1, file_2);
- if (type_compare != 0)
- return type_compare;
- }
- rules = ALLOC_RULES (2);
- rules[0] = GNOME_VFS_DIRECTORY_SORT_BYNAME_IGNORECASE;
- rules[1] = GNOME_VFS_DIRECTORY_SORT_NONE;
- break;
- case NAUTILUS_FILE_SORT_BY_MTIME:
- rules = ALLOC_RULES (3);
- rules[0] = GNOME_VFS_DIRECTORY_SORT_BYMTIME;
- rules[1] = GNOME_VFS_DIRECTORY_SORT_BYNAME_IGNORECASE;
- rules[2] = GNOME_VFS_DIRECTORY_SORT_NONE;
- break;
- default:
- g_assert_not_reached ();
- return 0;
- }
-
- if (reversed)
- return gnome_vfs_file_info_compare_for_sort_reversed (file_1->info,
- file_2->info,
- rules);
- else
- return gnome_vfs_file_info_compare_for_sort (file_1->info,
- file_2->info,
- rules);
-
-#undef ALLOC_RULES
-}
-
-/**
- * nautilus_file_compare_for_sort:
- * @file_1: A file object
- * @file_2: Another file object
- * @sort_type: Sort criterion
- *
- * Return value: int < 0 if @file_1 should come before file_2 in a smallest-to-largest
- * sorted list; int > 0 if @file_2 should come before file_1 in a smallest-to-largest
- * sorted list; 0 if @file_1 and @file_2 are equal for this sort criterion. Note
- * that each named sort type may actually break ties several ways, with the name
- * of the sort criterion being the primary but not only differentiator.
- **/
-int
-nautilus_file_compare_for_sort (NautilusFile *file_1,
- NautilusFile *file_2,
- NautilusFileSortType sort_type)
-{
- return nautilus_file_compare_for_sort_internal (file_1, file_2, sort_type, FALSE);
-}
-
-/**
- * nautilus_file_compare_for_sort_reversed:
- * @file_1: A file object
- * @file_2: Another file object
- * @sort_type: Sort criterion
- *
- * Return value: The opposite of nautilus_file_compare_for_sort: int > 0 if @file_1
- * should come before file_2 in a smallest-to-largest sorted list; int < 0 if @file_2
- * should come before file_1 in a smallest-to-largest sorted list; 0 if @file_1
- * and @file_2 are equal for this sort criterion. Note that each named sort type
- * may actually break ties several ways, with the name of the sort criterion
- * being the primary but not only differentiator.
- **/
-int
-nautilus_file_compare_for_sort_reversed (NautilusFile *file_1,
- NautilusFile *file_2,
- NautilusFileSortType sort_type)
-{
- return nautilus_file_compare_for_sort_internal (file_1, file_2, sort_type, TRUE);
-}
-
-char *
-nautilus_file_get_metadata (NautilusFile *file,
- const char *tag,
- const char *default_metadata)
-{
- g_return_val_if_fail (file != NULL, NULL);
-
- return nautilus_directory_get_file_metadata (file->directory,
- file->info->name,
- tag,
- default_metadata);
-}
-
void
-nautilus_file_set_metadata (NautilusFile *file,
- const char *tag,
- const char *default_metadata,
- const char *metadata)
+nautilus_directory_files_removed (NautilusDirectory *directory,
+ GList *removed_files)
{
- g_return_if_fail (file != NULL);
-
- nautilus_directory_set_file_metadata (file->directory,
- file->info->name,
- tag,
- default_metadata,
- metadata);
-}
-
-char *
-nautilus_file_get_name (NautilusFile *file)
-{
- g_return_val_if_fail (file != NULL, NULL);
-
- g_assert (file->directory == NULL || NAUTILUS_IS_DIRECTORY (file->directory));
- g_assert (file->info->name != NULL);
- g_assert (file->info->name[0] != '\0');
-
- return g_strdup (file->info->name);
-}
-
-char *
-nautilus_file_get_uri (NautilusFile *file)
-{
- GnomeVFSURI *uri;
- char *uri_text;
-
- g_return_val_if_fail (file != NULL, NULL);
- g_return_val_if_fail (file->directory != NULL, NULL);
-
- uri = gnome_vfs_uri_append_path (file->directory->details->uri, file->info->name);
- uri_text = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE);
- gnome_vfs_uri_unref (uri);
- return uri_text;
-}
-
-/**
- * nautilus_file_get_date_as_string:
- *
- * Get a user-displayable string representing a file modification date.
- * The caller is responsible for g_free-ing this string.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: Newly allocated string ready to display to the user.
- *
- **/
-static char *
-nautilus_file_get_date_as_string (NautilusFile *file, NautilusDateType date_type)
-{
- struct tm *file_time;
- const char *format;
- GDate *today;
- GDate *file_date;
- guint32 file_date_age;
-
- g_return_val_if_fail (file != NULL, NULL);
-
- switch (date_type)
- {
- case NAUTILUS_DATE_TYPE_CHANGED:
- file_time = localtime(&file->info->ctime);
- break;
- case NAUTILUS_DATE_TYPE_ACCESSED:
- file_time = localtime(&file->info->atime);
- break;
- case NAUTILUS_DATE_TYPE_MODIFIED:
- file_time = localtime(&file->info->mtime);
- break;
- default:
- g_assert_not_reached ();
- }
- file_date = nautilus_g_date_new_tm (file_time);
-
- today = g_date_new ();
- g_date_set_time (today, time (NULL));
-
- /* Overflow results in a large number; fine for our purposes. */
- file_date_age = g_date_julian (today) - g_date_julian (file_date);
-
- g_date_free (file_date);
- g_date_free (today);
-
- /* Format varies depending on how old the date is. This minimizes
- * the length (and thus clutter & complication) of typical dates
- * while providing sufficient detail for recent dates to make
- * them maximally understandable at a glance. Keep all format
- * strings separate rather than combining bits & pieces for
- * internationalization's sake.
- */
-
- if (file_date_age == 0)
- {
- /* today, use special word */
- format = _("today %-I:%M %p");
- }
- else if (file_date_age == 1)
- {
- /* yesterday, use special word */
- format = _("yesterday %-I:%M %p");
- }
- else if (file_date_age < 7)
- {
- /* current week, include day of week */
- format = _("%A %-m/%-d/%y %-I:%M %p");
- }
- else
- {
- format = _("%-m/%-d/%y %-I:%M %p");
- }
-
- return nautilus_strdup_strftime (format, file_time);
-}
-
-/**
- * nautilus_file_get_directory_item_count
- *
- * Get the number of items in a directory.
- * @file: NautilusFile representing a directory. It is an error to
- * call this function on a file that is not a directory.
- * @ignore_invisible_items: TRUE if invisible items should not be
- * included in count.
- *
- * Returns: item count for this directory.
- *
- **/
-guint
-nautilus_file_get_directory_item_count (NautilusFile *file,
- gboolean ignore_invisible_items)
-{
- g_return_val_if_fail (nautilus_file_is_directory (file), 0);
-
- return get_directory_item_count_hack (file, ignore_invisible_items);
-}
-
-/**
- * nautilus_file_get_size
- *
- * Get the file size.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: Size in bytes.
- *
- **/
-GnomeVFSFileSize
-nautilus_file_get_size (NautilusFile *file)
-{
- g_return_val_if_fail (file != NULL, 0);
-
- return file->info->size;
-}
-
-/**
- * nautilus_file_get_permissions_as_string:
- *
- * Get a user-displayable string representing a file's permissions. The caller
- * is responsible for g_free-ing this string.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: Newly allocated string ready to display to the user.
- *
- **/
-static char *
-nautilus_file_get_permissions_as_string (NautilusFile *file)
-{
- GnomeVFSFilePermissions permissions;
- gboolean is_directory;
- gboolean is_link;
-
- permissions = file->info->permissions;
- is_directory = nautilus_file_is_directory (file);
- is_link = GNOME_VFS_FILE_INFO_SYMLINK(file->info);
-
- return g_strdup_printf ("%c%c%c%c%c%c%c%c%c%c",
- is_link ? 'l' : is_directory ? 'd' : '-',
- permissions & GNOME_VFS_PERM_USER_READ ? 'r' : '-',
- permissions & GNOME_VFS_PERM_USER_WRITE ? 'w' : '-',
- permissions & GNOME_VFS_PERM_USER_EXEC ? 'x' : '-',
- permissions & GNOME_VFS_PERM_GROUP_READ ? 'r' : '-',
- permissions & GNOME_VFS_PERM_GROUP_WRITE ? 'w' : '-',
- permissions & GNOME_VFS_PERM_GROUP_EXEC ? 'x' : '-',
- permissions & GNOME_VFS_PERM_OTHER_READ ? 'r' : '-',
- permissions & GNOME_VFS_PERM_OTHER_WRITE ? 'w' : '-',
- permissions & GNOME_VFS_PERM_OTHER_EXEC ? 'x' : '-');
-}
-
-/**
- * nautilus_file_get_owner_as_string:
- *
- * Get a user-displayable string representing a file's owner. The caller
- * is responsible for g_free-ing this string.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: Newly allocated string ready to display to the user.
- *
- **/
-static char *
-nautilus_file_get_owner_as_string (NautilusFile *file)
-{
- struct passwd *password_info;
-
- /* FIXME: Can we trust the uid in the file info? Might
- * there be garbage there? What will it do for non-local files?
- */
- /* No need to free result of getpwuid */
- password_info = getpwuid (file->info->uid);
-
- g_print ("pointer to password info is %p\n", password_info);
-
- if (password_info == NULL)
- {
- return g_strdup (_("unknown owner"));
- }
-
- return g_strdup (password_info->pw_name);
-}
-
-/**
- * nautilus_file_get_group_as_string:
- *
- * Get a user-displayable string representing a file's group. The caller
- * is responsible for g_free-ing this string.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: Newly allocated string ready to display to the user.
- *
- **/
-static char *
-nautilus_file_get_group_as_string (NautilusFile *file)
-{
- struct group *group_info;
-
- /* FIXME: Can we trust the gid in the file info? Might
- * there be garbage there? What will it do for non-local files?
- */
- /* No need to free result of getgrgid */
- group_info = getgrgid (file->info->gid);
-
- if (group_info == NULL)
- {
- return g_strdup (_("unknown group"));
- }
-
- return g_strdup (group_info->gr_name);
-}
-
-
-/* This #include is part of the following hack, and should be removed with it */
-#include <dirent.h>
-
-static int
-get_directory_item_count_hack (NautilusFile *file, gboolean ignore_invisible_items)
-{
- /* Code borrowed from Gnomad and hacked into here for now */
-
- char * uri;
- char * path;
- DIR* directory;
- int count;
- struct dirent * entry;
-
- g_assert (nautilus_file_is_directory (file));
-
- uri = nautilus_file_get_uri (file);
- if (nautilus_has_prefix (uri, "file://"))
- path = uri + 7;
- else
- path = uri;
-
- directory = opendir (path);
-
- g_free (uri);
-
- if (!directory)
- return 0;
-
- count = 0;
-
- while ((entry = readdir(directory)) != NULL)
- // Only count invisible items if requested.
- if (!ignore_invisible_items || entry->d_name[0] != '.')
- count += 1;
-
- closedir(directory);
-
- /* This way of getting the count includes . and .., so we subtract those out */
- if (!ignore_invisible_items) {
- count -= 2;
- }
-
- return count;
-}
-
-/**
- * nautilus_file_get_size_as_string:
- *
- * Get a user-displayable string representing a file size. The caller
- * is responsible for g_free-ing this string. The string is an item
- * count for directories.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: Newly allocated string ready to display to the user.
- *
- **/
-static char *
-nautilus_file_get_size_as_string (NautilusFile *file)
-{
- g_return_val_if_fail (file != NULL, NULL);
-
- if (nautilus_file_is_directory (file))
- {
- /* FIXME: Since computing the item count is slow, we
- * want to do it in a deferred way. However, that
- * architecture doesn't exist yet, so we're hacking
- * it in for now.
- */
- int item_count;
-
- item_count = get_directory_item_count_hack (file, FALSE);
- if (item_count == 0) {
- return g_strdup (_("0 items"));
- } else if (item_count == 1) {
- return g_strdup (_("1 item"));
- } else {
- return g_strdup_printf (_("%d items"), item_count);
- }
- }
-
- return gnome_vfs_file_size_to_string (file->info->size);
-}
-
-/**
- * nautilus_file_get_string_attribute:
- *
- * Get a user-displayable string from a named attribute. Use g_free to
- * free this string.
- *
- * @file: NautilusFile representing the file in question.
- * @attribute_name: The name of the desired attribute. The currently supported
- * set includes "name", "type", "size", "date_modified", "date_changed",
- * "date_accessed", "owner", "group", "permissions".
- *
- * Returns: Newly allocated string ready to display to the user, or NULL
- * if @attribute_name is not supported.
- *
- **/
-char *
-nautilus_file_get_string_attribute (NautilusFile *file, const char *attribute_name)
-{
- /* FIXME: Use hash table and switch statement or function pointers for speed? */
-
- if (strcmp (attribute_name, "name") == 0) {
- return nautilus_file_get_name (file);
- }
-
- if (strcmp (attribute_name, "type") == 0) {
- return nautilus_file_get_type_as_string (file);
- }
-
- if (strcmp (attribute_name, "size") == 0) {
- return nautilus_file_get_size_as_string (file);
- }
-
- if (strcmp (attribute_name, "date_modified") == 0) {
- return nautilus_file_get_date_as_string (file,
- NAUTILUS_DATE_TYPE_MODIFIED);
- }
-
- if (strcmp (attribute_name, "date_changed") == 0) {
- return nautilus_file_get_date_as_string (file,
- NAUTILUS_DATE_TYPE_CHANGED);
- }
-
- if (strcmp (attribute_name, "date_accessed") == 0) {
- return nautilus_file_get_date_as_string (file,
- NAUTILUS_DATE_TYPE_ACCESSED);
- }
-
- if (strcmp (attribute_name, "permissions") == 0) {
- return nautilus_file_get_permissions_as_string (file);
- }
-
- if (strcmp (attribute_name, "owner") == 0) {
- return nautilus_file_get_owner_as_string (file);
- }
-
- if (strcmp (attribute_name, "group") == 0) {
- return nautilus_file_get_group_as_string (file);
- }
-
- return NULL;
-}
-
-/**
- * nautilus_file_get_type_as_string:
- *
- * Get a user-displayable string representing a file type. The caller
- * is responsible for g_free-ing this string.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: Newly allocated string ready to display to the user.
- *
- **/
-static char *
-nautilus_file_get_type_as_string (NautilusFile *file)
-{
- g_return_val_if_fail (file != NULL, NULL);
-
- if (nautilus_file_is_directory (file)) {
- /* Special-case this so it isn't "special/directory".
- * FIXME: Should this be "folder" instead?
- */
- return g_strdup (_("directory"));
- }
-
- if (nautilus_strlen (file->info->mime_type) == 0) {
- return g_strdup (_("unknown type"));
- }
-
- return g_strdup (file->info->mime_type);
-}
-
-/**
- * nautilus_file_get_type
- *
- * Return this file's type.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: The type.
- *
- **/
-GnomeVFSFileType
-nautilus_file_get_type (NautilusFile *file)
-{
- g_return_val_if_fail (file != NULL, FALSE);
-
- return file->info->type;
-}
-
-/**
- * nautilus_file_get_mime_type
- *
- * Return this file's mime type.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: The mime type.
- *
- **/
-const char *
-nautilus_file_get_mime_type (NautilusFile *file)
-{
- g_return_val_if_fail (file != NULL, FALSE);
-
- return file->info->mime_type;
-}
-
-/**
- * nautilus_file_get_keywords
- *
- * Return this file's keywords.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: A list of keywords.
- *
- **/
-GList *
-nautilus_file_get_keywords (NautilusFile *file)
-{
- GList *keywords;
- xmlNode *file_node, *child;
- xmlChar *property;
-
- g_return_val_if_fail (file != NULL, NULL);
-
- keywords = NULL;
-
- /* Put all the keywords into a list. */
- file_node = get_file_metadata_node (file->directory, file->info->name);
- if (file_node != NULL) {
- for (child = file_node->childs; child != NULL; child = child->next) {
- if (strcmp (child->name, "KEYWORD") == 0) {
- property = xmlGetProp (child, "NAME");
- if (property != NULL) {
- keywords = g_list_prepend (keywords,
- g_strdup (property));
- }
- }
- }
- }
-
- return g_list_reverse (keywords);
-}
-
-/**
- * nautilus_file_is_symbolic_link
- *
- * Check if this file is a symbolic link.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: True if the file is a symbolic link.
- *
- **/
-gboolean
-nautilus_file_is_symbolic_link (NautilusFile *file)
-{
- g_return_val_if_fail (file != NULL, FALSE);
-
- return GNOME_VFS_FILE_INFO_SYMLINK (file->info);
-}
-
-/**
- * nautilus_file_is_directory
- *
- * Check if this file is a directory.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: TRUE if @file is a directory.
- *
- **/
-gboolean
-nautilus_file_is_directory (NautilusFile *file)
-{
- g_return_val_if_fail (file != NULL, FALSE);
-
- return nautilus_file_get_type (file) == GNOME_VFS_FILE_TYPE_DIRECTORY;
-}
-
-/**
- * nautilus_file_is_executable
- *
- * Check if this file is executable at all.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: True if any of the execute bits are set.
- *
- **/
-gboolean
-nautilus_file_is_executable (NautilusFile *file)
-{
- g_return_val_if_fail (file != NULL, FALSE);
-
- return (file->info->flags & (GNOME_VFS_PERM_USER_EXEC
- | GNOME_VFS_PERM_GROUP_EXEC
- | GNOME_VFS_PERM_OTHER_EXEC)) != 0;
-}
-
-/**
- * nautilus_file_delete
- *
- * Delete this file.
- * @file: NautilusFile representing the file in question.
- **/
-void
-nautilus_file_delete (NautilusFile *file)
-{
- char *text_uri;
- GnomeVFSResult result;
- GList *removed_files;
-
- g_return_if_fail (file != NULL);
-
- /* Deleting a file that's already gone is easy. */
- if (file->is_gone) {
- return;
- }
-
- /* Do the actual deletion. */
- text_uri = nautilus_file_get_uri (file);
- if (nautilus_file_is_directory (file)) {
- result = gnome_vfs_remove_directory (text_uri);
- } else {
- result = gnome_vfs_unlink (text_uri);
- }
- g_free (text_uri);
-
- /* Mark the file gone. */
- if (result == GNOME_VFS_OK || result == GNOME_VFS_ERROR_NOTFOUND) {
- file->is_gone = TRUE;
-
- /* Let the directory know it's gone. */
- if (file->directory != NULL) {
- g_list_remove (file->directory->details->files, file);
-
- /* Send out a message. */
- removed_files = g_list_prepend (NULL, file);
- gtk_signal_emit (GTK_OBJECT (file->directory),
- nautilus_directory_signals[FILES_REMOVED],
- removed_files);
- g_list_free (removed_files);
- }
- }
-}
-
-/**
- * nautilus_file_is_gone
- *
- * Check if a file has already been deleted.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: TRUE if the file is already gone.
- **/
-gboolean
-nautilus_file_is_gone (NautilusFile *file)
-{
- g_return_val_if_fail (file != NULL, FALSE);
-
- return file->is_gone;
-}
-
-/**
- * nautilus_file_list_ref
- *
- * Ref all the files in a list.
- * @file_list: GList of files.
- **/
-void
-nautilus_file_list_ref (GList *file_list)
-{
- g_list_foreach (file_list, (GFunc) nautilus_file_ref, NULL);
-}
-
-/**
- * nautilus_file_list_unref
- *
- * Unref all the files in a list.
- * @file_list: GList of files.
- **/
-void
-nautilus_file_list_unref (GList *file_list)
-{
- g_list_foreach (file_list, (GFunc) nautilus_file_ref, NULL);
-}
-
-/**
- * nautilus_file_list_free
- *
- * Free a list of files after unrefing them.
- * @file_list: GList of files.
- **/
-void
-nautilus_file_list_free (GList *file_list)
-{
- nautilus_file_list_unref (file_list);
- g_list_free (file_list);
+ gtk_signal_emit (GTK_OBJECT (directory),
+ nautilus_directory_signals[FILES_REMOVED],
+ removed_files);
}
#if !defined (NAUTILUS_OMIT_SELF_CHECK)
diff --git a/libnautilus-extensions/nautilus-directory.h b/libnautilus-extensions/nautilus-directory.h
index 35058f26b..42ea0451b 100644
--- a/libnautilus-extensions/nautilus-directory.h
+++ b/libnautilus-extensions/nautilus-directory.h
@@ -26,7 +26,6 @@
#define NAUTILUS_DIRECTORY_H
#include <gtk/gtkobject.h>
-#include <libgnomevfs/gnome-vfs-types.h>
/* NautilusDirectory is a class that manages the model for a directory,
real or virtual, for Nautilus, mainly the file-manager component. The directory is
@@ -57,21 +56,6 @@ typedef struct NautilusDirectoryClass NautilusDirectoryClass;
#define NAUTILUS_IS_DIRECTORY_CLASS(klass) \
(GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_DIRECTORY))
-#define NAUTILUS_IS_FILE(object) \
- ((object) != NULL)
-
-typedef enum {
- NAUTILUS_FILE_SORT_NONE,
- NAUTILUS_FILE_SORT_BY_NAME,
- NAUTILUS_FILE_SORT_BY_SIZE,
- NAUTILUS_FILE_SORT_BY_TYPE,
- NAUTILUS_FILE_SORT_BY_MTIME
-} NautilusFileSortType;
-
-typedef struct NautilusFile NautilusFile;
-
-#define NAUTILUS_FILE(file) ((NautilusFile *)(file))
-
typedef void (*NautilusFileListCallback) (NautilusDirectory *directory,
GList *files,
gpointer callback_data);
@@ -124,61 +108,6 @@ void nautilus_directory_stop_monitoring (NautilusDirectory
*/
gboolean nautilus_directory_are_all_files_seen (NautilusDirectory *directory);
-/* Getting at a single file. */
-NautilusFile * nautilus_file_get (const char *uri);
-
-/* Basic operations on file objects. */
-void nautilus_file_ref (NautilusFile *file);
-void nautilus_file_unref (NautilusFile *file);
-void nautilus_file_delete (NautilusFile *file);
-
-/* Basic attributes for file objects. */
-char * nautilus_file_get_name (NautilusFile *file);
-char * nautilus_file_get_uri (NautilusFile *file);
-GnomeVFSFileSize nautilus_file_get_size (NautilusFile *file);
-GnomeVFSFileType nautilus_file_get_type (NautilusFile *file);
-const char * nautilus_file_get_mime_type (NautilusFile *file);
-gboolean nautilus_file_is_symbolic_link (NautilusFile *file);
-gboolean nautilus_file_is_executable (NautilusFile *file);
-gboolean nautilus_file_is_directory (NautilusFile *file);
-guint nautilus_file_get_directory_item_count (NautilusFile *file,
- gboolean ignore_invisible_items);
-GList * nautilus_file_get_keywords (NautilusFile *file);
-void nautilus_file_set_keywords (NautilusFile *file,
- GList *keywords);
-
-/* Simple getting and setting top-level metadata. */
-char * nautilus_file_get_metadata (NautilusFile *file,
- const char *tag,
- const char *default_metadata);
-void nautilus_file_set_metadata (NautilusFile *file,
- const char *tag,
- const char *default_metadata,
- const char *metadata);
-
-/* Attributes for file objects as user-displayable strings. */
-char * nautilus_file_get_string_attribute (NautilusFile *file,
- const char *attribute_name);
-
-/* Comparing two file objects for sorting */
-int nautilus_file_compare_for_sort (NautilusFile *file_1,
- NautilusFile *file_2,
- NautilusFileSortType sort_type);
-int nautilus_file_compare_for_sort_reversed (NautilusFile *file_1,
- NautilusFile *file_2,
- NautilusFileSortType sort_type);
-
-/* Convenience functions for dealing with a list of NautilusFile objects that each have a ref. */
-void nautilus_file_list_ref (GList *file_list);
-void nautilus_file_list_unref (GList *file_list);
-void nautilus_file_list_free (GList *file_list);
-
-/* Return true if this file has already been deleted.
- This object will be unref'd after sending the files_removed signal,
- but it could hang around longer if someone ref'd it.
-*/
-gboolean nautilus_file_is_gone (NautilusFile *file);
-
typedef struct NautilusDirectoryDetails NautilusDirectoryDetails;
struct NautilusDirectory
@@ -201,10 +130,10 @@ struct NautilusDirectoryClass
this is the last chance to forget about these file objects
which are about to be unref'd.
*/
- void (* files_added) (NautilusDirectory *directory,
- GList *added_files);
- void (* files_removed) (NautilusDirectory *directory,
- GList *removed_files);
+ void (* files_added) (NautilusDirectory *directory,
+ GList *added_files);
+ void (* files_removed) (NautilusDirectory *directory,
+ GList *removed_files);
/* The files_changed signal is emitted as changes occur to
existing files that are noticed by the synchronization framework.
diff --git a/libnautilus-extensions/nautilus-file-private.h b/libnautilus-extensions/nautilus-file-private.h
new file mode 100644
index 000000000..7ee311c9b
--- /dev/null
+++ b/libnautilus-extensions/nautilus-file-private.h
@@ -0,0 +1,37 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+
+ nautilus-directory.c: Nautilus directory model.
+
+ Copyright (C) 1999, 2000 Eazel, Inc.
+
+ 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 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 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 Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Darin Adler <darin@eazel.com>
+*/
+
+#include "nautilus-file.h"
+#include "nautilus-directory.h"
+
+struct NautilusFile
+{
+ guint ref_count;
+
+ NautilusDirectory *directory;
+ GnomeVFSFileInfo *info;
+ gboolean is_gone;
+};
+
+void nautilus_file_free (NautilusFile *);
diff --git a/libnautilus-extensions/nautilus-file.c b/libnautilus-extensions/nautilus-file.c
new file mode 100644
index 000000000..56efacead
--- /dev/null
+++ b/libnautilus-extensions/nautilus-file.c
@@ -0,0 +1,1014 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+
+ nautilus-file.c: Nautilus file model.
+
+ Copyright (C) 1999, 2000 Eazel, Inc.
+
+ 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 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 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 Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Darin Adler <darin@eazel.com>
+*/
+
+#include <config.h>
+#include "nautilus-file-private.h"
+
+#include <grp.h>
+#include <pwd.h>
+
+#include <libgnome/gnome-defs.h>
+#include <libgnome/gnome-i18n.h>
+
+#include "nautilus-glib-extensions.h"
+#include "nautilus-string.h"
+#include "nautilus-directory-private.h"
+
+typedef enum {
+ NAUTILUS_DATE_TYPE_MODIFIED,
+ NAUTILUS_DATE_TYPE_CHANGED,
+ NAUTILUS_DATE_TYPE_ACCESSED
+} NautilusDateType;
+
+/* FIXME: This hack needs to die eventually. See comments with function */
+static int get_directory_item_count_hack (NautilusFile *file,
+ gboolean ignore_invisible_items);
+
+static int nautilus_file_compare_by_type (NautilusFile *file_1,
+ NautilusFile *file_2);
+static int nautilus_file_compare_for_sort_internal (NautilusFile *file_1,
+ NautilusFile *file_2,
+ NautilusFileSortType sort_type,
+ gboolean reversed);
+static char *nautilus_file_get_date_as_string (NautilusFile *file,
+ NautilusDateType date_type);
+static char *nautilus_file_get_owner_as_string (NautilusFile *file);
+static char *nautilus_file_get_group_as_string (NautilusFile *file);
+static char *nautilus_file_get_permissions_as_string (NautilusFile *file);
+static char *nautilus_file_get_size_as_string (NautilusFile *file);
+static char *nautilus_file_get_type_as_string (NautilusFile *file);
+
+/**
+ * nautilus_file_get:
+ * @uri: URI of file to get.
+ *
+ * Get a file given a uri.
+ * Returns a referenced object. Unref when finished.
+ * If two windows are viewing the same uri, the file object is shared.
+ */
+NautilusFile *
+nautilus_file_get (const char *uri)
+{
+ GnomeVFSResult result;
+ GnomeVFSFileInfo *file_info;
+ GnomeVFSURI *vfs_uri, *directory_vfs_uri;
+ char *directory_uri;
+ NautilusDirectory *directory;
+ NautilusFile *file;
+
+ /* Get info on the file. */
+ file_info = gnome_vfs_file_info_new ();
+ result = gnome_vfs_get_file_info (uri, file_info,
+ GNOME_VFS_FILE_INFO_GETMIMETYPE
+ | GNOME_VFS_FILE_INFO_FASTMIMETYPE
+ | GNOME_VFS_FILE_INFO_FOLLOWLINKS, NULL);
+ if (result != GNOME_VFS_OK)
+ return NULL;
+
+ /* Make VFS version of URI. */
+ vfs_uri = gnome_vfs_uri_new (uri);
+ if (vfs_uri == NULL)
+ return NULL;
+
+ /* Make VFS version of directory URI. */
+ directory_vfs_uri = gnome_vfs_uri_get_parent (vfs_uri);
+ gnome_vfs_uri_unref (vfs_uri);
+ if (directory_vfs_uri == NULL)
+ return NULL;
+
+ /* Make text version of directory URI. */
+ directory_uri = gnome_vfs_uri_to_string (directory_vfs_uri,
+ GNOME_VFS_URI_HIDE_NONE);
+ gnome_vfs_uri_unref (directory_vfs_uri);
+
+ /* Get object that represents the directory. */
+ directory = nautilus_directory_get (directory_uri);
+ g_free (directory_uri);
+ if (directory == NULL)
+ return NULL;
+
+ file = nautilus_directory_new_file (directory, file_info);
+
+ gnome_vfs_file_info_unref (file_info);
+ nautilus_file_ref (file);
+ gtk_object_unref (GTK_OBJECT (directory));
+
+ return file;
+}
+
+void
+nautilus_file_ref (NautilusFile *file)
+{
+ g_return_if_fail (file != NULL);
+
+ g_assert (file->ref_count < G_MAXINT);
+ g_assert (file->directory != NULL);
+
+ /* Increment the ref count. */
+ if (file->ref_count++ != 0) {
+ return;
+ }
+
+ /* As soon as someone other than the directory holds a ref,
+ * we need to hold the directory too. */
+ gtk_object_ref (GTK_OBJECT (file->directory));
+}
+
+void
+nautilus_file_unref (NautilusFile *file)
+{
+ g_return_if_fail (file != NULL);
+
+ g_assert (file->ref_count != 0);
+ g_assert (file->directory != NULL);
+
+ /* Decrement the ref count. */
+ if (--file->ref_count != 0) {
+ return;
+ }
+
+ /* No references left, so it's time to release our hold on the directory. */
+ gtk_object_unref (GTK_OBJECT (file->directory));
+ if (file->is_gone) {
+ nautilus_file_free (file);
+ }
+}
+
+void
+nautilus_file_free (NautilusFile *file)
+{
+ g_assert (file->ref_count == 0);
+
+ /* Destroy the file object. */
+ gnome_vfs_file_info_unref (file->info);
+ g_free (file);
+}
+
+static int
+nautilus_file_compare_by_size_with_directories (NautilusFile *file_1, NautilusFile *file_2)
+{
+ gboolean is_directory_1;
+ gboolean is_directory_2;
+ int item_count_1;
+ int item_count_2;
+
+ is_directory_1 = nautilus_file_is_directory (file_1);
+ is_directory_2 = nautilus_file_is_directory (file_2);
+
+ if (is_directory_1 && !is_directory_2)
+ return -1;
+
+ if (is_directory_2 && !is_directory_1)
+ return +1;
+
+ if (!is_directory_1 && !is_directory_2)
+ return 0;
+
+ /* Both are directories, compare by item count. */
+ /* FIXME: get_directory_item_count_hack is slow, and calling
+ * it for every pairwise comparison here is nasty. Need to
+ * change this to (not-yet-existent) architecture where the
+ * item count can be calculated once in a deferred way, and
+ * then stored or cached.
+ */
+ item_count_1 = get_directory_item_count_hack (file_1, FALSE);
+ item_count_2 = get_directory_item_count_hack (file_2, FALSE);
+
+ if (item_count_1 < item_count_2)
+ return -1;
+
+ if (item_count_2 < item_count_1)
+ return +1;
+
+ return 0;
+}
+
+static int
+nautilus_file_compare_by_type (NautilusFile *file_1, NautilusFile *file_2)
+{
+ gboolean is_directory_1;
+ gboolean is_directory_2;
+ char * type_string_1;
+ char * type_string_2;
+ int result;
+
+ /* Directories go first. Then, if mime types are identical,
+ * don't bother getting strings (for speed). This assumes
+ * that the string is dependent entirely on the mime type,
+ * which is true now but might not be later.
+ */
+ is_directory_1 = nautilus_file_is_directory (file_1);
+ is_directory_2 = nautilus_file_is_directory (file_2);
+
+ if (is_directory_1 && is_directory_2)
+ return 0;
+
+ if (is_directory_1)
+ return -1;
+
+ if (is_directory_2)
+ return +1;
+
+ if (nautilus_strcmp (file_1->info->mime_type, file_2->info->mime_type) == 0)
+ return 0;
+
+ type_string_1 = nautilus_file_get_type_as_string (file_1);
+ type_string_2 = nautilus_file_get_type_as_string (file_2);
+
+ result = nautilus_strcmp (type_string_1, type_string_2);
+
+ g_free (type_string_1);
+ g_free (type_string_2);
+
+ return result;
+}
+
+static int
+nautilus_file_compare_for_sort_internal (NautilusFile *file_1,
+ NautilusFile *file_2,
+ NautilusFileSortType sort_type,
+ gboolean reversed)
+{
+ GnomeVFSDirectorySortRule rules[3];
+ int compare;
+
+ g_return_val_if_fail (file_1 != NULL, 0);
+ g_return_val_if_fail (file_2 != NULL, 0);
+ g_return_val_if_fail (sort_type != NAUTILUS_FILE_SORT_NONE, 0);
+
+ switch (sort_type) {
+ case NAUTILUS_FILE_SORT_BY_NAME:
+ /* Note: This used to put directories first. I
+ * thought that was counterintuitive and removed it,
+ * but I can imagine discussing this further.
+ * John Sullivan <sullivan@eazel.com>
+ */
+ rules[0] = GNOME_VFS_DIRECTORY_SORT_BYNAME_IGNORECASE;
+ rules[1] = GNOME_VFS_DIRECTORY_SORT_NONE;
+ break;
+ case NAUTILUS_FILE_SORT_BY_SIZE:
+ /* Compare directory sizes ourselves, then if necessary
+ * use GnomeVFS to compare file sizes.
+ */
+ compare = nautilus_file_compare_by_size_with_directories (file_1, file_2);
+ if (compare != 0) {
+ return compare;
+ }
+ rules[0] = GNOME_VFS_DIRECTORY_SORT_BYSIZE;
+ rules[1] = GNOME_VFS_DIRECTORY_SORT_BYNAME_IGNORECASE;
+ rules[2] = GNOME_VFS_DIRECTORY_SORT_NONE;
+ break;
+ case NAUTILUS_FILE_SORT_BY_TYPE:
+ /* GnomeVFS doesn't know about our special text for certain
+ * mime types, so we handle the mime-type sorting ourselves.
+ */
+ compare = nautilus_file_compare_by_type (file_1, file_2);
+ if (compare != 0) {
+ return compare;
+ }
+ rules[0] = GNOME_VFS_DIRECTORY_SORT_BYNAME_IGNORECASE;
+ rules[1] = GNOME_VFS_DIRECTORY_SORT_NONE;
+ break;
+ case NAUTILUS_FILE_SORT_BY_MTIME:
+ rules[0] = GNOME_VFS_DIRECTORY_SORT_BYMTIME;
+ rules[1] = GNOME_VFS_DIRECTORY_SORT_BYNAME_IGNORECASE;
+ rules[2] = GNOME_VFS_DIRECTORY_SORT_NONE;
+ break;
+ default:
+ g_assert_not_reached ();
+ return 0;
+ }
+
+ if (reversed)
+ return gnome_vfs_file_info_compare_for_sort_reversed (file_1->info,
+ file_2->info,
+ rules);
+ else
+ return gnome_vfs_file_info_compare_for_sort (file_1->info,
+ file_2->info,
+ rules);
+}
+
+/**
+ * nautilus_file_compare_for_sort:
+ * @file_1: A file object
+ * @file_2: Another file object
+ * @sort_type: Sort criterion
+ *
+ * Return value: int < 0 if @file_1 should come before file_2 in a smallest-to-largest
+ * sorted list; int > 0 if @file_2 should come before file_1 in a smallest-to-largest
+ * sorted list; 0 if @file_1 and @file_2 are equal for this sort criterion. Note
+ * that each named sort type may actually break ties several ways, with the name
+ * of the sort criterion being the primary but not only differentiator.
+ **/
+int
+nautilus_file_compare_for_sort (NautilusFile *file_1,
+ NautilusFile *file_2,
+ NautilusFileSortType sort_type)
+{
+ return nautilus_file_compare_for_sort_internal (file_1, file_2, sort_type, FALSE);
+}
+
+/**
+ * nautilus_file_compare_for_sort_reversed:
+ * @file_1: A file object
+ * @file_2: Another file object
+ * @sort_type: Sort criterion
+ *
+ * Return value: The opposite of nautilus_file_compare_for_sort: int > 0 if @file_1
+ * should come before file_2 in a smallest-to-largest sorted list; int < 0 if @file_2
+ * should come before file_1 in a smallest-to-largest sorted list; 0 if @file_1
+ * and @file_2 are equal for this sort criterion. Note that each named sort type
+ * may actually break ties several ways, with the name of the sort criterion
+ * being the primary but not only differentiator.
+ **/
+int
+nautilus_file_compare_for_sort_reversed (NautilusFile *file_1,
+ NautilusFile *file_2,
+ NautilusFileSortType sort_type)
+{
+ return nautilus_file_compare_for_sort_internal (file_1, file_2, sort_type, TRUE);
+}
+
+char *
+nautilus_file_get_metadata (NautilusFile *file,
+ const char *tag,
+ const char *default_metadata)
+{
+ g_return_val_if_fail (file != NULL, NULL);
+
+ return nautilus_directory_get_file_metadata (file->directory,
+ file->info->name,
+ tag,
+ default_metadata);
+}
+
+void
+nautilus_file_set_metadata (NautilusFile *file,
+ const char *tag,
+ const char *default_metadata,
+ const char *metadata)
+{
+ g_return_if_fail (file != NULL);
+
+ nautilus_directory_set_file_metadata (file->directory,
+ file->info->name,
+ tag,
+ default_metadata,
+ metadata);
+}
+
+char *
+nautilus_file_get_name (NautilusFile *file)
+{
+ g_return_val_if_fail (file != NULL, NULL);
+
+ g_assert (file->directory == NULL || NAUTILUS_IS_DIRECTORY (file->directory));
+ g_assert (file->info->name != NULL);
+ g_assert (file->info->name[0] != '\0');
+
+ return g_strdup (file->info->name);
+}
+
+char *
+nautilus_file_get_uri (NautilusFile *file)
+{
+ GnomeVFSURI *uri;
+ char *uri_text;
+
+ g_return_val_if_fail (file != NULL, NULL);
+ g_return_val_if_fail (file->directory != NULL, NULL);
+
+ uri = gnome_vfs_uri_append_path (file->directory->details->uri, file->info->name);
+ uri_text = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE);
+ gnome_vfs_uri_unref (uri);
+ return uri_text;
+}
+
+/**
+ * nautilus_file_get_date_as_string:
+ *
+ * Get a user-displayable string representing a file modification date.
+ * The caller is responsible for g_free-ing this string.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: Newly allocated string ready to display to the user.
+ *
+ **/
+static char *
+nautilus_file_get_date_as_string (NautilusFile *file, NautilusDateType date_type)
+{
+ struct tm *file_time;
+ const char *format;
+ GDate *today;
+ GDate *file_date;
+ guint32 file_date_age;
+
+ g_return_val_if_fail (file != NULL, NULL);
+
+ switch (date_type)
+ {
+ case NAUTILUS_DATE_TYPE_CHANGED:
+ file_time = localtime(&file->info->ctime);
+ break;
+ case NAUTILUS_DATE_TYPE_ACCESSED:
+ file_time = localtime(&file->info->atime);
+ break;
+ case NAUTILUS_DATE_TYPE_MODIFIED:
+ file_time = localtime(&file->info->mtime);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ file_date = nautilus_g_date_new_tm (file_time);
+
+ today = g_date_new ();
+ g_date_set_time (today, time (NULL));
+
+ /* Overflow results in a large number; fine for our purposes. */
+ file_date_age = g_date_julian (today) - g_date_julian (file_date);
+
+ g_date_free (file_date);
+ g_date_free (today);
+
+ /* Format varies depending on how old the date is. This minimizes
+ * the length (and thus clutter & complication) of typical dates
+ * while providing sufficient detail for recent dates to make
+ * them maximally understandable at a glance. Keep all format
+ * strings separate rather than combining bits & pieces for
+ * internationalization's sake.
+ */
+
+ if (file_date_age == 0)
+ {
+ /* today, use special word */
+ format = _("today %-I:%M %p");
+ }
+ else if (file_date_age == 1)
+ {
+ /* yesterday, use special word */
+ format = _("yesterday %-I:%M %p");
+ }
+ else if (file_date_age < 7)
+ {
+ /* current week, include day of week */
+ format = _("%A %-m/%-d/%y %-I:%M %p");
+ }
+ else
+ {
+ format = _("%-m/%-d/%y %-I:%M %p");
+ }
+
+ return nautilus_strdup_strftime (format, file_time);
+}
+
+/**
+ * nautilus_file_get_directory_item_count
+ *
+ * Get the number of items in a directory.
+ * @file: NautilusFile representing a directory. It is an error to
+ * call this function on a file that is not a directory.
+ * @ignore_invisible_items: TRUE if invisible items should not be
+ * included in count.
+ *
+ * Returns: item count for this directory.
+ *
+ **/
+guint
+nautilus_file_get_directory_item_count (NautilusFile *file,
+ gboolean ignore_invisible_items)
+{
+ g_return_val_if_fail (nautilus_file_is_directory (file), 0);
+
+ return get_directory_item_count_hack (file, ignore_invisible_items);
+}
+
+/**
+ * nautilus_file_get_size
+ *
+ * Get the file size.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: Size in bytes.
+ *
+ **/
+GnomeVFSFileSize
+nautilus_file_get_size (NautilusFile *file)
+{
+ g_return_val_if_fail (file != NULL, 0);
+
+ return file->info->size;
+}
+
+/**
+ * nautilus_file_get_permissions_as_string:
+ *
+ * Get a user-displayable string representing a file's permissions. The caller
+ * is responsible for g_free-ing this string.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: Newly allocated string ready to display to the user.
+ *
+ **/
+static char *
+nautilus_file_get_permissions_as_string (NautilusFile *file)
+{
+ GnomeVFSFilePermissions permissions;
+ gboolean is_directory;
+ gboolean is_link;
+
+ permissions = file->info->permissions;
+ is_directory = nautilus_file_is_directory (file);
+ is_link = GNOME_VFS_FILE_INFO_SYMLINK(file->info);
+
+ return g_strdup_printf ("%c%c%c%c%c%c%c%c%c%c",
+ is_link ? 'l' : is_directory ? 'd' : '-',
+ permissions & GNOME_VFS_PERM_USER_READ ? 'r' : '-',
+ permissions & GNOME_VFS_PERM_USER_WRITE ? 'w' : '-',
+ permissions & GNOME_VFS_PERM_USER_EXEC ? 'x' : '-',
+ permissions & GNOME_VFS_PERM_GROUP_READ ? 'r' : '-',
+ permissions & GNOME_VFS_PERM_GROUP_WRITE ? 'w' : '-',
+ permissions & GNOME_VFS_PERM_GROUP_EXEC ? 'x' : '-',
+ permissions & GNOME_VFS_PERM_OTHER_READ ? 'r' : '-',
+ permissions & GNOME_VFS_PERM_OTHER_WRITE ? 'w' : '-',
+ permissions & GNOME_VFS_PERM_OTHER_EXEC ? 'x' : '-');
+}
+
+/**
+ * nautilus_file_get_owner_as_string:
+ *
+ * Get a user-displayable string representing a file's owner. The caller
+ * is responsible for g_free-ing this string.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: Newly allocated string ready to display to the user.
+ *
+ **/
+static char *
+nautilus_file_get_owner_as_string (NautilusFile *file)
+{
+ struct passwd *password_info;
+
+ /* FIXME: Can we trust the uid in the file info? Might
+ * there be garbage there? What will it do for non-local files?
+ */
+ /* No need to free result of getpwuid */
+ password_info = getpwuid (file->info->uid);
+
+ g_print ("pointer to password info is %p\n", password_info);
+
+ if (password_info == NULL)
+ {
+ return g_strdup (_("unknown owner"));
+ }
+
+ return g_strdup (password_info->pw_name);
+}
+
+/**
+ * nautilus_file_get_group_as_string:
+ *
+ * Get a user-displayable string representing a file's group. The caller
+ * is responsible for g_free-ing this string.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: Newly allocated string ready to display to the user.
+ *
+ **/
+static char *
+nautilus_file_get_group_as_string (NautilusFile *file)
+{
+ struct group *group_info;
+
+ /* FIXME: Can we trust the gid in the file info? Might
+ * there be garbage there? What will it do for non-local files?
+ */
+ /* No need to free result of getgrgid */
+ group_info = getgrgid (file->info->gid);
+
+ if (group_info == NULL)
+ {
+ return g_strdup (_("unknown group"));
+ }
+
+ return g_strdup (group_info->gr_name);
+}
+
+
+/* This #include is part of the following hack, and should be removed with it */
+#include <dirent.h>
+
+static int
+get_directory_item_count_hack (NautilusFile *file, gboolean ignore_invisible_items)
+{
+ /* Code borrowed from Gnomad and hacked into here for now */
+
+ char * uri;
+ char * path;
+ DIR* directory;
+ int count;
+ struct dirent * entry;
+
+ g_assert (nautilus_file_is_directory (file));
+
+ uri = nautilus_file_get_uri (file);
+ if (nautilus_has_prefix (uri, "file://"))
+ path = uri + 7;
+ else
+ path = uri;
+
+ directory = opendir (path);
+
+ g_free (uri);
+
+ if (!directory)
+ return 0;
+
+ count = 0;
+
+ while ((entry = readdir(directory)) != NULL)
+ // Only count invisible items if requested.
+ if (!ignore_invisible_items || entry->d_name[0] != '.')
+ count += 1;
+
+ closedir(directory);
+
+ /* This way of getting the count includes . and .., so we subtract those out */
+ if (!ignore_invisible_items) {
+ count -= 2;
+ }
+
+ return count;
+}
+
+/**
+ * nautilus_file_get_size_as_string:
+ *
+ * Get a user-displayable string representing a file size. The caller
+ * is responsible for g_free-ing this string. The string is an item
+ * count for directories.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: Newly allocated string ready to display to the user.
+ *
+ **/
+static char *
+nautilus_file_get_size_as_string (NautilusFile *file)
+{
+ g_return_val_if_fail (file != NULL, NULL);
+
+ if (nautilus_file_is_directory (file))
+ {
+ /* FIXME: Since computing the item count is slow, we
+ * want to do it in a deferred way. However, that
+ * architecture doesn't exist yet, so we're hacking
+ * it in for now.
+ */
+ int item_count;
+
+ item_count = get_directory_item_count_hack (file, FALSE);
+ if (item_count == 0) {
+ return g_strdup (_("0 items"));
+ } else if (item_count == 1) {
+ return g_strdup (_("1 item"));
+ } else {
+ return g_strdup_printf (_("%d items"), item_count);
+ }
+ }
+
+ return gnome_vfs_file_size_to_string (file->info->size);
+}
+
+/**
+ * nautilus_file_get_string_attribute:
+ *
+ * Get a user-displayable string from a named attribute. Use g_free to
+ * free this string.
+ *
+ * @file: NautilusFile representing the file in question.
+ * @attribute_name: The name of the desired attribute. The currently supported
+ * set includes "name", "type", "size", "date_modified", "date_changed",
+ * "date_accessed", "owner", "group", "permissions".
+ *
+ * Returns: Newly allocated string ready to display to the user, or NULL
+ * if @attribute_name is not supported.
+ *
+ **/
+char *
+nautilus_file_get_string_attribute (NautilusFile *file, const char *attribute_name)
+{
+ /* FIXME: Use hash table and switch statement or function pointers for speed? */
+
+ if (strcmp (attribute_name, "name") == 0) {
+ return nautilus_file_get_name (file);
+ }
+
+ if (strcmp (attribute_name, "type") == 0) {
+ return nautilus_file_get_type_as_string (file);
+ }
+
+ if (strcmp (attribute_name, "size") == 0) {
+ return nautilus_file_get_size_as_string (file);
+ }
+
+ if (strcmp (attribute_name, "date_modified") == 0) {
+ return nautilus_file_get_date_as_string (file,
+ NAUTILUS_DATE_TYPE_MODIFIED);
+ }
+
+ if (strcmp (attribute_name, "date_changed") == 0) {
+ return nautilus_file_get_date_as_string (file,
+ NAUTILUS_DATE_TYPE_CHANGED);
+ }
+
+ if (strcmp (attribute_name, "date_accessed") == 0) {
+ return nautilus_file_get_date_as_string (file,
+ NAUTILUS_DATE_TYPE_ACCESSED);
+ }
+
+ if (strcmp (attribute_name, "permissions") == 0) {
+ return nautilus_file_get_permissions_as_string (file);
+ }
+
+ if (strcmp (attribute_name, "owner") == 0) {
+ return nautilus_file_get_owner_as_string (file);
+ }
+
+ if (strcmp (attribute_name, "group") == 0) {
+ return nautilus_file_get_group_as_string (file);
+ }
+
+ return NULL;
+}
+
+/**
+ * nautilus_file_get_type_as_string:
+ *
+ * Get a user-displayable string representing a file type. The caller
+ * is responsible for g_free-ing this string.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: Newly allocated string ready to display to the user.
+ *
+ **/
+static char *
+nautilus_file_get_type_as_string (NautilusFile *file)
+{
+ g_return_val_if_fail (file != NULL, NULL);
+
+ if (nautilus_file_is_directory (file)) {
+ /* Special-case this so it isn't "special/directory".
+ * FIXME: Should this be "folder" instead?
+ */
+ return g_strdup (_("directory"));
+ }
+
+ if (nautilus_strlen (file->info->mime_type) == 0) {
+ return g_strdup (_("unknown type"));
+ }
+
+ return g_strdup (file->info->mime_type);
+}
+
+/**
+ * nautilus_file_get_type
+ *
+ * Return this file's type.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: The type.
+ *
+ **/
+GnomeVFSFileType
+nautilus_file_get_type (NautilusFile *file)
+{
+ g_return_val_if_fail (file != NULL, FALSE);
+
+ return file->info->type;
+}
+
+/**
+ * nautilus_file_get_mime_type
+ *
+ * Return this file's mime type.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: The mime type.
+ *
+ **/
+const char *
+nautilus_file_get_mime_type (NautilusFile *file)
+{
+ g_return_val_if_fail (file != NULL, FALSE);
+
+ return file->info->mime_type;
+}
+
+/**
+ * nautilus_file_get_keywords
+ *
+ * Return this file's keywords.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: A list of keywords.
+ *
+ **/
+GList *
+nautilus_file_get_keywords (NautilusFile *file)
+{
+ GList *keywords;
+ xmlNode *file_node, *child;
+ xmlChar *property;
+
+ g_return_val_if_fail (file != NULL, NULL);
+
+ keywords = NULL;
+
+ /* Put all the keywords into a list. */
+ file_node = nautilus_directory_get_file_metadata_node (file->directory, file->info->name);
+ if (file_node != NULL) {
+ for (child = file_node->childs; child != NULL; child = child->next) {
+ if (strcmp (child->name, "KEYWORD") == 0) {
+ property = xmlGetProp (child, "NAME");
+ if (property != NULL) {
+ keywords = g_list_prepend (keywords,
+ g_strdup (property));
+ }
+ }
+ }
+ }
+
+ return g_list_reverse (keywords);
+}
+
+/**
+ * nautilus_file_is_symbolic_link
+ *
+ * Check if this file is a symbolic link.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: True if the file is a symbolic link.
+ *
+ **/
+gboolean
+nautilus_file_is_symbolic_link (NautilusFile *file)
+{
+ g_return_val_if_fail (file != NULL, FALSE);
+
+ return GNOME_VFS_FILE_INFO_SYMLINK (file->info);
+}
+
+/**
+ * nautilus_file_is_directory
+ *
+ * Check if this file is a directory.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: TRUE if @file is a directory.
+ *
+ **/
+gboolean
+nautilus_file_is_directory (NautilusFile *file)
+{
+ g_return_val_if_fail (file != NULL, FALSE);
+
+ return nautilus_file_get_type (file) == GNOME_VFS_FILE_TYPE_DIRECTORY;
+}
+
+/**
+ * nautilus_file_is_executable
+ *
+ * Check if this file is executable at all.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: True if any of the execute bits are set.
+ *
+ **/
+gboolean
+nautilus_file_is_executable (NautilusFile *file)
+{
+ g_return_val_if_fail (file != NULL, FALSE);
+
+ return (file->info->flags & (GNOME_VFS_PERM_USER_EXEC
+ | GNOME_VFS_PERM_GROUP_EXEC
+ | GNOME_VFS_PERM_OTHER_EXEC)) != 0;
+}
+
+/**
+ * nautilus_file_delete
+ *
+ * Delete this file.
+ * @file: NautilusFile representing the file in question.
+ **/
+void
+nautilus_file_delete (NautilusFile *file)
+{
+ char *text_uri;
+ GnomeVFSResult result;
+ GList *removed_files;
+
+ g_return_if_fail (file != NULL);
+
+ /* Deleting a file that's already gone is easy. */
+ if (file->is_gone) {
+ return;
+ }
+
+ /* Do the actual deletion. */
+ text_uri = nautilus_file_get_uri (file);
+ if (nautilus_file_is_directory (file)) {
+ result = gnome_vfs_remove_directory (text_uri);
+ } else {
+ result = gnome_vfs_unlink (text_uri);
+ }
+ g_free (text_uri);
+
+ /* Mark the file gone. */
+ if (result == GNOME_VFS_OK || result == GNOME_VFS_ERROR_NOTFOUND) {
+ file->is_gone = TRUE;
+
+ /* Let the directory know it's gone. */
+ if (file->directory != NULL) {
+ g_list_remove (file->directory->details->files, file);
+
+ /* Send out a signal. */
+ removed_files = g_list_prepend (NULL, file);
+ nautilus_directory_files_removed (file->directory, removed_files);
+ g_list_free (removed_files);
+ }
+ }
+}
+
+/**
+ * nautilus_file_is_gone
+ *
+ * Check if a file has already been deleted.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: TRUE if the file is already gone.
+ **/
+gboolean
+nautilus_file_is_gone (NautilusFile *file)
+{
+ g_return_val_if_fail (file != NULL, FALSE);
+
+ return file->is_gone;
+}
+
+/**
+ * nautilus_file_list_ref
+ *
+ * Ref all the files in a list.
+ * @file_list: GList of files.
+ **/
+void
+nautilus_file_list_ref (GList *file_list)
+{
+ g_list_foreach (file_list, (GFunc) nautilus_file_ref, NULL);
+}
+
+/**
+ * nautilus_file_list_unref
+ *
+ * Unref all the files in a list.
+ * @file_list: GList of files.
+ **/
+void
+nautilus_file_list_unref (GList *file_list)
+{
+ g_list_foreach (file_list, (GFunc) nautilus_file_ref, NULL);
+}
+
+/**
+ * nautilus_file_list_free
+ *
+ * Free a list of files after unrefing them.
+ * @file_list: GList of files.
+ **/
+void
+nautilus_file_list_free (GList *file_list)
+{
+ nautilus_file_list_unref (file_list);
+ g_list_free (file_list);
+}
diff --git a/libnautilus-extensions/nautilus-file.h b/libnautilus-extensions/nautilus-file.h
new file mode 100644
index 000000000..dc06290b5
--- /dev/null
+++ b/libnautilus-extensions/nautilus-file.h
@@ -0,0 +1,106 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+
+ nautilus-file.h: Nautilus file model.
+
+ Copyright (C) 1999, 2000 Eazel, Inc.
+
+ 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 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 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 Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Darin Adler <darin@eazel.com>
+*/
+
+#ifndef NAUTILUS_FILE_H
+#define NAUTILUS_FILE_H
+
+#include <glib.h> /* gnome-vfs-types.h requires glib.h but doesn't include it */
+#include <libgnomevfs/gnome-vfs-types.h>
+
+/* NautilusFile is an object used to represent a single element of a
+ * NautilusDirectory. It's lightweight and relies on NautilusDirectory
+ * to do most of the work.
+ */
+
+typedef enum {
+ NAUTILUS_FILE_SORT_NONE,
+ NAUTILUS_FILE_SORT_BY_NAME,
+ NAUTILUS_FILE_SORT_BY_SIZE,
+ NAUTILUS_FILE_SORT_BY_TYPE,
+ NAUTILUS_FILE_SORT_BY_MTIME
+} NautilusFileSortType;
+
+typedef struct NautilusFile NautilusFile;
+
+#define NAUTILUS_IS_FILE(object) \
+ ((object) != NULL)
+#define NAUTILUS_FILE(file) \
+ ((NautilusFile *)(file))
+
+/* Getting at a single file. */
+NautilusFile * nautilus_file_get (const char *uri);
+
+/* Basic operations on file objects. */
+void nautilus_file_ref (NautilusFile *file);
+void nautilus_file_unref (NautilusFile *file);
+void nautilus_file_delete (NautilusFile *file);
+
+/* Basic attributes for file objects. */
+char * nautilus_file_get_name (NautilusFile *file);
+char * nautilus_file_get_uri (NautilusFile *file);
+GnomeVFSFileSize nautilus_file_get_size (NautilusFile *file);
+GnomeVFSFileType nautilus_file_get_type (NautilusFile *file);
+const char * nautilus_file_get_mime_type (NautilusFile *file);
+gboolean nautilus_file_is_symbolic_link (NautilusFile *file);
+gboolean nautilus_file_is_executable (NautilusFile *file);
+gboolean nautilus_file_is_directory (NautilusFile *file);
+guint nautilus_file_get_directory_item_count (NautilusFile *file,
+ gboolean ignore_invisible_items);
+GList * nautilus_file_get_keywords (NautilusFile *file);
+void nautilus_file_set_keywords (NautilusFile *file,
+ GList *keywords);
+
+/* Simple getting and setting top-level metadata. */
+char * nautilus_file_get_metadata (NautilusFile *file,
+ const char *tag,
+ const char *default_metadata);
+void nautilus_file_set_metadata (NautilusFile *file,
+ const char *tag,
+ const char *default_metadata,
+ const char *metadata);
+
+/* Attributes for file objects as user-displayable strings. */
+char * nautilus_file_get_string_attribute (NautilusFile *file,
+ const char *attribute_name);
+
+/* Comparing two file objects for sorting */
+int nautilus_file_compare_for_sort (NautilusFile *file_1,
+ NautilusFile *file_2,
+ NautilusFileSortType sort_type);
+int nautilus_file_compare_for_sort_reversed (NautilusFile *file_1,
+ NautilusFile *file_2,
+ NautilusFileSortType sort_type);
+
+/* Convenience functions for dealing with a list of NautilusFile objects that each have a ref. */
+void nautilus_file_list_ref (GList *file_list);
+void nautilus_file_list_unref (GList *file_list);
+void nautilus_file_list_free (GList *file_list);
+
+/* Return true if this file has already been deleted.
+ This object will be unref'd after sending the files_removed signal,
+ but it could hang around longer if someone ref'd it.
+*/
+gboolean nautilus_file_is_gone (NautilusFile *file);
+
+#endif /* NAUTILUS_FILE_H */
diff --git a/libnautilus-extensions/nautilus-icon-factory.h b/libnautilus-extensions/nautilus-icon-factory.h
index 545211440..3e7bfa903 100644
--- a/libnautilus-extensions/nautilus-icon-factory.h
+++ b/libnautilus-extensions/nautilus-icon-factory.h
@@ -2,7 +2,7 @@
nautilus-icon-factory.h: Class for obtaining icons for files and other objects.
- * Copyright (C) 1999, 2000 Red Hat Inc.
+ Copyright (C) 1999, 2000 Red Hat Inc.
Copyright (C) 1999, 2000 Eazel, Inc.
This program is free software; you can redistribute it and/or
@@ -27,7 +27,8 @@
#define NAUTILUS_ICON_FACTORY_H
#include <gdk-pixbuf/gdk-pixbuf.h>
-#include <libnautilus/nautilus-directory.h>
+#include <libnautilus/nautilus-file.h>
+#include <gtk/gtkobject.h>
/* NautilusIconFactory is a class that knows how to hand out icons to be
* used for representing files and some other objects. It was designed
@@ -97,8 +98,8 @@ char * nautilus_icon_factory_get_theme (void);
void nautilus_icon_factory_set_theme (const char *theme_name);
/* Choose the appropriate icon, but don't render it yet. */
-NautilusScalableIcon *nautilus_icon_factory_get_icon_for_file (NautilusFile *file,
- void *controller);
+NautilusScalableIcon *nautilus_icon_factory_get_icon_for_file (NautilusFile *file,
+ void *controller);
NautilusScalableIcon *nautilus_icon_factory_get_icon_by_name (const char *icon_name);
GList * nautilus_icon_factory_get_emblem_icons_for_file (NautilusFile *file);
diff --git a/libnautilus-extensions/nautilus-string.c b/libnautilus-extensions/nautilus-string.c
index d2df8e286..c3ac00d5e 100644
--- a/libnautilus-extensions/nautilus-string.c
+++ b/libnautilus-extensions/nautilus-string.c
@@ -69,10 +69,12 @@ nautilus_has_prefix (const char *haystack_null_allowed, const char *needle_null_
h = haystack_null_allowed == NULL ? "" : haystack_null_allowed;
n = needle_null_allowed == NULL ? "" : needle_null_allowed;
do {
- if (*n == '\0')
+ if (*n == '\0') {
return TRUE;
- if (*h == '\0')
+ }
+ if (*h == '\0') {
return FALSE;
+ }
} while (*h++ == *n++);
return FALSE;
}
@@ -82,19 +84,23 @@ nautilus_has_suffix (const char *haystack_null_allowed, const char *needle_null_
{
const char *h, *n;
- if (haystack_null_allowed == NULL)
+ if (needle_null_allowed == NULL) {
return TRUE;
- if (needle_null_allowed == NULL)
- return FALSE;
+ }
+ if (haystack_null_allowed == NULL) {
+ return needle_null_allowed[0] == '\0';
+ }
/* Eat one character at a time. */
h = haystack_null_allowed + strlen(haystack_null_allowed);
n = needle_null_allowed + strlen(needle_null_allowed);
do {
- if (n == needle_null_allowed)
+ if (n == needle_null_allowed) {
return TRUE;
- if (h == haystack_null_allowed)
+ }
+ if (h == haystack_null_allowed) {
return FALSE;
+ }
} while (*--h == *--n);
return FALSE;
}
@@ -144,23 +150,28 @@ nautilus_string_to_int (const char *string, int *integer)
char *parse_end;
/* Check for the case of an empty string. */
- if (string == NULL || *string == '\0')
+ if (string == NULL || *string == '\0') {
return FALSE;
+ }
/* Call the standard library routine to do the conversion. */
errno = 0;
result = strtol (string, &parse_end, 0);
/* Check that the result is in range. */
- if ((result == G_MINLONG || result == G_MAXLONG) && errno == ERANGE)
+ if ((result == G_MINLONG || result == G_MAXLONG) && errno == ERANGE) {
return FALSE;
- if (result < G_MININT || result > G_MAXINT)
+ }
+ if (result < G_MININT || result > G_MAXINT) {
return FALSE;
+ }
/* Check that all the trailing characters are spaces. */
- while (*parse_end != '\0')
- if (!isspace (*parse_end++))
+ while (*parse_end != '\0') {
+ if (!isspace (*parse_end++)) {
return FALSE;
+ }
+ }
/* Return the result. */
*integer = result;
@@ -170,27 +181,27 @@ nautilus_string_to_int (const char *string, int *integer)
/**
* nautilus_strstrip:
* Remove all occurrences of a character from a string. The
- * original string is modified, and also returned for convenience.
+ * original string is modified in place, and also returned for convenience.
*
* @string_null_allowed: The string to be stripped.
* @remove_this: The char to remove from @string_null_allowed
*
* Return value: @string_null_allowed, after removing all occurrences
- * of @remove_this.
+ * of @remove_this.
*/
char *
nautilus_strstrip (char *string_null_allowed, char remove_this)
{
if (string_null_allowed != NULL) {
- char *pos;
+ char *in, *out;
- pos = string_null_allowed;
- while (*pos != '\0') {
- if (*pos == remove_this) {
- g_memmove (pos, pos + 1, strlen (pos));
+ in = string_null_allowed;
+ out = string_null_allowed;
+ do {
+ if (*in != remove_this) {
+ *out++ = *in;
}
- ++pos;
- }
+ } while (*in++ != '\0');
}
return string_null_allowed;
@@ -232,7 +243,6 @@ void
nautilus_self_check_string (void)
{
int integer;
- char *test_string;
NAUTILUS_CHECK_INTEGER_RESULT (nautilus_strlen (NULL), 0);
NAUTILUS_CHECK_INTEGER_RESULT (nautilus_strlen (""), 0);
@@ -283,6 +293,22 @@ nautilus_self_check_string (void)
NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_prefix ("aaa", "aaab"), FALSE);
NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_prefix ("aaab", "aaa"), TRUE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix (NULL, NULL), TRUE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix (NULL, ""), TRUE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("", NULL), TRUE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("a", "a"), TRUE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("aaab", "aaab"), TRUE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix (NULL, "a"), FALSE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("a", NULL), TRUE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("", "a"), FALSE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("a", ""), TRUE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("a", "b"), FALSE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("a", "ab"), FALSE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("ab", "a"), FALSE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("ab", "b"), TRUE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("aaa", "baaa"), FALSE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("baaa", "aaa"), TRUE);
+
NAUTILUS_CHECK_STRING_RESULT (nautilus_strdup_prefix (NULL, NULL), NULL);
NAUTILUS_CHECK_STRING_RESULT (nautilus_strdup_prefix (NULL, "foo"), NULL);
NAUTILUS_CHECK_STRING_RESULT (nautilus_strdup_prefix ("foo", NULL), "foo");
@@ -292,14 +318,11 @@ nautilus_self_check_string (void)
NAUTILUS_CHECK_STRING_RESULT (nautilus_strdup_prefix ("footle:bar", "tle:"), "foo");
NAUTILUS_CHECK_STRING_RESULT (nautilus_strstrip (NULL, '_'), NULL);
- test_string = g_strdup ("foo");
- NAUTILUS_CHECK_STRING_RESULT (nautilus_strstrip (test_string, '_'), "foo");
- test_string = g_strdup ("_foo");
- NAUTILUS_CHECK_STRING_RESULT (nautilus_strstrip (test_string, '_'), "foo");
- test_string = g_strdup ("foo_");
- NAUTILUS_CHECK_STRING_RESULT (nautilus_strstrip (test_string, '_'), "foo");
- test_string = g_strdup ("_foo_");
- NAUTILUS_CHECK_STRING_RESULT (nautilus_strstrip (test_string, '_'), "foo");
+ NAUTILUS_CHECK_STRING_RESULT (nautilus_strstrip (g_strdup ("foo"), '_'), "foo");
+ NAUTILUS_CHECK_STRING_RESULT (nautilus_strstrip (g_strdup ("_foo"), '_'), "foo");
+ NAUTILUS_CHECK_STRING_RESULT (nautilus_strstrip (g_strdup ("foo_"), '_'), "foo");
+ NAUTILUS_CHECK_STRING_RESULT (nautilus_strstrip (g_strdup ("_foo_"), '_'), "foo");
+ NAUTILUS_CHECK_STRING_RESULT (nautilus_strstrip (g_strdup ("_f_o__o_"), '_'), "foo");
#define TEST_INTEGER_CONVERSION_FUNCTIONS(string, boolean_result, integer_result) \
NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_string_to_int (string, &integer), boolean_result); \
diff --git a/libnautilus-extensions/nautilus-string.h b/libnautilus-extensions/nautilus-string.h
index 9d269dcd7..03c778f00 100644
--- a/libnautilus-extensions/nautilus-string.h
+++ b/libnautilus-extensions/nautilus-string.h
@@ -47,8 +47,8 @@ char * nautilus_strdup_prefix (const char *source_null_allowed,
gboolean nautilus_has_suffix (const char *target_null_allowed,
const char *suffix_null_allowed);
-char * nautilus_strstrip (char *string_null_allowed,
- char remove_this);
+char * nautilus_strstrip (char *string_null_allowed,
+ char remove_this);
/* Conversions to and from strings. */
diff --git a/libnautilus-private/Makefile.am b/libnautilus-private/Makefile.am
index 4e65cefad..002601a80 100644
--- a/libnautilus-private/Makefile.am
+++ b/libnautilus-private/Makefile.am
@@ -27,8 +27,6 @@ libnautilusincludedir=$(includedir)/libnautilus
libnautilusinclude_HEADERS= \
bonobo-stream-vfs.h \
gdk-extensions.h \
- gnome-icon-container-dnd.h \
- gnome-icon-container-private.h \
gnome-icon-container.h \
gtkflist.h \
gtkscrollframe.h \
@@ -38,13 +36,13 @@ libnautilusinclude_HEADERS= \
nautilus-bookmark.h \
nautilus-debug.h \
nautilus-directory.h \
+ nautilus-file.h \
nautilus-file-utilities.h \
nautilus-glib-extensions.h \
nautilus-gtk-extensions.h \
nautilus-icon-factory.h \
nautilus-icons-controller.h \
nautilus-icons-view-icon-item.h \
- nautilus-lib-self-check-functions.h \
nautilus-metadata.h \
nautilus-mime-type.h \
nautilus-self-checks.h \
@@ -68,6 +66,7 @@ libnautilus_la_SOURCES=$(nautilus_idl_sources) \
nautilus-default-file-icon.c \
nautilus-default-file-icon.h \
nautilus-directory.c \
+ nautilus-file.c \
nautilus-file-utilities.c \
nautilus-glib-extensions.c \
nautilus-gtk-extensions.c \
diff --git a/libnautilus-private/gnome-icon-container-dnd.c b/libnautilus-private/gnome-icon-container-dnd.c
index 987556da1..1057c984d 100644
--- a/libnautilus-private/gnome-icon-container-dnd.c
+++ b/libnautilus-private/gnome-icon-container-dnd.c
@@ -816,12 +816,12 @@ gnome_icon_container_dnd_begin_drag (GnomeIconContainer *container,
gtk_object_getv (GTK_OBJECT (item), 1, &pixbuf_arg);
pixbuf = GTK_VALUE_BOXED (pixbuf_arg);
- transparent_pixbuf = make_semi_transparent(pixbuf);
+ transparent_pixbuf = make_semi_transparent (pixbuf);
gdk_pixbuf_render_pixmap_and_mask (transparent_pixbuf,
&pixmap_for_dragged_file,
&mask_for_dragged_file,
128);
- gdk_pixbuf_unref(transparent_pixbuf);
+ gdk_pixbuf_unref (transparent_pixbuf);
/* compute the image's offset */
nautilus_icons_view_icon_item_get_icon_window_rectangle
diff --git a/libnautilus-private/gnome-icon-container.c b/libnautilus-private/gnome-icon-container.c
index 20ada54d2..ddf28423e 100644
--- a/libnautilus-private/gnome-icon-container.c
+++ b/libnautilus-private/gnome-icon-container.c
@@ -724,15 +724,17 @@ make_icon_visible (GnomeIconContainer *container,
icon_get_bounding_box (icon, &x1, &y1, &x2, &y2);
- if (y1 < vadj->value)
+ if (y1 < vadj->value) {
gtk_adjustment_set_value (vadj, y1);
- else if (y2 > vadj->value + allocation->height)
+ } else if (y2 > vadj->value + allocation->height) {
gtk_adjustment_set_value (vadj, y2 - allocation->height);
+ }
- if (x1 < hadj->value)
+ if (x1 < hadj->value) {
gtk_adjustment_set_value (hadj, x1);
- else if (x2 > hadj->value + allocation->width)
+ } else if (x2 > hadj->value + allocation->width) {
gtk_adjustment_set_value (hadj, x2 - allocation->width);
+ }
}
static gboolean
@@ -2145,6 +2147,17 @@ gnome_icon_container_initialize_class (GnomeIconContainerClass *class)
stipple = gdk_bitmap_create_from_data (NULL, stipple_bits, 2, 2);
}
+static GdkFont *
+load_font (const char *name)
+{
+ GdkFont *font;
+
+ /* FIXME: Eventually we need a runtime check, but an assert is better than nothing. */
+ font = gdk_font_load (name);
+ g_assert (font != NULL);
+ return font;
+}
+
static void
gnome_icon_container_initialize (GnomeIconContainer *container)
{
@@ -2159,15 +2172,15 @@ gnome_icon_container_initialize (GnomeIconContainer *container)
details->zoom_level = NAUTILUS_ZOOM_LEVEL_STANDARD;
- /* font table - this isnt exactly proportional, but it looks better than computed */
+ /* font table - this isn't exactly proportional, but it looks better than computed */
/* FIXME: read font from metadata and/or preferences */
- details->label_font[NAUTILUS_ZOOM_LEVEL_SMALLEST] = gdk_font_load("-*-helvetica-medium-r-normal-*-8-*-*-*-*-*-*-*");
- details->label_font[NAUTILUS_ZOOM_LEVEL_SMALLER] = gdk_font_load("-*-helvetica-medium-r-normal-*-8-*-*-*-*-*-*-*");
- details->label_font[NAUTILUS_ZOOM_LEVEL_SMALL] = gdk_font_load("-*-helvetica-medium-r-normal-*-10-*-*-*-*-*-*-*");
- details->label_font[NAUTILUS_ZOOM_LEVEL_STANDARD] = gdk_font_load("-*-helvetica-medium-r-normal-*-12-*-*-*-*-*-*-*");
- details->label_font[NAUTILUS_ZOOM_LEVEL_LARGE] = gdk_font_load("-*-helvetica-medium-r-normal-*-14-*-*-*-*-*-*-*");
- details->label_font[NAUTILUS_ZOOM_LEVEL_LARGER] = gdk_font_load("-*-helveticar-medium-r-normal-*-18-*-*-*-*-*-*-*");
- details->label_font[NAUTILUS_ZOOM_LEVEL_LARGEST] = gdk_font_load("-*-helvetica-medium-r-normal-*-18-*-*-*-*-*-*-*");
+ details->label_font[NAUTILUS_ZOOM_LEVEL_SMALLEST] = load_font ("-*-helvetica-medium-r-normal-*-8-*-*-*-*-*-*-*");
+ details->label_font[NAUTILUS_ZOOM_LEVEL_SMALLER] = load_font ("-*-helvetica-medium-r-normal-*-8-*-*-*-*-*-*-*");
+ details->label_font[NAUTILUS_ZOOM_LEVEL_SMALL] = load_font ("-*-helvetica-medium-r-normal-*-10-*-*-*-*-*-*-*");
+ details->label_font[NAUTILUS_ZOOM_LEVEL_STANDARD] = load_font ("-*-helvetica-medium-r-normal-*-12-*-*-*-*-*-*-*");
+ details->label_font[NAUTILUS_ZOOM_LEVEL_LARGE] = load_font ("-*-helvetica-medium-r-normal-*-14-*-*-*-*-*-*-*");
+ details->label_font[NAUTILUS_ZOOM_LEVEL_LARGER] = load_font ("-*-helvetica-medium-r-normal-*-18-*-*-*-*-*-*-*");
+ details->label_font[NAUTILUS_ZOOM_LEVEL_LARGEST] = load_font ("-*-helvetica-medium-r-normal-*-18-*-*-*-*-*-*-*");
/* FIXME: Read these from preferences. */
details->linger_selection_mode = FALSE;
diff --git a/libnautilus-private/nautilus-directory-private.h b/libnautilus-private/nautilus-directory-private.h
new file mode 100644
index 000000000..12496a3f6
--- /dev/null
+++ b/libnautilus-private/nautilus-directory-private.h
@@ -0,0 +1,72 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+
+ nautilus-directory.c: Nautilus directory model.
+
+ Copyright (C) 1999, 2000 Eazel, Inc.
+
+ 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 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 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 Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Darin Adler <darin@eazel.com>
+*/
+
+#include "nautilus-directory.h"
+
+#include <libgnomevfs/gnome-vfs-types.h>
+#include <libgnomevfs/gnome-vfs-uri.h>
+#include <libgnomevfs/gnome-vfs-file-info.h>
+
+#include <gnome-xml/tree.h>
+
+#include "nautilus-file.h"
+
+struct NautilusDirectoryDetails
+{
+ char *uri_text;
+ GnomeVFSURI *uri;
+
+ GnomeVFSURI *metafile_uri;
+ GnomeVFSURI *alternate_metafile_uri;
+ gboolean use_alternate_metafile;
+
+ xmlDoc *metafile_tree;
+ guint write_metafile_idle_id;
+
+ GnomeVFSAsyncHandle *directory_load_in_progress;
+ GnomeVFSDirectoryListPosition directory_load_list_last_handled;
+
+ GList *pending_file_info;
+ guint dequeue_pending_idle_id;
+
+ gboolean directory_loaded;
+
+ GList *files;
+};
+
+NautilusFile *nautilus_directory_new_file (NautilusDirectory *directory,
+ GnomeVFSFileInfo *info);
+char * nautilus_directory_get_file_metadata (NautilusDirectory *directory,
+ const char *file_name,
+ const char *tag,
+ const char *default_metadata);
+void nautilus_directory_set_file_metadata (NautilusDirectory *directory,
+ const char *file_name,
+ const char *tag,
+ const char *default_metadata,
+ const char *metadata);
+xmlNode * nautilus_directory_get_file_metadata_node (NautilusDirectory *directory,
+ const char *file_name);
+void nautilus_directory_files_removed (NautilusDirectory *directory,
+ GList *removed_files);
diff --git a/libnautilus-private/nautilus-directory.c b/libnautilus-private/nautilus-directory.c
index 643c290db..eaa37ac68 100644
--- a/libnautilus-private/nautilus-directory.c
+++ b/libnautilus-private/nautilus-directory.c
@@ -1,6 +1,6 @@
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
- nautilus-directory.c: Mautilus directory model.
+ nautilus-directory.c: Nautilus directory model.
Copyright (C) 1999, 2000 Eazel, Inc.
@@ -23,33 +23,20 @@
*/
#include <config.h>
-#include "nautilus-directory.h"
+#include "nautilus-directory-private.h"
-#include <grp.h>
-#include <pwd.h>
#include <stdlib.h>
#include <gtk/gtksignal.h>
#include <gtk/gtkmain.h>
-#include <libgnome/gnome-defs.h>
-#include <libgnome/gnome-i18n.h>
-
-#include <libgnomevfs/gnome-vfs-types.h>
-#include <libgnomevfs/gnome-vfs-uri.h>
-#include <libgnomevfs/gnome-vfs-file-info.h>
-#include <libgnomevfs/gnome-vfs-ops.h>
-#include <libgnomevfs/gnome-vfs-async-ops.h>
-
#include <gnome-xml/parser.h>
-#include <gnome-xml/tree.h>
#include <gnome-xml/xmlmemory.h>
-#include "nautilus-alloc.h"
-#include "nautilus-glib-extensions.h"
#include "nautilus-gtk-macros.h"
-#include "nautilus-lib-self-check-functions.h"
#include "nautilus-string.h"
+#include "nautilus-lib-self-check-functions.h"
+#include "nautilus-file-private.h"
#define METAFILE_NAME ".nautilus-metafile.xml"
#define METAFILE_PERMISSIONS (GNOME_VFS_PERM_USER_READ | GNOME_VFS_PERM_USER_WRITE \
@@ -67,12 +54,6 @@
#define DIRECTORY_LOAD_ITEMS_PER_CB 1
-typedef enum {
- NAUTILUS_DATE_TYPE_MODIFIED,
- NAUTILUS_DATE_TYPE_CHANGED,
- NAUTILUS_DATE_TYPE_ACCESSED
-} NautilusDateType;
-
enum
{
FILES_ADDED,
@@ -80,79 +61,25 @@ enum
LAST_SIGNAL
};
-/* FIXME: This hack needs to die eventually. See comments with function */
-static int get_directory_item_count_hack (NautilusFile *file, gboolean ignore_invisible_items);
-
-
static guint nautilus_directory_signals[LAST_SIGNAL];
-static void nautilus_directory_initialize_class (gpointer klass);
-static void nautilus_directory_initialize (gpointer object, gpointer klass);
-static void nautilus_directory_finalize (GtkObject *object);
-
-static NautilusDirectory *nautilus_directory_new (const char* uri);
-
-static void nautilus_directory_read_metafile (NautilusDirectory *directory);
-static void nautilus_directory_write_metafile (NautilusDirectory *directory);
-static void nautilus_directory_request_write_metafile (NautilusDirectory *directory);
-static void nautilus_directory_remove_write_metafile_idle (NautilusDirectory *directory);
-
-static void nautilus_file_free (NautilusFile *file);
-static int nautilus_file_compare_by_type (NautilusFile *file_1, NautilusFile *file_2);
-static int nautilus_file_compare_for_sort_internal (NautilusFile *file_1,
- NautilusFile *file_2,
- NautilusFileSortType sort_type,
- gboolean reversed);
-
-static char * nautilus_file_get_date_as_string (NautilusFile *file,
- NautilusDateType date_type);
-static char *nautilus_file_get_owner_as_string (NautilusFile *file);
-static char *nautilus_file_get_group_as_string (NautilusFile *file);
-static char *nautilus_file_get_permissions_as_string (NautilusFile *file);
-static char * nautilus_file_get_size_as_string (NautilusFile *file);
-static char * nautilus_file_get_type_as_string (NautilusFile *file);
-static void nautilus_directory_load_cb (GnomeVFSAsyncHandle *handle,
- GnomeVFSResult result,
- GnomeVFSDirectoryList *list,
- guint entries_read,
- gpointer callback_data);
-static NautilusFile *nautilus_directory_new_file (NautilusDirectory *directory,
- GnomeVFSFileInfo *info);
+static void nautilus_directory_initialize_class (gpointer klass);
+static void nautilus_directory_initialize (gpointer object,
+ gpointer klass);
+static void nautilus_directory_finalize (GtkObject *object);
+static NautilusDirectory *nautilus_directory_new (const char *uri);
+static void nautilus_directory_read_metafile (NautilusDirectory *directory);
+static void nautilus_directory_write_metafile (NautilusDirectory *directory);
+static void nautilus_directory_request_write_metafile (NautilusDirectory *directory);
+static void nautilus_directory_remove_write_metafile_idle (NautilusDirectory *directory);
+static void nautilus_directory_load_cb (GnomeVFSAsyncHandle *handle,
+ GnomeVFSResult result,
+ GnomeVFSDirectoryList *list,
+ guint entries_read,
+ gpointer callback_data);
NAUTILUS_DEFINE_CLASS_BOILERPLATE (NautilusDirectory, nautilus_directory, GTK_TYPE_OBJECT)
-struct NautilusDirectoryDetails
-{
- char *uri_text;
- GnomeVFSURI *uri;
-
- GnomeVFSURI *metafile_uri;
- GnomeVFSURI *alternate_metafile_uri;
- gboolean use_alternate_metafile;
-
- xmlDoc *metafile_tree;
- guint write_metafile_idle_id;
-
- GnomeVFSAsyncHandle *directory_load_in_progress;
- GnomeVFSDirectoryListPosition directory_load_list_last_handled;
-
- GList *pending_file_info;
- guint dequeue_pending_idle_id;
-
- gboolean directory_loaded;
-
- GList *files;
-};
-
-struct NautilusFile
-{
- guint ref_count;
-
- NautilusDirectory *directory;
- GnomeVFSFileInfo *info;
- gboolean is_gone;
-};
-
static GHashTable* directory_objects;
static void
@@ -1005,9 +932,9 @@ nautilus_directory_set_integer_metadata (NautilusDirectory *directory,
g_free (default_as_string);
}
-static xmlNode *
-get_file_metadata_node (NautilusDirectory *directory,
- const char *file_name)
+xmlNode *
+nautilus_directory_get_file_metadata_node (NautilusDirectory *directory,
+ const char *file_name)
{
xmlNode *root, *child;
xmlChar *property;
@@ -1038,18 +965,18 @@ get_file_metadata_node (NautilusDirectory *directory,
return NULL;
}
-static char *
+char *
nautilus_directory_get_file_metadata (NautilusDirectory *directory,
const char *file_name,
const char *tag,
const char *default_metadata)
{
return nautilus_directory_get_metadata_from_node
- (get_file_metadata_node (directory, file_name),
+ (nautilus_directory_get_file_metadata_node (directory, file_name),
tag, default_metadata);
}
-static void
+void
nautilus_directory_set_file_metadata (NautilusDirectory *directory,
const char *file_name,
const char *tag,
@@ -1118,7 +1045,7 @@ nautilus_directory_set_file_metadata (NautilusDirectory *directory,
nautilus_directory_request_write_metafile (directory);
}
-static NautilusFile *
+NautilusFile *
nautilus_directory_new_file (NautilusDirectory *directory, GnomeVFSFileInfo *info)
{
NautilusFile *file;
@@ -1135,973 +1062,13 @@ nautilus_directory_new_file (NautilusDirectory *directory, GnomeVFSFileInfo *inf
return file;
}
-/**
- * nautilus_file_get:
- * @uri: URI of file to get.
- *
- * Get a file given a uri.
- * Returns a referenced object. Unref when finished.
- * If two windows are viewing the same uri, the file object is shared.
- */
-NautilusFile *
-nautilus_file_get (const char *uri)
-{
- GnomeVFSResult result;
- GnomeVFSFileInfo *file_info;
- GnomeVFSURI *vfs_uri, *directory_vfs_uri;
- char *directory_uri;
- NautilusDirectory *directory;
- NautilusFile *file;
-
- /* Get info on the file. */
- file_info = gnome_vfs_file_info_new ();
- result = gnome_vfs_get_file_info (uri, file_info,
- GNOME_VFS_FILE_INFO_GETMIMETYPE
- | GNOME_VFS_FILE_INFO_FASTMIMETYPE
- | GNOME_VFS_FILE_INFO_FOLLOWLINKS, NULL);
- if (result != GNOME_VFS_OK)
- return NULL;
-
- /* Make VFS version of URI. */
- vfs_uri = gnome_vfs_uri_new (uri);
- if (vfs_uri == NULL)
- return NULL;
-
- /* Make VFS version of directory URI. */
- directory_vfs_uri = gnome_vfs_uri_get_parent (vfs_uri);
- gnome_vfs_uri_unref (vfs_uri);
- if (directory_vfs_uri == NULL)
- return NULL;
-
- /* Make text version of directory URI. */
- directory_uri = gnome_vfs_uri_to_string (directory_vfs_uri,
- GNOME_VFS_URI_HIDE_NONE);
- gnome_vfs_uri_unref (directory_vfs_uri);
-
- /* Get object that represents the directory. */
- directory = nautilus_directory_get (directory_uri);
- g_free (directory_uri);
- if (directory == NULL)
- return NULL;
-
- file = nautilus_directory_new_file (directory, file_info);
-
- gnome_vfs_file_info_unref (file_info);
- nautilus_file_ref (file);
- gtk_object_unref (GTK_OBJECT (directory));
-
- return file;
-}
-
-void
-nautilus_file_ref (NautilusFile *file)
-{
- g_return_if_fail (file != NULL);
-
- g_assert (file->ref_count < G_MAXINT);
- g_assert (file->directory != NULL);
-
- /* Increment the ref count. */
- if (file->ref_count++ != 0) {
- return;
- }
-
- /* As soon as someone other than the directory holds a ref,
- * we need to hold the directory too. */
- gtk_object_ref (GTK_OBJECT (file->directory));
-}
-
-void
-nautilus_file_unref (NautilusFile *file)
-{
- g_return_if_fail (file != NULL);
-
- g_assert (file->ref_count != 0);
- g_assert (file->directory != NULL);
-
- /* Decrement the ref count. */
- if (--file->ref_count != 0) {
- return;
- }
-
- /* No references left, so it's time to release our hold on the directory. */
- gtk_object_unref (GTK_OBJECT (file->directory));
- if (file->is_gone) {
- nautilus_file_free (file);
- }
-}
-
-static void
-nautilus_file_free (NautilusFile *file)
-{
- g_assert (file->ref_count == 0);
-
- /* Destroy the file object. */
- gnome_vfs_file_info_unref (file->info);
- g_free (file);
-}
-
-static int
-nautilus_file_compare_by_size_with_directories (NautilusFile *file_1, NautilusFile *file_2)
-{
- gboolean is_directory_1;
- gboolean is_directory_2;
- int item_count_1;
- int item_count_2;
-
- is_directory_1 = nautilus_file_is_directory (file_1);
- is_directory_2 = nautilus_file_is_directory (file_2);
-
- if (is_directory_1 && !is_directory_2)
- return -1;
-
- if (is_directory_2 && !is_directory_1)
- return +1;
-
- if (!is_directory_1 && !is_directory_2)
- return 0;
-
- /* Both are directories, compare by item count. */
- /* FIXME: get_directory_item_count_hack is slow, and calling
- * it for every pairwise comparison here is nasty. Need to
- * change this to (not-yet-existent) architecture where the
- * item count can be calculated once in a deferred way, and
- * then stored or cached.
- */
- item_count_1 = get_directory_item_count_hack (file_1, FALSE);
- item_count_2 = get_directory_item_count_hack (file_2, FALSE);
-
- if (item_count_1 < item_count_2)
- return -1;
-
- if (item_count_2 < item_count_1)
- return +1;
-
- return 0;
-}
-
-static int
-nautilus_file_compare_by_type (NautilusFile *file_1, NautilusFile *file_2)
-{
- gboolean is_directory_1;
- gboolean is_directory_2;
- char * type_string_1;
- char * type_string_2;
- int result;
-
- /* Directories go first. Then, if mime types are identical,
- * don't bother getting strings (for speed). This assumes
- * that the string is dependent entirely on the mime type,
- * which is true now but might not be later.
- */
- is_directory_1 = nautilus_file_is_directory (file_1);
- is_directory_2 = nautilus_file_is_directory (file_2);
-
- if (is_directory_1 && is_directory_2)
- return 0;
-
- if (is_directory_1)
- return -1;
-
- if (is_directory_2)
- return +1;
-
- if (nautilus_strcmp (file_1->info->mime_type, file_2->info->mime_type) == 0)
- return 0;
-
- type_string_1 = nautilus_file_get_type_as_string (file_1);
- type_string_2 = nautilus_file_get_type_as_string (file_2);
-
- result = nautilus_strcmp (type_string_1, type_string_2);
-
- g_free (type_string_1);
- g_free (type_string_2);
-
- return result;
-}
-
-static int
-nautilus_file_compare_for_sort_internal (NautilusFile *file_1,
- NautilusFile *file_2,
- NautilusFileSortType sort_type,
- gboolean reversed)
-{
- GnomeVFSDirectorySortRule *rules;
-
- g_return_val_if_fail (file_1 != NULL, 0);
- g_return_val_if_fail (file_2 != NULL, 0);
- g_return_val_if_fail (sort_type != NAUTILUS_FILE_SORT_NONE, 0);
-
-#define ALLOC_RULES(n) alloca ((n) * sizeof (GnomeVFSDirectorySortRule))
-
- switch (sort_type) {
- case NAUTILUS_FILE_SORT_BY_NAME:
- rules = ALLOC_RULES (2);
- /* Note: This used to put directories first. I
- * thought that was counterintuitive and removed it,
- * but I can imagine discussing this further.
- * John Sullivan <sullivan@eazel.com>
- */
- rules[0] = GNOME_VFS_DIRECTORY_SORT_BYNAME_IGNORECASE;
- rules[1] = GNOME_VFS_DIRECTORY_SORT_NONE;
- break;
- case NAUTILUS_FILE_SORT_BY_SIZE:
- /* Compare directory sizes ourselves, then if necessary
- * use GnomeVFS to compare file sizes.
- */
- {
- int size_compare;
-
- size_compare = nautilus_file_compare_by_size_with_directories (file_1, file_2);
- if (size_compare != 0)
- return size_compare;
- }
- rules = ALLOC_RULES (3);
- rules[0] = GNOME_VFS_DIRECTORY_SORT_BYSIZE;
- rules[1] = GNOME_VFS_DIRECTORY_SORT_BYNAME_IGNORECASE;
- rules[2] = GNOME_VFS_DIRECTORY_SORT_NONE;
- break;
- case NAUTILUS_FILE_SORT_BY_TYPE:
- /* GnomeVFS doesn't know about our special text for certain
- * mime types, so we handle the mime-type sorting ourselves.
- */
- {
- int type_compare;
-
- type_compare = nautilus_file_compare_by_type (file_1, file_2);
- if (type_compare != 0)
- return type_compare;
- }
- rules = ALLOC_RULES (2);
- rules[0] = GNOME_VFS_DIRECTORY_SORT_BYNAME_IGNORECASE;
- rules[1] = GNOME_VFS_DIRECTORY_SORT_NONE;
- break;
- case NAUTILUS_FILE_SORT_BY_MTIME:
- rules = ALLOC_RULES (3);
- rules[0] = GNOME_VFS_DIRECTORY_SORT_BYMTIME;
- rules[1] = GNOME_VFS_DIRECTORY_SORT_BYNAME_IGNORECASE;
- rules[2] = GNOME_VFS_DIRECTORY_SORT_NONE;
- break;
- default:
- g_assert_not_reached ();
- return 0;
- }
-
- if (reversed)
- return gnome_vfs_file_info_compare_for_sort_reversed (file_1->info,
- file_2->info,
- rules);
- else
- return gnome_vfs_file_info_compare_for_sort (file_1->info,
- file_2->info,
- rules);
-
-#undef ALLOC_RULES
-}
-
-/**
- * nautilus_file_compare_for_sort:
- * @file_1: A file object
- * @file_2: Another file object
- * @sort_type: Sort criterion
- *
- * Return value: int < 0 if @file_1 should come before file_2 in a smallest-to-largest
- * sorted list; int > 0 if @file_2 should come before file_1 in a smallest-to-largest
- * sorted list; 0 if @file_1 and @file_2 are equal for this sort criterion. Note
- * that each named sort type may actually break ties several ways, with the name
- * of the sort criterion being the primary but not only differentiator.
- **/
-int
-nautilus_file_compare_for_sort (NautilusFile *file_1,
- NautilusFile *file_2,
- NautilusFileSortType sort_type)
-{
- return nautilus_file_compare_for_sort_internal (file_1, file_2, sort_type, FALSE);
-}
-
-/**
- * nautilus_file_compare_for_sort_reversed:
- * @file_1: A file object
- * @file_2: Another file object
- * @sort_type: Sort criterion
- *
- * Return value: The opposite of nautilus_file_compare_for_sort: int > 0 if @file_1
- * should come before file_2 in a smallest-to-largest sorted list; int < 0 if @file_2
- * should come before file_1 in a smallest-to-largest sorted list; 0 if @file_1
- * and @file_2 are equal for this sort criterion. Note that each named sort type
- * may actually break ties several ways, with the name of the sort criterion
- * being the primary but not only differentiator.
- **/
-int
-nautilus_file_compare_for_sort_reversed (NautilusFile *file_1,
- NautilusFile *file_2,
- NautilusFileSortType sort_type)
-{
- return nautilus_file_compare_for_sort_internal (file_1, file_2, sort_type, TRUE);
-}
-
-char *
-nautilus_file_get_metadata (NautilusFile *file,
- const char *tag,
- const char *default_metadata)
-{
- g_return_val_if_fail (file != NULL, NULL);
-
- return nautilus_directory_get_file_metadata (file->directory,
- file->info->name,
- tag,
- default_metadata);
-}
-
void
-nautilus_file_set_metadata (NautilusFile *file,
- const char *tag,
- const char *default_metadata,
- const char *metadata)
+nautilus_directory_files_removed (NautilusDirectory *directory,
+ GList *removed_files)
{
- g_return_if_fail (file != NULL);
-
- nautilus_directory_set_file_metadata (file->directory,
- file->info->name,
- tag,
- default_metadata,
- metadata);
-}
-
-char *
-nautilus_file_get_name (NautilusFile *file)
-{
- g_return_val_if_fail (file != NULL, NULL);
-
- g_assert (file->directory == NULL || NAUTILUS_IS_DIRECTORY (file->directory));
- g_assert (file->info->name != NULL);
- g_assert (file->info->name[0] != '\0');
-
- return g_strdup (file->info->name);
-}
-
-char *
-nautilus_file_get_uri (NautilusFile *file)
-{
- GnomeVFSURI *uri;
- char *uri_text;
-
- g_return_val_if_fail (file != NULL, NULL);
- g_return_val_if_fail (file->directory != NULL, NULL);
-
- uri = gnome_vfs_uri_append_path (file->directory->details->uri, file->info->name);
- uri_text = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE);
- gnome_vfs_uri_unref (uri);
- return uri_text;
-}
-
-/**
- * nautilus_file_get_date_as_string:
- *
- * Get a user-displayable string representing a file modification date.
- * The caller is responsible for g_free-ing this string.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: Newly allocated string ready to display to the user.
- *
- **/
-static char *
-nautilus_file_get_date_as_string (NautilusFile *file, NautilusDateType date_type)
-{
- struct tm *file_time;
- const char *format;
- GDate *today;
- GDate *file_date;
- guint32 file_date_age;
-
- g_return_val_if_fail (file != NULL, NULL);
-
- switch (date_type)
- {
- case NAUTILUS_DATE_TYPE_CHANGED:
- file_time = localtime(&file->info->ctime);
- break;
- case NAUTILUS_DATE_TYPE_ACCESSED:
- file_time = localtime(&file->info->atime);
- break;
- case NAUTILUS_DATE_TYPE_MODIFIED:
- file_time = localtime(&file->info->mtime);
- break;
- default:
- g_assert_not_reached ();
- }
- file_date = nautilus_g_date_new_tm (file_time);
-
- today = g_date_new ();
- g_date_set_time (today, time (NULL));
-
- /* Overflow results in a large number; fine for our purposes. */
- file_date_age = g_date_julian (today) - g_date_julian (file_date);
-
- g_date_free (file_date);
- g_date_free (today);
-
- /* Format varies depending on how old the date is. This minimizes
- * the length (and thus clutter & complication) of typical dates
- * while providing sufficient detail for recent dates to make
- * them maximally understandable at a glance. Keep all format
- * strings separate rather than combining bits & pieces for
- * internationalization's sake.
- */
-
- if (file_date_age == 0)
- {
- /* today, use special word */
- format = _("today %-I:%M %p");
- }
- else if (file_date_age == 1)
- {
- /* yesterday, use special word */
- format = _("yesterday %-I:%M %p");
- }
- else if (file_date_age < 7)
- {
- /* current week, include day of week */
- format = _("%A %-m/%-d/%y %-I:%M %p");
- }
- else
- {
- format = _("%-m/%-d/%y %-I:%M %p");
- }
-
- return nautilus_strdup_strftime (format, file_time);
-}
-
-/**
- * nautilus_file_get_directory_item_count
- *
- * Get the number of items in a directory.
- * @file: NautilusFile representing a directory. It is an error to
- * call this function on a file that is not a directory.
- * @ignore_invisible_items: TRUE if invisible items should not be
- * included in count.
- *
- * Returns: item count for this directory.
- *
- **/
-guint
-nautilus_file_get_directory_item_count (NautilusFile *file,
- gboolean ignore_invisible_items)
-{
- g_return_val_if_fail (nautilus_file_is_directory (file), 0);
-
- return get_directory_item_count_hack (file, ignore_invisible_items);
-}
-
-/**
- * nautilus_file_get_size
- *
- * Get the file size.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: Size in bytes.
- *
- **/
-GnomeVFSFileSize
-nautilus_file_get_size (NautilusFile *file)
-{
- g_return_val_if_fail (file != NULL, 0);
-
- return file->info->size;
-}
-
-/**
- * nautilus_file_get_permissions_as_string:
- *
- * Get a user-displayable string representing a file's permissions. The caller
- * is responsible for g_free-ing this string.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: Newly allocated string ready to display to the user.
- *
- **/
-static char *
-nautilus_file_get_permissions_as_string (NautilusFile *file)
-{
- GnomeVFSFilePermissions permissions;
- gboolean is_directory;
- gboolean is_link;
-
- permissions = file->info->permissions;
- is_directory = nautilus_file_is_directory (file);
- is_link = GNOME_VFS_FILE_INFO_SYMLINK(file->info);
-
- return g_strdup_printf ("%c%c%c%c%c%c%c%c%c%c",
- is_link ? 'l' : is_directory ? 'd' : '-',
- permissions & GNOME_VFS_PERM_USER_READ ? 'r' : '-',
- permissions & GNOME_VFS_PERM_USER_WRITE ? 'w' : '-',
- permissions & GNOME_VFS_PERM_USER_EXEC ? 'x' : '-',
- permissions & GNOME_VFS_PERM_GROUP_READ ? 'r' : '-',
- permissions & GNOME_VFS_PERM_GROUP_WRITE ? 'w' : '-',
- permissions & GNOME_VFS_PERM_GROUP_EXEC ? 'x' : '-',
- permissions & GNOME_VFS_PERM_OTHER_READ ? 'r' : '-',
- permissions & GNOME_VFS_PERM_OTHER_WRITE ? 'w' : '-',
- permissions & GNOME_VFS_PERM_OTHER_EXEC ? 'x' : '-');
-}
-
-/**
- * nautilus_file_get_owner_as_string:
- *
- * Get a user-displayable string representing a file's owner. The caller
- * is responsible for g_free-ing this string.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: Newly allocated string ready to display to the user.
- *
- **/
-static char *
-nautilus_file_get_owner_as_string (NautilusFile *file)
-{
- struct passwd *password_info;
-
- /* FIXME: Can we trust the uid in the file info? Might
- * there be garbage there? What will it do for non-local files?
- */
- /* No need to free result of getpwuid */
- password_info = getpwuid (file->info->uid);
-
- g_print ("pointer to password info is %p\n", password_info);
-
- if (password_info == NULL)
- {
- return g_strdup (_("unknown owner"));
- }
-
- return g_strdup (password_info->pw_name);
-}
-
-/**
- * nautilus_file_get_group_as_string:
- *
- * Get a user-displayable string representing a file's group. The caller
- * is responsible for g_free-ing this string.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: Newly allocated string ready to display to the user.
- *
- **/
-static char *
-nautilus_file_get_group_as_string (NautilusFile *file)
-{
- struct group *group_info;
-
- /* FIXME: Can we trust the gid in the file info? Might
- * there be garbage there? What will it do for non-local files?
- */
- /* No need to free result of getgrgid */
- group_info = getgrgid (file->info->gid);
-
- if (group_info == NULL)
- {
- return g_strdup (_("unknown group"));
- }
-
- return g_strdup (group_info->gr_name);
-}
-
-
-/* This #include is part of the following hack, and should be removed with it */
-#include <dirent.h>
-
-static int
-get_directory_item_count_hack (NautilusFile *file, gboolean ignore_invisible_items)
-{
- /* Code borrowed from Gnomad and hacked into here for now */
-
- char * uri;
- char * path;
- DIR* directory;
- int count;
- struct dirent * entry;
-
- g_assert (nautilus_file_is_directory (file));
-
- uri = nautilus_file_get_uri (file);
- if (nautilus_has_prefix (uri, "file://"))
- path = uri + 7;
- else
- path = uri;
-
- directory = opendir (path);
-
- g_free (uri);
-
- if (!directory)
- return 0;
-
- count = 0;
-
- while ((entry = readdir(directory)) != NULL)
- // Only count invisible items if requested.
- if (!ignore_invisible_items || entry->d_name[0] != '.')
- count += 1;
-
- closedir(directory);
-
- /* This way of getting the count includes . and .., so we subtract those out */
- if (!ignore_invisible_items) {
- count -= 2;
- }
-
- return count;
-}
-
-/**
- * nautilus_file_get_size_as_string:
- *
- * Get a user-displayable string representing a file size. The caller
- * is responsible for g_free-ing this string. The string is an item
- * count for directories.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: Newly allocated string ready to display to the user.
- *
- **/
-static char *
-nautilus_file_get_size_as_string (NautilusFile *file)
-{
- g_return_val_if_fail (file != NULL, NULL);
-
- if (nautilus_file_is_directory (file))
- {
- /* FIXME: Since computing the item count is slow, we
- * want to do it in a deferred way. However, that
- * architecture doesn't exist yet, so we're hacking
- * it in for now.
- */
- int item_count;
-
- item_count = get_directory_item_count_hack (file, FALSE);
- if (item_count == 0) {
- return g_strdup (_("0 items"));
- } else if (item_count == 1) {
- return g_strdup (_("1 item"));
- } else {
- return g_strdup_printf (_("%d items"), item_count);
- }
- }
-
- return gnome_vfs_file_size_to_string (file->info->size);
-}
-
-/**
- * nautilus_file_get_string_attribute:
- *
- * Get a user-displayable string from a named attribute. Use g_free to
- * free this string.
- *
- * @file: NautilusFile representing the file in question.
- * @attribute_name: The name of the desired attribute. The currently supported
- * set includes "name", "type", "size", "date_modified", "date_changed",
- * "date_accessed", "owner", "group", "permissions".
- *
- * Returns: Newly allocated string ready to display to the user, or NULL
- * if @attribute_name is not supported.
- *
- **/
-char *
-nautilus_file_get_string_attribute (NautilusFile *file, const char *attribute_name)
-{
- /* FIXME: Use hash table and switch statement or function pointers for speed? */
-
- if (strcmp (attribute_name, "name") == 0) {
- return nautilus_file_get_name (file);
- }
-
- if (strcmp (attribute_name, "type") == 0) {
- return nautilus_file_get_type_as_string (file);
- }
-
- if (strcmp (attribute_name, "size") == 0) {
- return nautilus_file_get_size_as_string (file);
- }
-
- if (strcmp (attribute_name, "date_modified") == 0) {
- return nautilus_file_get_date_as_string (file,
- NAUTILUS_DATE_TYPE_MODIFIED);
- }
-
- if (strcmp (attribute_name, "date_changed") == 0) {
- return nautilus_file_get_date_as_string (file,
- NAUTILUS_DATE_TYPE_CHANGED);
- }
-
- if (strcmp (attribute_name, "date_accessed") == 0) {
- return nautilus_file_get_date_as_string (file,
- NAUTILUS_DATE_TYPE_ACCESSED);
- }
-
- if (strcmp (attribute_name, "permissions") == 0) {
- return nautilus_file_get_permissions_as_string (file);
- }
-
- if (strcmp (attribute_name, "owner") == 0) {
- return nautilus_file_get_owner_as_string (file);
- }
-
- if (strcmp (attribute_name, "group") == 0) {
- return nautilus_file_get_group_as_string (file);
- }
-
- return NULL;
-}
-
-/**
- * nautilus_file_get_type_as_string:
- *
- * Get a user-displayable string representing a file type. The caller
- * is responsible for g_free-ing this string.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: Newly allocated string ready to display to the user.
- *
- **/
-static char *
-nautilus_file_get_type_as_string (NautilusFile *file)
-{
- g_return_val_if_fail (file != NULL, NULL);
-
- if (nautilus_file_is_directory (file)) {
- /* Special-case this so it isn't "special/directory".
- * FIXME: Should this be "folder" instead?
- */
- return g_strdup (_("directory"));
- }
-
- if (nautilus_strlen (file->info->mime_type) == 0) {
- return g_strdup (_("unknown type"));
- }
-
- return g_strdup (file->info->mime_type);
-}
-
-/**
- * nautilus_file_get_type
- *
- * Return this file's type.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: The type.
- *
- **/
-GnomeVFSFileType
-nautilus_file_get_type (NautilusFile *file)
-{
- g_return_val_if_fail (file != NULL, FALSE);
-
- return file->info->type;
-}
-
-/**
- * nautilus_file_get_mime_type
- *
- * Return this file's mime type.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: The mime type.
- *
- **/
-const char *
-nautilus_file_get_mime_type (NautilusFile *file)
-{
- g_return_val_if_fail (file != NULL, FALSE);
-
- return file->info->mime_type;
-}
-
-/**
- * nautilus_file_get_keywords
- *
- * Return this file's keywords.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: A list of keywords.
- *
- **/
-GList *
-nautilus_file_get_keywords (NautilusFile *file)
-{
- GList *keywords;
- xmlNode *file_node, *child;
- xmlChar *property;
-
- g_return_val_if_fail (file != NULL, NULL);
-
- keywords = NULL;
-
- /* Put all the keywords into a list. */
- file_node = get_file_metadata_node (file->directory, file->info->name);
- if (file_node != NULL) {
- for (child = file_node->childs; child != NULL; child = child->next) {
- if (strcmp (child->name, "KEYWORD") == 0) {
- property = xmlGetProp (child, "NAME");
- if (property != NULL) {
- keywords = g_list_prepend (keywords,
- g_strdup (property));
- }
- }
- }
- }
-
- return g_list_reverse (keywords);
-}
-
-/**
- * nautilus_file_is_symbolic_link
- *
- * Check if this file is a symbolic link.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: True if the file is a symbolic link.
- *
- **/
-gboolean
-nautilus_file_is_symbolic_link (NautilusFile *file)
-{
- g_return_val_if_fail (file != NULL, FALSE);
-
- return GNOME_VFS_FILE_INFO_SYMLINK (file->info);
-}
-
-/**
- * nautilus_file_is_directory
- *
- * Check if this file is a directory.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: TRUE if @file is a directory.
- *
- **/
-gboolean
-nautilus_file_is_directory (NautilusFile *file)
-{
- g_return_val_if_fail (file != NULL, FALSE);
-
- return nautilus_file_get_type (file) == GNOME_VFS_FILE_TYPE_DIRECTORY;
-}
-
-/**
- * nautilus_file_is_executable
- *
- * Check if this file is executable at all.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: True if any of the execute bits are set.
- *
- **/
-gboolean
-nautilus_file_is_executable (NautilusFile *file)
-{
- g_return_val_if_fail (file != NULL, FALSE);
-
- return (file->info->flags & (GNOME_VFS_PERM_USER_EXEC
- | GNOME_VFS_PERM_GROUP_EXEC
- | GNOME_VFS_PERM_OTHER_EXEC)) != 0;
-}
-
-/**
- * nautilus_file_delete
- *
- * Delete this file.
- * @file: NautilusFile representing the file in question.
- **/
-void
-nautilus_file_delete (NautilusFile *file)
-{
- char *text_uri;
- GnomeVFSResult result;
- GList *removed_files;
-
- g_return_if_fail (file != NULL);
-
- /* Deleting a file that's already gone is easy. */
- if (file->is_gone) {
- return;
- }
-
- /* Do the actual deletion. */
- text_uri = nautilus_file_get_uri (file);
- if (nautilus_file_is_directory (file)) {
- result = gnome_vfs_remove_directory (text_uri);
- } else {
- result = gnome_vfs_unlink (text_uri);
- }
- g_free (text_uri);
-
- /* Mark the file gone. */
- if (result == GNOME_VFS_OK || result == GNOME_VFS_ERROR_NOTFOUND) {
- file->is_gone = TRUE;
-
- /* Let the directory know it's gone. */
- if (file->directory != NULL) {
- g_list_remove (file->directory->details->files, file);
-
- /* Send out a message. */
- removed_files = g_list_prepend (NULL, file);
- gtk_signal_emit (GTK_OBJECT (file->directory),
- nautilus_directory_signals[FILES_REMOVED],
- removed_files);
- g_list_free (removed_files);
- }
- }
-}
-
-/**
- * nautilus_file_is_gone
- *
- * Check if a file has already been deleted.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: TRUE if the file is already gone.
- **/
-gboolean
-nautilus_file_is_gone (NautilusFile *file)
-{
- g_return_val_if_fail (file != NULL, FALSE);
-
- return file->is_gone;
-}
-
-/**
- * nautilus_file_list_ref
- *
- * Ref all the files in a list.
- * @file_list: GList of files.
- **/
-void
-nautilus_file_list_ref (GList *file_list)
-{
- g_list_foreach (file_list, (GFunc) nautilus_file_ref, NULL);
-}
-
-/**
- * nautilus_file_list_unref
- *
- * Unref all the files in a list.
- * @file_list: GList of files.
- **/
-void
-nautilus_file_list_unref (GList *file_list)
-{
- g_list_foreach (file_list, (GFunc) nautilus_file_ref, NULL);
-}
-
-/**
- * nautilus_file_list_free
- *
- * Free a list of files after unrefing them.
- * @file_list: GList of files.
- **/
-void
-nautilus_file_list_free (GList *file_list)
-{
- nautilus_file_list_unref (file_list);
- g_list_free (file_list);
+ gtk_signal_emit (GTK_OBJECT (directory),
+ nautilus_directory_signals[FILES_REMOVED],
+ removed_files);
}
#if !defined (NAUTILUS_OMIT_SELF_CHECK)
diff --git a/libnautilus-private/nautilus-directory.h b/libnautilus-private/nautilus-directory.h
index 35058f26b..42ea0451b 100644
--- a/libnautilus-private/nautilus-directory.h
+++ b/libnautilus-private/nautilus-directory.h
@@ -26,7 +26,6 @@
#define NAUTILUS_DIRECTORY_H
#include <gtk/gtkobject.h>
-#include <libgnomevfs/gnome-vfs-types.h>
/* NautilusDirectory is a class that manages the model for a directory,
real or virtual, for Nautilus, mainly the file-manager component. The directory is
@@ -57,21 +56,6 @@ typedef struct NautilusDirectoryClass NautilusDirectoryClass;
#define NAUTILUS_IS_DIRECTORY_CLASS(klass) \
(GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_DIRECTORY))
-#define NAUTILUS_IS_FILE(object) \
- ((object) != NULL)
-
-typedef enum {
- NAUTILUS_FILE_SORT_NONE,
- NAUTILUS_FILE_SORT_BY_NAME,
- NAUTILUS_FILE_SORT_BY_SIZE,
- NAUTILUS_FILE_SORT_BY_TYPE,
- NAUTILUS_FILE_SORT_BY_MTIME
-} NautilusFileSortType;
-
-typedef struct NautilusFile NautilusFile;
-
-#define NAUTILUS_FILE(file) ((NautilusFile *)(file))
-
typedef void (*NautilusFileListCallback) (NautilusDirectory *directory,
GList *files,
gpointer callback_data);
@@ -124,61 +108,6 @@ void nautilus_directory_stop_monitoring (NautilusDirectory
*/
gboolean nautilus_directory_are_all_files_seen (NautilusDirectory *directory);
-/* Getting at a single file. */
-NautilusFile * nautilus_file_get (const char *uri);
-
-/* Basic operations on file objects. */
-void nautilus_file_ref (NautilusFile *file);
-void nautilus_file_unref (NautilusFile *file);
-void nautilus_file_delete (NautilusFile *file);
-
-/* Basic attributes for file objects. */
-char * nautilus_file_get_name (NautilusFile *file);
-char * nautilus_file_get_uri (NautilusFile *file);
-GnomeVFSFileSize nautilus_file_get_size (NautilusFile *file);
-GnomeVFSFileType nautilus_file_get_type (NautilusFile *file);
-const char * nautilus_file_get_mime_type (NautilusFile *file);
-gboolean nautilus_file_is_symbolic_link (NautilusFile *file);
-gboolean nautilus_file_is_executable (NautilusFile *file);
-gboolean nautilus_file_is_directory (NautilusFile *file);
-guint nautilus_file_get_directory_item_count (NautilusFile *file,
- gboolean ignore_invisible_items);
-GList * nautilus_file_get_keywords (NautilusFile *file);
-void nautilus_file_set_keywords (NautilusFile *file,
- GList *keywords);
-
-/* Simple getting and setting top-level metadata. */
-char * nautilus_file_get_metadata (NautilusFile *file,
- const char *tag,
- const char *default_metadata);
-void nautilus_file_set_metadata (NautilusFile *file,
- const char *tag,
- const char *default_metadata,
- const char *metadata);
-
-/* Attributes for file objects as user-displayable strings. */
-char * nautilus_file_get_string_attribute (NautilusFile *file,
- const char *attribute_name);
-
-/* Comparing two file objects for sorting */
-int nautilus_file_compare_for_sort (NautilusFile *file_1,
- NautilusFile *file_2,
- NautilusFileSortType sort_type);
-int nautilus_file_compare_for_sort_reversed (NautilusFile *file_1,
- NautilusFile *file_2,
- NautilusFileSortType sort_type);
-
-/* Convenience functions for dealing with a list of NautilusFile objects that each have a ref. */
-void nautilus_file_list_ref (GList *file_list);
-void nautilus_file_list_unref (GList *file_list);
-void nautilus_file_list_free (GList *file_list);
-
-/* Return true if this file has already been deleted.
- This object will be unref'd after sending the files_removed signal,
- but it could hang around longer if someone ref'd it.
-*/
-gboolean nautilus_file_is_gone (NautilusFile *file);
-
typedef struct NautilusDirectoryDetails NautilusDirectoryDetails;
struct NautilusDirectory
@@ -201,10 +130,10 @@ struct NautilusDirectoryClass
this is the last chance to forget about these file objects
which are about to be unref'd.
*/
- void (* files_added) (NautilusDirectory *directory,
- GList *added_files);
- void (* files_removed) (NautilusDirectory *directory,
- GList *removed_files);
+ void (* files_added) (NautilusDirectory *directory,
+ GList *added_files);
+ void (* files_removed) (NautilusDirectory *directory,
+ GList *removed_files);
/* The files_changed signal is emitted as changes occur to
existing files that are noticed by the synchronization framework.
diff --git a/libnautilus-private/nautilus-file-private.h b/libnautilus-private/nautilus-file-private.h
new file mode 100644
index 000000000..7ee311c9b
--- /dev/null
+++ b/libnautilus-private/nautilus-file-private.h
@@ -0,0 +1,37 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+
+ nautilus-directory.c: Nautilus directory model.
+
+ Copyright (C) 1999, 2000 Eazel, Inc.
+
+ 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 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 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 Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Darin Adler <darin@eazel.com>
+*/
+
+#include "nautilus-file.h"
+#include "nautilus-directory.h"
+
+struct NautilusFile
+{
+ guint ref_count;
+
+ NautilusDirectory *directory;
+ GnomeVFSFileInfo *info;
+ gboolean is_gone;
+};
+
+void nautilus_file_free (NautilusFile *);
diff --git a/libnautilus-private/nautilus-file.c b/libnautilus-private/nautilus-file.c
new file mode 100644
index 000000000..56efacead
--- /dev/null
+++ b/libnautilus-private/nautilus-file.c
@@ -0,0 +1,1014 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+
+ nautilus-file.c: Nautilus file model.
+
+ Copyright (C) 1999, 2000 Eazel, Inc.
+
+ 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 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 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 Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Darin Adler <darin@eazel.com>
+*/
+
+#include <config.h>
+#include "nautilus-file-private.h"
+
+#include <grp.h>
+#include <pwd.h>
+
+#include <libgnome/gnome-defs.h>
+#include <libgnome/gnome-i18n.h>
+
+#include "nautilus-glib-extensions.h"
+#include "nautilus-string.h"
+#include "nautilus-directory-private.h"
+
+typedef enum {
+ NAUTILUS_DATE_TYPE_MODIFIED,
+ NAUTILUS_DATE_TYPE_CHANGED,
+ NAUTILUS_DATE_TYPE_ACCESSED
+} NautilusDateType;
+
+/* FIXME: This hack needs to die eventually. See comments with function */
+static int get_directory_item_count_hack (NautilusFile *file,
+ gboolean ignore_invisible_items);
+
+static int nautilus_file_compare_by_type (NautilusFile *file_1,
+ NautilusFile *file_2);
+static int nautilus_file_compare_for_sort_internal (NautilusFile *file_1,
+ NautilusFile *file_2,
+ NautilusFileSortType sort_type,
+ gboolean reversed);
+static char *nautilus_file_get_date_as_string (NautilusFile *file,
+ NautilusDateType date_type);
+static char *nautilus_file_get_owner_as_string (NautilusFile *file);
+static char *nautilus_file_get_group_as_string (NautilusFile *file);
+static char *nautilus_file_get_permissions_as_string (NautilusFile *file);
+static char *nautilus_file_get_size_as_string (NautilusFile *file);
+static char *nautilus_file_get_type_as_string (NautilusFile *file);
+
+/**
+ * nautilus_file_get:
+ * @uri: URI of file to get.
+ *
+ * Get a file given a uri.
+ * Returns a referenced object. Unref when finished.
+ * If two windows are viewing the same uri, the file object is shared.
+ */
+NautilusFile *
+nautilus_file_get (const char *uri)
+{
+ GnomeVFSResult result;
+ GnomeVFSFileInfo *file_info;
+ GnomeVFSURI *vfs_uri, *directory_vfs_uri;
+ char *directory_uri;
+ NautilusDirectory *directory;
+ NautilusFile *file;
+
+ /* Get info on the file. */
+ file_info = gnome_vfs_file_info_new ();
+ result = gnome_vfs_get_file_info (uri, file_info,
+ GNOME_VFS_FILE_INFO_GETMIMETYPE
+ | GNOME_VFS_FILE_INFO_FASTMIMETYPE
+ | GNOME_VFS_FILE_INFO_FOLLOWLINKS, NULL);
+ if (result != GNOME_VFS_OK)
+ return NULL;
+
+ /* Make VFS version of URI. */
+ vfs_uri = gnome_vfs_uri_new (uri);
+ if (vfs_uri == NULL)
+ return NULL;
+
+ /* Make VFS version of directory URI. */
+ directory_vfs_uri = gnome_vfs_uri_get_parent (vfs_uri);
+ gnome_vfs_uri_unref (vfs_uri);
+ if (directory_vfs_uri == NULL)
+ return NULL;
+
+ /* Make text version of directory URI. */
+ directory_uri = gnome_vfs_uri_to_string (directory_vfs_uri,
+ GNOME_VFS_URI_HIDE_NONE);
+ gnome_vfs_uri_unref (directory_vfs_uri);
+
+ /* Get object that represents the directory. */
+ directory = nautilus_directory_get (directory_uri);
+ g_free (directory_uri);
+ if (directory == NULL)
+ return NULL;
+
+ file = nautilus_directory_new_file (directory, file_info);
+
+ gnome_vfs_file_info_unref (file_info);
+ nautilus_file_ref (file);
+ gtk_object_unref (GTK_OBJECT (directory));
+
+ return file;
+}
+
+void
+nautilus_file_ref (NautilusFile *file)
+{
+ g_return_if_fail (file != NULL);
+
+ g_assert (file->ref_count < G_MAXINT);
+ g_assert (file->directory != NULL);
+
+ /* Increment the ref count. */
+ if (file->ref_count++ != 0) {
+ return;
+ }
+
+ /* As soon as someone other than the directory holds a ref,
+ * we need to hold the directory too. */
+ gtk_object_ref (GTK_OBJECT (file->directory));
+}
+
+void
+nautilus_file_unref (NautilusFile *file)
+{
+ g_return_if_fail (file != NULL);
+
+ g_assert (file->ref_count != 0);
+ g_assert (file->directory != NULL);
+
+ /* Decrement the ref count. */
+ if (--file->ref_count != 0) {
+ return;
+ }
+
+ /* No references left, so it's time to release our hold on the directory. */
+ gtk_object_unref (GTK_OBJECT (file->directory));
+ if (file->is_gone) {
+ nautilus_file_free (file);
+ }
+}
+
+void
+nautilus_file_free (NautilusFile *file)
+{
+ g_assert (file->ref_count == 0);
+
+ /* Destroy the file object. */
+ gnome_vfs_file_info_unref (file->info);
+ g_free (file);
+}
+
+static int
+nautilus_file_compare_by_size_with_directories (NautilusFile *file_1, NautilusFile *file_2)
+{
+ gboolean is_directory_1;
+ gboolean is_directory_2;
+ int item_count_1;
+ int item_count_2;
+
+ is_directory_1 = nautilus_file_is_directory (file_1);
+ is_directory_2 = nautilus_file_is_directory (file_2);
+
+ if (is_directory_1 && !is_directory_2)
+ return -1;
+
+ if (is_directory_2 && !is_directory_1)
+ return +1;
+
+ if (!is_directory_1 && !is_directory_2)
+ return 0;
+
+ /* Both are directories, compare by item count. */
+ /* FIXME: get_directory_item_count_hack is slow, and calling
+ * it for every pairwise comparison here is nasty. Need to
+ * change this to (not-yet-existent) architecture where the
+ * item count can be calculated once in a deferred way, and
+ * then stored or cached.
+ */
+ item_count_1 = get_directory_item_count_hack (file_1, FALSE);
+ item_count_2 = get_directory_item_count_hack (file_2, FALSE);
+
+ if (item_count_1 < item_count_2)
+ return -1;
+
+ if (item_count_2 < item_count_1)
+ return +1;
+
+ return 0;
+}
+
+static int
+nautilus_file_compare_by_type (NautilusFile *file_1, NautilusFile *file_2)
+{
+ gboolean is_directory_1;
+ gboolean is_directory_2;
+ char * type_string_1;
+ char * type_string_2;
+ int result;
+
+ /* Directories go first. Then, if mime types are identical,
+ * don't bother getting strings (for speed). This assumes
+ * that the string is dependent entirely on the mime type,
+ * which is true now but might not be later.
+ */
+ is_directory_1 = nautilus_file_is_directory (file_1);
+ is_directory_2 = nautilus_file_is_directory (file_2);
+
+ if (is_directory_1 && is_directory_2)
+ return 0;
+
+ if (is_directory_1)
+ return -1;
+
+ if (is_directory_2)
+ return +1;
+
+ if (nautilus_strcmp (file_1->info->mime_type, file_2->info->mime_type) == 0)
+ return 0;
+
+ type_string_1 = nautilus_file_get_type_as_string (file_1);
+ type_string_2 = nautilus_file_get_type_as_string (file_2);
+
+ result = nautilus_strcmp (type_string_1, type_string_2);
+
+ g_free (type_string_1);
+ g_free (type_string_2);
+
+ return result;
+}
+
+static int
+nautilus_file_compare_for_sort_internal (NautilusFile *file_1,
+ NautilusFile *file_2,
+ NautilusFileSortType sort_type,
+ gboolean reversed)
+{
+ GnomeVFSDirectorySortRule rules[3];
+ int compare;
+
+ g_return_val_if_fail (file_1 != NULL, 0);
+ g_return_val_if_fail (file_2 != NULL, 0);
+ g_return_val_if_fail (sort_type != NAUTILUS_FILE_SORT_NONE, 0);
+
+ switch (sort_type) {
+ case NAUTILUS_FILE_SORT_BY_NAME:
+ /* Note: This used to put directories first. I
+ * thought that was counterintuitive and removed it,
+ * but I can imagine discussing this further.
+ * John Sullivan <sullivan@eazel.com>
+ */
+ rules[0] = GNOME_VFS_DIRECTORY_SORT_BYNAME_IGNORECASE;
+ rules[1] = GNOME_VFS_DIRECTORY_SORT_NONE;
+ break;
+ case NAUTILUS_FILE_SORT_BY_SIZE:
+ /* Compare directory sizes ourselves, then if necessary
+ * use GnomeVFS to compare file sizes.
+ */
+ compare = nautilus_file_compare_by_size_with_directories (file_1, file_2);
+ if (compare != 0) {
+ return compare;
+ }
+ rules[0] = GNOME_VFS_DIRECTORY_SORT_BYSIZE;
+ rules[1] = GNOME_VFS_DIRECTORY_SORT_BYNAME_IGNORECASE;
+ rules[2] = GNOME_VFS_DIRECTORY_SORT_NONE;
+ break;
+ case NAUTILUS_FILE_SORT_BY_TYPE:
+ /* GnomeVFS doesn't know about our special text for certain
+ * mime types, so we handle the mime-type sorting ourselves.
+ */
+ compare = nautilus_file_compare_by_type (file_1, file_2);
+ if (compare != 0) {
+ return compare;
+ }
+ rules[0] = GNOME_VFS_DIRECTORY_SORT_BYNAME_IGNORECASE;
+ rules[1] = GNOME_VFS_DIRECTORY_SORT_NONE;
+ break;
+ case NAUTILUS_FILE_SORT_BY_MTIME:
+ rules[0] = GNOME_VFS_DIRECTORY_SORT_BYMTIME;
+ rules[1] = GNOME_VFS_DIRECTORY_SORT_BYNAME_IGNORECASE;
+ rules[2] = GNOME_VFS_DIRECTORY_SORT_NONE;
+ break;
+ default:
+ g_assert_not_reached ();
+ return 0;
+ }
+
+ if (reversed)
+ return gnome_vfs_file_info_compare_for_sort_reversed (file_1->info,
+ file_2->info,
+ rules);
+ else
+ return gnome_vfs_file_info_compare_for_sort (file_1->info,
+ file_2->info,
+ rules);
+}
+
+/**
+ * nautilus_file_compare_for_sort:
+ * @file_1: A file object
+ * @file_2: Another file object
+ * @sort_type: Sort criterion
+ *
+ * Return value: int < 0 if @file_1 should come before file_2 in a smallest-to-largest
+ * sorted list; int > 0 if @file_2 should come before file_1 in a smallest-to-largest
+ * sorted list; 0 if @file_1 and @file_2 are equal for this sort criterion. Note
+ * that each named sort type may actually break ties several ways, with the name
+ * of the sort criterion being the primary but not only differentiator.
+ **/
+int
+nautilus_file_compare_for_sort (NautilusFile *file_1,
+ NautilusFile *file_2,
+ NautilusFileSortType sort_type)
+{
+ return nautilus_file_compare_for_sort_internal (file_1, file_2, sort_type, FALSE);
+}
+
+/**
+ * nautilus_file_compare_for_sort_reversed:
+ * @file_1: A file object
+ * @file_2: Another file object
+ * @sort_type: Sort criterion
+ *
+ * Return value: The opposite of nautilus_file_compare_for_sort: int > 0 if @file_1
+ * should come before file_2 in a smallest-to-largest sorted list; int < 0 if @file_2
+ * should come before file_1 in a smallest-to-largest sorted list; 0 if @file_1
+ * and @file_2 are equal for this sort criterion. Note that each named sort type
+ * may actually break ties several ways, with the name of the sort criterion
+ * being the primary but not only differentiator.
+ **/
+int
+nautilus_file_compare_for_sort_reversed (NautilusFile *file_1,
+ NautilusFile *file_2,
+ NautilusFileSortType sort_type)
+{
+ return nautilus_file_compare_for_sort_internal (file_1, file_2, sort_type, TRUE);
+}
+
+char *
+nautilus_file_get_metadata (NautilusFile *file,
+ const char *tag,
+ const char *default_metadata)
+{
+ g_return_val_if_fail (file != NULL, NULL);
+
+ return nautilus_directory_get_file_metadata (file->directory,
+ file->info->name,
+ tag,
+ default_metadata);
+}
+
+void
+nautilus_file_set_metadata (NautilusFile *file,
+ const char *tag,
+ const char *default_metadata,
+ const char *metadata)
+{
+ g_return_if_fail (file != NULL);
+
+ nautilus_directory_set_file_metadata (file->directory,
+ file->info->name,
+ tag,
+ default_metadata,
+ metadata);
+}
+
+char *
+nautilus_file_get_name (NautilusFile *file)
+{
+ g_return_val_if_fail (file != NULL, NULL);
+
+ g_assert (file->directory == NULL || NAUTILUS_IS_DIRECTORY (file->directory));
+ g_assert (file->info->name != NULL);
+ g_assert (file->info->name[0] != '\0');
+
+ return g_strdup (file->info->name);
+}
+
+char *
+nautilus_file_get_uri (NautilusFile *file)
+{
+ GnomeVFSURI *uri;
+ char *uri_text;
+
+ g_return_val_if_fail (file != NULL, NULL);
+ g_return_val_if_fail (file->directory != NULL, NULL);
+
+ uri = gnome_vfs_uri_append_path (file->directory->details->uri, file->info->name);
+ uri_text = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE);
+ gnome_vfs_uri_unref (uri);
+ return uri_text;
+}
+
+/**
+ * nautilus_file_get_date_as_string:
+ *
+ * Get a user-displayable string representing a file modification date.
+ * The caller is responsible for g_free-ing this string.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: Newly allocated string ready to display to the user.
+ *
+ **/
+static char *
+nautilus_file_get_date_as_string (NautilusFile *file, NautilusDateType date_type)
+{
+ struct tm *file_time;
+ const char *format;
+ GDate *today;
+ GDate *file_date;
+ guint32 file_date_age;
+
+ g_return_val_if_fail (file != NULL, NULL);
+
+ switch (date_type)
+ {
+ case NAUTILUS_DATE_TYPE_CHANGED:
+ file_time = localtime(&file->info->ctime);
+ break;
+ case NAUTILUS_DATE_TYPE_ACCESSED:
+ file_time = localtime(&file->info->atime);
+ break;
+ case NAUTILUS_DATE_TYPE_MODIFIED:
+ file_time = localtime(&file->info->mtime);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ file_date = nautilus_g_date_new_tm (file_time);
+
+ today = g_date_new ();
+ g_date_set_time (today, time (NULL));
+
+ /* Overflow results in a large number; fine for our purposes. */
+ file_date_age = g_date_julian (today) - g_date_julian (file_date);
+
+ g_date_free (file_date);
+ g_date_free (today);
+
+ /* Format varies depending on how old the date is. This minimizes
+ * the length (and thus clutter & complication) of typical dates
+ * while providing sufficient detail for recent dates to make
+ * them maximally understandable at a glance. Keep all format
+ * strings separate rather than combining bits & pieces for
+ * internationalization's sake.
+ */
+
+ if (file_date_age == 0)
+ {
+ /* today, use special word */
+ format = _("today %-I:%M %p");
+ }
+ else if (file_date_age == 1)
+ {
+ /* yesterday, use special word */
+ format = _("yesterday %-I:%M %p");
+ }
+ else if (file_date_age < 7)
+ {
+ /* current week, include day of week */
+ format = _("%A %-m/%-d/%y %-I:%M %p");
+ }
+ else
+ {
+ format = _("%-m/%-d/%y %-I:%M %p");
+ }
+
+ return nautilus_strdup_strftime (format, file_time);
+}
+
+/**
+ * nautilus_file_get_directory_item_count
+ *
+ * Get the number of items in a directory.
+ * @file: NautilusFile representing a directory. It is an error to
+ * call this function on a file that is not a directory.
+ * @ignore_invisible_items: TRUE if invisible items should not be
+ * included in count.
+ *
+ * Returns: item count for this directory.
+ *
+ **/
+guint
+nautilus_file_get_directory_item_count (NautilusFile *file,
+ gboolean ignore_invisible_items)
+{
+ g_return_val_if_fail (nautilus_file_is_directory (file), 0);
+
+ return get_directory_item_count_hack (file, ignore_invisible_items);
+}
+
+/**
+ * nautilus_file_get_size
+ *
+ * Get the file size.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: Size in bytes.
+ *
+ **/
+GnomeVFSFileSize
+nautilus_file_get_size (NautilusFile *file)
+{
+ g_return_val_if_fail (file != NULL, 0);
+
+ return file->info->size;
+}
+
+/**
+ * nautilus_file_get_permissions_as_string:
+ *
+ * Get a user-displayable string representing a file's permissions. The caller
+ * is responsible for g_free-ing this string.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: Newly allocated string ready to display to the user.
+ *
+ **/
+static char *
+nautilus_file_get_permissions_as_string (NautilusFile *file)
+{
+ GnomeVFSFilePermissions permissions;
+ gboolean is_directory;
+ gboolean is_link;
+
+ permissions = file->info->permissions;
+ is_directory = nautilus_file_is_directory (file);
+ is_link = GNOME_VFS_FILE_INFO_SYMLINK(file->info);
+
+ return g_strdup_printf ("%c%c%c%c%c%c%c%c%c%c",
+ is_link ? 'l' : is_directory ? 'd' : '-',
+ permissions & GNOME_VFS_PERM_USER_READ ? 'r' : '-',
+ permissions & GNOME_VFS_PERM_USER_WRITE ? 'w' : '-',
+ permissions & GNOME_VFS_PERM_USER_EXEC ? 'x' : '-',
+ permissions & GNOME_VFS_PERM_GROUP_READ ? 'r' : '-',
+ permissions & GNOME_VFS_PERM_GROUP_WRITE ? 'w' : '-',
+ permissions & GNOME_VFS_PERM_GROUP_EXEC ? 'x' : '-',
+ permissions & GNOME_VFS_PERM_OTHER_READ ? 'r' : '-',
+ permissions & GNOME_VFS_PERM_OTHER_WRITE ? 'w' : '-',
+ permissions & GNOME_VFS_PERM_OTHER_EXEC ? 'x' : '-');
+}
+
+/**
+ * nautilus_file_get_owner_as_string:
+ *
+ * Get a user-displayable string representing a file's owner. The caller
+ * is responsible for g_free-ing this string.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: Newly allocated string ready to display to the user.
+ *
+ **/
+static char *
+nautilus_file_get_owner_as_string (NautilusFile *file)
+{
+ struct passwd *password_info;
+
+ /* FIXME: Can we trust the uid in the file info? Might
+ * there be garbage there? What will it do for non-local files?
+ */
+ /* No need to free result of getpwuid */
+ password_info = getpwuid (file->info->uid);
+
+ g_print ("pointer to password info is %p\n", password_info);
+
+ if (password_info == NULL)
+ {
+ return g_strdup (_("unknown owner"));
+ }
+
+ return g_strdup (password_info->pw_name);
+}
+
+/**
+ * nautilus_file_get_group_as_string:
+ *
+ * Get a user-displayable string representing a file's group. The caller
+ * is responsible for g_free-ing this string.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: Newly allocated string ready to display to the user.
+ *
+ **/
+static char *
+nautilus_file_get_group_as_string (NautilusFile *file)
+{
+ struct group *group_info;
+
+ /* FIXME: Can we trust the gid in the file info? Might
+ * there be garbage there? What will it do for non-local files?
+ */
+ /* No need to free result of getgrgid */
+ group_info = getgrgid (file->info->gid);
+
+ if (group_info == NULL)
+ {
+ return g_strdup (_("unknown group"));
+ }
+
+ return g_strdup (group_info->gr_name);
+}
+
+
+/* This #include is part of the following hack, and should be removed with it */
+#include <dirent.h>
+
+static int
+get_directory_item_count_hack (NautilusFile *file, gboolean ignore_invisible_items)
+{
+ /* Code borrowed from Gnomad and hacked into here for now */
+
+ char * uri;
+ char * path;
+ DIR* directory;
+ int count;
+ struct dirent * entry;
+
+ g_assert (nautilus_file_is_directory (file));
+
+ uri = nautilus_file_get_uri (file);
+ if (nautilus_has_prefix (uri, "file://"))
+ path = uri + 7;
+ else
+ path = uri;
+
+ directory = opendir (path);
+
+ g_free (uri);
+
+ if (!directory)
+ return 0;
+
+ count = 0;
+
+ while ((entry = readdir(directory)) != NULL)
+ // Only count invisible items if requested.
+ if (!ignore_invisible_items || entry->d_name[0] != '.')
+ count += 1;
+
+ closedir(directory);
+
+ /* This way of getting the count includes . and .., so we subtract those out */
+ if (!ignore_invisible_items) {
+ count -= 2;
+ }
+
+ return count;
+}
+
+/**
+ * nautilus_file_get_size_as_string:
+ *
+ * Get a user-displayable string representing a file size. The caller
+ * is responsible for g_free-ing this string. The string is an item
+ * count for directories.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: Newly allocated string ready to display to the user.
+ *
+ **/
+static char *
+nautilus_file_get_size_as_string (NautilusFile *file)
+{
+ g_return_val_if_fail (file != NULL, NULL);
+
+ if (nautilus_file_is_directory (file))
+ {
+ /* FIXME: Since computing the item count is slow, we
+ * want to do it in a deferred way. However, that
+ * architecture doesn't exist yet, so we're hacking
+ * it in for now.
+ */
+ int item_count;
+
+ item_count = get_directory_item_count_hack (file, FALSE);
+ if (item_count == 0) {
+ return g_strdup (_("0 items"));
+ } else if (item_count == 1) {
+ return g_strdup (_("1 item"));
+ } else {
+ return g_strdup_printf (_("%d items"), item_count);
+ }
+ }
+
+ return gnome_vfs_file_size_to_string (file->info->size);
+}
+
+/**
+ * nautilus_file_get_string_attribute:
+ *
+ * Get a user-displayable string from a named attribute. Use g_free to
+ * free this string.
+ *
+ * @file: NautilusFile representing the file in question.
+ * @attribute_name: The name of the desired attribute. The currently supported
+ * set includes "name", "type", "size", "date_modified", "date_changed",
+ * "date_accessed", "owner", "group", "permissions".
+ *
+ * Returns: Newly allocated string ready to display to the user, or NULL
+ * if @attribute_name is not supported.
+ *
+ **/
+char *
+nautilus_file_get_string_attribute (NautilusFile *file, const char *attribute_name)
+{
+ /* FIXME: Use hash table and switch statement or function pointers for speed? */
+
+ if (strcmp (attribute_name, "name") == 0) {
+ return nautilus_file_get_name (file);
+ }
+
+ if (strcmp (attribute_name, "type") == 0) {
+ return nautilus_file_get_type_as_string (file);
+ }
+
+ if (strcmp (attribute_name, "size") == 0) {
+ return nautilus_file_get_size_as_string (file);
+ }
+
+ if (strcmp (attribute_name, "date_modified") == 0) {
+ return nautilus_file_get_date_as_string (file,
+ NAUTILUS_DATE_TYPE_MODIFIED);
+ }
+
+ if (strcmp (attribute_name, "date_changed") == 0) {
+ return nautilus_file_get_date_as_string (file,
+ NAUTILUS_DATE_TYPE_CHANGED);
+ }
+
+ if (strcmp (attribute_name, "date_accessed") == 0) {
+ return nautilus_file_get_date_as_string (file,
+ NAUTILUS_DATE_TYPE_ACCESSED);
+ }
+
+ if (strcmp (attribute_name, "permissions") == 0) {
+ return nautilus_file_get_permissions_as_string (file);
+ }
+
+ if (strcmp (attribute_name, "owner") == 0) {
+ return nautilus_file_get_owner_as_string (file);
+ }
+
+ if (strcmp (attribute_name, "group") == 0) {
+ return nautilus_file_get_group_as_string (file);
+ }
+
+ return NULL;
+}
+
+/**
+ * nautilus_file_get_type_as_string:
+ *
+ * Get a user-displayable string representing a file type. The caller
+ * is responsible for g_free-ing this string.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: Newly allocated string ready to display to the user.
+ *
+ **/
+static char *
+nautilus_file_get_type_as_string (NautilusFile *file)
+{
+ g_return_val_if_fail (file != NULL, NULL);
+
+ if (nautilus_file_is_directory (file)) {
+ /* Special-case this so it isn't "special/directory".
+ * FIXME: Should this be "folder" instead?
+ */
+ return g_strdup (_("directory"));
+ }
+
+ if (nautilus_strlen (file->info->mime_type) == 0) {
+ return g_strdup (_("unknown type"));
+ }
+
+ return g_strdup (file->info->mime_type);
+}
+
+/**
+ * nautilus_file_get_type
+ *
+ * Return this file's type.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: The type.
+ *
+ **/
+GnomeVFSFileType
+nautilus_file_get_type (NautilusFile *file)
+{
+ g_return_val_if_fail (file != NULL, FALSE);
+
+ return file->info->type;
+}
+
+/**
+ * nautilus_file_get_mime_type
+ *
+ * Return this file's mime type.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: The mime type.
+ *
+ **/
+const char *
+nautilus_file_get_mime_type (NautilusFile *file)
+{
+ g_return_val_if_fail (file != NULL, FALSE);
+
+ return file->info->mime_type;
+}
+
+/**
+ * nautilus_file_get_keywords
+ *
+ * Return this file's keywords.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: A list of keywords.
+ *
+ **/
+GList *
+nautilus_file_get_keywords (NautilusFile *file)
+{
+ GList *keywords;
+ xmlNode *file_node, *child;
+ xmlChar *property;
+
+ g_return_val_if_fail (file != NULL, NULL);
+
+ keywords = NULL;
+
+ /* Put all the keywords into a list. */
+ file_node = nautilus_directory_get_file_metadata_node (file->directory, file->info->name);
+ if (file_node != NULL) {
+ for (child = file_node->childs; child != NULL; child = child->next) {
+ if (strcmp (child->name, "KEYWORD") == 0) {
+ property = xmlGetProp (child, "NAME");
+ if (property != NULL) {
+ keywords = g_list_prepend (keywords,
+ g_strdup (property));
+ }
+ }
+ }
+ }
+
+ return g_list_reverse (keywords);
+}
+
+/**
+ * nautilus_file_is_symbolic_link
+ *
+ * Check if this file is a symbolic link.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: True if the file is a symbolic link.
+ *
+ **/
+gboolean
+nautilus_file_is_symbolic_link (NautilusFile *file)
+{
+ g_return_val_if_fail (file != NULL, FALSE);
+
+ return GNOME_VFS_FILE_INFO_SYMLINK (file->info);
+}
+
+/**
+ * nautilus_file_is_directory
+ *
+ * Check if this file is a directory.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: TRUE if @file is a directory.
+ *
+ **/
+gboolean
+nautilus_file_is_directory (NautilusFile *file)
+{
+ g_return_val_if_fail (file != NULL, FALSE);
+
+ return nautilus_file_get_type (file) == GNOME_VFS_FILE_TYPE_DIRECTORY;
+}
+
+/**
+ * nautilus_file_is_executable
+ *
+ * Check if this file is executable at all.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: True if any of the execute bits are set.
+ *
+ **/
+gboolean
+nautilus_file_is_executable (NautilusFile *file)
+{
+ g_return_val_if_fail (file != NULL, FALSE);
+
+ return (file->info->flags & (GNOME_VFS_PERM_USER_EXEC
+ | GNOME_VFS_PERM_GROUP_EXEC
+ | GNOME_VFS_PERM_OTHER_EXEC)) != 0;
+}
+
+/**
+ * nautilus_file_delete
+ *
+ * Delete this file.
+ * @file: NautilusFile representing the file in question.
+ **/
+void
+nautilus_file_delete (NautilusFile *file)
+{
+ char *text_uri;
+ GnomeVFSResult result;
+ GList *removed_files;
+
+ g_return_if_fail (file != NULL);
+
+ /* Deleting a file that's already gone is easy. */
+ if (file->is_gone) {
+ return;
+ }
+
+ /* Do the actual deletion. */
+ text_uri = nautilus_file_get_uri (file);
+ if (nautilus_file_is_directory (file)) {
+ result = gnome_vfs_remove_directory (text_uri);
+ } else {
+ result = gnome_vfs_unlink (text_uri);
+ }
+ g_free (text_uri);
+
+ /* Mark the file gone. */
+ if (result == GNOME_VFS_OK || result == GNOME_VFS_ERROR_NOTFOUND) {
+ file->is_gone = TRUE;
+
+ /* Let the directory know it's gone. */
+ if (file->directory != NULL) {
+ g_list_remove (file->directory->details->files, file);
+
+ /* Send out a signal. */
+ removed_files = g_list_prepend (NULL, file);
+ nautilus_directory_files_removed (file->directory, removed_files);
+ g_list_free (removed_files);
+ }
+ }
+}
+
+/**
+ * nautilus_file_is_gone
+ *
+ * Check if a file has already been deleted.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: TRUE if the file is already gone.
+ **/
+gboolean
+nautilus_file_is_gone (NautilusFile *file)
+{
+ g_return_val_if_fail (file != NULL, FALSE);
+
+ return file->is_gone;
+}
+
+/**
+ * nautilus_file_list_ref
+ *
+ * Ref all the files in a list.
+ * @file_list: GList of files.
+ **/
+void
+nautilus_file_list_ref (GList *file_list)
+{
+ g_list_foreach (file_list, (GFunc) nautilus_file_ref, NULL);
+}
+
+/**
+ * nautilus_file_list_unref
+ *
+ * Unref all the files in a list.
+ * @file_list: GList of files.
+ **/
+void
+nautilus_file_list_unref (GList *file_list)
+{
+ g_list_foreach (file_list, (GFunc) nautilus_file_ref, NULL);
+}
+
+/**
+ * nautilus_file_list_free
+ *
+ * Free a list of files after unrefing them.
+ * @file_list: GList of files.
+ **/
+void
+nautilus_file_list_free (GList *file_list)
+{
+ nautilus_file_list_unref (file_list);
+ g_list_free (file_list);
+}
diff --git a/libnautilus-private/nautilus-file.h b/libnautilus-private/nautilus-file.h
new file mode 100644
index 000000000..dc06290b5
--- /dev/null
+++ b/libnautilus-private/nautilus-file.h
@@ -0,0 +1,106 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+
+ nautilus-file.h: Nautilus file model.
+
+ Copyright (C) 1999, 2000 Eazel, Inc.
+
+ 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 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 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 Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Darin Adler <darin@eazel.com>
+*/
+
+#ifndef NAUTILUS_FILE_H
+#define NAUTILUS_FILE_H
+
+#include <glib.h> /* gnome-vfs-types.h requires glib.h but doesn't include it */
+#include <libgnomevfs/gnome-vfs-types.h>
+
+/* NautilusFile is an object used to represent a single element of a
+ * NautilusDirectory. It's lightweight and relies on NautilusDirectory
+ * to do most of the work.
+ */
+
+typedef enum {
+ NAUTILUS_FILE_SORT_NONE,
+ NAUTILUS_FILE_SORT_BY_NAME,
+ NAUTILUS_FILE_SORT_BY_SIZE,
+ NAUTILUS_FILE_SORT_BY_TYPE,
+ NAUTILUS_FILE_SORT_BY_MTIME
+} NautilusFileSortType;
+
+typedef struct NautilusFile NautilusFile;
+
+#define NAUTILUS_IS_FILE(object) \
+ ((object) != NULL)
+#define NAUTILUS_FILE(file) \
+ ((NautilusFile *)(file))
+
+/* Getting at a single file. */
+NautilusFile * nautilus_file_get (const char *uri);
+
+/* Basic operations on file objects. */
+void nautilus_file_ref (NautilusFile *file);
+void nautilus_file_unref (NautilusFile *file);
+void nautilus_file_delete (NautilusFile *file);
+
+/* Basic attributes for file objects. */
+char * nautilus_file_get_name (NautilusFile *file);
+char * nautilus_file_get_uri (NautilusFile *file);
+GnomeVFSFileSize nautilus_file_get_size (NautilusFile *file);
+GnomeVFSFileType nautilus_file_get_type (NautilusFile *file);
+const char * nautilus_file_get_mime_type (NautilusFile *file);
+gboolean nautilus_file_is_symbolic_link (NautilusFile *file);
+gboolean nautilus_file_is_executable (NautilusFile *file);
+gboolean nautilus_file_is_directory (NautilusFile *file);
+guint nautilus_file_get_directory_item_count (NautilusFile *file,
+ gboolean ignore_invisible_items);
+GList * nautilus_file_get_keywords (NautilusFile *file);
+void nautilus_file_set_keywords (NautilusFile *file,
+ GList *keywords);
+
+/* Simple getting and setting top-level metadata. */
+char * nautilus_file_get_metadata (NautilusFile *file,
+ const char *tag,
+ const char *default_metadata);
+void nautilus_file_set_metadata (NautilusFile *file,
+ const char *tag,
+ const char *default_metadata,
+ const char *metadata);
+
+/* Attributes for file objects as user-displayable strings. */
+char * nautilus_file_get_string_attribute (NautilusFile *file,
+ const char *attribute_name);
+
+/* Comparing two file objects for sorting */
+int nautilus_file_compare_for_sort (NautilusFile *file_1,
+ NautilusFile *file_2,
+ NautilusFileSortType sort_type);
+int nautilus_file_compare_for_sort_reversed (NautilusFile *file_1,
+ NautilusFile *file_2,
+ NautilusFileSortType sort_type);
+
+/* Convenience functions for dealing with a list of NautilusFile objects that each have a ref. */
+void nautilus_file_list_ref (GList *file_list);
+void nautilus_file_list_unref (GList *file_list);
+void nautilus_file_list_free (GList *file_list);
+
+/* Return true if this file has already been deleted.
+ This object will be unref'd after sending the files_removed signal,
+ but it could hang around longer if someone ref'd it.
+*/
+gboolean nautilus_file_is_gone (NautilusFile *file);
+
+#endif /* NAUTILUS_FILE_H */
diff --git a/libnautilus-private/nautilus-icon-factory.h b/libnautilus-private/nautilus-icon-factory.h
index 545211440..3e7bfa903 100644
--- a/libnautilus-private/nautilus-icon-factory.h
+++ b/libnautilus-private/nautilus-icon-factory.h
@@ -2,7 +2,7 @@
nautilus-icon-factory.h: Class for obtaining icons for files and other objects.
- * Copyright (C) 1999, 2000 Red Hat Inc.
+ Copyright (C) 1999, 2000 Red Hat Inc.
Copyright (C) 1999, 2000 Eazel, Inc.
This program is free software; you can redistribute it and/or
@@ -27,7 +27,8 @@
#define NAUTILUS_ICON_FACTORY_H
#include <gdk-pixbuf/gdk-pixbuf.h>
-#include <libnautilus/nautilus-directory.h>
+#include <libnautilus/nautilus-file.h>
+#include <gtk/gtkobject.h>
/* NautilusIconFactory is a class that knows how to hand out icons to be
* used for representing files and some other objects. It was designed
@@ -97,8 +98,8 @@ char * nautilus_icon_factory_get_theme (void);
void nautilus_icon_factory_set_theme (const char *theme_name);
/* Choose the appropriate icon, but don't render it yet. */
-NautilusScalableIcon *nautilus_icon_factory_get_icon_for_file (NautilusFile *file,
- void *controller);
+NautilusScalableIcon *nautilus_icon_factory_get_icon_for_file (NautilusFile *file,
+ void *controller);
NautilusScalableIcon *nautilus_icon_factory_get_icon_by_name (const char *icon_name);
GList * nautilus_icon_factory_get_emblem_icons_for_file (NautilusFile *file);
diff --git a/libnautilus-private/nautilus-string.c b/libnautilus-private/nautilus-string.c
index d2df8e286..c3ac00d5e 100644
--- a/libnautilus-private/nautilus-string.c
+++ b/libnautilus-private/nautilus-string.c
@@ -69,10 +69,12 @@ nautilus_has_prefix (const char *haystack_null_allowed, const char *needle_null_
h = haystack_null_allowed == NULL ? "" : haystack_null_allowed;
n = needle_null_allowed == NULL ? "" : needle_null_allowed;
do {
- if (*n == '\0')
+ if (*n == '\0') {
return TRUE;
- if (*h == '\0')
+ }
+ if (*h == '\0') {
return FALSE;
+ }
} while (*h++ == *n++);
return FALSE;
}
@@ -82,19 +84,23 @@ nautilus_has_suffix (const char *haystack_null_allowed, const char *needle_null_
{
const char *h, *n;
- if (haystack_null_allowed == NULL)
+ if (needle_null_allowed == NULL) {
return TRUE;
- if (needle_null_allowed == NULL)
- return FALSE;
+ }
+ if (haystack_null_allowed == NULL) {
+ return needle_null_allowed[0] == '\0';
+ }
/* Eat one character at a time. */
h = haystack_null_allowed + strlen(haystack_null_allowed);
n = needle_null_allowed + strlen(needle_null_allowed);
do {
- if (n == needle_null_allowed)
+ if (n == needle_null_allowed) {
return TRUE;
- if (h == haystack_null_allowed)
+ }
+ if (h == haystack_null_allowed) {
return FALSE;
+ }
} while (*--h == *--n);
return FALSE;
}
@@ -144,23 +150,28 @@ nautilus_string_to_int (const char *string, int *integer)
char *parse_end;
/* Check for the case of an empty string. */
- if (string == NULL || *string == '\0')
+ if (string == NULL || *string == '\0') {
return FALSE;
+ }
/* Call the standard library routine to do the conversion. */
errno = 0;
result = strtol (string, &parse_end, 0);
/* Check that the result is in range. */
- if ((result == G_MINLONG || result == G_MAXLONG) && errno == ERANGE)
+ if ((result == G_MINLONG || result == G_MAXLONG) && errno == ERANGE) {
return FALSE;
- if (result < G_MININT || result > G_MAXINT)
+ }
+ if (result < G_MININT || result > G_MAXINT) {
return FALSE;
+ }
/* Check that all the trailing characters are spaces. */
- while (*parse_end != '\0')
- if (!isspace (*parse_end++))
+ while (*parse_end != '\0') {
+ if (!isspace (*parse_end++)) {
return FALSE;
+ }
+ }
/* Return the result. */
*integer = result;
@@ -170,27 +181,27 @@ nautilus_string_to_int (const char *string, int *integer)
/**
* nautilus_strstrip:
* Remove all occurrences of a character from a string. The
- * original string is modified, and also returned for convenience.
+ * original string is modified in place, and also returned for convenience.
*
* @string_null_allowed: The string to be stripped.
* @remove_this: The char to remove from @string_null_allowed
*
* Return value: @string_null_allowed, after removing all occurrences
- * of @remove_this.
+ * of @remove_this.
*/
char *
nautilus_strstrip (char *string_null_allowed, char remove_this)
{
if (string_null_allowed != NULL) {
- char *pos;
+ char *in, *out;
- pos = string_null_allowed;
- while (*pos != '\0') {
- if (*pos == remove_this) {
- g_memmove (pos, pos + 1, strlen (pos));
+ in = string_null_allowed;
+ out = string_null_allowed;
+ do {
+ if (*in != remove_this) {
+ *out++ = *in;
}
- ++pos;
- }
+ } while (*in++ != '\0');
}
return string_null_allowed;
@@ -232,7 +243,6 @@ void
nautilus_self_check_string (void)
{
int integer;
- char *test_string;
NAUTILUS_CHECK_INTEGER_RESULT (nautilus_strlen (NULL), 0);
NAUTILUS_CHECK_INTEGER_RESULT (nautilus_strlen (""), 0);
@@ -283,6 +293,22 @@ nautilus_self_check_string (void)
NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_prefix ("aaa", "aaab"), FALSE);
NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_prefix ("aaab", "aaa"), TRUE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix (NULL, NULL), TRUE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix (NULL, ""), TRUE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("", NULL), TRUE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("a", "a"), TRUE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("aaab", "aaab"), TRUE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix (NULL, "a"), FALSE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("a", NULL), TRUE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("", "a"), FALSE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("a", ""), TRUE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("a", "b"), FALSE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("a", "ab"), FALSE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("ab", "a"), FALSE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("ab", "b"), TRUE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("aaa", "baaa"), FALSE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("baaa", "aaa"), TRUE);
+
NAUTILUS_CHECK_STRING_RESULT (nautilus_strdup_prefix (NULL, NULL), NULL);
NAUTILUS_CHECK_STRING_RESULT (nautilus_strdup_prefix (NULL, "foo"), NULL);
NAUTILUS_CHECK_STRING_RESULT (nautilus_strdup_prefix ("foo", NULL), "foo");
@@ -292,14 +318,11 @@ nautilus_self_check_string (void)
NAUTILUS_CHECK_STRING_RESULT (nautilus_strdup_prefix ("footle:bar", "tle:"), "foo");
NAUTILUS_CHECK_STRING_RESULT (nautilus_strstrip (NULL, '_'), NULL);
- test_string = g_strdup ("foo");
- NAUTILUS_CHECK_STRING_RESULT (nautilus_strstrip (test_string, '_'), "foo");
- test_string = g_strdup ("_foo");
- NAUTILUS_CHECK_STRING_RESULT (nautilus_strstrip (test_string, '_'), "foo");
- test_string = g_strdup ("foo_");
- NAUTILUS_CHECK_STRING_RESULT (nautilus_strstrip (test_string, '_'), "foo");
- test_string = g_strdup ("_foo_");
- NAUTILUS_CHECK_STRING_RESULT (nautilus_strstrip (test_string, '_'), "foo");
+ NAUTILUS_CHECK_STRING_RESULT (nautilus_strstrip (g_strdup ("foo"), '_'), "foo");
+ NAUTILUS_CHECK_STRING_RESULT (nautilus_strstrip (g_strdup ("_foo"), '_'), "foo");
+ NAUTILUS_CHECK_STRING_RESULT (nautilus_strstrip (g_strdup ("foo_"), '_'), "foo");
+ NAUTILUS_CHECK_STRING_RESULT (nautilus_strstrip (g_strdup ("_foo_"), '_'), "foo");
+ NAUTILUS_CHECK_STRING_RESULT (nautilus_strstrip (g_strdup ("_f_o__o_"), '_'), "foo");
#define TEST_INTEGER_CONVERSION_FUNCTIONS(string, boolean_result, integer_result) \
NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_string_to_int (string, &integer), boolean_result); \
diff --git a/libnautilus-private/nautilus-string.h b/libnautilus-private/nautilus-string.h
index 9d269dcd7..03c778f00 100644
--- a/libnautilus-private/nautilus-string.h
+++ b/libnautilus-private/nautilus-string.h
@@ -47,8 +47,8 @@ char * nautilus_strdup_prefix (const char *source_null_allowed,
gboolean nautilus_has_suffix (const char *target_null_allowed,
const char *suffix_null_allowed);
-char * nautilus_strstrip (char *string_null_allowed,
- char remove_this);
+char * nautilus_strstrip (char *string_null_allowed,
+ char remove_this);
/* Conversions to and from strings. */
diff --git a/libnautilus/Makefile.am b/libnautilus/Makefile.am
index 4e65cefad..002601a80 100644
--- a/libnautilus/Makefile.am
+++ b/libnautilus/Makefile.am
@@ -27,8 +27,6 @@ libnautilusincludedir=$(includedir)/libnautilus
libnautilusinclude_HEADERS= \
bonobo-stream-vfs.h \
gdk-extensions.h \
- gnome-icon-container-dnd.h \
- gnome-icon-container-private.h \
gnome-icon-container.h \
gtkflist.h \
gtkscrollframe.h \
@@ -38,13 +36,13 @@ libnautilusinclude_HEADERS= \
nautilus-bookmark.h \
nautilus-debug.h \
nautilus-directory.h \
+ nautilus-file.h \
nautilus-file-utilities.h \
nautilus-glib-extensions.h \
nautilus-gtk-extensions.h \
nautilus-icon-factory.h \
nautilus-icons-controller.h \
nautilus-icons-view-icon-item.h \
- nautilus-lib-self-check-functions.h \
nautilus-metadata.h \
nautilus-mime-type.h \
nautilus-self-checks.h \
@@ -68,6 +66,7 @@ libnautilus_la_SOURCES=$(nautilus_idl_sources) \
nautilus-default-file-icon.c \
nautilus-default-file-icon.h \
nautilus-directory.c \
+ nautilus-file.c \
nautilus-file-utilities.c \
nautilus-glib-extensions.c \
nautilus-gtk-extensions.c \
diff --git a/libnautilus/gnome-icon-container-dnd.c b/libnautilus/gnome-icon-container-dnd.c
index 987556da1..1057c984d 100644
--- a/libnautilus/gnome-icon-container-dnd.c
+++ b/libnautilus/gnome-icon-container-dnd.c
@@ -816,12 +816,12 @@ gnome_icon_container_dnd_begin_drag (GnomeIconContainer *container,
gtk_object_getv (GTK_OBJECT (item), 1, &pixbuf_arg);
pixbuf = GTK_VALUE_BOXED (pixbuf_arg);
- transparent_pixbuf = make_semi_transparent(pixbuf);
+ transparent_pixbuf = make_semi_transparent (pixbuf);
gdk_pixbuf_render_pixmap_and_mask (transparent_pixbuf,
&pixmap_for_dragged_file,
&mask_for_dragged_file,
128);
- gdk_pixbuf_unref(transparent_pixbuf);
+ gdk_pixbuf_unref (transparent_pixbuf);
/* compute the image's offset */
nautilus_icons_view_icon_item_get_icon_window_rectangle
diff --git a/libnautilus/gnome-icon-container.c b/libnautilus/gnome-icon-container.c
index 20ada54d2..ddf28423e 100644
--- a/libnautilus/gnome-icon-container.c
+++ b/libnautilus/gnome-icon-container.c
@@ -724,15 +724,17 @@ make_icon_visible (GnomeIconContainer *container,
icon_get_bounding_box (icon, &x1, &y1, &x2, &y2);
- if (y1 < vadj->value)
+ if (y1 < vadj->value) {
gtk_adjustment_set_value (vadj, y1);
- else if (y2 > vadj->value + allocation->height)
+ } else if (y2 > vadj->value + allocation->height) {
gtk_adjustment_set_value (vadj, y2 - allocation->height);
+ }
- if (x1 < hadj->value)
+ if (x1 < hadj->value) {
gtk_adjustment_set_value (hadj, x1);
- else if (x2 > hadj->value + allocation->width)
+ } else if (x2 > hadj->value + allocation->width) {
gtk_adjustment_set_value (hadj, x2 - allocation->width);
+ }
}
static gboolean
@@ -2145,6 +2147,17 @@ gnome_icon_container_initialize_class (GnomeIconContainerClass *class)
stipple = gdk_bitmap_create_from_data (NULL, stipple_bits, 2, 2);
}
+static GdkFont *
+load_font (const char *name)
+{
+ GdkFont *font;
+
+ /* FIXME: Eventually we need a runtime check, but an assert is better than nothing. */
+ font = gdk_font_load (name);
+ g_assert (font != NULL);
+ return font;
+}
+
static void
gnome_icon_container_initialize (GnomeIconContainer *container)
{
@@ -2159,15 +2172,15 @@ gnome_icon_container_initialize (GnomeIconContainer *container)
details->zoom_level = NAUTILUS_ZOOM_LEVEL_STANDARD;
- /* font table - this isnt exactly proportional, but it looks better than computed */
+ /* font table - this isn't exactly proportional, but it looks better than computed */
/* FIXME: read font from metadata and/or preferences */
- details->label_font[NAUTILUS_ZOOM_LEVEL_SMALLEST] = gdk_font_load("-*-helvetica-medium-r-normal-*-8-*-*-*-*-*-*-*");
- details->label_font[NAUTILUS_ZOOM_LEVEL_SMALLER] = gdk_font_load("-*-helvetica-medium-r-normal-*-8-*-*-*-*-*-*-*");
- details->label_font[NAUTILUS_ZOOM_LEVEL_SMALL] = gdk_font_load("-*-helvetica-medium-r-normal-*-10-*-*-*-*-*-*-*");
- details->label_font[NAUTILUS_ZOOM_LEVEL_STANDARD] = gdk_font_load("-*-helvetica-medium-r-normal-*-12-*-*-*-*-*-*-*");
- details->label_font[NAUTILUS_ZOOM_LEVEL_LARGE] = gdk_font_load("-*-helvetica-medium-r-normal-*-14-*-*-*-*-*-*-*");
- details->label_font[NAUTILUS_ZOOM_LEVEL_LARGER] = gdk_font_load("-*-helveticar-medium-r-normal-*-18-*-*-*-*-*-*-*");
- details->label_font[NAUTILUS_ZOOM_LEVEL_LARGEST] = gdk_font_load("-*-helvetica-medium-r-normal-*-18-*-*-*-*-*-*-*");
+ details->label_font[NAUTILUS_ZOOM_LEVEL_SMALLEST] = load_font ("-*-helvetica-medium-r-normal-*-8-*-*-*-*-*-*-*");
+ details->label_font[NAUTILUS_ZOOM_LEVEL_SMALLER] = load_font ("-*-helvetica-medium-r-normal-*-8-*-*-*-*-*-*-*");
+ details->label_font[NAUTILUS_ZOOM_LEVEL_SMALL] = load_font ("-*-helvetica-medium-r-normal-*-10-*-*-*-*-*-*-*");
+ details->label_font[NAUTILUS_ZOOM_LEVEL_STANDARD] = load_font ("-*-helvetica-medium-r-normal-*-12-*-*-*-*-*-*-*");
+ details->label_font[NAUTILUS_ZOOM_LEVEL_LARGE] = load_font ("-*-helvetica-medium-r-normal-*-14-*-*-*-*-*-*-*");
+ details->label_font[NAUTILUS_ZOOM_LEVEL_LARGER] = load_font ("-*-helvetica-medium-r-normal-*-18-*-*-*-*-*-*-*");
+ details->label_font[NAUTILUS_ZOOM_LEVEL_LARGEST] = load_font ("-*-helvetica-medium-r-normal-*-18-*-*-*-*-*-*-*");
/* FIXME: Read these from preferences. */
details->linger_selection_mode = FALSE;
diff --git a/libnautilus/nautilus-directory-private.h b/libnautilus/nautilus-directory-private.h
new file mode 100644
index 000000000..12496a3f6
--- /dev/null
+++ b/libnautilus/nautilus-directory-private.h
@@ -0,0 +1,72 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+
+ nautilus-directory.c: Nautilus directory model.
+
+ Copyright (C) 1999, 2000 Eazel, Inc.
+
+ 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 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 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 Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Darin Adler <darin@eazel.com>
+*/
+
+#include "nautilus-directory.h"
+
+#include <libgnomevfs/gnome-vfs-types.h>
+#include <libgnomevfs/gnome-vfs-uri.h>
+#include <libgnomevfs/gnome-vfs-file-info.h>
+
+#include <gnome-xml/tree.h>
+
+#include "nautilus-file.h"
+
+struct NautilusDirectoryDetails
+{
+ char *uri_text;
+ GnomeVFSURI *uri;
+
+ GnomeVFSURI *metafile_uri;
+ GnomeVFSURI *alternate_metafile_uri;
+ gboolean use_alternate_metafile;
+
+ xmlDoc *metafile_tree;
+ guint write_metafile_idle_id;
+
+ GnomeVFSAsyncHandle *directory_load_in_progress;
+ GnomeVFSDirectoryListPosition directory_load_list_last_handled;
+
+ GList *pending_file_info;
+ guint dequeue_pending_idle_id;
+
+ gboolean directory_loaded;
+
+ GList *files;
+};
+
+NautilusFile *nautilus_directory_new_file (NautilusDirectory *directory,
+ GnomeVFSFileInfo *info);
+char * nautilus_directory_get_file_metadata (NautilusDirectory *directory,
+ const char *file_name,
+ const char *tag,
+ const char *default_metadata);
+void nautilus_directory_set_file_metadata (NautilusDirectory *directory,
+ const char *file_name,
+ const char *tag,
+ const char *default_metadata,
+ const char *metadata);
+xmlNode * nautilus_directory_get_file_metadata_node (NautilusDirectory *directory,
+ const char *file_name);
+void nautilus_directory_files_removed (NautilusDirectory *directory,
+ GList *removed_files);
diff --git a/libnautilus/nautilus-directory.c b/libnautilus/nautilus-directory.c
index 643c290db..eaa37ac68 100644
--- a/libnautilus/nautilus-directory.c
+++ b/libnautilus/nautilus-directory.c
@@ -1,6 +1,6 @@
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
- nautilus-directory.c: Mautilus directory model.
+ nautilus-directory.c: Nautilus directory model.
Copyright (C) 1999, 2000 Eazel, Inc.
@@ -23,33 +23,20 @@
*/
#include <config.h>
-#include "nautilus-directory.h"
+#include "nautilus-directory-private.h"
-#include <grp.h>
-#include <pwd.h>
#include <stdlib.h>
#include <gtk/gtksignal.h>
#include <gtk/gtkmain.h>
-#include <libgnome/gnome-defs.h>
-#include <libgnome/gnome-i18n.h>
-
-#include <libgnomevfs/gnome-vfs-types.h>
-#include <libgnomevfs/gnome-vfs-uri.h>
-#include <libgnomevfs/gnome-vfs-file-info.h>
-#include <libgnomevfs/gnome-vfs-ops.h>
-#include <libgnomevfs/gnome-vfs-async-ops.h>
-
#include <gnome-xml/parser.h>
-#include <gnome-xml/tree.h>
#include <gnome-xml/xmlmemory.h>
-#include "nautilus-alloc.h"
-#include "nautilus-glib-extensions.h"
#include "nautilus-gtk-macros.h"
-#include "nautilus-lib-self-check-functions.h"
#include "nautilus-string.h"
+#include "nautilus-lib-self-check-functions.h"
+#include "nautilus-file-private.h"
#define METAFILE_NAME ".nautilus-metafile.xml"
#define METAFILE_PERMISSIONS (GNOME_VFS_PERM_USER_READ | GNOME_VFS_PERM_USER_WRITE \
@@ -67,12 +54,6 @@
#define DIRECTORY_LOAD_ITEMS_PER_CB 1
-typedef enum {
- NAUTILUS_DATE_TYPE_MODIFIED,
- NAUTILUS_DATE_TYPE_CHANGED,
- NAUTILUS_DATE_TYPE_ACCESSED
-} NautilusDateType;
-
enum
{
FILES_ADDED,
@@ -80,79 +61,25 @@ enum
LAST_SIGNAL
};
-/* FIXME: This hack needs to die eventually. See comments with function */
-static int get_directory_item_count_hack (NautilusFile *file, gboolean ignore_invisible_items);
-
-
static guint nautilus_directory_signals[LAST_SIGNAL];
-static void nautilus_directory_initialize_class (gpointer klass);
-static void nautilus_directory_initialize (gpointer object, gpointer klass);
-static void nautilus_directory_finalize (GtkObject *object);
-
-static NautilusDirectory *nautilus_directory_new (const char* uri);
-
-static void nautilus_directory_read_metafile (NautilusDirectory *directory);
-static void nautilus_directory_write_metafile (NautilusDirectory *directory);
-static void nautilus_directory_request_write_metafile (NautilusDirectory *directory);
-static void nautilus_directory_remove_write_metafile_idle (NautilusDirectory *directory);
-
-static void nautilus_file_free (NautilusFile *file);
-static int nautilus_file_compare_by_type (NautilusFile *file_1, NautilusFile *file_2);
-static int nautilus_file_compare_for_sort_internal (NautilusFile *file_1,
- NautilusFile *file_2,
- NautilusFileSortType sort_type,
- gboolean reversed);
-
-static char * nautilus_file_get_date_as_string (NautilusFile *file,
- NautilusDateType date_type);
-static char *nautilus_file_get_owner_as_string (NautilusFile *file);
-static char *nautilus_file_get_group_as_string (NautilusFile *file);
-static char *nautilus_file_get_permissions_as_string (NautilusFile *file);
-static char * nautilus_file_get_size_as_string (NautilusFile *file);
-static char * nautilus_file_get_type_as_string (NautilusFile *file);
-static void nautilus_directory_load_cb (GnomeVFSAsyncHandle *handle,
- GnomeVFSResult result,
- GnomeVFSDirectoryList *list,
- guint entries_read,
- gpointer callback_data);
-static NautilusFile *nautilus_directory_new_file (NautilusDirectory *directory,
- GnomeVFSFileInfo *info);
+static void nautilus_directory_initialize_class (gpointer klass);
+static void nautilus_directory_initialize (gpointer object,
+ gpointer klass);
+static void nautilus_directory_finalize (GtkObject *object);
+static NautilusDirectory *nautilus_directory_new (const char *uri);
+static void nautilus_directory_read_metafile (NautilusDirectory *directory);
+static void nautilus_directory_write_metafile (NautilusDirectory *directory);
+static void nautilus_directory_request_write_metafile (NautilusDirectory *directory);
+static void nautilus_directory_remove_write_metafile_idle (NautilusDirectory *directory);
+static void nautilus_directory_load_cb (GnomeVFSAsyncHandle *handle,
+ GnomeVFSResult result,
+ GnomeVFSDirectoryList *list,
+ guint entries_read,
+ gpointer callback_data);
NAUTILUS_DEFINE_CLASS_BOILERPLATE (NautilusDirectory, nautilus_directory, GTK_TYPE_OBJECT)
-struct NautilusDirectoryDetails
-{
- char *uri_text;
- GnomeVFSURI *uri;
-
- GnomeVFSURI *metafile_uri;
- GnomeVFSURI *alternate_metafile_uri;
- gboolean use_alternate_metafile;
-
- xmlDoc *metafile_tree;
- guint write_metafile_idle_id;
-
- GnomeVFSAsyncHandle *directory_load_in_progress;
- GnomeVFSDirectoryListPosition directory_load_list_last_handled;
-
- GList *pending_file_info;
- guint dequeue_pending_idle_id;
-
- gboolean directory_loaded;
-
- GList *files;
-};
-
-struct NautilusFile
-{
- guint ref_count;
-
- NautilusDirectory *directory;
- GnomeVFSFileInfo *info;
- gboolean is_gone;
-};
-
static GHashTable* directory_objects;
static void
@@ -1005,9 +932,9 @@ nautilus_directory_set_integer_metadata (NautilusDirectory *directory,
g_free (default_as_string);
}
-static xmlNode *
-get_file_metadata_node (NautilusDirectory *directory,
- const char *file_name)
+xmlNode *
+nautilus_directory_get_file_metadata_node (NautilusDirectory *directory,
+ const char *file_name)
{
xmlNode *root, *child;
xmlChar *property;
@@ -1038,18 +965,18 @@ get_file_metadata_node (NautilusDirectory *directory,
return NULL;
}
-static char *
+char *
nautilus_directory_get_file_metadata (NautilusDirectory *directory,
const char *file_name,
const char *tag,
const char *default_metadata)
{
return nautilus_directory_get_metadata_from_node
- (get_file_metadata_node (directory, file_name),
+ (nautilus_directory_get_file_metadata_node (directory, file_name),
tag, default_metadata);
}
-static void
+void
nautilus_directory_set_file_metadata (NautilusDirectory *directory,
const char *file_name,
const char *tag,
@@ -1118,7 +1045,7 @@ nautilus_directory_set_file_metadata (NautilusDirectory *directory,
nautilus_directory_request_write_metafile (directory);
}
-static NautilusFile *
+NautilusFile *
nautilus_directory_new_file (NautilusDirectory *directory, GnomeVFSFileInfo *info)
{
NautilusFile *file;
@@ -1135,973 +1062,13 @@ nautilus_directory_new_file (NautilusDirectory *directory, GnomeVFSFileInfo *inf
return file;
}
-/**
- * nautilus_file_get:
- * @uri: URI of file to get.
- *
- * Get a file given a uri.
- * Returns a referenced object. Unref when finished.
- * If two windows are viewing the same uri, the file object is shared.
- */
-NautilusFile *
-nautilus_file_get (const char *uri)
-{
- GnomeVFSResult result;
- GnomeVFSFileInfo *file_info;
- GnomeVFSURI *vfs_uri, *directory_vfs_uri;
- char *directory_uri;
- NautilusDirectory *directory;
- NautilusFile *file;
-
- /* Get info on the file. */
- file_info = gnome_vfs_file_info_new ();
- result = gnome_vfs_get_file_info (uri, file_info,
- GNOME_VFS_FILE_INFO_GETMIMETYPE
- | GNOME_VFS_FILE_INFO_FASTMIMETYPE
- | GNOME_VFS_FILE_INFO_FOLLOWLINKS, NULL);
- if (result != GNOME_VFS_OK)
- return NULL;
-
- /* Make VFS version of URI. */
- vfs_uri = gnome_vfs_uri_new (uri);
- if (vfs_uri == NULL)
- return NULL;
-
- /* Make VFS version of directory URI. */
- directory_vfs_uri = gnome_vfs_uri_get_parent (vfs_uri);
- gnome_vfs_uri_unref (vfs_uri);
- if (directory_vfs_uri == NULL)
- return NULL;
-
- /* Make text version of directory URI. */
- directory_uri = gnome_vfs_uri_to_string (directory_vfs_uri,
- GNOME_VFS_URI_HIDE_NONE);
- gnome_vfs_uri_unref (directory_vfs_uri);
-
- /* Get object that represents the directory. */
- directory = nautilus_directory_get (directory_uri);
- g_free (directory_uri);
- if (directory == NULL)
- return NULL;
-
- file = nautilus_directory_new_file (directory, file_info);
-
- gnome_vfs_file_info_unref (file_info);
- nautilus_file_ref (file);
- gtk_object_unref (GTK_OBJECT (directory));
-
- return file;
-}
-
-void
-nautilus_file_ref (NautilusFile *file)
-{
- g_return_if_fail (file != NULL);
-
- g_assert (file->ref_count < G_MAXINT);
- g_assert (file->directory != NULL);
-
- /* Increment the ref count. */
- if (file->ref_count++ != 0) {
- return;
- }
-
- /* As soon as someone other than the directory holds a ref,
- * we need to hold the directory too. */
- gtk_object_ref (GTK_OBJECT (file->directory));
-}
-
-void
-nautilus_file_unref (NautilusFile *file)
-{
- g_return_if_fail (file != NULL);
-
- g_assert (file->ref_count != 0);
- g_assert (file->directory != NULL);
-
- /* Decrement the ref count. */
- if (--file->ref_count != 0) {
- return;
- }
-
- /* No references left, so it's time to release our hold on the directory. */
- gtk_object_unref (GTK_OBJECT (file->directory));
- if (file->is_gone) {
- nautilus_file_free (file);
- }
-}
-
-static void
-nautilus_file_free (NautilusFile *file)
-{
- g_assert (file->ref_count == 0);
-
- /* Destroy the file object. */
- gnome_vfs_file_info_unref (file->info);
- g_free (file);
-}
-
-static int
-nautilus_file_compare_by_size_with_directories (NautilusFile *file_1, NautilusFile *file_2)
-{
- gboolean is_directory_1;
- gboolean is_directory_2;
- int item_count_1;
- int item_count_2;
-
- is_directory_1 = nautilus_file_is_directory (file_1);
- is_directory_2 = nautilus_file_is_directory (file_2);
-
- if (is_directory_1 && !is_directory_2)
- return -1;
-
- if (is_directory_2 && !is_directory_1)
- return +1;
-
- if (!is_directory_1 && !is_directory_2)
- return 0;
-
- /* Both are directories, compare by item count. */
- /* FIXME: get_directory_item_count_hack is slow, and calling
- * it for every pairwise comparison here is nasty. Need to
- * change this to (not-yet-existent) architecture where the
- * item count can be calculated once in a deferred way, and
- * then stored or cached.
- */
- item_count_1 = get_directory_item_count_hack (file_1, FALSE);
- item_count_2 = get_directory_item_count_hack (file_2, FALSE);
-
- if (item_count_1 < item_count_2)
- return -1;
-
- if (item_count_2 < item_count_1)
- return +1;
-
- return 0;
-}
-
-static int
-nautilus_file_compare_by_type (NautilusFile *file_1, NautilusFile *file_2)
-{
- gboolean is_directory_1;
- gboolean is_directory_2;
- char * type_string_1;
- char * type_string_2;
- int result;
-
- /* Directories go first. Then, if mime types are identical,
- * don't bother getting strings (for speed). This assumes
- * that the string is dependent entirely on the mime type,
- * which is true now but might not be later.
- */
- is_directory_1 = nautilus_file_is_directory (file_1);
- is_directory_2 = nautilus_file_is_directory (file_2);
-
- if (is_directory_1 && is_directory_2)
- return 0;
-
- if (is_directory_1)
- return -1;
-
- if (is_directory_2)
- return +1;
-
- if (nautilus_strcmp (file_1->info->mime_type, file_2->info->mime_type) == 0)
- return 0;
-
- type_string_1 = nautilus_file_get_type_as_string (file_1);
- type_string_2 = nautilus_file_get_type_as_string (file_2);
-
- result = nautilus_strcmp (type_string_1, type_string_2);
-
- g_free (type_string_1);
- g_free (type_string_2);
-
- return result;
-}
-
-static int
-nautilus_file_compare_for_sort_internal (NautilusFile *file_1,
- NautilusFile *file_2,
- NautilusFileSortType sort_type,
- gboolean reversed)
-{
- GnomeVFSDirectorySortRule *rules;
-
- g_return_val_if_fail (file_1 != NULL, 0);
- g_return_val_if_fail (file_2 != NULL, 0);
- g_return_val_if_fail (sort_type != NAUTILUS_FILE_SORT_NONE, 0);
-
-#define ALLOC_RULES(n) alloca ((n) * sizeof (GnomeVFSDirectorySortRule))
-
- switch (sort_type) {
- case NAUTILUS_FILE_SORT_BY_NAME:
- rules = ALLOC_RULES (2);
- /* Note: This used to put directories first. I
- * thought that was counterintuitive and removed it,
- * but I can imagine discussing this further.
- * John Sullivan <sullivan@eazel.com>
- */
- rules[0] = GNOME_VFS_DIRECTORY_SORT_BYNAME_IGNORECASE;
- rules[1] = GNOME_VFS_DIRECTORY_SORT_NONE;
- break;
- case NAUTILUS_FILE_SORT_BY_SIZE:
- /* Compare directory sizes ourselves, then if necessary
- * use GnomeVFS to compare file sizes.
- */
- {
- int size_compare;
-
- size_compare = nautilus_file_compare_by_size_with_directories (file_1, file_2);
- if (size_compare != 0)
- return size_compare;
- }
- rules = ALLOC_RULES (3);
- rules[0] = GNOME_VFS_DIRECTORY_SORT_BYSIZE;
- rules[1] = GNOME_VFS_DIRECTORY_SORT_BYNAME_IGNORECASE;
- rules[2] = GNOME_VFS_DIRECTORY_SORT_NONE;
- break;
- case NAUTILUS_FILE_SORT_BY_TYPE:
- /* GnomeVFS doesn't know about our special text for certain
- * mime types, so we handle the mime-type sorting ourselves.
- */
- {
- int type_compare;
-
- type_compare = nautilus_file_compare_by_type (file_1, file_2);
- if (type_compare != 0)
- return type_compare;
- }
- rules = ALLOC_RULES (2);
- rules[0] = GNOME_VFS_DIRECTORY_SORT_BYNAME_IGNORECASE;
- rules[1] = GNOME_VFS_DIRECTORY_SORT_NONE;
- break;
- case NAUTILUS_FILE_SORT_BY_MTIME:
- rules = ALLOC_RULES (3);
- rules[0] = GNOME_VFS_DIRECTORY_SORT_BYMTIME;
- rules[1] = GNOME_VFS_DIRECTORY_SORT_BYNAME_IGNORECASE;
- rules[2] = GNOME_VFS_DIRECTORY_SORT_NONE;
- break;
- default:
- g_assert_not_reached ();
- return 0;
- }
-
- if (reversed)
- return gnome_vfs_file_info_compare_for_sort_reversed (file_1->info,
- file_2->info,
- rules);
- else
- return gnome_vfs_file_info_compare_for_sort (file_1->info,
- file_2->info,
- rules);
-
-#undef ALLOC_RULES
-}
-
-/**
- * nautilus_file_compare_for_sort:
- * @file_1: A file object
- * @file_2: Another file object
- * @sort_type: Sort criterion
- *
- * Return value: int < 0 if @file_1 should come before file_2 in a smallest-to-largest
- * sorted list; int > 0 if @file_2 should come before file_1 in a smallest-to-largest
- * sorted list; 0 if @file_1 and @file_2 are equal for this sort criterion. Note
- * that each named sort type may actually break ties several ways, with the name
- * of the sort criterion being the primary but not only differentiator.
- **/
-int
-nautilus_file_compare_for_sort (NautilusFile *file_1,
- NautilusFile *file_2,
- NautilusFileSortType sort_type)
-{
- return nautilus_file_compare_for_sort_internal (file_1, file_2, sort_type, FALSE);
-}
-
-/**
- * nautilus_file_compare_for_sort_reversed:
- * @file_1: A file object
- * @file_2: Another file object
- * @sort_type: Sort criterion
- *
- * Return value: The opposite of nautilus_file_compare_for_sort: int > 0 if @file_1
- * should come before file_2 in a smallest-to-largest sorted list; int < 0 if @file_2
- * should come before file_1 in a smallest-to-largest sorted list; 0 if @file_1
- * and @file_2 are equal for this sort criterion. Note that each named sort type
- * may actually break ties several ways, with the name of the sort criterion
- * being the primary but not only differentiator.
- **/
-int
-nautilus_file_compare_for_sort_reversed (NautilusFile *file_1,
- NautilusFile *file_2,
- NautilusFileSortType sort_type)
-{
- return nautilus_file_compare_for_sort_internal (file_1, file_2, sort_type, TRUE);
-}
-
-char *
-nautilus_file_get_metadata (NautilusFile *file,
- const char *tag,
- const char *default_metadata)
-{
- g_return_val_if_fail (file != NULL, NULL);
-
- return nautilus_directory_get_file_metadata (file->directory,
- file->info->name,
- tag,
- default_metadata);
-}
-
void
-nautilus_file_set_metadata (NautilusFile *file,
- const char *tag,
- const char *default_metadata,
- const char *metadata)
+nautilus_directory_files_removed (NautilusDirectory *directory,
+ GList *removed_files)
{
- g_return_if_fail (file != NULL);
-
- nautilus_directory_set_file_metadata (file->directory,
- file->info->name,
- tag,
- default_metadata,
- metadata);
-}
-
-char *
-nautilus_file_get_name (NautilusFile *file)
-{
- g_return_val_if_fail (file != NULL, NULL);
-
- g_assert (file->directory == NULL || NAUTILUS_IS_DIRECTORY (file->directory));
- g_assert (file->info->name != NULL);
- g_assert (file->info->name[0] != '\0');
-
- return g_strdup (file->info->name);
-}
-
-char *
-nautilus_file_get_uri (NautilusFile *file)
-{
- GnomeVFSURI *uri;
- char *uri_text;
-
- g_return_val_if_fail (file != NULL, NULL);
- g_return_val_if_fail (file->directory != NULL, NULL);
-
- uri = gnome_vfs_uri_append_path (file->directory->details->uri, file->info->name);
- uri_text = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE);
- gnome_vfs_uri_unref (uri);
- return uri_text;
-}
-
-/**
- * nautilus_file_get_date_as_string:
- *
- * Get a user-displayable string representing a file modification date.
- * The caller is responsible for g_free-ing this string.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: Newly allocated string ready to display to the user.
- *
- **/
-static char *
-nautilus_file_get_date_as_string (NautilusFile *file, NautilusDateType date_type)
-{
- struct tm *file_time;
- const char *format;
- GDate *today;
- GDate *file_date;
- guint32 file_date_age;
-
- g_return_val_if_fail (file != NULL, NULL);
-
- switch (date_type)
- {
- case NAUTILUS_DATE_TYPE_CHANGED:
- file_time = localtime(&file->info->ctime);
- break;
- case NAUTILUS_DATE_TYPE_ACCESSED:
- file_time = localtime(&file->info->atime);
- break;
- case NAUTILUS_DATE_TYPE_MODIFIED:
- file_time = localtime(&file->info->mtime);
- break;
- default:
- g_assert_not_reached ();
- }
- file_date = nautilus_g_date_new_tm (file_time);
-
- today = g_date_new ();
- g_date_set_time (today, time (NULL));
-
- /* Overflow results in a large number; fine for our purposes. */
- file_date_age = g_date_julian (today) - g_date_julian (file_date);
-
- g_date_free (file_date);
- g_date_free (today);
-
- /* Format varies depending on how old the date is. This minimizes
- * the length (and thus clutter & complication) of typical dates
- * while providing sufficient detail for recent dates to make
- * them maximally understandable at a glance. Keep all format
- * strings separate rather than combining bits & pieces for
- * internationalization's sake.
- */
-
- if (file_date_age == 0)
- {
- /* today, use special word */
- format = _("today %-I:%M %p");
- }
- else if (file_date_age == 1)
- {
- /* yesterday, use special word */
- format = _("yesterday %-I:%M %p");
- }
- else if (file_date_age < 7)
- {
- /* current week, include day of week */
- format = _("%A %-m/%-d/%y %-I:%M %p");
- }
- else
- {
- format = _("%-m/%-d/%y %-I:%M %p");
- }
-
- return nautilus_strdup_strftime (format, file_time);
-}
-
-/**
- * nautilus_file_get_directory_item_count
- *
- * Get the number of items in a directory.
- * @file: NautilusFile representing a directory. It is an error to
- * call this function on a file that is not a directory.
- * @ignore_invisible_items: TRUE if invisible items should not be
- * included in count.
- *
- * Returns: item count for this directory.
- *
- **/
-guint
-nautilus_file_get_directory_item_count (NautilusFile *file,
- gboolean ignore_invisible_items)
-{
- g_return_val_if_fail (nautilus_file_is_directory (file), 0);
-
- return get_directory_item_count_hack (file, ignore_invisible_items);
-}
-
-/**
- * nautilus_file_get_size
- *
- * Get the file size.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: Size in bytes.
- *
- **/
-GnomeVFSFileSize
-nautilus_file_get_size (NautilusFile *file)
-{
- g_return_val_if_fail (file != NULL, 0);
-
- return file->info->size;
-}
-
-/**
- * nautilus_file_get_permissions_as_string:
- *
- * Get a user-displayable string representing a file's permissions. The caller
- * is responsible for g_free-ing this string.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: Newly allocated string ready to display to the user.
- *
- **/
-static char *
-nautilus_file_get_permissions_as_string (NautilusFile *file)
-{
- GnomeVFSFilePermissions permissions;
- gboolean is_directory;
- gboolean is_link;
-
- permissions = file->info->permissions;
- is_directory = nautilus_file_is_directory (file);
- is_link = GNOME_VFS_FILE_INFO_SYMLINK(file->info);
-
- return g_strdup_printf ("%c%c%c%c%c%c%c%c%c%c",
- is_link ? 'l' : is_directory ? 'd' : '-',
- permissions & GNOME_VFS_PERM_USER_READ ? 'r' : '-',
- permissions & GNOME_VFS_PERM_USER_WRITE ? 'w' : '-',
- permissions & GNOME_VFS_PERM_USER_EXEC ? 'x' : '-',
- permissions & GNOME_VFS_PERM_GROUP_READ ? 'r' : '-',
- permissions & GNOME_VFS_PERM_GROUP_WRITE ? 'w' : '-',
- permissions & GNOME_VFS_PERM_GROUP_EXEC ? 'x' : '-',
- permissions & GNOME_VFS_PERM_OTHER_READ ? 'r' : '-',
- permissions & GNOME_VFS_PERM_OTHER_WRITE ? 'w' : '-',
- permissions & GNOME_VFS_PERM_OTHER_EXEC ? 'x' : '-');
-}
-
-/**
- * nautilus_file_get_owner_as_string:
- *
- * Get a user-displayable string representing a file's owner. The caller
- * is responsible for g_free-ing this string.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: Newly allocated string ready to display to the user.
- *
- **/
-static char *
-nautilus_file_get_owner_as_string (NautilusFile *file)
-{
- struct passwd *password_info;
-
- /* FIXME: Can we trust the uid in the file info? Might
- * there be garbage there? What will it do for non-local files?
- */
- /* No need to free result of getpwuid */
- password_info = getpwuid (file->info->uid);
-
- g_print ("pointer to password info is %p\n", password_info);
-
- if (password_info == NULL)
- {
- return g_strdup (_("unknown owner"));
- }
-
- return g_strdup (password_info->pw_name);
-}
-
-/**
- * nautilus_file_get_group_as_string:
- *
- * Get a user-displayable string representing a file's group. The caller
- * is responsible for g_free-ing this string.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: Newly allocated string ready to display to the user.
- *
- **/
-static char *
-nautilus_file_get_group_as_string (NautilusFile *file)
-{
- struct group *group_info;
-
- /* FIXME: Can we trust the gid in the file info? Might
- * there be garbage there? What will it do for non-local files?
- */
- /* No need to free result of getgrgid */
- group_info = getgrgid (file->info->gid);
-
- if (group_info == NULL)
- {
- return g_strdup (_("unknown group"));
- }
-
- return g_strdup (group_info->gr_name);
-}
-
-
-/* This #include is part of the following hack, and should be removed with it */
-#include <dirent.h>
-
-static int
-get_directory_item_count_hack (NautilusFile *file, gboolean ignore_invisible_items)
-{
- /* Code borrowed from Gnomad and hacked into here for now */
-
- char * uri;
- char * path;
- DIR* directory;
- int count;
- struct dirent * entry;
-
- g_assert (nautilus_file_is_directory (file));
-
- uri = nautilus_file_get_uri (file);
- if (nautilus_has_prefix (uri, "file://"))
- path = uri + 7;
- else
- path = uri;
-
- directory = opendir (path);
-
- g_free (uri);
-
- if (!directory)
- return 0;
-
- count = 0;
-
- while ((entry = readdir(directory)) != NULL)
- // Only count invisible items if requested.
- if (!ignore_invisible_items || entry->d_name[0] != '.')
- count += 1;
-
- closedir(directory);
-
- /* This way of getting the count includes . and .., so we subtract those out */
- if (!ignore_invisible_items) {
- count -= 2;
- }
-
- return count;
-}
-
-/**
- * nautilus_file_get_size_as_string:
- *
- * Get a user-displayable string representing a file size. The caller
- * is responsible for g_free-ing this string. The string is an item
- * count for directories.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: Newly allocated string ready to display to the user.
- *
- **/
-static char *
-nautilus_file_get_size_as_string (NautilusFile *file)
-{
- g_return_val_if_fail (file != NULL, NULL);
-
- if (nautilus_file_is_directory (file))
- {
- /* FIXME: Since computing the item count is slow, we
- * want to do it in a deferred way. However, that
- * architecture doesn't exist yet, so we're hacking
- * it in for now.
- */
- int item_count;
-
- item_count = get_directory_item_count_hack (file, FALSE);
- if (item_count == 0) {
- return g_strdup (_("0 items"));
- } else if (item_count == 1) {
- return g_strdup (_("1 item"));
- } else {
- return g_strdup_printf (_("%d items"), item_count);
- }
- }
-
- return gnome_vfs_file_size_to_string (file->info->size);
-}
-
-/**
- * nautilus_file_get_string_attribute:
- *
- * Get a user-displayable string from a named attribute. Use g_free to
- * free this string.
- *
- * @file: NautilusFile representing the file in question.
- * @attribute_name: The name of the desired attribute. The currently supported
- * set includes "name", "type", "size", "date_modified", "date_changed",
- * "date_accessed", "owner", "group", "permissions".
- *
- * Returns: Newly allocated string ready to display to the user, or NULL
- * if @attribute_name is not supported.
- *
- **/
-char *
-nautilus_file_get_string_attribute (NautilusFile *file, const char *attribute_name)
-{
- /* FIXME: Use hash table and switch statement or function pointers for speed? */
-
- if (strcmp (attribute_name, "name") == 0) {
- return nautilus_file_get_name (file);
- }
-
- if (strcmp (attribute_name, "type") == 0) {
- return nautilus_file_get_type_as_string (file);
- }
-
- if (strcmp (attribute_name, "size") == 0) {
- return nautilus_file_get_size_as_string (file);
- }
-
- if (strcmp (attribute_name, "date_modified") == 0) {
- return nautilus_file_get_date_as_string (file,
- NAUTILUS_DATE_TYPE_MODIFIED);
- }
-
- if (strcmp (attribute_name, "date_changed") == 0) {
- return nautilus_file_get_date_as_string (file,
- NAUTILUS_DATE_TYPE_CHANGED);
- }
-
- if (strcmp (attribute_name, "date_accessed") == 0) {
- return nautilus_file_get_date_as_string (file,
- NAUTILUS_DATE_TYPE_ACCESSED);
- }
-
- if (strcmp (attribute_name, "permissions") == 0) {
- return nautilus_file_get_permissions_as_string (file);
- }
-
- if (strcmp (attribute_name, "owner") == 0) {
- return nautilus_file_get_owner_as_string (file);
- }
-
- if (strcmp (attribute_name, "group") == 0) {
- return nautilus_file_get_group_as_string (file);
- }
-
- return NULL;
-}
-
-/**
- * nautilus_file_get_type_as_string:
- *
- * Get a user-displayable string representing a file type. The caller
- * is responsible for g_free-ing this string.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: Newly allocated string ready to display to the user.
- *
- **/
-static char *
-nautilus_file_get_type_as_string (NautilusFile *file)
-{
- g_return_val_if_fail (file != NULL, NULL);
-
- if (nautilus_file_is_directory (file)) {
- /* Special-case this so it isn't "special/directory".
- * FIXME: Should this be "folder" instead?
- */
- return g_strdup (_("directory"));
- }
-
- if (nautilus_strlen (file->info->mime_type) == 0) {
- return g_strdup (_("unknown type"));
- }
-
- return g_strdup (file->info->mime_type);
-}
-
-/**
- * nautilus_file_get_type
- *
- * Return this file's type.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: The type.
- *
- **/
-GnomeVFSFileType
-nautilus_file_get_type (NautilusFile *file)
-{
- g_return_val_if_fail (file != NULL, FALSE);
-
- return file->info->type;
-}
-
-/**
- * nautilus_file_get_mime_type
- *
- * Return this file's mime type.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: The mime type.
- *
- **/
-const char *
-nautilus_file_get_mime_type (NautilusFile *file)
-{
- g_return_val_if_fail (file != NULL, FALSE);
-
- return file->info->mime_type;
-}
-
-/**
- * nautilus_file_get_keywords
- *
- * Return this file's keywords.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: A list of keywords.
- *
- **/
-GList *
-nautilus_file_get_keywords (NautilusFile *file)
-{
- GList *keywords;
- xmlNode *file_node, *child;
- xmlChar *property;
-
- g_return_val_if_fail (file != NULL, NULL);
-
- keywords = NULL;
-
- /* Put all the keywords into a list. */
- file_node = get_file_metadata_node (file->directory, file->info->name);
- if (file_node != NULL) {
- for (child = file_node->childs; child != NULL; child = child->next) {
- if (strcmp (child->name, "KEYWORD") == 0) {
- property = xmlGetProp (child, "NAME");
- if (property != NULL) {
- keywords = g_list_prepend (keywords,
- g_strdup (property));
- }
- }
- }
- }
-
- return g_list_reverse (keywords);
-}
-
-/**
- * nautilus_file_is_symbolic_link
- *
- * Check if this file is a symbolic link.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: True if the file is a symbolic link.
- *
- **/
-gboolean
-nautilus_file_is_symbolic_link (NautilusFile *file)
-{
- g_return_val_if_fail (file != NULL, FALSE);
-
- return GNOME_VFS_FILE_INFO_SYMLINK (file->info);
-}
-
-/**
- * nautilus_file_is_directory
- *
- * Check if this file is a directory.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: TRUE if @file is a directory.
- *
- **/
-gboolean
-nautilus_file_is_directory (NautilusFile *file)
-{
- g_return_val_if_fail (file != NULL, FALSE);
-
- return nautilus_file_get_type (file) == GNOME_VFS_FILE_TYPE_DIRECTORY;
-}
-
-/**
- * nautilus_file_is_executable
- *
- * Check if this file is executable at all.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: True if any of the execute bits are set.
- *
- **/
-gboolean
-nautilus_file_is_executable (NautilusFile *file)
-{
- g_return_val_if_fail (file != NULL, FALSE);
-
- return (file->info->flags & (GNOME_VFS_PERM_USER_EXEC
- | GNOME_VFS_PERM_GROUP_EXEC
- | GNOME_VFS_PERM_OTHER_EXEC)) != 0;
-}
-
-/**
- * nautilus_file_delete
- *
- * Delete this file.
- * @file: NautilusFile representing the file in question.
- **/
-void
-nautilus_file_delete (NautilusFile *file)
-{
- char *text_uri;
- GnomeVFSResult result;
- GList *removed_files;
-
- g_return_if_fail (file != NULL);
-
- /* Deleting a file that's already gone is easy. */
- if (file->is_gone) {
- return;
- }
-
- /* Do the actual deletion. */
- text_uri = nautilus_file_get_uri (file);
- if (nautilus_file_is_directory (file)) {
- result = gnome_vfs_remove_directory (text_uri);
- } else {
- result = gnome_vfs_unlink (text_uri);
- }
- g_free (text_uri);
-
- /* Mark the file gone. */
- if (result == GNOME_VFS_OK || result == GNOME_VFS_ERROR_NOTFOUND) {
- file->is_gone = TRUE;
-
- /* Let the directory know it's gone. */
- if (file->directory != NULL) {
- g_list_remove (file->directory->details->files, file);
-
- /* Send out a message. */
- removed_files = g_list_prepend (NULL, file);
- gtk_signal_emit (GTK_OBJECT (file->directory),
- nautilus_directory_signals[FILES_REMOVED],
- removed_files);
- g_list_free (removed_files);
- }
- }
-}
-
-/**
- * nautilus_file_is_gone
- *
- * Check if a file has already been deleted.
- * @file: NautilusFile representing the file in question.
- *
- * Returns: TRUE if the file is already gone.
- **/
-gboolean
-nautilus_file_is_gone (NautilusFile *file)
-{
- g_return_val_if_fail (file != NULL, FALSE);
-
- return file->is_gone;
-}
-
-/**
- * nautilus_file_list_ref
- *
- * Ref all the files in a list.
- * @file_list: GList of files.
- **/
-void
-nautilus_file_list_ref (GList *file_list)
-{
- g_list_foreach (file_list, (GFunc) nautilus_file_ref, NULL);
-}
-
-/**
- * nautilus_file_list_unref
- *
- * Unref all the files in a list.
- * @file_list: GList of files.
- **/
-void
-nautilus_file_list_unref (GList *file_list)
-{
- g_list_foreach (file_list, (GFunc) nautilus_file_ref, NULL);
-}
-
-/**
- * nautilus_file_list_free
- *
- * Free a list of files after unrefing them.
- * @file_list: GList of files.
- **/
-void
-nautilus_file_list_free (GList *file_list)
-{
- nautilus_file_list_unref (file_list);
- g_list_free (file_list);
+ gtk_signal_emit (GTK_OBJECT (directory),
+ nautilus_directory_signals[FILES_REMOVED],
+ removed_files);
}
#if !defined (NAUTILUS_OMIT_SELF_CHECK)
diff --git a/libnautilus/nautilus-directory.h b/libnautilus/nautilus-directory.h
index 35058f26b..42ea0451b 100644
--- a/libnautilus/nautilus-directory.h
+++ b/libnautilus/nautilus-directory.h
@@ -26,7 +26,6 @@
#define NAUTILUS_DIRECTORY_H
#include <gtk/gtkobject.h>
-#include <libgnomevfs/gnome-vfs-types.h>
/* NautilusDirectory is a class that manages the model for a directory,
real or virtual, for Nautilus, mainly the file-manager component. The directory is
@@ -57,21 +56,6 @@ typedef struct NautilusDirectoryClass NautilusDirectoryClass;
#define NAUTILUS_IS_DIRECTORY_CLASS(klass) \
(GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_DIRECTORY))
-#define NAUTILUS_IS_FILE(object) \
- ((object) != NULL)
-
-typedef enum {
- NAUTILUS_FILE_SORT_NONE,
- NAUTILUS_FILE_SORT_BY_NAME,
- NAUTILUS_FILE_SORT_BY_SIZE,
- NAUTILUS_FILE_SORT_BY_TYPE,
- NAUTILUS_FILE_SORT_BY_MTIME
-} NautilusFileSortType;
-
-typedef struct NautilusFile NautilusFile;
-
-#define NAUTILUS_FILE(file) ((NautilusFile *)(file))
-
typedef void (*NautilusFileListCallback) (NautilusDirectory *directory,
GList *files,
gpointer callback_data);
@@ -124,61 +108,6 @@ void nautilus_directory_stop_monitoring (NautilusDirectory
*/
gboolean nautilus_directory_are_all_files_seen (NautilusDirectory *directory);
-/* Getting at a single file. */
-NautilusFile * nautilus_file_get (const char *uri);
-
-/* Basic operations on file objects. */
-void nautilus_file_ref (NautilusFile *file);
-void nautilus_file_unref (NautilusFile *file);
-void nautilus_file_delete (NautilusFile *file);
-
-/* Basic attributes for file objects. */
-char * nautilus_file_get_name (NautilusFile *file);
-char * nautilus_file_get_uri (NautilusFile *file);
-GnomeVFSFileSize nautilus_file_get_size (NautilusFile *file);
-GnomeVFSFileType nautilus_file_get_type (NautilusFile *file);
-const char * nautilus_file_get_mime_type (NautilusFile *file);
-gboolean nautilus_file_is_symbolic_link (NautilusFile *file);
-gboolean nautilus_file_is_executable (NautilusFile *file);
-gboolean nautilus_file_is_directory (NautilusFile *file);
-guint nautilus_file_get_directory_item_count (NautilusFile *file,
- gboolean ignore_invisible_items);
-GList * nautilus_file_get_keywords (NautilusFile *file);
-void nautilus_file_set_keywords (NautilusFile *file,
- GList *keywords);
-
-/* Simple getting and setting top-level metadata. */
-char * nautilus_file_get_metadata (NautilusFile *file,
- const char *tag,
- const char *default_metadata);
-void nautilus_file_set_metadata (NautilusFile *file,
- const char *tag,
- const char *default_metadata,
- const char *metadata);
-
-/* Attributes for file objects as user-displayable strings. */
-char * nautilus_file_get_string_attribute (NautilusFile *file,
- const char *attribute_name);
-
-/* Comparing two file objects for sorting */
-int nautilus_file_compare_for_sort (NautilusFile *file_1,
- NautilusFile *file_2,
- NautilusFileSortType sort_type);
-int nautilus_file_compare_for_sort_reversed (NautilusFile *file_1,
- NautilusFile *file_2,
- NautilusFileSortType sort_type);
-
-/* Convenience functions for dealing with a list of NautilusFile objects that each have a ref. */
-void nautilus_file_list_ref (GList *file_list);
-void nautilus_file_list_unref (GList *file_list);
-void nautilus_file_list_free (GList *file_list);
-
-/* Return true if this file has already been deleted.
- This object will be unref'd after sending the files_removed signal,
- but it could hang around longer if someone ref'd it.
-*/
-gboolean nautilus_file_is_gone (NautilusFile *file);
-
typedef struct NautilusDirectoryDetails NautilusDirectoryDetails;
struct NautilusDirectory
@@ -201,10 +130,10 @@ struct NautilusDirectoryClass
this is the last chance to forget about these file objects
which are about to be unref'd.
*/
- void (* files_added) (NautilusDirectory *directory,
- GList *added_files);
- void (* files_removed) (NautilusDirectory *directory,
- GList *removed_files);
+ void (* files_added) (NautilusDirectory *directory,
+ GList *added_files);
+ void (* files_removed) (NautilusDirectory *directory,
+ GList *removed_files);
/* The files_changed signal is emitted as changes occur to
existing files that are noticed by the synchronization framework.
diff --git a/libnautilus/nautilus-file-private.h b/libnautilus/nautilus-file-private.h
new file mode 100644
index 000000000..7ee311c9b
--- /dev/null
+++ b/libnautilus/nautilus-file-private.h
@@ -0,0 +1,37 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+
+ nautilus-directory.c: Nautilus directory model.
+
+ Copyright (C) 1999, 2000 Eazel, Inc.
+
+ 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 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 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 Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Darin Adler <darin@eazel.com>
+*/
+
+#include "nautilus-file.h"
+#include "nautilus-directory.h"
+
+struct NautilusFile
+{
+ guint ref_count;
+
+ NautilusDirectory *directory;
+ GnomeVFSFileInfo *info;
+ gboolean is_gone;
+};
+
+void nautilus_file_free (NautilusFile *);
diff --git a/libnautilus/nautilus-file.c b/libnautilus/nautilus-file.c
new file mode 100644
index 000000000..56efacead
--- /dev/null
+++ b/libnautilus/nautilus-file.c
@@ -0,0 +1,1014 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+
+ nautilus-file.c: Nautilus file model.
+
+ Copyright (C) 1999, 2000 Eazel, Inc.
+
+ 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 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 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 Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Darin Adler <darin@eazel.com>
+*/
+
+#include <config.h>
+#include "nautilus-file-private.h"
+
+#include <grp.h>
+#include <pwd.h>
+
+#include <libgnome/gnome-defs.h>
+#include <libgnome/gnome-i18n.h>
+
+#include "nautilus-glib-extensions.h"
+#include "nautilus-string.h"
+#include "nautilus-directory-private.h"
+
+typedef enum {
+ NAUTILUS_DATE_TYPE_MODIFIED,
+ NAUTILUS_DATE_TYPE_CHANGED,
+ NAUTILUS_DATE_TYPE_ACCESSED
+} NautilusDateType;
+
+/* FIXME: This hack needs to die eventually. See comments with function */
+static int get_directory_item_count_hack (NautilusFile *file,
+ gboolean ignore_invisible_items);
+
+static int nautilus_file_compare_by_type (NautilusFile *file_1,
+ NautilusFile *file_2);
+static int nautilus_file_compare_for_sort_internal (NautilusFile *file_1,
+ NautilusFile *file_2,
+ NautilusFileSortType sort_type,
+ gboolean reversed);
+static char *nautilus_file_get_date_as_string (NautilusFile *file,
+ NautilusDateType date_type);
+static char *nautilus_file_get_owner_as_string (NautilusFile *file);
+static char *nautilus_file_get_group_as_string (NautilusFile *file);
+static char *nautilus_file_get_permissions_as_string (NautilusFile *file);
+static char *nautilus_file_get_size_as_string (NautilusFile *file);
+static char *nautilus_file_get_type_as_string (NautilusFile *file);
+
+/**
+ * nautilus_file_get:
+ * @uri: URI of file to get.
+ *
+ * Get a file given a uri.
+ * Returns a referenced object. Unref when finished.
+ * If two windows are viewing the same uri, the file object is shared.
+ */
+NautilusFile *
+nautilus_file_get (const char *uri)
+{
+ GnomeVFSResult result;
+ GnomeVFSFileInfo *file_info;
+ GnomeVFSURI *vfs_uri, *directory_vfs_uri;
+ char *directory_uri;
+ NautilusDirectory *directory;
+ NautilusFile *file;
+
+ /* Get info on the file. */
+ file_info = gnome_vfs_file_info_new ();
+ result = gnome_vfs_get_file_info (uri, file_info,
+ GNOME_VFS_FILE_INFO_GETMIMETYPE
+ | GNOME_VFS_FILE_INFO_FASTMIMETYPE
+ | GNOME_VFS_FILE_INFO_FOLLOWLINKS, NULL);
+ if (result != GNOME_VFS_OK)
+ return NULL;
+
+ /* Make VFS version of URI. */
+ vfs_uri = gnome_vfs_uri_new (uri);
+ if (vfs_uri == NULL)
+ return NULL;
+
+ /* Make VFS version of directory URI. */
+ directory_vfs_uri = gnome_vfs_uri_get_parent (vfs_uri);
+ gnome_vfs_uri_unref (vfs_uri);
+ if (directory_vfs_uri == NULL)
+ return NULL;
+
+ /* Make text version of directory URI. */
+ directory_uri = gnome_vfs_uri_to_string (directory_vfs_uri,
+ GNOME_VFS_URI_HIDE_NONE);
+ gnome_vfs_uri_unref (directory_vfs_uri);
+
+ /* Get object that represents the directory. */
+ directory = nautilus_directory_get (directory_uri);
+ g_free (directory_uri);
+ if (directory == NULL)
+ return NULL;
+
+ file = nautilus_directory_new_file (directory, file_info);
+
+ gnome_vfs_file_info_unref (file_info);
+ nautilus_file_ref (file);
+ gtk_object_unref (GTK_OBJECT (directory));
+
+ return file;
+}
+
+void
+nautilus_file_ref (NautilusFile *file)
+{
+ g_return_if_fail (file != NULL);
+
+ g_assert (file->ref_count < G_MAXINT);
+ g_assert (file->directory != NULL);
+
+ /* Increment the ref count. */
+ if (file->ref_count++ != 0) {
+ return;
+ }
+
+ /* As soon as someone other than the directory holds a ref,
+ * we need to hold the directory too. */
+ gtk_object_ref (GTK_OBJECT (file->directory));
+}
+
+void
+nautilus_file_unref (NautilusFile *file)
+{
+ g_return_if_fail (file != NULL);
+
+ g_assert (file->ref_count != 0);
+ g_assert (file->directory != NULL);
+
+ /* Decrement the ref count. */
+ if (--file->ref_count != 0) {
+ return;
+ }
+
+ /* No references left, so it's time to release our hold on the directory. */
+ gtk_object_unref (GTK_OBJECT (file->directory));
+ if (file->is_gone) {
+ nautilus_file_free (file);
+ }
+}
+
+void
+nautilus_file_free (NautilusFile *file)
+{
+ g_assert (file->ref_count == 0);
+
+ /* Destroy the file object. */
+ gnome_vfs_file_info_unref (file->info);
+ g_free (file);
+}
+
+static int
+nautilus_file_compare_by_size_with_directories (NautilusFile *file_1, NautilusFile *file_2)
+{
+ gboolean is_directory_1;
+ gboolean is_directory_2;
+ int item_count_1;
+ int item_count_2;
+
+ is_directory_1 = nautilus_file_is_directory (file_1);
+ is_directory_2 = nautilus_file_is_directory (file_2);
+
+ if (is_directory_1 && !is_directory_2)
+ return -1;
+
+ if (is_directory_2 && !is_directory_1)
+ return +1;
+
+ if (!is_directory_1 && !is_directory_2)
+ return 0;
+
+ /* Both are directories, compare by item count. */
+ /* FIXME: get_directory_item_count_hack is slow, and calling
+ * it for every pairwise comparison here is nasty. Need to
+ * change this to (not-yet-existent) architecture where the
+ * item count can be calculated once in a deferred way, and
+ * then stored or cached.
+ */
+ item_count_1 = get_directory_item_count_hack (file_1, FALSE);
+ item_count_2 = get_directory_item_count_hack (file_2, FALSE);
+
+ if (item_count_1 < item_count_2)
+ return -1;
+
+ if (item_count_2 < item_count_1)
+ return +1;
+
+ return 0;
+}
+
+static int
+nautilus_file_compare_by_type (NautilusFile *file_1, NautilusFile *file_2)
+{
+ gboolean is_directory_1;
+ gboolean is_directory_2;
+ char * type_string_1;
+ char * type_string_2;
+ int result;
+
+ /* Directories go first. Then, if mime types are identical,
+ * don't bother getting strings (for speed). This assumes
+ * that the string is dependent entirely on the mime type,
+ * which is true now but might not be later.
+ */
+ is_directory_1 = nautilus_file_is_directory (file_1);
+ is_directory_2 = nautilus_file_is_directory (file_2);
+
+ if (is_directory_1 && is_directory_2)
+ return 0;
+
+ if (is_directory_1)
+ return -1;
+
+ if (is_directory_2)
+ return +1;
+
+ if (nautilus_strcmp (file_1->info->mime_type, file_2->info->mime_type) == 0)
+ return 0;
+
+ type_string_1 = nautilus_file_get_type_as_string (file_1);
+ type_string_2 = nautilus_file_get_type_as_string (file_2);
+
+ result = nautilus_strcmp (type_string_1, type_string_2);
+
+ g_free (type_string_1);
+ g_free (type_string_2);
+
+ return result;
+}
+
+static int
+nautilus_file_compare_for_sort_internal (NautilusFile *file_1,
+ NautilusFile *file_2,
+ NautilusFileSortType sort_type,
+ gboolean reversed)
+{
+ GnomeVFSDirectorySortRule rules[3];
+ int compare;
+
+ g_return_val_if_fail (file_1 != NULL, 0);
+ g_return_val_if_fail (file_2 != NULL, 0);
+ g_return_val_if_fail (sort_type != NAUTILUS_FILE_SORT_NONE, 0);
+
+ switch (sort_type) {
+ case NAUTILUS_FILE_SORT_BY_NAME:
+ /* Note: This used to put directories first. I
+ * thought that was counterintuitive and removed it,
+ * but I can imagine discussing this further.
+ * John Sullivan <sullivan@eazel.com>
+ */
+ rules[0] = GNOME_VFS_DIRECTORY_SORT_BYNAME_IGNORECASE;
+ rules[1] = GNOME_VFS_DIRECTORY_SORT_NONE;
+ break;
+ case NAUTILUS_FILE_SORT_BY_SIZE:
+ /* Compare directory sizes ourselves, then if necessary
+ * use GnomeVFS to compare file sizes.
+ */
+ compare = nautilus_file_compare_by_size_with_directories (file_1, file_2);
+ if (compare != 0) {
+ return compare;
+ }
+ rules[0] = GNOME_VFS_DIRECTORY_SORT_BYSIZE;
+ rules[1] = GNOME_VFS_DIRECTORY_SORT_BYNAME_IGNORECASE;
+ rules[2] = GNOME_VFS_DIRECTORY_SORT_NONE;
+ break;
+ case NAUTILUS_FILE_SORT_BY_TYPE:
+ /* GnomeVFS doesn't know about our special text for certain
+ * mime types, so we handle the mime-type sorting ourselves.
+ */
+ compare = nautilus_file_compare_by_type (file_1, file_2);
+ if (compare != 0) {
+ return compare;
+ }
+ rules[0] = GNOME_VFS_DIRECTORY_SORT_BYNAME_IGNORECASE;
+ rules[1] = GNOME_VFS_DIRECTORY_SORT_NONE;
+ break;
+ case NAUTILUS_FILE_SORT_BY_MTIME:
+ rules[0] = GNOME_VFS_DIRECTORY_SORT_BYMTIME;
+ rules[1] = GNOME_VFS_DIRECTORY_SORT_BYNAME_IGNORECASE;
+ rules[2] = GNOME_VFS_DIRECTORY_SORT_NONE;
+ break;
+ default:
+ g_assert_not_reached ();
+ return 0;
+ }
+
+ if (reversed)
+ return gnome_vfs_file_info_compare_for_sort_reversed (file_1->info,
+ file_2->info,
+ rules);
+ else
+ return gnome_vfs_file_info_compare_for_sort (file_1->info,
+ file_2->info,
+ rules);
+}
+
+/**
+ * nautilus_file_compare_for_sort:
+ * @file_1: A file object
+ * @file_2: Another file object
+ * @sort_type: Sort criterion
+ *
+ * Return value: int < 0 if @file_1 should come before file_2 in a smallest-to-largest
+ * sorted list; int > 0 if @file_2 should come before file_1 in a smallest-to-largest
+ * sorted list; 0 if @file_1 and @file_2 are equal for this sort criterion. Note
+ * that each named sort type may actually break ties several ways, with the name
+ * of the sort criterion being the primary but not only differentiator.
+ **/
+int
+nautilus_file_compare_for_sort (NautilusFile *file_1,
+ NautilusFile *file_2,
+ NautilusFileSortType sort_type)
+{
+ return nautilus_file_compare_for_sort_internal (file_1, file_2, sort_type, FALSE);
+}
+
+/**
+ * nautilus_file_compare_for_sort_reversed:
+ * @file_1: A file object
+ * @file_2: Another file object
+ * @sort_type: Sort criterion
+ *
+ * Return value: The opposite of nautilus_file_compare_for_sort: int > 0 if @file_1
+ * should come before file_2 in a smallest-to-largest sorted list; int < 0 if @file_2
+ * should come before file_1 in a smallest-to-largest sorted list; 0 if @file_1
+ * and @file_2 are equal for this sort criterion. Note that each named sort type
+ * may actually break ties several ways, with the name of the sort criterion
+ * being the primary but not only differentiator.
+ **/
+int
+nautilus_file_compare_for_sort_reversed (NautilusFile *file_1,
+ NautilusFile *file_2,
+ NautilusFileSortType sort_type)
+{
+ return nautilus_file_compare_for_sort_internal (file_1, file_2, sort_type, TRUE);
+}
+
+char *
+nautilus_file_get_metadata (NautilusFile *file,
+ const char *tag,
+ const char *default_metadata)
+{
+ g_return_val_if_fail (file != NULL, NULL);
+
+ return nautilus_directory_get_file_metadata (file->directory,
+ file->info->name,
+ tag,
+ default_metadata);
+}
+
+void
+nautilus_file_set_metadata (NautilusFile *file,
+ const char *tag,
+ const char *default_metadata,
+ const char *metadata)
+{
+ g_return_if_fail (file != NULL);
+
+ nautilus_directory_set_file_metadata (file->directory,
+ file->info->name,
+ tag,
+ default_metadata,
+ metadata);
+}
+
+char *
+nautilus_file_get_name (NautilusFile *file)
+{
+ g_return_val_if_fail (file != NULL, NULL);
+
+ g_assert (file->directory == NULL || NAUTILUS_IS_DIRECTORY (file->directory));
+ g_assert (file->info->name != NULL);
+ g_assert (file->info->name[0] != '\0');
+
+ return g_strdup (file->info->name);
+}
+
+char *
+nautilus_file_get_uri (NautilusFile *file)
+{
+ GnomeVFSURI *uri;
+ char *uri_text;
+
+ g_return_val_if_fail (file != NULL, NULL);
+ g_return_val_if_fail (file->directory != NULL, NULL);
+
+ uri = gnome_vfs_uri_append_path (file->directory->details->uri, file->info->name);
+ uri_text = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE);
+ gnome_vfs_uri_unref (uri);
+ return uri_text;
+}
+
+/**
+ * nautilus_file_get_date_as_string:
+ *
+ * Get a user-displayable string representing a file modification date.
+ * The caller is responsible for g_free-ing this string.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: Newly allocated string ready to display to the user.
+ *
+ **/
+static char *
+nautilus_file_get_date_as_string (NautilusFile *file, NautilusDateType date_type)
+{
+ struct tm *file_time;
+ const char *format;
+ GDate *today;
+ GDate *file_date;
+ guint32 file_date_age;
+
+ g_return_val_if_fail (file != NULL, NULL);
+
+ switch (date_type)
+ {
+ case NAUTILUS_DATE_TYPE_CHANGED:
+ file_time = localtime(&file->info->ctime);
+ break;
+ case NAUTILUS_DATE_TYPE_ACCESSED:
+ file_time = localtime(&file->info->atime);
+ break;
+ case NAUTILUS_DATE_TYPE_MODIFIED:
+ file_time = localtime(&file->info->mtime);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ file_date = nautilus_g_date_new_tm (file_time);
+
+ today = g_date_new ();
+ g_date_set_time (today, time (NULL));
+
+ /* Overflow results in a large number; fine for our purposes. */
+ file_date_age = g_date_julian (today) - g_date_julian (file_date);
+
+ g_date_free (file_date);
+ g_date_free (today);
+
+ /* Format varies depending on how old the date is. This minimizes
+ * the length (and thus clutter & complication) of typical dates
+ * while providing sufficient detail for recent dates to make
+ * them maximally understandable at a glance. Keep all format
+ * strings separate rather than combining bits & pieces for
+ * internationalization's sake.
+ */
+
+ if (file_date_age == 0)
+ {
+ /* today, use special word */
+ format = _("today %-I:%M %p");
+ }
+ else if (file_date_age == 1)
+ {
+ /* yesterday, use special word */
+ format = _("yesterday %-I:%M %p");
+ }
+ else if (file_date_age < 7)
+ {
+ /* current week, include day of week */
+ format = _("%A %-m/%-d/%y %-I:%M %p");
+ }
+ else
+ {
+ format = _("%-m/%-d/%y %-I:%M %p");
+ }
+
+ return nautilus_strdup_strftime (format, file_time);
+}
+
+/**
+ * nautilus_file_get_directory_item_count
+ *
+ * Get the number of items in a directory.
+ * @file: NautilusFile representing a directory. It is an error to
+ * call this function on a file that is not a directory.
+ * @ignore_invisible_items: TRUE if invisible items should not be
+ * included in count.
+ *
+ * Returns: item count for this directory.
+ *
+ **/
+guint
+nautilus_file_get_directory_item_count (NautilusFile *file,
+ gboolean ignore_invisible_items)
+{
+ g_return_val_if_fail (nautilus_file_is_directory (file), 0);
+
+ return get_directory_item_count_hack (file, ignore_invisible_items);
+}
+
+/**
+ * nautilus_file_get_size
+ *
+ * Get the file size.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: Size in bytes.
+ *
+ **/
+GnomeVFSFileSize
+nautilus_file_get_size (NautilusFile *file)
+{
+ g_return_val_if_fail (file != NULL, 0);
+
+ return file->info->size;
+}
+
+/**
+ * nautilus_file_get_permissions_as_string:
+ *
+ * Get a user-displayable string representing a file's permissions. The caller
+ * is responsible for g_free-ing this string.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: Newly allocated string ready to display to the user.
+ *
+ **/
+static char *
+nautilus_file_get_permissions_as_string (NautilusFile *file)
+{
+ GnomeVFSFilePermissions permissions;
+ gboolean is_directory;
+ gboolean is_link;
+
+ permissions = file->info->permissions;
+ is_directory = nautilus_file_is_directory (file);
+ is_link = GNOME_VFS_FILE_INFO_SYMLINK(file->info);
+
+ return g_strdup_printf ("%c%c%c%c%c%c%c%c%c%c",
+ is_link ? 'l' : is_directory ? 'd' : '-',
+ permissions & GNOME_VFS_PERM_USER_READ ? 'r' : '-',
+ permissions & GNOME_VFS_PERM_USER_WRITE ? 'w' : '-',
+ permissions & GNOME_VFS_PERM_USER_EXEC ? 'x' : '-',
+ permissions & GNOME_VFS_PERM_GROUP_READ ? 'r' : '-',
+ permissions & GNOME_VFS_PERM_GROUP_WRITE ? 'w' : '-',
+ permissions & GNOME_VFS_PERM_GROUP_EXEC ? 'x' : '-',
+ permissions & GNOME_VFS_PERM_OTHER_READ ? 'r' : '-',
+ permissions & GNOME_VFS_PERM_OTHER_WRITE ? 'w' : '-',
+ permissions & GNOME_VFS_PERM_OTHER_EXEC ? 'x' : '-');
+}
+
+/**
+ * nautilus_file_get_owner_as_string:
+ *
+ * Get a user-displayable string representing a file's owner. The caller
+ * is responsible for g_free-ing this string.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: Newly allocated string ready to display to the user.
+ *
+ **/
+static char *
+nautilus_file_get_owner_as_string (NautilusFile *file)
+{
+ struct passwd *password_info;
+
+ /* FIXME: Can we trust the uid in the file info? Might
+ * there be garbage there? What will it do for non-local files?
+ */
+ /* No need to free result of getpwuid */
+ password_info = getpwuid (file->info->uid);
+
+ g_print ("pointer to password info is %p\n", password_info);
+
+ if (password_info == NULL)
+ {
+ return g_strdup (_("unknown owner"));
+ }
+
+ return g_strdup (password_info->pw_name);
+}
+
+/**
+ * nautilus_file_get_group_as_string:
+ *
+ * Get a user-displayable string representing a file's group. The caller
+ * is responsible for g_free-ing this string.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: Newly allocated string ready to display to the user.
+ *
+ **/
+static char *
+nautilus_file_get_group_as_string (NautilusFile *file)
+{
+ struct group *group_info;
+
+ /* FIXME: Can we trust the gid in the file info? Might
+ * there be garbage there? What will it do for non-local files?
+ */
+ /* No need to free result of getgrgid */
+ group_info = getgrgid (file->info->gid);
+
+ if (group_info == NULL)
+ {
+ return g_strdup (_("unknown group"));
+ }
+
+ return g_strdup (group_info->gr_name);
+}
+
+
+/* This #include is part of the following hack, and should be removed with it */
+#include <dirent.h>
+
+static int
+get_directory_item_count_hack (NautilusFile *file, gboolean ignore_invisible_items)
+{
+ /* Code borrowed from Gnomad and hacked into here for now */
+
+ char * uri;
+ char * path;
+ DIR* directory;
+ int count;
+ struct dirent * entry;
+
+ g_assert (nautilus_file_is_directory (file));
+
+ uri = nautilus_file_get_uri (file);
+ if (nautilus_has_prefix (uri, "file://"))
+ path = uri + 7;
+ else
+ path = uri;
+
+ directory = opendir (path);
+
+ g_free (uri);
+
+ if (!directory)
+ return 0;
+
+ count = 0;
+
+ while ((entry = readdir(directory)) != NULL)
+ // Only count invisible items if requested.
+ if (!ignore_invisible_items || entry->d_name[0] != '.')
+ count += 1;
+
+ closedir(directory);
+
+ /* This way of getting the count includes . and .., so we subtract those out */
+ if (!ignore_invisible_items) {
+ count -= 2;
+ }
+
+ return count;
+}
+
+/**
+ * nautilus_file_get_size_as_string:
+ *
+ * Get a user-displayable string representing a file size. The caller
+ * is responsible for g_free-ing this string. The string is an item
+ * count for directories.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: Newly allocated string ready to display to the user.
+ *
+ **/
+static char *
+nautilus_file_get_size_as_string (NautilusFile *file)
+{
+ g_return_val_if_fail (file != NULL, NULL);
+
+ if (nautilus_file_is_directory (file))
+ {
+ /* FIXME: Since computing the item count is slow, we
+ * want to do it in a deferred way. However, that
+ * architecture doesn't exist yet, so we're hacking
+ * it in for now.
+ */
+ int item_count;
+
+ item_count = get_directory_item_count_hack (file, FALSE);
+ if (item_count == 0) {
+ return g_strdup (_("0 items"));
+ } else if (item_count == 1) {
+ return g_strdup (_("1 item"));
+ } else {
+ return g_strdup_printf (_("%d items"), item_count);
+ }
+ }
+
+ return gnome_vfs_file_size_to_string (file->info->size);
+}
+
+/**
+ * nautilus_file_get_string_attribute:
+ *
+ * Get a user-displayable string from a named attribute. Use g_free to
+ * free this string.
+ *
+ * @file: NautilusFile representing the file in question.
+ * @attribute_name: The name of the desired attribute. The currently supported
+ * set includes "name", "type", "size", "date_modified", "date_changed",
+ * "date_accessed", "owner", "group", "permissions".
+ *
+ * Returns: Newly allocated string ready to display to the user, or NULL
+ * if @attribute_name is not supported.
+ *
+ **/
+char *
+nautilus_file_get_string_attribute (NautilusFile *file, const char *attribute_name)
+{
+ /* FIXME: Use hash table and switch statement or function pointers for speed? */
+
+ if (strcmp (attribute_name, "name") == 0) {
+ return nautilus_file_get_name (file);
+ }
+
+ if (strcmp (attribute_name, "type") == 0) {
+ return nautilus_file_get_type_as_string (file);
+ }
+
+ if (strcmp (attribute_name, "size") == 0) {
+ return nautilus_file_get_size_as_string (file);
+ }
+
+ if (strcmp (attribute_name, "date_modified") == 0) {
+ return nautilus_file_get_date_as_string (file,
+ NAUTILUS_DATE_TYPE_MODIFIED);
+ }
+
+ if (strcmp (attribute_name, "date_changed") == 0) {
+ return nautilus_file_get_date_as_string (file,
+ NAUTILUS_DATE_TYPE_CHANGED);
+ }
+
+ if (strcmp (attribute_name, "date_accessed") == 0) {
+ return nautilus_file_get_date_as_string (file,
+ NAUTILUS_DATE_TYPE_ACCESSED);
+ }
+
+ if (strcmp (attribute_name, "permissions") == 0) {
+ return nautilus_file_get_permissions_as_string (file);
+ }
+
+ if (strcmp (attribute_name, "owner") == 0) {
+ return nautilus_file_get_owner_as_string (file);
+ }
+
+ if (strcmp (attribute_name, "group") == 0) {
+ return nautilus_file_get_group_as_string (file);
+ }
+
+ return NULL;
+}
+
+/**
+ * nautilus_file_get_type_as_string:
+ *
+ * Get a user-displayable string representing a file type. The caller
+ * is responsible for g_free-ing this string.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: Newly allocated string ready to display to the user.
+ *
+ **/
+static char *
+nautilus_file_get_type_as_string (NautilusFile *file)
+{
+ g_return_val_if_fail (file != NULL, NULL);
+
+ if (nautilus_file_is_directory (file)) {
+ /* Special-case this so it isn't "special/directory".
+ * FIXME: Should this be "folder" instead?
+ */
+ return g_strdup (_("directory"));
+ }
+
+ if (nautilus_strlen (file->info->mime_type) == 0) {
+ return g_strdup (_("unknown type"));
+ }
+
+ return g_strdup (file->info->mime_type);
+}
+
+/**
+ * nautilus_file_get_type
+ *
+ * Return this file's type.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: The type.
+ *
+ **/
+GnomeVFSFileType
+nautilus_file_get_type (NautilusFile *file)
+{
+ g_return_val_if_fail (file != NULL, FALSE);
+
+ return file->info->type;
+}
+
+/**
+ * nautilus_file_get_mime_type
+ *
+ * Return this file's mime type.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: The mime type.
+ *
+ **/
+const char *
+nautilus_file_get_mime_type (NautilusFile *file)
+{
+ g_return_val_if_fail (file != NULL, FALSE);
+
+ return file->info->mime_type;
+}
+
+/**
+ * nautilus_file_get_keywords
+ *
+ * Return this file's keywords.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: A list of keywords.
+ *
+ **/
+GList *
+nautilus_file_get_keywords (NautilusFile *file)
+{
+ GList *keywords;
+ xmlNode *file_node, *child;
+ xmlChar *property;
+
+ g_return_val_if_fail (file != NULL, NULL);
+
+ keywords = NULL;
+
+ /* Put all the keywords into a list. */
+ file_node = nautilus_directory_get_file_metadata_node (file->directory, file->info->name);
+ if (file_node != NULL) {
+ for (child = file_node->childs; child != NULL; child = child->next) {
+ if (strcmp (child->name, "KEYWORD") == 0) {
+ property = xmlGetProp (child, "NAME");
+ if (property != NULL) {
+ keywords = g_list_prepend (keywords,
+ g_strdup (property));
+ }
+ }
+ }
+ }
+
+ return g_list_reverse (keywords);
+}
+
+/**
+ * nautilus_file_is_symbolic_link
+ *
+ * Check if this file is a symbolic link.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: True if the file is a symbolic link.
+ *
+ **/
+gboolean
+nautilus_file_is_symbolic_link (NautilusFile *file)
+{
+ g_return_val_if_fail (file != NULL, FALSE);
+
+ return GNOME_VFS_FILE_INFO_SYMLINK (file->info);
+}
+
+/**
+ * nautilus_file_is_directory
+ *
+ * Check if this file is a directory.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: TRUE if @file is a directory.
+ *
+ **/
+gboolean
+nautilus_file_is_directory (NautilusFile *file)
+{
+ g_return_val_if_fail (file != NULL, FALSE);
+
+ return nautilus_file_get_type (file) == GNOME_VFS_FILE_TYPE_DIRECTORY;
+}
+
+/**
+ * nautilus_file_is_executable
+ *
+ * Check if this file is executable at all.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: True if any of the execute bits are set.
+ *
+ **/
+gboolean
+nautilus_file_is_executable (NautilusFile *file)
+{
+ g_return_val_if_fail (file != NULL, FALSE);
+
+ return (file->info->flags & (GNOME_VFS_PERM_USER_EXEC
+ | GNOME_VFS_PERM_GROUP_EXEC
+ | GNOME_VFS_PERM_OTHER_EXEC)) != 0;
+}
+
+/**
+ * nautilus_file_delete
+ *
+ * Delete this file.
+ * @file: NautilusFile representing the file in question.
+ **/
+void
+nautilus_file_delete (NautilusFile *file)
+{
+ char *text_uri;
+ GnomeVFSResult result;
+ GList *removed_files;
+
+ g_return_if_fail (file != NULL);
+
+ /* Deleting a file that's already gone is easy. */
+ if (file->is_gone) {
+ return;
+ }
+
+ /* Do the actual deletion. */
+ text_uri = nautilus_file_get_uri (file);
+ if (nautilus_file_is_directory (file)) {
+ result = gnome_vfs_remove_directory (text_uri);
+ } else {
+ result = gnome_vfs_unlink (text_uri);
+ }
+ g_free (text_uri);
+
+ /* Mark the file gone. */
+ if (result == GNOME_VFS_OK || result == GNOME_VFS_ERROR_NOTFOUND) {
+ file->is_gone = TRUE;
+
+ /* Let the directory know it's gone. */
+ if (file->directory != NULL) {
+ g_list_remove (file->directory->details->files, file);
+
+ /* Send out a signal. */
+ removed_files = g_list_prepend (NULL, file);
+ nautilus_directory_files_removed (file->directory, removed_files);
+ g_list_free (removed_files);
+ }
+ }
+}
+
+/**
+ * nautilus_file_is_gone
+ *
+ * Check if a file has already been deleted.
+ * @file: NautilusFile representing the file in question.
+ *
+ * Returns: TRUE if the file is already gone.
+ **/
+gboolean
+nautilus_file_is_gone (NautilusFile *file)
+{
+ g_return_val_if_fail (file != NULL, FALSE);
+
+ return file->is_gone;
+}
+
+/**
+ * nautilus_file_list_ref
+ *
+ * Ref all the files in a list.
+ * @file_list: GList of files.
+ **/
+void
+nautilus_file_list_ref (GList *file_list)
+{
+ g_list_foreach (file_list, (GFunc) nautilus_file_ref, NULL);
+}
+
+/**
+ * nautilus_file_list_unref
+ *
+ * Unref all the files in a list.
+ * @file_list: GList of files.
+ **/
+void
+nautilus_file_list_unref (GList *file_list)
+{
+ g_list_foreach (file_list, (GFunc) nautilus_file_ref, NULL);
+}
+
+/**
+ * nautilus_file_list_free
+ *
+ * Free a list of files after unrefing them.
+ * @file_list: GList of files.
+ **/
+void
+nautilus_file_list_free (GList *file_list)
+{
+ nautilus_file_list_unref (file_list);
+ g_list_free (file_list);
+}
diff --git a/libnautilus/nautilus-file.h b/libnautilus/nautilus-file.h
new file mode 100644
index 000000000..dc06290b5
--- /dev/null
+++ b/libnautilus/nautilus-file.h
@@ -0,0 +1,106 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+
+ nautilus-file.h: Nautilus file model.
+
+ Copyright (C) 1999, 2000 Eazel, Inc.
+
+ 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 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 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 Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Darin Adler <darin@eazel.com>
+*/
+
+#ifndef NAUTILUS_FILE_H
+#define NAUTILUS_FILE_H
+
+#include <glib.h> /* gnome-vfs-types.h requires glib.h but doesn't include it */
+#include <libgnomevfs/gnome-vfs-types.h>
+
+/* NautilusFile is an object used to represent a single element of a
+ * NautilusDirectory. It's lightweight and relies on NautilusDirectory
+ * to do most of the work.
+ */
+
+typedef enum {
+ NAUTILUS_FILE_SORT_NONE,
+ NAUTILUS_FILE_SORT_BY_NAME,
+ NAUTILUS_FILE_SORT_BY_SIZE,
+ NAUTILUS_FILE_SORT_BY_TYPE,
+ NAUTILUS_FILE_SORT_BY_MTIME
+} NautilusFileSortType;
+
+typedef struct NautilusFile NautilusFile;
+
+#define NAUTILUS_IS_FILE(object) \
+ ((object) != NULL)
+#define NAUTILUS_FILE(file) \
+ ((NautilusFile *)(file))
+
+/* Getting at a single file. */
+NautilusFile * nautilus_file_get (const char *uri);
+
+/* Basic operations on file objects. */
+void nautilus_file_ref (NautilusFile *file);
+void nautilus_file_unref (NautilusFile *file);
+void nautilus_file_delete (NautilusFile *file);
+
+/* Basic attributes for file objects. */
+char * nautilus_file_get_name (NautilusFile *file);
+char * nautilus_file_get_uri (NautilusFile *file);
+GnomeVFSFileSize nautilus_file_get_size (NautilusFile *file);
+GnomeVFSFileType nautilus_file_get_type (NautilusFile *file);
+const char * nautilus_file_get_mime_type (NautilusFile *file);
+gboolean nautilus_file_is_symbolic_link (NautilusFile *file);
+gboolean nautilus_file_is_executable (NautilusFile *file);
+gboolean nautilus_file_is_directory (NautilusFile *file);
+guint nautilus_file_get_directory_item_count (NautilusFile *file,
+ gboolean ignore_invisible_items);
+GList * nautilus_file_get_keywords (NautilusFile *file);
+void nautilus_file_set_keywords (NautilusFile *file,
+ GList *keywords);
+
+/* Simple getting and setting top-level metadata. */
+char * nautilus_file_get_metadata (NautilusFile *file,
+ const char *tag,
+ const char *default_metadata);
+void nautilus_file_set_metadata (NautilusFile *file,
+ const char *tag,
+ const char *default_metadata,
+ const char *metadata);
+
+/* Attributes for file objects as user-displayable strings. */
+char * nautilus_file_get_string_attribute (NautilusFile *file,
+ const char *attribute_name);
+
+/* Comparing two file objects for sorting */
+int nautilus_file_compare_for_sort (NautilusFile *file_1,
+ NautilusFile *file_2,
+ NautilusFileSortType sort_type);
+int nautilus_file_compare_for_sort_reversed (NautilusFile *file_1,
+ NautilusFile *file_2,
+ NautilusFileSortType sort_type);
+
+/* Convenience functions for dealing with a list of NautilusFile objects that each have a ref. */
+void nautilus_file_list_ref (GList *file_list);
+void nautilus_file_list_unref (GList *file_list);
+void nautilus_file_list_free (GList *file_list);
+
+/* Return true if this file has already been deleted.
+ This object will be unref'd after sending the files_removed signal,
+ but it could hang around longer if someone ref'd it.
+*/
+gboolean nautilus_file_is_gone (NautilusFile *file);
+
+#endif /* NAUTILUS_FILE_H */
diff --git a/libnautilus/nautilus-icon-factory.h b/libnautilus/nautilus-icon-factory.h
index 545211440..3e7bfa903 100644
--- a/libnautilus/nautilus-icon-factory.h
+++ b/libnautilus/nautilus-icon-factory.h
@@ -2,7 +2,7 @@
nautilus-icon-factory.h: Class for obtaining icons for files and other objects.
- * Copyright (C) 1999, 2000 Red Hat Inc.
+ Copyright (C) 1999, 2000 Red Hat Inc.
Copyright (C) 1999, 2000 Eazel, Inc.
This program is free software; you can redistribute it and/or
@@ -27,7 +27,8 @@
#define NAUTILUS_ICON_FACTORY_H
#include <gdk-pixbuf/gdk-pixbuf.h>
-#include <libnautilus/nautilus-directory.h>
+#include <libnautilus/nautilus-file.h>
+#include <gtk/gtkobject.h>
/* NautilusIconFactory is a class that knows how to hand out icons to be
* used for representing files and some other objects. It was designed
@@ -97,8 +98,8 @@ char * nautilus_icon_factory_get_theme (void);
void nautilus_icon_factory_set_theme (const char *theme_name);
/* Choose the appropriate icon, but don't render it yet. */
-NautilusScalableIcon *nautilus_icon_factory_get_icon_for_file (NautilusFile *file,
- void *controller);
+NautilusScalableIcon *nautilus_icon_factory_get_icon_for_file (NautilusFile *file,
+ void *controller);
NautilusScalableIcon *nautilus_icon_factory_get_icon_by_name (const char *icon_name);
GList * nautilus_icon_factory_get_emblem_icons_for_file (NautilusFile *file);
diff --git a/libnautilus/nautilus-string.c b/libnautilus/nautilus-string.c
index d2df8e286..c3ac00d5e 100644
--- a/libnautilus/nautilus-string.c
+++ b/libnautilus/nautilus-string.c
@@ -69,10 +69,12 @@ nautilus_has_prefix (const char *haystack_null_allowed, const char *needle_null_
h = haystack_null_allowed == NULL ? "" : haystack_null_allowed;
n = needle_null_allowed == NULL ? "" : needle_null_allowed;
do {
- if (*n == '\0')
+ if (*n == '\0') {
return TRUE;
- if (*h == '\0')
+ }
+ if (*h == '\0') {
return FALSE;
+ }
} while (*h++ == *n++);
return FALSE;
}
@@ -82,19 +84,23 @@ nautilus_has_suffix (const char *haystack_null_allowed, const char *needle_null_
{
const char *h, *n;
- if (haystack_null_allowed == NULL)
+ if (needle_null_allowed == NULL) {
return TRUE;
- if (needle_null_allowed == NULL)
- return FALSE;
+ }
+ if (haystack_null_allowed == NULL) {
+ return needle_null_allowed[0] == '\0';
+ }
/* Eat one character at a time. */
h = haystack_null_allowed + strlen(haystack_null_allowed);
n = needle_null_allowed + strlen(needle_null_allowed);
do {
- if (n == needle_null_allowed)
+ if (n == needle_null_allowed) {
return TRUE;
- if (h == haystack_null_allowed)
+ }
+ if (h == haystack_null_allowed) {
return FALSE;
+ }
} while (*--h == *--n);
return FALSE;
}
@@ -144,23 +150,28 @@ nautilus_string_to_int (const char *string, int *integer)
char *parse_end;
/* Check for the case of an empty string. */
- if (string == NULL || *string == '\0')
+ if (string == NULL || *string == '\0') {
return FALSE;
+ }
/* Call the standard library routine to do the conversion. */
errno = 0;
result = strtol (string, &parse_end, 0);
/* Check that the result is in range. */
- if ((result == G_MINLONG || result == G_MAXLONG) && errno == ERANGE)
+ if ((result == G_MINLONG || result == G_MAXLONG) && errno == ERANGE) {
return FALSE;
- if (result < G_MININT || result > G_MAXINT)
+ }
+ if (result < G_MININT || result > G_MAXINT) {
return FALSE;
+ }
/* Check that all the trailing characters are spaces. */
- while (*parse_end != '\0')
- if (!isspace (*parse_end++))
+ while (*parse_end != '\0') {
+ if (!isspace (*parse_end++)) {
return FALSE;
+ }
+ }
/* Return the result. */
*integer = result;
@@ -170,27 +181,27 @@ nautilus_string_to_int (const char *string, int *integer)
/**
* nautilus_strstrip:
* Remove all occurrences of a character from a string. The
- * original string is modified, and also returned for convenience.
+ * original string is modified in place, and also returned for convenience.
*
* @string_null_allowed: The string to be stripped.
* @remove_this: The char to remove from @string_null_allowed
*
* Return value: @string_null_allowed, after removing all occurrences
- * of @remove_this.
+ * of @remove_this.
*/
char *
nautilus_strstrip (char *string_null_allowed, char remove_this)
{
if (string_null_allowed != NULL) {
- char *pos;
+ char *in, *out;
- pos = string_null_allowed;
- while (*pos != '\0') {
- if (*pos == remove_this) {
- g_memmove (pos, pos + 1, strlen (pos));
+ in = string_null_allowed;
+ out = string_null_allowed;
+ do {
+ if (*in != remove_this) {
+ *out++ = *in;
}
- ++pos;
- }
+ } while (*in++ != '\0');
}
return string_null_allowed;
@@ -232,7 +243,6 @@ void
nautilus_self_check_string (void)
{
int integer;
- char *test_string;
NAUTILUS_CHECK_INTEGER_RESULT (nautilus_strlen (NULL), 0);
NAUTILUS_CHECK_INTEGER_RESULT (nautilus_strlen (""), 0);
@@ -283,6 +293,22 @@ nautilus_self_check_string (void)
NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_prefix ("aaa", "aaab"), FALSE);
NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_prefix ("aaab", "aaa"), TRUE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix (NULL, NULL), TRUE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix (NULL, ""), TRUE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("", NULL), TRUE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("a", "a"), TRUE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("aaab", "aaab"), TRUE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix (NULL, "a"), FALSE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("a", NULL), TRUE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("", "a"), FALSE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("a", ""), TRUE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("a", "b"), FALSE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("a", "ab"), FALSE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("ab", "a"), FALSE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("ab", "b"), TRUE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("aaa", "baaa"), FALSE);
+ NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_has_suffix ("baaa", "aaa"), TRUE);
+
NAUTILUS_CHECK_STRING_RESULT (nautilus_strdup_prefix (NULL, NULL), NULL);
NAUTILUS_CHECK_STRING_RESULT (nautilus_strdup_prefix (NULL, "foo"), NULL);
NAUTILUS_CHECK_STRING_RESULT (nautilus_strdup_prefix ("foo", NULL), "foo");
@@ -292,14 +318,11 @@ nautilus_self_check_string (void)
NAUTILUS_CHECK_STRING_RESULT (nautilus_strdup_prefix ("footle:bar", "tle:"), "foo");
NAUTILUS_CHECK_STRING_RESULT (nautilus_strstrip (NULL, '_'), NULL);
- test_string = g_strdup ("foo");
- NAUTILUS_CHECK_STRING_RESULT (nautilus_strstrip (test_string, '_'), "foo");
- test_string = g_strdup ("_foo");
- NAUTILUS_CHECK_STRING_RESULT (nautilus_strstrip (test_string, '_'), "foo");
- test_string = g_strdup ("foo_");
- NAUTILUS_CHECK_STRING_RESULT (nautilus_strstrip (test_string, '_'), "foo");
- test_string = g_strdup ("_foo_");
- NAUTILUS_CHECK_STRING_RESULT (nautilus_strstrip (test_string, '_'), "foo");
+ NAUTILUS_CHECK_STRING_RESULT (nautilus_strstrip (g_strdup ("foo"), '_'), "foo");
+ NAUTILUS_CHECK_STRING_RESULT (nautilus_strstrip (g_strdup ("_foo"), '_'), "foo");
+ NAUTILUS_CHECK_STRING_RESULT (nautilus_strstrip (g_strdup ("foo_"), '_'), "foo");
+ NAUTILUS_CHECK_STRING_RESULT (nautilus_strstrip (g_strdup ("_foo_"), '_'), "foo");
+ NAUTILUS_CHECK_STRING_RESULT (nautilus_strstrip (g_strdup ("_f_o__o_"), '_'), "foo");
#define TEST_INTEGER_CONVERSION_FUNCTIONS(string, boolean_result, integer_result) \
NAUTILUS_CHECK_BOOLEAN_RESULT (nautilus_string_to_int (string, &integer), boolean_result); \
diff --git a/libnautilus/nautilus-string.h b/libnautilus/nautilus-string.h
index 9d269dcd7..03c778f00 100644
--- a/libnautilus/nautilus-string.h
+++ b/libnautilus/nautilus-string.h
@@ -47,8 +47,8 @@ char * nautilus_strdup_prefix (const char *source_null_allowed,
gboolean nautilus_has_suffix (const char *target_null_allowed,
const char *suffix_null_allowed);
-char * nautilus_strstrip (char *string_null_allowed,
- char remove_this);
+char * nautilus_strstrip (char *string_null_allowed,
+ char remove_this);
/* Conversions to and from strings. */
diff --git a/src/file-manager/Makefile.am b/src/file-manager/Makefile.am
index de6d20e66..36412e10d 100644
--- a/src/file-manager/Makefile.am
+++ b/src/file-manager/Makefile.am
@@ -33,6 +33,8 @@ libntl_file_manager_la_SOURCES= \
fm-icon-text-window.h \
fm-icons-controller.c \
fm-icons-controller.h \
+ fm-properties-window.c \
+ fm-properties-window.h \
fm-signaller.c \
fm-signaller.h
diff --git a/src/file-manager/fm-directory-view-icons.c b/src/file-manager/fm-directory-view-icons.c
index 561602c4d..4c1940c7c 100644
--- a/src/file-manager/fm-directory-view-icons.c
+++ b/src/file-manager/fm-directory-view-icons.c
@@ -49,11 +49,11 @@
#define DEFAULT_BACKGROUND_COLOR "rgb:FFFF/FFFF/FFFF"
/* Paths to use when creating & referring to bonobo menu items */
-#define FM_DIRECTORY_VIEW_ICONS_MENU_PATH_BEFORE_STRETCH_SEPARATOR "/Settings/Before Stretch Separator"
-#define FM_DIRECTORY_VIEW_ICONS_MENU_PATH_STRETCH_ICON "/Settings/Stretch"
-#define FM_DIRECTORY_VIEW_ICONS_MENU_PATH_RESTORE_STRETCHED_ICONS "/Settings/Restore"
-#define FM_DIRECTORY_VIEW_ICONS_MENU_PATH_AFTER_STRETCH_SEPARATOR "/Settings/After Stretch Separator"
-#define FM_DIRECTORY_VIEW_ICONS_MENU_PATH_CUSTOMIZE_ICON_TEXT "/Settings/Icon Text"
+#define MENU_PATH_BEFORE_STRETCH_SEPARATOR "/Settings/Before Stretch Separator"
+#define MENU_PATH_STRETCH_ICON "/Settings/Stretch"
+#define MENU_PATH_RESTORE_STRETCHED_ICONS "/Settings/Restore"
+#define MENU_PATH_AFTER_STRETCH_SEPARATOR "/Settings/After Stretch Separator"
+#define MENU_PATH_CUSTOMIZE_ICON_TEXT "/Settings/Icon Text"
/* forward declarations */
@@ -367,14 +367,14 @@ fm_directory_view_icons_compute_menu_item_info (FMDirectoryViewIcons *view,
icon_container = get_icon_container (view);
- if (strcmp (FM_DIRECTORY_VIEW_ICONS_MENU_PATH_STRETCH_ICON, menu_path) == 0) {
+ if (strcmp (MENU_PATH_STRETCH_ICON, menu_path) == 0) {
*return_name = g_strdup (_("_Stretch Icon"));
/* Current stretching UI only works on one item at a time, so we'll
* desensitize the menu item if that's not the case.
*/
*sensitive_return = g_list_length (files) == 1
&& !gnome_icon_container_has_stretch_handles (icon_container);
- } else if (strcmp (FM_DIRECTORY_VIEW_ICONS_MENU_PATH_RESTORE_STRETCHED_ICONS, menu_path) == 0) {
+ } else if (strcmp (MENU_PATH_RESTORE_STRETCHED_ICONS, menu_path) == 0) {
if (g_list_length (files) > 1) {
*return_name = g_strdup (_("_Restore Icons to Unstretched Size"));
} else {
@@ -383,7 +383,7 @@ fm_directory_view_icons_compute_menu_item_info (FMDirectoryViewIcons *view,
*sensitive_return = gnome_icon_container_is_stretched (icon_container);
- } else if (strcmp (FM_DIRECTORY_VIEW_ICONS_MENU_PATH_CUSTOMIZE_ICON_TEXT, menu_path) == 0) {
+ } else if (strcmp (MENU_PATH_CUSTOMIZE_ICON_TEXT, menu_path) == 0) {
*return_name = g_strdup (_("Customize _Icon Text..."));
*sensitive_return = TRUE;
} else {
@@ -433,26 +433,20 @@ fm_directory_view_icons_append_selection_context_menu_items (FMDirectoryView *vi
(view, menu, files));
append_one_context_menu_item (FM_DIRECTORY_VIEW_ICONS (view), menu, files,
- FM_DIRECTORY_VIEW_ICONS_MENU_PATH_STRETCH_ICON,
+ MENU_PATH_STRETCH_ICON,
GTK_SIGNAL_FUNC (show_stretch_handles_cb));
append_one_context_menu_item (FM_DIRECTORY_VIEW_ICONS (view), menu, files,
- FM_DIRECTORY_VIEW_ICONS_MENU_PATH_RESTORE_STRETCHED_ICONS,
+ MENU_PATH_RESTORE_STRETCHED_ICONS,
GTK_SIGNAL_FUNC (unstretch_icons_cb));
}
-/**
- * Note that this is used both as a Bonobo menu callback and a signal callback.
+/* Note that this is used both as a Bonobo menu callback and a signal callback.
* The first parameter is different in these cases, but we just ignore it anyway.
*/
static void
-customize_icon_text_cb (gpointer ignored, gpointer view)
+customize_icon_text_cb (gpointer ignored1, gpointer ignored2)
{
- GtkWindow *window;
-
- g_assert (FM_IS_DIRECTORY_VIEW_ICONS (view));
-
- window = GTK_WINDOW (fm_icon_text_window_get_or_create ());
- nautilus_gtk_window_present (window);
+ nautilus_gtk_window_present (fm_icon_text_window_get_or_create ());
}
static void
@@ -476,7 +470,7 @@ fm_directory_view_icons_append_background_context_menu_items (FMDirectoryView *v
gtk_menu_append (menu, menu_item);
append_one_context_menu_item (FM_DIRECTORY_VIEW_ICONS (view), menu, NULL,
- FM_DIRECTORY_VIEW_ICONS_MENU_PATH_CUSTOMIZE_ICON_TEXT,
+ MENU_PATH_CUSTOMIZE_ICON_TEXT,
GTK_SIGNAL_FUNC (customize_icon_text_cb));
}
@@ -791,26 +785,26 @@ fm_directory_view_icons_merge_menus (FMDirectoryView *view)
ui_handler = fm_directory_view_get_bonobo_ui_handler (view);
bonobo_ui_handler_menu_new_separator (ui_handler,
- FM_DIRECTORY_VIEW_ICONS_MENU_PATH_BEFORE_STRETCH_SEPARATOR,
+ MENU_PATH_BEFORE_STRETCH_SEPARATOR,
-1);
append_bonobo_menu_item (FM_DIRECTORY_VIEW_ICONS (view), ui_handler, selection,
- FM_DIRECTORY_VIEW_ICONS_MENU_PATH_STRETCH_ICON,
+ MENU_PATH_STRETCH_ICON,
_("Make the selected icon stretchable"),
- (BonoboUIHandlerCallbackFunc)show_stretch_handles_cb, view);
+ (BonoboUIHandlerCallbackFunc) show_stretch_handles_cb, view);
append_bonobo_menu_item (FM_DIRECTORY_VIEW_ICONS (view), ui_handler, selection,
- FM_DIRECTORY_VIEW_ICONS_MENU_PATH_RESTORE_STRETCHED_ICONS,
+ MENU_PATH_RESTORE_STRETCHED_ICONS,
_("Restore each selected icon to its original size"),
- (BonoboUIHandlerCallbackFunc)unstretch_icons_cb, view);
+ (BonoboUIHandlerCallbackFunc) unstretch_icons_cb, view);
bonobo_ui_handler_menu_new_separator (ui_handler,
- FM_DIRECTORY_VIEW_ICONS_MENU_PATH_AFTER_STRETCH_SEPARATOR,
+ MENU_PATH_AFTER_STRETCH_SEPARATOR,
-1);
append_bonobo_menu_item (FM_DIRECTORY_VIEW_ICONS (view), ui_handler, selection,
- FM_DIRECTORY_VIEW_ICONS_MENU_PATH_CUSTOMIZE_ICON_TEXT,
+ MENU_PATH_CUSTOMIZE_ICON_TEXT,
_("Choose which information appears beneath each icon's name"),
- (BonoboUIHandlerCallbackFunc)customize_icon_text_cb, view);
+ (BonoboUIHandlerCallbackFunc) customize_icon_text_cb, view);
nautilus_file_list_free (selection);
}
@@ -842,9 +836,9 @@ fm_directory_view_icons_update_menus (FMDirectoryView *view)
selection = fm_directory_view_get_selection (view);
update_bonobo_menu_item (FM_DIRECTORY_VIEW_ICONS (view), ui_handler, selection,
- FM_DIRECTORY_VIEW_ICONS_MENU_PATH_STRETCH_ICON);
+ MENU_PATH_STRETCH_ICON);
update_bonobo_menu_item (FM_DIRECTORY_VIEW_ICONS (view), ui_handler, selection,
- FM_DIRECTORY_VIEW_ICONS_MENU_PATH_RESTORE_STRETCHED_ICONS);
+ MENU_PATH_RESTORE_STRETCHED_ICONS);
nautilus_file_list_free (selection);
}
diff --git a/src/file-manager/fm-directory-view.c b/src/file-manager/fm-directory-view.c
index ce8dfa3a2..80ef16a14 100644
--- a/src/file-manager/fm-directory-view.c
+++ b/src/file-manager/fm-directory-view.c
@@ -45,15 +45,18 @@
#include <libnautilus/nautilus-icon-factory.h>
#include <libnautilus/nautilus-string.h>
+#include "fm-properties-window.h"
+
#define DISPLAY_TIMEOUT_INTERVAL_MSECS 500
/* Paths to use when creating & referring to bonobo menu items */
-#define FM_DIRECTORY_VIEW_MENU_PATH_OPEN "/File/Open"
-#define FM_DIRECTORY_VIEW_MENU_PATH_OPEN_IN_NEW_WINDOW "/File/OpenNew"
-#define FM_DIRECTORY_VIEW_MENU_PATH_DELETE "/File/Delete"
-#define FM_DIRECTORY_VIEW_MENU_PATH_SELECT_ALL "/Edit/Select All"
+#define MENU_PATH_OPEN "/File/Open"
+#define MENU_PATH_OPEN_IN_NEW_WINDOW "/File/OpenNew"
+#define MENU_PATH_DELETE "/File/Delete"
+#define MENU_PATH_SELECT_ALL "/Edit/Select All"
+#define MENU_PATH_SET_PROPERTIES "/Edit/Set Properties"
-enum
+enum
{
ADD_ENTRY,
APPEND_BACKGROUND_CONTEXT_MENU_ITEMS,
@@ -88,48 +91,51 @@ struct _FMDirectoryViewDetails
};
/* forward declarations */
-static void delete_cb (GtkMenuItem *item, GList *files);
-static int display_selection_info_idle_cb (gpointer data);
-static void display_selection_info (FMDirectoryView *view);
-static void fm_directory_view_initialize_class (FMDirectoryViewClass *klass);
-static void fm_directory_view_initialize (FMDirectoryView *view);
-static void fm_directory_view_delete_with_confirm (FMDirectoryView *view, GList *files);
-static void fm_directory_view_destroy (GtkObject *object);
-static void fm_directory_view_append_background_context_menu_items
- (FMDirectoryView *view,
- GtkMenu *menu);
-static void fm_directory_view_merge_menus (FMDirectoryView *view);
-static void fm_directory_view_real_append_background_context_menu_items
- (FMDirectoryView *view,
- GtkMenu *menu);
-static void fm_directory_view_real_append_selection_context_menu_items
- (FMDirectoryView *view,
- GtkMenu *menu,
- GList *files);
-static void fm_directory_view_real_merge_menus (FMDirectoryView *view);
-static void fm_directory_view_real_update_menus (FMDirectoryView *view);
-static GtkMenu *create_selection_context_menu (FMDirectoryView *view);
-static GtkMenu *create_background_context_menu (FMDirectoryView *view);
-static BonoboControl *get_bonobo_control (FMDirectoryView *view);
-static void stop_location_change_cb (NautilusViewFrame *view_frame,
- FMDirectoryView *directory_view);
-static void notify_location_change_cb (NautilusViewFrame *view_frame,
- Nautilus_NavigationInfo *nav_context,
- FMDirectoryView *directory_view);
-static void open_cb (GtkMenuItem *item, NautilusFile *file);
-static void open_in_new_window_cb (GtkMenuItem *item, GList *files);
-static void open_one_in_new_window (gpointer data, gpointer user_data);
-static void select_all_cb (GtkMenuItem *item, FMDirectoryView *directory_view);
-static void zoom_in_cb (GtkMenuItem *item, FMDirectoryView *directory_view);
-static void zoom_out_cb (GtkMenuItem *item, FMDirectoryView *directory_view);
-
-static void schedule_idle_display_of_pending_files (FMDirectoryView *view);
-static void unschedule_idle_display_of_pending_files (FMDirectoryView *view);
-static void schedule_timeout_display_of_pending_files (FMDirectoryView *view);
-static void unschedule_timeout_display_of_pending_files (FMDirectoryView *view);
-static void unschedule_display_of_pending_files (FMDirectoryView *view);
-
-static void disconnect_model_handlers (FMDirectoryView *view);
+static void delete_cb (GtkMenuItem *item,
+ GList *files);
+static int display_selection_info_idle_cb (gpointer data);
+static void display_selection_info (FMDirectoryView *view);
+static void fm_directory_view_initialize_class (FMDirectoryViewClass *klass);
+static void fm_directory_view_initialize (FMDirectoryView *view);
+static void fm_directory_view_delete_with_confirm (FMDirectoryView *view,
+ GList *files);
+static void fm_directory_view_destroy (GtkObject *object);
+static void fm_directory_view_append_background_context_menu_items (FMDirectoryView *view,
+ GtkMenu *menu);
+static void fm_directory_view_merge_menus (FMDirectoryView *view);
+static void fm_directory_view_real_append_background_context_menu_items (FMDirectoryView *view,
+ GtkMenu *menu);
+static void fm_directory_view_real_append_selection_context_menu_items (FMDirectoryView *view,
+ GtkMenu *menu,
+ GList *files);
+static void fm_directory_view_real_merge_menus (FMDirectoryView *view);
+static void fm_directory_view_real_update_menus (FMDirectoryView *view);
+static GtkMenu * create_selection_context_menu (FMDirectoryView *view);
+static GtkMenu * create_background_context_menu (FMDirectoryView *view);
+static BonoboControl *get_bonobo_control (FMDirectoryView *view);
+static void stop_location_change_cb (NautilusViewFrame *view_frame,
+ FMDirectoryView *directory_view);
+static void notify_location_change_cb (NautilusViewFrame *view_frame,
+ Nautilus_NavigationInfo *nav_context,
+ FMDirectoryView *directory_view);
+static void open_cb (GtkMenuItem *item,
+ GList *files);
+static void open_in_new_window_cb (GtkMenuItem *item,
+ GList *files);
+static void open_one_in_new_window (gpointer data,
+ gpointer user_data);
+static void select_all_cb (GtkMenuItem *item,
+ FMDirectoryView *directory_view);
+static void zoom_in_cb (GtkMenuItem *item,
+ FMDirectoryView *directory_view);
+static void zoom_out_cb (GtkMenuItem *item,
+ FMDirectoryView *directory_view);
+static void schedule_idle_display_of_pending_files (FMDirectoryView *view);
+static void unschedule_idle_display_of_pending_files (FMDirectoryView *view);
+static void schedule_timeout_display_of_pending_files (FMDirectoryView *view);
+static void unschedule_timeout_display_of_pending_files (FMDirectoryView *view);
+static void unschedule_display_of_pending_files (FMDirectoryView *view);
+static void disconnect_model_handlers (FMDirectoryView *view);
NAUTILUS_DEFINE_CLASS_BOILERPLATE (FMDirectoryView, fm_directory_view, GTK_TYPE_SCROLLED_WINDOW)
NAUTILUS_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, add_entry)
@@ -292,8 +298,8 @@ bonobo_menu_delete_cb (BonoboUIHandler *ui_handler, gpointer user_data, const ch
static BonoboControl *
get_bonobo_control (FMDirectoryView *view)
{
- return BONOBO_CONTROL (nautilus_view_frame_get_bonobo_control (
- NAUTILUS_VIEW_FRAME (view->details->view_frame)));
+ return BONOBO_CONTROL (nautilus_view_frame_get_bonobo_control
+ (NAUTILUS_VIEW_FRAME (view->details->view_frame)));
}
static void
@@ -423,10 +429,11 @@ display_selection_info (FMDirectoryView *view)
non_folder_size += nautilus_file_get_size (file);
}
- if (first_item_name == NULL)
+ if (first_item_name == NULL) {
first_item_name = nautilus_file_get_name (file);
+ }
}
-
+
nautilus_file_list_free (selection);
memset (&request, 0, sizeof (request));
@@ -1090,13 +1097,16 @@ delete_cb (GtkMenuItem *item, GList *files)
/* handle the open command */
static void
-open_cb (GtkMenuItem *item, NautilusFile *file)
+open_cb (GtkMenuItem *item, GList *files)
{
FMDirectoryView *directory_view;
+ g_assert (g_list_length (files) == 1);
+ g_assert (NAUTILUS_IS_FILE (files->data));
+
directory_view = FM_DIRECTORY_VIEW (gtk_object_get_data (GTK_OBJECT (item), "directory_view"));
- fm_directory_view_activate_entry (directory_view, file, FALSE);
+ fm_directory_view_activate_entry (directory_view, files->data, FALSE);
}
static void
@@ -1119,6 +1129,25 @@ open_in_new_window_cb (GtkMenuItem *item, GList *files)
}
static void
+open_one_properties_window (gpointer data, gpointer user_data)
+{
+ g_assert (NAUTILUS_IS_FILE (data));
+ g_assert (FM_IS_DIRECTORY_VIEW (user_data));
+
+ nautilus_gtk_window_present (fm_properties_window_get_or_create (data));
+}
+
+static void
+open_properties_window_cb (GtkMenuItem *item, GList *files)
+{
+ FMDirectoryView *directory_view;
+
+ directory_view = FM_DIRECTORY_VIEW (gtk_object_get_data (GTK_OBJECT (item), "directory_view"));
+
+ g_list_foreach (files, open_one_properties_window, directory_view);
+}
+
+static void
finish_adding_menu_item (GtkMenu *menu, GtkWidget *menu_item, gboolean sensitive)
{
gtk_widget_set_sensitive (menu_item, sensitive);
@@ -1157,19 +1186,22 @@ compute_menu_item_info (const char *path,
char **return_name,
gboolean *return_sensitivity)
{
- if (strcmp (path, FM_DIRECTORY_VIEW_MENU_PATH_OPEN) == 0) {
+ if (strcmp (path, MENU_PATH_OPEN) == 0) {
*return_name = g_strdup_printf (_("_Open"));
*return_sensitivity = selection_length == 1;
- } else if (strcmp (path, FM_DIRECTORY_VIEW_MENU_PATH_OPEN_IN_NEW_WINDOW) == 0) {
+ } else if (strcmp (path, MENU_PATH_OPEN_IN_NEW_WINDOW) == 0) {
if (selection_length <= 1) {
*return_name = g_strdup (_("Open in _New Window"));
} else {
*return_name = g_strdup_printf (_("Open in %d _New Windows"), selection_length);
}
*return_sensitivity = selection_length > 0;
- } else if (strcmp (path, FM_DIRECTORY_VIEW_MENU_PATH_DELETE) == 0) {
+ } else if (strcmp (path, MENU_PATH_DELETE) == 0) {
*return_name = g_strdup (_("_Delete..."));
*return_sensitivity = selection_length > 0;
+ } else if (strcmp (path, MENU_PATH_SET_PROPERTIES) == 0) {
+ *return_name = g_strdup (_("Set _Properties..."));
+ *return_sensitivity = selection_length > 0;
} else {
g_assert_not_reached ();
}
@@ -1180,84 +1212,52 @@ compute_menu_item_info (const char *path,
}
static void
-append_one_selection_context_menu_item (GtkMenu *menu,
- const char *path,
- int item_count,
- const char *item_data_id,
- gpointer item_data,
- GtkDestroyNotify item_data_destroy_func,
- gboolean ref_item_data,
- GtkSignalFunc callback,
- gpointer callback_data)
+append_selection_menu_item (FMDirectoryView *view,
+ GtkMenu *menu,
+ GList *files,
+ const char *path,
+ GtkSignalFunc callback)
{
GtkWidget *menu_item;
char *label_string;
gboolean sensitive;
- compute_menu_item_info (path, item_count, FALSE, &label_string, &sensitive);
+ compute_menu_item_info (path, g_list_length (files), FALSE, &label_string, &sensitive);
menu_item = gtk_menu_item_new_with_label (label_string);
g_free (label_string);
+
if (sensitive)
{
- if (item_data != NULL) {
- gtk_object_set_data_full (GTK_OBJECT (menu_item),
- item_data_id,
- item_data,
- item_data_destroy_func);
- if (ref_item_data) {
- gtk_object_ref (GTK_OBJECT (item_data));
- }
- }
-
+ /* Attach directory view to item. */
+ gtk_object_ref (GTK_OBJECT (view));
+ gtk_object_set_data_full (GTK_OBJECT (menu_item),
+ "directory_view",
+ view,
+ (GtkDestroyNotify) gtk_object_unref);
+
+ /* Attack callback function to item. */
gtk_signal_connect (GTK_OBJECT (menu_item),
"activate",
callback,
- callback_data);
+ files);
}
finish_adding_menu_item (menu, menu_item, sensitive);
-}
+}
static void
fm_directory_view_real_append_selection_context_menu_items (FMDirectoryView *view,
GtkMenu *menu,
GList *files)
{
- int item_count;
-
- item_count = g_list_length (files);
-
- g_assert (item_count >= 1);
-
- append_one_selection_context_menu_item (menu,
- FM_DIRECTORY_VIEW_MENU_PATH_OPEN,
- item_count,
- "directory_view",
- view,
- (GtkDestroyNotify) gtk_object_unref,
- TRUE,
- open_cb,
- files->data);
-
- append_one_selection_context_menu_item (menu,
- FM_DIRECTORY_VIEW_MENU_PATH_OPEN_IN_NEW_WINDOW,
- item_count,
- "directory_view",
- view,
- (GtkDestroyNotify) gtk_object_unref,
- TRUE,
- open_in_new_window_cb,
- files);
-
- append_one_selection_context_menu_item (menu,
- FM_DIRECTORY_VIEW_MENU_PATH_DELETE,
- item_count,
- "directory_view",
- view,
- (GtkDestroyNotify) gtk_object_unref,
- TRUE,
- delete_cb,
- files);
+ append_selection_menu_item (view, menu, files,
+ MENU_PATH_OPEN, open_cb);
+ append_selection_menu_item (view, menu, files,
+ MENU_PATH_OPEN_IN_NEW_WINDOW, open_in_new_window_cb);
+ append_selection_menu_item (view, menu, files,
+ MENU_PATH_DELETE, delete_cb);
+ append_selection_menu_item (view, menu, files,
+ MENU_PATH_SET_PROPERTIES, open_properties_window_cb);
}
static void
@@ -1273,7 +1273,7 @@ fm_directory_view_real_merge_menus (FMDirectoryView *view)
* right places without special knowledge like this.
*/
bonobo_ui_handler_menu_new_item (ui_handler,
- FM_DIRECTORY_VIEW_MENU_PATH_OPEN,
+ MENU_PATH_OPEN,
_("_Open"),
_("Open the selected item in this window"),
1,
@@ -1284,7 +1284,7 @@ fm_directory_view_real_merge_menus (FMDirectoryView *view)
bonobo_menu_open_cb,
view);
bonobo_ui_handler_menu_new_item (ui_handler,
- FM_DIRECTORY_VIEW_MENU_PATH_OPEN_IN_NEW_WINDOW,
+ MENU_PATH_OPEN_IN_NEW_WINDOW,
_("Open in New Window"),
_("Open each selected item in a new window"),
2,
@@ -1295,7 +1295,7 @@ fm_directory_view_real_merge_menus (FMDirectoryView *view)
bonobo_menu_open_in_new_window_cb,
view);
bonobo_ui_handler_menu_new_item (ui_handler,
- FM_DIRECTORY_VIEW_MENU_PATH_DELETE,
+ MENU_PATH_DELETE,
_("Delete..."),
_("Delete all selected items"),
3,
@@ -1306,15 +1306,15 @@ fm_directory_view_real_merge_menus (FMDirectoryView *view)
bonobo_menu_delete_cb,
view);
bonobo_ui_handler_menu_new_item (ui_handler,
- FM_DIRECTORY_VIEW_MENU_PATH_SELECT_ALL,
+ MENU_PATH_SELECT_ALL,
_("Select All"),
_("Select all items in this window"),
- bonobo_ui_handler_menu_get_pos (ui_handler, FM_DIRECTORY_VIEW_MENU_PATH_SELECT_ALL),
+ bonobo_ui_handler_menu_get_pos (ui_handler, MENU_PATH_SELECT_ALL),
BONOBO_UI_HANDLER_PIXMAP_NONE,
NULL,
0,
0,
- (BonoboUIHandlerCallbackFunc)select_all_cb,
+ (BonoboUIHandlerCallbackFunc) select_all_cb,
view);
}
@@ -1342,9 +1342,9 @@ fm_directory_view_real_update_menus (FMDirectoryView *view)
count = g_list_length (selection);
nautilus_file_list_free (selection);
- update_one_menu_item (handler, FM_DIRECTORY_VIEW_MENU_PATH_OPEN, count);
- update_one_menu_item (handler, FM_DIRECTORY_VIEW_MENU_PATH_OPEN_IN_NEW_WINDOW, count);
- update_one_menu_item (handler, FM_DIRECTORY_VIEW_MENU_PATH_DELETE, count);
+ update_one_menu_item (handler, MENU_PATH_OPEN, count);
+ update_one_menu_item (handler, MENU_PATH_OPEN_IN_NEW_WINDOW, count);
+ update_one_menu_item (handler, MENU_PATH_DELETE, count);
}
static GtkMenu *
@@ -1410,8 +1410,6 @@ fm_directory_view_append_background_context_menu_items (FMDirectoryView *view,
}
-/* FIXME - need a way for specific views to add custom commands here. */
-
static GtkMenu *
create_background_context_menu (FMDirectoryView *view)
{
@@ -1462,7 +1460,6 @@ fm_directory_view_pop_up_background_context_menu (FMDirectoryView *view)
NAUTILUS_DEFAULT_POPUP_MENU_DISPLACEMENT);
}
-
/**
* fm_directory_view_notify_selection_changed:
*
@@ -1581,7 +1578,6 @@ fm_directory_view_load_uri (FMDirectoryView *view,
view);
}
-
/**
* fm_directory_view_merge_menus:
*
diff --git a/src/file-manager/fm-directory-view.h b/src/file-manager/fm-directory-view.h
index b18c274f7..f240d60b4 100644
--- a/src/file-manager/fm-directory-view.h
+++ b/src/file-manager/fm-directory-view.h
@@ -30,6 +30,7 @@
#include <gtk/gtkscrolledwindow.h>
#include <libnautilus/ntl-content-view-frame.h>
#include <libnautilus/nautilus-directory.h>
+#include <libnautilus/nautilus-file.h>
typedef struct _FMDirectoryView FMDirectoryView;
typedef struct _FMDirectoryViewClass FMDirectoryViewClass;
diff --git a/src/file-manager/fm-icon-text-window.c b/src/file-manager/fm-icon-text-window.c
index 030fb230e..66e0057cf 100644
--- a/src/file-manager/fm-icon-text-window.c
+++ b/src/file-manager/fm-icon-text-window.c
@@ -36,8 +36,10 @@
#include <gtk/gtktext.h>
#include <gtk/gtkradiobutton.h>
#include <gtk/gtkvbox.h>
+#include <libgnome/gnome-defs.h>
#include <libgnome/gnome-i18n.h>
#include <libgnomeui/gnome-uidefs.h>
+#include "fm-directory-view-icons.h"
static void ensure_unique_attributes (int menu_index);
static gboolean fm_icon_text_window_delete_event_cb (GtkWidget *widget,
@@ -288,14 +290,14 @@ fm_icon_text_window_delete_event_cb (GtkWidget *widget,
* beneath icons.
*
**/
-GtkWidget *
+GtkWindow *
fm_icon_text_window_get_or_create (void)
{
static GtkWidget *icon_text_window = NULL;
- if (icon_text_window == NULL)
+ if (icon_text_window == NULL) {
icon_text_window = create_icon_text_window ();
+ }
- g_assert (GTK_IS_WINDOW (icon_text_window));
- return icon_text_window;
+ return GTK_WINDOW (icon_text_window);
}
diff --git a/src/file-manager/fm-icon-text-window.h b/src/file-manager/fm-icon-text-window.h
index 55f18444d..6ef905db5 100644
--- a/src/file-manager/fm-icon-text-window.h
+++ b/src/file-manager/fm-icon-text-window.h
@@ -26,9 +26,8 @@
#ifndef FM_ICON_TEXT_WINDOW_H
#define FM_ICON_TEXT_WINDOW_H
-#include "fm-directory-view-icons.h"
#include <gtk/gtkwindow.h>
-GtkWidget * fm_icon_text_window_get_or_create (void);
+GtkWindow *fm_icon_text_window_get_or_create (void);
#endif /* FM_ICON_TEXT_WINDOW_H */
diff --git a/src/file-manager/fm-properties-window.c b/src/file-manager/fm-properties-window.c
new file mode 100644
index 000000000..afdc95476
--- /dev/null
+++ b/src/file-manager/fm-properties-window.c
@@ -0,0 +1,34 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+
+/* fm-properties-window.c - window that lets user modify file properties
+
+ Copyright (C) 2000 Eazel, Inc.
+
+ The Gnome Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Library 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 GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Authors: Darin Adler <darin@eazel.com>
+*/
+
+#include <config.h>
+#include "fm-properties-window.h"
+
+/* static GHashTable *windows; */
+
+GtkWindow *
+fm_properties_window_get_or_create (NautilusFile *file)
+{
+ return NULL;
+}
diff --git a/src/file-manager/fm-properties-window.h b/src/file-manager/fm-properties-window.h
new file mode 100644
index 000000000..db57c6642
--- /dev/null
+++ b/src/file-manager/fm-properties-window.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+
+/* fm-properties-window.h - interface for window that lets user modify
+ icon properties
+
+ Copyright (C) 2000 Eazel, Inc.
+
+ The Gnome Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Library 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 GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Authors: Darin Adler <darin@eazel.com>
+*/
+
+#ifndef FM_PROPERTIES_WINDOW_H
+#define FM_PROPERTIES_WINDOW_H
+
+#include <gtk/gtkwindow.h>
+#include <libnautilus/nautilus-file.h>
+
+GtkWindow *fm_properties_window_get_or_create (NautilusFile *);
+
+#endif /* FM_PROPERTIES_WINDOW_H */
diff --git a/src/nautilus-information-panel.c b/src/nautilus-information-panel.c
index c3652a053..54d2b46e7 100644
--- a/src/nautilus-information-panel.c
+++ b/src/nautilus-information-panel.c
@@ -37,6 +37,7 @@
#include <libgnomevfs/gnome-vfs-uri.h>
#include <libnautilus/nautilus-background.h>
#include <libnautilus/nautilus-directory.h>
+#include <libnautilus/nautilus-file.h>
#include <libnautilus/nautilus-glib-extensions.h>
#include <libnautilus/nautilus-gtk-macros.h>
#include <libnautilus/nautilus-metadata.h>
diff --git a/src/nautilus-sidebar.c b/src/nautilus-sidebar.c
index c3652a053..54d2b46e7 100644
--- a/src/nautilus-sidebar.c
+++ b/src/nautilus-sidebar.c
@@ -37,6 +37,7 @@
#include <libgnomevfs/gnome-vfs-uri.h>
#include <libnautilus/nautilus-background.h>
#include <libnautilus/nautilus-directory.h>
+#include <libnautilus/nautilus-file.h>
#include <libnautilus/nautilus-glib-extensions.h>
#include <libnautilus/nautilus-gtk-macros.h>
#include <libnautilus/nautilus-metadata.h>
diff --git a/src/ntl-index-panel.c b/src/ntl-index-panel.c
index c3652a053..54d2b46e7 100644
--- a/src/ntl-index-panel.c
+++ b/src/ntl-index-panel.c
@@ -37,6 +37,7 @@
#include <libgnomevfs/gnome-vfs-uri.h>
#include <libnautilus/nautilus-background.h>
#include <libnautilus/nautilus-directory.h>
+#include <libnautilus/nautilus-file.h>
#include <libnautilus/nautilus-glib-extensions.h>
#include <libnautilus/nautilus-gtk-macros.h>
#include <libnautilus/nautilus-metadata.h>