[PATCH] - New sidepanel plug-in for Gtk bookmarks and places




Attached is a patch (+2 new files) for a cool new sidepanel plug-in for the browser that mimics the GTK FileChooser. Files nautilus-places-sidebar.* need to be in the src subdirectory.

See my new blog for further info and screenshots:
http://www.advogato.org/person/jamiemcc/diary.html?start=0

jamie.
Index: src/nautilus-application.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/nautilus-application.c,v
retrieving revision 1.232
diff -u -r1.232 nautilus-application.c
--- src/nautilus-application.c	3 Mar 2005 16:01:44 -0000	1.232
+++ src/nautilus-application.c	27 Jun 2005 13:17:24 -0000
@@ -36,6 +36,7 @@
 #include "file-manager/fm-tree-view.h"
 #include "nautilus-information-panel.h"
 #include "nautilus-history-sidebar.h"
+#include "nautilus-places-sidebar.h"
 #include "nautilus-notes-viewer.h"
 #include "nautilus-emblem-sidebar.h"
 #include "nautilus-image-properties-page.h"
@@ -176,6 +177,7 @@
 	fm_list_view_register ();
 
 	/* register sidebars */
+	nautilus_places_sidebar_register ();
 	nautilus_information_panel_register ();
 	fm_tree_view_register ();
 	nautilus_history_sidebar_register ();
Index: src/Makefile.am
===================================================================
RCS file: /cvs/gnome/nautilus/src/Makefile.am,v
retrieving revision 1.158
diff -u -r1.158 Makefile.am
--- src/Makefile.am	14 Jan 2005 11:11:38 -0000	1.158
+++ src/Makefile.am	27 Jun 2005 13:17:26 -0000
@@ -95,6 +95,8 @@
 	nautilus-navigation-window.h            \
 	nautilus-notes-viewer.c			\
 	nautilus-notes-viewer.h			\
+	nautilus-places-sidebar.c		\
+	nautilus-places-sidebar.h		\
 	nautilus-property-browser.c     	\
 	nautilus-property-browser.h		\
 	nautilus-self-check-functions.c 	\
Index: src/nautilus-navigation-window-menus.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/nautilus-navigation-window-menus.c,v
retrieving revision 1.270
diff -u -r1.270 nautilus-navigation-window-menus.c
--- src/nautilus-navigation-window-menus.c	17 Feb 2005 02:51:08 -0000	1.270
+++ src/nautilus-navigation-window-menus.c	27 Jun 2005 13:17:28 -0000
@@ -69,7 +69,7 @@
 #define RESPONSE_FORGET		1000
 
 static GtkWindow *bookmarks_window = NULL;
-static NautilusBookmarkList *bookmarks = NULL;
+static NautilusBookmarkList *bookmarks;
 
 static void                  schedule_refresh_go_menu                      (NautilusNavigationWindow   *window);
 static void                  append_dynamic_bookmarks                      (NautilusNavigationWindow   *window);
@@ -77,7 +77,7 @@
 static void                  refresh_bookmarks_menu                        (NautilusNavigationWindow   *window);
 static void                  add_bookmark_for_current_location             (NautilusNavigationWindow   *window);
 static void                  edit_bookmarks                                (NautilusNavigationWindow   *window);
-static NautilusBookmarkList *get_bookmark_list                             (void);
+
 
 static void
 action_close_all_windows_callback (GtkAction *action, 
@@ -237,22 +237,7 @@
         edit_bookmarks (NAUTILUS_NAVIGATION_WINDOW (user_data));
 }
 
-static void
-free_bookmark_list (void)
-{
-	g_object_unref (bookmarks);
-}
 
-static NautilusBookmarkList *
-get_bookmark_list (void)
-{
-        if (bookmarks == NULL) {
-                bookmarks = nautilus_bookmark_list_new ();
-                eel_debug_call_at_shutdown (free_bookmark_list);
-        }
-	
-        return bookmarks;
-}
 
 
 static void
@@ -265,7 +250,7 @@
 
 	if (response == GTK_RESPONSE_YES) {
 		uri = callback_data;
-		nautilus_bookmark_list_delete_items_with_uri (get_bookmark_list (), uri);
+		nautilus_bookmark_list_delete_items_with_uri (bookmarks, uri);
 	}
 
 	gtk_object_destroy (GTK_OBJECT (dialog));
