[nautilus-actions] Display Nautilus-Actions actions as a submenu in Nautilus context menu



commit 2061e6c1b8cf40c33f957f8694ffcd4628271f3a
Author: Pierre Wieser <pwieser trychlos org>
Date:   Thu Aug 20 17:48:29 2009 +0200

    Display Nautilus-Actions actions as a submenu in Nautilus context menu
    
    Note that for now the modification is not taken into account while Nautilus selection
    has not changed, or Nautilus has been relaunched.

 ChangeLog                                |   29 ++
 src/common/Makefile.am                   |    2 +
 src/common/na-gconf.c                    |    3 +
 src/common/na-iprefs.c                   |  173 +++++++++++++
 src/common/na-iprefs.h                   |   77 ++++++
 src/nact/Makefile.am                     |    2 +
 src/nact/nact-imenubar.c                 |   25 ++-
 src/nact/nact-iprefs.c                   |   36 ++--
 src/nact/nact-iprefs.h                   |   26 +-
 src/nact/nact-preferences-editor.c       |  411 ++++++++++++++++++++++++++++++
 src/nact/nact-preferences-editor.h       |   74 ++++++
 src/nact/nautilus-actions-config-tool.ui |  120 ++++++++-
 src/plugin/nautilus-actions.c            |   56 ++++-
 13 files changed, 986 insertions(+), 48 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 9cdb506..97a123d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+2009-08-20 Pierre Wieser <pwieser trychlos org>
+
+	Display actions as a submenu.
+
+	* src/common/na-iprefs.c:
+	* src/common/na-iprefs.h: New files.
+	Manage preferences which are used by Nautilus-Actions plugin.
+
+	* src/common/na-gconf.c: Fix typo.
+
+	* src/nact/nact-imenubar.c:
+	Add an item in the menubar to run the Preferences dialog.
+
+	* src/nact/nact-iprefs.c:
+	* src/nact/nact-iprefs.h: Fix typos.
+
+	* src/nact/nact-preferences-editor.c:
+	* src/nact/nact-preferences-editor.h: New files.
+	Let the user edit its preferences.
+
+	* src/nact/nautilus-actions-config-tool.ui:
+	Creates the PreferencesDialog dialog.
+
+	* src/common/Makefile.am:
+	* src/nact/Makefile.am: Updated accordingly.
+
+	* src/plugin/nautilus-actions.c:
+	Take into account the DisplayAsSubmenu preference.
+
 2009-08-19 Pierre Wieser <pwieser trychlos org>
 
 	* src/nact/nact-statusbar.c:
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 9110d1d..f801450 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -52,6 +52,8 @@ libnact_la_SOURCES = \
 	na-iio-provider.h							\
 	na-ipivot-consumer.c						\
 	na-ipivot-consumer.h						\
+	na-iprefs.c									\
+	na-iprefs.h									\
 	na-object.c									\
 	na-object.h									\
 	na-pivot.c									\
diff --git a/src/common/na-gconf.c b/src/common/na-gconf.c
index 8fa2b88..70ed9c8 100644
--- a/src/common/na-gconf.c
+++ b/src/common/na-gconf.c
@@ -1079,6 +1079,7 @@ install_gconf_watch( NAGConf *gconf )
 			NULL,
 			&error
 		);
