README: add deprecation notice
[nautilus-actions.git] / src / plugin-tracker / fma-tracker-plugin.c
blobea257cf11e52e1d19288438ca671271557d69cb3
1 /*
2 * FileManager-Actions
3 * A file-manager extension which offers configurable context menu actions.
5 * Copyright (C) 2005 The GNOME Foundation
6 * Copyright (C) 2006-2008 Frederic Ruaudel and others (see AUTHORS)
7 * Copyright (C) 2009-2015 Pierre Wieser and others (see AUTHORS)
9 * FileManager-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.
14 * FileManager-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.
19 * You should have received a copy of the GNU General Public License
20 * along with FileManager-Actions; see the file COPYING. If not, see
21 * <http://www.gnu.org/licenses/>.
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)
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
34 #include <gio/gio.h>
36 #include "api/fma-dbus.h"
37 #include "api/fma-fm-defines.h"
39 #include "plugin-tracker/fma-tracker-plugin.h"
40 #include "plugin-tracker/fma-tracker-gdbus.h"
42 /* private class data
44 struct _FMATrackerPluginClassPrivate {
45 void *empty; /* so that gcc -pedantic is happy */
48 /* private instance data
50 struct _FMATrackerPluginPrivate {
51 gboolean dispose_has_run;
52 guint owner_id; /* the identifier returns by g_bus_own_name */
53 GDBusObjectManagerServer *manager;
54 GList *selected;
57 static GObjectClass *st_parent_class = NULL;
58 static GType st_module_type = 0;
60 static void class_init( FMATrackerPluginClass *klass );
61 static void instance_init( GTypeInstance *instance, gpointer klass );
62 static void initialize_dbus_connection( FMATrackerPlugin *tracker );
63 static void on_bus_acquired( GDBusConnection *connection, const gchar *name, FMATrackerPlugin *tracker );
64 static void on_name_acquired( GDBusConnection *connection, const gchar *name, FMATrackerPlugin *tracker );
65 static void on_name_lost( GDBusConnection *connection, const gchar *name, FMATrackerPlugin *tracker );
66 static gboolean on_properties1_get_selected_paths( FMATrackerGDBusProperties1 *properties, GDBusMethodInvocation *invocation, FMATrackerPlugin *tracker );
67 static void instance_dispose( GObject *object );
68 static void instance_finalize( GObject *object );
70 static void menu_provider_iface_init( FileManagerMenuProviderIface *iface );
71 static GList *menu_provider_get_background_items( FileManagerMenuProvider *provider, GtkWidget *window, FileManagerFileInfo *folder );
72 static GList *menu_provider_get_file_items( FileManagerMenuProvider *provider, GtkWidget *window, GList *files );
74 static void set_uris( FMATrackerPlugin *tracker, GList *files );
75 static gchar **get_selected_paths( FMATrackerPlugin *tracker );
76 static GList *free_selected( GList *selected );
78 GType
79 fma_tracker_plugin_get_type( void )
81 g_assert( st_module_type );
82 return( st_module_type );
85 void
86 fma_tracker_plugin_register_type( GTypeModule *module )
88 static const gchar *thisfn = "fma_tracker_plugin_register_type";
90 static const GTypeInfo info = {
91 sizeof( FMATrackerPluginClass ),
92 ( GBaseInitFunc ) NULL,
93 ( GBaseFinalizeFunc ) NULL,
94 ( GClassInitFunc ) class_init,
95 NULL,
96 NULL,
97 sizeof( FMATrackerPlugin ),
99 ( GInstanceInitFunc ) instance_init,
102 static const GInterfaceInfo menu_provider_iface_info = {
103 ( GInterfaceInitFunc ) menu_provider_iface_init,
104 NULL,
105 NULL
108 g_debug( "%s: module=%p", thisfn, ( void * ) module );
109 g_assert( st_module_type == 0 );
111 st_module_type = g_type_module_register_type( module, G_TYPE_OBJECT, "FMATrackerPlugin", &info, 0 );
113 g_type_module_add_interface( module, st_module_type, FILE_MANAGER_TYPE_MENU_PROVIDER, &menu_provider_iface_info );
116 static void
117 class_init( FMATrackerPluginClass *klass )
119 static const gchar *thisfn = "fma_tracker_plugin_class_init";
120 GObjectClass *gobject_class;
122 g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
124 st_parent_class = g_type_class_peek_parent( klass );
126 gobject_class = G_OBJECT_CLASS( klass );
127 gobject_class->dispose = instance_dispose;
128 gobject_class->finalize = instance_finalize;
130 klass->private = g_new0( FMATrackerPluginClassPrivate, 1 );
133 static void
134 instance_init( GTypeInstance *instance, gpointer klass )
136 static const gchar *thisfn = "fma_tracker_plugin_instance_init";
137 FMATrackerPlugin *self;
139 g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
140 g_return_if_fail( FMA_IS_TRACKER_PLUGIN( instance ));
142 self = FMA_TRACKER_PLUGIN( instance );
144 self->private = g_new0( FMATrackerPluginPrivate, 1 );
145 self->private->dispose_has_run = FALSE;
147 initialize_dbus_connection( self );
151 * initialize the DBus connection at instanciation time
152 * & instantiate the object which will do effective tracking
154 static void
155 initialize_dbus_connection( FMATrackerPlugin *tracker )
157 FMATrackerPluginPrivate *priv = tracker->private;
159 priv->owner_id = g_bus_own_name(
160 G_BUS_TYPE_SESSION,
161 FILEMANAGER_ACTIONS_DBUS_SERVICE,
162 G_BUS_NAME_OWNER_FLAGS_REPLACE,
163 ( GBusAcquiredCallback ) on_bus_acquired,
164 ( GBusNameAcquiredCallback ) on_name_acquired,
165 ( GBusNameLostCallback ) on_name_lost,
166 tracker,
167 NULL );
170 static void
171 on_bus_acquired( GDBusConnection *connection, const gchar *name, FMATrackerPlugin *tracker )
173 static const gchar *thisfn = "fma_tracker_plugin_on_bus_acquired";
174 FMATrackerGDBusObjectSkeleton *tracker_object;
175 FMATrackerGDBusProperties1 *tracker_properties1;
177 /*FMATrackerGDBusDBus *tracker_object;*/
179 g_debug( "%s: connection=%p, name=%s, tracker=%p",
180 thisfn,
181 ( void * ) connection,
182 name,
183 ( void * ) tracker );
185 /* create a new org.freedesktop.DBus.ObjectManager rooted at
186 * /org/filemanager_actions/DBus/Tracker
188 tracker->private->manager = g_dbus_object_manager_server_new( FILEMANAGER_ACTIONS_DBUS_TRACKER_PATH );
190 /* create a new D-Bus object at the path
191 * /org/filemanager_actions/DBus/Tracker
192 * (which must be same or below than that of object manager server)
194 tracker_object = fma_tracker_gdbus_object_skeleton_new( FILEMANAGER_ACTIONS_DBUS_TRACKER_PATH "/0" );
196 /* make a newly created object export the interface
197 * org.filemanager_actions.DBus.Tracker.Properties1
198 * and attach it to the D-Bus object, which takes its own reference on it
200 tracker_properties1 = fma_tracker_gdbus_properties1_skeleton_new();
201 fma_tracker_gdbus_object_skeleton_set_properties1( tracker_object, tracker_properties1 );
202 g_object_unref( tracker_properties1 );
204 /* handle GetSelectedPaths method invocation on the .Properties1 interface
206 g_signal_connect(
207 tracker_properties1,
208 "handle-get-selected-paths",
209 G_CALLBACK( on_properties1_get_selected_paths ),
210 tracker );
212 /* and export the DBus object on the object manager server
213 * (which takes its own reference on it)
215 g_dbus_object_manager_server_export( tracker->private->manager, G_DBUS_OBJECT_SKELETON( tracker_object ));
216 g_object_unref( tracker_object );
218 /* and connect the object manager server to the D-Bus session
219 * exporting all attached objects
221 g_dbus_object_manager_server_set_connection( tracker->private->manager, connection );
224 static void
225 on_name_acquired( GDBusConnection *connection, const gchar *name, FMATrackerPlugin *tracker )
227 static const gchar *thisfn = "fma_tracker_plugin_on_name_acquired";
229 g_debug( "%s: connection=%p, name=%s, tracker=%p",
230 thisfn,
231 ( void * ) connection,
232 name,
233 ( void * ) tracker );
236 static void
237 on_name_lost( GDBusConnection *connection, const gchar *name, FMATrackerPlugin *tracker )
239 static const gchar *thisfn = "fma_tracker_plugin_on_name_lost";
241 g_debug( "%s: connection=%p, name=%s, tracker=%p",
242 thisfn,
243 ( void * ) connection,
244 name,
245 ( void * ) tracker );
248 static void
249 instance_dispose( GObject *object )
251 static const gchar *thisfn = "fma_tracker_plugin_instance_dispose";
252 FMATrackerPluginPrivate *priv;
254 g_debug( "%s: object=%p", thisfn, ( void * ) object );
255 g_return_if_fail( FMA_IS_TRACKER_PLUGIN( object ));
257 priv = FMA_TRACKER_PLUGIN( object )->private;
259 if( !priv->dispose_has_run ){
261 priv->dispose_has_run = TRUE;
263 if( priv->owner_id ){
264 g_bus_unown_name( priv->owner_id );
266 if( priv->manager ){
267 g_object_unref( priv->manager );
270 priv->selected = free_selected( priv->selected );
272 /* chain up to the parent class */
273 if( G_OBJECT_CLASS( st_parent_class )->dispose ){
274 G_OBJECT_CLASS( st_parent_class )->dispose( object );
279 static void
280 instance_finalize( GObject *object )
282 static const gchar *thisfn = "fma_tracker_plugin_instance_finalize";
283 FMATrackerPlugin *self;
285 g_debug( "%s: object=%p", thisfn, ( void * ) object );
286 g_return_if_fail( FMA_IS_TRACKER_PLUGIN( object ));
287 self = FMA_TRACKER_PLUGIN( object );
289 g_free( self->private );
291 /* chain up to the parent class */
292 if( G_OBJECT_CLASS( st_parent_class )->finalize ){
293 G_OBJECT_CLASS( st_parent_class )->finalize( object );
297 static void
298 menu_provider_iface_init( FileManagerMenuProviderIface *iface )
300 static const gchar *thisfn = "fma_tracker_plugin_menu_provider_iface_init";
302 g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
304 iface->get_background_items = menu_provider_get_background_items;
305 iface->get_file_items = menu_provider_get_file_items;
308 static GList *
309 menu_provider_get_background_items( FileManagerMenuProvider *provider, GtkWidget *window, FileManagerFileInfo *folder )
311 static const gchar *thisfn = "fma_tracker_plugin_menu_provider_get_background_items";
312 FMATrackerPlugin *tracker;
313 gchar *uri;
314 GList *selected;
316 g_return_val_if_fail( FMA_IS_TRACKER_PLUGIN( provider ), NULL );
318 tracker = FMA_TRACKER_PLUGIN( provider );
320 if( !tracker->private->dispose_has_run ){
322 uri = file_manager_file_info_get_uri( folder );
323 g_debug( "%s: provider=%p, window=%p, folder=%s",
324 thisfn,
325 ( void * ) provider,
326 ( void * ) window,
327 uri );
328 g_free( uri );
330 selected = g_list_prepend( NULL, folder );
331 set_uris( tracker, selected );
332 g_list_free( selected );
335 return( NULL );
339 * this function is called each time the selection changed
340 * menus items are available :
341 * a) in Edit menu while the selection stays unchanged
342 * b) in contextual menu while the selection stays unchanged
344 static GList *
345 menu_provider_get_file_items( FileManagerMenuProvider *provider, GtkWidget *window, GList *files )
347 static const gchar *thisfn = "fma_tracker_plugin_menu_provider_get_file_items";
348 FMATrackerPlugin *tracker;
350 g_return_val_if_fail( FMA_IS_TRACKER_PLUGIN( provider ), NULL );
352 tracker = FMA_TRACKER_PLUGIN( provider );
354 if( !tracker->private->dispose_has_run ){
356 g_debug( "%s: provider=%p, window=%p, files=%p, count=%d",
357 thisfn,
358 ( void * ) provider,
359 ( void * ) window,
360 ( void * ) files, g_list_length( files ));
362 set_uris( tracker, files );
365 return( NULL );
369 * set_uris:
370 * @tracker: this #FMATrackerPlugin instance.
371 * @files: the list of currently selected items.
373 * Maintains our own list of uris.
375 static void
376 set_uris( FMATrackerPlugin *tracker, GList *files )
378 FMATrackerPluginPrivate *priv;
380 priv = tracker->private;
382 priv->selected = free_selected( tracker->private->selected );
383 priv->selected = file_manager_file_info_list_copy( files );
387 * Returns: %TRUE if the method has been handled.
389 static gboolean
390 on_properties1_get_selected_paths( FMATrackerGDBusProperties1 *properties, GDBusMethodInvocation *invocation, FMATrackerPlugin *tracker )
392 gchar **paths;
394 g_return_val_if_fail( FMA_IS_TRACKER_PLUGIN( tracker ), FALSE );
396 paths = get_selected_paths( tracker );
398 fma_tracker_gdbus_properties1_complete_get_selected_paths(
399 properties,
400 invocation,
401 ( const gchar * const * ) paths );
403 return( TRUE );
407 * get_selected_paths:
408 * @tracker: this #FMATrackerPlugin object.
410 * Sends on session D-Bus the list of currently selected items, as two
411 * strings for each item :
412 * - the uri
413 * - the mimetype as returned by NautilusFileInfo.
415 * This is required as some particular items are only known by Nautilus
416 * (e.g. computer), and standard GLib functions are not able to retrieve
417 * their mimetype.
419 * Exported as GetSelectedPaths method on Tracker.Properties1 interface.
421 static gchar **
422 get_selected_paths( FMATrackerPlugin *tracker )
424 static const gchar *thisfn = "fma_tracker_plugin_get_selected_paths";
425 FMATrackerPluginPrivate *priv;
426 gchar **paths;
427 GList *it;
428 int count;
429 gchar **iter;
431 paths = NULL;
432 priv = tracker->private;
434 g_debug( "%s: tracker=%p", thisfn, ( void * ) tracker );
436 count = 2 * g_list_length( priv->selected );
437 paths = ( char ** ) g_new0( gchar *, 1+count );
438 iter = paths;
440 for( it = priv->selected ; it ; it = it->next ){
441 *iter = file_manager_file_info_get_uri(( FileManagerFileInfo * ) it->data );
442 iter++;
443 *iter = file_manager_file_info_get_mime_type(( FileManagerFileInfo * ) it->data );
444 iter++;
447 return( paths );
450 static GList *
451 free_selected( GList *selected )
453 file_manager_file_info_list_free( selected );
455 return( NULL );