[nautilus-actions] Define new src/nact/nact-match-list.{c,h} files



commit ecf0b5545ffc272a602cee7508a809ba2e9132c1
Author: Pierre Wieser <pwieser trychlos org>
Date:   Fri Jun 4 13:11:41 2010 +0200

    Define new src/nact/nact-match-list.{c,h} files

 ChangeLog                      |   14 +
 src/api/na-object-api.h        |    4 +-
 src/nact/Makefile.am           |    2 +
 src/nact/base-window.c         |   16 +
 src/nact/base-window.h         |    1 +
 src/nact/nact-ibasenames-tab.c |  713 ++---------------------------------
 src/nact/nact-ischemes-tab.c   |    3 +-
 src/nact/nact-match-list.c     |  812 ++++++++++++++++++++++++++++++++++++++++
 src/nact/nact-match-list.h     |   65 ++++
 9 files changed, 952 insertions(+), 678 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 52454b9..1f309c5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -6,6 +6,20 @@
 
 	* src/core/na-iabout.c: Update copyright notice.
 
+2010-06-04 Pierre Wieser <pwieser trychlos org>
+
+	* src/nact/nact-match-list.c:
+	* src/nact/nact-match-list.h: New files.
+
+	* src/nact/Makefile.am: Updated accordingly.
+
+	* src/nact/base-window.c:
+	* src/nact/base-window.h (base_window_signal_connect_with_data):
+	New function.
+
+	* src/nact/nact-ibasenames-tab.c: 
+	Take advantage of new nact_match_list_xxx functions.
+
 2010-06-03 Pierre Wieser <pwieser trychlos org>
 
 	* src/nact/nact-ibasenames-tab.c: Implement NactIBasenamesInterface interface.
diff --git a/src/api/na-object-api.h b/src/api/na-object-api.h
index 77e7891..7d95961 100644
--- a/src/api/na-object-api.h
+++ b/src/api/na-object-api.h
@@ -162,8 +162,6 @@ G_BEGIN_DECLS
 
 #define na_object_set_path( obj, path )					na_ifactory_object_set_from_void( NA_IFACTORY_OBJECT( obj ), NAFO_DATA_PATH, ( const void * )( path ))
 #define na_object_set_parameters( obj, parms )			na_ifactory_object_set_from_void( NA_IFACTORY_OBJECT( obj ), NAFO_DATA_PARAMETERS, ( const void * )( parms ))
-#define na_object_set_basenames( obj, bnames )			na_ifactory_object_set_from_void( NA_IFACTORY_OBJECT( obj ), NAFO_DATA_BASENAMES, ( const void * )( bnames ))
-#define na_object_set_matchcase( obj, match )			na_ifactory_object_set_from_void( NA_IFACTORY_OBJECT( obj ), NAFO_DATA_MATCHCASE, ( const void * ) GUINT_TO_POINTER( match ))
 #define na_object_set_isfile( obj, isfile )				na_ifactory_object_set_from_void( NA_IFACTORY_OBJECT( obj ), NAFO_DATA_ISFILE, ( const void * ) GUINT_TO_POINTER( isfile ))
 #define na_object_set_isdir( obj, isdir )				na_ifactory_object_set_from_void( NA_IFACTORY_OBJECT( obj ), NAFO_DATA_ISDIR, ( const void * ) GUINT_TO_POINTER( isdir ))
 #define na_object_set_multiple( obj, multiple )			na_ifactory_object_set_from_void( NA_IFACTORY_OBJECT( obj ), NAFO_DATA_MULTIPLE, ( const void * ) GUINT_TO_POINTER( multiple ))
@@ -189,6 +187,8 @@ G_BEGIN_DECLS
 
 #define na_object_set_mimetypes( obj, types )			na_ifactory_object_set_from_void( NA_IFACTORY_OBJECT( obj ), NAFO_DATA_MIMETYPES, ( const void * )( types ))
 #define na_object_set_all_mimetypes( obj, all )			na_ifactory_object_set_from_void( NA_IFACTORY_OBJECT( obj ), NAFO_DATA_ALL_MIMETYPES, ( const void * ) GUINT_TO_POINTER( all ))
+#define na_object_set_basenames( obj, bnames )			na_ifactory_object_set_from_void( NA_IFACTORY_OBJECT( obj ), NAFO_DATA_BASENAMES, ( const void * )( bnames ))
+#define na_object_set_matchcase( obj, match )			na_ifactory_object_set_from_void( NA_IFACTORY_OBJECT( obj ), NAFO_DATA_MATCHCASE, ( const void * ) GUINT_TO_POINTER( match ))
 #define na_object_set_scheme( obj, scheme, add )		na_icontext_set_scheme( NA_ICONTEXT( obj ), ( const gchar * )( scheme ), ( add ))
 #define na_object_replace_folder( obj, old, new )		na_icontext_replace_folder( NA_ICONTEXT( obj ), ( const gchar * )( old ), ( const gchar * )( new ))
 
diff --git a/src/nact/Makefile.am b/src/nact/Makefile.am
index d83db20..d7f90ad 100644
--- a/src/nact/Makefile.am
+++ b/src/nact/Makefile.am
@@ -136,6 +136,8 @@ nautilus_actions_config_tool_SOURCES = \
 	nact-main-toolbar.h									\
 	nact-main-window.c									\
 	nact-main-window.h									\
+	nact-match-list.c									\
+	nact-match-list.h									\
 	nact-preferences-editor.c							\
 	nact-preferences-editor.h							\
 	nact-providers-list.c								\
diff --git a/src/nact/base-window.c b/src/nact/base-window.c
index 1f0c673..27d221c 100644
--- a/src/nact/base-window.c
+++ b/src/nact/base-window.c
@@ -1372,6 +1372,22 @@ base_window_signal_connect_by_name( BaseWindow *window, const gchar *name, const
 	return( handler_id );
 }
 