+
 	if( error ){
 		g_warning( "%s: error=%s", thisfn, error->message );
 		g_error_free( error );
@@ -1096,6 +1097,7 @@ install_gconf_watched_dir( NAGConf *gconf )
 
 	gconf_client_add_dir(
 			gconf->private->gconf, NA_GCONF_CONFIG_PATH, GCONF_CLIENT_PRELOAD_RECURSIVE, &error );
+
 	if( error ){
 		g_warning( "%s: error=%s", thisfn, error->message );
 		g_error_free( error );
@@ -1119,6 +1121,7 @@ remove_gconf_watched_dir( NAGConf *gconf )
 	GError *error = NULL;
 
 	gconf_client_remove_dir( gconf->private->gconf, NA_GCONF_CONFIG_PATH, &error );
+
 	if( error ){
 		g_warning( "%s: error=%s", thisfn, error->message );
 		g_error_free( error );
diff --git a/src/common/na-iprefs.c b/src/common/na-iprefs.c
new file mode 100644
index 0000000..e46eb0a
--- /dev/null
+++ b/src/common/na-iprefs.c
@@ -0,0 +1,173 @@
+/*
+ * 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 <gconf/gconf.h>
+#include <gconf/gconf-client.h>
+
+#include "na-iprefs.h"
+
+/* private interface data
+ */
+struct NAIPrefsInterfacePrivate {
+	GConfClient *client;
+};
+
+static GType    register_type( void );
+static void     interface_base_init( NAIPrefsInterface *klass );
+static void     interface_base_finalize( NAIPrefsInterface *klass );
+
+static gboolean read_key_bool( NAIPrefs *instance, const gchar *name );
+static void     write_key_bool( NAIPrefs *instance, const gchar *name, gboolean value );
+
+GType
+na_iprefs_get_type( void )
+{
+	static GType iface_type = 0;
+
+	if( !iface_type ){
+		iface_type = register_type();
+	}
+
+	return( iface_type );
+}
+
+static GType
+register_type( void )
+{
+	static const gchar *thisfn = "na_iprefs_register_type";
+	g_debug( "%s", thisfn );
+
+	static const GTypeInfo info = {
+		sizeof( NAIPrefsInterface ),
+		( GBaseInitFunc ) interface_base_init,
+		( GBaseFinalizeFunc ) interface_base_finalize,
+		NULL,
+		NULL,
+		NULL,
+		0,
+		0,
+		NULL
+	};
+
+	GType type = g_type_register_static( G_TYPE_INTERFACE, "NAIPrefs", &info, 0 );
+
+	g_type_interface_add_prerequisite( type, G_TYPE_OBJECT );
+
+	return( type );
+}
+
+static void
+interface_base_init( NAIPrefsInterface *klass )
+{
+	static const gchar *thisfn = "na_iprefs_interface_base_init";
+	static gboolean initialized = FALSE;
+
+	if( !initialized ){
+		g_debug( "%s: klass=%p", thisfn, klass );
+
+		klass->private = g_new0( NAIPrefsInterfacePrivate, 1 );
+
+		klass->private->client = gconf_client_get_default();
+
+		initialized = TRUE;
+	}
+}
+
+static void
+interface_base_finalize( NAIPrefsInterface *klass )
+{
+	static const gchar *thisfn = "na_iprefs_interface_base_finalize";
+	static gboolean finalized = FALSE ;
+
+	if( !finalized ){
+		g_debug( "%s: klass=%p", thisfn, klass );
+
+		g_free( klass->private );
+
+		finalized = TRUE;
+	}
+}
+
+/**
+ * Get/set a named boolean.
+ *
+ * @window: this NAWindow-derived window.
+ */
+gboolean
+na_iprefs_get_bool( NAIPrefs *instance, const gchar *name )
+{
+	return( read_key_bool( instance, name ));
+}
+
+void
+na_iprefs_set_bool( NAIPrefs *instance, const gchar *name, gboolean value )
+{
+	write_key_bool( instance, name, value );
+}
+
+static gboolean
+read_key_bool( NAIPrefs *instance, const gchar *name )
+{
+	static const gchar *thisfn = "na_iprefs_read_key_bool";
+	GError *error = NULL;
+	gchar *path = g_strdup_printf( "%s/%s", NA_GCONF_PREFS_PATH, name );
+
+	gboolean value = gconf_client_get_bool( NA_IPREFS_GET_INTERFACE( instance )->private->client, path, &error );
+
+	if( error ){
+		g_warning( "%s: name=%s, %s", thisfn, name, error->message );
+		g_error_free( error );
+	}
+
+	g_free( path );
+	return( value );
+}
+
+static void
+write_key_bool( NAIPrefs *instance, const gchar *name, gboolean value )
+{
+	static const gchar *thisfn = "na_iprefs_write_key_bool";
+	GError *error = NULL;
+	gchar *path = g_strdup_printf( "%s/%s", NA_GCONF_PREFS_PATH, name );
+
+	gconf_client_set_bool( NA_IPREFS_GET_INTERFACE( instance )->private->client, path, value, &error );
+
+	if( error ){
+		g_warning( "%s: name=%s, %s", thisfn, name, error->message );
+		g_error_free( error );
+	}
+
+	g_free( path );
+}
diff --git a/src/common/na-iprefs.h b/src/common/na-iprefs.h
new file mode 100644
index 0000000..e8abe26
--- /dev/null
+++ b/src/common/na-iprefs.h
@@ -0,0 +1,77 @@
+/*
+ * 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 __NA_IPREFS_H__
+#define __NA_IPREFS_H__
+
+/*
+ * NAIPrefs interface definition.
+ *
+ * This interface is to be implemented by all modules which wish take
+ * benefit of preferences management.
+ */
+
+#include <glib-object.h>
+
+#include "na-gconf-keys.h"
+
+G_BEGIN_DECLS
+
+#define NA_IPREFS_TYPE						( na_iprefs_get_type())
+#define NA_IPREFS( object )					( G_TYPE_CHECK_INSTANCE_CAST( object, NA_IPREFS_TYPE, NAIPrefs ))
+#define NA_IS_IPREFS( object )				( G_TYPE_CHECK_INSTANCE_TYPE( object, NA_IPREFS_TYPE ))
+#define NA_IPREFS_GET_INTERFACE( instance )	( G_TYPE_INSTANCE_GET_INTERFACE(( instance ), NA_IPREFS_TYPE, NAIPrefsInterface ))
+
+typedef struct NAIPrefs NAIPrefs;
+
+typedef struct NAIPrefsInterfacePrivate NAIPrefsInterfacePrivate;
+
+typedef struct {
+	GTypeInterface            parent;
+	NAIPrefsInterfacePrivate *private;
+}
+	NAIPrefsInterface;
+
+GType    na_iprefs_get_type( void );
+
+gboolean na_iprefs_get_bool( NAIPrefs *instance, const gchar *key );
+void     na_iprefs_set_bool( NAIPrefs *instance, const gchar *key, gboolean value );
+
+/* GConf general information
+ */
+#define NA_GCONF_PREFS_PATH		NAUTILUS_ACTIONS_CONFIG_GCONF_BASEDIR "/" NA_GCONF_SCHEMA_PREFERENCES
+
+/* Preference keys managed by IPrefs interface
+ */
+#define PREFS_DISPLAY_AS_SUBMENU			"display-as-submenu"
+
+G_END_DECLS
+
+#endif /* __NA_IPREFS_H__ */
diff --git a/src/nact/Makefile.am b/src/nact/Makefile.am
index a52c660..c8acd94 100644
--- a/src/nact/Makefile.am
+++ b/src/nact/Makefile.am
@@ -70,6 +70,8 @@ nautilus_actions_config_tool_SOURCES = \
 	nact-main.c											\
 	nact-main-window.c									\
 	nact-main-window.h									\
+	nact-preferences-editor.c							\
+	nact-preferences-editor.h							\
 	nact-statusbar.c									\
 	nact-statusbar.h									\
 	nact-window.c										\
diff --git a/src/nact/nact-imenubar.c b/src/nact/nact-imenubar.c
index c601f17..ec4863a 100644
--- a/src/nact/nact-imenubar.c
+++ b/src/nact/nact-imenubar.c
@@ -37,6 +37,7 @@
 #include "nact-application.h"
 #include "nact-assistant-export.h"
 #include "nact-assistant-import.h"
+#include "nact-preferences-editor.h"
 #include "nact-statusbar.h"
 #include "nact-imenubar.h"
 
@@ -84,6 +85,8 @@ static void       on_delete_activated( GtkMenuItem *item, NactWindow *window );
 static void       on_delete_selected( GtkItem *item, NactWindow *window );
 static void       on_reload_activated( GtkMenuItem *item, NactWindow *window );
 static void       on_reload_selected( GtkItem *item, NactWindow *window );
+static void       on_preferences_activated( GtkMenuItem *item, NactWindow *window );
+static void       on_preferences_selected( GtkItem *item, NactWindow *window );
 
 static void       on_tools_selected( GtkMenuItem *item, NactWindow *window );
 static void       on_import_activated( GtkMenuItem *item, NactWindow *window );
@@ -342,6 +345,13 @@ create_edit_menu( NactMainWindow *window, GtkMenuBar *menubar )
 	item = gtk_image_menu_item_new_with_mnemonic( _( "_Reload the list of actions" ));
 	gtk_menu_shell_append( GTK_MENU_SHELL( menu ), item );
 	signal_connect( window, item, G_CALLBACK( on_reload_activated ), G_CALLBACK( on_reload_selected ));
+
+	item = gtk_separator_menu_item_new();
+	gtk_menu_shell_append( GTK_MENU_SHELL( menu ), item );
+
+	item = gtk_image_menu_item_new_from_stock( GTK_STOCK_PREFERENCES, NULL );
+	gtk_menu_shell_append( GTK_MENU_SHELL( menu ), item );
+	signal_connect( window, item, G_CALLBACK( on_preferences_activated ), G_CALLBACK( on_preferences_selected ));
 }
 
 static void
@@ -748,7 +758,20 @@ static void
 on_reload_selected( GtkItem *item, NactWindow *window )
 {
 	/* i18n: tooltip displayed in the status bar when selecting the 'Reload' item */
-	nact_statusbar_display_status( NACT_MAIN_WINDOW( window ), PROP_IMENUBAR_STATUS_CONTEXT, _( " Cancel your current modifications and reload the list of actions." ));
+	nact_statusbar_display_status( NACT_MAIN_WINDOW( window ), PROP_IMENUBAR_STATUS_CONTEXT, _( "Cancel your current modifications and reload the list of actions." ));
+}
+
+static void
+on_preferences_activated( GtkMenuItem *item, NactWindow *window )
+{
+	nact_preferences_editor_run( window );
+}
+
+static void
+on_preferences_selected( GtkItem *item, NactWindow *window )
+{
+	/* i18n: tooltip displayed in the status bar when selecting the 'Preferences' item */
+	nact_statusbar_display_status( NACT_MAIN_WINDOW( window ), PROP_IMENUBAR_STATUS_CONTEXT, _( "Edit your preferences." ));
 }
 
 static void
diff --git a/src/nact/nact-iprefs.c b/src/nact/nact-iprefs.c
index 4da3dc9..923cf5e 100644
--- a/src/nact/nact-iprefs.c
+++ b/src/nact/nact-iprefs.c
@@ -36,7 +36,7 @@
 #include <gconf/gconf.h>
 #include <gconf/gconf-client.h>
 
-#include <common/na-gconf-keys.h>
+#include <common/na-iprefs.h>
 
 #include "nact-iprefs.h"
 
@@ -46,31 +46,27 @@ struct NactIPrefsInterfacePrivate {
 	GConfClient *client;
 };
 
-/* GConf general information
- */
-#define NA_GCONF_PREFS_PATH		NAUTILUS_ACTIONS_CONFIG_GCONF_BASEDIR "/" NA_GCONF_SCHEMA_PREFERENCES
-
 /* key to read/write the last visited folder when browsing for a file
  */
 #define IPREFS_ICONDITION_FOLDER_URI			"iconditions-folder-uri"
 #define IPREFS_IMPORT_ACTIONS_FOLDER_URI		"import-folder-uri"
 #define IPREFS_EXPORT_ACTIONS_FOLDER_URI		"export-folder-uri"
 
-static GType   register_type( void );
-static void    interface_base_init( NactIPrefsInterface *klass );
-static void    interface_base_finalize( NactIPrefsInterface *klass );
-
-static gchar  *v_get_iprefs_window_id( NactWindow *window );
-
-static GSList *read_key_listint( NactWindow *window, const gchar *key );
-static void    write_key_listint( NactWindow *window, const gchar *key, GSList *list );
-static void    listint_to_position( NactWindow *window, GSList *list, gint *x, gint *y, gint *width, gint *height );
-static GSList *position_to_listint( NactWindow *window, gint x, gint y, gint width, gint height );
-static void    free_listint( GSList *list );
-static gchar  *read_key_str( NactWindow *window, const gchar *key );
-static void    save_key_str( NactWindow *window, const gchar *key, const gchar *text );
-static gint    read_key_int( NactWindow *window, const gchar *name );
-static void    write_key_int( NactWindow *window, const gchar *name, gint value );
+static GType    register_type( void );
+static void     interface_base_init( NactIPrefsInterface *klass );
+static void     interface_base_finalize( NactIPrefsInterface *klass );
+
+static gchar   *v_get_iprefs_window_id( NactWindow *window );
+
+static GSList  *read_key_listint( NactWindow *window, const gchar *key );
+static void     write_key_listint( NactWindow *window, const gchar *key, GSList *list );
+static void     listint_to_position( NactWindow *window, GSList *list, gint *x, gint *y, gint *width, gint *height );
+static GSList  *position_to_listint( NactWindow *window, gint x, gint y, gint width, gint height );
+static void     free_listint( GSList *list );
+static gchar   *read_key_str( NactWindow *window, const gchar *key );
+static void     save_key_str( NactWindow *window, const gchar *key, const gchar *text );
+static gint     read_key_int( NactWindow *window, const gchar *name );
+static void     write_key_int( NactWindow *window, const gchar *name, gint value );
 
 GType
 nact_iprefs_get_type( void )
diff --git a/src/nact/nact-iprefs.h b/src/nact/nact-iprefs.h
index e2caa23..0e3fe2c 100644
--- a/src/nact/nact-iprefs.h
+++ b/src/nact/nact-iprefs.h
@@ -63,25 +63,25 @@ typedef struct {
 }
 	NactIPrefsInterface;
 
-GType nact_iprefs_get_type( void );
+GType    nact_iprefs_get_type( void );
 
-void   nact_iprefs_position_window( NactWindow *window );
-void   nact_iprefs_position_named_window( NactWindow *window, GtkWindow *toplevel, const gchar *name );
+void     nact_iprefs_position_window( NactWindow *window );
+void     nact_iprefs_position_named_window( NactWindow *window, GtkWindow *toplevel, const gchar *name );
 
-void   nact_iprefs_save_window_position( NactWindow *window );
-void   nact_iprefs_save_named_window_position( NactWindow *window, GtkWindow *toplevel, const gchar *name );
+void     nact_iprefs_save_window_position( NactWindow *window );
+void     nact_iprefs_save_named_window_position( NactWindow *window, GtkWindow *toplevel, const gchar *name );
 
-gchar *nact_iprefs_get_iconditions_folder_uri( NactWindow *window );
-void   nact_iprefs_save_iconditions_folder_uri( NactWindow *window, const gchar *uri );
+gchar   *nact_iprefs_get_iconditions_folder_uri( NactWindow *window );
+void     nact_iprefs_save_iconditions_folder_uri( NactWindow *window, const gchar *uri );
 
-gchar *nact_iprefs_get_import_folder_uri( NactWindow *window );
-void   nact_iprefs_save_import_folder_uri( NactWindow *window, const gchar *uri );
+gchar   *nact_iprefs_get_import_folder_uri( NactWindow *window );
+void     nact_iprefs_save_import_folder_uri( NactWindow *window, const gchar *uri );
 
-gchar *nact_iprefs_get_export_folder_uri( NactWindow *window );
-void   nact_iprefs_save_export_folder_uri( NactWindow *window, const gchar *uri );
+gchar   *nact_iprefs_get_export_folder_uri( NactWindow *window );
+void     nact_iprefs_save_export_folder_uri( NactWindow *window, const gchar *uri );
 
-gint   nact_iprefs_get_int( NactWindow *window, const gchar *key );
-void   nact_iprefs_set_int( NactWindow *window, const gchar *key, gint value );
+gint     nact_iprefs_get_int( NactWindow *window, const gchar *key );
+void     nact_iprefs_set_int( NactWindow *window, const gchar *key, gint value );
 
 G_END_DECLS
 
diff --git a/src/nact/nact-preferences-editor.c b/src/nact/nact-preferences-editor.c
new file mode 100644
index 0000000..82f567b
--- /dev/null
+++ b/src/nact/nact-preferences-editor.c
@@ -0,0 +1,411 @@
+/*
+ * 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 <glib/gi18n.h>
+
+#include <common/na-iprefs.h>
+
+#include "nact-application.h"
+#include "nact-iprefs.h"
+#include "nact-preferences-editor.h"
+
+/* private class data
+ */
+struct NactPreferencesEditorClassPrivate {
+};
+
+/* private instance data
+ */
+struct NactPreferencesEditorPrivate {
+	gboolean         dispose_has_run;
+	NactWindow      *parent;
+};
+
+static GObjectClass *st_parent_class = NULL;
+
+static GType    register_type( void );
+static void     class_init( NactPreferencesEditorClass *klass );
+static void     iprefs_iface_init( NAIPrefsInterface *iface );
+static void     instance_init( GTypeInstance *instance, gpointer klass );
+static void     instance_dispose( GObject *dialog );
+static void     instance_finalize( GObject *dialog );
+
+static NactPreferencesEditor *preferences_editor_new( BaseApplication *application );
+
+static gchar   *do_get_iprefs_window_id( NactWindow *window );
+static gchar   *do_get_dialog_name( BaseWindow *dialog );
+static void     on_initial_load_dialog( BaseWindow *dialog );
+static void     on_runtime_init_dialog( BaseWindow *dialog );
+static void     on_all_widgets_showed( BaseWindow *dialog );
+/*static void     setup_buttons( NactPreferencesEditor *dialog, gboolean is_modified );
+static void     on_modified_field( NactWindow *dialog );*/
+static void     on_submenu_toggled( GtkToggleButton *button, NactWindow *window );
+static void     on_cancel_clicked( GtkButton *button, NactWindow *window );
+static void     on_ok_clicked( GtkButton *button, NactWindow *window );
+static void     save_preferences( NactPreferencesEditor *editor );
+static gboolean on_dialog_response( GtkDialog *dialog, gint code, BaseWindow *window );
+
+GType
+nact_preferences_editor_get_type( void )
+{
+	static GType dialog_type = 0;
+
+	if( !dialog_type ){
+		dialog_type = register_type();
+	}
+
+	return( dialog_type );
+}
+
+static GType
+register_type( void )
+{
+	static const gchar *thisfn = "nact_preferences_editor_register_type";
+	g_debug( "%s", thisfn );
+
+	static GTypeInfo info = {
+		sizeof( NactPreferencesEditorClass ),
+		( GBaseInitFunc ) NULL,
+		( GBaseFinalizeFunc ) NULL,
+		( GClassInitFunc ) class_init,
+		NULL,
+		NULL,
+		sizeof( NactPreferencesEditor ),
+		0,
+		( GInstanceInitFunc ) instance_init
+	};
+
+	GType type = g_type_register_static( NACT_WINDOW_TYPE, "NactPreferencesEditor", &info, 0 );
+
+	/* implement IPrefs interface
+	 */
+	static const GInterfaceInfo prefs_iface_info = {
+		( GInterfaceInitFunc ) iprefs_iface_init,
+		NULL,
+		NULL
+	};
+
+	g_type_add_interface_static( type, NA_IPREFS_TYPE, &prefs_iface_info );
+
+	return( type );
+}
+
+static void
+class_init( NactPreferencesEditorClass *klass )
+{
+	static const gchar *thisfn = "nact_preferences_editor_class_init";
+	g_debug( "%s: klass=%p", thisfn, klass );
+
+	st_parent_class = g_type_class_peek_parent( klass );
+
+	GObjectClass *object_class = G_OBJECT_CLASS( klass );
+	object_class->dispose = instance_dispose;
+	object_class->finalize = instance_finalize;
+
+	klass->private = g_new0( NactPreferencesEditorClassPrivate, 1 );
+
+	BaseWindowClass *base_class = BASE_WINDOW_CLASS( klass );
+	base_class->initial_load_toplevel = on_initial_load_dialog;
+	base_class->runtime_init_toplevel = on_runtime_init_dialog;
+	base_class->all_widgets_showed = on_all_widgets_showed;
+	base_class->dialog_response = on_dialog_response;
+	base_class->get_toplevel_name = do_get_dialog_name;
+
+	NactWindowClass *nact_class = NACT_WINDOW_CLASS( klass );
+	nact_class->get_iprefs_window_id = do_get_iprefs_window_id;
+}
+
+static void
+iprefs_iface_init( NAIPrefsInterface *iface )
+{
+	static const gchar *thisfn = "nact_preferences_editor_iprefs_iface_init";
+	g_debug( "%s: iface=%p", thisfn, iface );
+}
+
+static void
+instance_init( GTypeInstance *instance, gpointer klass )
+{
+	static const gchar *thisfn = "nact_preferences_editor_instance_init";
+	g_debug( "%s: instance=%p, klass=%p", thisfn, instance, klass );
+
+	g_assert( NACT_IS_PREFERENCES_EDITOR( instance ));
+	NactPreferencesEditor *self = NACT_PREFERENCES_EDITOR( instance );
+
+	self->private = g_new0( NactPreferencesEditorPrivate, 1 );
+
+	self->private->dispose_has_run = FALSE;
+}
+
+static void
+instance_dispose( GObject *dialog )
+{
+	static const gchar *thisfn = "nact_preferences_editor_instance_dispose";
+	g_debug( "%s: dialog=%p", thisfn, dialog );
+
+	g_assert( NACT_IS_PREFERENCES_EDITOR( dialog ));
+	NactPreferencesEditor *self = NACT_PREFERENCES_EDITOR( dialog );
+
+	if( !self->private->dispose_has_run ){
+
+		self->private->dispose_has_run = TRUE;
+
+		/* chain up to the parent class */
+		G_OBJECT_CLASS( st_parent_class )->dispose( dialog );
+	}
+}
+
+static void
+instance_finalize( GObject *dialog )
+{
+	static const gchar *thisfn = "nact_preferences_editor_instance_finalize";
+	g_debug( "%s: dialog=%p", thisfn, dialog );
+
+	g_assert( NACT_IS_PREFERENCES_EDITOR( dialog ));
+	NactPreferencesEditor *self = ( NactPreferencesEditor * ) dialog;
+
+	g_free( self->private );
+
+	/* chain call to parent class */
+	if( st_parent_class->finalize ){
+		G_OBJECT_CLASS( st_parent_class )->finalize( dialog );
+	}
+}
+
+/*
+ * Returns a newly allocated NactPreferencesEditor object.
+ *
+ * @parent: the BaseWindow parent of this dialog (usually, the main
+ * toplevel window of the application).
+ */
+static NactPreferencesEditor *
+preferences_editor_new( BaseApplication *application )
+{
+	return( g_object_new( NACT_PREFERENCES_EDITOR_TYPE, PROP_WINDOW_APPLICATION_STR, application, NULL ));
+}
+
+/**
+ * Initializes and runs the dialog.
+ *
+ * @parent: the NactWindow parent of this dialog.
+ * Usually the NactMainWindow.
+ */
+void
+nact_preferences_editor_run( NactWindow *parent )
+{
+	static const gchar *thisfn = "nact_preferences_editor_run";
+	g_debug( "%s: parent=%p", thisfn, parent );
+
+	g_assert( NACT_IS_WINDOW( parent ));
+
+	BaseApplication *application = BASE_APPLICATION( base_window_get_application( BASE_WINDOW( parent )));
+	g_assert( NACT_IS_APPLICATION( application ));
+
+	NactPreferencesEditor *editor = preferences_editor_new( application );
+	editor->private->parent = parent;
+
+	base_window_run( BASE_WINDOW( editor ));
+}
+
+static gchar *
+do_get_iprefs_window_id( NactWindow *window )
+{
+	return( g_strdup( "preferences-editor" ));
+}
+
+static gchar *
+do_get_dialog_name( BaseWindow *dialog )
+{
+	return( g_strdup( "PreferencesDialog" ));
+}
+
+static void
+on_initial_load_dialog( BaseWindow *dialog )
+{
+	static const gchar *thisfn = "nact_preferences_editor_on_initial_load_dialog";
+
+	/* call parent class at the very beginning */
+	if( BASE_WINDOW_CLASS( st_parent_class )->initial_load_toplevel ){
+		BASE_WINDOW_CLASS( st_parent_class )->initial_load_toplevel( dialog );
+	}
+
+	g_debug( "%s: dialog=%p", thisfn, dialog );
+	g_assert( NACT_IS_PREFERENCES_EDITOR( dialog ));
+	NactPreferencesEditor *editor = NACT_PREFERENCES_EDITOR( dialog );
+
+	GtkWindow *toplevel = base_window_get_toplevel_dialog( dialog );
+	GtkWindow *parent_toplevel = base_window_get_toplevel_dialog( BASE_WINDOW( editor->private->parent ));
+	gtk_window_set_transient_for( toplevel, parent_toplevel );
+}
+
+static void
+on_runtime_init_dialog( BaseWindow *dialog )
+{
+	static const gchar *thisfn = "nact_preferences_editor_on_runtime_init_dialog";
+
+	/* call parent class at the very beginning */
+	if( BASE_WINDOW_CLASS( st_parent_class )->runtime_init_toplevel ){
+		BASE_WINDOW_CLASS( st_parent_class )->runtime_init_toplevel( dialog );
+	}
+
+	g_debug( "%s: dialog=%p", thisfn, dialog );
+	g_assert( NACT_IS_PREFERENCES_EDITOR( dialog ));
+	NactPreferencesEditor *editor = NACT_PREFERENCES_EDITOR( dialog );
+
+	gboolean as_submenu = na_iprefs_get_bool( NA_IPREFS( editor ), PREFS_DISPLAY_AS_SUBMENU );
+	GtkWidget *button = base_window_get_widget( dialog, "AsSubmenuButton" );
+	gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( button ), as_submenu );
+
+	nact_window_signal_connect_by_name( NACT_WINDOW( editor ), "AsSubmenuButton", "toggled", G_CALLBACK( on_submenu_toggled ));
+
+	nact_window_signal_connect_by_name( NACT_WINDOW( editor ), "CancelButton", "clicked", G_CALLBACK( on_cancel_clicked ));
+	nact_window_signal_connect_by_name( NACT_WINDOW( editor ), "OKButton", "clicked", G_CALLBACK( on_ok_clicked ));
+
+	/*setup_buttons( editor, FALSE );*/
+}
+
+static void
+on_all_widgets_showed( BaseWindow *dialog )
+{
+	static const gchar *thisfn = "nact_preferences_editor_on_all_widgets_showed";
+
+	/* call parent class at the very beginning */
+	if( BASE_WINDOW_CLASS( st_parent_class )->all_widgets_showed ){
+		BASE_WINDOW_CLASS( st_parent_class )->all_widgets_showed( dialog );
+	}
+
+	g_debug( "%s: dialog=%p", thisfn, dialog );
+	g_assert( NACT_IS_PREFERENCES_EDITOR( dialog ));
+}
+
+/*
+ * rationale:
+ * - while the preferences are not modified, only the cancel
+ *   button is activated (showed as close)
+ * - when at least one preference has been modified, we have a OK and a
+ *   cancel buttons
+ */
+/*static void
+setup_buttons( NactPreferencesEditor *editor, gboolean is_modified )
+{
+	GtkWidget *cancel_stock = gtk_button_new_from_stock( GTK_STOCK_CANCEL );
+	GtkWidget *close_stock = gtk_button_new_from_stock( GTK_STOCK_CLOSE );
+
+	GtkWidget *cancel_button = base_window_get_widget( BASE_WINDOW( editor ), "CancelButton" );
+	gtk_button_set_label( GTK_BUTTON( cancel_button ), is_modified ? _( "_Cancel" ) : _( "_Close" ));
+	gtk_button_set_image( GTK_BUTTON( cancel_button ), is_modified ? gtk_button_get_image( GTK_BUTTON( cancel_stock )) : gtk_button_get_image( GTK_BUTTON( close_stock )));
+
+	gtk_widget_destroy( close_stock );
+	gtk_widget_destroy( cancel_stock );
+
+	GtkWidget *ok_button = base_window_get_widget( BASE_WINDOW( editor ), "OKButton" );
+	gtk_widget_set_sensitive( ok_button, is_modified );
+}*/
+
+/*static void
+on_modified_field( NactWindow *window )
+{
+	static const gchar *thisfn = "nact_preferences_editor_on_modified_field";
+
+	g_assert( NACT_IS_PREFERENCES_EDITOR( window ));
+	NactPreferencesEditor *editor = ( NACT_PREFERENCES_EDITOR( window ));
+
+	gboolean is_modified = is_edited_modified( editor );
+	setup_dialog_title( editor, is_modified );
+
+	gboolean can_save = is_modified &&
+		(( editor->private->show_profile_item && nact_iprofile_item_has_label( window )) ||
+				nact_imenu_item_has_label( window ));
+
+	setup_buttons( editor, can_save );
+}*/
+
+static void
+on_submenu_toggled( GtkToggleButton *button, NactWindow *window )
+{
+	g_assert( NACT_IS_PREFERENCES_EDITOR( window ));
+	/*NactPreferencesEditor *editor = NACT_PREFERENCES_EDITOR( window );*/
+}
+
+static void
+on_cancel_clicked( GtkButton *button, NactWindow *window )
+{
+	GtkWindow *toplevel = base_window_get_toplevel_dialog( BASE_WINDOW( window ));
+	gtk_dialog_response( GTK_DIALOG( toplevel ), GTK_RESPONSE_CLOSE );
+}
+
+static void
+on_ok_clicked( GtkButton *button, NactWindow *window )
+{
+	GtkWindow *toplevel = base_window_get_toplevel_dialog( BASE_WINDOW( window ));
+	gtk_dialog_response( GTK_DIALOG( toplevel ), GTK_RESPONSE_OK );
+}
+
+static void
+save_preferences( NactPreferencesEditor *editor )
+{
+	GtkWidget *button = base_window_get_widget( BASE_WINDOW( editor ), "AsSubmenuButton" );
+	gboolean as_submenu = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( button ));
+	na_iprefs_set_bool( NA_IPREFS( editor ), PREFS_DISPLAY_AS_SUBMENU, as_submenu );
+}
+
+static gboolean
+on_dialog_response( GtkDialog *dialog, gint code, BaseWindow *window )
+{
+	static const gchar *thisfn = "nact_preferences_editor_on_dialog_response";
+	g_debug( "%s: dialog=%p, code=%d, window=%p", thisfn, dialog, code, window );
+
+	g_assert( NACT_IS_PREFERENCES_EDITOR( window ));
+	NactPreferencesEditor *editor = NACT_PREFERENCES_EDITOR( window );
+
+	/*gboolean is_modified = is_edited_modified( editor );*/
+
+	switch( code ){
+		case GTK_RESPONSE_NONE:
+		case GTK_RESPONSE_DELETE_EVENT:
+		case GTK_RESPONSE_CLOSE:
+		case GTK_RESPONSE_CANCEL:
+
+			g_object_unref( editor );
+			return( TRUE );
+			break;
+
+		case GTK_RESPONSE_OK:
+			save_preferences( editor );
+			g_object_unref( editor );
+			return( TRUE );
+			break;
+	}
+
+	return( FALSE );
+}
diff --git a/src/nact/nact-preferences-editor.h b/src/nact/nact-preferences-editor.h
new file mode 100644
index 0000000..5b1b069
--- /dev/null
+++ b/src/nact/nact-preferences-editor.h
@@ -0,0 +1,74 @@
+/*
+ * 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 __NACT_PREFERENCES_EDITOR_H__
+#define __NACT_PREFERENCES_EDITOR_H__
+
+/*
+ * NactPreferencesEditor class definition.
+ *
+ * This class is derived from NactWindow.
+ * It encapsulates the "PreferencesDialog" widget dialog.
+ */
+
+#include "nact-window.h"
+
+G_BEGIN_DECLS
+
+#define NACT_PREFERENCES_EDITOR_TYPE				( nact_preferences_editor_get_type())
+#define NACT_PREFERENCES_EDITOR( object )			( G_TYPE_CHECK_INSTANCE_CAST( object, NACT_PREFERENCES_EDITOR_TYPE, NactPreferencesEditor ))
+#define NACT_PREFERENCES_EDITOR_CLASS( klass )		( G_TYPE_CHECK_CLASS_CAST( klass, NACT_PREFERENCES_EDITOR_TYPE, NactPreferencesEditorClass ))
+#define NACT_IS_PREFERENCES_EDITOR( object )		( G_TYPE_CHECK_INSTANCE_TYPE( object, NACT_PREFERENCES_EDITOR_TYPE ))
+#define NACT_IS_PREFERENCES_EDITOR_CLASS( klass )	( G_TYPE_CHECK_CLASS_TYPE(( klass ), NACT_PREFERENCES_EDITOR_TYPE ))
+#define NACT_PREFERENCES_EDITOR_GET_CLASS( object )	( G_TYPE_INSTANCE_GET_CLASS(( object ), NACT_PREFERENCES_EDITOR_TYPE, NactPreferencesEditorClass ))
+
+typedef struct NactPreferencesEditorPrivate NactPreferencesEditorPrivate;
+
+typedef struct {
+	NactWindow                    parent;
+	NactPreferencesEditorPrivate *private;
+}
+	NactPreferencesEditor;
+
+typedef struct NactPreferencesEditorClassPrivate NactPreferencesEditorClassPrivate;
+
+typedef struct {
+	NactWindowClass                    parent;
+	NactPreferencesEditorClassPrivate *private;
+}
+	NactPreferencesEditorClass;
+
+GType nact_preferences_editor_get_type( void );
+
+void  nact_preferences_editor_run( NactWindow *parent );
+
+G_END_DECLS
+
+#endif /* __NACT_PREFERENCES_EDITOR_H__ */
diff --git a/src/nact/nautilus-actions-config-tool.ui b/src/nact/nautilus-actions-config-tool.ui
index 7880cc0..7734fb2 100644
--- a/src/nact/nautilus-actions-config-tool.ui
+++ b/src/nact/nautilus-actions-config-tool.ui
@@ -1007,13 +1007,10 @@ Defining several profiles lets you have several commands, each applying with a d
     <child>
       <object class="GtkFileChooserWidget" id="filechooserwidget1">
         <property name="visible">True</property>
