[nautilus-actions] Definitive BaseWindow hierarchy management



commit e42b15ac2248ce6d03c9a17b032966ce42eab305
Author: Pierre Wieser <pwieser trychlos org>
Date:   Sun Jun 28 11:07:00 2009 +0200

    Definitive BaseWindow hierarchy management

 ChangeLog                                          |   36 ++
 src/common/na-action.c                             |   16 +-
 src/nact/Makefile.am                               |   12 +-
 src/nact/base-window.c                             |  136 ++++++--
 src/nact/base-window.h                             |   18 +-
 src/nact/nact-action-conditions-editor.c           |  344 ++++++++++++++++++++
 src/nact/nact-action-conditions-editor.h           |   74 +++++
 ...ion-profile.c => nact-action-profiles-editor.c} |  236 ++++++--------
 ...ion-profile.h => nact-action-profiles-editor.h} |   36 +-
 src/nact/nact-iaction-conditions.h                 |   69 ----
 src/nact/nact-iactions-list.c                      |  187 +++++++----
 src/nact/nact-iactions-list.h                      |   11 +-
 src/nact/nact-imenu-item.c                         |  257 +++++++++++++++-
 src/nact/nact-imenu-item.h                         |   10 +-
 ...ion-conditions.c => nact-iprofile-conditions.c} |   46 ++-
 src/nact/nact-iprofile-conditions.h                |   72 ++++
 src/nact/nact-main-window.c                        |  131 ++++----
 src/nact/nact-profile-conditions-editor.c          |  311 ++++++++++++++++++
 src/nact/nact-profile-conditions-editor.h          |   74 +++++
 src/nact/nact-window.c                             |   65 ++++-
 src/nact/nact-window.h                             |   10 +-
 src/nact/nautilus-actions-config.ui                |    6 +-
 22 files changed, 1715 insertions(+), 442 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 0599318..92e7f93 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,39 @@
+2009-06-28 Pierre Wieser <pwieser trychlos org>
+
+	* src/common/na-action.c:
+	UUID no more a contruction only parameter.
+	NAAction is now initialized with suitable default values.
+
+	* src/nact/nact-action-conditions-editor.c:
+	* src/nact/nact-action-conditions-editor.h:
+	* src/nact/nact-action-profiles-editor.c:
+	* src/nact/nact-action-profiles-editor.h:
+	* src/nact/nact-profile-conditions-editor.c:
+	* src/nact/nact-profile-conditions-editor.h:
+	Definitive names for dialog management.
+
+	* src/nact/nact-iprofile-conditions.c:
+	* src/nact/nact-iprofile-conditions.h:
+	IActionConditions interface is renamed as IProfileConditions.
+
+	* src/nact/Makefile.am:
+	Updated accordingly.
+
+	* src/nact/base-window.c:
+	* src/nact/base-window.h:
+	initial_load_toplevel, runtime_init_toplevel, all_widgets_showed:
+	new functions.
+	
+	* src/nact/nact-imenu-item.c:
+	signal_recorded: new function.
+
+	* src/nact/nact-main-window.c:
+	Implement initial_load_toplevel and runtime_init_toplevel
+	functions.
+
+	* src/nact/nact-window.c:
+	nact_window_on_signal_recorded: new function.
+
 2009-06-26 Pierre Wieser <pwieser trychlos org>
 
 	Migration to GtkBuilder.
diff --git a/src/common/na-action.c b/src/common/na-action.c
index d5502e6..afa2b4b 100644
--- a/src/common/na-action.c
+++ b/src/common/na-action.c
@@ -158,7 +158,7 @@ class_init( NAActionClass *klass )
 			PROP_ACTION_UUID_STR,
 			PROP_ACTION_UUID_STR,
 			"Globally unique identifier (UUID) of the action", "",
-			G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+			G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
 	g_object_class_install_property( object_class, PROP_ACTION_UUID, spec );
 
 	spec = g_param_spec_string(
@@ -220,9 +220,9 @@ instance_init( GTypeInstance *instance, gpointer klass )
 	 * mandatory
 	 */
 	self->private->version = g_strdup( NA_ACTION_LATEST_VERSION );
-	self->private->label = NULL;
-	self->private->tooltip = NULL;
-	self->private->icon = NULL;
+	self->private->label = g_strdup( "" );
+	self->private->tooltip = g_strdup( "" );
+	self->private->icon = g_strdup( "" );
 	self->private->read_only = FALSE;
 }
 
@@ -352,7 +352,8 @@ instance_finalize( GObject *object )
 /**
  * Allocates a new NAAction object.
  *
- * @uuid: the globally unique identifier (UUID) of the action.
+ * @uuid: the globally unique identifier (UUID) of the action. If NULL,
+ * a new UUID is allocated for this action.
  *
  * Return a newly allocated NAAction object.
  */
@@ -360,6 +361,11 @@ NAAction *
 na_action_new( const gchar *uuid )
 {
 	NAAction *action = g_object_new( NA_ACTION_TYPE, PROP_ACTION_UUID_STR, uuid, NULL );
+
+	if( !uuid || !strlen( uuid )){
+		na_action_set_new_uuid( action );
+	}
+
 	return( action );
 }
 
diff --git a/src/nact/Makefile.am b/src/nact/Makefile.am
index 51815ff..0dede13 100644
--- a/src/nact/Makefile.am
+++ b/src/nact/Makefile.am
@@ -44,19 +44,23 @@ nautilus_actions_config_SOURCES = \
 	base-application.h									\
 	base-window.c										\
 	base-window.h										\
-	nact-action-profile.c								\
-	nact-action-profile.h								\
+	nact-action-conditions-editor.c						\
+	nact-action-conditions-editor.h						\
+	nact-action-profiles-editor.c						\
+	nact-action-profiles-editor.h						\
 	nact-application.c									\
 	nact-application.h									\
-	nact-iaction-conditions.c							\
-	nact-iaction-conditions.h							\
 	nact-iactions-list.c								\
 	nact-iactions-list.h								\
 	nact-imenu-item.c									\
 	nact-imenu-item.h									\
+	nact-iprofile-conditions.c							\
+	nact-iprofile-conditions.h							\
 	nact-main.c											\
 	nact-main-window.c									\
 	nact-main-window.h									\
+	nact-profile-conditions-editor.c					\
+	nact-profile-conditions-editor.h					\
 	nact-utils.c										\
 	nact-utils.h										\
 	nact-prefs.c										\
diff --git a/src/nact/base-window.c b/src/nact/base-window.c
index 3c59d9d..8281341 100644
--- a/src/nact/base-window.c
+++ b/src/nact/base-window.c
@@ -74,19 +74,24 @@ static void        instance_set_property( GObject *object, guint property_id, co
 static void        instance_dispose( GObject *application );
 static void        instance_finalize( GObject *application );
 
-static void        do_init_window( BaseWindow *window );
-static void        do_run_window( BaseWindow *window );
-
 static gchar      *v_get_toplevel_name( BaseWindow *window );
-static void        v_init_widget( BaseWindow *window );
+static void        v_initial_load_toplevel( BaseWindow *window );
+static void        v_runtime_init_toplevel( BaseWindow *window );
+static void        v_all_widgets_showed( BaseWindow *window );
 static void        v_dialog_response( GtkDialog *dialog, gint code, BaseWindow *window );
 
-static void        do_init_widget( BaseWindow *window );
+static void        do_init_window( BaseWindow *window );
+static void        do_initial_load_toplevel( BaseWindow *window );
+static void        do_runtime_init_toplevel( BaseWindow *window );
+static void        do_all_widgets_showed( BaseWindow *window );
+static void        do_run_window( BaseWindow *window );
 static void        do_dialog_response( GtkDialog *dialog, gint code, BaseWindow *window );
 static GObject    *do_get_application( BaseWindow *window );
 static GtkWindow  *do_get_toplevel_widget( BaseWindow *window );
 static GtkWidget  *do_get_widget( BaseWindow *window, const gchar *name );
 
+static gboolean    is_toplevel_initialized( BaseWindow *window );
+static void        set_toplevel_initialized( BaseWindow *window );
 static gboolean    is_main_window( BaseWindow *window );
 
 GType
@@ -169,8 +174,10 @@ class_init( BaseWindowClass *klass )
 
 	klass->init = do_init_window;
 	klass->run = do_run_window;
-	klass->on_init_widget = do_init_widget;
-	klass->on_dialog_response = do_dialog_response;
+	klass->initial_load_toplevel = do_initial_load_toplevel;
+	klass->runtime_init_toplevel = do_runtime_init_toplevel;
+	klass->all_widgets_showed = do_all_widgets_showed;
+	klass->dialog_response = do_dialog_response;
 	klass->get_application = do_get_application;
 	klass->get_toplevel_name = NULL;
 	klass->get_toplevel_widget = do_get_toplevel_widget;
@@ -367,6 +374,17 @@ base_window_get_widget( BaseWindow *window, const gchar *name )
 	return( BASE_WINDOW_GET_CLASS( window )->get_widget( window, name ));
 }
 
+/**
+ * Connects a signal to a handler, assuring that the BaseWindow pointer
+ * is passed as user data.
+ */
+void
+base_window_connect( BaseWindow *window, const gchar *widget, const gchar *signal, GCallback handler )
+{
+	GtkWidget *target = base_window_get_widget( window, widget );
+	g_signal_connect( G_OBJECT( target ), signal, handler, window );
+}
+
 static gchar *
 v_get_toplevel_name( BaseWindow *window )
 {
@@ -386,13 +404,41 @@ v_get_toplevel_name( BaseWindow *window )
 }
 
 static void
-v_init_widget( BaseWindow *window )
+v_initial_load_toplevel( BaseWindow *window )
+{
+	g_assert( BASE_IS_WINDOW( window ));
+
+	GtkWindow *toplevel = window->private->toplevel_widget;
+	g_assert( toplevel );
+	g_assert( GTK_IS_WINDOW( toplevel ));
+
+	if( window->private->toplevel_widget ){
+		if( BASE_WINDOW_GET_CLASS( window )->initial_load_toplevel ){
+			BASE_WINDOW_GET_CLASS( window )->initial_load_toplevel( window );
+		}
+	}
+}
+
+static void
+v_runtime_init_toplevel( BaseWindow *window )
+{
+	g_assert( BASE_IS_WINDOW( window ));
+
+	if( window->private->toplevel_widget ){
+		if( BASE_WINDOW_GET_CLASS( window )->runtime_init_toplevel ){
+			BASE_WINDOW_GET_CLASS( window )->runtime_init_toplevel( window );
+		}
+	}
+}
+
+static void
+v_all_widgets_showed( BaseWindow *window )
 {
 	g_assert( BASE_IS_WINDOW( window ));
 
 	if( window->private->toplevel_widget ){
-		if( BASE_WINDOW_GET_CLASS( window )->on_init_widget ){
-			BASE_WINDOW_GET_CLASS( window )->on_init_widget( window );
+		if( BASE_WINDOW_GET_CLASS( window )->all_widgets_showed ){
+			BASE_WINDOW_GET_CLASS( window )->all_widgets_showed( window );
 		}
 	}
 }
@@ -402,8 +448,8 @@ v_dialog_response( GtkDialog *dialog, gint code, BaseWindow *window )
 {
 	g_assert( BASE_IS_WINDOW( window ));
 
-	if( BASE_WINDOW_GET_CLASS( window )->on_dialog_response ){
-		BASE_WINDOW_GET_CLASS( window )->on_dialog_response( dialog, code, window );
+	if( BASE_WINDOW_GET_CLASS( window )->dialog_response ){
+		BASE_WINDOW_GET_CLASS( window )->dialog_response( dialog, code, window );
 	}
 }
 
@@ -423,39 +469,38 @@ do_init_window( BaseWindow *window )
 
 	if( toplevel ){
 		g_assert( GTK_IS_WINDOW( toplevel ));
-		v_init_widget( window );
-		gtk_widget_show_all( toplevel );
+
+		if( !is_toplevel_initialized( window )){
+			v_initial_load_toplevel( window );
+			set_toplevel_initialized( window );
+		}
+
+		v_runtime_init_toplevel( window );
 	}
 
 	g_free( widget_name );
-
 	window->private->initialized = TRUE;
 }
 
 static void
-do_init_widget( BaseWindow *window )
+do_initial_load_toplevel( BaseWindow *window )
 {
-	static const gchar *thisfn = "base_window_do_init_widget";
+	static const gchar *thisfn = "base_window_do_initial_load_toplevel";
 	g_debug( "%s: window=%p", thisfn, window );
 }
 
-
 static void
-do_dialog_response( GtkDialog *dialog, gint code, BaseWindow *window )
+do_runtime_init_toplevel( BaseWindow *window )
 {
-	static const gchar *thisfn = "base_window_do_dialog_response";
-	g_debug( "%s: dialog=%p, code=%d, window=%p", thisfn, dialog, code, window );
+	static const gchar *thisfn = "base_window_do_runtime_init_toplevel";
+	g_debug( "%s: window=%p", thisfn, window );
 }
 
-/**
- * Connects a signal to a handler, assuring that the BaseWindow pointer
- * is passed as user data.
- */
-void
-base_window_connect( BaseWindow *window, const gchar *widget, const gchar *signal, GCallback handler )
+static void
+do_all_widgets_showed( BaseWindow *window )
 {
-	GtkWidget *target = base_window_get_widget( window, widget );
-	g_signal_connect( G_OBJECT( target ), signal, handler, window );
+	static const gchar *thisfn = "base_window_do_all_widgets_showed";
+	g_debug( "%s: window=%p", thisfn, window );
 }
 
 static void
@@ -469,6 +514,8 @@ do_run_window( BaseWindow *window )
 	g_debug( "%s: window=%p", thisfn, window );
 
 	GtkWidget *this_widget = GTK_WIDGET( window->private->toplevel_widget );
+	gtk_widget_show_all( this_widget );
+	v_all_widgets_showed( window );
 
 	if( is_main_window( window )){
 		g_signal_connect( G_OBJECT( this_widget ), "response", G_CALLBACK( v_dialog_response ), window );
@@ -482,6 +529,13 @@ do_run_window( BaseWindow *window )
 	}
 }
 
