Blob Blame History Raw
From 6c890a95222228d3773fb6efe1f98f31f1102540 Mon Sep 17 00:00:00 2001
From: Michael Webster <miketwebster@gmail.com>
Date: Sun, 8 Jun 2014 16:34:11 -0400
Subject: [PATCH 3/3] Refactor bookmarks code a bit from upstream, specifically
 fixes #627

Adds some initial work for displaying symbolic icons for bookmarks (like
in the sidebar) but no actual implementation yet.
---
 libnemo-private/nemo-bookmark.c       | 989 +++++++++++++++++++---------------
 libnemo-private/nemo-bookmark.h       |  20 +-
 libnemo-private/nemo-file-utilities.c |  39 ++
 libnemo-private/nemo-file-utilities.h |   3 +
 libnemo-private/nemo-icon-names.h     |  10 +
 src/nemo-bookmark-list.c              | 308 ++++++-----
 src/nemo-bookmarks-window.c           |   3 +-
 src/nemo-places-sidebar.c             |  41 +-
 src/nemo-view.c                       |   2 +-
 src/nemo-window-bookmarks.c           |   4 +-
 src/nemo-window-manage-views.c        |   2 +-
 11 files changed, 810 insertions(+), 611 deletions(-)

diff --git a/libnemo-private/nemo-bookmark.c b/libnemo-private/nemo-bookmark.c
index 3e1342a..996d81f 100644
--- a/libnemo-private/nemo-bookmark.c
+++ b/libnemo-private/nemo-bookmark.c
@@ -17,8 +17,7 @@
  *
  * You should have received a copy of the GNU Library General Public
  * License along with the Gnome Library; see the file COPYING.LIB.  If not,
- * write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500,
- * Boston, MA 02110-1335, USA.
+ * see <http://www.gnu.org/licenses/>.
  *
  * Authors: John Sullivan <sullivan@eazel.com>
  *          Cosimo Cecchi <cosimoc@redhat.com>
@@ -35,22 +34,24 @@
 
 #include <libnemo-private/nemo-file.h>
 #include <libnemo-private/nemo-file-utilities.h>
+#include <libnemo-private/nemo-global-preferences.h>
 #include <libnemo-private/nemo-icon-names.h>
 
 #define DEBUG_FLAG NEMO_DEBUG_BOOKMARKS
 #include <libnemo-private/nemo-debug.h>
 
 enum {
-	CONTENTS_CHANGED,
-	LAST_SIGNAL
+    CONTENTS_CHANGED,
+    LAST_SIGNAL
 };
 
 enum {
-	PROP_NAME = 1,
-	PROP_CUSTOM_NAME,
-	PROP_LOCATION,
-	PROP_ICON,
-	NUM_PROPERTIES
+    PROP_NAME = 1,
+    PROP_CUSTOM_NAME,
+    PROP_LOCATION,
+    PROP_ICON,
+    PROP_SYMBOLIC_ICON,
+    NUM_PROPERTIES
 };
 
 #define ELLIPSISED_MENU_ITEM_MIN_CHARS  32
@@ -60,386 +61,577 @@ static guint signals[LAST_SIGNAL];
 
 struct NemoBookmarkDetails
 {
-	char *name;
-	gboolean has_custom_name;
-	GFile *location;
-	GIcon *icon;
-	NemoFile *file;
-	
-	char *scroll_file;
+    char *name;
+    gboolean has_custom_name;
+    GFile *location;
+    GIcon *icon;
+    GIcon *symbolic_icon;
+    NemoFile *file;
+    
+    char *scroll_file;
+
+    gboolean exists;
+    guint exists_id;
+    GCancellable *cancellable;
 };
 
-static void	  nemo_bookmark_disconnect_file	  (NemoBookmark	 *file);
+static void   nemo_bookmark_disconnect_file   (NemoBookmark  *file);
 
 G_DEFINE_TYPE (NemoBookmark, nemo_bookmark, G_TYPE_OBJECT);
 
 static void
 nemo_bookmark_set_name_internal (NemoBookmark *bookmark,
-				     const char *new_name)
+                     const char *new_name)
 {
-	if (g_strcmp0 (bookmark->details->name, new_name) != 0) {
-		g_free (bookmark->details->name);
-		bookmark->details->name = g_strdup (new_name);
+    if (g_strcmp0 (bookmark->details->name, new_name) != 0) {
+        g_free (bookmark->details->name);
+        bookmark->details->name = g_strdup (new_name);
 
-		g_object_notify_by_pspec (G_OBJECT (bookmark), properties[PROP_NAME]);
-	}
+        g_object_notify_by_pspec (G_OBJECT (bookmark), properties[PROP_NAME]);
+    }
 }
 
 static void
-nemo_bookmark_update_icon (NemoBookmark *bookmark)
+bookmark_set_name_from_ready_file (NemoBookmark *self,
+                   NemoFile *file)
 {
-	GIcon *new_icon;
+    gchar *display_name;
 
-	if (bookmark->details->file == NULL) {
-		return;
-	}
+    if (self->details->has_custom_name) {
+        return;
+    }
 
-	if (!nemo_file_is_local (bookmark->details->file)) {
-		/* never update icons for remote bookmarks */
-		return;
-	}
+    display_name = nemo_file_get_display_name (self->details->file);
 
-	if (!nemo_file_is_not_yet_confirmed (bookmark->details->file) &&
-	    nemo_file_check_if_ready (bookmark->details->file,
-					  NEMO_FILE_ATTRIBUTES_FOR_ICON)) {
-		DEBUG ("%s: set new icon", nemo_bookmark_get_name (bookmark));
+    if (nemo_file_is_home (self->details->file)) {
+        nemo_bookmark_set_name_internal (self, _("Home"));
+    } else if (g_strcmp0 (self->details->name, display_name) != 0) {
+        nemo_bookmark_set_name_internal (self, display_name);
+        DEBUG ("%s: name changed to %s", nemo_bookmark_get_name (self), display_name);
+    }
 
-		new_icon = nemo_file_get_gicon (bookmark->details->file, 0);
-		g_object_set (bookmark,
-			      "icon", new_icon,
-			      NULL);
+    g_free (display_name);
+}
 
-		g_object_unref (new_icon);
-	}
+static void
+bookmark_file_changed_callback (NemoFile *file,
+                NemoBookmark *bookmark)
+{
+    GFile *location;
+
+    g_assert (file == bookmark->details->file);
+
+    DEBUG ("%s: file changed", nemo_bookmark_get_name (bookmark));
+
+    location = nemo_file_get_location (file);
+
+    if (!g_file_equal (bookmark->details->location, location) &&
+        !nemo_file_is_in_trash (file)) {
+        DEBUG ("%s: file got moved", nemo_bookmark_get_name (bookmark));
+
+        g_object_unref (bookmark->details->location);
+        bookmark->details->location = g_object_ref (location);
+
+        g_object_notify_by_pspec (G_OBJECT (bookmark), properties[PROP_LOCATION]);
+        g_signal_emit (bookmark, signals[CONTENTS_CHANGED], 0);
+    }
+
+    g_object_unref (location);
+
+    if (nemo_file_is_gone (file) ||
+        nemo_file_is_in_trash (file)) {
+        /* The file we were monitoring has been trashed, deleted,
+         * or moved in a way that we didn't notice. We should make 
+         * a spanking new NemoFile object for this 
+         * location so if a new file appears in this place 
+         * we will notice. However, we can't immediately do so
+         * because creating a new NemoFile directly as a result
+         * of noticing a file goes away may trigger i/o on that file
+         * again, noticeing it is gone, leading to a loop.
+         * So, the new NemoFile is created when the bookmark
+         * is used again. However, this is not really a problem, as
+         * we don't want to change the icon or anything about the
+         * bookmark just because its not there anymore.
+         */
+        DEBUG ("%s: trashed", nemo_bookmark_get_name (bookmark));
+        nemo_bookmark_disconnect_file (bookmark);
+    } else {
+        bookmark_set_name_from_ready_file (bookmark, file);
+    }
 }
 
 static void
-bookmark_set_name_from_ready_file (NemoBookmark *self,
-				   NemoFile *file)
+apply_warning_emblem (GIcon **base,
+              gboolean symbolic)
 {
-	gchar *display_name;
+    GIcon *warning, *emblemed_icon;
+    GEmblem *emblem;
 
-	if (self->details->has_custom_name) {
-		return;
-	}
+    if (symbolic) {
+        warning = g_themed_icon_new ("dialog-warning-symbolic");
+    } else {
+        warning = g_themed_icon_new ("dialog-warning");
+    }
 
-	display_name = nemo_file_get_display_name (self->details->file);
+    emblem = g_emblem_new (warning);
+    emblemed_icon = g_emblemed_icon_new (*base, emblem);
 
-	if (nemo_file_is_home (self->details->file)) {
-		nemo_bookmark_set_name_internal (self, _("Home"));
-	} else if (g_strcmp0 (self->details->name, display_name) != 0) {
-		nemo_bookmark_set_name_internal (self, display_name);
-		DEBUG ("%s: name changed to %s", nemo_bookmark_get_name (self), display_name);
-	}
+    g_object_unref (emblem);
+    g_object_unref (warning);
+    g_object_unref (*base);
 
-	g_free (display_name);
+    *base = emblemed_icon;
 }
 