@@ -310,7 +295,7 @@
 get_or_create_bookmarks_window (GObject *undo_manager_source)
 {
 	if (bookmarks_window == NULL) {
-		bookmarks_window = create_bookmarks_window (get_bookmark_list(), undo_manager_source);
+		bookmarks_window = create_bookmarks_window (bookmarks, undo_manager_source);
 	} else {
 		edit_bookmarks_dialog_set_signals (undo_manager_source);
 	}
@@ -347,8 +332,8 @@
 
 	bookmark = NAUTILUS_WINDOW (window)->current_location_bookmark;
 
-	if (!nautilus_bookmark_list_contains (get_bookmark_list (), bookmark)) {
-		nautilus_bookmark_list_append (get_bookmark_list (), bookmark); 
+	if (!nautilus_bookmark_list_contains (bookmarks, bookmark)) {
+		nautilus_bookmark_list_append (bookmarks, bookmark); 
 	}
 }
 
@@ -388,10 +373,11 @@
 	g_assert (NAUTILUS_IS_NAVIGATION_WINDOW (window));
 
 	/* Construct the initial set of bookmarks. */
+	bookmarks = nautilus_window_get_bookmark_list (NAUTILUS_WINDOW (window));
 	refresh_bookmarks_menu (window);
 
 	/* Recreate dynamic part of menu if bookmark list changes */
-	g_signal_connect_object (get_bookmark_list (), "contents_changed",
+	g_signal_connect_object (bookmarks, "contents_changed",
 				 G_CALLBACK (schedule_refresh_bookmarks_menu),
 				 window, G_CONNECT_SWAPPED);
 
@@ -701,7 +687,7 @@
 	g_assert (window->details->bookmarks_merge_id == 0);
 	g_assert (window->details->bookmarks_action_group == NULL);
 
-	bookmarks = get_bookmark_list ();
+	bookmarks = nautilus_window_get_bookmark_list (NAUTILUS_WINDOW (window));
 
 	ui_manager = nautilus_window_get_ui_manager (NAUTILUS_WINDOW (window));
 	
@@ -741,7 +727,7 @@
 static void
 schedule_refresh_bookmarks_menu (NautilusNavigationWindow *window)
 {
-	g_assert (NAUTILUS_IS_NAVIGATION_WINDOW (window));
+	g_return_if_fail (NAUTILUS_IS_NAVIGATION_WINDOW (window));
 
 	if (window->details->refresh_bookmarks_menu_idle_id == 0) {
                 window->details->refresh_bookmarks_menu_idle_id
Index: src/nautilus-window.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/nautilus-window.c,v
retrieving revision 1.443
diff -u -r1.443 nautilus-window.c
--- src/nautilus-window.c	22 Feb 2005 08:46:38 -0000	1.443
+++ src/nautilus-window.c	27 Jun 2005 13:17:30 -0000
@@ -32,6 +32,7 @@
 
 #include "nautilus-actions.h"
 #include "nautilus-application.h"
+#include "nautilus-bookmark-list.h"
 #include "nautilus-bookmarks-window.h"
 #include "nautilus-information-panel.h"
 #include "nautilus-main.h"
@@ -119,6 +120,7 @@
 					     ActivateViewData        *data);
 
 static GList *history_list;
+static NautilusBookmarkList *bookmarks = NULL;
 
 G_DEFINE_TYPE_WITH_CODE (NautilusWindow, nautilus_window, GTK_TYPE_WINDOW,
 			 G_IMPLEMENT_INTERFACE (NAUTILUS_TYPE_WINDOW_INFO,
@@ -1352,12 +1354,30 @@
 	return history_list;
 }
 
+
+static void
+free_bookmark_list (void)
+{
+	g_object_unref (bookmarks);
+}
+
 static GList *
 nautilus_window_get_history (NautilusWindow *window)
 {
 	return eel_g_object_list_copy (history_list);
 }
 
+NautilusBookmarkList *
+nautilus_window_get_bookmark_list (NautilusWindow *window)
+{
+        if (bookmarks == NULL) {
+                bookmarks = nautilus_bookmark_list_new ();
+                eel_debug_call_at_shutdown (free_bookmark_list);
+        }
+	
+        return bookmarks;
+}
+
 
 static NautilusWindowType
 nautilus_window_get_window_type (NautilusWindow *window)
@@ -1412,6 +1432,7 @@
 	iface->get_window_type = nautilus_window_get_window_type;
 	iface->get_title = nautilus_window_get_cached_title;
 	iface->get_history = nautilus_window_get_history;
+	iface->get_bookmark_list = nautilus_window_get_bookmark_list;
 	iface->get_current_location = nautilus_window_get_location;
 	iface->get_ui_manager = nautilus_window_get_ui_manager;
 	iface->get_selection_count = nautilus_window_get_selection_count;
Index: src/nautilus-window.h
===================================================================
RCS file: /cvs/gnome/nautilus/src/nautilus-window.h,v
retrieving revision 1.117
diff -u -r1.117 nautilus-window.h
--- src/nautilus-window.h	22 Nov 2004 15:24:37 -0000	1.117
+++ src/nautilus-window.h	27 Jun 2005 13:17:31 -0000
@@ -37,6 +37,7 @@
 #include "nautilus-application.h"
 #include "nautilus-information-panel.h"
 #include "nautilus-side-pane.h"
+#include "nautilus-bookmark-list.h"
 
 #define NAUTILUS_TYPE_WINDOW              (nautilus_window_get_type())
 #define NAUTILUS_WINDOW(obj)	          (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_WINDOW, NautilusWindow))
@@ -109,7 +110,12 @@
         NautilusView *new_content_view;
 };
 
+NautilusBookmarkList * nautilus_window_get_bookmark_list (NautilusWindow *window);
+
+
+
 GType            nautilus_window_get_type             (void);
+
 void             nautilus_window_close                (NautilusWindow    *window);
 char *           nautilus_window_get_location         (NautilusWindow    *window);
 void             nautilus_window_go_to                (NautilusWindow    *window,
Index: libnautilus-private/nautilus-window-info.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-window-info.c,v
retrieving revision 1.2
diff -u -r1.2 nautilus-window-info.c
--- libnautilus-private/nautilus-window-info.c	22 Nov 2004 15:24:36 -0000	1.2
+++ libnautilus-private/nautilus-window-info.c	27 Jun 2005 13:17:31 -0000
@@ -209,6 +209,15 @@
 	return (* NAUTILUS_WINDOW_INFO_GET_IFACE (window)->get_history) (window);
 }
 
+NautilusBookmarkList *
+nautilus_window_info_get_bookmark_list (NautilusWindowInfo *window)
+{
+	g_return_val_if_fail (NAUTILUS_IS_WINDOW_INFO (window), NULL);
+	
+	return (* NAUTILUS_WINDOW_INFO_GET_IFACE (window)->get_bookmark_list) (window);
+}
+
+
 char *
 nautilus_window_info_get_current_location (NautilusWindowInfo *window)
 {
Index: libnautilus-private/nautilus-window-info.h
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-window-info.h,v
retrieving revision 1.2
diff -u -r1.2 nautilus-window-info.h
--- libnautilus-private/nautilus-window-info.h	22 Nov 2004 15:24:36 -0000	1.2
+++ libnautilus-private/nautilus-window-info.h	27 Jun 2005 13:17:32 -0000
@@ -28,6 +28,9 @@
 #include <glib-object.h>
 #include <libnautilus-private/nautilus-view.h>
 #include <gtk/gtkuimanager.h>
+#include "../src/nautilus-bookmark-list.h"
+
+
 
 G_BEGIN_DECLS
 
@@ -110,11 +113,14 @@
 	/* Returns a list of uris for th selected items in the view, caller frees it */	
 	GList *(* get_selection)      (NautilusWindowInfo    *window);
 
-	char * (* get_current_location)  (NautilusWindowInfo *window);
-	void   (* set_status)            (NautilusWindowInfo *window,
-					  const char *status);
-	char * (* get_title)             (NautilusWindowInfo *window);
-	GList *(* get_history)           (NautilusWindowInfo *window);
+	char * 			(* get_current_location)  (NautilusWindowInfo *window);
+	void   			(* set_status)            (NautilusWindowInfo *window,
+							  const char *status);
+	char * 			(* get_title)             (NautilusWindowInfo *window);
+	GList *			(* get_history)           (NautilusWindowInfo *window);
+	NautilusBookmarkList *  (* get_bookmark_list)     (NautilusWindowInfo *window);
+	
+	
 	NautilusWindowType
 	       (* get_window_type)       (NautilusWindowInfo *window);
 	NautilusWindowShowHiddenFilesMode
@@ -150,6 +156,7 @@
 NautilusWindowType                nautilus_window_info_get_window_type          (NautilusWindowInfo                *window);
 char *                            nautilus_window_info_get_title                (NautilusWindowInfo                *window);
 GList *                           nautilus_window_info_get_history              (NautilusWindowInfo                *window);
+NautilusBookmarkList *		  nautilus_window_info_get_bookmark_list        (NautilusWindowInfo                *window);
 char *                            nautilus_window_info_get_current_location     (NautilusWindowInfo                *window);
 int                               nautilus_window_info_get_selection_count      (NautilusWindowInfo                *window);
 GList *                           nautilus_window_info_get_selection            (NautilusWindowInfo                *window);
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */

/*
 *  Nautilus
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU General Public License as
 *  published by the Free Software Foundation; either version 2 of the
 *  License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this library; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *  Author : Mr Jamie McCracken (jamiemcc at blueyonder dot co dot uk)
 *
 */
 
#include <config.h>

#include <eel/eel-debug.h>
#include <eel/eel-gtk-extensions.h>
#include <eel/eel-glib-extensions.h>
#include <eel/eel-preferences.h>
#include <eel/eel-string.h>
#include <gtk/gtkalignment.h>
#include <gtk/gtkbutton.h>
#include <gtk/gtkhbox.h>
#include <gtk/gtkvbox.h>
#include <gtk/gtkcellrendererpixbuf.h>
#include <gtk/gtkcellrenderertext.h>
#include <gtk/gtkliststore.h>
#include <gtk/gtksizegroup.h>
#include <gtk/gtkstock.h>
#include <gtk/gtktreemodel.h>
#include <gtk/gtktreeselection.h>
#include <libgnome/gnome-macros.h>
#include <libgnome/gnome-i18n.h>
#include <libnautilus-private/nautilus-bookmark.h>
#include <libnautilus-private/nautilus-global-preferences.h>
#include <libnautilus-private/nautilus-sidebar-provider.h>
#include <libnautilus-private/nautilus-module.h>
#include <libnautilus-private/nautilus-file-utilities.h>
#include <libgnomevfs/gnome-vfs-utils.h>
#include <libgnomevfs/gnome-vfs-volume-monitor.h>

#include "nautilus-bookmark-list.h"
#include "nautilus-places-sidebar.h"

#define NAUTILUS_PLACES_SIDEBAR_CLASS(klass)    (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_PLACES_SIDEBAR, NautilusPlacesSidebarClass))
#define NAUTILUS_IS_PLACES_SIDEBAR(obj)         (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_PLACES_SIDEBAR))
#define NAUTILUS_IS_PLACES_SIDEBAR_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_PLACES_SIDEBAR))

typedef struct {
	GtkScrolledWindowClass parent;
} NautilusPlacesSidebarClass;

typedef struct {
        GObject parent;
} NautilusPlacesSidebarProvider;

typedef struct {
        GObjectClass parent;
} NautilusPlacesSidebarProviderClass;


enum {
	PLACES_SIDEBAR_COLUMN_ICON,
	PLACES_SIDEBAR_COLUMN_NAME,
	PLACES_SIDEBAR_COLUMN_BOOKMARK,
	PLACES_SIDEBAR_COLUMN_BOOKMARK_TYPE,
	PLACES_SIDEBAR_COLUMN_COUNT
};

typedef enum {
	PLACES_BUILT_IN,
	PLACES_MOUNTED_VOLUME,
	PLACES_BOOKMARK,
	PLACES_SEPARATOR
} PlaceType;

static NautilusBookmarkList *bookmarks;

static void  nautilus_places_sidebar_iface_init        (NautilusSidebarIface         *iface);
static void  sidebar_provider_iface_init               (NautilusSidebarProviderIface *iface);
static GType nautilus_places_sidebar_provider_get_type (void);

G_DEFINE_TYPE_WITH_CODE (NautilusPlacesSidebar, nautilus_places_sidebar, GTK_TYPE_SCROLLED_WINDOW,
			 G_IMPLEMENT_INTERFACE (NAUTILUS_TYPE_SIDEBAR,
						nautilus_places_sidebar_iface_init));

G_DEFINE_TYPE_WITH_CODE (NautilusPlacesSidebarProvider, nautilus_places_sidebar_provider, G_TYPE_OBJECT,
			 G_IMPLEMENT_INTERFACE (NAUTILUS_TYPE_SIDEBAR_PROVIDER,
						sidebar_provider_iface_init));


static GtkTreeIter
add_place (GtkListStore *store, NautilusBookmark *bookmark, PlaceType place_type, const char *icon)
{
	GdkPixbuf            *pixbuf;
	GtkTreeIter           iter;
	char 		     *name;

	if (!icon) { 
		pixbuf = nautilus_bookmark_get_pixbuf (bookmark, NAUTILUS_ICON_SIZE_FOR_MENUS, FALSE);
	} else {
		pixbuf = nautilus_icon_factory_get_pixbuf_from_name (icon, NULL, NAUTILUS_ICON_SIZE_FOR_MENUS, TRUE, NULL);
	}
	name = nautilus_bookmark_get_name (bookmark);
	gtk_list_store_append (store, &iter);
	gtk_list_store_set (store, &iter,
			    PLACES_SIDEBAR_COLUMN_ICON, pixbuf,
			    PLACES_SIDEBAR_COLUMN_NAME, name,
			    PLACES_SIDEBAR_COLUMN_BOOKMARK, bookmark,
			    PLACES_SIDEBAR_COLUMN_BOOKMARK_TYPE, place_type,
			    -1);
	if (pixbuf != NULL) {
		g_object_unref (pixbuf);
	}
	g_free (name);
	return iter;

}



static void
update_places (NautilusPlacesSidebar *sidebar)
{
	GtkListStore          *store;
	NautilusBookmark      *bookmark;
	GtkTreeSelection      *selection;
	GtkTreeIter           iter, last_iter;
	GnomeVFSVolumeMonitor *volume_monitor;
	GList 		      *volumes, *l;
	GnomeVFSVolume 	      *volume;
	int 		      bookmark_count, index;
	char 		      *uri, *location, *icon, *mount_uri, *name, *file_path;
		
	g_assert (bookmarks != NULL);
	store = GTK_LIST_STORE (gtk_tree_view_get_model (sidebar->tree_view));
	selection = gtk_tree_view_get_selection (sidebar->tree_view);
	gtk_list_store_clear (store);
	location = nautilus_window_info_get_current_location (sidebar->window);

	/* add built in bookmarks */

	file_path = g_build_filename (g_get_home_dir (), "Documents", NULL);
	if (g_file_test (file_path, G_FILE_TEST_IS_DIR)) {
		mount_uri = g_strconcat ("file://", file_path, NULL);
		name = g_strdup ("Documents");
		bookmark = nautilus_bookmark_new (mount_uri, name);
		last_iter = add_place (store, bookmark, PLACES_BUILT_IN, NULL);
		if (strcmp (location, mount_uri) == 0) {
			gtk_tree_selection_select_iter (selection, &last_iter);
		}	
		g_free (mount_uri);
		g_free (name);
	}
	g_free (file_path);

	file_path = g_strdup (g_get_home_dir ());
 	mount_uri = g_strconcat ("file://", file_path, NULL);
	name = g_strdup ("Home");
	bookmark = nautilus_bookmark_new (mount_uri, name);
	last_iter = add_place (store, bookmark, PLACES_BUILT_IN, NULL);
	if (strcmp (location, mount_uri) == 0) {
		gtk_tree_selection_select_iter (selection, &last_iter);
	}	
	g_free (mount_uri);
	g_free (name);
	g_free (file_path);

	file_path = g_build_filename (g_get_home_dir (), "Desktop", NULL);
	if (g_file_test (file_path, G_FILE_TEST_IS_DIR)) {
		mount_uri = g_strconcat ("file://", file_path, NULL);
		name = g_strdup ("Desktop");
		bookmark = nautilus_bookmark_new (mount_uri, name);
		last_iter = add_place (store, bookmark, PLACES_BUILT_IN, "gnome-fs-desktop");
		if (strcmp (location, mount_uri) == 0) {
			gtk_tree_selection_select_iter (selection, &last_iter);
		}	
		g_free (mount_uri);
		g_free (name);
	}
	g_free (file_path);
	
 	mount_uri = g_strdup ("file:///");
	name = g_strdup ("Filesystem");
	bookmark = nautilus_bookmark_new (mount_uri, name);
	last_iter = add_place (store, bookmark, PLACES_BUILT_IN, "gnome-fs-blockdev");
	if (strcmp (location, mount_uri) == 0) {
		gtk_tree_selection_select_iter (selection, &last_iter);
	}	
	g_free (mount_uri);
	g_free (name);



	/* add mounted volumes */

	volume_monitor = gnome_vfs_get_volume_monitor ();
	volumes = gnome_vfs_volume_monitor_get_mounted_volumes (volume_monitor);
	for (l = volumes; l != NULL; l = l->next) {
		volume = l->data;
		if (!gnome_vfs_volume_is_user_visible (volume)) {
			gnome_vfs_volume_unref (volume);
			continue;
		}
		icon = gnome_vfs_volume_get_icon (volume);
		mount_uri = gnome_vfs_volume_get_activation_uri (volume);
		name = gnome_vfs_volume_get_display_name (volume);
		bookmark = nautilus_bookmark_new (mount_uri, name);
		last_iter = add_place (store, bookmark, PLACES_MOUNTED_VOLUME, icon);
		if (strcmp (location, mount_uri) == 0) {
			gtk_tree_selection_select_iter (selection, &last_iter);
		}
		gnome_vfs_volume_unref (volume);
		g_free (icon);
		g_free (name);
		g_free (mount_uri);

	}
	g_list_free (volumes);
	

	/* add separator */

	gtk_list_store_append (store, &iter);
	gtk_list_store_set (store, &iter,
			    PLACES_SIDEBAR_COLUMN_BOOKMARK_TYPE, PLACES_SEPARATOR,
			    -1);

	/* add bookmarks */

	bookmark_count = nautilus_bookmark_list_length (bookmarks);
	for (index = 0; index < bookmark_count; ++index) {
		bookmark = nautilus_bookmark_list_item_at (bookmarks, index),
		last_iter = add_place (store, bookmark, PLACES_BOOKMARK, NULL);
		
		/* set selection if place is the current location */
		uri = nautilus_bookmark_get_uri (bookmark);
		
		if (strcmp (location, uri) == 0) {
			gtk_tree_selection_select_iter (selection, &last_iter);
		}
		g_free (uri);
	}

	g_free (location);
	
}


static void
selection_changed_callback (GtkTreeSelection *selection,
		      	    gpointer user_data)
{
	GtkTreeModel     	*model;
	GtkTreeIter      	iter;
	PlaceType	 	type; 
	NautilusPlacesSidebar 	*sidebar;

	sidebar = NAUTILUS_PLACES_SIDEBAR (user_data);

	/* only bookmarks can be removed */
	if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
    		gtk_tree_model_get (model, &iter, PLACES_SIDEBAR_COLUMN_BOOKMARK_TYPE, &type, -1);
		gtk_widget_set_sensitive (sidebar->remove_button, (type == PLACES_BOOKMARK));
	}
}

static gboolean
shortcuts_row_separator_func (GtkTreeModel *model,
			      GtkTreeIter  *iter,
			      gpointer      data)
{
	gint column;
  	char *text;

	column = GPOINTER_TO_INT (data);
  	gtk_tree_model_get (model, iter, column, &text, -1);
  
  	if (!text) {
   		return TRUE;
	}

  	g_free (text);

  	return FALSE;
}


static GtkWidget *
button_new (const char *text,
	    const char *stock_id,
	    gboolean    sensitive,
	    gboolean    show,
	    GCallback   callback,
	    gpointer    user_data)
{
	GtkWidget *button;
	GtkWidget *hbox;
	GtkWidget *widget;
	GtkWidget *align;

	button = gtk_button_new ();
	hbox = gtk_hbox_new (FALSE, 2);
	align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
	
	gtk_container_add (GTK_CONTAINER (button), align);
	gtk_container_add (GTK_CONTAINER (align), hbox);
	widget = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_BUTTON);

  	gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);

  	widget = gtk_label_new_with_mnemonic (text);
	gtk_label_set_mnemonic_widget (GTK_LABEL (widget), GTK_WIDGET (button));
	gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
	
	gtk_widget_set_sensitive (button, sensitive);
  	g_signal_connect (button, "clicked", callback, user_data);

  	gtk_widget_show_all (align);

	if (show) {
		gtk_widget_show (button);
	}
	return button;
}

static void
volume_mounted_callback (GnomeVFSVolumeMonitor *volume_monitor,
			 GnomeVFSVolume *volume,
			 NautilusPlacesSidebar *sidebar)
{
	update_places (sidebar);
}

static void
volume_unmounted_callback (GnomeVFSVolumeMonitor *volume_monitor,
			   GnomeVFSVolume *volume,
			   NautilusPlacesSidebar *sidebar)
{
	update_places (sidebar);
}



static void
row_activated_callback (GtkTreeView *tree_view,
			GtkTreePath *path,
			GtkTreeViewColumn *column,
			gpointer user_data)
{
	NautilusPlacesSidebar *sidebar;
	GtkTreeModel *model;
	GtkTreeIter iter;
	NautilusBookmark *bookmark;
	char *uri;
	
	sidebar = NAUTILUS_PLACES_SIDEBAR (user_data);
	model = gtk_tree_view_get_model (tree_view);
	
	if (!gtk_tree_model_get_iter (model, &iter, path)) {
		return;
	}
	

	gtk_tree_model_get 
		(model, &iter, PLACES_SIDEBAR_COLUMN_BOOKMARK, &bookmark, -1);
	if (!bookmark) {
		return;
	}
	
	/* Navigate to the clicked location. */
	uri = nautilus_bookmark_get_uri (NAUTILUS_BOOKMARK (bookmark));
	nautilus_window_info_open_location
		(sidebar->window, 
		 uri, NAUTILUS_WINDOW_OPEN_ACCORDING_TO_MODE, 0, NULL);
	g_free (uri);
}

static void
update_click_policy (NautilusPlacesSidebar *sidebar)
{
	int policy;
	
	policy = eel_preferences_get_enum (NAUTILUS_PREFERENCES_CLICK_POLICY);
	
	eel_gtk_tree_view_set_activate_on_single_click
		(sidebar->tree_view, policy == NAUTILUS_CLICK_POLICY_SINGLE);
}

static void
click_policy_changed_callback (gpointer user_data)
{
	NautilusPlacesSidebar *sidebar;
	
	sidebar = NAUTILUS_PLACES_SIDEBAR (user_data);

	update_click_policy (sidebar);
}

static void
add_bookmark_button_clicked_callback (GtkButton *button, gpointer user_data)
{
	NautilusPlacesSidebar 	 *sidebar;
	NautilusBookmark     	 *bookmark;
	GtkListStore	         *store;
	char			 *name;

	sidebar = NAUTILUS_PLACES_SIDEBAR (user_data);
	store = GTK_LIST_STORE (gtk_tree_view_get_model (sidebar->tree_view));
	name = nautilus_compute_title_for_uri (sidebar->uri);
	bookmark = nautilus_bookmark_new (sidebar->uri, name);
	g_free (name);
	nautilus_bookmark_list_append (bookmarks, bookmark);
}

static void
remove_bookmark_button_clicked_callback (GtkButton *button, gpointer user_data)
{
	GtkTreeSelection 	*selection;
	GtkTreeModel     	*model;
	GtkTreeIter       	iter;
	PlaceType	 	type; 
	NautilusPlacesSidebar 	*sidebar;
	NautilusBookmark     	*bookmark;
	char *			uri;

	sidebar = NAUTILUS_PLACES_SIDEBAR (user_data);
	selection = gtk_tree_view_get_selection (sidebar->tree_view);
	if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
    		gtk_tree_model_get (model, &iter, PLACES_SIDEBAR_COLUMN_BOOKMARK_TYPE, &type, -1);
		if (type == PLACES_BOOKMARK) {
			gtk_tree_model_get (model, &iter, PLACES_SIDEBAR_COLUMN_BOOKMARK, &bookmark, -1);
			g_assert (bookmark != NULL);
			uri = nautilus_bookmark_get_uri (bookmark);
			nautilus_bookmark_list_delete_items_with_uri (bookmarks, uri);
			g_free (uri);
		}
  	}
}


