diff -Nrup -x '*.orig' -x '*.rej' -x '*.*~' ../SUNWgnome-file-mgr-2.30.0-b4/nautilus-2.30.1/configure.in nautilus-2.30.1/configure.in
--- ../SUNWgnome-file-mgr-2.30.0-b4/nautilus-2.30.1/configure.in	2010-05-14 17:16:20.583765747 +0200
+++ nautilus-2.30.1/configure.in	2010-05-14 17:16:39.539580939 +0200
@@ -232,6 +232,52 @@ if test "x$enable_packagekit" != "xno"; 
 	msg_packagekit=yes
 	AC_DEFINE(ENABLE_PACKAGEKIT, 1, [define to enable PackageKit mimetype installer])
 fi
+dnl ==========================================================================
+
+dnl ********************
+dnl * Check for libzfs *
+dnl ********************
+ZFS_LIBS=
+msg_zfs=no
+AC_CHECK_LIB(zfs, zfs_iter_root,
+   [AC_CHECK_HEADER(libzfs.h,
+       [AC_DEFINE(HAVE_ZFS, 1, [Define to 1 if ZFS is available])
+        ZFS_LIBS="-lzfs"
+        msg_zfs=yes])
+     ])
+AC_SUBST(ZFS_LIBS)
+
+dnl ==========================================================================
+
+dnl ********************
+dnl * Check for libscf*
+dnl ********************
+SCF_LIBS=
+msg_scf=no
+AC_CHECK_LIB(scf, scf_handle_bind,
+   [AC_CHECK_HEADER(libscf.h,
+       [AC_DEFINE(HAVE_SCF, 1, [Define to 1 if SCF is available])
+        SCF_LIBS="-lscf"
+        msg_scf=yes])
+     ])
+AC_SUBST(SCF_LIBS)
+
+dnl ==========================================================================
+
+dnl ********************
+dnl * Check for libscf*
+dnl ********************
+NVPAIR_LIBS=
+msg_nvpair=no
+AC_CHECK_LIB(nvpair, nvpair_value_match,
+   [AC_CHECK_HEADER(libscf.h,
+       [AC_DEFINE(NVPAIR_LIBS, 1, [Define to 1 if nvpair is available])
+        NVPAIR_LIBS="-lnvpair"
+        msg_nvpair=yes])
+     ])
+AC_SUBST(NVPAIR_LIBS)
+
+
 
 dnl ==========================================================================
 
--- nautilus-3.1.3/icons/Makefile.am.orig	2011-04-04 19:01:22.000000000 +0100
+++ nautilus-3.1.3/icons/Makefile.am	2011-07-22 09:20:35.708887571 +0100
@@ -4,7 +4,11 @@
 
 icon_DATA =\
 	audio.svg \
+	camera.png \
 	knob.png \
+	restore.png \
+	restore-no.png \
+	restore-search.png \
 	thumbnail_frame.png \
 	$(NULL)
 
--- nautilus-3.1.3/libnautilus-private/Makefile.am.orig	2011-07-22 09:23:13.721321695 +0100
+++ nautilus-3.1.3/libnautilus-private/Makefile.am	2011-07-22 09:27:45.285633388 +0100
@@ -49,6 +49,9 @@
 	$(BASE_LIBS)			\
 	$(COMMON_LIBS)			\
 	$(NAUTILUS_LIBS)		\
+	$(ZFS_LIBS)			\
+	$(SCF_LIBS)			\
+	$(NVPAIR_LIBS)			\
 	$(NULL)
 
 libnautilus_private_la_SOURCES = \
@@ -192,6 +195,8 @@
 	nautilus-vfs-directory.h \
 	nautilus-vfs-file.c \
 	nautilus-vfs-file.h \
+	nautilus-zfs.c \
+	nautilus-zfs.h \
 	$(NULL)
 
 nodist_libnautilus_private_la_SOURCES =\
--- nautilus-3.1.3/libnautilus-private/org.gnome.nautilus.gschema.xml.in.orig	2011-07-22 09:34:01.449051792 +0100
+++ nautilus-3.1.3/libnautilus-private/org.gnome.nautilus.gschema.xml.in	2011-07-22 09:38:31.164878925 +0100
@@ -72,6 +72,11 @@
       <_summary>Where to position newly open tabs in browser windows.</_summary>
       <_description>If set to "after-current-tab", then new tabs are inserted after the current tab. If set to "end", then new tabs are appended to the end of the tab list.</_description>
     </key>
+    <key name="enable-time-slider" type="b">
+      <default>true</default>
+      <_summary>Enables the visualization of ZFS snapshots timeline</_summary>
+      <_description>If set to true, the visualization of the ZFS snapshots timeline is enabled.</_description>
+    </key>
     <key name="always-use-browser" type="b">
       <default>true</default>
       <_summary>Enables the classic Nautilus behavior, where all windows are browsers</_summary>
--- nautilus-3.1.3/libnautilus-private/nautilus-column-utilities.c.orig	2011-04-04 19:01:22.000000000 +0100
+++ nautilus-3.1.3/libnautilus-private/nautilus-column-utilities.c	2011-07-22 09:46:21.698069053 +0100
@@ -129,6 +129,15 @@
 					       "label", _("Location"),
 					       "description", _("The location of the file."),
 					       NULL));
+	columns = g_list_append (columns,
+				 g_object_new (NAUTILUS_TYPE_COLUMN,
+					       "name", "restore_info",
+					       "attribute", "restore_info",
+					       /* SUN_BRANDING */
+					       "label", _("Restore information"),
+					       /* SUN_BRANDING */
+					       "description", _("Restore information of the file."),
+					       NULL));
 
 	return columns;
 }
diff -Nrup -x '*.orig' -x '*.rej' -x '*.*~' ../SUNWgnome-file-mgr-2.30.0-b4/nautilus-2.30.1/libnautilus-private/nautilus-directory-async.c nautilus-2.30.1/libnautilus-private/nautilus-directory-async.c
--- ../SUNWgnome-file-mgr-2.30.0-b4/nautilus-2.30.1/libnautilus-private/nautilus-directory-async.c	2010-05-14 17:16:20.620971445 +0200
+++ nautilus-2.30.1/libnautilus-private/nautilus-directory-async.c	2010-05-14 17:16:39.543203000 +0200
@@ -658,6 +658,7 @@ remove_monitor_link (NautilusDirectory *
 		g_list_free_1 (link);
 	}
 }
+	
 
 static void
 remove_monitor (NautilusDirectory *directory,
@@ -722,6 +723,10 @@ nautilus_directory_set_up_request (Nauti
 		REQUEST_SET_TYPE (request, REQUEST_FILESYSTEM_INFO);
 	}
 
+	if (file_attributes & NAUTILUS_FILE_ATTRIBUTE_RESTORE_INFO) {
+		REQUEST_SET_TYPE (request, REQUEST_RESTORE_INFO);
+	}
+
 	return request;
 }
 
@@ -4759,6 +4764,18 @@ cancel_link_info_for_file (NautilusDirec
 	}
 }
 
+void nautilus_directory_cancel_restore_info (NautilusDirectory *directory)
+{
+  if (NAUTILUS_IS_DIRECTORY (directory))
+    {
+      if (directory->details->restore_cancel)
+	{
+	  g_cancellable_cancel (directory->details->restore_cancel);
+	  directory->details->restore_cancel = NULL;
+	}
+    }
+}
+
 
 static void
 cancel_loading_attributes (NautilusDirectory *directory,
@@ -4801,7 +4818,9 @@ cancel_loading_attributes (NautilusDirec
 	if (REQUEST_WANTS_TYPE (request, REQUEST_MOUNT)) {
 		mount_cancel (directory);
 	}
-	
+        if (REQUEST_WANTS_TYPE (request, REQUEST_RESTORE_INFO)) {
+            nautilus_directory_cancel_restore_info (directory);
+        }
 	nautilus_directory_async_state_changed (directory);
 }
 
@@ -4843,7 +4862,9 @@ nautilus_directory_cancel_loading_file_a
 	if (REQUEST_WANTS_TYPE (request, REQUEST_MOUNT)) {
 		cancel_mount_for_file (directory, file);
 	}
-
+        if (REQUEST_WANTS_TYPE (request, REQUEST_RESTORE_INFO)) {
+            nautilus_directory_cancel_restore_info (directory);
+        }
 	nautilus_directory_async_state_changed (directory);
 }
 
diff -Nrup -x '*.orig' -x '*.rej' -x '*.*~' ../SUNWgnome-file-mgr-2.30.0-b4/nautilus-2.30.1/libnautilus-private/nautilus-directory-private.h nautilus-2.30.1/libnautilus-private/nautilus-directory-private.h
--- ../SUNWgnome-file-mgr-2.30.0-b4/nautilus-2.30.1/libnautilus-private/nautilus-directory-private.h	2009-12-09 12:03:51.000000000 +0100
+++ nautilus-2.30.1/libnautilus-private/nautilus-directory-private.h	2010-05-14 17:16:39.543661242 +0200
@@ -58,6 +58,7 @@ typedef enum {
 	REQUEST_THUMBNAIL,
 	REQUEST_MOUNT,
 	REQUEST_FILESYSTEM_INFO,
+	REQUEST_RESTORE_INFO,
 	REQUEST_TYPE_LAST
 } RequestType;
 
@@ -140,6 +141,9 @@ struct NautilusDirectoryDetails
 
 	guint64 free_space; /* (guint)-1 for unknown */
 	time_t free_space_read; /* The time free_space was updated, or 0 for never */
+	GCancellable *restore_cancel;
+	/* zfs snapshot info */
+ 	GList *zfs_snapshots;
 };
 
 NautilusDirectory *nautilus_directory_get_existing                    (GFile                     *location);
--- nautilus-3.1.3/libnautilus-private/nautilus-directory.c.orig	2011-07-22 15:39:09.879596935 +0100
+++ nautilus-3.1.3/libnautilus-private/nautilus-directory.c	2011-07-22 15:46:56.201033321 +0100
@@ -35,6 +35,7 @@
 #include "nautilus-metadata.h"
 #include "nautilus-desktop-directory.h"
 #include "nautilus-vfs-directory.h"
+#include "nautilus-zfs.h"
 #include <eel/eel-glib-extensions.h>
 #include <eel/eel-gtk-macros.h>
 #include <eel/eel-string.h>
@@ -129,6 +130,8 @@
 	directory->details->low_priority_queue = nautilus_file_queue_new ();
 	directory->details->extension_queue = nautilus_file_queue_new ();
 	directory->details->free_space = (guint64)-1;
+        directory->details->zfs_snapshots = NULL;
+        directory->details->restore_cancel = NULL;
 }
 
 NautilusDirectory *
@@ -160,7 +163,7 @@
 nautilus_directory_finalize (GObject *object)
 {
 	NautilusDirectory *directory;
-
+	
 	directory = NAUTILUS_DIRECTORY (object);
 
 	g_hash_table_remove (directories, directory->details->location);
@@ -196,7 +199,13 @@
 	if (directory->details->hidden_file_hash) {
 		g_hash_table_destroy (directory->details->hidden_file_hash);
 	}
-	
+
+	if (directory->details->zfs_snapshots) {
+	        ts_free_snapshots (directory->details->zfs_snapshots);
+	}
+	if (directory->details->restore_cancel)
+	  g_cancellable_cancel (directory->details->restore_cancel);
+
 	nautilus_file_queue_destroy (directory->details->high_priority_queue);
 	nautilus_file_queue_destroy (directory->details->low_priority_queue);
 	nautilus_file_queue_destroy (directory->details->extension_queue);
@@ -308,11 +317,26 @@
 	g_hash_table_foreach (directories, async_state_changed_one, NULL);
 }
 
+static gboolean time_slider_enabled = TRUE;
+
+gboolean is_time_slider_enabled ()
+{
+	return time_slider_enabled;
+}
+
+static void time_slider_pref_changed_callback (gpointer callback_data)
+{
+	time_slider_enabled = g_settings_get_boolean(nautilus_preferences,
+				NAUTILUS_PREFERENCES_ENABLE_TIME_SLIDER);
+}
+
 static void
 add_preferences_callbacks (void)
 {
 	nautilus_global_preferences_init ();
 
+	time_slider_enabled = g_settings_get_boolean(nautilus_preferences,
+				NAUTILUS_PREFERENCES_ENABLE_TIME_SLIDER);
 	g_signal_connect_swapped (nautilus_preferences,
 				  "changed::" NAUTILUS_PREFERENCES_SHOW_HIDDEN_FILES,
 				  G_CALLBACK(filtering_changed_callback),
@@ -330,6 +354,10 @@
 				  "changed::" NAUTILUS_PREFERENCES_DATE_FORMAT,
 				  G_CALLBACK(async_data_preference_changed_callback),
 				  NULL);
+	g_signal_connect_swapped (nautilus_preferences,
+				  "changed::" NAUTILUS_PREFERENCES_ENABLE_TIME_SLIDER,
+				  G_CALLBACK(time_slider_pref_changed_callback),
+				  NULL);
 }
 
 static void
@@ -534,6 +562,7 @@
 {
 	NautilusDirectory *directory;
 	char *uri;
+	char *path;
 
 	uri = g_file_get_uri (location);
 	
@@ -545,10 +574,13 @@
 		directory = NAUTILUS_DIRECTORY (nautilus_search_directory_new_from_saved_search (uri));
 	} else {
 		directory = NAUTILUS_DIRECTORY (g_object_new (NAUTILUS_TYPE_VFS_DIRECTORY, NULL));
+		path = g_file_get_path (location);
+		g_free (path);
 	}
 
 	set_directory_location (directory, location);
 
+
 	g_free (uri);
 	
 	return directory;
@@ -567,6 +599,201 @@
 	       g_file_is_native (directory->details->location);
 }
 
+typedef struct {
+  NautilusDirectory         *dir;
+  GCancellable	            *cancel;
+  TsReadyCallback	     callback;
+  gpointer		     callback_user_data;
+} QuerySnapshotsAsyncData;
+
+
+static void snapshot_list_ready_callback (GObject *source_object,
+					  GAsyncResult *res,
+					  gpointer user_data)
+{
+  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+  QuerySnapshotsAsyncData *data = (QuerySnapshotsAsyncData*) user_data;
+
+  if (!g_cancellable_is_cancelled (data->cancel))
+    {
+      data->dir->details->zfs_snapshots = g_simple_async_result_get_op_res_gpointer (simple);
+    }
+
+  data->callback (data->dir, data->cancel, data->callback_user_data);
+}
+
+void
+nautilus_directory_get_snapshots_async (NautilusDirectory *directory, 
+					TsReadyCallback ready_callback, 
+					GCancellable *cancel, 
+					gpointer      callback_user_data)
+{
+	g_assert (NAUTILUS_IS_DIRECTORY (directory));
+	
+	if (directory->details->location == NULL) 
+	  return;
+
+	if (directory->details->zfs_snapshots) {
+	  ts_free_snapshots (directory->details->zfs_snapshots);
+	  directory->details->zfs_snapshots = NULL;
+	}
+	
+	if (is_time_slider_enabled ())
+	  {
+	    QuerySnapshotsAsyncData *data;
+	    data = g_new0 (QuerySnapshotsAsyncData,1);
+	    data->dir = directory;
+	    data->cancel = cancel;
+	    data->callback = ready_callback;
+	    data->callback_user_data = callback_user_data;
+
+	    ts_get_snapshots_for_dir_async (directory->details->location, 
+					    snapshot_list_ready_callback, 
+					    cancel,
+					    data);
+	  }
+}
+
+gboolean
+nautilus_directory_has_snapshots (NautilusDirectory *directory)
+{
+	g_assert (NAUTILUS_IS_DIRECTORY (directory));
+	
+	if (directory->details->zfs_snapshots)
+	  return TRUE;
+
+	return FALSE;
+}
+int
+nautilus_directory_get_num_snapshots (NautilusDirectory	*directory)
+{
+  g_assert (NAUTILUS_IS_DIRECTORY (directory));
+
+    if (directory->details->zfs_snapshots)
+      {
+	int i = 0;
+	GList *tmp;
+	for (tmp = directory->details->zfs_snapshots;tmp;tmp = tmp->next)
+	  i++;
+	return i;
+      }
+    return 0;
+}
+
+gboolean           
+nautilus_directory_is_in_snapshot (NautilusDirectory         *directory)
+{
+  char *directory_uri;
+  gboolean result = FALSE;
+
+  g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), FALSE);
+  
+  directory_uri = nautilus_directory_get_uri (directory);
+  
+  result = ts_is_in_snapshot (directory_uri);
+
+  g_free (directory_uri);
+
+  return result;
+}
+
+GList *
+nautilus_directory_get_snapshots (NautilusDirectory *directory)
+{
+  g_assert (NAUTILUS_IS_DIRECTORY (directory));
+
+  return directory->details->zfs_snapshots;
+}
+
+void  nautilus_directory_remove_snapshot (NautilusDirectory *directory,
+					  ZfsDataSet *snap)
+{
+  if (directory->details->zfs_snapshots)
+    {
+      directory->details->zfs_snapshots = g_list_remove (directory->details->zfs_snapshots, snap);
+      ts_free_zfs_dataset (snap);
+    }
+}
+/* return true if snapdir dir path is a dir or subdir of refdir */
+gboolean 
+nautilus_directory_is_a_snapshot_dir_of (NautilusDirectory *snapdir,
+					 NautilusDirectory *refdir)
+{
+
+   gboolean result = FALSE;   
+
+  if (nautilus_directory_is_in_snapshot (snapdir))
+    {
+      char snapdir_root_real_path [PATH_MAX+1];
+      char refdir_real_path [PATH_MAX+1];
+      NautilusDirectory *snapdir_root = nautilus_directory_get_snap_root (snapdir);
+      GFile *snapdir_root_file = nautilus_directory_get_location (snapdir_root);
+      GFile *refdir_file = nautilus_directory_get_location (refdir);
+      char* snapdir_root_path = g_file_get_path (snapdir_root_file);
+      char* refdir_path = g_file_get_path (refdir_file);
+      
+      if (ts_realpath (snapdir_root_path, snapdir_root_real_path) && 
+	      ts_realpath (refdir_path, refdir_real_path))
+	    {
+	      if (g_strrstr (snapdir_root_real_path,refdir_real_path))
+		result = TRUE;
+	    }
+
+	  g_free (snapdir_root_path);
+	  g_free (refdir_path);
+	  g_object_unref (snapdir_root_file);
+	  g_object_unref (refdir_file);
+	  g_object_unref (snapdir_root);
+    }
+
+  return result;
+}
+
+NautilusDirectory *nautilus_directory_get_snap_root (NautilusDirectory	  *directory)
+{
+  char *directory_uri, *snap_root;
+  char *zfs, *iter;
+  int count = 0;
+  NautilusDirectory *new_dir;
+
+  g_assert (NAUTILUS_IS_DIRECTORY (directory));
+  
+  directory_uri = nautilus_directory_get_uri (directory);
+
+
+  if (!nautilus_directory_is_in_snapshot (directory))
+    {
+      g_free (directory_uri);
+      return directory;
+    }
+
+  /*remove .zfs/snapshot/blah/ */
+  zfs = g_strrstr (directory_uri, ".zfs/snapshot/");
+  iter = zfs;
+
+  if (iter)
+    {
+      iter += sizeof (".zfs/snapshot/");
+      while (*iter != '/' && *iter != '\0')
+	iter++;
+
+      if (*iter == '/')
+	iter++;
+      
+      *zfs = '\0';
+      snap_root = g_strdup_printf ("%s%s", directory_uri, iter);
+      
+      *zfs = 'a';
+      g_free (directory_uri);
+      new_dir = nautilus_directory_get_by_uri (snap_root);
+      g_free (snap_root);
+      return new_dir;
+    }
+  return directory;
+}
+
+
+
 gboolean
 nautilus_directory_is_in_trash (NautilusDirectory *directory)
 {
diff -Nrup -x '*.orig' -x '*.rej' -x '*.*~' ../SUNWgnome-file-mgr-2.30.0-b4/nautilus-2.30.1/libnautilus-private/nautilus-directory.h nautilus-2.30.1/libnautilus-private/nautilus-directory.h
--- ../SUNWgnome-file-mgr-2.30.0-b4/nautilus-2.30.1/libnautilus-private/nautilus-directory.h	2009-12-08 16:17:07.000000000 +0100
+++ nautilus-2.30.1/libnautilus-private/nautilus-directory.h	2010-05-14 17:16:39.545571596 +0200
@@ -28,6 +28,7 @@
 #include <gtk/gtk.h>
 #include <gio/gio.h>
 #include <libnautilus-private/nautilus-file-attributes.h>
+#include <libnautilus-private/nautilus-zfs.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
@@ -219,6 +220,24 @@ gboolean           nautilus_directory_ar
 gboolean           nautilus_directory_is_local                 (NautilusDirectory         *directory);
 
 gboolean           nautilus_directory_is_in_trash              (NautilusDirectory         *directory);
+typedef void (*TsReadyCallback) (NautilusDirectory *directory,
+				 GCancellable	   *cancellable,
+				 gpointer           callback_data);
+
+void		   nautilus_directory_get_snapshots_async      (NautilusDirectory	  *directory, 
+								TsReadyCallback		   ready_callback, 
+								GCancellable		  *cancel, 
+								gpointer		   callback_user_data);
+gboolean           nautilus_directory_has_snapshots            (NautilusDirectory         *directory);
+gboolean           nautilus_directory_is_in_snapshot           (NautilusDirectory         *directory);
+int		   nautilus_directory_get_num_snapshots	       (NautilusDirectory	  *directory);
+GList *		   nautilus_directory_get_snapshots	       (NautilusDirectory	  *directory);
+void		   nautilus_directory_remove_snapshot	       (NautilusDirectory	  *directory,
+								ZfsDataSet		  *snap);
+NautilusDirectory *nautilus_directory_get_snap_root	       (NautilusDirectory	  *directory);
+gboolean	   nautilus_directory_is_a_snapshot_dir_of     (NautilusDirectory	  *snapdir,
+								NautilusDirectory	  *refdir);
+void		   nautilus_directory_cancel_restore_info      (NautilusDirectory	  *directory);
 
 /* Return false if directory contains anything besides a Nautilus metafile.
  * Only valid if directory is monitored. Used by the Trash monitor.
@@ -239,6 +258,7 @@ GList *            nautilus_directory_li
 gboolean           nautilus_directory_is_desktop_directory     (NautilusDirectory         *directory);
 
 gboolean           nautilus_directory_is_editable              (NautilusDirectory         *directory);
+gboolean	   is_time_slider_enabled ();
 
 
 #endif /* NAUTILUS_DIRECTORY_H */
diff -Nrup -x '*.orig' -x '*.rej' -x '*.*~' ../SUNWgnome-file-mgr-2.30.0-b4/nautilus-2.30.1/libnautilus-private/nautilus-file-attributes.h nautilus-2.30.1/libnautilus-private/nautilus-file-attributes.h
--- ../SUNWgnome-file-mgr-2.30.0-b4/nautilus-2.30.1/libnautilus-private/nautilus-file-attributes.h	2009-12-09 12:03:51.000000000 +0100
+++ nautilus-2.30.1/libnautilus-private/nautilus-file-attributes.h	2010-05-14 17:16:39.545856449 +0200
@@ -41,6 +41,7 @@ typedef enum {
 	NAUTILUS_FILE_ATTRIBUTE_THUMBNAIL = 1 << 8,
 	NAUTILUS_FILE_ATTRIBUTE_MOUNT = 1 << 9,
 	NAUTILUS_FILE_ATTRIBUTE_FILESYSTEM_INFO = 1 << 10,
+        NAUTILUS_FILE_ATTRIBUTE_RESTORE_INFO = 1 << 12,
 } NautilusFileAttributes;
 
 #endif /* NAUTILUS_FILE_ATTRIBUTES_H */
diff -Nrup -x '*.orig' -x '*.rej' -x '*.*~' ../SUNWgnome-file-mgr-2.30.0-b4/nautilus-2.30.1/libnautilus-private/nautilus-file-private.h nautilus-2.30.1/libnautilus-private/nautilus-file-private.h
--- ../SUNWgnome-file-mgr-2.30.0-b4/nautilus-2.30.1/libnautilus-private/nautilus-file-private.h	2009-12-09 12:03:51.000000000 +0100
+++ nautilus-2.30.1/libnautilus-private/nautilus-file-private.h	2010-05-14 17:16:39.546288851 +0200
@@ -146,6 +146,15 @@ struct NautilusFileDetails
 
 	/* Mount for mountpoint or the references GMount for a "mountable" */
 	GMount *mount;
+
+	/* time slider file difference information */
+
+	char *restore_info;
+
+        /* snapshot directory for versions */
+
+        char *snapshot_directory;
+        GCancellable *has_snapshot_cancel;
 	
 	/* boolean fields: bitfield to save space, since there can be
            many NautilusFile objects. */
@@ -194,6 +203,13 @@ struct NautilusFileDetails
 	
 	eel_boolean_bit is_thumbnailing               : 1;
 
+	eel_boolean_bit restore_info_is_up_to_date    : 1;
+	eel_boolean_bit restore_info_in_progress      : 1;
+
+        eel_boolean_bit has_snap_versions_is_up_to_date    : 1;
+	eel_boolean_bit has_snap_versions_in_progress      : 1;
+        eel_boolean_bit has_snap_versions                  : 1;
+
 	/* TRUE if the file is open in a spatial window */
 	eel_boolean_bit has_open_window               : 1;
 
--- nautilus-3.1.3/libnautilus-private/nautilus-file.c.orig	2011-07-22 15:55:37.274869941 +0100
+++ nautilus-3.1.3/libnautilus-private/nautilus-file.c	2011-07-22 16:05:34.306574660 +0100
@@ -47,6 +47,7 @@
 #include "nautilus-vfs-file.h"
 #include "nautilus-saved-search-file.h"
 #include "nautilus-lockdown.h"
+#include "nautilus-zfs.h"
 #include <eel/eel-debug.h>
 #include <eel/eel-glib-extensions.h>
 #include <eel/eel-gtk-extensions.h>
@@ -142,7 +143,8 @@
 	attribute_where_q,
 	attribute_link_target_q,
 	attribute_volume_q,
-	attribute_free_space_q;
+	attribute_free_space_q,
+	attribute_restore_info_q;
 
 static void     nautilus_file_info_iface_init                (NautilusFileInfoIface *iface);
 static char *   nautilus_file_get_owner_as_string            (NautilusFile          *file,
@@ -152,6 +154,7 @@
 							      GFileInfo             *info);
 static const char * nautilus_file_peek_display_name (NautilusFile *file);
 static const char * nautilus_file_peek_display_name_collation_key (NautilusFile *file);
+static void invalidate_restore_info (NautilusFile *file);
 static void file_mount_unmounted (GMount *mount,  gpointer data);
 static void metadata_hash_free (GHashTable *hash);
 
@@ -486,7 +489,14 @@
 
 	eel_ref_str_unref (file->details->filesystem_id);
 	file->details->filesystem_id = NULL;
-
+        g_free (file->details->restore_info);
+        file->details->restore_info = NULL;
+        invalidate_restore_info (file);
+        g_free (file->details->snapshot_directory);
+        file->details->snapshot_directory = NULL;
+        file->details->has_snap_versions_in_progress = FALSE;
+        file->details->has_snap_versions_is_up_to_date = FALSE;
+        file->details->has_snap_versions = FALSE;
 	clear_metadata (file);
 }
 