+gulong
+base_window_signal_connect_with_data( BaseWindow *window, GObject *instance, const gchar *signal, GCallback fn, void *user_data )
+{
+	gulong handler_id = 0;
+
+	g_return_val_if_fail( BASE_IS_WINDOW( window ), ( gulong ) 0 );
+
+	if( !window->private->dispose_has_run ){
+
+		handler_id = g_signal_connect( instance, signal, fn, user_data );
+		record_connected_signal( window, instance, handler_id );
+	}
+
+	return( handler_id );
+}
+
 static void
 record_connected_signal( BaseWindow *window, GObject *instance, gulong handler_id )
 {
diff --git a/src/nact/base-window.h b/src/nact/base-window.h
index 8a8805a..b5f1204 100644
--- a/src/nact/base-window.h
+++ b/src/nact/base-window.h
@@ -90,6 +90,7 @@ gboolean         base_window_yesno_dlg( const BaseWindow *window, GtkMessageType
 gulong           base_window_signal_connect( BaseWindow *window, GObject *instance, const gchar *signal, GCallback fn );
 gulong           base_window_signal_connect_after( BaseWindow *window, GObject *instance, const gchar *signal, GCallback fn );
 gulong           base_window_signal_connect_by_name( BaseWindow *window, const gchar *name, const gchar *signal, GCallback fn );
+gulong           base_window_signal_connect_with_data( BaseWindow *window, GObject *instance, const gchar *signal, GCallback fn, void *user_data );
 
 G_END_DECLS
 
diff --git a/src/nact/nact-ibasenames-tab.c b/src/nact/nact-ibasenames-tab.c
index 200644d..4c2b4b7 100644
--- a/src/nact/nact-ibasenames-tab.c
+++ b/src/nact/nact-ibasenames-tab.c
@@ -32,14 +32,12 @@
 #include <config.h>
 #endif
 
-#include <gdk/gdkkeysyms.h>
 #include <glib/gi18n.h>
 
 #include <api/na-object-api.h>
-#include <api/na-core-utils.h>
 
-#include "nact-gtk-utils.h"
 #include "nact-main-tab.h"
+#include "nact-match-list.h"
 #include "nact-ibasenames-tab.h"
 
 /* private interface data
@@ -48,47 +46,20 @@ struct NactIBasenamesTabInterfacePrivate {
 	void *empty;						/* so that gcc -pedantic is happy */
 };
 
-/* column ordering
- */
-enum {
-	BASENAMES_ITEM_COLUMN = 0,
-	BASENAMES_MUST_MATCH_COLUMN,
-	BASENAMES_MUST_NOT_MATCH_COLUMN,
-	BASENAMES_N_COLUMN
-};
-
-#define BASENAMES_LIST_VIEW				"nact-ibasenames-list-view"
-#define BASENAMES_LIST_EDITABLE			"nact-ibasenames-list-editable"
-#define BASENAMES_LIST_SORT_HEADER		"nact-ibasenames-list-sort-header"
-#define BASENAMES_LIST_SORT_ORDER		"nact-ibasenames-list-sort-order"
+#define ITAB_NAME						"basenames"
 
 static gboolean st_initialized = FALSE;
 static gboolean st_finalized = FALSE;
-static gboolean st_on_selection_change = FALSE;
 
 static GType    register_type( void );
 static void     interface_base_init( NactIBasenamesTabInterface *klass );
 static void     interface_base_finalize( NactIBasenamesTabInterface *klass );
 
-static void     on_add_filter_clicked( GtkButton *button, BaseWindow *window );
-static void     on_filter_clicked( GtkTreeViewColumn *treeviewcolumn, BaseWindow *window );
-static void     on_filter_edited( GtkCellRendererText *renderer, const gchar *path, const gchar *text, BaseWindow *window );
-static gboolean on_key_pressed_event( GtkWidget *widget, GdkEventKey *event, BaseWindow *window );
-static void     on_must_match_clicked( GtkTreeViewColumn *treeviewcolumn, BaseWindow *window );
-static void     on_must_match_toggled( GtkCellRendererToggle *cell_renderer, gchar *path, BaseWindow *window );
-static void     on_must_not_match_clicked( GtkTreeViewColumn *treeviewcolumn, BaseWindow *window );
-static void     on_must_not_match_toggled( GtkCellRendererToggle *cell_renderer, gchar *path, BaseWindow *window );
-static void     on_remove_filter_clicked( GtkButton *button, BaseWindow *window );
-static void     on_selection_changed( GtkTreeSelection *selection, BaseWindow *window );
-static void     on_tab_updatable_selection_changed( NactIBasenamesTab *instance, gint count_selected );
-static void     on_tab_updatable_enable_tab( NactIBasenamesTab *instance, NAObjectItem *item );
-
-static void     delete_current_row( BaseWindow *window );
-static void     edit_inline( BaseWindow *window );
-static void     insert_new_row( BaseWindow *window );
-static void     iter_for_setup( gchar *filter, GtkTreeModel *model );
-static void     sort_on_column( GtkTreeViewColumn *treeviewcolumn, BaseWindow *window, guint colid );
-static gboolean tab_set_sensitive( NactIBasenamesTab *instance );
+static void     on_tab_updatable_selection_changed( BaseWindow *window, gint count_selected );
+static void     on_tab_updatable_enable_tab( BaseWindow *window, NAObjectItem *item );
+
+static GSList  *get_basenames( void *context );
+static void     set_basenames( void *context, GSList *filters );
 
 GType
 nact_ibasenames_tab_get_type( void )
@@ -169,56 +140,26 @@ void
 nact_ibasenames_tab_initial_load_toplevel( NactIBasenamesTab *instance )
 {
 	static const gchar *thisfn = "nact_ibasenames_tab_initial_load_toplevel";
-	GtkListStore *model;
-	GtkTreeView *listview;
-	GtkCellRenderer *text_cell, *radio_cell;
-	GtkTreeViewColumn *column;
-	GtkTreeSelection *selection;
+	GtkWidget *list, *add, *remove;
 
-	g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
 	g_return_if_fail( NACT_IS_IBASENAMES_TAB( instance ));
 
 	if( st_initialized && !st_finalized ){
 
-		model = gtk_list_store_new( BASENAMES_N_COLUMN, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN );
-		listview = GTK_TREE_VIEW( base_window_get_widget( BASE_WINDOW( instance ), "BasenamesTreeView" ));
-		gtk_tree_view_set_model( listview, GTK_TREE_MODEL( model ));
-		g_object_unref( model );
-
-		text_cell = gtk_cell_renderer_text_new();
-		column = gtk_tree_view_column_new_with_attributes(
-				_( "Basename filter" ),
-				text_cell,
-				"text", BASENAMES_ITEM_COLUMN,
-				NULL );
-		gtk_tree_view_append_column( listview, column );
-
-		radio_cell = gtk_cell_renderer_toggle_new();
-		gtk_cell_renderer_toggle_set_radio( GTK_CELL_RENDERER_TOGGLE( radio_cell ), TRUE );
-		column = gtk_tree_view_column_new_with_attributes(
-				_( "Must match one" ),
-				radio_cell,
-				"active", BASENAMES_MUST_MATCH_COLUMN,
-				NULL );
-		gtk_tree_view_append_column( listview, column );
-
-		radio_cell = gtk_cell_renderer_toggle_new();
-		gtk_cell_renderer_toggle_set_radio( GTK_CELL_RENDERER_TOGGLE( radio_cell ), TRUE );
-		column = gtk_tree_view_column_new_with_attributes(
-				_( "Must not match any" ),
-				radio_cell,
-				"active", BASENAMES_MUST_NOT_MATCH_COLUMN,
-				NULL );
-		gtk_tree_view_append_column( listview, column );
-
-		column = gtk_tree_view_column_new();
-		gtk_tree_view_append_column( listview, column );
-
-		gtk_tree_view_set_headers_visible( listview, TRUE );
-		gtk_tree_view_set_headers_clickable( listview, TRUE );
-
-		selection = gtk_tree_view_get_selection( listview );
-		gtk_tree_selection_set_mode( selection, GTK_SELECTION_BROWSE );
+		g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
+
+		list = base_window_get_widget( BASE_WINDOW( instance ), "BasenamesTreeView" );
+		add = base_window_get_widget( BASE_WINDOW( instance ), "AddBasenameButton" );
+		remove = base_window_get_widget( BASE_WINDOW( instance ), "RemoveBasenameButton" );
+
+		nact_match_list_create_model(
+				BASE_WINDOW( instance ),
+				ITAB_NAME,
+				TAB_BASENAMES,
+				list, add, remove,
+				( pget_filters ) get_basenames,
+				( pset_filters ) set_basenames,
+				_( "Basename filter" ));
 	}
 }
 
@@ -233,17 +174,13 @@ void
 nact_ibasenames_tab_runtime_init_toplevel( NactIBasenamesTab *instance )
 {
 	static const gchar *thisfn = "nact_ibasenames_tab_runtime_init_toplevel";
-	GtkTreeView *listview;
-	GtkTreeViewColumn *column;
-	GList *renderers;
-	GtkWidget *add_button, *remove_button;
-	GtkTreeModel *model;
 
-	g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
 	g_return_if_fail( NACT_IS_IBASENAMES_TAB( instance ));
 
 	if( st_initialized && !st_finalized ){
 
+		g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
+
 		base_window_signal_connect(
 				BASE_WINDOW( instance ),
 				G_OBJECT( instance ),
@@ -256,82 +193,7 @@ nact_ibasenames_tab_runtime_init_toplevel( NactIBasenamesTab *instance )
 				TAB_UPDATABLE_SIGNAL_ENABLE_TAB,
 				G_CALLBACK( on_tab_updatable_enable_tab ));
 
-		listview = GTK_TREE_VIEW( base_window_get_widget( BASE_WINDOW( instance ), "BasenamesTreeview" ));
-		column = gtk_tree_view_get_column( listview, BASENAMES_ITEM_COLUMN );
-		base_window_signal_connect(
-				BASE_WINDOW( instance ),
-				G_OBJECT( column ),
-				"clicked",
-				G_CALLBACK( on_filter_clicked ));
-
-		renderers = gtk_cell_layout_get_cells( GTK_CELL_LAYOUT( column ));
-		base_window_signal_connect(
-				BASE_WINDOW( instance ),
-				G_OBJECT( renderers->data ),
-				"edited",
-				G_CALLBACK( on_filter_edited ));
-
-		column = gtk_tree_view_get_column( listview, BASENAMES_MUST_MATCH_COLUMN );
-		base_window_signal_connect(
-				BASE_WINDOW( instance ),
-				G_OBJECT( column ),
-				"clicked",
-				G_CALLBACK( on_must_match_clicked ));
-
-		renderers = gtk_cell_layout_get_cells( GTK_CELL_LAYOUT( column ));
-		base_window_signal_connect(
-				BASE_WINDOW( instance ),
-				G_OBJECT( renderers->data ),
-				"toggled",
-				G_CALLBACK( on_must_match_toggled ));
-
-		column = gtk_tree_view_get_column( listview, BASENAMES_MUST_NOT_MATCH_COLUMN );
-		base_window_signal_connect(
-				BASE_WINDOW( instance ),
-				G_OBJECT( column ),
-				"clicked",
-				G_CALLBACK( on_must_not_match_clicked ));
-
-		renderers = gtk_cell_layout_get_cells( GTK_CELL_LAYOUT( column ));
-		base_window_signal_connect(
-				BASE_WINDOW( instance ),
-				G_OBJECT( renderers->data ),
-				"toggled",
-				G_CALLBACK( on_must_not_match_toggled ));
-
-		add_button = base_window_get_widget( BASE_WINDOW( instance ), "AddBasenameButton");
-		base_window_signal_connect(
-				BASE_WINDOW( instance ),
-				G_OBJECT( add_button ),
-				"clicked",
-				G_CALLBACK( on_add_filter_clicked ));
-
-		remove_button = base_window_get_widget( BASE_WINDOW( instance ), "RemoveBasenameButton");
-		base_window_signal_connect(
-				BASE_WINDOW( instance ),
-				G_OBJECT( remove_button ),
-				"clicked",
-				G_CALLBACK( on_remove_filter_clicked ));
-
-		base_window_signal_connect(
-				BASE_WINDOW( instance ),
-				G_OBJECT( gtk_tree_view_get_selection( listview )),
-				"changed",
-				G_CALLBACK( on_selection_changed ));
-
-		base_window_signal_connect(
-				BASE_WINDOW( instance ),
-				G_OBJECT( listview ),
-				"key-press-event",
-				G_CALLBACK( on_key_pressed_event ));
-
-		g_object_set_data( G_OBJECT( instance ), BASENAMES_LIST_VIEW, listview );
-
-		model = gtk_tree_view_get_model( listview );
-		gtk_tree_sortable_set_sort_column_id( GTK_TREE_SORTABLE( model ), BASENAMES_ITEM_COLUMN, GTK_SORT_ASCENDING );
-
-		g_object_set_data( G_OBJECT( listview ), BASENAMES_LIST_SORT_HEADER, GUINT_TO_POINTER( BASENAMES_ITEM_COLUMN ));
-		g_object_set_data( G_OBJECT( listview ), BASENAMES_LIST_SORT_ORDER, GUINT_TO_POINTER( GTK_SORT_ASCENDING ));
+		nact_match_list_init_view( BASE_WINDOW( instance ), ITAB_NAME );
 	}
 }
 
@@ -340,10 +202,11 @@ nact_ibasenames_tab_all_widgets_showed( NactIBasenamesTab *instance )
 {
 	static const gchar *thisfn = "nact_ibasenames_tab_all_widgets_showed";
 
-	g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
 	g_return_if_fail( NACT_IS_IBASENAMES_TAB( instance ));
 
 	if( st_initialized && !st_finalized ){
+
+		g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
 	}
 }
 
@@ -358,536 +221,36 @@ nact_ibasenames_tab_dispose( NactIBasenamesTab *instance )
 {
 	static const gchar *thisfn = "nact_ibasenames_tab_dispose";
 
-	g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
 	g_return_if_fail( NACT_IS_IBASENAMES_TAB( instance ));
 
 	if( st_initialized && !st_finalized ){
-	}
-}
 
-static void
-on_add_filter_clicked( GtkButton *button, BaseWindow *window )
-{
-	insert_new_row( window );
-}
+		g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
 
-static void
-on_filter_clicked( GtkTreeViewColumn *treeviewcolumn, BaseWindow *window )
-{
-	sort_on_column( treeviewcolumn, window, BASENAMES_ITEM_COLUMN );
-}
-
-static void
-on_filter_edited( GtkCellRendererText *renderer, const gchar *path_str, const gchar *text, BaseWindow *window )
-{
-	GtkTreeView *listview;
-	GtkTreeModel *model;
-	GtkTreeIter iter;
-	GtkTreePath *path;
-	gchar *old_text;
-	NAObjectItem *item;
-	NAObjectProfile *profile;
-	NAIContext *context;
-	gboolean must_match, must_not_match;
-	gchar *to_add, *to_remove;
-	GSList *basenames;
-
-	listview = GTK_TREE_VIEW( g_object_get_data( G_OBJECT( window ), BASENAMES_LIST_VIEW ));
-	model = gtk_tree_view_get_model( listview );
-	path = gtk_tree_path_new_from_string( path_str );
-	gtk_tree_model_get_iter( model, &iter, path );
-	gtk_tree_path_free( path );
-
-	gtk_tree_model_get( model, &iter,
-			BASENAMES_ITEM_COLUMN, &old_text,
-			BASENAMES_MUST_MATCH_COLUMN, &must_match,
-			BASENAMES_MUST_NOT_MATCH_COLUMN, &must_not_match,
-			-1 );
-
-	gtk_list_store_set( GTK_LIST_STORE( model ), &iter, BASENAMES_ITEM_COLUMN, text, -1 );
-
-	g_object_get(
-			G_OBJECT( window ),
-			TAB_UPDATABLE_PROP_EDITED_ACTION, &item,
-			TAB_UPDATABLE_PROP_EDITED_PROFILE, &profile,
-			NULL );
-
-	context = ( profile ? NA_ICONTEXT( profile ) : ( NAIContext * ) item );
-
-	if( context ){
-		basenames = na_object_get_basenames( context );
-
-		if( basenames ){
-			to_remove = g_strdup( old_text );
-			basenames = na_core_utils_slist_remove_ascii( basenames, to_remove );
-			g_free( to_remove );
-			to_remove = g_strdup_printf( "!%s", old_text );
-			basenames = na_core_utils_slist_remove_ascii( basenames, to_remove );
-			g_free( to_remove );
-		}
-
-		if( must_match ){
-			basenames = g_slist_prepend( basenames, g_strdup( text ));
-
-		} else if( must_not_match ){
-			to_add = g_strdup_printf( "!%s", text );
-			basenames = g_slist_prepend( basenames, to_add );
-		}
-
-		na_object_set_basenames( context, basenames );
-		na_core_utils_slist_free( basenames );
-		g_signal_emit_by_name( G_OBJECT( window ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, context, FALSE );
+		nact_match_list_dispose( BASE_WINDOW( instance ), ITAB_NAME );
 	}
-
-	g_free( old_text );
 }
 
-static gboolean
-on_key_pressed_event( GtkWidget *widget, GdkEventKey *event, BaseWindow *window )
-{
-	gboolean stop;
-
-	stop = FALSE;
-
-	if( event->keyval == GDK_F2 ){
-		edit_inline( window );
-		stop = TRUE;
-	}
-
-	if( event->keyval == GDK_Insert || event->keyval == GDK_KP_Insert ){
-		insert_new_row( window );
-		stop = TRUE;
-	}
-
-	if( event->keyval == GDK_Delete || event->keyval == GDK_KP_Delete ){
-		delete_current_row( window );
-		stop = TRUE;
-	}
-
-	return( stop );
-}
-
-static void
-on_must_match_clicked( GtkTreeViewColumn *treeviewcolumn, BaseWindow *window )
-{
-	sort_on_column( treeviewcolumn, window, BASENAMES_MUST_MATCH_COLUMN );
-}
-
-/*
- * clicking on an already active toggle button has no effect
- * clicking on an inactive toggle button has a double effect:
- * - the other toggle button becomes inactive
- * - this toggle button becomes active
- * the corresponding strings must be respectively removed/added to the
- * filters list
- */
 static void
-on_must_match_toggled( GtkCellRendererToggle *cell_renderer, gchar *path_str, BaseWindow *window )
+on_tab_updatable_selection_changed( BaseWindow *window, gint count_selected )
 {
-	/*static const gchar *thisfn = "nact_ibasenames_tab_on_must_match_toggled";*/
-	GtkTreeView *listview;
-	GtkTreeModel *model;
-	GtkTreePath *path;
-	GtkTreeIter iter;
-	gchar *filter;
-	NAObjectItem *item;
-	NAObjectProfile *profile;
-	NAIContext *context;
-	GSList *basenames;
-	gchar *to_remove;
-
-	/*gboolean is_active = gtk_cell_renderer_toggle_get_active( cell_renderer );
-	g_debug( "%s: is_active=%s", thisfn, is_active ? "True":"False" );*/
-
-	if( !gtk_cell_renderer_toggle_get_active( cell_renderer )){
-		listview = GTK_TREE_VIEW( g_object_get_data( G_OBJECT( window ), BASENAMES_LIST_VIEW ));
-		model = gtk_tree_view_get_model( listview );
-		path = gtk_tree_path_new_from_string( path_str );
-		gtk_tree_model_get_iter( model, &iter, path );
-		gtk_tree_path_free( path );
-
-		gtk_tree_model_get( model, &iter, BASENAMES_ITEM_COLUMN, &filter, -1 );
-		gtk_list_store_set( GTK_LIST_STORE( model ), &iter, BASENAMES_MUST_MATCH_COLUMN, TRUE, BASENAMES_MUST_NOT_MATCH_COLUMN, FALSE, -1 );
-
-		g_object_get(
-				G_OBJECT( window ),
-				TAB_UPDATABLE_PROP_EDITED_ACTION, &item,
-				TAB_UPDATABLE_PROP_EDITED_PROFILE, &profile,
-				NULL );
-
-		context = ( profile ? NA_ICONTEXT( profile ) : ( NAIContext * ) item );
-
-		if( context ){
-			basenames = na_object_get_basenames( context );
-			if( basenames ){
-				to_remove = g_strdup_printf( "!%s", filter );
-				basenames = na_core_utils_slist_remove_ascii( basenames, to_remove );
-				g_free( to_remove );
-			}
-			basenames = g_slist_prepend( basenames, filter );
-			na_object_set_basenames( context, basenames );
-			na_core_utils_slist_free( basenames );
-			g_signal_emit_by_name( G_OBJECT( window ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, context, FALSE );
-		}
-	}
+	nact_match_list_on_selection_changed( window, ITAB_NAME, count_selected );
 }
 
 static void
-on_must_not_match_clicked( GtkTreeViewColumn *treeviewcolumn, BaseWindow *window )
+on_tab_updatable_enable_tab( BaseWindow *window, NAObjectItem *item )
 {
-	sort_on_column( treeviewcolumn, window, BASENAMES_MUST_MATCH_COLUMN );
+	nact_match_list_on_enable_tab( window, ITAB_NAME, item );
 }
 
-static void
-on_must_not_match_toggled( GtkCellRendererToggle *cell_renderer, gchar *path_str, BaseWindow *window )
+static GSList *
+get_basenames( void *context )
 {
-	/*static const gchar *thisfn = "nact_ibasenames_tab_on_must_not_match_toggled";*/
-	GtkTreeView *listview;
-	GtkTreeModel *model;
-	GtkTreePath *path;
-	GtkTreeIter iter;
-	gchar *filter;
-	NAObjectItem *item;
-	NAObjectProfile *profile;
-	NAIContext *context;
-	GSList *basenames;
-	gchar *to_add;
-
-	/*gboolean is_active = gtk_cell_renderer_toggle_get_active( cell_renderer );
-	g_debug( "%s: is_active=%s", thisfn, is_active ? "True":"False" );*/
-
-	if( !gtk_cell_renderer_toggle_get_active( cell_renderer )){
-		listview = GTK_TREE_VIEW( g_object_get_data( G_OBJECT( window ), BASENAMES_LIST_VIEW ));
-		model = gtk_tree_view_get_model( listview );
-		path = gtk_tree_path_new_from_string( path_str );
-		gtk_tree_model_get_iter( model, &iter, path );
-		gtk_tree_path_free( path );
-
-		gtk_tree_model_get( model, &iter, BASENAMES_ITEM_COLUMN, &filter, -1 );
-		gtk_list_store_set( GTK_LIST_STORE( model ), &iter, BASENAMES_MUST_MATCH_COLUMN, FALSE, BASENAMES_MUST_NOT_MATCH_COLUMN, TRUE, -1 );
-
-		g_object_get(
-				G_OBJECT( window ),
-				TAB_UPDATABLE_PROP_EDITED_ACTION, &item,
-				TAB_UPDATABLE_PROP_EDITED_PROFILE, &profile,
-				NULL );
-
-		context = ( profile ? NA_ICONTEXT( profile ) : ( NAIContext * ) item );
-
-		if( context ){
-			basenames = na_object_get_basenames( context );
-			if( basenames ){
-				basenames = na_core_utils_slist_remove_ascii( basenames, filter );
-			}
-			to_add = g_strdup_printf( "!%s", filter );
-			basenames = g_slist_prepend( basenames, to_add );
-			na_object_set_basenames( context, basenames );
-			na_core_utils_slist_free( basenames );
-			g_signal_emit_by_name( G_OBJECT( window ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, context, FALSE );
-		}
-
-		g_free( filter );
-	}
+	return( na_object_get_basenames( context ));
 }
 
 static void
-on_remove_filter_clicked( GtkButton *button, BaseWindow *window )
+set_basenames( void *context, GSList *filters )
 {
-	delete_current_row( window );
-}
-
-static void
-on_selection_changed( GtkTreeSelection *selection, BaseWindow *window )
-{
-	GtkTreeView *listview;
-	gboolean editable;
-	GtkButton *button;
-
-	listview = GTK_TREE_VIEW( g_object_get_data( G_OBJECT( window ), BASENAMES_LIST_VIEW ));
-	editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( listview ), BASENAMES_LIST_EDITABLE ));
-	button = GTK_BUTTON( base_window_get_widget( BASE_WINDOW( window ), "RemoveBasenameButton"));
-	gtk_widget_set_sensitive( GTK_WIDGET( button ), editable && gtk_tree_selection_count_selected_rows( selection ) > 0);
-}
-
-/*
- * basically we are using here a rather common scheme:
- * - object has a GSList of strings, each of one being a basename description,
- *   which may be negated
- * - the list is displayed in a listview with radio toggle buttons
- *   so that a user cannot have both positive and negative assertions
- *   for the same basename filter
- * - update the object with a summary of the listbox contents
- */
-static void
-on_tab_updatable_selection_changed( NactIBasenamesTab *instance, gint count_selected )
-{
-	static const gchar *thisfn = "nact_ibasenames_tab_on_tab_updatable_selection_changed";
-	NAObjectItem *item;
-	NAObjectProfile *profile;
-	NAIContext *context;
-	GSList *basenames;
-	gboolean editable;
-	GtkTreeView *listview;
-	GtkTreeModel *model;
-	GtkTreeSelection *selection;
-	GtkTreeViewColumn *column;
-	GtkWidget *button;
-	GtkTreePath *path;
-
-	g_return_if_fail( NACT_IS_IBASENAMES_TAB( instance ));
-
-	if( st_initialized && !st_finalized ){
-
-		g_debug( "%s: instance=%p, count_selected=%d", thisfn, ( void * ) instance, count_selected );
-
-		g_object_get(
-				G_OBJECT( instance ),
-				TAB_UPDATABLE_PROP_EDITED_ACTION, &item,
-				TAB_UPDATABLE_PROP_EDITED_PROFILE, &profile,
-				TAB_UPDATABLE_PROP_EDITABLE, &editable,
-				NULL );
-
-		context = ( profile ? NA_ICONTEXT( profile ) : ( NAIContext * ) item );
-		basenames = na_object_get_basenames( context );
-
-		st_on_selection_change = TRUE;
-
-		listview = GTK_TREE_VIEW( base_window_get_widget( BASE_WINDOW( instance ), "BasenamesTreeview" ));
-		model = gtk_tree_view_get_model( listview );
-		selection = gtk_tree_view_get_selection( listview );
-		gtk_tree_selection_unselect_all( selection );
-		gtk_list_store_clear( GTK_LIST_STORE( model ));
-
-		if( basenames ){
-			g_slist_foreach( basenames, ( GFunc ) iter_for_setup, model );
-		}
-
-		g_object_set_data( G_OBJECT( listview ), BASENAMES_LIST_EDITABLE, GUINT_TO_POINTER(( guint ) editable ));
-
-		column = gtk_tree_view_get_column( listview, BASENAMES_ITEM_COLUMN );
-		nact_gtk_utils_set_editable( GTK_OBJECT( column ), editable );
-
-		button = base_window_get_widget( BASE_WINDOW( instance ), "AddBasenameButton");
-		nact_gtk_utils_set_editable( GTK_OBJECT( button ), editable );
-
-		button = base_window_get_widget( BASE_WINDOW( instance ), "RemoveBasenameButton");
-		nact_gtk_utils_set_editable( GTK_OBJECT( button ), editable );
-
-		st_on_selection_change = FALSE;
-
-		path = gtk_tree_path_new_first();
-		if( path ){
-			selection = gtk_tree_view_get_selection( listview );
-			gtk_tree_selection_select_path( selection, path );
-			gtk_tree_path_free( path );
-		}
-	}
-}
-
-static void
-on_tab_updatable_enable_tab( NactIBasenamesTab *instance, NAObjectItem *item )
-{
-	static const gchar *thisfn = "nact_ibasenames_tab_on_tab_updatable_enable_tab";
-
-	if( st_initialized && !st_finalized ){
-
-		g_debug( "%s: instance=%p, item=%p", thisfn, ( void * ) instance, ( void * ) item );
-		g_return_if_fail( NACT_IS_IBASENAMES_TAB( instance ));
-
-		tab_set_sensitive( instance );
-	}
-}
-
-static void
-delete_current_row( BaseWindow *window )
-{
-	GtkTreeView *listview;
-	GtkTreeSelection *selection;
-	GtkTreeModel *model;
-	GList *rows;
-	GtkTreePath *path;
-	GtkTreeIter iter;
-	gchar *filter;
-	NAObjectItem *item;
-	NAObjectProfile *profile;
-	NAIContext *context;
-	GSList *basenames;
-	gchar *to_remove;
-
-	listview = GTK_TREE_VIEW( g_object_get_data( G_OBJECT( window ), BASENAMES_LIST_VIEW ));
-	selection = gtk_tree_view_get_selection( listview );
-	model = gtk_tree_view_get_model( listview );
-	rows = gtk_tree_selection_get_selected_rows( selection, NULL );
-
-	if( g_list_length( rows ) == 1 ){
-		path = ( GtkTreePath * ) rows->data;
-		gtk_tree_model_get_iter( model, &iter, path );
-		gtk_tree_model_get( model, &iter, BASENAMES_ITEM_COLUMN, &filter, -1 );
-		gtk_list_store_remove( GTK_LIST_STORE( model ), &iter );
-
-		g_object_get(
-				G_OBJECT( window ),
-				TAB_UPDATABLE_PROP_EDITED_ACTION, &item,
-				TAB_UPDATABLE_PROP_EDITED_PROFILE, &profile,
-				NULL );
-
-		context = ( profile ? NA_ICONTEXT( profile ) : ( NAIContext * ) item );
-
-		if( context ){
-			basenames = na_object_get_basenames( context );
-			if( basenames ){
-				to_remove = g_strdup_printf( "!%s", filter );
-				basenames = na_core_utils_slist_remove_ascii( basenames, to_remove );
-				g_free( to_remove );
-				basenames = na_core_utils_slist_remove_ascii( basenames, filter );
-				na_object_set_basenames( context, basenames );
-				na_core_utils_slist_free( basenames );
-				g_signal_emit_by_name( G_OBJECT( window ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, context, FALSE );
-			}
-		}
-
-		g_free( filter );
-
-		if( gtk_tree_model_get_iter( model, &iter, path ) ||
-			gtk_tree_path_prev( path )){
-			gtk_tree_view_set_cursor( listview, path, NULL, FALSE );
-		}
-	}
-
-	g_list_foreach( rows, ( GFunc ) gtk_tree_path_free, NULL );
-	g_list_free( rows );
-}
-
-static void
-edit_inline( BaseWindow *window )
-{
-	static const gchar *thisfn = "nact_ibasenames_tab_edit_inline";
-	GtkTreeView *listview;
-	GtkTreeSelection *selection;
-	GList *rows;
-	GtkTreePath *path;
-	GtkTreeViewColumn *column;
-
-	g_debug( "%s: window=%p", thisfn, ( void * ) window );
-
-	listview = GTK_TREE_VIEW( g_object_get_data( G_OBJECT( window ), BASENAMES_LIST_VIEW ));
-	selection = gtk_tree_view_get_selection( listview );
-	rows = gtk_tree_selection_get_selected_rows( selection, NULL );
-
-	if( g_list_length( rows ) == 1 ){
-		gtk_tree_view_get_cursor( listview, &path, &column );
-		gtk_tree_view_set_cursor( listview, path, column, TRUE );
-		gtk_tree_path_free( path );
-	}
-
-	g_list_foreach( rows, ( GFunc ) gtk_tree_path_free, NULL );
-	g_list_free( rows );
-}
-
-static void
-insert_new_row( BaseWindow *window )
-{
-	GtkTreeView *listview;
-	GtkTreeModel *model;
-	GtkTreeIter iter;
-	GtkTreePath *path;
-	GtkTreeViewColumn *column;
-
-	listview = GTK_TREE_VIEW( g_object_get_data( G_OBJECT( window ), BASENAMES_LIST_VIEW ));
-	model = gtk_tree_view_get_model( listview );
-
-	gtk_list_store_insert_with_values( GTK_LIST_STORE( model ), &iter, 0,
-			/* i18n notes : new basename filter for a new row in the basenames list */
-			BASENAMES_ITEM_COLUMN, _( "new-basename-filter" ),
-			BASENAMES_MUST_MATCH_COLUMN, FALSE,
-			BASENAMES_MUST_NOT_MATCH_COLUMN, FALSE,
-			-1 );
-
-	path = gtk_tree_model_get_path( model, &iter );
-	column = gtk_tree_view_get_column( listview, BASENAMES_ITEM_COLUMN );
-	gtk_tree_view_set_cursor( listview, path, column, TRUE );
-	gtk_tree_path_free( path );
-}
-
-static void
-iter_for_setup( gchar *basename, GtkTreeModel *model )
-{
-	GtkTreeIter iter;
-	gchar *tmp, *filter;
-	gboolean positive;
-	gboolean negative;
-
-	filter = g_strstrip( g_strdup( basename ));
-	positive = FALSE;
-	negative = FALSE;
-
-	if( filter[0] == '!' ){
-		tmp = g_strstrip( g_strdup( filter+1 ));
-		g_free( filter );
-		filter = tmp;
-		negative = TRUE;
-
-	} else {
-		positive = TRUE;
-	}
-
-	gtk_list_store_append( GTK_LIST_STORE( model ), &iter );
-	gtk_list_store_set(
-			GTK_LIST_STORE( model ),
-			&iter,
-			BASENAMES_ITEM_COLUMN, filter,
-			BASENAMES_MUST_MATCH_COLUMN, positive,
-			BASENAMES_MUST_NOT_MATCH_COLUMN, negative,
-			-1 );
-
-	g_free( filter );
-}
-
-static void
-sort_on_column( GtkTreeViewColumn *treeviewcolumn, BaseWindow *window, guint new_col_id )
-{
-	GtkTreeView *listview;
-	guint prev_col_id;
-	guint prev_order, new_order;
-	GtkTreeModel *model;
-
-	listview = GTK_TREE_VIEW( g_object_get_data( G_OBJECT( window ), BASENAMES_LIST_VIEW ));
-	prev_col_id = GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( listview ), BASENAMES_LIST_SORT_HEADER ));
-	prev_order = GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( listview ), BASENAMES_LIST_SORT_ORDER ));
-
-	if( new_col_id == prev_col_id ){
-		new_order = ( prev_order == GTK_SORT_ASCENDING ? GTK_SORT_DESCENDING : GTK_SORT_ASCENDING );
-	} else {
-		new_order = GTK_SORT_ASCENDING;
-	}
-
-	g_object_set_data( G_OBJECT( listview ), BASENAMES_LIST_SORT_HEADER, GUINT_TO_POINTER( new_col_id ));
-	g_object_set_data( G_OBJECT( listview ), BASENAMES_LIST_SORT_ORDER, GUINT_TO_POINTER( new_order ));
-
-	model = gtk_tree_view_get_model( listview );
-	gtk_tree_sortable_set_sort_column_id( GTK_TREE_SORTABLE( model ), new_col_id, new_order );
-
-	/*gtk_tree_sortable_set_sort_func( GTK_TREE_SORTABLE( model ), new_col_id,
-			IACTIONS_LIST_LABEL_COLUMN,
-			( GtkTreeIterCompareFunc ) sort_actions_list,
-			NULL,
-			NULL );*/
-}
-
-static gboolean
-tab_set_sensitive( NactIBasenamesTab *instance )
-{
-	NAObjectProfile *profile;
-	gboolean enable_tab;
-
-	g_object_get(
-			G_OBJECT( instance ),
-			TAB_UPDATABLE_PROP_EDITED_PROFILE, &profile,
-			NULL );
-
-	enable_tab = ( profile != NULL );
-	nact_main_tab_enable_page( NACT_MAIN_WINDOW( instance ), TAB_BASENAMES, enable_tab );
-	nact_main_tab_enable_page( NACT_MAIN_WINDOW( instance ), TAB_BASENAMES, TRUE );
-
-	return( enable_tab );
+	na_object_set_basenames( context, filters );
 }