static void
loading_uri_callback (NautilusWindowInfo *window,
		      char *location,
		      NautilusPlacesSidebar *sidebar)
{
	GtkTreeSelection *selection;
	GtkTreeIter 	 iter;
	GtkListStore     *store;
	gboolean 	 valid;
	NautilusBookmark *bookmark;
	char  		 *uri;

        if (strcmp (sidebar->uri, location) != 0) {
		if (sidebar->uri) {
	                g_free (sidebar->uri);
		}
                sidebar->uri = g_strdup (location);
        }       
  
	/* set selection if any place matches location */
 	store = GTK_LIST_STORE (gtk_tree_view_get_model (sidebar->tree_view));
	selection = gtk_tree_view_get_selection (sidebar->tree_view);
	gtk_tree_selection_unselect_all (selection);
  	valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter);

	while (valid) {
    	
		gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, 
	        		PLACES_SIDEBAR_COLUMN_BOOKMARK, &bookmark,
	                        -1);
		if (bookmark) {
			uri = nautilus_bookmark_get_uri (bookmark);
			if (strcmp (uri, location) == 0) {
				gtk_tree_selection_select_iter (selection, &iter);
				break;
			}
			g_free (uri);
		}
         	valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter);
    	}
}


static void
nautilus_places_sidebar_init (NautilusPlacesSidebar *sidebar)
{
	GtkTreeView       *tree_view;
	GtkTreeViewColumn *col;
	GtkCellRenderer   *cell;
	GtkListStore      *store;
	GtkTreeSelection  *selection;
	GtkWidget 	  *swin;
   	GtkWidget 	  *vbox;
  	GtkWidget 	  *hbox;
  	GtkWidget 	  *widget;
        GtkSizeGroup *size_group;

  	/* size group is used by the [+][-] buttons*/
  	size_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
  	
	vbox = gtk_vbox_new (FALSE, 6);
  	gtk_widget_show (vbox);

 	/* Scrolled window */
	swin = gtk_scrolled_window_new (NULL, NULL);
	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swin),
		  		        GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (swin),
				             GTK_SHADOW_IN);
	gtk_widget_show (swin);
  	gtk_box_pack_start (GTK_BOX (vbox), swin, TRUE, TRUE, 0);


  	/* tree view */
	tree_view = GTK_TREE_VIEW (gtk_tree_view_new ());
	gtk_tree_view_set_headers_visible (tree_view, FALSE);

	col = GTK_TREE_VIEW_COLUMN (gtk_tree_view_column_new ());
	
	cell = gtk_cell_renderer_pixbuf_new ();
	gtk_tree_view_column_pack_start (col, cell, FALSE);
	gtk_tree_view_column_set_attributes (col, cell,
					     "pixbuf", PLACES_SIDEBAR_COLUMN_ICON,
					     NULL);
	
	cell = gtk_cell_renderer_text_new ();
	gtk_tree_view_column_pack_start (col, cell, TRUE);
	gtk_tree_view_column_set_attributes (col, cell,
					     "text", PLACES_SIDEBAR_COLUMN_NAME,
					     NULL);

	gtk_tree_view_set_row_separator_func (tree_view,
					      shortcuts_row_separator_func,
					      GINT_TO_POINTER (PLACES_SIDEBAR_COLUMN_NAME),
					      NULL);

	gtk_tree_view_column_set_fixed_width (col, NAUTILUS_ICON_SIZE_SMALLER);
	gtk_tree_view_append_column (tree_view, col);
	
	store = gtk_list_store_new (PLACES_SIDEBAR_COLUMN_COUNT,
				    GDK_TYPE_PIXBUF,
				    G_TYPE_STRING,
				    NAUTILUS_TYPE_BOOKMARK,
				    G_TYPE_INT);

	gtk_tree_view_set_model (tree_view, GTK_TREE_MODEL (store));
	gtk_container_add (GTK_CONTAINER (swin), GTK_WIDGET (tree_view));
	gtk_widget_show (GTK_WIDGET (tree_view));

  	/* Box for buttons */

  	hbox = gtk_hbox_new (TRUE, 6);
  	gtk_container_set_border_width (GTK_CONTAINER (hbox), 1);
	gtk_size_group_add_widget (size_group, hbox);
  	gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  	gtk_widget_show (hbox);

  	/* Add bookmark button */

  	widget = button_new (_("_Add"),
			    GTK_STOCK_ADD,
			    TRUE,
			    TRUE,
			    G_CALLBACK (add_bookmark_button_clicked_callback),
			    sidebar);

	gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0);
	sidebar->add_button = widget;

	/* Remove bookmark button */

  	widget = button_new (_("_Remove"),
			    GTK_STOCK_REMOVE,
			    FALSE,
			    TRUE,
			    G_CALLBACK (remove_bookmark_button_clicked_callback),
			    sidebar);

	gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0);
	sidebar->remove_button = widget;

	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sidebar),
					GTK_POLICY_NEVER,
					GTK_POLICY_AUTOMATIC);
	gtk_scrolled_window_set_hadjustment (GTK_SCROLLED_WINDOW (sidebar), NULL);
	gtk_scrolled_window_set_vadjustment (GTK_SCROLLED_WINDOW (sidebar), NULL);
	gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (sidebar), GTK_WIDGET (vbox));
	gtk_widget_show (GTK_WIDGET (sidebar));
	sidebar->tree_view = tree_view;

	selection = gtk_tree_view_get_selection (tree_view);
	gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);

	g_signal_connect_object
		(tree_view, "row_activated", 
		 G_CALLBACK (row_activated_callback), sidebar, 0);

	g_signal_connect (selection, "changed",
			  G_CALLBACK (selection_changed_callback), sidebar);
	
	eel_preferences_add_callback (NAUTILUS_PREFERENCES_CLICK_POLICY,
				      click_policy_changed_callback,
				      sidebar);
	update_click_policy (sidebar);

}

