[nautilus-actions] Improve delete process in case of an item cannot be deleted



commit a1bcc7cff820bfbc3036946761d9a039e452f888
Author: Pierre Wieser <pwieser trychlos org>
Date:   Tue Dec 14 21:28:40 2010 +0100

    Improve delete process in case of an item cannot be deleted

 ChangeLog                         |   13 +++++++
 src/core/na-pivot.c               |    5 +++
 src/nact/nact-main-menubar-file.c |   50 +++++++++++++++++++++++++---
 src/nact/nact-main-window.c       |   65 ++++++++++++++++++++++++++++--------
 src/nact/nact-main-window.h       |    2 +-
 src/nact/nact-window.c            |   40 ++++++++++------------
 src/nact/nact-window.h            |    4 +-
 7 files changed, 133 insertions(+), 46 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 8413c61..086ce68 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2010-12-14 Pierre Wieser <pwieser trychlos org>
+
+	* src/core/na-pivot.c (na_pivot_write_level_zero): Improve comment.
+
+	* src/nact/nact-main-menubar-file.c (nact_main_menubar_file_save_items):
+	Improve delete process, restoring items which cannot have been deleted.
+
+	* src/nact/nact-main-window.c:
+	* src/nact/nact-main-window.h (nact_main_window_remove_deleted):
+	* src/nact/nact-window.c:
+	* src/nact/nact-window.h (nact_window_delete_item):
+	Improve delete process, returning a status and an error message.
+
 2010-12-13 Pierre Wieser <pwieser trychlos org>
 
 	* src/nact/nact-main-menubar-file.c (nact_main_menubar_file_save_items):
diff --git a/src/core/na-pivot.c b/src/core/na-pivot.c
index fb1cef2..49ebf60 100644
--- a/src/core/na-pivot.c
+++ b/src/core/na-pivot.c
@@ -693,6 +693,11 @@ time_val_diff( const GTimeVal *recent, const GTimeVal *old )
  *
  * Returns: %TRUE if successfully written (i.e. writable, not locked,
  * and so on), %FALSE else.
+ *
+ * @messages #GSList is only filled up in case of an error has occured.
+ * If there is no error (na_pivot_write_level_zero() returns %TRUE), then
+ * the caller may safely assume that @messages is returned in the same
+ * state that it has been provided.
  */
 gboolean
 na_pivot_write_level_zero( const NAPivot *pivot, GList *items, GSList **messages )
diff --git a/src/nact/nact-main-menubar-file.c b/src/nact/nact-main-menubar-file.c
index 5acbe91..0baabdd 100644
--- a/src/nact/nact-main-menubar-file.c
+++ b/src/nact/nact-main-menubar-file.c
@@ -49,6 +49,7 @@ static guint  st_event_autosave   = 0;
 static gchar *st_save_error       = N_( "Save error" );
 static gchar *st_save_warning     = N_( "Some items may not have been saved" );
 static gchar *st_level_zero_write = N_( "Unable to rewrite the level-zero items list" );
+static gchar *st_delete_error     = N_( "Some items cannot have been deleted" );
 
 static gboolean save_item( NactMainWindow *window, NAUpdater *updater, NAObjectItem *item, GSList **messages );
 static gboolean autosave_callback( NactMainWindow *window );