+static void
+do_dialog_response( GtkDialog *dialog, gint code, BaseWindow *window )
+{
+	static const gchar *thisfn = "base_window_do_dialog_response";
+	g_debug( "%s: dialog=%p, code=%d, window=%p", thisfn, dialog, code, window );
+}
+
 static GObject *
 do_get_application( BaseWindow *window )
 {
@@ -502,6 +556,30 @@ do_get_widget( BaseWindow *window, const gchar *name )
 }
 
 static gboolean
+is_toplevel_initialized( BaseWindow *window )
+{
+	GtkWindow *toplevel = window->private->toplevel_widget;
+	g_assert( toplevel );
+	g_assert( GTK_IS_WINDOW( toplevel ));
+
+	gpointer data = g_object_get_data( G_OBJECT( toplevel ), "toplevel-initialized" );
+	if( !data ){
+		return( FALSE );
+	}
+	return(( gboolean ) data );
+}
+
+static void
+set_toplevel_initialized( BaseWindow *window )
+{
+	GtkWindow *toplevel = window->private->toplevel_widget;
+	g_assert( toplevel );
+	g_assert( GTK_IS_WINDOW( toplevel ));
+
+	g_object_set_data( G_OBJECT( toplevel ), "toplevel-initialized", ( gpointer ) TRUE );
+}
+
+static gboolean
 is_main_window( BaseWindow *window )
 {
 	BaseApplication *appli = window->private->application;
diff --git a/src/nact/base-window.h b/src/nact/base-window.h
index 6be8e26..e121392 100644
--- a/src/nact/base-window.h
+++ b/src/nact/base-window.h
@@ -64,14 +64,16 @@ typedef struct {
 	BaseWindowClassPrivate *private;
 
 	/* virtual functions */
-	void        ( *init )               ( BaseWindow *window );
-	void        ( *run )                ( BaseWindow *window );
-	void        ( *on_init_widget )     ( BaseWindow *window );
-	void        ( *on_dialog_response ) ( GtkDialog *dialog, gint code, BaseWindow *window );
-	GObject   * ( *get_application )    ( BaseWindow *window );
-	gchar     * ( *get_toplevel_name )  ( BaseWindow *window );
-	GtkWindow * ( *get_toplevel_widget )( BaseWindow *window );
-	GtkWidget * ( *get_widget )         ( BaseWindow *window, const gchar *name );
+	void        ( *init )                 ( BaseWindow *window );
+	void        ( *run )                  ( BaseWindow *window );
+	void        ( *initial_load_toplevel )( BaseWindow *window );
+	void        ( *runtime_init_toplevel )( BaseWindow *window );
+	void        ( *all_widgets_showed )   ( BaseWindow *window );
+	void        ( *dialog_response )      ( GtkDialog *dialog, gint code, BaseWindow *window );
+	GObject   * ( *get_application )      ( BaseWindow *window );
+	gchar     * ( *get_toplevel_name )    ( BaseWindow *window );
+	GtkWindow * ( *get_toplevel_widget )  ( BaseWindow *window );
+	GtkWidget * ( *get_widget )           ( BaseWindow *window, const gchar *name );
 }
 	BaseWindowClass;
 
diff --git a/src/nact/nact-action-conditions-editor.c b/src/nact/nact-action-conditions-editor.c
new file mode 100644
index 0000000..3d9c7c1
--- /dev/null
+++ b/src/nact/nact-action-conditions-editor.c
@@ -0,0 +1,344 @@
+/*
+ * 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-action.h>
+
+#include "nact-application.h"
+#include "nact-action-conditions-editor.h"
+#include "nact-imenu-item.h"
+#include "nact-iprofile-conditions.h"
+#include "nact-main-window.h"
+
+/* private class data
+ */
+struct NactActionConditionsEditorClassPrivate {
+};
+
+/* private instance data
+ */
+struct NactActionConditionsEditorPrivate {
+	gboolean  dispose_has_run;
+	NAAction *action;
+	gboolean  is_new;
+};
+
+static GObjectClass *st_parent_class = NULL;
+
+static GType  register_type( void );
+static void   class_init( NactActionConditionsEditorClass *klass );
+static void   imenu_item_iface_init( NactIMenuItemInterface *iface );
+static void   iprofile_conditions_iface_init( NactIProfileConditionsInterface *iface );
+static void   instance_init( GTypeInstance *instance, gpointer klass );
+static void   instance_dispose( GObject *dialog );
+static void   instance_finalize( GObject *dialog );
+
+static NactActionConditionsEditor *action_conditions_editor_new( BaseApplication *application );
+
+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   init_dialog_title( NactActionConditionsEditor *dialog );
+static void   on_dialog_response( GtkDialog *dialog, gint code, BaseWindow *window );
+
+GType
+nact_action_conditions_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_action_conditions_editor_register_type";
+	g_debug( "%s", thisfn );
+
+	static GTypeInfo info = {
+		sizeof( NactActionConditionsEditorClass ),
+		( GBaseInitFunc ) NULL,
+		( GBaseFinalizeFunc ) NULL,
+		( GClassInitFunc ) class_init,
+		NULL,
+		NULL,
+		sizeof( NactActionConditionsEditor ),
+		0,
+		( GInstanceInitFunc ) instance_init
+	};
+
+	GType type = g_type_register_static( NACT_WINDOW_TYPE, "NactActionConditionsEditor", &info, 0 );
+
+	/* implement IMenuItem interface
+	 */
+	static const GInterfaceInfo imenu_item_iface_info = {
+		( GInterfaceInitFunc ) imenu_item_iface_init,
+		NULL,
+		NULL
+	};
+
+	g_type_add_interface_static( type, NACT_IMENU_ITEM_TYPE, &imenu_item_iface_info );
+
+	/* implement IProfileConditions interface
+	 */
+	static const GInterfaceInfo iprofile_conditions_iface_info = {
+		( GInterfaceInitFunc ) iprofile_conditions_iface_init,
+		NULL,
+		NULL
+	};
+
+	g_type_add_interface_static( type, NACT_IPROFILE_CONDITIONS_TYPE, &iprofile_conditions_iface_info );
+
+	return( type );
+}
+
+static void
+class_init( NactActionConditionsEditorClass *klass )
+{
+	static const gchar *thisfn = "nact_action_conditions_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( NactActionConditionsEditorClassPrivate, 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;
+}
+
+static void
+imenu_item_iface_init( NactIMenuItemInterface *iface )
+{
+	static const gchar *thisfn = "nact_action_conditions_editor_imenu_item_iface_init";
+	g_debug( "%s: iface=%p", thisfn, iface );
+
+	iface->signal_connected = nact_window_on_signal_connected;
+}
+
+static void
+iprofile_conditions_iface_init( NactIProfileConditionsInterface *iface )
+{
+	static const gchar *thisfn = "nact_action_conditions_editor_iprofile_conditions_iface_init";
+	g_debug( "%s: iface=%p", thisfn, iface );
+}
+
+static void
+instance_init( GTypeInstance *instance, gpointer klass )
+{
+	static const gchar *thisfn = "nact_action_conditions_editor_instance_init";
+	g_debug( "%s: instance=%p, klass=%p", thisfn, instance, klass );
+
+	g_assert( NACT_IS_ACTION_CONDITIONS_EDITOR( instance ));
+	NactActionConditionsEditor *self = NACT_ACTION_CONDITIONS_EDITOR( instance );
+
+	self->private = g_new0( NactActionConditionsEditorPrivate, 1 );
+
+	self->private->dispose_has_run = FALSE;
+}
+
+static void
+instance_dispose( GObject *dialog )
+{
+	static const gchar *thisfn = "nact_action_conditions_editor_instance_dispose";
+	g_debug( "%s: dialog=%p", thisfn, dialog );
+
+	g_assert( NACT_IS_ACTION_CONDITIONS_EDITOR( dialog ));
+	NactActionConditionsEditor *self = NACT_ACTION_CONDITIONS_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_action_conditions_editor_instance_finalize";
+	g_debug( "%s: dialog=%p", thisfn, dialog );
+
+	g_assert( NACT_IS_ACTION_CONDITIONS_EDITOR( dialog ));
+	/*NactActionConditionsEditor *self = ( NactActionConditionsEditor * ) dialog;*/
+
+	/* chain call to parent class */
+	if( st_parent_class->finalize ){
+		G_OBJECT_CLASS( st_parent_class )->finalize( dialog );
+	}
+}
+
+/**
+ * Returns a newly allocated NactActionConditionsEditor object.
+ *
+ * @parent: is the BaseWindow parent of this dialog (usually, the main
+ * toplevel window of the application).
+ */
+static NactActionConditionsEditor *
+action_conditions_editor_new( BaseApplication *application )
+{
+	return( g_object_new( NACT_ACTION_CONDITIONS_EDITOR_TYPE, PROP_WINDOW_APPLICATION_STR, application, NULL ));
+}
+
+/**
+ * Initializes and runs the dialog.
+ *
+ * @parent: is the BaseWindow parent of this dialog (usually, the main
+ * toplevel window of the application).
+ *
+ * @user_data: a pointer to the NAAction to edit, or NULL. If NULL, a
+ * new NAAction is created.
+ *
+ * Returns TRUE if the NAAction has been edited and saved, or FALSE if
+ * there has been no modification at all.
+ */
+gboolean
+nact_action_conditions_editor_run_editor( NactWindow *parent, gpointer user_data )
+{
+	g_assert( NACT_IS_MAIN_WINDOW( parent ));
+
+	BaseApplication *application = BASE_APPLICATION( base_window_get_application( BASE_WINDOW( parent )));
+	g_assert( NACT_IS_APPLICATION( application ));
+
+	NactActionConditionsEditor *dialog = action_conditions_editor_new( application );
+
+	g_assert( NA_IS_ACTION( user_data ) || !user_data );
+	NAAction *action = NA_ACTION( user_data );
+
+	if( !action ){
+		dialog->private->action = na_action_new( NULL );
+		dialog->private->is_new = TRUE;
+
+	} else {
+		dialog->private->action = na_action_duplicate( action );
+		dialog->private->is_new = FALSE;
+	}
+
+	base_window_run( BASE_WINDOW( dialog ));
+
+	g_object_unref( dialog->private->action );
+	return( TRUE );
+}
+
+static gchar *
+do_get_dialog_name( BaseWindow *dialog )
+{
+	/*g_debug( "nact_action_conditions_editor_do_get_dialog_name" );*/
+	return( g_strdup( "EditActionDialogExt"));
+}
+
+static void
+on_initial_load_dialog( BaseWindow *dialog )
+{
+	static const gchar *thisfn = "nact_action_conditions_editor_on_initial_load_dialog";
+	g_debug( "%s: dialog=%p", thisfn, dialog );
+
+	g_assert( NACT_IS_ACTION_CONDITIONS_EDITOR( dialog ));
+	NactActionConditionsEditor *window = NACT_ACTION_CONDITIONS_EDITOR( dialog );
+
+	nact_imenu_item_initial_load( NACT_WINDOW( window ), window->private->action );
+	nact_iprofile_conditions_initial_load( NACT_WINDOW( window ), window->private->action );
+}
+
+static void
+on_runtime_init_dialog( BaseWindow *dialog )
+{
+	static const gchar *thisfn = "nact_action_conditions_editor_on_runtime_init_dialog";
+	g_debug( "%s: dialog=%p", thisfn, dialog );
+
+	g_assert( NACT_IS_ACTION_CONDITIONS_EDITOR( dialog ));
+	NactActionConditionsEditor *window = NACT_ACTION_CONDITIONS_EDITOR( dialog );
+
+	init_dialog_title( window );
+	nact_imenu_item_runtime_init( NACT_WINDOW( window ), window->private->action );
+	nact_iprofile_conditions_runtime_init( NACT_WINDOW( window ), window->private->action );
+}
+
+static void
+init_dialog_title( NactActionConditionsEditor *dialog )
+{
+	GtkWindow *toplevel = base_window_get_toplevel_widget( BASE_WINDOW( dialog ));
+
+	if( dialog->private->is_new ){
+		gtk_window_set_title( toplevel, _( "Adding a new action" ));
+
+	} else {
+		gchar *label = na_action_get_label( dialog->private->action );
+		gchar* title = g_strdup_printf( _( "Editing \"%s\" action" ), label );
+		gtk_window_set_title( toplevel, title );
+		g_free( label );
+		g_free( title );
+	}
+}
+
+static void
+on_all_widgets_showed( BaseWindow *dialog )
+{
+	static const gchar *thisfn = "nact_action_conditions_editor_on_all_widgets_showed";
+	g_debug( "%s: dialog=%p", thisfn, dialog );
+
+	nact_iprofile_conditions_all_widgets_showed( NACT_WINDOW( dialog ));
+}
+
+static void
+on_dialog_response( GtkDialog *dialog, gint code, BaseWindow *window )
+{
+	static const gchar *thisfn = "nact_action_conditions_editor_on_dialog_response";
+	g_debug( "%s: dialog=%p, code=%d, window=%p", thisfn, dialog, code, window );
+
+	g_assert( NACT_IS_ACTION_CONDITIONS_EDITOR( window ));
+
+	switch( code ){
+		case GTK_RESPONSE_NONE:
+		case GTK_RESPONSE_DELETE_EVENT:
+		case GTK_RESPONSE_CLOSE:
+			g_object_unref( window );
+			break;
+	}
+}
diff --git a/src/nact/nact-action-conditions-editor.h b/src/nact/nact-action-conditions-editor.h
new file mode 100644
index 0000000..76c99a3
--- /dev/null
+++ b/src/nact/nact-action-conditions-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_ACTION_CONDITIONS_EDITOR_H__
+#define __NACT_ACTION_CONDITIONS_EDITOR_H__
+
+/*
+ * NactActionConditionsEditor class definition.
+ *
+ * This class is derived from NactWindow.
+ * It encapsulates the "EditActionDialogExt" widget dialog.
+ */
+
+#include "nact-window.h"
+
+G_BEGIN_DECLS
+
+#define NACT_ACTION_CONDITIONS_EDITOR_TYPE					( nact_action_conditions_editor_get_type())
+#define NACT_ACTION_CONDITIONS_EDITOR( object )				( G_TYPE_CHECK_INSTANCE_CAST( object, NACT_ACTION_CONDITIONS_EDITOR_TYPE, NactActionConditionsEditor ))
+#define NACT_ACTION_CONDITIONS_EDITOR_CLASS( klass )		( G_TYPE_CHECK_CLASS_CAST( klass, NACT_ACTION_CONDITIONS_EDITOR_TYPE, NactActionConditionsEditorClass ))
+#define NACT_IS_ACTION_CONDITIONS_EDITOR( object )			( G_TYPE_CHECK_INSTANCE_TYPE( object, NACT_ACTION_CONDITIONS_EDITOR_TYPE ))
+#define NACT_IS_ACTION_CONDITIONS_EDITOR_CLASS( klass )		( G_TYPE_CHECK_CLASS_TYPE(( klass ), NACT_ACTION_CONDITIONS_EDITOR_TYPE ))
+#define NACT_ACTION_CONDITIONS_EDITOR_GET_CLASS( object )	( G_TYPE_INSTANCE_GET_CLASS(( object ), NACT_ACTION_CONDITIONS_EDITOR_TYPE, NactActionConditionsEditorClass ))
+
+typedef struct NactActionConditionsEditorPrivate NactActionConditionsEditorPrivate;
+
+typedef struct {
+	NactWindow                         parent;
+	NactActionConditionsEditorPrivate *private;
+}
+	NactActionConditionsEditor;
+
+typedef struct NactActionConditionsEditorClassPrivate NactActionConditionsEditorClassPrivate;
+
+typedef struct {
+	NactWindowClass                         parent;
+	NactActionConditionsEditorClassPrivate *private;
+}
+	NactActionConditionsEditorClass;
+
+GType    nact_action_conditions_editor_get_type( void );
+
+gboolean nact_action_conditions_editor_run_editor( NactWindow *parent, gpointer user_data );
+
+G_END_DECLS
+
+#endif /* __NACT_ACTION_CONDITIONS_EDITOR_H__ */
diff --git a/src/nact/nact-action-profile.c b/src/nact/nact-action-profiles-editor.c
similarity index 51%
rename from src/nact/nact-action-profile.c
rename to src/nact/nact-action-profiles-editor.c
index adc5720..08812b8 100644
--- a/src/nact/nact-action-profile.c
+++ b/src/nact/nact-action-profiles-editor.c
@@ -32,44 +32,47 @@
 #include <config.h>
 #endif
 