static void
nautilus_places_sidebar_finalize (GObject *object)
{
	NautilusPlacesSidebar *sidebar;
	
	sidebar = NAUTILUS_PLACES_SIDEBAR (object);

	if (sidebar->uri) {
		g_free (sidebar->uri);
	}

	eel_preferences_remove_callback (NAUTILUS_PREFERENCES_CLICK_POLICY,
					 click_policy_changed_callback,
					 sidebar);

	G_OBJECT_CLASS (nautilus_places_sidebar_parent_class)->finalize (object);
}

static void
nautilus_places_sidebar_class_init (NautilusPlacesSidebarClass *class)
{
	G_OBJECT_CLASS (class)->finalize = nautilus_places_sidebar_finalize;
}

static const char *
nautilus_places_sidebar_get_sidebar_id (NautilusSidebar *sidebar)
{
	return NAUTILUS_PLACES_SIDEBAR_ID;
}

static char *
nautilus_places_sidebar_get_tab_label (NautilusSidebar *sidebar)
{
	return g_strdup (_("Places"));
}

static GdkPixbuf *
nautilus_places_sidebar_get_tab_icon (NautilusSidebar *sidebar)
{
	return NULL;
}

static void
nautilus_places_sidebar_is_visible_changed (NautilusSidebar *sidebar,
					     gboolean         is_visible)
{
	/* Do nothing */
}

