1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
2
3 nemo-monitor.c: file and directory change monitoring for nemo
4
5 Copyright (C) 2000, 2001 Eazel, Inc.
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public
18 License along with this program; if not, write to the
19 Free Software Foundation, Inc., 51 Franklin Street - Suite 500,
20 Boston, MA 02110-1335, USA.
21
22 Authors: Seth Nickell <seth@eazel.com>
23 Darin Adler <darin@bentspoon.com>
24 Alex Graveley <alex@ximian.com>
25 */
26
27 #include <config.h>
28 #include "nemo-monitor.h"
29 #include "nemo-file-changes-queue.h"
30 #include "nemo-file-utilities.h"
31
32 #include <gio/gio.h>
33
34 struct NemoMonitor {
35 GFileMonitor *monitor;
36 GVolumeMonitor *volume_monitor;
37 GFile *location;
38 };
39
40 gboolean
nemo_monitor_active(void)41 nemo_monitor_active (void)
42 {
43 static gboolean tried_monitor = FALSE;
44 static gboolean monitor_success;
45 GFileMonitor *dir_monitor;
46 GFile *file;
47
48 if (tried_monitor == FALSE) {
49 file = g_file_new_for_path (g_get_home_dir ());
50 dir_monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL);
51 g_object_unref (file);
52
53 monitor_success = (dir_monitor != NULL);
54 if (dir_monitor) {
55 g_object_unref (dir_monitor);
56 }
57
58 tried_monitor = TRUE;
59 }
60
61 return monitor_success;
62 }
63
64 static gboolean call_consume_changes_idle_id = 0;
65
66 static gboolean
call_consume_changes_idle_cb(gpointer not_used)67 call_consume_changes_idle_cb (gpointer not_used)
68 {
69 nemo_file_changes_consume_changes (TRUE);
70 call_consume_changes_idle_id = 0;
71 return FALSE;
72 }
73
74 static void
schedule_call_consume_changes(void)75 schedule_call_consume_changes (void)
76 {
77 if (call_consume_changes_idle_id == 0) {
78 call_consume_changes_idle_id =
79 g_idle_add (call_consume_changes_idle_cb, NULL);
80 }
81 }
82
83 static void
mount_removed(GVolumeMonitor * volume_monitor,GMount * mount,gpointer user_data)84 mount_removed (GVolumeMonitor *volume_monitor,
85 GMount *mount,
86 gpointer user_data)
87 {
88 NemoMonitor *monitor = user_data;
89 GFile *mount_location;
90
91 mount_location = g_mount_get_root (mount);
92
93 if (g_file_has_prefix (monitor->location, mount_location)) {
94 nemo_file_changes_queue_file_removed (monitor->location);
95 schedule_call_consume_changes ();
96 }
97
98 g_object_unref (mount_location);
99 }
100
101 static void
dir_changed(GFileMonitor * monitor,GFile * child,GFile * other_file,GFileMonitorEvent event_type,gpointer user_data)102 dir_changed (GFileMonitor* monitor,
103 GFile *child,
104 GFile *other_file,
105 GFileMonitorEvent event_type,
106 gpointer user_data)
107 {
108 char *uri, *to_uri;
109
110 uri = g_file_get_uri (child);
111 // g_printerr ("ATT CHANGED %s %d\n", uri, event_type);
112 to_uri = NULL;
113 if (other_file) {
114 to_uri = g_file_get_uri (other_file);
115 }
116
117 switch (event_type) {
118 case G_FILE_MONITOR_EVENT_MOVED:
119 case G_FILE_MONITOR_EVENT_RENAMED:
120 case G_FILE_MONITOR_EVENT_MOVED_IN:
121 case G_FILE_MONITOR_EVENT_MOVED_OUT:
122 default:
123 case G_FILE_MONITOR_EVENT_CHANGED:
124 /* ignore */
125 break;
126 case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED:
127 case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
128 nemo_file_changes_queue_file_changed (child);
129 break;
130 case G_FILE_MONITOR_EVENT_DELETED:
131 nemo_file_changes_queue_file_removed (child);
132 break;
133 case G_FILE_MONITOR_EVENT_CREATED:
134 nemo_file_changes_queue_file_added (child);
135 break;
136
137 case G_FILE_MONITOR_EVENT_PRE_UNMOUNT:
138 /* TODO: Do something */
139 break;
140 case G_FILE_MONITOR_EVENT_UNMOUNTED:
141 /* TODO: Do something */
142 break;
143 }
144
145 g_free (uri);
146 g_free (to_uri);
147
148 schedule_call_consume_changes ();
149 }
150
151 NemoMonitor *
nemo_monitor_directory(GFile * location)152 nemo_monitor_directory (GFile *location)
153 {
154 GFileMonitor *dir_monitor;
155 NemoMonitor *ret;
156
157 ret = g_new0 (NemoMonitor, 1);
158 dir_monitor = g_file_monitor_directory (location, G_FILE_MONITOR_WATCH_MOUNTS, NULL, NULL);
159
160 if (dir_monitor != NULL) {
161 ret->monitor = dir_monitor;
162 } else if (!g_file_is_native (location)) {
163 ret->location = g_object_ref (location);
164 ret->volume_monitor = g_volume_monitor_get ();
165 }
166
167 if (ret->monitor != NULL) {
168 g_signal_connect (ret->monitor, "changed",
169 G_CALLBACK (dir_changed), ret);
170 }
171
172
173 if (ret->volume_monitor != NULL) {
174 g_signal_connect (ret->volume_monitor, "mount-removed",
175 G_CALLBACK (mount_removed), ret);
176 }
177
178 /* We return a monitor even on failure, so we can avoid later trying again */
179 return ret;
180 }
181
182 void
nemo_monitor_cancel(NemoMonitor * monitor)183 nemo_monitor_cancel (NemoMonitor *monitor)
184 {
185 if (monitor->monitor != NULL) {
186 g_signal_handlers_disconnect_by_func (monitor->monitor, dir_changed, monitor);
187 g_file_monitor_cancel (monitor->monitor);
188 g_object_unref (monitor->monitor);
189 }
190
191 if (monitor->volume_monitor != NULL) {
192 g_signal_handlers_disconnect_by_func (monitor->volume_monitor, mount_removed, monitor);
193 g_object_unref (monitor->volume_monitor);
194 }
195
196 g_clear_object (&monitor->location);
197 g_free (monitor);
198 }
199