@@ -804,6 +814,10 @@
 	g_free (file->details->activation_uri);
 	g_clear_object (&file->details->custom_icon);
 
+	g_free (file->details->restore_info);
+	if (file->details->snapshot_directory)
+		g_free (file->details->snapshot_directory);
+
 	if (file->details->thumbnail) {
 		g_object_unref (file->details->thumbnail);
 	}
@@ -4423,6 +4437,76 @@
 	NULL
 };
 
+char *
+nautilus_date_as_string (time_t time_raw, gboolean use_smallest)
+{
+	struct tm *ttime;
+	const char **formats;
+	const char *width_template;
+	const char *format;
+	char *date_string;
+	char *result;
+	GDate *today;
+	GDate *date;
+	guint32 date_age;
+	int i, date_format_pref;
+
+	ttime = localtime (&time_raw);
+
+	if (!use_smallest)
+	  {
+	    date_format_pref = g_settings_get_enum (nautilus_preferences,
+						NAUTILUS_PREFERENCES_DATE_FORMAT);
+	    if (date_format_pref == NAUTILUS_DATE_FORMAT_LOCALE) {
+	      return eel_strdup_strftime ("%c", ttime);
+	    } else if (date_format_pref == NAUTILUS_DATE_FORMAT_ISO) {
+	      return eel_strdup_strftime ("%Y-%m-%d %H:%M:%S",ttime);
+	    }
+	  }
+	
+	date = eel_g_date_new_tm (ttime);
+	
+	today = g_date_new ();
+	g_date_set_time_t (today, time (NULL));
+
+	/* Overflow results in a large number; fine for our purposes. */
+	date_age = (g_date_get_julian (today) -
+			 g_date_get_julian (date));
+
+	g_date_free (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 (date_age == 0)	{
+		formats = TODAY_TIME_FORMATS;
+	} else if (date_age == 1) {
+		formats = YESTERDAY_TIME_FORMATS;
+	} else if (date_age < 7) {
+		formats = CURRENT_WEEK_TIME_FORMATS;
+	} else {
+		formats = CURRENT_WEEK_TIME_FORMATS;
+	}
+
+
+	if (!use_smallest)
+	  format = _(formats[1]);
+	else
+	  {
+	    int i=0; 
+	    while (formats[i] != NULL) 
+	      i++;
+	    format = _(formats[i-3]);
+	  }
+	return eel_strdup_strftime (format, ttime);
+}
+
 static char *
 nautilus_file_fit_date_as_string (NautilusFile *file,
 				  NautilusDateType date_type,
@@ -6103,7 +6187,9 @@
 	if (attribute_q == attribute_free_space_q) {
 		return nautilus_file_get_volume_free_space (file);
 	}
-
+	if (attribute_q == attribute_restore_info_q) {
+		return nautilus_file_get_restore_info_async (file);
+	}
 	extension_attribute = NULL;
 	
 	if (file->details->pending_extension_attributes) {
@@ -7037,6 +7123,616 @@
 
 }
 
+gboolean                
+nautilus_file_is_in_snapshot (NautilusFile *file)
+{
+  char *file_uri = nautilus_file_get_uri (file);
+  gboolean result = ts_is_in_snapshot (file_uri);
+  g_free (file_uri);
+  return result;
+}
+
+static gboolean nautilus_file_in_snap_exist_in_current (NautilusFile *file, GCancellable *cancel)
+{
+  /* get path without /.zfs/snapshot/blah/ */
+  /* test is file exist */
+  char *file_uri = nautilus_file_get_uri (file);
+  char *file_uri_without_snap = NULL;
+  gboolean result = FALSE;
+
+  if (g_cancellable_is_cancelled (cancel))
+    {
+      g_free (file_uri);
+      return FALSE;
+    }
+
+  file_uri_without_snap = ts_remove_snapshot_dir (file_uri);
+
+  if (file_uri_without_snap)
+    {
+      GFile* root_file = g_file_new_for_uri (file_uri_without_snap);
+      char *path = g_file_get_path (root_file);
+	  
+      if (path)
+	{
+	  result =  g_file_test (path, G_FILE_TEST_EXISTS);
+	  g_free (path);
+	}
+      g_object_unref (root_file);
+      g_free (file_uri_without_snap);
+
+    }
+  
+  g_free (file_uri);
+
+  return result;
+}
+
+
+char * nautilus_file_in_snapshot_get_info (NautilusFile *file, GCancellable *cancel)
+{
+  char *info = NULL;
+  GFile *then_gfile = nautilus_file_get_location (file);
+  char *then_path = g_file_get_path (then_gfile);
+  g_object_unref (then_gfile);
+
+  if (g_cancellable_is_cancelled (cancel))
+    {
+      g_free (then_gfile);
+      g_free (then_path);
+      return g_strdup ("cancelled");
+    }
+  if (then_path)
+    {
+      struct stat64 now;
+      struct stat64 then;
+      char *now_path = ts_remove_snapshot_dir (then_path);
+
+      if (lstat64 (now_path, &now) == 0)
+	{
+	  if (lstat64 (then_path, &then) == 0)
+	    {
+
+	      if (now.st_mtime != then.st_mtime)
+		{
+		  if (now.st_size == then.st_size)
+		    /* SUN_BRANDING */
+		    info = g_strdup (_("different date, same size as latest version"));
+		  else if (now.st_size > then.st_size)
+		    /* SUN_BRANDING */
+		    info = g_strdup (_("different date, smaller than latest version"));
+		  else if ( now.st_size < then.st_size)
+		    /* SUN_BRANDING */
+		    info = g_strdup (_("different date, bigger than latest version"));
+		}
+	      else
+		/* SUN_BRANDING */
+		info = g_strdup (_("identical to latest version"));
+	    }
+	  else
+	    info = g_strdup_printf ("FIXME no then %s", then_path);
+	}
+      else
+	/* SUN_BRANDING */
+	info = g_strdup (_("not present in latest version"));
+
+      g_free (now_path);
+      g_free (then_path);
+    }
+
+  return info;
+}
+
+static char * restore_string (char *str, GCancellable *cancel)
+{
+  if (g_cancellable_is_cancelled (cancel))
+    {
+      g_free (str);
+      return g_strdup (_("unknown"));
+    }
+  else
+    return str;
+}
+
+gint time_cmp (time_t *a,
+	       time_t *b)
+{
+  if (*a == *b)
+    return 0;
+  if (*a > *b)
+    return 1;
+  if (*a < *b)
+    return -1;
+
+}
+
+char *			
+nautilus_file_get_num_snapshot_version (NautilusFile *file, 
+                                        GCancellable *cancel,
+                                        gboolean stop_at_first)
+{
+  GList *tmp = NULL;
+  GList *tmp2 = NULL;
+  GList *time = NULL;
+  time_t* now_time = NULL;
+  char *result = NULL;
+  int version = 0;
+  NautilusFile *parent = NULL;
+  NautilusDirectory *dir = NULL;
+  char *snapdir = NULL;
+
+  if (NAUTILUS_IS_FILE (file))
+    {
+      parent = nautilus_file_get_parent (file);
+      if (parent)
+	{
+	  dir = nautilus_directory_get_for_file (parent);
+	  g_object_unref (parent);
+	}
+    }
+  if (dir)
+    {
+      struct stat64 now;
+      struct stat64 then;
+      char snap_name[PATH_MAX+1];
+      char *name = nautilus_file_get_name (file);
+      
+      g_object_ref (dir);
+      tmp = nautilus_directory_get_snapshots (dir);
+      
+      GFile *now_gfile = nautilus_file_get_location (file);
+      char *now_path = g_file_get_path (now_gfile);
+      g_object_unref (now_gfile);
+
+      if (now_path)
+	{
+	  if (lstat64 (now_path, &now) != 0)
+	    {
+	      g_free (now_path);
+	      g_object_unref (dir);
+	      return NULL;
+	    }
+	}
+      
+      g_free (now_path);
+
+      time = NULL;
+
+      /* get list of mtime for all files in snapshots */
+
+      now_time = g_new0 (time_t, 1);
+      *now_time = now.st_mtim.tv_sec;
+      time = g_list_prepend (time, now_time);
+
+
+      for (tmp; tmp; tmp = tmp->next)
+	{
+	  g_sprintf (snap_name, "%s/%s", 
+		     ((ZfsDataSet *) tmp->data)->mountpoint, 
+		     name);
+	  if (g_cancellable_is_cancelled (cancel))
+	    goto cancel;
+	  if (lstat64 (snap_name, &then) == 0)
+	    {
+	      if (g_list_find_custom (time, &then.st_mtim.tv_sec, (GCompareFunc) time_cmp) == NULL)
+		{ /*insert in list only is unique */
+		  time_t* snap_time = g_new0 (time_t, 1);
+		  *snap_time = then.st_mtim.tv_sec;
+		  time = g_list_prepend (time, snap_time);
+                  if (stop_at_first)
+                    {
+                      snapdir = g_strdup (((ZfsDataSet *) tmp->data)->mountpoint);
+                      goto cancel;
+                    }
+		}
+	    }
+
+	}
+cancel:
+      g_free (name);
+      g_object_unref (dir);
+    }
+
+
+  for (tmp = time; tmp; tmp = tmp->next)
+    {
+      g_free ((time_t*) tmp->data);
+      version++;
+    }
+
+  /* remove current version */
+  version--;
+
+  g_list_free (time);
+
+  if (version == 0)
+    {
+      if (stop_at_first)
+        return NULL;
+      else /*SUN_BRANDING*/
+        return restore_string (g_strdup_printf (_("no other version")), cancel);
+    }
+
+  if (stop_at_first)
+    return snapdir;
+  else
+    return restore_string (g_strdup_printf ("%d %s", version,
+                                            /* SUN_BRANDING */
+                                            version > 1 ? _("other versions") : /* SUN_BRANDING */ _("other version")),
+                           cancel);
+}
+
+static gboolean worker_thread_started = FALSE;
+
+typedef void (*ReadyCallback) (gpointer		  data,
+			       GCancellable      *cancellable);
+typedef void (*WorkerFunction) (gpointer		  data,
+			       GCancellable      *cancellable);
+typedef struct {
+  gpointer	    data;
+  gpointer	    return_data;
+  ReadyCallback	    ready_callback;
+  WorkerFunction    worker_func;
+  GCancellable	    *cancellable;
+} QueryData;
+
+static void 		
+nautilus_file_get_restore_info (gpointer data,
+				GCancellable       *cancellable)
+{
+  QueryData *qdata = (QueryData*) data;
+  NautilusFile *file = NAUTILUS_FILE (qdata->data);
+  char *result = NULL;
+
+  /*{
+    struct timespec ts;
+    ts.tv_sec = 1;
+    ts.tv_nsec = 0;
+    nanosleep (&ts, NULL);
+  }
+
+    {
+      GFile *f = nautilus_file_get_location (file);
+      char *path = g_file_get_uri (f);
+      printf ("start restore info for %s", path);
+      g_free (path);
+      g_object_unref (f);
+    }*/
+  if (!g_cancellable_is_cancelled (cancellable))
+    {
+
+      if (nautilus_file_is_directory (file))
+	{
+	  NautilusDirectory *dir = nautilus_directory_get_for_file (file);
+	  g_object_ref (dir);
+	  if (nautilus_directory_is_in_snapshot (dir))
+	    {
+	      if (!nautilus_file_in_snap_exist_in_current (file, cancellable))
+		/* SUN_BRANDING */
+		result = g_strdup (_("not present in latest version"));
+	      else
+		/* SUN_BRANDING */
+		result = g_strdup (_("present in latest version"));
+	    }
+	  else
+	    {
+	      int version = nautilus_directory_get_num_snapshots (dir);
+
+	      if (version == 0)
+		/* SUN_BRANDING */
+		result = g_strdup (_("no version"));
+	      else
+		result = g_strdup_printf ("%d %s",version,
+					  /* SUN_BRANDING */
+					  version > 1 ? _("versions") : /* SUN_BRANDING */ _("version"));
+	    }
+	  g_object_unref (dir);
+	}
+      else
+	{
+	  if (nautilus_file_is_in_snapshot (file))
+	      result = nautilus_file_in_snapshot_get_info (file, cancellable);
+	  else
+	      result = nautilus_file_get_num_snapshot_version (file, cancellable, FALSE);
+	}
+    }
+
+/*    {
+      printf ("is %s\n", result);
+    }*/
+
+
+  qdata->return_data = restore_string (result, cancellable);
+}
+
+
+static void restore_information_ready_callback (gpointer data,
+						GCancellable *cancellable)
+{
+  QueryData *qdata = (QueryData*) data;
+  NautilusFile *file = (NautilusFile*) qdata->data;
+  char *return_data = qdata->return_data;
+
+  if (!NAUTILUS_IS_FILE (file))
+    return;
+
+  file->details->restore_info_in_progress = FALSE;
+
+  if (g_cancellable_is_cancelled (cancellable))
+    {
+      file->details->restore_info = g_strdup (_("unknown"));
+      invalidate_restore_info (file);
+      if (return_data)
+	g_free (return_data);
+    }
+  else
+    {
+      file->details->restore_info_is_up_to_date = TRUE;
+      file->details->restore_info = return_data;
+    }
+
+  nautilus_file_changed (file);
+  nautilus_file_unref (file);
+}
+
+
+static gboolean
+complete_in_idle_cb (gpointer data)
+{
+  QueryData *qdata = (QueryData*)data;
+  qdata->ready_callback (data, qdata->cancellable);
+  g_free (qdata);
+  return FALSE;
+}
+
+static void
+worker_queue_finished_callback (GObject *source_object,
+				GAsyncResult *res,
+				gpointer user_data)
+{
+  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+  GCancellable *cancel = (GCancellable*) user_data;
+
+  worker_thread_started = FALSE;
+
+  if (g_cancellable_is_cancelled (cancel))
+    {
+      return;
+    }
+
+  g_simple_async_result_get_op_res_gpointer (simple);
+
+}
+
+static void
+worker_queue_func (GSimpleAsyncResult *res,
+		   GObject            *object,
+		   GCancellable       *cancellable)
+{
+  QueryData *data = NULL;
+
+  GTimeVal timeout;
+  GAsyncQueue *queue = (GAsyncQueue*) g_simple_async_result_get_op_res_gpointer (res);
+  g_async_queue_ref (queue);
+
+  g_get_current_time (&timeout);
+  g_time_val_add (&timeout, 3000000);
+
+  data = g_async_queue_timed_pop (queue, &timeout);
+
+  while (data)
+    {
+      GSource *source;
+
+      /* only call the worker fct if not cancel 
+       * but execute ready function anyway */
+      if (!g_cancellable_is_cancelled (data->cancellable))
+	data->worker_func (data, data->cancellable);
+
+      /*call ready callback in main loop/thread */
+      source = g_idle_source_new ();
+      g_source_set_priority (source, G_PRIORITY_DEFAULT);
+      g_source_set_callback (source, complete_in_idle_cb, data, NULL);
+      g_source_attach (source, NULL);
+      g_source_unref (source);
+
+      /* pop next one */
+      g_get_current_time (&timeout);
+      g_time_val_add (&timeout, 3000000);
+      data = g_async_queue_timed_pop (queue, &timeout);
+    }
+
+  g_async_queue_unref (queue);
+}
+
+char * nautilus_file_get_restore_info_async (NautilusFile *file)
+{
+  if (!is_time_slider_enabled ())
+    return NULL;
+
+  if (!ts_is_restore_column_enabled ())
+    return NULL;
+
+  if (file->details->restore_info_is_up_to_date)
+    {
+      /*if ( file->details->restore_info == NULL)
+	return g_strdup ("null cached info");*/
+      return g_strdup (file->details->restore_info);
+    }
+
+  if (file->details->restore_info_in_progress)
+    return g_strdup ("...");
+  else
+    {
+      static GAsyncQueue *queue = NULL;
+      QueryData *data  = NULL;
+
+      if (!file->details->directory)
+	return g_strdup ("no directory element\n");
+
+      if (!nautilus_directory_has_snapshots (file->details->directory) && !nautilus_file_is_in_snapshot (file))
+	return g_strdup ("doesn't have snap nor is in snap\n");
+
+      if (!file->details->directory->details->restore_cancel)
+	{
+	  file->details->directory->details->restore_cancel = g_cancellable_new ();
+	}
+      else
+	{
+	  if (g_cancellable_is_cancelled (file->details->directory->details->restore_cancel))
+	    return NULL;
+	}
+
+      g_free (file->details->restore_info);
+      file->details->restore_info = NULL;
+      file->details->restore_info_in_progress = TRUE;
+
+      if (!queue)
+	queue = g_async_queue_new ();
+
+      data = g_new0 (QueryData, 1);
+      data->data = file;
+      nautilus_file_ref (file);
+      data->cancellable = file->details->directory->details->restore_cancel;
+      data->ready_callback = restore_information_ready_callback;
+      data->worker_func = nautilus_file_get_restore_info;
+
+      g_async_queue_push (queue, data);
+
+      if (!worker_thread_started)
+	{
+	  GSimpleAsyncResult *res;
+	  worker_thread_started = TRUE;
+
+	  res = g_simple_async_result_new (G_OBJECT (file), 
+					   worker_queue_finished_callback, 
+					   NULL, 
+					   (gpointer) worker_queue_func);
+
+	  g_simple_async_result_set_op_res_gpointer (res, queue, NULL);
+	  g_simple_async_result_run_in_thread (res, 
+					       worker_queue_func, 
+					       G_PRIORITY_DEFAULT, 
+					       data->cancellable);
+	}
+
+      return g_strdup ("...");
+    }
+}
+
+HasSnapshotResult
+nautilus_file_has_snapshot_version (NautilusFile *file)
+{
+    if (file->details->has_snap_versions_is_up_to_date)
+        return (file->details->has_snap_versions);
+    return UNKNOWN_STATE;
+}
+
+typedef struct {
+  NautilusFile              *file;
+  GCancellable              *cancel;
+  FileHasSnapshotCallback    callback;
+  gpointer		     callback_user_data;
+  char                      *snap_dir;
+} HasSnapshotAsyncData;
+
+typedef void (*HasSnapReadyCallback) (NautilusDirectory *file,
+                                      GCancellable	*cancel,
+                                      gpointer           callback_data);
+
+
+static void has_snapshot_ready_callback (GObject *source_object,
+                                         GAsyncResult *res,
+                                         gpointer user_data)
+{
+  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+  HasSnapshotAsyncData *data = (HasSnapshotAsyncData*) user_data;
+
+  if (g_cancellable_is_cancelled (data->cancel))
+    {
+      data->file->details->has_snap_versions_in_progress = FALSE;
+      data->file->details->has_snap_versions_is_up_to_date = FALSE;
+      if (data->file->details->snapshot_directory)
+        g_free (data->file->details->snapshot_directory);
+      
+      data->file->details->has_snapshot_cancel = NULL;
+    }
+  else
+    {
+      data->file->details->has_snap_versions_in_progress = FALSE;
+      data->file->details->has_snap_versions_is_up_to_date = TRUE;
+      if (data->file->details->snapshot_directory)
+        g_free (data->file->details->snapshot_directory);
+      data->file->details->snapshot_directory = g_simple_async_result_get_op_res_gpointer (simple);
+      if (data->file->details->snapshot_directory)
+        data->file->details->has_snap_versions = TRUE;
+      else
+        data->file->details->has_snap_versions = FALSE;
+    }
+  data->callback (data->callback_user_data);
+}
+char *
+nautilus_file_get_snapshot_dir (NautilusFile *file)
+{
+  return file->details->snapshot_directory;
+}
+void nautilus_file_real_get_snapshot_version (GSimpleAsyncResult *res,
+            				      GObject            *object,
+        				      GCancellable       *cancellable)
+{
+  NautilusFile *file = NAUTILUS_FILE (object);
+  char *snap_info = nautilus_file_get_num_snapshot_version (file, cancellable, TRUE);
+
+  if (!snap_info) /* scan for .zfs directory*/
+    snap_info = ts_get_not_zfs_snapshot_dir (nautilus_file_get_location (file));
+/*
+  {
+    struct timespec ts;
+    ts.tv_sec = 4;
+    ts.tv_nsec = 0;
+    nanosleep (&ts, NULL);
+  }
+*/
+  if (snap_info)
+    g_simple_async_result_set_op_res_gpointer (res, snap_info, (GDestroyNotify) NULL);
+  else
+    g_simple_async_result_set_op_res_gpointer (res, NULL, (GDestroyNotify) NULL);
+}
+
+void nautilus_file_get_snapshot_version (NautilusFile *file,
+                                         FileHasSnapshotCallback callback,
+                                         GCancellable *cancel,
+                                         gpointer user_data)
+{
+    HasSnapshotAsyncData *data;
+    GSimpleAsyncResult *res;
+
+    if (file->details->has_snap_versions_in_progress)
+    {
+        g_cancellable_cancel(file->details->has_snapshot_cancel);
+        file->details->has_snapshot_cancel = NULL;
+        file->details->has_snap_versions_in_progress = FALSE;        
+    }
+
+    file->details->has_snapshot_cancel = cancel;
+    file->details->has_snap_versions_in_progress = TRUE;
+    file->details->has_snap_versions_is_up_to_date  = FALSE;
+
+    data = g_new0 (HasSnapshotAsyncData, 1);
+    data->file = file;
+    data->cancel = cancel;
+    data->callback = callback;
+    data->callback_user_data = user_data;
+
+    res = g_simple_async_result_new (G_OBJECT (file),
+                                     has_snapshot_ready_callback,
+                                     data,
+                                    (gpointer) nautilus_file_real_get_snapshot_version);
+    g_simple_async_result_run_in_thread (res, nautilus_file_real_get_snapshot_version,
+                                         G_PRIORITY_DEFAULT, cancel);
+}
+
+
 void
 nautilus_file_mark_gone (NautilusFile *file)
 {
@@ -7296,6 +7992,12 @@
 	file->details->mount_is_up_to_date = FALSE;
 }
 
+static void
+invalidate_restore_info (NautilusFile *file)
+{
+        file->details->restore_info_is_up_to_date = FALSE;
+}
+
 void
 nautilus_file_invalidate_extension_info_internal (NautilusFile *file)
 {
@@ -7350,6 +8052,9 @@
 	if (REQUEST_WANTS_TYPE (request, REQUEST_THUMBNAIL)) {
 		invalidate_thumbnail (file);
 	}
+        if (REQUEST_WANTS_TYPE (request, REQUEST_RESTORE_INFO)) {
+                invalidate_restore_info (file);
+        }
 	if (REQUEST_WANTS_TYPE (request, REQUEST_MOUNT)) {
 		invalidate_mount (file);
 	}
@@ -7432,7 +8137,8 @@
 		NAUTILUS_FILE_ATTRIBUTE_LARGE_TOP_LEFT_TEXT |
 		NAUTILUS_FILE_ATTRIBUTE_EXTENSION_INFO |
 		NAUTILUS_FILE_ATTRIBUTE_THUMBNAIL |
-		NAUTILUS_FILE_ATTRIBUTE_MOUNT;
+		NAUTILUS_FILE_ATTRIBUTE_MOUNT | 
+		NAUTILUS_FILE_ATTRIBUTE_RESTORE_INFO ;
 }
 
 void
@@ -8011,6 +8717,7 @@
 	attribute_link_target_q = g_quark_from_static_string ("link_target");
 	attribute_volume_q = g_quark_from_static_string ("volume");
 	attribute_free_space_q = g_quark_from_static_string ("free_space");
+	attribute_restore_info_q = g_quark_from_static_string ("restore_info");
 	
 	G_OBJECT_CLASS (class)->finalize = finalize;
 	G_OBJECT_CLASS (class)->constructor = nautilus_file_constructor;
diff -Nrup -x '*.orig' -x '*.rej' -x '*.*~' ../SUNWgnome-file-mgr-2.30.0-b4/nautilus-2.30.1/libnautilus-private/nautilus-file.h nautilus-2.30.1/libnautilus-private/nautilus-file.h
--- ../SUNWgnome-file-mgr-2.30.0-b4/nautilus-2.30.1/libnautilus-private/nautilus-file.h	2009-12-09 12:03:51.000000000 +0100
+++ nautilus-2.30.1/libnautilus-private/nautilus-file.h	2010-05-14 17:16:39.550338308 +0200
@@ -173,6 +173,7 @@ gboolean                nautilus_file_is
 									 const char                     *mime_type);
 gboolean                nautilus_file_is_launchable                     (NautilusFile                   *file);
 gboolean                nautilus_file_is_symbolic_link                  (NautilusFile                   *file);
+gboolean                nautilus_file_is_in_snapshot			(NautilusFile                   *file);
 gboolean                nautilus_file_is_mountpoint                     (NautilusFile                   *file);
 GMount *                nautilus_file_get_mount                         (NautilusFile                   *file);
 char *                  nautilus_file_get_volume_free_space             (NautilusFile                   *file);
@@ -228,6 +229,26 @@ char *                  nautilus_file_ge
 
 NautilusFile *          nautilus_file_get_trash_original_file           (NautilusFile                   *file);
 
+char *			nautilus_file_get_num_snapshot_version		(NautilusFile			*file,
+									 GCancellable			*cancel,
+                                                                         gboolean                        stop_at_first);
+char *			nautilus_file_get_restore_info_async		(NautilusFile			*file);
+
+typedef enum {
+	NO,
+	YES,
+	UNKNOWN_STATE
+} HasSnapshotResult;
+
+HasSnapshotResult       nautilus_file_has_snapshot_version              (NautilusFile                   *file);
+char *                  nautilus_file_get_snapshot_dir                  (NautilusFile                   *file);
+typedef void (*FileHasSnapshotCallback)	(gpointer user_data);
+
+void                    nautilus_file_get_snapshot_version              (NautilusFile                   *file,
+                                                                         FileHasSnapshotCallback        callback,
+                                                                         GCancellable *cancel,
+                                                                         gpointer                       user_data);
+
 /* Permissions. */
 gboolean                nautilus_file_can_get_permissions               (NautilusFile                   *file);
 gboolean                nautilus_file_can_set_permissions               (NautilusFile                   *file);
--- nautilus-3.1.3/libnautilus-private/nautilus-global-preferences.h.orig	2011-07-22 10:33:34.400109504 +0100
+++ nautilus-3.1.3/libnautilus-private/nautilus-global-preferences.h	2011-07-22 10:37:38.055064000 +0100
@@ -42,6 +42,7 @@
 #define NAUTILUS_PREFERENCES_SHOW_HIDDEN_FILES			"show-hidden-files"
 #define NAUTILUS_PREFERENCES_SHOW_ADVANCED_PERMISSIONS		"show-advanced-permissions"
 #define NAUTILUS_PREFERENCES_DATE_FORMAT			"date-format"
+#define NAUTILUS_PREFERENCES_ENABLE_TIME_SLIDER			"enable-time-slider"
 
 /* Mouse */
 #define NAUTILUS_PREFERENCES_MOUSE_USE_EXTRA_BUTTONS		"mouse-use-extra-buttons"
--- /dev/null	2011-07-25 14:19:16.000000000 +0100
+++ nautilus-3.1.3/libnautilus-private/nautilus-zfs.c	2011-07-25 14:19:15.457833851 +0100
@@ -0,0 +1,1221 @@
+/* 
+ * Copyright (C) 2010 Sun Microsystems (Erwann Chenede)
+ *
+ */
+
+
+#include <stdio.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "nautilus-zfs.h"
+#include <time.h>
+#include <locale.h>
+#include <langinfo.h>
+#include <stdint.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <eel/eel-glib-extensions.h>
+#include <sys/mnttab.h>
+#include <sys/mkdev.h>
+#include <libscf.h>
+#include <dirent.h>
+#include <sys/utsname.h>
+#include  "nautilus-global-preferences.h"
+#define ZFS_SNAPSHOT_DIR ".zfs/snapshot/"
+#define ZFS_BACKUP_DIR ".time-slider/rsync"
+
+char* ts_realpath (char * dir, char *resolved_name)
+{
+  char real_dir[PATH_MAX+1]; 
+  char real_path[PATH_MAX+1];
+  gboolean  found = FALSE;
+  struct stat64 dir_stat64;
+  char *result;
+  
+  result = realpath(dir, real_dir);
+  
+  if (!result)
+    return NULL;
+
+  if (stat64 (real_dir, &dir_stat64) == 0)
+    { 
+      if (strcmp (dir_stat64.st_fstype, "lofs") == 0)
+	{
+	  FILE		    *fp;
+	  struct extmnttab   mtab;
+	  int		     status;
+	  fp = fopen (MNTTAB,"r");
+
+	  resetmnttab(fp);
+	  while ((status = getextmntent(fp, &mtab, sizeof (struct extmnttab))) == 0) 
+	    {
+	      if (strcmp (mtab.mnt_fstype, "lofs") == 0)
+		{
+		  dev_t dev = NODEV;
+		  dev = makedev(mtab.mnt_major, mtab.mnt_minor);
+		  if (dev == dir_stat64.st_dev)
+		    {
+		      if (strcmp (real_dir, mtab.mnt_mountp) == 0)
+			strcpy (real_path, mtab.mnt_special);
+		      else
+			{
+			  gchar **split;
+			  split = g_strsplit (real_dir, mtab.mnt_mountp, 2);
+			  /*split 2nd part contains path without mount point */
+			  sprintf (real_path,"%s%s",mtab.mnt_special,split[1]);
+			  g_strfreev (split);
+			}
+		      found = TRUE;
+		      break;
+		    }
+		}
+	    }
+	  (void) fclose(fp);
+	}
+    }
+  if (found)
+      return strcpy (resolved_name, real_path);
+  else
+      return strcpy (resolved_name, real_dir);
+}
+
+static void ts_set_snapshot_used_space (zfs_handle_t *zhp, ZfsDataSet *snap)
+{
+  gchar buf[ZFS_MAXNAMELEN];
+  if (zfs_prop_get(zhp, ZFS_PROP_USED, buf, sizeof (buf), NULL, NULL, 0, B_FALSE) == 0)
+    {
+      char unit[10];
+      char format_float[5] = "%f%s";
+      char format_int[5] = "%d%s";
+      char *format = format_int;
+      int   used_space_int = 0;
+      gboolean success = FALSE;
+
+      snap->used_space_str = g_strdup (buf);
+
+      if (strchr (buf, '.'))
+	{
+	  format = format_float;
+	  if (sscanf(buf, format,&snap->used_space,unit) == 2)
+	    success = TRUE;
+	}
+      else
+	{
+	  if (sscanf(buf, format,&used_space_int,unit) == 2)
+	    {
+	      success = TRUE;
+	      snap->used_space = (float) used_space_int;
+	    }
+	}
+      if (strcmp (buf, "0") == 0)
+	{
+	  g_free (snap->used_space_str);
+	  snap->used_space_str = g_strdup ("0 K");
+	  success = TRUE;
+	}
+
+      if (success)
+	{
+	  if (strcmp (unit, "M") == 0)
+	    snap->used_space *= 1024; 
+	  if (strcmp (unit, "G") == 0)
+	    snap->used_space *= 1024 * 1024; 
+	}
+      else
+	{
+	  g_free (snap->used_space_str);
+	  /* SUN_BRANDING */
+	  snap->used_space_str = g_strdup (_("Unknown"));
+	}
+    }
+  else
+    {
+      g_free (snap->used_space_str);
+      /* SUN_BRANDING */
+      snap->used_space_str = g_strdup (_("Unknown"));
+    }
+}
+
+static void ts_set_snapshot_mtime_and_time_diff (zfs_handle_t *zhp, ZfsDataSet *snap)
+{
+  GDate now;
+  GDate then;
+  time_t time_now;
+  gint days_diff;
+  const gchar *format;
+  gchar *locale_format = NULL;
+  gchar buf[ZFS_MAXNAMELEN];
+  gchar *date_str = NULL;
+
+  if (zfs_prop_get(zhp, ZFS_PROP_CREATION, buf, sizeof (buf), NULL, NULL, 0, B_TRUE) == 0)
+    {
+      struct tm tms;
+
+      sscanf (buf, "%llu", &snap->mtime);
+      snap->mtime_str = nautilus_date_as_string (snap->mtime, FALSE);
+    }
+
+}
+
+void print_snap_list (char *dir, GList *snap_list)
+{
+  GList *tmp;
+  printf ("list of snapshots for %s :\n", dir);
+  for (tmp = snap_list; tmp->next; tmp = tmp->next)
+    {
+      ZfsDataSet *snap = (ZfsDataSet*) tmp->data;
+      printf (" name: %s\n mountpoint: %s\n mtime_str :%s\n space used : %s\n size in kilobytes : %f\n",
+	      snap->name, snap->mountpoint, snap->mtime_str, snap->used_space_str, snap->used_space);
+
+    }
+  printf ("\n");
+}
+
+static GString *
+dump_zds (ZfsDataSet *zds)
+{
+  GString *msg;
+  gchar *type;
+
+  if (!zds)
+    return NULL;
+
+  msg = g_string_new ("");
+  g_string_printf (msg, 
+		   "\tname: %s\n"
+		   "\tmountpoint: %s\n"
+		   "\ttype: %s\n",
+		   zds->name,zds->mountpoint, zfs_type_to_name(zds->type));
+  if (zds->snapshots)
+    {
+      GList *tmp;
+      g_string_append_printf(msg,"\tsnapshots :\n");
+      for (tmp=zds->snapshots;tmp;tmp = tmp->next)
+	{ 
+	  ZfsDataSet *tmp_zds= (ZfsDataSet*) tmp->data;
+	  g_string_append_printf (msg,"\t\tname: %s\n\t\tpath: %s\n",
+				  tmp_zds->name,
+				  tmp_zds->mountpoint);
+	}
+    }
+  g_string_append_printf (msg, "\n");
+  return msg;
+}
+
+
+static void
+dump_sds (SearchDataSet *sds)
+{
+  GString *msg;
+  gchar *type;
+  GList *tmp;
+
+  if (!sds)
+    {
+      printf ("Search DataSet is empty\n");
+      return;
+    }
+
+  msg = g_string_new ("");
+  g_string_printf (msg, "DDS Dump:\n"
+		   "\tsearched_path: %s\n",
+		   sds->searched_path);
+
+  g_string_append_printf (msg, "Zfs Data set :\n");
+  for (tmp=sds->datasets;tmp;tmp=tmp->next)
+    {
+      GString * zds_dump = dump_zds ((ZfsDataSet *)tmp->data);
+      g_string_append_printf (msg,"%s",zds_dump->str); 
+      g_string_free (zds_dump, TRUE);
+    }
+  g_string_append_printf (msg, "\n");
+  printf ("%s", msg->str);
+  g_string_free (msg, TRUE);
+}
+
+static ZfsDataSet*
+ts_new_zfs_dataset (SearchDataSet* sds)
+{
+	ZfsDataSet *zds;
+	zds = g_new0 (ZfsDataSet, 1);
+	zds->search_dataset = sds;
+	return zds;
+}
+
+void
+ts_free_zfs_dataset (ZfsDataSet* zds)
+{
+	if (!zds)
+	  return;
+	if (zds->name)
+	  g_free (zds->name);
+	if (zds->mountpoint)
+	  g_free (zds->mountpoint);
+	if (zds->mtime_str)
+	  g_free (zds->mtime_str);
+	if (zds->used_space_str)
+	  g_free (zds->used_space_str);
+
+	if (zds->snapshots)
+	  {
+	    GList *tmp;
+	    for (tmp = zds->snapshots;tmp;tmp = tmp->next)
+	      ts_free_zfs_dataset ((ZfsDataSet*)tmp->data);
+	  }
+	g_free (zds);
+}
+
+static SearchDataSet *
+ts_new_search_dataset (GCancellable *cancel)
+{
+	SearchDataSet *sds;
+	sds = g_new0 (SearchDataSet, 1);
+	sds->cancel = cancel;
+	return sds;
+}
+static void
+ts_free_search_dataset (SearchDataSet *sds)
+{
+	if (!sds)
+	  return;
+	if (sds->searched_path)
+	  g_free (sds->searched_path);
+	if (sds->mountpoint)
+	  g_free (sds->mountpoint);
+	if (sds->datasets)
+	  {
+	    GList *tmp;
+	    for (tmp = sds->datasets;tmp;tmp = tmp->next)
+	      ts_free_zfs_dataset ((ZfsDataSet*)tmp->data);
+	  }
+	g_free (sds);
+}
+
+static char* construct_check_snapshot_path (SearchDataSet *sds, char* mountpoint, const char *name, char *searched_path)
+{
+  gchar *result = NULL;
+  gchar **split;
+  gchar **split2;
+
+  gchar *snap_name = NULL;
+  gchar *remaining_path = NULL;
+  
+  /* get the snapshot name part pool@snap-name we are only interested in snap-name split[1] */
+  split = g_strsplit (name,"@",2);
+  /* get the path after the mountpoint */
+  split2 = g_strsplit (searched_path, mountpoint, 2);
+
+  if (split && split[1])
+      snap_name = split[1];
+
+  if (split2 && split2[1])
+      remaining_path = split2[1];
+  
+/*  printf ("mountpoint : %s \nname : %s \nsearched_path: %s\n", mountpoint, name, searched_path);
+  printf ("split %s at @ = [%s] [%s]\n", name, split[0],split[1]); 
+  printf ("split %s at [%s] = [%s] [%s]\n", searched_path, mountpoint, split2[0],split2[1]); 
+  printf ("%s/.zfs/snapshot/%s/%s\n\n", mountpoint, split[1], split2[1]);*/
+
+  if (snap_name && remaining_path)
+    result = g_strdup_printf ("%s/.zfs/snapshot/%s/%s", mountpoint, snap_name, remaining_path);
+  
+  g_strfreev (split);
+  g_strfreev (split2);
+  
+  /* don't test for file presence if searched path is the same as the mount point */
+  if (sds->searched_path_match_mp)
+      return result;
+      
+  if (result && g_file_test (result, G_FILE_TEST_IS_DIR))
+      {
+	char real_dir[PATH_MAX+1]; 
+	if (!ts_realpath(result, real_dir))
+	  {
+	    g_free (result);
+	    result = NULL;
+	  }
+	else
+	  {
+	    g_free (result);
+	    result = g_strdup (real_dir);
+	  }
+	return result;
+      }
+
+  g_free (result);
+  return NULL;
+}
+
+static int
+snapshot_callback (zfs_handle_t *zhp, void *data)
+{
+  ZfsDataSet *main_zds = (ZfsDataSet*) data;
+
+  /* only add snapshot dir that exist */
+
+  if (zfs_get_type (zhp) == ZFS_TYPE_SNAPSHOT && !g_cancellable_is_cancelled (main_zds->search_dataset->cancel)) 
+    {
+      const char* name = zfs_get_name (zhp);
+      char *snap_path = construct_check_snapshot_path (main_zds->search_dataset,
+						       main_zds->mountpoint, 
+						       name, 
+						       main_zds->search_dataset->searched_path);
+      if (snap_path)
+	{
+	  ZfsDataSet *zds = ts_new_zfs_dataset (main_zds->search_dataset);
+	  zds->name = g_strdup (name);
+	  zds->type = ZFS_TYPE_SNAPSHOT;
+	  zds->mountpoint = snap_path;
+	  ts_set_snapshot_mtime_and_time_diff (zhp, zds);
+	  ts_set_snapshot_used_space (zhp, zds);
+	  main_zds->snapshots = g_list_append (main_zds->snapshots,zds);
+	}
+    }
+  zfs_close (zhp);
+  return 0;
+}
+
+
+static struct mnttab *
+mygetmntent(FILE *f)
+{
+  static struct mnttab mt;
+  int status;
+
+  if ((status = getmntent(f, &mt)) == 0)
+    return (&mt);
+
+  return (NULL);
+}
+
+static char *
+is_fs_mounted (const char *fs_name)
+{
+  FILE		   *mnttab;
+  struct mnttab    *mntp;
+
+
+  mnttab = fopen (MNTTAB,"r");
+
+  while ((mntp = mygetmntent(mnttab)) != NULL) 
+    {
+      if (mntp->mnt_fstype == (char *)0 || strcmp(mntp->mnt_fstype, "zfs") != 0)
+	continue;
+      if (strcmp (mntp->mnt_special, fs_name) == 0)
+	{
+	  fclose (mnttab);
+	  return g_strdup (mntp->mnt_mountp);
+	}
+  }
+  fclose (mnttab);
+  return NULL;
+}
+
+static char* rsync_get_smf_dir()
+{
+  char data_store[MAXPATHLEN];
+
+  int retval = -1;
+
+  scf_handle_t	*handle = NULL;
+  scf_scope_t	*sc = NULL;
+  scf_service_t	*svc = NULL;
+  scf_instance_t *inst = NULL;
+  scf_propertygroup_t	*pg = NULL;
+  scf_property_t	*prop = NULL;
+  scf_value_t	*value = NULL;
+  scf_iter_t	*value_iter = NULL;
+
+
+  /* connect to the current SMF global repository */
+  handle = scf_handle_create(SCF_VERSION);
+
+  /* allocate scf resources */
+  sc = scf_scope_create(handle);
+  svc = scf_service_create(handle);
+  inst = scf_instance_create (handle);
+  pg = scf_pg_create(handle);
+  prop = scf_property_create(handle);
+  value = scf_value_create(handle);
+  value_iter = scf_iter_create(handle);
+
+  char *result = NULL;
+
+  /* if failed to allocate resources, exit */
+  if (handle == NULL || sc == NULL || svc == NULL || pg == NULL ||
+      prop == NULL || value == NULL || value_iter == NULL) {
+    /* scf handles allocation failed. */
+    goto out;
+  }
+
+  /* bind scf handle to the running svc.configd daemon */
+  if (scf_handle_bind(handle) == -1) {
+    /* scf binding failed. */
+    goto out;
+  }
+
+  /* get the scope of the localhost in the current repository */
+  if (scf_handle_get_scope(handle, SCF_SCOPE_LOCAL, sc) == -1) {
+    /* Getting scf scope failed.*/
+    goto out;
+  }
+
+  /* get the service within the scope */
+  if (scf_scope_get_service(sc, "application/time-slider/plugin", svc) == -1) {
+    /* failed getting service */
+    goto out;
+  }
+
+  /* get the instance within the service */
+  if (scf_service_get_instance(svc, "rsync", inst) == -1)
+    goto out;
+
+
+  /* get the property group within the instance */
+  if (scf_instance_get_pg(inst, "rsync", pg) == -1) {
+      /* Getting property group failed.  */
+    goto out;
+  }
+
+  /*
+   * Now get the properties.
+   */
+  if (scf_pg_get_property(pg, "target_dir", prop) == -1) {
+    goto out;
+  }
+
+  if (scf_property_get_value(prop, value) == -1) {
+    goto out;
+  }
+
+  data_store[0] = 0;
+  if (scf_value_get_astring(value, data_store, MAXPATHLEN) == -1) {
+    goto out;
+  }
+  else {
+    result = strdup (data_store);
+  }
+
+out:
+  /* destroy scf pointers */
+  if (value != NULL) 
+    scf_value_destroy(value);
+  if (value_iter != NULL) 
+    scf_iter_destroy(value_iter);
+  if (prop != NULL) 
+    scf_property_destroy(prop);
+  if (pg != NULL) 
+    scf_pg_destroy(pg);
+  if (inst != NULL)
+    scf_instance_destroy (inst);
+  if (svc != NULL) 
+    scf_service_destroy(svc);
+  if (sc != NULL) 
+    scf_scope_destroy(sc);
+  if (handle != NULL) 
+    scf_handle_destroy(handle);
+
+  return result;
+}
+
+static char *rsync_get_dir (zfs_handle_t *zhp)
+{
+  nvlist_t *propval;
+
+  if (nvlist_lookup_nvlist(zfs_get_user_props(zhp),
+			   "org.opensolaris:time-slider-rsync", &propval) == 0) 
+    {
+      boolean_t ret_bool = FALSE;
+      char *strval;
+      char *dir;
+      nvlist_lookup_string(propval, ZPROP_VALUE, &strval);
+
+      if (strcmp (strval, "true") == 0)
+	{
+	  dir = rsync_get_smf_dir ();
+	  if (dir)
+	    return dir;
+	}
+    }
+  return NULL;
+}
+
+void sync_backups_add (zfs_handle_t *zhp, ZfsDataSet *main_zds)
+{
+  char *rsync_dir = rsync_get_dir (zhp);
+  DIR *d;
+  struct dirent *dir;
+  char *fs_rsync_dir;
+  struct utsname machine;
+
+  if (!rsync_dir)
+    return;
+
+  /* format SMF backup dir , TIMESLIDER, nodename from uname, path, .time-slider/rsync */
+  if (uname (&machine) == -1)
+    return;
+
+  fs_rsync_dir = g_strdup_printf ("%s/TIMESLIDER/%s/%s/%s/",
+				  rsync_dir,
+				  machine.nodename,
+				  main_zds->name,
+				  ZFS_BACKUP_DIR);
+
+  if (!g_file_test (fs_rsync_dir, G_FILE_TEST_IS_DIR))
+    {
+      g_free (rsync_dir);
+      g_free (fs_rsync_dir);
+      return;
+    }
+
+  d = opendir (fs_rsync_dir);
+
+  if (!d)
+    {
+      g_free (rsync_dir);
+      g_free (fs_rsync_dir);
+      return;
+    }
+
+  while ((dir = readdir (d)))
+    {
+      if (strstr (dir->d_name, "zfs-auto-snap_"))
+	{ /* got a snap copy dir */
+	  char **comma_split = NULL;
+	  char **freq_split = NULL;
+	  struct tm tms;
+	  ZfsDataSet *zds = NULL;
+
+	  /* extract creation time from dir name */
+	  comma_split = g_strsplit (dir->d_name, "_", 2);
+	  /* printf ("comma_split[1] = %s\n", comma_split[1]); */
+	  freq_split = g_strsplit (comma_split[1], "-", 2);
+	  /* printf ("freq_split[1] = %s\n", freq_split[1]);  */
+
+	  /* parse time string */
+	  if (strptime (freq_split[1], "%Y-%m-%d-%Hh%M", &tms) != NULL)
+	    { 
+	      zds = ts_new_zfs_dataset (main_zds->search_dataset);
+	      zds->name = g_strdup (dir->d_name);
+	      zds->type = NULL;
+	      zds->mountpoint = g_strdup_printf ("%s%s/", fs_rsync_dir, dir->d_name);
+	      zds->mtime = mktime (&tms);
+	      zds->mtime_str =  nautilus_date_as_string (zds->mtime, FALSE);
+	      zds->used_space_str = g_strdup (_("Separate Backup"));
+	      main_zds->snapshots = g_list_append (main_zds->snapshots,zds);
+	      /* printf ("in sync_backups_add adding %s %s\n", zds->name, zds->mountpoint); */
+	    }
+	  if (comma_split)
+	    g_strfreev (comma_split);
+	  if (freq_split)
+	    g_strfreev (freq_split);
+	}
+    }
+
+  closedir (d);
+  g_free (rsync_dir);
+}
+
+static int
+zfs_callback (zfs_handle_t *zhp, void *data)
+{
+  char buf[ZFS_MAXPROPLEN];
+  SearchDataSet *sds = (SearchDataSet*) data;
+
+  if (sds->match_found)
+    {
+      zfs_close (zhp);
+      return 0;
+    }
+
+  if (zfs_get_type (zhp) & sds->type & !g_cancellable_is_cancelled (sds->cancel))
+    {
+/*      struct timespec ts;
+      ts.tv_sec = 3;
+      ts.tv_nsec = 100000000; 
+      nanosleep (&ts, NULL);*/
+
+      if (sds->prop >= ZFS_PROP_TYPE && sds->prop < ZFS_NUM_PROPS) 
+	{
+	  zfs_prop_get(zhp, sds->prop, buf, sizeof (buf), NULL, NULL,  0, TRUE);
+	  
+	  if (strcmp (sds->mountpoint, buf) == 0)
+	    {
+	      ZfsDataSet *zds = ts_new_zfs_dataset (sds);
+	      zds->type = zfs_get_type (zhp);
+	      zds->name = g_strdup (zfs_get_name(zhp));
+	      zds->mountpoint = g_strdup (buf);
+	      zfs_iter_snapshots (zhp, snapshot_callback, zds);
+	      sync_backups_add (zhp, zds);
+	      sds->datasets = g_list_append (sds->datasets, zds);
+	      sds->match_found = TRUE;
+	    }
+	  else if (strcmp ("legacy", buf) == 0)
+	    { /* parse /etc/mnttab to get the mount point */
+	      char *mountp = is_fs_mounted (zfs_get_name(zhp));
+	      if (mountp)
+		{
+		  if (strcmp (sds->mountpoint, mountp) == 0)
+		    {
+		      ZfsDataSet *zds = ts_new_zfs_dataset (sds);
+		      zds->type = zfs_get_type (zhp);
+		      zds->name = g_strdup (zfs_get_name(zhp));
+		      zds->mountpoint = mountp;
+		      zfs_iter_snapshots (zhp, snapshot_callback, zds);
+		      sync_backups_add (zhp, zds);
+		      sds->datasets = g_list_append (sds->datasets, zds);
+		      sds->match_found = TRUE;
+		    }
+		  else
+		    g_free (mountp);
+		}
+	    }
+	}
+      if (!sds->match_found)
+	zfs_iter_filesystems (zhp, zfs_callback, sds); 
+    }
+  zfs_close (zhp);
+  return 0;
+}
+
+static SearchDataSet *
+ts_get_data_from_mountpoint (const char* searched_path, const char *mountpoint, GCancellable *cancel)
+{
+  static libzfs_handle_t *zfs_handle = NULL;
+  SearchDataSet *sds;
+
+  sds = ts_new_search_dataset (cancel);
+
+  sds->prop = ZFS_PROP_MOUNTPOINT;
+  sds->type = ZFS_TYPE_FILESYSTEM;
+  sds->searched_path = g_strdup (searched_path);
+  sds->mountpoint = g_strdup (mountpoint);
+
+  if (strcmp (searched_path, mountpoint) == 0)
+    sds->searched_path_match_mp = TRUE;
+
+  if (!zfs_handle)
+    {
+      if ((zfs_handle = libzfs_init()) == NULL) {
+	g_warning ("internal error: failed to initialize ZFS library\n");
+	ts_free_search_dataset (sds);
+	return NULL;
+      }
+    }
+  zfs_iter_root (zfs_handle, zfs_callback, sds);
+
+  return sds;
+}
+static gint
+snap_sort_by_age (gconstpointer a,
+		  gconstpointer b)
+{
+  const ZfsDataSet *snap1 = a;
+  const ZfsDataSet *snap2 = b;
+
+  if (snap1->mtime == snap2->mtime)
+    return 0;
+  if (snap1->mtime < snap2->mtime)
+    return -1;
+  if (snap1->mtime > snap2->mtime)
+    return 1;
+
+}
+
+char* 
+ts_get_zfs_filesystem (char *dir)
+{
+  char real_dir[PATH_MAX+1]; 
+  char filesystem[PATH_MAX+1];
+  gboolean  found_fs= FALSE;
+  struct stat64 dir_stat64;
+
+  if (!ts_realpath(dir, real_dir))
+    {
+      return NULL;
+    }
+    if (stat64 (real_dir, &dir_stat64) == 0)
+    { /* check is fs is zfs */
+      if (strcmp (dir_stat64.st_fstype, "zfs") == 0)
+	{
+	  FILE		    *fp;
+	  struct extmnttab   mtab;
+	  int		     status;
+
+	  /* get mount point */
+
+	  fp = fopen (MNTTAB,"r");
+
+	  resetmnttab(fp);
+	  while ((status = getextmntent(fp, &mtab, sizeof (struct extmnttab))) == 0) 
+	    {
+	      dev_t dev = NODEV;
+	      dev = makedev(mtab.mnt_major, mtab.mnt_minor);
+	      if (dev == dir_stat64.st_dev)
+		{
+		  strcpy (filesystem, mtab.mnt_special);
+		  found_fs = TRUE;
+		  break;
+		}
+	    }
+	  (void) fclose(fp);
+	}
+    }
+    if (found_fs)
+      return g_strdup(filesystem);
+
+    return NULL;
+}
+
+static char * get_zfs_mountpoint (char *dir)
+{
+  char real_dir[PATH_MAX+1]; 
+  char mountpoint[PATH_MAX+1];
+  gboolean  found_mount_point = FALSE;
+  struct stat64 dir_stat64;
+
+  if (!ts_realpath(dir, real_dir))
+    {
+      return NULL;
+    }
+    if (stat64 (real_dir, &dir_stat64) == 0)
+    { /* check is fs is zfs */
+      if (strcmp (dir_stat64.st_fstype, "zfs") == 0)
+	{
+	  FILE		    *fp;
+	  struct extmnttab   mtab;
+	  int		     status;
+
+	  /* get mount point */
+
+	  fp = fopen (MNTTAB,"r");
+
+	  resetmnttab(fp);
+	  while ((status = getextmntent(fp, &mtab, sizeof (struct extmnttab))) == 0) 
+	    {
+	      dev_t dev = NODEV;
+	      dev = makedev(mtab.mnt_major, mtab.mnt_minor);
+	      if (dev == dir_stat64.st_dev)
+		{
+		  strcpy (mountpoint, mtab.mnt_mountp);
+		  found_mount_point = TRUE;
+		  break;
+		}
+	    }
+	  (void) fclose(fp);
+	}
+    }
+    if (found_mount_point)
+      return g_strdup(mountpoint);
+
+    return NULL;
+}
+
+
+char *ts_get_snapshot_dir (char *dir)
+{
+  char *zfs_dir = get_zfs_mountpoint (dir);
+  if (zfs_dir)
+    {
+      char *snapshot_dir = g_strdup_printf ("%s/.zfs/snapshot", zfs_dir);
+      g_free (zfs_dir);
+      return snapshot_dir;
+    }
+  else
+    return NULL;
+}
+
+
+
+static void ts_get_snapshots_for_dir (GSimpleAsyncResult *res,
+				      GObject            *object,
+				      GCancellable       *cancellable)
+{
+  char *mountpoint = NULL; 
+  char real_dir[PATH_MAX+1]; 
+  SearchDataSet *sds;
+  GList* snap_result = NULL;
+  GFile *file = G_FILE (object);
+  char *dir = g_file_get_path (file);
+
+  mountpoint = get_zfs_mountpoint (dir);
+  
+
+  if (!mountpoint)
+    {
+      g_simple_async_result_set_op_res_gpointer (res, snap_result, (GDestroyNotify) NULL);
+      g_free (dir);
+      return;
+    }
+
+  ts_realpath(dir, real_dir);
+
+  sds = ts_get_data_from_mountpoint (real_dir, mountpoint, cancellable);
+
+  g_free (mountpoint);
+
+  if (g_cancellable_is_cancelled (cancellable))
+    {
+      /* printf ("ts_get_snapshots_for_dir %s cancelled\n", dir); */
+      if (sds)
+	{
+	  ts_free_search_dataset (sds);
+	  sds = NULL;
+	}
+    }
+
+  if (sds)
+    {
+      GList *tmp;
+      for (tmp=sds->datasets;tmp;tmp=tmp->next)
+	{
+	  ZfsDataSet *zds = (ZfsDataSet*) tmp->data;
+	  if (zds->snapshots)
+	    {
+	      snap_result = g_list_concat (snap_result, zds->snapshots);
+	      zds->snapshots = NULL;
+	    }
+	}
+      ts_free_search_dataset (sds);
+    }
+
+  if (snap_result) 
+    {
+      snap_result = g_list_sort (snap_result, (GCompareFunc)snap_sort_by_age);
+      /* print_snap_list (dir, snap_result);  */
+    }
+
+  g_free (dir);
+  g_simple_async_result_set_op_res_gpointer (res, snap_result, (GDestroyNotify) NULL);
+}
+
+
+GList *ts_get_snapshots_for_dir_async (GFile *file, 
+				       GAsyncReadyCallback result_ready, 
+				       GCancellable *cancel,
+				       gpointer  user_data)
+{
+   GSimpleAsyncResult *res;
+
+   res = g_simple_async_result_new (G_OBJECT (file), result_ready, user_data, (gpointer) ts_get_snapshots_for_dir);
+   g_simple_async_result_run_in_thread (res, ts_get_snapshots_for_dir, G_PRIORITY_DEFAULT, cancel);
+   return NULL;
+}
+
+
+void ts_free_snapshots (GList *snaps)
+{
+  if (snaps)
+    {
+      GList *tmp;
+      for (tmp=snaps;tmp;tmp=tmp->next)
+	ts_free_zfs_dataset ((ZfsDataSet*) tmp->data);
+      g_list_free (snaps);
+    }
+}
+
+gboolean ts_is_in_remote_backup (char *str)
+{
+    if (str != NULL)
+    {
+      if (g_strrstr (str, ZFS_BACKUP_DIR))
+	return TRUE;
+    }
+  return FALSE;
+}
+
+
+gboolean ts_is_in_snapshot (char * str)
+{
+  if (str != NULL)
+    {
+      if (g_strrstr (str, ZFS_SNAPSHOT_DIR))
+	return TRUE;
+      if (g_strrstr (str, ZFS_BACKUP_DIR))
+	return TRUE;
+    }
+  return FALSE;
+}
+
+char* ts_remove_snapshot_dir (char *str)
+{
+  if (ts_is_in_snapshot (str))
+    {
+      char *snap_root;
+      char *zfs, *iter, point;
+      int count = 0;
+
+      /*remove .zfs/snapshot/blah/ */
+      zfs = g_strrstr (str, ZFS_SNAPSHOT_DIR);
+      iter = zfs;
+
+      if (iter)
+	{
+	  iter += sizeof (ZFS_SNAPSHOT_DIR);
+	  while (*iter != '/' && *iter != '\0')
+	    iter++;
+
+	  if (*iter == '/')
+	    iter++;
+
+	  point = *zfs;
+	  *zfs = '\0';
+	  snap_root = g_strdup_printf ("%s%s", str, iter);
+
+	  *zfs = point;
+	  return snap_root;
+	}
+    }
+  return NULL;
+}
+
+
+static gboolean restore_col_enabled = FALSE;
+
+gboolean 
+ts_is_restore_column_enabled ()
+{
+  return restore_col_enabled;
+}
+
+void ts_is_restore_column_enabled_init ();
+
+static void
+visible_columns_changed (gpointer callback_data)
+{
+  ts_is_restore_column_enabled_init ();
+}
+
+
+void ts_is_restore_column_enabled_init ()
+{
+  char **visible_columns;
+  static gboolean init = FALSE;
+  int i = 0;
+
+  if (!init)
+    {
+      g_signal_connect_swapped(nautilus_preferences,
+			       "changed::" NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_VISIBLE_COLUMNS,
+			       G_CALLBACK(visible_columns_changed), NULL);
+      init = TRUE;
+    }
+  
+  restore_col_enabled = FALSE;
+
+  visible_columns = g_settings_get_strv (nautilus_preferences, NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_VISIBLE_COLUMNS);
+
+  while (visible_columns[i])
+    {
+      if (strcmp (visible_columns [i], "restore_info") == 0)
+	{
+	  restore_col_enabled = TRUE;
+	  break;
+	}
+      i++;
+    }
+  g_strfreev (visible_columns);
+}
+
+
+static GList * get_dir_entries (char *dir_path)
+{
+  const char *entry_name;
+  GDir *dir;
+  GList *dir_entries = NULL;
+  dir = g_dir_open (dir_path, 0, NULL);
+
+  while ((entry_name = g_dir_read_name (dir)) != NULL)
+    dir_entries = g_list_prepend (dir_entries, g_strdup (entry_name));
+
+  g_dir_close (dir);
+
+  return dir_entries;
+}
+
+static void free_dir_entries (GList *entries)
+{
+  g_list_foreach (entries, (GFunc)g_free, NULL);
+  g_list_free (entries);
+}
+
+static gboolean are_entries_identical (GList *old, GList *new)
+{
+  if (g_list_length (old) != g_list_length (new))
+    return FALSE;
+
+  for (old; old; old = old->next)
+    {
+      gboolean found = FALSE;
+      for (new; new; new = new->next)
+	{
+	  if (strcmp (old->data, new->data) == 0)
+	    {
+	      found = TRUE;
+	      break;
+	    }
+	}
+      if (!found)
+	return FALSE;
+    }
+  return TRUE;
+}
+
+void monitor_zfs_snap_directory_cancel (ZfsSnapDirMonitor *monitor_data)
+{
+  if (monitor_data)
+    {
+      /* printf ("in monitor_zfs_snap_directory_cancel %s\n", monitor_data->path); */
+      g_source_remove (monitor_data->timeout_id);
+      free_dir_entries (monitor_data->entries);
+      g_free (monitor_data->path);
+      g_free (monitor_data);
+    }
+}
+
+static gboolean        
+monitor_snap_dir (ZfsSnapDirMonitor *monitor_data)
+{
+  GList *new_entries;
+
+  if (!g_file_test (monitor_data->path, G_FILE_TEST_IS_DIR))
+    {
+      monitor_zfs_snap_directory_cancel (monitor_data);
+      return TRUE;
+    }
+
+  new_entries = get_dir_entries (monitor_data->path);
+
+  if (are_entries_identical (monitor_data->entries, new_entries))
+    {
+      free_dir_entries (new_entries);
+    }
+  else
+    {
+      free_dir_entries (monitor_data->entries);
+      monitor_data->entries = new_entries;
+      monitor_data->change_callback (monitor_data, monitor_data->user_data);
+    }
+
+  if (monitor_data->backup_path)
+    {
+      if (!g_file_test (monitor_data->backup_path, G_FILE_TEST_IS_DIR))
+	{
+	  monitor_zfs_snap_directory_cancel (monitor_data);
+	  return TRUE;
+	}
+
+      new_entries = get_dir_entries (monitor_data->backup_path);
+      
+      if (are_entries_identical (monitor_data->backup_entries, new_entries))
+	{
+	  free_dir_entries (new_entries);
+	}
+      else
+	{
+	  free_dir_entries (monitor_data->backup_entries);
+	  monitor_data->backup_entries = new_entries;
+	  monitor_data->change_callback (monitor_data, monitor_data->user_data);
+	}
+    }
+  return TRUE;
+}
+
+  
+ZfsSnapDirMonitor *monitor_zfs_snap_directory (char *path, 
+					       char *backup_path,
+					       ZfsDirChangeCallback change_callback,
+					       gpointer data)
+{
+  ZfsSnapDirMonitor *monitor_data = g_new0 (ZfsSnapDirMonitor, 1);
+
+  /* printf ("start monitoring %s\n", path); */
+
+  monitor_data->path = g_strdup (path);
+  monitor_data->entries = get_dir_entries (path);
+  if (backup_path)
+    {
+      monitor_data->backup_path = g_strdup (backup_path);
+      monitor_data->backup_entries = get_dir_entries (backup_path);
+    }
+  monitor_data->change_callback = change_callback;
+  monitor_data->user_data = data;
+
+  monitor_data->timeout_id = g_timeout_add_seconds (5, (GSourceFunc)monitor_snap_dir, monitor_data);
+  return monitor_data;
+}
+
+char *
+ts_get_not_zfs_snapshot_dir (GFile *file)
+{
+  char tmp_path[PATH_MAX + 1];
+  gboolean found = FALSE;
+  gboolean end_path = FALSE;
+  GFile *d = g_file_get_parent(file);
+  GFile *tmp;
+  char *full_path = g_file_get_path (file);
+  char *stripped_path = g_file_get_path (d);
+  struct stat64 dir_stat64;
+
+  if (!full_path)
+     return NULL;
+
+  if (stat64 (full_path, &dir_stat64) == 0)
+    { /* check is fs is zfs if so don't try to check for nfs mounted .zfs dir*/
+      if (strcmp (dir_stat64.st_fstype, "zfs") == 0)
+        end_path = TRUE;
+    }
+
+  while (!found && !end_path)
+    {
+      g_sprintf (tmp_path, "%s/.zfs/snapshot", stripped_path);
+      if (g_file_test (tmp_path, G_FILE_TEST_IS_DIR))
+        {
+          GList *entries = get_dir_entries (tmp_path);
+          if (entries != NULL)
+            {
+              char *after_snap_path = full_path + strlen (stripped_path);
+
+              for (entries; entries; entries = entries->next)
+                {
+                  char test_path[PATH_MAX +1];
+                  g_sprintf (test_path, "%s/%s/%s", tmp_path, 
+                             entries->data,
+                             after_snap_path);
+                  if (g_file_test (test_path, G_FILE_TEST_EXISTS))
+                    {
+                      found = TRUE;
+                      break;
+                    }
+                }
+              free_dir_entries (entries);
+            }
+        }
+      tmp = d;
+      d = g_file_get_parent (tmp);
+      g_object_unref (tmp);
+      g_free (stripped_path);
+      stripped_path=NULL;
+      if (d == NULL)
+        {
+          end_path = TRUE;
+        }
+      else
+        {
+          stripped_path = g_file_get_path (d);
+        }
+    }
+
+  g_free (full_path);
+
+  if (stripped_path)
+    g_free (stripped_path);
+
+  if (found)
+    return g_strdup (tmp_path);
+  else
+    return NULL;
+
+}
diff -Nrup -x '*.orig' -x '*.rej' -x '*.*~' ../SUNWgnome-file-mgr-2.30.0-b4/nautilus-2.30.1/libnautilus-private/nautilus-zfs.h nautilus-2.30.1/libnautilus-private/nautilus-zfs.h
--- ../SUNWgnome-file-mgr-2.30.0-b4/nautilus-2.30.1/libnautilus-private/nautilus-zfs.h	1970-01-01 01:00:00.000000000 +0100
+++ nautilus-2.30.1/libnautilus-private/nautilus-zfs.h	2010-05-14 17:17:27.383965864 +0200
@@ -0,0 +1,77 @@
+/* #include <config.h> */
+#ifndef NAUTILUS_ZFS_H
+#define NAUTILUS_ZFS_H
+
+#include <glib.h>
+#include <libzfs.h>
+#include <gio/gio.h>
+
+typedef struct 
+{
+  zfs_type_t	type;
+  zfs_prop_t	prop;
+  char	       *searched_path;
+  char         *mountpoint;
+  GList        *datasets;
+  GCancellable *cancel;
+  gboolean	match_found;
+  gboolean	searched_path_match_mp;
+
+} SearchDataSet;
+
+typedef struct
+{
+  char		  *name;	
+  char		  *mountpoint;	
+  char		  *mtime_str;
+  time_t	   mtime;
+  float		   used_space;
+  char		  *used_space_str;
+  zfs_type_t	   type;
+  GList		  *snapshots;
+  SearchDataSet	  *search_dataset;
+} ZfsDataSet;
+
+
+GList *ts_get_snapshots_for_dir_async	(GFile *file, 
+					 GAsyncReadyCallback result_ready, 
+					 GCancellable *cancel,
+					 gpointer  user_data);
+void ts_free_snapshots			(GList *snaps);
+void ts_free_zfs_dataset		(ZfsDataSet* zds);
+
+gboolean ts_is_in_snapshot		(char * str);
+gboolean ts_is_in_remote_backup		(char *str);
+char* ts_remove_snapshot_dir		(char *str);
+char *ts_get_snapshot_dir		(char *dir);
+char *ts_get_zfs_filesystem		(char *dir);
+char * ts_get_not_zfs_snapshot_dir      (GFile *file);
+gboolean ts_is_restore_column_enabled	();
+void ts_is_restore_column_enabled_init	();
+void print_snap_list			(char *dir, GList *snap_list);
+char* ts_realpath			(char * dir, char *resolved_name);
+
+char *
+nautilus_date_as_string			(time_t time_raw, gboolean use_smallest);
+
+typedef void (*ZfsDirChangeCallback)	(gpointer monitor_data, 
+					 gpointer user_data);
+
+typedef struct 
+{
+  char	*		path;
+  GList			*entries;
+  char	*		backup_path;
+  GList			*backup_entries;
+  guint			timeout_id;
+  ZfsDirChangeCallback	change_callback;
+  gpointer		user_data;
+} ZfsSnapDirMonitor;
+
+void monitor_zfs_snap_directory_cancel (ZfsSnapDirMonitor *monitor_data);
+ZfsSnapDirMonitor *monitor_zfs_snap_directory (char		    *path, 
+					       char		    *backup_path,
+					       ZfsDirChangeCallback change_callback,
+					       gpointer		    data);
+#endif /* NAUTILUS_ZFS_H */
+
--- nautilus-3.1.3/src/Makefile.am.orig	2011-07-01 17:50:32.000000000 +0100
+++ nautilus-3.1.3/src/Makefile.am	2011-07-22 10:47:37.617231822 +0100
@@ -41,6 +41,8 @@
 	$(EXIF_LIBS) \
 	$(EXEMPI_LIBS) \
 	$(POPT_LIBS) \
+	$(SCF_LIBS) \
+	$(NVPAIR_LIBS) \
 	$(NULL)
 
 nautilus_SOURCES = \
@@ -142,6 +144,10 @@
 	nautilus-window-types.h			\
 	nautilus-x-content-bar.c		\
 	nautilus-x-content-bar.h		\
+	nautilus-zfs-bar.c			\
+	nautilus-zfs-bar.h			\
+	timescale.c				\
+	timescale.h				\
 	$(NULL)
 
 EMPTY_VIEW_SOURCES = \
--- nautilus-3.1.3/src/nautilus-actions.h.orig	2011-07-22 10:54:06.075754016 +0100
+++ nautilus-3.1.3/src/nautilus-actions.h	2011-07-22 10:56:03.673858543 +0100
@@ -85,6 +85,9 @@
 #define NAUTILUS_ACTION_NEW_LAUNCHER "New Launcher"
 #define NAUTILUS_ACTION_NEW_LAUNCHER_DESKTOP "New Launcher Desktop"
 #define NAUTILUS_ACTION_RENAME "Rename"
+#define NAUTILUS_ACTION_RESTORE_TO "Restore to"
+#define NAUTILUS_ACTION_HAS_SNAPSHOT "View Snap"
+#define NAUTILUS_ACTION_SNAP_NOW "Snap Now"
 #define NAUTILUS_ACTION_DUPLICATE "Duplicate"
 #define NAUTILUS_ACTION_CREATE_LINK "Create Link"
 #define NAUTILUS_ACTION_SELECT_ALL "Select All"
--- nautilus-3.1.3/src/nautilus-view.c.orig	2011-07-25 14:46:18.267955464 +0100
+++ nautilus-3.1.3/src/nautilus-view.c	2011-07-25 14:45:21.541051018 +0100
@@ -1366,6 +1366,73 @@
 }
 
 static void