static void
nautilus_places_sidebar_iface_init (NautilusSidebarIface *iface)
{
	iface->get_sidebar_id = nautilus_places_sidebar_get_sidebar_id;
	iface->get_tab_label = nautilus_places_sidebar_get_tab_label;
	iface->get_tab_icon = nautilus_places_sidebar_get_tab_icon;
	iface->is_visible_changed = nautilus_places_sidebar_is_visible_changed;
}

static void
nautilus_places_sidebar_set_parent_window (NautilusPlacesSidebar *sidebar,
					    NautilusWindowInfo *window)
{	
	GnomeVFSVolumeMonitor *volume_monitor;

	sidebar->window = window;
	
	bookmarks = nautilus_window_info_get_bookmark_list (window);
	sidebar->uri = nautilus_window_info_get_current_location (window);

	g_signal_connect_object (bookmarks, "contents_changed",
				 G_CALLBACK (update_places),
				 sidebar, G_CONNECT_SWAPPED);

	g_signal_connect_object (window, "loading_uri",
				 G_CALLBACK (loading_uri_callback),
				 sidebar, 0);
			 
	volume_monitor = gnome_vfs_get_volume_monitor ();
	
	g_signal_connect_object (volume_monitor, "volume_mounted",
				 G_CALLBACK (volume_mounted_callback), sidebar, 0);
	g_signal_connect_object (volume_monitor, "volume_unmounted",
				 G_CALLBACK (volume_unmounted_callback), sidebar, 0);

	update_places (sidebar);
}

