[nautilus-actions] Add files to desktop provider module



commit 81b9b0e7440c58a793855811df9533620e55f4c1
Author: Pierre Wieser <pwieser trychlos org>
Date:   Mon Nov 30 20:25:14 2009 +0100

    Add files to desktop provider module

 ChangeLog                                          |   20 ++
 TODO                                               |    2 +
 nautilus-actions/io-provider-desktop/Makefile.am   |   10 +
 .../io-provider-desktop/egg-desktop-file.h         |   44 ++--
 .../io-provider-desktop/nadp-desktop-file.c        |  248 ++++++++++++++++++
 .../io-provider-desktop/nadp-desktop-file.h        |   84 ++++++
 .../io-provider-desktop/nadp-desktop-provider.c    |   12 +-
 .../io-provider-desktop/nadp-desktop-provider.h    |   12 +-
 nautilus-actions/io-provider-desktop/nadp-read.c   |  263 +++++++++++++++++++
 nautilus-actions/io-provider-desktop/nadp-read.h   |   42 +++
 nautilus-actions/io-provider-desktop/nadp-utils.c  |  276 ++++++++++++++++++++
 nautilus-actions/io-provider-desktop/nadp-utils.h  |   60 +++++
 nautilus-actions/io-provider-desktop/nadp-write.c  |  190 ++++++++++++++
 nautilus-actions/io-provider-desktop/nadp-write.h  |   49 ++++
 .../io-provider-desktop/nadp-xdg-data-dirs.c       |  142 ++++++++++
 .../io-provider-desktop/nadp-xdg-data-dirs.h       |   46 ++++
 nautilus-actions/io-provider-gconf/nagp-read.h     |   13 -
 nautilus-actions/io-provider-gconf/nagp-write.h    |   13 -
 18 files changed, 1471 insertions(+), 55 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 5e1a8ee..88c5e43 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2009-11-30 Pierre Wieser <pwieser trychlos org>
+
+	* nautilus-actions/io-provider-desktop/nadp-desktop-file.c:
+	* utilus-actions/io-provider-desktop/nadp-desktop-file.h:
+	* nautilus-actions/io-provider-desktop/nadp-read.c:
+	* nautilus-actions/io-provider-desktop/nadp-read.h:
+	* nautilus-actions/io-provider-desktop/nadp-utils.c:
+	* nautilus-actions/io-provider-desktop/nadp-utils.h:
+	* nautilus-actions/io-provider-desktop/nadp-write.c:
+	* nautilus-actions/io-provider-desktop/nadp-write.h:
+	* nautilus-actions/io-provider-desktop/nadp-xdg-data-dirs.c:
+	* nautilus-actions/io-provider-desktop/nadp-xdg-data-dirs.h:
+	New files.
+
+	* nautilus-actions/io-provider-desktop/Makefile.am:
+	Updated accordingly.
+
+	* nautilus-actions/io-provider-desktop/nadp-desktop-provider.h:
+	Define NADP_DESKTOP_PROVIDER_SUBDIRS.
+
 2009-11-25 Pierre Wieser <pwieser trychlos org>
 
 	Read-only flag is moved to NAObjectItem: action and menu may be
diff --git a/TODO b/TODO
index 1823d64..8ac7a21 100644
--- a/TODO
+++ b/TODO
@@ -95,3 +95,5 @@
 
 - may we have a read-only menu ?
   this implies dnd of an action inside of the menu would be forbidden
+
+- nact: if item is read-only, all fields should be disabled
diff --git a/nautilus-actions/io-provider-desktop/Makefile.am b/nautilus-actions/io-provider-desktop/Makefile.am
index 715e51c..17c28de 100644
--- a/nautilus-actions/io-provider-desktop/Makefile.am
+++ b/nautilus-actions/io-provider-desktop/Makefile.am
@@ -39,9 +39,19 @@ AM_CPPFLAGS += \
 libna_io_provider_desktop_la_SOURCES = \
 	egg-desktop-file.c											\
 	egg-desktop-file.h											\
+	nadp-desktop-file.c											\
+	nadp-desktop-file.h											\
 	nadp-desktop-provider.c										\
 	nadp-desktop-provider.h										\
 	nadp-module.c												\
+	nadp-read.c													\
+	nadp-read.h													\
+	nadp-utils.c												\
+	nadp-utils.h												\
+	nadp-write.c												\
+	nadp-write.h												\
+	nadp-xdg-data-dirs.c										\
+	nadp-xdg-data-dirs.h										\
 	$(NULL)
 
 libna_io_provider_desktop_la_LIBADD = \
diff --git a/nautilus-actions/io-provider-desktop/egg-desktop-file.h b/nautilus-actions/io-provider-desktop/egg-desktop-file.h
index 18fe463..027dac1 100644
--- a/nautilus-actions/io-provider-desktop/egg-desktop-file.h
+++ b/nautilus-actions/io-provider-desktop/egg-desktop-file.h
@@ -32,7 +32,8 @@ typedef enum {
 	EGG_DESKTOP_FILE_TYPE_APPLICATION,
 	EGG_DESKTOP_FILE_TYPE_LINK,
 	EGG_DESKTOP_FILE_TYPE_DIRECTORY
-} EggDesktopFileType;
+}
+	EggDesktopFileType;
 
 EggDesktopFile     *egg_desktop_file_new                (const char   *desktop_file_path,
 							 GError      **error);
@@ -88,27 +89,27 @@ typedef enum {
 } EggDesktopFileLaunchOption;
 
 /* Standard Keys */
-#define EGG_DESKTOP_FILE_GROUP			"Desktop Entry"
-
-#define EGG_DESKTOP_FILE_KEY_TYPE		"Type"
-#define EGG_DESKTOP_FILE_KEY_VERSION		"Version"
-#define EGG_DESKTOP_FILE_KEY_NAME		"Name"
-#define EGG_DESKTOP_FILE_KEY_GENERIC_NAME	"GenericName"
-#define EGG_DESKTOP_FILE_KEY_NO_DISPLAY		"NoDisplay"
-#define EGG_DESKTOP_FILE_KEY_COMMENT		"Comment"
-#define EGG_DESKTOP_FILE_KEY_ICON		"Icon"
-#define EGG_DESKTOP_FILE_KEY_HIDDEN		"Hidden"
-#define EGG_DESKTOP_FILE_KEY_ONLY_SHOW_IN	"OnlyShowIn"
-#define EGG_DESKTOP_FILE_KEY_NOT_SHOW_IN	"NotShowIn"
-#define EGG_DESKTOP_FILE_KEY_TRY_EXEC		"TryExec"
-#define EGG_DESKTOP_FILE_KEY_EXEC		"Exec"
-#define EGG_DESKTOP_FILE_KEY_PATH		"Path"
-#define EGG_DESKTOP_FILE_KEY_TERMINAL		"Terminal"
-#define EGG_DESKTOP_FILE_KEY_MIME_TYPE		"MimeType"
-#define EGG_DESKTOP_FILE_KEY_CATEGORIES		"Categories"
-#define EGG_DESKTOP_FILE_KEY_STARTUP_NOTIFY	"StartupNotify"
+#define EGG_DESKTOP_FILE_GROUP					"Desktop Entry"
+
+#define EGG_DESKTOP_FILE_KEY_TYPE				"Type"
+#define EGG_DESKTOP_FILE_KEY_VERSION			"Version"
+#define EGG_DESKTOP_FILE_KEY_NAME				"Name"
+#define EGG_DESKTOP_FILE_KEY_GENERIC_NAME		"GenericName"
+#define EGG_DESKTOP_FILE_KEY_NO_DISPLAY			"NoDisplay"
+#define EGG_DESKTOP_FILE_KEY_COMMENT			"Comment"
+#define EGG_DESKTOP_FILE_KEY_ICON				"Icon"
+#define EGG_DESKTOP_FILE_KEY_HIDDEN				"Hidden"
+#define EGG_DESKTOP_FILE_KEY_ONLY_SHOW_IN		"OnlyShowIn"
+#define EGG_DESKTOP_FILE_KEY_NOT_SHOW_IN		"NotShowIn"
+#define EGG_DESKTOP_FILE_KEY_TRY_EXEC			"TryExec"
+#define EGG_DESKTOP_FILE_KEY_EXEC				"Exec"
+#define EGG_DESKTOP_FILE_KEY_PATH				"Path"
+#define EGG_DESKTOP_FILE_KEY_TERMINAL			"Terminal"
+#define EGG_DESKTOP_FILE_KEY_MIME_TYPE			"MimeType"
+#define EGG_DESKTOP_FILE_KEY_CATEGORIES			"Categories"
+#define EGG_DESKTOP_FILE_KEY_STARTUP_NOTIFY		"StartupNotify"
 #define EGG_DESKTOP_FILE_KEY_STARTUP_WM_CLASS	"StartupWMClass"