@@ -233,7 +234,7 @@ nact_main_menubar_file_on_new_profile( GtkAction *gtk_action, NactMainWindow *wi
  * Saving is not only saving modified items, but also saving hierarchy
  * (and order if alpha order is not set).
  *
- * This is the same function that #nact_main_menubar_file_save_items(), just with
+ * This is the same function that nact_main_menubar_file_save_items(), just with
  * different arguments.
  */
 void
@@ -254,8 +255,29 @@ nact_main_menubar_file_on_save( GtkAction *gtk_action, NactMainWindow *window )
  * @window: the #NactMainWindow main window.
  *
  * Save items.
- * This is the same function that #nact_main_menubar_file_on_save(), just with
- * different arguments.
+ * This is the same function that nact_main_menubar_file_on_save(), just
+ * with different arguments.
+ *
+ * Synopsis:
+ * - rewrite the level-zero items list
+ * - delete the items which are marked to be deleted
+ * - rewrite (i.e. delete/write) updated items
+ *
+ * The difficulty here is that some sort of pseudo-transactionnal process
+ * must be setup:
+ *
+ * - if the level-zero items list cannot be updated, then an error message
+ *   is displayed, and we abort the whole processus
+ *
+ * - if some items cannot be actually deleted, then an error message is
+ *   displayed, and the whole processus is aborted;
+ *   plus:
+ *   a/ items which have not been deleted must be restored (maybe marked
+ *      as deleted ?) -> so these items are modified
+ *   b/ the level-zero list must be updated with these restored items
+ *      and reset modified
+ *
+ * - idem if some items cannot be actually rewritten...
  */
 void
 nact_main_menubar_file_save_items( NactMainWindow *window )
@@ -288,7 +310,6 @@ nact_main_menubar_file_save_items( NactMainWindow *window )
 	messages = NULL;
 
 	if( !na_pivot_write_level_zero( NA_PIVOT( updater ), items, &messages )){
-
 		if( g_slist_length( messages )){
 			msg = na_core_utils_slist_join_at_end( messages, "\n" );
 		} else {
@@ -306,7 +327,17 @@ nact_main_menubar_file_save_items( NactMainWindow *window )
 	/* remove deleted items
 	 * so that new actions with same id do not risk to be deleted later
 	 */
-	nact_main_window_remove_deleted( window );
+	if( !nact_main_window_remove_deleted( window, &messages )){
+		if( g_slist_length( messages )){
+			msg = na_core_utils_slist_join_at_end( messages, "\n" );
+		} else {
+			msg = g_strdup( st_delete_error );
+		}
+		base_window_error_dlg( BASE_WINDOW( window ), GTK_MESSAGE_ERROR, st_save_error, msg );
+		g_free( msg );
+		na_core_utils_slist_free( messages );
+		return;
+	}
 
 	/* recursively save the modified items
 	 * check is useless here if item was not modified, but not very costly;
@@ -384,6 +415,7 @@ save_item( NactMainWindow *window, NAUpdater *updater, NAObjectItem *item, GSLis
 	NAIOProvider *provider_before;
 	NAIOProvider *provider_after;
 	GList *subitems, *it;
+	gchar *msg;
 
 	g_return_val_if_fail( NACT_IS_MAIN_WINDOW( window ), FALSE );
 	g_return_val_if_fail( NA_IS_UPDATER( updater ), FALSE );
@@ -394,8 +426,9 @@ save_item( NactMainWindow *window, NAUpdater *updater, NAObjectItem *item, GSLis
 
 	if( na_object_is_modified( item )){
 		ret = FALSE;
+		msg = NULL;
 
-		if( nact_window_save_item( NACT_WINDOW( window ), item )){
+		if( nact_window_save_item( NACT_WINDOW( window ), item, &msg )){
 
 			if( NA_IS_OBJECT_ACTION( item )){
 				na_object_reset_last_allocated( item );
@@ -407,6 +440,11 @@ save_item( NactMainWindow *window, NAUpdater *updater, NAObjectItem *item, GSLis
 			if( provider_after != provider_before ){
 				g_signal_emit_by_name( window, TAB_UPDATABLE_SIGNAL_PROVIDER_CHANGED, item );
 			}
+
+		} else {
+			/* TODO:
+			 * add the error message to the GSList
+			 */
 		}
 	}
 
diff --git a/src/nact/nact-main-window.c b/src/nact/nact-main-window.c
index d8e7d8d..2fbaae9 100644
--- a/src/nact/nact-main-window.c
+++ b/src/nact/nact-main-window.c
@@ -161,7 +161,7 @@ static void     instance_set_property( GObject *object, guint property_id, const
 static void     instance_dispose( GObject *application );
 static void     instance_finalize( GObject *application );
 
-static void     actually_delete_item( NactMainWindow *window, NAObject *item, NAUpdater *updater );
+static gboolean actually_delete_item( NactMainWindow *window, NAObject *item, NAUpdater *updater, GList **not_deleted, GSList **messages );
 
 static gchar   *base_get_toplevel_name( const BaseWindow *window );
 static gchar   *base_get_iprefs_window_id( const BaseWindow *window );
@@ -978,34 +978,57 @@ nact_main_window_reload( NactMainWindow *window )
 /**
  * nact_main_window_remove_deleted:
  * @window: this #NactMainWindow instance.
+ * @messages: a pointer to a #GSList of error messages.
  *
  * Removes the deleted items from the underlying I/O storage subsystem.
+ *
+ * Each item of <structfield>NactMainWindow::private::deleted</structfield>
+ * #GList may actually itself be a tree (e.g. a #NAObjectMenu). The embedded
+ * items will be recursivelly removed, starting from the root.
+ *
+ * Returns: %TRUE if all candidate items have been successfully deleted,
+ * %FALSE else.
+ *
+ * @messages #GSList is only filled up in case of an error has occured.
+ * If there is no error (nact_main_window_remove_deleted() returns %TRUE),
+ * then the caller may safely assume that @messages is returned in the
+ * same state that it has been provided.
  */
-void
-nact_main_window_remove_deleted( NactMainWindow *window )
+gboolean
+nact_main_window_remove_deleted( NactMainWindow *window, GSList **messages )
 {
+	gboolean delete_ok = TRUE;
 	NactApplication *application;
 	NAUpdater *updater;
 	GList *it;
 	NAObject *item;
+	GList *not_deleted;
 
-	g_return_if_fail( NACT_IS_MAIN_WINDOW( window ));
+	g_return_val_if_fail( NACT_IS_MAIN_WINDOW( window ), FALSE );
 
 	if( !window->private->dispose_has_run ){
 
 		application = NACT_APPLICATION( base_window_get_application( BASE_WINDOW( window )));
 		updater = nact_application_get_updater( application );
+		not_deleted = NULL;
 
 		for( it = window->private->deleted ; it ; it = it->next ){
 			item = NA_OBJECT( it->data );
-			actually_delete_item( window, item, updater );
+			delete_ok = actually_delete_item( window, item, updater, &not_deleted, messages );
 		}
 
 		na_object_unref_items( window->private->deleted );
 		window->private->deleted = NULL;
 
 		setup_dialog_title( window );
+
+		if( g_list_length( not_deleted )){
+			nact_iactions_list_bis_insert_items( NACT_IACTIONS_LIST( window ), not_deleted, NULL );
+			na_object_unref_items( not_deleted );
+		}
 	}
+
+	return( delete_ok );
 }
 
 /*
@@ -1013,31 +1036,43 @@ nact_main_window_remove_deleted( NactMainWindow *window )
  * action has been marked as modified when the profile has been deleted,
  * and thus updated in the storage subsystem as well as in the pivot
  */
-static void
-actually_delete_item( NactMainWindow *window, NAObject *item, NAUpdater *updater )
+static gboolean
+actually_delete_item( NactMainWindow *window, NAObject *item, NAUpdater *updater, GList **not_deleted, GSList **messages )
 {
+	gboolean delete_ok = TRUE;
 	GList *items, *it;
 	NAObject *origin;
+	gchar *msg;
 
 	g_debug( "nact_main_window_actually_delete_item: item=%p (%s)",
 			( void * ) item, G_OBJECT_TYPE_NAME( item ));
 
 	if( NA_IS_OBJECT_ITEM( item )){
-		nact_window_delete_item( NACT_WINDOW( window ), NA_OBJECT_ITEM( item ));
+		msg = NULL;
+		delete_ok = nact_window_delete_item( NACT_WINDOW( window ), NA_OBJECT_ITEM( item ), &msg );
 
-		if( NA_IS_OBJECT_MENU( item )){
+		if( !delete_ok ){
+			*messages = g_slist_append( *messages, msg );
+			*not_deleted = g_list_append( *not_deleted, na_object_ref( item ));
+			g_free( msg );
+
+		} else if( NA_IS_OBJECT_MENU( item )){
 			items = na_object_get_items( item );
-			for( it = items ; it ; it = it->next ){
-				actually_delete_item( window, NA_OBJECT( it->data ), updater );
+			for( it = items ; delete_ok && it ; it = it->next ){
+				delete_ok &= actually_delete_item( window, NA_OBJECT( it->data ), updater, not_deleted, messages );
 			}
 		}
 
-		origin = ( NAObject * ) na_object_get_origin( item );
-		if( origin ){
-			na_updater_remove_item( updater, origin );
-			g_object_unref( origin );
+		if( delete_ok ){
+			origin = ( NAObject * ) na_object_get_origin( item );
+			if( origin ){
+				na_updater_remove_item( updater, origin );
+				g_object_unref( origin );
+			}
 		}
 	}
+
+	return( delete_ok );
 }
 
 static gchar *
diff --git a/src/nact/nact-main-window.h b/src/nact/nact-main-window.h
index ae3403d..a4a643f 100644
--- a/src/nact/nact-main-window.h
+++ b/src/nact/nact-main-window.h
@@ -82,7 +82,7 @@ NAObjectItem   *nact_main_window_get_item          ( const NactMainWindow *windo
 gboolean        nact_main_window_has_modified_items( const NactMainWindow *window );
 void            nact_main_window_move_to_deleted   ( NactMainWindow *window, GList *items );
 void            nact_main_window_reload            ( NactMainWindow *window );
-void            nact_main_window_remove_deleted    ( NactMainWindow *window );
+gboolean        nact_main_window_remove_deleted    ( NactMainWindow *window, GSList **messages );
 
 G_END_DECLS
 
diff --git a/src/nact/nact-window.c b/src/nact/nact-window.c
index d40690f..78aff6c 100644
--- a/src/nact/nact-window.c
+++ b/src/nact/nact-window.c
@@ -308,6 +308,7 @@ nact_window_is_item_writable( const NactWindow *window, const NAObjectItem *item
  * nact_window_save_item:
  * @window: this #NactWindow instance.
  * @item: the #NAObjectItem to be saved.
+ * @msg: a pointer to a location where wi may allocate a new error message.
  *
  * Saves a modified item (action or menu) to the I/O storage subsystem.
  *
@@ -315,10 +316,14 @@ nact_window_is_item_writable( const NactWindow *window, const NAObjectItem *item
  *
  * Writing a menu only involves writing its NAObjectItem properties,
  * along with the list and the order of its subitems, but not the
- * subitems themselves (because they may be unmodified)
+ * subitems themselves (because they may be unmodified).
+ *
+ * 2010-12-13 pwi v 3.0.3
+ * As we are displaying a summary of errors from the calling function,
+ * we no more care here of displaying each individual error message.
  */
 gboolean
-nact_window_save_item( NactWindow *window, NAObjectItem *item )
+nact_window_save_item( NactWindow *window, NAObjectItem *item, gchar **msg )
 {
 	static const gchar *thisfn = "nact_window_save_item";
 	gboolean save_ok = FALSE;
@@ -326,7 +331,6 @@ nact_window_save_item( NactWindow *window, NAObjectItem *item )
 	NAUpdater *updater;
 	GSList *messages = NULL;
 	guint ret;
-	gchar *msgerr;
 
 	g_debug( "%s: window=%p, item=%p (%s)", thisfn,
 			( void * ) window, ( void * ) item, G_OBJECT_TYPE_NAME( item ));
@@ -341,23 +345,12 @@ nact_window_save_item( NactWindow *window, NAObjectItem *item )
 		ret = na_updater_write_item( updater, item, &messages );
 		g_debug( "nact_window_save_item: ret=%d", ret );
 
-		msgerr = NULL;
-
 		if( messages ){
-			msgerr = na_core_utils_slist_join_at_end( messages, "\n" );
+			*msg = na_core_utils_slist_join_at_end( messages, "\n" );
 			na_core_utils_slist_free( messages );
 
 		} else if( ret != NA_IIO_PROVIDER_CODE_OK ){
-			msgerr = na_io_provider_get_return_code_label( ret );
-		}
-
-		if( msgerr ){
-			base_window_error_dlg(
-					BASE_WINDOW( window ),
-					GTK_MESSAGE_WARNING,
-					_( "An error has occured when trying to save the item" ),
-					msgerr );
-			g_free( msgerr );
+			*msg = na_io_provider_get_return_code_label( ret );
 		}
 
 		save_ok = ( ret == NA_IIO_PROVIDER_CODE_OK );
@@ -372,9 +365,13 @@ nact_window_save_item( NactWindow *window, NAObjectItem *item )
  * @item: the item (action or menu) to delete.
  *
  * Deleted an item from the I/O storage subsystem.
+ *
+ * 2010-12-13 pwi v 3.0.3
+ * As we are displaying a summary of errors from the calling function,
+ * we no more care here of displaying each individual error message.
  */
 gboolean
-nact_window_delete_item( NactWindow *window, const NAObjectItem *item )
+nact_window_delete_item( NactWindow *window, const NAObjectItem *item, gchar **msg )
 {
 	static const gchar *thisfn = "nact_window_delete_item";
 	gboolean delete_ok = FALSE;
@@ -398,12 +395,11 @@ nact_window_delete_item( NactWindow *window, const NAObjectItem *item )
 		ret = na_updater_delete_item( updater, item, &messages );
 
 		if( messages ){
-			base_window_error_dlg(
-					BASE_WINDOW( window ),
-					GTK_MESSAGE_WARNING,
-					_( "An error has occured when trying to delete the item" ),
-					( const gchar * ) messages->data );
+			*msg = na_core_utils_slist_join_at_end( messages, "\n" );
 			na_core_utils_slist_free( messages );
+
+		} else if( ret != NA_IIO_PROVIDER_CODE_OK ){
+			*msg = na_io_provider_get_return_code_label( ret );
 		}
 
 		delete_ok = ( ret == NA_IIO_PROVIDER_CODE_OK );
diff --git a/src/nact/nact-window.h b/src/nact/nact-window.h
index 22504c8..565242b 100644
--- a/src/nact/nact-window.h
+++ b/src/nact/nact-window.h
@@ -75,8 +75,8 @@ gboolean   nact_window_has_writable_providers( NactWindow *window );
 
 gboolean   nact_window_is_item_writable( const NactWindow *window, const NAObjectItem *item, guint *reason );
 
-gboolean   nact_window_save_item  ( NactWindow *window, NAObjectItem *item );
-gboolean   nact_window_delete_item( NactWindow *window, const NAObjectItem *item );
+gboolean   nact_window_save_item  ( NactWindow *window, NAObjectItem *item, gchar **msgerr );
+gboolean   nact_window_delete_item( NactWindow *window, const NAObjectItem *item, gchar **msgerr );
 
 void       nact_window_count_level_zero_items( GList *items, guint *actions, guint *profiles, guint *menus );
 



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