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