summaryrefslogtreecommitdiffstats
path: root/src/nautilus-monitor.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nautilus-monitor.c')
-rw-r--r--src/nautilus-monitor.c182
1 files changed, 182 insertions, 0 deletions
diff --git a/src/nautilus-monitor.c b/src/nautilus-monitor.c
new file mode 100644
index 0000000..cf3ef4e
--- /dev/null
+++ b/src/nautilus-monitor.c
@@ -0,0 +1,182 @@
+/*
+ * nautilus-monitor.c: file and directory change monitoring for nautilus
+ *
+ * Copyright (C) 2000, 2001 Eazel, Inc.
+ * Copyright (C) 2016 Red Hat
+ *
+ * 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/>.
+ *
+ * Authors: Seth Nickell <seth@eazel.com>
+ * Darin Adler <darin@bentspoon.com>
+ * Alex Graveley <alex@ximian.com>
+ * Carlos Soriano <csoriano@gnome.org>
+ */
+
+#include <config.h>
+#include "nautilus-monitor.h"
+#include "nautilus-file-changes-queue.h"
+#include "nautilus-file-utilities.h"
+
+#include <gio/gio.h>
+
+struct NautilusMonitor
+{
+ GFileMonitor *monitor;
+ GVolumeMonitor *volume_monitor;
+ GFile *location;
+};
+
+static gboolean call_consume_changes_idle_id = 0;
+
+static gboolean
+call_consume_changes_idle_cb (gpointer not_used)
+{
+ nautilus_file_changes_consume_changes (TRUE);
+ call_consume_changes_idle_id = 0;
+ return FALSE;
+}
+
+static void
+schedule_call_consume_changes (void)
+{
+ if (call_consume_changes_idle_id == 0)
+ {
+ call_consume_changes_idle_id =
+ g_idle_add (call_consume_changes_idle_cb, NULL);
+ }
+}
+
+static void
+mount_removed (GVolumeMonitor *volume_monitor,
+ GMount *mount,
+ gpointer user_data)
+{
+ NautilusMonitor *monitor = user_data;
+ GFile *mount_location;
+
+ mount_location = g_mount_get_root (mount);
+
+ if (g_file_has_prefix (monitor->location, mount_location))
+ {
+ nautilus_file_changes_queue_file_removed (monitor->location);
+ schedule_call_consume_changes ();
+ }
+
+ g_object_unref (mount_location);
+}
+
+static void
+dir_changed (GFileMonitor *monitor,
+ GFile *child,
+ GFile *other_file,
+ GFileMonitorEvent event_type,
+ gpointer user_data)
+{
+ char *to_uri;
+
+ to_uri = NULL;
+ if (other_file)
+ {
+ to_uri = g_file_get_uri (other_file);
+ }
+
+ switch (event_type)
+ {
+ default:
+ case G_FILE_MONITOR_EVENT_CHANGED:
+ {
+ /* ignore */
+ }
+ break;
+
+ case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED:
+ case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
+ {
+ nautilus_file_changes_queue_file_changed (child);
+ }
+ break;
+
+ case G_FILE_MONITOR_EVENT_UNMOUNTED:
+ case G_FILE_MONITOR_EVENT_DELETED:
+ {
+ nautilus_file_changes_queue_file_removed (child);
+ }
+ break;
+
+ case G_FILE_MONITOR_EVENT_CREATED:
+ {
+ nautilus_file_changes_queue_file_added (child);
+ }
+ break;
+ }
+
+ g_free (to_uri);
+
+ schedule_call_consume_changes ();
+}
+
+NautilusMonitor *
+nautilus_monitor_directory (GFile *location)
+{
+ GFileMonitor *dir_monitor;
+ NautilusMonitor *ret;
+
+ ret = g_slice_new0 (NautilusMonitor);
+ dir_monitor = g_file_monitor_directory (location, G_FILE_MONITOR_WATCH_MOUNTS, NULL, NULL);
+
+ if (dir_monitor != NULL)
+ {
+ ret->monitor = dir_monitor;
+ }
+ else if (!g_file_is_native (location))
+ {
+ ret->location = g_object_ref (location);
+ ret->volume_monitor = g_volume_monitor_get ();
+ }
+
+ if (ret->monitor != NULL)
+ {
+ g_signal_connect (ret->monitor, "changed",
+ G_CALLBACK (dir_changed), ret);
+ }
+
+ if (ret->volume_monitor != NULL)
+ {
+ g_signal_connect (ret->volume_monitor, "mount-removed",
+ G_CALLBACK (mount_removed), ret);
+ }
+
+ /* We return a monitor even on failure, so we can avoid later trying again */
+ return ret;
+}
+
+void
+nautilus_monitor_cancel (NautilusMonitor *monitor)
+{
+ if (monitor->monitor != NULL)
+ {
+ g_signal_handlers_disconnect_by_func (monitor->monitor, dir_changed, monitor);
+ g_file_monitor_cancel (monitor->monitor);
+ g_object_unref (monitor->monitor);
+ }
+
+ if (monitor->volume_monitor != NULL)
+ {
+ g_signal_handlers_disconnect_by_func (monitor->volume_monitor, mount_removed, monitor);
+ g_object_unref (monitor->volume_monitor);
+ }
+
+ g_clear_object (&monitor->location);
+ g_slice_free (NautilusMonitor, monitor);
+}