[Planner Dev] New patch for undo in link/unlink tasks



Hi guys!

Finally here goes a corrected patch for undo/redo in link/unlink tasks.
It uses now the GError framework to show problems to the user and also,
I have changed the task move undo/redo to use it also.

My next goal is to make works undo/redo when you move and link tasks in
which it fails in some scenarios.

Cheers

-- Alvaro
Index: src/planner-cmd-manager.h
===================================================================
RCS file: /cvs/gnome/planner/src/planner-cmd-manager.h,v
retrieving revision 1.3
diff -u -b -B -p -r1.3 planner-cmd-manager.h
Index: src/planner-gantt-chart.h
===================================================================
RCS file: /cvs/gnome/planner/src/planner-gantt-chart.h,v
retrieving revision 1.3
diff -u -b -B -p -r1.3 planner-gantt-chart.h
Index: src/planner-gantt-row.c
===================================================================
RCS file: /cvs/gnome/planner/src/planner-gantt-row.c,v
retrieving revision 1.10
diff -u -b -B -p -r1.10 planner-gantt-row.c
--- src/planner-gantt-row.c	27 Apr 2004 18:58:02 -0000	1.10
+++ src/planner-gantt-row.c	8 May 2004 17:42:31 -0000
@@ -2050,15 +2049,24 @@ gantt_row_event (GnomeCanvasItem *item, 
 			
 			if (target_item && target_item != item) {
 				GError *error = NULL;
+				PlannerCmd        *cmd;
+				PlannerGanttChart *chart;
+				PlannerTaskTree   *tree;
 				
 				task = priv->task;
 				target_task = PLANNER_GANTT_ROW (target_item)->priv->task;
 				
-				if (!mrp_task_add_predecessor (target_task,
+				chart = g_object_get_data (G_OBJECT (item->canvas), "chart");
+				tree = planner_gantt_chart_get_view (chart);
+
+				cmd = planner_task_tree_task_cmd_link (tree,
 							       task,
+								       target_task,
 							       MRP_RELATION_FS,
 							       0,
-							       &error)) {
+								       &error);
+				
+				if (!cmd) {
 					GtkWidget *dialog;
 
 					gnome_canvas_item_ungrab (item, event->button.time);
@@ -2070,7 +2078,6 @@ gantt_row_event (GnomeCanvasItem *item, 
 									 "%s", error->message);
 					gtk_dialog_run (GTK_DIALOG (dialog));
 					gtk_widget_destroy (dialog);
-					
 					g_error_free (error);
 				}
 			}
Index: src/planner-task-tree.c
===================================================================
RCS file: /cvs/gnome/planner/src/planner-task-tree.c,v
retrieving revision 1.23
diff -u -b -B -p -r1.23 planner-task-tree.c
--- src/planner-task-tree.c	2 May 2004 16:21:28 -0000	1.23
+++ src/planner-task-tree.c	8 May 2004 17:42:38 -0000
@@ -157,9 +157,6 @@ static gint        task_tree_parse_time_
 static MrpProject *task_tree_get_project               (PlannerTaskTree      *tree);
 static MrpTask *   task_tree_get_task_from_path        (PlannerTaskTree      *tree,
 							GtkTreePath          *path);
-static PlannerCmd *task_cmd_remove                     (PlannerTaskTree      *tree,
-							GtkTreePath          *path,
-							MrpTask              *task);
 
 
 static GtkTreeViewClass *parent_class = NULL;
@@ -193,7 +190,6 @@ task_cmd_insert_free (PlannerCmd *cmd_ba
 	gtk_tree_path_free (cmd->path);
 	g_object_unref (cmd->task);
 	cmd->task = NULL;
-	g_free (cmd);
 }
 
 static gboolean
@@ -329,13 +325,9 @@ task_cmd_edit_property_free (PlannerCmd 
 	
 	cmd = (TaskCmdEditProperty*) cmd_base;
 
-	g_free (cmd_base->label);
 	g_free (cmd->property);
 	g_value_unset (cmd->value);
 	g_value_unset (cmd->old_value);
-	g_free (cmd);
-
-	
 }
 
 static PlannerCmd *
@@ -701,10 +693,7 @@ task_cmd_remove_free (PlannerCmd *cmd_ba
 	g_list_foreach (cmd->assignments, (GFunc) g_object_unref, NULL);
 	g_list_free (cmd->assignments);
 		
-	g_free (cmd_base->label);
 	gtk_tree_path_free (cmd->path);
-	
-	g_free (cmd);
 }
 
 static PlannerCmd *
@@ -781,8 +770,6 @@ task_cmd_constraint_free (PlannerCmd *cm
 	g_object_unref (cmd->task);
 	g_free (cmd->constraint);
 	g_free (cmd->constraint_old);
-
-	g_free (cmd);
 }
 
 
@@ -828,16 +815,17 @@ typedef struct {
 	MrpTask    *sibling;
 	gboolean    before;
 	gboolean    before_old;
-	gboolean    success;
-} TaskCmdTaskMove;
+	GError     *error;
+} TaskCmdMove;
 
 static gboolean
-task_cmd_task_move_do (PlannerCmd *cmd_base)
+task_cmd_move_do (PlannerCmd *cmd_base)
 {
-	TaskCmdTaskMove *cmd;
-	GError          *error;
+	TaskCmdMove *cmd;
+	GError      *error = NULL;
+	gboolean     retval;
 
-	cmd = (TaskCmdTaskMove*) cmd_base;
+	cmd = (TaskCmdMove*) cmd_base;
 
 	if (g_getenv ("PLANNER_DEBUG_UNDO_TASK")) {
 		if (cmd->before) {
@@ -853,28 +841,28 @@ task_cmd_task_move_do (PlannerCmd *cmd_b
 		}
 	}
 
-	cmd->success = mrp_project_move_task (cmd->project,
+	retval = mrp_project_move_task (cmd->project,
 					 cmd->task,
 					 cmd->sibling,
 					 cmd->parent,
 					 cmd->before,
 					 &error);
 
-	return TRUE;
+	if (!retval) {
+		cmd->error = error;
+	}
+
+	return retval;
 }
 
 static void
-task_cmd_task_move_undo (PlannerCmd *cmd_base)
+task_cmd_move_undo (PlannerCmd *cmd_base)
 {
-	TaskCmdTaskMove *cmd;
+	TaskCmdMove *cmd;
 	GError          *error;
+	gboolean     result;
 
-	cmd = (TaskCmdTaskMove*) cmd_base;
-
-	if (!cmd->success) {
-		return;
-	}
-	
+	cmd = (TaskCmdMove*) cmd_base;
 
 	if (g_getenv ("PLANNER_DEBUG_UNDO_TASK")) {
 		if (cmd->before_old) {
@@ -890,22 +878,21 @@ task_cmd_task_move_undo (PlannerCmd *cmd
 		}
 	}
 
-	cmd->success = mrp_project_move_task (cmd->project,
+	result = mrp_project_move_task (cmd->project,
 					 cmd->task,
 					 cmd->sibling,
 					 cmd->parent_old,
 					 cmd->before_old,
 					 &error);
-
-	g_assert (cmd->success);
+	g_assert (result);
 }
 
 static void
-task_cmd_task_move_free (PlannerCmd *cmd_base)
+task_cmd_move_free (PlannerCmd *cmd_base)
 {
-	TaskCmdTaskMove *cmd;
+	TaskCmdMove *cmd;
 
-	cmd = (TaskCmdTaskMove*) cmd_base;
+	cmd = (TaskCmdMove*) cmd_base;
 
 	g_object_unref (cmd->project);
 	g_object_unref (cmd->task);
@@ -916,48 +903,30 @@ task_cmd_task_move_free (PlannerCmd *cmd
 	if (cmd->sibling != NULL) {
 		g_object_unref (cmd->sibling);
 	}
-	g_free (cmd);
 }
 
 
 static PlannerCmd *
-task_cmd_task_move (PlannerTaskTree *tree,
+task_cmd_move (PlannerTaskTree *tree,
 		    MrpTask         *task,
 		    MrpTask         *sibling,
 		    MrpTask         *parent,
-		    gboolean         before)
+	       gboolean         before,
+	       GError         **error)
 {
 	PlannerTaskTreePriv *priv = tree->priv;
 	PlannerCmd          *cmd_base;
-	TaskCmdTaskMove     *cmd;
-	GError              *error;
-	gboolean             success;
+	TaskCmdMove         *cmd;
 	MrpTask             *parent_old;
 
 
-	parent_old = mrp_task_get_parent (task);
-	success = mrp_project_move_task (tree->priv->project,
-					 task,
-					 sibling,
-					 parent,
-					 before,
-					 &error);
-
-	if (!success) {
-		if (g_getenv ("PLANNER_DEBUG_UNDO_TASK")) {
-			g_message ("Task move can't be done %s!",
-				   mrp_task_get_name (task));
-		}
-		return NULL;
-	}
-
-	cmd = g_new0 (TaskCmdTaskMove, 1);
+	cmd = g_new0 (TaskCmdMove, 1);
 
 	cmd_base = (PlannerCmd*) cmd;
 	cmd_base->label = g_strdup (_("Move task"));
-	cmd_base->do_func = task_cmd_task_move_do;
-	cmd_base->undo_func = task_cmd_task_move_undo;
-	cmd_base->free_func = task_cmd_task_move_free;
+	cmd_base->do_func = task_cmd_move_do;
+	cmd_base->undo_func = task_cmd_move_undo;
+	cmd_base->free_func = task_cmd_move_free;
 	
 	cmd->project = g_object_ref (tree->priv->project);
 	cmd->task = g_object_ref (task);
@@ -965,7 +934,12 @@ task_cmd_task_move (PlannerTaskTree *tre
 	if (parent != NULL) {
 		cmd->parent = g_object_ref (parent);
 	}
+	
+	parent_old = mrp_task_get_parent (task);
+
+	if (parent_old != NULL) {
 	cmd->parent_old = g_object_ref (parent_old);
+	}
 
 	if (sibling != NULL) {
 		cmd->sibling = g_object_ref (sibling);
@@ -984,6 +959,172 @@ task_cmd_task_move (PlannerTaskTree *tre
 	planner_cmd_manager_insert_and_do (planner_window_get_cmd_manager 
 					   (priv->main_window),
 					   cmd_base);
+
+	if (cmd->error) {
+		g_propagate_error (error, cmd->error);
+		return NULL;
+	} 
+
+	return cmd_base;
+}
+
+typedef struct {
+	PlannerCmd        base;
+
+	MrpProject       *project;
+	MrpTask          *before;
+	MrpTask          *after;
+	MrpRelationType   relationship;
+	glong             lag;
+	GError           *error;
+} TaskCmdLink;
+
+static gboolean
+task_cmd_link_do (PlannerCmd *cmd_base)
+{
+	TaskCmdLink *cmd;
+	GError      *error = NULL;
+	MrpRelation *relation;
+	gboolean     retval;
+
+	cmd = (TaskCmdLink *) cmd_base;
+
+	relation = mrp_task_add_predecessor (cmd->after,
+					     cmd->before,
+					     cmd->relationship,
+					     cmd->lag,
+					     &error);
+	if (!error) {
+		retval = TRUE;
+	} else {
+		cmd->error = error;
+		retval = FALSE;		
+	} 
+
+	return retval;
+}
+
+static void
+task_cmd_link_undo (PlannerCmd *cmd_base)
+{
+	TaskCmdLink *cmd;
+	
+	cmd = (TaskCmdLink*) cmd_base;
+	
+	mrp_task_remove_predecessor (cmd->after, cmd->before);
+}
+
+static void
+task_cmd_link_free (PlannerCmd *cmd_base)
+{
+	TaskCmdLink *cmd;
+
+	cmd = (TaskCmdLink *) cmd_base;
+
+	g_object_unref (cmd->project);
+	g_object_unref (cmd->before);
+	g_object_unref (cmd->after);
+}
+
+
+PlannerCmd *
+planner_task_tree_task_cmd_link (PlannerTaskTree *tree,
+				 MrpTask         *before,
+				 MrpTask         *after,
+				 MrpRelationType  relationship,
+				 glong            lag,
+				 GError         **error)
+{
+	PlannerTaskTreePriv *priv = tree->priv;
+	PlannerCmd          *cmd_base;
+	TaskCmdLink         *cmd;
+
+	cmd = g_new0 (TaskCmdLink, 1);
+
+	cmd_base = (PlannerCmd*) cmd;
+	cmd_base->label = g_strdup (_("Link task"));
+	cmd_base->do_func = task_cmd_link_do;
+	cmd_base->undo_func = task_cmd_link_undo;
+	cmd_base->free_func = task_cmd_link_free;
+
+	cmd->project = g_object_ref (tree->priv->project);
+
+	cmd->before = g_object_ref (before);
+	cmd->after = g_object_ref (after);
+	cmd->relationship = relationship;
+	cmd->lag = lag;
+			
+	planner_cmd_manager_insert_and_do (planner_window_get_cmd_manager 
+					   (priv->main_window),
+					   cmd_base);
+
+	if (cmd->error) {
+		g_propagate_error (error, cmd->error);
+		return NULL;
+	}
+
+	return cmd_base;	
+}
+
+static gboolean
+task_cmd_unlink_do (PlannerCmd *cmd_base)
+{
+	TaskCmdLink *cmd;
+	
+	cmd = (TaskCmdLink*) cmd_base;
+
+	if (g_getenv ("PLANNER_DEBUG_UNDO_TASK")) {
+		g_message ("Removing the link ...");
+	}
+	
+	mrp_task_remove_predecessor (cmd->after, cmd->before);
+
+	return TRUE;
+}
+
+static void
+task_cmd_unlink_undo (PlannerCmd *cmd_base)
+{
+	TaskCmdLink *cmd;
+	GError      *error;
+	MrpRelation *relation;
+
+	cmd = (TaskCmdLink *) cmd_base;
+
+	relation = mrp_task_add_predecessor (cmd->after,
+					     cmd->before,
+					     cmd->relationship,
+					     cmd->lag,
+					     &error);
+	g_assert (relation);
+}
+
+static PlannerCmd *
+task_cmd_unlink (PlannerTaskTree *tree,
+		 MrpRelation     *relation)
+{
+	PlannerTaskTreePriv *priv = tree->priv;
+	PlannerCmd          *cmd_base;
+	TaskCmdLink         *cmd;
+
+	cmd = g_new0 (TaskCmdLink, 1);
+
+	cmd_base = (PlannerCmd*) cmd;
+	cmd_base->label = g_strdup (_("Unlink task"));
+	cmd_base->do_func = task_cmd_unlink_do;
+	cmd_base->undo_func = task_cmd_unlink_undo;
+	cmd_base->free_func = task_cmd_link_free;
+	
+	cmd->project = g_object_ref (tree->priv->project);
+
+	cmd->before = g_object_ref (mrp_relation_get_predecessor (relation));
+	cmd->after = g_object_ref (mrp_relation_get_successor (relation));
+	cmd->relationship = mrp_relation_get_relation_type (relation);
+	cmd->lag = mrp_relation_get_lag (relation);
+			
+	planner_cmd_manager_insert_and_do (planner_window_get_cmd_manager 
+					   (priv->main_window),
+					   cmd_base);
 	return cmd_base;
 }
 
@@ -2662,8 +2803,6 @@ planner_task_tree_unlink_task (PlannerTa
 	GList       *relations, *r;
 	MrpRelation *relation;
 
-	/* FIXME: undo */
-	
 	list = planner_task_tree_get_selected_tasks (tree);
 	if (list == NULL) {
 		return;
@@ -2676,8 +2815,10 @@ planner_task_tree_unlink_task (PlannerTa
 		for (r = relations; r; r = r->next) {
 			relation = r->data;
 			
-			mrp_task_remove_predecessor (
-				task, mrp_relation_get_predecessor (relation));
+			/* mrp_task_remove_predecessor (
+			   task, mrp_relation_get_predecessor (relation)); */
+
+			task_cmd_unlink (tree, relation); 
 		}
 
 		g_list_free (relations);
@@ -2686,8 +2827,10 @@ planner_task_tree_unlink_task (PlannerTa
 		for (r = relations; r; r = r->next) {
 			relation = r->data;
 			
-			mrp_task_remove_predecessor (
-				mrp_relation_get_successor (relation), task);
+			/* mrp_task_remove_predecessor (
+			   mrp_relation_get_successor (relation), task); */
+
+			task_cmd_unlink (tree, relation);
 		}
 
 		g_list_free (relations);
@@ -2705,8 +2848,6 @@ planner_task_tree_link_tasks (PlannerTas
 	GList     *list, *l;
 	GtkWidget *dialog;
 
-	/* FIXME: undo */
-
 	list = planner_task_tree_get_selected_tasks (tree);
 	if (list == NULL) {
 		return;
@@ -2716,15 +2857,20 @@ planner_task_tree_link_tasks (PlannerTas
 	
 	target_task = list->data;
 	for (l = list->next; l; l = l->next) {
+		PlannerCmd  *cmd;
 		GError *error = NULL;
 
 		task = l->data;
 
-		if (!mrp_task_add_predecessor (target_task,
+		cmd = planner_task_tree_task_cmd_link (tree, task, target_task, 
+						       relationship, 0, &error);
+
+		/* cmd = mrp_task_add_predecessor (target_task,
 					       task,
 					       relationship,
 					       0,
-					       &error)) {
+						&error)); */
+		if (!cmd) {
 			dialog = gtk_message_dialog_new (NULL,
 							 GTK_DIALOG_DESTROY_WITH_PARENT,
 							 GTK_MESSAGE_ERROR,
@@ -2751,7 +2897,6 @@ planner_task_tree_indent_task (PlannerTa
 	MrpProject        *project;
 	GList             *list, *l;
 	GList             *indent_tasks = NULL;
-	GError            *error = NULL;
 	GtkTreePath       *path;
 	GtkWidget         *dialog;
 	GtkTreeSelection  *selection;
@@ -2788,12 +2933,13 @@ planner_task_tree_indent_task (PlannerTa
 	indent_tasks = g_list_reverse (indent_tasks);
 
 	for (l = indent_tasks; l; l = l->next) {
-		TaskCmdTaskMove *cmd;
+		TaskCmdMove *cmd;
+		GError      *error = NULL;
 		
 		task = l->data;
 
-		cmd = (TaskCmdTaskMove *) 
-			task_cmd_task_move (tree, task, NULL, new_parent, FALSE); 
+		cmd = (TaskCmdMove *) 
+			task_cmd_move (tree, task, NULL, new_parent, FALSE, &error); 
 
 		/* cmd = mrp_project_move_task (project,
 						 task,
@@ -2802,7 +2948,7 @@ planner_task_tree_indent_task (PlannerTa
 						 FALSE,
 					     &error); */
 
-		if (cmd == NULL) {
+		if (!cmd) {
 			dialog = gtk_message_dialog_new (GTK_WINDOW (tree->priv->main_window),
 							 GTK_DIALOG_DESTROY_WITH_PARENT,
 							 GTK_MESSAGE_ERROR,
@@ -2812,8 +2958,7 @@ planner_task_tree_indent_task (PlannerTa
 			
 			gtk_dialog_run (GTK_DIALOG (dialog));
 			gtk_widget_destroy (dialog);
-			
-			g_clear_error (&error);
+			g_error_free (error);
 		}
 	}
 
@@ -2881,7 +3026,7 @@ planner_task_tree_unindent_task (Planner
 	for (l = unindent_tasks; l; l = l->next) {
 		task = l->data;
 
-		task_cmd_task_move (tree, task, NULL, new_parent, FALSE);
+		task_cmd_move (tree, task, NULL, new_parent, FALSE, NULL);
 
 		/* mrp_project_move_task (project,
 				       task,
@@ -2975,7 +3120,7 @@ planner_task_tree_move_task_up (PlannerT
  		if (!skip && position != 0 && proceed) {
 			/* Move task from position to position - 1. */
  			sibling = mrp_task_get_nth_child (parent, position - 1);
-			task_cmd_task_move (tree, task, sibling, parent, TRUE);
+			task_cmd_move (tree, task, sibling, parent, TRUE, NULL);
  			/* mrp_project_move_task (project, task, sibling, 
 			   parent, TRUE, NULL);*/
  		}
@@ -3086,7 +3231,7 @@ planner_task_tree_move_task_down (Planne
 			sibling = mrp_task_get_nth_child (parent, position + 1);
 
 			/* Moving task from 'position' to 'position + 1' */
-			task_cmd_task_move (tree, task, sibling, parent, FALSE);
+			task_cmd_move (tree, task, sibling, parent, FALSE, NULL);
 			/* mrp_project_move_task (project, task, sibling, 
 			   parent, FALSE, NULL); */
 		}
Index: src/planner-task-tree.h
===================================================================
RCS file: /cvs/gnome/planner/src/planner-task-tree.h,v
retrieving revision 1.7
diff -u -b -B -p -r1.7 planner-task-tree.h
--- src/planner-task-tree.h	27 Apr 2004 18:58:02 -0000	1.7
+++ src/planner-task-tree.h	8 May 2004 17:42:38 -0000
@@ -85,6 +85,13 @@ void         planner_task_tree_set_ancho
 						       GtkTreePath           *anchor);
 GtkTreePath* planner_task_tree_get_anchor             (PlannerTaskTree       *tree);
 
+/* Undo support */
 
+PlannerCmd*  planner_task_tree_task_cmd_link          (PlannerTaskTree       *tree,
+						       MrpTask               *before,
+						       MrpTask               *after,
+						       MrpRelationType        relationship,
+						       glong                  lag,
+						       GError               **error);
 
 #endif /* __PLANNER_TASK_TREE_H__ */

Attachment: signature.asc
Description: Esta parte del mensaje =?ISO-8859-1?Q?est=E1?= firmada digitalmente



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