diff --git a/src/nact/nact-ischemes-tab.c b/src/nact/nact-ischemes-tab.c
index 9f8f1ec..e22bb4a 100644
--- a/src/nact/nact-ischemes-tab.c
+++ b/src/nact/nact-ischemes-tab.c
@@ -132,10 +132,11 @@ nact_ischemes_tab_initial_load_toplevel( NactISchemesTab *instance )
 {
 	static const gchar *thisfn = "nact_ischemes_tab_initial_load_toplevel";
 
+	g_return_if_fail( NACT_IS_ISCHEMES_TAB( instance ));
+
 	if( st_initialized && !st_finalized ){
 
 		g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
-		g_return_if_fail( NACT_IS_ISCHEMES_TAB( instance ));
 
 		nact_schemes_list_create_model( get_schemes_tree_view( instance ), TRUE );
 	}
diff --git a/src/nact/nact-match-list.c b/src/nact/nact-match-list.c
new file mode 100644
index 0000000..9e6e5fe
--- /dev/null
+++ b/src/nact/nact-match-list.c
@@ -0,0 +1,812 @@
+/*
+ * 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, 2010 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 <gdk/gdkkeysyms.h>
+#include <glib/gi18n.h>
+
+#include <api/na-object-api.h>
+#include <api/na-core-utils.h>
+
+#include "nact-gtk-utils.h"
+#include "nact-main-tab.h"
+#include "nact-match-list.h"
+
+typedef struct {
+	BaseWindow  *window;
+	guint        tab_id;
+	GtkTreeView *listview;
+	GtkWidget   *addbutton;
+	GtkWidget   *removebutton;
+	pget_filters pget;
+	pset_filters pset;
+	gchar       *item_header;
+	gboolean     editable;
+	guint        sort_column;
+	guint        sort_order;
+}
+	MatchListStr;
+
+/* column ordering
+ */
+enum {
+	ITEM_COLUMN = 0,
+	MUST_MATCH_COLUMN,
+	MUST_NOT_MATCH_COLUMN,
+	N_COLUMN
+};
+
+static gboolean st_on_selection_change = FALSE;
+
+static void     on_add_filter_clicked( GtkButton *button, MatchListStr *data );
+static void     on_filter_clicked( GtkTreeViewColumn *treeviewcolumn, MatchListStr *data );
+static void     on_filter_edited( GtkCellRendererText *renderer, const gchar *path, const gchar *text, MatchListStr *data );
+static gboolean on_key_pressed_event( GtkWidget *widget, GdkEventKey *event, MatchListStr *data );
+static void     on_must_match_clicked( GtkTreeViewColumn *treeviewcolumn, MatchListStr *data );
+static void     on_must_match_toggled( GtkCellRendererToggle *cell_renderer, gchar *path, MatchListStr *data );
+static void     on_must_not_match_clicked( GtkTreeViewColumn *treeviewcolumn, MatchListStr *data );
+static void     on_must_not_match_toggled( GtkCellRendererToggle *cell_renderer, gchar *path, MatchListStr *data );
+static void     on_remove_filter_clicked( GtkButton *button, MatchListStr *data );
+static void     on_selection_changed( GtkTreeSelection *selection, MatchListStr *data );
+
+static void     delete_current_row( MatchListStr *data );
+static void     edit_inline( MatchListStr *data );
+static void     insert_new_row( MatchListStr *data );
+static void     iter_for_setup( gchar *filter, GtkTreeModel *model );
+static void     sort_on_column( GtkTreeViewColumn *treeviewcolumn, MatchListStr *data, guint colid );
+static gboolean tab_set_sensitive( MatchListStr *data );
+
+/**
+ * nact_match_list_create_model:
+ * @window: the #BaseWindow window which contains the view.
+ * @tab_name: a string constant which identifies this page.
+ * @tab_id: our id for this page.
+ * @listview: the #GtkTreeView widget.
+ * @addbutton: the #GtkButton widget.
+ * @removebutton: the #GtkButton widget.
+ * @pget: a pointer to the function to get the list of filters.
+ * @pset: a pointer to the function to set the list of filters.
+ * @item_header: the title of the item header.
+ *
+ * Creates the tree model.
+ */
+void
+nact_match_list_create_model( BaseWindow *window,
+		const gchar *tab_name, guint tab_id,
+		GtkWidget *listview, GtkWidget *addbutton, GtkWidget *removebutton,
+		pget_filters pget, pset_filters pset,
+		const gchar *item_header )
+{
+	MatchListStr *data;
+	GtkListStore *model;
+	GtkCellRenderer *text_cell, *radio_cell;
+	GtkTreeViewColumn *column;
+	GtkTreeSelection *selection;
+
+	data = g_new0( MatchListStr, 1 );
+	data->window = window;
+	data->tab_id = tab_id;
+	data->listview = GTK_TREE_VIEW( listview );
+	data->addbutton = addbutton;
+	data->removebutton = removebutton;
+	data->pget = pget;
+	data->pset = pset;
+	data->item_header = g_strdup( item_header );
+	data->editable = FALSE;
+	data->sort_column = 0;
+	data->sort_order = 0;
+	g_object_set_data( G_OBJECT( window ), tab_name, data );
+
+	model = gtk_list_store_new( N_COLUMN, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN );
+	gtk_tree_view_set_model( data->listview, GTK_TREE_MODEL( model ));
+	g_object_unref( model );
+
+	text_cell = gtk_cell_renderer_text_new();
+	column = gtk_tree_view_column_new_with_attributes(
+			data->item_header,
+			text_cell,
+			"text", ITEM_COLUMN,
+			NULL );
+	gtk_tree_view_append_column( data->listview, column );
+
+	radio_cell = gtk_cell_renderer_toggle_new();
+	gtk_cell_renderer_toggle_set_radio( GTK_CELL_RENDERER_TOGGLE( radio_cell ), TRUE );
+	column = gtk_tree_view_column_new_with_attributes(
+			_( "Must match one" ),
+			radio_cell,
+			"active", MUST_MATCH_COLUMN,
+			NULL );
+	gtk_tree_view_append_column( data->listview, column );
+
+	radio_cell = gtk_cell_renderer_toggle_new();
+	gtk_cell_renderer_toggle_set_radio( GTK_CELL_RENDERER_TOGGLE( radio_cell ), TRUE );
+	column = gtk_tree_view_column_new_with_attributes(
+			_( "Must not match any" ),
+			radio_cell,
+			"active", MUST_NOT_MATCH_COLUMN,
+			NULL );
+	gtk_tree_view_append_column( data->listview, column );
+
+	/* an empty column to fill out the view
+	 */
+	column = gtk_tree_view_column_new();
+	gtk_tree_view_append_column( data->listview, column );
+
+	gtk_tree_view_set_headers_visible( data->listview, TRUE );
+	gtk_tree_view_set_headers_clickable( data->listview, TRUE );
+
+	selection = gtk_tree_view_get_selection( data->listview );
+	gtk_tree_selection_set_mode( selection, GTK_SELECTION_BROWSE );
+}
+
+/**
+ * nact_match_list_init_view:
+ * @window: the #BaseWindow window which contains the view.
+ * @tab_name: a string constant which identifies this page.
+ *
+ * Initializes the tab widget at each time the widget will be displayed.
+ * Connect signals.
+ */
+void
+nact_match_list_init_view( BaseWindow *window, const gchar *tab_name )
+{
+	MatchListStr *data;
+	GtkTreeViewColumn *column;
+	GList *renderers;
+	GtkTreeModel *model;
+
+	data = ( MatchListStr * ) g_object_get_data( G_OBJECT( window ), tab_name );
+	g_return_if_fail( data != NULL );
+
+	column = gtk_tree_view_get_column( data->listview, ITEM_COLUMN );
+	base_window_signal_connect_with_data(
+			window,
+			G_OBJECT( column ),
+			"clicked",
+			G_CALLBACK( on_filter_clicked ),
+			data );
+
+	renderers = gtk_cell_layout_get_cells( GTK_CELL_LAYOUT( column ));
+	base_window_signal_connect_with_data(
+			window,
+			G_OBJECT( renderers->data ),
+			"edited",
+			G_CALLBACK( on_filter_edited ),
+			data );
+
+	column = gtk_tree_view_get_column( data->listview, MUST_MATCH_COLUMN );
+	base_window_signal_connect_with_data(
+			window,
+			G_OBJECT( column ),
+			"clicked",
+			G_CALLBACK( on_must_match_clicked ),
+			data );
+
+	renderers = gtk_cell_layout_get_cells( GTK_CELL_LAYOUT( column ));
+	base_window_signal_connect_with_data(
+			window,
+			G_OBJECT( renderers->data ),
+			"toggled",
+			G_CALLBACK( on_must_match_toggled ),
+			data );
+
+	column = gtk_tree_view_get_column( data->listview, MUST_NOT_MATCH_COLUMN );
+	base_window_signal_connect_with_data(
+			window,
+			G_OBJECT( column ),
+			"clicked",
+			G_CALLBACK( on_must_not_match_clicked ),
+			data );
+
+	renderers = gtk_cell_layout_get_cells( GTK_CELL_LAYOUT( column ));
+	base_window_signal_connect_with_data(
+			window,
+			G_OBJECT( renderers->data ),
+			"toggled",
+			G_CALLBACK( on_must_not_match_toggled ),
+			data );
+
+	base_window_signal_connect_with_data(
+			window,
+			G_OBJECT( data->addbutton ),
+			"clicked",
+			G_CALLBACK( on_add_filter_clicked ),
+			data );
+
+	base_window_signal_connect_with_data(
+			window,
+			G_OBJECT( data->removebutton ),
+			"clicked",
+			G_CALLBACK( on_remove_filter_clicked ),
+			data );
+
+	base_window_signal_connect_with_data(
+			window,
+			G_OBJECT( gtk_tree_view_get_selection( data->listview )),
+			"changed",
+			G_CALLBACK( on_selection_changed ),
+			data );
+
+	base_window_signal_connect_with_data(
+			window,
+			G_OBJECT( data->listview ),
+			"key-press-event",
+			G_CALLBACK( on_key_pressed_event ),
+			data );
+
+	model = gtk_tree_view_get_model( data->listview );
+	gtk_tree_sortable_set_sort_column_id( GTK_TREE_SORTABLE( model ), ITEM_COLUMN, GTK_SORT_ASCENDING );
+	data->sort_column = ITEM_COLUMN;
+	data->sort_order = GTK_SORT_ASCENDING;
+}
+
+/**
+ * nact_match_list_on_selection_changed:
+ * @window: the #BaseWindow window which contains the view.
+ * @tab_name: a string constant which identifies this page.
+ * @count_selected: count of selected items in the #NactIActionsList list view.
+ *
+ * Called at instance_dispose time.
+ *
+ * Basically we are using here a rather common scheme:
+ * - object has a GSList of strings, each of one being a filter description,
+ *   which may be negated
+ * - the list is displayed in a listview with radio toggle buttons
+ *   so that a user cannot have both positive and negative assertions
+ *   for the same basename filter
+ * - update the object with a summary of the listbox contents
+ */
+void
+nact_match_list_on_selection_changed( BaseWindow *window, const gchar *tab_name, guint count_selected )
+{
+	static const gchar *thisfn = "nact_match_list_on_selection_changed";
+	MatchListStr *data;
+	NAObjectItem *item;
+	NAObjectProfile *profile;
+	gboolean editable;
+	NAIContext *context;
+	GSList *filters;
+	GtkTreeModel *model;
+	GtkTreeSelection *selection;
+	GtkTreeViewColumn *column;
+	GtkTreePath *path;
+
+	g_debug( "%s: window=%p, tab=%s, count_selected=%d", thisfn, ( void * ) window, tab_name, count_selected );
+
+	data = ( MatchListStr * ) g_object_get_data( G_OBJECT( window ), tab_name );
+	g_return_if_fail( data != NULL );
+
+	g_object_get(
+			G_OBJECT( window ),
+			TAB_UPDATABLE_PROP_EDITED_ACTION, &item,
+			TAB_UPDATABLE_PROP_EDITED_PROFILE, &profile,
+			TAB_UPDATABLE_PROP_EDITABLE, &editable,
+			NULL );
+
+	context = ( profile ? NA_ICONTEXT( profile ) : ( NAIContext * ) item );
+	data->editable = editable;
+	filters = ( *data->pget )( context );
+
+	st_on_selection_change = TRUE;
+
+	model = gtk_tree_view_get_model( data->listview );
+	selection = gtk_tree_view_get_selection( data->listview );
+	gtk_tree_selection_unselect_all( selection );
+	gtk_list_store_clear( GTK_LIST_STORE( model ));
+
+	if( filters ){
+		g_slist_foreach( filters, ( GFunc ) iter_for_setup, model );
+	}
+
+	column = gtk_tree_view_get_column( data->listview, ITEM_COLUMN );
+	nact_gtk_utils_set_editable( GTK_OBJECT( column ), data->editable );
+
+	nact_gtk_utils_set_editable( GTK_OBJECT( data->addbutton ), data->editable );
+	nact_gtk_utils_set_editable( GTK_OBJECT( data->removebutton ), data->editable );
+
+	st_on_selection_change = FALSE;
+
+	path = gtk_tree_path_new_first();
+	if( path ){
+		selection = gtk_tree_view_get_selection( data->listview );
+		gtk_tree_selection_select_path( selection, path );
+		gtk_tree_path_free( path );
+	}
+}
+
+/**
+ * nact_match_list_on_enable_tab:
+ * @window: the #BaseWindow window which contains the view.
+ * @tab_name: a string constant which identifies this page.
+ * @item: the currently selected #NAObjectItem.
+ *
+ * Enable/disable this page of the notebook.
+ */
+void
+nact_match_list_on_enable_tab( BaseWindow *window, const gchar *tab_name, NAObjectItem *item )
+{
+	static const gchar *thisfn = "nact_match_list_on_tab_updatable_enable_tab";
+	MatchListStr *data;
+
+	g_debug( "%s: window=%p, tab=%s, item=%p", thisfn, ( void * ) window, tab_name, ( void * ) item );
+
+	data = ( MatchListStr * ) g_object_get_data( G_OBJECT( window ), tab_name );
+	g_return_if_fail( data != NULL );
+
+	tab_set_sensitive( data );
+}
+
+/**
+ * nact_match_list_dispose:
+ * @window: the #BaseWindow window which contains the view.
+ * @tab_name: a string constant which identifies this page.
+ *
+ * Called at instance_dispose time.
+ */
+void
+nact_match_list_dispose( BaseWindow *window, const gchar *tab_name )
+{
+	MatchListStr *data;
+	GtkTreeModel *model;
+	GtkTreeSelection *selection;
+
+	data = ( MatchListStr * ) g_object_get_data( G_OBJECT( window ), tab_name );
+	g_return_if_fail( data != NULL );
+
+	model = gtk_tree_view_get_model( data->listview );
+	selection = gtk_tree_view_get_selection( data->listview );
+	gtk_tree_selection_unselect_all( selection );
+	gtk_list_store_clear( GTK_LIST_STORE( model ));
+
+	g_free( data->item_header );
+
+	g_free( data );
+	g_object_set_data( G_OBJECT( window ), tab_name, NULL );
+}
+
+static void
+on_add_filter_clicked( GtkButton *button, MatchListStr *data )
+{
+	insert_new_row( data );
+}
+
+static void
+on_filter_clicked( GtkTreeViewColumn *treeviewcolumn, MatchListStr *data )
+{
+	sort_on_column( treeviewcolumn, data, ITEM_COLUMN );
+}
+
+static void
+on_filter_edited( GtkCellRendererText *renderer, const gchar *path_str, const gchar *text, MatchListStr *data )
+{
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	GtkTreePath *path;
+	gchar *old_text;
+	NAObjectItem *item;
+	NAObjectProfile *profile;
+	NAIContext *context;
+	gboolean must_match, must_not_match;
+	gchar *to_add, *to_remove;
+	GSList *filters;
+
+	model = gtk_tree_view_get_model( data->listview );
+	path = gtk_tree_path_new_from_string( path_str );
+	gtk_tree_model_get_iter( model, &iter, path );
+	gtk_tree_path_free( path );
+
+	gtk_tree_model_get( model, &iter,
+			ITEM_COLUMN, &old_text,
+			MUST_MATCH_COLUMN, &must_match,
+			MUST_NOT_MATCH_COLUMN, &must_not_match,
+			-1 );
+
+	gtk_list_store_set( GTK_LIST_STORE( model ), &iter, ITEM_COLUMN, text, -1 );
+
+	g_object_get(
+			G_OBJECT( data->window ),
+			TAB_UPDATABLE_PROP_EDITED_ACTION, &item,
+			TAB_UPDATABLE_PROP_EDITED_PROFILE, &profile,
+			NULL );
+
+	context = ( profile ? NA_ICONTEXT( profile ) : ( NAIContext * ) item );
+
+	if( context ){
+		filters = ( *data->pget )( context );
+
+		if( filters ){
+			to_remove = g_strdup( old_text );
+			filters = na_core_utils_slist_remove_ascii( filters, to_remove );
+			g_free( to_remove );
+			to_remove = g_strdup_printf( "!%s", old_text );
+			filters = na_core_utils_slist_remove_ascii( filters, to_remove );
+			g_free( to_remove );
+		}
+
+		if( must_match ){
+			filters = g_slist_prepend( filters, g_strdup( text ));
+
+		} else if( must_not_match ){
+			to_add = g_strdup_printf( "!%s", text );
+			filters = g_slist_prepend( filters, to_add );
+		}
+
+		( *data->pset )( context, filters );
+		na_core_utils_slist_free( filters );
+
+		g_signal_emit_by_name( G_OBJECT( data->window ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, context, FALSE );
+	}
+
+	g_free( old_text );
+}
+
+static gboolean
+on_key_pressed_event( GtkWidget *widget, GdkEventKey *event, MatchListStr *data )
+{
+	gboolean stop;
+
+	stop = FALSE;
+
+	if( event->keyval == GDK_F2 ){
+		edit_inline( data );
+		stop = TRUE;
+	}
+
+	if( event->keyval == GDK_Insert || event->keyval == GDK_KP_Insert ){
+		insert_new_row( data );
+		stop = TRUE;
+	}
+
+	if( event->keyval == GDK_Delete || event->keyval == GDK_KP_Delete ){
+		delete_current_row( data );
+		stop = TRUE;
+	}
+
+	return( stop );
+}
+
+static void
+on_must_match_clicked( GtkTreeViewColumn *treeviewcolumn, MatchListStr *data )
+{
+	sort_on_column( treeviewcolumn, data, MUST_MATCH_COLUMN );
+}
+
+/*
+ * clicking on an already active toggle button has no effect
+ * clicking on an inactive toggle button has a double effect:
+ * - the other toggle button becomes inactive
+ * - this toggle button becomes active
+ * the corresponding strings must be respectively removed/added to the
+ * filters list
+ */
+static void
+on_must_match_toggled( GtkCellRendererToggle *cell_renderer, gchar *path_str, MatchListStr *data )
+{
+	/*static const gchar *thisfn = "nact_ibasenames_tab_on_must_match_toggled";*/
+	GtkTreeModel *model;
+	GtkTreePath *path;
+	GtkTreeIter iter;
+	gchar *filter;
+	NAObjectItem *item;
+	NAObjectProfile *profile;
+	NAIContext *context;
+	GSList *filters;
+	gchar *to_remove;
+
+	/*gboolean is_active = gtk_cell_renderer_toggle_get_active( cell_renderer );
+	g_debug( "%s: is_active=%s", thisfn, is_active ? "True":"False" );*/
+
+	if( !gtk_cell_renderer_toggle_get_active( cell_renderer )){
+
+		model = gtk_tree_view_get_model( data->listview );
+		path = gtk_tree_path_new_from_string( path_str );
+		gtk_tree_model_get_iter( model, &iter, path );
+		gtk_tree_path_free( path );
+
+		gtk_tree_model_get( model, &iter, ITEM_COLUMN, &filter, -1 );
+		gtk_list_store_set( GTK_LIST_STORE( model ), &iter, MUST_MATCH_COLUMN, TRUE, MUST_NOT_MATCH_COLUMN, FALSE, -1 );
+
+		g_object_get(
+				G_OBJECT( data->window ),
+				TAB_UPDATABLE_PROP_EDITED_ACTION, &item,
+				TAB_UPDATABLE_PROP_EDITED_PROFILE, &profile,
+				NULL );
+
+		context = ( profile ? NA_ICONTEXT( profile ) : ( NAIContext * ) item );
+
+		if( context ){
+			filters = ( *data->pget )( context );
+			if( filters ){
+				to_remove = g_strdup_printf( "!%s", filter );
+				filters = na_core_utils_slist_remove_ascii( filters, to_remove );
+				g_free( to_remove );
+			}
+			filters = g_slist_prepend( filters, filter );
+			( *data->pset )( context, filters );
+			na_core_utils_slist_free( filters );
+
+			g_signal_emit_by_name( G_OBJECT( data->window ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, context, FALSE );
+		}
+	}
+}
+
+static void
+on_must_not_match_clicked( GtkTreeViewColumn *treeviewcolumn, MatchListStr *data )
+{
+	sort_on_column( treeviewcolumn, data, MUST_MATCH_COLUMN );
+}
+
+static void
+on_must_not_match_toggled( GtkCellRendererToggle *cell_renderer, gchar *path_str, MatchListStr *data )
+{
+	/*static const gchar *thisfn = "nact_ibasenames_tab_on_must_not_match_toggled";*/
+	GtkTreeModel *model;
+	GtkTreePath *path;
+	GtkTreeIter iter;
+	gchar *filter;
+	NAObjectItem *item;
+	NAObjectProfile *profile;
+	NAIContext *context;
+	GSList *filters;
+	gchar *to_add;
+
+	/*gboolean is_active = gtk_cell_renderer_toggle_get_active( cell_renderer );
+	g_debug( "%s: is_active=%s", thisfn, is_active ? "True":"False" );*/
+
+	if( !gtk_cell_renderer_toggle_get_active( cell_renderer )){
+
+		model = gtk_tree_view_get_model( data->listview );
+		path = gtk_tree_path_new_from_string( path_str );
+		gtk_tree_model_get_iter( model, &iter, path );
+		gtk_tree_path_free( path );
+
+		gtk_tree_model_get( model, &iter, ITEM_COLUMN, &filter, -1 );
+		gtk_list_store_set( GTK_LIST_STORE( model ), &iter, MUST_MATCH_COLUMN, FALSE, MUST_NOT_MATCH_COLUMN, TRUE, -1 );
+
+		g_object_get(
+				G_OBJECT( data->window ),
+				TAB_UPDATABLE_PROP_EDITED_ACTION, &item,
+				TAB_UPDATABLE_PROP_EDITED_PROFILE, &profile,
+				NULL );
+
+		context = ( profile ? NA_ICONTEXT( profile ) : ( NAIContext * ) item );
+
+		if( context ){
+			filters = ( *data->pget )( context );
+			if( filters ){
+				filters = na_core_utils_slist_remove_ascii( filters, filter );
+			}
+			to_add = g_strdup_printf( "!%s", filter );
+			filters = g_slist_prepend( filters, to_add );
+			( *data->pset )( context, filters );
+			na_core_utils_slist_free( filters );
+
+			g_signal_emit_by_name( G_OBJECT( data->window ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, context, FALSE );
+		}
+
+		g_free( filter );
+	}
+}
+
+static void
+on_remove_filter_clicked( GtkButton *button, MatchListStr *data )
+{
+	delete_current_row( data );
+}
+
+static void
+on_selection_changed( GtkTreeSelection *selection, MatchListStr *data )
+{
+	gtk_widget_set_sensitive( data->removebutton,
+			data->editable && gtk_tree_selection_count_selected_rows( selection ) > 0 );
+}
+
+static void
+delete_current_row( MatchListStr *data )
+{
+	GtkTreeSelection *selection;
+	GtkTreeModel *model;
+	GList *rows;
+	GtkTreePath *path;
+	GtkTreeIter iter;
+	gchar *filter;
+	NAObjectItem *item;
+	NAObjectProfile *profile;
+	NAIContext *context;
+	GSList *filters;
+	gchar *to_remove;
+
+	selection = gtk_tree_view_get_selection( data->listview );
+	model = gtk_tree_view_get_model( data->listview );
+	rows = gtk_tree_selection_get_selected_rows( selection, NULL );
+
+	if( g_list_length( rows ) == 1 ){
+		path = ( GtkTreePath * ) rows->data;
+		gtk_tree_model_get_iter( model, &iter, path );
+		gtk_tree_model_get( model, &iter, ITEM_COLUMN, &filter, -1 );
+		gtk_list_store_remove( GTK_LIST_STORE( model ), &iter );
+
+		g_object_get(
+				G_OBJECT( data->window ),
+				TAB_UPDATABLE_PROP_EDITED_ACTION, &item,
+				TAB_UPDATABLE_PROP_EDITED_PROFILE, &profile,
+				NULL );
+
+		context = ( profile ? NA_ICONTEXT( profile ) : ( NAIContext * ) item );
+
+		if( context ){
+			filters = ( *data->pget )( context );
+
+			if( filters ){
+				to_remove = g_strdup_printf( "!%s", filter );
+				filters = na_core_utils_slist_remove_ascii( filters, to_remove );
+				g_free( to_remove );
+				filters = na_core_utils_slist_remove_ascii( filters, filter );
+				( *data->pset )( context, filters );
+				na_core_utils_slist_free( filters );
+
+				g_signal_emit_by_name( G_OBJECT( data->window ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, context, FALSE );
+			}
+		}
+
+		g_free( filter );
+
+		if( gtk_tree_model_get_iter( model, &iter, path ) ||
+			gtk_tree_path_prev( path )){
+			gtk_tree_view_set_cursor( data->listview, path, NULL, FALSE );
+		}
+	}
+
+	g_list_foreach( rows, ( GFunc ) gtk_tree_path_free, NULL );
+	g_list_free( rows );
+}
+
+static void
+edit_inline( MatchListStr *data )
+{
+	GtkTreeSelection *selection;
+	GList *rows;
+	GtkTreePath *path;
+	GtkTreeViewColumn *column;
+
+	selection = gtk_tree_view_get_selection( data->listview );
+	rows = gtk_tree_selection_get_selected_rows( selection, NULL );
+
+	if( g_list_length( rows ) == 1 ){
+		gtk_tree_view_get_cursor( data->listview, &path, &column );
+		gtk_tree_view_set_cursor( data->listview, path, column, TRUE );
+		gtk_tree_path_free( path );
+	}
+
+	g_list_foreach( rows, ( GFunc ) gtk_tree_path_free, NULL );
+	g_list_free( rows );
+}
+
+static void
+insert_new_row( MatchListStr *data )
+{
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	GtkTreePath *path;
+	GtkTreeViewColumn *column;
+
+	model = gtk_tree_view_get_model( data->listview );
+
+	gtk_list_store_insert_with_values( GTK_LIST_STORE( model ), &iter, 0,
+			/* i18n notes : new filter for a new row in a match/no matchlist */
+			ITEM_COLUMN, _( "new-filter" ),
+			MUST_MATCH_COLUMN, FALSE,
+			MUST_NOT_MATCH_COLUMN, FALSE,
+			-1 );
+
+	path = gtk_tree_model_get_path( model, &iter );
+	column = gtk_tree_view_get_column( data->listview, ITEM_COLUMN );
+	gtk_tree_view_set_cursor( data->listview, path, column, TRUE );
+	gtk_tree_path_free( path );
+}
+
+static void
+iter_for_setup( gchar *filter_orig, GtkTreeModel *model )
+{
+	GtkTreeIter iter;
+	gchar *tmp, *filter;
+	gboolean positive;
+	gboolean negative;
+
+	filter = g_strstrip( g_strdup( filter_orig ));
+	positive = FALSE;
+	negative = FALSE;
+
+	if( filter[0] == '!' ){
+		tmp = g_strstrip( g_strdup( filter+1 ));
+		g_free( filter );
+		filter = tmp;
+		negative = TRUE;
+
+	} else {
+		positive = TRUE;
+	}
+
+	gtk_list_store_append( GTK_LIST_STORE( model ), &iter );
+	gtk_list_store_set(
+			GTK_LIST_STORE( model ),
+			&iter,
+			ITEM_COLUMN, filter,
+			MUST_MATCH_COLUMN, positive,
+			MUST_NOT_MATCH_COLUMN, negative,
+			-1 );
+
+	g_free( filter );
+}
+
+static void
+sort_on_column( GtkTreeViewColumn *treeviewcolumn, MatchListStr *data, guint new_col_id )
+{
+	guint prev_col_id;
+	guint prev_order, new_order;
+	GtkTreeModel *model;
+
+	prev_col_id = data->sort_column;
+	prev_order = data->sort_order;
+
+	if( new_col_id == prev_col_id ){
+		new_order = ( prev_order == GTK_SORT_ASCENDING ? GTK_SORT_DESCENDING : GTK_SORT_ASCENDING );
+	} else {
+		new_order = GTK_SORT_ASCENDING;
+	}
+
+	data->sort_column = new_col_id;
+	data->sort_order = new_order;
+
+	model = gtk_tree_view_get_model( data->listview );
+	gtk_tree_sortable_set_sort_column_id( GTK_TREE_SORTABLE( model ), new_col_id, new_order );
+}
+
+static gboolean
+tab_set_sensitive( MatchListStr *data )
+{
+	NAObjectItem *item;
+	NAObjectProfile *profile;
+	gboolean enable_tab;
+
+	g_object_get(
+			G_OBJECT( data->window ),
+			TAB_UPDATABLE_PROP_EDITED_ACTION, &item,
+			TAB_UPDATABLE_PROP_EDITED_PROFILE, &profile,
+			NULL );
+
+	enable_tab = ( profile != NULL || item != NULL );
+	nact_main_tab_enable_page( NACT_MAIN_WINDOW( data->window ), data->tab_id, enable_tab );
+
+	return( enable_tab );
+}
diff --git a/src/nact/nact-match-list.h b/src/nact/nact-match-list.h
new file mode 100644
index 0000000..ef7e007
--- /dev/null
+++ b/src/nact/nact-match-list.h
@@ -0,0 +1,65 @@
+/*
+ * 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, 2010 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_MATCH_LIST_H__
+#define __NACT_MATCH_LIST_H__
+
+/**
+ * SECTION: nact_match_list
+ * @short_description: Implementation of a list match/does not match.
+ * @include: nact/nact-match-list.h
+ */
+
+#include "base-window.h"
+
+G_BEGIN_DECLS
+
+typedef GSList * ( *pget_filters )( void * );
+typedef void     ( *pset_filters )( void *, GSList * );
+
+void  nact_match_list_create_model        ( BaseWindow *window, const gchar *tab_name,
+		guint tab_id,
+		GtkWidget *listview, GtkWidget *addbutton, GtkWidget *removebutton,
+		pget_filters pget, pset_filters pset,
+		const gchar *item_header );
+
+void  nact_match_list_init_view           ( BaseWindow *window, const gchar *tab_name );
+
+void  nact_match_list_on_selection_changed( BaseWindow *window, const gchar *tab_name,
+		guint count );
+
+void  nact_match_list_on_enable_tab       ( BaseWindow *window, const gchar *tab_name,
+		NAObjectItem *item );
+
+void  nact_match_list_dispose             ( BaseWindow *window, const gchar *tab_name );
+
+G_END_DECLS
+
+#endif /* __NACT_MATCH_LIST_H__ */



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