+action_snap_now (GtkAction *action,
+                 gpointer callback_data)
+{
+	NautilusView *view = NAUTILUS_VIEW (callback_data);
+	GList *selection = nautilus_view_get_selection_for_file_transfer (view);
+	GFile *file = nautilus_file_get_location (NAUTILUS_FILE (selection->data));
+	char *path = g_file_get_path (file);
+	char *fs = ts_get_zfs_filesystem (path);
+	char *cmd = g_strdup_printf ("/usr/lib/time-slider-snapshot '%s' '%s'", path, fs);
+        nautilus_launch_application_from_command (gtk_window_get_screen (GTK_WIDGET(callback_data)), cmd, FALSE, NULL);
+
+	g_free (cmd);
+	g_free (fs);
+	g_free (path);
+	g_object_unref (file);
+}
+
+static void
+action_restore_to_desktop_callback (GtkAction *action,
+                                    gpointer callback_data)
+{
+	GList *locations = NULL;
+	GList *node;
+	NautilusView *view = NAUTILUS_VIEW (callback_data);
+	char *desktop_directory = nautilus_get_desktop_directory_uri();
+	GList *selection = nautilus_view_get_selection_for_file_transfer (view);
+
+	if (selection == NULL)
+		return;
+
+	if (desktop_directory == NULL)
+		return;
+
+
+	for (node = selection; node != NULL; node = node->next) {
+		locations = g_list_prepend (locations,
+				nautilus_file_get_uri ((NautilusFile *) node->data));
+	}
+
+	nautilus_view_move_copy_items (locations, NULL, desktop_directory,
+				GDK_ACTION_COPY, 0, 0, view);
+
+	nautilus_file_list_free (selection);
+}
+
+static void
+action_show_snapshot_versions_callback (GtkAction *action,
+                                        gpointer callback_data)
+{
+	NautilusView *view = NAUTILUS_VIEW (callback_data);
+	GList *selection = nautilus_view_get_selection_for_file_transfer (view);
+	GFile *file = nautilus_file_get_location (NAUTILUS_FILE (selection->data));
+	char *dir = nautilus_file_get_snapshot_dir (NAUTILUS_FILE (selection->data));
+	char *file_path = g_file_get_path (file);
+	char real_file_path [PATH_MAX + 1];
+	if (ts_realpath (file_path, real_file_path)) {
+		char *cmd = g_strdup_printf ("/usr/lib/time-slider-version '%s' '%s'", dir,
+			real_file_path);
+                nautilus_launch_application_from_command (gtk_window_get_screen (GTK_WIDGET(callback_data)), cmd, FALSE, NULL);
+		g_free (cmd);
+	}
+
+	g_free (file_path);
+	g_object_unref (file);
+}
+
+static void
 action_trash_callback (GtkAction *action,
 		       gpointer callback_data)
 {
@@ -7076,6 +7143,24 @@
   /* label, accelerator */       "RenameSelectAll", "<shift>F2",
   /* tooltip */                  NULL,
 				 G_CALLBACK (action_rename_select_all_callback) },