-        <property name="preview_widget_active">False</property>
-        <property name="select_multiple">True</property>
-        <property name="use_preview_label">False</property>
-        <property name="local_only">False</property>
-        <property name="preview_widget_active">False</property>
         <property name="use_preview_label">False</property>
         <property name="select_multiple">True</property>
+        <property name="preview_widget_active">False</property>
+        <property name="local_only">False</property>
       </object>
     </child>
     <child>
@@ -1116,10 +1113,10 @@ to extend a selection.</property>
         <child>
           <object class="GtkFileChooserWidget" id="ExportFolderChooser">
             <property name="visible">True</property>
-            <property name="preview_widget_active">False</property>
-            <property name="action">select-folder</property>
             <property name="use_preview_label">False</property>
+            <property name="preview_widget_active">False</property>
             <property name="local_only">False</property>
+            <property name="action">select-folder</property>
           </object>
           <packing>
             <property name="position">0</property>
@@ -1722,18 +1719,119 @@ The exported file may later be imported via :
       </object>
     </child>
   </object>
+  <object class="GtkDialog" id="PreferencesDialog">
+    <property name="border_width">5</property>
+    <property name="title" translatable="yes">Nautilus Actions Preferences</property>
+    <property name="modal">True</property>
+    <property name="type_hint">dialog</property>
+    <child internal-child="vbox">
+      <object class="GtkVBox" id="dialog-vbox1">
+        <property name="visible">True</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">2</property>
+        <child>
+          <object class="GtkFrame" id="frame1">
+            <property name="visible">True</property>
+            <property name="label_xalign">0</property>
+            <property name="shadow_type">in</property>
+            <child>
+              <object class="GtkAlignment" id="alignment1">
+                <property name="visible">True</property>
+                <property name="left_padding">12</property>
+                <child>
+                  <object class="GtkVBox" id="vbox2">
+                    <property name="visible">True</property>
+                    <property name="border_width">5</property>
+                    <property name="orientation">vertical</property>
+                    <property name="spacing">10</property>
+                    <child>
+                      <object class="GtkCheckButton" id="AsSubmenuButton">
+                        <property name="label" translatable="yes">Display available actions as a Nautilus _submenu</property>
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="use_underline">True</property>
+                        <property name="draw_indicator">True</property>
+                      </object>
+                      <packing>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child type="label">
+              <object class="GtkLabel" id="label1">
+                <property name="visible">True</property>
+                <property name="xpad">5</property>
+                <property name="label" translatable="yes">&lt;b&gt;Edit your preferences here&lt;/b&gt;</property>
+                <property name="use_markup">True</property>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="position">2</property>
+          </packing>
+        </child>
+        <child internal-child="action_area">
+          <object class="GtkHButtonBox" id="dialog-action_area1">
+            <property name="visible">True</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="CancelButton">
+                <property name="label" translatable="yes">gtk-cancel</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="OKButton">
+                <property name="label" translatable="yes">gtk-ok</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="0">CancelButton</action-widget>
+      <action-widget response="0">OKButton</action-widget>
+    </action-widgets>
+  </object>
   <object class="GtkSizeGroup" id="CommandLabelSizeGroup">
     <widgets>
