nautilus-monitor.c 4.67 KB
Newer Older
1
/*
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 *  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>
 */
25

Darin Adler's avatar
Darin Adler committed
26
#include <config.h>
27
#include "nautilus-monitor.h"
Darin Adler's avatar
Darin Adler committed
28
#include "nautilus-file-changes-queue.h"
Alex Graveley's avatar
Alex Graveley committed
29 30
#include "nautilus-file-utilities.h"

31
#include <gio/gio.h>
32

33 34 35 36 37
struct NautilusMonitor
{
    GFileMonitor *monitor;
    GVolumeMonitor *volume_monitor;
    GFile *location;
Darin Adler's avatar
Darin Adler committed
38
};
39

Alex Graveley's avatar
Alex Graveley committed
40
static gboolean call_consume_changes_idle_id = 0;
41

Alex Graveley's avatar
Alex Graveley committed
42 43
static gboolean
call_consume_changes_idle_cb (gpointer not_used)
44
{
45 46 47
    nautilus_file_changes_consume_changes (TRUE);
    call_consume_changes_idle_id = 0;
    return FALSE;
48 49
}

50 51 52
static void
schedule_call_consume_changes (void)
{
53 54 55 56 57
    if (call_consume_changes_idle_id == 0)
    {
        call_consume_changes_idle_id =
            g_idle_add (call_consume_changes_idle_cb, NULL);
    }
58 59 60 61
}

static void
mount_removed (GVolumeMonitor *volume_monitor,
62 63
               GMount         *mount,
               gpointer        user_data)
64
{
65 66
    NautilusMonitor *monitor = user_data;
    GFile *mount_location;
67

68
    mount_location = g_mount_get_root (mount);
69

70 71 72 73 74
    if (g_file_has_prefix (monitor->location, mount_location))
    {
        nautilus_file_changes_queue_file_removed (monitor->location);
        schedule_call_consume_changes ();
    }
75

76
    g_object_unref (mount_location);
77 78
}

Alexander Larsson's avatar
Alexander Larsson committed
79
static void
80 81 82 83 84
dir_changed (GFileMonitor      *monitor,
             GFile             *child,
             GFile             *other_file,
             GFileMonitorEvent  event_type,
             gpointer           user_data)
85
{
86
    char *to_uri;
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126

    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 ();
Alex Graveley's avatar
Alex Graveley committed
127
}
128

Alexander Larsson's avatar
Alexander Larsson committed
129 130
NautilusMonitor *
nautilus_monitor_directory (GFile *location)
Alex Graveley's avatar
Alex Graveley committed
131
{
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
    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;
162 163
}

164
void
Darin Adler's avatar
Darin Adler committed
165
nautilus_monitor_cancel (NautilusMonitor *monitor)
Alex Graveley's avatar
Alex Graveley committed
166
{
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
    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);
182
}