+  /* name, stock id */         { "Restore to", NULL,
+  /* SUN_BRANDING */
+  /* label, accelerator */       N_("Restore to Desktop"), NULL,
+  /* SUN_BRANDING */
+  /* tooltip */                  N_("Move each selected item to the Desktop"),
+                                 G_CALLBACK (action_restore_to_desktop_callback) },
+  /* name, stock id */         { "View Snap", NULL,
+  /* SUN_BRANDING */
+  /* label, accelerator */       N_("View versions"), NULL,
+  /* SUN_BRANDING */
+  /* tooltip */                  N_("View the versions of this file available in ZFS snapshots"),
+                                 G_CALLBACK (action_show_snapshot_versions_callback) },
+  /* name, stock id */         { "Snap Now", NULL,
+  /* SUN_BRANDING */
+  /* label, accelerator */       N_("Snapshot now"), NULL,
+  /* SUN_BRANDING */
+  /* tooltip */                  N_("Take a ZFS snapshot of this directory now"),
+                                 G_CALLBACK (action_snap_now) },
   /* name, stock id */         { "Trash", NULL,
   /* label, accelerator */       N_("Mo_ve to Trash"), "<control>Delete",
   /* tooltip */                  N_("Move each selected item to the Trash"),
@@ -8294,6 +8379,41 @@
 	return FALSE;
 }
 
+typedef struct {
+  NautilusFile              *file;
+  GCancellable              *cancel;
+  GtkAction                 *action;
+} HasSnapshotData;
+
+static void
+has_snapshot_ready_callback (gpointer user_data)
+{
+  GValue name = {0,};
+  HasSnapshotData *data = (HasSnapshotData*) user_data;
+  HasSnapshotResult result = nautilus_file_has_snapshot_version (data->file);
+
+  switch (result)
+    {
+    case UNKNOWN_STATE:
+    case NO:
+      gtk_action_set_sensitive (data->action, FALSE);
+      g_value_init (&name, G_TYPE_STRING);
+      /* SUN_BRANDING */
+      g_value_set_static_string (&name, _("No versions"));
+      g_object_set_property (G_OBJECT (data->action), "label", &name);
+      break;
+    case YES:
+      gtk_action_set_sensitive (data->action, TRUE);
+      g_value_init (&name, G_TYPE_STRING);
+      /* SUN_BRANDING */
+      g_value_set_static_string (&name, _("Explore versions"));
+      g_object_set_property (G_OBJECT (data->action), "label", &name);
+      break;
+    }
+  g_free (data);
+ }
+
+
 static void
 real_update_menus (NautilusView *view)
 {
@@ -8609,6 +8729,74 @@
 					      NAUTILUS_ACTION_COPY);
 	gtk_action_set_sensitive (action, can_copy_files);
 
+        action = gtk_action_group_get_action (view->details->dir_action_group,
+                                              NAUTILUS_ACTION_RESTORE_TO);
+        gtk_action_set_visible (action, can_copy_files &&
+                                  nautilus_directory_is_in_snapshot (view->details->model));
+
+        action = gtk_action_group_get_action (view->details->dir_action_group,
+                                              NAUTILUS_ACTION_SNAP_NOW);
+
+        if (selection_count == 1 && nautilus_file_is_directory (NAUTILUS_FILE (selection->data)))
+            {
+              GFile *file = nautilus_file_get_location (NAUTILUS_FILE (selection->data));
+              char *path = g_file_get_path (file);
+              char *fs = ts_get_zfs_filesystem (path);
+              if (fs)
+                {
+                  gtk_action_set_visible (action, TRUE);
+                  g_free (fs);
+                }
+              g_free (path);
+              g_object_unref (file);
+            }
+        else
+          gtk_action_set_visible (action, FALSE);
+
+        action = gtk_action_group_get_action (view->details->dir_action_group,
+                                              NAUTILUS_ACTION_HAS_SNAPSHOT);
+   if (selection_count == 1)
+     {
+       GValue name = { 0, };
+       int result = nautilus_file_has_snapshot_version (NAUTILUS_FILE (selection->data));
+
+       switch (result)
+         {
+         case NO:
+           gtk_action_set_visible (action, FALSE);
+           break;
+         case YES:
+           gtk_action_set_visible (action, TRUE);
+           gtk_action_set_sensitive (action, TRUE);
+           g_value_init (&name,G_TYPE_STRING);
+           /* SUN_BRANDING */
+           g_value_set_static_string (&name, _("Explore versions"));
+           g_object_set_property (G_OBJECT (action), "label", &name);
+           break;
+         case UNKNOWN_STATE:
+           gtk_action_set_visible (action, TRUE);
+           gtk_action_set_sensitive (action, FALSE);
+           g_value_init (&name,G_TYPE_STRING);
+           /* SUN_BRANDING */
+           g_value_set_static_string (&name, _("Scanning for versions"));
+           g_object_set_property (G_OBJECT (action), "label", &name);
+           break;
+         }
+       if (result == UNKNOWN_STATE)
+         {
+           HasSnapshotData *data = g_new0 (HasSnapshotData, 1);
+           data->action = action;
+           data->file = NAUTILUS_FILE (selection->data);
+           data->cancel = g_cancellable_new ();
+           nautilus_file_get_snapshot_version (NAUTILUS_FILE (selection->data),
+                                               has_snapshot_ready_callback,
+                                               data->cancel,
+                                               data);
+         }
+     }
+   else
+     gtk_action_set_visible (action, FALSE);
+
 	real_update_paste_menu (view, selection, selection_count);
 
 	disable_command_line = g_settings_get_boolean (gnome_lockdown_preferences, NAUTILUS_PREFERENCES_LOCKDOWN_COMMAND_LINE);
