~ubuntu-branches/ubuntu/utopic/nautilus/utopic-proposed

« back to all changes in this revision

Viewing changes to src/nautilus-places-sidebar.c

  • Committer: Package Import Robot
  • Author(s): Tim Lunn
  • Date: 2014-01-02 16:50:06 UTC
  • mto: This revision was merged to the branch mainline in revision 343.
  • Revision ID: package-import@ubuntu.com-20140102165006-ufn0so3frq4zox7l
Tags: upstream-3.10.1
ImportĀ upstreamĀ versionĀ 3.10.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
 
 
3
 
/*
4
 
 *  Nautilus
5
 
 *
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.
10
 
 *
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.
15
 
 *
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.
19
 
 *
20
 
 *  Authors : Mr Jamie McCracken (jamiemcc at blueyonder dot co dot uk)
21
 
 *            Cosimo Cecchi <cosimoc@gnome.org>
22
 
 *
23
 
 */
24
 
 
25
 
#include <config.h>
26
 
 
27
 
#include <gdk/gdkkeysyms.h>
28
 
#include <gdk/gdkx.h>
29
 
#include <gtk/gtk.h>
30
 
#include <glib/gi18n.h>
31
 
#include <gio/gio.h>
32
 
#include <gio/gdesktopappinfo.h>
33
 
 
34
 
#include <libnautilus-private/nautilus-dnd.h>
35
 
#include <libnautilus-private/nautilus-bookmark.h>
36
 
#include <libnautilus-private/nautilus-global-preferences.h>
37
 
#include <libnautilus-private/nautilus-file.h>
38
 
#include <libnautilus-private/nautilus-file-utilities.h>
39
 
#include <libnautilus-private/nautilus-file-operations.h>
40
 
#include <libnautilus-private/nautilus-trash-monitor.h>
41
 
#include <libnautilus-private/nautilus-icon-names.h>
42
 
 
43
 
#include <eel/eel-debug.h>
44
 
#include <eel/eel-gtk-extensions.h>
45
 
#include <eel/eel-glib-extensions.h>
46
 
#include <eel/eel-graphic-effects.h>
47
 
#include <eel/eel-string.h>
48
 
#include <eel/eel-stock-dialogs.h>
49
 
 
50
 
#include "nautilus-application.h"
51
 
#include "nautilus-bookmark-list.h"
52
 
#include "nautilus-places-sidebar.h"
53
 
#include "nautilus-properties-window.h"
54
 
#include "nautilus-window.h"
55
 
#include "nautilus-window-slot.h"
56
 
 
57
 
#define DEBUG_FLAG NAUTILUS_DEBUG_PLACES
58
 
#include <libnautilus-private/nautilus-debug.h>
59
 
 
60
 
#define EJECT_BUTTON_XPAD 6
61
 
#define ICON_CELL_XPAD 6
62
 
 
63
 
typedef struct {
64
 
        GtkScrolledWindow  parent;
65
 
        GtkTreeView        *tree_view;
66
 
        GtkCellRenderer    *eject_icon_cell_renderer;
67
 
        char               *uri;
68
 
        GtkListStore       *store;
69
 
        NautilusWindow *window;
70
 
        NautilusBookmarkList *bookmarks;
71
 
        GVolumeMonitor *volume_monitor;
72
 
 
73
 
        gboolean devices_header_added;
74
 
        gboolean bookmarks_header_added;
75
 
 
76
 
        /* DnD */
77
 
        GList     *drag_list;
78
 
        gboolean  drag_data_received;
79
 
        int       drag_data_info;
80
 
        gboolean  drop_occured;
81
 
        char     *target_uri;
82
 
 
83
 
        GtkWidget *popup_menu;
84
 
        GtkWidget *popup_menu_open_in_new_tab_item;
85
 
        GtkWidget *popup_menu_add_shortcut_item;
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_empty_trash_item;
94
 
        GtkWidget *popup_menu_start_item;
95
 
        GtkWidget *popup_menu_stop_item;
96
 
        GtkWidget *popup_menu_properties_separator_item;
97
 
        GtkWidget *popup_menu_properties_item;
98
 
        GtkWidget *popup_menu_format_item;
99
 
 
100
 
        /* volume mounting - delayed open process */
101
 
        gboolean mounting;
102
 
        NautilusWindowSlot *go_to_after_mount_slot;
103
 
        NautilusWindowOpenFlags go_to_after_mount_flags;
104
 
 
105
 
        GDBusProxy *hostnamed_proxy;
106
 
        GCancellable *hostnamed_cancellable;
107
 
        char *hostname;
108
 
 
109
 
        guint bookmarks_changed_id;
110
 
        guint switch_location_timer;
111
 
} NautilusPlacesSidebar;
112
 
 
113
 
typedef struct {
114
 
        GtkScrolledWindowClass parent;
115
 
} NautilusPlacesSidebarClass;
116
 
 
117
 
typedef struct {
118
 
        GObject parent;
119
 
} NautilusPlacesSidebarProvider;
120
 
 
121
 
typedef struct {
122
 
        GObjectClass parent;
123
 
} NautilusPlacesSidebarProviderClass;
124
 
 
125
 
enum {
126
 
        PLACES_SIDEBAR_COLUMN_ROW_TYPE,
127
 
        PLACES_SIDEBAR_COLUMN_URI,
128
 
        PLACES_SIDEBAR_COLUMN_DRIVE,
129
 
        PLACES_SIDEBAR_COLUMN_VOLUME,
130
 
        PLACES_SIDEBAR_COLUMN_MOUNT,
131
 
        PLACES_SIDEBAR_COLUMN_NAME,
132
 
        PLACES_SIDEBAR_COLUMN_GICON,
133
 
        PLACES_SIDEBAR_COLUMN_INDEX,
134
 
        PLACES_SIDEBAR_COLUMN_EJECT,
135
 
        PLACES_SIDEBAR_COLUMN_NO_EJECT,
136
 
        PLACES_SIDEBAR_COLUMN_BOOKMARK,
137
 
        PLACES_SIDEBAR_COLUMN_TOOLTIP,
138
 
        PLACES_SIDEBAR_COLUMN_SECTION_TYPE,
139
 
        PLACES_SIDEBAR_COLUMN_HEADING_TEXT,
140
 
 
141
 
        PLACES_SIDEBAR_COLUMN_COUNT
142
 
};
143
 
 
144
 
typedef enum {
145
 
        PLACES_BUILT_IN,
146
 
        PLACES_XDG_DIR,
147
 
        PLACES_MOUNTED_VOLUME,
148
 
        PLACES_BOOKMARK,
149
 
        PLACES_HEADING,
150
 
        PLACES_CONNECT_SERVER
151
 
} PlaceType;
152
 
 
153
 
typedef enum {
154
 
        SECTION_DEVICES,
155
 
        SECTION_BOOKMARKS,
156
 
        SECTION_COMPUTER,
157
 
        SECTION_NETWORK,
158
 
} SectionType;
159
 
 
160
 
static void  open_selected_bookmark                    (NautilusPlacesSidebar        *sidebar,
161
 
                                                        GtkTreeModel                 *model,
162
 
                                                        GtkTreeIter                  *iter,
163
 
                                                        NautilusWindowOpenFlags flags);
164
 
static void  nautilus_places_sidebar_style_set         (GtkWidget                    *widget,
165
 
                                                        GtkStyle                     *previous_style);
166
 
static gboolean eject_or_unmount_bookmark              (NautilusPlacesSidebar *sidebar,
167
 
                                                        GtkTreePath *path);
168
 
static gboolean eject_or_unmount_selection             (NautilusPlacesSidebar *sidebar);
169
 
static void  check_unmount_and_eject                   (GMount *mount,
170
 
                                                        GVolume *volume,
171
 
                                                        GDrive *drive,
172
 
                                                        gboolean *show_unmount,
173
 
                                                        gboolean *show_eject);
174
 
 
175
 
static void bookmarks_check_popup_sensitivity          (NautilusPlacesSidebar *sidebar);
176
 
 
177
 
/* Identifiers for target types */
178
 
enum {
179
 
        GTK_TREE_MODEL_ROW,
180
 
        TEXT_URI_LIST
181
 
};
182
 
 
183
 
/* Target types for dragging from the shortcuts list */
184
 
static const GtkTargetEntry nautilus_shortcuts_source_targets[] = {
185
 
        { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, GTK_TREE_MODEL_ROW }
186
 
};
187
 
 
188
 
/* Target types for dropping into the shortcuts list */
189
 
static const GtkTargetEntry nautilus_shortcuts_drop_targets [] = {
190
 
        { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, GTK_TREE_MODEL_ROW },
191
 
        { "text/uri-list", 0, TEXT_URI_LIST }
192
 
};
193
 
 
194
 
/* Drag and drop interface declarations */
195
 
typedef struct {
196
 
        GtkListStore parent;
197
 
 
198
 
        NautilusPlacesSidebar *sidebar;
199
 
} NautilusShortcutsModel;
200
 
 
201
 
typedef struct {
202
 
        GtkListStoreClass parent_class;
203
 
} NautilusShortcutsModelClass;
204
 
 
205
 
GType _nautilus_shortcuts_model_get_type (void);
206
 
static void _nautilus_shortcuts_model_drag_source_init (GtkTreeDragSourceIface *iface);
207
 
G_DEFINE_TYPE_WITH_CODE (NautilusShortcutsModel, _nautilus_shortcuts_model, GTK_TYPE_LIST_STORE,
208
 
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE,
209
 
                                                _nautilus_shortcuts_model_drag_source_init));
210
 
static GtkListStore *nautilus_shortcuts_model_new (NautilusPlacesSidebar *sidebar);
211
 
 
212
 
G_DEFINE_TYPE (NautilusPlacesSidebar, nautilus_places_sidebar, GTK_TYPE_SCROLLED_WINDOW);
213
 
 
214
 
static GtkTreeIter
215
 
add_heading (NautilusPlacesSidebar *sidebar,
216
 
             SectionType section_type,
217
 
             const gchar *title)
218
 
{
219
 
        GtkTreeIter iter;
220
 
 
221
 
        gtk_list_store_append (sidebar->store, &iter);
222
 
        gtk_list_store_set (sidebar->store, &iter,
223
 
                            PLACES_SIDEBAR_COLUMN_ROW_TYPE, PLACES_HEADING,
224
 
                            PLACES_SIDEBAR_COLUMN_SECTION_TYPE, section_type,   
225
 
                            PLACES_SIDEBAR_COLUMN_HEADING_TEXT, title,
226
 
                            PLACES_SIDEBAR_COLUMN_EJECT, FALSE,
227
 
                            PLACES_SIDEBAR_COLUMN_NO_EJECT, TRUE,
228
 
                            -1);
229
 
 
230
 
        return iter;
231
 
}
232
 
 
233
 
static void
234
 
check_heading_for_section (NautilusPlacesSidebar *sidebar,
235
 
                           SectionType section_type)
236
 
{
237
 
        switch (section_type) {
238
 
        case SECTION_DEVICES:
239
 
                if (!sidebar->devices_header_added) {
240
 
                        add_heading (sidebar, SECTION_DEVICES,
241
 
                                     _("Devices"));
242
 
                        sidebar->devices_header_added = TRUE;
243
 
                }
244
 
 
245
 
                break;
246
 
        case SECTION_BOOKMARKS:
247
 
                if (!sidebar->bookmarks_header_added) {
248
 
                        add_heading (sidebar, SECTION_BOOKMARKS,
249
 
                                     _("Bookmarks"));
250
 
                        sidebar->bookmarks_header_added = TRUE;
251
 
                }
252
 
 
253
 
                break;
254
 
        default:
255
 
                break;
256
 
        }
257
 
}
258
 
 
259
 
static void
260
 
add_place (NautilusPlacesSidebar *sidebar,
261
 
           PlaceType place_type,
262
 
           SectionType section_type,
263
 
           const char *name,
264
 
           GIcon *icon,
265
 
           const char *uri,
266
 
           GDrive *drive,
267
 
           GVolume *volume,
268
 
           GMount *mount,
269
 
           const int index,
270
 
           const char *tooltip)
271
 
{
272
 
        GtkTreeIter           iter;
273
 
        gboolean show_eject, show_unmount;
274
 
        gboolean show_eject_button;
275
 
 
276
 
        check_heading_for_section (sidebar, section_type);
277
 
 
278
 
        check_unmount_and_eject (mount, volume, drive,
279
 
                                 &show_unmount, &show_eject);
280
 
 
281
 
        if (show_unmount || show_eject) {
282
 
                g_assert (place_type != PLACES_BOOKMARK);
283
 
        }
284
 
 
285
 
        if (mount == NULL) {
286
 
                show_eject_button = FALSE;
287
 
        } else {
288
 
                show_eject_button = (show_unmount || show_eject);
289
 
        }
290
 
 
291
 
        gtk_list_store_append (sidebar->store, &iter);
292
 
        gtk_list_store_set (sidebar->store, &iter,
293
 
                            PLACES_SIDEBAR_COLUMN_GICON, icon,
294
 
                            PLACES_SIDEBAR_COLUMN_NAME, name,
295
 
                            PLACES_SIDEBAR_COLUMN_URI, uri,
296
 
                            PLACES_SIDEBAR_COLUMN_DRIVE, drive,
297
 
                            PLACES_SIDEBAR_COLUMN_VOLUME, volume,
298
 
                            PLACES_SIDEBAR_COLUMN_MOUNT, mount,
299
 
                            PLACES_SIDEBAR_COLUMN_ROW_TYPE, place_type,
300
 
                            PLACES_SIDEBAR_COLUMN_INDEX, index,
301
 
                            PLACES_SIDEBAR_COLUMN_EJECT, show_eject_button,
302
 
                            PLACES_SIDEBAR_COLUMN_NO_EJECT, !show_eject_button,
303
 
                            PLACES_SIDEBAR_COLUMN_BOOKMARK, place_type != PLACES_BOOKMARK,
304
 
                            PLACES_SIDEBAR_COLUMN_TOOLTIP, tooltip,
305
 
                            PLACES_SIDEBAR_COLUMN_SECTION_TYPE, section_type,
306
 
                            -1);
307
 
}
308
 
 
309
 
typedef struct {
310
 
        const gchar *location;
311
 
        const gchar *last_uri;
312
 
        NautilusPlacesSidebar *sidebar;
313
 
        GtkTreePath *path;
314
 
} RestoreLocationData;
315
 
 
316
 
static gboolean
317
 
restore_selection_foreach (GtkTreeModel *model,
318
 
                           GtkTreePath *path,
319
 
                           GtkTreeIter *iter,
320
 
                           gpointer user_data)
321
 
{
322
 
        RestoreLocationData *data = user_data;
323
 
        gchar *uri;
324
 
 
325
 
        gtk_tree_model_get (model, iter,
326
 
                            PLACES_SIDEBAR_COLUMN_URI, &uri,
327
 
                            -1);
328
 
 
329
 
        if (g_strcmp0 (uri, data->last_uri) == 0 ||
330
 
            g_strcmp0 (uri, data->location) == 0) {
331
 
                data->path = gtk_tree_path_copy (path);
332
 
        }
333
 
 
334
 
        g_free (uri);
335
 
 
336
 
        return (data->path != NULL);
337
 
}
338
 
 
339
 
static void
340
 
sidebar_update_restore_selection (NautilusPlacesSidebar *sidebar,
341
 
                                  const gchar *location,
342
 
                                  const gchar *last_uri)
343
 
{
344
 
        RestoreLocationData data;
345
 
        GtkTreeSelection *selection;
346
 
 
347
 
        data.location = location;
348
 
        data.last_uri = last_uri;
349
 
        data.sidebar = sidebar;
350
 
        data.path = NULL;
351
 
 
352
 
        gtk_tree_model_foreach (GTK_TREE_MODEL (sidebar->store),
353
 
                                restore_selection_foreach, &data);
354
 
 
355
 
        if (data.path != NULL) {
356
 
                selection = gtk_tree_view_get_selection (sidebar->tree_view);
357
 
                gtk_tree_selection_select_path (selection, data.path);
358
 
                gtk_tree_path_free (data.path);
359
 
        }
360
 
}
361
 
 
362
 
static gboolean
363
 
recent_is_supported (void)
364
 
{
365
 
        const char * const *supported;
366
 
        gboolean enabled;
367
 
        int i;
368
 
 
369
 
        enabled = g_settings_get_boolean (gnome_privacy_preferences,
370
 
                                          NAUTILUS_PREFERENCES_RECENT_FILES_ENABLED);
371
 
 
372
 
        if (!enabled) {
373
 
                return FALSE;
374
 
        }
375
 
 
376
 
        supported = g_vfs_get_supported_uri_schemes (g_vfs_get_default ());
377
 
        if (!supported) {
378
 
                return FALSE;
379
 
        }
380
 
 
381
 
        for (i = 0; supported[i] != NULL; i++) {
382
 
                if (strcmp ("recent", supported[i]) == 0) {
383
 
                        return TRUE;
384
 
                }
385
 
        }
386
 
        return FALSE;
387
 
}
388
 
 
389
 
static void
390
 
add_special_dirs (NautilusPlacesSidebar *sidebar)
391
 
{
392
 
        GList *dirs;
393
 
        int index;
394
 
 
395
 
        dirs = NULL;
396
 
        for (index = 0; index < G_USER_N_DIRECTORIES; index++) {
397
 
                const char *path;
398
 
                char *name;
399
 
                GFile *root;
400
 
                GIcon *icon;
401
 
                char *mount_uri;
402
 
                NautilusBookmark *bookmark;
403
 
                guint idx;
404
 
 
405
 
                if (index == G_USER_DIRECTORY_DESKTOP ||
406
 
                    index == G_USER_DIRECTORY_TEMPLATES ||
407
 
                    index == G_USER_DIRECTORY_PUBLIC_SHARE) {
408
 
                        continue;
409
 
                }
410
 
 
411
 
                path = g_get_user_special_dir (index);
412
 
 
413
 
                /* xdg resets special dirs to the home directory in case
414
 
                 * it's not finiding what it expects. We don't want the home
415
 
                 * to be added multiple times in that weird configuration.
416
 
                 */
417
 
                if (path == NULL
418
 
                    || g_strcmp0 (path, g_get_home_dir ()) == 0
419
 
                    || g_list_find_custom (dirs, path, (GCompareFunc) g_strcmp0) != NULL) {
420
 
                        continue;
421
 
                }
422
 
 
423
 
                root = g_file_new_for_path (path);
424
 
 
425
 
                /* Don't add the bookmark to the sidebar if it was removed from
426
 
                 * the user dir list, or if its location doesn't exist.
427
 
                 */
428
 
                bookmark = nautilus_bookmark_list_item_with_location (sidebar->bookmarks, root, &idx);
429
 
                if (bookmark && !nautilus_bookmark_get_exists (bookmark)) {
430
 
                        g_object_unref (root);
431
 
                        continue;
432
 
                }
433
 
 
434
 
                if (bookmark) {
435
 
                        name = g_strdup (nautilus_bookmark_get_name (bookmark));
436
 
                        icon = nautilus_bookmark_get_symbolic_icon (bookmark);
437
 
                } else {
438
 
                        name = g_file_get_basename (root);
439
 
                        icon = nautilus_special_directory_get_symbolic_icon (index);
440
 
                        idx = -1;
441
 
                }
442
 
 
443
 
                mount_uri = g_file_get_uri (root);
444
 
 
445
 
                add_place (sidebar, PLACES_XDG_DIR,
446
 
                           SECTION_COMPUTER,
447
 
                           name, icon, mount_uri,
448
 
                           NULL, NULL, NULL, idx,
449
 
                           name);
450
 
 
451
 
                g_object_unref (root);
452
 
                g_object_unref (icon);
453
 
                g_free (name);
454
 
                g_free (mount_uri);
455
 
 
456
 
                dirs = g_list_prepend (dirs, (char *)path);
457
 
        }
458
 
 
459
 
        g_list_free (dirs);
460
 
}
461
 
 
462
 
static void
463
 
update_places (NautilusPlacesSidebar *sidebar)
464
 
