1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
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)
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>
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))
71 GtkScrolledWindow parent
;
72 GtkTreeView
*tree_view
;
75 GtkTreeModel
*filter_model
;
76 NautilusWindowInfo
*window
;
77 NautilusBookmarkList
*bookmarks
;
78 GVolumeMonitor
*volume_monitor
;
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
;
98 GtkScrolledWindowClass parent
;
99 } NautilusPlacesSidebarClass
;
103 } NautilusPlacesSidebarProvider
;
107 } NautilusPlacesSidebarProviderClass
;
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
124 PLACES_MOUNTED_VOLUME
,
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
,
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 */
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 */
158 GtkTreeModelFilter parent
;
160 NautilusPlacesSidebar
*sidebar
;
161 } NautilusShortcutsModelFilter
;
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
,
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
));
192 add_place (NautilusPlacesSidebar
*sidebar
,
193 PlaceType place_type
,
203 GtkTreeIter iter
, child_iter
;
204 NautilusIconInfo
*icon_info
;
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
,
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
),
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
;
246 int bookmark_count
, index
;
247 char *location
, *mount_uri
, *name
, *desktop_path
;
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) {
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
,
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
);
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
,
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
);
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
,
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
) {
315 volumes
= g_drive_get_volumes (drive
);
316 if (volumes
!= NULL
) {
317 for (ll
= volumes
; ll
!= NULL
; ll
= ll
->next
) {
319 mount
= g_volume_get_mount (volume
);
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
);
338 /* Do show the unmounted volumes in the sidebar;
339 * this is so the user can mount it (in case automounting
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
,
350 drive
, volume
, NULL
, 0);
351 g_object_unref (icon
);
354 g_object_unref (volume
);
356 g_list_free (volumes
);
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
,
371 drive
, NULL
, NULL
, 0);
372 g_object_unref (icon
);
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
) {
384 drive
= g_volume_get_drive (volume
);
386 g_object_unref (volume
);
387 g_object_unref (drive
);
390 mount
= g_volume_get_mount (volume
);
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
);
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
,
413 NULL
, volume
, NULL
, 0);
414 g_object_unref (icon
);
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
) {
425 volume
= g_mount_get_volume (mount
);
426 if (volume
!= NULL
) {
427 g_object_unref (volume
);
428 g_object_unref (mount
);
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
);
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
);
461 gtk_list_store_append (sidebar
->store
, &iter
);
462 gtk_list_store_set (sidebar
->store
, &iter
,
463 PLACES_SIDEBAR_COLUMN_ROW_TYPE
, PLACES_SEPARATOR
,
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
)) {
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
);
486 g_object_unref (icon
);
493 nautilus_shortcuts_row_separator_func (GtkTreeModel
*model
,
499 gtk_tree_model_get (model
, iter
, PLACES_SIDEBAR_COLUMN_ROW_TYPE
, &type
, -1);
501 if (type
== PLACES_SEPARATOR
) {
509 mount_added_callback (GVolumeMonitor
*volume_monitor
,
511 NautilusPlacesSidebar
*sidebar
)
513 update_places (sidebar
);
517 mount_removed_callback (GVolumeMonitor
*volume_monitor
,
519 NautilusPlacesSidebar
*sidebar
)
521 update_places (sidebar
);
525 mount_changed_callback (GVolumeMonitor
*volume_monitor
,
527 NautilusPlacesSidebar
*sidebar
)
529 update_places (sidebar
);
533 volume_added_callback (GVolumeMonitor
*volume_monitor
,
535 NautilusPlacesSidebar
*sidebar
)
537 update_places (sidebar
);
541 volume_removed_callback (GVolumeMonitor
*volume_monitor
,
543 NautilusPlacesSidebar
*sidebar
)
545 update_places (sidebar
);
549 volume_changed_callback (GVolumeMonitor
*volume_monitor
,
551 NautilusPlacesSidebar
*sidebar
)
553 update_places (sidebar
);
557 drive_disconnected_callback (GVolumeMonitor
*volume_monitor
,
559 NautilusPlacesSidebar
*sidebar
)
561 update_places (sidebar
);
565 drive_connected_callback (GVolumeMonitor
*volume_monitor
,
567 NautilusPlacesSidebar
*sidebar
)
569 update_places (sidebar
);
573 drive_changed_callback (GVolumeMonitor
*volume_monitor
,
575 NautilusPlacesSidebar
*sidebar
)
577 update_places (sidebar
);
581 row_activated_callback (GtkTreeView
*tree_view
,
583 GtkTreeViewColumn
*column
,
586 open_selected_bookmark (NAUTILUS_PLACES_SIDEBAR (user_data
),
587 gtk_tree_view_get_model (tree_view
),
593 desktop_location_changed_callback (gpointer user_data
)
595 NautilusPlacesSidebar
*sidebar
;
597 sidebar
= NAUTILUS_PLACES_SIDEBAR (user_data
);
599 update_places (sidebar
);
603 loading_uri_callback (NautilusWindowInfo
*window
,
605 NautilusPlacesSidebar
*sidebar
)
607 GtkTreeSelection
*selection
;
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
);
622 gtk_tree_model_get (sidebar
->filter_model
, &iter
,
623 PLACES_SIDEBAR_COLUMN_URI
, &uri
,
626 if (strcmp (uri
, location
) == 0) {
628 gtk_tree_selection_select_iter (selection
, &iter
);
633 valid
= gtk_tree_model_iter_next (sidebar
->filter_model
, &iter
);
640 get_bookmark_index (GtkTreeView
*tree_view
)
645 PlaceType place_type
;
648 model
= gtk_tree_view_get_model (tree_view
);
653 p
= gtk_tree_path_new_first ();
655 gtk_tree_model_get_iter (model
, &iter
, p
);
656 gtk_tree_model_get (model
, &iter
,
657 PLACES_SIDEBAR_COLUMN_ROW_TYPE
, &place_type
,
660 if (place_type
== PLACES_SEPARATOR
) {
661 bookmark_index
= *gtk_tree_path_get_indices (p
) + 1;
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 */
676 compute_drop_position (GtkTreeView
*tree_view
,
680 GtkTreeViewDropPosition
*pos
,
681 NautilusPlacesSidebar
*sidebar
)
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
,
696 row
= bookmarks_index
+ num_bookmarks
- 1;
697 *path
= gtk_tree_path_new_from_indices (row
, -1);
698 *pos
= GTK_TREE_VIEW_DROP_AFTER
;
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);
719 get_drag_data (GtkTreeView
*tree_view
,
720 GdkDragContext
*context
,
725 target
= gtk_drag_dest_find_target (GTK_WIDGET (tree_view
),
729 gtk_drag_get_data (GTK_WIDGET (tree_view
),
730 context
, target
, time
);
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
;
745 can_accept_file_as_bookmark (NautilusFile
*file
)
747 return nautilus_file_is_directory (file
);
751 can_accept_items_as_bookmarks (const GList
*items
)
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
);
767 nautilus_file_unref (file
);
774 drag_data_delete_callback (GtkWidget
*widget
,
775 GdkDragContext
*context
,
776 NautilusPlacesSidebar
*sidebar
)
778 g_signal_stop_emission_by_name (widget
, "drag-data-delete");
782 drag_motion_callback (GtkTreeView
*tree_view
,
783 GdkDragContext
*context
,
787 NautilusPlacesSidebar
*sidebar
)
790 GtkTreeViewDropPosition pos
;
792 GtkTreeIter iter
, child_iter
;
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
;
809 if (sidebar
->drag_list
== NULL
) {
812 gtk_tree_model_get_iter (sidebar
->filter_model
,
814 gtk_tree_model_filter_convert_iter_to_child_iter (
815 GTK_TREE_MODEL_FILTER (sidebar
->filter_model
),
817 gtk_tree_model_get (GTK_TREE_MODEL (sidebar
->store
),
819 PLACES_SIDEBAR_COLUMN_URI
, &uri
,
821 nautilus_drag_default_drop_action_for_icons (context
, 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");
833 gdk_drag_status (context
, action
, time
);
841 drag_leave_callback (GtkTreeView
*tree_view
,
842 GdkDragContext
*context
,
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 */
853 bookmarks_drop_uris (NautilusPlacesSidebar
*sidebar
,
854 GtkSelectionData
*selection_data
,
857 NautilusBookmark
*bookmark
;
865 uris
= gtk_selection_data_get_uris (selection_data
);
869 for (i
= 0; uris
[i
]; i
++) {
871 file
= nautilus_file_get_by_uri (uri
);
873 if (!can_accept_file_as_bookmark (file
)) {
874 nautilus_file_unref (file
);
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
,
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
);
903 uri_list_from_selection (GList
*selection
)
905 NautilusDragSelectionItem
*item
;
910 for (l
= selection
; l
!= NULL
; l
= l
->next
) {
912 ret
= g_list_prepend (ret
, item
->uri
);
915 return g_list_reverse (ret
);
919 build_selection_list (const char *data
)
921 NautilusDragSelectionItem
*item
;
927 uris
= g_uri_list_extract_uris (data
);
930 for (i
= 0; uris
[i
]; 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
);
940 return g_list_reverse (result
);
944 get_selected_iter (NautilusPlacesSidebar
*sidebar
,
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
)) {
954 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (sidebar
->filter_model
),
960 /* Reorders the selected bookmark to the specified position */
962 reorder_bookmarks (NautilusPlacesSidebar
*sidebar
,
967 NautilusBookmark
*bookmark
;
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) {
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
) {
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
) {
997 nautilus_bookmark_list_delete_item_at (sidebar
->bookmarks
, old_position
);
1001 drag_data_received_callback (GtkWidget
*widget
,
1002 GdkDragContext
*context
,
1005 GtkSelectionData
*selection_data
,
1008 NautilusPlacesSidebar
*sidebar
)
1010 GtkTreeView
*tree_view
;
1011 GtkTreePath
*tree_path
;
1012 GtkTreeViewDropPosition tree_pos
;
1014 int position
, bookmarks_index
;
1015 GtkTreeModel
*model
;
1017 GList
*selection_list
, *uris
;
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
);
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
) {
1038 /* Compute position */
1039 compute_drop_position (tree_view
, x
, y
, &tree_path
, &tree_pos
, sidebar
);
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
) {
1053 g_assert (position
>= bookmarks_index
);
1054 position
-= bookmarks_index
;
1058 bookmarks_drop_uris (sidebar
, selection_data
, position
);
1061 case GTK_TREE_MODEL_ROW
:
1062 reorder_bookmarks (sidebar
, position
);
1066 g_assert_not_reached ();
1070 /* file transfer requested */
1071 if (context
->action
== GDK_ACTION_ASK
) {
1073 nautilus_drag_drop_action_ask (GTK_WIDGET (tree_view
),
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
,
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
),
1092 nautilus_drag_destroy_selection_list (selection_list
);
1096 case GTK_TREE_MODEL_ROW
:
1100 g_assert_not_reached ();
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
);
1116 drag_drop_callback (GtkTreeView
*tree_view
,
1117 GdkDragContext
*context
,
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");
1129 /* Callback used when the file list's popup menu is detached */
1131 bookmarks_popup_menu_detach_cb (GtkWidget
*attach_widget
,
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
;
1152 check_visibility (GMount
*mount
,
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
);
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
);
1189 g_find_program_in_path ("gfloppy")) {
1190 *show_format
= TRUE
;
1196 bookmarks_check_popup_sensitivity (NautilusPlacesSidebar
*sidebar
)
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
;
1211 type
= PLACES_BUILT_IN
;
1213 if (sidebar
->popup_menu
== NULL
) {
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
,
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
);
1253 /* Callback used when the selection in the shortcuts tree changes */
1255 bookmarks_selection_changed_cb (GtkTreeSelection
*selection
,
1256 NautilusPlacesSidebar
*sidebar
)
1258 bookmarks_check_popup_sensitivity (sidebar
);
1262 open_selected_bookmark (NautilusPlacesSidebar
*sidebar
,
1263 GtkTreeModel
*model
,
1265 gboolean open_in_new_window
)
1275 if (!gtk_tree_model_get_iter (model
, &iter
, path
)) {
1279 gtk_tree_model_get (model
, &iter
, PLACES_SIDEBAR_COLUMN_URI
, &uri
, -1);
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
,
1292 NautilusWindow
*cur
, *new;
1294 cur
= NAUTILUS_WINDOW (sidebar
->window
);
1295 new = nautilus_application_create_navigation_window (cur
->application
,
1297 gtk_window_get_screen (GTK_WINDOW (cur
)));
1298 nautilus_window_go_to (new, location
);
1300 g_object_unref (location
);
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
);
1314 open_shortcut_from_menu (NautilusPlacesSidebar
*sidebar
,
1315 gboolean open_in_new_window
)
1317 GtkTreeModel
*model
;
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
);
1329 open_shortcut_cb (GtkMenuItem
*item
,
1330 NautilusPlacesSidebar
*sidebar
)
1332 open_shortcut_from_menu (sidebar
, FALSE
);
1336 open_shortcut_in_new_window_cb (GtkMenuItem
*item
,
1337 NautilusPlacesSidebar
*sidebar
)
1339 open_shortcut_from_menu (sidebar
, TRUE
);
1342 /* Rename the selected bookmark */
1344 rename_selected_bookmark (NautilusPlacesSidebar
*sidebar
)
1348 GtkTreeViewColumn
*column
;
1349 GtkCellRenderer
*cell
;
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
);
1366 rename_shortcut_cb (GtkMenuItem
*item
,
1367 NautilusPlacesSidebar
*sidebar
)
1369 rename_selected_bookmark (sidebar
);
1372 /* Removes the selected bookmarks */
1374 remove_selected_bookmarks (NautilusPlacesSidebar
*sidebar
)
1380 if (!get_selected_iter (sidebar
, &iter
)) {
1384 gtk_tree_model_get (GTK_TREE_MODEL (sidebar
->store
), &iter
,
1385 PLACES_SIDEBAR_COLUMN_ROW_TYPE
, &type
,
1388 if (type
!= PLACES_BOOKMARK
) {
1392 gtk_tree_model_get (GTK_TREE_MODEL (sidebar
->store
), &iter
,
1393 PLACES_SIDEBAR_COLUMN_INDEX
, &index
,
1396 nautilus_bookmark_list_delete_item_at (sidebar
->bookmarks
, index
);
1400 remove_shortcut_cb (GtkMenuItem
*item
,
1401 NautilusPlacesSidebar
*sidebar
)
1403 remove_selected_bookmarks (sidebar
);
1407 mount_shortcut_cb (GtkMenuItem
*item
,
1408 NautilusPlacesSidebar
*sidebar
)
1413 if (!get_selected_iter (sidebar
, &iter
)) {
1417 gtk_tree_model_get (GTK_TREE_MODEL (sidebar
->store
), &iter
,
1418 PLACES_SIDEBAR_COLUMN_VOLUME
, &volume
,
1421 if (volume
!= NULL
) {
1422 nautilus_file_operations_mount_volume (NULL
, volume
, FALSE
);
1423 g_object_unref (volume
);
1428 unmount_shortcut_cb (GtkMenuItem
*item
,
1429 NautilusPlacesSidebar
*sidebar
)
1435 if (!get_selected_iter (sidebar
, &iter
)) {
1439 gtk_tree_model_get (GTK_TREE_MODEL (sidebar
->store
), &iter
,
1440 PLACES_SIDEBAR_COLUMN_VOLUME
, &volume
,
1441 PLACES_SIDEBAR_COLUMN_MOUNT
, &mount
,
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
);
1460 drive_eject_cb (GObject
*source_object
,
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
);
1473 eel_show_error_dialog (primary
,
1478 g_error_free (error
);
1483 volume_eject_cb (GObject
*source_object
,
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
);
1496 eel_show_error_dialog (primary
,
1501 g_error_free (error
);
1506 mount_eject_cb (GObject
*source_object
,
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
);
1519 eel_show_error_dialog (primary
,
1524 g_error_free (error
);
1529 eject_shortcut_cb (GtkMenuItem
*item
,
1530 NautilusPlacesSidebar
*sidebar
)
1537 if (!get_selected_iter (sidebar
, &iter
)) {
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
,
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
);
1556 g_object_unref (mount
);
1558 g_object_unref (volume
);
1560 g_object_unref (drive
);
1564 drive_poll_for_media_cb (GObject
*source_object
,
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
);
1578 eel_show_error_dialog (primary
,
1583 g_error_free (error
);
1588 rescan_shortcut_cb (GtkMenuItem
*item
,
1589 NautilusPlacesSidebar
*sidebar
)
1594 if (!get_selected_iter (sidebar
, &iter
)) {
1598 gtk_tree_model_get (GTK_TREE_MODEL (sidebar
->store
), &iter
,
1599 PLACES_SIDEBAR_COLUMN_DRIVE
, &drive
,
1602 if (drive
!= NULL
) {
1603 g_drive_poll_for_media (drive
, NULL
, drive_poll_for_media_cb
, NULL
);
1605 g_object_unref (drive
);
1609 format_shortcut_cb (GtkMenuItem
*item
,
1610 NautilusPlacesSidebar
*sidebar
)
1612 g_spawn_command_line_async ("gfloppy", NULL
);
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 */
1624 bookmarks_key_press_event_cb (GtkWidget
*widget
,
1626 NautilusPlacesSidebar
*sidebar
)
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
);
1640 if ((event
->keyval
== GDK_F2
)
1641 && (event
->state
& modifiers
) == 0) {
1642 rename_selected_bookmark (sidebar
);
1649 /* Constructs the popup menu for the file list if needed */
1651 bookmarks_build_popup_menu (NautilusPlacesSidebar
*sidebar
)
1655 if (sidebar
->popup_menu
) {
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
);
1747 bookmarks_update_popup_menu (NautilusPlacesSidebar
*sidebar
)
1749 bookmarks_build_popup_menu (sidebar
);
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
,
1763 /* Callback used for the GtkWidget::popup-menu signal of the shortcuts list */
1765 bookmarks_popup_menu_cb (GtkWidget
*widget
,
1766 NautilusPlacesSidebar
*sidebar
)
1768 bookmarks_popup_menu (sidebar
, NULL
);
1772 /* Callback used when a button is pressed on the shortcuts list.
1773 * We trap button 3 to bring up a popup menu.
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
);
1788 bookmarks_edited (GtkCellRenderer
*cell
,
1791 NautilusPlacesSidebar
*sidebar
)
1795 NautilusBookmark
*bookmark
;
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
,
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
);
1815 bookmarks_editing_canceled (GtkCellRenderer
*cell
,
1816 NautilusPlacesSidebar
*sidebar
)
1818 g_object_set (cell
, "editable", FALSE
, NULL
);
1822 trash_state_changed_cb (NautilusTrashMonitor
*trash_monitor
,
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
);
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
),
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
);
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
,
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
,
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
,
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
,
1893 sidebar
->filter_model
= nautilus_shortcuts_model_filter_new (sidebar
,
1894 GTK_TREE_MODEL (sidebar
->store
),
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
),
1914 nautilus_shortcuts_source_targets
,
1915 G_N_ELEMENTS (nautilus_shortcuts_source_targets
),
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
,
1945 eel_preferences_add_callback_while_alive (NAUTILUS_PREFERENCES_DESKTOP_IS_HOME_DIR
,
1946 desktop_location_changed_callback
,
1948 G_OBJECT (sidebar
));
1950 g_signal_connect_object (nautilus_trash_monitor_get (),
1951 "trash_state_changed",
1952 G_CALLBACK (trash_state_changed_cb
),
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
);
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
;
1993 nautilus_places_sidebar_get_sidebar_id (NautilusSidebar
*sidebar
)
1995 return NAUTILUS_PLACES_SIDEBAR_ID
;
1999 nautilus_places_sidebar_get_tab_label (NautilusSidebar
*sidebar
)
2001 return g_strdup (_("Places"));
2005 nautilus_places_sidebar_get_tab_tooltip (NautilusSidebar
*sidebar
)
2007 return g_strdup (_("Show Places"));
2011 nautilus_places_sidebar_get_tab_icon (NautilusSidebar
*sidebar
)
2017 nautilus_places_sidebar_is_visible_changed (NautilusSidebar
*sidebar
,
2018 gboolean is_visible
)
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
;
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
),
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
);
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
);
2098 sidebar_provider_iface_init (NautilusSidebarProviderIface
*iface
)
2100 iface
->create
= nautilus_places_sidebar_create
;
2104 nautilus_places_sidebar_provider_init (NautilusPlacesSidebarProvider
*sidebar
)
2109 nautilus_places_sidebar_provider_class_init (NautilusPlacesSidebarProviderClass
*class)
2114 nautilus_places_sidebar_register (void)
2116 nautilus_module_add_type (nautilus_places_sidebar_provider_get_type ());
2119 /* Drag and drop interfaces */
2122 _nautilus_shortcuts_model_filter_class_init (NautilusShortcutsModelFilterClass
*class)
2127 _nautilus_shortcuts_model_filter_init (NautilusShortcutsModelFilter
*model
)
2129 model
->sidebar
= NULL
;
2132 /* GtkTreeDragSource::row_draggable implementation for the shortcuts filter model */
2134 nautilus_shortcuts_model_filter_row_draggable (GtkTreeDragSource
*drag_source
,
2137 NautilusShortcutsModelFilter
*model
;
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 */
2153 nautilus_shortcuts_model_filter_drag_data_get (GtkTreeDragSource
*drag_source
,
2155 GtkSelectionData
*selection_data
)
2157 NautilusShortcutsModelFilter
*model
;
2159 model
= NAUTILUS_SHORTCUTS_MODEL_FILTER (drag_source
);
2166 /* Fill the GtkTreeDragSourceIface vtable */
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
,
2179 NautilusShortcutsModelFilter
*model
;
2181 model
= g_object_new (NAUTILUS_SHORTCUTS_MODEL_FILTER_TYPE
,
2182 "child-model", child_model
,
2183 "virtual-root", root
,
2186 model
->sidebar
= sidebar
;
2188 return GTK_TREE_MODEL (model
);