Branch data Line data Source code
1 : : /* GIO - GLib Input, Output and Streaming Library
2 : : *
3 : : * Copyright (C) 2006-2007 Red Hat, Inc.
4 : : *
5 : : * SPDX-License-Identifier: LGPL-2.1-or-later
6 : : *
7 : : * This library is free software; you can redistribute it and/or
8 : : * modify it under the terms of the GNU Lesser General Public
9 : : * License as published by the Free Software Foundation; either
10 : : * version 2.1 of the License, or (at your option) any later version.
11 : : *
12 : : * This library 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 : : * Lesser General Public License for more details.
16 : : *
17 : : * You should have received a copy of the GNU Lesser General
18 : : * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 : : *
20 : : * Author: Alexander Larsson <alexl@redhat.com>
21 : : */
22 : :
23 : : #include "config.h"
24 : : #include <string.h>
25 : :
26 : : #include "gfilemonitor.h"
27 : : #include "gioenumtypes.h"
28 : : #include "gmarshal-internal.h"
29 : : #include "gfile.h"
30 : : #include "gvfs.h"
31 : : #include "glibintl.h"
32 : :
33 : : /**
34 : : * GFileMonitor:
35 : : *
36 : : * Monitors a file or directory for changes.
37 : : *
38 : : * To obtain a `GFileMonitor` for a file or directory, use
39 : : * [method@Gio.File.monitor], [method@Gio.File.monitor_file], or
40 : : * [method@Gio.File.monitor_directory].
41 : : *
42 : : * To get informed about changes to the file or directory you are
43 : : * monitoring, connect to the [signal@Gio.FileMonitor::changed] signal. The
44 : : * signal will be emitted in the thread-default main context (see
45 : : * [method@GLib.MainContext.push_thread_default]) of the thread that the monitor
46 : : * was created in (though if the global default main context is blocked, this
47 : : * may cause notifications to be blocked even if the thread-default
48 : : * context is still running).
49 : : **/
50 : :
51 : : #define DEFAULT_RATE_LIMIT_MSECS 800
52 : :
53 : : struct _GFileMonitorPrivate
54 : : {
55 : : gboolean cancelled;
56 : : };
57 : :
58 : 3675 : G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GFileMonitor, g_file_monitor, G_TYPE_OBJECT)
59 : :
60 : : enum
61 : : {
62 : : PROP_0,
63 : : PROP_RATE_LIMIT,
64 : : PROP_CANCELLED
65 : : };
66 : :
67 : : static guint g_file_monitor_changed_signal;
68 : :
69 : : static void
70 : 0 : g_file_monitor_set_property (GObject *object,
71 : : guint prop_id,
72 : : const GValue *value,
73 : : GParamSpec *pspec)
74 : : {
75 : : //GFileMonitor *monitor;
76 : :
77 : : //monitor = G_FILE_MONITOR (object);
78 : :
79 : 0 : switch (prop_id)
80 : : {
81 : 0 : case PROP_RATE_LIMIT:
82 : : /* not supported by default */
83 : 0 : break;
84 : :
85 : 0 : default:
86 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
87 : 0 : break;
88 : : }
89 : 0 : }
90 : :
91 : : static void
92 : 0 : g_file_monitor_get_property (GObject *object,
93 : : guint prop_id,
94 : : GValue *value,
95 : : GParamSpec *pspec)
96 : : {
97 : 0 : switch (prop_id)
98 : : {
99 : 0 : case PROP_RATE_LIMIT:
100 : : /* we expect this to be overridden... */
101 : 0 : g_value_set_int (value, DEFAULT_RATE_LIMIT_MSECS);
102 : 0 : break;
103 : :
104 : 0 : case PROP_CANCELLED:
105 : : //g_mutex_lock (&fms->lock);
106 : 0 : g_value_set_boolean (value, FALSE);//fms->cancelled);
107 : : //g_mutex_unlock (&fms->lock);
108 : 0 : break;
109 : :
110 : 0 : default:
111 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
112 : 0 : break;
113 : : }
114 : 0 : }
115 : :
116 : : static void
117 : 484 : g_file_monitor_dispose (GObject *object)
118 : : {
119 : 484 : GFileMonitor *monitor = G_FILE_MONITOR (object);
120 : :
121 : : /* Make sure we cancel on last unref */
122 : 484 : g_file_monitor_cancel (monitor);
123 : :
124 : 484 : G_OBJECT_CLASS (g_file_monitor_parent_class)->dispose (object);
125 : 484 : }
126 : :
127 : : static void
128 : 676 : g_file_monitor_init (GFileMonitor *monitor)
129 : : {
130 : 676 : monitor->priv = g_file_monitor_get_instance_private (monitor);
131 : 676 : }
132 : :
133 : : static void
134 : 58 : g_file_monitor_class_init (GFileMonitorClass *klass)
135 : : {
136 : : GObjectClass *object_class;
137 : :
138 : 58 : object_class = G_OBJECT_CLASS (klass);
139 : 58 : object_class->dispose = g_file_monitor_dispose;
140 : 58 : object_class->get_property = g_file_monitor_get_property;
141 : 58 : object_class->set_property = g_file_monitor_set_property;
142 : :
143 : : /**
144 : : * GFileMonitor::changed:
145 : : * @monitor: a #GFileMonitor.
146 : : * @file: a #GFile.
147 : : * @other_file: (nullable): a #GFile or #NULL.
148 : : * @event_type: a #GFileMonitorEvent.
149 : : *
150 : : * Emitted when @file has been changed.
151 : : *
152 : : * If using %G_FILE_MONITOR_WATCH_MOVES on a directory monitor, and
153 : : * the information is available (and if supported by the backend),
154 : : * @event_type may be %G_FILE_MONITOR_EVENT_RENAMED,
155 : : * %G_FILE_MONITOR_EVENT_MOVED_IN or %G_FILE_MONITOR_EVENT_MOVED_OUT.
156 : : *
157 : : * In all cases @file will be a child of the monitored directory. For
158 : : * renames, @file will be the old name and @other_file is the new
159 : : * name. For "moved in" events, @file is the name of the file that
160 : : * appeared and @other_file is the old name that it was moved from (in
161 : : * another directory). For "moved out" events, @file is the name of
162 : : * the file that used to be in this directory and @other_file is the
163 : : * name of the file at its new location.
164 : : *
165 : : * It makes sense to treat %G_FILE_MONITOR_EVENT_MOVED_IN as
166 : : * equivalent to %G_FILE_MONITOR_EVENT_CREATED and
167 : : * %G_FILE_MONITOR_EVENT_MOVED_OUT as equivalent to
168 : : * %G_FILE_MONITOR_EVENT_DELETED, with extra information.
169 : : * %G_FILE_MONITOR_EVENT_RENAMED is equivalent to a delete/create
170 : : * pair. This is exactly how the events will be reported in the case
171 : : * that the %G_FILE_MONITOR_WATCH_MOVES flag is not in use.
172 : : *
173 : : * If using the deprecated flag %G_FILE_MONITOR_SEND_MOVED flag and @event_type is
174 : : * %G_FILE_MONITOR_EVENT_MOVED, @file will be set to a #GFile containing the
175 : : * old path, and @other_file will be set to a #GFile containing the new path.
176 : : *
177 : : * In all the other cases, @other_file will be set to #NULL.
178 : : **/
179 : 58 : g_file_monitor_changed_signal = g_signal_new (I_("changed"),
180 : : G_TYPE_FILE_MONITOR,
181 : : G_SIGNAL_RUN_LAST,
182 : : G_STRUCT_OFFSET (GFileMonitorClass, changed),
183 : : NULL, NULL,
184 : : _g_cclosure_marshal_VOID__OBJECT_OBJECT_ENUM,
185 : : G_TYPE_NONE, 3,
186 : : G_TYPE_FILE, G_TYPE_FILE, G_TYPE_FILE_MONITOR_EVENT);
187 : 58 : g_signal_set_va_marshaller (g_file_monitor_changed_signal,
188 : : G_TYPE_FROM_CLASS (klass),
189 : : _g_cclosure_marshal_VOID__OBJECT_OBJECT_ENUMv);
190 : :
191 : : /**
192 : : * GFileMonitor:rate-limit:
193 : : *
194 : : * The limit of the monitor to watch for changes, in milliseconds.
195 : : */
196 : 58 : g_object_class_install_property (object_class, PROP_RATE_LIMIT,
197 : : g_param_spec_int ("rate-limit", NULL, NULL,
198 : : 0, G_MAXINT, DEFAULT_RATE_LIMIT_MSECS, G_PARAM_READWRITE |
199 : : G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
200 : :
201 : : /**
202 : : * GFileMonitor:cancelled:
203 : : *
204 : : * Whether the monitor has been cancelled.
205 : : */
206 : 58 : g_object_class_install_property (object_class, PROP_CANCELLED,
207 : : g_param_spec_boolean ("cancelled", NULL, NULL,
208 : : FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
209 : 58 : }
210 : :
211 : : /**
212 : : * g_file_monitor_is_cancelled:
213 : : * @monitor: a #GFileMonitor
214 : : *
215 : : * Returns whether the monitor is canceled.
216 : : *
217 : : * Returns: %TRUE if monitor is canceled. %FALSE otherwise.
218 : : **/
219 : : gboolean
220 : 10 : g_file_monitor_is_cancelled (GFileMonitor *monitor)
221 : : {
222 : : gboolean res;
223 : :
224 : 10 : g_return_val_if_fail (G_IS_FILE_MONITOR (monitor), FALSE);
225 : :
226 : 10 : res = monitor->priv->cancelled;
227 : :
228 : 10 : return res;
229 : : }
230 : :
231 : : /**
232 : : * g_file_monitor_cancel:
233 : : * @monitor: a #GFileMonitor.
234 : : *
235 : : * Cancels a file monitor.
236 : : *
237 : : * Returns: always %TRUE
238 : : **/
239 : : gboolean
240 : 860 : g_file_monitor_cancel (GFileMonitor *monitor)
241 : : {
242 : 860 : g_return_val_if_fail (G_IS_FILE_MONITOR (monitor), FALSE);
243 : :
244 : 860 : if (!monitor->priv->cancelled)
245 : : {
246 : 484 : G_FILE_MONITOR_GET_CLASS (monitor)->cancel (monitor);
247 : :
248 : 484 : monitor->priv->cancelled = TRUE;
249 : 484 : g_object_notify (G_OBJECT (monitor), "cancelled");
250 : : }
251 : :
252 : 860 : return TRUE;
253 : : }
254 : :
255 : : /**
256 : : * g_file_monitor_set_rate_limit:
257 : : * @monitor: a #GFileMonitor.
258 : : * @limit_msecs: a non-negative integer with the limit in milliseconds
259 : : * to poll for changes
260 : : *
261 : : * Sets the rate limit to which the @monitor will report
262 : : * consecutive change events to the same file.
263 : : */
264 : : void
265 : 12 : g_file_monitor_set_rate_limit (GFileMonitor *monitor,
266 : : gint limit_msecs)
267 : : {
268 : 12 : g_object_set (monitor, "rate-limit", limit_msecs, NULL);
269 : 12 : }
270 : :
271 : : /**
272 : : * g_file_monitor_emit_event:
273 : : * @monitor: a #GFileMonitor.
274 : : * @child: a #GFile.
275 : : * @other_file: a #GFile.
276 : : * @event_type: a set of #GFileMonitorEvent flags.
277 : : *
278 : : * Emits the #GFileMonitor::changed signal if a change
279 : : * has taken place. Should be called from file monitor
280 : : * implementations only.
281 : : *
282 : : * Implementations are responsible to call this method from the
283 : : * [thread-default main context][g-main-context-push-thread-default] of the
284 : : * thread that the monitor was created in.
285 : : **/
286 : : void
287 : 548 : g_file_monitor_emit_event (GFileMonitor *monitor,
288 : : GFile *child,
289 : : GFile *other_file,
290 : : GFileMonitorEvent event_type)
291 : : {
292 : 548 : g_return_if_fail (G_IS_FILE_MONITOR (monitor));
293 : 548 : g_return_if_fail (G_IS_FILE (child));
294 : 548 : g_return_if_fail (!other_file || G_IS_FILE (other_file));
295 : :
296 : 548 : if (monitor->priv->cancelled)
297 : 0 : return;
298 : :
299 : 548 : g_signal_emit (monitor, g_file_monitor_changed_signal, 0, child, other_file, event_type);
300 : : }
|