{
465
 
        NautilusBookmark *bookmark;
466
 
        GtkTreeSelection *selection;
467
 
        GtkTreeIter last_iter;
468
 
        GtkTreeModel *model;
469
 
        GVolumeMonitor *volume_monitor;
470
 
        GList *mounts, *l, *ll;
471
 
        GMount *mount;
472
 
        GList *drives;
473
 
        GDrive *drive;
474
 
        GList *volumes;
475
 
        GVolume *volume;
476
 
        int bookmark_count, index;
477
 
        char *location, *mount_uri, *name, *last_uri, *identifier;
478
 
        const gchar *bookmark_name;
479
 
        GIcon *icon;
480
 
        GFile *root;
481
 
        NautilusWindowSlot *slot;
482
 
        char *tooltip;
483
 
        GList *network_mounts, *network_volumes;
484
 
 
485
 
        DEBUG ("Updating places sidebar");
486
 
 
487
 
        model = NULL;
488
 
        last_uri = NULL;
489
 
 
490
 
        selection = gtk_tree_view_get_selection (sidebar->tree_view);
491
 
        if (gtk_tree_selection_get_selected (selection, &model, &last_iter)) {
492
 
                gtk_tree_model_get (model,
493
 
                                    &last_iter,
494
 
                                    PLACES_SIDEBAR_COLUMN_URI, &last_uri, -1);
495
 
        }
496
 
        gtk_list_store_clear (sidebar->store);
497
 
 
498
 
        sidebar->devices_header_added = FALSE;
499
 
        sidebar->bookmarks_header_added = FALSE;
500
 
 
501
 
        slot = nautilus_window_get_active_slot (sidebar->window);
502
 
        location = nautilus_window_slot_get_current_uri (slot);
503
 
 
504
 
        network_mounts = network_volumes = NULL;
505
 
        volume_monitor = sidebar->volume_monitor;
506
 
 
507
 
        /* add built in bookmarks */
508
 
 
509
 
        add_heading (sidebar, SECTION_COMPUTER,
510
 
                     _("Places"));
511
 
 
512
 
        if (recent_is_supported ()) {
513
 
                mount_uri = "recent:///"; /* No need to strdup */
514
 
                icon = g_themed_icon_new ("document-open-recent-symbolic");
515
 
                add_place (sidebar, PLACES_BUILT_IN,
516
 
                           SECTION_COMPUTER,
517
 
                           _("Recent"), icon, mount_uri,
518
 
                           NULL, NULL, NULL, 0,
519
 
                           _("Recent files"));
520
 
                g_object_unref (icon);
521
 
        }
522
 
 
523
 
        /* home folder */
524
 
        mount_uri = nautilus_get_home_directory_uri ();
525
 
        icon = g_themed_icon_new (NAUTILUS_ICON_HOME);
526
 
        add_place (sidebar, PLACES_BUILT_IN,
527
 
                   SECTION_COMPUTER,
528
 
                   _("Home"), icon, mount_uri,
529
 
                   NULL, NULL, NULL, 0,
530
 
                   _("Open your personal folder"));
531
 
        g_object_unref (icon);
532
 
        g_free (mount_uri);
533
 
 
534
 
        if (g_settings_get_boolean (gnome_background_preferences, NAUTILUS_PREFERENCES_SHOW_DESKTOP)) {
535
 
                /* desktop */
536
 
                mount_uri = nautilus_get_desktop_directory_uri ();
537
 
                icon = g_themed_icon_new (NAUTILUS_ICON_FOLDER);
538
 
                add_place (sidebar, PLACES_BUILT_IN,
539
 
                           SECTION_COMPUTER,
540
 
                           _("Desktop"), icon, mount_uri,
541
 
                           NULL, NULL, NULL, 0,
542
 
                           _("Open the contents of your desktop in a folder"));
543
 
                g_object_unref (icon);
544
 
                g_free (mount_uri);
545
 
        }
546
 
 
547
 
        /* XDG directories */
548
 
        add_special_dirs (sidebar);
549
 
 
550
 
        mount_uri = "trash:///"; /* No need to strdup */
551
 
        icon = nautilus_trash_monitor_get_icon ();
552
 
        add_place (sidebar, PLACES_BUILT_IN,
553
 
                   SECTION_COMPUTER,
554
 
                   _("Trash"), icon, mount_uri,
555
 
                   NULL, NULL, NULL, 0,
556
 
                   _("Open the trash"));
557
 
        g_object_unref (icon);
558
 
 
559
 
        /* go through all connected drives */
560
 
        drives = g_volume_monitor_get_connected_drives (volume_monitor);
561
 
 
562
 
        for (l = drives; l != NULL; l = l->next) {
563
 
                drive = l->data;
564
 
 
565
 
                volumes = g_drive_get_volumes (drive);
566
 
                if (volumes != NULL) {
567
 
                        for (ll = volumes; ll != NULL; ll = ll->next) {
568
 
                                volume = ll->data;
569
 
                                identifier = g_volume_get_identifier (volume, G_VOLUME_IDENTIFIER_KIND_CLASS);
570
 
 
571
 
                                if (g_strcmp0 (identifier, "network") == 0) {
572
 
                                        g_free (identifier);
573
 
                                        network_volumes = g_list_prepend (network_volumes, volume);
574
 
                                        continue;
575
 
                                }
576
 
                                g_free (identifier);
577
 
 
578
 
                                mount = g_volume_get_mount (volume);
579
 
                                if (mount != NULL) {
580
 
                                        /* Show mounted volume in the sidebar */
581
 
                                        icon = g_mount_get_symbolic_icon (mount);
582
 
                                        root = g_mount_get_default_location (mount);
583
 
                                        mount_uri = g_file_get_uri (root);
584
 
                                        name = g_mount_get_name (mount);
585
 
                                        tooltip = g_file_get_parse_name (root);
586
 
 
587
 
                                        add_place (sidebar, PLACES_MOUNTED_VOLUME,
588
 
                                                   SECTION_DEVICES,
589
 
                                                   name, icon, mount_uri,
590
 
                                                   drive, volume, mount, 0, tooltip);
591
 
                                        g_object_unref (root);
592
 
                                        g_object_unref (mount);
593
 
                                        g_object_unref (icon);
594
 
                                        g_free (tooltip);
595
 
                                        g_free (name);
596
 
                                        g_free (mount_uri);
597
 
                                } else {
598
 
                                        /* Do show the unmounted volumes in the sidebar;
599
 
                                         * this is so the user can mount it (in case automounting
600
 
                                         * is off).
601
 
                                         *
602
 
                                         * Also, even if automounting is enabled, this gives a visual
603
 
                                         * cue that the user should remember to yank out the media if
604
 
                                         * he just unmounted it.
605
 
                                         */
606
 
                                        icon = g_volume_get_symbolic_icon (volume);
607
 
                                        name = g_volume_get_name (volume);
608
 
                                        tooltip = g_strdup_printf (_("Mount and open %s"), name);
609
 
 
610
 
                                        add_place (sidebar, PLACES_MOUNTED_VOLUME,
611
 
                                                   SECTION_DEVICES,
612
 
                                                   name, icon, NULL,
613
 
                                                   drive, volume, NULL, 0, tooltip);
614
 
                                        g_object_unref (icon);
615
 
                                        g_free (name);
616
 
                                        g_free (tooltip);
617
 
                                }
618
 
                                g_object_unref (volume);
619
 
                        }
620
 
                        g_list_free (volumes);
621
 
                } else {
622
 
                        if (g_drive_is_media_removable (drive) && !g_drive_is_media_check_automatic (drive)) {
623
 
                                /* If the drive has no mountable volumes and we cannot detect media change.. we
624
 
                                 * display the drive in the sidebar so the user can manually poll the drive by
625
 
                                 * right clicking and selecting "Rescan..."
626
 
                                 *
627
 
                                 * This is mainly for drives like floppies where media detection doesn't
628
 
                                 * work.. but it's also for human beings who like to turn off media detection
629
 
                                 * in the OS to save battery juice.
630
 
                                 */
631
 
                                icon = g_drive_get_symbolic_icon (drive);
632
 
                                name = g_drive_get_name (drive);
633
 
                                tooltip = g_strdup_printf (_("Mount and open %s"), name);
634
 
 
635
 
                                add_place (sidebar, PLACES_BUILT_IN,
636
 
                                           SECTION_DEVICES,
637
 
                                           name, icon, NULL,
638
 
                                           drive, NULL, NULL, 0, tooltip);
639
 
                                g_object_unref (icon);
640
 
                                g_free (tooltip);
641
 
                                g_free (name);
642
 
                        }
643
 
                }
644
 
                g_object_unref (drive);
645
 
        }
646
 
        g_list_free (drives);
647
 
 
648
 
        /* add all volumes that is not associated with a drive */
649
 
        volumes = g_volume_monitor_get_volumes (volume_monitor);
650
 
        for (l = volumes; l != NULL; l = l->next) {
651
 
                volume = l->data;
652
 
                drive = g_volume_get_drive (volume);
653
 
                if (drive != NULL) {
654
 
                        g_object_unref (volume);
655
 
                        g_object_unref (drive);
656
 
                        continue;
657
 
                }
658
 
 
659
 
                identifier = g_volume_get_identifier (volume, G_VOLUME_IDENTIFIER_KIND_CLASS);
660
 
 
661
 
                if (g_strcmp0 (identifier, "network") == 0) {
662
 
                        g_free (identifier);
663
 
                        network_volumes = g_list_prepend (network_volumes, volume);
664
 
                        continue;
665
 
                }
666
 
                g_free (identifier);
667
 
 
668
 
                mount = g_volume_get_mount (volume);
669
 
                if (mount != NULL) {
670
 
                        icon = g_mount_get_symbolic_icon (mount);
671
 
                        root = g_mount_get_default_location (mount);
672
 
                        mount_uri = g_file_get_uri (root);
673
 
                        tooltip = g_file_get_parse_name (root);
674
 
                        g_object_unref (root);
675
 
                        name = g_mount_get_name (mount);
676
 
                        add_place (sidebar, PLACES_MOUNTED_VOLUME,
677
 
                                   SECTION_DEVICES,
678
 
                                   name, icon, mount_uri,
679
 
                                   NULL, volume, mount, 0, tooltip);
680
 
                        g_object_unref (mount);
681
 
                        g_object_unref (icon);
682
 
                        g_free (name);
683
 
                        g_free (tooltip);
684
 
                        g_free (mount_uri);
685
 
                } else {
686
 
                        /* see comment above in why we add an icon for an unmounted mountable volume */
687
 
                        icon = g_volume_get_symbolic_icon (volume);
688
 
                        name = g_volume_get_name (volume);
689
 
                        add_place (sidebar, PLACES_MOUNTED_VOLUME,
690
 
                                   SECTION_DEVICES,
691
 
                                   name, icon, NULL,
692
 
                                   NULL, volume, NULL, 0, name);
693
 
                        g_object_unref (icon);
694
 
                        g_free (name);
695
 
                }
696
 
                g_object_unref (volume);
697
 
        }
698
 
        g_list_free (volumes);
699
 
 
700
 
        /* file system root */
701
 
 
702
 
        mount_uri = "file:///"; /* No need to strdup */
703
 
        icon = g_themed_icon_new (NAUTILUS_ICON_FILESYSTEM);
704
 
        add_place (sidebar, PLACES_BUILT_IN,
705
 
                   SECTION_DEVICES,
706
 
                   sidebar->hostname, icon, mount_uri,
707
 
                   NULL, NULL, NULL, 0,
708
 
                   _("Open the contents of the File System"));
709
 
        g_object_unref (icon);
710
 
 
711
 
        /* add mounts that has no volume (/etc/mtab mounts, ftp, sftp,...) */
712
 
        mounts = g_volume_monitor_get_mounts (volume_monitor);
713
 
 
714
 
        for (l = mounts; l != NULL; l = l->next) {
715
 
                mount = l->data;
716
 
                if (g_mount_is_shadowed (mount)) {
717
 
                        g_object_unref (mount);
718
 
                        continue;
719
 
                }
720
 
                volume = g_mount_get_volume (mount);
721
 
                if (volume != NULL) {
722
 
                        g_object_unref (volume);
723
 
                        g_object_unref (mount);
724
 
                        continue;
725
 
                }
726
 
                root = g_mount_get_default_location (mount);
727
 
 
728
 
                if (!g_file_is_native (root)) {
729
 
                        network_mounts = g_list_prepend (network_mounts, mount);
730
 
                        g_object_unref (root);
731
 
                        continue;
732
 
                }
733
 
 
734
 
                icon = g_mount_get_symbolic_icon (mount);
735
 
                mount_uri = g_file_get_uri (root);
736
 
                name = g_mount_get_name (mount);
737
 
                tooltip = g_file_get_parse_name (root);
738
 
                add_place (sidebar, PLACES_MOUNTED_VOLUME,
739
 
                           SECTION_COMPUTER,
740
 
                           name, icon, mount_uri,
741
 
                           NULL, NULL, mount, 0, tooltip);
742
 
                g_object_unref (root);
743
 
                g_object_unref (mount);
744
 
                g_object_unref (icon);
745
 
                g_free (name);
746
 
                g_free (mount_uri);
747
 
                g_free (tooltip);
748
 
        }
749
 
        g_list_free (mounts);
750
 
 
751
 
        /* add bookmarks */
752
 
        bookmark_count = nautilus_bookmark_list_length (sidebar->bookmarks);
753
 
 
754
 
        for (index = 0; index < bookmark_count; ++index) {
755
 
                bookmark = nautilus_bookmark_list_item_at (sidebar->bookmarks, index);
756
 
                root = nautilus_bookmark_get_location (bookmark);
757
 
 
758
 
                if (!nautilus_bookmark_get_exists (bookmark) && g_file_is_native (root)) {
759
 
                        g_object_unref (root);
760
 
                        continue;
761
 
                }
762
 
 
763
 
                if (nautilus_bookmark_get_is_builtin (bookmark)) {
764
 
                        g_object_unref (root);
765
 
                        continue;
766
 
                }
767
 
 
768
 
                bookmark_name = nautilus_bookmark_get_name (bookmark);
769
 
                icon = nautilus_bookmark_get_symbolic_icon (bookmark);
770
 
                mount_uri = nautilus_bookmark_get_uri (bookmark);
771
 
                tooltip = g_file_get_parse_name (root);
772
 
 
773
 
                add_place (sidebar, PLACES_BOOKMARK,
774
 
                           SECTION_BOOKMARKS,
775
 
                           bookmark_name, icon, mount_uri,
776
 
                           NULL, NULL, NULL, index,
777
 
                           tooltip);
778
 
                g_object_unref (root);
779
 
                g_object_unref (icon);
780
 
                g_free (mount_uri);
781
 
                g_free (tooltip);
782
 
        }
783
 
 
784
 
        /* network */
785
 
        add_heading (sidebar, SECTION_NETWORK,
786
 
                     _("Network"));
787
 
 
788
 
        mount_uri = "network:///"; /* No need to strdup */
789
 
        icon = g_themed_icon_new (NAUTILUS_ICON_NETWORK);
790
 
        add_place (sidebar, PLACES_BUILT_IN,
791
 
                   SECTION_NETWORK,
792
 
                   _("Browse Network"), icon, mount_uri,
793
 
                   NULL, NULL, NULL, 0,
794
 
                   _("Browse the contents of the network"));
795
 
        g_object_unref (icon);
796
 
 
797
 
        icon = g_themed_icon_new (NAUTILUS_ICON_NETWORK_SERVER);
798
 
        add_place (sidebar, PLACES_CONNECT_SERVER,
799
 
                   SECTION_NETWORK,
800
 
                   _("Connect to Server"), icon, NULL,
801
 
                   NULL, NULL, NULL, 0,
802
 
                   _("Connect to a network server address"));
803
 
        g_object_unref (icon);
804
 
 
805
 
        network_volumes = g_list_reverse (network_volumes);
806
 
        for (l = network_volumes; l != NULL; l = l->next) {
807
 
                volume = l->data;
808
 
                mount = g_volume_get_mount (volume);
809
 
 
810
 
                if (mount != NULL) {
811
 
                        network_mounts = g_list_prepend (network_mounts, mount);
812
 
                        continue;
813
 
                } else {
814
 
                        icon = g_volume_get_symbolic_icon (volume);
815
 
                        name = g_volume_get_name (volume);
816
 
                        tooltip = g_strdup_printf (_("Mount and open %s"), name);
817
 
 
818
 
                        add_place (sidebar, PLACES_MOUNTED_VOLUME,
819
 
                                   SECTION_NETWORK,
820
 
                                   name, icon, NULL,
821
 
                                   NULL, volume, NULL, 0, tooltip);
822
 
                        g_object_unref (icon);
823
 
                        g_free (name);
824
 
                        g_free (tooltip);
825
 
                }
826
 
        }
827
 
 
828
 
        g_list_free_full (network_volumes, g_object_unref);
829
 
 
830
 
        network_mounts = g_list_reverse (network_mounts);
831
 
        for (l = network_mounts; l != NULL; l = l->next) {
832
 
                mount = l->data;
833
 
                root = g_mount_get_default_location (mount);
834
 
                icon = g_mount_get_symbolic_icon (mount);
835
 
                mount_uri = g_file_get_uri (root);
836
 
                name = g_mount_get_name (mount);
837
 
                tooltip = g_file_get_parse_name (root);
838
 
                add_place (sidebar, PLACES_MOUNTED_VOLUME,
839
 
                           SECTION_NETWORK,
840
 
                           name, icon, mount_uri,
841
 
                           NULL, NULL, mount, 0, tooltip);
842
 
                g_object_unref (root);
843
 
                g_object_unref (icon);
844
 
                g_free (name);
845
 
                g_free (mount_uri);
846
 
                g_free (tooltip);
847
 
        }
848
 
 
849
 
        g_list_free_full (network_mounts, g_object_unref);
850
 
 
851
 
        /* restore selection */
852
 
        sidebar_update_restore_selection (sidebar, location, last_uri);
853
 
 
854
 
        g_free (location);
855
 
        g_free (last_uri);
856
 
}
857
 
 
858
 
static void
859
 
mount_added_callback (GVolumeMonitor *volume_monitor,
860
 
                      GMount *mount,
861
 
                      NautilusPlacesSidebar *sidebar)
862
 
{
863
 
        update_places (sidebar);
864
 
}
865
 
 
866
 
static void
867
 
mount_removed_callback (GVolumeMonitor *volume_monitor,
868
 
                        GMount *mount,
869
 
                        NautilusPlacesSidebar *sidebar)
870
 
{
871
 
        update_places (sidebar);
872
 
}
873
 
 
874
 
static void
875
 
mount_changed_callback (GVolumeMonitor *volume_monitor,
876
 
                        GMount *mount,
877
 
                        NautilusPlacesSidebar *sidebar)
878
 
{
879
 
        update_places (sidebar);
880
 
}
881
 
 
882
 
static void
883
 
volume_added_callback (GVolumeMonitor *volume_monitor,
884
 
                       GVolume *volume,
885
 
                       NautilusPlacesSidebar *sidebar)
886
 
{
887
 
        update_places (sidebar);
888
 
}
889
 
 
890
 
static void
891
 
volume_removed_callback (GVolumeMonitor *volume_monitor,
892
 
                         GVolume *volume,
893
 
                         NautilusPlacesSidebar *sidebar)
894
 
{
895
 
        update_places (sidebar);
896
 
}
897
 
 
898
 
static void
899
 
volume_changed_callback (GVolumeMonitor *volume_monitor,
900
 
                         GVolume *volume,
901
 
                         NautilusPlacesSidebar *sidebar)
902
 
{
903
 
        update_places (sidebar);
904
 
}
905
 
 
906
 
static void
907
 
drive_disconnected_callback (GVolumeMonitor *volume_monitor,
908
 
                             GDrive         *drive,
909
 
                             NautilusPlacesSidebar *sidebar)
910
 
{
911
 
        update_places (sidebar);
912
 
}
913
 
 
914
 
static void
915
 
drive_connected_callback (GVolumeMonitor *volume_monitor,
916
 
                          GDrive         *drive,
917
 
                          NautilusPlacesSidebar *sidebar)
918
 
{
919
 
        update_places (sidebar);
920
 
}
921
 
 
922
 
static void
923
 
drive_changed_callback (GVolumeMonitor *volume_monitor,
924
 
                        GDrive         *drive,
925
 
                        NautilusPlacesSidebar *sidebar)
926
 
{
927
 
        update_places (sidebar);
928
 
}
929
 
 
930
 
static gboolean
931
 
over_eject_button (NautilusPlacesSidebar *sidebar,
932
 
                   gint x,
933
 
                   gint y,
934
 
                   GtkTreePath **path)
935
 