--- nautilus-3.1.3/src/nautilus-directory-view-ui.xml.orig	2011-07-22 11:25:04.446118499 +0100
+++ nautilus-3.1.3/src/nautilus-directory-view-ui.xml	2011-07-22 11:32:36.728336937 +0100
@@ -66,6 +66,9 @@
 			<menuitem name="Duplicate" action="Duplicate"/>
 			<menuitem name="Create Link" action="Create Link"/>
 			<menuitem name="Rename" action="Rename"/>
+			<menuitem name="Restore to" action="Restore to"/>
+			<menuitem name="Snapshot now" action="Snap Now"/>
+			<menuitem name="Scanning...." action="View Snap"/>
 			<menu action="CopyToMenu">
 				<menuitem name="Copy to next pane" action="Copy to next pane"/>
 				<menuitem name="Copy to Home" action="Copy to Home"/>
@@ -161,6 +164,9 @@
 		<menuitem name="Create Link" action="Create Link"/>
 		<menuitem name="Rename" action="Rename"/>
 		<menu action="CopyToMenu">
+		<menuitem name="Restore to" action="Restore to"/>
+		<menuitem name="Snapshot now" action="Snap Now"/>
+		<menuitem name="Scanning...." action="View Snap"/>
 			<menuitem name="Copy to next pane" action="Copy to next pane"/>
 			<menuitem name="Copy to Home" action="Copy to Home"/>
 			<menuitem name="Copy to Desktop" action="Copy to Desktop"/>
@@ -173,6 +179,7 @@
 	</placeholder>
 	<separator name="Dangerous separator"/>
 	<placeholder name="Dangerous File Actions">
+		<menuitem name="Restore" action="Restore"/>
 		<menuitem name="Trash" action="Trash"/>
 		<menuitem name="Delete" action="Delete"/>
 		<menuitem name="Restore From Trash" action="Restore From Trash"/>
diff -Nrup -x '*.orig' -x '*.rej' -x '*.*~' ../SUNWgnome-file-mgr-2.30.0-b4/nautilus-2.30.1/src/nautilus-actions.h nautilus-2.30.1/src/nautilus-actions.h
--- ../SUNWgnome-file-mgr-2.30.0-b4/nautilus-2.30.1/src/nautilus-actions.h	2010-01-22 16:45:17.000000000 +0100
+++ nautilus-2.30.1/src/nautilus-actions.h	2010-05-14 17:16:39.557199636 +0200
@@ -28,6 +28,7 @@
 
 #define NAUTILUS_ACTION_STOP "Stop"
 #define NAUTILUS_ACTION_RELOAD "Reload"
+#define NAUTILUS_ACTION_RESTORE "Restore"
 #define NAUTILUS_ACTION_BACK "Back"
 #define NAUTILUS_ACTION_UP "Up"
 #define NAUTILUS_ACTION_UP_ACCEL "UpAccel"
--- nautilus-3.1.3/src/nautilus-file-management-properties.c.orig	2011-04-25 18:02:09.000000000 +0100
+++ nautilus-3.1.3/src/nautilus-file-management-properties.c	2011-07-22 11:42:27.957358494 +0100
@@ -62,6 +62,7 @@
 #define NAUTILUS_FILE_MANAGEMENT_PROPERTIES_OPEN_NEW_WINDOW_WIDGET "new_window_checkbutton"
 #define NAUTILUS_FILE_MANAGEMENT_PROPERTIES_SHOW_HIDDEN_WIDGET "hidden_files_checkbutton"
 #define NAUTILUS_FILE_MANAGEMENT_PROPERTIES_TREE_VIEW_FOLDERS_WIDGET "treeview_folders_checkbutton"
+#define NAUTILUS_FILE_MANAGEMENT_PROPERTIES_ENABLE_TIME_SLIDER "time_slider_enabled_checkbutton"
 
 /* int enums */
 #define NAUTILUS_FILE_MANAGEMENT_PROPERTIES_THUMBNAIL_LIMIT_WIDGET "preview_image_size_combobox"
@@ -749,6 +750,10 @@
 			   NAUTILUS_FILE_MANAGEMENT_PROPERTIES_TREE_VIEW_FOLDERS_WIDGET,
 			   NAUTILUS_PREFERENCES_TREE_SHOW_ONLY_DIRECTORIES);
 
+	bind_builder_bool (builder, nautilus_tree_sidebar_preferences,
+			   NAUTILUS_FILE_MANAGEMENT_PROPERTIES_ENABLE_TIME_SLIDER,
+			   NAUTILUS_PREFERENCES_ENABLE_TIME_SLIDER);
+
 	bind_builder_enum (builder, nautilus_preferences,
 			   NAUTILUS_FILE_MANAGEMENT_PROPERTIES_DEFAULT_VIEW_WIDGET,
 			   NAUTILUS_PREFERENCES_DEFAULT_FOLDER_VIEWER,
--- nautilus-3.1.3/src/nautilus-shell-ui.xml.orig	2011-07-22 13:50:25.148071442 +0100
+++ nautilus-3.1.3/src/nautilus-shell-ui.xml	2011-07-22 13:57:43.720949058 +0100
@@ -53,6 +53,7 @@
 	<menu action="View">
 		<menuitem name="Stop" action="Stop"/>
 		<menuitem name="Reload" action="Reload"/>
+		<menuitem name="Restore" action="Restore"/>
 		<separator/>
 		<placeholder name="Show Hide Placeholder">
 			<menu action="Sidebar List">
--- nautilus-3.1.3/src/nautilus-window-manage-views.c.orig	2011-07-25 08:16:41.926463390 +0100
+++ nautilus-3.1.3/src/nautilus-window-manage-views.c	2011-07-25 08:49:32.039217259 +0100
@@ -39,6 +39,7 @@
 #include "nautilus-trash-bar.h"
 #include "nautilus-view-factory.h"
 #include "nautilus-x-content-bar.h"
+#include "nautilus-zfs-bar.h"
 #include <eel/eel-accessibility.h>
 #include <eel/eel-debug.h>
 #include <eel/eel-gdk-extensions.h>
@@ -50,6 +51,7 @@
 #include <gtk/gtk.h>
 #include <gdk/gdkx.h>
 #include <glib/gi18n.h>
+#include <stdlib.h>
 #include <libnautilus-extension/nautilus-location-widget-provider.h>
 #include <libnautilus-private/nautilus-file-attributes.h>
 #include <libnautilus-private/nautilus-file-utilities.h>
@@ -693,7 +695,9 @@
         NautilusFile *file;
 	gboolean force_reload;
         char *current_pos;
+	GFile *old_file = NULL;
 	GFile *from_folder, *parent;
+	NautilusWindow *window;
 
 	g_assert (slot != NULL);
         g_assert (location != NULL);
@@ -722,12 +726,43 @@
 
 	end_location_change (slot);
 
+	old_file = nautilus_window_slot_get_location (slot);
+	if (old_file) {
+		directory = nautilus_directory_get (old_file);
+		if (directory) {
+			nautilus_directory_cancel_restore_info (directory);
+			g_object_unref (directory);
+			directory = NULL;
+		}
+		g_object_unref (old_file);
+		old_file = NULL;
+	}
+
 	nautilus_window_slot_set_allow_stop (slot, TRUE);
 	nautilus_window_slot_set_status (slot, " ", NULL);
 
 	g_assert (slot->pending_location == NULL);
 	g_assert (slot->pending_selection == NULL);
 	
+	directory = nautilus_directory_get (location);
+
+	window = slot->pane->window;
+	g_assert (NAUTILUS_IS_WINDOW (window));
+	/* if snap and (ts is enabled and displayed )
+	 *  check if the directory exist
+	 *    if it doesn't move to the next available one */
+	 if (nautilus_directory_is_in_snapshot (directory) && is_time_slider_enabled ()) {
+		 if (gtk_widget_get_visible (window->details->zfs_bar)) {
+			char *path = g_file_get_path (location);
+			if (!g_file_test (path, G_FILE_TEST_IS_DIR)) {
+				nautilus_zfs_bar_remove_and_skip_snap (NAUTILUS_ZFS_BAR (window->details->zfs_bar), path);
+				g_free (path);
+				return;
+			}
+			g_free (path);
+		}
+	}
+
 	slot->pending_location = g_object_ref (location);
         slot->location_change_type = type;
         slot->location_change_distance = distance;
@@ -739,8 +774,6 @@
 	slot->open_callback = callback;
 	slot->open_callback_user_data = user_data;
 
-        directory = nautilus_directory_get (location);
-
 	/* The code to force a reload is here because if we do it
 	 * after determining an initial view (in the components), then
 	 * we end up fetching things twice.
@@ -919,8 +952,17 @@
 		/* If fallback, don't use view from metadata */
 		if (slot->location_change_type != NAUTILUS_LOCATION_CHANGE_FALLBACK) {
 			/* Look in metadata for view */
-			view_id = nautilus_file_get_metadata 
-				(file, NAUTILUS_METADATA_KEY_DEFAULT_VIEW, NULL);
+                   if (nautilus_file_is_in_snapshot (file))
+                     {
+                       NautilusDirectory* root_dir = nautilus_zfs_bar_get_dir (NAUTILUS_ZFS_BAR (window->details->zfs_bar));
+		       if (root_dir)
+			 view_id = nautilus_file_get_metadata (nautilus_directory_get_corresponding_file (root_dir), 
+							       NAUTILUS_METADATA_KEY_DEFAULT_VIEW, NULL);
+                     }
+                   if (view_id == NULL)
+                     view_id = nautilus_file_get_metadata
+                         (file, NAUTILUS_METADATA_KEY_DEFAULT_VIEW, NULL);
+
 			if (view_id != NULL && 
 			    !nautilus_view_factory_view_supports_uri (view_id,
 								      location,
@@ -1495,6 +1537,30 @@
 		/* Load menus from nautilus extensions for this location */
 		nautilus_window_load_extension_menus (window);
 	}
+		
+	/* time slider pref can be just enabled so we need 
+	 * to rescan for snapshots */
+	directory = nautilus_directory_get (slot->location);
+
+	if (window)
+	  {
+	    if (slot->find_zfs_snapshots_cancellable != NULL)
+	      {
+		g_cancellable_cancel (slot->find_zfs_snapshots_cancellable);
+		slot->find_zfs_snapshots_cancellable = NULL;
+	      }
+	    slot->find_zfs_snapshots_cancellable = g_cancellable_new ();
+	    nautilus_zfs_bar_display (NAUTILUS_ZFS_BAR (window->details->zfs_bar),
+				      window,
+				      directory,
+				      slot->find_zfs_snapshots_cancellable);
+
+	  }
+	else
+	  nautilus_window_allow_restore (window, FALSE);
+
+	nautilus_directory_unref (directory);
+
 
 	if (location_really_changed) {
 		nautilus_window_slot_remove_extra_location_widgets (slot);
@@ -1833,11 +1899,19 @@
 nautilus_window_slot_stop_loading (NautilusWindowSlot *slot)
 {
 	NautilusWindow *window;
+	NautilusDirectory *directory;
 
 	window = NAUTILUS_WINDOW (slot->pane->window);
 	g_assert (NAUTILUS_IS_WINDOW (window));
 
 	nautilus_view_stop_loading (slot->content_view);
+ 
+ 	if (slot->find_zfs_snapshots_cancellable)
+ 	  g_cancellable_cancel (slot->find_zfs_snapshots_cancellable);
+ 
+ 	directory = nautilus_directory_get (slot->location);
+ 	nautilus_directory_cancel_restore_info (directory);
+ 	nautilus_directory_unref (directory);
 	
 	if (slot->new_content_view != NULL) {
 		window->details->temporarily_ignore_view_signals = TRUE;
@@ -1898,6 +1972,8 @@
 		nautilus_window_disconnect_content_view (slot->pane->window, slot->content_view);
 	}
 
+	nautilus_window_slot_stop_loading (slot);
+
 	free_location_change (slot);
 	cancel_viewed_file_changed_callback (slot);
 }
--- nautilus-3.1.3/src/nautilus-window-menus.c.orig	2011-07-25 10:08:19.966466156 +0100
+++ nautilus-3.1.3/src/nautilus-window-menus.c	2011-07-25 10:08:46.797184803 +0100
@@ -40,6 +40,7 @@
 #include "nautilus-window-private.h"
 #include "nautilus-desktop-window.h"
 #include "nautilus-search-bar.h"
+#include "nautilus-zfs-bar.h"
 #include <gtk/gtk.h>
 #include <gio/gio.h>
 #include <glib/gi18n.h>
@@ -257,6 +258,33 @@
 }
 
 static void
+action_restore_callback (GtkToggleAction *action, 
+			gpointer user_data) 
+{
+  NautilusWindowSlot *slot;
+  GFile *directory;
+  NautilusDirectory *n_dir;
+  GtkWidget *bar = NAUTILUS_WINDOW (user_data)->details->zfs_bar;
+
+  slot = nautilus_window_get_active_slot (NAUTILUS_WINDOW (user_data));
+  directory = nautilus_window_slot_get_location (slot);
+  n_dir = nautilus_directory_get (directory);
+
+  if (gtk_toggle_action_get_active (action))
+    {
+      nautilus_zfs_bar_setup (NAUTILUS_ZFS_BAR (bar), n_dir, slot, action); 
+      gtk_widget_show (bar); 
+    }
+  else
+    {
+      nautilus_zfs_bar_hide (NAUTILUS_ZFS_BAR (bar));
+      nautilus_window_reload (NAUTILUS_WINDOW (user_data));
+    }
+  g_object_unref (n_dir);
+  g_object_unref (directory);
+}
+
+static void
 action_zoom_in_callback (GtkAction *action, 
 			 gpointer user_data) 
 {
@@ -1113,6 +1141,12 @@
 };
 
 static const GtkToggleActionEntry main_toggle_entries[] = {
+  /* name, stock id */         { "Restore", "stock_help",
+  /* SUN_BRANDING */
+  /* label, accelerator */       N_("R_estore"), "<control>E",
+  /* SUN_BRANDING */
+  /* tooltip */                  N_("Browse the current location snapshot history"),
+                                 G_CALLBACK (action_restore_callback) },
   /* name, stock id */         { "Show Hidden Files", NULL,
   /* label, accelerator */       N_("Show _Hidden Files"), "<control>H",
   /* tooltip */                  N_("Toggle the display of hidden files in the current window"),
diff -Nrup -x '*.orig' -x '*.rej' -x '*.*~' ../SUNWgnome-file-mgr-2.30.0-b4/nautilus-2.30.1/src/nautilus-window-slot.c nautilus-2.30.1/src/nautilus-window-slot.c
--- ../SUNWgnome-file-mgr-2.30.0-b4/nautilus-2.30.1/src/nautilus-window-slot.c	2009-12-16 17:53:51.000000000 +0100
+++ nautilus-2.30.1/src/nautilus-window-slot.c	2010-05-14 17:16:39.566465378 +0200
@@ -650,6 +650,13 @@ nautilus_window_slot_dispose (GObject *o
 		slot->find_mount_cancellable = NULL;
 	}
 
+ 	if (slot->find_zfs_snapshots_cancellable)
+ 	  {
+ 	    g_cancellable_cancel (slot->find_zfs_snapshots_cancellable);
+ 	    g_object_unref (slot->find_zfs_snapshots_cancellable);
+ 	    slot->find_zfs_snapshots_cancellable = NULL;
+ 	  }
+
 	slot->pane = NULL;
 
 	g_free (slot->title);
--- nautilus-3.1.3/src/nautilus-window-slot.h.orig	2011-06-28 14:41:41.000000000 +0100
+++ nautilus-3.1.3/src/nautilus-window-slot.h	2011-07-22 14:33:49.936636702 +0100
@@ -113,6 +113,7 @@
 	gpointer open_callback_user_data;
 
 	GCancellable *find_mount_cancellable;
+	GCancellable *find_zfs_snapshots_cancellable;
 
 	gboolean visible;
 
--- nautilus-3.1.3/src/nautilus-window.c.orig	2011-07-25 14:28:16.524301501 +0100
+++ nautilus-3.1.3/src/nautilus-window.c	2011-07-25 14:28:29.183307666 +0100
@@ -44,6 +44,7 @@
 #include "nautilus-window-manage-views.h"
 #include "nautilus-window-bookmarks.h"
 #include "nautilus-window-slot.h"
+#include "nautilus-zfs-bar.h"
 
 #include <eel/eel-debug.h>
 #include <eel/eel-gtk-extensions.h>
@@ -95,6 +96,7 @@
 static void mouse_back_button_changed		     (gpointer                  callback_data);
 static void mouse_forward_button_changed	     (gpointer                  callback_data);
 static void use_extra_mouse_buttons_changed          (gpointer                  callback_data);
+static void restore_pref_changed                     (gpointer                  callback_data);
 
 /* Sanity check: highest mouse button value I could find was 14. 5 is our 
  * lower threshold (well-documented to be the one of the button events for the 
@@ -269,6 +271,18 @@
 	gtk_action_set_sensitive (action, allow);
 }
 
+void
+nautilus_window_allow_restore (NautilusWindow *window, gboolean enable)
+{
+	GtkAction *action;
+
+	g_assert (NAUTILUS_IS_WINDOW (window));
+
+	action = gtk_action_group_get_action (window->details->main_action_group,
+					      NAUTILUS_ACTION_RESTORE);
+	gtk_action_set_sensitive (action, enable);
+}
+
 static void
 update_cursor (NautilusWindow *window)
 {
@@ -277,7 +291,7 @@
 
 	slot = window->details->active_pane->active_slot;
 
-	if (slot->allow_stop) {
+	if (slot && slot->allow_stop) {
 		cursor = gdk_cursor_new (GDK_WATCH);
 		gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (window)), cursor);
 		g_object_unref (cursor);
@@ -303,8 +317,14 @@
 	if (slot != window->details->active_pane->active_slot ||
 	    allow_stop != slot->allow_stop) {
 		if (slot == window->details->active_pane->active_slot) {
-			gtk_action_set_sensitive (action, slot->allow_stop);
-		}
+			if (!slot->allow_stop && slot->find_zfs_snapshots_cancellable != NULL) { 
+			/* if slot want to stop and snap find is finished/cancel then disable */
+				if (g_cancellable_is_cancelled (slot->find_zfs_snapshots_cancellable))
+					gtk_action_set_sensitive (action, slot->allow_stop);
+			} else {
+				gtk_action_set_sensitive (action, slot->allow_stop);
+                	}
+                }
 
 		if (gtk_widget_get_realized (GTK_WIDGET (window))) {
 			update_cursor (window);
@@ -575,7 +595,7 @@
 
 	G_OBJECT_CLASS (nautilus_window_parent_class)->constructed (self);
 
-	table = gtk_table_new (1, 6, FALSE);
+	table = gtk_table_new (1, 7, FALSE);
 	window->details->table = table;
 	gtk_widget_show (table);
 	gtk_container_add (GTK_CONTAINER (window), table);
@@ -592,6 +612,7 @@
 	menu = gtk_ui_manager_get_widget (window->details->ui_manager, "/MenuBar");
 	window->details->menubar = menu;
 	gtk_widget_show (menu);
+
 	gtk_table_attach (GTK_TABLE (table),
 			  menu, 
 			  /* X direction */                   /* Y direction */
@@ -607,7 +628,7 @@
 	gtk_table_attach (GTK_TABLE (window->details->table),
 			  window->details->content_paned,
 			  /* X direction */                   /* Y direction */
-			  0, 1,                               3, 4,
+			  0, 1,                               4, 5,
 			  GTK_EXPAND | GTK_FILL | GTK_SHRINK, GTK_EXPAND | GTK_FILL | GTK_SHRINK,
 			  0,                                  0);
 	gtk_widget_show (window->details->content_paned);
@@ -632,6 +653,15 @@
 				      nautilus_window_disable_chrome_mapping, NULL,
 				      window, NULL);
 
+	/* add custom icon */
+
+	nautilus_window_set_restore_icon (window, RESTORE_SEARCH);
+	/* add preference callback */
+	g_signal_connect_swapped (nautilus_preferences,
+				  "changed::" NAUTILUS_PREFERENCES_ENABLE_TIME_SLIDER,
+				  G_CALLBACK(restore_pref_changed),
+				  (gpointer) window);
+
 	pane = nautilus_window_pane_new (window);
 	window->details->panes = g_list_prepend (window->details->panes, pane);
 
@@ -656,6 +686,15 @@
 	slot = nautilus_window_open_slot (window->details->active_pane, 0);
 	nautilus_window_set_active_slot (window, slot);
 	nautilus_window_menus_lockdown_notify_add (window);
+
+	window->details->zfs_bar = nautilus_zfs_bar_new ();
+
+	gtk_table_attach (GTK_TABLE (NAUTILUS_WINDOW (window)->details->table),
+			  window->details->zfs_bar,
+			  /* X direction */                    /* Y direction */
+			  0, 1,                                3, 4,
+			  GTK_EXPAND | GTK_FILL | GTK_SHRINK,  0,
+			  0,                                   0);
 }
 
 static void
@@ -1913,7 +1952,7 @@
 	return slot;
 }
 
-static void
+void
 nautilus_window_reload (NautilusWindow *window)
 {
 	NautilusWindowSlot *active_slot;
@@ -1997,6 +2036,13 @@
 }
 
 static void
+restore_pref_changed (gpointer callback_data)
+{
+	g_assert (NAUTILUS_IS_WINDOW (callback_data));
+	nautilus_window_reload (NAUTILUS_WINDOW(callback_data));
+}
+
+static void
 mouse_back_button_changed (gpointer callback_data)
 {
 	int new_back_button;
@@ -2030,7 +2076,6 @@
 	mouse_extra_buttons = g_settings_get_boolean (nautilus_preferences, NAUTILUS_PREFERENCES_MOUSE_USE_EXTRA_BUTTONS);
 }
 
-
 /*
  * Main API
  */
@@ -2249,3 +2294,47 @@
 {
 	return g_list_length (NAUTILUS_WINDOW (window)->details->panes) > 1;
 }
+
+void nautilus_window_set_restore_icon (NautilusWindow* window,
+				       NautilusRestoreIconType type)
+{
+	static gboolean init = 0;
+	static GdkPixbuf *normal = NULL;
+	static GdkPixbuf *search = NULL;
+	static GdkPixbuf *no = NULL;
+	GdkPixbuf *pb = NULL;
+	GtkWidget *image = NULL;
+	GtkAction* action = gtk_ui_manager_get_action (nautilus_window_get_ui_manager (NAUTILUS_WINDOW (window)), "/Toolbar/Restore");
+
+	if (!init) {
+		char *path = nautilus_pixmap_file ("restore.png");
+		normal = gdk_pixbuf_new_from_file (path, NULL);
+		g_free (path);
+		path = nautilus_pixmap_file ("restore-search.png");
+		search = gdk_pixbuf_new_from_file (path, NULL);
+		g_free (path);
+		init = TRUE;
+	}
+
+	switch (type) {
+	case RESTORE_NORMAL :
+		pb = normal;
+		break;
+	case RESTORE_SEARCH:
+		pb = search;
+		break;
+	case RESTORE_NO:
+		pb = no;
+		break;
+	}
+
+	image = gtk_image_new_from_pixbuf (pb);
+	g_object_ref (image);
+	gtk_widget_show (image);
+	GSList *tmp = gtk_action_get_proxies (action);
+	for (tmp; tmp ; tmp = tmp->next) {
+		GtkWidget *proxy = (GtkWidget *)tmp->data;
+		if (GTK_IS_TOOL_BUTTON (proxy))
+			gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (proxy), image);
+	}
+}
--- nautilus-3.1.3/src/nautilus-window-private.h.orig	2011-07-25 10:54:12.777383655 +0100
+++ nautilus-3.1.3/src/nautilus-window-private.h	2011-07-25 11:06:58.227055497 +0100
@@ -94,6 +94,8 @@
         GtkWidget *sidebar;
         gchar *sidebar_id;
         
+        GtkWidget *zfs_bar;
+
         /* Toolbar */
         GtkWidget *toolbar;
 
@@ -111,6 +113,12 @@
         guint sidebar_width_handler_id;
 };
 
+typedef enum {
+	RESTORE_NORMAL,
+	RESTORE_SEARCH,
+	RESTORE_NO
+} NautilusRestoreIconType;
+
 /* window geometry */
 /* Min values are very small, and a Nautilus window at this tiny size is *almost*
  * completely unusable. However, if all the extra bits (sidebar, location bar, etc)
@@ -176,6 +184,9 @@
 void               nautilus_window_update_show_hide_menu_items           (NautilusWindow     *window);
 void               nautilus_window_menus_lockdown_notify_add             (NautilusWindow    *window);
 void               nautilus_window_menus_lockdown_notify_remove          (NautilusWindow    *window);
+gboolean           nautilus_window_zfs_bar_showing                       (NautilusWindow    *window);
+void               nautilus_window_set_restore_icon                      (NautilusWindow    *window,
+                                                                          NautilusRestoreIconType type);
 
 /* window toolbar */
 void               nautilus_window_close_pane                            (NautilusWindowPane *pane);
--- nautilus-3.1.3/src/nautilus-window.h.orig	2011-06-28 14:41:41.000000000 +0100
+++ nautilus-3.1.3/src/nautilus-window.h	2011-07-22 14:56:24.534238012 +0100
@@ -152,6 +152,8 @@
                                                gboolean       allow);
 void     nautilus_window_allow_forward        (NautilusWindow *window,
                                                gboolean        allow);
+void     nautilus_window_allow_restore        (NautilusWindow *window,
+                                               gboolean        allow);
 void     nautilus_window_clear_back_list      (NautilusWindow *window);
 void     nautilus_window_clear_forward_list   (NautilusWindow *window);
 void     nautilus_forget_history              (void);