+#include <glib/gi18n.h>
+
 #include <common/na-action.h>
 
 #include "nact-application.h"
-#include "nact-action-profile.h"
-#include "nact-iaction-conditions.h"
+#include "nact-action-profiles-editor.h"
 #include "nact-imenu-item.h"
 #include "nact-main-window.h"
 
 /* private class data
  */
-struct NactActionProfileClassPrivate {
+struct NactActionProfilesEditorClassPrivate {
 };
 
 /* private instance data
  */
-struct NactActionProfilePrivate {
+struct NactActionProfilesEditorPrivate {
 	gboolean  dispose_has_run;
 	NAAction *action;
+	gboolean  is_new;
 };
 
 static GObjectClass *st_parent_class = NULL;
 
 static GType  register_type( void );
-static void   class_init( NactActionProfileClass *klass );
+static void   class_init( NactActionProfilesEditorClass *klass );
 static void   imenu_item_iface_init( NactIMenuItemInterface *iface );
-static void   iaction_conditions_iface_init( NactIActionConditionsInterface *iface );
 static void   instance_init( GTypeInstance *instance, gpointer klass );
 static void   instance_dispose( GObject *dialog );
 static void   instance_finalize( GObject *dialog );
 
-static NactActionProfile *action_profile_new( BaseApplication *application );
+static NactActionProfilesEditor *action_profiles_editor_new( BaseApplication *application );
 
 static gchar *do_get_dialog_name( BaseWindow *dialog );
-static void   on_init_dialog( BaseWindow *dialog );
+static void   on_initial_load_dialog( BaseWindow *dialog );
+static void   on_runtime_init_dialog( BaseWindow *dialog );
+static void   init_dialog_title( NactActionProfilesEditor *dialog );
 static void   on_dialog_response( GtkDialog *dialog, gint code, BaseWindow *window );
 
 GType
-nact_action_profile_get_type( void )
+nact_action_profiles_editor_get_type( void )
 {
 	static GType dialog_type = 0;
 
@@ -83,22 +86,22 @@ nact_action_profile_get_type( void )
 static GType
 register_type( void )
 {
-	static const gchar *thisfn = "nact_action_profile_register_type";
+	static const gchar *thisfn = "nact_action_profiles_editor_register_type";
 	g_debug( "%s", thisfn );
 
 	static GTypeInfo info = {
-		sizeof( NactActionProfileClass ),
+		sizeof( NactActionProfilesEditorClass ),
 		( GBaseInitFunc ) NULL,
 		( GBaseFinalizeFunc ) NULL,
 		( GClassInitFunc ) class_init,
 		NULL,
 		NULL,
-		sizeof( NactActionProfile ),
+		sizeof( NactActionProfilesEditor ),
 		0,
 		( GInstanceInitFunc ) instance_init
 	};
 
-	GType type = g_type_register_static( NACT_WINDOW_TYPE, "NactActionProfile", &info, 0 );
+	GType type = g_type_register_static( NACT_WINDOW_TYPE, "NactActionProfilesEditor", &info, 0 );
 
 	/* implement IMenuItem interface
 	 */
@@ -110,23 +113,13 @@ register_type( void )
 
 	g_type_add_interface_static( type, NACT_IMENU_ITEM_TYPE, &imenu_item_iface_info );
 
-	/* implement IActionConditions interface
-	 */
-	static const GInterfaceInfo iaction_conditions_iface_info = {
-		( GInterfaceInitFunc ) iaction_conditions_iface_init,
-		NULL,
-		NULL
-	};
-
-	g_type_add_interface_static( type, NACT_IACTION_CONDITIONS_TYPE, &iaction_conditions_iface_info );
-
 	return( type );
 }
 
 static void
-class_init( NactActionProfileClass *klass )
+class_init( NactActionProfilesEditorClass *klass )
 {
-	static const gchar *thisfn = "nact_action_profile_class_init";
+	static const gchar *thisfn = "nact_action_profiles_editor_class_init";
 	g_debug( "%s: klass=%p", thisfn, klass );
 
 	st_parent_class = g_type_class_peek_parent( klass );
@@ -134,138 +127,47 @@ class_init( NactActionProfileClass *klass )
 	GObjectClass *object_class = G_OBJECT_CLASS( klass );
 	object_class->dispose = instance_dispose;
 	object_class->finalize = instance_finalize;
-	/*object_class->get_property = instance_get_property;
-	object_class->set_property = instance_set_property;*/
 
-	klass->private = g_new0( NactActionProfileClassPrivate, 1 );
+	klass->private = g_new0( NactActionProfilesEditorClassPrivate, 1 );
 
 	BaseWindowClass *base_class = BASE_WINDOW_CLASS( klass );
-	base_class->on_init_widget = on_init_dialog;
-	base_class->on_dialog_response = on_dialog_response;
+	base_class->initial_load_toplevel = on_initial_load_dialog;
+	base_class->runtime_init_toplevel = on_runtime_init_dialog;
+	base_class->dialog_response = on_dialog_response;
 	base_class->get_toplevel_name = do_get_dialog_name;
 }
 
 static void
 imenu_item_iface_init( NactIMenuItemInterface *iface )
 {
-	static const gchar *thisfn = "nact_action_profile_imenu_item_iface_init";
+	static const gchar *thisfn = "nact_action_profiles_editor_imenu_item_iface_init";
 	g_debug( "%s: iface=%p", thisfn, iface );
-}
 
-static void
-iaction_conditions_iface_init( NactIActionConditionsInterface *iface )
-{
-	static const gchar *thisfn = "nact_action_profile_iaction_conditions_iface_init";
-	g_debug( "%s: iface=%p", thisfn, iface );
+	iface->signal_connected = nact_window_on_signal_connected;
 }
 
 static void
 instance_init( GTypeInstance *instance, gpointer klass )
 {
-	static const gchar *thisfn = "nact_action_profile_instance_init";
+	static const gchar *thisfn = "nact_action_profiles_editor_instance_init";
 	g_debug( "%s: instance=%p, klass=%p", thisfn, instance, klass );
 
-	g_assert( NACT_IS_ACTION_PROFILE( instance ));
-	NactActionProfile *self = NACT_ACTION_PROFILE( instance );
+	g_assert( NACT_IS_ACTION_PROFILES_EDITOR( instance ));
+	NactActionProfilesEditor *self = NACT_ACTION_PROFILES_EDITOR( instance );
 
-	self->private = g_new0( NactActionProfilePrivate, 1 );
+	self->private = g_new0( NactActionProfilesEditorPrivate, 1 );
 
 	self->private->dispose_has_run = FALSE;
 }
 
-/*static void
-instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec )
-{
-	g_assert( NACT_IS_ACTION_PROFILE( object ));
-	NactActionProfile *self = NACT_ACTION_PROFILE( object );
-
-	switch( property_id ){
-		case PROP_ARGC:
-			g_value_set_int( value, self->private->argc );
-			break;
-
-		case PROP_ARGV:
-			g_value_set_pointer( value, self->private->argv );
-			break;
-
-		case PROP_UNIQUE_NAME:
-			g_value_set_string( value, self->private->unique_name );
-			break;
-
-		case PROP_UNIQUE_APP:
-			g_value_set_pointer( value, self->private->unique_app );
-			break;
-
-		case PROP_MAIN_WINDOW:
-			g_value_set_pointer( value, self->private->main_window );
-			break;
-
-		case PROP_DLG_NAME:
-			g_value_set_string( value, self->private->application_name );
-			break;
-
-		case PROP_ICON_NAME:
-			g_value_set_string( value, self->private->icon_name );
-			break;
-
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
-			break;
-	}
-}
-
-static void
-instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec )
-{
-	g_assert( NACT_IS_ACTION_PROFILE( object ));
-	NactActionProfile *self = NACT_ACTION_PROFILE( object );
-
-	switch( property_id ){
-		case PROP_ARGC:
-			self->private->argc = g_value_get_int( value );
-			break;
-
-		case PROP_ARGV:
-			self->private->argv = g_value_get_pointer( value );
-			break;
-
-		case PROP_UNIQUE_NAME:
-			g_free( self->private->unique_name );
-			self->private->unique_name = g_value_dup_string( value );
-			break;
-
-		case PROP_UNIQUE_APP:
-			self->private->unique_app = g_value_get_pointer( value );
-			break;
-
-		case PROP_MAIN_WINDOW:
-			self->private->main_window = g_value_get_pointer( value );
-			break;
-
-		case PROP_DLG_NAME:
-			g_free( self->private->application_name );
-			self->private->application_name = g_value_dup_string( value );
-			break;
-
-		case PROP_ICON_NAME:
-			g_free( self->private->icon_name );
-			self->private->icon_name = g_value_dup_string( value );
-			break;
-
-		default:
-			G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
-			break;
-	}
-}*/
-
 static void
 instance_dispose( GObject *dialog )
 {
-	static const gchar *thisfn = "nact_action_profile_instance_dispose";
+	static const gchar *thisfn = "nact_action_profiles_editor_instance_dispose";
 	g_debug( "%s: dialog=%p", thisfn, dialog );
 
-	g_assert( NACT_IS_ACTION_PROFILE( dialog ));
-	NactActionProfile *self = NACT_ACTION_PROFILE( dialog );
+	g_assert( NACT_IS_ACTION_PROFILES_EDITOR( dialog ));
+	NactActionProfilesEditor *self = NACT_ACTION_PROFILES_EDITOR( dialog );
 
 	if( !self->private->dispose_has_run ){
 
@@ -279,11 +181,11 @@ instance_dispose( GObject *dialog )
 static void
 instance_finalize( GObject *dialog )
 {
-	static const gchar *thisfn = "nact_action_profile_instance_finalize";
+	static const gchar *thisfn = "nact_action_profiles_editor_instance_finalize";
 	g_debug( "%s: dialog=%p", thisfn, dialog );
 
-	g_assert( NACT_IS_ACTION_PROFILE( dialog ));
-	/*NactActionProfile *self = ( NactActionProfile * ) dialog;*/
+	g_assert( NACT_IS_ACTION_PROFILES_EDITOR( dialog ));
+	/*NactActionProfilesEditor *self = ( NactActionProfilesEditor * ) dialog;*/
 
 	/* chain call to parent class */
 	if( st_parent_class->finalize ){
@@ -292,15 +194,15 @@ instance_finalize( GObject *dialog )
 }
 
 /**
- * Returns a newly allocated NactActionProfile object.
+ * Returns a newly allocated NactActionProfilesEditor object.
  *
  * @parent: is the BaseWindow parent of this dialog (usually, the main
  * toplevel window of the application).
  */
-static NactActionProfile *
-action_profile_new( BaseApplication *application )
+static NactActionProfilesEditor *
+action_profiles_editor_new( BaseApplication *application )
 {
-	return( g_object_new( NACT_ACTION_PROFILE_TYPE, PROP_WINDOW_APPLICATION_STR, application, NULL ));
+	return( g_object_new( NACT_ACTION_PROFILES_EDITOR_TYPE, PROP_WINDOW_APPLICATION_STR, application, NULL ));
 }
 
 /**
@@ -316,44 +218,90 @@ action_profile_new( BaseApplication *application )
  * there has been no modification at all.
  */
 gboolean
-nact_action_profile_run_editor( NactWindow *parent, gpointer user_data )
+nact_action_profiles_editor_run_editor( NactWindow *parent, gpointer user_data )
 {
 	g_assert( NACT_IS_MAIN_WINDOW( parent ));
 
 	BaseApplication *application = BASE_APPLICATION( base_window_get_application( BASE_WINDOW( parent )));
 	g_assert( NACT_IS_APPLICATION( application ));
 
-	NactActionProfile *dialog = action_profile_new( application );
+	NactActionProfilesEditor *dialog = action_profiles_editor_new( application );
 
 	g_assert( NA_IS_ACTION( user_data ) || !user_data );
-	dialog->private->action = NA_ACTION( user_data );
+	NAAction *action = NA_ACTION( user_data );
+
+	if( !action ){
+		dialog->private->action = na_action_new( NULL );
+		dialog->private->is_new = TRUE;
+
+	} else {
+		dialog->private->action = na_action_duplicate( action );
+		dialog->private->is_new = FALSE;
+	}
 
 	base_window_run( BASE_WINDOW( dialog ));
 
+	g_object_unref( dialog->private->action );
 	return( TRUE );
 }
 
 static gchar *
 do_get_dialog_name( BaseWindow *dialog )
 {
-	/*g_debug( "nact_action_profile_do_get_dialog_name" );*/
+	/*g_debug( "nact_action_profiles_editor_do_get_dialog_name" );*/
 	return( g_strdup( "EditActionDialogExt"));
 }
 
 static void
-on_init_dialog( BaseWindow *dialog )
+on_initial_load_dialog( BaseWindow *dialog )
 {
-	static const gchar *thisfn = "nact_action_profile_on_init_dialog";
+	static const gchar *thisfn = "nact_action_profiles_editor_on_initial_load_dialog";
 	g_debug( "%s: dialog=%p", thisfn, dialog );
+
+	g_assert( NACT_IS_ACTION_PROFILES_EDITOR( dialog ));
+	NactActionProfilesEditor *window = NACT_ACTION_PROFILES_EDITOR( dialog );
+
+	init_dialog_title( window );
+	nact_imenu_item_initial_load( NACT_WINDOW( window ), window->private->action );
+}
+
+static void
+on_runtime_init_dialog( BaseWindow *dialog )
+{
+	static const gchar *thisfn = "nact_action_profiles_editor_on_runtime_init_dialog";
+	g_debug( "%s: dialog=%p", thisfn, dialog );
+
+	g_assert( NACT_IS_ACTION_PROFILES_EDITOR( dialog ));
+	NactActionProfilesEditor *window = NACT_ACTION_PROFILES_EDITOR( dialog );
+
+	init_dialog_title( window );
+	nact_imenu_item_runtime_init( NACT_WINDOW( window ), window->private->action );
+}
+
+static void
+init_dialog_title( NactActionProfilesEditor *dialog )
+{
+	GtkWindow *toplevel = base_window_get_toplevel_widget( BASE_WINDOW( dialog ));
+
+	if( dialog->private->is_new ){
+		gtk_window_set_title( toplevel, _( "Adding a new action" ));
+
+	} else {
+		gchar *label = na_action_get_label( dialog->private->action );
+		gchar* title = g_strdup_printf( _( "Editing \"%s\" action" ), label );
+		gtk_window_set_title( toplevel, title );
+		g_free( label );
+		g_free( title );
+	}
 }
 
 static void
 on_dialog_response( GtkDialog *dialog, gint code, BaseWindow *window )
 {
-	static const gchar *thisfn = "nact_action_profile_on_dialog_response";
+	static const gchar *thisfn = "nact_action_profiles_editor_on_dialog_response";
 	g_debug( "%s: dialog=%p, code=%d, window=%p", thisfn, dialog, code, window );
 
-	g_assert( NACT_IS_ACTION_PROFILE( window ));
+	g_assert( NACT_IS_ACTION_PROFILES_EDITOR( window ));
 
 	switch( code ){
 		case GTK_RESPONSE_NONE:
diff --git a/src/nact/nact-action-profile.h b/src/nact/nact-action-profiles-editor.h
similarity index 51%
rename from src/nact/nact-action-profile.h
rename to src/nact/nact-action-profiles-editor.h
index d87c952..99f8896 100644
--- a/src/nact/nact-action-profile.h
+++ b/src/nact/nact-action-profiles-editor.h
@@ -28,11 +28,11 @@
  *   ... and many others (see AUTHORS)
  */
 
-#ifndef __NACT_ACTION_PROFILE_H__
-#define __NACT_ACTION_PROFILE_H__
+#ifndef __NACT_ACTION_PROFILES_EDITOR_H__
+#define __NACT_ACTION_PROFILES_EDITOR_H__
 
 /*
- * NactActionProfile class definition.
+ * NactActionProfilesEditor class definition.
  *
  * This class is derived from NactWindow.
  * It encapsulates the "EditActionDialogExt" widget dialog.
@@ -42,33 +42,33 @@
 
 G_BEGIN_DECLS
 
-#define NACT_ACTION_PROFILE_TYPE					( nact_action_profile_get_type())
-#define NACT_ACTION_PROFILE( object )				( G_TYPE_CHECK_INSTANCE_CAST( object, NACT_ACTION_PROFILE_TYPE, NactActionProfile ))
-#define NACT_ACTION_PROFILE_CLASS( klass )			( G_TYPE_CHECK_CLASS_CAST( klass, NACT_ACTION_PROFILE_TYPE, NactActionProfileClass ))
-#define NACT_IS_ACTION_PROFILE( object )			( G_TYPE_CHECK_INSTANCE_TYPE( object, NACT_ACTION_PROFILE_TYPE ))
-#define NACT_IS_ACTION_PROFILE_CLASS( klass )		( G_TYPE_CHECK_CLASS_TYPE(( klass ), NACT_ACTION_PROFILE_TYPE ))
-#define NACT_ACTION_PROFILE_GET_CLASS( object )	( G_TYPE_INSTANCE_GET_CLASS(( object ), NACT_ACTION_PROFILE_TYPE, NactActionProfileClass ))
+#define NACT_ACTION_PROFILES_EDITOR_TYPE				( nact_action_profiles_editor_get_type())
+#define NACT_ACTION_PROFILES_EDITOR( object )			( G_TYPE_CHECK_INSTANCE_CAST( object, NACT_ACTION_PROFILES_EDITOR_TYPE, NactActionProfilesEditor ))
+#define NACT_ACTION_PROFILES_EDITOR_CLASS( klass )		( G_TYPE_CHECK_CLASS_CAST( klass, NACT_ACTION_PROFILES_EDITOR_TYPE, NactActionProfilesEditorClass ))
+#define NACT_IS_ACTION_PROFILES_EDITOR( object )		( G_TYPE_CHECK_INSTANCE_TYPE( object, NACT_ACTION_PROFILES_EDITOR_TYPE ))
+#define NACT_IS_ACTION_PROFILES_EDITOR_CLASS( klass )	( G_TYPE_CHECK_CLASS_TYPE(( klass ), NACT_ACTION_PROFILES_EDITOR_TYPE ))
+#define NACT_ACTION_PROFILES_EDITOR_GET_CLASS( object )	( G_TYPE_INSTANCE_GET_CLASS(( object ), NACT_ACTION_PROFILES_EDITOR_TYPE, NactActionProfilesEditorClass ))
 
-typedef struct NactActionProfilePrivate NactActionProfilePrivate;
+typedef struct NactActionProfilesEditorPrivate NactActionProfilesEditorPrivate;
 
 typedef struct {
 	NactWindow                       parent;
-	NactActionProfilePrivate *private;
+	NactActionProfilesEditorPrivate *private;
 }
-	NactActionProfile;
+	NactActionProfilesEditor;
 
-typedef struct NactActionProfileClassPrivate NactActionProfileClassPrivate;
+typedef struct NactActionProfilesEditorClassPrivate NactActionProfilesEditorClassPrivate;
 
 typedef struct {
 	NactWindowClass                       parent;
-	NactActionProfileClassPrivate *private;
+	NactActionProfilesEditorClassPrivate *private;
 }
-	NactActionProfileClass;
+	NactActionProfilesEditorClass;
 
-GType    nact_action_profile_get_type( void );
+GType    nact_action_profiles_editor_get_type( void );
 
-gboolean nact_action_profile_run_editor( NactWindow *parent, gpointer user_data );
+gboolean nact_action_profiles_editor_run_editor( NactWindow *parent, gpointer user_data );
 
 G_END_DECLS
 
-#endif /* __NACT_ACTION_PROFILE_H__ */
+#endif /* __NACT_ACTION_PROFILES_EDITOR_H__ */
diff --git a/src/nact/nact-iactions-list.c b/src/nact/nact-iactions-list.c
index 188c632..8b3fcf7 100644
--- a/src/nact/nact-iactions-list.c
+++ b/src/nact/nact-iactions-list.c
@@ -56,13 +56,14 @@ static GType      register_type( void );
 static void       interface_base_init( NactIActionsListInterface *klass );
 static void       interface_base_finalize( NactIActionsListInterface *klass );
 
-static void       do_init_widget( NactWindow *window );
-static void       do_fill_actions_list( NactWindow *window );
-static GtkWidget *get_actions_list( NactWindow *window );
-
 static void       v_on_selection_changed( GtkTreeSelection *selection, gpointer user_data );
 static gboolean   v_on_button_press_event( GtkWidget *widget, GdkEventButton *event, gpointer data );
 
+static void       do_initial_load_widget( NactWindow *window );
+static void       do_runtime_init_widget( NactWindow *window );
+static void       do_fill_actions_list( NactWindow *window );
+static GtkWidget *get_actions_list_widget( NactWindow *window );
+
 GType
 nact_iactions_list_get_type( void )
 {
@@ -111,7 +112,8 @@ interface_base_init( NactIActionsListInterface *klass )
 
 		klass->private = g_new0( NactIActionsListInterfacePrivate, 1 );
 
-		klass->init_widget = do_init_widget;
+		klass->initial_load_widget = do_initial_load_widget;
+		klass->runtime_init_widget = do_runtime_init_widget;
 		klass->on_selection_changed = NULL;
 
 		initialized = TRUE;
@@ -137,26 +139,123 @@ interface_base_finalize( NactIActionsListInterface *klass )
  * Allocates and initializes the ActionsList widget.
  */
 void
-nact_iactions_list_init( NactWindow *window )
+nact_iactions_list_initial_load( NactWindow *window )
+{
+	g_assert( NACT_IS_IACTIONS_LIST( window ));
+
+	if( NACT_IACTIONS_LIST_GET_INTERFACE( window )->initial_load_widget ){
+		NACT_IACTIONS_LIST_GET_INTERFACE( window )->initial_load_widget( window );
+	} else {
+		do_initial_load_widget( window );
+	}
+}
+
+/**
+ * Allocates and initializes the ActionsList widget.
+ */
+void
+nact_iactions_list_runtime_init( NactWindow *window )
 {
 	g_assert( NACT_IS_IACTIONS_LIST( window ));
 
-	if( NACT_IACTIONS_LIST_GET_INTERFACE( window )->init_widget ){
-		NACT_IACTIONS_LIST_GET_INTERFACE( window )->init_widget( window );
+	if( NACT_IACTIONS_LIST_GET_INTERFACE( window )->runtime_init_widget ){
+		NACT_IACTIONS_LIST_GET_INTERFACE( window )->runtime_init_widget( window );
 	} else {
-		do_init_widget( window );
+		do_runtime_init_widget( window );
+	}
+}
+
+/**
+ * Fill the listbox with current actions.
+ */
+void
+nact_iactions_list_fill( NactWindow *window )
+{
+	g_assert( NACT_IS_IACTIONS_LIST( window ));
+
+	if( NACT_IACTIONS_LIST_GET_INTERFACE( window )->fill_actions_list ){
+		NACT_IACTIONS_LIST_GET_INTERFACE( window )->fill_actions_list( window );
+	} else {
+		do_fill_actions_list( window );
+	}
+}
+
+/**
+ * Returns the currently selected action.
+ */
+GObject *
+nact_iactions_list_get_selected_action( NactWindow *window )
+{
+	GObject *action = NULL;
+
+	GtkWidget *list = get_actions_list_widget( window );
+	GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW( list ));
+
+	GtkTreeIter iter;
+	GtkTreeModel *model;
+
+	if( gtk_tree_selection_get_selected( selection, &model, &iter )){
+
+		gchar *uuid;
+		gtk_tree_model_get( model, &iter, IACTIONS_LIST_UUID_COLUMN, &uuid, -1 );
+		action = nact_window_get_action( window, uuid );
+		g_free (uuid);
+	}
+
+	return( action );
+}
+
+static void
+v_on_selection_changed( GtkTreeSelection *selection, gpointer user_data )
+{
+	g_assert( NACT_IS_IACTIONS_LIST( user_data ));
+	g_assert( BASE_IS_WINDOW( user_data ));
+
+	NactIActionsList *instance = NACT_IACTIONS_LIST( user_data );
+
+	if( NACT_IACTIONS_LIST_GET_INTERFACE( instance )->on_selection_changed ){
+		NACT_IACTIONS_LIST_GET_INTERFACE( instance )->on_selection_changed( selection, user_data );
+	}
+}
+
+static gboolean
+v_on_button_press_event( GtkWidget *widget, GdkEventButton *event, gpointer user_data )
+{
+	/*static const gchar *thisfn = "nact_iactions_list_v_on_button_pres_event";
+	g_debug( "%s: widget=%p, event=%p, user_data=%p", thisfn, widget, event, user_data );*/
+
+	g_assert( NACT_IS_IACTIONS_LIST( user_data ));
+	g_assert( NACT_IS_WINDOW( user_data ));
+
+	gboolean stop = FALSE;
+	NactIActionsList *instance = NACT_IACTIONS_LIST( user_data );
+
+	if( NACT_IACTIONS_LIST_GET_INTERFACE( instance )->on_button_press_event ){
+		stop = NACT_IACTIONS_LIST_GET_INTERFACE( instance )->on_button_press_event( widget, event, user_data );
+	}
+
+	if( !stop ){
+		if( event->type == GDK_2BUTTON_PRESS ){
+			if( NACT_IACTIONS_LIST_GET_INTERFACE( instance )->on_double_click ){
+				stop = NACT_IACTIONS_LIST_GET_INTERFACE( instance )->on_double_click( widget, event, user_data );
+			}
+		}
 	}
+	return( stop );
 }
 
 void
-do_init_widget( NactWindow *window )
+do_initial_load_widget( NactWindow *window )
 {
+	static const gchar *thisfn = "nact_iactions_list_do_initial_load_widget";
+	g_debug( "%s: window=%p", thisfn, window );
+
 	GtkListStore *model;
 	GtkTreeViewColumn *column;
 
 	g_assert( BASE_IS_WINDOW( window ));
 
-	GtkWidget *widget = get_actions_list( window );
+	GtkWidget *widget = get_actions_list_widget( window );
 
 	/* create the model */
 	model = gtk_list_store_new( IACTIONS_LIST_N_COLUMN, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING );
@@ -172,6 +271,17 @@ do_init_widget( NactWindow *window )
 	column = gtk_tree_view_column_new_with_attributes(
 			"label", gtk_cell_renderer_text_new(), "text", IACTIONS_LIST_LABEL_COLUMN, NULL );
 	gtk_tree_view_append_column( GTK_TREE_VIEW( widget ), column );
+}
+
+void
+do_runtime_init_widget( NactWindow *window )
+{
+	static const gchar *thisfn = "nact_iactions_list_do_runtime_init_widget";
+	g_debug( "%s: window=%p", thisfn, window );
+
+	g_assert( BASE_IS_WINDOW( window ));
+
+	GtkWidget *widget = get_actions_list_widget( window );
 
 	/* set up selection */
 	g_signal_connect(
@@ -188,28 +298,13 @@ do_init_widget( NactWindow *window )
 			window );
 }
 
-/**
- * Fill the listbox with current actions.
- */
-void
-nact_iactions_list_fill( NactWindow *window )
-{
-	g_assert( NACT_IS_IACTIONS_LIST( window ));
-
-	if( NACT_IACTIONS_LIST_GET_INTERFACE( window )->fill_actions_list ){
-		NACT_IACTIONS_LIST_GET_INTERFACE( window )->fill_actions_list( window );
-	} else {
-		do_fill_actions_list( window );
-	}
-}
-
 static void
 do_fill_actions_list( NactWindow *window )
 {
 	static const gchar *thisfn = "nact_iactions_list_do_fill_actions_list";
 	g_debug( "%s: window=%p", thisfn, window );
 
-	GtkWidget *widget = get_actions_list( window );
+	GtkWidget *widget = get_actions_list_widget( window );
 	GtkListStore *model = GTK_LIST_STORE( gtk_tree_view_get_model( GTK_TREE_VIEW( widget )));
 	gtk_list_store_clear( model );
 
@@ -266,43 +361,7 @@ do_fill_actions_list( NactWindow *window )
 }
 
 static GtkWidget *
-get_actions_list( NactWindow *window )
+get_actions_list_widget( NactWindow *window )
 {
 	return( base_window_get_widget( BASE_WINDOW( window ), "ActionsList" ));
 }
-
-static void
-v_on_selection_changed( GtkTreeSelection *selection, gpointer user_data )
-{
-	g_assert( NACT_IS_IACTIONS_LIST( user_data ));
-	g_assert( BASE_IS_WINDOW( user_data ));
-
-	NactIActionsList *instance = NACT_IACTIONS_LIST( user_data );
-
-	if( NACT_IACTIONS_LIST_GET_INTERFACE( instance )->on_selection_changed ){
-		NACT_IACTIONS_LIST_GET_INTERFACE( instance )->on_selection_changed( selection, user_data );
-	}
-}
-
-static gboolean
-v_on_button_press_event( GtkWidget *widget, GdkEventButton *event, gpointer user_data )
-{
-	g_assert( NACT_IS_IACTIONS_LIST( user_data ));
-	g_assert( BASE_IS_WINDOW( user_data ));
-
-	gboolean stop = FALSE;
-	NactIActionsList *instance = NACT_IACTIONS_LIST( user_data );
-
-	if( NACT_IACTIONS_LIST_GET_INTERFACE( instance )->on_button_press_event ){
-		stop = NACT_IACTIONS_LIST_GET_INTERFACE( instance )->on_button_press_event( widget, event, user_data );
-	}
-
-	if( !stop ){
-		if( event->type == GDK_2BUTTON_PRESS ){
-			if( NACT_IACTIONS_LIST_GET_INTERFACE( instance )->on_double_click ){
-				stop = NACT_IACTIONS_LIST_GET_INTERFACE( instance )->on_double_click( widget, event, user_data );
-			}
-		}
-	}
-	return( stop );
-}
diff --git a/src/nact/nact-iactions-list.h b/src/nact/nact-iactions-list.h
index 33a72f9..b7a5b73 100644
--- a/src/nact/nact-iactions-list.h
+++ b/src/nact/nact-iactions-list.h
@@ -59,7 +59,8 @@ typedef struct {
 	NactIActionsListInterfacePrivate *private;
 
 	/* api */
-	void     ( *init_widget )          ( NactWindow *window );
+	void     ( *initial_load_widget )  ( NactWindow *window );
+	void     ( *runtime_init_widget )  ( NactWindow *window );
 	void     ( *fill_actions_list )    ( NactWindow *window );
 	void     ( *on_selection_changed ) ( GtkTreeSelection *selection, gpointer user_data );
 	gboolean ( *on_button_press_event )( GtkWidget *widget, GdkEventButton *event, gpointer data );
@@ -67,10 +68,12 @@ typedef struct {
 }
 	NactIActionsListInterface;
 
-GType nact_iactions_list_get_type( void );
+GType    nact_iactions_list_get_type( void );
 
-void  nact_iactions_list_init( NactWindow *window );
-void  nact_iactions_list_fill( NactWindow *window );
+void     nact_iactions_list_initial_load( NactWindow *window );
+void     nact_iactions_list_runtime_init( NactWindow *window );
+void     nact_iactions_list_fill( NactWindow *window );
+GObject *nact_iactions_list_get_selected_action( NactWindow *window );
 
 G_END_DECLS
 
diff --git a/src/nact/nact-imenu-item.c b/src/nact/nact-imenu-item.c
index 533a8ef..1326c27 100644
--- a/src/nact/nact-imenu-item.c
+++ b/src/nact/nact-imenu-item.c
@@ -32,6 +32,9 @@
 #include <config.h>
 #endif
 
+#include <glib/gi18n.h>
+#include <string.h>
+
 #include <common/na-action.h>
 #include <common/na-action-profile.h>
 
@@ -42,9 +45,28 @@
 struct NactIMenuItemInterfacePrivate {
 };
 
-static GType      register_type( void );
-static void       interface_base_init( NactIMenuItemInterface *klass );
-static void       interface_base_finalize( NactIMenuItemInterface *klass );
+/* columns in the icon combobox
+ */
+enum {
+	ICON_STOCK_COLUMN = 0,
+	ICON_LABEL_COLUMN,
+	ICON_N_COLUMN
+};
+
+static GType         register_type( void );
+static void          interface_base_init( NactIMenuItemInterface *klass );
+static void          interface_base_finalize( NactIMenuItemInterface *klass );
+
+static void          icon_combo_list_fill( GtkComboBoxEntry* combo );
+static GtkTreeModel *create_stock_icon_model( void );
+static gint          sort_stock_ids( gconstpointer a, gconstpointer b );
+static gchar        *strip_underscore( const gchar *text );
+static void          on_label_changed( GtkEntry *entry, gpointer user_data );
+static void          on_tooltip_changed( GtkEntry *entry, gpointer user_data );
+static void          on_icon_changed( GtkEntry *entry, gpointer user_data );
+
+static void          record_signal( NactWindow *window, GObject *instance, const gchar *signal, GCallback fn, gpointer user_data );
+static void          v_signal_connected( NactWindow *window, gpointer instance, gulong handler_id );
 
 GType
 nact_imenu_item_get_type( void )
@@ -94,6 +116,8 @@ interface_base_init( NactIMenuItemInterface *klass )
 
 		klass->private = g_new0( NactIMenuItemInterfacePrivate, 1 );
 
+		klass->signal_connected = NULL;
+
 		initialized = TRUE;
 	}
 }
@@ -112,3 +136,230 @@ interface_base_finalize( NactIMenuItemInterface *klass )
 		finalized = TRUE;
 	}
 }
+
+void
+nact_imenu_item_initial_load( NactWindow *dialog, NAAction *action )
+{
+	static const gchar *thisfn = "nact_imenu_item_initial_load";
+	g_debug( "%s: dialog=%p, action=%p", thisfn, dialog, action );
+
+	GtkWidget *icon_widget = base_window_get_widget( BASE_WINDOW( dialog ), "MenuIconComboBoxEntry" );
+
+	gtk_combo_box_set_model( GTK_COMBO_BOX( icon_widget ), create_stock_icon_model());
+
+	icon_combo_list_fill( GTK_COMBO_BOX_ENTRY( icon_widget ));
+}
+
+void
+nact_imenu_item_runtime_init( NactWindow *dialog, NAAction *action )
+{
+	static const gchar *thisfn = "nact_imenu_item_runtime_init";
+	g_debug( "%s: dialog=%p, action=%p", thisfn, dialog, action );
+
+	GtkWidget *label_widget = base_window_get_widget( BASE_WINDOW( dialog ), "MenuLabelEntry" );
+	gchar *label = na_action_get_label( action );
+	gtk_entry_set_text( GTK_ENTRY( label_widget ), label );
+	g_free( label );
+	record_signal( dialog, G_OBJECT( label_widget ), "changed", G_CALLBACK( on_label_changed ), dialog );
+
+	GtkWidget *tooltip_widget = base_window_get_widget( BASE_WINDOW( dialog ), "MenuTooltipEntry" );
+	gchar *tooltip = na_action_get_tooltip( action );
+	gtk_entry_set_text( GTK_ENTRY( tooltip_widget ), tooltip );
+	g_free( tooltip );
+	record_signal( dialog, G_OBJECT( tooltip_widget ), "changed", G_CALLBACK( on_tooltip_changed ), dialog );
+
+	GtkWidget *icon_widget = base_window_get_widget( BASE_WINDOW( dialog ), "MenuIconComboBoxEntry" );
+	gchar *icon = na_action_get_icon( action );
+	gtk_entry_set_text( GTK_ENTRY( GTK_BIN( icon_widget )->child ), icon );
+	g_free( icon );
+	record_signal( dialog, G_OBJECT( GTK_BIN( icon_widget )->child ), "changed", G_CALLBACK( on_icon_changed ), dialog );
+}
+
+static void
+icon_combo_list_fill( GtkComboBoxEntry* combo )
+{
+	GtkCellRenderer *cell_renderer_pix;
+	GtkCellRenderer *cell_renderer_text;
+
+	if( gtk_combo_box_entry_get_text_column( combo ) == -1 ){
+		gtk_combo_box_entry_set_text_column( combo, ICON_STOCK_COLUMN );
+	}
+	gtk_cell_layout_clear( GTK_CELL_LAYOUT( combo ));
+
+	cell_renderer_pix = gtk_cell_renderer_pixbuf_new();
+	gtk_cell_layout_pack_start( GTK_CELL_LAYOUT( combo ), cell_renderer_pix, FALSE );
+	gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT( combo ), cell_renderer_pix, "stock-id", ICON_STOCK_COLUMN );
+
+	cell_renderer_text = gtk_cell_renderer_text_new();
+	gtk_cell_layout_pack_start( GTK_CELL_LAYOUT( combo ), cell_renderer_text, TRUE );
+	gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT( combo ), cell_renderer_text, "text", ICON_LABEL_COLUMN );
+
+	gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), 0 );
+}
+
+static GtkTreeModel *
+create_stock_icon_model( void )
+{
+	GtkStockItem stock_item;
+	gchar* label;
+
+	GtkListStore *model = gtk_list_store_new( ICON_N_COLUMN, G_TYPE_STRING, G_TYPE_STRING );
+
+	GtkTreeIter row;
+	gtk_list_store_append( model, &row );
+
+	/* i18n notes: when no icon is selected in the drop-down list */
+	gtk_list_store_set( model, &row, ICON_STOCK_COLUMN, "", ICON_LABEL_COLUMN, _( "None" ), -1 );
+
+	GSList *stock_list = gtk_stock_list_ids();
+	GtkIconTheme *icon_theme = gtk_icon_theme_get_default();
+	stock_list = g_slist_sort( stock_list, ( GCompareFunc ) sort_stock_ids );
+
+	GSList *iter;
+	for( iter = stock_list ; iter ; iter = iter->next ){
+		GtkIconInfo *icon_info = gtk_icon_theme_lookup_icon( icon_theme, ( gchar * ) iter->data, GTK_ICON_SIZE_MENU, GTK_ICON_LOOKUP_FORCE_SVG );
+		if( icon_info ){
+			if( gtk_stock_lookup(( gchar * ) iter->data, &stock_item )){
+				gtk_list_store_append( model, &row );
+				label = strip_underscore( stock_item.label );
+				gtk_list_store_set( model, &row, ICON_STOCK_COLUMN, ( gchar * ) iter->data, ICON_LABEL_COLUMN, label, -1 );
+				g_free( label );
+			}
+			gtk_icon_info_free( icon_info );
+		}
+	}
+
+	g_slist_foreach( stock_list, ( GFunc ) g_free, NULL );
+	g_slist_free( stock_list );
+
+	return( GTK_TREE_MODEL( model ));
+}
+
+static gint
+sort_stock_ids( gconstpointer a, gconstpointer b )
+{
+	GtkStockItem stock_item_a;
+	GtkStockItem stock_item_b;
+	gchar *label_a, *label_b;
+	gboolean is_a, is_b;
+	int retv = 0;
+
+	is_a = gtk_stock_lookup(( gchar * ) a, &stock_item_a );
+	is_b = gtk_stock_lookup(( gchar * ) b, &stock_item_b );
+
+	if( is_a && !is_b ){
+		retv = 1;
+
+	} else if( !is_a && is_b ){
+		retv = -1;
+
+	} else if( !is_a && !is_b ){
+		retv = 0;
+
+	} else {
+		label_a = strip_underscore( stock_item_a.label );
+		label_b = strip_underscore( stock_item_b.label );
+		retv = g_utf8_collate( label_a, label_b );
+		g_free( label_a );
+		g_free( label_b );
+	}
+
+	return( retv );
+}
+
+static gchar *
+strip_underscore( const gchar *text )
+{
+	/* Code from gtk-demo */
+	gchar *p, *q, *result;
+
+	result = g_strdup( text );
+	p = q = result;
+	while( *p ){
+		if( *p != '_' ){
+			*q = *p;
+			q++;
+		}
+		p++;
+	}
+	*q = '\0';
+
+	return( result );
+}
+
+static void
+on_label_changed( GtkEntry *entry, gpointer user_data )
+{
+	g_assert( NACT_IS_WINDOW( user_data ));
+	/*NactWindow *dialog = NACT_WINDOW( user_data );*/
+}
+
+static void
+on_tooltip_changed( GtkEntry *entry, gpointer user_data )
+{
+	g_assert( NACT_IS_WINDOW( user_data ));
+	/*NactWindow *dialog = NACT_WINDOW( user_data );*/
+}
+
+static void
+on_icon_changed( GtkEntry *icon_entry, gpointer user_data )
+{
+	g_assert( NACT_IS_WINDOW( user_data ));
+	NactWindow *dialog = NACT_WINDOW( user_data );
+
+	GtkWidget *image = base_window_get_widget( BASE_WINDOW( dialog ), "IconImage" );
+	const gchar *icon_name = gtk_entry_get_text( icon_entry );
+	GtkStockItem stock_item;
+	GdkPixbuf *icon = NULL;
+	gchar *error_msg;
+
+	if( icon_name && strlen( icon_name ) > 0 ){
+
+		/* TODO: code should be mutualized with those IActionsList */
+		if( gtk_stock_lookup( icon_name, &stock_item )){
+			gtk_image_set_from_stock( GTK_IMAGE( image ), icon_name, GTK_ICON_SIZE_MENU );
+			gtk_widget_show( image );
+
+		} else if( g_file_test( icon_name, G_FILE_TEST_EXISTS ) &&
+					g_file_test( icon_name, G_FILE_TEST_IS_REGULAR )){
+			gint width;
+			gint height;
+			GError *error = NULL;
+
+			gtk_icon_size_lookup( GTK_ICON_SIZE_MENU, &width, &height );
+			icon = gdk_pixbuf_new_from_file_at_size( icon_name, width, height, &error );
+			if( error ){
+				icon = NULL;
+
+				error_msg = g_strdup_printf( "Can't load icon from file %s !", icon_name );
+				/*nautilus_actions_display_error (error_msg,  error->message);*/
+				g_free( error_msg );
+				g_error_free( error );
+			}
+			gtk_image_set_from_pixbuf( GTK_IMAGE( image ), icon );
+			gtk_widget_show( image );
+		}
+		else {
+			gtk_widget_hide( image );
+		}
+	} else {
+		gtk_widget_hide( image );
+	}
+}
+
+static void
+record_signal( NactWindow *window, GObject *instance, const gchar *signal, GCallback fn, gpointer user_data )
+{
+	gulong handler_id = g_signal_connect( instance, signal, fn, user_data );
+	v_signal_connected( window, instance, handler_id );
+}
+
+static void
+v_signal_connected( NactWindow *window, gpointer instance, gulong handler_id )
+{
+	g_assert( NACT_IS_IMENU_ITEM( window ));
+
+	if( NACT_IMENU_ITEM_GET_INTERFACE( window )->signal_connected ){
+		NACT_IMENU_ITEM_GET_INTERFACE( window )->signal_connected( window, instance, handler_id );
+	}
+}
diff --git a/src/nact/nact-imenu-item.h b/src/nact/nact-imenu-item.h
index 89955dd..7349b5f 100644
--- a/src/nact/nact-imenu-item.h
+++ b/src/nact/nact-imenu-item.h
@@ -34,12 +34,10 @@
 /*
  * NactIMenuItem interface definition.
  *
- * This interface defines some API against the ActionsList listbox.
- * Our NactWindow may implement it in order to personalize the
- * behaviour of the listbox.
+ * This interface implements the "Nautilus Menu Item" box.
  */
 
-#include <gtk/gtk.h>
+#include <common/na-action.h>
 
 #include "nact-window.h"
 
@@ -59,11 +57,15 @@ typedef struct {
 	NactIMenuItemInterfacePrivate *private;
 
 	/* api */
+	void ( *signal_connected )( NactWindow *window, gpointer instance, gulong handler_id );
 }
 	NactIMenuItemInterface;
 
 GType nact_imenu_item_get_type( void );
 
+void  nact_imenu_item_initial_load( NactWindow *dialog, NAAction *action );
+void  nact_imenu_item_runtime_init( NactWindow *dialog, NAAction *action );
+
 G_END_DECLS
 
 #endif /* __NACT_IMENU_ITEM_H__ */
diff --git a/src/nact/nact-iaction-conditions.c b/src/nact/nact-iprofile-conditions.c
similarity index 60%
rename from src/nact/nact-iaction-conditions.c
rename to src/nact/nact-iprofile-conditions.c
index 245c1a6..c9c8bb1 100644
--- a/src/nact/nact-iaction-conditions.c
+++ b/src/nact/nact-iprofile-conditions.c
@@ -35,19 +35,19 @@
 #include <common/na-action.h>
 #include <common/na-action-profile.h>
 
-#include "nact-iaction-conditions.h"
+#include "nact-iprofile-conditions.h"
 
 /* private interface data
  */
-struct NactIActionConditionsInterfacePrivate {
+struct NactIProfileConditionsInterfacePrivate {
 };
 
 static GType      register_type( void );
-static void       interface_base_init( NactIActionConditionsInterface *klass );
-static void       interface_base_finalize( NactIActionConditionsInterface *klass );
+static void       interface_base_init( NactIProfileConditionsInterface *klass );
+static void       interface_base_finalize( NactIProfileConditionsInterface *klass );
 
 GType
-nact_iaction_conditions_get_type( void )
+nact_iprofile_conditions_get_type( void )
 {
 	static GType iface_type = 0;
 
@@ -61,11 +61,11 @@ nact_iaction_conditions_get_type( void )
 static GType
 register_type( void )
 {
-	static const gchar *thisfn = "nact_iaction_conditions_register_type";
+	static const gchar *thisfn = "nact_iprofile_conditions_register_type";
 	g_debug( "%s", thisfn );
 
 	static const GTypeInfo info = {
-		sizeof( NactIActionConditionsInterface ),
+		sizeof( NactIProfileConditionsInterface ),
 		( GBaseInitFunc ) interface_base_init,
 		( GBaseFinalizeFunc ) interface_base_finalize,
 		NULL,
@@ -76,7 +76,7 @@ register_type( void )
 		NULL
 	};
 
-	GType type = g_type_register_static( G_TYPE_INTERFACE, "NactIActionConditions", &info, 0 );
+	GType type = g_type_register_static( G_TYPE_INTERFACE, "NactIProfileConditions", &info, 0 );
 
 	g_type_interface_add_prerequisite( type, G_TYPE_OBJECT );
 
@@ -84,24 +84,24 @@ register_type( void )
 }
 
 static void
-interface_base_init( NactIActionConditionsInterface *klass )
+interface_base_init( NactIProfileConditionsInterface *klass )
 {
-	static const gchar *thisfn = "nact_iaction_conditions_interface_base_init";
+	static const gchar *thisfn = "nact_iprofile_conditions_interface_base_init";
 	static gboolean initialized = FALSE;
 
 	if( !initialized ){
 		g_debug( "%s: klass=%p", thisfn, klass );
 
-		klass->private = g_new0( NactIActionConditionsInterfacePrivate, 1 );
+		klass->private = g_new0( NactIProfileConditionsInterfacePrivate, 1 );
 
 		initialized = TRUE;
 	}
 }
 
 static void
-interface_base_finalize( NactIActionConditionsInterface *klass )
+interface_base_finalize( NactIProfileConditionsInterface *klass )
 {
-	static const gchar *thisfn = "nact_iaction_conditions_interface_base_finalize";
+	static const gchar *thisfn = "nact_iprofile_conditions_interface_base_finalize";
 	static gboolean finalized = FALSE ;
 
 	if( !finalized ){
@@ -112,3 +112,23 @@ interface_base_finalize( NactIActionConditionsInterface *klass )
 		finalized = TRUE;
 	}
 }
+
+void
+nact_iprofile_conditions_initial_load( NactWindow *dialog, NAAction *action )
+{
+}
+
+void
+nact_iprofile_conditions_runtime_init( NactWindow *dialog, NAAction *action )
+{
+}
+
+void
+nact_iprofile_conditions_all_widgets_showed( NactWindow *dialog )
+{
+	static const gchar *thisfn = "nact_iprofile_conditions_all_widgets_showed";
+	g_debug( "%s: dialog=%p", thisfn, dialog );
+
+	GtkNotebook *notebook = GTK_NOTEBOOK( base_window_get_widget( BASE_WINDOW( dialog ), "notebook2" ));
+	gtk_notebook_set_current_page( notebook, 0 );
+}
diff --git a/src/nact/nact-iprofile-conditions.h b/src/nact/nact-iprofile-conditions.h
new file mode 100644
index 0000000..f748272
--- /dev/null
+++ b/src/nact/nact-iprofile-conditions.h
@@ -0,0 +1,72 @@
+/*
+ * 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_IPROFILE_CONDITIONS_H__
+#define __NACT_IPROFILE_CONDITIONS_H__
+
+/*
+ * NactIProfileConditions interface definition.
+ *
+ * This interface implements all the widgets which define the
+ * conditions for the action.
+ */
+
+#include <common/na-action.h>
+
+#include "nact-window.h"
+
+G_BEGIN_DECLS
+
+#define NACT_IPROFILE_CONDITIONS_TYPE						( nact_iprofile_conditions_get_type())
+#define NACT_IPROFILE_CONDITIONS( object )					( G_TYPE_CHECK_INSTANCE_CAST( object, NACT_IPROFILE_CONDITIONS_TYPE, NactIProfileConditions ))
+#define NACT_IS_IPROFILE_CONDITIONS( object )				( G_TYPE_CHECK_INSTANCE_TYPE( object, NACT_IPROFILE_CONDITIONS_TYPE ))
+#define NACT_IPROFILE_CONDITIONS_GET_INTERFACE( instance )	( G_TYPE_INSTANCE_GET_INTERFACE(( instance ), NACT_IPROFILE_CONDITIONS_TYPE, NactIProfileConditionsInterface ))
+
+typedef struct NactIProfileConditions NactIProfileConditions;
+
+typedef struct NactIProfileConditionsInterfacePrivate NactIProfileConditionsInterfacePrivate;
+
+typedef struct {
+	GTypeInterface                          parent;
+	NactIProfileConditionsInterfacePrivate *private;
+
+	/* api */
+}
+	NactIProfileConditionsInterface;
+
+GType nact_iprofile_conditions_get_type( void );
+
+void  nact_iprofile_conditions_initial_load( NactWindow *dialog, NAAction *action );
+void  nact_iprofile_conditions_runtime_init( NactWindow *dialog, NAAction *action );
+void  nact_iprofile_conditions_all_widgets_showed( NactWindow *dialog );
+
+G_END_DECLS
+
+#endif /* __NACT_IPROFILE_CONDITIONS_H__ */
diff --git a/src/nact/nact-main-window.c b/src/nact/nact-main-window.c
index 67c3aa6..5b74e70 100644
--- a/src/nact/nact-main-window.c
+++ b/src/nact/nact-main-window.c
@@ -43,9 +43,10 @@
 #include <common/na-ipivot-container.h>
 
 #include "nact-application.h"
-#include "nact-action-profile.h"
-#include "nact-main-window.h"
+#include "nact-action-conditions-editor.h"
+#include "nact-action-profiles-editor.h"
 #include "nact-iactions-list.h"
+#include "nact-main-window.h"
 
 /* private class data
  */
@@ -69,7 +70,8 @@ static void     instance_dispose( GObject *application );
 static void     instance_finalize( GObject *application );
 
 static gchar   *get_toplevel_name( BaseWindow *window );
-static void     on_init_widget( BaseWindow *window );
+static void     on_initial_load_toplevel( BaseWindow *window );
+static void     on_runtime_init_toplevel( BaseWindow *window );
 
 static void     on_actions_list_selection_changed( GtkTreeSelection *selection, gpointer user_data );
 static gboolean on_actions_list_double_click( GtkWidget *widget, GdkEventButton *event, gpointer data );
@@ -156,8 +158,9 @@ class_init( NactMainWindowClass *klass )
 	klass->private = g_new0( NactMainWindowClassPrivate, 1 );
 
 	BaseWindowClass *base_class = BASE_WINDOW_CLASS( klass );
-	base_class->on_init_widget = on_init_widget;
-	base_class->on_dialog_response = on_dialog_response;
+	base_class->initial_load_toplevel = on_initial_load_toplevel;
+	base_class->runtime_init_toplevel = on_runtime_init_toplevel;
+	base_class->dialog_response = on_dialog_response;
 	base_class->get_toplevel_name = get_toplevel_name;
 }
 
@@ -167,7 +170,8 @@ iactions_list_iface_init( NactIActionsListInterface *iface )
 	static const gchar *thisfn = "nact_main_window_iactions_list_iface_init";
 	g_debug( "%s: iface=%p", thisfn, iface );
 
-	iface->init_widget = NULL;
+	iface->initial_load_widget = NULL;
+	iface->runtime_init_widget = NULL;
 	iface->on_selection_changed = on_actions_list_selection_changed;
 	iface->on_double_click = on_actions_list_double_click;
 }
@@ -248,15 +252,27 @@ get_toplevel_name( BaseWindow *window )
 }
 
 static void
-on_init_widget( BaseWindow *window )
+on_initial_load_toplevel( BaseWindow *window )
+{
+	static const gchar *thisfn = "nact_main_window_on_initial_load_toplevel";
+	g_debug( "%s: window=%p", thisfn, window );
+
+	g_assert( NACT_IS_MAIN_WINDOW( window ));
+	/*NactMainWindow *wnd = NACT_MAIN_WINDOW( window );*/
+
+	nact_iactions_list_initial_load( NACT_WINDOW( window ));
+}
+
+static void
+on_runtime_init_toplevel( BaseWindow *window )
 {
-	static const gchar *thisfn = "nact_main_window_init_widget";
+	static const gchar *thisfn = "nact_main_window_on_runtime_init_toplevel";
 	g_debug( "%s: window=%p", thisfn, window );
 
 	g_assert( NACT_IS_MAIN_WINDOW( window ));
 	/*NactMainWindow *wnd = NACT_MAIN_WINDOW( window );*/
 
-	nact_iactions_list_init( NACT_WINDOW( window ));
+	nact_iactions_list_runtime_init( NACT_WINDOW( window ));
 
 	base_window_connect( window, "AboutButton", "clicked", G_CALLBACK( on_about_button_clicked ));
 	base_window_connect( window, "AddActionButton", "clicked", G_CALLBACK( on_add_button_clicked ));
@@ -379,10 +395,11 @@ on_add_button_clicked( GtkButton *button, gpointer user_data )
 	g_assert( NACT_IS_MAIN_WINDOW( user_data ));
 	NactWindow *wndmain = NACT_WINDOW( user_data );
 
+	nact_action_conditions_editor_run_editor( wndmain, NULL );
+
 	/* TODO: set the selection to the newly created action
 	 * or restore the previous selection
 	 */
-	nact_action_profile_run_editor( wndmain, NULL );
 }
 
 /*
@@ -402,39 +419,24 @@ on_edit_button_clicked( GtkButton *button, gpointer user_data )
 	static const gchar *thisfn = "nact_main_window_on_edit_button_clicked";
 	g_debug( "%s: button=%p, user_data=%p", thisfn, button, user_data );
 
-	/*GtkTreeSelection *selection;
-	GtkTreeIter iter;
-	GtkWidget *nact_actions_list;
-	GtkTreeModel* model;*/
-
-	/*NAAction *action = nact_iactions_list_get_selected_action( BASE_WINDOW( user_data ));*/
-
-	/*nact_actions_list = nact_get_glade_widget ("ActionsList");
-
-	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (nact_actions_list));
+	g_assert( NACT_IS_MAIN_WINDOW( user_data ));
+	NactWindow *wndmain = NACT_WINDOW( user_data );
 
-	if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
-		gchar *uuid;
-		NAAction *action;
+	NAAction *action = NA_ACTION( nact_iactions_list_get_selected_action( wndmain ));
 
-		gtk_tree_model_get (model, &iter, IACTIONS_LIST_UUID_COLUMN, &uuid, -1);
+	if( action ){
+		guint count = na_action_get_profiles_count( action );
 
-		action = NA_ACTION( na_pivot_get_action( st_pivot, uuid ));*/
+		if( count > 1 ){
+			nact_action_profiles_editor_run_editor( wndmain, action );
 
-		/*NautilusActionsConfigAction *action;
-		if( action ){
-			guint count = na_action_get_profiles_count( action );
-			if( count > 1 ){
-				if (nact_editor_edit_action (( NautilusActionsConfigAction *) action))
-					fill_actions_list (nact_actions_list);
-			} else {
-				if( nact_action_editor_edit( ( NautilusActionsConfigAction *) action ))
-					fill_actions_list( nact_actions_list );
-			}
-		}*/
+		} else {
+			nact_action_conditions_editor_run_editor( wndmain, action );
+		}
 
-		/*g_free (uuid);
-	}*/
+	} else {
+		g_assert_not_reached();
+	}
 }
 
 static void