{
936
 
        GtkTreeViewColumn *column;
937
 
        int width, x_offset, hseparator;
938
 
        int eject_button_size;
939
 
        gboolean show_eject;
940
 
        GtkTreeIter iter;
941
 
        GtkTreeModel *model;
942
 
 
943
 
        *path = NULL;
944
 
        model = gtk_tree_view_get_model (sidebar->tree_view);
945
 
 
946
 
        if (gtk_tree_view_get_path_at_pos (sidebar->tree_view,
947
 
                                           x, y,
948
 
                                           path, &column, NULL, NULL)) {
949
 
 
950
 
                gtk_tree_model_get_iter (model, &iter, *path);
951
 
                gtk_tree_model_get (model, &iter,
952
 
                                    PLACES_SIDEBAR_COLUMN_EJECT, &show_eject,
953
 
                                    -1);
954
 
 
955
 
                if (!show_eject) {
956
 
                        goto out;
957
 
                }
958
 
 
959
 
 
960
 
                gtk_widget_style_get (GTK_WIDGET (sidebar->tree_view),
961
 
                                      "horizontal-separator", &hseparator,
962
 
                                      NULL);
963
 
 
964
 
                /* Reload cell attributes for this particular row */
965
 
                gtk_tree_view_column_cell_set_cell_data (column,
966
 
                                                         model, &iter, FALSE, FALSE);
967
 
 
968
 
                gtk_tree_view_column_cell_get_position (column,
969
 
                                                        sidebar->eject_icon_cell_renderer,
970
 
                                                        &x_offset, &width);
971
 
 
972
 
                eject_button_size = nautilus_get_icon_size_for_stock_size (GTK_ICON_SIZE_MENU);
973
 
 
974
 
                /* This is kinda weird, but we have to do it to workaround gtk+ expanding
975
 
                 * the eject cell renderer (even thought we told it not to) and we then
976
 
                 * had to set it right-aligned */
977
 
                x_offset += width - hseparator - EJECT_BUTTON_XPAD - eject_button_size;
978
 
 
979
 
                if (x - x_offset >= 0 &&
980
 
                    x - x_offset <= eject_button_size) {
981
 
                        return TRUE;
982
 
                }
983
 
        }
984
 
 
985
 
 out:
986
 
        if (*path != NULL) {
987
 
                gtk_tree_path_free (*path);
988
 
                *path = NULL;
989
 
        }
990
 
 
991
 
        return FALSE;
992
 
}
993
 
 
994
 
static gboolean
995
 
clicked_eject_button (NautilusPlacesSidebar *sidebar,
996
 
                      GtkTreePath **path)
997
 
{
998
 
        GdkEvent *event = gtk_get_current_event ();
999
 
        GdkEventButton *button_event = (GdkEventButton *) event;
1000
 
 
1001
 
        if ((event->type == GDK_BUTTON_PRESS || event->type == GDK_BUTTON_RELEASE) &&
1002
 
             over_eject_button (sidebar, button_event->x, button_event->y, path)) {
1003
 
                return TRUE;
1004
 
        }
1005
 
 
1006
 
        return FALSE;
1007
 
}
1008
 
 
1009
 
static void
1010
 
update_current_uri (NautilusPlacesSidebar *sidebar)
1011
 
{
1012
 
        GtkTreeSelection *selection;
1013
 
        GtkTreeIter      iter;
1014
 
        gboolean         valid;
1015
 
        char             *uri;
1016
 
 
1017
 
        if (sidebar->uri == NULL) {
1018
 
                return;
1019
 
        }
1020
 
 
1021
 
        /* set selection if any place matches location */
1022
 
        selection = gtk_tree_view_get_selection (sidebar->tree_view);
1023
 
        gtk_tree_selection_unselect_all (selection);
1024
 
        valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (sidebar->store),
1025
 
                                               &iter);
1026
 
 
1027
 
        while (valid) {
1028
 
                gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
1029
 
                                    PLACES_SIDEBAR_COLUMN_URI, &uri,
1030
 
                                    -1);
1031
 
 
1032
 
                if (uri != NULL) {
1033
 
                        if (strcmp (uri, sidebar->uri) == 0) {
1034
 
                                g_free (uri);
1035
 
                                gtk_tree_selection_select_iter (selection, &iter);
1036
 
                                break;
1037
 
                        }
1038
 
                        g_free (uri);
1039
 
                }
1040
 
                valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (sidebar->store),
1041
 
                                                  &iter);
1042
 
        }
1043
 
}
1044
 
 
1045
 
static void
1046
 
loading_uri_callback (NautilusWindow *window,
1047
 
                      char *location,
1048
 
                      NautilusPlacesSidebar *sidebar)
1049
 
{
1050
 
        if (g_strcmp0 (sidebar->uri, location) != 0) {
1051
 
                g_free (sidebar->uri);
1052
 
                sidebar->uri = g_strdup (location);
1053
 
 
1054
 
                update_current_uri (sidebar);
1055
 
        }
1056
 
}
1057
 
 
1058
 
/* Computes the appropriate row and position for dropping */
1059
 
static gboolean
1060
 
compute_drop_position (GtkTreeView             *tree_view,
1061
 
                       int                      x,
1062
 
                       int                      y,
1063
 
                       GtkTreePath            **path,
1064
 
                       GtkTreeViewDropPosition *pos,
1065
 
                       NautilusPlacesSidebar   *sidebar)
1066
 
{
1067
 
        GtkTreeModel *model;
1068
 
        GtkTreeIter iter;
1069
 
        PlaceType place_type;
1070
 
        SectionType section_type;
1071
 
 
1072
 
        if (!gtk_tree_view_get_dest_row_at_pos (tree_view,
1073
 
                                                x, y,
1074
 
                                                path, pos)) {
1075
 
                return FALSE;
1076
 
        }
1077
 
 
1078
 
        model = gtk_tree_view_get_model (tree_view);
1079
 
 
1080
 
        gtk_tree_model_get_iter (model, &iter, *path);
1081
 
        gtk_tree_model_get (model, &iter,
1082
 
                            PLACES_SIDEBAR_COLUMN_ROW_TYPE, &place_type,
1083
 
                            PLACES_SIDEBAR_COLUMN_SECTION_TYPE, &section_type,
1084
 
                            -1);
1085
 
 
1086
 
        if (section_type != SECTION_BOOKMARKS &&
1087
 
            place_type == PLACES_HEADING) {
1088
 
                /* never drop on headings, but special case the bookmarks heading,
1089
 
                 * so we can drop bookmarks in between it and the first item when
1090
 
                 * reordering.
1091
 
                 */
1092
 
                gtk_tree_path_free (*path);
1093
 
                *path = NULL;
1094
 
                
1095
 
                return FALSE;
1096
 
        }
1097
 
 
1098
 
        if (section_type != SECTION_BOOKMARKS &&
1099
 
            sidebar->drag_data_received &&
1100
 
            sidebar->drag_data_info == GTK_TREE_MODEL_ROW) {
1101
 
                /* don't allow dropping bookmarks into non-bookmark areas */
1102
 
                gtk_tree_path_free (*path);
1103
 
                *path = NULL;
1104
 
 
1105
 
                return FALSE;
1106
 
        }
1107
 
 
1108
 
        if (sidebar->drag_data_received &&
1109
 
            sidebar->drag_data_info == GTK_TREE_MODEL_ROW) {
1110
 
                /* bookmark rows can only be reordered */
1111
 
                *pos = GTK_TREE_VIEW_DROP_AFTER;
1112
 
        } else {
1113
 
                *pos = GTK_TREE_VIEW_DROP_INTO_OR_BEFORE;
1114
 
        }
1115
 
 
1116
 
        return TRUE;
1117
 
}
1118
 
 
1119
 
static gboolean
1120
 
get_drag_data (GtkTreeView *tree_view,
1121
 
               GdkDragContext *context, 
1122
 
               unsigned int time)
1123
 
{
1124
 
        GdkAtom target;
1125
 
 
1126
 
        target = gtk_drag_dest_find_target (GTK_WIDGET (tree_view), 
1127
 
                                            context, 
1128
 
                                            NULL);
1129
 
 
1130
 
        if (target == GDK_NONE) {
1131
 
                return FALSE;
1132
 
        }
1133
 
 
1134
 
        gtk_drag_get_data (GTK_WIDGET (tree_view),
1135
 
                           context, target, time);
1136
 
 
1137
 
        return TRUE;
1138
 
}
1139
 
 
1140
 
static void
1141
 
remove_switch_location_timer (NautilusPlacesSidebar *sidebar)
1142
 
{
1143
 
        if (sidebar->switch_location_timer != 0) {
1144
 
                g_source_remove (sidebar->switch_location_timer);
1145
 
                sidebar->switch_location_timer = 0;
1146
 
        }
1147
 
}
1148
 
 
1149
 
static void
1150
 
free_drag_data (NautilusPlacesSidebar *sidebar)
1151
 
{
1152
 
        sidebar->drag_data_received = FALSE;
1153
 
 
1154
 
        if (sidebar->drag_list) {
1155
 
                nautilus_drag_destroy_selection_list (sidebar->drag_list);
1156
 
                sidebar->drag_list = NULL;
1157
 
        }
1158
 
 
1159
 
        remove_switch_location_timer (sidebar);
1160
 
 
1161
 
        g_free (sidebar->target_uri);
1162
 
        sidebar->target_uri = NULL;
1163
 
}
1164
 
 
1165
 
static gboolean
1166
 
switch_location_timer (gpointer user_data)
1167
 
{
1168
 
        NautilusPlacesSidebar *sidebar = user_data;
1169
 
        GFile *location;
1170
 
        NautilusWindowSlot *target_slot;
1171
 
 
1172
 
        sidebar->switch_location_timer = 0;
1173
 
 
1174
 
        target_slot = nautilus_window_get_active_slot (NAUTILUS_WINDOW (sidebar->window));
1175
 
 
1176
 
        location = g_file_new_for_uri (sidebar->target_uri);
1177
 
        nautilus_window_slot_open_location (target_slot, location, 0);
1178
 
        g_object_unref (location);
1179
 
 
1180
 
        return FALSE;
1181
 
}
1182
 
 
1183
 
static void
1184
 
check_switch_location_timer (NautilusPlacesSidebar *sidebar,
1185
 
                             const char            *uri)
1186
 
{
1187
 
        GtkSettings *settings;
1188
 
        guint timeout;
1189
 
 
1190
 
        if (g_strcmp0 (uri, sidebar->target_uri) == 0) {
1191
 
                return;
1192
 
        }
1193
 
        remove_switch_location_timer (sidebar);
1194
 
 
1195
 
        settings = gtk_widget_get_settings (GTK_WIDGET (sidebar));
1196
 
        g_object_get (settings, "gtk-timeout-expand", &timeout, NULL);
1197
 
 
1198
 
        g_free (sidebar->target_uri);
1199
 
        sidebar->target_uri = NULL;
1200
 
 
1201
 
        if (uri != NULL) {
1202
 
                sidebar->target_uri = g_strdup (uri);
1203
 
                sidebar->switch_location_timer =
1204
 
                        gdk_threads_add_timeout (timeout,
1205
 
                                                 switch_location_timer,
1206
 
                                                 sidebar);
1207
 
        }
1208
 
}
1209
 
 
1210
 
static gboolean
1211
 
drag_motion_callback (GtkTreeView *tree_view,
1212
 
                      GdkDragContext *context,
1213
 
                      int x,
1214
 
                      int y,
1215
 
                      unsigned int time,
1216
 
                      NautilusPlacesSidebar *sidebar)
1217
 
{
1218
 
        GtkTreePath *path;
1219
 
        GtkTreeViewDropPosition pos;
1220
 
        int action;
1221
 
        GtkTreeIter iter;
1222
 
        char *target_uri = NULL;
1223
 
        gboolean res;
1224
 
 
1225
 
        if (!sidebar->drag_data_received) {
1226
 
                if (!get_drag_data (tree_view, context, time)) {
1227
 
                        return FALSE;
1228
 
                }
1229
 
        }
1230
 
 
1231
 
        path = NULL;
1232
 
        res = compute_drop_position (tree_view, x, y, &path, &pos, sidebar);
1233
 
 
1234
 
        if (!res) {
1235
 
                goto out;
1236
 
        }
1237
 
 
1238
 
        if (pos == GTK_TREE_VIEW_DROP_AFTER ) {
1239
 
                if (sidebar->drag_data_received &&
1240
 
                    sidebar->drag_data_info == GTK_TREE_MODEL_ROW) {
1241
 
                        action = GDK_ACTION_MOVE;
1242
 
                } else {
1243
 
                        action = 0;
1244
 
                }
1245
 
        } else {
1246
 
                if (sidebar->drag_list == NULL) {
1247
 
                        action = 0;
1248
 
                } else {
1249
 
                        gtk_tree_model_get_iter (GTK_TREE_MODEL (sidebar->store),
1250
 
                                                 &iter, path);
1251
 
                        gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store),
1252
 
                                            &iter,
1253
 
                                            PLACES_SIDEBAR_COLUMN_URI, &target_uri,
1254
 
                                            -1);
1255
 
                        nautilus_drag_default_drop_action_for_icons (context, target_uri,
1256
 
                                                                     sidebar->drag_list,
1257
 
                                                                     &action);
1258
 
                }
1259
 
        }
1260
 
 
1261
 
        if (action != 0) {
1262
 
                gtk_tree_view_set_drag_dest_row (tree_view, path, pos);
1263
 
        }
1264
 
 
1265
 
        if (path != NULL) {
1266
 
                gtk_tree_path_free (path);
1267
 
        }
1268
 
 
1269
 
 out:
1270
 
        g_signal_stop_emission_by_name (tree_view, "drag-motion");
1271
 
 
1272
 
        if (action != 0) {
1273
 
                check_switch_location_timer (sidebar, target_uri);
1274
 
                gdk_drag_status (context, action, time);
1275
 
        } else {
1276
 
                remove_switch_location_timer (sidebar);
1277
 
                gdk_drag_status (context, 0, time);
1278
 
        }
1279
 
 
1280
 
        g_free (target_uri);
1281
 
 
1282
 
        return TRUE;
1283
 
}
1284
 
 
1285
 
static void
1286
 
drag_leave_callback (GtkTreeView *tree_view,
1287
 
                     GdkDragContext *context,
1288
 
                     unsigned int time,
1289
 
                     NautilusPlacesSidebar *sidebar)
1290
 
{
1291
 
        free_drag_data (sidebar);
1292
 
        gtk_tree_view_set_drag_dest_row (tree_view, NULL, 0);
1293
 
        g_signal_stop_emission_by_name (tree_view, "drag-leave");
1294
 
}
1295
 
 
1296
 
static GList *
1297
 
uri_list_from_selection (GList *selection)
1298
 
{
1299
 
        NautilusDragSelectionItem *item;
1300
 
        GList *ret;
1301
 
        GList *l;
1302
 
        
1303
 
        ret = NULL;
1304
 
        for (l = selection; l != NULL; l = l->next) {
1305
 
                item = l->data;
1306
 
                ret = g_list_prepend (ret, item->uri);
1307
 
        }
1308
 
        
1309
 
        return g_list_reverse (ret);
1310
 
}
1311
 
 
1312
 
static GList*
1313
 
build_selection_list (const char *data)
1314
 
{
1315
 
        NautilusDragSelectionItem *item;
1316
 
        GList *result;
1317
 
        char **uris;
1318
 
        char *uri;
1319
 
        int i;
1320
 
 
1321
 
        uris = g_uri_list_extract_uris (data);
1322
 
        result = NULL;
1323
 
        for (i = 0; uris[i]; i++) {
1324
 
                uri = uris[i];
1325
 
                item = nautilus_drag_selection_item_new ();
1326
 
                item->uri = g_strdup (uri);
1327
 
                item->file = nautilus_file_get_existing_by_uri (uri);
1328
 
                item->got_icon_position = FALSE;
1329
 
                result = g_list_prepend (result, item);
1330
 
        }
1331
 
 
1332
 
        g_strfreev (uris);
1333
 
 
1334
 
        return g_list_reverse (result);
1335
 
}
1336
 
 
1337
 
static gboolean
1338
 
get_selected_iter (NautilusPlacesSidebar *sidebar,
1339
 
                   GtkTreeIter *iter)
1340
 
{
1341
 
        GtkTreeSelection *selection;
1342
 
 
1343
 
        selection = gtk_tree_view_get_selection (sidebar->tree_view);
1344
 
 
1345
 
        return gtk_tree_selection_get_selected (selection, NULL, iter);
1346
 
}
1347
 
 
1348
 
/* Reorders the selected bookmark to the specified position */
1349
 
static void
1350
 
reorder_bookmarks (NautilusPlacesSidebar *sidebar,
1351
 
                   int                   new_position)
1352
 
{
1353
 
        GtkTreeIter iter;
1354
 
        PlaceType type; 
1355
 
        int old_position;
1356
 
 
1357
 
        /* Get the selected path */
1358
 
        if (!get_selected_iter (sidebar, &iter)) {
1359
 
                return;
1360
 
        }
1361
 
 
1362
 
        gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
1363
 
                            PLACES_SIDEBAR_COLUMN_ROW_TYPE, &type,
1364
 
                            PLACES_SIDEBAR_COLUMN_INDEX, &old_position,
1365
 
                            -1);
1366
 
 
1367
 
        if (type != PLACES_BOOKMARK ||
1368
 
            old_position < 0 ||
1369
 
            old_position >= nautilus_bookmark_list_length (sidebar->bookmarks)) {
1370
 
                return;
1371
 
        }
1372
 
 
1373
 
        nautilus_bookmark_list_move_item (sidebar->bookmarks, old_position,
1374
 
                                          new_position);
1375
 
}
1376
 
 
1377
 
static void
1378
 
drag_data_received_callback (GtkWidget *widget,
1379
 
                             GdkDragContext *context,
1380
 
                             int x,
1381
 
                             int y,
1382
 
                             GtkSelectionData *selection_data,
1383
 
                             unsigned int info,
1384
 
                             unsigned int time,
1385
 
                             NautilusPlacesSidebar *sidebar)
1386
 
{
1387
 
        GtkTreeView *tree_view;
1388
 
        GtkTreePath *tree_path;
1389
 
        GtkTreeViewDropPosition tree_pos;
1390
 
        GtkTreeIter iter;
1391
 
        int position;
1392
 
        GtkTreeModel *model;
1393
 
        char *drop_uri;
1394
 
        GList *selection_list, *uris;
1395
 
        PlaceType place_type;
1396
 
        SectionType section_type;
1397
 
        gboolean success;
1398
 
 
1399
 
        tree_view = GTK_TREE_VIEW (widget);
1400
 
 
1401
 
        if (!sidebar->drag_data_received) {
1402
 
                if (gtk_selection_data_get_target (selection_data) != GDK_NONE &&
1403
 
                    info == TEXT_URI_LIST) {
1404
 
                        sidebar->drag_list = build_selection_list ((const gchar *) gtk_selection_data_get_data (selection_data));
1405
 
                } else {
1406
 
                        sidebar->drag_list = NULL;
1407
 
                }
1408
 
                sidebar->drag_data_received = TRUE;
1409
 
                sidebar->drag_data_info = info;
1410
 
        }
1411
 
 
1412
 
        g_signal_stop_emission_by_name (widget, "drag-data-received");
1413
 
 
1414
 
        if (!sidebar->drop_occured) {
1415
 
                return;
1416
 
        }
1417
 
 
1418
 
        /* Compute position */
1419
 
        success = compute_drop_position (tree_view, x, y, &tree_path, &tree_pos, sidebar);
1420
 
        if (!success) {
1421
 
                goto out;
1422
 
        }
1423
 
 
1424
 
        success = FALSE;
1425
 
 
1426
 
        if (tree_pos == GTK_TREE_VIEW_DROP_AFTER) {
1427
 
                model = gtk_tree_view_get_model (tree_view);
1428
 
 
1429
 
                if (!gtk_tree_model_get_iter (model, &iter, tree_path)) {
1430
 
                        goto out;
1431
 
                }
1432
 
 
1433
 
                gtk_tree_model_get (model, &iter,
1434
 
                                    PLACES_SIDEBAR_COLUMN_SECTION_TYPE, &section_type,
1435
 
                                    PLACES_SIDEBAR_COLUMN_ROW_TYPE, &place_type,
1436
 
                                    PLACES_SIDEBAR_COLUMN_INDEX, &position,
1437
 
                                    -1);
1438
 
 
1439
 
                if (section_type != SECTION_BOOKMARKS) {
1440
 
                        goto out;
1441
 
                }
1442
 
 
1443
 
                if (tree_pos == GTK_TREE_VIEW_DROP_AFTER && place_type != PLACES_HEADING) {
1444
 
                        /* heading already has position 0 */
1445
 
                        position++;
1446
 
                }
1447
 
 
1448
 
                switch (info) {
1449
 
                case GTK_TREE_MODEL_ROW:
1450
 
                        reorder_bookmarks (sidebar, position);
1451
 
                        success = TRUE;
1452
 
                        break;
1453
 
                default:
1454
 
                        g_assert_not_reached ();
1455
 
                        break;
1456
 
                }
1457
 
        } else {
1458
 
                GdkDragAction real_action;
1459
 
 
1460
 
                /* file transfer requested */
1461
 
                real_action = gdk_drag_context_get_selected_action (context);
1462
 
 
1463
 
                if (real_action == GDK_ACTION_ASK) {
1464
 
                        real_action =
1465
 
                                nautilus_drag_drop_action_ask (GTK_WIDGET (tree_view),
1466
 
                                                               gdk_drag_context_get_actions (context));
1467
 
                }
1468
 
 
1469
 
                if (real_action > 0) {
1470
 
                        model = gtk_tree_view_get_model (tree_view);
1471
 
 
1472
 
                        gtk_tree_model_get_iter (model, &iter, tree_path);
1473
 
                        gtk_tree_model_get (model, &iter,
1474
 
                                            PLACES_SIDEBAR_COLUMN_URI, &drop_uri,
1475
 
                                            -1);
1476
 
 
1477
 
                        switch (info) {
1478
 
                        case TEXT_URI_LIST:
1479
 
                                selection_list = build_selection_list ((const gchar *) gtk_selection_data_get_data (selection_data));
1480
 
                                g_assert (selection_list);
1481
 
                                uris = uri_list_from_selection (selection_list);
1482
 
                                g_assert (uris);
1483
 
                                nautilus_file_operations_copy_move (uris, NULL, drop_uri,
1484
 
                                                                    real_action, GTK_WIDGET (tree_view),
1485
 
                                                                    NULL, NULL);
1486
 
                                nautilus_drag_destroy_selection_list (selection_list);
1487
 
                                g_list_free (uris);
1488
 
                                success = TRUE;
1489
 
                                break;
1490
 
                        case GTK_TREE_MODEL_ROW:
1491
 
                                success = FALSE;
1492
 
                                break;
1493
 
                        default:
1494
 
                                g_assert_not_reached ();
1495
 
                                break;
1496
 
                        }
1497
 
 
1498
 
                        g_free (drop_uri);
1499
 
                }
1500
 
        }
1501
 
 
1502
 
out:
1503
 
        sidebar->drop_occured = FALSE;
1504
 
        free_drag_data (sidebar);
1505
 
        gtk_drag_finish (context, success, FALSE, time);
1506
 
 
1507
 
        gtk_tree_path_free (tree_path);
1508
 
}
1509
 
 
1510
 