-static void
-bookmark_file_changed_callback (NemoFile *file,
-				NemoBookmark *bookmark)
+gboolean
+nemo_bookmark_get_is_builtin (NemoBookmark *bookmark)
+{
+    GUserDirectory xdg_type;
+
+    /* if this is not an XDG dir, it's never builtin */
+    if (!nemo_bookmark_get_xdg_type (bookmark, &xdg_type)) {
+        return FALSE;
+    }
+
+    /* exclude XDG locations which are not in our builtin list */
+    if (xdg_type == G_USER_DIRECTORY_DESKTOP &&
+        !g_settings_get_boolean (gnome_background_preferences, NEMO_PREFERENCES_SHOW_DESKTOP)) {
+        return FALSE;
+    }
+
+    return (xdg_type != G_USER_DIRECTORY_TEMPLATES) && (xdg_type != G_USER_DIRECTORY_PUBLIC_SHARE);
+}
+
+gboolean
+nemo_bookmark_get_xdg_type (NemoBookmark *bookmark,
+                GUserDirectory   *directory)
 {
-	GFile *location;
+    gboolean match;
+    GFile *location;
+    const gchar *path;
+    GUserDirectory dir;
 
-	g_assert (file == bookmark->details->file);
+    match = FALSE;
 
-	DEBUG ("%s: file changed", nemo_bookmark_get_name (bookmark));
+    for (dir = 0; dir < G_USER_N_DIRECTORIES; dir++) {
+        path = g_get_user_special_dir (dir);
+        if (!path) {
+            continue;
+        }
 
-	location = nemo_file_get_location (file);
+        location = g_file_new_for_path (path);
+        match = g_file_equal (location, bookmark->details->location);
+        g_object_unref (location);
 
-	if (!g_file_equal (bookmark->details->location, location) &&
-	    !nemo_file_is_in_trash (file)) {
-		DEBUG ("%s: file got moved", nemo_bookmark_get_name (bookmark));
+        if (match) {
+            break;
+        }
+    }
 
-		g_object_unref (bookmark->details->location);
-		bookmark->details->location = g_object_ref (location);
+    if (match && directory != NULL) {
+        *directory = dir;
+    }
 
-		g_object_notify_by_pspec (G_OBJECT (bookmark), properties[PROP_LOCATION]);
-		g_signal_emit (bookmark, signals[CONTENTS_CHANGED], 0);
-	}
+    return match;
+}
 
-	g_object_unref (location);
+static GIcon *
+get_native_icon (NemoBookmark *bookmark,
+         gboolean symbolic)
+{
+    GUserDirectory xdg_type;
+    GIcon *icon = NULL;
+
+    if (bookmark->details->file == NULL) {
+        goto out;
+    }
+
+    if (!nemo_bookmark_get_xdg_type (bookmark, &xdg_type)) {
+        goto out;
+    }
+
+    if (xdg_type < G_USER_N_DIRECTORIES) {
+        if (symbolic) {
+            icon = nemo_special_directory_get_symbolic_icon (xdg_type);
+        } else {
+            icon = nemo_special_directory_get_icon (xdg_type);
+        }
+    }
+
+ out:
+    if (icon == NULL) {
+        if (symbolic) {
+            icon = g_themed_icon_new (NEMO_ICON_FOLDER);
+        } else {
+            icon = g_themed_icon_new (NEMO_ICON_FULLCOLOR_FOLDER);
+        }
+    }
 
-	if (nemo_file_is_gone (file) ||
-	    nemo_file_is_in_trash (file)) {
-		/* The file we were monitoring has been trashed, deleted,
-		 * or moved in a way that we didn't notice. We should make 
-		 * a spanking new NemoFile object for this 
-		 * location so if a new file appears in this place 
-		 * we will notice. However, we can't immediately do so
-		 * because creating a new NemoFile directly as a result
-		 * of noticing a file goes away may trigger i/o on that file
-		 * again, noticeing it is gone, leading to a loop.
-		 * So, the new NemoFile is created when the bookmark
-		 * is used again. However, this is not really a problem, as
-		 * we don't want to change the icon or anything about the
-		 * bookmark just because its not there anymore.
-		 */
-		DEBUG ("%s: trashed", nemo_bookmark_get_name (bookmark));
-		nemo_bookmark_disconnect_file (bookmark);
-	} else {
-		nemo_bookmark_update_icon (bookmark);
-		bookmark_set_name_from_ready_file (bookmark, file);
-	}
+    return icon;
 }
 
 static void
 nemo_bookmark_set_icon_to_default (NemoBookmark *bookmark)
 {
-	GIcon *icon, *emblemed_icon, *folder;
-	GEmblem *emblem;
-	char *uri;
+    GIcon *icon, *symbolic_icon;
+    char *uri;
+
+    if (g_file_is_native (bookmark->details->location)) {
+        symbolic_icon = get_native_icon (bookmark, TRUE);
+        icon = get_native_icon (bookmark, FALSE);
+    } else {
+        uri = nemo_bookmark_get_uri (bookmark);
+        if (g_str_has_prefix (uri, EEL_SEARCH_URI)) {
+            symbolic_icon = g_themed_icon_new (NEMO_ICON_FOLDER_SAVED_SEARCH);
+            icon = g_themed_icon_new (NEMO_ICON_FULLCOLOR_FOLDER_SAVED_SEARCH);
+        } else {
+            symbolic_icon = g_themed_icon_new (NEMO_ICON_FOLDER_REMOTE);
+            icon = g_themed_icon_new (NEMO_ICON_FULLCOLOR_FOLDER_REMOTE);
+        }
+        g_free (uri);
+    }
+
+    if (!bookmark->details->exists) {
+        DEBUG ("%s: file does not exist, add emblem", nemo_bookmark_get_name (bookmark));
 
-	if (g_file_is_native (bookmark->details->location)) {
-		folder = g_themed_icon_new (NEMO_ICON_FOLDER);
-	} else {
-		uri = nemo_bookmark_get_uri (bookmark);
-		if (g_str_has_prefix (uri, EEL_SEARCH_URI)) {
-			folder = g_themed_icon_new (NEMO_ICON_FOLDER_SAVED_SEARCH);
-		} else {
-			folder = g_themed_icon_new (NEMO_ICON_FOLDER_REMOTE);
-		}
-		g_free (uri);
-	}
+        apply_warning_emblem (&icon, FALSE);
+        apply_warning_emblem (&symbolic_icon, TRUE);
+    }
 
-	if (nemo_bookmark_uri_known_not_to_exist (bookmark)) {
-		DEBUG ("%s: file does not exist, add emblem", nemo_bookmark_get_name (bookmark));
+    DEBUG ("%s: setting icon to default", nemo_bookmark_get_name (bookmark));
 
-		icon = g_themed_icon_new (GTK_STOCK_DIALOG_WARNING);
-		emblem = g_emblem_new (icon);
+    g_object_set (bookmark,
+              "icon", icon,
+              "symbolic-icon", symbolic_icon,
+              NULL);
 
-		emblemed_icon = g_emblemed_icon_new (folder, emblem);
+    g_object_unref (icon);
+    g_object_unref (symbolic_icon);
+}
+
+static void
+nemo_bookmark_disconnect_file (NemoBookmark *bookmark)
+{
+    if (bookmark->details->file != NULL) {
+        DEBUG ("%s: disconnecting file",
+               nemo_bookmark_get_name (bookmark));
+
+        g_signal_handlers_disconnect_by_func (bookmark->details->file,
+                              G_CALLBACK (bookmark_file_changed_callback),
+                              bookmark);
+        g_clear_object (&bookmark->details->file);
+    }
+
+    if (bookmark->details->cancellable != NULL) {
+        g_cancellable_cancel (bookmark->details->cancellable);
+        g_clear_object (&bookmark->details->cancellable);
+    }
+
+    if (bookmark->details->exists_id != 0) {
+        g_source_remove (bookmark->details->exists_id);
+        bookmark->details->exists_id = 0;
+    }
+}
 
-		g_object_unref (emblem);
-		g_object_unref (icon);
-		g_object_unref (folder);
+static void
+nemo_bookmark_connect_file (NemoBookmark *bookmark)
+{
+    if (bookmark->details->file != NULL) {
+        DEBUG ("%s: file already connected, returning",
+               nemo_bookmark_get_name (bookmark));
+        return;
+    }
 
-		folder = emblemed_icon;
-	}
+    if (bookmark->details->exists) {
+        DEBUG ("%s: creating file", nemo_bookmark_get_name (bookmark));
+
+        bookmark->details->file = nemo_file_get (bookmark->details->location);
+        g_assert (!nemo_file_is_gone (bookmark->details->file));
+
+        g_signal_connect_object (bookmark->details->file, "changed",
+                     G_CALLBACK (bookmark_file_changed_callback), bookmark, 0);
+    }
 
-	DEBUG ("%s: setting icon to default", nemo_bookmark_get_name (bookmark));
+    if (bookmark->details->icon == NULL ||
+        bookmark->details->symbolic_icon == NULL) {
+        nemo_bookmark_set_icon_to_default (bookmark);
+    }
 
-	g_object_set (bookmark,
-		      "icon", folder,
-		      NULL);
+    if (bookmark->details->file != NULL &&
+        nemo_file_check_if_ready (bookmark->details->file, NEMO_FILE_ATTRIBUTE_INFO)) {
+        bookmark_set_name_from_ready_file (bookmark, bookmark->details->file);
+    }
 
-	g_object_unref (folder);
+    if (bookmark->details->name == NULL) {
+        bookmark->details->name = nemo_compute_title_for_location (bookmark->details->location);
+    }
 }
 
 static void