-#define EGG_DESKTOP_FILE_KEY_URL		"URL"
+#define EGG_DESKTOP_FILE_KEY_URL				"URL"
 
 /* Accessors */
 gboolean  egg_desktop_file_has_key                (EggDesktopFile  *desktop_file,
@@ -137,7 +138,6 @@ char    **egg_desktop_file_get_locale_string_list (EggDesktopFile  *desktop_file
 						   gsize           *length,
 						   GError         **error) G_GNUC_MALLOC;
 
-
 /* Errors */
 #define EGG_DESKTOP_FILE_ERROR egg_desktop_file_error_quark()
 
diff --git a/nautilus-actions/io-provider-desktop/nadp-desktop-file.c b/nautilus-actions/io-provider-desktop/nadp-desktop-file.c
new file mode 100644
index 0000000..1311b60
--- /dev/null
+++ b/nautilus-actions/io-provider-desktop/nadp-desktop-file.c
@@ -0,0 +1,248 @@
+/*
+ * Nautilus Actions
+ * A Nautilus extension which offers configurable context menu actions.
+ *
+ * Copyright (C) 2005 The GNOME Foundation
+ * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
+ * Copyright (C) 2009 Pierre Wieser and others (see AUTHORS)
+ *
+ * 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 Library; see the file COPYING.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ *   Frederic Ruaudel <grumz grumz net>
+ *   Rodrigo Moya <rodrigo gnome-db org>
+ *   Pierre Wieser <pwieser trychlos org>
+ *   ... and many others (see AUTHORS)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "nadp-desktop-file.h"
+#include "nadp-utils.h"
+
+/* private class data
+ */
+struct NadpDesktopFileClassPrivate {
+	void *empty;						/* so that gcc -pedantic is happy */
+};
+
+/* private instance data
+ */
+struct NadpDesktopFilePrivate {
+	gboolean        dispose_has_run;
+	gchar          *id;
+	EggDesktopFile *edf;
+};
+
+static GObjectClass *st_parent_class = NULL;
+
+static GType register_type( void );
+static void  class_init( NadpDesktopFileClass *klass );
+static void  instance_init( GTypeInstance *instance, gpointer klass );
+static void  instance_dispose( GObject *object );
+static void  instance_finalize( GObject *object );
+
+GType
+nadp_desktop_file_get_type( void )
+{
+	static GType class_type = 0;
+
+	if( !class_type ){
+		class_type = register_type();
+	}
+
+	return( class_type );
+}
+
+static GType
+register_type( void )
+{
+	static const gchar *thisfn = "nadp_desktop_file_register_type";
+	GType type;
+
+	static GTypeInfo info = {
+		sizeof( NadpDesktopFileClass ),
+		NULL,
+		NULL,
+		( GClassInitFunc ) class_init,
+		NULL,
+		NULL,
+		sizeof( NadpDesktopFile ),
+		0,
+		( GInstanceInitFunc ) instance_init
+	};
+
+	g_debug( "%s", thisfn );
+
+	type = g_type_register_static( G_TYPE_OBJECT, "NadpDesktopFile", &info, 0 );
+
+	return( type );
+}
+
+static void
+class_init( NadpDesktopFileClass *klass )
+{
+	static const gchar *thisfn = "nadp_desktop_file_class_init";
+	GObjectClass *object_class;
+
+	g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
+
+	st_parent_class = g_type_class_peek_parent( klass );
+
+	object_class = G_OBJECT_CLASS( klass );
+	object_class->dispose = instance_dispose;
+	object_class->finalize = instance_finalize;
+
+	klass->private = g_new0( NadpDesktopFileClassPrivate, 1 );
+}
+
+static void
+instance_init( GTypeInstance *instance, gpointer klass )
+{
+	static const gchar *thisfn = "nadp_desktop_file_instance_init";
+	NadpDesktopFile *self;
+
+	g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
+	g_return_if_fail( NADP_IS_DESKTOP_FILE( instance ));
+	self = NADP_DESKTOP_FILE( instance );
+
+	self->private = g_new0( NadpDesktopFilePrivate, 1 );
+
+	self->private->dispose_has_run = FALSE;
+}
+
+static void
+instance_dispose( GObject *object )
+{
+	static const gchar *thisfn = "nadp_desktop_file_instance_dispose";
+	NadpDesktopFile *self;
+
+	g_debug( "%s: object=%p", thisfn, ( void * ) object );
+	g_return_if_fail( NADP_IS_DESKTOP_FILE( object ));
+	self = NADP_DESKTOP_FILE( object );
+
+	if( !self->private->dispose_has_run ){
+
+		self->private->dispose_has_run = TRUE;
+
+		if( self->private->edf ){
+			egg_desktop_file_free( self->private->edf );
+			self->private->edf = NULL;
+		}
+
+		/* chain up to the parent class */
+		if( G_OBJECT_CLASS( st_parent_class )->dispose ){
+			G_OBJECT_CLASS( st_parent_class )->dispose( object );
+		}
+	}
+}
+
+static void
+instance_finalize( GObject *object )
+{
+	NadpDesktopFile *self;
+
+	g_assert( NADP_IS_DESKTOP_FILE( object ));
+	self = NADP_DESKTOP_FILE( object );
+
+	if( self->private->id ){
+		g_free( self->private->id );
+		self->private->id = NULL;
+	}
+
+	g_free( self->private );
+
+	/* chain call to parent class */
+	if( G_OBJECT_CLASS( st_parent_class )->finalize ){
+		G_OBJECT_CLASS( st_parent_class )->finalize( object );
+	}
+}
+
+/**
+ * nadp_desktop_file_new_from_path:
+ * @path: the full pathname of a .desktop file.
+ *
+ * Retuns: a newly allocated #NadpDesktopFile object.
+ */
+NadpDesktopFile *
+nadp_desktop_file_new_from_path( const gchar *path )
+{
+	static const gchar *thisfn = "nadp_desktop_file_new_from_path";
+	NadpDesktopFile *ndf;
+	EggDesktopFile *edf;
+	GError *error;
+
+	ndf = NULL;
+	g_debug( "%s: path=%s", thisfn, path );
+	g_return_val_if_fail( path && g_utf8_strlen( path, -1 ), ndf );
+
+	error = NULL;
+	edf = egg_desktop_file_new( path, &error );
+	if( error ){
+		g_warning( "%s: %s: %s", thisfn, path, error->message );
+		g_error_free( error );
+		return( NULL );
+	}
+
+	ndf = g_object_new( NADP_DESKTOP_FILE_TYPE, NULL );
+	ndf->private->edf = edf;
+	ndf->private->id = nadp_utils_path2id( path );
+
+	return( ndf );
+}
+
+/**
+ * nadp_desktop_file_get_id:
+ * @ndf: the #NadpDesktopFile instance.
+ *
+ * Returns: the id of the file, as a newly allocated string which should
+ * be g_free() by the caller.
+ */
+gchar *
+nadp_desktop_file_get_id( const NadpDesktopFile *ndf )
+{
+	gchar *id;
+
+	id = NULL;
+	g_return_val_if_fail( NADP_IS_DESKTOP_FILE( ndf ), id );
+
+	if( !ndf->private->dispose_has_run ){
+		id = ndf->private->id;
+	}
+
+	return( id );
+}
+
+/**
+ * nadp_desktop_file_get_egg_desktop_file:
+ * @ndf: the #NadpDesktopFile instance.
+ */
+EggDesktopFile *
+nadp_desktop_file_get_egg_desktop_file( const NadpDesktopFile *ndf )
+{
+	EggDesktopFile *edf;
+
+	edf = NULL;
+	g_return_val_if_fail( NADP_IS_DESKTOP_FILE( ndf ), edf );
+
+	if( !ndf->private->dispose_has_run ){
+		edf = ndf->private->edf;
+	}
+
+	return( edf );
+}
diff --git a/nautilus-actions/io-provider-desktop/nadp-desktop-file.h b/nautilus-actions/io-provider-desktop/nadp-desktop-file.h
new file mode 100644
index 0000000..3a7face
--- /dev/null
+++ b/nautilus-actions/io-provider-desktop/nadp-desktop-file.h
@@ -0,0 +1,84 @@
+/*
+ * Nautilus Actions
+ * A Nautilus extension which offers configurable context menu actions.
+ *
+ * Copyright (C) 2005 The GNOME Foundation
+ * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
+ * Copyright (C) 2009 Pierre Wieser and others (see AUTHORS)
+ *
+ * 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 Library; see the file COPYING.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ *   Frederic Ruaudel <grumz grumz net>
+ *   Rodrigo Moya <rodrigo gnome-db org>
+ *   Pierre Wieser <pwieser trychlos org>
+ *   ... and many others (see AUTHORS)
+ */
+
+#ifndef __NADP_DESKTOP_FILE_H__
+#define __NADP_DESKTOP_FILE_H__
+
+/**
+ * SECTION: nadp_desktop_file
+ * @short_description: #NadpDesktopFile class definition.
+ * @include: nadp-desktop-file.h
+ *
+ * This class encapÅ?ulates the EggDesktopFile structure, adding some
+ * private properties. An instance of this class is associated with
+ * every #NAObjectItem for this provider.
+ */
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "egg-desktop-file.h"
+
+G_BEGIN_DECLS
+
+#define NADP_DESKTOP_FILE_TYPE					( nadp_desktop_file_get_type())
+#define NADP_DESKTOP_FILE( object )				( G_TYPE_CHECK_INSTANCE_CAST( object, NADP_DESKTOP_FILE_TYPE, NadpDesktopFile ))
+#define NADP_DESKTOP_FILE_CLASS( klass )		( G_TYPE_CHECK_CLASS_CAST( klass, NADP_DESKTOP_FILE_TYPE, NadpDesktopFileClass ))
+#define NADP_IS_DESKTOP_FILE( object )			( G_TYPE_CHECK_INSTANCE_TYPE( object, NADP_DESKTOP_FILE_TYPE ))
+#define NADP_IS_DESKTOP_FILE_CLASS( klass )		( G_TYPE_CHECK_CLASS_TYPE(( klass ), NADP_DESKTOP_FILE_TYPE ))
+#define NADP_DESKTOP_FILE_GET_CLASS( object )	( G_TYPE_INSTANCE_GET_CLASS(( object ), NADP_DESKTOP_FILE_TYPE, NadpDesktopFileClass ))
+
+typedef struct NadpDesktopFilePrivate NadpDesktopFilePrivate;
+
+typedef struct {
+	GObject                 parent;
+	NadpDesktopFilePrivate *private;
+}
+	NadpDesktopFile;
+
+typedef struct NadpDesktopFileClassPrivate NadpDesktopFileClassPrivate;
+
+typedef struct {
+	GObjectClass                 parent;
+	NadpDesktopFileClassPrivate *private;
+}
+	NadpDesktopFileClass;
+
+GType            nadp_desktop_file_get_type( void );
+
+NadpDesktopFile *nadp_desktop_file_new_from_path( const gchar *path );
+
+gchar           *nadp_desktop_file_get_id              ( const NadpDesktopFile *ndf );
+
+EggDesktopFile  *nadp_desktop_file_get_egg_desktop_file( const NadpDesktopFile *ndf );
+
+G_END_DECLS
+
+#endif /* __NADP_DESKTOP_FILE_H__ */
diff --git a/nautilus-actions/io-provider-desktop/nadp-desktop-provider.c b/nautilus-actions/io-provider-desktop/nadp-desktop-provider.c
index 5774eec..82b4bdd 100644
--- a/nautilus-actions/io-provider-desktop/nadp-desktop-provider.c
+++ b/nautilus-actions/io-provider-desktop/nadp-desktop-provider.c
@@ -37,6 +37,8 @@
 #include <nautilus-actions/api/na-iio-provider.h>
 
 #include "nadp-desktop-provider.h"
+#include "nadp-read.h"
+#include "nadp-write.h"
 
 /* private class data
  */
@@ -113,11 +115,11 @@ iio_provider_iface_init( NAIIOProviderInterface *iface )
 
 	g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
 
-	iface->read_items = NULL;
-	iface->is_willing_to_write = NULL;
-	iface->is_writable = NULL;
-	iface->write_item = NULL;
-	iface->delete_item = NULL;
+	iface->read_items = nadp_iio_provider_read_items;
+	iface->is_willing_to_write = nadp_iio_provider_is_willing_to_write;
+	iface->is_writable = nadp_iio_provider_is_writable;
+	iface->write_item = nadp_iio_provider_write_item;
+	iface->delete_item = nadp_iio_provider_delete_item;
 }
 
 static void