static gboolean
1511
 
drag_drop_callback (GtkTreeView *tree_view,
1512
 
                    GdkDragContext *context,
1513
 
                    int x,
1514
 
                    int y,
1515
 
                    unsigned int time,
1516
 
                    NautilusPlacesSidebar *sidebar)
1517
 
{
1518
 
        gboolean retval = FALSE;
1519
 
        sidebar->drop_occured = TRUE;
1520
 
        retval = get_drag_data (tree_view, context, time);
1521
 
        g_signal_stop_emission_by_name (tree_view, "drag-drop");
1522
 
        return retval;
1523
 
}
1524
 
 
1525
 
/* Callback used when the file list's popup menu is detached */
1526
 
static void
1527
 
bookmarks_popup_menu_detach_cb (GtkWidget *attach_widget,
1528
 
                                GtkMenu   *menu)
1529
 
{
1530
 
        NautilusPlacesSidebar *sidebar;
1531
 
        
1532
 
        sidebar = NAUTILUS_PLACES_SIDEBAR (attach_widget);
1533
 
        g_assert (NAUTILUS_IS_PLACES_SIDEBAR (sidebar));
1534
 
        
1535
 
        sidebar->popup_menu = NULL;
1536
 
        sidebar->popup_menu_add_shortcut_item = NULL;
1537
 
        sidebar->popup_menu_remove_item = NULL;
1538
 
        sidebar->popup_menu_rename_item = NULL;
1539
 
        sidebar->popup_menu_separator_item = NULL;
1540
 
        sidebar->popup_menu_mount_item = NULL;
1541
 
        sidebar->popup_menu_unmount_item = NULL;
1542
 
        sidebar->popup_menu_eject_item = NULL;
1543
 
        sidebar->popup_menu_rescan_item = NULL;
1544
 
        sidebar->popup_menu_start_item = NULL;
1545
 
        sidebar->popup_menu_stop_item = NULL;
1546
 
        sidebar->popup_menu_empty_trash_item = NULL;
1547
 
        sidebar->popup_menu_properties_separator_item = NULL;
1548
 
        sidebar->popup_menu_properties_item = NULL;
1549
 
        sidebar->popup_menu_format_item = NULL;
1550
 
}
1551
 
 
1552
 
static gboolean
1553
 
check_have_gnome_disks (void)
1554
 
{
1555
 
        gchar *disks_path;
1556
 
        gboolean res;
1557
 
 
1558
 
        disks_path = g_find_program_in_path ("gnome-disks");
1559
 
        res = (disks_path != NULL);
1560
 
        g_free (disks_path);
1561
 
 
1562
 
        return res;
1563
 
}
1564
 
 
1565
 
static void
1566
 
check_unmount_and_eject (GMount *mount,
1567
 
                         GVolume *volume,
1568
 
                         GDrive *drive,
1569
 
                         gboolean *show_unmount,
1570
 
                         gboolean *show_eject)
1571
 
{
1572
 
        *show_unmount = FALSE;
1573
 
        *show_eject = FALSE;
1574
 
 
1575
 
        if (drive != NULL) {
1576
 
                *show_eject = g_drive_can_eject (drive);
1577
 
        }
1578
 
 
1579
 
        if (volume != NULL) {
1580
 
                *show_eject |= g_volume_can_eject (volume);
1581
 
        }
1582
 
        if (mount != NULL) {
1583
 
                *show_eject |= g_mount_can_eject (mount);
1584
 
                *show_unmount = g_mount_can_unmount (mount) && !*show_eject;
1585
 
        }
1586
 
}
1587
 
 
1588
 
static void
1589
 
check_visibility (GMount           *mount,
1590
 
                  GVolume          *volume,
1591
 
                  GDrive           *drive,
1592
 
                  gboolean         *show_mount,
1593
 
                  gboolean         *show_unmount,
1594
 
                  gboolean         *show_eject,
1595
 
                  gboolean         *show_rescan,
1596
 
                  gboolean         *show_start,
1597
 
                  gboolean         *show_stop,
1598
 
                  gboolean         *show_format)
1599
 
{
1600
 
        gchar *unix_device_id;
1601
 
 
1602
 
        *show_mount = FALSE;
1603
 
        *show_rescan = FALSE;
1604
 
        *show_start = FALSE;
1605
 
        *show_stop = FALSE;
1606
 
        *show_format = FALSE;
1607
 
 
1608
 
        check_unmount_and_eject (mount, volume, drive, show_unmount, show_eject);
1609
 
 
1610
 
        if (drive != NULL) {
1611
 
                if (g_drive_is_media_removable (drive) &&
1612
 
                    !g_drive_is_media_check_automatic (drive) && 
1613
 
                    g_drive_can_poll_for_media (drive))
1614
 
                        *show_rescan = TRUE;
1615
 
 
1616
 
                *show_start = g_drive_can_start (drive) || g_drive_can_start_degraded (drive);
1617
 
                *show_stop  = g_drive_can_stop (drive);
1618
 
 
1619
 
                if (*show_stop)
1620
 
                        *show_unmount = FALSE;
1621
 
        }
1622
 
 
1623
 
        if (volume != NULL) {
1624
 
                if (mount == NULL)
1625
 
                        *show_mount = g_volume_can_mount (volume);
1626
 
 
1627
 
                unix_device_id = g_volume_get_identifier (volume, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
1628
 
                *show_format = (unix_device_id != NULL) && check_have_gnome_disks ();
1629
 
                g_free (unix_device_id);
1630
 
        }
1631
 
}
1632
 
 
1633
 
static void
1634
 
bookmarks_check_popup_sensitivity (NautilusPlacesSidebar *sidebar)
1635
 
{
1636
 
        GtkTreeIter iter;
1637
 
        PlaceType type; 
1638
 
        GDrive *drive = NULL;
1639
 
        GVolume *volume = NULL;
1640
 
        GMount *mount = NULL;
1641
 
        GFile *location;
1642
 
        NautilusDirectory *directory;
1643
 
        gboolean show_mount;
1644
 
        gboolean show_unmount;
1645
 
        gboolean show_eject;
1646
 
        gboolean show_rescan;
1647
 
        gboolean show_start;
1648
 
        gboolean show_stop;
1649
 
        gboolean show_empty_trash;
1650
 
        gboolean show_properties;
1651
 
        gboolean show_format;
1652
 
        char *uri = NULL;
1653
 
        
1654
 
        type = PLACES_BUILT_IN;
1655
 
 
1656
 
        if (sidebar->popup_menu == NULL) {
1657
 
                return;
1658
 
        }
1659
 
 
1660
 
        if (get_selected_iter (sidebar, &iter)) {
1661
 
                gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
1662
 
                                    PLACES_SIDEBAR_COLUMN_ROW_TYPE, &type,
1663
 
                                    PLACES_SIDEBAR_COLUMN_DRIVE, &drive,
1664
 
                                    PLACES_SIDEBAR_COLUMN_VOLUME, &volume,
1665
 
                                    PLACES_SIDEBAR_COLUMN_MOUNT, &mount,
1666
 
                                    PLACES_SIDEBAR_COLUMN_URI, &uri,
1667
 
                                    -1);
1668
 
        }
1669
 
 
1670
 
        gtk_widget_set_visible (sidebar->popup_menu_add_shortcut_item, (type == PLACES_MOUNTED_VOLUME));
1671
 
 
1672
 
        gtk_widget_set_sensitive (sidebar->popup_menu_remove_item, (type == PLACES_BOOKMARK));
1673
 
        gtk_widget_set_sensitive (sidebar->popup_menu_rename_item, (type == PLACES_BOOKMARK || type == PLACES_XDG_DIR));
1674
 
        gtk_widget_set_sensitive (sidebar->popup_menu_empty_trash_item, !nautilus_trash_monitor_is_empty ());
1675
 
 
1676
 
        check_visibility (mount, volume, drive,
1677
 
                          &show_mount, &show_unmount, &show_eject, &show_rescan, &show_start, &show_stop, &show_format);
1678
 
 
1679
 
        /* We actually want both eject and unmount since eject will unmount all volumes. 
1680
 
         * TODO: hide unmount if the drive only has a single mountable volume 
1681
 
         */
1682
 
 
1683
 
        show_empty_trash = (uri != NULL) &&
1684
 
                           (!strcmp (uri, "trash:///"));
1685
 
 
1686
 
        /* Only show properties for local mounts */
1687
 
        show_properties = (mount != NULL);
1688
 
        if (mount != NULL) {
1689
 
                location = g_mount_get_default_location (mount);
1690
 
                directory = nautilus_directory_get (location);
1691
 
 
1692
 
                show_properties = nautilus_directory_is_local (directory);
1693
 
 
1694
 
                nautilus_directory_unref (directory);
1695
 
                g_object_unref (location);
1696
 
        }
1697
 
 
1698
 
        gtk_widget_set_visible (sidebar->popup_menu_separator_item,
1699
 
                      show_mount || show_unmount || show_eject || show_empty_trash);
1700
 
        gtk_widget_set_visible (sidebar->popup_menu_mount_item, show_mount);
1701
 
        gtk_widget_set_visible (sidebar->popup_menu_unmount_item, show_unmount);
1702
 
        gtk_widget_set_visible (sidebar->popup_menu_eject_item, show_eject);
1703
 
        gtk_widget_set_visible (sidebar->popup_menu_rescan_item, show_rescan);
1704
 
        gtk_widget_set_visible (sidebar->popup_menu_start_item, show_start);
1705
 
        gtk_widget_set_visible (sidebar->popup_menu_stop_item, show_stop);
1706
 
        gtk_widget_set_visible (sidebar->popup_menu_empty_trash_item, show_empty_trash);
1707
 
        gtk_widget_set_visible (sidebar->popup_menu_properties_separator_item, show_properties);
1708
 
        gtk_widget_set_visible (sidebar->popup_menu_properties_item, show_properties);
1709
 
        gtk_widget_set_visible (sidebar->popup_menu_format_item, show_format);
1710
 
 
1711
 
        /* Adjust start/stop items to reflect the type of the drive */
1712
 
        gtk_menu_item_set_label (GTK_MENU_ITEM (sidebar->popup_menu_start_item), _("_Start"));
1713
 
        gtk_menu_item_set_label (GTK_MENU_ITEM (sidebar->popup_menu_stop_item), _("_Stop"));
1714
 
        if ((show_start || show_stop) && drive != NULL) {
1715
 
                switch (g_drive_get_start_stop_type (drive)) {
1716
 
                case G_DRIVE_START_STOP_TYPE_SHUTDOWN:
1717
 
                        /* start() for type G_DRIVE_START_STOP_TYPE_SHUTDOWN is normally not used */
1718
 
                        gtk_menu_item_set_label (GTK_MENU_ITEM (sidebar->popup_menu_start_item), _("_Power On"));
1719
 
                        gtk_menu_item_set_label (GTK_MENU_ITEM (sidebar->popup_menu_stop_item), _("_Safely Remove Drive"));
1720
 
                        break;
1721
 
                case G_DRIVE_START_STOP_TYPE_NETWORK:
1722
 
                        gtk_menu_item_set_label (GTK_MENU_ITEM (sidebar->popup_menu_start_item), _("_Connect Drive"));
1723
 
                        gtk_menu_item_set_label (GTK_MENU_ITEM (sidebar->popup_menu_stop_item), _("_Disconnect Drive"));
1724
 
                        break;
1725
 
                case G_DRIVE_START_STOP_TYPE_MULTIDISK:
1726
 
                        gtk_menu_item_set_label (GTK_MENU_ITEM (sidebar->popup_menu_start_item), _("_Start Multi-disk Device"));
1727
 
                        gtk_menu_item_set_label (GTK_MENU_ITEM (sidebar->popup_menu_stop_item), _("_Stop Multi-disk Device"));
1728
 
                        break;
1729
 
                case G_DRIVE_START_STOP_TYPE_PASSWORD:
1730
 
                        /* stop() for type G_DRIVE_START_STOP_TYPE_PASSWORD is normally not used */
1731
 
                        gtk_menu_item_set_label (GTK_MENU_ITEM (sidebar->popup_menu_start_item), _("_Unlock Drive"));
1732
 
                        gtk_menu_item_set_label (GTK_MENU_ITEM (sidebar->popup_menu_stop_item), _("_Lock Drive"));
1733
 
                        break;
1734
 
 
1735
 
                default:
1736
 
                case G_DRIVE_START_STOP_TYPE_UNKNOWN:
1737
 
                        /* uses defaults set above */
1738
 
                        break;
1739
 
                }
1740
 
        }
1741
 
 
1742
 
 
1743
 
        g_free (uri);
1744
 
}
1745
 
 
1746
 
/* Callback used when the selection in the shortcuts tree changes */
1747
 
static void
1748
 
bookmarks_selection_changed_cb (GtkTreeSelection      *selection,
1749
 
                                NautilusPlacesSidebar *sidebar)
1750
 
{
1751
 
        bookmarks_check_popup_sensitivity (sidebar);
1752
 
}
1753
 
 
1754
 
static void
1755
 
volume_mounted_cb (GVolume *volume,
1756
 
                   gboolean success,
1757
 
                   GObject *user_data)
1758
 
{
1759
 
        GMount *mount;
1760
 
        NautilusPlacesSidebar *sidebar;
1761
 
        GFile *location;
1762
 
 
1763
 
        sidebar = NAUTILUS_PLACES_SIDEBAR (user_data);
1764
 
 
1765
 
        sidebar->mounting = FALSE;
1766
 
 
1767
 
        mount = g_volume_get_mount (volume);
1768
 
        if (mount != NULL) {
1769
 
                location = g_mount_get_default_location (mount);
1770
 
 
1771
 
                if (sidebar->go_to_after_mount_slot != NULL) {
1772
 
                        if ((sidebar->go_to_after_mount_flags & NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW) == 0) {
1773
 
                                nautilus_window_slot_open_location (sidebar->go_to_after_mount_slot, location,
1774
 
                                                                    sidebar->go_to_after_mount_flags);
1775
 
                        } else {
1776
 
                                NautilusWindow *new, *cur;
1777
 
 
1778
 
                                cur = NAUTILUS_WINDOW (sidebar->window);
1779
 
                                new = nautilus_application_create_window (NAUTILUS_APPLICATION (g_application_get_default ()),
1780
 
                                                                          gtk_window_get_screen (GTK_WINDOW (cur)));
1781
 
                                nautilus_window_go_to (new, location);
1782
 
                        }
1783
 
                }
1784
 
 
1785
 
                g_object_unref (G_OBJECT (location));
1786
 
                g_object_unref (G_OBJECT (mount));
1787
 
        }
1788
 
 
1789
 
        if (sidebar->go_to_after_mount_slot) {
1790
 
                g_object_remove_weak_pointer (G_OBJECT (sidebar->go_to_after_mount_slot),
1791
 
                                              (gpointer *) &sidebar->go_to_after_mount_slot);
1792
 
                sidebar->go_to_after_mount_slot = NULL;
1793
 
        }
1794
 
}
1795
 
 
1796
 
static void
1797
 
drive_start_from_bookmark_cb (GObject      *source_object,
1798
 
                              GAsyncResult *res,
1799
 
                              gpointer      user_data)
1800
 
{
1801
 
        GError *error;
1802
 
        char *primary;
1803
 
        char *name;
1804
 
 
1805
 
        error = NULL;
1806
 
        if (!g_drive_poll_for_media_finish (G_DRIVE (source_object), res, &error)) {
1807
 
                if (error->code != G_IO_ERROR_FAILED_HANDLED) {
1808
 
                        name = g_drive_get_name (G_DRIVE (source_object));
1809
 
                        primary = g_strdup_printf (_("Unable to start %s"), name);
1810
 
                        g_free (name);
1811
 
                        eel_show_error_dialog (primary,
1812
 
                                               error->message,
1813
 
                                               NULL);
1814
 
                        g_free (primary);
1815
 
                }
1816
 
                g_error_free (error);
1817
 
        }
1818
 
}
1819
 
 
1820
 
static void
1821
 
open_selected_volume (NautilusPlacesSidebar *sidebar,
1822
 
                      GtkTreeModel *model,
1823
 
                      GtkTreeIter *iter,
1824
 
                      NautilusWindowOpenFlags flags)
1825
 
{
1826
 
        GDrive *drive;
1827
 
        GVolume *volume;
1828
 
        NautilusWindowSlot *slot;
1829
 
 
1830
 
        gtk_tree_model_get (model, iter,
1831
 
                            PLACES_SIDEBAR_COLUMN_DRIVE, &drive,
1832
 
                            PLACES_SIDEBAR_COLUMN_VOLUME, &volume,
1833
 
                            -1);
1834
 
 
1835
 
        if (volume != NULL && !sidebar->mounting) {
1836
 
                sidebar->mounting = TRUE;
1837
 
 
1838
 
                g_assert (sidebar->go_to_after_mount_slot == NULL);
1839
 
 
1840
 
                slot = nautilus_window_get_active_slot (sidebar->window);
1841
 
                sidebar->go_to_after_mount_slot = slot;
1842
 
                g_object_add_weak_pointer (G_OBJECT (sidebar->go_to_after_mount_slot),
1843
 
                                           (gpointer *) &sidebar->go_to_after_mount_slot);
1844
 
 
1845
 
                sidebar->go_to_after_mount_flags = flags;
1846
 
 
1847
 
                nautilus_file_operations_mount_volume_full (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (sidebar))),
1848
 
                                                            volume,
1849
 
                                                            volume_mounted_cb,
1850
 
                                                            G_OBJECT (sidebar));
1851
 
        } else if (volume == NULL && drive != NULL &&
1852
 
                   (g_drive_can_start (drive) || g_drive_can_start_degraded (drive))) {
1853
 
                GMountOperation *mount_op;
1854
 
 
1855
 
                mount_op = gtk_mount_operation_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (sidebar))));
1856
 
                g_drive_start (drive, G_DRIVE_START_NONE, mount_op, NULL, drive_start_from_bookmark_cb, NULL);
1857
 
                g_object_unref (mount_op);
1858
 
        }
1859
 
 
1860
 
        if (drive != NULL)
1861
 
                g_object_unref (drive);
1862
 
        if (volume != NULL)
1863
 
                g_object_unref (volume);
1864
 
}
1865
 
 
1866
 
static void
1867
 
open_selected_uri (NautilusPlacesSidebar *sidebar,
1868
 
                   const gchar *uri,
1869
 
                   NautilusWindowOpenFlags flags)
1870
 