-      <widget name="ProfileLabelLabel"/>
-      <widget name="CommandPathLabel"/>
-      <widget name="CommandParametersLabel"/>
       <widget name="CommandExamplePreLabel"/>
+      <widget name="CommandParametersLabel"/>
+      <widget name="CommandPathLabel"/>
+      <widget name="ProfileLabelLabel"/>
     </widgets>
   </object>
   <object class="GtkSizeGroup" id="CommandButtonSizeGroup">
     <widgets>
-      <widget name="CommandPathButton"/>
       <widget name="CommandLegendButton"/>
+      <widget name="CommandPathButton"/>
     </widgets>
   </object>
 </interface>
diff --git a/src/plugin/nautilus-actions.c b/src/plugin/nautilus-actions.c
index 705734a..50b1612 100644
--- a/src/plugin/nautilus-actions.c
+++ b/src/plugin/nautilus-actions.c
@@ -42,6 +42,7 @@
 #include <common/na-action-profile.h>
 #include <common/na-pivot.h>
 #include <common/na-ipivot-consumer.h>
+#include <common/na-iprefs.h>
 
 #include "nautilus-actions.h"
 
@@ -63,6 +64,7 @@ static GType         st_actions_type = 0;
 static void              class_init( NautilusActionsClass *klass );
 static void              menu_provider_iface_init( NautilusMenuProviderIface *iface );
 static void              pivot_consumer_iface_init( NAIPivotConsumerInterface *iface );