-nemo_bookmark_disconnect_file (NemoBookmark *bookmark)
+nemo_bookmark_set_exists (NemoBookmark *bookmark,
+                  gboolean exists)
+{
+    if (bookmark->details->exists == exists) {
+        return;
+    }
+
+    bookmark->details->exists = exists;
+    DEBUG ("%s: setting bookmark to exist: %d\n",
+           nemo_bookmark_get_name (bookmark), exists);
+
+    /* refresh icon */
+    nemo_bookmark_set_icon_to_default (bookmark);
+}
+
+static gboolean
+exists_non_native_idle_cb (gpointer user_data)
 {
-	if (bookmark->details->file != NULL) {
-		DEBUG ("%s: disconnecting file",
-		       nemo_bookmark_get_name (bookmark));
+    NemoBookmark *bookmark = user_data;
+    bookmark->details->exists_id = 0;
+    nemo_bookmark_set_exists (bookmark, FALSE);
 
-		g_signal_handlers_disconnect_by_func (bookmark->details->file,
-						      G_CALLBACK (bookmark_file_changed_callback),
-						      bookmark);
-		g_clear_object (&bookmark->details->file);
-	}
+    return FALSE;
 }
 
 static void
-nemo_bookmark_connect_file (NemoBookmark *bookmark)
+exists_query_info_ready_cb (GObject *source,
+                GAsyncResult *res,
+                gpointer user_data)
 {
-	if (bookmark->details->file != NULL) {
-		DEBUG ("%s: file already connected, returning",
-		       nemo_bookmark_get_name (bookmark));
-		return;
-	}
+    GFileInfo *info;
+    NemoBookmark *bookmark;
+    GError *error = NULL;
+    gboolean exists = FALSE;
 
-	if (!nemo_bookmark_uri_known_not_to_exist (bookmark)) {
-		DEBUG ("%s: creating file", nemo_bookmark_get_name (bookmark));
+    info = g_file_query_info_finish (G_FILE (source), res, &error);
+    if (!info && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+        g_clear_error (&error);
+        return;
+    }
 
-		bookmark->details->file = nemo_file_get (bookmark->details->location);
-		if (!nemo_file_is_gone (bookmark->details->file)) {
-            g_signal_connect_object (bookmark->details->file, "changed",
-                     G_CALLBACK (bookmark_file_changed_callback), bookmark, 0);
-        }
-	}
+    g_clear_error (&error);
+    bookmark = user_data;
 
-	/* Set icon based on available information. */
-	nemo_bookmark_update_icon (bookmark);
+    if (info) {
+        exists = TRUE;
 
-	if (bookmark->details->icon == NULL) {
-		nemo_bookmark_set_icon_to_default (bookmark);
-	}
+        g_object_unref (info);
+        g_clear_object (&bookmark->details->cancellable);
+    }
 
-	if (bookmark->details->file != NULL &&
-	    nemo_file_check_if_ready (bookmark->details->file, NEMO_FILE_ATTRIBUTE_INFO)) {
-		bookmark_set_name_from_ready_file (bookmark, bookmark->details->file);
-	}
+    nemo_bookmark_set_exists (bookmark, exists);
+}
 
