mirror of
https://gitlab.gnome.org/GNOME/nautilus
synced 2024-10-05 23:40:01 +00:00
498596add8
2009-02-10 David Zeuthen <davidz@redhat.com> Don't use shadowed mounts. * libnautilus-private/nautilus-desktop-link-monitor.c (has_mount), (create_mount_link), (remove_mount_link), (mount_added_callback), (mount_removed_callback), (mount_changed_callback): * libnautilus-private/nautilus-directory-async.c (get_mount_at): * src/file-manager/fm-tree-view.c (add_root_for_mount): * src/nautilus-pathbar.c (is_file_path_mounted_mount): * src/nautilus-places-sidebar.c (update_places): Honor g_mount_is_shadowed(). svn path=/trunk/; revision=14953
541 lines
14 KiB
C
541 lines
14 KiB
C
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
|
|
|
|
nautilus-desktop-link-monitor.c: singleton thatn manages the links
|
|
|
|
Copyright (C) 2003 Red Hat, Inc.
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation; either version 2 of the
|
|
License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public
|
|
License along with this program; if not, write to the
|
|
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
Boston, MA 02111-1307, USA.
|
|
|
|
Author: Alexander Larsson <alexl@redhat.com>
|
|
*/
|
|
|
|
#include <config.h>
|
|
#include "nautilus-desktop-link-monitor.h"
|
|
#include "nautilus-desktop-link.h"
|
|
#include "nautilus-desktop-icon-file.h"
|
|
#include "nautilus-directory.h"
|
|
#include "nautilus-desktop-directory.h"
|
|
#include "nautilus-global-preferences.h"
|
|
|
|
#include <eel/eel-debug.h>
|
|
#include <eel/eel-gtk-macros.h>
|
|
#include <eel/eel-glib-extensions.h>
|
|
#include <eel/eel-vfs-extensions.h>
|
|
#include <eel/eel-stock-dialogs.h>
|
|
#include <gtk/gtk.h>
|
|
#include <glib/gi18n.h>
|
|
#include <gio/gio.h>
|
|
#include <libnautilus-private/nautilus-trash-monitor.h>
|
|
#include <string.h>
|
|
|
|
struct NautilusDesktopLinkMonitorDetails {
|
|
GVolumeMonitor *volume_monitor;
|
|
NautilusDirectory *desktop_dir;
|
|
|
|
NautilusDesktopLink *home_link;
|
|
NautilusDesktopLink *computer_link;
|
|
NautilusDesktopLink *trash_link;
|
|
NautilusDesktopLink *network_link;
|
|
|
|
gulong mount_id;
|
|
gulong unmount_id;
|
|
gulong changed_id;
|
|
|
|
GList *mount_links;
|
|
};
|
|
|
|
|
|
static void nautilus_desktop_link_monitor_init (gpointer object,
|
|
gpointer klass);
|
|
static void nautilus_desktop_link_monitor_class_init (gpointer klass);
|
|
|
|
EEL_CLASS_BOILERPLATE (NautilusDesktopLinkMonitor,
|
|
nautilus_desktop_link_monitor,
|
|
G_TYPE_OBJECT)
|
|
|
|
static NautilusDesktopLinkMonitor *the_link_monitor = NULL;
|
|
|
|
static void
|
|
destroy_desktop_link_monitor (void)
|
|
{
|
|
if (the_link_monitor != NULL) {
|
|
g_object_unref (the_link_monitor);
|
|
}
|
|
}
|
|
|
|
NautilusDesktopLinkMonitor *
|
|
nautilus_desktop_link_monitor_get (void)
|
|
{
|
|
if (the_link_monitor == NULL) {
|
|
g_object_new (NAUTILUS_TYPE_DESKTOP_LINK_MONITOR, NULL);
|
|
eel_debug_call_at_shutdown (destroy_desktop_link_monitor);
|
|
}
|
|
return the_link_monitor;
|
|
}
|
|
|
|
static void
|
|
volume_delete_dialog (GtkWidget *parent_view,
|
|
NautilusDesktopLink *link)
|
|
{
|
|
GMount *mount;
|
|
char *dialog_str;
|
|
char *display_name;
|
|
|
|
mount = nautilus_desktop_link_get_mount (link);
|
|
|
|
if (mount != NULL) {
|
|
display_name = nautilus_desktop_link_get_display_name (link);
|
|
dialog_str = g_strdup_printf (_("You cannot move the volume \"%s\" to the trash."),
|
|
display_name);
|
|
g_free (display_name);
|
|
|
|
if (g_mount_can_eject (mount)) {
|
|
eel_run_simple_dialog
|
|
(parent_view,
|
|
FALSE,
|
|
GTK_MESSAGE_ERROR,
|
|
dialog_str,
|
|
_("If you want to eject the volume, please use \"Eject\" in the "
|
|
"popup menu of the volume."),
|
|
GTK_STOCK_OK, NULL);
|
|
} else {
|
|
eel_run_simple_dialog
|
|
(parent_view,
|
|
FALSE,
|
|
GTK_MESSAGE_ERROR,
|
|
dialog_str,
|
|
_("If you want to unmount the volume, please use \"Unmount Volume\" in the "
|
|
"popup menu of the volume."),
|
|
GTK_STOCK_OK, NULL);
|
|
}
|
|
|
|
g_object_unref (mount);
|
|
g_free (dialog_str);
|
|
}
|
|
}
|
|
|
|
void
|
|
nautilus_desktop_link_monitor_delete_link (NautilusDesktopLinkMonitor *monitor,
|
|
NautilusDesktopLink *link,
|
|
GtkWidget *parent_view)
|
|
{
|
|
switch (nautilus_desktop_link_get_link_type (link)) {
|
|
case NAUTILUS_DESKTOP_LINK_HOME:
|
|
case NAUTILUS_DESKTOP_LINK_COMPUTER:
|
|
case NAUTILUS_DESKTOP_LINK_TRASH:
|
|
case NAUTILUS_DESKTOP_LINK_NETWORK:
|
|
/* just ignore. We don't allow you to delete these */
|
|
break;
|
|
default:
|
|
volume_delete_dialog (parent_view, link);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
volume_file_name_used (NautilusDesktopLinkMonitor *monitor,
|
|
const char *name)
|
|
{
|
|
GList *l;
|
|
char *other_name;
|
|
gboolean same;
|
|
|
|
for (l = monitor->details->mount_links; l != NULL; l = l->next) {
|
|
other_name = nautilus_desktop_link_get_file_name (l->data);
|
|
same = strcmp (name, other_name) == 0;
|
|
g_free (other_name);
|
|
|
|
if (same) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
char *
|
|
nautilus_desktop_link_monitor_make_filename_unique (NautilusDesktopLinkMonitor *monitor,
|
|
const char *filename)
|
|
{
|
|
char *unique_name;
|
|
int i;
|
|
|
|
i = 2;
|
|
unique_name = g_strdup (filename);
|
|
while (volume_file_name_used (monitor, unique_name)) {
|
|
g_free (unique_name);
|
|
unique_name = g_strdup_printf ("%s.%d", filename, i++);
|
|
}
|
|
return unique_name;
|
|
}
|
|
|
|
static gboolean
|
|
has_mount (NautilusDesktopLinkMonitor *monitor,
|
|
GMount *mount)
|
|
{
|
|
gboolean ret;
|
|
GMount *other_mount;
|
|
GList *l;
|
|
|
|
ret = FALSE;
|
|
|
|
for (l = monitor->details->mount_links; l != NULL; l = l->next) {
|
|
other_mount = nautilus_desktop_link_get_mount (l->data);
|
|
if (mount == other_mount) {
|
|
g_object_unref (other_mount);
|
|
ret = TRUE;
|
|
break;
|
|
}
|
|
g_object_unref (other_mount);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void
|
|
create_mount_link (NautilusDesktopLinkMonitor *monitor,
|
|
GMount *mount)
|
|
{
|
|
NautilusDesktopLink *link;
|
|
|
|
if (has_mount (monitor, mount))
|
|
return;
|
|
|
|
if ((!g_mount_is_shadowed (mount)) &&
|
|
eel_preferences_get_boolean (NAUTILUS_PREFERENCES_DESKTOP_VOLUMES_VISIBLE)) {
|
|
link = nautilus_desktop_link_new_from_mount (mount);
|
|
monitor->details->mount_links = g_list_prepend (monitor->details->mount_links, link);
|
|
}
|
|
}
|
|
|
|
static void
|
|
remove_mount_link (NautilusDesktopLinkMonitor *monitor,
|
|
GMount *mount)
|
|
{
|
|
GList *l;
|
|
NautilusDesktopLink *link;
|
|
GMount *other_mount;
|
|
|
|
link = NULL;
|
|
for (l = monitor->details->mount_links; l != NULL; l = l->next) {
|
|
other_mount = nautilus_desktop_link_get_mount (l->data);
|
|
if (mount == other_mount) {
|
|
g_object_unref (other_mount);
|
|
link = l->data;
|
|
break;
|
|
}
|
|
g_object_unref (other_mount);
|
|
}
|
|
|
|
if (link) {
|
|
monitor->details->mount_links = g_list_remove (monitor->details->mount_links, link);
|
|
g_object_unref (link);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
mount_added_callback (GVolumeMonitor *volume_monitor,
|
|
GMount *mount,
|
|
NautilusDesktopLinkMonitor *monitor)
|
|
{
|
|
create_mount_link (monitor, mount);
|
|
}
|
|
|
|
|
|
static void
|
|
mount_removed_callback (GVolumeMonitor *volume_monitor,
|
|
GMount *mount,
|
|
NautilusDesktopLinkMonitor *monitor)
|
|
{
|
|
remove_mount_link (monitor, mount);
|
|
}
|
|
|
|
static void
|
|
mount_changed_callback (GVolumeMonitor *volume_monitor,
|
|
GMount *mount,
|
|
NautilusDesktopLinkMonitor *monitor)
|
|
{
|
|
/* TODO: update the mount with other details */
|
|
|
|
/* remove a mount if it goes into the shadows */
|
|
if (g_mount_is_shadowed (mount) && has_mount (monitor, mount)) {
|
|
remove_mount_link (monitor, mount);
|
|
}}
|
|
|
|
static void
|
|
update_link_visibility (NautilusDesktopLinkMonitor *monitor,
|
|
NautilusDesktopLink **link_ref,
|
|
NautilusDesktopLinkType link_type,
|
|
const char *preference_key)
|
|
{
|
|
if (eel_preferences_get_boolean (preference_key)) {
|
|
if (*link_ref == NULL) {
|
|
*link_ref = nautilus_desktop_link_new (link_type);
|
|
}
|
|
} else {
|
|
if (*link_ref != NULL) {
|
|
g_object_unref (*link_ref);
|
|
*link_ref = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
desktop_home_visible_changed (gpointer callback_data)
|
|
{
|
|
NautilusDesktopLinkMonitor *monitor;
|
|
|
|
monitor = NAUTILUS_DESKTOP_LINK_MONITOR (callback_data);
|
|
|
|
update_link_visibility (NAUTILUS_DESKTOP_LINK_MONITOR (monitor),
|
|
&monitor->details->home_link,
|
|
NAUTILUS_DESKTOP_LINK_HOME,
|
|
NAUTILUS_PREFERENCES_DESKTOP_HOME_VISIBLE);
|
|
}
|
|
|
|
static void
|
|
desktop_computer_visible_changed (gpointer callback_data)
|
|
{
|
|
NautilusDesktopLinkMonitor *monitor;
|
|
|
|
monitor = NAUTILUS_DESKTOP_LINK_MONITOR (callback_data);
|
|
|
|
update_link_visibility (NAUTILUS_DESKTOP_LINK_MONITOR (callback_data),
|
|
&monitor->details->computer_link,
|
|
NAUTILUS_DESKTOP_LINK_COMPUTER,
|
|
NAUTILUS_PREFERENCES_DESKTOP_COMPUTER_VISIBLE);
|
|
}
|
|
|
|
static void
|
|
desktop_trash_visible_changed (gpointer callback_data)
|
|
{
|
|
NautilusDesktopLinkMonitor *monitor;
|
|
|
|
monitor = NAUTILUS_DESKTOP_LINK_MONITOR (callback_data);
|
|
|
|
update_link_visibility (NAUTILUS_DESKTOP_LINK_MONITOR (callback_data),
|
|
&monitor->details->trash_link,
|
|
NAUTILUS_DESKTOP_LINK_TRASH,
|
|
NAUTILUS_PREFERENCES_DESKTOP_TRASH_VISIBLE);
|
|
}
|
|
|
|
static void
|
|
desktop_network_visible_changed (gpointer callback_data)
|
|
{
|
|
NautilusDesktopLinkMonitor *monitor;
|
|
|
|
monitor = NAUTILUS_DESKTOP_LINK_MONITOR (callback_data);
|
|
|
|
update_link_visibility (NAUTILUS_DESKTOP_LINK_MONITOR (callback_data),
|
|
&monitor->details->network_link,
|
|
NAUTILUS_DESKTOP_LINK_NETWORK,
|
|
NAUTILUS_PREFERENCES_DESKTOP_NETWORK_VISIBLE);
|
|
}
|
|
|
|
static void
|
|
desktop_volumes_visible_changed (gpointer callback_data)
|
|
{
|
|
NautilusDesktopLinkMonitor *monitor;
|
|
GList *l, *mounts;
|
|
|
|
monitor = NAUTILUS_DESKTOP_LINK_MONITOR (callback_data);
|
|
|
|
if (eel_preferences_get_boolean (NAUTILUS_PREFERENCES_DESKTOP_VOLUMES_VISIBLE)) {
|
|
if (monitor->details->mount_links == NULL) {
|
|
mounts = g_volume_monitor_get_mounts (monitor->details->volume_monitor);
|
|
for (l = mounts; l != NULL; l = l->next) {
|
|
create_mount_link (monitor, l->data);
|
|
g_object_unref (l->data);
|
|
}
|
|
g_list_free (mounts);
|
|
}
|
|
} else {
|
|
g_list_foreach (monitor->details->mount_links, (GFunc)g_object_unref, NULL);
|
|
g_list_free (monitor->details->mount_links);
|
|
monitor->details->mount_links = NULL;
|
|
}
|
|
}
|
|
|
|
static void
|
|
create_link_and_add_preference (NautilusDesktopLink **link_ref,
|
|
NautilusDesktopLinkType link_type,
|
|
const char *preference_key,
|
|
EelPreferencesCallback callback,
|
|
gpointer callback_data)
|
|
{
|
|
if (eel_preferences_get_boolean (preference_key)) {
|
|
*link_ref = nautilus_desktop_link_new (link_type);
|
|
}
|
|
|
|
eel_preferences_add_callback (preference_key, callback, callback_data);
|
|
}
|
|
|
|
static void
|
|
nautilus_desktop_link_monitor_init (gpointer object, gpointer klass)
|
|
{
|
|
NautilusDesktopLinkMonitor *monitor;
|
|
GList *l, *mounts;
|
|
GMount *mount;
|
|
|
|
monitor = NAUTILUS_DESKTOP_LINK_MONITOR (object);
|
|
|
|
the_link_monitor = monitor;
|
|
|
|
monitor->details = g_new0 (NautilusDesktopLinkMonitorDetails, 1);
|
|
|
|
monitor->details->volume_monitor = g_volume_monitor_get ();
|
|
|
|
/* We keep around a ref to the desktop dir */
|
|
monitor->details->desktop_dir = nautilus_directory_get_by_uri (EEL_DESKTOP_URI);
|
|
|
|
/* Default links */
|
|
|
|
create_link_and_add_preference (&monitor->details->home_link,
|
|
NAUTILUS_DESKTOP_LINK_HOME,
|
|
NAUTILUS_PREFERENCES_DESKTOP_HOME_VISIBLE,
|
|
desktop_home_visible_changed,
|
|
monitor);
|
|
|
|
create_link_and_add_preference (&monitor->details->computer_link,
|
|
NAUTILUS_DESKTOP_LINK_COMPUTER,
|
|
NAUTILUS_PREFERENCES_DESKTOP_COMPUTER_VISIBLE,
|
|
desktop_computer_visible_changed,
|
|
monitor);
|
|
|
|
create_link_and_add_preference (&monitor->details->trash_link,
|
|
NAUTILUS_DESKTOP_LINK_TRASH,
|
|
NAUTILUS_PREFERENCES_DESKTOP_TRASH_VISIBLE,
|
|
desktop_trash_visible_changed,
|
|
monitor);
|
|
|
|
create_link_and_add_preference (&monitor->details->network_link,
|
|
NAUTILUS_DESKTOP_LINK_NETWORK,
|
|
NAUTILUS_PREFERENCES_DESKTOP_NETWORK_VISIBLE,
|
|
desktop_network_visible_changed,
|
|
monitor);
|
|
|
|
/* Mount links */
|
|
|
|
mounts = g_volume_monitor_get_mounts (monitor->details->volume_monitor);
|
|
for (l = mounts; l != NULL; l = l->next) {
|
|
mount = l->data;
|
|
create_mount_link (monitor, mount);
|
|
g_object_unref (mount);
|
|
}
|
|
g_list_free (mounts);
|
|
|
|
eel_preferences_add_callback (NAUTILUS_PREFERENCES_DESKTOP_VOLUMES_VISIBLE,
|
|
desktop_volumes_visible_changed,
|
|
monitor);
|
|
|
|
monitor->details->mount_id =
|
|
g_signal_connect_object (monitor->details->volume_monitor, "mount_added",
|
|
G_CALLBACK (mount_added_callback), monitor, 0);
|
|
monitor->details->unmount_id =
|
|
g_signal_connect_object (monitor->details->volume_monitor, "mount_removed",
|
|
G_CALLBACK (mount_removed_callback), monitor, 0);
|
|
monitor->details->changed_id =
|
|
g_signal_connect_object (monitor->details->volume_monitor, "mount_changed",
|
|
G_CALLBACK (mount_changed_callback), monitor, 0);
|
|
|
|
}
|
|
|
|
static void
|
|
remove_link_and_preference (NautilusDesktopLink **link_ref,
|
|
const char *preference_key,
|
|
EelPreferencesCallback callback,
|
|
gpointer callback_data)
|
|
{
|
|
if (*link_ref != NULL) {
|
|
g_object_unref (*link_ref);
|
|
*link_ref = NULL;
|
|
}
|
|
|
|
eel_preferences_remove_callback (preference_key, callback, callback_data);
|
|
}
|
|
|
|
static void
|
|
desktop_link_monitor_finalize (GObject *object)
|
|
{
|
|
NautilusDesktopLinkMonitor *monitor;
|
|
|
|
monitor = NAUTILUS_DESKTOP_LINK_MONITOR (object);
|
|
|
|
g_object_unref (monitor->details->volume_monitor);
|
|
|
|
/* Default links */
|
|
|
|
remove_link_and_preference (&monitor->details->home_link,
|
|
NAUTILUS_PREFERENCES_DESKTOP_HOME_VISIBLE,
|
|
desktop_home_visible_changed,
|
|
monitor);
|
|
|
|
remove_link_and_preference (&monitor->details->computer_link,
|
|
NAUTILUS_PREFERENCES_DESKTOP_COMPUTER_VISIBLE,
|
|
desktop_computer_visible_changed,
|
|
monitor);
|
|
|
|
remove_link_and_preference (&monitor->details->trash_link,
|
|
NAUTILUS_PREFERENCES_DESKTOP_TRASH_VISIBLE,
|
|
desktop_trash_visible_changed,
|
|
monitor);
|
|
|
|
remove_link_and_preference (&monitor->details->network_link,
|
|
NAUTILUS_PREFERENCES_DESKTOP_NETWORK_VISIBLE,
|
|
desktop_network_visible_changed,
|
|
monitor);
|
|
|
|
/* Mounts */
|
|
|
|
g_list_foreach (monitor->details->mount_links, (GFunc)g_object_unref, NULL);
|
|
g_list_free (monitor->details->mount_links);
|
|
monitor->details->mount_links = NULL;
|
|
|
|
nautilus_directory_unref (monitor->details->desktop_dir);
|
|
monitor->details->desktop_dir = NULL;
|
|
|
|
eel_preferences_remove_callback (NAUTILUS_PREFERENCES_DESKTOP_VOLUMES_VISIBLE,
|
|
desktop_volumes_visible_changed,
|
|
monitor);
|
|
|
|
if (monitor->details->mount_id != 0) {
|
|
g_source_remove (monitor->details->mount_id);
|
|
}
|
|
if (monitor->details->unmount_id != 0) {
|
|
g_source_remove (monitor->details->unmount_id);
|
|
}
|
|
if (monitor->details->changed_id != 0) {
|
|
g_source_remove (monitor->details->changed_id);
|
|
}
|
|
|
|
g_free (monitor->details);
|
|
|
|
EEL_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
|
|
}
|
|
|
|
static void
|
|
nautilus_desktop_link_monitor_class_init (gpointer klass)
|
|
{
|
|
GObjectClass *object_class;
|
|
|
|
object_class = G_OBJECT_CLASS (klass);
|
|
|
|
object_class->finalize = desktop_link_monitor_finalize;
|
|
|
|
}
|