The backtrace of the core dumps says:
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 16384 (LWP 12939)]
0x40a1c2c9 in gtk_widget_destroy () from /usr/lib/libgtk-x11-2.0.so.0
(gdb) bt
#0 0x40a1c2c9 in gtk_widget_destroy () from
/usr/lib/libgtk-x11-2.0.so.0
#1 0x40e5d212 in g_cclosure_marshal_VOID__VOID () from
/usr/lib/libgobject-2.0.so.0
#2 0x40e4ca92 in g_closure_invoke () from /usr/lib/libgobject-2.0.so.0
#3 0x40e5cda6 in g_signal_emit_by_name () from
/usr/lib/libgobject-2.0.so.0
#4 0x40e5bec2 in g_signal_emit_valist () from
/usr/lib/libgobject-2.0.so.0
#5 0x40e5c0d6 in g_signal_emit () from /usr/lib/libgobject-2.0.so.0
#6 0x40024205 in mrp_object_removed (object=0x8264a58) at
mrp-object.c:347
#7 0x40028656 in mrp_project_remove_task (project=0x80e97a0,
task=0x8264a58) at mrp-project.c:1733
#8 0x41233e4a in task_cmd_remove_do (cmd_base=0x8299068) at
planner-task-tree.c:605
#9 0x08062cf5 in cmd_manager_insert (manager=0x80e6428, cmd=0x8299068,
run_do=1) at planner-cmd-manager.c:312
Cheers
------------------------------------------------------------------------
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/planner/ChangeLog,v
retrieving revision 1.79
diff -u -b -B -p -r1.79 ChangeLog
--- ChangeLog 29 Mar 2004 15:18:08 -0000 1.79
+++ ChangeLog 3 Apr 2004 17:21:06 -0000
@@ -1,3 +1,9 @@
+2004-04-03 Alvaro del Castillo <acs barrapunto com>
+
+ * src/planner-task-tree.c: implemented task remove undo
+ Currently recovers the task, the position in the tasks tree
+ the task relations and the resources assignments.
+
2004-03-29 Richard Hult <richard imendio com>
* libplanner/mrp-old-xml.c (old_xml_read_assignment): Be more
Index: src/planner-task-tree.c
===================================================================
RCS file: /cvs/gnome/planner/src/planner-task-tree.c,v
retrieving revision 1.14
diff -u -b -B -p -r1.14 planner-task-tree.c
--- src/planner-task-tree.c 28 Mar 2004 23:03:49 -0000 1.14
+++ src/planner-task-tree.c 3 Apr 2004 17:21:15 -0000
@@ -152,6 +152,9 @@ 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;
@@ -167,7 +170,6 @@ typedef struct {
PlannerTaskTree *tree;
MrpProject *project;
- gchar *name;
gint work;
gint duration;
@@ -177,11 +179,25 @@ typedef struct {
} TaskCmdInsert;
static void
+task_cmd_insert_free (PlannerCmd *cmd_base)
+{
+ TaskCmdInsert *cmd;
+
+ cmd = (TaskCmdInsert*) cmd_base;
+
+ gtk_tree_path_free (cmd->path);
+ g_object_unref (cmd->task);
+ cmd->task = NULL;
+ g_free (cmd);
+ cmd = NULL;
+}
+
+static void
task_cmd_insert_do (PlannerCmd *cmd_base)
{
TaskCmdInsert *cmd;
GtkTreePath *path;
- MrpTask *task, *parent;
+ MrpTask *parent;
gint depth;
gint position;
@@ -201,18 +217,17 @@ task_cmd_insert_do (PlannerCmd *cmd_base
gtk_tree_path_free (path);
- task = g_object_new (MRP_TYPE_TASK,
+ if (cmd->task == NULL)
+ cmd->task = g_object_new (MRP_TYPE_TASK,
"work", cmd->work,
"duration", cmd->duration,
- "name", cmd->name ? cmd->name : "",
NULL);
mrp_project_insert_task (cmd->project,
parent,
position,
- task);
+ cmd->task);
- cmd->task = task;
}
static void
@@ -224,8 +239,6 @@ task_cmd_insert_undo (PlannerCmd *cmd_ba
mrp_project_remove_task (cmd->project,
cmd->task);
-
- cmd->task = NULL;
}
static PlannerCmd *
@@ -245,10 +258,11 @@ task_cmd_insert (PlannerTaskTree *tree,
cmd_base->label = g_strdup (_("Insert task"));
cmd_base->do_func = task_cmd_insert_do;
cmd_base->undo_func = task_cmd_insert_undo;
- cmd_base->free_func = NULL; /* FIXME */
+ cmd_base->free_func = task_cmd_insert_free;
cmd->tree = tree;
cmd->project = task_tree_get_project (tree);
+ cmd->task = NULL;
cmd->path = gtk_tree_path_copy (path);
cmd->work = work;
@@ -350,6 +364,357 @@ task_cmd_edit_property (PlannerTaskTree
return cmd_base;
}
+typedef struct {
+ PlannerCmd base;
+
+ PlannerTaskTree *tree;
+ MrpProject *project;
+
+ GtkTreePath *path;
+ MrpTask *task;
+ GList *childs;
+ GList *successors;
+ GList *predecessors;
+ GList *assignments;
+} TaskCmdRemove;
+
+static gboolean is_task_in_project (MrpTask *task, PlannerTaskTree *tree)
+{
+ PlannerGanttModel *model;
+ GtkTreePath *path;
+
+ model = PLANNER_GANTT_MODEL (gtk_tree_view_get_model (GTK_TREE_VIEW (tree)));
+ path = planner_gantt_model_get_path_from_task (model, task);
+
+ if (path != NULL) {
+ gtk_tree_path_free (path);
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+static void
+task_cmd_save_assignments (TaskCmdRemove *cmd)
+{
+ GList *l;
+
+ cmd->assignments = g_list_copy (mrp_task_get_assignments (cmd->task));
+ for (l = cmd->assignments; l; l = l->next) {
+ if (g_getenv ("PLANNER_DEBUG_UNDO_TASK"))
+ g_message ("Assignment save %s is done by %s (%d)",
+ mrp_task_get_name (cmd->task),
+ mrp_resource_get_name (mrp_assignment_get_resource (l->data)),
+ mrp_assignment_get_units (l->data));
+ g_object_ref (l->data);
+ }
+}
+
+static void
+task_cmd_restore_assignments (TaskCmdRemove *cmd)
+{
+ GList *l;
+ MrpAssignment *assignment;
+ MrpResource *resource;
+
+ for (l = cmd->assignments; l; l = l->next) {
+ assignment = l->data;
+ resource = mrp_assignment_get_resource (assignment);
+
+ // if (!is_task_in_project (rel_task, cmd->tree)) continue;
+
+ if (g_getenv ("PLANNER_DEBUG_UNDO_TASK"))
+ g_message ("Resource recover: %s is done by %s",
+ mrp_task_get_name (cmd->task),
+ mrp_resource_get_name (mrp_assignment_get_resource (l->data)));
+
+ mrp_resource_assign (resource, cmd->task,
+ mrp_assignment_get_units (assignment));
+ }
+}
+
+
+static void
+task_cmd_save_relations (TaskCmdRemove *cmd)
+{
+ GList *l;
+
+ cmd->predecessors = g_list_copy (mrp_task_get_predecessor_relations (cmd->task));
+ for (l = cmd->predecessors; l; l = l->next) {
+ if (g_getenv ("PLANNER_DEBUG_UNDO_TASK"))
+ g_message ("Predecessor save %s -> %s",
+ mrp_task_get_name (mrp_relation_get_predecessor (l->data)),
+ mrp_task_get_name (mrp_relation_get_successor (l->data)));
+
+ g_object_ref (l->data);
+ }
+
+ cmd->successors = g_list_copy (mrp_task_get_successor_relations (cmd->task));
+ for (l = cmd->successors; l; l = l->next) {
+ if (g_getenv ("PLANNER_DEBUG_UNDO_TASK"))
+ g_message ("Successor save %s -> %s",
+ mrp_task_get_name (mrp_relation_get_predecessor (l->data)),
+ mrp_task_get_name (mrp_relation_get_successor (l->data)));
+ g_object_ref (l->data);
+ }
+}
+
+static void
+task_cmd_restore_relations (TaskCmdRemove *cmd)
+{
+ GList *l;
+ MrpRelation *relation;
+ MrpTask *rel_task;
+
+
+ for (l = cmd->predecessors; l; l = l->next) {
+ relation = l->data;
+ rel_task = mrp_relation_get_predecessor (relation);
+
+ if (!is_task_in_project (rel_task, cmd->tree)) continue;
+
+ if (g_getenv ("PLANNER_DEBUG_UNDO_TASK"))
+ g_message ("Predecessor recover: %s -> %s",
+ mrp_task_get_name (mrp_relation_get_predecessor (l->data)),
+ mrp_task_get_name (mrp_relation_get_successor (l->data)));
+
+ mrp_task_add_predecessor (cmd->task, rel_task,
+ mrp_relation_get_relation_type (relation),
+ mrp_relation_get_lag (relation), NULL);
+ }
+
+ for (l = cmd->successors; l; l = l->next) {
+ relation = l->data;
+ rel_task = mrp_relation_get_successor (relation);
+
+ if (!is_task_in_project (rel_task, cmd->tree)) continue;
+
+ if (g_getenv ("PLANNER_DEBUG_UNDO_TASK"))
+ g_message ("Successor recover: %s -> %s",
+ mrp_task_get_name (mrp_relation_get_predecessor (l->data)),
+ mrp_task_get_name (mrp_relation_get_successor (l->data)));
+
+ mrp_task_add_predecessor (rel_task, cmd->task,
+ mrp_relation_get_relation_type (relation),
+ mrp_relation_get_lag (relation), NULL);
+ }
+}
+
+static void
+task_cmd_save_childs (TaskCmdRemove *cmd)
+{
+ gint childs, i;
+
+ childs = mrp_task_get_n_children (cmd->task);
+
+ for (i = 0; i < childs; i++) {
+ MrpTask *task;
+ TaskCmdRemove *cmd_child;
+ GtkTreePath *path;
+ PlannerGanttModel *model;
+
+ model = PLANNER_GANTT_MODEL (gtk_tree_view_get_model (GTK_TREE_VIEW (cmd->tree)));
+ task = mrp_task_get_nth_child (cmd->task, i);
+
+ path = planner_gantt_model_get_path_from_task (model, task);
+
+ /* We don't insert this command in the undo manager */
+ cmd_child = g_new0 (TaskCmdRemove, 1);
+ cmd_child->tree = cmd->tree;
+ cmd_child->project = task_tree_get_project (cmd->tree);
+ cmd_child->path = gtk_tree_path_copy (path);
+ cmd_child->task = g_object_ref (task);
+ task_cmd_save_relations (cmd_child);
+ task_cmd_save_assignments (cmd_child);
+
+ cmd->childs = g_list_append (cmd->childs, cmd_child);
+
+ task_cmd_save_childs (cmd_child);
+ }
+
+ if (g_getenv ("PLANNER_DEBUG_UNDO_TASK")) {
+ if (cmd->childs != NULL) {
+ GList *l;
+ for (l = cmd->childs; l; l = l->next) {
+ TaskCmdRemove *cmd_child = l->data;
+ g_message ("Child saved: %s", mrp_task_get_name (cmd_child->task));
+ }
+ }
+ }
+
+}
+
+static void
+task_cmd_restore_childs (TaskCmdRemove *cmd)
+{
+ PlannerGanttModel *model;
+ gint position, depth;
+ GtkTreePath *path;
+ MrpTask *parent;
+ GList *l;
+
+ for (l = cmd->childs; l; l = l->next) {
+ TaskCmdRemove *cmd_child;
+
+ cmd_child = l->data;
+
+ path = gtk_tree_path_copy (cmd_child->path);
+ model = PLANNER_GANTT_MODEL (gtk_tree_view_get_model
+ (GTK_TREE_VIEW (cmd_child->tree)));
+
+ depth = gtk_tree_path_get_depth (path);
+ position = gtk_tree_path_get_indices (path)[depth - 1];
+
+ if (depth > 1) {
+ gtk_tree_path_up (path);
+ parent = task_tree_get_task_from_path (cmd_child->tree, path);
+ } else {
+ parent = NULL;
+ }
+
+ gtk_tree_path_free (path);
+
+ mrp_project_insert_task (cmd_child->project,
+ parent,
+ position,
+ cmd_child->task);
+
+ task_cmd_restore_childs (cmd_child);
+ task_cmd_restore_relations (cmd_child);
+ task_cmd_restore_assignments (cmd_child);
+ }
+}
+
+static void
+task_cmd_remove_do (PlannerCmd *cmd_base)
+{
+ TaskCmdRemove *cmd;
+ gint childs;
+
+ cmd = (TaskCmdRemove*) cmd_base;
+
+ task_cmd_save_relations (cmd);
+ task_cmd_save_assignments (cmd);
+
+ childs = mrp_task_get_n_children (cmd->task);
+
+ if (childs > 0 && cmd->childs == NULL) task_cmd_save_childs (cmd);
+
+ g_message ("Removing the task : %p", cmd->task);
+
+ mrp_project_remove_task (cmd->project, cmd->task);
+}
+
+static void
+task_cmd_remove_undo (PlannerCmd *cmd_base)
+{
+ PlannerGanttModel *model;
+ TaskCmdRemove *cmd;
+ gint position, depth;
+ GtkTreePath *path;
+ MrpTask *parent;
+ MrpTask *child_parent;
+
+ cmd = (TaskCmdRemove*) cmd_base;
+
+ path = gtk_tree_path_copy (cmd->path);
+ model = PLANNER_GANTT_MODEL (gtk_tree_view_get_model (GTK_TREE_VIEW (cmd->tree)));
+
+ depth = gtk_tree_path_get_depth (path);
+ position = gtk_tree_path_get_indices (path)[depth - 1];
+
+ if (depth > 1) {
+ gtk_tree_path_up (path);
+ parent = task_tree_get_task_from_path (cmd->tree, path);
+ } else {
+ parent = NULL;
+ }
+
+ gtk_tree_path_free (path);
+
+ g_message ("Recovering the task : %p", cmd->task);
+
+ mrp_project_insert_task (cmd->project,
+ parent,
+ position,
+ cmd->task);
+
+ child_parent = planner_gantt_model_get_indent_task_target (model, cmd->task);
+
+ if (cmd->childs != NULL) task_cmd_restore_childs (cmd);
+
+ task_cmd_restore_relations (cmd);
+ task_cmd_restore_assignments (cmd);
+}
+
+static void
+task_cmd_remove_free (PlannerCmd *cmd_base)
+{
+ TaskCmdRemove *cmd;
+ GList *l;
+
+ cmd = (TaskCmdRemove*) cmd_base;
+
+ for (l = cmd->childs; l; l = l->next)
+ task_cmd_remove_free (l->data);
+
+ g_object_unref (cmd->task);
+
+ g_list_free (cmd->childs);
+
+ for (l = cmd->predecessors; l; l = l->next)
+ g_object_unref (l->data);
+ g_list_free (cmd->predecessors);
+
+ for (l = cmd->successors; l; l = l->next)
+ g_object_unref (l->data);
+ g_list_free (cmd->successors);
+
+ for (l = cmd->assignments; l; l = l->next)
+ g_object_unref (l->data);
+ g_list_free (cmd->assignments);
+
+ g_free (cmd_base->label);
+ gtk_tree_path_free (cmd->path);
+
+
+ g_free (cmd);
+ cmd = NULL;
+}
+
+static PlannerCmd *
+task_cmd_remove (PlannerTaskTree *tree,
+ GtkTreePath *path,
+ MrpTask *task)
+{
+ PlannerTaskTreePriv *priv = tree->priv;
+ PlannerCmd *cmd_base;
+ TaskCmdRemove *cmd;
+
+ g_return_val_if_fail (MRP_IS_TASK (task), NULL);
+
+ cmd = g_new0 (TaskCmdRemove, 1);
+
+ cmd_base = (PlannerCmd*) cmd;
+ cmd_base->label = g_strdup (_("Remove task"));
+ cmd_base->do_func = task_cmd_remove_do;
+ cmd_base->undo_func = task_cmd_remove_undo;
+ cmd_base->free_func = task_cmd_remove_free;
+
+ cmd->tree = tree;
+ cmd->project = task_tree_get_project (tree);
+
+ cmd->path = gtk_tree_path_copy (path);
+
+ cmd->task = g_object_ref (task);
+
+ 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)
{
@@ -1820,8 +2185,8 @@ void
planner_task_tree_remove_task (PlannerTaskTree *tree)
{
GList *list, *l;
+ TaskCmdRemove *cmd;
- /* FIXME: undo */
list = planner_task_tree_get_selected_tasks (tree);
if (list == NULL) {
@@ -1829,7 +2194,18 @@ planner_task_tree_remove_task (PlannerTa
}
for (l = list; l; l = l->next) {
- mrp_project_remove_task (tree->priv->project, l->data);
+ MrpTask *task = l->data;
+ PlannerGanttModel *model;
+ GtkTreePath *path;
+
+ model = PLANNER_GANTT_MODEL (gtk_tree_view_get_model (GTK_TREE_VIEW (tree)));
+ path = planner_gantt_model_get_path_from_task (model, task);
+
+ /* childs are removed with the parent */
+ if (path != NULL)
+ cmd = (TaskCmdRemove*) task_cmd_remove (tree, path, task);
+ gtk_tree_path_free (path);
+ /* mrp_project_remove_task (tree->priv->project, l->data); */
}
g_list_free (list);
------------------------------------------------------------------------
<?xml version="1.0"?>
<project name="" company="" manager="" phase="" project-start="20040403T000000Z" mrproject-version="2" calendar="1">
<properties>
<property name="cost" type="cost" owner="resource" label="Cost" description="standard cost for a resource"/>
</properties>
<phases/>
<calendars>
<day-types>
<day-type id="0" name="Working" description="A default working day"/>
<day-type id="1" name="Nonworking" description="A default non working day"/>
<day-type id="2" name="Use base" description="Use day from base calendar"/>
</day-types>
<calendar id="1" name="Default">
<default-week mon="0" tue="0" wed="0" thu="0" fri="0" sat="1" sun="1"/>
<overridden-day-types>
<overridden-day-type id="0">
<interval start="0800" end="1200"/>
<interval start="1300" end="1700"/>
</overridden-day-type>
</overridden-day-types>
<days/>
</calendar>
</calendars>
<tasks>
<task id="1" name="" note="" work="28800" start="20040403T000000Z" end="20040409T170000Z" percent-complete="0" type="normal" scheduling="fixed-work"/>
</tasks>
<resource-groups/>
<resources>
<resource id="1" name="r1" short-name="" type="1" units="0" email="" note="" std-rate="0">
<properties>
<property name="cost" value=""/>
</properties>
</resource>
<resource id="2" name="r2" short-name="" type="1" units="0" email="" note="" std-rate="0">
<properties>
<property name="cost" value=""/>
</properties>
</resource>
</resources>
<allocations>
<allocation task-id="1" resource-id="1" units="10"/>
<allocation task-id="1" resource-id="2" units="10"/>
</allocations>
</project>
------------------------------------------------------------------------
_______________________________________________
Planner-dev mailing list
Planner-dev lists imendio com
http://lists.imendio.com/mailman/listinfo/planner-dev