-	if (bookmark->details->name == NULL) {
-		bookmark->details->name = nemo_compute_title_for_location (bookmark->details->location);
-	}
+static void
+nemo_bookmark_update_exists (NemoBookmark *bookmark)
+{
+    /* Convert to a path, returning FALSE if not local. */
+    if (!g_file_is_native (bookmark->details->location) &&
+        bookmark->details->exists_id == 0) {
+        bookmark->details->exists_id =
+            g_idle_add (exists_non_native_idle_cb, bookmark);
+        return;
+    }
+
+    if (bookmark->details->cancellable != NULL) {
+        return;
+    }
+
+    bookmark->details->cancellable = g_cancellable_new ();
+    g_file_query_info_async (bookmark->details->location,
+                 G_FILE_ATTRIBUTE_STANDARD_TYPE,
+                 0, G_PRIORITY_DEFAULT,
+                 bookmark->details->cancellable,
+                 exists_query_info_ready_cb, bookmark);
 }
 
 /* GObject methods */
 
 static void
 nemo_bookmark_set_property (GObject *object,
-				guint property_id,
-				const GValue *value,
-				GParamSpec *pspec)
-{
-	NemoBookmark *self = NEMO_BOOKMARK (object);
-	GIcon *new_icon;
-
-	switch (property_id) {
-	case PROP_ICON:
-		new_icon = g_value_get_object (value);
-
-		if (new_icon != NULL && !g_icon_equal (self->details->icon, new_icon)) {
-			g_clear_object (&self->details->icon);
-			self->details->icon = g_object_ref (new_icon);
-		}
-
-		break;
-	case PROP_LOCATION:
-		self->details->location = g_value_dup_object (value);
-		break;
-	case PROP_CUSTOM_NAME:
-		self->details->has_custom_name = g_value_get_boolean (value);
-		break;
-	case PROP_NAME:
-		nemo_bookmark_set_name_internal (self, g_value_get_string (value));
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-		break;
-	}
+                guint property_id,
+                const GValue *value,
+                GParamSpec *pspec)
+{
+    NemoBookmark *self = NEMO_BOOKMARK (object);
+    GIcon *new_icon;
+
+    switch (property_id) {
+    case PROP_ICON:
+        new_icon = g_value_get_object (value);
+
+        if (new_icon != NULL && !g_icon_equal (self->details->icon, new_icon)) {
+            g_clear_object (&self->details->icon);
+            self->details->icon = g_object_ref (new_icon);
+        }
+
+        break;
+    case PROP_SYMBOLIC_ICON:
+        new_icon = g_value_get_object (value);
+
+        if (new_icon != NULL && !g_icon_equal (self->details->symbolic_icon, new_icon)) {
+            g_clear_object (&self->details->symbolic_icon);
+            self->details->symbolic_icon = g_object_ref (new_icon);
+        }
+
+        break;
+    case PROP_LOCATION:
+        self->details->location = g_value_dup_object (value);
+        break;
+    case PROP_CUSTOM_NAME:
+        self->details->has_custom_name = g_value_get_boolean (value);
+        break;
+    case PROP_NAME:
+        nemo_bookmark_set_name_internal (self, g_value_get_string (value));
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+        break;
+    }
 }
 
 static void
 nemo_bookmark_get_property (GObject *object,
-				guint property_id,
-				GValue *value,
-				GParamSpec *pspec)
-{
-	NemoBookmark *self = NEMO_BOOKMARK (object);
-
-	switch (property_id) {
-	case PROP_NAME:
-		g_value_set_string (value, self->details->name);
-		break;
-	case PROP_ICON:
-		g_value_set_object (value, self->details->icon);
-		break;
-	case PROP_LOCATION:
-		g_value_set_object (value, self->details->location);
-		break;
-	case PROP_CUSTOM_NAME:
-		g_value_set_boolean (value, self->details->has_custom_name);
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-		break;
-	}
+                guint property_id,
+                GValue *value,
+                GParamSpec *pspec)
+{
+    NemoBookmark *self = NEMO_BOOKMARK (object);
+
+    switch (property_id) {
+    case PROP_NAME:
+        g_value_set_string (value, self->details->name);
+        break;
+    case PROP_ICON:
+        g_value_set_object (value, self->details->icon);
+        break;
+    case PROP_SYMBOLIC_ICON:
+        g_value_set_object (value, self->details->symbolic_icon);
+        break;
+    case PROP_LOCATION:
+        g_value_set_object (value, self->details->location);
+        break;
+    case PROP_CUSTOM_NAME:
+        g_value_set_boolean (value, self->details->has_custom_name);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+        break;
+    }
 }
 
 static void
 nemo_bookmark_finalize (GObject *object)
 {
-	NemoBookmark *bookmark;
+    NemoBookmark *bookmark;
 
-	g_assert (NEMO_IS_BOOKMARK (object));
+    g_assert (NEMO_IS_BOOKMARK (object));
 
-	bookmark = NEMO_BOOKMARK (object);
+    bookmark = NEMO_BOOKMARK (object);
 
-	nemo_bookmark_disconnect_file (bookmark);	
+    nemo_bookmark_disconnect_file (bookmark);   
 
-	g_object_unref (bookmark->details->location);
-	g_clear_object (&bookmark->details->icon);
+    g_object_unref (bookmark->details->location);
+    g_clear_object (&bookmark->details->icon);
+    g_clear_object (&bookmark->details->symbolic_icon);
 
-	g_free (bookmark->details->name);
-	g_free (bookmark->details->scroll_file);
+    g_free (bookmark->details->name);
+    g_free (bookmark->details->scroll_file);
 
-	G_OBJECT_CLASS (nemo_bookmark_parent_class)->finalize (object);
+    G_OBJECT_CLASS (nemo_bookmark_parent_class)->finalize (object);
 }
 
 static void
 nemo_bookmark_constructed (GObject *obj)
 {
-	NemoBookmark *self = NEMO_BOOKMARK (obj);
+    NemoBookmark *self = NEMO_BOOKMARK (obj);
 
-	nemo_bookmark_connect_file (self);
+    nemo_bookmark_connect_file (self);
+    nemo_bookmark_update_exists (self);
 }
 
 static void
 nemo_bookmark_class_init (NemoBookmarkClass *class)
 {
-	GObjectClass *oclass = G_OBJECT_CLASS (class);
-
-	oclass->finalize = nemo_bookmark_finalize;
-	oclass->get_property = nemo_bookmark_get_property;
-	oclass->set_property = nemo_bookmark_set_property;
-	oclass->constructed = nemo_bookmark_constructed;
-
-	signals[CONTENTS_CHANGED] =
-		g_signal_new ("contents-changed",
-		              G_TYPE_FROM_CLASS (class),
-		              G_SIGNAL_RUN_LAST,
-		              G_STRUCT_OFFSET (NemoBookmarkClass, contents_changed),
-		              NULL, NULL,
-		              g_cclosure_marshal_VOID__VOID,
-		              G_TYPE_NONE, 0);
-
-	properties[PROP_NAME] =
-		g_param_spec_string ("name",
-				     "Bookmark's name",
-				     "The name of this bookmark",
-				     NULL,
-				     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
-
-	properties[PROP_CUSTOM_NAME] =
-		g_param_spec_boolean ("custom-name",
-				      "Whether the bookmark has a custom name",
-				      "Whether the bookmark has a custom name",
-				      FALSE,
-				      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
-
-	properties[PROP_LOCATION] =
-		g_param_spec_object ("location",
-				     "Bookmark's location",
-				     "The location of this bookmark",
-				     G_TYPE_FILE,
-				     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
-
-	properties[PROP_ICON] =
-		g_param_spec_object ("icon",
-				     "Bookmark's icon",
-				     "The icon of this bookmark",
-				     G_TYPE_ICON,
-				     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
-	g_object_class_install_properties (oclass, NUM_PROPERTIES, properties);
-
-	g_type_class_add_private (class, sizeof (NemoBookmarkDetails));
+    GObjectClass *oclass = G_OBJECT_CLASS (class);
+
+    oclass->finalize = nemo_bookmark_finalize;
+    oclass->get_property = nemo_bookmark_get_property;
+    oclass->set_property = nemo_bookmark_set_property;
+    oclass->constructed = nemo_bookmark_constructed;
+
+    signals[CONTENTS_CHANGED] =
+        g_signal_new ("contents-changed",
+                      G_TYPE_FROM_CLASS (class),
+                      G_SIGNAL_RUN_LAST,
+                      G_STRUCT_OFFSET (NemoBookmarkClass, contents_changed),
+                      NULL, NULL,
+                      g_cclosure_marshal_VOID__VOID,
+                      G_TYPE_NONE, 0);
+
+    properties[PROP_NAME] =
+        g_param_spec_string ("name",
+                     "Bookmark's name",
+                     "The name of this bookmark",
+                     NULL,
+                     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
+
+    properties[PROP_CUSTOM_NAME] =
+        g_param_spec_boolean ("custom-name",
+                      "Whether the bookmark has a custom name",
+                      "Whether the bookmark has a custom name",
+                      FALSE,
+                      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT);
+
+    properties[PROP_LOCATION] =
+        g_param_spec_object ("location",
+                     "Bookmark's location",
+                     "The location of this bookmark",
+                     G_TYPE_FILE,
+                     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
+
+    properties[PROP_ICON] =
+        g_param_spec_object ("icon",
+                     "Bookmark's icon",
+                     "The icon of this bookmark",
+                     G_TYPE_ICON,
+                     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    properties[PROP_SYMBOLIC_ICON] =
+        g_param_spec_object ("symbolic-icon",
+                     "Bookmark's symbolic icon",
+                     "The symbolic icon of this bookmark",
+                     G_TYPE_ICON,
+                     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    g_object_class_install_properties (oclass, NUM_PROPERTIES, properties);
+
+    g_type_class_add_private (class, sizeof (NemoBookmarkDetails));
 }
 
 static void
 nemo_bookmark_init (NemoBookmark *bookmark)
 {
-	bookmark->details = G_TYPE_INSTANCE_GET_PRIVATE (bookmark, NEMO_TYPE_BOOKMARK,
-							 NemoBookmarkDetails);
+    bookmark->details = G_TYPE_INSTANCE_GET_PRIVATE (bookmark, NEMO_TYPE_BOOKMARK,
+                             NemoBookmarkDetails);
+
+    bookmark->details->exists = TRUE;
 }
 
 const gchar *
 nemo_bookmark_get_name (NemoBookmark *bookmark)
 {
-	g_return_val_if_fail (NEMO_IS_BOOKMARK (bookmark), NULL);
+    g_return_val_if_fail (NEMO_IS_BOOKMARK (bookmark), NULL);
 
-	return bookmark->details->name;
+    return bookmark->details->name;
 }
 
 gboolean
 nemo_bookmark_get_has_custom_name (NemoBookmark *bookmark)
 {
-	g_return_val_if_fail(NEMO_IS_BOOKMARK (bookmark), FALSE);
+    g_return_val_if_fail(NEMO_IS_BOOKMARK (bookmark), FALSE);
 
-	return (bookmark->details->has_custom_name);
+    return (bookmark->details->has_custom_name);
 }
 
 /**
@@ -451,17 +643,17 @@ nemo_bookmark_get_has_custom_name (NemoBookmark *bookmark)
  **/
 void
 nemo_bookmark_set_custom_name (NemoBookmark *bookmark,
-				   const char *new_name)
+                   const char *new_name)
 {
-	g_return_if_fail (new_name != NULL);
-	g_return_if_fail (NEMO_IS_BOOKMARK (bookmark));
+    g_return_if_fail (new_name != NULL);
+    g_return_if_fail (NEMO_IS_BOOKMARK (bookmark));
 
-	g_object_set (bookmark,
-		      "custom-name", TRUE,
-		      "name", new_name,
-		      NULL);
+    g_object_set (bookmark,
+              "custom-name", TRUE,
+              "name", new_name,
+              NULL);
 
-	g_signal_emit (bookmark, signals[CONTENTS_CHANGED], 0);
+    g_signal_emit (bookmark, signals[CONTENTS_CHANGED], 0);
 }
 
 /**
@@ -474,147 +666,101 @@ nemo_bookmark_set_custom_name (NemoBookmark *bookmark,
  * Return value: 0 if @a and @b have same name and uri, 1 otherwise 
  * (GCompareFunc style)
  **/
-int		    
+int         
 nemo_bookmark_compare_with (gconstpointer a, gconstpointer b)
 {
-	NemoBookmark *bookmark_a;
-	NemoBookmark *bookmark_b;
-
-	g_return_val_if_fail (NEMO_IS_BOOKMARK (a), 1);
-	g_return_val_if_fail (NEMO_IS_BOOKMARK (b), 1);
-
-	bookmark_a = NEMO_BOOKMARK (a);
-	bookmark_b = NEMO_BOOKMARK (b);
-
-	if (!g_file_equal (bookmark_a->details->location,
-			   bookmark_b->details->location)) {
-		return 1;
-	}
-	
-	if (g_strcmp0 (bookmark_a->details->name,
-		       bookmark_b->details->name) != 0) {
-		return 1;
-	}
-	
-	return 0;
+    NemoBookmark *bookmark_a;
+    NemoBookmark *bookmark_b;
+
+    g_return_val_if_fail (NEMO_IS_BOOKMARK (a), 1);
+    g_return_val_if_fail (NEMO_IS_BOOKMARK (b), 1);
+
+    bookmark_a = NEMO_BOOKMARK (a);
+    bookmark_b = NEMO_BOOKMARK (b);
+
+    if (!g_file_equal (bookmark_a->details->location,
+               bookmark_b->details->location)) {
+        return 1;
+    }
+    
+    if (g_strcmp0 (bookmark_a->details->name,
+               bookmark_b->details->name) != 0) {
+        return 1;
+    }
+    
+    return 0;
 }
 
-/**
- * nemo_bookmark_compare_uris:
- *
- * Check whether the uris of two bookmarks are for the same location.
- * @a: first NemoBookmark*.
- * @b: second NemoBookmark*.
- * 
- * Return value: 0 if @a and @b have matching uri, 1 otherwise 
- * (GCompareFunc style)
- **/
-int		    
-nemo_bookmark_compare_uris (gconstpointer a, gconstpointer b)
+GIcon *
+nemo_bookmark_get_symbolic_icon (NemoBookmark *bookmark)
 {
-	NemoBookmark *bookmark_a;
-	NemoBookmark *bookmark_b;
+    g_return_val_if_fail (NEMO_IS_BOOKMARK (bookmark), NULL);
 
-	g_return_val_if_fail (NEMO_IS_BOOKMARK (a), 1);
-	g_return_val_if_fail (NEMO_IS_BOOKMARK (b), 1);
+    /* Try to connect a file in case file exists now but didn't earlier. */
+    nemo_bookmark_connect_file (bookmark);
 
-	bookmark_a = NEMO_BOOKMARK (a);
-	bookmark_b = NEMO_BOOKMARK (b);
-
-	return !g_file_equal (bookmark_a->details->location,
-			      bookmark_b->details->location);
-}
-
-NemoBookmark *
-nemo_bookmark_copy (NemoBookmark *bookmark)
-{
-	g_return_val_if_fail (NEMO_IS_BOOKMARK (bookmark), NULL);
-
-	return nemo_bookmark_new (
-			bookmark->details->location,
-			bookmark->details->has_custom_name ?
-			bookmark->details->name : NULL,
-			bookmark->details->icon);
+    if (bookmark->details->symbolic_icon) {
+        return g_object_ref (bookmark->details->symbolic_icon);
+    }
+    return NULL;
 }
 
 GIcon *
 nemo_bookmark_get_icon (NemoBookmark *bookmark)
 {
-	g_return_val_if_fail (NEMO_IS_BOOKMARK (bookmark), NULL);
+    g_return_val_if_fail (NEMO_IS_BOOKMARK (bookmark), NULL);
 
-	/* Try to connect a file in case file exists now but didn't earlier. */
-	nemo_bookmark_connect_file (bookmark);
+    /* Try to connect a file in case file exists now but didn't earlier. */
+    nemo_bookmark_connect_file (bookmark);
 
-	if (bookmark->details->icon) {
-		return g_object_ref (bookmark->details->icon);
-	}
-	return NULL;
+    if (bookmark->details->icon) {
+        return g_object_ref (bookmark->details->icon);
+    }
+    return NULL;
 }
 
 GFile *
 nemo_bookmark_get_location (NemoBookmark *bookmark)
 {
-	g_return_val_if_fail(NEMO_IS_BOOKMARK (bookmark), NULL);
+    g_return_val_if_fail(NEMO_IS_BOOKMARK (bookmark), NULL);
 
-	/* Try to connect a file in case file exists now but didn't earlier.
-	 * This allows a bookmark to update its image properly in the case
-	 * where a new file appears with the same URI as a previously-deleted
-	 * file. Calling connect_file here means that attempts to activate the 
-	 * bookmark will update its image if possible. 
-	 */
-	nemo_bookmark_connect_file (bookmark);
+    /* Try to connect a file in case file exists now but didn't earlier.
+     * This allows a bookmark to update its image properly in the case
+     * where a new file appears with the same URI as a previously-deleted
+     * file. Calling connect_file here means that attempts to activate the 
+     * bookmark will update its image if possible. 
+     */
+    nemo_bookmark_connect_file (bookmark);
 
-	return g_object_ref (bookmark->details->location);
+    return g_object_ref (bookmark->details->location);
 }
 
 char *
 nemo_bookmark_get_uri (NemoBookmark *bookmark)
 {
-	GFile *file;
-	char *uri;
+    GFile *file;
+    char *uri;
 
-	file = nemo_bookmark_get_location (bookmark);
-	uri = g_file_get_uri (file);
-	g_object_unref (file);
-	return uri;
+    file = nemo_bookmark_get_location (bookmark);
+    uri = g_file_get_uri (file);
+    g_object_unref (file);
+    return uri;
 }
 
 NemoBookmark *
 nemo_bookmark_new (GFile *location,
-		       const gchar *custom_name,
-                       GIcon *icon)
-{
-	NemoBookmark *new_bookmark;
-    gchar *name;
-
-    if (custom_name == NULL)
-        name = g_file_get_basename (location);
-    else
-        name = g_strdup (custom_name);
-
-	new_bookmark = NEMO_BOOKMARK (g_object_new (NEMO_TYPE_BOOKMARK,
-							"location", location,
-							"icon", icon,
-							"name", name,
-							"custom-name", custom_name != NULL,
-							NULL));
-    g_free (name);
-
-	return new_bookmark;
-}				 
-
-static GtkWidget *
-create_image_widget_for_bookmark (NemoBookmark *bookmark)
+               const gchar *custom_name)
 {
-	GIcon *icon;
-	GtkWidget *widget;
+    NemoBookmark *new_bookmark;
 
-	icon = nemo_bookmark_get_icon (bookmark);
-        widget = gtk_image_new_from_gicon (icon, GTK_ICON_SIZE_MENU);
-	g_object_unref (icon);
+    new_bookmark = NEMO_BOOKMARK (g_object_new (NEMO_TYPE_BOOKMARK,
+                            "location", location,
+                            "name", custom_name,
+                            "custom-name", custom_name != NULL,
+                            NULL));
 
-	return widget;
-}
+    return new_bookmark;
+}                
 
 /**
  * nemo_bookmark_menu_item_new:
@@ -626,57 +772,36 @@ create_image_widget_for_bookmark (NemoBookmark *bookmark)
 GtkWidget *
 nemo_bookmark_menu_item_new (NemoBookmark *bookmark)
 {
-	GtkWidget *menu_item;
-	GtkWidget *image_widget;
-	GtkLabel *label;
-	const char *name;
-
-	name = nemo_bookmark_get_name (bookmark);
-	menu_item = gtk_image_menu_item_new_with_label (name);
-	label = GTK_LABEL (gtk_bin_get_child (GTK_BIN (menu_item)));
-	gtk_label_set_use_underline (label, FALSE);
-	gtk_label_set_ellipsize (label, PANGO_ELLIPSIZE_END);
-	gtk_label_set_max_width_chars (label, ELLIPSISED_MENU_ITEM_MIN_CHARS);
-
-	image_widget = create_image_widget_for_bookmark (bookmark);
-	if (image_widget != NULL) {
-		gtk_widget_show (image_widget);
-		gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item),
-					       image_widget);
-	}
-
-	return menu_item;
-}
-
-gboolean
-nemo_bookmark_uri_known_not_to_exist (NemoBookmark *bookmark)
-{
-	char *path_name;
-	gboolean exists;
-
-	/* Convert to a path, returning FALSE if not local. */
-	if (!g_file_is_native (bookmark->details->location)) {
-		return FALSE;
-	}
-	path_name = g_file_get_path (bookmark->details->location);
-
-	/* Now check if the file exists (sync. call OK because it is local). */
-	exists = g_file_test (path_name, G_FILE_TEST_EXISTS);
-	g_free (path_name);
-
-	return !exists;
+    GtkWidget *menu_item;
+    GtkLabel *label;
+    const char *name;
+
+    name = nemo_bookmark_get_name (bookmark);
+    menu_item = gtk_menu_item_new_with_label (name);
+    label = GTK_LABEL (gtk_bin_get_child (GTK_BIN (menu_item)));
+    gtk_label_set_use_underline (label, FALSE);
+    gtk_label_set_ellipsize (label, PANGO_ELLIPSIZE_END);
+    gtk_label_set_max_width_chars (label, ELLIPSISED_MENU_ITEM_MIN_CHARS);
+
+    return menu_item;
 }
 
 void
 nemo_bookmark_set_scroll_pos (NemoBookmark      *bookmark,
-				  const char            *uri)
+                  const char            *uri)
 {
-	g_free (bookmark->details->scroll_file);
-	bookmark->details->scroll_file = g_strdup (uri);
+    g_free (bookmark->details->scroll_file);
+    bookmark->details->scroll_file = g_strdup (uri);
 }
 
 char *
 nemo_bookmark_get_scroll_pos (NemoBookmark      *bookmark)
 {
-	return g_strdup (bookmark->details->scroll_file);
+    return g_strdup (bookmark->details->scroll_file);
+}
+
+gboolean
+nemo_bookmark_get_exists (NemoBookmark *bookmark)
+{
+    return bookmark->details->exists;
 }
diff --git a/libnemo-private/nemo-bookmark.h b/libnemo-private/nemo-bookmark.h
index 59bd0b6..dc2bd64 100644
--- a/libnemo-private/nemo-bookmark.h
+++ b/libnemo-private/nemo-bookmark.h
@@ -65,24 +65,24 @@ typedef struct NemoBookmarkClass NemoBookmarkClass;
 
 GType                 nemo_bookmark_get_type               (void);
 NemoBookmark *    nemo_bookmark_new                    (GFile *location,
-                                                                const char *custom_name,
-                                                                GIcon *icon);
-NemoBookmark *    nemo_bookmark_copy                   (NemoBookmark      *bookmark);
+                                                                const char *custom_name);
 const char *          nemo_bookmark_get_name               (NemoBookmark      *bookmark);
 GFile *               nemo_bookmark_get_location           (NemoBookmark      *bookmark);
 char *                nemo_bookmark_get_uri                (NemoBookmark      *bookmark);
 GIcon *               nemo_bookmark_get_icon               (NemoBookmark      *bookmark);
-gboolean	      nemo_bookmark_get_has_custom_name    (NemoBookmark      *bookmark);		
+GIcon *               nemo_bookmark_get_symbolic_icon      (NemoBookmark      *bookmark);
+gboolean              nemo_bookmark_get_exists             (NemoBookmark      *bookmark);
+gboolean              nemo_bookmark_get_xdg_type           (NemoBookmark      *bookmark,
+                                GUserDirectory        *directory);
+gboolean              nemo_bookmark_get_is_builtin         (NemoBookmark      *bookmark);
+gboolean          nemo_bookmark_get_has_custom_name    (NemoBookmark      *bookmark);
 void                  nemo_bookmark_set_custom_name        (NemoBookmark      *bookmark,
-								const char            *new_name);		
-gboolean              nemo_bookmark_uri_known_not_to_exist (NemoBookmark      *bookmark);
+                                const char            *new_name);
 int                   nemo_bookmark_compare_with           (gconstpointer          a,
-								gconstpointer          b);
-int                   nemo_bookmark_compare_uris           (gconstpointer          a,
-								gconstpointer          b);
+                                gconstpointer          b);
 
 void                  nemo_bookmark_set_scroll_pos         (NemoBookmark      *bookmark,
-								const char            *uri);
+                                const char            *uri);
 char *                nemo_bookmark_get_scroll_pos         (NemoBookmark      *bookmark);
 
 