--- /dev/null	2011-07-25 11:57:58.000000000 +0100
+++ nautilus-3.1.3/src/nautilus-zfs-bar.c	2011-07-25 11:55:15.960654076 +0100
@@ -0,0 +1,841 @@
+/* 
+ * Copyright (C) 2008 Sun Microsystems (Erwann Chenede)
+ *
+ */
+
+#include "config.h"
+#include <strings.h>
+#include <glib/gi18n-lib.h>
+#include <gtk/gtk.h>
+
+#include "nautilus-zfs-bar.h"
+#include "nautilus-window.h"
+#include "nautilus-window-private.h"
+#include "nautilus-file-utilities.h"
+#include "timescale.h"
+#include <libnautilus-private/nautilus-zfs.h>
+#include <libnautilus-private/nautilus-file.h>
+#include <libnautilus-private/nautilus-global-preferences.h>
+#include "nautilus-window-slot.h"
+
+#define NAUTILUS_ZFS_BAR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NAUTILUS_TYPE_ZFS_BAR, NautilusZfsBarPrivate))
+
+struct NautilusZfsBarPrivate
+{
+       NautilusDirectory *dir;
+       GtkWidget	 *scale;
+       GtkWidget	 *delete_button;
+       GdkColor		  in_snapshot;
+       GtkToggleAction	 *action;
+       NautilusWindowSlot *slot;
+       int		  num_range_items;
+       gboolean		  is_setup;
+       gboolean		  set_only;
+       char		 *current_path;
+       ZfsSnapDirMonitor *zfs_dir_monitor_data;
+       gboolean		  in_snapshot_dir;
+       GtkWidget	 *camera_image;
+       GtkWidget	 *delete_image;
+       gboolean		  explicit_user_hide;
+};
+
+G_DEFINE_TYPE (NautilusZfsBar, nautilus_zfs_bar, GTK_TYPE_EVENT_BOX)
+
+static void
+close_clicked_callback (GtkWidget *widget,
+                        NautilusZfsBar *bar);
+static void 
+slider_moved_callback (TimeScale *ts,
+		       NautilusZfsBar *bar);
+static void 
+update_delete_or_snap_button (NautilusZfsBar *bar, 
+			      gboolean in_snap);
+
+static void
+nautilus_zfs_bar_class_init (NautilusZfsBarClass *klass)
+{
+	GObjectClass *object_class;
+
+	object_class = G_OBJECT_CLASS (klass);
+
+	g_type_class_add_private (klass, sizeof (NautilusZfsBarPrivate));
+}
+
+static void 
+set_scale_range (NautilusZfsBar *bar, gboolean set_initial_position)
+{
+  int i;
+  GList *tmp;
+
+  if (bar->priv->dir)
+    {
+      i = nautilus_directory_get_num_snapshots (bar->priv->dir);   
+
+      if (i==0)
+	return;
+
+      bar->priv->num_range_items = i;
+      
+      tmp = nautilus_directory_get_snapshots (bar->priv->dir);
+
+      if (set_initial_position)
+	timescale_set_snapshots (TIMESCALE (bar->priv->scale), tmp, -1);
+      else
+	timescale_set_snapshots (TIMESCALE (bar->priv->scale), tmp, bar->priv->num_range_items);
+    }
+}
+
+static void 
+update_range (NautilusZfsBar *bar)
+{
+  if (nautilus_directory_get_snapshots (bar->priv->dir))
+    {
+      set_scale_range (bar, FALSE);
+      slider_moved_callback (TIMESCALE (bar->priv->scale), bar);
+    }
+  else
+    close_clicked_callback (NULL, bar);
+}
+
+static int match_func (ZfsDataSet *set, char *dir)
+{
+  /* remove trailing slash from dir */
+  char mountp[PATH_MAX+1];
+  int length = strlen (set->mountpoint);
+
+  if (set->mountpoint[length-1] == '/')
+    {
+      memcpy (mountp, set->mountpoint, length - 1);
+      mountp[length-1] = NULL;
+      return strcmp (mountp, dir);
+    }
+  else
+    return strcmp (set->mountpoint, dir);
+}
+
+void 
+nautilus_zfs_bar_remove_and_skip_snap (NautilusZfsBar *bar, char *path)
+{
+  GList* match = NULL;
+  GList* snap_list = NULL;
+  ZfsDataSet *snap;
+
+  snap_list = nautilus_directory_get_snapshots (bar->priv->dir);
+  match = g_list_find_custom (snap_list, path, (GCompareFunc)match_func);
+
+  if (match)
+    {
+      snap = (ZfsDataSet*) match->data;
+      nautilus_directory_remove_snapshot (bar->priv->dir, snap);
+      update_range (bar);
+    }
+}
+
+static void 
+update_delete_or_snap_button (NautilusZfsBar *bar, gboolean in_snap)
+{
+       if (in_snap)
+	{
+	  if (!bar->priv->in_snapshot_dir)
+	    { /*in main dir to snap */
+	      bar->priv->in_snapshot_dir = TRUE;
+	      g_object_ref (bar->priv->camera_image);
+	      gtk_button_set_image (GTK_BUTTON (bar->priv->delete_button),
+				    bar->priv->delete_image);
+	      gtk_widget_set_tooltip_text (bar->priv->delete_button,
+					   /* SUN_BRANDING */
+					   _("Delete this snapshot"));
+	    }
+	}
+      else
+	{
+	  if (bar->priv->in_snapshot_dir)
+	    { /* in snap to main dir */
+	      bar->priv->in_snapshot_dir = FALSE;
+	      g_object_ref (bar->priv->delete_image);
+	      gtk_button_set_image (GTK_BUTTON (bar->priv->delete_button),
+				    bar->priv->camera_image);
+	      gtk_widget_set_tooltip_text (bar->priv->delete_button,
+					   /* SUN_BRANDING */
+					   _("Take a zfs snapshot of this directory now"));
+	    }
+	}
+}
+
+static void 
+slider_moved_callback (TimeScale *ts,
+		       NautilusZfsBar *bar)
+{
+  GList *tmp;
+  ZfsDataSet *snap;
+  GFile *snap_file;
+  int pos = timescale_get_position (ts);
+
+  if (pos < bar->priv->num_range_items)
+    {
+      tmp = nautilus_directory_get_snapshots (bar->priv->dir);
+
+      snap = g_list_nth_data (tmp, pos);
+
+      snap_file = g_file_new_for_path (snap->mountpoint);
+    }
+  else
+    {
+      snap_file = nautilus_directory_get_location (bar->priv->dir);
+      pos = bar->priv->num_range_items;
+    }
+
+  if (!bar->priv->set_only)
+    {
+      gboolean in_snap = FALSE;
+      char *path = g_file_get_path (snap_file);
+
+      if (g_file_test (path, G_FILE_TEST_IS_DIR))
+	{
+	  nautilus_window_slot_go_to (bar->priv->slot,
+				      snap_file,
+				      FALSE);
+	  if (bar->priv->current_path)
+	    g_free (bar->priv->current_path);
+	  bar->priv->current_path = path;
+	}
+      else
+	{ /* the snapshot diappeared try the next one */
+	  g_free (path);
+	  g_object_unref (snap_file);
+	  /* remove snap from list */
+	  nautilus_directory_remove_snapshot (bar->priv->dir, snap);
+	  update_range (bar);
+	  return;
+	}
+
+      in_snap = ts_is_in_snapshot (path);
+      update_delete_or_snap_button (bar, ts_is_in_snapshot (path));
+
+     }
+
+g_object_unref (snap_file);
+
+}
+
+
+static void
+delete_clicked_callback (GtkWidget *widget,
+			 NautilusZfsBar *bar)
+{
+  GList *tmp;
+  ZfsDataSet *snap;
+  GFile *snap_file;
+  char *path;
+  char *full_command;
+  int pos = timescale_get_position (TIMESCALE (bar->priv->scale));
+
+  if (bar->priv->in_snapshot_dir)
+    {
+      tmp = nautilus_directory_get_snapshots (bar->priv->dir);
+      snap = g_list_nth_data (tmp, pos);
+      snap_file = g_file_new_for_path (snap->mountpoint);
+      path = g_file_get_path (snap_file);
+
+      g_object_unref (snap_file);
+      if (snap->type)
+	{
+	  /*printf ("path %s snapshot to delete %s\n", path, snap->name);*/
+	  full_command = g_strdup_printf ("/usr/lib/time-slider-delete '%s'", snap->name);
+	}
+      else
+	{
+	  /*printf ("path %s backup to delete %s\n", path, snap->name);*/
+	  full_command = g_strdup_printf ("/usr/lib/time-slider-delete '%s'", path);
+	}
+
+      nautilus_launch_application_from_command (gtk_widget_get_screen (widget),
+					full_command, NULL);
+    }
+  else
+    {
+      path = g_file_get_path (nautilus_directory_get_location (bar->priv->dir));
+      char *fs = ts_get_zfs_filesystem (path);
+      /* printf ("take a snapshot of zfs fs %s for dir %s\n", fs, path); */
+      full_command = g_strdup_printf ("/usr/lib/time-slider-snapshot '%s' '%s'", path, fs);
+      nautilus_launch_application_from_command (gtk_widget_get_screen (widget),
+					full_command, NULL);
+      g_free (fs);
+    }
+
+    g_free (full_command);
+    g_free (path);
+}
+
+static void
+close_clicked_callback (GtkWidget *widget,
+                        NautilusZfsBar *bar)
+{
+  GFile *snap_file = nautilus_directory_get_location (bar->priv->dir);
+
+  nautilus_window_slot_go_to (bar->priv->slot,
+			      snap_file,
+			      FALSE);
+  g_object_unref (snap_file);
+
+  bar->priv->is_setup = FALSE;
+
+  gtk_widget_hide (GTK_WIDGET (bar));
+  gtk_toggle_action_set_active (bar->priv->action, FALSE);
+
+}
+
+static void
+nautilus_zfs_bar_init (NautilusZfsBar *bar)
+{
+  GtkWidget *hbox, *toolbar, *close, *delete, *image, *button_vbox;
+  GtkToolItem *item;
+  char *path;
+
+  bar->priv = NAUTILUS_ZFS_BAR_GET_PRIVATE (bar);
+
+  bar->priv->dir = NULL;
+  bar->priv->num_range_items = 0;
+  bar->priv->action = NULL;
+  bar->priv->slot = NULL;
+  bar->priv->is_setup = FALSE;
+  bar->priv->set_only = FALSE;
+
+  /* GUI init */
+
+  toolbar = gtk_toolbar_new ();
+  gtk_widget_show (toolbar);
+
+  item = gtk_tool_item_new ();
+  gtk_widget_show (GTK_WIDGET (item));
+  gtk_tool_item_set_expand (item, TRUE);
+
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (GTK_WIDGET (hbox));
+
+  gtk_container_add (GTK_CONTAINER (item),hbox);
+
+  gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1);
+  gtk_container_add (GTK_CONTAINER (bar),toolbar);
+  gtk_container_set_border_width (GTK_CONTAINER (bar), 0);
+
+  /* buttons */
+
+  button_vbox = gtk_vbox_new (FALSE, 0);
+  gtk_widget_show (button_vbox);
+
+  close = gtk_button_new ();
+  gtk_button_set_relief (GTK_BUTTON (close), GTK_RELIEF_NONE);
+  gtk_widget_set_tooltip_text (close,
+			       /* SUN_BRANDING */
+			       _("Close Time Slider and return to original directory"));
+  gtk_widget_show (close);
+
+  g_signal_connect (close,
+		    "clicked",
+		    G_CALLBACK (close_clicked_callback),
+		    bar);
+
+  image = gtk_image_new_from_stock (GTK_STOCK_CLOSE,
+				    GTK_ICON_SIZE_MENU);
+  gtk_widget_show (image);
+  
+  gtk_container_add (GTK_CONTAINER (close), image);
+  
+  gtk_box_pack_start (GTK_BOX (button_vbox), close, FALSE, FALSE, 0);
+
+  delete = gtk_button_new ();
+  gtk_button_set_relief (GTK_BUTTON (delete), GTK_RELIEF_NONE);
+  gtk_widget_set_tooltip_text (delete,
+			       /* SUN_BRANDING */
+			       _("Take a zfs snapshot of this directory now"));
+  gtk_widget_show (delete);
+
+  g_signal_connect (delete,
+		    "clicked",
+		    G_CALLBACK (delete_clicked_callback),
+		    bar);
+  
+    {
+      GtkIconTheme *it =  gtk_icon_theme_get_default ();
+      GdkPixbuf * pb = gtk_icon_theme_load_icon (it,
+						 "user-trash-full.png",
+						 16,
+                                                 GTK_ICON_LOOKUP_GENERIC_FALLBACK,
+						 NULL);
+      bar->priv->delete_image = gtk_image_new_from_pixbuf (pb);
+      g_object_unref (pb);
+    }
+
+  path = nautilus_pixmap_file ("camera.png");
+  bar->priv->camera_image = gtk_image_new_from_file (path);
+  g_free (path);
+
+  gtk_widget_show (bar->priv->delete_image);
+  gtk_widget_show (bar->priv->camera_image);
+  
+  gtk_container_add (GTK_CONTAINER (delete), bar->priv->camera_image);
+  
+  gtk_box_pack_end (GTK_BOX (button_vbox), delete, FALSE, FALSE, 0);
+  gtk_box_pack_end (GTK_BOX (hbox), button_vbox, FALSE, FALSE, 0);
+
+  bar->priv->delete_button = delete;
+  
+  bar->priv->scale = timescale_new();
+
+  g_signal_connect (bar->priv->scale,
+		    "value-changed",
+		    G_CALLBACK (slider_moved_callback),
+		    bar);
+
+  gtk_widget_show (bar->priv->scale);
+
+  gtk_box_pack_start (GTK_BOX (hbox), bar->priv->scale, TRUE, TRUE, 0);
+  
+}
+
+NautilusDirectory * 
+nautilus_zfs_bar_get_dir (NautilusZfsBar* bar)
+{
+  g_return_val_if_fail (NAUTILUS_IS_ZFS_BAR (bar), NULL);
+  return bar->priv->dir;
+}
+
+static void snapshot_data_ready (NautilusDirectory *dir, 
+				 GCancellable      *cancellable,
+				 gpointer callback_data)
+{
+  NautilusWindowSlot *slot;
+  GFile *location;
+  GFile *dir_location;
+  NautilusWindow *window = (NautilusWindow*)callback_data;
+
+  g_return_if_fail (NAUTILUS_IS_WINDOW (window));
+
+  slot = nautilus_window_get_active_slot (window);
+  location = nautilus_window_slot_get_location (slot);
+  dir_location = nautilus_directory_get_location (dir);
+
+  if (g_cancellable_is_cancelled (cancellable) && g_file_equal (location, dir_location))
+    {
+      nautilus_window_set_restore_icon (window, RESTORE_NO);
+    }
+  else if (g_file_equal (location, dir_location))
+    {
+      char *path = g_file_get_path (dir_location);
+      g_cancellable_cancel (cancellable);
+      nautilus_window_slot_set_allow_stop (slot, FALSE);
+      nautilus_window_set_restore_icon (window, 
+					nautilus_directory_has_snapshots (dir) ? RESTORE_NORMAL : RESTORE_NO);
+      if (nautilus_directory_has_snapshots (dir))
+	nautilus_window_allow_restore (window, TRUE);
+      else
+	nautilus_window_allow_restore (window, FALSE);
+      g_free (path);
+    }
+  g_object_unref (location);
+  g_object_unref (dir_location);
+}
+
+
+void nautilus_zfs_bar_cancel_tasks (NautilusWindow *window)
+{
+  if (NAUTILUS_IS_WINDOW (window))
+    {
+      if (NAUTILUS_IS_WINDOW_SLOT (window->details->active_pane->active_slot))
+	{
+	  NautilusDirectory *directory = NULL;
+	  g_cancellable_cancel (window->details->active_pane->active_slot->find_zfs_snapshots_cancellable);
+	  g_object_unref (window->details->active_pane->active_slot->find_zfs_snapshots_cancellable);
+	  window->details->active_pane->active_slot->find_zfs_snapshots_cancellable = NULL;
+	  directory = nautilus_directory_get (window->details->active_pane->active_slot->location);
+	  if (directory)
+	    {
+	      nautilus_directory_cancel_restore_info (directory);
+	      nautilus_directory_unref (directory);
+	    }
+	}
+      if (NAUTILUS_WINDOW (window))
+	{
+	  NautilusZfsBar *bar = NAUTILUS_ZFS_BAR (window->details->zfs_bar);
+	  monitor_zfs_snap_directory_cancel (bar->priv->zfs_dir_monitor_data);
+	  bar->priv->zfs_dir_monitor_data = NULL;
+	}
+    }
+}
+
+void nautilus_zfs_bar_hide (NautilusZfsBar *bar)
+{
+  bar->priv->explicit_user_hide = TRUE;
+  close_clicked_callback (NULL, bar);
+}
+
+
+/* Display AND Scan */
+
+void		 
+nautilus_zfs_bar_display (NautilusZfsBar *bar,
+			  NautilusWindow *window,
+			  NautilusDirectory *new_dir,
+			  GCancellable *cancellable)
+{
+  gboolean show = FALSE;
+  gboolean time_slider_enabled = g_settings_get_boolean (nautilus_preferences, NAUTILUS_PREFERENCES_ENABLE_TIME_SLIDER);
+  gboolean visible = gtk_widget_get_visible (GTK_WIDGET (bar));
+  gboolean enable_button = FALSE;
+  gboolean do_scan = FALSE;
+  gboolean do_cancel = FALSE;
+
+
+  /* if bar visible
+   *	if feature disabled
+   *	  close bar
+   *	  disable button
+   *	if in root dir
+   *	  enable button
+   * else
+   *	if bar was previously displayed and in same tab
+   *	   if in snapshot
+   *	     redisplay 
+   *	     re-align
+   *	     disable button
+   *	   if root dir 
+   *	     redisplay 
+   *	     re-align
+   *	     enable button
+   *	   else
+   *	      scan
+   *	else
+   *	  if feature enabled 
+   *	    scan
+   *	    disable button
+   *
+   *
+   *  NOTE : action_restore_callback display bar when enabled
+   */
+
+  if (visible)
+    {
+      if (!time_slider_enabled)
+	{
+	  close_clicked_callback (NULL, bar);
+	  return;
+	}
+      if (new_dir == bar->priv->dir)
+	enable_button = TRUE;
+      if (nautilus_directory_is_a_snapshot_dir_of (new_dir, bar->priv->dir) || new_dir == bar->priv->dir)
+	{
+	  show = TRUE;
+	  do_cancel = TRUE;
+	  enable_button = TRUE;
+	}
+      else
+	do_scan = TRUE;
+    }
+  else
+    { /* bar is not visible */
+      NautilusWindowSlot *slot = nautilus_window_get_active_slot (window);
+
+      if (bar->priv->is_setup && slot == bar->priv->slot && time_slider_enabled) /* check if we can redisplay the bar */
+	{
+	  if (nautilus_directory_is_a_snapshot_dir_of (new_dir, bar->priv->dir) && !bar->priv->explicit_user_hide)
+	    show = TRUE;
+
+	  if (bar->priv->explicit_user_hide)
+	    enable_button = FALSE;
+
+	  if (new_dir == bar->priv->dir)
+	    {
+	      show = TRUE;
+	      enable_button = TRUE;
+	    }
+	  else
+	    do_scan = TRUE;
+	}
+      else
+	{ /* icon and throbber set is snapshot_data_ready */
+	  if (time_slider_enabled)
+	    do_scan = TRUE;
+	}
+
+    }
+
+  if (enable_button) /* if button enabled set the icon to normal */
+    nautilus_window_set_restore_icon (window, RESTORE_NORMAL);
+
+  nautilus_window_allow_restore (window, enable_button); 
+
+
+  if (show)
+    {
+      gtk_widget_show (GTK_WIDGET (bar));
+      nautilus_zfs_set_snap (bar, new_dir);
+    }
+  else
+    {
+      gtk_widget_hide (GTK_WIDGET (bar));
+      if (bar->priv->action)
+	gtk_toggle_action_set_active (bar->priv->action, FALSE);
+    }
+
+  if (do_cancel)
+    g_cancellable_cancel (cancellable);
+
+  if (do_scan)
+    {
+      g_cancellable_reset (cancellable);
+      nautilus_window_set_restore_icon (window, RESTORE_SEARCH);
+      nautilus_window_slot_set_allow_stop (nautilus_window_get_active_slot (window), TRUE);
+      nautilus_directory_get_snapshots_async (new_dir,
+					      snapshot_data_ready, 
+					      cancellable, 
+					      window);
+    }
+
+   /* {
+      GFile *file = nautilus_directory_get_location (new_dir);
+      char *path = g_file_get_path (file);
+
+      printf ("nautilus_zfs_bar_display %s\nenable_button : %s, show : %s, do_cancel : %s, do_scan : %s\n\n",
+	      path,
+	      enable_button ? "true" : "false",
+	      show ? "true" : "false",
+	      do_cancel ? "true" : "false",
+	      do_scan ? "true" : "false");
+      g_free (path);
+    }*/
+
+}
+
+
+void nautilus_zfs_set_snap (NautilusZfsBar *bar,
+			    NautilusDirectory *dir)
+{
+  GList* match = NULL;
+  GList* snap_list = NULL;
+  gboolean in_snap = FALSE;
+  char real_path [PATH_MAX+1];
+  GFile *file;
+  char* path;
+  int pos;
+  int set_pos = -2;
+
+  if (!bar->priv->is_setup)
+    return;
+
+  file = nautilus_directory_get_location (dir);
+  path = g_file_get_path (file);
+  ts_realpath (path, real_path);
+
+
+  if (ts_is_in_remote_backup (real_path))
+    { /* hmmm */
+      /*gnome_vfs_init();*/
+      g_object_ref (dir); 
+    }
+
+  in_snap = ts_is_in_snapshot (real_path);
+
+  if (in_snap)
+    {
+      snap_list = nautilus_directory_get_snapshots (bar->priv->dir);
+      match = g_list_find_custom (snap_list, real_path, (GCompareFunc)match_func);
+    }
+  g_free (path);
+  g_object_unref (file);
+
+  timescale_set_position (TIMESCALE (bar->priv->scale), match ? ((ZfsDataSet*)match->data)->mountpoint : NULL);
+  update_delete_or_snap_button (bar, in_snap);
+  
+/*  printf ("nautilus_zfs_set_snap current_path %s real_path %s match %s\n", bar->priv->current_path, real_path,
+	  match ? "found" : "not found");*/
+
+  if (bar->priv->current_path && (strcmp (bar->priv->current_path, real_path) != 0))
+    {
+      bar->priv->set_only = TRUE;
+      bar->priv->set_only = FALSE;
+
+    }
+}
+
+static void snapshot_data_ready_from_change (NautilusDirectory *dir, 
+					     GCancellable      *cancellable,
+					     gpointer callback_data)
+{
+  NautilusZfsBar *bar = NAUTILUS_ZFS_BAR (callback_data);
+
+  snapshot_data_ready (dir, cancellable, bar->priv->slot->pane->window);
+  update_range (bar);
+  gtk_widget_set_sensitive (bar->priv->scale, TRUE);
+}
+
+
+static void zfs_dir_change_callback (ZfsSnapDirMonitor *monitor_data,
+				     NautilusZfsBar *bar)
+{
+  gtk_widget_set_sensitive (bar->priv->scale, FALSE);
+
+  g_cancellable_reset (bar->priv->slot->find_zfs_snapshots_cancellable);
+  nautilus_window_set_restore_icon (bar->priv->slot->pane->window, RESTORE_SEARCH);
+  nautilus_window_slot_set_allow_stop (bar->priv->slot, TRUE);
+  nautilus_directory_get_snapshots_async (bar->priv->dir,
+					  snapshot_data_ready_from_change, 
+					  bar->priv->slot->find_zfs_snapshots_cancellable,
+					  bar);
+}
+
+static char* 
+get_backup_dir (GList *snaplist)
+{
+  GList *tmp = snaplist;
+
+  while (tmp)
+    {
+      ZfsDataSet *snap = (ZfsDataSet*) tmp->data;
+      if (snap->type == 0)
+	{
+	  char **root_split = NULL;
+	  char *result = NULL;
+	  root_split = g_strsplit (snap->mountpoint, snap->name, 2);
+	  /*printf (" name: %s\n mountpoint: %s\n mtime_str :%s\n space used : %s\n size in kilobytes : %f\n",
+	      snap->name, snap->mountpoint, snap->mtime_str, snap->used_space_str, snap->used_space); */
+	  result = g_strdup (root_split[0]);
+	  if (root_split)
+	    g_strfreev (root_split);
+	  return result;
+	}
+      tmp = tmp->next;
+    }
+  return NULL;
+  
+
+}
+
+void		
+nautilus_zfs_bar_setup (NautilusZfsBar* bar,
+			NautilusDirectory *dir,	
+			NautilusWindowSlot *active_slot,
+			GtkToggleAction* action)
+{
+  GFile *file;
+  char *path, *zfs_dir, *backup_dir = NULL;
+  bar->priv->dir = dir;
+  g_object_ref (dir);
+  bar->priv->slot = active_slot;
+  g_object_ref (active_slot);
+
+  bar->priv->action = action;
+  set_scale_range (bar, TRUE);  
+  bar->priv->is_setup = TRUE;
+  bar->priv->explicit_user_hide = FALSE;
+
+  file = nautilus_directory_get_location (dir);
+  path = g_file_get_path (file);
+  zfs_dir = ts_get_snapshot_dir (path);
+  backup_dir = get_backup_dir (nautilus_directory_get_snapshots (dir));
+
+  bar->priv->zfs_dir_monitor_data = monitor_zfs_snap_directory (zfs_dir, 
+								backup_dir,
+								(ZfsDirChangeCallback) zfs_dir_change_callback, 
+								bar);
+  nautilus_zfs_set_snap (bar, dir);
+  g_free (path);
+  g_free (zfs_dir);
+  if (backup_dir)
+    g_free(backup_dir);
+  g_object_unref (file);
+}
+
+static void 
+zfs_bar_show_column (GtkWidget *widget, gpointer user_data)
+{
+  char **visible_columns;
+  gboolean restore_col_visible = FALSE;
+  int i = 0;
+  GPtrArray *ret = NULL;
+
+  visible_columns = g_settings_get_strv (nautilus_list_view_preferences,
+                                         NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_VISIBLE_COLUMNS);
+
+  ret = g_ptr_array_new ();
+
+  /* convert visible_columns in ptr array without "restore_info" */
+  while (visible_columns[i])
+    {
+      if (strcmp (visible_columns [i], "restore_info") == 0)
+	{
+	  restore_col_visible = TRUE;
+	  break;
+	}
+      else
+	g_ptr_array_add (ret, g_strdup (visible_columns [i]));
+      i++;
+    }
+
+  g_strfreev (visible_columns);
+
+  if (restore_col_visible)
+    {
+      if (!gtk_widget_get_visible (widget)) /* hide bar remove pref */
+	{
+	  char **col_array;
+	  g_ptr_array_add (ret, NULL);
+	  col_array = (char **)g_ptr_array_free (ret, FALSE);
+          g_settings_set_strv (nautilus_list_view_preferences,
+                               NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_VISIBLE_COLUMNS,
+                               (const char * const *) col_array);
+	  g_strfreev (col_array);
+	  ret = NULL;
+	}
+    }
+  else
+    {
+      if (gtk_widget_get_visible (widget))
+	{
+	  char **col_array;
+	  g_ptr_array_add (ret,strdup ("restore_info"));
+	  g_ptr_array_add (ret,NULL);
+	  col_array = (char **)g_ptr_array_free (ret, FALSE);
+          g_settings_set_strv (nautilus_list_view_preferences,
+                               NAUTILUS_PREFERENCES_LIST_VIEW_DEFAULT_VISIBLE_COLUMNS,
+                               (const char * const *) col_array);
+	  g_strfreev (col_array);
+	  ret = NULL;
+	}
+      
+    }
+
+  if (ret)
+    g_ptr_array_free (ret, TRUE);
+
+}
+
+static void 
+zfs_bar_hidden (GtkWidget *widget, gpointer user_data)
+{
+  NautilusZfsBar *bar = NAUTILUS_ZFS_BAR (user_data);
+  monitor_zfs_snap_directory_cancel (bar->priv->zfs_dir_monitor_data);
+  bar->priv->zfs_dir_monitor_data = NULL;
+  nautilus_directory_cancel_restore_info (bar->priv->dir);
+}
+
+GtkWidget *
+nautilus_zfs_bar_new ()
+{
+	GObject *bar;
+	NautilusZfsBar *zfs_bar;
+
+	bar = g_object_new (NAUTILUS_TYPE_ZFS_BAR, NULL);
+
+	g_signal_connect_object (bar, "show", G_CALLBACK (zfs_bar_show_column), bar, NULL);
+	g_signal_connect_object (bar, "hide", G_CALLBACK (zfs_bar_show_column), bar, NULL);
+	g_signal_connect_object (bar, "hide", G_CALLBACK (zfs_bar_hidden), bar, NULL);
+
+	zfs_bar_show_column (GTK_WIDGET (bar), NULL); 
+
+	ts_is_restore_column_enabled_init ();
+
+	zfs_bar = NAUTILUS_ZFS_BAR (bar);
+
+	return GTK_WIDGET (bar);
+}
diff -Nrup -x '*.orig' -x '*.rej' -x '*.*~' ../SUNWgnome-file-mgr-2.30.0-b4/nautilus-2.30.1/src/nautilus-zfs-bar.h nautilus-2.30.1/src/nautilus-zfs-bar.h
--- ../SUNWgnome-file-mgr-2.30.0-b4/nautilus-2.30.1/src/nautilus-zfs-bar.h	1970-01-01 01:00:00.000000000 +0100
+++ nautilus-2.30.1/src/nautilus-zfs-bar.h	2010-05-14 17:16:39.568719551 +0200
@@ -0,0 +1,57 @@
+#ifndef __NAUTILUS_ZFS_BAR_H
+#define __NAUTILUS_ZFS_BAR_H
+
+#include <gtk/gtk.h>
+#include <libnautilus-private/nautilus-directory.h>
+#include "nautilus-window-slot.h"
+
+G_BEGIN_DECLS
+
+#define NAUTILUS_TYPE_ZFS_BAR         (nautilus_zfs_bar_get_type ())
+#define NAUTILUS_ZFS_BAR(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), NAUTILUS_TYPE_ZFS_BAR, NautilusZfsBar))
+#define NAUTILUS_ZFS_BAR_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), NAUTILUS_TYPE_ZFS_BAR, NautilusZfsBarClass))
+#define NAUTILUS_IS_ZFS_BAR(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), NAUTILUS_TYPE_ZFS_BAR))
+#define NAUTILUS_IS_ZFS_BAR_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), NAUTILUS_TYPE_ZFS_BAR))
+#define NAUTILUS_ZFS_BAR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), NAUTILUS_TYPE_ZFS_BAR, NautilusZfsBarClass))
+
+typedef struct NautilusZfsBarPrivate NautilusZfsBarPrivate;
+
+typedef struct
+{
+  GtkEventBox eventbox;
+  NautilusZfsBarPrivate *priv;
+} NautilusZfsBar;
+
+typedef struct
+{
+  GtkEventBoxClass parent_class;
+} NautilusZfsBarClass;
+
+GType		 nautilus_zfs_bar_get_type	(void) G_GNUC_CONST;
+
+GtkWidget	*nautilus_zfs_bar_new		();
+
+void		 nautilus_zfs_bar_setup (NautilusZfsBar* bar,
+					 NautilusDirectory *dir,
+					 NautilusWindowSlot *active_slot,
+					 GtkToggleAction* action);
+
+void		 nautilus_zfs_bar_display (NautilusZfsBar *bar,
+					   NautilusWindow *window,
+					   NautilusDirectory *new_dir,
+					   GCancellable* cancellable);
+
+void		 nautilus_zfs_set_snap	  (NautilusZfsBar *bar,
+					   NautilusDirectory *dir);
+void		 nautilus_zfs_bar_remove_and_skip_snap 
+					  (NautilusZfsBar *bar, char *path);
+
+void		nautilus_zfs_bar_hide (NautilusZfsBar *bar);					  
+
+void		 nautilus_zfs_bar_cancel_tasks (NautilusWindow *window);
+NautilusDirectory * nautilus_zfs_bar_get_dir (NautilusZfsBar* bar);
+G_END_DECLS
+
+
+
+#endif /* __NAUTILUS_ZFS_BAR_H */
--- /dev/null	2011-07-25 13:54:15.000000000 +0100
+++ nautilus-3.1.3/src/timescale.c	2011-07-25 13:53:42.519729725 +0100
@@ -0,0 +1,1278 @@
+/* 
+ * Copyright (C) 2010 Sun Microsystems (Erwann Chenede)
+ *
+ */
+
+#include "config.h"
+#include "timescale.h"
+#include <math.h>
+#include <stdlib.h>
+#include <libnautilus-private/nautilus-zfs.h>
+#include <glib/gi18n-lib.h>
+#include <gdk/gdkkeysyms.h>
+
+#define BAR_W_MAX 20
+#define BAR_SPACE 2
+
+
+typedef struct
+{
+  char		  *name;	
+  char		  *mountpoint;	
+  char		  *mtime_str;
+  char		  *mtime_short_str;
+  time_t	   mtime;
+  float		   used_space;
+  char		  *used_space_str;
+  SnapType	   type;
+  char		  *type_str;
+} Snap;
+
+
+struct TimeScalePrivate 
+{
+  GList* all_snaps;
+  GList* snaps;
+  int*	bar_x_end;
+  int   current_pos;
+  int   num_snaps;
+  char  *num_rev_string;
+  int	current_period;
+  GList *today;
+  GList *yesterday;
+  GList *this_week;
+  GList *last_week;
+  GList *this_month;
+  GList *last_month;
+  gboolean scrollbar_set;
+  gboolean key_pressed;
+  GtkWidget *darea;
+  GtkWidget *period;
+  GtkWidget *info;
+  GtkWidget *scrolled;
+  GtkWidget *label_tip;
+};
+
+enum {
+  VALUE_CHANGED,
+  LAST_SIGNAL
+};
+
+enum {
+  ALL,
+  TODAY,
+  YESTERDAY,
+  THIS_WEEK,
+  LAST_WEEK,
+  THIS_MONTH,
+  LAST_MONTH
+};
+
+enum {
+  COLUMN_INDEX,
+  COLUMN_STRING
+};
+
+
+static guint signals[LAST_SIGNAL];
+
+G_DEFINE_TYPE (TimeScale, timescale, GTK_TYPE_HBOX)
+
+#define TIMESCALE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_TIMESCALE, TimeScalePrivate))
+
+static gboolean
+timescale_expose (GtkWidget *widget,
+		  GdkEventExpose *event, TimeScale *ts);
+static gboolean
+query_tooltip (GtkWidget  *widget,
+	       gint        x,
+	       gint        y,
+	       gboolean    keyboard_tip,
+	       GtkTooltip *tooltip,
+	       gpointer    data);
+static int 
+key_pressed (GtkWidget *widget, GdkEventKey *event, TimeScale *ts);
+static void
+button_pressed (GtkWidget *widget, GdkEventButton *event, TimeScale *ts);
+
+static void print_snaps (GList *list)
+{
+  GList* tmp = list;
+  int i = 0;
+
+  while (tmp)
+    {
+      Snap *snap = (Snap*) tmp->data;
+      printf ("=-= %d =-=\nname: %s\nmountpoint: %s\nmtime: %s\nused_space: %s\n",i,
+	      snap->name, snap->mountpoint, snap->mtime_str, snap->used_space_str);
+      i++;
+      tmp = tmp->next;
+    }
+}
+
+static char * get_num_snap_string (GList *snap_list)
+{
+  goffset total = 0;
+  int i = 0;
+  GList *tmp = snap_list;
+  char *num_rev;
+
+  char *size_str = NULL;
+  
+  for (tmp; tmp; tmp = tmp->next)
+    {
+      Snap *snap = ((Snap*) tmp->data);
+      total += snap->used_space;
+      i++;
+    }
+
+  total *= 1024;
+
+  size_str = g_format_size_for_display (total);
+     
+      /* SUN_BRANDING */
+  num_rev = g_strdup_printf (_("%d %s\n%s"),
+			     i, 
+			     /* SUN_BRANDING */
+			     ngettext ("snapshot", "snapshots", i),
+			     size_str);
+  g_free (size_str);
+
+  return num_rev;
+}
+
+
+static char * get_date (GDate *date)
+{
+  return g_strdup_printf ("%d/%d/%d", g_date_get_day (date), 
+			  g_date_get_month (date),
+			  g_date_get_year (date));
+}
+
+static GList *trim_list_by_date (GList *list, int type)
+{
+  GDate then;
+  GDate now;
+  GDate range_min;
+  GDate range_max;
+  GDateWeekday weekday;
+
+  time_t time_now;
+  int diff  = 0;
+  time_now = time (NULL);
+  g_date_set_time_t (&now, time_now);
+  g_date_set_time_t (&range_min, time_now);
+  GList *return_list = NULL;
+  int days_diff = 0;
+  gboolean range = FALSE;
+
+  switch (type)
+    {
+    case TODAY:
+      days_diff = 0;
+      break;
+    case YESTERDAY:
+      days_diff = 1;
+      break;
+    case THIS_WEEK:
+      weekday = g_date_get_weekday(&now);
+      days_diff = weekday - G_DATE_MONDAY;
+      memcpy (&range_max, &range_min, sizeof (GDate));
+      g_date_subtract_days (&range_min, days_diff);
+      range = TRUE;
+      break;
+    case LAST_WEEK:
+      g_date_subtract_days (&range_min, 7);
+      weekday = g_date_get_weekday(&range_min);
+      days_diff = weekday - G_DATE_MONDAY;
+      g_date_subtract_days (&range_min, days_diff);
+      memcpy (&range_max, &range_min, sizeof (GDate));
+      g_date_add_days (&range_max, 6);
+      range = TRUE;
+      break;
+    case THIS_MONTH:
+      g_date_set_dmy (&range_min, 1, g_date_get_month (&now),
+		      g_date_get_year (&now));
+      g_date_set_time_t (&range_max, time_now);
+      range = TRUE;
+      break;
+    case LAST_MONTH:
+      g_date_subtract_months (&range_min, 1);
+      g_date_set_dmy (&range_min, 1, 
+		      g_date_get_month (&range_min),
+		      g_date_get_year (&range_min));
+      memcpy (&range_max, &range_min, sizeof (GDate));
+      g_date_add_days (&range_max, g_date_get_days_in_month (g_date_get_month (&range_min), g_date_get_year (&range_min)) - 1);
+      range = TRUE;
+      break;
+    }
+
+  while (list)
+    {
+      Snap* snap = (Snap*) list->data;
+
+      if (snap->mtime != 0)
+	{
+	  g_date_set_time_t (&then, snap->mtime);
+
+	  if (!range)
+	    {
+	      if (g_date_get_julian (&now) - g_date_get_julian (&then) == days_diff)
+		return_list = g_list_append (return_list, snap);
+	    }
+	  else
+	    {
+	      if (g_date_compare (&then, &range_min) >= 0 && g_date_compare (&then, &range_max) <= 0)
+		return_list = g_list_append (return_list, snap);
+	    }
+	}
+      list = list->next;
+    }
+  return return_list;
+}
+
+
+static void 
+free_periods (TimeScale *ts)
+{
+  if (ts->priv->today)
+    {
+      g_list_free (ts->priv->today);
+      ts->priv->today = NULL;
+    }
+  if (ts->priv->yesterday)
+    {
+      g_list_free (ts->priv->yesterday);
+      ts->priv->yesterday = NULL;
+    }
+  if (ts->priv->this_week)
+    {
+      g_list_free (ts->priv->this_week);
+      ts->priv->this_week = NULL;
+    }
+  if (ts->priv->last_week)
+    {
+      g_list_free (ts->priv->last_week);
+      ts->priv->last_week = NULL;
+    }
+  if (ts->priv->this_month)
+    {
+      g_list_free (ts->priv->this_month);
+      ts->priv->this_month = NULL;
+    }
+  if (ts->priv->last_month)
+    {
+      g_list_free (ts->priv->last_month);
+      ts->priv->last_month = NULL;
+    }
+}
+
+static GtkListStore *
+create_periods (TimeScale *ts)
+{
+  GtkTreeIter iter;
+  GtkListStore* periods = gtk_list_store_new (3, G_TYPE_INT, G_TYPE_STRING, G_TYPE_POINTER);
+
+  free_periods (ts);
+
+  gtk_list_store_append (periods, &iter);
+  gtk_list_store_set (periods, &iter, 0, ALL, 1, _("All"), 2, ts->priv->all_snaps, -1); 
+
+  ts->priv->today = trim_list_by_date (ts->priv->all_snaps, TODAY);
+  
+  if (ts->priv->today)
+    {
+      gtk_list_store_append (periods, &iter);
+      gtk_list_store_set (periods, &iter, 0, TODAY, 1, _("Today"), 2, ts->priv->today, -1); 
+    }
+  
+  ts->priv->yesterday = trim_list_by_date (ts->priv->all_snaps, YESTERDAY);
+  if (ts->priv->yesterday)
+    {
+      gtk_list_store_append (periods, &iter);
+      gtk_list_store_set (periods, &iter, 0, YESTERDAY, 1, _("Yesterday"), 2, ts->priv->yesterday, -1); 
+    }
+
+  ts->priv->this_week = trim_list_by_date (ts->priv->all_snaps, THIS_WEEK);
+  if (ts->priv->this_week)
+    {
+      gtk_list_store_append (periods, &iter);
+      gtk_list_store_set (periods, &iter, 0, THIS_WEEK, 1, _("This Week"), 2, ts->priv->this_week, -1); 
+    }
+
+  ts->priv->last_week = trim_list_by_date (ts->priv->all_snaps, LAST_WEEK);
+  if (ts->priv->last_week)
+    {
+      gtk_list_store_append (periods, &iter);
+      gtk_list_store_set (periods, &iter, 0, LAST_WEEK, 1, _("Last Week"), 2, ts->priv->last_week, -1); 
+    }
+
+  ts->priv->this_month = trim_list_by_date (ts->priv->all_snaps, THIS_MONTH);
+  if (ts->priv->this_month)
+    {
+      gtk_list_store_append (periods, &iter);
+      gtk_list_store_set (periods, &iter, 0, THIS_MONTH, 1, _("This Month"), 2, ts->priv->this_month, -1); 
+    }
+
+  ts->priv->last_month = trim_list_by_date (ts->priv->all_snaps, LAST_MONTH);
+  if (ts->priv->last_month)
+    {
+      gtk_list_store_append (periods, &iter);
+      gtk_list_store_set (periods, &iter, 0, LAST_MONTH, 1, _("Last Month"), 2, ts->priv->last_month, -1); 
+    }
+
+  return periods;
+}
+
+static void
+period_changed (GtkComboBox *combo,
+		TimeScale *ts)
+{
+  gint type;
+  GtkTreePath *path;
+  GtkTreeModel *model;
+  GtkTreeIter  iter;
+  GList *period;
+
+  if (!gtk_combo_box_get_active_iter (combo, &iter))
+    return;
+
+  model = gtk_combo_box_get_model (combo);
+
+  gtk_tree_model_get (model, &iter, 0, &type, 2, &period, -1);
+
+  if (ts->priv->current_period == type)
+    return;
+
+  ts->priv->current_period = type;
+
+  ts->priv->snaps = period;
+  
+  ts->priv->num_snaps = g_list_length (ts->priv->snaps);
+  if (ts->priv->bar_x_end)
+    g_free (ts->priv->bar_x_end);
+  
+  ts->priv->bar_x_end = g_new (int, g_list_length (ts->priv->snaps));
+
+  ts->priv->current_pos = -1;
+  
+  if (ts->priv->num_rev_string)
+    g_free (ts->priv->num_rev_string);
+
+  ts->priv->num_rev_string = get_num_snap_string (ts->priv->snaps);
+  gtk_label_set_label (GTK_LABEL (ts->priv->info), ts->priv->num_rev_string);
+
+  gtk_widget_set_size_request (ts->priv->darea, ((BAR_SPACE + BAR_W_MAX ) * ts->priv->num_snaps) + PADDING * 2, 60);
+
+  gtk_widget_queue_draw (ts->priv->darea);
+}
+
+static void
+timescale_init (TimeScale *ts)
+{
+  GtkWidget *vbox;
+  GtkCellRenderer *renderer;
+
+  ts->priv = TIMESCALE_GET_PRIVATE (ts);
+  ts->priv->snaps = NULL;
+  ts->priv->all_snaps = NULL;
+  ts->priv->num_snaps = 0;
+  ts->priv->bar_x_end = NULL;
+  ts->priv->current_pos = 0;
+  ts->priv->num_rev_string = NULL;
+  ts->priv->current_period = ALL;
+  ts->priv->today = NULL;
+  ts->priv->yesterday = NULL;
+  ts->priv->this_week = NULL;
+  ts->priv->last_week = NULL;
+  ts->priv->this_month = NULL;
+  ts->priv->last_month = NULL;
+  ts->priv->key_pressed = FALSE;
+
+  gtk_box_set_homogeneous (GTK_BOX (ts), FALSE);
+
+  /* setup drawing area */
+
+  ts->priv->darea = gtk_drawing_area_new (); 
+
+  g_signal_connect(ts->priv->darea, "expose-event",
+		   G_CALLBACK(timescale_expose), ts);
+
+  g_signal_connect (ts->priv->darea, "query-tooltip",
+		    G_CALLBACK (query_tooltip), ts);
+
+  g_signal_connect(ts->priv->darea, "key-press-event",
+      G_CALLBACK(key_pressed), ts);
+  g_signal_connect(ts->priv->darea, "button_press_event",
+      G_CALLBACK(button_pressed), ts);
+  gtk_widget_set_can_focus (GTK_WIDGET (ts->priv->darea), TRUE);
+  gtk_widget_add_events (GTK_WIDGET (ts->priv->darea), GDK_BUTTON_PRESS_MASK | GDK_KEY_PRESS_MASK);
+  g_object_set (G_OBJECT (ts->priv->darea), "has-tooltip", TRUE, NULL);
+  gtk_widget_set_size_request (GTK_WIDGET (ts->priv->darea), -1, 60);
+
+  ts->priv->scrolled = gtk_scrolled_window_new (NULL, NULL);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (ts->priv->scrolled),
+				  GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER);
+  gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (ts->priv->scrolled), 
+					 ts->priv->darea);
+  gtk_viewport_set_shadow_type (GTK_VIEWPORT (gtk_bin_get_child (GTK_BIN (ts->priv->scrolled))), GTK_SHADOW_NONE);
+  gtk_widget_show (ts->priv->scrolled);
+
+  ts->priv->label_tip = gtk_label_new ("Hello");
+  gtk_widget_set_name (ts->priv->label_tip, "gtk-tooltip");
+  g_object_ref_sink (ts->priv->label_tip);
+  gtk_label_set_justify (GTK_LABEL (ts->priv->label_tip), GTK_JUSTIFY_CENTER);
+
+  /* setup period combo and snap info */
+
+  vbox = gtk_vbox_new (FALSE, 5);
+  ts->priv->period = gtk_combo_box_new ();
+  renderer = gtk_cell_renderer_text_new ();
+  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (ts->priv->period),
+			      renderer,
+			      TRUE);
+  gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (ts->priv->period), renderer,
+				  "text", 1,
+				  NULL);
+  g_signal_connect (ts->priv->period, "changed", G_CALLBACK (period_changed), ts);
+
+  ts->priv->info = gtk_label_new ("info\ninfo");
+  gtk_label_set_justify (GTK_LABEL (ts->priv->info), GTK_JUSTIFY_CENTER);
+  gtk_box_pack_start (GTK_BOX (vbox), ts->priv->period, FALSE, FALSE, 5);
+  gtk_box_pack_end (GTK_BOX (vbox), ts->priv->info, FALSE, FALSE, 5);
+
+  /* setup container */
+
+  gtk_box_pack_start (GTK_BOX (ts), vbox, FALSE, FALSE, 0);
+  gtk_box_pack_start (GTK_BOX (ts), ts->priv->scrolled, TRUE, TRUE, 0);
+
+  gtk_widget_set_can_focus (GTK_WIDGET (ts), TRUE);
+  gtk_widget_show_all (GTK_WIDGET (ts));
+}
+
+static float
+get_max_snap_size (GList *snaps)
+{
+  Snap *snap;
+  float max_size = 0;
+  while (snaps)
+    {
+      GList *next = snaps->next;
+      snap = (Snap*) snaps->data;
+      if (snap->used_space > max_size)
+	max_size = snap->used_space;
+      snaps = next;
+    }
+  return max_size;
+}
+
+
+static Snap*
+get_now_snap (TimeScale* ts)
+{
+  Snap *last_snap;
+  last_snap = g_new0 (Snap, 1);
+  last_snap->name = g_strdup (_("Now"));
+  last_snap->mountpoint = g_strdup (_("None"));
+  last_snap->mtime_str = g_strdup (_("Now"));
+  last_snap->mtime_short_str = g_strdup (_("Now"));
+  last_snap->used_space_str = g_strdup (_("-"));
+  last_snap->used_space = 0.0;
+  last_snap->type = NOW;
+  last_snap->type_str = g_strdup (_("Current Directory"));
+  return last_snap;
+}
+
+static char *get_type_str (SnapType type)
+{
+  switch (type)
+    {
+    case LOCAL_AUTOMATIC:
+      return g_strdup (_("Automatic Snapshot"));
+      break;
+    case LOCAL_MANUAL:
+      return g_strdup (_("Manual Snapshot"));
+      break;
+    case REMOTE_AUTOMATIC:
+      return g_strdup (_("Automatic Remote Backup"));
+      break;
+    case REMOTE_MANUAL:
+      return g_strdup (_("Manual Remote Backup"));
+      break;
+    default:
+      break;
+    }
+  return NULL;
+}
+
+static SnapType 
+get_type (ZfsDataSet* snap)
+{
+  if (snap->type)
+    {
+      if (strstr (snap->name, "zfs-auto-snap"))
+	return LOCAL_AUTOMATIC;
+      else
+	return LOCAL_MANUAL;
+    }
+  else
+    {
+      if (strstr (snap->name, "zfs-auto-snap"))
+	return REMOTE_AUTOMATIC;
+      else
+	return REMOTE_MANUAL;
+    }
+}
+
+static GList *
+copy_zfs_list (GList *list)
+{
+  ZfsDataSet *snap;
+  GList *new_list = NULL;
+  Snap *ts_shot;
+  GList *tmp_list = list;
+  while (tmp_list)
+    {
+      snap = (ZfsDataSet*) tmp_list->data;
+      ts_shot = g_new0 (Snap, 1);
+      ts_shot->name = g_strdup (snap->name);
+      ts_shot->mountpoint = g_strdup (snap->mountpoint);
+      ts_shot->mtime_str = g_strdup (snap->mtime_str);
+      ts_shot->mtime_short_str = nautilus_date_as_string (snap->mtime, TRUE);
+      ts_shot->used_space_str = g_strdup (snap->used_space_str); 
+      ts_shot->used_space = snap->used_space;
+      ts_shot->mtime = snap->mtime;
+      ts_shot->type = get_type (snap);
+      ts_shot->type_str = get_type_str (ts_shot->type);
+      new_list = g_list_append (new_list, ts_shot);
+      tmp_list = tmp_list->next;
+    }
+  return new_list;
+}
+
+static void 
+free_snap (Snap *snap)
+{
+  if (snap->name)
+    g_free (snap->name);
+  if (snap->mountpoint)
+    g_free (snap->mountpoint);
+  if (snap->mtime_str)
+    g_free (snap->mtime_str);
+  if (snap->mtime_short_str)
+    g_free (snap->mtime_short_str);
+  if (snap->used_space_str)
+    g_free (snap->used_space_str); 
+  if (snap->type_str)
+    g_free (snap->type_str); 
+
+  g_free (snap);
+}
+
+static void 
+free_snap_list (GList *list)
+{
+  GList *tmp_list = list;
+  while (tmp_list)
+    {
+      free_snap ((Snap*) tmp_list->data);
+      tmp_list = tmp_list->next;
+    }
+}
+
+
+void 
+timescale_set_snapshots (TimeScale* ts, GList *list, int init_position)
+{
+  if (ts->priv->bar_x_end)
+    g_free (ts->priv->bar_x_end);
+
+  if (ts->priv->num_rev_string)
+    g_free (ts->priv->num_rev_string);
+
+  if (ts->priv->all_snaps)
+    free_snap_list (ts->priv->all_snaps);
+  
+  ts->priv->all_snaps = copy_zfs_list (list);
+  ts->priv->all_snaps = g_list_append (ts->priv->all_snaps, get_now_snap(ts));
+  ts->priv->snaps = ts->priv->all_snaps;
+  ts->priv->num_snaps = g_list_length (ts->priv->snaps);
+
+  ts->priv->bar_x_end = g_new (int, g_list_length (ts->priv->snaps));
+  ts->priv->current_pos = ts->priv->num_snaps - 1;
+
+  if (init_position >= 0 && init_position <= ts->priv->num_snaps - 1)
+    ts->priv->current_pos = init_position;
+
+  ts->priv->num_rev_string = get_num_snap_string (ts->priv->snaps);
+
+  gtk_label_set_label (GTK_LABEL (ts->priv->info), ts->priv->num_rev_string);
+  ts->priv->current_period = ALL;
+
+  gtk_combo_box_set_model (GTK_COMBO_BOX (ts->priv->period), GTK_TREE_MODEL (create_periods (ts)));
+  gtk_combo_box_set_active (GTK_COMBO_BOX (ts->priv->period), ALL);
+  
+  gtk_widget_set_size_request (ts->priv->darea, ((BAR_SPACE + BAR_W_MAX) * ts->priv->num_snaps) + PADDING * 2, 60);
+  ts->priv->scrollbar_set = FALSE;
+}
+
+GtkWidget*
+timescale_new ()
+{
+  return g_object_new (TYPE_TIMESCALE, NULL);
+}
+
+static void draw_type (cairo_t *cr, int x_c, int y_c, int w, SnapType type)
+{
+  int x = x_c - w/2;
+  int y = y_c - w/2;
+
+  
+
+ switch (type)
+    {
+    case LOCAL_MANUAL:
+	cairo_move_to (cr,x,y_c);
+	cairo_line_to (cr,x+w/2,y_c-w/2); 
+	cairo_line_to (cr,x+w,y_c); 
+	/*y = y_c - w/4;
+	cairo_rectangle (cr, x, y, w, w/2);*/
+      break;
+    case LOCAL_AUTOMATIC:
+	cairo_arc (cr, x_c, y_c, w/2, M_PI, M_PI*2);
+      break;
+    case REMOTE_MANUAL:
+	/* cairo_rectangle (cr, x, y, w, w); */
+	cairo_move_to (cr,x,y_c);
+	cairo_line_to (cr,x+w/2,y_c+w/2); 
+	cairo_line_to (cr,x+w,y_c); 
+	cairo_line_to (cr,x+w/2,y_c-w/2); 
+      break;
+    case REMOTE_AUTOMATIC:
+	cairo_arc (cr, x_c, y_c, w/2, 0.0, M_PI*2);
+      break;
+    default:
+      break;
+    }
+}
+
+static void draw_rounded_bar (cairo_t *cr, int x, int y, double w, double h, int r)
+{
+    /* bottom y instead of top */
+    y -= h;
+
+    if (h == 0 || h < (w / 2) + r)
+      {
+	y += h;
+	cairo_arc (cr, x+(w/2), y+.5, w/2, M_PI, M_PI*2);
+	cairo_line_to (cr,x,y+.5);
+	return;
+      }
+
+    /*    A****BQ
+         H      C
+         *      *
+         G      D
+	  F****E */
+
+
+    cairo_arc (cr, x+(w/2), y+(w/2), w/2, M_PI, M_PI*2); /* arc from H to C */
+    cairo_line_to (cr,x+w,y+h-r);		     /* Move to D */
+    cairo_curve_to(cr, x+w,y+h,x+w,y+h,x+w-r,y+h);   /* Curve to E */
+    cairo_line_to(cr, x+r,y+h);			     /* Line to F */
+    cairo_curve_to(cr, x,y+h,x,y+h,x,y+h-r);	     /* Curve to G */
+    cairo_line_to(cr, x,y+(w/2));			     /* Line to H */
+
+}
+
+
+
+static void draw_rounded_rec (cairo_t *cr, int x, int y, double w, double h, int r)
+{
+    /* bottom y instead of top */
+    y -= h;
+
+    if (h == 0)
+      {
+	cairo_set_line_width (cr, 1); 
+	cairo_move_to (cr,x,y - .5);
+	cairo_line_to (cr, x + w, y -.5);
+	return;
+      }
+
+    if (h < r * 2)
+      r = h / 2;
+
+    /*    A****BQ
+         H      C
+         *      *
+         G      D
+          F****E */
+
+    cairo_move_to (cr,x+r,y);			     /* Move to A */
+    cairo_line_to (cr,x+w-r,y);                      /* Straight line to B */
+    cairo_curve_to (cr,x+w,y,x+w,y,x+w,y+r);         /* Curve to C, Control points are both at Q */
+    cairo_line_to (cr,x+w,y+h-r);		     /* Move to D */
+    cairo_curve_to(cr, x+w,y+h,x+w,y+h,x+w-r,y+h);   /* Curve to E */
+    cairo_line_to(cr, x+r,y+h);			     /* Line to F */
+    cairo_curve_to(cr, x,y+h,x,y+h,x,y+h-r);	     /* Curve to G */
+    cairo_line_to(cr, x,y+r);			     /* Line to H */
+    cairo_curve_to(cr, x,y,x,y,x+r,y);		     /*  Curve to A */
+}
+
+static void 
+set_cr_color (GtkWidget *widget, cairo_t* cr, SnapType type, double alpha)
+{
+    GtkStyle *style = gtk_widget_get_style(widget);
+    switch (type)
+    {
+    case LOCAL_MANUAL:
+    case REMOTE_MANUAL:
+      gdk_cairo_set_source_color (cr, &style->dark[GTK_STATE_SELECTED]);
+      gdk_cairo_set_source_color (cr, &style->dark[GTK_STATE_SELECTED]);
+      break;
+    case LOCAL_AUTOMATIC:
+    case REMOTE_AUTOMATIC:
+      gdk_cairo_set_source_color (cr, &style->light[GTK_STATE_SELECTED]);
+      break;
+    case NOW:
+      gdk_cairo_set_source_color (cr, &style->black);
+      break;
+    default:
+      break;
+    }
+}
+
+int get_snap_index_from_coord (TimeScale* ts, gdouble x, gdouble y)
+{
+  int i;
+
+  for (i = 0; i < ts->priv->num_snaps; i++)
+    {
+      if (x < ts->priv->bar_x_end[i])
+	return i;
+    }
+  return -1;
+}
+
+static gboolean
+timescale_expose (GtkWidget *widget,
+		  GdkEventExpose *event, TimeScale* ts)
+{
+  PangoContext *context;
+  PangoFontMetrics *metrics;
+  PangoRectangle logical_rect;
+  gint ascent, descent;
+  cairo_t *cr = gdk_cairo_create (gtk_widget_get_window(widget));
+  int i = 0;
+  double x;
+  int y;
+  int selected_x = -1;
+  int remaining_timeline_space;
+  int remaining_x_start;
+  int remaining_x_end;
+  int bar_space = BAR_SPACE;
+  int bar_w = BAR_W_MAX;
+  int line_padding = 3;
+  float bar_max_h_inc;
+  float bar_max_h;
+  int last_bar_x;
+  int line_height = 0;
+  int timeline_line_height = 0;
+  float max_size = 0;
+  GList *view_snaps = NULL;
+  int num_view_snaps = 0;
+  PangoLayout *layout = pango_cairo_create_layout (cr);
+  Snap *tmp_snap = NULL;
+  gboolean space_left = TRUE;
+  PangoFontDescription *timeline_font = NULL;
+  GtkStyle *style = gtk_widget_get_style(widget);
+  GtkAllocation allocation;
+
+  gtk_widget_get_allocation(widget, &allocation);
+
+  if (gtk_widget_has_focus (widget))
+      gtk_paint_focus (style, cr, gtk_widget_get_state (widget),
+		       widget, NULL,
+		       0, 0,
+		       allocation.width-1, allocation.height-1);
+
+  if (!ts->priv->snaps)
+    goto end;
+
+  /* smaller font for timeline */
+
+  timeline_font = pango_font_description_copy_static(style->font_desc);
+  pango_font_description_set_size (timeline_font, pango_font_description_get_size (timeline_font) - (PANGO_SCALE*2));
+
+  /* determine space needed for 2 lines of text + padding with 
+   * current widget->style->font_desc 
+   * and widget->style->font_desc - 1*/
+
+  context = gtk_widget_get_pango_context (widget);
+  metrics = pango_context_get_metrics (context, style->font_desc,
+				       pango_context_get_language (context));
+  ascent = pango_font_metrics_get_ascent (metrics);
+  descent = pango_font_metrics_get_descent (metrics);
+  pango_font_metrics_unref (metrics);
+
+  line_height = PANGO_PIXELS (ascent + descent);
+
+  metrics = pango_context_get_metrics (context, timeline_font,
+				       pango_context_get_language (context));
+  ascent = pango_font_metrics_get_ascent (metrics);
+  descent = pango_font_metrics_get_descent (metrics);
+  pango_font_metrics_unref (metrics);
+
+  timeline_line_height = PANGO_PIXELS (ascent + descent);
+
+
+  x = PADDING;
+  bar_max_h = allocation.height - ((line_height + timeline_line_height) + PADDING * 4);
+  y =  allocation.height - (line_height + (PADDING * 2));
+
+  num_view_snaps = ts->priv->num_snaps;
+  view_snaps = ts->priv->snaps;
+
+  max_size = log ((float)get_max_snap_size (view_snaps));
+
+  bar_max_h_inc =  max_size / bar_max_h;
+
+  if (!ts->priv->scrollbar_set)
+    {
+      GtkAdjustment *adj;
+      adj = gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (ts->priv->scrolled));
+      gtk_adjustment_set_value (adj, gtk_adjustment_get_upper(adj) - gtk_adjustment_get_page_size(adj));
+      gtk_adjustment_set_step_increment(adj, BAR_W_MAX + BAR_SPACE);
+      gtk_scrolled_window_set_hadjustment (GTK_SCROLLED_WINDOW (ts->priv->scrolled), adj);
+      ts->priv->scrollbar_set = TRUE;
+    }
+
+  /* draw the bars */
+	    
+  cairo_set_line_width (cr, 1); 
+
+  for (i = 0; i < num_view_snaps; i++)
+    {
+      tmp_snap = g_list_nth_data (view_snaps, i);
+      int rounded_radius = ROUNDED_RADIUS;
+      int height = 0;
+      gboolean draw_bar = TRUE;
+      double alpha = 1.0;
+
+      if (tmp_snap->used_space != 0)
+	height = (int) log (tmp_snap->used_space) / bar_max_h_inc;
+
+      /*printf ("drawing %d height %d size %f log of size %f\n", i, 
+	      height, 
+	      tmp_snap->used_space, log (tmp_snap->used_space));*/
+
+      if (height == 0 & tmp_snap->used_space != 0)
+	height = 1;
+
+      if (tmp_snap->type == REMOTE_AUTOMATIC ||
+	  tmp_snap->type == REMOTE_MANUAL)
+	height = bar_max_h - bar_max_h_inc; /* placeholder until we get rsync size */
+
+      if (height < ROUNDED_RADIUS) 
+	    height = 0;
+
+      /* printf ("height %d name %s size %s\n", height, tmp_snap->name, tmp_snap->used_space_str);  */
+
+      if (i == ts->priv->current_pos)
+	{
+
+	  cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 1);
+	  draw_rounded_rec (cr, x-1, y+2, bar_w+2, bar_max_h+8, ROUNDED_RADIUS);
+
+	  cairo_fill (cr); 
+	  cairo_stroke(cr);
+
+	  alpha = 0.5;
+	  selected_x = x-1 + ((bar_w+2) / 2);
+  
+	  if (tmp_snap->type != NOW)
+	    {
+	      char *selected_time_size = g_strdup_printf ("%s - %s",
+							  tmp_snap->mtime_str, 
+							  tmp_snap->used_space_str);
+	      gdk_cairo_set_source_color (cr, style->text);
+	      pango_layout_set_font_description (layout, style->font_desc);
+	      pango_layout_set_text (layout, selected_time_size, -1);
+	      g_free (selected_time_size);
+	    }
+	  else
+	      pango_layout_set_text (layout, tmp_snap->mtime_str, -1);
+	}
+
+      cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.8);
+
+      ts->priv->bar_x_end[i] = x + bar_w;
+
+      if (draw_bar)
+	{
+	  int tmp_y = y;
+	  float tmp_w = bar_w;
+	  set_cr_color (widget, cr, tmp_snap->type, 1.0);
+	  if (tmp_snap->type == LOCAL_AUTOMATIC || tmp_snap->type == LOCAL_MANUAL)
+	    {
+	      tmp_y -= 1;
+	      tmp_w -= 1;
+	    }
+
+	  if (tmp_snap->type == LOCAL_AUTOMATIC || tmp_snap->type == REMOTE_AUTOMATIC)
+	      draw_rounded_bar (cr, x, tmp_y, tmp_w, height, rounded_radius);
+	  else if (tmp_snap->type == LOCAL_MANUAL || tmp_snap->type == REMOTE_MANUAL)
+	      draw_rounded_rec (cr, x, tmp_y, tmp_w, height, rounded_radius);
+	  else /* Now Shape */
+	    draw_type (cr, (x + ((bar_w+bar_space)/2)) - .5, y - (bar_max_h/2), bar_w - 4, REMOTE_MANUAL);
+
+	  if (tmp_snap->type == REMOTE_MANUAL || tmp_snap->type == REMOTE_AUTOMATIC || tmp_snap->type == NOW)
+	    cairo_fill (cr);
+	}
+      
+      cairo_stroke(cr);
+
+      x += bar_w + bar_space;
+    }
+
+  last_bar_x = x;
+
+  /* ensure selected bar is visible on key press when scrollbar is enabled */
+
+  if (ts->priv->current_pos != -1 && ts->priv->key_pressed)
+    {
+
+      GtkAdjustment *adj;
+      adj = gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (ts->priv->scrolled));
+      ts->priv->key_pressed = FALSE;
+
+      if (gtk_adjustment_get_value(adj) > selected_x)
+	{
+	  gtk_adjustment_set_value (adj, selected_x - BAR_W_MAX);
+	  gtk_scrolled_window_set_hadjustment (GTK_SCROLLED_WINDOW (ts->priv->scrolled), adj);
+	}
+      if (gtk_adjustment_get_value(adj) + gtk_adjustment_get_page_size(adj) < selected_x)
+	{
+	  gtk_adjustment_set_value (adj, (selected_x + BAR_W_MAX) - gtk_adjustment_get_page_size(adj));
+	  gtk_scrolled_window_set_hadjustment (GTK_SCROLLED_WINDOW (ts->priv->scrolled), adj);
+	}
+    }
+
+  pango_layout_set_font_description (layout, style->font_desc);
+
+  /* try to center the selected text */
+
+  pango_layout_get_pixel_extents (layout,NULL, &logical_rect);
+
+  if (ts->priv->current_pos != -1 && selected_x != -1)
+    {
+
+      int right_space = last_bar_x - selected_x;
+
+      if (logical_rect.width /2 > selected_x)
+	/* no space on the left, left align */
+	selected_x = PADDING;
+      else if (logical_rect.width /2 > right_space) 
+	/* no space on the right, right align */
+	selected_x = last_bar_x - logical_rect.width;
+      else
+	selected_x -= logical_rect.width /2;
+
+      if (selected_x < 0)
+	selected_x = PADDING;
+
+      /* draw background */
+      cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 1);
+      draw_rounded_rec (cr, selected_x-2, line_height + 3 , logical_rect.width + 4, line_height+1, ROUNDED_RADIUS);
+      cairo_fill (cr);
+      cairo_stroke(cr);
+
+      /* then selected text */
+      gdk_cairo_set_source_color (cr, style->text);
+      cairo_move_to(cr, selected_x, PADDING);
+      pango_cairo_show_layout (cr, layout);
+    }
+
+  /* timeline */
+
+  /* what to do  
+   * try to draw oldest 
+   * then "now" first
+   * then in between dates
+   * draw additional is possible starting with newest first */
+
+  x = PADDING;
+
+
+  /* Can the oldest time fit ? */
+  tmp_snap = g_list_nth_data (view_snaps, 0);
+  pango_layout_set_text (layout, tmp_snap->mtime_short_str, -1);
+  pango_layout_set_font_description (layout, timeline_font);
+  pango_layout_get_pixel_extents (layout,NULL, &logical_rect);
+
+  if (logical_rect.width > allocation.width)
+    goto end;
+
+  /* draw anchor line */
+
+  x += bar_w/2 + .5;
+
+  cairo_set_line_width (cr, 1);
+  gdk_cairo_set_source_color (cr, style->text_aa);
+  cairo_move_to (cr, x, allocation.height - ((line_height + PADDING*2)-1));
+  cairo_line_to (cr, x, allocation.height - (line_height/2 + PADDING)-.5);
+  cairo_line_to (cr, x+2.5, allocation.height - (line_height/2 + PADDING)-.5);
+  cairo_stroke(cr);
+
+  x += 3;
+
+  gdk_cairo_set_source_color (cr, style->text_aa);
+  cairo_move_to(cr, x, allocation.height - (line_height + PADDING));
+  pango_cairo_show_layout (cr, layout);
+
+  remaining_timeline_space = last_bar_x - (x + logical_rect.width);
+
+  remaining_x_start = x + logical_rect.width;
+
+  /* try to draw last item */
+
+  tmp_snap = g_list_nth_data (view_snaps, num_view_snaps-1);
+  pango_layout_set_text (layout, tmp_snap->mtime_short_str, -1);
+  pango_layout_get_pixel_extents (layout,NULL, &logical_rect);
+
+  if (remaining_timeline_space < (logical_rect.width + bar_w))
+    goto end;
+
+  remaining_timeline_space -= logical_rect.width + bar_w;
+
+  x = last_bar_x;
+
+
+  x -= bar_space + bar_w/2 + 0.5;
+
+  cairo_move_to (cr, x, allocation.height - ((line_height + PADDING*2)-2));
+  cairo_line_to (cr, x, allocation.height - (line_height/2 + PADDING)-.5);
+  cairo_line_to (cr, x-2.5, allocation.height - (line_height/2 + PADDING)-.5);
+  cairo_stroke(cr);
+
+  cairo_move_to(cr, x - (logical_rect.width + 3.5),
+		allocation.height - (line_height + PADDING));
+  pango_cairo_show_layout (cr, layout);
+
+  remaining_x_end = x - (logical_rect.width + 3.5);
+
+  /* now find the next bar that we can to the timeline and loop */
+
+
+  while (space_left)
+    {
+      int bar = get_snap_index_from_coord (ts, remaining_x_start, 0);
+      /* get the next snap */
+      bar++;
+      if (bar >= num_view_snaps)
+	goto end;
+
+      tmp_snap = g_list_nth_data (view_snaps, bar);
+      pango_layout_set_text (layout, tmp_snap->mtime_short_str, -1);
+
+      pango_layout_get_pixel_extents (layout,NULL, &logical_rect);
+
+      if (remaining_timeline_space < logical_rect.width + 4)
+	goto end;
+
+      /* get middle x coord of current bar */
+
+      x = PADDING + ((bar_w + bar_space) * bar) + bar_w / 2;
+
+      if ( x + 4 + logical_rect.width > remaining_x_end)
+	goto end;
+
+      /* draw anchor and text */
+      x += 0.5;
+
+      cairo_move_to (cr, x, allocation.height - ((line_height + PADDING*2)-1));
+      cairo_line_to (cr, x, allocation.height - (line_height/2 + PADDING)-.5);
+      cairo_line_to (cr, x+2.5, allocation.height - (line_height/2 + PADDING)-.5);
+      cairo_stroke(cr);
+
+      x += 3;
+
+      cairo_move_to(cr, x, allocation.height - (line_height + PADDING));
+      pango_cairo_show_layout (cr, layout);
+
+      remaining_x_start = x + logical_rect.width;
+
+      remaining_timeline_space = remaining_x_end - remaining_x_start;
+
+      if (remaining_timeline_space <= 0)
+	space_left = FALSE;
+    }
+end:     
+  if (timeline_font)
+    pango_font_description_free(timeline_font);
+  cairo_destroy(cr);
+
+  return FALSE;
+}
+
+static int 
+key_pressed (GtkWidget *widget, GdkEventKey *event, TimeScale* ts)
+{
+   switch (event->keyval)
+    {
+    case GDK_KEY_KP_Left:
+    case GDK_KEY_KP_Up:
+    case GDK_KEY_Left:
+    case GDK_KEY_Up:
+      
+      if (ts->priv->current_pos >= 1)
+	{
+	  ts->priv->current_pos -= 1;
+	  gtk_widget_queue_draw (widget);
+	  ts->priv->key_pressed = TRUE;
+	  g_signal_emit (ts, signals[VALUE_CHANGED], 0);
+	  /* printf ("key_pressed back %d\n", ts->priv->current_pos); */
+	}
+      return TRUE;
+    case GDK_KEY_KP_Right:
+    case GDK_KEY_KP_Down:
+    case GDK_KEY_Right:
+    case GDK_KEY_Down:
+      if (ts->priv->current_pos <= ts->priv->num_snaps - 2)
+	{
+	  ts->priv->current_pos += 1;
+	  gtk_widget_queue_draw (widget);
+	  ts->priv->key_pressed = TRUE;
+	  g_signal_emit (ts, signals[VALUE_CHANGED], 0);
+	  /* printf ("key_pressed forward %d\n", ts->priv->current_pos); */
+	}
+      return TRUE;
+
+    default:
+      return FALSE;
+    }
+}
+
+int timescale_get_position (TimeScale* ts)
+{
+  /* translate into all_snaps position */
+  gconstpointer data;
+  data = g_list_nth_data (ts->priv->snaps, ts->priv->current_pos);
+  return g_list_index (ts->priv->all_snaps, data);
+}
+
+static int match_func (ZfsDataSet *set, char *dir)
+{
+  return strcmp (set->mountpoint, dir);
+}
+
+void 
+timescale_set_position (TimeScale* ts, char *mountpoint) 
+{
+  gboolean redraw = FALSE;
+  int num_snaps = g_list_length (ts->priv->all_snaps);
+    if (mountpoint)
+      {
+	int pos;
+	GList* match = NULL;
+	match = g_list_find_custom (ts->priv->all_snaps, mountpoint, (GCompareFunc)match_func);
+	pos = g_list_index (ts->priv->all_snaps, match->data);
+	if (pos != -1 && ts->priv->current_pos != pos)
+	  {
+	    redraw = TRUE;
+	    ts->priv->current_pos = pos;
+	  }
+      }
+    else
+      { /* Now special case */
+	if (ts->priv->current_pos != num_snaps - 1)
+	  {
+	    redraw = TRUE;
+	    ts->priv->current_pos = num_snaps - 1;
+	  }
+      }
+
+  if (redraw)
+      gtk_widget_queue_draw (GTK_WIDGET (ts));
+}
+
+static void 
+button_pressed (GtkWidget *widget, GdkEventButton *event, TimeScale* ts)
+{
+  int new_pos;
+
+  gtk_widget_grab_focus (widget);
+  new_pos = get_snap_index_from_coord (ts, event->x, event->y);
+
+  if (new_pos == -1)
+    return;
+
+  if (new_pos != ts->priv->current_pos)
+    {
+      ts->priv->current_pos = new_pos;
+      /* printf ("button_pressed (%g,%g) selected %d\n", event->x, event->y, ts->priv->current_pos); */
+      g_signal_emit (ts, signals[VALUE_CHANGED], 0);
+      gtk_widget_queue_draw (widget);
+    }
+}
+
+static gboolean
+query_tooltip (GtkWidget  *widget,
+	       gint        x,
+	       gint        y,
+	       gboolean    keyboard_tip,
+	       GtkTooltip *tooltip,
+	       gpointer    data)
+{
+  static gboolean set = FALSE;
+  static int old_pos = -1;
+  TimeScale* ts = TIMESCALE (data);
+  int new_pos = get_snap_index_from_coord (ts, x, y);
+  /* printf ("in query_tooltip new_pos %d total %d num_snap %d\n", new_pos, g_list_length (ts->priv->snaps), ts->priv->num_snaps); */
+  Snap *tmp_snap = NULL;
+  char *tip = NULL;
+
+  if (new_pos == -1)
+    return FALSE;
+
+  if (new_pos != old_pos)
+    {
+      old_pos = new_pos;
+      return FALSE;
+    }
+
+  if (new_pos >= ts->priv->num_snaps)
+    return FALSE;
+
+  tmp_snap = g_list_nth_data (ts->priv->snaps, new_pos);
+
+  tip = g_strdup_printf ("%s\nCreated: %s\nSize: %s\nName: %s", tmp_snap->type_str, tmp_snap->mtime_str, tmp_snap->used_space_str, tmp_snap->name);
+  gtk_label_set_text (GTK_LABEL(ts->priv->label_tip), tip);
+  gtk_tooltip_set_custom (tooltip, ts->priv->label_tip);
+  g_free (tip);
+  return TRUE;
+}
+
+static void
+timescale_class_init (TimeScaleClass *class)
+{
+  GtkWidgetClass *widget_class;
+  GtkScaleClass *scale_class;
+  GObjectClass *object_class;
+	
+  object_class = G_OBJECT_CLASS (class);
+  g_type_class_add_private (class, sizeof (TimeScalePrivate));
+  
+  widget_class = GTK_WIDGET_CLASS (class);
+
+  signals[VALUE_CHANGED] =
+    g_signal_new ("value-changed",
+                  G_TYPE_FROM_CLASS (object_class),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (TimeScaleClass, value_changed),
+                  NULL, NULL,
+                  g_cclosure_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
+}
+
diff -Nrup -x '*.orig' -x '*.rej' -x '*.*~' ../SUNWgnome-file-mgr-2.30.0-b4/nautilus-2.30.1/src/timescale.h nautilus-2.30.1/src/timescale.h
--- ../SUNWgnome-file-mgr-2.30.0-b4/nautilus-2.30.1/src/timescale.h	1970-01-01 01:00:00.000000000 +0100
+++ nautilus-2.30.1/src/timescale.h	2010-05-14 17:16:39.569612048 +0200
@@ -0,0 +1,58 @@
+#ifndef __TIMESCALE_H__
+#define __TIMESCALE_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+
+
+G_BEGIN_DECLS
+
+#define TYPE_TIMESCALE            (timescale_get_type ())
+#define TIMESCALE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_TIMESCALE, TimeScale))
+#define TIMESCALE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_TIMESCALE, TimeScaleClass))
+#define IS_TIMESCALE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_TIMESCALE))
+#define IS_TIMESCALE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_TIMESCALE))
+#define TIMESCALE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_TIMESCALE, TimeScaleClass))
+
+
+typedef struct _TimeScale       TimeScale;
+typedef struct _TimeScaleClass  TimeScaleClass;
+typedef struct TimeScalePrivate TimeScalePrivate;
+
+struct _TimeScale
+{
+  GtkHBox hbox;
+  TimeScalePrivate *priv;
+};
+
+struct _TimeScaleClass
+{
+  GtkHBoxClass parent_class;
+  void (* value_changed)    (TimeScale *timescale);
+
+};
+
+
+GType      timescale_get_type       (void) G_GNUC_CONST;
+GtkWidget* timescale_new            ();
+void	   timescale_set_snapshots (TimeScale* ts, GList *list, int init_position);
+int	   timescale_get_position   (TimeScale* ts);
+void	   timescale_set_position   (TimeScale* ts, char *mountpoint);
+
+
+#define ROUNDED_RADIUS 6
+#define PADDING 3  
+
+typedef enum {
+  LOCAL_MANUAL,
+  LOCAL_AUTOMATIC,
+  REMOTE_MANUAL,
+  REMOTE_AUTOMATIC,
+  NOW
+} SnapType;
+
+
+G_END_DECLS
+
+#endif /* __TIMESCALE_H__ */
--- nautilus-3.1.3/src/nautilus-toolbar-ui.xml.orig	2011-04-04 19:01:24.000000000 +0100
+++ nautilus-3.1.3/src/nautilus-toolbar-ui.xml	2011-07-25 09:50:58.998044977 +0100
@@ -2,6 +2,7 @@
 <toolbar name="Toolbar">
 	<toolitem name="Back" action="Back"/>
 	<toolitem name="Forward" action="Forward"/>
+	<toolitem name="Restore" action="Restore"/>
         <toolitem name="Search" action="Search"/>
 </toolbar>
-</ui>
\ No newline at end of file
+</ui>