diff --git a/nautilus-actions/io-provider-desktop/nadp-desktop-provider.h b/nautilus-actions/io-provider-desktop/nadp-desktop-provider.h
index 8b0fe9c..8c068ef 100644
--- a/nautilus-actions/io-provider-desktop/nadp-desktop-provider.h
+++ b/nautilus-actions/io-provider-desktop/nadp-desktop-provider.h
@@ -44,9 +44,10 @@
  * tree. Modifications are notified to the NAIIOProvider interface.
  */
 
-#include <glib.h>
 #include <glib-object.h>
 
+#include "egg-desktop-file.h"
+
 G_BEGIN_DECLS
 
 #define NADP_DESKTOP_PROVIDER_TYPE					( nadp_desktop_provider_get_type())
@@ -59,7 +60,8 @@ G_BEGIN_DECLS
 /* private instance data
  */
 typedef struct NadpDesktopProviderPrivate {
-	gboolean     dispose_has_run;
+	gboolean        dispose_has_run;
+	EggDesktopFile *egg_desktop_file;
 }
 	NadpDesktopProviderPrivate;
 
@@ -77,6 +79,12 @@ typedef struct {
 }
 	NadpDesktopProviderClass;
 
+/* this is a ':'-separated list of subdirs searched for actions desktop
+ * files.
+ */
+#define NADP_DESKTOP_PROVIDER_SUBDIRS		"file-manager/actions"
+#define NADP_DESKTOP_SUFFIX					".desktop"
+
 GType nadp_desktop_provider_get_type     ( void );
 void  nadp_desktop_provider_register_type( GTypeModule *module );
 