diff --git a/libnemo-private/nemo-file-utilities.c b/libnemo-private/nemo-file-utilities.c
index b4c9f0b..dac26af 100644
--- a/libnemo-private/nemo-file-utilities.c
+++ b/libnemo-private/nemo-file-utilities.c
@@ -26,6 +26,7 @@
 #include "nemo-file-utilities.h"
 
 #include "nemo-global-preferences.h"
+#include "nemo-icon-names.h"
 #include "nemo-lib-self-check-functions.h"
 #include "nemo-metadata.h"
 #include "nemo-file.h"
@@ -980,6 +981,44 @@ have_program_in_path (const char *name)
 	return result;
 }
 
+static GIcon *
+special_directory_get_icon (GUserDirectory directory,
+                gboolean symbolic)
+{
+
+#define ICON_CASE(x)                             \
+    case G_USER_DIRECTORY_ ## x:                     \
+        return (symbolic) ? g_themed_icon_new (NEMO_ICON_FOLDER_ ## x) : g_themed_icon_new (NEMO_ICON_FULLCOLOR_FOLDER_ ## x);
+
+    switch (directory) {
+
+        ICON_CASE (DOCUMENTS);
+        ICON_CASE (DOWNLOAD);
+        ICON_CASE (MUSIC);
+        ICON_CASE (PICTURES);
+        ICON_CASE (PUBLIC_SHARE);
+        ICON_CASE (TEMPLATES);
+        ICON_CASE (VIDEOS);
+
+    default:
+        return (symbolic) ? g_themed_icon_new (NEMO_ICON_FOLDER) : g_themed_icon_new (NEMO_ICON_FULLCOLOR_FOLDER);
+    }
+
+#undef ICON_CASE
+}
+
+GIcon *
+nemo_special_directory_get_symbolic_icon (GUserDirectory directory)
+{
+    return special_directory_get_icon (directory, TRUE);
+}
+
+GIcon *
+nemo_special_directory_get_icon (GUserDirectory directory)
+{
+    return special_directory_get_icon (directory, FALSE);
+}
+
 gboolean
 nemo_is_file_roller_installed (void)
 {
diff --git a/libnemo-private/nemo-file-utilities.h b/libnemo-private/nemo-file-utilities.h
index 77975f9..4a6ff6b 100644
--- a/libnemo-private/nemo-file-utilities.h
+++ b/libnemo-private/nemo-file-utilities.h
@@ -104,4 +104,7 @@ void nemo_get_x_content_types_for_mount_async (GMount *mount,
 						   GCancellable *cancellable,
 						   gpointer user_data);
 
+GIcon * nemo_special_directory_get_icon (GUserDirectory directory);
+GIcon * nemo_special_directory_get_symbolic_icon (GUserDirectory directory);
+
 #endif /* NEMO_FILE_UTILITIES_H */
diff --git a/libnemo-private/nemo-icon-names.h b/libnemo-private/nemo-icon-names.h
index 601c510..34eeb50 100644
--- a/libnemo-private/nemo-icon-names.h
+++ b/libnemo-private/nemo-icon-names.h
@@ -25,6 +25,16 @@
 #define NEMO_ICON_FOLDER_VIDEOS     "folder-videos"
 #define NEMO_ICON_FOLDER_SAVED_SEARCH "folder-saved-search"
 
+#define NEMO_ICON_FULLCOLOR_FOLDER              NEMO_ICON_FOLDER
+#define NEMO_ICON_FULLCOLOR_FOLDER_DOCUMENTS    NEMO_ICON_FOLDER_DOCUMENTS
+#define NEMO_ICON_FULLCOLOR_FOLDER_DOWNLOAD     NEMO_ICON_FOLDER_DOWNLOAD
+#define NEMO_ICON_FULLCOLOR_FOLDER_MUSIC        NEMO_ICON_FOLDER_MUSIC
+#define NEMO_ICON_FULLCOLOR_FOLDER_PICTURES     NEMO_ICON_FOLDER_PICTURES
+#define NEMO_ICON_FULLCOLOR_FOLDER_PUBLIC_SHARE NEMO_ICON_FOLDER_PUBLIC_SHARE
+#define NEMO_ICON_FULLCOLOR_FOLDER_TEMPLATES    NEMO_ICON_FOLDER_TEMPLATES
+#define NEMO_ICON_FULLCOLOR_FOLDER_VIDEOS       NEMO_ICON_FOLDER_VIDEOS
+#define NEMO_ICON_FULLCOLOR_FOLDER_REMOTE       NEMO_ICON_FOLDER_REMOTE
+#define NEMO_ICON_FULLCOLOR_FOLDER_SAVED_SEARCH NEMO_ICON_FOLDER_SAVED_SEARCH
 /* Other icons */
 #define NEMO_ICON_TEMPLATE		"text-x-generic-template"
 
diff --git a/src/nemo-bookmark-list.c b/src/nemo-bookmark-list.c
index a5ec991..91b5abb 100644
--- a/src/nemo-bookmark-list.c
+++ b/src/nemo-bookmark-list.c
@@ -69,7 +69,7 @@ new_bookmark_from_uri (const char *uri, const char *label)
 	new_bookmark = NULL;
 
 	if (location) {
-		new_bookmark = nemo_bookmark_new (location, label, NULL);
+		new_bookmark = nemo_bookmark_new (location, label);
 		g_object_unref (location);
 	}
 
@@ -282,7 +282,7 @@ nemo_bookmark_list_append (NemoBookmarkList *bookmarks,
 	g_return_if_fail (NEMO_IS_BOOKMARK (bookmark));
 
 	insert_bookmark_internal (bookmarks, 
-				  nemo_bookmark_copy (bookmark), 
+				  g_object_ref (bookmark), 
 				  -1);
 
 	nemo_bookmark_list_save_file (bookmarks);
@@ -444,7 +444,7 @@ nemo_bookmark_list_insert_item (NemoBookmarkList *bookmarks,
 	g_return_if_fail (index <= g_list_length (bookmarks->list));
 
 	insert_bookmark_internal (bookmarks,
-				  nemo_bookmark_copy (new_bookmark), 
+				  g_object_ref (new_bookmark), 
 				  index);
 
 	nemo_bookmark_list_save_file (bookmarks);
@@ -485,196 +485,216 @@ nemo_bookmark_list_length (NemoBookmarkList *bookmarks)
 }
 
 static void
-load_file_finish (NemoBookmarkList *bookmarks,
-		  GObject *source,
-		  GAsyncResult *res)
-{
-	GError *error = NULL;
-	gchar *contents = NULL;
-
-	g_file_load_contents_finish (G_FILE (source),
-				     res, &contents, NULL, NULL, &error);
-
-	if (error == NULL) {
-        	char **lines;
-      		int i;
-
-		lines = g_strsplit (contents, "\n", -1);
-      	 	for (i = 0; lines[i]; i++) {
-			/* Ignore empty or invalid lines that cannot be parsed properly */
-	  		if (lines[i][0] != '\0' && lines[i][0] != ' ') {
-				/* gtk 2.7/2.8 might have labels appended to bookmarks which are separated by a space */
-				/* we must seperate the bookmark uri and the potential label */
- 				char *space, *label;
-
-				label = NULL;
-      				space = strchr (lines[i], ' ');
-      				if (space) {
-					*space = '\0';
-					label = g_strdup (space + 1);
-				}
-				insert_bookmark_internal (bookmarks, 
-						          new_bookmark_from_uri (lines[i], label), 
-						          -1);
-
-				g_free (label);
-			}
-		}
-      		g_free (contents);
-       		g_strfreev (lines);
+process_next_op (NemoBookmarkList *bookmarks);
 
-		g_signal_emit (bookmarks, signals[CHANGED], 0);
-	} else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) {
-		g_warning ("Could not load bookmark file: %s\n", error->message);
-		g_error_free (error);
-	}
+static void
+op_processed_cb (NemoBookmarkList *self)
+{
+    g_queue_pop_tail (self->pending_ops);
+
+    if (!g_queue_is_empty (self->pending_ops)) {
+        process_next_op (self);
+    }
 }
 
 static void
-load_file_async (NemoBookmarkList *self,
-		 GAsyncReadyCallback callback)
+load_callback (GObject *source,
+           GAsyncResult *res,
+           gpointer user_data)
 {
-	GFile *file;
+    NemoBookmarkList *self = NEMO_BOOKMARK_LIST (source);
+    gchar *contents;
+    char **lines;
+    int i;
 
-	file = nemo_bookmark_list_get_file ();
+    contents = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res));
 
-	/* Wipe out old list. */
-	clear (self);
+    if (contents == NULL) {
+        return;
+    }
 
-	/* keep the bookmark list alive */
-	g_object_ref (self);
-	g_file_load_contents_async (file, NULL, callback, self);
+    lines = g_strsplit (contents, "\n", -1);
+    for (i = 0; lines[i]; i++) {
+        /* Ignore empty or invalid lines that cannot be parsed properly */
+        if (lines[i][0] != '\0' && lines[i][0] != ' ') {
+            /* gtk 2.7/2.8 might have labels appended to bookmarks which are separated by a space */
+            /* we must seperate the bookmark uri and the potential label */
+            char *space, *label;
+
+            label = NULL;
+            space = strchr (lines[i], ' ');
+            if (space) {
+                *space = '\0';
+                label = g_strdup (space + 1);
+            }
+
+            insert_bookmark_internal (self, new_bookmark_from_uri (lines[i], label), -1);
+            g_free (label);
+        }
+    }
 
-	g_object_unref (file);
+    g_signal_emit (self, signals[CHANGED], 0);
+    op_processed_cb (self);
+
+    g_strfreev (lines);
 }
 
 static void
-save_file_finish (NemoBookmarkList *bookmarks,
-		  GObject *source,
-		  GAsyncResult *res)
+load_io_thread (GSimpleAsyncResult *result,
+        GObject *object,
+        GCancellable *cancellable)
 {
-	GError *error = NULL;
-	GFile *file;
+    GFile *file;
+    gchar *contents;
+    GError *error = NULL;
 
-	g_file_replace_contents_finish (G_FILE (source),
-					res, NULL, &error);
+    file = nemo_bookmark_list_get_file ();
+    if (!g_file_query_exists (file, NULL)) {
+        file = nemo_bookmark_list_get_legacy_file ();
+    }
 
-	if (error != NULL) {
-		g_warning ("Unable to replace contents of the bookmarks file: %s",
-			   error->message);
-		g_error_free (error);
-	}
+    g_file_load_contents (file, NULL, &contents, NULL, NULL, &error);
 
-	file = nemo_bookmark_list_get_file ();
+    if (error != NULL) {
+        if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) {
+            g_warning ("Could not load bookmark file: %s\n", error->message);
+        }
+        g_error_free (error);
+    } else {
+        g_simple_async_result_set_op_res_gpointer (result, contents, g_free);
+    }
+}
 
