1 /*
2 * Nautilus-Actions
3 * A Nautilus extension which offers configurable context menu actions.
4 *
5 * Copyright (C) 2005 The GNOME Foundation
6 * Copyright (C) 2006-2008 Frederic Ruaudel and others (see AUTHORS)
7 * Copyright (C) 2009-2014 Pierre Wieser and others (see AUTHORS)
8 *
9 * Nautilus-Actions is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
13 *
14 * Nautilus-Actions is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with Nautilus-Actions; see the file COPYING. If not, see
21 * <http://www.gnu.org/licenses/>.
22 *
23 * Authors:
24 * Frederic Ruaudel <grumz@grumz.net>
25 * Rodrigo Moya <rodrigo@gnome-db.org>
26 * Pierre Wieser <pwieser@trychlos.org>
27 * ... and many others (see AUTHORS)
28 */
29
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
33
34 #include <gio/gio.h>
35
36 #include "nadp-monitor.h"
37
38 /* private class data
39 */
40 struct _NadpMonitorClassPrivate {
41 void *empty; /* so that gcc -pedantic is happy */
42 };
43
44 /* private instance data
45 */
46 struct _NadpMonitorPrivate {
47 gboolean dispose_has_run;
48 NadpDesktopProvider *provider;
49 gchar *name;
50 GFile *file;
51 GFileMonitor *monitor;
52 gulong handler;
53 };
54
55 static GObjectClass *st_parent_class = NULL;
56
57 static GType register_type( void );
58 static void class_init( NadpMonitorClass *klass );
59 static void instance_init( GTypeInstance *instance, gpointer klass );
60 static void instance_dispose( GObject *object );
61 static void instance_finalize( GObject *object );
62
63 static void on_monitor_changed( GFileMonitor *monitor, GFile *file, GFile *other_file, GFileMonitorEvent event_type, NadpMonitor *my_monitor );
64
65 GType
nadp_monitor_get_type(void)66 nadp_monitor_get_type( void )
67 {
68 static GType class_type = 0;
69
70 if( !class_type ){
71 class_type = register_type();
72 }
73
74 return( class_type );
75 }
76
77 static GType
register_type(void)78 register_type( void )
79 {
80 static const gchar *thisfn = "nadp_monitor_register_type";
81 GType type;
82
83 static GTypeInfo info = {
84 sizeof( NadpMonitorClass ),
85 NULL,
86 NULL,
87 ( GClassInitFunc ) class_init,
88 NULL,
89 NULL,
90 sizeof( NadpMonitor ),
91 0,
92 ( GInstanceInitFunc ) instance_init
93 };
94
95 g_debug( "%s", thisfn );
96
97 type = g_type_register_static( G_TYPE_OBJECT, "NadpMonitor", &info, 0 );
98
99 return( type );
100 }
101
102 static void
class_init(NadpMonitorClass * klass)103 class_init( NadpMonitorClass *klass )
104 {
105 static const gchar *thisfn = "nadp_monitor_class_init";
106 GObjectClass *object_class;
107
108 g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
109
110 st_parent_class = g_type_class_peek_parent( klass );
111
112 object_class = G_OBJECT_CLASS( klass );
113 object_class->dispose = instance_dispose;
114 object_class->finalize = instance_finalize;
115
116 klass->private = g_new0( NadpMonitorClassPrivate, 1 );
117 }
118
119 static void
instance_init(GTypeInstance * instance,gpointer klass)120 instance_init( GTypeInstance *instance, gpointer klass )
121 {
122 static const gchar *thisfn = "nadp_monitor_instance_init";
123 NadpMonitor *self;
124
125 g_return_if_fail( NADP_IS_MONITOR( instance ));
126
127 g_debug( "%s: instance=%p (%s), klass=%p",
128 thisfn, ( void * ) instance, G_OBJECT_TYPE_NAME( instance ), ( void * ) klass );
129
130 self = NADP_MONITOR( instance );
131
132 self->private = g_new0( NadpMonitorPrivate, 1 );
133
134 self->private->dispose_has_run = FALSE;
135 }
136
137 static void
instance_dispose(GObject * object)138 instance_dispose( GObject *object )
139 {
140 static const gchar *thisfn = "nadp_monitor_instance_dispose";
141 NadpMonitor *self;
142
143 g_return_if_fail( NADP_IS_MONITOR( object ));
144
145 self = NADP_MONITOR( object );
146
147 if( !self->private->dispose_has_run ){
148
149 g_debug( "%s: object=%p (%s)", thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
150
151 if( self->private->handler ){
152 g_signal_handler_disconnect( self->private->monitor, self->private->handler );
153 }
154
155 if( self->private->monitor ){
156 g_object_unref( self->private->monitor );
157 }
158
159 if( self->private->file ){
160 g_object_unref( self->private->file );
161 }
162
163 self->private->dispose_has_run = TRUE;
164
165 /* chain up to the parent class */
166 if( G_OBJECT_CLASS( st_parent_class )->dispose ){
167 G_OBJECT_CLASS( st_parent_class )->dispose( object );
168 }
169 }
170 }
171
172 static void
instance_finalize(GObject * object)173 instance_finalize( GObject *object )
174 {
175 static const gchar *thisfn = "nadp_monitor_instance_finalize";
176 NadpMonitor *self;
177
178 g_return_if_fail( NADP_IS_MONITOR( object ));
179
180 g_debug( "%s: object=%p (%s)", thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
181
182 self = NADP_MONITOR( object );
183
184 g_free( self->private->name );
185
186 g_free( self->private );
187
188 /* chain call to parent class */
189 if( G_OBJECT_CLASS( st_parent_class )->finalize ){
190 G_OBJECT_CLASS( st_parent_class )->finalize( object );
191 }
192 }
193
194 /**
195 * nadp_monitor_new:
196 * @provider: the #NadpDesktopProvider instance.
197 * @path: the path of a directory to be monitored.
198 *
199 * Installs a new monitor on the given directory.
200 *
201 * Returns: a new #NadpMonitor instance.
202 */
203 NadpMonitor *
nadp_monitor_new(const NadpDesktopProvider * provider,const gchar * path)204 nadp_monitor_new( const NadpDesktopProvider *provider, const gchar *path )
205 {
206 static const gchar *thisfn = "nadp_monitor_new";
207 NadpMonitor *monitor;
208 GFileMonitorFlags flags;
209 GError *error;
210
211 monitor = g_object_new( NADP_TYPE_MONITOR, NULL );
212
213 monitor->private->provider = NADP_DESKTOP_PROVIDER( provider );
214 monitor->private->name = g_strdup( path );
215 monitor->private->file = g_file_new_for_path( path );
216
217 error = NULL;
218 flags = G_FILE_MONITOR_NONE;
219
220 monitor->private->monitor = g_file_monitor_directory( monitor->private->file, flags, NULL, &error );
221 if( error ){
222 g_warning( "%s: g_file_monitor: %s", thisfn, error->message );
223 g_error_free( error );
224 error = NULL;
225 g_object_unref( monitor );
226 return( NULL );
227 }
228
229 g_return_val_if_fail( monitor->private->monitor, NULL );
230
231 monitor->private->handler = g_signal_connect(
232 monitor->private->monitor, "changed", G_CALLBACK( on_monitor_changed ), monitor );
233
234 return( monitor );
235 }
236
237 /*
238 * - an existing file is modified: n events on dir + m events on file
239 * - an existing file is deleted: 1 event on file + 1 event on dir
240 * - a new file is created: n events on the dir
241 * - a new directory is created: 1 event of this new dir
242 * - a directory is removed: 1 event of this new dir
243 * - an existing file is renamed: 1 event on file + n events on dir
244 * - the renamed file is modified: n events on dir
245 */
246 static void
on_monitor_changed(GFileMonitor * monitor,GFile * file,GFile * other_file,GFileMonitorEvent event_type,NadpMonitor * my_monitor)247 on_monitor_changed( GFileMonitor *monitor, GFile *file, GFile *other_file, GFileMonitorEvent event_type, NadpMonitor *my_monitor )
248 {
249 nadp_desktop_provider_on_monitor_event( my_monitor->private->provider );
250 }
251