{
1871
 
        NautilusWindowSlot *slot;
1872
 
        GFile *location;
1873
 
 
1874
 
        DEBUG ("Activating bookmark %s", uri);
1875
 
 
1876
 
        location = g_file_new_for_uri (uri);
1877
 
 
1878
 
        /* Navigate to the clicked location */
1879
 
        if ((flags & NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW) == 0) {
1880
 
                slot = nautilus_window_get_active_slot (sidebar->window);
1881
 
                nautilus_window_slot_open_location (slot, location, flags);
1882
 
        } else {
1883
 
                NautilusWindow *cur, *new;
1884
 
 
1885
 
                cur = NAUTILUS_WINDOW (sidebar->window);
1886
 
                new = nautilus_application_create_window (NAUTILUS_APPLICATION (g_application_get_default ()),
1887
 
                                                          gtk_window_get_screen (GTK_WINDOW (cur)));
1888
 
                nautilus_window_go_to (new, location);
1889
 
        }
1890
 
 
1891
 
        g_object_unref (location);
1892
 
}
1893
 
 
1894
 
static void
1895
 
open_connect_to_server (NautilusPlacesSidebar *sidebar)
1896
 
{
1897
 
        NautilusApplication *application = NAUTILUS_APPLICATION (g_application_get_default ());
1898
 
        GtkWidget *dialog;
1899
 
 
1900
 
        dialog = nautilus_application_connect_server (application, sidebar->window);
1901
 
        gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
1902
 
}
1903
 
 
1904
 
static void
1905
 
open_selected_bookmark (NautilusPlacesSidebar *sidebar,
1906
 
                        GtkTreeModel          *model,
1907
 
                        GtkTreeIter           *iter,
1908
 
                        NautilusWindowOpenFlags       flags)
1909
 
{
1910
 
        char *uri;
1911
 
        PlaceType row_type;
1912
 
 
1913
 
        if (!iter) {
1914
 
                return;
1915
 
        }
1916
 
 
1917
 
        gtk_tree_model_get (model, iter,
1918
 
                            PLACES_SIDEBAR_COLUMN_URI, &uri,
1919
 
                            PLACES_SIDEBAR_COLUMN_ROW_TYPE, &row_type,
1920
 
                            -1);
1921
 
 
1922
 
        if (uri != NULL) {
1923
 
                open_selected_uri (sidebar, uri, flags);
1924
 
                g_free (uri);
1925
 
        } else if (row_type == PLACES_CONNECT_SERVER) {
1926
 
                open_connect_to_server (sidebar);
1927
 
        } else {
1928
 
                open_selected_volume (sidebar, model, iter, flags);
1929
 
        }
1930
 
}
1931
 
 
1932
 
static void
1933
 
open_shortcut_from_menu (NautilusPlacesSidebar *sidebar,
1934
 
                         NautilusWindowOpenFlags               flags)
1935
 
{
1936
 
        GtkTreeModel *model;
1937
 
        GtkTreeIter iter;
1938
 
        GtkTreePath *path = NULL;
1939
 
 
1940
 
        model = gtk_tree_view_get_model (sidebar->tree_view);
1941
 
        gtk_tree_view_get_cursor (sidebar->tree_view, &path, NULL);
1942
 
 
1943
 
        if (path != NULL && gtk_tree_model_get_iter (model, &iter, path)) {
1944
 
                open_selected_bookmark (sidebar, model, &iter, flags);
1945
 
        }
1946
 
 
1947
 
        gtk_tree_path_free (path);
1948
 
}
1949
 
 
1950
 
static void
1951
 
open_shortcut_cb (GtkMenuItem           *item,
1952
 
                  NautilusPlacesSidebar *sidebar)
1953
 
{
1954
 
        open_shortcut_from_menu (sidebar, 0);
1955
 
}
1956
 
 
1957
 
static void
1958
 
open_shortcut_in_new_window_cb (GtkMenuItem           *item,
1959
 
                                NautilusPlacesSidebar *sidebar)
1960
 
{
1961
 
        open_shortcut_from_menu (sidebar, NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW);
1962
 
}
1963
 
 
1964
 
static void
1965
 
open_shortcut_in_new_tab_cb (GtkMenuItem              *item,
1966
 
                                NautilusPlacesSidebar *sidebar)
1967
 
{
1968
 
        open_shortcut_from_menu (sidebar, NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB);
1969
 
}
1970
 
 
1971
 
/* Add bookmark for the selected item */
1972
 
static void
1973
 
add_bookmark (NautilusPlacesSidebar *sidebar)
1974
 
{
1975
 
        GtkTreeModel *model;
1976
 
        GtkTreeIter iter;
1977
 
        char *uri;
1978
 
        char *name;
1979
 
        GFile *location;
1980
 
        NautilusBookmark *bookmark;
1981
 
 
1982
 
        model = gtk_tree_view_get_model (sidebar->tree_view);
1983
 
 
1984
 
        if (get_selected_iter (sidebar, &iter)) {
1985
 
                gtk_tree_model_get (model, &iter,
1986
 
                                    PLACES_SIDEBAR_COLUMN_URI, &uri,
1987
 
                                    PLACES_SIDEBAR_COLUMN_NAME, &name,
1988
 
                                    -1);
1989
 
 
1990
 
                if (uri == NULL) {
1991
 
                        return;
1992
 
                }
1993
 
 
1994
 
                location = g_file_new_for_uri (uri);
1995
 
                bookmark = nautilus_bookmark_new (location, name);
1996
 
                nautilus_bookmark_list_append (sidebar->bookmarks, bookmark);
1997
 
 
1998
 
                g_object_unref (location);
1999
 
                g_object_unref (bookmark);
2000
 
                g_free (uri);
2001
 
                g_free (name);
2002
 
        }
2003
 
}
2004
 
 
2005
 
static void
2006
 
add_shortcut_cb (GtkMenuItem           *item,
2007
 
                 NautilusPlacesSidebar *sidebar)
2008
 
{
2009
 
        add_bookmark (sidebar);
2010
 
}
2011
 
 
2012
 
/* Rename the selected bookmark */
2013
 
static void
2014
 
rename_selected_bookmark (NautilusPlacesSidebar *sidebar)
2015
 
{
2016
 
        GtkTreeIter iter;
2017
 
        GtkTreePath *path;
2018
 
        GtkTreeViewColumn *column;
2019
 
        GtkCellRenderer *cell;
2020
 
        GList *renderers;
2021
 
        PlaceType type;
2022
 
        
2023
 
        if (get_selected_iter (sidebar, &iter)) {
2024
 
                gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
2025
 
                                    PLACES_SIDEBAR_COLUMN_ROW_TYPE, &type,
2026
 
                                    -1);
2027
 
 
2028
 
                if (type != PLACES_BOOKMARK && type != PLACES_XDG_DIR) {
2029
 
                        return;
2030
 
                }
2031
 
 
2032
 
                path = gtk_tree_model_get_path (GTK_TREE_MODEL (sidebar->store), &iter);
2033
 
                column = gtk_tree_view_get_column (GTK_TREE_VIEW (sidebar->tree_view), 0);
2034
 
                renderers = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
2035
 
                cell = g_list_nth_data (renderers, 6);
2036
 
                g_list_free (renderers);
2037
 
                g_object_set (cell, "editable", TRUE, NULL);
2038
 
                gtk_tree_view_set_cursor_on_cell (GTK_TREE_VIEW (sidebar->tree_view),
2039
 
                                                path, column, cell, TRUE);
2040
 
                gtk_tree_path_free (path);
2041
 
        }
2042
 
}
2043
 
 
2044
 
static void
2045
 
rename_shortcut_cb (GtkMenuItem           *item,
2046
 
                    NautilusPlacesSidebar *sidebar)
2047
 
{
2048
 
        rename_selected_bookmark (sidebar);
2049
 
}
2050
 
 
2051
 
/* Removes the selected bookmarks */
2052
 
static void
2053
 
remove_selected_bookmarks (NautilusPlacesSidebar *sidebar)
2054
 
{
2055
 
        GtkTreeIter iter;
2056
 
        PlaceType type; 
2057
 
        int index;
2058
 
 
2059
 
        if (!get_selected_iter (sidebar, &iter)) {
2060
 
                return;
2061
 
        }
2062
 
        
2063
 
        gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
2064
 
                            PLACES_SIDEBAR_COLUMN_ROW_TYPE, &type,
2065
 
                            -1);
2066
 
 
2067
 
        if (type != PLACES_BOOKMARK) {
2068
 
                return;
2069
 
        }
2070
 
 
2071
 
        gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
2072
 
                            PLACES_SIDEBAR_COLUMN_INDEX, &index,
2073
 
                            -1);
2074
 
 
2075
 
        nautilus_bookmark_list_delete_item_at (sidebar->bookmarks, index);
2076
 
}
2077
 
 
2078
 
static void
2079
 
remove_shortcut_cb (GtkMenuItem           *item,
2080
 
                    NautilusPlacesSidebar *sidebar)
2081
 
{
2082
 
        remove_selected_bookmarks (sidebar);
2083
 
}
2084
 
 
2085
 
static void
2086
 
mount_shortcut_cb (GtkMenuItem           *item,
2087
 
                   NautilusPlacesSidebar *sidebar)
2088
 
{
2089
 
        GtkTreeIter iter;
2090
 
        GVolume *volume;
2091
 
 
2092
 
        if (!get_selected_iter (sidebar, &iter)) {
2093
 
                return;
2094
 
        }
2095
 
 
2096
 
        gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
2097
 
                            PLACES_SIDEBAR_COLUMN_VOLUME, &volume,
2098
 
                            -1);
2099
 
 
2100
 
        if (volume != NULL) {
2101
 
                nautilus_file_operations_mount_volume (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (sidebar))), volume);
2102
 
                g_object_unref (volume);
2103
 
        }
2104
 
}
2105
 
 
2106
 
static void
2107
 
unmount_done (gpointer data)
2108
 
{
2109
 
        NautilusWindow *window;
2110
 
 
2111
 
        window = data;
2112
 
        g_object_unref (window);
2113
 
}
2114
 
 
2115
 
static void
2116
 
show_unmount_progress_cb (GMountOperation *op,
2117
 
                          const gchar *message,
2118
 
                          gint64 time_left,
2119
 
                          gint64 bytes_left,
2120
 
                          gpointer user_data)
2121
 
{
2122
 
        NautilusApplication *app = NAUTILUS_APPLICATION (g_application_get_default ());
2123
 
 
2124
 
        if (bytes_left == 0) {
2125
 
                nautilus_application_notify_unmount_done (app, message);
2126
 
        } else {
2127
 
                nautilus_application_notify_unmount_show (app, message);
2128
 
        }
2129
 
}
2130
 
 
2131
 
static void
2132
 
show_unmount_progress_aborted_cb (GMountOperation *op,
2133
 
                                  gpointer user_data)
2134
 
{
2135
 
        NautilusApplication *app = NAUTILUS_APPLICATION (g_application_get_default ());
2136
 
        nautilus_application_notify_unmount_done (app, NULL);
2137
 
}
2138
 
 
2139
 
static GMountOperation *
2140
 
get_unmount_operation (NautilusPlacesSidebar *sidebar)
2141
 
{
2142
 
        GMountOperation *mount_op;
2143
 
 
2144
 
        mount_op = gtk_mount_operation_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (sidebar))));
2145
 
        g_signal_connect (mount_op, "show-unmount-progress",
2146
 
                          G_CALLBACK (show_unmount_progress_cb), sidebar);
2147
 
        g_signal_connect (mount_op, "aborted",
2148
 
                          G_CALLBACK (show_unmount_progress_aborted_cb), sidebar);
2149
 
 
2150
 
        return mount_op;
2151
 
}
2152
 
 
2153
 
static void
2154
 
do_unmount (GMount *mount,
2155
 
            NautilusPlacesSidebar *sidebar)
2156
 
{
2157
 
        GMountOperation *mount_op;
2158
 
 
2159
 
        if (mount != NULL) {
2160
 
                mount_op = get_unmount_operation (sidebar);
2161
 
                nautilus_file_operations_unmount_mount_full (NULL, mount, mount_op, FALSE, TRUE,
2162
 
                                                             unmount_done,
2163
 
                                                             g_object_ref (sidebar->window));
2164
 
                g_object_unref (mount_op);
2165
 
        }
2166
 
}
2167
 
 
2168
 
static void
2169
 
do_unmount_selection (NautilusPlacesSidebar *sidebar)
2170
 
{
2171
 
        GtkTreeIter iter;
2172
 
        GMount *mount;
2173
 
 
2174
 
        if (!get_selected_iter (sidebar, &iter)) {
2175
 
                return;
2176
 
        }
2177
 
 
2178
 
        gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
2179
 
                            PLACES_SIDEBAR_COLUMN_MOUNT, &mount,
2180
 
                            -1);
2181
 
 
2182
 
        if (mount != NULL) {
2183
 
                do_unmount (mount, sidebar);
2184
 
                g_object_unref (mount);
2185
 
        }
2186
 
}
2187
 
 
2188
 
static void
2189
 
unmount_shortcut_cb (GtkMenuItem           *item,
2190
 
                     NautilusPlacesSidebar *sidebar)
2191
 
{
2192
 
        do_unmount_selection (sidebar);
2193
 
}
2194
 
 
2195
 
static void
2196
 
drive_eject_cb (GObject *source_object,
2197
 
                GAsyncResult *res,
2198
 
                gpointer user_data)
2199
 
{
2200
 
        NautilusWindow *window;
2201
 
        GError *error;
2202
 
        char *primary;
2203
 
        char *name;
2204
 
 
2205
 
        window = user_data;
2206
 
        g_object_unref (window);
2207
 
 
2208
 
        error = NULL;
2209
 
        if (!g_drive_eject_with_operation_finish (G_DRIVE (source_object), res, &error)) {
2210
 
                if (error->code != G_IO_ERROR_FAILED_HANDLED) {
2211
 
                        name = g_drive_get_name (G_DRIVE (source_object));
2212
 
                        primary = g_strdup_printf (_("Unable to eject %s"), name);
2213
 
                        g_free (name);
2214
 
                        eel_show_error_dialog (primary,
2215
 
                                               error->message,
2216
 
                                       NULL);
2217
 
                        g_free (primary);
2218
 
                }
2219
 
                g_error_free (error);
2220
 
        }
2221
 
}
2222
 
 
2223
 
static void
2224
 
volume_eject_cb (GObject *source_object,
2225
 
                GAsyncResult *res,
2226
 
                gpointer user_data)
2227
 
{
2228
 
        NautilusWindow *window;
2229
 
        GError *error;
2230
 
        char *primary;
2231
 
        char *name;
2232
 
 
2233
 
        window = user_data;
2234
 
        g_object_unref (window);
2235
 
 
2236
 
        error = NULL;
2237
 
        if (!g_volume_eject_with_operation_finish (G_VOLUME (source_object), res, &error)) {
2238
 
                if (error->code != G_IO_ERROR_FAILED_HANDLED) {
2239
 
                        name = g_volume_get_name (G_VOLUME (source_object));
2240
 
                        primary = g_strdup_printf (_("Unable to eject %s"), name);
2241
 
                        g_free (name);
2242
 
                        eel_show_error_dialog (primary,
2243
 
                                               error->message,
2244
 
                                               NULL);
2245
 
                        g_free (primary);
2246
 
                }
2247
 
                g_error_free (error);
2248
 
        }
2249
 
}
2250
 
 
2251
 
static void
2252
 
mount_eject_cb (GObject *source_object,
2253
 
                GAsyncResult *res,
2254
 
                gpointer user_data)
2255
 
{
2256
 
        NautilusWindow *window;
2257
 
        GError *error;
2258
 
        char *primary;
2259
 
        char *name;
2260
 
 
2261
 
        window = user_data;
2262
 
        g_object_unref (window);
2263
 
 
2264
 
        error = NULL;
2265
 
        if (!g_mount_eject_with_operation_finish (G_MOUNT (source_object), res, &error)) {
2266
 
                if (error->code != G_IO_ERROR_FAILED_HANDLED) {
2267
 
                        name = g_mount_get_name (G_MOUNT (source_object));
2268
 
                        primary = g_strdup_printf (_("Unable to eject %s"), name);
2269
 
                        g_free (name);
2270
 
                        eel_show_error_dialog (primary,
2271
 
                                               error->message,
2272
 
                                               NULL);
2273
 
                        g_free (primary);
2274
 
                }
2275
 
                g_error_free (error);
2276
 
        }
2277
 
}
2278
 
 
2279
 
static void
2280
 
do_eject (GMount *mount,
2281
 
          GVolume *volume,
2282
 
          GDrive *drive,
2283
 
          NautilusPlacesSidebar *sidebar)
2284
 
{
2285
 
        GMountOperation *mount_op = get_unmount_operation (sidebar);
2286
 
 
2287
 
        if (mount != NULL) {
2288
 
                g_mount_eject_with_operation (mount, 0, mount_op, NULL, mount_eject_cb,
2289
 
                                              g_object_ref (sidebar->window));
2290
 
        } else if (volume != NULL) {
2291
 
                g_volume_eject_with_operation (volume, 0, mount_op, NULL, volume_eject_cb,
2292
 
                                              g_object_ref (sidebar->window));
2293
 
        } else if (drive != NULL) {
2294
 
                g_drive_eject_with_operation (drive, 0, mount_op, NULL, drive_eject_cb,
2295
 
                                              g_object_ref (sidebar->window));
2296
 
        }
2297
 
 
2298
 
        g_object_unref (mount_op);
2299
 
}
2300
 
 
2301
 
static void
2302
 
eject_shortcut_cb (GtkMenuItem           *item,
2303
 
                   NautilusPlacesSidebar *sidebar)
2304
 
{
2305
 
        GtkTreeIter iter;
2306
 
        GMount *mount;
2307
 
        GVolume *volume;
2308
 
        GDrive *drive;
2309
 
 
2310
 
        if (!get_selected_iter (sidebar, &iter)) {
2311
 
                return;
2312
 
        }
2313
 
 
2314
 
        gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
2315
 
                            PLACES_SIDEBAR_COLUMN_MOUNT, &mount,
2316
 
                            PLACES_SIDEBAR_COLUMN_VOLUME, &volume,
2317
 
                            PLACES_SIDEBAR_COLUMN_DRIVE, &drive,
2318
 
                            -1);
2319
 
 
2320
 
        do_eject (mount, volume, drive, sidebar);
2321
 
}
2322
 
 
2323
 
static gboolean
2324
 
eject_or_unmount_bookmark (NautilusPlacesSidebar *sidebar,
2325
 
                           GtkTreePath *path)
2326
 
{
2327
 
        GtkTreeModel *model;
2328
 
        GtkTreeIter iter;
2329
 
        gboolean can_unmount, can_eject;
2330
 
        GMount *mount;
2331
 
        GVolume *volume;
2332
 
        GDrive *drive;
2333
 
        gboolean ret;
2334
 
 
2335
 
        model = GTK_TREE_MODEL (sidebar->store);
2336
 
 
2337
 
        if (!path) {
2338
 
                return FALSE;
2339
 
        }
2340
 
        if (!gtk_tree_model_get_iter (model, &iter, path)) {
2341
 
                return FALSE;
2342
 
        }
2343
 
 
2344
 
        gtk_tree_model_get (model, &iter,
2345
 
                            PLACES_SIDEBAR_COLUMN_MOUNT, &mount,
2346
 
                            PLACES_SIDEBAR_COLUMN_VOLUME, &volume,
2347
 
                            PLACES_SIDEBAR_COLUMN_DRIVE, &drive,
2348
 
                            -1);
2349
 
 
2350
 
        ret = FALSE;
2351
 
 
2352
 
        check_unmount_and_eject (mount, volume, drive, &can_unmount, &can_eject);
2353
 
        /* if we can eject, it has priority over unmount */
2354
 
        if (can_eject) {
2355
 
                do_eject (mount, volume, drive, sidebar);
2356
 
                ret = TRUE;
2357
 
        } else if (can_unmount) {
2358
 
                do_unmount (mount, sidebar);
2359
 
                ret = TRUE;
2360
 
        }
2361
 
 
2362
 
        if (mount != NULL)
2363
 
                g_object_unref (mount);
2364
 
        if (volume != NULL)
2365
 
                g_object_unref (volume);
2366
 
        if (drive != NULL)
2367
 
                g_object_unref (drive);
2368
 
 
2369
 
        return ret;
2370
 
}
2371
 
 
2372
 
static gboolean
2373
 
eject_or_unmount_selection (NautilusPlacesSidebar *sidebar)
2374
 