-	/* re-enable bookmark file monitoring */
-	bookmarks->monitor = g_file_monitor_file (file, 0, NULL, NULL);
-	g_file_monitor_set_rate_limit (bookmarks->monitor, 1000);
-	g_signal_connect (bookmarks->monitor, "changed",
-			  G_CALLBACK (bookmark_monitor_changed_cb), bookmarks);
+static void
+load_file_async (NemoBookmarkList *self)
+{
+    GSimpleAsyncResult *result;
 
-	g_object_unref (file);
+    /* Wipe out old list. */
+    clear (self);
+
+    result = g_simple_async_result_new (G_OBJECT (self), 
+                        load_callback, NULL, NULL);
+    g_simple_async_result_run_in_thread (result, load_io_thread,
+                         G_PRIORITY_DEFAULT, NULL);
+    g_object_unref (result);
 }
 
 static void
-save_file_async (NemoBookmarkList *bookmarks,
-		 GAsyncReadyCallback callback)
+save_callback (GObject *source,
+           GAsyncResult *res,
+           gpointer user_data)
 {
-	GFile *file;
-	GList *l;
-	GString *bookmark_string;
-    GFile *parent;
-    char *path;
-
-	/* temporarily disable bookmark file monitoring when writing file */
-	if (bookmarks->monitor != NULL) {
-		g_file_monitor_cancel (bookmarks->monitor);
-		bookmarks->monitor = NULL;
-	}
+    NemoBookmarkList *self = NEMO_BOOKMARK_LIST (source);
+    GFile *file;
 
-	file = nemo_bookmark_list_get_file ();
-	bookmark_string = g_string_new (NULL);
-
-	for (l = bookmarks->list; l; l = l->next) {
-		NemoBookmark *bookmark;
-
-		bookmark = NEMO_BOOKMARK (l->data);
-
-		/* make sure we save label if it has one for compatibility with GTK 2.7 and 2.8 */
-		if (nemo_bookmark_get_has_custom_name (bookmark)) {
-			const char *label;
-			char *uri;
-			label = nemo_bookmark_get_name (bookmark);
-			uri = nemo_bookmark_get_uri (bookmark);
-			g_string_append_printf (bookmark_string,
-						"%s %s\n", uri, label);
-			g_free (uri);
-		} else {
-			char *uri;
-			uri = nemo_bookmark_get_uri (bookmark);
-			g_string_append_printf (bookmark_string, "%s\n", uri);
-			g_free (uri);
-		}
-	}
+    /* re-enable bookmark file monitoring */
+    file = nemo_bookmark_list_get_file ();
+    self->monitor = g_file_monitor_file (file, 0, NULL, NULL);
+    g_object_unref (file);
+
+    g_file_monitor_set_rate_limit (self->monitor, 1000);
+    g_signal_connect (self->monitor, "changed",
+              G_CALLBACK (bookmark_monitor_changed_cb), self);
 
-	/* keep the bookmark list alive */
-	g_object_ref (bookmarks);
+    op_processed_cb (self);
+}
+
+static void
+save_io_thread (GSimpleAsyncResult *result,
+        GObject *object,
+        GCancellable *cancellable)
+{
+    gchar *contents, *path;
+    GFile *parent, *file;
+    GError *error = NULL;
 
+    file = nemo_bookmark_list_get_file ();
     parent = g_file_get_parent (file);
     path = g_file_get_path (parent);
     g_mkdir_with_parents (path, 0700);
     g_free (path);
     g_object_unref (parent);
 
-	g_file_replace_contents_async (file, bookmark_string->str,
-				       bookmark_string->len, NULL,
-				       FALSE, 0, NULL, callback,
-				       bookmarks);
+    contents = g_simple_async_result_get_op_res_gpointer (result);
+    g_file_replace_contents (file, 
+                 contents, strlen (contents),
+                 NULL, FALSE, 0, NULL,
+                 NULL, &error);
 
-	g_object_unref (file);
-}
+    if (error != NULL) {
+        g_warning ("Unable to replace contents of the bookmarks file: %s",
+               error->message);
+        g_error_free (error);
+    }
 