@@ -443,44 +445,33 @@ on_duplicate_button_clicked( GtkButton *button, gpointer user_data )
 	static const gchar *thisfn = "nact_main_window_on_duplicate_button_clicked";
 	g_debug( "%s: button=%p, user_data=%p", thisfn, button, user_data );
 
-	/*GtkTreeSelection *selection;
-	GtkTreeIter iter;
-	GtkWidget *nact_actions_list;
-	GtkTreeModel* model;
-	gchar *error = NULL;
-	gchar *tmp, *label;
+	g_assert( NACT_IS_MAIN_WINDOW( user_data ));
+	NactWindow *wndmain = NACT_WINDOW( user_data );
 
-	nact_actions_list = nact_get_glade_widget ("ActionsList");
+	NAAction *action = NA_ACTION( nact_iactions_list_get_selected_action( wndmain ));
 
-	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (nact_actions_list));
+	if( action ){
+		NAAction *duplicate = na_action_duplicate( action );
+		na_action_set_new_uuid( duplicate );
 
-	if (gtk_tree_selection_get_selected (selection, &model, &iter))
-	{
-		gchar *uuid;
-		NAAction *action;
-		NAAction* new_action;
-
-		gtk_tree_model_get (model, &iter, IACTIONS_LIST_UUID_COLUMN, &uuid, -1);
-
-		action = NA_ACTION( na_pivot_get_action( st_pivot, uuid ));
-		new_action = na_action_duplicate( action );
-		na_action_set_new_uuid( new_action );*/
-
-		/*if( nautilus_actions_config_add_action( NAUTILUS_ACTIONS_CONFIG (config), new_action, &error )){*/
-		/*if( na_pivot_write_action( st_pivot, G_OBJECT( new_action ), &error )){
-			fill_actions_list (nact_actions_list);
-		} else {*/
-			/* i18n notes: will be displayed in a dialog */
-			/*label = na_action_get_label( action );
-			tmp = g_strdup_printf (_("Can't duplicate action '%s'!"), label);
-			nautilus_actions_display_error( tmp, error );
-			g_free( error );
+		gchar *msg = NULL;
+		NAPivot *pivot = NA_PIVOT( nact_window_get_pivot( wndmain ));
+		if( !na_pivot_write_action( pivot, G_OBJECT( duplicate ), &msg )){
+
+			BaseApplication *application;
+			g_object_get( G_OBJECT( wndmain ), PROP_WINDOW_APPLICATION_STR, &application, NULL );
+			g_assert( NACT_IS_APPLICATION( application ));
+			gchar *label = na_action_get_label( action );
+			gchar *first = g_strdup_printf( _( "Unable to duplicate \"%s\" action." ), label );
+			base_application_error_dlg( application, GTK_MESSAGE_ERROR, first, msg );
+			g_free( first );
 			g_free( label );
-			g_free( tmp );
+			g_free( msg );
 		}
 
-		g_free( uuid );
-	}*/
+	} else {
+		g_assert_not_reached();
+	}
 }
 
 static void