{
2375
 
        GtkTreeIter iter;
2376
 
        GtkTreePath *path;
2377
 
        gboolean ret;
2378
 
 
2379
 
        if (!get_selected_iter (sidebar, &iter)) {
2380
 
                return FALSE;
2381
 
        }
2382
 
 
2383
 
        path = gtk_tree_model_get_path (GTK_TREE_MODEL (sidebar->store), &iter);
2384
 
        if (path == NULL) {
2385
 
                return FALSE;
2386
 
        }
2387
 
 
2388
 
        ret = eject_or_unmount_bookmark (sidebar, path);
2389
 
 
2390
 
        gtk_tree_path_free (path);
2391
 
 
2392
 
        return ret;
2393
 
}
2394
 
 
2395
 
static void
2396
 
drive_poll_for_media_cb (GObject *source_object,
2397
 
                         GAsyncResult *res,
2398
 
                         gpointer user_data)
2399
 
{
2400
 
        GError *error;
2401
 
        char *primary;
2402
 
        char *name;
2403
 
 
2404
 
        error = NULL;
2405
 
        if (!g_drive_poll_for_media_finish (G_DRIVE (source_object), res, &error)) {
2406
 
                if (error->code != G_IO_ERROR_FAILED_HANDLED) {
2407
 
                        name = g_drive_get_name (G_DRIVE (source_object));
2408
 
                        primary = g_strdup_printf (_("Unable to poll %s for media changes"), name);
2409
 
                        g_free (name);
2410
 
                        eel_show_error_dialog (primary,
2411
 
                                               error->message,
2412
 
                                               NULL);
2413
 
                        g_free (primary);
2414
 
                }
2415
 
                g_error_free (error);
2416
 
        }
2417
 
}
2418
 
 
2419
 
static void
2420
 
rescan_shortcut_cb (GtkMenuItem           *item,
2421
 
                    NautilusPlacesSidebar *sidebar)
2422
 
{
2423
 
        GtkTreeIter iter;
2424
 
        GDrive  *drive;
2425
 
 
2426
 
        if (!get_selected_iter (sidebar, &iter)) {
2427
 
                return;
2428
 
        }
2429
 
 
2430
 
        gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
2431
 
                            PLACES_SIDEBAR_COLUMN_DRIVE, &drive,
2432
 
                            -1);
2433
 
 
2434
 
        if (drive != NULL) {
2435
 
                g_drive_poll_for_media (drive, NULL, drive_poll_for_media_cb, NULL);
2436
 
        }
2437
 
        g_object_unref (drive);
2438
 
}
2439
 
 
2440
 
static void
2441
 
drive_start_cb (GObject      *source_object,
2442
 
                GAsyncResult *res,
2443
 
                gpointer      user_data)
2444
 
{
2445
 
        GError *error;
2446
 
        char *primary;
2447
 
        char *name;
2448
 
 
2449
 
        error = NULL;
2450
 
        if (!g_drive_poll_for_media_finish (G_DRIVE (source_object), res, &error)) {
2451
 
                if (error->code != G_IO_ERROR_FAILED_HANDLED) {
2452
 
                        name = g_drive_get_name (G_DRIVE (source_object));
2453
 
                        primary = g_strdup_printf (_("Unable to start %s"), name);
2454
 
                        g_free (name);
2455
 
                        eel_show_error_dialog (primary,
2456
 
                                               error->message,
2457
 
                                               NULL);
2458
 
                        g_free (primary);
2459
 
                }
2460
 
                g_error_free (error);
2461
 
        }
2462
 
}
2463
 
 
2464
 
static void
2465
 
start_shortcut_cb (GtkMenuItem           *item,
2466
 
                   NautilusPlacesSidebar *sidebar)
2467
 
{
2468
 
        GtkTreeIter iter;
2469
 
        GDrive  *drive;
2470
 
 
2471
 
        if (!get_selected_iter (sidebar, &iter)) {
2472
 
                return;
2473
 
        }
2474
 
 
2475
 
        gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
2476
 
                            PLACES_SIDEBAR_COLUMN_DRIVE, &drive,
2477
 
                            -1);
2478
 
 
2479
 
        if (drive != NULL) {
2480
 
                GMountOperation *mount_op;
2481
 
 
2482
 
                mount_op = gtk_mount_operation_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (sidebar))));
2483
 
 
2484
 
                g_drive_start (drive, G_DRIVE_START_NONE, mount_op, NULL, drive_start_cb, NULL);
2485
 
 
2486
 
                g_object_unref (mount_op);
2487
 
        }
2488
 
        g_object_unref (drive);
2489
 
}
2490
 
 
2491
 
static void
2492
 
drive_stop_cb (GObject *source_object,
2493
 
               GAsyncResult *res,
2494
 
               gpointer user_data)
2495
 
{
2496
 
        NautilusWindow *window;
2497
 
        GError *error;
2498
 
        char *primary;
2499
 
        char *name;
2500
 
 
2501
 
        window = user_data;
2502
 
        g_object_unref (window);
2503
 
 
2504
 
        error = NULL;
2505
 
        if (!g_drive_poll_for_media_finish (G_DRIVE (source_object), res, &error)) {
2506
 
                if (error->code != G_IO_ERROR_FAILED_HANDLED) {
2507
 
                        name = g_drive_get_name (G_DRIVE (source_object));
2508
 
                        primary = g_strdup_printf (_("Unable to stop %s"), name);
2509
 
                        g_free (name);
2510
 
                        eel_show_error_dialog (primary,
2511
 
                                               error->message,
2512
 
                                               NULL);
2513
 
                        g_free (primary);
2514
 
                }
2515
 
                g_error_free (error);
2516
 
        }
2517
 
}
2518
 
 
2519
 
static void
2520
 
stop_shortcut_cb (GtkMenuItem           *item,
2521
 
                  NautilusPlacesSidebar *sidebar)
2522
 
{
2523
 
        GtkTreeIter iter;
2524
 
        GDrive  *drive;
2525
 
 
2526
 
        if (!get_selected_iter (sidebar, &iter)) {
2527
 
                return;
2528
 
        }
2529
 
 
2530
 
        gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
2531
 
                            PLACES_SIDEBAR_COLUMN_DRIVE, &drive,
2532
 
                            -1);
2533
 
 
2534
 
        if (drive != NULL) {
2535
 
                GMountOperation *mount_op = get_unmount_operation (sidebar);
2536
 
                g_drive_stop (drive, G_MOUNT_UNMOUNT_NONE, mount_op, NULL, drive_stop_cb,
2537
 
                              g_object_ref (sidebar->window));
2538
 
                g_object_unref (mount_op);
2539
 
        }
2540
 
        g_object_unref (drive);
2541
 
}
2542
 
 
2543
 
static void
2544
 
format_shortcut_cb (GtkMenuItem           *item,
2545
 
                    NautilusPlacesSidebar *sidebar)
2546
 
{
2547
 
        GAppInfo *app_info;
2548
 
        gchar *cmdline, *device_identifier, *xid_string;
2549
 
        GVolume *volume;
2550
 
        GtkTreeIter iter;
2551
 
        gint xid;
2552
 
 
2553
 
        if (!get_selected_iter (sidebar, &iter)) {
2554
 
                return;
2555
 
        }
2556
 
 
2557
 
        gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
2558
 
                            PLACES_SIDEBAR_COLUMN_VOLUME, &volume,
2559
 
                            -1);
2560
 
 
2561
 
        if (!volume) {
2562
 
                return;
2563
 
        }
2564
 
 
2565
 
        device_identifier = g_volume_get_identifier (volume, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
2566
 
        xid = (gint) gdk_x11_window_get_xid (gtk_widget_get_window (GTK_WIDGET (sidebar->window)));
2567
 
        xid_string = g_strdup_printf ("%d", xid);
2568
 
 
2569
 
        cmdline = g_strconcat ("gnome-disks ",
2570
 
                               "--block-device ", device_identifier, " ",
2571
 
                               "--format-device ",
2572
 
                               "--xid ", xid_string,
2573
 
                               NULL);
2574
 
        app_info = g_app_info_create_from_commandline (cmdline, NULL, 0, NULL);
2575
 
        g_app_info_launch (app_info, NULL, NULL, NULL);
2576
 
 
2577
 
        g_free (cmdline);
2578
 
        g_free (device_identifier);
2579
 
        g_free (xid_string);
2580
 
        g_clear_object (&volume);
2581
 
        g_clear_object (&app_info);
2582
 
}
2583
 
 
2584
 
static void
2585
 
empty_trash_cb (GtkMenuItem           *item,
2586
 
                NautilusPlacesSidebar *sidebar)
2587
 
{
2588
 
        nautilus_file_operations_empty_trash (GTK_WIDGET (sidebar->window));
2589
 
}
2590
 
 
2591
 
static gboolean
2592
 
find_prev_or_next_row (NautilusPlacesSidebar *sidebar,
2593
 
                       GtkTreeIter *iter,
2594
 
                       gboolean go_up)
2595
 
{
2596
 
        GtkTreeModel *model = GTK_TREE_MODEL (sidebar->store);
2597
 
        gboolean res;
2598
 
        int place_type;
2599
 
 
2600
 
        if (go_up) {
2601
 
                res = gtk_tree_model_iter_previous (model, iter);
2602
 
        } else {
2603
 
                res = gtk_tree_model_iter_next (model, iter);
2604
 
        }
2605
 
 
2606
 
        if (res) {
2607
 
                gtk_tree_model_get (model, iter,
2608
 
                                    PLACES_SIDEBAR_COLUMN_ROW_TYPE, &place_type,
2609
 
                                    -1);
2610
 
                if (place_type == PLACES_HEADING) {
2611
 
                        if (go_up) {
2612
 
                                res = gtk_tree_model_iter_previous (model, iter);
2613
 
                        } else {
2614
 
                                res = gtk_tree_model_iter_next (model, iter);
2615
 
                        }
2616
 
                }
2617
 
        }
2618
 
 
2619
 
        return res;
2620
 
}
2621
 
 
2622
 
static gboolean
2623
 
find_prev_row (NautilusPlacesSidebar *sidebar, GtkTreeIter *iter)
2624
 
{
2625
 
        return find_prev_or_next_row (sidebar, iter, TRUE);
2626
 
}
2627
 
 
2628
 
static gboolean
2629
 
find_next_row (NautilusPlacesSidebar *sidebar, GtkTreeIter *iter)
2630
 
{
2631
 
        return find_prev_or_next_row (sidebar, iter, FALSE);
2632
 
}
2633
 
 
2634
 
static void
2635
 
properties_cb (GtkMenuItem           *item,
2636
 
               NautilusPlacesSidebar *sidebar)
2637
 
{
2638
 
        GtkTreeModel *model;
2639
 
        GtkTreePath *path = NULL;
2640
 
        GtkTreeIter iter;
2641
 
        GList *list;
2642
 
        NautilusFile *file;
2643
 
        char *uri;
2644
 
 
2645
 
        model = gtk_tree_view_get_model (sidebar->tree_view);
2646
 
        gtk_tree_view_get_cursor (sidebar->tree_view, &path, NULL);
2647
 
 
2648
 
        if (path == NULL || !gtk_tree_model_get_iter (model, &iter, path)) {
2649
 
                gtk_tree_path_free (path);
2650
 
                return;
2651
 
        }
2652
 
 
2653
 
        gtk_tree_model_get (model, &iter, PLACES_SIDEBAR_COLUMN_URI, &uri, -1);
2654
 
 
2655
 
        if (uri != NULL) {
2656
 
 
2657
 
                file = nautilus_file_get_by_uri (uri);
2658
 
                list = g_list_prepend (NULL, nautilus_file_ref (file));
2659
 
 
2660
 
                nautilus_properties_window_present (list, GTK_WIDGET (sidebar), NULL);
2661
 
 
2662
 
                nautilus_file_list_free (list);
2663
 
                g_free (uri);
2664
 
        }
2665
 
 
2666
 
        gtk_tree_path_free (path);
2667
 
}
2668
 
 
2669
 
static gboolean
2670
 
nautilus_places_sidebar_focus (GtkWidget *widget,
2671
 
                               GtkDirectionType direction)
2672
 
{
2673
 
        NautilusPlacesSidebar *sidebar = NAUTILUS_PLACES_SIDEBAR (widget);
2674
 
        GtkTreePath *path;
2675
 
        GtkTreeIter iter;
2676
 
        gboolean res;
2677
 
 
2678
 
        res = get_selected_iter (sidebar, &iter);
2679
 
 
2680
 
        if (!res) {
2681
 
                gtk_tree_model_get_iter_first (GTK_TREE_MODEL (sidebar->store), &iter);
2682
 
                res = find_next_row (sidebar, &iter);
2683
 
                if (res) {
2684
 
                        path = gtk_tree_model_get_path (GTK_TREE_MODEL (sidebar->store), &iter);
2685
 
                        gtk_tree_view_set_cursor (sidebar->tree_view, path, NULL, FALSE);
2686
 
                        gtk_tree_path_free (path);
2687
 
                }
2688
 
        }
2689
 
 
2690
 
        return GTK_WIDGET_CLASS (nautilus_places_sidebar_parent_class)->focus (widget, direction);
2691
 
}
2692
 
 
2693
 
/* Handler for GtkWidget::key-press-event on the shortcuts list */
2694
 
static gboolean
2695
 
bookmarks_key_press_event_cb (GtkWidget             *widget,
2696
 
                              GdkEventKey           *event,
2697
 
                              NautilusPlacesSidebar *sidebar)
2698
 
{
2699
 
  guint modifiers;
2700
 
  GtkTreeIter selected_iter;
2701
 
  GtkTreePath *path;
2702
 
 
2703
 
  if (!get_selected_iter (sidebar, &selected_iter)) {
2704
 
          return FALSE;
2705
 
  }
2706
 
 
2707
 
  modifiers = gtk_accelerator_get_default_mod_mask ();
2708
 
 
2709
 
  if ((event->keyval == GDK_KEY_Return ||
2710
 
       event->keyval == GDK_KEY_KP_Enter ||
2711
 
       event->keyval == GDK_KEY_ISO_Enter ||
2712
 
       event->keyval == GDK_KEY_space)) {
2713
 
      NautilusWindowOpenFlags flags = 0;
2714
 
 
2715
 
      if ((event->state & modifiers) == GDK_SHIFT_MASK) {
2716
 
          flags = NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB;
2717
 
      } else if ((event->state & modifiers) == GDK_CONTROL_MASK) {
2718
 
          flags = NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW;
2719
 
      }
2720
 
 
2721
 
      open_selected_bookmark (sidebar, GTK_TREE_MODEL (sidebar->store),
2722
 
                              &selected_iter, flags);
2723
 
      return TRUE;
2724
 
  }
2725
 
 
2726
 
  if (event->keyval == GDK_KEY_Down &&
2727
 
      (event->state & modifiers) == GDK_MOD1_MASK) {
2728
 
      return eject_or_unmount_selection (sidebar);
2729
 
  }
2730
 
 
2731
 
  if (event->keyval == GDK_KEY_Up) {
2732
 
      if (find_prev_row (sidebar, &selected_iter)) {
2733
 
              path = gtk_tree_model_get_path (GTK_TREE_MODEL (sidebar->store), &selected_iter);
2734
 
              gtk_tree_view_set_cursor (sidebar->tree_view, path, NULL, FALSE);
2735
 
              gtk_tree_path_free (path);
2736
 
      }
2737
 
      return TRUE;
2738
 
  }
2739
 
 
2740
 
  if (event->keyval == GDK_KEY_Down) {
2741
 
      if (find_next_row (sidebar, &selected_iter)) {
2742
 
              path = gtk_tree_model_get_path (GTK_TREE_MODEL (sidebar->store), &selected_iter);
2743
 
              gtk_tree_view_set_cursor (sidebar->tree_view, path, NULL, FALSE);
2744
 
              gtk_tree_path_free (path);
2745
 
      }
2746
 
      return TRUE;
2747
 
  }
2748
 
 
2749
 
  if ((event->keyval == GDK_KEY_Delete
2750
 
      || event->keyval == GDK_KEY_KP_Delete)
2751
 
      && (event->state & modifiers) == 0) {
2752
 
      remove_selected_bookmarks (sidebar);
2753
 
      return TRUE;
2754
 
  }
2755
 
 
2756
 
  if ((event->keyval == GDK_KEY_F2)
2757
 
      && (event->state & modifiers) == 0) {
2758
 
      rename_selected_bookmark (sidebar);
2759
 
      return TRUE;
2760
 
  }
2761
 
 
2762
 
  return FALSE;
2763
 
}
2764
 
 
2765
 
/* Constructs the popup menu for the file list if needed */
2766
 
static void
2767
 
bookmarks_build_popup_menu (NautilusPlacesSidebar *sidebar)
2768
 
{
2769
 
        GtkWidget *item;
2770
 
        
2771
 
        if (sidebar->popup_menu) {
2772
 
                return;
2773
 
        }
2774
 
 
2775
 
        sidebar->popup_menu = gtk_menu_new ();
2776
 
        gtk_menu_attach_to_widget (GTK_MENU (sidebar->popup_menu),
2777
 
                                   GTK_WIDGET (sidebar),
2778
 
                                   bookmarks_popup_menu_detach_cb);
2779
 
        
2780
 
        item = gtk_image_menu_item_new_with_mnemonic (_("_Open"));
2781
 
        gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),
2782
 
                                       gtk_image_new_from_stock (GTK_STOCK_OPEN, GTK_ICON_SIZE_MENU));
2783
 
        g_signal_connect (item, "activate",
2784
 
                          G_CALLBACK (open_shortcut_cb), sidebar);
2785
 
        gtk_widget_show (item);
2786
 
        gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
2787
 
 
2788
 
        item = gtk_menu_item_new_with_mnemonic (_("Open in New _Tab"));
2789
 
        sidebar->popup_menu_open_in_new_tab_item = item;
2790
 
        g_signal_connect (item, "activate",
2791
 
                          G_CALLBACK (open_shortcut_in_new_tab_cb), sidebar);
2792
 
        gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
2793
 
        gtk_widget_show (item);
2794
 
 
2795
 
        item = gtk_menu_item_new_with_mnemonic (_("Open in New _Window"));
2796
 
        g_signal_connect (item, "activate",
2797
 
                          G_CALLBACK (open_shortcut_in_new_window_cb), sidebar);
2798
 
        gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
2799
 
        gtk_widget_show (item);
2800
 
 
2801
 
        eel_gtk_menu_append_separator (GTK_MENU (sidebar->popup_menu));
2802
 
 
2803
 
        item = gtk_menu_item_new_with_mnemonic (_("_Add Bookmark"));
2804
 
        sidebar->popup_menu_add_shortcut_item = item;
2805
 
        g_signal_connect (item, "activate",
2806
 
                          G_CALLBACK (add_shortcut_cb), sidebar);
2807
 
        gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
2808
 
 
2809
 
        item = gtk_image_menu_item_new_with_label (_("Remove"));
2810
 
        sidebar->popup_menu_remove_item = item;
2811
 
        gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),
2812
 
                                 gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU));
2813
 
        g_signal_connect (item, "activate",
2814
 
                    G_CALLBACK (remove_shortcut_cb), sidebar);
2815
 
        gtk_widget_show (item);
2816
 
        gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
2817
 
        
2818
 
        item = gtk_menu_item_new_with_label (_("Renameā€¦"));
2819
 
        sidebar->popup_menu_rename_item = item;
2820
 
        g_signal_connect (item, "activate",
2821
 
                    G_CALLBACK (rename_shortcut_cb), sidebar);
2822
 
        gtk_widget_show (item);
2823
 
        gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
2824
 
        
2825
 
        /* Mount/Unmount/Eject menu items */
2826
 
 
2827
 
        sidebar->popup_menu_separator_item =
2828
 
                GTK_WIDGET (eel_gtk_menu_append_separator (GTK_MENU (sidebar->popup_menu)));
2829
 
 
2830
 
        item = gtk_menu_item_new_with_mnemonic (_("_Mount"));
2831
 
        sidebar->popup_menu_mount_item = item;
2832
 
        g_signal_connect (item, "activate",
2833
 
                    G_CALLBACK (mount_shortcut_cb), sidebar);
2834
 
        gtk_widget_show (item);
2835
 
        gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
2836
 
 
2837
 
        item = gtk_menu_item_new_with_mnemonic (_("_Unmount"));
2838
 
        sidebar->popup_menu_unmount_item = item;
2839
 
        g_signal_connect (item, "activate",
2840
 
                    G_CALLBACK (unmount_shortcut_cb), sidebar);
2841
 
        gtk_widget_show (item);
2842
 
        gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
2843
 
 
2844
 
        item = gtk_menu_item_new_with_mnemonic (_("_Eject"));
2845
 
        sidebar->popup_menu_eject_item = item;
2846
 
        g_signal_connect (item, "activate",
2847
 
                    G_CALLBACK (eject_shortcut_cb), sidebar);
2848
 
        gtk_widget_show (item);
2849
 
        gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
2850
 
 
2851
 
        item = gtk_menu_item_new_with_mnemonic (_("_Detect Media"));