-static void
-process_next_op (NemoBookmarkList *bookmarks);
+    g_object_unref (file);
+}
 
 static void
-op_processed_cb (GObject *source,
-		 GAsyncResult *res,
-		 gpointer user_data)
+save_file_async (NemoBookmarkList *self)
 {
-	NemoBookmarkList *self = user_data;
-	int op;
+    GSimpleAsyncResult *result;
+    GString *bookmark_string;
+    gchar *contents;
+    GList *l;
 
-	op = GPOINTER_TO_INT (g_queue_pop_tail (self->pending_ops));
+    bookmark_string = g_string_new (NULL);
 
-	if (op == LOAD_JOB) {
-		load_file_finish (self, source, res);
-	} else {
-		save_file_finish (self, source, res);
-	}
+    /* temporarily disable bookmark file monitoring when writing file */
+    if (self->monitor != NULL) {
+        g_file_monitor_cancel (self->monitor);
+        self->monitor = NULL;
+    }
 
-	if (!g_queue_is_empty (self->pending_ops)) {
-		process_next_op (self);
-	}
+    for (l = self->list; l; l = l->next) {
+        NemoBookmark *bookmark;
+
+        bookmark = NEMO_BOOKMARK (l->data);
+
+        /* make sure we save label if it has one for compatibility with GTK 2.7 and 2.8 */
+        if (nemo_bookmark_get_has_custom_name (bookmark)) {
+            const char *label;
+            char *uri;
+            label = nemo_bookmark_get_name (bookmark);
+            uri = nemo_bookmark_get_uri (bookmark);
+            g_string_append_printf (bookmark_string,
+                        "%s %s\n", uri, label);
+            g_free (uri);
+        } else {
+            char *uri;
+            uri = nemo_bookmark_get_uri (bookmark);
+            g_string_append_printf (bookmark_string, "%s\n", uri);
+            g_free (uri);
+        }
+    }
+
+    result = g_simple_async_result_new (G_OBJECT (self),
+                        save_callback, NULL, NULL);
+    contents = g_string_free (bookmark_string, FALSE);
+    g_simple_async_result_set_op_res_gpointer (result, contents, g_free);
 
-	/* release the reference acquired during the _async method */
-	g_object_unref (self);
+    g_simple_async_result_run_in_thread (result, save_io_thread,
+                         G_PRIORITY_DEFAULT, NULL);
+    g_object_unref (result);
 }
 
 static void
 process_next_op (NemoBookmarkList *bookmarks)
 {
-	gint op;
+    gint op;
 
-	op = GPOINTER_TO_INT (g_queue_peek_tail (bookmarks->pending_ops));
+    op = GPOINTER_TO_INT (g_queue_peek_tail (bookmarks->pending_ops));
 
-	if (op == LOAD_JOB) {
-		load_file_async (bookmarks, op_processed_cb);
-	} else {
-		save_file_async (bookmarks, op_processed_cb);
-	}
+    if (op == LOAD_JOB) {
+        load_file_async (bookmarks);
+    } else {
+        save_file_async (bookmarks);
+    }
 }
 