diff --git a/src/nact/nact-profile-conditions-editor.c b/src/nact/nact-profile-conditions-editor.c
new file mode 100644
index 0000000..a87611d
--- /dev/null
+++ b/src/nact/nact-profile-conditions-editor.c
@@ -0,0 +1,311 @@
+/*
+ * 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-action.h>
+
+#include "nact-application.h"
+#include "nact-profile-conditions-editor.h"
+#include "nact-iprofile-conditions.h"
+#include "nact-main-window.h"
+
+/* private class data
+ */
+struct NactProfileConditionsEditorClassPrivate {
+};
+
+/* private instance data
+ */
+struct NactProfileConditionsEditorPrivate {
+	gboolean  dispose_has_run;
+	NAAction *action;
+	gboolean  is_new;
+};
+
+static GObjectClass *st_parent_class = NULL;
+
+static GType  register_type( void );
+static void   class_init( NactProfileConditionsEditorClass *klass );
+static void   iprofile_conditions_iface_init( NactIProfileConditionsInterface *iface );
+static void   instance_init( GTypeInstance *instance, gpointer klass );
+static void   instance_dispose( GObject *dialog );
+static void   instance_finalize( GObject *dialog );
+
+static NactProfileConditionsEditor *profile_conditions_editor_new( BaseApplication *application );
+
+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   init_dialog_title( NactProfileConditionsEditor *dialog );
+static void   on_dialog_response( GtkDialog *dialog, gint code, BaseWindow *window );
+
+GType
+nact_profile_conditions_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_profile_conditions_editor_register_type";
+	g_debug( "%s", thisfn );
+
+	static GTypeInfo info = {
+		sizeof( NactProfileConditionsEditorClass ),
+		( GBaseInitFunc ) NULL,
+		( GBaseFinalizeFunc ) NULL,
+		( GClassInitFunc ) class_init,
+		NULL,
+		NULL,
+		sizeof( NactProfileConditionsEditor ),
+		0,
+		( GInstanceInitFunc ) instance_init
+	};
+
+	GType type = g_type_register_static( NACT_WINDOW_TYPE, "NactProfileConditionsEditor", &info, 0 );
+
+	/* implement IProfileConditions interface
+	 */
+	static const GInterfaceInfo iprofile_conditions_iface_info = {
+		( GInterfaceInitFunc ) iprofile_conditions_iface_init,
+		NULL,
+		NULL
+	};
+
+	g_type_add_interface_static( type, NACT_IPROFILE_CONDITIONS_TYPE, &iprofile_conditions_iface_info );
+
+	return( type );
+}
+
+static void
+class_init( NactProfileConditionsEditorClass *klass )
+{
+	static const gchar *thisfn = "nact_profile_conditions_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( NactProfileConditionsEditorClassPrivate, 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->dialog_response = on_dialog_response;
+	base_class->get_toplevel_name = do_get_dialog_name;
+}
+
+static void
+iprofile_conditions_iface_init( NactIProfileConditionsInterface *iface )
+{
+	static const gchar *thisfn = "nact_profile_conditions_editor_iprofile_conditions_iface_init";
+	g_debug( "%s: iface=%p", thisfn, iface );
+}
+
+static void
+instance_init( GTypeInstance *instance, gpointer klass )
+{
+	static const gchar *thisfn = "nact_profile_conditions_editor_instance_init";
+	g_debug( "%s: instance=%p, klass=%p", thisfn, instance, klass );
+
+	g_assert( NACT_IS_PROFILE_CONDITIONS_EDITOR( instance ));
+	NactProfileConditionsEditor *self = NACT_PROFILE_CONDITIONS_EDITOR( instance );
+
+	self->private = g_new0( NactProfileConditionsEditorPrivate, 1 );
+
+	self->private->dispose_has_run = FALSE;
+}
+
+static void
+instance_dispose( GObject *dialog )
+{
+	static const gchar *thisfn = "nact_profile_conditions_editor_instance_dispose";
+	g_debug( "%s: dialog=%p", thisfn, dialog );
+
+	g_assert( NACT_IS_PROFILE_CONDITIONS_EDITOR( dialog ));
+	NactProfileConditionsEditor *self = NACT_PROFILE_CONDITIONS_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_profile_conditions_editor_instance_finalize";
+	g_debug( "%s: dialog=%p", thisfn, dialog );
+
+	g_assert( NACT_IS_PROFILE_CONDITIONS_EDITOR( dialog ));
+	/*NactProfileConditionsEditor *self = ( NactProfileConditionsEditor * ) dialog;*/
+
+	/* chain call to parent class */
+	if( st_parent_class->finalize ){
+		G_OBJECT_CLASS( st_parent_class )->finalize( dialog );
+	}
+}
+
+/**
+ * Returns a newly allocated NactProfileConditionsEditor object.
+ *
+ * @parent: is the BaseWindow parent of this dialog (usually, the main
+ * toplevel window of the application).
+ */
+static NactProfileConditionsEditor *
+profile_conditions_editor_new( BaseApplication *application )
+{
+	return( g_object_new( NACT_PROFILE_CONDITIONS_EDITOR_TYPE, PROP_WINDOW_APPLICATION_STR, application, NULL ));
+}
+
+/**
+ * Initializes and runs the dialog.
+ *
+ * @parent: is the BaseWindow parent of this dialog (usually, the main
+ * toplevel window of the application).
+ *
+ * @user_data: a pointer to the NAAction to edit, or NULL. If NULL, a
+ * new NAAction is created.
+ *
+ * Returns TRUE if the NAAction has been edited and saved, or FALSE if
+ * there has been no modification at all.
+ */
+gboolean
+nact_profile_conditions_editor_run_editor( NactWindow *parent, gpointer user_data )
+{
+	g_assert( NACT_IS_MAIN_WINDOW( parent ));
+
+	BaseApplication *application = BASE_APPLICATION( base_window_get_application( BASE_WINDOW( parent )));
+	g_assert( NACT_IS_APPLICATION( application ));
+
+	NactProfileConditionsEditor *dialog = profile_conditions_editor_new( application );
+
+	g_assert( NA_IS_ACTION( user_data ) || !user_data );
+	NAAction *action = NA_ACTION( user_data );
+
+	if( !action ){
+		dialog->private->action = na_action_new( NULL );
+		dialog->private->is_new = TRUE;
+
+	} else {
+		dialog->private->action = na_action_duplicate( action );
+		dialog->private->is_new = FALSE;
+	}
+
+	base_window_run( BASE_WINDOW( dialog ));
+
+	g_object_unref( dialog->private->action );
+	return( TRUE );
+}
+
+static gchar *
+do_get_dialog_name( BaseWindow *dialog )
+{
+	/*g_debug( "nact_profile_conditions_editor_do_get_dialog_name" );*/
+	return( g_strdup( "EditActionDialogExt"));
+}
+
+static void
+on_initial_load_dialog( BaseWindow *dialog )
+{
+	static const gchar *thisfn = "nact_profile_conditions_editor_on_initial_load_dialog";
+	g_debug( "%s: dialog=%p", thisfn, dialog );
+
+	g_assert( NACT_IS_PROFILE_CONDITIONS_EDITOR( dialog ));
+	NactProfileConditionsEditor *window = NACT_PROFILE_CONDITIONS_EDITOR( dialog );
+
+	init_dialog_title( window );
+	nact_iprofile_conditions_initial_load( NACT_WINDOW( window ), window->private->action );
+}
+
+static void
+on_runtime_init_dialog( BaseWindow *dialog )
+{
+	static const gchar *thisfn = "nact_profile_conditions_editor_on_runtime_init_dialog";
+	g_debug( "%s: dialog=%p", thisfn, dialog );
+
+	g_assert( NACT_IS_PROFILE_CONDITIONS_EDITOR( dialog ));
+	NactProfileConditionsEditor *window = NACT_PROFILE_CONDITIONS_EDITOR( dialog );
+
+	init_dialog_title( window );
+	nact_iprofile_conditions_runtime_init( NACT_WINDOW( window ), window->private->action );
+}
+
+static void
+init_dialog_title( NactProfileConditionsEditor *dialog )
+{
+	GtkWindow *toplevel = base_window_get_toplevel_widget( BASE_WINDOW( dialog ));
+
+	if( dialog->private->is_new ){
+		gtk_window_set_title( toplevel, _( "Adding a new action" ));
+
+	} else {
+		gchar *label = na_action_get_label( dialog->private->action );
+		gchar* title = g_strdup_printf( _( "Editing \"%s\" action" ), label );
+		gtk_window_set_title( toplevel, title );
+		g_free( label );
+		g_free( title );
+	}
+}
+
+static void
+on_dialog_response( GtkDialog *dialog, gint code, BaseWindow *window )
+{
+	static const gchar *thisfn = "nact_profile_conditions_editor_on_dialog_response";
+	g_debug( "%s: dialog=%p, code=%d, window=%p", thisfn, dialog, code, window );
+
+	g_assert( NACT_IS_PROFILE_CONDITIONS_EDITOR( window ));
+
+	switch( code ){
+		case GTK_RESPONSE_NONE:
+		case GTK_RESPONSE_DELETE_EVENT:
+		case GTK_RESPONSE_CLOSE:
+			g_object_unref( window );
+			break;
+	}
+}
diff --git a/src/nact/nact-profile-conditions-editor.h b/src/nact/nact-profile-conditions-editor.h
new file mode 100644
index 0000000..a10d32c
--- /dev/null
+++ b/src/nact/nact-profile-conditions-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_PROFILE_CONDITIONS_EDITOR_H__
+#define __NACT_PROFILE_CONDITIONS_EDITOR_H__
+
+/*
+ * NactProfileConditionsEditor class definition.
+ *
+ * This class is derived from NactWindow.
+ * It encapsulates the "EditActionDialogExt" widget dialog.
+ */
+
+#include "nact-window.h"
+
+G_BEGIN_DECLS
+
+#define NACT_PROFILE_CONDITIONS_EDITOR_TYPE					( nact_profile_conditions_editor_get_type())
+#define NACT_PROFILE_CONDITIONS_EDITOR( object )			( G_TYPE_CHECK_INSTANCE_CAST( object, NACT_PROFILE_CONDITIONS_EDITOR_TYPE, NactProfileConditionsEditor ))
+#define NACT_PROFILE_CONDITIONS_EDITOR_CLASS( klass )		( G_TYPE_CHECK_CLASS_CAST( klass, NACT_PROFILE_CONDITIONS_EDITOR_TYPE, NactProfileConditionsEditorClass ))
+#define NACT_IS_PROFILE_CONDITIONS_EDITOR( object )			( G_TYPE_CHECK_INSTANCE_TYPE( object, NACT_PROFILE_CONDITIONS_EDITOR_TYPE ))
+#define NACT_IS_PROFILE_CONDITIONS_EDITOR_CLASS( klass )	( G_TYPE_CHECK_CLASS_TYPE(( klass ), NACT_PROFILE_CONDITIONS_EDITOR_TYPE ))
+#define NACT_PROFILE_CONDITIONS_EDITOR_GET_CLASS( object )	( G_TYPE_INSTANCE_GET_CLASS(( object ), NACT_PROFILE_CONDITIONS_EDITOR_TYPE, NactProfileConditionsEditorClass ))
+
+typedef struct NactProfileConditionsEditorPrivate NactProfileConditionsEditorPrivate;
+
+typedef struct {
+	NactWindow                          parent;
+	NactProfileConditionsEditorPrivate *private;
+}
+	NactProfileConditionsEditor;
+
+typedef struct NactProfileConditionsEditorClassPrivate NactProfileConditionsEditorClassPrivate;
+
+typedef struct {
+	NactWindowClass                          parent;
+	NactProfileConditionsEditorClassPrivate *private;
+}
+	NactProfileConditionsEditorClass;
+
+GType    nact_profile_conditions_editor_get_type( void );
+
+gboolean nact_profile_conditions_editor_run_editor( NactWindow *parent, gpointer user_data );
+
+G_END_DECLS
+
+#endif /* __NACT_PROFILE_CONDITIONS_EDITOR_H__ */
diff --git a/src/nact/nact-window.c b/src/nact/nact-window.c
index ad7986d..d99fe0d 100644
--- a/src/nact/nact-window.c
+++ b/src/nact/nact-window.c
@@ -48,8 +48,17 @@ struct NactWindowClassPrivate {
  */
 struct NactWindowPrivate {
 	gboolean dispose_has_run;
+	GSList  *signals;
 };
 
+/* connected signal, to be disconnected at NactWindow dispose
+ */
+typedef struct {
+	gpointer instance;
+	gulong   handler_id;
+}
+	NactWindowRecordedSignal;
+
 static GObjectClass *st_parent_class = NULL;
 
 static GType register_type( void );
@@ -120,6 +129,7 @@ instance_init( GTypeInstance *instance, gpointer klass )
 	self->private = g_new0( NactWindowPrivate, 1 );
 
 	self->private->dispose_has_run = FALSE;
+	self->private->signals = NULL;
 }
 
 static void
