[nautilus-actions] Define an import mode in the Import assistant
- From: Pierre Wieser <pwieser src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [nautilus-actions] Define an import mode in the Import assistant
- Date: Sat, 26 Sep 2009 22:49:51 +0000 (UTC)
commit aa31f46cd114ad8d09001abd95f77b80a942cdad
Author: Pierre Wieser <pwieser trychlos org>
Date: Fri Sep 25 02:59:17 2009 +0200
Define an import mode in the Import assistant
Let the user decide what to do if UUID of imported actions already exist.
ChangeLog | 21 +++
data/nautilus-actions.schemas.in | 14 ++
src/nact/nact-assistant-export.ui | 6 +-
src/nact/nact-assistant-import.c | 234 +++++++++++++++++++++++-------
src/nact/nact-tree-model.c | 78 ++++++++++-
src/nact/nact-xml-reader.c | 115 +++++++++++++--
src/nact/nact-xml-reader.h | 10 +-
src/nact/nautilus-actions-config-tool.ui | 199 ++++++++++++++++++++++++-
8 files changed, 595 insertions(+), 82 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index c63c0a9..b937c65 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+2009-09-25 Pierre Wieser <pwieser trychlos org>
+
+ * data/nautilus-actions.schemas.in:
+ Defines a new key for the "import-mode" preference.
+
+ * src/nact/nact-assistant-export.ui:
+ All titles are verbs.
+
+ * src/nact/nact-assistant-import.c:
+ Let the user define an import mode if the UUID already exists.
+
+ * src/nact/nact-tree-model.c:
+ Override the object when inserting an already existing UUID.
+
+ * src/nact/nact-xml-reader.c:
+ * src/nact/nact-xml-reader.h:
+ Manage the import mode, renumbering the imported action if needed.
+
+ * src/nact/nautilus-actions-config-tool.ui:
+ Add a page to the Import assistant to manage the import mode.
+
2009-09-24 Pierre Wieser <pwieser trychlos org>
* src/nact/nact-main-menubar.c:
diff --git a/data/nautilus-actions.schemas.in b/data/nautilus-actions.schemas.in
index ccc1995..c5890ea 100644
--- a/data/nautilus-actions.schemas.in
+++ b/data/nautilus-actions.schemas.in
@@ -298,6 +298,20 @@ All schemes used by Nautilus can be used here.</long>
</schema>
<schema>
+ <key>/schemas/apps/nautilus-actions/preferences/import-mode</key>
+ <owner>nautilus-actions</owner>
+ <type>int</type>
+ <locale name="C">
+ <short>Import mode</short>
+ <long>Last import mode choosen in the Import assistant. Possible values are:
+1: do not import an action whose UUID already exists
+2: allocate a new UUID if the imported UUID already exists
+3: override the existing action with the imported one.</long>
+ </locale>
+ <default>/tmp</default>
+ </schema>
+
+ <schema>
<key>/schemas/apps/nautilus-actions/preferences/iprefs-add-about-item</key>
<owner>nautilus-actions</owner>
<type>bool</type>
diff --git a/src/nact/nact-assistant-export.ui b/src/nact/nact-assistant-export.ui
index 92a758f..cc47eaa 100644
--- a/src/nact/nact-assistant-export.ui
+++ b/src/nact/nact-assistant-export.ui
@@ -76,7 +76,7 @@ to extend a selection.</property>
</child>
</object>
<packing>
- <property name="title">Selection of the exported actions</property>
+ <property name="title">Selecting the exported actions</property>
</packing>
</child>
<child>
@@ -96,7 +96,7 @@ to extend a selection.</property>
</child>
</object>
<packing>
- <property name="title">Selection of the target folder</property>
+ <property name="title">Selecting the target folder</property>
</packing>
</child>
<child>
@@ -283,7 +283,7 @@ The exported file may later be imported via :
</child>
</object>
<packing>
- <property name="title">Select the export format</property>
+ <property name="title">Selecting the export format</property>
</packing>
</child>
<child>
diff --git a/src/nact/nact-assistant-import.c b/src/nact/nact-assistant-import.c
index b2efe75..b0fa595 100644
--- a/src/nact/nact-assistant-import.c
+++ b/src/nact/nact-assistant-import.c
@@ -50,9 +50,10 @@
/* Import Assistant
*
* pos. type title
- * --- ------- ------------------------------------
+ * --- ------- --------------------------------------------------
* 0 Intro Introduction
* 1 Content Selection of the files
+ * 2 Content Duplicate management: what to do with duplicates ?
* 2 Confirm Display the selected files before import
* 3 Summary Import is done: summary of the done operations
*/
@@ -60,6 +61,7 @@
enum {
ASSIST_PAGE_INTRO = 0,
ASSIST_PAGE_FILES_SELECTION,
+ ASSIST_PAGE_DUPLICATES,
ASSIST_PAGE_CONFIRM,
ASSIST_PAGE_DONE
};
@@ -86,6 +88,7 @@ struct NactAssistantImportPrivate {
};
#define IPREFS_IMPORT_ACTIONS_FOLDER_URI "import-folder-uri"
+#define IPREFS_IMPORT_ACTIONS_IMPORT_MODE "import-mode"
static BaseAssistantClass *st_parent_class = NULL;
@@ -105,11 +108,14 @@ static void runtime_init_intro( NactAssistantImport *window, GtkAssistant *a
static void runtime_init_file_selector( NactAssistantImport *window, GtkAssistant *assistant );
static void on_file_selection_changed( GtkFileChooser *chooser, gpointer user_data );
static gboolean has_readable_files( GSList *uris );
+static void runtime_init_duplicates( NactAssistantImport *window, GtkAssistant *assistant );
+static void set_import_mode( NactAssistantImport *window, gint mode );
-static void assistant_apply( BaseAssistant *window, GtkAssistant *assistant );
static void assistant_prepare( BaseAssistant *window, GtkAssistant *assistant, GtkWidget *page );
-
static void prepare_confirm( NactAssistantImport *window, GtkAssistant *assistant, GtkWidget *page );
+static gint get_import_mode( NactAssistantImport *window );
+static gchar *add_import_mode( NactAssistantImport *window, const gchar *text );
+static void assistant_apply( BaseAssistant *window, GtkAssistant *assistant );
static void prepare_importdone( NactAssistantImport *window, GtkAssistant *assistant, GtkWidget *page );
static void free_results( GSList *list );
@@ -288,40 +294,49 @@ on_runtime_init_dialog( NactAssistantImport *dialog, gpointer user_data )
GtkAssistant *assistant;
g_debug( "%s: dialog=%p, user_data=%p", thisfn, ( void * ) dialog, ( void * ) user_data );
- g_assert( NACT_IS_ASSISTANT_IMPORT( dialog ));
+ g_return_if_fail( NACT_IS_ASSISTANT_IMPORT( dialog ));
+
+ if( !dialog->private->dispose_has_run ){
- assistant = GTK_ASSISTANT( base_window_get_toplevel_window( BASE_WINDOW( dialog )));
+ base_assistant_set_cancel_on_esc( BASE_ASSISTANT( dialog ), TRUE );
+ base_assistant_set_warn_on_esc( BASE_ASSISTANT( dialog ), TRUE );
- runtime_init_intro( dialog, assistant );
- runtime_init_file_selector( dialog, assistant );
+ assistant = GTK_ASSISTANT( base_window_get_toplevel_window( BASE_WINDOW( dialog )));
+
+ runtime_init_intro( dialog, assistant );
+ runtime_init_file_selector( dialog, assistant );
+ runtime_init_duplicates( dialog, assistant );
+ }
}
static void
runtime_init_intro( NactAssistantImport *window, GtkAssistant *assistant )
{
static const gchar *thisfn = "nact_assistant_import_runtime_init_intro";
- GtkWidget *content;
+ GtkWidget *page;
- content = gtk_assistant_get_nth_page( assistant, ASSIST_PAGE_INTRO );
+ page = gtk_assistant_get_nth_page( assistant, ASSIST_PAGE_INTRO );
- g_debug( "%s: window=%p, assistant=%p, content=%p",
- thisfn, ( void * ) window, ( void * ) assistant, ( void * ) content );
+ g_debug( "%s: window=%p, assistant=%p, page=%p",
+ thisfn, ( void * ) window, ( void * ) assistant, ( void * ) page );
- gtk_assistant_set_page_complete( assistant, content, TRUE );
+ gtk_assistant_set_page_complete( assistant, page, TRUE );
}
static void
runtime_init_file_selector( NactAssistantImport *window, GtkAssistant *assistant )
{
static const gchar *thisfn = "nact_assistant_import_runtime_init_file_selector";
+ GtkWidget *page;
GtkWidget *chooser;
gchar *uri;
- chooser = gtk_assistant_get_nth_page( assistant, ASSIST_PAGE_FILES_SELECTION );
+ page = gtk_assistant_get_nth_page( assistant, ASSIST_PAGE_FILES_SELECTION );
- g_debug( "%s: window=%p, assistant=%p, chooser=%p",
- thisfn, ( void * ) window, ( void * ) assistant, ( void * ) chooser );
+ g_debug( "%s: window=%p, assistant=%p, page=%p",
+ thisfn, ( void * ) window, ( void * ) assistant, ( void * ) page );
+ chooser = base_window_get_widget( BASE_WINDOW( window ), "ImportFileChooser" );
uri = base_iprefs_get_string( BASE_WINDOW( window ), IPREFS_IMPORT_ACTIONS_FOLDER_URI );
if( uri && strlen( uri )){
gtk_file_chooser_set_current_folder_uri( GTK_FILE_CHOOSER( chooser ), uri );
@@ -334,7 +349,7 @@ runtime_init_file_selector( NactAssistantImport *window, GtkAssistant *assistant
"selection-changed",
G_CALLBACK( on_file_selection_changed ));
- gtk_assistant_set_page_complete( assistant, chooser, FALSE );
+ gtk_assistant_set_page_complete( assistant, page, FALSE );
}
static void
@@ -426,45 +441,42 @@ has_readable_files( GSList *uris )
}
static void
-assistant_apply( BaseAssistant *wnd, GtkAssistant *assistant )
+runtime_init_duplicates( NactAssistantImport *window, GtkAssistant *assistant )
{
- static const gchar *thisfn = "nact_assistant_import_assistant_apply";
- NactAssistantImport *window;
- GtkWidget *chooser;
- GSList *uris, *is, *msg;
- NAObjectAction *action;
- ImportUriStruct *str;
- GList *items;
- BaseWindow *mainwnd;
-
- g_debug( "%s: window=%p, assistant=%p", thisfn, ( void * ) wnd, ( void * ) assistant );
- g_assert( NACT_IS_ASSISTANT_IMPORT( wnd ));
- window = NACT_ASSISTANT_IMPORT( wnd );
+ static const gchar *thisfn = "nact_assistant_import_runtime_init_duplicates";
+ GtkWidget *page;
+ gint mode;
- chooser = gtk_assistant_get_nth_page( assistant, ASSIST_PAGE_FILES_SELECTION );
- uris = gtk_file_chooser_get_uris( GTK_FILE_CHOOSER( chooser ));
+ g_debug( "%s: window=%p", thisfn, ( void * ) window );
- g_object_get( G_OBJECT( wnd ), BASE_WINDOW_PROP_PARENT, &mainwnd, NULL );
+ mode = base_iprefs_get_int( BASE_WINDOW( window ), IPREFS_IMPORT_ACTIONS_IMPORT_MODE );
+ set_import_mode( window, mode );
- for( is = uris ; is ; is = is->next ){
+ page = gtk_assistant_get_nth_page( assistant, ASSIST_PAGE_DUPLICATES );
+ gtk_assistant_set_page_complete( assistant, page, TRUE );
+}
- msg = NULL;
- action = nact_xml_reader_import( BASE_WINDOW( window ), ( const gchar * ) is->data, &msg );
+static void
+set_import_mode( NactAssistantImport *window, gint mode )
+{
+ GtkToggleButton *button;
- str = g_new0( ImportUriStruct, 1 );
- str->uri = g_strdup(( const gchar * ) is->data );
- str->action = action;
- str->msg = na_utils_duplicate_string_list( msg );
- na_utils_free_string_list( msg );
+ switch( mode ){
+ case NO_IMPORT_MODE:
+ button = GTK_TOGGLE_BUTTON( base_window_get_widget( BASE_WINDOW( window ), "NoImportButton" ));
+ gtk_toggle_button_set_active( button, TRUE );
+ break;
- window->private->results = g_slist_prepend( window->private->results, str );
+ case RENUMBER_MODE:
+ button = GTK_TOGGLE_BUTTON( base_window_get_widget( BASE_WINDOW( window ), "RenumberButton" ));
+ gtk_toggle_button_set_active( button, TRUE );
+ break;
- items = g_list_prepend( NULL, action );
- nact_iactions_list_insert_items( NACT_IACTIONS_LIST( mainwnd ), items, NULL );
- na_object_free_items( items );
+ case OVERRIDE_MODE:
+ button = GTK_TOGGLE_BUTTON( base_window_get_widget( BASE_WINDOW( window ), "OverrideButton" ));
+ gtk_toggle_button_set_active( button, TRUE );
+ break;
}
-
- na_utils_free_string_list( uris );
}
static void
@@ -509,7 +521,7 @@ prepare_confirm( NactAssistantImport *window, GtkAssistant *assistant, GtkWidget
g_free( text );
text = tmp;
- chooser = gtk_assistant_get_nth_page( assistant, ASSIST_PAGE_FILES_SELECTION );
+ chooser = base_window_get_widget( BASE_WINDOW( window ), "ImportFileChooser" );
uris = gtk_file_chooser_get_uris( GTK_FILE_CHOOSER( chooser ));
for( is = uris ; is ; is = is->next ){
@@ -518,12 +530,128 @@ prepare_confirm( NactAssistantImport *window, GtkAssistant *assistant, GtkWidget
text = tmp;
}
+ tmp = add_import_mode( window, text );
+ g_free( text );
+ text = tmp;
+
gtk_label_set_markup( GTK_LABEL( page ), text );
g_free( text );
gtk_assistant_set_page_complete( assistant, page, TRUE );
}
+static gint
+get_import_mode( NactAssistantImport *window )
+{
+ GtkToggleButton *no_import_button;
+ GtkToggleButton *renumber_button;
+ GtkToggleButton *override_button;
+ gint mode;
+
+ no_import_button = GTK_TOGGLE_BUTTON( base_window_get_widget( BASE_WINDOW( window ), "NoImportButton" ));
+ renumber_button = GTK_TOGGLE_BUTTON( base_window_get_widget( BASE_WINDOW( window ), "RenumberButton" ));
+ override_button = GTK_TOGGLE_BUTTON( base_window_get_widget( BASE_WINDOW( window ), "OverrideButton" ));
+
+ if( gtk_toggle_button_get_active( no_import_button )){
+ mode = NO_IMPORT_MODE;
+ } else if( gtk_toggle_button_get_active( renumber_button )){
+ mode = RENUMBER_MODE;
+ } else {
+ g_return_val_if_fail( gtk_toggle_button_get_active( override_button ), 0 );
+ mode = OVERRIDE_MODE;
+ }
+
+ return( mode );
+}
+
+static gchar *
+add_import_mode( NactAssistantImport *window, const gchar *text )
+{
+ gint mode;
+ gchar *label1, *label2;
+ gchar *result;
+
+ mode = get_import_mode( window );
+ label1 = NULL;
+ label2 = NULL;
+ result = NULL;
+
+ switch( mode ){
+ case NO_IMPORT_MODE:
+ label1 = g_strdup( gtk_button_get_label( GTK_BUTTON( base_window_get_widget( BASE_WINDOW( window ), "NoImportButton" ))));
+ label2 = g_strdup( gtk_label_get_text( GTK_LABEL( base_window_get_widget( BASE_WINDOW( window ), "NoImportLabel"))));
+ break;
+
+ case RENUMBER_MODE:
+ label1 = g_strdup( gtk_button_get_label( GTK_BUTTON( base_window_get_widget( BASE_WINDOW( window ), "RenumberButton" ))));
+ label2 = g_strdup( gtk_label_get_text( GTK_LABEL( base_window_get_widget( BASE_WINDOW( window ), "RenumberLabel"))));
+ break;
+
+ case OVERRIDE_MODE:
+ label1 = g_strdup( gtk_button_get_label( GTK_BUTTON( base_window_get_widget( BASE_WINDOW( window ), "OverrideButton" ))));
+ label2 = g_strdup( gtk_label_get_text( GTK_LABEL( base_window_get_widget( BASE_WINDOW( window ), "OverrideLabel"))));
+ break;
+
+ default:
+ break;
+ }
+
+ if( label1 ){
+ result = g_strdup_printf( "%s\n\n<b>%s</b>\n\n%s", text, label1, label2 );
+ g_free( label2 );
+ g_free( label1 );
+ }
+
+ return( result );
+}
+
+/*
+ * do import here
+ */
+static void
+assistant_apply( BaseAssistant *wnd, GtkAssistant *assistant )
+{
+ static const gchar *thisfn = "nact_assistant_import_assistant_apply";
+ NactAssistantImport *window;
+ GtkWidget *chooser;
+ GSList *uris, *is, *msg;
+ NAObjectAction *action;
+ ImportUriStruct *str;
+ GList *items;
+ BaseWindow *mainwnd;
+ gint mode;
+
+ g_debug( "%s: window=%p, assistant=%p", thisfn, ( void * ) wnd, ( void * ) assistant );
+ g_assert( NACT_IS_ASSISTANT_IMPORT( wnd ));
+ window = NACT_ASSISTANT_IMPORT( wnd );
+
+ chooser = base_window_get_widget( BASE_WINDOW( window ), "ImportFileChooser" );
+ uris = gtk_file_chooser_get_uris( GTK_FILE_CHOOSER( chooser ));
+ mode = get_import_mode( window );
+
+ g_object_get( G_OBJECT( wnd ), BASE_WINDOW_PROP_PARENT, &mainwnd, NULL );
+
+ for( is = uris ; is ; is = is->next ){
+
+ msg = NULL;
+ action = nact_xml_reader_import( BASE_WINDOW( window ), ( const gchar * ) is->data, mode, &msg );
+
+ str = g_new0( ImportUriStruct, 1 );
+ str->uri = g_strdup(( const gchar * ) is->data );
+ str->action = action;
+ str->msg = na_utils_duplicate_string_list( msg );
+ na_utils_free_string_list( msg );
+
+ window->private->results = g_slist_prepend( window->private->results, str );
+
+ items = g_list_prepend( NULL, action );
+ nact_iactions_list_insert_items( NACT_IACTIONS_LIST( mainwnd ), items, NULL );
+ na_object_free_items( items );
+ }
+
+ na_utils_free_string_list( uris );
+}
+
static void
prepare_importdone( NactAssistantImport *window, GtkAssistant *assistant, GtkWidget *page )
{
@@ -533,6 +661,7 @@ prepare_importdone( NactAssistantImport *window, GtkAssistant *assistant, GtkWid
GSList *is, *im;
ImportUriStruct *str;
GFile *file;
+ gint mode;
g_debug( "%s: window=%p, assistant=%p, page=%p",
thisfn, ( void * ) window, ( void * ) assistant, ( void * ) page );
@@ -551,7 +680,7 @@ prepare_importdone( NactAssistantImport *window, GtkAssistant *assistant, GtkWid
file = g_file_new_for_uri( str->uri );
bname = g_file_get_basename( file );
g_object_unref( file );
- tmp = g_strdup_printf( "%s\t%s\n\n", text, bname );
+ tmp = g_strdup_printf( "%s\t%s\n", text, bname );
g_free( text );
text = tmp;
g_free( bname );
@@ -563,26 +692,28 @@ prepare_importdone( NactAssistantImport *window, GtkAssistant *assistant, GtkWid
text2 = g_strdup_printf( _( "UUID: %s\t%s" ), uuid, label);
g_free( label );
g_free( uuid );
- tmp = g_strdup_printf( "%s\t\t%s\n\n", text, text2 );
+ tmp = g_strdup_printf( "%s\t\t%s\n", text, text2 );
window->private->actions = g_slist_prepend( window->private->actions, str->action );
} else {
/* i18n: just indicate that the import of this file was unsuccessfull */
text2 = g_strdup( _( "NOT OK" ));
- tmp = g_strdup_printf( "%s\t\t %s\n\n", text, text2 );
+ tmp = g_strdup_printf( "%s\t\t %s\n", text, text2 );
g_free( text2 );
}
g_free( text );
text = tmp;
+ /* add messages if any */
for( im = str->msg ; im ; im = im->next ){
tmp = g_strdup_printf( "%s\t\t%s\n", text, ( const char * ) im->data );
g_free( text );
text = tmp;
}
+ /* add a blank line between two actions */
tmp = g_strdup_printf( "%s\n", text );
g_free( text );
text = tmp;
@@ -591,6 +722,9 @@ prepare_importdone( NactAssistantImport *window, GtkAssistant *assistant, GtkWid
gtk_label_set_markup( GTK_LABEL( page ), text );
g_free( text );
+ mode = get_import_mode( window );
+ base_iprefs_set_int( BASE_WINDOW( window ), IPREFS_IMPORT_ACTIONS_IMPORT_MODE, mode );
+
gtk_assistant_set_page_complete( assistant, page, TRUE );
base_assistant_set_warn_on_cancel( BASE_ASSISTANT( window ), FALSE );
}
diff --git a/src/nact/nact-tree-model.c b/src/nact/nact-tree-model.c
index 33cd5cd..5f732b4 100644
--- a/src/nact/nact-tree-model.c
+++ b/src/nact/nact-tree-model.c
@@ -133,6 +133,14 @@ typedef struct {
}
ntmSearchStruct;
+typedef struct {
+ GtkTreeModel *store;
+ gchar *id;
+ gboolean found;
+ GtkTreeIter *iter;
+}
+ ntmSearchIdStruct;
+
static GtkTreeModelFilterClass *st_parent_class = NULL;
static GType register_type( void );
@@ -153,6 +161,7 @@ static void insert_get_iters_menu( GtkTreeModel *model, const NAObject
static void insert_before_get_iters( GtkTreeModel *model, GtkTreePath *select_path, const NAObject *object, GtkTreeIter *parent_iter, gboolean *has_parent_iter, GtkTreeIter *sibling_iter, gboolean *has_sibling_iter, NAObject **parent_object );
static void insert_before_parent_get_iters( GtkTreeModel *model, GtkTreePath *select_path, const NAObject *object, GtkTreeIter *parent_iter, gboolean *has_parent_iter, GtkTreeIter *sibling_iter, gboolean *has_sibling_iter, NAObject **parent_object );
static void insert_as_last_child_get_iters( GtkTreeModel *model, GtkTreePath *select_path, const NAObject *object, GtkTreeIter *parent_iter, gboolean *has_parent_iter, GtkTreeIter *sibling_iter, gboolean *has_sibling_iter, NAObject **parent_object );
+static void remove_if_exists( NactTreeModel *model, GtkTreeModel *store, const NAObject *object );
static GList *add_parent( GList *parents, GtkTreeModel *store, GtkTreeIter *obj_iter, GtkTreePath *obj_path );
static void append_item( GtkTreeStore *model, GtkTreeView *treeview, GtkTreeIter *parent, GtkTreeIter *iter, const NAObject *object );
@@ -162,6 +171,8 @@ static void iter_on_store( NactTreeModel *model, GtkTreeModel *store,
static gboolean iter_on_store_item( NactTreeModel *model, GtkTreeModel *store, GtkTreeIter *iter, FnIterOnStore fn, gpointer user_data );
static gboolean search_for_object( NactTreeModel *model, GtkTreeModel *store, const NAObject *object, GtkTreeIter *iter );
static gboolean search_for_objet_iter( NactTreeModel *model, GtkTreePath *path, NAObject *object, ntmSearchStruct *ntm );
+static gboolean search_for_object_id( NactTreeModel *model, GtkTreeModel *store, const NAObject *object, GtkTreeIter *iter );
+static gboolean search_for_object_id_iter( NactTreeModel *model, GtkTreePath *path, NAObject *object, ntmSearchIdStruct *ntm );
static gboolean imulti_drag_source_row_draggable( EggTreeMultiDragSource *drag_source, GList *path_list );
static gboolean imulti_drag_source_drag_data_get( EggTreeMultiDragSource *drag_source, GdkDragContext *context, GtkSelectionData *selection_data, GList *path_list, guint info );
@@ -707,6 +718,8 @@ nact_tree_model_insert( NactTreeModel *model, const NAObject *object, GtkTreePat
has_sibling_iter = FALSE;
*obj_parent = NA_OBJECT( object );
+ remove_if_exists( model, store, object );
+
if( path ){
gtk_tree_model_get_iter( GTK_TREE_MODEL( model ), &select_iter, path );
gtk_tree_model_get( GTK_TREE_MODEL( model ), &select_iter, IACTIONS_LIST_NAOBJECT_COLUMN, &select_object, -1 );
@@ -715,15 +728,15 @@ nact_tree_model_insert( NactTreeModel *model, const NAObject *object, GtkTreePat
g_return_val_if_fail( NA_IS_OBJECT( select_object ), NULL );
if( NA_IS_OBJECT_ACTION( object )){
- insert_get_iters_action( GTK_TREE_MODEL( store ), select_object, path, object, &parent_iter, &has_parent_iter, &sibling_iter, &has_sibling_iter, obj_parent );
+ insert_get_iters_action( store, select_object, path, object, &parent_iter, &has_parent_iter, &sibling_iter, &has_sibling_iter, obj_parent );
}
if( NA_IS_OBJECT_PROFILE( object )){
- insert_get_iters_profile( GTK_TREE_MODEL( store ), select_object, path, object, &parent_iter, &has_parent_iter, &sibling_iter, &has_sibling_iter, obj_parent );
+ insert_get_iters_profile( store, select_object, path, object, &parent_iter, &has_parent_iter, &sibling_iter, &has_sibling_iter, obj_parent );
}
if( NA_IS_OBJECT_MENU( object )){
- insert_get_iters_menu( GTK_TREE_MODEL( store ), select_object, path, object, &parent_iter, &has_parent_iter, &sibling_iter, &has_sibling_iter, obj_parent );
+ insert_get_iters_menu( store, select_object, path, object, &parent_iter, &has_parent_iter, &sibling_iter, &has_sibling_iter, obj_parent );
}
g_object_unref( select_object );
@@ -891,6 +904,21 @@ insert_as_last_child_get_iters( GtkTreeModel *model, GtkTreePath *select_path, c
g_object_unref( *parent_object );
}
+/*
+ * if the object, identified by its uuid, already exists, then remove it first
+ */
+static void
+remove_if_exists( NactTreeModel *model, GtkTreeModel *store, const NAObject *object )
+{
+ GtkTreeIter iter;
+
+ if( NA_IS_OBJECT_ITEM( object )){
+ if( search_for_object_id( model, store, object, &iter )){
+ gtk_tree_store_remove( GTK_TREE_STORE( store ), &iter );
+ }
+ }
+}
+
void
nact_tree_model_iter( NactTreeModel *model, FnIterOnStore fn, gpointer user_data )
{
@@ -1107,6 +1135,50 @@ search_for_objet_iter( NactTreeModel *model, GtkTreePath *path, NAObject *object
return( ntm->found );
}
+static gboolean
+search_for_object_id( NactTreeModel *model, GtkTreeModel *store, const NAObject *object, GtkTreeIter *result_iter )
+{
+ gboolean found = FALSE;
+ ntmSearchIdStruct *ntm;
+ GtkTreeIter iter;
+
+ ntm = g_new0( ntmSearchIdStruct, 1 );
+ ntm->store = store;
+ ntm->id = na_object_get_id( object );
+ ntm->found = FALSE;
+ ntm->iter = &iter;
+
+ iter_on_store( model, store, NULL, ( FnIterOnStore ) search_for_object_id_iter, ntm );
+
+ if( ntm->found ){
+ found = TRUE;
+ memcpy( result_iter, ntm->iter, sizeof( GtkTreeIter ));
+ }
+
+ g_free( ntm->id );
+ g_free( ntm );
+ return( found );
+}
+
+static gboolean
+search_for_object_id_iter( NactTreeModel *model, GtkTreePath *path, NAObject *object, ntmSearchIdStruct *ntm )
+{
+ gchar *id;
+
+ id = na_object_get_id( object );
+
+ if( !g_ascii_strcasecmp( id, ntm->id )){
+ if( gtk_tree_model_get_iter( ntm->store, ntm->iter, path )){
+ ntm->found = TRUE;
+ }
+ }
+
+ g_free( id );
+
+ /* stop iteration when found */
+ return( ntm->found );
+}
+
/*
* all rows are draggable
*/
diff --git a/src/nact/nact-xml-reader.c b/src/nact/nact-xml-reader.c
index fcdd7cd..939d367 100644
--- a/src/nact/nact-xml-reader.c
+++ b/src/nact/nact-xml-reader.c
@@ -62,9 +62,11 @@ struct NactXMLReaderClassPrivate {
struct NactXMLReaderPrivate {
gboolean dispose_has_run;
BaseWindow *window;
+ gint import_mode;
NAObjectAction *action; /* the action that we will return, or NULL */
GSList *messages;
gboolean uuid_set; /* set at first uuid, then checked against */
+ gboolean relabel; /* renumbered action: set a 'renumbered' label */
/* following values are reset at each schema/entry node
*/
@@ -156,7 +158,8 @@ static gchar *get_uuid_from_key( NactXMLReader *reader, const gchar *key, guin
static gboolean is_uuid_valid( const gchar *uuid );
static gchar *get_entry_from_key( const gchar *key );
static void free_reader_values( NactXMLReader *reader );
-static gboolean action_exists( NactXMLReader *reader, const gchar *uuid );
+static gboolean manage_import_mode( NactXMLReader *reader );
+static void relabel( NactXMLReader *reader );
GType
nact_xml_reader_get_type( void )
@@ -228,6 +231,7 @@ instance_init( GTypeInstance *instance, gpointer klass )
self->private->action = NULL;
self->private->messages = NULL;
self->private->uuid_set = FALSE;
+ self->private->relabel = FALSE;
self->private->profile = NULL;
self->private->locale_waited = FALSE;
self->private->entry = NULL;
@@ -288,10 +292,18 @@ gconf_reader_new( void )
}
/**
+ * nact_xml_reader_import:
+ * window: the #NactAssistantImport instance.
+ * @uri: the uri of the file to import.
+ * import_mode: the import mode.
+ * msg: a list of error messages which may be set by this function.
+ *
* Import the specified file as an NAAction XML description.
+ *
+ * Returns: the imported action, or NULL.
*/
NAObjectAction *
-nact_xml_reader_import( BaseWindow *window, const gchar *uri, GSList **msg )
+nact_xml_reader_import( BaseWindow *window, const gchar *uri, gint import_mode, GSList **msg )
{
static const gchar *thisfn = "nact_xml_reader_import";
NAObjectAction *action = NULL;
@@ -303,8 +315,9 @@ nact_xml_reader_import( BaseWindow *window, const gchar *uri, GSList **msg )
reader = gconf_reader_new();
reader->private->window = window;
+ reader->private->import_mode = import_mode;
- g_assert( BASE_IS_ASSISTANT( window ));
+ g_return_val_if_fail( BASE_IS_ASSISTANT( window ), NULL );
doc = xmlParseFile( uri );
@@ -426,6 +439,10 @@ gconf_reader_parse_schemalist( NactXMLReader *reader, xmlNode *schema )
g_free( label );
}
+ if( ok && reader->private->relabel ){
+ relabel( reader );
+ }
+
if( !ok ){
g_object_unref( reader->private->action );
reader->private->action = NULL;
@@ -614,13 +631,13 @@ gconf_reader_parse_applyto( NactXMLReader *reader, xmlNode *node )
if( ret ){
if( !reader->private->uuid_set ){
- if( action_exists( reader, uuid )){
- add_message( reader, ERR_UUID_ALREADY_EXISTS, uuid );
- ret = FALSE;
+ na_object_set_id( reader->private->action, uuid );
- } else {
- na_object_set_id( reader->private->action, uuid );
+ if( manage_import_mode( reader )){
reader->private->uuid_set = TRUE;
+ } else {
+ add_message( reader, ERR_UUID_ALREADY_EXISTS, uuid, node->line );
+ ret = FALSE;
}
} else {
@@ -836,6 +853,7 @@ gconf_reader_parse_entrylist( NactXMLReader *reader, xmlNode *entrylist )
static const gchar *thisfn = "gconf_reader_parse_entrylist";
xmlChar *path;
gchar *uuid, *label;
+ gboolean ok;
g_debug( "%s: reader=%p, entrylist=%p", thisfn, ( void * ) reader, ( void * ) entrylist );
@@ -845,19 +863,22 @@ gconf_reader_parse_entrylist( NactXMLReader *reader, xmlNode *entrylist )
/*g_debug( "%s: uuid=%s", thisfn, uuid );*/
if( is_uuid_valid( uuid )){
- if( action_exists( reader, uuid )){
- add_message( reader, ERR_UUID_ALREADY_EXISTS, uuid, entrylist->line );
- } else {
- na_object_set_id( reader->private->action, uuid );
+ na_object_set_id( reader->private->action, uuid );
+
+ if( manage_import_mode( reader )){
reader->private->uuid_set = TRUE;
+ } else {
+ add_message( reader, ERR_UUID_ALREADY_EXISTS, uuid, entrylist->line );
}
+
} else {
add_message( reader, ERR_NOT_AN_UUID, uuid, entrylist->line );
}
g_free( uuid );
xmlFree( path );
+ ok = TRUE;
if( reader->private->uuid_set ){
xmlNode *iter;
@@ -882,14 +903,20 @@ gconf_reader_parse_entrylist( NactXMLReader *reader, xmlNode *entrylist )
label = na_object_get_label( reader->private->action );
if( !label || !g_utf8_strlen( label, -1 )){
add_message( reader, ERR_ACTION_LABEL_NOT_FOUND );
+ ok = FALSE;
}
g_free( label );
+ if( ok && reader->private->relabel ){
+ relabel( reader );
+ }
+
} else {
g_object_unref( reader->private->action );
reader->private->action = NULL;
}
}
+
static gboolean
gconf_reader_parse_entry( NactXMLReader *reader, xmlNode *entry )
{
@@ -1245,10 +1272,66 @@ free_reader_values( NactXMLReader *reader )
}
}
+/*
+ * returns TRUE if we can safely insert the action
+ * - the uuid doesn't already exist
+ * - the uuid already exist, but import mode is renumber
+ * - the uuid already exists, but import mode is override
+ */
static gboolean
-action_exists( NactXMLReader *reader, const gchar *uuid )
+manage_import_mode( NactXMLReader *reader )
+{
+ gboolean exists;
+ gchar *uuid;
+ BaseApplication *appli;
+ NactMainWindow *main_window;
+ gboolean ret;
+
+ appli = base_window_get_application( BASE_WINDOW( reader->private->window ));
+ main_window = NACT_MAIN_WINDOW( base_application_get_main_window( appli ));
+
+ uuid = na_object_get_id( reader->private->action );
+ exists = nact_main_window_action_exists( main_window, uuid );
+ g_free( uuid );
+
+ if( !exists ){
+ return( TRUE );
+ }
+
+ switch( reader->private->import_mode ){
+ case RENUMBER_MODE:
+ na_object_set_new_id( reader->private->action );
+ reader->private->relabel = TRUE;
+ ret = TRUE;
+ break;
+
+ case OVERRIDE_MODE:
+ ret = TRUE;
+ break;
+
+ case NO_IMPORT_MODE:
+ default:
+ ret = FALSE;
+ }
+
+ return( ret );
+}
+
+/*
+ * set a new label because the action has been renumbered
+ */
+static void
+relabel( NactXMLReader *reader )
{
- BaseApplication *appli = base_window_get_application( BASE_WINDOW( reader->private->window ));
- NactMainWindow *main_window = NACT_MAIN_WINDOW( base_application_get_main_window( appli ));
- return( nact_main_window_action_exists( main_window, uuid ));
+ gchar *label, *tmp;
+
+ label = na_object_get_label( reader->private->action );
+
+ /* i18n: the action has been renumbered during import operation */
+ tmp = g_strdup_printf( "%s %s", label, _( "(renumbered)" ));
+
+ na_object_set_label( reader->private->action, tmp );
+
+ g_free( tmp );
+ g_free( label );
}
diff --git a/src/nact/nact-xml-reader.h b/src/nact/nact-xml-reader.h
index a6926cc..159e3f7 100644
--- a/src/nact/nact-xml-reader.h
+++ b/src/nact/nact-xml-reader.h
@@ -67,9 +67,17 @@ typedef struct {
}
NactXMLReaderClass;
+/* import mode of an existing uuid
+ */
+enum {
+ NO_IMPORT_MODE = 1,
+ RENUMBER_MODE,
+ OVERRIDE_MODE
+};
+
GType nact_xml_reader_get_type( void );
-NAObjectAction *nact_xml_reader_import( BaseWindow *window, const gchar *uri, GSList **msg );
+NAObjectAction *nact_xml_reader_import( BaseWindow *window, const gchar *uri, gint mode, GSList **msg );
G_END_DECLS
diff --git a/src/nact/nautilus-actions-config-tool.ui b/src/nact/nautilus-actions-config-tool.ui
index f065a22..0918be4 100644
--- a/src/nact/nautilus-actions-config-tool.ui
+++ b/src/nact/nautilus-actions-config-tool.ui
@@ -1009,13 +1009,192 @@ Defining several profiles lets you have several commands, each applying with a d
</packing>
</child>
<child>
- <object class="GtkFileChooserWidget" id="filechooserwidget1">
+ <object class="GtkVBox" id="vbox18">
<property name="visible">True</property>
- <property name="use_preview_label">False</property>
- <property name="local_only">False</property>
- <property name="select_multiple">True</property>
- <property name="preview_widget_active">False</property>
+ <child>
+ <object class="GtkFileChooserWidget" id="ImportFileChooser">
+ <property name="visible">True</property>
+ <property name="preview_widget_active">False</property>
+ <property name="local_only">False</property>
+ <property name="select_multiple">True</property>
+ <property name="use_preview_label">False</property>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="title">Selecting what files to import</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox19">
+ <property name="visible">True</property>
+ <property name="border_width">10</property>
+ <property name="spacing">10</property>
+ <child>
+ <object class="GtkVBox" id="vbox20">
+ <property name="visible">True</property>
+ <property name="spacing">10</property>
+ <child>
+ <object class="GtkLabel" id="label38">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">What should I do when importing an action whose UUID already exists ?</property>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox21">
+ <property name="visible">True</property>
+ <property name="spacing">10</property>
+ <child>
+ <object class="GtkVBox" id="vbox22">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkRadioButton" id="NoImportButton">
+ <property name="label" translatable="yes">Do not import the action which UUID already exists</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox5">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="NoImportLabel">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="xpad">14</property>
+ <property name="label" translatable="yes">This used to be the historical behavior.
+The selected file will be marked as "NOT OK" in the Summary page.
+The existing action will not be modified.</property>
+ </object>
+ <packing>
+ <property name="padding">4</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox23">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkRadioButton" id="RenumberButton">
+ <property name="label" translatable="yes">Allocate a new identifiant for the imported action</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">NoImportButton</property>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox6">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="RenumberLabel">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="xpad">14</property>
+ <property name="label" translatable="yes">The selected file will be imported with a slightly modified label indicating the renumbering.
+The existing action will not be modified.</property>
+ <property name="wrap">True</property>
+ </object>
+ <packing>
+ <property name="padding">4</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVBox" id="vbox24">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkRadioButton" id="OverrideButton">
+ <property name="label" translatable="yes">Override the existing action</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">NoImportButton</property>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox7">
+ <property name="visible">True</property>
+ <child>
+ <object class="GtkLabel" id="OverrideLabel">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="xpad">14</property>
+ <property name="label" translatable="yes">The action found in the selected file will silently override the current action which has the same identifiant.
+Be warned: you will not be prompted another time. This mode may be dangerous.</property>
+ <property name="wrap">True</property>
+ </object>
+ <packing>
+ <property name="padding">4</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
</object>
+ <packing>
+ <property name="title">Managing duplicates</property>
+ </packing>
</child>
<child>
<object class="GtkLabel" id="label17">
@@ -1023,6 +1202,7 @@ Defining several profiles lets you have several commands, each applying with a d
</object>
<packing>
<property name="page_type">confirm</property>
+ <property name="title">Summary</property>
</packing>
</child>
<child>
@@ -1031,6 +1211,7 @@ Defining several profiles lets you have several commands, each applying with a d
</object>
<packing>
<property name="page_type">summary</property>
+ <property name="title">Import is done</property>
</packing>
</child>
</object>
@@ -1534,16 +1715,16 @@ Defining several profiles lets you have several commands, each applying with a d
</object>
<object class="GtkSizeGroup" id="CommandLabelSizeGroup">
<widgets>
- <widget name="CommandExamplePreLabel"/>
- <widget name="CommandParametersLabel"/>
- <widget name="CommandPathLabel"/>
<widget name="ProfileLabelLabel"/>
+ <widget name="CommandPathLabel"/>
+ <widget name="CommandParametersLabel"/>
+ <widget name="CommandExamplePreLabel"/>
</widgets>
</object>
<object class="GtkSizeGroup" id="CommandButtonSizeGroup">
<widgets>
- <widget name="CommandLegendButton"/>
<widget name="CommandPathButton"/>
+ <widget name="CommandLegendButton"/>
</widgets>
</object>
</interface>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]