Re: [Planner Dev] Fourth patch for task undo removal: assingments also - Problem with gantt widget?
- From: Richard Hult <richard imendio com>
- To: acs lambdaux com, Planner Project Manager - Development List <planner-dev lists imendio com>
- Cc:
- Subject: Re: [Planner Dev] Fourth patch for task undo removal: assingments also - Problem with gantt widget?
- Date: Sat, 03 Apr 2004 23:53:05 +0200
Hi,
Thanks a lot for this patch, it's a lot of work :)
The patch looks great, I have just a few comments, mostly style issues.
> @@ -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;
> +}
No need to set cmd to NULL there.
> +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);
Looks like there are some { } missing here.
> @@ -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;
No need to set task to NULL, it's already NULL.
> @@ -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)
Should be:
static gboolean
is_...
>
> +{
> + 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;
is_task_in_project should probably just be used for debugging, if it
fails then there is a bug somewhere.
+ 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;
As above.
> + 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;
Again.
> + 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)
Should be children, I believe :) Likewise for the other places.
It would also be better to use mrp_task_get_first_child and then iterate
with mrp_task_get_next_sibling, should be much more efficient.
> +{
> + 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);
Just checking cmd->childs should be enough here.
> + 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);
I would do g_list_foreach (cmd->foo, (GFunc) g_object_unref, NULL) here,
and the same above when the objects are reffed.
> + g_free (cmd_base->label);
> + gtk_tree_path_free (cmd->path);
> +
> +
> + g_free (cmd);
> + cmd = NULL;
No need for the last row.
> +}
> +
> +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);
No need to check this in the internal functions (we're probably not
consistent with this).
Thanks again, this looks very nice! I'd say it's ready to be committed
after fixing the small details that I mentioned.
Cheers,
Richard
--
Richard Hult richard imendio com
Imendio http://www.imendio.com
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]