[Planner Dev] New undo patch: Link/unlink tasks



Hi guys!

Here goes another patch for the undo system. With this one you can
do/undo link/unlink tasks, using the link/unlink button and also,
linking tasks with drag and drop.

I have had to modify a little the PlannerCmd and here goes a proposal to
add 2 new fields: error and success. Richard, what do you think? I am
not sure I like to add new fields in this way to PlannerCmd.

Also, when a "_do" command returns fails, showing that it can't complete
the operation, the command is inserted in the CmdManager also. Is that
right? Or is something wrong (something I think)?

Cheers

-- Alvaro
Index: src/planner-cmd-manager.c
===================================================================
RCS file: /cvs/gnome/planner/src/planner-cmd-manager.c,v
retrieving revision 1.9
diff -u -b -B -p -r1.9 planner-cmd-manager.c
--- src/planner-cmd-manager.c	2 May 2004 16:21:28 -0000	1.9
+++ src/planner-cmd-manager.c	5 May 2004 05:47:27 -0000
@@ -258,6 +258,8 @@ cmd_manager_free_func (PlannerCmd *cmd,
 /*	g_free (cmd->label);
 	g_free (cmd);
 */
+
+	g_free (cmd->error);
 }
 
 static gboolean
@@ -320,6 +322,8 @@ cmd_manager_insert (PlannerCmdManager *m
 	} else {
 		retval = TRUE;
 	}
+	
+	cmd->success = retval;
 	
 	cmd_manager_dump (manager);
 
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
--- src/planner-cmd-manager.h	2 May 2004 16:21:28 -0000	1.3
+++ src/planner-cmd-manager.h	5 May 2004 05:47:27 -0000
@@ -58,6 +58,8 @@ typedef enum {
 
 struct _PlannerCmd {
 	gchar              *label;
+	gboolean            success;
+	gchar              *error;
 
 	PlannerCmdManager  *manager;
 	
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	5 May 2004 05:47:32 -0000
@@ -2049,16 +2048,24 @@ gantt_row_event (GnomeCanvasItem *item, 
 								event->button.y);
 			
 			if (target_item && target_item != item) {
-				GError *error = NULL;
+				/* GError            *error; */
+				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)) {
+								       0);
+				
+				if (cmd->success == FALSE) {
 					GtkWidget *dialog;
 
 					gnome_canvas_item_ungrab (item, event->button.time);
@@ -2067,11 +2074,10 @@ gantt_row_event (GnomeCanvasItem *item, 
 									 GTK_DIALOG_DESTROY_WITH_PARENT,
 									 GTK_MESSAGE_ERROR,
 									 GTK_BUTTONS_OK,
-									 "%s", error->message);
+									 "%s", cmd->error);
 					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	5 May 2004 05:47:38 -0000
@@ -193,7 +193,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 +328,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 +696,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 +773,6 @@ task_cmd_constraint_free (PlannerCmd *cm
 	g_object_unref (cmd->task);
 	g_free (cmd->constraint);
 	g_free (cmd->constraint_old);
-
-	g_free (cmd);
 }
 
 
@@ -829,15 +819,15 @@ typedef struct {
 	gboolean    before;
 	gboolean    before_old;
 	gboolean    success;
-} TaskCmdTaskMove;
+} TaskCmdMove;
 
 static gboolean
-task_cmd_task_move_do (PlannerCmd *cmd_base)
+task_cmd_move_do (PlannerCmd *cmd_base)
 {
-	TaskCmdTaskMove *cmd;
+	TaskCmdMove *cmd;
 	GError          *error;
 
-	cmd = (TaskCmdTaskMove*) cmd_base;
+	cmd = (TaskCmdMove*) cmd_base;
 
 	if (g_getenv ("PLANNER_DEBUG_UNDO_TASK")) {
 		if (cmd->before) {
@@ -864,17 +854,14 @@ task_cmd_task_move_do (PlannerCmd *cmd_b
 }
 
 static void
-task_cmd_task_move_undo (PlannerCmd *cmd_base)
+task_cmd_move_undo (PlannerCmd *cmd_base)
 {
-	TaskCmdTaskMove *cmd;
+	TaskCmdMove *cmd;
 	GError          *error;
 
-	cmd = (TaskCmdTaskMove*) cmd_base;
-
-	if (!cmd->success) {
-		return;
-	}
+	cmd = (TaskCmdMove*) cmd_base;
 	
+	g_assert (cmd->success);
 
 	if (g_getenv ("PLANNER_DEBUG_UNDO_TASK")) {
 		if (cmd->before_old) {
@@ -901,11 +888,11 @@ task_cmd_task_move_undo (PlannerCmd *cmd
 }
 
 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,12 +903,11 @@ 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,
@@ -929,7 +915,7 @@ task_cmd_task_move (PlannerTaskTree *tre
 {
 	PlannerTaskTreePriv *priv = tree->priv;
 	PlannerCmd          *cmd_base;
-	TaskCmdTaskMove     *cmd;
+	TaskCmdMove         *cmd;
 	GError              *error;
 	gboolean             success;
 	MrpTask             *parent_old;
@@ -951,13 +937,13 @@ task_cmd_task_move (PlannerTaskTree *tre
 		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);
@@ -987,6 +973,159 @@ task_cmd_task_move (PlannerTaskTree *tre
 	return cmd_base;
 }
 
+typedef struct {
+	PlannerCmd        base;
+
+	MrpProject       *project;
+	MrpTask          *before;
+	MrpTask          *after;
+	MrpRelationType   relationship;
+	glong             lag;
+} 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 (relation) {
+		retval = TRUE;
+	} else {
+		cmd_base->error = g_strdup (error->message);
+		g_error_free (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)
+{
+	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);
+	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;
+}
+
 
 GType
 planner_task_tree_get_type (void)
@@ -2662,8 +2801,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 +2813,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 +2825,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 +2846,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,23 +2855,26 @@ planner_task_tree_link_tasks (PlannerTas
 	
 	target_task = list->data;
 	for (l = list->next; l; l = l->next) {
-		GError *error = NULL;
+		PlannerCmd  *cmd;
 
 		task = l->data;
 
-		if (!mrp_task_add_predecessor (target_task,
+		cmd = planner_task_tree_task_cmd_link (tree, task, target_task, 
+						       relationship, 0);
+
+		/* cmd = mrp_task_add_predecessor (target_task,
 					       task,
 					       relationship,
 					       0,
-					       &error)) {
+						&error)); */
+		if (cmd->success == FALSE) {
 			dialog = gtk_message_dialog_new (NULL,
 							 GTK_DIALOG_DESTROY_WITH_PARENT,
 							 GTK_MESSAGE_ERROR,
 							 GTK_BUTTONS_OK,
-							 "%s", error->message);
+							 "%s", cmd->error);
 			gtk_dialog_run (GTK_DIALOG (dialog));
 			gtk_widget_destroy (dialog);
-			g_error_free (error);
 		}
 		
 		target_task = task;
@@ -2788,12 +2930,12 @@ 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;
 		
 		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); 
 
 		/* cmd = mrp_project_move_task (project,
 						 task,
@@ -2881,7 +3023,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);
 
 		/* mrp_project_move_task (project,
 				       task,
@@ -2975,7 +3117,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);
  			/* mrp_project_move_task (project, task, sibling, 
 			   parent, TRUE, NULL);*/
  		}
@@ -3086,7 +3228,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);
 			/* 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	5 May 2004 05:47:39 -0000
@@ -85,6 +85,12 @@ 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);
 
 #endif /* __PLANNER_TASK_TREE_H__ */


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