/* * 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, see . * * Author: Alexander Larsson */ #include #include "nautilus-desktop-link-monitor.h" #include "nautilus-desktop-link.h" #include "nautilus-desktop-icon-file.h" #include "nautilus-desktop-directory.h" #include #include #include #include #include #include #include #include #include #include struct NautilusDesktopLinkMonitorDetails { GVolumeMonitor *volume_monitor; NautilusDirectory *desktop_dir; NautilusDesktopLink *home_link; NautilusDesktopLink *trash_link; NautilusDesktopLink *network_link; GList *mount_links; }; G_DEFINE_TYPE (NautilusDesktopLinkMonitor, nautilus_desktop_link_monitor, G_TYPE_OBJECT); static NautilusDesktopLinkMonitor *the_link_monitor = NULL; void nautilus_desktop_link_monitor_shutdown (void) { g_clear_object (&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 (nautilus_desktop_link_monitor_shutdown); } return the_link_monitor; } 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)) && g_settings_get_boolean (nautilus_desktop_preferences, 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 (g_settings_get_boolean (nautilus_desktop_preferences, 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_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 (g_settings_get_boolean (nautilus_desktop_preferences, 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, GCallback callback, gpointer callback_data) { char *detailed_signal; if (g_settings_get_boolean (nautilus_desktop_preferences, preference_key)) { *link_ref = nautilus_desktop_link_new (link_type); } detailed_signal = g_strconcat ("changed::", preference_key, NULL); g_signal_connect_swapped (nautilus_desktop_preferences, detailed_signal, callback, callback_data); g_free (detailed_signal); } static void nautilus_desktop_link_monitor_init (NautilusDesktopLinkMonitor *monitor) { GList *l, *mounts; GMount *mount; monitor->details = G_TYPE_INSTANCE_GET_PRIVATE (monitor, NAUTILUS_TYPE_DESKTOP_LINK_MONITOR, NautilusDesktopLinkMonitorDetails); the_link_monitor = monitor; 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, G_CALLBACK (desktop_home_visible_changed), monitor); create_link_and_add_preference (&monitor->details->trash_link, NAUTILUS_DESKTOP_LINK_TRASH, NAUTILUS_PREFERENCES_DESKTOP_TRASH_VISIBLE, G_CALLBACK (desktop_trash_visible_changed), monitor); create_link_and_add_preference (&monitor->details->network_link, NAUTILUS_DESKTOP_LINK_NETWORK, NAUTILUS_PREFERENCES_DESKTOP_NETWORK_VISIBLE, G_CALLBACK (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); g_signal_connect_swapped (nautilus_desktop_preferences, "changed::" NAUTILUS_PREFERENCES_DESKTOP_VOLUMES_VISIBLE, G_CALLBACK (desktop_volumes_visible_changed), monitor); g_signal_connect_object (monitor->details->volume_monitor, "mount-added", G_CALLBACK (mount_added_callback), monitor, 0); g_signal_connect_object (monitor->details->volume_monitor, "mount-removed", G_CALLBACK (mount_removed_callback), monitor, 0); 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, GCallback callback, gpointer callback_data) { if (*link_ref != NULL) { g_object_unref (*link_ref); *link_ref = NULL; } g_signal_handlers_disconnect_by_func (nautilus_desktop_preferences, callback, callback_data); } static void desktop_link_monitor_finalize (GObject *object) { NautilusDesktopLinkMonitor *monitor; monitor = NAUTILUS_DESKTOP_LINK_MONITOR (object); /* Default links */ remove_link_and_preference (&monitor->details->home_link, NAUTILUS_PREFERENCES_DESKTOP_HOME_VISIBLE, G_CALLBACK (desktop_home_visible_changed), monitor); remove_link_and_preference (&monitor->details->trash_link, NAUTILUS_PREFERENCES_DESKTOP_TRASH_VISIBLE, G_CALLBACK (desktop_trash_visible_changed), monitor); remove_link_and_preference (&monitor->details->network_link, NAUTILUS_PREFERENCES_DESKTOP_NETWORK_VISIBLE, G_CALLBACK (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; g_signal_handlers_disconnect_by_func (nautilus_desktop_preferences, desktop_volumes_visible_changed, monitor); g_object_unref (monitor->details->volume_monitor); G_OBJECT_CLASS (nautilus_desktop_link_monitor_parent_class)->finalize (object); } static void nautilus_desktop_link_monitor_class_init (NautilusDesktopLinkMonitorClass *klass) { GObjectClass *object_class; object_class = G_OBJECT_CLASS (klass); object_class->finalize = desktop_link_monitor_finalize; g_type_class_add_private (klass, sizeof (NautilusDesktopLinkMonitorDetails)); }