/*
* 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 .
*
* Authors: Seth Nickell
* Darin Adler
* Alex Graveley
* Carlos Soriano
*/
#include
#include "nautilus-monitor.h"
#include "nautilus-file-changes-queue.h"
#include "nautilus-file-utilities.h"
#include
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);
}