static NautilusSidebar *
nautilus_places_sidebar_create (NautilusSidebarProvider *provider,
				 NautilusWindowInfo *window)
{
	NautilusPlacesSidebar *sidebar;
	
	sidebar = g_object_new (nautilus_places_sidebar_get_type (), NULL);
	nautilus_places_sidebar_set_parent_window (sidebar, window);
	g_object_ref (sidebar);
	gtk_object_sink (GTK_OBJECT (sidebar));

	return NAUTILUS_SIDEBAR (sidebar);
}

static void 
sidebar_provider_iface_init (NautilusSidebarProviderIface *iface)
{
	iface->create = nautilus_places_sidebar_create;
}

static void
nautilus_places_sidebar_provider_init (NautilusPlacesSidebarProvider *sidebar)
{
}

static void
nautilus_places_sidebar_provider_class_init (NautilusPlacesSidebarProviderClass *class)
{
}

void
nautilus_places_sidebar_register (void)
{
        nautilus_module_add_type (nautilus_places_sidebar_provider_get_type ());
}

/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */

/*
 *  Nautilus
 *
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU General Public License as
 *  published by the Free Software Foundation; either version 2 of the
 *  License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this library; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *  Author : Mr Jamie McCracken (jamiemcc at blueyonder dot co dot uk)
 *
 */
#ifndef _NAUTILUS_PLACES_SIDEBAR_H
#define _NAUTILUS_PLACES_SIDEBAR_H

#include <gtk/gtktreeview.h>
#include <libnautilus-private/nautilus-view.h>
#include <libnautilus-private/nautilus-window-info.h>
#include <gtk/gtkscrolledwindow.h>

#define NAUTILUS_PLACES_SIDEBAR_ID    "NautilusPlacesSidebar"

#define NAUTILUS_TYPE_PLACES_SIDEBAR (nautilus_places_sidebar_get_type ())
#define NAUTILUS_PLACES_SIDEBAR(obj) (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_PLACES_SIDEBAR, NautilusPlacesSidebar))

typedef struct {
	GtkScrolledWindow  parent;
	GtkTreeView        *tree_view;
	GtkWidget          *add_button;
	GtkWidget          *remove_button;
	char 	           *uri;
	NautilusWindowInfo *window;
} NautilusPlacesSidebar;

GType nautilus_places_sidebar_get_type (void);
void nautilus_places_sidebar_register (void);

#endif


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]