2852
 
        sidebar->popup_menu_rescan_item = item;
2853
 
        g_signal_connect (item, "activate",
2854
 
                    G_CALLBACK (rescan_shortcut_cb), sidebar);
2855
 
        gtk_widget_show (item);
2856
 
        gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
2857
 
 
2858
 
        item = gtk_menu_item_new_with_mnemonic (_("_Start"));
2859
 
        sidebar->popup_menu_start_item = item;
2860
 
        g_signal_connect (item, "activate",
2861
 
                          G_CALLBACK (start_shortcut_cb), sidebar);
2862
 
        gtk_widget_show (item);
2863
 
        gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
2864
 
 
2865
 
        item = gtk_menu_item_new_with_mnemonic (_("_Stop"));
2866
 
        sidebar->popup_menu_stop_item = item;
2867
 
        g_signal_connect (item, "activate",
2868
 
                          G_CALLBACK (stop_shortcut_cb), sidebar);
2869
 
        gtk_widget_show (item);
2870
 
        gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
2871
 
 
2872
 
        item = gtk_menu_item_new_with_mnemonic (_("_Formatā€¦"));
2873
 
        sidebar->popup_menu_format_item = item;
2874
 
        g_signal_connect (item, "activate",
2875
 
                          G_CALLBACK (format_shortcut_cb), sidebar);
2876
 
        gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
2877
 
 
2878
 
        /* Empty Trash menu item */
2879
 
 
2880
 
        item = gtk_menu_item_new_with_mnemonic (_("Empty _Trash"));
2881
 
        sidebar->popup_menu_empty_trash_item = item;
2882
 
        g_signal_connect (item, "activate",
2883
 
                    G_CALLBACK (empty_trash_cb), sidebar);
2884
 
        gtk_widget_show (item);
2885
 
        gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
2886
 
 
2887
 
        /* Properties menu item */
2888
 
 
2889
 
        sidebar->popup_menu_properties_separator_item =
2890
 
                GTK_WIDGET (eel_gtk_menu_append_separator (GTK_MENU (sidebar->popup_menu)));
2891
 
 
2892
 
        item = gtk_menu_item_new_with_mnemonic (_("_Properties"));
2893
 
        sidebar->popup_menu_properties_item = item;
2894
 
        g_signal_connect (item, "activate",
2895
 
                          G_CALLBACK (properties_cb), sidebar);
2896
 
        gtk_widget_show (item);
2897
 
        gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
2898
 
 
2899
 
        bookmarks_check_popup_sensitivity (sidebar);
2900
 
}
2901
 
 
2902
 
static void
2903
 
bookmarks_popup_menu (NautilusPlacesSidebar *sidebar,
2904
 
                      GdkEventButton        *event)
2905
 
{
2906
 
        bookmarks_build_popup_menu (sidebar);
2907
 
        eel_pop_up_context_menu (GTK_MENU(sidebar->popup_menu),
2908
 
                                 event);
2909
 
}
2910
 
 
2911
 
/* Callback used for the GtkWidget::popup-menu signal of the shortcuts list */
2912
 
static gboolean
2913
 
bookmarks_popup_menu_cb (GtkWidget *widget,
2914
 
                         NautilusPlacesSidebar *sidebar)
2915
 
{
2916
 
        bookmarks_popup_menu (sidebar, NULL);
2917
 
        return TRUE;
2918
 
}
2919
 
 
2920
 
static void
2921
 
bookmarks_row_activated_cb (GtkWidget *widget,
2922
 
                            GtkTreePath *path,
2923
 
                            GtkTreeViewColumn *column,
2924
 
                            NautilusPlacesSidebar *sidebar)
2925
 
{
2926
 
        GtkTreeIter iter;
2927
 
        GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget));
2928
 
 
2929
 
        if (!gtk_tree_model_get_iter (model, &iter, path)) {
2930
 
                return;
2931
 
        }
2932
 
 
2933
 
        open_selected_bookmark (sidebar, model, &iter, 0);
2934
 
}
2935
 
 
2936
 
static gboolean
2937
 
bookmarks_button_release_event_cb (GtkWidget *widget,
2938
 
                                   GdkEventButton *event,
2939
 
                                   NautilusPlacesSidebar *sidebar)
2940
 
{
2941
 
        GtkTreePath *path;
2942
 
        GtkTreeIter iter;
2943
 
        GtkTreeModel *model;
2944
 
        GtkTreeView *tree_view;
2945
 
        gboolean ret = FALSE;
2946
 
        gboolean res;
2947
 
 
2948
 
        path = NULL;
2949
 
 
2950
 
        if (event->type != GDK_BUTTON_RELEASE) {
2951
 
                return TRUE;
2952
 
        }
2953
 
 
2954
 
        if (clicked_eject_button (sidebar, &path)) {
2955
 
                eject_or_unmount_bookmark (sidebar, path);
2956
 
                gtk_tree_path_free (path);
2957
 
 
2958
 
                return FALSE;
2959
 
        }
2960
 
 
2961
 
        if (event->button == 1) {
2962
 
                return FALSE;
2963
 
        }
2964
 
 
2965
 
        tree_view = GTK_TREE_VIEW (widget);
2966
 
        model = gtk_tree_view_get_model (tree_view);
2967
 
 
2968
 
        if (event->window != gtk_tree_view_get_bin_window (tree_view)) {
2969
 
                return FALSE;
2970
 
        }
2971
 
 
2972
 
        res = gtk_tree_view_get_path_at_pos (tree_view, (int) event->x, (int) event->y,
2973
 
                                             &path, NULL, NULL, NULL);
2974
 
 
2975
 
        if (!res || path == NULL) {
2976
 
                return FALSE;
2977
 
        }
2978
 
 
2979
 
        res = gtk_tree_model_get_iter (model, &iter, path);
2980
 
        if (!res) {
2981
 
                gtk_tree_path_free (path);
2982
 
                return FALSE;
2983
 
        }
2984
 
 
2985
 
        if (event->button == 2) {
2986
 
                NautilusWindowOpenFlags flags = 0;
2987
 
 
2988
 
                flags = (event->state & GDK_CONTROL_MASK) ?
2989
 
                        NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW :
2990
 
                        NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB;
2991
 
 
2992
 
                open_selected_bookmark (sidebar, model, &iter, flags);
2993
 
                ret = TRUE;
2994
 
        } else if (event->button == 3) {
2995
 
                PlaceType row_type;
2996
 
 
2997
 
                gtk_tree_model_get (model, &iter,
2998
 
                                    PLACES_SIDEBAR_COLUMN_ROW_TYPE, &row_type,
2999
 
                                    -1);
3000
 
 
3001
 
                if (row_type != PLACES_HEADING &&
3002
 
                    row_type != PLACES_CONNECT_SERVER) {
3003
 
                        bookmarks_popup_menu (sidebar, event);
3004
 
                }
3005
 
        }
3006
 
 
3007
 
        gtk_tree_path_free (path);
3008
 
 
3009
 
        return ret;
3010
 
}
3011
 
 
3012
 
static void
3013
 
bookmarks_edited (GtkCellRenderer       *cell,
3014
 
                  gchar                 *path_string,
3015
 
                  gchar                 *new_text,
3016
 
                  NautilusPlacesSidebar *sidebar)
3017
 
{
3018
 
        GtkTreePath *path;
3019
 
        GtkTreeIter iter;
3020
 
        gchar *uri;
3021
 
        GFile *location;
3022
 
        NautilusBookmark *bookmark;
3023
 
        PlaceType type;
3024
 
 
3025
 
        g_object_set (cell, "editable", FALSE, NULL);
3026
 
        
3027
 
        path = gtk_tree_path_new_from_string (path_string);
3028
 
        if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (sidebar->store), &iter, path)) {
3029
 
                goto out;
3030
 
        }
3031
 
 
3032
 
        uri = NULL;
3033
 
        gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
3034
 
                            PLACES_SIDEBAR_COLUMN_URI, &uri,
3035
 
                            PLACES_SIDEBAR_COLUMN_ROW_TYPE, &type,
3036
 
                            -1);
3037
 
        if (!uri) {
3038
 
                goto out;
3039
 
        }
3040
 
 
3041
 
        location = g_file_new_for_uri (uri);
3042
 
        bookmark = nautilus_bookmark_list_item_with_location (sidebar->bookmarks, location, NULL);
3043
 
 
3044
 
        if (bookmark != NULL) {
3045
 
                nautilus_bookmark_set_custom_name (bookmark, new_text);
3046
 
        } else if (type == PLACES_XDG_DIR) {
3047
 
                /* In case we're renaming a built-in bookmark, and it's not in the
3048
 
                 * list, add it with a custom name.
3049
 
                 */
3050
 
                bookmark = nautilus_bookmark_new (location, new_text);
3051
 
                nautilus_bookmark_list_append (sidebar->bookmarks, bookmark);
3052
 
                g_object_unref (bookmark);
3053
 
        }
3054
 
 
3055
 
        g_object_unref (location);
3056
 
 
3057
 
 out:
3058
 
        g_free (uri);
3059
 
        gtk_tree_path_free (path);
3060
 
}
3061
 
 
3062
 
static void
3063
 
bookmarks_editing_canceled (GtkCellRenderer       *cell,
3064
 
                            NautilusPlacesSidebar *sidebar)
3065
 
{
3066
 
        g_object_set (cell, "editable", FALSE, NULL);
3067
 
}
3068
 
 
3069
 
static void
3070
 
trash_state_changed_cb (NautilusTrashMonitor *trash_monitor,
3071
 
                        gboolean             state,
3072
 
                        gpointer             data)
3073
 
{
3074
 
        NautilusPlacesSidebar *sidebar;
3075
 
 
3076
 
        sidebar = NAUTILUS_PLACES_SIDEBAR (data);
3077
 
 
3078
 
        /* The trash icon changed, update the sidebar */
3079
 
        update_places (sidebar);
3080
 
 
3081
 
        bookmarks_check_popup_sensitivity (sidebar);
3082
 
}
3083
 
 
3084
 
static gboolean
3085
 
tree_selection_func (GtkTreeSelection *selection,
3086
 
                     GtkTreeModel *model,
3087
 
                     GtkTreePath *path,
3088
 
                     gboolean path_currently_selected,
3089
 
                     gpointer user_data)
3090
 
{
3091
 
        GtkTreeIter iter;
3092
 
        PlaceType row_type;
3093
 
 
3094
 
        gtk_tree_model_get_iter (model, &iter, path);
3095
 
        gtk_tree_model_get (model, &iter,
3096
 
                            PLACES_SIDEBAR_COLUMN_ROW_TYPE, &row_type,
3097
 
                            -1);
3098
 
 
3099
 
        if (row_type == PLACES_HEADING) {
3100
 
                return FALSE;
3101
 
        }
3102
 
 
3103
 
        return TRUE;
3104
 
}
3105
 
 
3106
 
static void
3107
 
icon_cell_renderer_func (GtkTreeViewColumn *column,
3108
 
                         GtkCellRenderer *cell,
3109
 
                         GtkTreeModel *model,
3110
 
                         GtkTreeIter *iter,
3111
 
                         gpointer user_data)
3112
 
{
3113
 
        PlaceType type;
3114
 
 
3115
 
        gtk_tree_model_get (model, iter,
3116
 
                            PLACES_SIDEBAR_COLUMN_ROW_TYPE, &type,
3117
 
                            -1);
3118
 
 
3119
 
        if (type == PLACES_HEADING) {
3120
 
                g_object_set (cell,
3121
 
                              "visible", FALSE,
3122
 
                              NULL);
3123
 
        } else {
3124
 
                g_object_set (cell,
3125
 
                              "visible", TRUE,
3126
 
                              NULL);
3127
 
        }
3128
 
}
3129
 
 
3130
 
static void
3131
 
padding_cell_renderer_func (GtkTreeViewColumn *column,
3132
 
                            GtkCellRenderer *cell,
3133
 
                            GtkTreeModel *model,
3134
 
                            GtkTreeIter *iter,
3135
 
                            gpointer user_data)
3136
 
{
3137
 
        PlaceType type;
3138
 
 
3139
 
        gtk_tree_model_get (model, iter,
3140
 
                            PLACES_SIDEBAR_COLUMN_ROW_TYPE, &type,
3141
 
                            -1);
3142
 
 
3143
 
        if (type == PLACES_HEADING) {
3144
 
                g_object_set (cell,
3145
 
                              "visible", FALSE,
3146
 
                              "xpad", 0,
3147
 
                              "ypad", 0,
3148
 
                              NULL);
3149
 
        } else {
3150
 
                g_object_set (cell,
3151
 
                              "visible", TRUE,
3152
 
                              "xpad", 3,
3153
 
                              "ypad", 3,
3154
 
                              NULL);
3155
 
        }
3156
 
}
3157
 
 
3158
 
static void
3159
 
heading_cell_renderer_func (GtkTreeViewColumn *column,
3160
 
                            GtkCellRenderer *cell,
3161
 
                            GtkTreeModel *model,
3162
 
                            GtkTreeIter *iter,
3163
 
                            gpointer user_data)
3164
 
{
3165
 
        PlaceType type;
3166
 
 
3167
 
        gtk_tree_model_get (model, iter,
3168
 
                            PLACES_SIDEBAR_COLUMN_ROW_TYPE, &type,
3169
 
                            -1);
3170
 
 
3171
 
        if (type == PLACES_HEADING) {
3172
 
                g_object_set (cell,
3173
 
                              "visible", TRUE,
3174
 
                              NULL);
3175
 
        } else {
3176
 
                g_object_set (cell,
3177
 
                              "visible", FALSE,
3178
 
                              NULL);
3179
 
        }
3180
 
}
3181
 
 
3182
 
static gint
3183
 
places_sidebar_sort_func (GtkTreeModel *model,
3184
 
                          GtkTreeIter *iter_a,
3185
 
                          GtkTreeIter *iter_b,
3186
 
                          gpointer user_data)
3187
 
{
3188
 
        SectionType section_type_a, section_type_b;
3189
 
        PlaceType place_type_a, place_type_b;
3190
 
        gint retval = 0;
3191
 
 
3192
 
        gtk_tree_model_get (model, iter_a,
3193
 
                            PLACES_SIDEBAR_COLUMN_SECTION_TYPE, &section_type_a,
3194
 
                            PLACES_SIDEBAR_COLUMN_ROW_TYPE, &place_type_a,
3195
 
                            -1);
3196
 
        gtk_tree_model_get (model, iter_b,
3197
 
                            PLACES_SIDEBAR_COLUMN_SECTION_TYPE, &section_type_b,
3198
 
                            PLACES_SIDEBAR_COLUMN_ROW_TYPE, &place_type_b,
3199
 
                            -1);
3200
 
 
3201
 
        /* fall back to the default order if we're not in the
3202
 
         * XDG part of the computer section.
3203
 
         */
3204
 
        if ((section_type_a == section_type_b) &&
3205
 
            (section_type_a == SECTION_COMPUTER) &&
3206
 
            (place_type_a == place_type_b) &&
3207
 
            (place_type_a == PLACES_XDG_DIR)) {
3208
 
                gchar *name_a, *name_b;
3209
 
 
3210
 
                gtk_tree_model_get (model, iter_a,
3211
 
                                    PLACES_SIDEBAR_COLUMN_NAME, &name_a,
3212
 
                                    -1);
3213
 
                gtk_tree_model_get (model, iter_b,
3214
 
                                    PLACES_SIDEBAR_COLUMN_NAME, &name_b,
3215
 
                                    -1);
3216
 
 
3217
 
                retval = g_utf8_collate (name_a, name_b);
3218
 
 
3219
 
                g_free (name_a);
3220
 
                g_free (name_b);
3221
 
        } else if (place_type_a == PLACES_CONNECT_SERVER) {
3222
 
                retval = 1;
3223
 
        }
3224
 
 
3225
 
        return retval;
3226
 
}
3227
 
 
3228
 
static void
3229
 
update_hostname (NautilusPlacesSidebar *sidebar)
3230
 
{
3231
 
        GVariant *variant;
3232
 
        gsize len;
3233
 
        const gchar *hostname;
3234
 
 
3235
 
        if (sidebar->hostnamed_proxy == NULL)
3236
 
                return;
3237
 
 
3238
 
        variant = g_dbus_proxy_get_cached_property (sidebar->hostnamed_proxy,
3239
 
                                                    "PrettyHostname");
3240
 
        if (variant == NULL) {
3241
 
                return;
3242
 
        }
3243
 
 
3244
 
        hostname = g_variant_get_string (variant, &len);
3245
 
        if (len > 0 &&
3246
 
            g_strcmp0 (sidebar->hostname, hostname) != 0) {
3247
 
                g_free (sidebar->hostname);
3248
 
                sidebar->hostname = g_strdup (hostname);
3249
 
                update_places (sidebar);
3250
 
        }
3251
 
 
3252
 
        g_variant_unref (variant);
3253
 
}
3254
 
 
3255
 
static void
3256
 
hostname_proxy_new_cb (GObject      *source_object,
3257
 
                       GAsyncResult *res,
3258
 
                       gpointer      user_data)
3259
 
{
3260
 
        NautilusPlacesSidebar *sidebar = user_data;
3261
 
        GError *error = NULL;
3262
 
 
3263
 
        sidebar->hostnamed_proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
3264
 
        g_clear_object (&sidebar->hostnamed_cancellable);
3265
 
 
3266
 
        if (error != NULL) {
3267
 
                g_debug ("Failed to create D-Bus proxy: %s", error->message);
3268
 
                g_error_free (error);
3269
 
                return;
3270
 
        }
3271
 
 
3272
 
        g_signal_connect_swapped (sidebar->hostnamed_proxy,
3273
 
                                  "g-properties-changed",
3274
 
                                  G_CALLBACK (update_hostname),
3275
 
                                  sidebar);
3276
 
        update_hostname (sidebar);
3277
 
}
3278
 
 
3279
 
static void
3280
 
nautilus_places_sidebar_init (NautilusPlacesSidebar *sidebar)
3281
 
{
3282
 
        GtkTreeView       *tree_view;
3283
 
        GtkTreeViewColumn *col;
3284
 
        GtkCellRenderer   *cell;
3285
 
        GtkTreeSelection  *selection;
3286
 
        GIcon             *eject;
3287
 
 
3288
 
        sidebar->volume_monitor = g_volume_monitor_get ();
3289
 
        
3290
 
        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sidebar),
3291
 
                                        GTK_POLICY_NEVER,
3292
 
                                        GTK_POLICY_AUTOMATIC);
3293
 
        gtk_scrolled_window_set_hadjustment (GTK_SCROLLED_WINDOW (sidebar), NULL);
3294
 
        gtk_scrolled_window_set_vadjustment (GTK_SCROLLED_WINDOW (sidebar), NULL);
3295
 
        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sidebar), GTK_SHADOW_IN);
3296
 
 
3297
 
        gtk_style_context_set_junction_sides (gtk_widget_get_style_context (GTK_WIDGET (sidebar)),
3298
 
                                              GTK_JUNCTION_RIGHT | GTK_JUNCTION_LEFT);
3299
 
 
3300
 
        /* tree view */
3301
 
        tree_view = GTK_TREE_VIEW (gtk_tree_view_new ());
3302
 
        gtk_tree_view_set_headers_visible (tree_view, FALSE);
3303
 
 
3304
 
        col = GTK_TREE_VIEW_COLUMN (gtk_tree_view_column_new ());
3305
 
 
3306
 
        /* initial padding */
3307
 
        cell = gtk_cell_renderer_text_new ();
3308
 
        gtk_tree_view_column_pack_start (col, cell, FALSE);
3309
 
        g_object_set (cell,
3310
 
                      "xpad", 6,
3311
 
                      NULL);
3312
 
 
3313
 
        /* headings */
3314
 
        cell = gtk_cell_renderer_text_new ();
3315
 
        gtk_tree_view_column_pack_start (col, cell, FALSE);
3316
 
        gtk_tree_view_column_set_attributes (col, cell,
3317
 
                                             "text", PLACES_SIDEBAR_COLUMN_HEADING_TEXT,
3318
 
                                             NULL);
3319
 
        g_object_set (cell,
3320
 
                      "weight", PANGO_WEIGHT_BOLD,
3321
 
                      "weight-set", TRUE,
3322
 
                      "ypad", 6,
3323
 
                      "xpad", 0,
3324
 
                      NULL);
3325
 
        gtk_tree_view_column_set_cell_data_func (col, cell,
3326
 
                                                 heading_cell_renderer_func,
3327
 
                                                 sidebar, NULL);
3328
 
 
3329
 
        /* icon padding */
3330
 
        cell = gtk_cell_renderer_text_new ();
3331
 
        gtk_tree_view_column_pack_start (col, cell, FALSE);