@@ -135,6 +145,15 @@ instance_dispose( GObject *window )
 
 		self->private->dispose_has_run = TRUE;
 
+		GSList *is;
+		for( is = self->private->signals ; is ; is = is->next ){
+			NactWindowRecordedSignal *str = ( NactWindowRecordedSignal * ) is->data;
+			g_signal_handler_disconnect( str->instance, str->handler_id );
+			g_debug( "%s: disconnecting signal handler %p:%lu", thisfn, str->instance, str->handler_id );
+			g_free( str );
+		}
+		g_slist_free( self->private->signals );
+
 		/* chain up to the parent class */
 		G_OBJECT_CLASS( st_parent_class )->dispose( window );
 	}
@@ -160,16 +179,56 @@ instance_finalize( GObject *window )
 /**
  * Returns a pointer to the list of actions.
  */
-GSList *
-nact_window_get_actions( NactWindow *window )
+GObject *
+nact_window_get_pivot( NactWindow *window )
 {
 	NactApplication *application;
 	g_object_get( G_OBJECT( window ), PROP_WINDOW_APPLICATION_STR, &application, NULL );
 	g_return_val_if_fail( NACT_IS_APPLICATION( application ), NULL );
 
-	NAPivot *pivot = NA_PIVOT( nact_application_get_pivot( application ));
+	GObject *pivot = nact_application_get_pivot( application );
+	g_return_val_if_fail( NA_IS_PIVOT( pivot ), NULL );
+
+	return( pivot );
+}
+
+/**
+ * Returns a pointer to the specified action.
+ */
+GObject *
+nact_window_get_action( NactWindow *window, const gchar *uuid )
+{
+	NAPivot *pivot = NA_PIVOT( nact_window_get_pivot( window ));
+	g_return_val_if_fail( NA_IS_PIVOT( pivot ), NULL );
+
+	GObject *action = na_pivot_get_action( pivot, uuid );
+	return( action );
+}
+
+/**
+ * Returns a pointer to the list of actions.
+ */
+GSList *
+nact_window_get_actions( NactWindow *window )
+{
+	NAPivot *pivot = NA_PIVOT( nact_window_get_pivot( window ));
 	g_return_val_if_fail( NA_IS_PIVOT( pivot ), NULL );
 
 	GSList *actions = na_pivot_get_actions( pivot );
 	return( actions );
 }
