summaryrefslogtreecommitdiff
path: root/nautilus-desktop/nautilus-desktop-link-monitor.c
diff options
context:
space:
mode:
Diffstat (limited to 'nautilus-desktop/nautilus-desktop-link-monitor.c')
-rw-r--r--nautilus-desktop/nautilus-desktop-link-monitor.c432
1 files changed, 432 insertions, 0 deletions
diff --git a/nautilus-desktop/nautilus-desktop-link-monitor.c b/nautilus-desktop/nautilus-desktop-link-monitor.c
new file mode 100644
index 000000000..54ce6daf9
--- /dev/null
+++ b/nautilus-desktop/nautilus-desktop-link-monitor.c
@@ -0,0 +1,432 @@
+/*
+ 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 <http://www.gnu.org/licenses/>.
+
+ 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-desktop-directory.h"
+
+#include <eel/eel-debug.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 <libnautilus-private/nautilus-global-preferences.h>
+#include <libnautilus-private/nautilus-directory.h>
+
+#include <string.h>
+
+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));
+}