3332
 
        gtk_tree_view_column_set_cell_data_func (col, cell,
3333
 
                                                 padding_cell_renderer_func,
3334
 
                                                 sidebar, NULL);
3335
 
 
3336
 
        /* icon renderer */
3337
 
        cell = gtk_cell_renderer_pixbuf_new ();
3338
 
        g_object_set (cell, "follow-state", TRUE, NULL);
3339
 
        gtk_tree_view_column_pack_start (col, cell, FALSE);
3340
 
        gtk_tree_view_column_set_attributes (col, cell,
3341
 
                                             "gicon", PLACES_SIDEBAR_COLUMN_GICON,
3342
 
                                             NULL);
3343
 
        gtk_tree_view_column_set_cell_data_func (col, cell,
3344
 
                                                 icon_cell_renderer_func,
3345
 
                                                 sidebar, NULL);
3346
 
 
3347
 
        /* eject text renderer */
3348
 
        cell = gtk_cell_renderer_text_new ();
3349
 
        gtk_tree_view_column_pack_start (col, cell, TRUE);
3350
 
        gtk_tree_view_column_set_attributes (col, cell,
3351
 
                                             "text", PLACES_SIDEBAR_COLUMN_NAME,
3352
 
                                             "visible", PLACES_SIDEBAR_COLUMN_EJECT,
3353
 
                                             NULL);
3354
 
        g_object_set (cell,
3355
 
                      "ellipsize", PANGO_ELLIPSIZE_END,
3356
 
                      "ellipsize-set", TRUE,
3357
 
                      NULL);
3358
 
 
3359
 
        /* eject icon renderer */
3360
 
        cell = gtk_cell_renderer_pixbuf_new ();
3361
 
        sidebar->eject_icon_cell_renderer = cell;
3362
 
        eject = g_themed_icon_new_with_default_fallbacks ("media-eject-symbolic");
3363
 
        g_object_set (cell,
3364
 
                      "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE,
3365
 
                      "stock-size", GTK_ICON_SIZE_MENU,
3366
 
                      "xpad", EJECT_BUTTON_XPAD,
3367
 
                      /* align right, because for some reason gtk+ expands
3368
 
                         this even though we tell it not to. */
3369
 
                      "xalign", 1.0,
3370
 
                      "follow-state", TRUE,
3371
 
                      "gicon", eject,
3372
 
                      NULL);
3373
 
        gtk_tree_view_column_pack_start (col, cell, FALSE);
3374
 
        gtk_tree_view_column_set_attributes (col, cell,
3375
 
                                             "visible", PLACES_SIDEBAR_COLUMN_EJECT,
3376
 
                                             NULL);
3377
 
        g_object_unref (eject);
3378
 
 
3379
 
        /* normal text renderer */
3380
 
        cell = gtk_cell_renderer_text_new ();
3381
 
        gtk_tree_view_column_pack_start (col, cell, TRUE);
3382
 
        g_object_set (G_OBJECT (cell), "editable", FALSE, NULL);
3383
 
        gtk_tree_view_column_set_attributes (col, cell,
3384
 
                                             "text", PLACES_SIDEBAR_COLUMN_NAME,
3385
 
                                             "visible", PLACES_SIDEBAR_COLUMN_NO_EJECT,
3386
 
                                             "editable-set", PLACES_SIDEBAR_COLUMN_BOOKMARK,
3387
 
                                             NULL);
3388
 
        g_object_set (cell,
3389
 
                      "ellipsize", PANGO_ELLIPSIZE_END,
3390
 
                      "ellipsize-set", TRUE,
3391
 
                      NULL);
3392
 
 
3393
 
        g_signal_connect (cell, "edited", 
3394
 
                          G_CALLBACK (bookmarks_edited), sidebar);
3395
 
        g_signal_connect (cell, "editing-canceled", 
3396
 
                          G_CALLBACK (bookmarks_editing_canceled), sidebar);
3397
 
 
3398
 
        /* this is required to align the eject buttons to the right */
3399
 
        gtk_tree_view_column_set_max_width (GTK_TREE_VIEW_COLUMN (col), NAUTILUS_ICON_SIZE_SMALLER);
3400
 
        gtk_tree_view_append_column (tree_view, col);
3401
 
 
3402
 
        sidebar->store = nautilus_shortcuts_model_new (sidebar);
3403
 
        gtk_tree_view_set_tooltip_column (tree_view, PLACES_SIDEBAR_COLUMN_TOOLTIP);
3404
 
        gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sidebar->store),
3405
 
                                              PLACES_SIDEBAR_COLUMN_NAME,
3406
 
                                              GTK_SORT_ASCENDING);
3407
 
        gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (sidebar->store),
3408
 
                                         PLACES_SIDEBAR_COLUMN_NAME,
3409
 
                                         places_sidebar_sort_func,
3410
 
                                         sidebar, NULL);
3411
 
 
3412
 
        gtk_tree_view_set_model (tree_view, GTK_TREE_MODEL (sidebar->store));
3413
 
        gtk_container_add (GTK_CONTAINER (sidebar), GTK_WIDGET (tree_view));
3414
 
        gtk_widget_show (GTK_WIDGET (tree_view));
3415
 
        gtk_tree_view_set_enable_search (tree_view, FALSE);
3416
 
 
3417
 
        gtk_widget_show (GTK_WIDGET (sidebar));
3418
 
        sidebar->tree_view = tree_view;
3419
 
 
3420
 
        gtk_tree_view_set_search_column (tree_view, PLACES_SIDEBAR_COLUMN_NAME);
3421
 
        selection = gtk_tree_view_get_selection (tree_view);
3422
 
        gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
3423
 
 
3424
 
        gtk_tree_selection_set_select_function (selection,
3425
 
                                                tree_selection_func,
3426
 
                                                sidebar,
3427
 
                                                NULL);
3428
 
 
3429
 
        gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (tree_view),
3430
 
                                                GDK_BUTTON1_MASK,
3431
 
                                                nautilus_shortcuts_source_targets,
3432
 
                                                G_N_ELEMENTS (nautilus_shortcuts_source_targets),
3433
 
                                                GDK_ACTION_MOVE);
3434
 
        gtk_drag_dest_set (GTK_WIDGET (tree_view),
3435
 
                           0,
3436
 
                           nautilus_shortcuts_drop_targets, G_N_ELEMENTS (nautilus_shortcuts_drop_targets),
3437
 
                           GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK);
3438
 
 
3439
 
        g_signal_connect (tree_view, "key-press-event",
3440
 
                          G_CALLBACK (bookmarks_key_press_event_cb), sidebar);
3441
 
 
3442
 
        g_signal_connect (tree_view, "drag-motion",
3443
 
                          G_CALLBACK (drag_motion_callback), sidebar);
3444
 
        g_signal_connect (tree_view, "drag-leave",
3445
 
                          G_CALLBACK (drag_leave_callback), sidebar);
3446
 
        g_signal_connect (tree_view, "drag-data-received",
3447
 
                          G_CALLBACK (drag_data_received_callback), sidebar);
3448
 
        g_signal_connect (tree_view, "drag-drop",
3449
 
                          G_CALLBACK (drag_drop_callback), sidebar);
3450
 
 
3451
 
        g_signal_connect (selection, "changed",
3452
 
                          G_CALLBACK (bookmarks_selection_changed_cb), sidebar);
3453
 
        g_signal_connect (tree_view, "popup-menu",
3454
 
                          G_CALLBACK (bookmarks_popup_menu_cb), sidebar);
3455
 
        g_signal_connect (tree_view, "button-release-event",
3456
 
                          G_CALLBACK (bookmarks_button_release_event_cb), sidebar);
3457
 
        g_signal_connect (tree_view, "row-activated",
3458
 
                          G_CALLBACK (bookmarks_row_activated_cb), sidebar);
3459
 
 
3460
 
        gtk_tree_view_set_activate_on_single_click (sidebar->tree_view, TRUE);
3461
 
 
3462
 
        g_signal_connect_swapped (gnome_background_preferences, "changed::" NAUTILUS_PREFERENCES_SHOW_DESKTOP,
3463
 
                                  G_CALLBACK (update_places),
3464
 
                                  sidebar);
3465
 
        g_signal_connect_swapped (gnome_privacy_preferences, "changed::" NAUTILUS_PREFERENCES_RECENT_FILES_ENABLED,
3466
 
                                  G_CALLBACK (update_places),
3467
 
                                  sidebar);
3468
 
 
3469
 
        sidebar->hostname = g_strdup (_("Computer"));
3470
 
        sidebar->hostnamed_cancellable = g_cancellable_new ();
3471
 
        g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
3472
 
                                  G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES,
3473
 
                                  NULL,
3474
 
                                  "org.freedesktop.hostname1",
3475
 
                                  "/org/freedesktop/hostname1",
3476
 
                                  "org.freedesktop.hostname1",
3477
 
                                  sidebar->hostnamed_cancellable,
3478
 
                                  hostname_proxy_new_cb,
3479
 
                                  sidebar);
3480
 
 
3481
 
        g_signal_connect_object (nautilus_trash_monitor_get (),
3482
 
                                 "trash-state-changed",
3483
 
                                 G_CALLBACK (trash_state_changed_cb),
3484
 
                                 sidebar, 0);
3485
 
}
3486
 
 
3487
 
static void
3488
 
nautilus_places_sidebar_dispose (GObject *object)
3489
 
{
3490
 
        NautilusPlacesSidebar *sidebar;
3491
 
 
3492
 
        sidebar = NAUTILUS_PLACES_SIDEBAR (object);
3493
 
 
3494
 
        sidebar->window = NULL;
3495
 
        sidebar->tree_view = NULL;
3496
 
 
3497
 
        g_free (sidebar->uri);
3498
 
        sidebar->uri = NULL;
3499
 
 
3500
 
        free_drag_data (sidebar);
3501
 
 
3502
 
        if (sidebar->bookmarks_changed_id != 0) {
3503
 
                g_signal_handler_disconnect (sidebar->bookmarks,
3504
 
                                             sidebar->bookmarks_changed_id);
3505
 
                sidebar->bookmarks_changed_id = 0;
3506
 
        }
3507
 
 
3508
 
        g_clear_object (&sidebar->store);
3509
 
 
3510
 
        if (sidebar->go_to_after_mount_slot) {
3511
 
                g_object_remove_weak_pointer (G_OBJECT (sidebar->go_to_after_mount_slot),
3512
 
                                              (gpointer *) &sidebar->go_to_after_mount_slot);
3513
 
                sidebar->go_to_after_mount_slot = NULL;
3514
 
        }
3515
 
 
3516
 
        g_signal_handlers_disconnect_by_func (nautilus_preferences,
3517
 
                                              bookmarks_popup_menu_detach_cb,
3518
 
                                              sidebar);
3519
 
 
3520
 
        g_signal_handlers_disconnect_by_func (gnome_background_preferences,
3521
 
                                              update_places,
3522
 
                                              sidebar);
3523
 
 
3524
 
        g_signal_handlers_disconnect_by_func (gnome_privacy_preferences,
3525
 
                                              update_places,
3526
 
                                              sidebar);
3527
 
 
3528
 
        if (sidebar->volume_monitor != NULL) {
3529
 
                g_signal_handlers_disconnect_by_func (sidebar->volume_monitor, 
3530
 
                                                      volume_added_callback, sidebar);
3531
 
                g_signal_handlers_disconnect_by_func (sidebar->volume_monitor, 
3532
 
                                                      volume_removed_callback, sidebar);
3533
 
                g_signal_handlers_disconnect_by_func (sidebar->volume_monitor, 
3534
 
                                                      volume_changed_callback, sidebar);
3535
 
                g_signal_handlers_disconnect_by_func (sidebar->volume_monitor, 
3536
 
                                                      mount_added_callback, sidebar);
3537
 
                g_signal_handlers_disconnect_by_func (sidebar->volume_monitor, 
3538
 
                                                      mount_removed_callback, sidebar);
3539
 
                g_signal_handlers_disconnect_by_func (sidebar->volume_monitor, 
3540
 
                                                      mount_changed_callback, sidebar);
3541
 
                g_signal_handlers_disconnect_by_func (sidebar->volume_monitor, 
3542
 
                                                      drive_disconnected_callback, sidebar);
3543
 
                g_signal_handlers_disconnect_by_func (sidebar->volume_monitor, 
3544
 
                                                      drive_connected_callback, sidebar);
3545
 
                g_signal_handlers_disconnect_by_func (sidebar->volume_monitor, 
3546
 
                                                      drive_changed_callback, sidebar);
3547
 
 
3548
 
                g_clear_object (&sidebar->volume_monitor);
3549
 
        }
3550
 
 
3551
 
        if (sidebar->hostnamed_cancellable != NULL) {
3552
 
                g_cancellable_cancel (sidebar->hostnamed_cancellable);
3553
 
                g_clear_object (&sidebar->hostnamed_cancellable);
3554
 
        }
3555
 
 
3556
 
        g_clear_object (&sidebar->hostnamed_proxy);
3557
 
        g_free (sidebar->hostname);
3558
 
        sidebar->hostname = NULL;
3559
 
 
3560
 
        G_OBJECT_CLASS (nautilus_places_sidebar_parent_class)->dispose (object);
3561
 
}
3562
 
 
3563
 
static void
3564
 
nautilus_places_sidebar_class_init (NautilusPlacesSidebarClass *class)
3565
 
{
3566
 
        G_OBJECT_CLASS (class)->dispose = nautilus_places_sidebar_dispose;
3567
 
 
3568
 
        GTK_WIDGET_CLASS (class)->style_set = nautilus_places_sidebar_style_set;
3569
 
        GTK_WIDGET_CLASS (class)->focus = nautilus_places_sidebar_focus;
3570
 
}
3571
 
 
3572
 
static void
3573
 
nautilus_places_sidebar_set_parent_window (NautilusPlacesSidebar *sidebar,
3574
 
                                           NautilusWindow *window)
3575
 
{
3576
 
        NautilusWindowSlot *slot;
3577
 
        NautilusApplication *app = NAUTILUS_APPLICATION (g_application_get_default ());
3578
 
 
3579
 
        sidebar->window = window;
3580
 
 
3581
 
        slot = nautilus_window_get_active_slot (window);
3582
 
 
3583
 
        sidebar->bookmarks = nautilus_application_get_bookmarks (app);
3584
 
        sidebar->bookmarks_changed_id =
3585
 
                g_signal_connect_swapped (sidebar->bookmarks, "changed",
3586
 
                                          G_CALLBACK (update_places),
3587
 
                                          sidebar);
3588
 
 
3589
 
        g_signal_connect_object (sidebar->volume_monitor, "volume-added",
3590
 
                                 G_CALLBACK (volume_added_callback), sidebar, 0);
3591
 
        g_signal_connect_object (sidebar->volume_monitor, "volume-removed",
3592
 
                                 G_CALLBACK (volume_removed_callback), sidebar, 0);
3593
 
        g_signal_connect_object (sidebar->volume_monitor, "volume-changed",
3594
 
                                 G_CALLBACK (volume_changed_callback), sidebar, 0);
3595
 
        g_signal_connect_object (sidebar->volume_monitor, "mount-added",
3596
 
                                 G_CALLBACK (mount_added_callback), sidebar, 0);
3597
 
        g_signal_connect_object (sidebar->volume_monitor, "mount-removed",
3598
 
                                 G_CALLBACK (mount_removed_callback), sidebar, 0);
3599
 
        g_signal_connect_object (sidebar->volume_monitor, "mount-changed",
3600
 
                                 G_CALLBACK (mount_changed_callback), sidebar, 0);
3601
 
        g_signal_connect_object (sidebar->volume_monitor, "drive-disconnected",
3602
 
                                 G_CALLBACK (drive_disconnected_callback), sidebar, 0);
3603
 
        g_signal_connect_object (sidebar->volume_monitor, "drive-connected",
3604
 
                                 G_CALLBACK (drive_connected_callback), sidebar, 0);
3605
 
        g_signal_connect_object (sidebar->volume_monitor, "drive-changed",
3606
 
                                 G_CALLBACK (drive_changed_callback), sidebar, 0);
3607
 
 
3608
 
        update_places (sidebar);
3609
 
 
3610
 
        g_signal_connect_object (window, "loading-uri",
3611
 
                                 G_CALLBACK (loading_uri_callback),
3612
 
                                 sidebar, 0);
3613
 
        sidebar->uri = nautilus_window_slot_get_current_uri (slot);
3614
 
        update_current_uri (sidebar);
3615
 
}
3616
 
 
3617
 
static void
3618
 
nautilus_places_sidebar_style_set (GtkWidget *widget,
3619
 
                                   GtkStyle  *previous_style)
3620
 
{
3621
 
        NautilusPlacesSidebar *sidebar;
3622
 
 
3623
 
        sidebar = NAUTILUS_PLACES_SIDEBAR (widget);
3624
 
 
3625
 
        update_places (sidebar);
3626
 
}
3627
 
 
3628
 
GtkWidget *
3629
 
nautilus_places_sidebar_new (NautilusWindow *window)
3630
 
{
3631
 
        NautilusPlacesSidebar *sidebar;
3632
 
        
3633
 
        sidebar = g_object_new (nautilus_places_sidebar_get_type (), NULL);
3634
 
        nautilus_places_sidebar_set_parent_window (sidebar, window);
3635
 
 
3636
 
        return GTK_WIDGET (sidebar);
3637
 
}
3638
 
 
3639
 
 
3640
 
/* Drag and drop interfaces */
3641
 
 
3642
 
/* GtkTreeDragSource::row_draggable implementation for the shortcuts filter model */
3643
 
 
3644
 
static gboolean
3645
 
nautilus_shortcuts_model_row_draggable (GtkTreeDragSource *drag_source,
3646
 
                                        GtkTreePath       *path)
3647
 
{
3648
 
        GtkTreeModel *model;
3649
 
        GtkTreeIter iter;
3650
 
        PlaceType place_type;
3651
 
        SectionType section_type;
3652
 
 
3653
 
        model = GTK_TREE_MODEL (drag_source);
3654
 
 
3655
 
        gtk_tree_model_get_iter (model, &iter, path);
3656
 
        gtk_tree_model_get (model, &iter,
3657
 
                            PLACES_SIDEBAR_COLUMN_ROW_TYPE, &place_type,
3658
 
                            PLACES_SIDEBAR_COLUMN_SECTION_TYPE, &section_type,
3659
 
                            -1);
3660
 
 
3661
 
        if (place_type != PLACES_HEADING && section_type == SECTION_BOOKMARKS)
3662
 
                return TRUE;
3663
 
 
3664
 
        return FALSE;
3665
 
}
3666
 
 
3667
 
static void
3668
 
_nautilus_shortcuts_model_class_init (NautilusShortcutsModelClass *klass)
3669
 
{
3670
 
 
3671
 
}
3672
 
 
3673
 
static void
3674
 
_nautilus_shortcuts_model_init (NautilusShortcutsModel *model)
3675
 
{
3676
 
        model->sidebar = NULL;
3677
 
}
3678
 
 
3679
 
static void
3680
 
_nautilus_shortcuts_model_drag_source_init (GtkTreeDragSourceIface *iface)
3681
 
{
3682
 
        iface->row_draggable = nautilus_shortcuts_model_row_draggable;
3683
 
}
3684
 
 
3685
 
static GtkListStore *
3686
 
nautilus_shortcuts_model_new (NautilusPlacesSidebar *sidebar)
3687
 
{
3688
 
        NautilusShortcutsModel *model;
3689
 
        GType model_types[PLACES_SIDEBAR_COLUMN_COUNT] = {
3690
 
                G_TYPE_INT, 
3691
 
                G_TYPE_STRING,
3692
 
                G_TYPE_DRIVE,
3693
 
                G_TYPE_VOLUME,
3694
 
                G_TYPE_MOUNT,
3695
 
                G_TYPE_STRING,
3696
 
                G_TYPE_ICON,
3697
 
                G_TYPE_INT,
3698
 
                G_TYPE_BOOLEAN,
3699
 
                G_TYPE_BOOLEAN,
3700
 
                G_TYPE_BOOLEAN,
3701
 
                G_TYPE_STRING,
3702
 
                G_TYPE_INT,
3703
 
                G_TYPE_STRING
3704
 
        };
3705
 
 
3706
 
        model = g_object_new (_nautilus_shortcuts_model_get_type (), NULL);
3707
 
        model->sidebar = sidebar;
3708
 
 
3709
 
        gtk_list_store_set_column_types (GTK_LIST_STORE (model),
3710
 
                                         PLACES_SIDEBAR_COLUMN_COUNT,
3711
 
                                         model_types);
3712
 
 
3713
 
        return GTK_LIST_STORE (model);
3714
 
}