+
+/**
+ * Records a connected signal, to be disconnected at NactWindow dispose.
+ */
+void
+nact_window_on_signal_connected( NactWindow *window, gpointer instance, gulong handler_id )
+{
+	static const gchar *thisfn = "nact_window_on_signal_connected";
+	g_debug( "%s: window=%p, instance=%p, handler_id=%lu", thisfn, window, instance, handler_id );
+
+	NactWindowRecordedSignal *str = g_new0( NactWindowRecordedSignal, 1 );
+	str->instance = instance;
+	str->handler_id = handler_id;
+	window->private->signals = g_slist_prepend( window->private->signals, str );
+}
diff --git a/src/nact/nact-window.h b/src/nact/nact-window.h
index a3cd8f8..d6e3cb0 100644
--- a/src/nact/nact-window.h
+++ b/src/nact/nact-window.h
@@ -65,9 +65,15 @@ typedef struct {
 }
 	NactWindowClass;
 
-GType   nact_window_get_type( void );
+GType    nact_window_get_type( void );
 
-GSList *nact_window_get_actions( NactWindow *window );
+GObject *nact_window_get_pivot( NactWindow *window );
+
+GObject *nact_window_get_action( NactWindow *window, const gchar *uuid );
+
+GSList  *nact_window_get_actions( NactWindow *window );
+
+void     nact_window_on_signal_connected( NactWindow *window, gpointer instance, gulong handler_id );
 
 G_END_DECLS
 