diff --git a/nautilus-actions/io-provider-desktop/nadp-read.c b/nautilus-actions/io-provider-desktop/nadp-read.c
new file mode 100644
index 0000000..8cd7cb9
--- /dev/null
+++ b/nautilus-actions/io-provider-desktop/nadp-read.c
@@ -0,0 +1,263 @@
+/*
+ * Nautilus Actions
+ * A Nautilus extension which offers configurable context menu actions.
+ *
+ * Copyright (C) 2005 The GNOME Foundation
+ * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
+ * Copyright (C) 2009 Pierre Wieser and others (see AUTHORS)
+ *
+ * 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 Library; see the file COPYING.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ *   Frederic Ruaudel <grumz grumz net>
+ *   Rodrigo Moya <rodrigo gnome-db org>
+ *   Pierre Wieser <pwieser trychlos org>
+ *   ... and many others (see AUTHORS)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <nautilus-actions/api/na-object-api.h>
+
+#include "nadp-desktop-file.h"
+#include "nadp-desktop-provider.h"
+#include "nadp-read.h"
+#include "nadp-utils.h"
+#include "nadp-xdg-data-dirs.h"
+
+typedef struct {
+	gchar *path;
+	gchar *id;
+}
+	DesktopPath;
+
+static GList          *get_list_of_desktop_paths( const NadpDesktopProvider *provider, GSList **mesages );
+static void            get_list_of_desktop_files( const NadpDesktopProvider *provider, GList **files, const gchar *dir, GSList **messages );
+static gboolean        is_already_loaded( const NadpDesktopProvider *provider, GList *files, const gchar *desktop_id );
+static GList          *desktop_path_from_id( const NadpDesktopProvider *provider, GList *files, const gchar *dir, const gchar *id );
+static NAObjectAction *action_from_desktop_path( const NadpDesktopProvider *provider, DesktopPath *dps, GSList **messages );
+static void            read_action_properties( const NadpDesktopProvider *provider, NAObjectAction *action, NadpDesktopFile *ndf, GSList **messages );
+static void            free_desktop_paths( GList *paths );
+
+/*
+ * Returns an unordered list of NAObjectItem-derived objects
+ */
+GList *
+nadp_iio_provider_read_items( const NAIIOProvider *provider, GSList **messages )
+{
+	static const gchar *thisfn = "nadp_read_iio_provider_read_items";
+	GList *items;
+	GList *paths, *ip;
+	DesktopPath *dps;
+	NAObjectAction *action;
+
+	g_debug( "%s: provider=%p, messages=%p", thisfn, ( void * ) provider, ( void * ) messages );
+
+	items = NULL;
+
+	paths = get_list_of_desktop_paths( NADP_DESKTOP_PROVIDER( provider ), messages );
+	for( ip = paths ; ip ; ip = ip->next ){
+		dps = ( DesktopPath * ) ip->data;
+		action = action_from_desktop_path( NADP_DESKTOP_PROVIDER( provider ), dps, messages );
+		if( action ){
+			items = g_list_prepend( items, action );
+		}
+	}
+
+	free_desktop_paths( paths );
+
+	return( items );
+}
+
+/*
+ * returns a list of DesktopPath items
+ */
+static GList *
+get_list_of_desktop_paths( const NadpDesktopProvider *provider, GSList **messages )
+{
+	GList *files;
+	GSList *xdg_dirs, *idir;
+	GSList *subdirs, *isub;
+	gchar *dir;
+
+	files = NULL;
+	xdg_dirs = nadp_xdg_data_dirs_get_dirs( provider, messages );
+	subdirs = nadp_utils_split_path_list( NADP_DESKTOP_PROVIDER_SUBDIRS );
+
+	for( idir = xdg_dirs ; idir ; idir = idir->next ){
+		for( isub = subdirs ; isub ; isub = isub->next ){
+			dir = g_build_filename(( gchar * ) idir->data, ( gchar * ) isub->data, NULL );
+			get_list_of_desktop_files( provider, &files, dir, messages );
+			g_free( dir );
+		}
+	}
+
+	nadp_utils_gslist_free( subdirs );
+	nadp_utils_gslist_free( xdg_dirs );
+
+	return( files );
+}
+
+/*
+ * scans the directory for a list of not yet loaded .desktop files
+ */
+static void
+get_list_of_desktop_files( const NadpDesktopProvider *provider, GList **files, const gchar *dir, GSList **messages )
+{
+	static const gchar *thisfn = "nadp_read_get_list_of_desktop_files";
+	GDir *dir_handle;
+	GError *error;
+	const gchar *name;
+	gchar *desktop_id;
+
+	g_debug( "%s: provider=%p, files=%p (count=%d), dir=%s, messages=%p",
+			thisfn, ( void * ) provider, ( void * ) files, g_list_length( *files ), dir, ( void * ) messages );
+
+	error = NULL;
+	dir_handle = NULL;
+	/* do not warn when the directory just doesn't exist
+	 */
+	if( g_file_test( dir, G_FILE_TEST_IS_DIR )){
+		dir_handle = g_dir_open( dir, 0, &error );
+		if( error ){
+			g_warning( "%s: %s: %s", thisfn, dir, error->message );
+			g_error_free( error );
+			goto close_dir_handle;
+		}
+	} else {
+		g_debug( "%s: %s: directory doesn't exist", thisfn, dir );
+	}
+
+	if( dir_handle ){
+		while(( name = g_dir_read_name( dir_handle ))){
+			if( g_str_has_suffix( name, NADP_DESKTOP_SUFFIX )){
+				desktop_id = nadp_utils_remove_suffix( name, NADP_DESKTOP_SUFFIX );
+				if( !is_already_loaded( provider, *files, desktop_id )){
+					*files = desktop_path_from_id( provider, *files, dir, desktop_id );
+				}
+				g_free( desktop_id );
+			}
+		}
+	}
+
+close_dir_handle:
+	if( dir_handle ){
+		g_dir_close( dir_handle );
+	}
+}
+
+static gboolean
+is_already_loaded( const NadpDesktopProvider *provider, GList *files, const gchar *desktop_id )
+{
+	gboolean found;
+	GList *ip;
+	DesktopPath *dps;
+
+	found = FALSE;
+	for( ip = files ; ip && !found ; ip = ip->next ){
+		dps = ( DesktopPath * ) ip->data;
+		if( !g_ascii_strcasecmp( dps->id, desktop_id )){
+			found = TRUE;
+		}
+	}
+
+	return( found );
+}
+
+static GList *
+desktop_path_from_id( const NadpDesktopProvider *provider, GList *files, const gchar *dir, const gchar *id )
+{
+	DesktopPath *dps;
+	gchar *bname;
+	GList *list;
+
+	dps = g_new0( DesktopPath, 1 );
+
+	bname = g_strdup_printf( "%s%s", id, NADP_DESKTOP_SUFFIX );
+	dps->path = g_build_filename( dir, bname, NULL );
+	g_free( bname );
+
+	dps->id = g_strdup( id );
+
+	list = g_list_append( files, dps );
+
+	return( list );
+}
+
+/*
+ * returns a newly allocated NAObjectAction object, initialized
+ * from the .desktop file pointed to by DesktopPath struct
+ */
+static NAObjectAction *
+action_from_desktop_path( const NadpDesktopProvider *provider, DesktopPath *dps, GSList **messages )
+{
+	NadpDesktopFile *ndf;
+	NAObjectAction *action;
+
+	ndf = nadp_desktop_file_new_from_path( dps->path );
+	if( !ndf ){
+		return( NULL );
+	}
+
+	action = na_object_action_new();
+	read_action_properties( provider, action, ndf, messages );
+
+	g_object_set_data( G_OBJECT( action ), "nadp-desktop-file", ndf );
+	g_object_weak_ref( G_OBJECT( action ), ( GWeakNotify ) g_object_unref, ndf );
+
+	return( action );
+}
+
+static void
+read_action_properties( const NadpDesktopProvider *provider, NAObjectAction *action, NadpDesktopFile *ndf, GSList **messages )
+{
+	static const gchar *thisfn = "nadp_action_item_properties";
+	EggDesktopFile *edf;
+	gchar *id;
+	gchar *label;
+
+	edf = nadp_desktop_file_get_egg_desktop_file( ndf );
+	id = nadp_desktop_file_get_id( ndf );
+
+	label = ( gchar * ) egg_desktop_file_get_name( edf );
+	if( !label || !g_utf8_strlen( label, -1 )){
+		g_warning( "%s: id=%s, label not found or empty", thisfn, id );
+		g_free( label );
+		label = g_strdup( "" );
+	}
+	na_object_set_label( action, label );
+	g_free( label );
+
+	g_free( id );
+}
+
+static void
+free_desktop_paths( GList *paths )
+{
+	GList *ip;
+	DesktopPath *dps;
+
+	for( ip = paths ; ip ; ip = ip->next ){
+		dps = ( DesktopPath * ) ip->data;
+		g_free( dps->path );
+		g_free( dps->id );
+		g_free( dps );
+	}
+
+	g_list_free( paths );
+}
diff --git a/nautilus-actions/io-provider-desktop/nadp-read.h b/nautilus-actions/io-provider-desktop/nadp-read.h
new file mode 100644
index 0000000..96900b8
--- /dev/null
+++ b/nautilus-actions/io-provider-desktop/nadp-read.h
@@ -0,0 +1,42 @@
+/*
+ * Nautilus Actions
+ * A Nautilus extension which offers configurable context menu actions.
+ *
+ * Copyright (C) 2005 The GNOME Foundation
+ * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
+ * Copyright (C) 2009 Pierre Wieser and others (see AUTHORS)
+ *
+ * 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 Library; see the file COPYING.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ *   Frederic Ruaudel <grumz grumz net>
+ *   Rodrigo Moya <rodrigo gnome-db org>
+ *   Pierre Wieser <pwieser trychlos org>
+ *   ... and many others (see AUTHORS)
+ */
+
+#include <nautilus-actions/api/na-iio-provider.h>
+
+#ifndef __NADP_READ_H__
+#define __NADP_READ_H__
+
+G_BEGIN_DECLS
+
+GList *nadp_iio_provider_read_items( const NAIIOProvider *provider, GSList **messages );
+
+G_END_DECLS
+
+#endif /* __NADP_READ_H__ */
diff --git a/nautilus-actions/io-provider-desktop/nadp-utils.c b/nautilus-actions/io-provider-desktop/nadp-utils.c
new file mode 100644
index 0000000..8a3a6a3
--- /dev/null
+++ b/nautilus-actions/io-provider-desktop/nadp-utils.c
@@ -0,0 +1,276 @@
+/*
+ * Nautilus Actions
+ * A Nautilus extension which offers configurable context menu actions.
+ *
+ * Copyright (C) 2005 The GNOME Foundation
+ * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
+ * Copyright (C) 2009 Pierre Wieser and others (see AUTHORS)
+ *
+ * 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 Library; see the file COPYING.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ *   Frederic Ruaudel <grumz grumz net>
+ *   Rodrigo Moya <rodrigo gnome-db org>
+ *   Pierre Wieser <pwieser trychlos org>
+ *   ... and many others (see AUTHORS)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <gio/gio.h>
+#include <glib/gstdio.h>
+#include <uuid/uuid.h>
+
+#include "nadp-desktop-provider.h"
+#include "nadp-utils.h"
+
+static GSList *text_to_string_list( const gchar *text, const gchar *separator, const gchar *default_value );
+
+/**
+ * nadp_utils_split_path_list:
+ * @path_list: a ':'-separated list of paths.
+ *
+ * Returns: an ordered GSList of paths, as newly allocated strings.
+ *
+ * The returned GSList should be freed by the caller.
+ */
+GSList *
+nadp_utils_split_path_list( const gchar *path_list )
+{
+	return( text_to_string_list( path_list, ":", NULL ));
+}
+
+/*
+ * split a text buffer in lines
+ */
+static GSList *
+text_to_string_list( const gchar *text, const gchar *separator, const gchar *default_value )
+{
+	GSList *strlist = NULL;
+	gchar **tokens, **iter;
+	gchar *tmp;
+	gchar *source = g_strdup( text );
+
+	tmp = g_strstrip( source );
+	if( !g_utf8_strlen( tmp, -1 ) && default_value ){
+		strlist = g_slist_append( strlist, g_strdup( default_value ));
+
+	} else {
+		tokens = g_strsplit( source, separator, -1 );
+		iter = tokens;
+
+		while( *iter ){
+			tmp = g_strstrip( *iter );
+			strlist = g_slist_append( strlist, g_strdup( tmp ));
+			iter++;
+		}
+
+		g_strfreev( tokens );
+	}
+
+	g_free( source );
+	return( strlist );
+}
+
+/**
+ * nadp_utils_gslist_free:
+ * @list: the GSList to be freed.
+ *
+ * Frees a GSList of strings.
+ */
+void
+nadp_utils_gslist_free( GSList *list )
+{
+	g_slist_foreach( list, ( GFunc ) g_free, NULL );
+	g_slist_free( list );
+}
+
+/**
+ * nadp_utils_remove_suffix:
+ * @string: source string.
+ * @suffix: suffix to be removed from @string.
+ *
+ * Returns: a newly allocated string, which is a copy of the source @string,
+ * minus the removed @suffix if present. If @strings doesn't terminate with
+ * @suffix, then the returned string is equal to source @string.
+ *
+ * The returned string should be g_free() by the caller.
+ */
+gchar *
+nadp_utils_remove_suffix( const gchar *string, const gchar *suffix )
+{
+	gchar *removed;
+	gchar *ptr;
+
+	removed = g_strdup( string );
+
+	if( g_str_has_suffix( string, suffix )){
+		ptr = g_strrstr( removed, suffix );
+		ptr[0] = '\0';
+	}
+
+	return( removed );
+}
+
+/**
+ * nadp_utils_is_writable_dir:
+ * @path: the path of the directory to be tested.
+ *
+ * Returns: %TRUE if the directory is writable, %FALSE else.
+ *
+ * Please note that this type of test is subject to race conditions,
+ * as the directory may become unwritable after a successfull test,
+ * but before the caller has been able to actually write into it.
+ *
+ * There is no "super-test". Just try...
+ */
+gboolean
+nadp_utils_is_writable_dir( const gchar *path )
+{
+	static const gchar *thisfn = "nadp_utils_is_writable_dir";
+	GFile *file;
+	GError *error = NULL;
+	GFileInfo *info;
+	GFileType type;
+	gboolean writable;
+
+	if( !path || !g_utf8_strlen( path, -1 )){
+		return( FALSE );
+	}
+
+	file = g_file_new_for_path( path );
+	info = g_file_query_info( file,
+			G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE "," G_FILE_ATTRIBUTE_STANDARD_TYPE,
+			G_FILE_QUERY_INFO_NONE, NULL, &error );
+
+	if( error ){
+		g_warning( "%s: g_file_query_info error: %s", thisfn, error->message );
+		g_error_free( error );
+		g_object_unref( file );
+		return( FALSE );
+	}
+
+	type = g_file_info_get_file_type( info );
+	if( type != G_FILE_TYPE_DIRECTORY ){
+		g_debug( "%s: %s is not a directory", thisfn, path );
+		g_object_unref( info );
+		return( FALSE );
+	}
+
+	writable = g_file_info_get_attribute_boolean( info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE );
+	if( !writable ){
+		g_debug( "%s: %s is not writable", thisfn, path );
+	}
+	g_object_unref( info );
+
+	return( writable );
+}
+
+/**
+ * nadp_utils_path2id:
+ * @path: a full pathname.
+ *
+ * Returns: the id of the file, as a newly allocated string which
+ * should be g_free() by the caller.
+ *
+ * The id of the file is equal to the basename, minus the suffix.
+ */
+gchar *
+nadp_utils_path2id( const gchar *path )
+{
+	gchar *bname;
+	gchar *id;
+
+	bname = g_path_get_basename( path );
+	id = nadp_utils_remove_suffix( bname, NADP_DESKTOP_SUFFIX );
+	g_free( bname );
+
+	return( id );
+}
+
+/**
+ * nadp_utils_is_writable_file:
+ * @path: the path of the file to be tested.
+ *
+ * Returns: %TRUE if the file is writable, %FALSE else.
+ *
+ * Please note that this type of test is subject to race conditions,
+ * as the file may become unwritable after a successfull test,
+ * but before the caller has been able to actually write into it.
+ *
+ * There is no "super-test". Just try...
+ */
+gboolean
+nadp_utils_is_writable_file( const gchar *path )
+{
+	static const gchar *thisfn = "nadp_utils_is_writable_file";
+	GFile *file;
+	GError *error = NULL;
+	GFileInfo *info;
+	gboolean writable;
+
+	if( !path || !g_utf8_strlen( path, -1 )){
+		return( FALSE );
+	}
+
+	file = g_file_new_for_path( path );
+	info = g_file_query_info( file,
+			G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE "," G_FILE_ATTRIBUTE_STANDARD_TYPE,
+			G_FILE_QUERY_INFO_NONE, NULL, &error );
+
+	if( error ){
+		g_warning( "%s: g_file_query_info error: %s", thisfn, error->message );
+		g_error_free( error );
+		g_object_unref( file );
+		return( FALSE );
+	}
+
+	writable = g_file_info_get_attribute_boolean( info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE );
+	if( !writable ){
+		g_debug( "%s: %s is not writable", thisfn, path );
+	}
+	g_object_unref( info );
+
+	return( writable );
+}
+
+/**
+ * nadp_utils_delete_file:
+ * @path: the path of the file to be deleted.
+ *
+ * Returns: %TRUE if the file is successfully deleted, %FALSE else.
+ */
+gboolean
+nadp_utils_delete_file( const gchar *path )
+{
+	static const gchar *thisfn = "nadp_utils_delete_file";
+	gboolean deleted = FALSE;
+
+	if( !path || !g_utf8_strlen( path, -1 )){
+		return( FALSE );
+	}
+
+	if( g_unlink( path ) == 0 ){
+		deleted = TRUE;
+	} else {
+		g_warning( "%s: %s: %s", thisfn, path, g_strerror( errno ));
+	}
+
+	return( deleted );
+}
diff --git a/nautilus-actions/io-provider-desktop/nadp-utils.h b/nautilus-actions/io-provider-desktop/nadp-utils.h
new file mode 100644
index 0000000..9ff091c
--- /dev/null
+++ b/nautilus-actions/io-provider-desktop/nadp-utils.h
@@ -0,0 +1,60 @@
+/*
+ * Nautilus Actions
+ * A Nautilus extension which offers configurable context menu actions.
+ *
+ * Copyright (C) 2005 The GNOME Foundation
+ * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
+ * Copyright (C) 2009 Pierre Wieser and others (see AUTHORS)
+ *
+ * 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 Library; see the file COPYING.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ *   Frederic Ruaudel <grumz grumz net>
+ *   Rodrigo Moya <rodrigo gnome-db org>
+ *   Pierre Wieser <pwieser trychlos org>
+ *   ... and many others (see AUTHORS)
+ */
+
+#include "egg-desktop-file.h"
+
+#ifndef __NADP_UTILS_H__
+#define __NADP_UTILS_H__
+
+G_BEGIN_DECLS
+
+typedef struct {
+	gchar          *id;
+	EggDesktopFile *edf;
+}
+	NadpPropertiesStruct;
+
+GSList  *nadp_utils_split_path_list( const gchar *path_list );
+
+void     nadp_utils_gslist_free( GSList *list );
+
+gchar   *nadp_utils_remove_suffix( const gchar *string, const gchar *suffix );
+
+gboolean nadp_utils_is_writable_dir( const gchar *path );
+
+gchar   *nadp_utils_path2id( const gchar *path );
+
+gboolean nadp_utils_is_writable_file( const gchar *path );
+
+gboolean nadp_utils_delete_file( const gchar *path );
+
+G_END_DECLS
+
+#endif /* __NADP_UTILS_H__ */
diff --git a/nautilus-actions/io-provider-desktop/nadp-write.c b/nautilus-actions/io-provider-desktop/nadp-write.c
new file mode 100644
index 0000000..c65e96e
--- /dev/null
+++ b/nautilus-actions/io-provider-desktop/nadp-write.c
@@ -0,0 +1,190 @@
+/*
+ * Nautilus Actions
+ * A Nautilus extension which offers configurable context menu actions.
+ *
+ * Copyright (C) 2005 The GNOME Foundation
+ * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
+ * Copyright (C) 2009 Pierre Wieser and others (see AUTHORS)
+ *
+ * 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 Library; see the file COPYING.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ *   Frederic Ruaudel <grumz grumz net>
+ *   Rodrigo Moya <rodrigo gnome-db org>
+ *   Pierre Wieser <pwieser trychlos org>
+ *   ... and many others (see AUTHORS)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+
+#include "nadp-desktop-file.h"
+#include "nadp-desktop-provider.h"
+#include "nadp-write.h"
+#include "nadp-utils.h"
+#include "nadp-xdg-data-dirs.h"
+
+static guint write_item( const NAIIOProvider *provider, const NAObjectItem *item, const gchar *path, GSList **messages );
+
+/*
+ * NadpDesktopProvider is willing to write if user data dir exists (or
+ * can be created) and is writable
+ */
+gboolean
+nadp_iio_provider_is_willing_to_write( const NAIIOProvider *provider )
+{
+	static const gchar *thisfn = "nadp_write_iio_provider_is_willing_to_write";
+	gboolean willing_to;
+	gchar *userdir;
+	GSList *messages;
+
+	willing_to = FALSE;
+	messages = NULL;
+	g_debug( "%s: provider=%p", thisfn, ( void * ) provider );
+	g_return_val_if_fail( NADP_IS_DESKTOP_PROVIDER( provider ), willing_to );
+
+	userdir = nadp_xdg_data_dirs_get_user_dir( NADP_DESKTOP_PROVIDER( provider ), &messages );
+
+	if( g_file_test( userdir, G_FILE_TEST_IS_DIR )){
+		willing_to = nadp_utils_is_writable_dir( userdir );
+
+	} else if( g_mkdir_with_parents( userdir, 700 )){
+		g_warning( "%s: %s: %s", thisfn, userdir, g_strerror( errno ));
+
+	} else {
+		willing_to = nadp_utils_is_writable_dir( userdir );
+	}
+
+	g_free( userdir );
+
+	return( willing_to );
+}
+
+/*
+ * the item has been initially readen from a desktop file
+ * -> see if this initial desktop file is writable ?
+ *
+ * else we are going to write a new desktop file in user data dir
+ * -> see writability status of the desktop provider
+ */
+gboolean
+nadp_iio_provider_is_writable( const NAIIOProvider *provider, const NAObjectItem *item )
+{
+	gboolean writable;
+	NadpDesktopFile *ndf;
+	EggDesktopFile *edf;
+	const char *path;
+
+	writable = FALSE;
+	g_return_val_if_fail( NADP_IS_DESKTOP_PROVIDER( provider ), writable );
+	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), writable );
+
+	ndf = ( NadpDesktopFile * ) g_object_get_data( G_OBJECT( item ), "nadp-desktop-file" );
+
+	if( ndf ){
+		g_return_val_if_fail( NADP_IS_DESKTOP_FILE( ndf ), writable );
+		edf = nadp_desktop_file_get_egg_desktop_file( ndf );
+		path = egg_desktop_file_get_source( edf );
+		writable = nadp_utils_is_writable_file( path );
+
+	} else {
+		writable = nadp_iio_provider_is_willing_to_write( provider );
+	}
+
+	return( writable );
+}
+
+guint
+nadp_iio_provider_write_item( const NAIIOProvider *provider, const NAObjectItem *item, GSList **messages )
+{
+	guint ret;
+	NadpDesktopFile *ndf;
+	EggDesktopFile *edf;
+	gchar *path;
+	gchar *userdir;
+	gchar *id;
+	gchar *bname;
+
+	ret = NA_IIO_PROVIDER_NOT_WILLING_TO_WRITE;
+	g_return_val_if_fail( NADP_IS_DESKTOP_PROVIDER( provider ), ret );
+	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), ret );
+
+	ndf = ( NadpDesktopFile * ) g_object_get_data( G_OBJECT( item ), "nadp-desktop-file" );
+
+	if( ndf ){
+		g_return_val_if_fail( NADP_IS_DESKTOP_FILE( ndf ), ret );
+		edf = nadp_desktop_file_get_egg_desktop_file( ndf );
+		path = ( gchar * ) egg_desktop_file_get_source( edf );
+
+	} else {
+		userdir = nadp_xdg_data_dirs_get_user_dir( NADP_DESKTOP_PROVIDER( provider ), messages );
+		id = na_object_get_id( item );
+		bname = g_strdup_printf( "%s%s", id, NADP_DESKTOP_SUFFIX );
+		g_free( id );
+		path = g_build_filename( userdir, NADP_DESKTOP_PROVIDER_SUBDIRS, bname, NULL );
+		g_free( bname );
+		g_free( userdir );
+
+		ret = write_item( provider, item, path, messages );
+
+		if( ret == NA_IIO_PROVIDER_WRITE_OK ){
+			ndf = nadp_desktop_file_new_from_path( path );
+			g_object_set_data( G_OBJECT( item ), "nadp-desktop-file", ndf );
+			g_object_weak_ref( G_OBJECT( item ), ( GWeakNotify ) g_object_unref, ndf );
+		}
+
+		g_free( path );
+	}
+
+	return( ret );
+}
+
+static guint
+write_item( const NAIIOProvider *provider, const NAObjectItem *item, const gchar *path, GSList **messages )
+{
+	return( NA_IIO_PROVIDER_WRITE_OK );
+}
+
+guint
+nadp_iio_provider_delete_item( const NAIIOProvider *provider, const NAObjectItem *item, GSList **messages )
+{
+	guint ret;
+	NadpDesktopFile *ndf;
+	EggDesktopFile *edf;
+	const char *path;
+
+	ret = NA_IIO_PROVIDER_NOT_WILLING_TO_WRITE;
+	g_return_val_if_fail( NADP_IS_DESKTOP_PROVIDER( provider ), ret );
+	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), ret );
+
+	ndf = ( NadpDesktopFile * ) g_object_get_data( G_OBJECT( item ), "nadp-desktop-file" );
+
+	if( ndf ){
+		g_return_val_if_fail( NADP_IS_DESKTOP_FILE( ndf ), ret );
+		edf = nadp_desktop_file_get_egg_desktop_file( ndf );
+		path = egg_desktop_file_get_source( edf );
+		if( nadp_utils_delete_file( path )){
+			ret = NA_IIO_PROVIDER_WRITE_OK;
+		}
+	} else {
+		ret = NA_IIO_PROVIDER_WRITE_OK;
+	}
+
+	return( ret );
+}
diff --git a/nautilus-actions/io-provider-desktop/nadp-write.h b/nautilus-actions/io-provider-desktop/nadp-write.h
new file mode 100644
index 0000000..ddeb4c0
--- /dev/null
+++ b/nautilus-actions/io-provider-desktop/nadp-write.h
@@ -0,0 +1,49 @@
+/*
+ * Nautilus Actions
+ * A Nautilus extension which offers configurable context menu actions.
+ *
+ * Copyright (C) 2005 The GNOME Foundation
+ * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
+ * Copyright (C) 2009 Pierre Wieser and others (see AUTHORS)
+ *
+ * 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 Library; see the file COPYING.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ *   Frederic Ruaudel <grumz grumz net>
+ *   Rodrigo Moya <rodrigo gnome-db org>
+ *   Pierre Wieser <pwieser trychlos org>
+ *   ... and many others (see AUTHORS)
+ */
+
+#include <nautilus-actions/api/na-iio-provider.h>
+#include <nautilus-actions/api/na-object-api.h>
+
+#ifndef __NADP_WRITE_H__
+#define __NADP_WRITE_H__
+
+G_BEGIN_DECLS
+
+gboolean nadp_iio_provider_is_willing_to_write( const NAIIOProvider *provider );
+
+gboolean nadp_iio_provider_is_writable( const NAIIOProvider *provider, const NAObjectItem *item );
+
+guint    nadp_iio_provider_write_item( const NAIIOProvider *provider, const NAObjectItem *item, GSList **messages );
+
+guint    nadp_iio_provider_delete_item( const NAIIOProvider *provider, const NAObjectItem *item, GSList **messages );
+
+G_END_DECLS
+
+#endif /* __NADP_WRITE_H__ */
diff --git a/nautilus-actions/io-provider-desktop/nadp-xdg-data-dirs.c b/nautilus-actions/io-provider-desktop/nadp-xdg-data-dirs.c
new file mode 100644
index 0000000..15056ac
--- /dev/null
+++ b/nautilus-actions/io-provider-desktop/nadp-xdg-data-dirs.c
@@ -0,0 +1,142 @@
+/*
+ * Nautilus Actions
+ * A Nautilus extension which offers configurable context menu actions.
+ *
+ * Copyright (C) 2005 The GNOME Foundation
+ * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
+ * Copyright (C) 2009 Pierre Wieser and others (see AUTHORS)
+ *
+ * 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 Library; see the file COPYING.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ *   Frederic Ruaudel <grumz grumz net>
+ *   Rodrigo Moya <rodrigo gnome-db org>
+ *   Pierre Wieser <pwieser trychlos org>
+ *   ... and many others (see AUTHORS)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "nadp-desktop-provider.h"
+#include "nadp-xdg-data-dirs.h"
+
+/**
+ * nadp_xdg_data_dirs_get_dirs:
+ * @provider: this #NadpDesktopProvider instance.
+ * @messages: error messages go here.
+ *
+ * Returns: the ordered list of data directories, most important first,
+ * as a GSList of newly allocated strings.
+ *
+ * The returned list, along with the pointed out strings, should be
+ * freed by the caller.
+ */
+GSList *
+nadp_xdg_data_dirs_get_dirs( const NadpDesktopProvider *provider, GSList **messages )
+{
+	GSList *listdirs;
+	gchar *userdir;
+	GSList *datadirs;
+
+	userdir = nadp_xdg_data_dirs_get_user_dir( provider, messages );
+	listdirs = g_slist_prepend( NULL, userdir );
+
+	datadirs = nadp_xdg_data_dirs_get_data_dirs( provider, messages );
+	listdirs = g_slist_concat( listdirs, datadirs );
+
+	return( listdirs );
+}
+
+/**
+ * nadp_xdg_data_dirs_get_user_dir:
+ * @provider: this #NadpDesktopProvider instance.
+ * @messages: error messages go here.
+ *
+ * Returns: the path to the single base directory relative to which
+ * user-specific data files should be written, as a newly allocated
+ * string.
+ *
+ * This directory is defined by the environment variable XDG_DATA_HOME.
+ * It defaults to ~/.local/share.
+ *
+ * source: http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html
+ *
+ * The returned string should be g_free() by the caller.
+ */
+gchar *
+nadp_xdg_data_dirs_get_user_dir( const NadpDesktopProvider *provider, GSList **messages )
+{
+	static const gchar *thisfn = "nadp_xdg_data_dirs_get_user_dir";
+	gchar *dir;
+
+	/*dir = g_strdup( g_getenv( "XDG_DATA_HOME" ));
+
+	if( !dir || !g_utf8_strlen( dir, -1 )){
+		g_free( dir );
+		dir = g_strdup_printf( "%s/.local/share", )
+	}*/
+
+	dir = g_strdup( g_get_user_data_dir());
+
+	g_debug( "%s: provider=%p, messages=%p, user_dir=%s", thisfn, ( void * ) provider, ( void * ) messages, dir );
+
+	return( dir );
+}
+
+/**
+ * nadp_xdg_data_dirs_get_data_dirs:
+ * @provider: this #NadpDesktopProvider instance.
+ * @messages: error messages go here.
+ *
+ * Returns: the set of preference ordered base directories relative to
+ * which data files should be written, as a GSList of newly allocated
+ * strings.
+ *
+ * This set of directories is defined by the environment variable
+ * XDG_DATA_DIRS. It defaults to /usr/local/share:/usr/share.
+ *
+ * source: http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html
+ *
+ * The returned list, along with the pointed out strings, should be freed
+ * by the caller.
+ */
+GSList *
+nadp_xdg_data_dirs_get_data_dirs( const NadpDesktopProvider *provider, GSList **messages )
+{
+	static const gchar *thisfn = "nadp_xdg_data_dirs_get_data_dirs";
+	gchar **dirs;
+	gchar **id;
+	GSList *paths, *ip;
+
+	paths = NULL;
+	dirs = ( gchar ** ) g_get_system_data_dirs();
+	id = dirs;
+	while( *id ){
+		paths = g_slist_prepend( paths, g_strdup( *id ));
+		id++;
+	}
+
+	paths = g_slist_reverse( paths );
+
+	for( ip = paths ; ip ; ip = ip->next ){
+		g_debug( "%s: provider=%p, messages=%p, data_dir=%s",
+				thisfn, ( void * ) provider, ( void * ) messages, ( const gchar * ) ip->data );
+	}
+
+	return( paths );
+}
diff --git a/nautilus-actions/io-provider-desktop/nadp-xdg-data-dirs.h b/nautilus-actions/io-provider-desktop/nadp-xdg-data-dirs.h
new file mode 100644
index 0000000..b637240
--- /dev/null
+++ b/nautilus-actions/io-provider-desktop/nadp-xdg-data-dirs.h
@@ -0,0 +1,46 @@
+/*
+ * Nautilus Actions
+ * A Nautilus extension which offers configurable context menu actions.
+ *
+ * Copyright (C) 2005 The GNOME Foundation
+ * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
+ * Copyright (C) 2009 Pierre Wieser and others (see AUTHORS)
+ *
+ * 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 Library; see the file COPYING.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ *   Frederic Ruaudel <grumz grumz net>
+ *   Rodrigo Moya <rodrigo gnome-db org>
+ *   Pierre Wieser <pwieser trychlos org>
+ *   ... and many others (see AUTHORS)
+ */
+
+#include "nadp-desktop-provider.h"
+
+#ifndef __NADP_XDG_DATA_DIRS_H__
+#define __NADP_XDG_DATA_DIRS_H__
+
+G_BEGIN_DECLS
+
+GSList *nadp_xdg_data_dirs_get_dirs( const NadpDesktopProvider *provider, GSList **messages );
+
+gchar  *nadp_xdg_data_dirs_get_user_dir( const NadpDesktopProvider *provider, GSList **messages );
+
+GSList *nadp_xdg_data_dirs_get_data_dirs( const NadpDesktopProvider *provider, GSList **messages );
+
+G_END_DECLS
+
+#endif /* __NADP_XDG_DATA_DIRS_H__ */
diff --git a/nautilus-actions/io-provider-gconf/nagp-read.h b/nautilus-actions/io-provider-gconf/nagp-read.h
index 9dcdc8d..42565ca 100644
--- a/nautilus-actions/io-provider-gconf/nagp-read.h
+++ b/nautilus-actions/io-provider-gconf/nagp-read.h
@@ -31,19 +31,6 @@
 #ifndef __NAGP_READ_H__
 #define __NAGP_READ_H__
 
