Blame src/nautilus-monitor.c

Packit a189e0
/*
Packit a189e0
 *  nautilus-monitor.c: file and directory change monitoring for nautilus
Packit a189e0
 *
Packit a189e0
 *  Copyright (C) 2000, 2001 Eazel, Inc.
Packit a189e0
 *  Copyright (C) 2016 Red Hat
Packit a189e0
 *
Packit a189e0
 *  This program is free software; you can redistribute it and/or
Packit a189e0
 *  modify it under the terms of the GNU General Public License as
Packit a189e0
 *  published by the Free Software Foundation; either version 2 of the
Packit a189e0
 *  License, or (at your option) any later version.
Packit a189e0
 *
Packit a189e0
 *  This program is distributed in the hope that it will be useful,
Packit a189e0
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit a189e0
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit a189e0
 *  General Public License for more details.
Packit a189e0
 *
Packit a189e0
 *  You should have received a copy of the GNU General Public
Packit a189e0
 *  License along with this program; if not, see <http://www.gnu.org/licenses/>.
Packit a189e0
 *
Packit a189e0
 *  Authors: Seth Nickell <seth@eazel.com>
Packit a189e0
 *           Darin Adler <darin@bentspoon.com>
Packit a189e0
 *           Alex Graveley <alex@ximian.com>
Packit a189e0
 *           Carlos Soriano <csoriano@gnome.org>
Packit a189e0
 */
Packit a189e0
Packit a189e0
#include <config.h>
Packit a189e0
#include "nautilus-monitor.h"
Packit a189e0
#include "nautilus-file-changes-queue.h"
Packit a189e0
#include "nautilus-file-utilities.h"
Packit a189e0
Packit a189e0
#include <gio/gio.h>
Packit a189e0
Packit a189e0
struct NautilusMonitor
Packit a189e0
{
Packit a189e0
    GFileMonitor *monitor;
Packit a189e0
    GVolumeMonitor *volume_monitor;
Packit a189e0
    GFile *location;
Packit a189e0
};
Packit a189e0
Packit a189e0
static gboolean call_consume_changes_idle_id = 0;
Packit a189e0
Packit a189e0
static gboolean
Packit a189e0
call_consume_changes_idle_cb (gpointer not_used)
Packit a189e0
{
Packit a189e0
    nautilus_file_changes_consume_changes (TRUE);
Packit a189e0
    call_consume_changes_idle_id = 0;
Packit a189e0
    return FALSE;
Packit a189e0
}
Packit a189e0
Packit a189e0
static void
Packit a189e0
schedule_call_consume_changes (void)
Packit a189e0
{
Packit a189e0
    if (call_consume_changes_idle_id == 0)
Packit a189e0
    {
Packit a189e0
        call_consume_changes_idle_id =
Packit a189e0
            g_idle_add (call_consume_changes_idle_cb, NULL);
Packit a189e0
    }
Packit a189e0
}
Packit a189e0
Packit a189e0
static void
Packit a189e0
mount_removed (GVolumeMonitor *volume_monitor,
Packit a189e0
               GMount         *mount,
Packit a189e0
               gpointer        user_data)
Packit a189e0
{
Packit a189e0
    NautilusMonitor *monitor = user_data;
Packit a189e0
    GFile *mount_location;
Packit a189e0
Packit a189e0
    mount_location = g_mount_get_root (mount);
Packit a189e0
Packit a189e0
    if (g_file_has_prefix (monitor->location, mount_location))
Packit a189e0
    {
Packit a189e0
        nautilus_file_changes_queue_file_removed (monitor->location);
Packit a189e0
        schedule_call_consume_changes ();
Packit a189e0
    }
Packit a189e0
Packit a189e0
    g_object_unref (mount_location);
Packit a189e0
}
Packit a189e0
Packit a189e0
static void
Packit a189e0
dir_changed (GFileMonitor      *monitor,
Packit a189e0
             GFile             *child,
Packit a189e0
             GFile             *other_file,
Packit a189e0
             GFileMonitorEvent  event_type,
Packit a189e0
             gpointer           user_data)