+static void              prefs_iface_init( NAIPrefsInterface *iface );
 static void              instance_init( GTypeInstance *instance, gpointer klass );
 static void              instance_dispose( GObject *object );
 static void              instance_finalize( GObject *object );
@@ -70,6 +72,7 @@ static void              instance_finalize( GObject *object );
 static GList            *get_background_items( NautilusMenuProvider *provider, GtkWidget *window, NautilusFileInfo *current_folder );
 static GList            *get_file_items( NautilusMenuProvider *provider, GtkWidget *window, GList *files );
 static NautilusMenuItem *create_menu_item( NAAction *action, NAActionProfile *profile, GList *files );
+static NautilusMenuItem *create_sub_menu( NautilusMenu **menu );
 static void              execute_action( NautilusMenuItem *item, NAActionProfile *profile );
 static void              actions_changed_handler( NAIPivotConsumer *instance, gpointer user_data );
 
@@ -100,10 +103,10 @@ nautilus_actions_register_type( GTypeModule *module )
 		( GInstanceInitFunc ) instance_init,
 	};
 
-	/* implements NautilusMenuItem interface
-	 */
 	st_actions_type = g_type_module_register_type( module, G_TYPE_OBJECT, "NautilusActions", &info, 0 );
 
+	/* implements NautilusMenuItem interface
+	 */
 	static const GInterfaceInfo menu_provider_iface_info = {
 		( GInterfaceInitFunc ) menu_provider_iface_init,
 		NULL,
@@ -121,6 +124,16 @@ nautilus_actions_register_type( GTypeModule *module )
 	};
 
 	g_type_module_add_interface( module, st_actions_type, NA_IPIVOT_CONSUMER_TYPE, &pivot_consumer_iface_info );