diff --git a/src/nact/nautilus-actions-config.ui b/src/nact/nautilus-actions-config.ui
index 4e788aa..50cba4f 100644
--- a/src/nact/nautilus-actions-config.ui
+++ b/src/nact/nautilus-actions-config.ui
@@ -319,7 +319,9 @@
                         <property name="visible">True</property>
                         <property name="spacing">6</property>
                         <child>
-                          <object class="GtkImage" id="IconImage"/>
+                          <object class="GtkImage" id="IconImage">
+                            <property name="icon-size">1</property>
+                          </object>
                           <packing>
                             <property name="expand">False</property>
                             <property name="fill">False</property>
@@ -329,6 +331,7 @@
                         <child>
                           <object class="GtkComboBoxEntry" id="MenuIconComboBoxEntry">
                             <property name="visible">True</property>
+                            <property name="tooltip_text" translatable="yes">Icon of the menu item in the Nautilus popup menu.</property>
                             <child>
                               <object class="GtkCellRendererText" id="cellrenderertext1"/>
                               <attributes>
@@ -408,7 +411,6 @@
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
                         <property name="tooltip_text" translatable="yes">Label of the menu item in the Nautilus popup menu.</property>
-                        <signal name="changed" handler="action_field_changed_cb"/>
                       </object>
                       <packing>
                         <property name="left_attach">1</property>



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