Packit a189e0
{
Packit a189e0
    char *uri, *to_uri;
Packit a189e0
Packit a189e0
    uri = g_file_get_uri (child);
Packit a189e0
    to_uri = NULL;
Packit a189e0
    if (other_file)
Packit a189e0
    {
Packit a189e0
        to_uri = g_file_get_uri (other_file);
Packit a189e0
    }
Packit a189e0
Packit a189e0
    switch (event_type)
Packit a189e0
    {
Packit a189e0
        default:
Packit a189e0
        case G_FILE_MONITOR_EVENT_CHANGED:
Packit a189e0
        {
Packit a189e0
            /* ignore */
Packit a189e0
        }
Packit a189e0
        break;
Packit a189e0
Packit a189e0
        case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED:
Packit a189e0
        case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
Packit a189e0
        {
Packit a189e0
            nautilus_file_changes_queue_file_changed (child);
Packit a189e0
        }
Packit a189e0
        break;
Packit a189e0
Packit a189e0
        case G_FILE_MONITOR_EVENT_UNMOUNTED:
Packit a189e0
        case G_FILE_MONITOR_EVENT_DELETED:
Packit a189e0
        {
Packit a189e0
            nautilus_file_changes_queue_file_removed (child);
Packit a189e0
        }
Packit a189e0
        break;
Packit a189e0
Packit a189e0
        case G_FILE_MONITOR_EVENT_CREATED:
Packit a189e0
        {
Packit a189e0
            nautilus_file_changes_queue_file_added (child);
Packit a189e0
        }
Packit a189e0
        break;
Packit a189e0
    }
Packit a189e0
Packit a189e0
    g_free (uri);
Packit a189e0
    g_free (to_uri);
Packit a189e0
Packit a189e0
    schedule_call_consume_changes ();
Packit a189e0
}
Packit a189e0
Packit a189e0
NautilusMonitor *
Packit a189e0
nautilus_monitor_directory (GFile *location)
Packit a189e0
{
Packit a189e0
    GFileMonitor *dir_monitor;
Packit a189e0
    NautilusMonitor *ret;
Packit a189e0
Packit a189e0
    ret = g_slice_new0 (NautilusMonitor);
Packit a189e0
    dir_monitor = g_file_monitor_directory (location, G_FILE_MONITOR_WATCH_MOUNTS, NULL, NULL);
Packit a189e0
Packit a189e0
    if (dir_monitor != NULL)
Packit a189e0
    {
Packit a189e0
        ret->monitor = dir_monitor;
Packit a189e0
    }
Packit a189e0
    else if (!g_file_is_native (location))
Packit a189e0
    {
Packit a189e0
        ret->location = g_object_ref (location);
Packit a189e0
        ret->volume_monitor = g_volume_monitor_get ();
Packit a189e0
    }
Packit a189e0
Packit a189e0
    if (ret->monitor != NULL)
Packit a189e0
    {
Packit a189e0
        g_signal_connect (ret->monitor, "changed",
Packit a189e0
                          G_CALLBACK (dir_changed), ret);
Packit a189e0
    }
Packit a189e0
Packit a189e0
    if (ret->volume_monitor != NULL)
Packit a189e0
    {
Packit a189e0
        g_signal_connect (ret->volume_monitor, "mount-removed",
Packit a189e0
                          G_CALLBACK (mount_removed), ret);
Packit a189e0
    }
Packit a189e0
Packit a189e0
    /* We return a monitor even on failure, so we can avoid later trying again */
Packit a189e0
    return ret;
Packit a189e0
}
Packit a189e0
Packit a189e0
void
Packit a189e0
nautilus_monitor_cancel (NautilusMonitor *monitor)
Packit a189e0
{
Packit a189e0
    if (monitor->monitor != NULL)
Packit a189e0
    {
Packit a189e0
        g_signal_handlers_disconnect_by_func (monitor->monitor, dir_changed, monitor);
Packit a189e0
        g_file_monitor_cancel (monitor->monitor);
Packit a189e0
        g_object_unref (monitor->monitor);
Packit a189e0
    }
Packit a189e0
Packit a189e0
    if (monitor->volume_monitor != NULL)
Packit a189e0
    {
Packit a189e0
        g_signal_handlers_disconnect_by_func (monitor->volume_monitor, mount_removed, monitor);
Packit a189e0
        g_object_unref (monitor->volume_monitor);
Packit a189e0
    }
Packit a189e0
Packit a189e0
    g_clear_object (&monitor->location);
Packit a189e0
    g_slice_free (NautilusMonitor, monitor);
Packit a189e0
}