+
+
 /**
  * nemo_bookmark_list_load_file:
  * 
diff --git a/src/nemo-bookmarks-window.c b/src/nemo-bookmarks-window.c
index 86fa6f7..495ea36 100644
--- a/src/nemo-bookmarks-window.c
+++ b/src/nemo-bookmarks-window.c
@@ -798,8 +798,7 @@ update_bookmark_from_text (void)
 			(gtk_entry_get_text (GTK_ENTRY (uri_field)));
 		
 		bookmark = nemo_bookmark_new (location,
-						  name_text_changed ? gtk_entry_get_text (GTK_ENTRY (name_field)) : NULL,
-						  NULL);
+						  name_text_changed ? gtk_entry_get_text (GTK_ENTRY (name_field)) : NULL);
 		
 		g_object_unref (location);
 
diff --git a/src/nemo-places-sidebar.c b/src/nemo-places-sidebar.c
index 5b1a4b9..68e7e9e 100644
--- a/src/nemo-places-sidebar.c
+++ b/src/nemo-places-sidebar.c
@@ -321,7 +321,7 @@ static gboolean
 is_built_in_bookmark (NemoFile *file)
 {
 	gboolean built_in;
-	gint idx;
+	// gint idx;
 
 	if (nemo_file_is_home (file)) {
 		return TRUE;
@@ -333,16 +333,16 @@ is_built_in_bookmark (NemoFile *file)
 
 	built_in = FALSE;
 
-	for (idx = 0; idx < G_USER_N_DIRECTORIES; idx++) {
-		/* PUBLIC_SHARE and TEMPLATES are not in our built-in list */
-		if (nemo_file_is_user_special_directory (file, idx)) {
-			if (idx != G_USER_DIRECTORY_PUBLIC_SHARE &&  idx != G_USER_DIRECTORY_TEMPLATES) {
-				built_in = TRUE;
-			}
+	// for (idx = 0; idx < G_USER_N_DIRECTORIES; idx++) {
+	// 	/* PUBLIC_SHARE and TEMPLATES are not in our built-in list */
+	// 	if (nemo_file_is_user_special_directory (file, idx)) {
+	// 		if (idx != G_USER_DIRECTORY_PUBLIC_SHARE &&  idx != G_USER_DIRECTORY_TEMPLATES) {
+	// 			built_in = TRUE;
+	// 		}
 
-			break;
-		}
-	}
+	// 		break;
+	// 	}
+	// }
 
 	return built_in;
 }
@@ -753,19 +753,22 @@ update_places (NemoPlacesSidebar *sidebar)
     bookmark_count = nemo_bookmark_list_length (sidebar->bookmarks);
     for (index = 0; index < bookmark_count; ++index) {
         bookmark = nemo_bookmark_list_item_at (sidebar->bookmarks, index);
+        root = nemo_bookmark_get_location (bookmark);
 
-        if (nemo_bookmark_uri_known_not_to_exist (bookmark)) {
+        if (!nemo_bookmark_get_exists (bookmark) && g_file_is_native (root)) {
+            g_printerr ("blah\n");
+            g_object_unref (root);
             continue;
         }
 
-        root = nemo_bookmark_get_location (bookmark);
         file = nemo_file_get (root);
 
-        //if (is_built_in_bookmark (file)) {
-        //  g_object_unref (root);
-        //  nemo_file_unref (file);
-        //  continue;
-        //}
+        if (is_built_in_bookmark (file)) {
+            g_printerr ("book\n");
+            g_object_unref (root);
+            nemo_file_unref (file);
+            continue;
+        }
         nemo_file_unref (file);
 
         bookmark_name = nemo_bookmark_get_name (bookmark);
@@ -1684,7 +1687,7 @@ bookmarks_drop_uris (NemoPlacesSidebar *sidebar,
 		location = g_file_new_for_uri (uri);
 		nemo_file_unref (file);
 
-		bookmark = nemo_bookmark_new (location, NULL, NULL);
+		bookmark = nemo_bookmark_new (location, NULL);
 
 		if (!nemo_bookmark_list_contains (sidebar->bookmarks, bookmark)) {
 			nemo_bookmark_list_insert_item (sidebar->bookmarks, bookmark, position++);
@@ -2377,7 +2380,7 @@ add_bookmark (NemoPlacesSidebar *sidebar)
 		}
 
 		location = g_file_new_for_uri (uri);
-		bookmark = nemo_bookmark_new (location, NULL, NULL);
+		bookmark = nemo_bookmark_new (location, NULL);
 
 		if (!nemo_bookmark_list_contains (sidebar->bookmarks, bookmark)) {
 			nemo_bookmark_list_append (sidebar->bookmarks, bookmark);
diff --git a/src/nemo-view.c b/src/nemo-view.c
index 9e8eba9..6c17acb 100644
--- a/src/nemo-view.c
+++ b/src/nemo-view.c
@@ -5072,7 +5072,7 @@ reset_move_copy_to_menu (NemoView *view)
         for (index = 0; index < bookmark_count; ++index) {
             bookmark = nemo_bookmark_list_item_at (view->details->bookmarks, index);
 
-            if (nemo_bookmark_uri_known_not_to_exist (bookmark)) {
+            if (!nemo_bookmark_get_exists (bookmark)) {
                 continue;
             }
 
diff --git a/src/nemo-window-bookmarks.c b/src/nemo-window-bookmarks.c
index 99ca16f..8e9046b 100644
--- a/src/nemo-window-bookmarks.c
+++ b/src/nemo-window-bookmarks.c
@@ -269,7 +269,7 @@ activate_bookmark_in_menu_item (GtkAction *action, gpointer user_data)
 
         holder = (BookmarkHolder *)user_data;
 
-	if (nemo_bookmark_uri_known_not_to_exist (holder->bookmark)) {
+	if (!nemo_bookmark_get_exists (holder->bookmark)) {
 		holder->failed_callback (holder->window, holder->bookmark);
 	} else {
 	        location = nemo_bookmark_get_location (holder->bookmark);
@@ -383,7 +383,7 @@ update_bookmarks (NemoWindow *window)
 	for (index = 0; index < bookmark_count; ++index) {
 		bookmark = nemo_bookmark_list_item_at (bookmarks, index);
 
-		if (nemo_bookmark_uri_known_not_to_exist (bookmark)) {
+		if (!nemo_bookmark_get_exists (bookmark)) {
 			continue;
 		}
 
diff --git a/src/nemo-window-manage-views.c b/src/nemo-window-manage-views.c
index ef76f12..75d4f46 100644
--- a/src/nemo-window-manage-views.c
+++ b/src/nemo-window-manage-views.c
@@ -123,7 +123,7 @@ set_displayed_location (NemoWindowSlot *slot, GFile *location)
 
 		slot->last_location_bookmark = slot->current_location_bookmark;
 		slot->current_location_bookmark = (location == NULL) ? NULL
-                        : nemo_bookmark_new (location, NULL, NULL);
+                        : nemo_bookmark_new (location, NULL);
         }
 }
 
-- 
1.9.3