+
+	/* implement IPrefs interface
+	 */
+	static const GInterfaceInfo prefs_iface_info = {
+		( GInterfaceInitFunc ) prefs_iface_init,
+		NULL,
+		NULL
+	};
+
+	g_type_module_add_interface( module, st_actions_type, NA_IPREFS_TYPE, &prefs_iface_info );
 }
 
 static void
@@ -158,6 +171,13 @@ pivot_consumer_iface_init( NAIPivotConsumerInterface *iface )
 }
 
 static void
+prefs_iface_init( NAIPrefsInterface *iface )
+{
+	static const gchar *thisfn = "nautilus_actions_prefs_iface_init";
+	g_debug( "%s: iface=%p", thisfn, iface );
+}
+
+static void
 instance_init( GTypeInstance *instance, gpointer klass )
 {
 	static const gchar *thisfn = "nautilus_actions_instance_init";
@@ -251,6 +271,7 @@ get_file_items( NautilusMenuProvider *provider, GtkWidget *window, GList *files
 	GList *items = NULL;
 	GSList* profiles;
 	GSList *ia, *ip;
+	NautilusMenu *menu = NULL;
 	NautilusMenuItem *item;
 	GSList *actions = NULL;
 	gchar *label, *uuid;
@@ -263,6 +284,8 @@ get_file_items( NautilusMenuProvider *provider, GtkWidget *window, GList *files
 		return(( GList * ) NULL );
 	}
 
+	gboolean have_submenu = na_iprefs_get_bool( NA_IPREFS( self ), PREFS_DISPLAY_AS_SUBMENU );
+
 	if( !self->private->dispose_has_run ){
 		actions = na_pivot_get_actions( self->private->pivot );
 
@@ -300,7 +323,16 @@ get_file_items( NautilusMenuProvider *provider, GtkWidget *window, GList *files
 
 				if( na_action_profile_is_candidate( profile, files )){
 					item = create_menu_item( action, profile, files );
-					items = g_list_append( items, item );
+
+					if( have_submenu ){
+						if( !menu ){
+							items = g_list_append( items, create_sub_menu( &menu ));
+						}
+						nautilus_menu_append_item( menu, item );
+
+					} else {
+						items = g_list_append( items, item );
+					}
 					break;
 				}
 			}
@@ -351,6 +383,24 @@ create_menu_item( NAAction *action, NAActionProfile *profile, GList *files )
 	return( item );
 }
 
+static NautilusMenuItem *
+create_sub_menu( NautilusMenu **menu )
+{
+	NautilusMenuItem *item;
+
+	item = nautilus_menu_item_new( "NautilusActionsExtensions",
+			_( "Nautilus-Actions extensions" ),
+			_( "A submenu which embeds the currently available Nautilus-Actions extensions" ),
+			PACKAGE );
+
+	if( menu ){
+		*menu = nautilus_menu_new();
+		nautilus_menu_item_set_submenu( item, *menu );
+	}
+
+	return( item );
+}
+
 static void
 execute_action( NautilusMenuItem *item, NAActionProfile *profile )
 {



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