2008-05-05 Paolo Borelli <pborelli@katamail.com>
[nautilus.git] / src / nautilus-places-sidebar.c
blob75ffb93e5cecb3af5b161fc2591b99b6d19363fc
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
3 /*
4 * Nautilus
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this library; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 * Author : Mr Jamie McCracken (jamiemcc at blueyonder dot co dot uk)
24 #include <config.h>
26 #include <eel/eel-debug.h>
27 #include <eel/eel-gtk-extensions.h>
28 #include <eel/eel-glib-extensions.h>
29 #include <eel/eel-preferences.h>
30 #include <eel/eel-string.h>
31 #include <eel/eel-stock-dialogs.h>
32 #include <gdk/gdkkeysyms.h>
33 #include <gtk/gtkalignment.h>
34 #include <gtk/gtkbutton.h>
35 #include <gtk/gtkvbox.h>
36 #include <gtk/gtkcellrendererpixbuf.h>
37 #include <gtk/gtkcellrenderertext.h>
38 #include <gtk/gtkliststore.h>
39 #include <gtk/gtkmain.h>
40 #include <gtk/gtksizegroup.h>
41 #include <gtk/gtkstock.h>
42 #include <gtk/gtktreemodel.h>
43 #include <gtk/gtktreeselection.h>
44 #include <gtk/gtkimagemenuitem.h>
45 #include <libgnome/gnome-macros.h>
46 #include <glib/gi18n.h>
47 #include <libgnomeui/gnome-popup-menu.h>
48 #include <libnautilus-private/nautilus-debug-log.h>
49 #include <libnautilus-private/nautilus-dnd.h>
50 #include <libnautilus-private/nautilus-bookmark.h>
51 #include <libnautilus-private/nautilus-global-preferences.h>
52 #include <libnautilus-private/nautilus-sidebar-provider.h>
53 #include <libnautilus-private/nautilus-module.h>
54 #include <libnautilus-private/nautilus-file.h>
55 #include <libnautilus-private/nautilus-file-utilities.h>
56 #include <libnautilus-private/nautilus-file-operations.h>
57 #include <libnautilus-private/nautilus-trash-monitor.h>
58 #include <libnautilus-private/nautilus-icon-names.h>
59 #include <libnautilus-private/nautilus-autorun.h>
60 #include <gio/gio.h>
62 #include "nautilus-bookmark-list.h"
63 #include "nautilus-places-sidebar.h"
64 #include "nautilus-window.h"
66 #define NAUTILUS_PLACES_SIDEBAR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_PLACES_SIDEBAR, NautilusPlacesSidebarClass))
67 #define NAUTILUS_IS_PLACES_SIDEBAR(obj) (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_PLACES_SIDEBAR))
68 #define NAUTILUS_IS_PLACES_SIDEBAR_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_PLACES_SIDEBAR))
70 typedef struct {
71 GtkScrolledWindow parent;
72 GtkTreeView *tree_view;
73 char *uri;
74 GtkListStore *store;
75 GtkTreeModel *filter_model;
76 NautilusWindowInfo *window;
77 NautilusBookmarkList *bookmarks;
78 GVolumeMonitor *volume_monitor;
80 /* DnD */
81 GList *drag_list;
82 gboolean drag_data_received;
83 gboolean drop_occured;
85 GtkWidget *popup_menu;
86 GtkWidget *popup_menu_remove_item;
87 GtkWidget *popup_menu_rename_item;
88 GtkWidget *popup_menu_separator_item;
89 GtkWidget *popup_menu_mount_item;
90 GtkWidget *popup_menu_unmount_item;
91 GtkWidget *popup_menu_eject_item;
92 GtkWidget *popup_menu_rescan_item;
93 GtkWidget *popup_menu_format_item;
94 GtkWidget *popup_menu_empty_trash_item;
95 } NautilusPlacesSidebar;
97 typedef struct {
98 GtkScrolledWindowClass parent;
99 } NautilusPlacesSidebarClass;
101 typedef struct {
102 GObject parent;
103 } NautilusPlacesSidebarProvider;
105 typedef struct {
106 GObjectClass parent;
107 } NautilusPlacesSidebarProviderClass;
109 enum {
110 PLACES_SIDEBAR_COLUMN_ROW_TYPE,
111 PLACES_SIDEBAR_COLUMN_URI,
112 PLACES_SIDEBAR_COLUMN_DRIVE,
113 PLACES_SIDEBAR_COLUMN_VOLUME,
114 PLACES_SIDEBAR_COLUMN_MOUNT,
115 PLACES_SIDEBAR_COLUMN_NAME,
116 PLACES_SIDEBAR_COLUMN_ICON,
117 PLACES_SIDEBAR_COLUMN_INDEX,
119 PLACES_SIDEBAR_COLUMN_COUNT
122 typedef enum {
123 PLACES_BUILT_IN,
124 PLACES_MOUNTED_VOLUME,
125 PLACES_BOOKMARK,
126 PLACES_SEPARATOR
127 } PlaceType;
129 static void nautilus_places_sidebar_iface_init (NautilusSidebarIface *iface);
130 static void sidebar_provider_iface_init (NautilusSidebarProviderIface *iface);
131 static GType nautilus_places_sidebar_provider_get_type (void);
132 static void open_selected_bookmark (NautilusPlacesSidebar *sidebar,
133 GtkTreeModel *model,
134 GtkTreePath *path,
135 gboolean open_in_new_window);
136 static void nautilus_places_sidebar_style_set (GtkWidget *widget,
137 GtkStyle *previous_style);
139 /* Identifiers for target types */
140 enum {
141 GTK_TREE_MODEL_ROW,
142 TEXT_URI_LIST
145 /* Target types for dragging from the shortcuts list */
146 static const GtkTargetEntry nautilus_shortcuts_source_targets[] = {
147 { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, GTK_TREE_MODEL_ROW }
150 /* Target types for dropping into the shortcuts list */
151 static const GtkTargetEntry nautilus_shortcuts_drop_targets [] = {
152 { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, GTK_TREE_MODEL_ROW },
153 { "text/uri-list", 0, TEXT_URI_LIST }
156 /* Drag and drop interface declarations */
157 typedef struct {
158 GtkTreeModelFilter parent;
160 NautilusPlacesSidebar *sidebar;
161 } NautilusShortcutsModelFilter;
163 typedef struct {
164 GtkTreeModelFilterClass parent_class;
165 } NautilusShortcutsModelFilterClass;
167 #define NAUTILUS_SHORTCUTS_MODEL_FILTER_TYPE (_nautilus_shortcuts_model_filter_get_type ())
168 #define NAUTILUS_SHORTCUTS_MODEL_FILTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NAUTILUS_SHORTCUTS_MODEL_FILTER_TYPE, NautilusShortcutsModelFilter))
170 GType _nautilus_shortcuts_model_filter_get_type (void);
171 static void nautilus_shortcuts_model_filter_drag_source_iface_init (GtkTreeDragSourceIface *iface);
173 G_DEFINE_TYPE_WITH_CODE (NautilusShortcutsModelFilter,
174 _nautilus_shortcuts_model_filter,
175 GTK_TYPE_TREE_MODEL_FILTER,
176 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE,
177 nautilus_shortcuts_model_filter_drag_source_iface_init));
179 static GtkTreeModel *nautilus_shortcuts_model_filter_new (NautilusPlacesSidebar *sidebar,
180 GtkTreeModel *child_model,
181 GtkTreePath *root);
183 G_DEFINE_TYPE_WITH_CODE (NautilusPlacesSidebar, nautilus_places_sidebar, GTK_TYPE_SCROLLED_WINDOW,
184 G_IMPLEMENT_INTERFACE (NAUTILUS_TYPE_SIDEBAR,
185 nautilus_places_sidebar_iface_init));
187 G_DEFINE_TYPE_WITH_CODE (NautilusPlacesSidebarProvider, nautilus_places_sidebar_provider, G_TYPE_OBJECT,
188 G_IMPLEMENT_INTERFACE (NAUTILUS_TYPE_SIDEBAR_PROVIDER,
189 sidebar_provider_iface_init));
191 static GtkTreeIter
192 add_place (NautilusPlacesSidebar *sidebar,
193 PlaceType place_type,
194 const char *name,
195 GIcon *icon,
196 const char *uri,
197 GDrive *drive,
198 GVolume *volume,
199 GMount *mount,
200 const int index)
202 GdkPixbuf *pixbuf;
203 GtkTreeIter iter, child_iter;
204 NautilusIconInfo *icon_info;
205 int icon_size;
207 icon_size = nautilus_get_icon_size_for_stock_size (GTK_ICON_SIZE_MENU);
208 icon_info = nautilus_icon_info_lookup (icon, icon_size);
210 pixbuf = nautilus_icon_info_get_pixbuf_at_size (icon_info, icon_size);
211 g_object_unref (icon_info);
212 gtk_list_store_append (sidebar->store, &iter);
213 gtk_list_store_set (sidebar->store, &iter,
214 PLACES_SIDEBAR_COLUMN_ICON, pixbuf,
215 PLACES_SIDEBAR_COLUMN_NAME, name,
216 PLACES_SIDEBAR_COLUMN_URI, uri,
217 PLACES_SIDEBAR_COLUMN_DRIVE, drive,
218 PLACES_SIDEBAR_COLUMN_VOLUME, volume,
219 PLACES_SIDEBAR_COLUMN_MOUNT, mount,
220 PLACES_SIDEBAR_COLUMN_ROW_TYPE, place_type,
221 PLACES_SIDEBAR_COLUMN_INDEX, index,
222 -1);
223 if (pixbuf != NULL) {
224 g_object_unref (pixbuf);
226 gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (sidebar->filter_model));
227 gtk_tree_model_filter_convert_child_iter_to_iter (GTK_TREE_MODEL_FILTER (sidebar->filter_model),
228 &child_iter,
229 &iter);
230 return child_iter;
233 static void
234 update_places (NautilusPlacesSidebar *sidebar)
236 NautilusBookmark *bookmark;
237 GtkTreeSelection *selection;
238 GtkTreeIter iter, last_iter;
239 GVolumeMonitor *volume_monitor;
240 GList *mounts, *l, *ll;
241 GMount *mount;
242 GList *drives;
243 GDrive *drive;
244 GList *volumes;
245 GVolume *volume;
246 int bookmark_count, index;
247 char *location, *mount_uri, *name, *desktop_path;
248 GIcon *icon;
249 GFile *root;
252 selection = gtk_tree_view_get_selection (sidebar->tree_view);
253 gtk_list_store_clear (sidebar->store);
254 location = nautilus_window_info_get_current_location (sidebar->window);
256 /* add built in bookmarks */
257 desktop_path = nautilus_get_desktop_directory ();
259 if (strcmp (g_get_home_dir(), desktop_path) != 0) {
260 char *display_name;
262 mount_uri = nautilus_get_home_directory_uri ();
263 display_name = g_filename_display_basename (g_get_home_dir ());
264 icon = g_themed_icon_new (NAUTILUS_ICON_HOME);
265 last_iter = add_place (sidebar, PLACES_BUILT_IN,
266 display_name, icon,
267 mount_uri, NULL, NULL, NULL, 0);
268 g_object_unref (icon);
269 g_free (display_name);
270 if (strcmp (location, mount_uri) == 0) {
271 gtk_tree_selection_select_iter (selection, &last_iter);
273 g_free (mount_uri);
276 mount_uri = g_filename_to_uri (desktop_path, NULL, NULL);
277 icon = g_themed_icon_new (NAUTILUS_ICON_DESKTOP);
278 last_iter = add_place (sidebar, PLACES_BUILT_IN,
279 _("Desktop"), icon,
280 mount_uri, NULL, NULL, NULL, 0);
281 g_object_unref (icon);
282 if (strcmp (location, mount_uri) == 0) {
283 gtk_tree_selection_select_iter (selection, &last_iter);
285 g_free (mount_uri);
286 g_free (desktop_path);
288 mount_uri = "file:///"; /* No need to strdup */
289 icon = g_themed_icon_new (NAUTILUS_ICON_FILESYSTEM);
290 last_iter = add_place (sidebar, PLACES_BUILT_IN,
291 _("File System"), icon,
292 mount_uri, NULL, NULL, NULL, 0);
293 g_object_unref (icon);
294 if (strcmp (location, mount_uri) == 0) {
295 gtk_tree_selection_select_iter (selection, &last_iter);
298 mount_uri = "network:///"; /* No need to strdup */
299 icon = g_themed_icon_new (NAUTILUS_ICON_NETWORK);
300 last_iter = add_place (sidebar, PLACES_BUILT_IN,
301 _("Network"), icon,
302 mount_uri, NULL, NULL, NULL, 0);
303 g_object_unref (icon);
304 if (strcmp (location, mount_uri) == 0) {
305 gtk_tree_selection_select_iter (selection, &last_iter);
308 volume_monitor = sidebar->volume_monitor;
310 /* first go through all connected drives */
311 drives = g_volume_monitor_get_connected_drives (volume_monitor);
312 for (l = drives; l != NULL; l = l->next) {
313 drive = l->data;
315 volumes = g_drive_get_volumes (drive);
316 if (volumes != NULL) {
317 for (ll = volumes; ll != NULL; ll = ll->next) {
318 volume = ll->data;
319 mount = g_volume_get_mount (volume);
320 if (mount != NULL) {
321 /* Show mounted volume in the sidebar */
322 icon = g_mount_get_icon (mount);
323 root = g_mount_get_root (mount);
324 mount_uri = g_file_get_uri (root);
325 g_object_unref (root);
326 name = g_mount_get_name (mount);
327 last_iter = add_place (sidebar, PLACES_MOUNTED_VOLUME,
328 name, icon, mount_uri,
329 drive, volume, mount, 0);
330 if (strcmp (location, mount_uri) == 0) {
331 gtk_tree_selection_select_iter (selection, &last_iter);
333 g_object_unref (mount);
334 g_object_unref (icon);
335 g_free (name);
336 g_free (mount_uri);
337 } else {
338 /* Do show the unmounted volumes in the sidebar;
339 * this is so the user can mount it (in case automounting
340 * is off).
342 * Also, even if automounting is enabled, this gives a visual
343 * cue that the user should remember to yank out the media if
344 * he just unmounted it.
346 icon = g_volume_get_icon (volume);
347 name = g_volume_get_name (volume);
348 last_iter = add_place (sidebar, PLACES_MOUNTED_VOLUME,
349 name, icon, NULL,
350 drive, volume, NULL, 0);
351 g_object_unref (icon);
352 g_free (name);
354 g_object_unref (volume);
356 g_list_free (volumes);
357 } else {
358 if (g_drive_is_media_removable (drive) && !g_drive_is_media_check_automatic (drive)) {
359 /* If the drive has no mountable volumes and we cannot detect media change.. we
360 * display the drive in the sidebar so the user can manually poll the drive by
361 * right clicking and selecting "Rescan..."
363 * This is mainly for drives like floppies where media detection doesn't
364 * work.. but it's also for human beings who like to turn off media detection
365 * in the OS to save battery juice.
367 icon = g_drive_get_icon (drive);
368 name = g_drive_get_name (drive);
369 last_iter = add_place (sidebar, PLACES_BUILT_IN,
370 name, icon, NULL,
371 drive, NULL, NULL, 0);
372 g_object_unref (icon);
373 g_free (name);
376 g_object_unref (drive);
378 g_list_free (drives);
380 /* add all volumes that is not associated with a drive */
381 volumes = g_volume_monitor_get_volumes (volume_monitor);
382 for (l = volumes; l != NULL; l = l->next) {
383 volume = l->data;
384 drive = g_volume_get_drive (volume);
385 if (drive != NULL) {
386 g_object_unref (volume);
387 g_object_unref (drive);
388 continue;
390 mount = g_volume_get_mount (volume);
391 if (mount != NULL) {
392 icon = g_mount_get_icon (mount);
393 root = g_mount_get_root (mount);
394 mount_uri = g_file_get_uri (root);
395 g_object_unref (root);
396 name = g_mount_get_name (mount);
397 last_iter = add_place (sidebar, PLACES_MOUNTED_VOLUME,
398 name, icon, mount_uri,
399 NULL, volume, mount, 0);
400 if (strcmp (location, mount_uri) == 0) {
401 gtk_tree_selection_select_iter (selection, &last_iter);
403 g_object_unref (mount);
404 g_object_unref (icon);
405 g_free (name);
406 g_free (mount_uri);
407 } else {
408 /* see comment above in why we add an icon for an unmounted mountable volume */
409 icon = g_volume_get_icon (volume);
410 name = g_volume_get_name (volume);
411 last_iter = add_place (sidebar, PLACES_MOUNTED_VOLUME,
412 name, icon, NULL,
413 NULL, volume, NULL, 0);
414 g_object_unref (icon);
415 g_free (name);
417 g_object_unref (volume);
419 g_list_free (volumes);
421 /* add mounts that has no volume (/etc/mtab mounts, ftp, sftp,...) */
422 mounts = g_volume_monitor_get_mounts (volume_monitor);
423 for (l = mounts; l != NULL; l = l->next) {
424 mount = l->data;
425 volume = g_mount_get_volume (mount);
426 if (volume != NULL) {
427 g_object_unref (volume);
428 g_object_unref (mount);
429 continue;
431 icon = g_mount_get_icon (mount);
432 root = g_mount_get_root (mount);
433 mount_uri = g_file_get_uri (root);
434 g_object_unref (root);
435 name = g_mount_get_name (mount);
436 last_iter = add_place (sidebar, PLACES_MOUNTED_VOLUME,
437 name, icon, mount_uri,
438 NULL, NULL, mount, 0);
439 if (strcmp (location, mount_uri) == 0) {
440 gtk_tree_selection_select_iter (selection, &last_iter);
442 g_object_unref (mount);
443 g_object_unref (icon);
444 g_free (name);
445 g_free (mount_uri);
447 g_list_free (mounts);
449 mount_uri = "trash:///"; /* No need to strdup */
450 icon = nautilus_trash_monitor_get_icon ();
451 last_iter = add_place (sidebar, PLACES_BUILT_IN,
452 _("Trash"), icon, mount_uri,
453 NULL, NULL, NULL, 0);
454 if (strcmp (location, mount_uri) == 0) {
455 gtk_tree_selection_select_iter (selection, &last_iter);
457 g_object_unref (icon);
459 /* add separator */
461 gtk_list_store_append (sidebar->store, &iter);
462 gtk_list_store_set (sidebar->store, &iter,
463 PLACES_SIDEBAR_COLUMN_ROW_TYPE, PLACES_SEPARATOR,
464 -1);
466 /* add bookmarks */
468 bookmark_count = nautilus_bookmark_list_length (sidebar->bookmarks);
469 for (index = 0; index < bookmark_count; ++index) {
470 bookmark = nautilus_bookmark_list_item_at (sidebar->bookmarks, index);
472 if (nautilus_bookmark_uri_known_not_to_exist (bookmark)) {
473 continue;
476 name = nautilus_bookmark_get_name (bookmark);
477 icon = nautilus_bookmark_get_icon (bookmark);
478 mount_uri = nautilus_bookmark_get_uri (bookmark);
479 last_iter = add_place (sidebar, PLACES_BOOKMARK,
480 name, icon, mount_uri,
481 NULL, NULL, NULL, index);
482 if (strcmp (location, mount_uri) == 0) {
483 gtk_tree_selection_select_iter (selection, &last_iter);
485 g_free (name);
486 g_object_unref (icon);
487 g_free (mount_uri);
489 g_free (location);
492 static gboolean
493 nautilus_shortcuts_row_separator_func (GtkTreeModel *model,
494 GtkTreeIter *iter,
495 gpointer data)
497 PlaceType type;
499 gtk_tree_model_get (model, iter, PLACES_SIDEBAR_COLUMN_ROW_TYPE, &type, -1);
501 if (type == PLACES_SEPARATOR) {
502 return TRUE;
505 return FALSE;
508 static void
509 mount_added_callback (GVolumeMonitor *volume_monitor,
510 GMount *mount,
511 NautilusPlacesSidebar *sidebar)
513 update_places (sidebar);
516 static void
517 mount_removed_callback (GVolumeMonitor *volume_monitor,
518 GMount *mount,
519 NautilusPlacesSidebar *sidebar)
521 update_places (sidebar);
524 static void
525 mount_changed_callback (GVolumeMonitor *volume_monitor,
526 GMount *mount,
527 NautilusPlacesSidebar *sidebar)
529 update_places (sidebar);
532 static void
533 volume_added_callback (GVolumeMonitor *volume_monitor,
534 GVolume *volume,
535 NautilusPlacesSidebar *sidebar)
537 update_places (sidebar);
540 static void
541 volume_removed_callback (GVolumeMonitor *volume_monitor,
542 GVolume *volume,
543 NautilusPlacesSidebar *sidebar)
545 update_places (sidebar);
548 static void
549 volume_changed_callback (GVolumeMonitor *volume_monitor,
550 GVolume *volume,
551 NautilusPlacesSidebar *sidebar)
553 update_places (sidebar);
556 static void
557 drive_disconnected_callback (GVolumeMonitor *volume_monitor,
558 GDrive *drive,
559 NautilusPlacesSidebar *sidebar)
561 update_places (sidebar);
564 static void
565 drive_connected_callback (GVolumeMonitor *volume_monitor,
566 GDrive *drive,
567 NautilusPlacesSidebar *sidebar)
569 update_places (sidebar);
572 static void
573 drive_changed_callback (GVolumeMonitor *volume_monitor,
574 GDrive *drive,
575 NautilusPlacesSidebar *sidebar)
577 update_places (sidebar);
580 static void
581 row_activated_callback (GtkTreeView *tree_view,
582 GtkTreePath *path,
583 GtkTreeViewColumn *column,
584 gpointer user_data)
586 open_selected_bookmark (NAUTILUS_PLACES_SIDEBAR (user_data),
587 gtk_tree_view_get_model (tree_view),
588 path,
589 FALSE);
592 static void
593 desktop_location_changed_callback (gpointer user_data)
595 NautilusPlacesSidebar *sidebar;
597 sidebar = NAUTILUS_PLACES_SIDEBAR (user_data);
599 update_places (sidebar);
602 static void
603 loading_uri_callback (NautilusWindowInfo *window,
604 char *location,
605 NautilusPlacesSidebar *sidebar)
607 GtkTreeSelection *selection;
608 GtkTreeIter iter;
609 gboolean valid;
610 char *uri;
612 if (strcmp (sidebar->uri, location) != 0) {
613 g_free (sidebar->uri);
614 sidebar->uri = g_strdup (location);
616 /* set selection if any place matches location */
617 selection = gtk_tree_view_get_selection (sidebar->tree_view);
618 gtk_tree_selection_unselect_all (selection);
619 valid = gtk_tree_model_get_iter_first (sidebar->filter_model, &iter);
621 while (valid) {
622 gtk_tree_model_get (sidebar->filter_model, &iter,
623 PLACES_SIDEBAR_COLUMN_URI, &uri,
624 -1);
625 if (uri != NULL) {
626 if (strcmp (uri, location) == 0) {
627 g_free (uri);
628 gtk_tree_selection_select_iter (selection, &iter);
629 break;
631 g_free (uri);
633 valid = gtk_tree_model_iter_next (sidebar->filter_model, &iter);
639 static unsigned int
640 get_bookmark_index (GtkTreeView *tree_view)
642 GtkTreeModel *model;
643 GtkTreePath *p;
644 GtkTreeIter iter;
645 PlaceType place_type;
646 int bookmark_index;
648 model = gtk_tree_view_get_model (tree_view);
650 bookmark_index = -1;
652 /* find separator */
653 p = gtk_tree_path_new_first ();
654 while (p != NULL) {
655 gtk_tree_model_get_iter (model, &iter, p);
656 gtk_tree_model_get (model, &iter,
657 PLACES_SIDEBAR_COLUMN_ROW_TYPE, &place_type,
658 -1);
660 if (place_type == PLACES_SEPARATOR) {
661 bookmark_index = *gtk_tree_path_get_indices (p) + 1;
662 break;
665 gtk_tree_path_next (p);
667 gtk_tree_path_free (p);
669 g_assert (bookmark_index >= 0);
671 return bookmark_index;
674 /* Computes the appropriate row and position for dropping */
675 static void
676 compute_drop_position (GtkTreeView *tree_view,
677 int x,
678 int y,
679 GtkTreePath **path,
680 GtkTreeViewDropPosition *pos,
681 NautilusPlacesSidebar *sidebar)
683 int bookmarks_index;
684 int num_bookmarks;
685 int row;
687 bookmarks_index = get_bookmark_index (tree_view);
689 num_bookmarks = nautilus_bookmark_list_length (sidebar->bookmarks);
691 if (!gtk_tree_view_get_dest_row_at_pos (tree_view,
694 path,
695 pos)) {
696 row = bookmarks_index + num_bookmarks - 1;
697 *path = gtk_tree_path_new_from_indices (row, -1);
698 *pos = GTK_TREE_VIEW_DROP_AFTER;
699 return;
702 row = *gtk_tree_path_get_indices (*path);
703 gtk_tree_path_free (*path);
705 if (row < bookmarks_index) {
706 /* Hardcoded shortcuts can only be dragged into */
707 *pos = GTK_TREE_VIEW_DROP_INTO_OR_BEFORE;
709 else if (row > bookmarks_index + num_bookmarks - 1) {
710 row = bookmarks_index + num_bookmarks - 1;
711 *pos = GTK_TREE_VIEW_DROP_AFTER;
714 *path = gtk_tree_path_new_from_indices (row, -1);
718 static void
719 get_drag_data (GtkTreeView *tree_view,
720 GdkDragContext *context,
721 unsigned int time)
723 GdkAtom target;
725 target = gtk_drag_dest_find_target (GTK_WIDGET (tree_view),
726 context,
727 NULL);
729 gtk_drag_get_data (GTK_WIDGET (tree_view),
730 context, target, time);
733 static void
734 free_drag_data (NautilusPlacesSidebar *sidebar)
736 sidebar->drag_data_received = FALSE;
738 if (sidebar->drag_list) {
739 nautilus_drag_destroy_selection_list (sidebar->drag_list);
740 sidebar->drag_list = NULL;
744 static gboolean
745 can_accept_file_as_bookmark (NautilusFile *file)
747 return nautilus_file_is_directory (file);
750 static gboolean
751 can_accept_items_as_bookmarks (const GList *items)
753 int max;
754 char *uri;
755 NautilusFile *file;
757 /* Iterate through selection checking if item will get accepted as a bookmark.
758 * If more than 100 items selected, return an over-optimistic result.
760 for (max = 100; items != NULL && max >= 0; items = items->next, max--) {
761 uri = ((NautilusDragSelectionItem *)items->data)->uri;
762 file = nautilus_file_get_by_uri (uri);
763 if (!can_accept_file_as_bookmark (file)) {
764 nautilus_file_unref (file);
765 return FALSE;
767 nautilus_file_unref (file);
770 return TRUE;
773 static void
774 drag_data_delete_callback (GtkWidget *widget,
775 GdkDragContext *context,
776 NautilusPlacesSidebar *sidebar)
778 g_signal_stop_emission_by_name (widget, "drag-data-delete");
781 static gboolean
782 drag_motion_callback (GtkTreeView *tree_view,
783 GdkDragContext *context,
784 int x,
785 int y,
786 unsigned int time,
787 NautilusPlacesSidebar *sidebar)
789 GtkTreePath *path;
790 GtkTreeViewDropPosition pos;
791 int action;
792 GtkTreeIter iter, child_iter;
793 char *uri;
795 if (!sidebar->drag_data_received) {
796 get_drag_data (tree_view, context, time);
799 compute_drop_position (tree_view, x, y, &path, &pos, sidebar);
801 if (pos == GTK_TREE_VIEW_DROP_BEFORE ||
802 pos == GTK_TREE_VIEW_DROP_AFTER ) {
803 if (can_accept_items_as_bookmarks (sidebar->drag_list)) {
804 action = GDK_ACTION_COPY;
805 } else {
806 action = 0;
808 } else {
809 if (sidebar->drag_list == NULL) {
810 action = 0;
811 } else {
812 gtk_tree_model_get_iter (sidebar->filter_model,
813 &iter, path);
814 gtk_tree_model_filter_convert_iter_to_child_iter (
815 GTK_TREE_MODEL_FILTER (sidebar->filter_model),
816 &child_iter, &iter);
817 gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store),
818 &child_iter,
819 PLACES_SIDEBAR_COLUMN_URI, &uri,
820 -1);
821 nautilus_drag_default_drop_action_for_icons (context, uri,
822 sidebar->drag_list,
823 &action);
824 g_free (uri);
828 gtk_tree_view_set_drag_dest_row (tree_view, path, pos);
829 gtk_tree_path_free (path);
830 g_signal_stop_emission_by_name (tree_view, "drag-motion");
832 if (action != 0) {
833 gdk_drag_status (context, action, time);
834 return TRUE;
835 } else {
836 return FALSE;
840 static void
841 drag_leave_callback (GtkTreeView *tree_view,
842 GdkDragContext *context,
843 unsigned int time,
844 NautilusPlacesSidebar *sidebar)
846 free_drag_data (sidebar);
847 gtk_tree_view_set_drag_dest_row (tree_view, NULL, GTK_TREE_VIEW_DROP_BEFORE);
848 g_signal_stop_emission_by_name (tree_view, "drag-leave");
851 /* Parses a "text/uri-list" string and inserts its URIs as bookmarks */
852 static void
853 bookmarks_drop_uris (NautilusPlacesSidebar *sidebar,
854 GtkSelectionData *selection_data,
855 int position)
857 NautilusBookmark *bookmark;
858 NautilusFile *file;
859 char *uri, *name;
860 char **uris;
861 int i;
862 GFile *location;
863 GIcon *icon;
865 uris = gtk_selection_data_get_uris (selection_data);
866 if (!uris)
867 return;
869 for (i = 0; uris[i]; i++) {
870 uri = uris[i];
871 file = nautilus_file_get_by_uri (uri);
873 if (!can_accept_file_as_bookmark (file)) {
874 nautilus_file_unref (file);
875 continue;
878 uri = nautilus_file_get_drop_target_uri (file);
879 location = g_file_new_for_uri (uri);
880 nautilus_file_unref (file);
882 name = nautilus_compute_title_for_location (location);
884 icon = g_themed_icon_new (NAUTILUS_ICON_FOLDER);
885 bookmark = nautilus_bookmark_new_with_icon (location, name,
886 FALSE, icon);
887 g_object_unref (icon);
889 if (!nautilus_bookmark_list_contains (sidebar->bookmarks, bookmark)) {
890 nautilus_bookmark_list_insert_item (sidebar->bookmarks, bookmark, position++);
893 g_object_unref (location);
894 g_object_unref (bookmark);
895 g_free (name);
896 g_free (uri);
899 g_strfreev (uris);
902 static GList *
903 uri_list_from_selection (GList *selection)
905 NautilusDragSelectionItem *item;
906 GList *ret;
907 GList *l;
909 ret = NULL;
910 for (l = selection; l != NULL; l = l->next) {
911 item = l->data;
912 ret = g_list_prepend (ret, item->uri);
915 return g_list_reverse (ret);
918 static GList*
919 build_selection_list (const char *data)
921 NautilusDragSelectionItem *item;
922 GList *result;
923 char **uris;
924 char *uri;
925 int i;
927 uris = g_uri_list_extract_uris (data);
929 result = NULL;
930 for (i = 0; uris[i]; i++) {
931 uri = uris[i];
932 item = nautilus_drag_selection_item_new ();
933 item->uri = g_strdup (uri);
934 item->got_icon_position = FALSE;
935 result = g_list_prepend (result, item);
938 g_strfreev (uris);
940 return g_list_reverse (result);
943 static gboolean
944 get_selected_iter (NautilusPlacesSidebar *sidebar,
945 GtkTreeIter *iter)
947 GtkTreeSelection *selection;
948 GtkTreeIter parent_iter;
950 selection = gtk_tree_view_get_selection (sidebar->tree_view);
951 if (!gtk_tree_selection_get_selected (selection, NULL, &parent_iter)) {
952 return FALSE;
954 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (sidebar->filter_model),
955 iter,
956 &parent_iter);
957 return TRUE;
960 /* Reorders the selected bookmark to the specified position */
961 static void
962 reorder_bookmarks (NautilusPlacesSidebar *sidebar,
963 int new_position)
965 GtkTreeIter iter;
966 GtkTreePath *path;
967 NautilusBookmark *bookmark;
968 int old_position;
969 int bookmarks_index;
971 /* Get the selected path */
973 if (!get_selected_iter (sidebar, &iter))
974 g_assert_not_reached ();
976 path = gtk_tree_model_get_path (GTK_TREE_MODEL (sidebar->store), &iter);
977 old_position = *gtk_tree_path_get_indices (path);
978 gtk_tree_path_free (path);
980 bookmarks_index = get_bookmark_index (sidebar->tree_view);
981 old_position -= bookmarks_index;
982 if (old_position < 0) {
983 return;
985 g_assert (old_position < nautilus_bookmark_list_length (sidebar->bookmarks));
987 /* Remove the path from the old position and insert it in the new one */
989 if (old_position == new_position) {
990 return;
992 bookmark = nautilus_bookmark_list_item_at (sidebar->bookmarks, old_position);
993 nautilus_bookmark_list_insert_item (sidebar->bookmarks, bookmark, new_position);
994 if (old_position > new_position) {
995 old_position++;
997 nautilus_bookmark_list_delete_item_at (sidebar->bookmarks, old_position);
1000 static void
1001 drag_data_received_callback (GtkWidget *widget,
1002 GdkDragContext *context,
1003 int x,
1004 int y,
1005 GtkSelectionData *selection_data,
1006 unsigned int info,
1007 unsigned int time,
1008 NautilusPlacesSidebar *sidebar)
1010 GtkTreeView *tree_view;
1011 GtkTreePath *tree_path;
1012 GtkTreeViewDropPosition tree_pos;
1013 GtkTreeIter iter;
1014 int position, bookmarks_index;
1015 GtkTreeModel *model;
1016 char *drop_uri;
1017 GList *selection_list, *uris;
1018 gboolean success;
1020 tree_view = GTK_TREE_VIEW (widget);
1022 if (!sidebar->drag_data_received) {
1023 if (selection_data->target != GDK_NONE &&
1024 info == TEXT_URI_LIST) {
1025 sidebar->drag_list = build_selection_list (selection_data->data);
1026 } else {
1027 sidebar->drag_list = NULL;
1029 sidebar->drag_data_received = TRUE;
1032 g_signal_stop_emission_by_name (widget, "drag-data-received");
1034 if (!sidebar->drop_occured) {
1035 return;
1038 /* Compute position */
1039 compute_drop_position (tree_view, x, y, &tree_path, &tree_pos, sidebar);
1041 success = FALSE;
1043 if (tree_pos == GTK_TREE_VIEW_DROP_BEFORE ||
1044 tree_pos == GTK_TREE_VIEW_DROP_AFTER) {
1045 /* bookmark addition requested */
1046 bookmarks_index = get_bookmark_index (tree_view);
1047 position = *gtk_tree_path_get_indices (tree_path);
1049 if (tree_pos == GTK_TREE_VIEW_DROP_AFTER) {
1050 position++;
1053 g_assert (position >= bookmarks_index);
1054 position -= bookmarks_index;
1056 switch (info) {
1057 case TEXT_URI_LIST:
1058 bookmarks_drop_uris (sidebar, selection_data, position);
1059 success = TRUE;
1060 break;
1061 case GTK_TREE_MODEL_ROW:
1062 reorder_bookmarks (sidebar, position);
1063 success = TRUE;
1064 break;
1065 default:
1066 g_assert_not_reached ();
1067 break;
1069 } else {
1070 /* file transfer requested */
1071 if (context->action == GDK_ACTION_ASK) {
1072 context->action =
1073 nautilus_drag_drop_action_ask (GTK_WIDGET (tree_view),
1074 context->actions);
1077 if (context->action > 0) {
1078 model = gtk_tree_view_get_model (tree_view);
1080 gtk_tree_model_get_iter (model, &iter, tree_path);
1081 gtk_tree_model_get (model, &iter,
1082 PLACES_SIDEBAR_COLUMN_URI, &drop_uri,
1083 -1);
1085 switch (info) {
1086 case TEXT_URI_LIST:
1087 selection_list = build_selection_list (selection_data->data);
1088 uris = uri_list_from_selection (selection_list);
1089 nautilus_file_operations_copy_move (uris, NULL, drop_uri,
1090 context->action, GTK_WIDGET (tree_view),
1091 NULL, NULL);
1092 nautilus_drag_destroy_selection_list (selection_list);
1093 g_list_free (uris);
1094 success = TRUE;
1095 break;
1096 case GTK_TREE_MODEL_ROW:
1097 success = FALSE;
1098 break;
1099 default:
1100 g_assert_not_reached ();
1101 break;
1104 g_free (drop_uri);
1108 sidebar->drop_occured = FALSE;
1109 free_drag_data (sidebar);
1110 gtk_drag_finish (context, success, FALSE, time);
1112 gtk_tree_path_free (tree_path);
1115 static gboolean
1116 drag_drop_callback (GtkTreeView *tree_view,
1117 GdkDragContext *context,
1118 int x,
1119 int y,
1120 unsigned int time,
1121 NautilusPlacesSidebar *sidebar)
1123 sidebar->drop_occured = TRUE;
1124 get_drag_data (tree_view, context, time);
1125 g_signal_stop_emission_by_name (tree_view, "drag-drop");
1126 return TRUE;
1129 /* Callback used when the file list's popup menu is detached */
1130 static void
1131 bookmarks_popup_menu_detach_cb (GtkWidget *attach_widget,
1132 GtkMenu *menu)
1134 NautilusPlacesSidebar *sidebar;
1136 sidebar = NAUTILUS_PLACES_SIDEBAR (attach_widget);
1137 g_assert (NAUTILUS_IS_PLACES_SIDEBAR (sidebar));
1139 sidebar->popup_menu = NULL;
1140 sidebar->popup_menu_remove_item = NULL;
1141 sidebar->popup_menu_rename_item = NULL;
1142 sidebar->popup_menu_separator_item = NULL;
1143 sidebar->popup_menu_mount_item = NULL;
1144 sidebar->popup_menu_unmount_item = NULL;
1145 sidebar->popup_menu_eject_item = NULL;
1146 sidebar->popup_menu_rescan_item = NULL;
1147 sidebar->popup_menu_format_item = NULL;
1148 sidebar->popup_menu_empty_trash_item = NULL;
1151 static void
1152 check_visibility (GMount *mount,
1153 GVolume *volume,
1154 GDrive *drive,
1155 gboolean *show_mount,
1156 gboolean *show_unmount,
1157 gboolean *show_eject,
1158 gboolean *show_rescan,
1159 gboolean *show_format)
1161 *show_mount = FALSE;
1162 *show_unmount = FALSE;
1163 *show_eject = FALSE;
1164 *show_format = FALSE;
1165 *show_rescan = FALSE;
1167 if (drive != NULL) {
1168 *show_eject = g_drive_can_eject (drive);
1170 if (g_drive_is_media_removable (drive) &&
1171 !g_drive_is_media_check_automatic (drive) &&
1172 g_drive_can_poll_for_media (drive))
1173 *show_rescan = TRUE;
1176 if (volume != NULL) {
1177 *show_eject |= g_volume_can_eject (volume);
1178 if (mount == NULL)
1179 *show_mount = g_volume_can_mount (volume);
1182 if (mount != NULL) {
1183 *show_unmount = g_mount_can_unmount (mount);
1184 *show_eject |= g_mount_can_eject (mount);
1187 #ifdef TODO_GIO
1188 if (something &&
1189 g_find_program_in_path ("gfloppy")) {
1190 *show_format = TRUE;
1192 #endif
1195 static void
1196 bookmarks_check_popup_sensitivity (NautilusPlacesSidebar *sidebar)
1198 GtkTreeIter iter;
1199 PlaceType type;
1200 GDrive *drive = NULL;
1201 GVolume *volume = NULL;
1202 GMount *mount = NULL;
1203 gboolean show_mount;
1204 gboolean show_unmount;
1205 gboolean show_eject;
1206 gboolean show_rescan;
1207 gboolean show_format;
1208 gboolean show_empty_trash;
1209 char *uri = NULL;
1211 type = PLACES_BUILT_IN;
1213 if (sidebar->popup_menu == NULL) {
1214 return;
1217 if (get_selected_iter (sidebar, &iter)) {
1218 gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
1219 PLACES_SIDEBAR_COLUMN_ROW_TYPE, &type,
1220 PLACES_SIDEBAR_COLUMN_DRIVE, &drive,
1221 PLACES_SIDEBAR_COLUMN_VOLUME, &volume,
1222 PLACES_SIDEBAR_COLUMN_MOUNT, &mount,
1223 PLACES_SIDEBAR_COLUMN_URI, &uri,
1224 -1);
1227 gtk_widget_set_sensitive (sidebar->popup_menu_remove_item, (type == PLACES_BOOKMARK));
1228 gtk_widget_set_sensitive (sidebar->popup_menu_rename_item, (type == PLACES_BOOKMARK));
1229 gtk_widget_set_sensitive (sidebar->popup_menu_empty_trash_item, !nautilus_trash_monitor_is_empty ());
1231 check_visibility (mount, volume, drive,
1232 &show_mount, &show_unmount, &show_eject, &show_rescan, &show_format);
1234 /* We actually want both eject and unmount since eject will unmount all volumes.
1235 * TODO: hide unmount if the drive only has a single mountable volume
1238 show_empty_trash = (uri != NULL) &&
1239 (!strcmp (uri, "trash:///"));
1241 eel_gtk_widget_set_shown (sidebar->popup_menu_separator_item,
1242 show_mount || show_unmount || show_eject || show_format || show_empty_trash);
1243 eel_gtk_widget_set_shown (sidebar->popup_menu_mount_item, show_mount);
1244 eel_gtk_widget_set_shown (sidebar->popup_menu_unmount_item, show_unmount);
1245 eel_gtk_widget_set_shown (sidebar->popup_menu_eject_item, show_eject);
1246 eel_gtk_widget_set_shown (sidebar->popup_menu_rescan_item, show_rescan);
1247 eel_gtk_widget_set_shown (sidebar->popup_menu_format_item, show_format);
1248 eel_gtk_widget_set_shown (sidebar->popup_menu_empty_trash_item, show_empty_trash);
1250 g_free (uri);
1253 /* Callback used when the selection in the shortcuts tree changes */
1254 static void
1255 bookmarks_selection_changed_cb (GtkTreeSelection *selection,
1256 NautilusPlacesSidebar *sidebar)
1258 bookmarks_check_popup_sensitivity (sidebar);
1261 static void
1262 open_selected_bookmark (NautilusPlacesSidebar *sidebar,
1263 GtkTreeModel *model,
1264 GtkTreePath *path,
1265 gboolean open_in_new_window)
1267 GtkTreeIter iter;
1268 GFile *location;
1269 char *uri;
1271 if (!path) {
1272 return;
1275 if (!gtk_tree_model_get_iter (model, &iter, path)) {
1276 return;
1279 gtk_tree_model_get (model, &iter, PLACES_SIDEBAR_COLUMN_URI, &uri, -1);
1281 if (uri != NULL) {
1282 nautilus_debug_log (FALSE, NAUTILUS_DEBUG_LOG_DOMAIN_USER,
1283 "activate from places sidebar window=%p: %s",
1284 sidebar->window, uri);
1285 location = g_file_new_for_uri (uri);
1286 /* Navigate to the clicked location */
1287 if (!open_in_new_window) {
1288 nautilus_window_info_open_location (sidebar->window, location,
1289 NAUTILUS_WINDOW_OPEN_ACCORDING_TO_MODE,
1290 0, NULL);
1291 } else {
1292 NautilusWindow *cur, *new;
1294 cur = NAUTILUS_WINDOW (sidebar->window);
1295 new = nautilus_application_create_navigation_window (cur->application,
1296 NULL,
1297 gtk_window_get_screen (GTK_WINDOW (cur)));
1298 nautilus_window_go_to (new, location);
1300 g_object_unref (location);
1301 g_free (uri);
1303 } else {
1304 GVolume *volume;
1305 gtk_tree_model_get (model, &iter, PLACES_SIDEBAR_COLUMN_VOLUME, &volume, -1);
1306 if (volume != NULL) {
1307 nautilus_file_operations_mount_volume (NULL, volume, FALSE);
1308 g_object_unref (volume);
1313 static void
1314 open_shortcut_from_menu (NautilusPlacesSidebar *sidebar,
1315 gboolean open_in_new_window)
1317 GtkTreeModel *model;
1318 GtkTreePath *path;
1320 model = gtk_tree_view_get_model (sidebar->tree_view);
1321 gtk_tree_view_get_cursor (sidebar->tree_view, &path, NULL);
1323 open_selected_bookmark (sidebar, model, path, open_in_new_window);
1325 gtk_tree_path_free (path);
1328 static void
1329 open_shortcut_cb (GtkMenuItem *item,
1330 NautilusPlacesSidebar *sidebar)
1332 open_shortcut_from_menu (sidebar, FALSE);
1335 static void
1336 open_shortcut_in_new_window_cb (GtkMenuItem *item,
1337 NautilusPlacesSidebar *sidebar)
1339 open_shortcut_from_menu (sidebar, TRUE);
1342 /* Rename the selected bookmark */
1343 static void
1344 rename_selected_bookmark (NautilusPlacesSidebar *sidebar)
1346 GtkTreeIter iter;
1347 GtkTreePath *path;
1348 GtkTreeViewColumn *column;
1349 GtkCellRenderer *cell;
1350 GList *renderers;
1352 if (get_selected_iter (sidebar, &iter)) {
1353 path = gtk_tree_model_get_path (GTK_TREE_MODEL (sidebar->store), &iter);
1354 column = gtk_tree_view_get_column (GTK_TREE_VIEW (sidebar->tree_view), 0);
1355 renderers = gtk_tree_view_column_get_cell_renderers (column);
1356 cell = g_list_nth_data (renderers, 1);
1357 g_list_free (renderers);
1358 g_object_set (cell, "editable", TRUE, NULL);
1359 gtk_tree_view_set_cursor_on_cell (GTK_TREE_VIEW (sidebar->tree_view),
1360 path, column, cell, TRUE);
1361 gtk_tree_path_free (path);
1365 static void
1366 rename_shortcut_cb (GtkMenuItem *item,
1367 NautilusPlacesSidebar *sidebar)
1369 rename_selected_bookmark (sidebar);
1372 /* Removes the selected bookmarks */
1373 static void
1374 remove_selected_bookmarks (NautilusPlacesSidebar *sidebar)
1376 GtkTreeIter iter;
1377 PlaceType type;
1378 int index;
1380 if (!get_selected_iter (sidebar, &iter)) {
1381 return;
1384 gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
1385 PLACES_SIDEBAR_COLUMN_ROW_TYPE, &type,
1386 -1);
1388 if (type != PLACES_BOOKMARK) {
1389 return;
1392 gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
1393 PLACES_SIDEBAR_COLUMN_INDEX, &index,
1394 -1);
1396 nautilus_bookmark_list_delete_item_at (sidebar->bookmarks, index);
1399 static void
1400 remove_shortcut_cb (GtkMenuItem *item,
1401 NautilusPlacesSidebar *sidebar)
1403 remove_selected_bookmarks (sidebar);
1406 static void
1407 mount_shortcut_cb (GtkMenuItem *item,
1408 NautilusPlacesSidebar *sidebar)
1410 GtkTreeIter iter;
1411 GVolume *volume;
1413 if (!get_selected_iter (sidebar, &iter)) {
1414 return;
1417 gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
1418 PLACES_SIDEBAR_COLUMN_VOLUME, &volume,
1419 -1);
1421 if (volume != NULL) {
1422 nautilus_file_operations_mount_volume (NULL, volume, FALSE);
1423 g_object_unref (volume);
1427 static void
1428 unmount_shortcut_cb (GtkMenuItem *item,
1429 NautilusPlacesSidebar *sidebar)
1431 GtkTreeIter iter;
1432 GMount *mount;
1433 GVolume *volume;
1435 if (!get_selected_iter (sidebar, &iter)) {
1436 return;
1439 gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
1440 PLACES_SIDEBAR_COLUMN_VOLUME, &volume,
1441 PLACES_SIDEBAR_COLUMN_MOUNT, &mount,
1442 -1);
1444 if (mount != NULL) {
1445 GtkWidget *toplevel;
1447 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (sidebar->tree_view));
1448 nautilus_file_operations_unmount_mount (GTK_WINDOW (toplevel),
1449 mount, FALSE, TRUE);
1451 if (mount != NULL) {
1452 g_object_unref (mount);
1454 if (volume != NULL) {
1455 g_object_unref (volume);
1459 static void
1460 drive_eject_cb (GObject *source_object,
1461 GAsyncResult *res,
1462 gpointer user_data)
1464 GError *error;
1465 char *primary;
1466 char *name;
1467 error = NULL;
1468 if (!g_drive_eject_finish (G_DRIVE (source_object), res, &error)) {
1469 if (error->code != G_IO_ERROR_FAILED_HANDLED) {
1470 name = g_drive_get_name (G_DRIVE (source_object));
1471 primary = g_strdup_printf (_("Unable to eject %s"), name);
1472 g_free (name);
1473 eel_show_error_dialog (primary,
1474 error->message,
1475 NULL);
1476 g_free (primary);
1478 g_error_free (error);
1482 static void
1483 volume_eject_cb (GObject *source_object,
1484 GAsyncResult *res,
1485 gpointer user_data)
1487 GError *error;
1488 char *primary;
1489 char *name;
1490 error = NULL;
1491 if (!g_volume_eject_finish (G_VOLUME (source_object), res, &error)) {
1492 if (error->code != G_IO_ERROR_FAILED_HANDLED) {
1493 name = g_volume_get_name (G_VOLUME (source_object));
1494 primary = g_strdup_printf (_("Unable to eject %s"), name);
1495 g_free (name);
1496 eel_show_error_dialog (primary,
1497 error->message,
1498 NULL);
1499 g_free (primary);
1501 g_error_free (error);
1505 static void
1506 mount_eject_cb (GObject *source_object,
1507 GAsyncResult *res,
1508 gpointer user_data)
1510 GError *error;
1511 char *primary;
1512 char *name;
1513 error = NULL;
1514 if (!g_mount_eject_finish (G_MOUNT (source_object), res, &error)) {
1515 if (error->code != G_IO_ERROR_FAILED_HANDLED) {
1516 name = g_mount_get_name (G_MOUNT (source_object));
1517 primary = g_strdup_printf (_("Unable to eject %s"), name);
1518 g_free (name);
1519 eel_show_error_dialog (primary,
1520 error->message,
1521 NULL);
1522 g_free (primary);
1524 g_error_free (error);
1528 static void
1529 eject_shortcut_cb (GtkMenuItem *item,
1530 NautilusPlacesSidebar *sidebar)
1532 GtkTreeIter iter;
1533 GMount *mount;
1534 GVolume *volume;
1535 GDrive *drive;
1537 if (!get_selected_iter (sidebar, &iter)) {
1538 return;
1541 gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
1542 PLACES_SIDEBAR_COLUMN_MOUNT, &mount,
1543 PLACES_SIDEBAR_COLUMN_VOLUME, &volume,
1544 PLACES_SIDEBAR_COLUMN_DRIVE, &drive,
1545 -1);
1547 if (mount != NULL) {
1548 g_mount_eject (mount, 0, NULL, mount_eject_cb, NULL);
1549 } else if (volume != NULL) {
1550 g_volume_eject (volume, 0, NULL, volume_eject_cb, NULL);
1551 } else if (drive != NULL) {
1552 g_drive_eject (drive, 0, NULL, drive_eject_cb, NULL);
1555 if (mount != NULL)
1556 g_object_unref (mount);
1557 if (volume != NULL)
1558 g_object_unref (volume);
1559 if (drive != NULL)
1560 g_object_unref (drive);
1563 static void
1564 drive_poll_for_media_cb (GObject *source_object,
1565 GAsyncResult *res,
1566 gpointer user_data)
1568 GError *error;
1569 char *primary;
1570 char *name;
1572 error = NULL;
1573 if (!g_drive_poll_for_media_finish (G_DRIVE (source_object), res, &error)) {
1574 if (error->code != G_IO_ERROR_FAILED_HANDLED) {
1575 name = g_drive_get_name (G_DRIVE (source_object));
1576 primary = g_strdup_printf (_("Unable to poll %s for media changes"), name);
1577 g_free (name);
1578 eel_show_error_dialog (primary,
1579 error->message,
1580 NULL);
1581 g_free (primary);
1583 g_error_free (error);
1587 static void
1588 rescan_shortcut_cb (GtkMenuItem *item,
1589 NautilusPlacesSidebar *sidebar)
1591 GtkTreeIter iter;
1592 GDrive *drive;
1594 if (!get_selected_iter (sidebar, &iter)) {
1595 return;
1598 gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
1599 PLACES_SIDEBAR_COLUMN_DRIVE, &drive,
1600 -1);
1602 if (drive != NULL) {
1603 g_drive_poll_for_media (drive, NULL, drive_poll_for_media_cb, NULL);
1605 g_object_unref (drive);
1608 static void
1609 format_shortcut_cb (GtkMenuItem *item,
1610 NautilusPlacesSidebar *sidebar)
1612 g_spawn_command_line_async ("gfloppy", NULL);
1615 static void
1616 empty_trash_cb (GtkMenuItem *item,
1617 NautilusPlacesSidebar *sidebar)
1619 nautilus_file_operations_empty_trash (GTK_WIDGET (sidebar->window));
1622 /* Handler for GtkWidget::key-press-event on the shortcuts list */
1623 static gboolean
1624 bookmarks_key_press_event_cb (GtkWidget *widget,
1625 GdkEventKey *event,
1626 NautilusPlacesSidebar *sidebar)
1628 guint modifiers;
1630 modifiers = gtk_accelerator_get_default_mod_mask ();
1632 if ((event->keyval == GDK_BackSpace
1633 || event->keyval == GDK_Delete
1634 || event->keyval == GDK_KP_Delete)
1635 && (event->state & modifiers) == 0) {
1636 remove_selected_bookmarks (sidebar);
1637 return TRUE;
1640 if ((event->keyval == GDK_F2)
1641 && (event->state & modifiers) == 0) {
1642 rename_selected_bookmark (sidebar);
1643 return TRUE;
1646 return FALSE;
1649 /* Constructs the popup menu for the file list if needed */
1650 static void
1651 bookmarks_build_popup_menu (NautilusPlacesSidebar *sidebar)
1653 GtkWidget *item;
1655 if (sidebar->popup_menu) {
1656 return;
1659 sidebar->popup_menu = gtk_menu_new ();
1660 gtk_menu_attach_to_widget (GTK_MENU (sidebar->popup_menu),
1661 GTK_WIDGET (sidebar),
1662 bookmarks_popup_menu_detach_cb);
1664 item = gtk_image_menu_item_new_with_mnemonic (_("_Open"));
1665 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),
1666 gtk_image_new_from_stock (GTK_STOCK_OPEN, GTK_ICON_SIZE_MENU));
1667 g_signal_connect (item, "activate",
1668 G_CALLBACK (open_shortcut_cb), sidebar);
1669 gtk_widget_show (item);
1670 gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
1672 item = gtk_menu_item_new_with_mnemonic (_("Open in New _Window"));
1673 g_signal_connect (item, "activate",
1674 G_CALLBACK (open_shortcut_in_new_window_cb), sidebar);
1675 gtk_widget_show (item);
1676 gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
1678 item = gtk_image_menu_item_new_with_label (_("Remove"));
1679 sidebar->popup_menu_remove_item = item;
1680 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),
1681 gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU));
1682 g_signal_connect (item, "activate",
1683 G_CALLBACK (remove_shortcut_cb), sidebar);
1684 gtk_widget_show (item);
1685 gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
1687 item = gtk_menu_item_new_with_label (_("Rename..."));
1688 sidebar->popup_menu_rename_item = item;
1689 g_signal_connect (item, "activate",
1690 G_CALLBACK (rename_shortcut_cb), sidebar);
1691 gtk_widget_show (item);
1692 gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
1694 /* Mount/Unmount/Eject menu items */
1696 sidebar->popup_menu_separator_item =
1697 GTK_WIDGET (eel_gtk_menu_append_separator (GTK_MENU (sidebar->popup_menu)));
1699 item = gtk_menu_item_new_with_mnemonic (_("_Mount"));
1700 sidebar->popup_menu_mount_item = item;
1701 g_signal_connect (item, "activate",
1702 G_CALLBACK (mount_shortcut_cb), sidebar);
1703 gtk_widget_show (item);
1704 gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
1706 item = gtk_menu_item_new_with_mnemonic (_("_Unmount"));
1707 sidebar->popup_menu_unmount_item = item;
1708 g_signal_connect (item, "activate",
1709 G_CALLBACK (unmount_shortcut_cb), sidebar);
1710 gtk_widget_show (item);
1711 gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
1713 item = gtk_menu_item_new_with_mnemonic (_("_Eject"));
1714 sidebar->popup_menu_eject_item = item;
1715 g_signal_connect (item, "activate",
1716 G_CALLBACK (eject_shortcut_cb), sidebar);
1717 gtk_widget_show (item);
1718 gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
1720 item = gtk_menu_item_new_with_mnemonic (_("_Rescan"));
1721 sidebar->popup_menu_rescan_item = item;
1722 g_signal_connect (item, "activate",
1723 G_CALLBACK (rescan_shortcut_cb), sidebar);
1724 gtk_widget_show (item);
1725 gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
1727 item = gtk_menu_item_new_with_mnemonic (_("_Format"));
1728 sidebar->popup_menu_format_item = item;
1729 g_signal_connect (item, "activate",
1730 G_CALLBACK (format_shortcut_cb), sidebar);
1731 gtk_widget_show (item);
1732 gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
1734 /* Empty Trash menu item */
1736 item = gtk_menu_item_new_with_mnemonic (_("Empty _Trash"));
1737 sidebar->popup_menu_empty_trash_item = item;
1738 g_signal_connect (item, "activate",
1739 G_CALLBACK (empty_trash_cb), sidebar);
1740 gtk_widget_show (item);
1741 gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
1743 bookmarks_check_popup_sensitivity (sidebar);
1746 static void
1747 bookmarks_update_popup_menu (NautilusPlacesSidebar *sidebar)
1749 bookmarks_build_popup_menu (sidebar);
1752 static void
1753 bookmarks_popup_menu (NautilusPlacesSidebar *sidebar,
1754 GdkEventButton *event)
1756 bookmarks_update_popup_menu (sidebar);
1757 eel_pop_up_context_menu (GTK_MENU(sidebar->popup_menu),
1758 EEL_DEFAULT_POPUP_MENU_DISPLACEMENT,
1759 EEL_DEFAULT_POPUP_MENU_DISPLACEMENT,
1760 event);
1763 /* Callback used for the GtkWidget::popup-menu signal of the shortcuts list */
1764 static gboolean
1765 bookmarks_popup_menu_cb (GtkWidget *widget,
1766 NautilusPlacesSidebar *sidebar)
1768 bookmarks_popup_menu (sidebar, NULL);
1769 return TRUE;
1772 /* Callback used when a button is pressed on the shortcuts list.
1773 * We trap button 3 to bring up a popup menu.
1775 static gboolean
1776 bookmarks_button_press_event_cb (GtkWidget *widget,
1777 GdkEventButton *event,
1778 NautilusPlacesSidebar *sidebar)
1780 if (event->button == 3) {
1781 bookmarks_popup_menu (sidebar, event);
1783 return FALSE;
1787 static void
1788 bookmarks_edited (GtkCellRenderer *cell,
1789 gchar *path_string,
1790 gchar *new_text,
1791 NautilusPlacesSidebar *sidebar)
1793 GtkTreePath *path;
1794 GtkTreeIter iter;
1795 NautilusBookmark *bookmark;
1796 int index;
1798 g_object_set (cell, "editable", FALSE, NULL);
1800 path = gtk_tree_path_new_from_string (path_string);
1801 gtk_tree_model_get_iter (GTK_TREE_MODEL (sidebar->store), &iter, path);
1802 gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
1803 PLACES_SIDEBAR_COLUMN_INDEX, &index,
1804 -1);
1805 gtk_tree_path_free (path);
1806 bookmark = nautilus_bookmark_list_item_at (sidebar->bookmarks, index);
1808 if (bookmark != NULL) {
1809 nautilus_bookmark_set_has_custom_name (bookmark, TRUE);
1810 nautilus_bookmark_set_name (bookmark, new_text);
1814 static void
1815 bookmarks_editing_canceled (GtkCellRenderer *cell,
1816 NautilusPlacesSidebar *sidebar)
1818 g_object_set (cell, "editable", FALSE, NULL);
1821 static void
1822 trash_state_changed_cb (NautilusTrashMonitor *trash_monitor,
1823 gboolean state,
1824 gpointer data)
1826 NautilusPlacesSidebar *sidebar;
1828 sidebar = NAUTILUS_PLACES_SIDEBAR (data);
1830 /* The trash icon changed, update the sidebar */
1831 update_places (sidebar);
1833 bookmarks_check_popup_sensitivity (sidebar);
1836 static void
1837 nautilus_places_sidebar_init (NautilusPlacesSidebar *sidebar)
1839 GtkTreeView *tree_view;
1840 GtkTreeViewColumn *col;
1841 GtkCellRenderer *cell;
1842 GtkTreeSelection *selection;
1844 sidebar->volume_monitor = g_volume_monitor_get ();
1846 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sidebar),
1847 GTK_POLICY_NEVER,
1848 GTK_POLICY_AUTOMATIC);
1849 gtk_scrolled_window_set_hadjustment (GTK_SCROLLED_WINDOW (sidebar), NULL);
1850 gtk_scrolled_window_set_vadjustment (GTK_SCROLLED_WINDOW (sidebar), NULL);
1852 /* tree view */
1853 tree_view = GTK_TREE_VIEW (gtk_tree_view_new ());
1854 gtk_tree_view_set_headers_visible (tree_view, FALSE);
1856 col = GTK_TREE_VIEW_COLUMN (gtk_tree_view_column_new ());
1858 cell = gtk_cell_renderer_pixbuf_new ();
1859 gtk_tree_view_column_pack_start (col, cell, FALSE);
1860 gtk_tree_view_column_set_attributes (col, cell,
1861 "pixbuf", PLACES_SIDEBAR_COLUMN_ICON,
1862 NULL);
1864 cell = gtk_cell_renderer_text_new ();
1865 gtk_tree_view_column_pack_start (col, cell, TRUE);
1866 gtk_tree_view_column_set_attributes (col, cell,
1867 "text", PLACES_SIDEBAR_COLUMN_NAME,
1868 NULL);
1870 g_signal_connect (cell, "edited",
1871 G_CALLBACK (bookmarks_edited), sidebar);
1872 g_signal_connect (cell, "editing-canceled",
1873 G_CALLBACK (bookmarks_editing_canceled), sidebar);
1875 gtk_tree_view_set_row_separator_func (tree_view,
1876 nautilus_shortcuts_row_separator_func,
1877 NULL,
1878 NULL);
1880 gtk_tree_view_column_set_fixed_width (col, NAUTILUS_ICON_SIZE_SMALLER);
1881 gtk_tree_view_append_column (tree_view, col);
1883 sidebar->store = gtk_list_store_new (PLACES_SIDEBAR_COLUMN_COUNT,
1884 G_TYPE_INT,
1885 G_TYPE_STRING,
1886 G_TYPE_DRIVE,
1887 G_TYPE_VOLUME,
1888 G_TYPE_MOUNT,
1889 G_TYPE_STRING,
1890 GDK_TYPE_PIXBUF,
1891 G_TYPE_INT
1893 sidebar->filter_model = nautilus_shortcuts_model_filter_new (sidebar,
1894 GTK_TREE_MODEL (sidebar->store),
1895 NULL);
1897 gtk_tree_view_set_model (tree_view, sidebar->filter_model);
1898 gtk_container_add (GTK_CONTAINER (sidebar), GTK_WIDGET (tree_view));
1899 gtk_widget_show (GTK_WIDGET (tree_view));
1901 gtk_widget_show (GTK_WIDGET (sidebar));
1902 sidebar->tree_view = tree_view;
1904 selection = gtk_tree_view_get_selection (tree_view);
1905 gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
1907 g_signal_connect_object
1908 (tree_view, "row_activated",
1909 G_CALLBACK (row_activated_callback), sidebar, 0);
1912 gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (tree_view),
1913 GDK_BUTTON1_MASK,
1914 nautilus_shortcuts_source_targets,
1915 G_N_ELEMENTS (nautilus_shortcuts_source_targets),
1916 GDK_ACTION_MOVE);
1917 gtk_drag_dest_set (GTK_WIDGET (tree_view),
1919 nautilus_shortcuts_drop_targets, G_N_ELEMENTS (nautilus_shortcuts_drop_targets),
1920 GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK);
1922 g_signal_connect (tree_view, "key-press-event",
1923 G_CALLBACK (bookmarks_key_press_event_cb), sidebar);
1925 g_signal_connect (tree_view, "drag-data-delete",
1926 G_CALLBACK (drag_data_delete_callback), sidebar);
1927 g_signal_connect (tree_view, "drag-motion",
1928 G_CALLBACK (drag_motion_callback), sidebar);
1929 g_signal_connect (tree_view, "drag-leave",
1930 G_CALLBACK (drag_leave_callback), sidebar);
1931 g_signal_connect (tree_view, "drag-data-received",
1932 G_CALLBACK (drag_data_received_callback), sidebar);
1933 g_signal_connect (tree_view, "drag-drop",
1934 G_CALLBACK (drag_drop_callback), sidebar);
1935 g_signal_connect (selection, "changed",
1936 G_CALLBACK (bookmarks_selection_changed_cb), sidebar);
1937 g_signal_connect (tree_view, "popup-menu",
1938 G_CALLBACK (bookmarks_popup_menu_cb), sidebar);
1939 g_signal_connect (tree_view, "button-press-event",
1940 G_CALLBACK (bookmarks_button_press_event_cb), sidebar);
1942 eel_gtk_tree_view_set_activate_on_single_click (sidebar->tree_view,
1943 TRUE);
1945 eel_preferences_add_callback_while_alive (NAUTILUS_PREFERENCES_DESKTOP_IS_HOME_DIR,
1946 desktop_location_changed_callback,
1947 sidebar,
1948 G_OBJECT (sidebar));
1950 g_signal_connect_object (nautilus_trash_monitor_get (),
1951 "trash_state_changed",
1952 G_CALLBACK (trash_state_changed_cb),
1953 sidebar, 0);
1956 static void
1957 nautilus_places_sidebar_dispose (GObject *object)
1959 NautilusPlacesSidebar *sidebar;
1961 sidebar = NAUTILUS_PLACES_SIDEBAR (object);
1963 sidebar->window = NULL;
1964 sidebar->tree_view = NULL;
1966 g_free (sidebar->uri);
1967 sidebar->uri = NULL;
1969 free_drag_data (sidebar);
1971 if (sidebar->store != NULL) {
1972 g_object_unref (sidebar->store);
1973 sidebar->store = NULL;
1976 if (sidebar->volume_monitor != NULL) {
1977 g_object_unref (sidebar->volume_monitor);
1978 sidebar->volume_monitor = NULL;
1981 G_OBJECT_CLASS (nautilus_places_sidebar_parent_class)->dispose (object);
1984 static void
1985 nautilus_places_sidebar_class_init (NautilusPlacesSidebarClass *class)
1987 G_OBJECT_CLASS (class)->dispose = nautilus_places_sidebar_dispose;
1989 GTK_WIDGET_CLASS (class)->style_set = nautilus_places_sidebar_style_set;
1992 static const char *
1993 nautilus_places_sidebar_get_sidebar_id (NautilusSidebar *sidebar)
1995 return NAUTILUS_PLACES_SIDEBAR_ID;
1998 static char *
1999 nautilus_places_sidebar_get_tab_label (NautilusSidebar *sidebar)
2001 return g_strdup (_("Places"));
2004 static char *
2005 nautilus_places_sidebar_get_tab_tooltip (NautilusSidebar *sidebar)
2007 return g_strdup (_("Show Places"));
2010 static GdkPixbuf *
2011 nautilus_places_sidebar_get_tab_icon (NautilusSidebar *sidebar)
2013 return NULL;
2016 static void
2017 nautilus_places_sidebar_is_visible_changed (NautilusSidebar *sidebar,
2018 gboolean is_visible)
2020 /* Do nothing */
2023 static void
2024 nautilus_places_sidebar_iface_init (NautilusSidebarIface *iface)
2026 iface->get_sidebar_id = nautilus_places_sidebar_get_sidebar_id;
2027 iface->get_tab_label = nautilus_places_sidebar_get_tab_label;
2028 iface->get_tab_tooltip = nautilus_places_sidebar_get_tab_tooltip;
2029 iface->get_tab_icon = nautilus_places_sidebar_get_tab_icon;
2030 iface->is_visible_changed = nautilus_places_sidebar_is_visible_changed;
2033 static void
2034 nautilus_places_sidebar_set_parent_window (NautilusPlacesSidebar *sidebar,
2035 NautilusWindowInfo *window)
2037 sidebar->window = window;
2039 sidebar->bookmarks = nautilus_window_info_get_bookmark_list (window);
2040 sidebar->uri = nautilus_window_info_get_current_location (window);
2042 g_signal_connect_object (sidebar->bookmarks, "contents_changed",
2043 G_CALLBACK (update_places),
2044 sidebar, G_CONNECT_SWAPPED);
2046 g_signal_connect_object (window, "loading_uri",
2047 G_CALLBACK (loading_uri_callback),
2048 sidebar, 0);
2050 g_signal_connect_object (sidebar->volume_monitor, "volume_added",
2051 G_CALLBACK (volume_added_callback), sidebar, 0);
2052 g_signal_connect_object (sidebar->volume_monitor, "volume_removed",
2053 G_CALLBACK (volume_removed_callback), sidebar, 0);
2054 g_signal_connect_object (sidebar->volume_monitor, "volume_changed",
2055 G_CALLBACK (volume_changed_callback), sidebar, 0);
2056 g_signal_connect_object (sidebar->volume_monitor, "mount_added",
2057 G_CALLBACK (mount_added_callback), sidebar, 0);
2058 g_signal_connect_object (sidebar->volume_monitor, "mount_removed",
2059 G_CALLBACK (mount_removed_callback), sidebar, 0);
2060 g_signal_connect_object (sidebar->volume_monitor, "mount_changed",
2061 G_CALLBACK (mount_changed_callback), sidebar, 0);
2062 g_signal_connect_object (sidebar->volume_monitor, "drive_disconnected",
2063 G_CALLBACK (drive_disconnected_callback), sidebar, 0);
2064 g_signal_connect_object (sidebar->volume_monitor, "drive_connected",
2065 G_CALLBACK (drive_connected_callback), sidebar, 0);
2066 g_signal_connect_object (sidebar->volume_monitor, "drive_changed",
2067 G_CALLBACK (drive_changed_callback), sidebar, 0);
2069 update_places (sidebar);
2072 static void
2073 nautilus_places_sidebar_style_set (GtkWidget *widget,
2074 GtkStyle *previous_style)
2076 NautilusPlacesSidebar *sidebar;
2078 sidebar = NAUTILUS_PLACES_SIDEBAR (widget);
2080 update_places (sidebar);
2083 static NautilusSidebar *
2084 nautilus_places_sidebar_create (NautilusSidebarProvider *provider,
2085 NautilusWindowInfo *window)
2087 NautilusPlacesSidebar *sidebar;
2089 sidebar = g_object_new (nautilus_places_sidebar_get_type (), NULL);
2090 nautilus_places_sidebar_set_parent_window (sidebar, window);
2091 g_object_ref (sidebar);
2092 gtk_object_sink (GTK_OBJECT (sidebar));
2094 return NAUTILUS_SIDEBAR (sidebar);
2097 static void
2098 sidebar_provider_iface_init (NautilusSidebarProviderIface *iface)
2100 iface->create = nautilus_places_sidebar_create;
2103 static void
2104 nautilus_places_sidebar_provider_init (NautilusPlacesSidebarProvider *sidebar)
2108 static void
2109 nautilus_places_sidebar_provider_class_init (NautilusPlacesSidebarProviderClass *class)
2113 void
2114 nautilus_places_sidebar_register (void)
2116 nautilus_module_add_type (nautilus_places_sidebar_provider_get_type ());
2119 /* Drag and drop interfaces */
2121 static void
2122 _nautilus_shortcuts_model_filter_class_init (NautilusShortcutsModelFilterClass *class)
2126 static void
2127 _nautilus_shortcuts_model_filter_init (NautilusShortcutsModelFilter *model)
2129 model->sidebar = NULL;
2132 /* GtkTreeDragSource::row_draggable implementation for the shortcuts filter model */
2133 static gboolean
2134 nautilus_shortcuts_model_filter_row_draggable (GtkTreeDragSource *drag_source,
2135 GtkTreePath *path)
2137 NautilusShortcutsModelFilter *model;
2138 int pos;
2139 int bookmarks_pos;
2140 int num_bookmarks;
2142 model = NAUTILUS_SHORTCUTS_MODEL_FILTER (drag_source);
2144 pos = *gtk_tree_path_get_indices (path);
2145 bookmarks_pos = get_bookmark_index (model->sidebar->tree_view);
2146 num_bookmarks = nautilus_bookmark_list_length (model->sidebar->bookmarks);
2148 return (pos >= bookmarks_pos && pos < bookmarks_pos + num_bookmarks);
2151 /* GtkTreeDragSource::drag_data_get implementation for the shortcuts filter model */
2152 static gboolean
2153 nautilus_shortcuts_model_filter_drag_data_get (GtkTreeDragSource *drag_source,
2154 GtkTreePath *path,
2155 GtkSelectionData *selection_data)
2157 NautilusShortcutsModelFilter *model;
2159 model = NAUTILUS_SHORTCUTS_MODEL_FILTER (drag_source);
2161 /* FIXME */
2163 return FALSE;
2166 /* Fill the GtkTreeDragSourceIface vtable */
2167 static void
2168 nautilus_shortcuts_model_filter_drag_source_iface_init (GtkTreeDragSourceIface *iface)
2170 iface->row_draggable = nautilus_shortcuts_model_filter_row_draggable;
2171 iface->drag_data_get = nautilus_shortcuts_model_filter_drag_data_get;
2174 static GtkTreeModel *
2175 nautilus_shortcuts_model_filter_new (NautilusPlacesSidebar *sidebar,
2176 GtkTreeModel *child_model,
2177 GtkTreePath *root)
2179 NautilusShortcutsModelFilter *model;
2181 model = g_object_new (NAUTILUS_SHORTCUTS_MODEL_FILTER_TYPE,
2182 "child-model", child_model,
2183 "virtual-root", root,
2184 NULL);
2186 model->sidebar = sidebar;
2188 return GTK_TREE_MODEL (model);