-/**
- * SECTION: nagp_gconf_provider
- * @short_description: #NagpGConfProvider class definition.
- * @include: na-gconf-provider.h
- *
- * This class manages the GConf I/O storage subsystem, or, in other words,
- * the GConf subsystem as an NAIIOProvider. As this, it should only be
- * used through the NAIIOProvider interface.
- *
- * #NagpGConfProvider uses #NAGConfMonitor to watch at the configuration
- * tree. Modifications are notified to the NAIIOProvider interface.
- */
-
 #include <nautilus-actions/api/na-iio-provider.h>
 
 G_BEGIN_DECLS
diff --git a/nautilus-actions/io-provider-gconf/nagp-write.h b/nautilus-actions/io-provider-gconf/nagp-write.h
index 366458b..426a83a 100644
--- a/nautilus-actions/io-provider-gconf/nagp-write.h
+++ b/nautilus-actions/io-provider-gconf/nagp-write.h
@@ -31,19 +31,6 @@
 #ifndef __NAGP_WRITE_H__
 #define __NAGP_WRITE_H__
 
-/**
- * SECTION: nagp_gconf_provider
- * @short_description: #NagpGConfProvider class definition.
- * @include: na-gconf-provider.h
- *
- * This class manages the GConf I/O storage subsystem, or, in other words,
- * the GConf subsystem as an NAIIOProvider. As this, it should only be
- * used through the NAIIOProvider interface.
- *
- * #NagpGConfProvider uses #NAGConfMonitor to watch at the configuration
- * tree. Modifications are notified to the NAIIOProvider interface.
- */
-
 #include <nautilus-actions/api/na-iio-provider.h>
 #include <nautilus-actions/api/na-object-api.h>
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]