Re: [Planner Dev] Fourth patch for task undo removal: assingments also - Problem with gantt widget?



Hi guys!

The commit has been done!

Any test of the new code will be very welcome. I attach the sample files
I have used to test as I advance.

Richard, is it s good idea to put this files in a directory called
"tasks-undo" under directory tests?

Cheers

El dom, 04-04-2004 a las 16:14, Alvaro del Castillo escribió:
> Hi!
> 
> El sáb, 03-04-2004 a las 21:53, Richard Hult escribió:
> > 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.
> > 
> 
> Great!
> 
> > > @@ -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.
> > 
> 
> Ok, I am a bit paranoid about memory issues ;-)
> 
> 
> > > +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.
> 
> Done!
> 
> > 
> > > @@ -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.
> > 
> 
> Done! I think when I coded it I was not sure that the compiler init to
> NULL pointers.
> 
> > > @@ -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_...
> 
> Sure!!!
> 
> > 
> > > 
> > > +{
> > > + 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.
> 
> Hmm, not sure. If you delete a task, all the subtasks are deleted. But
> you could select also the subtasks to be removed, so when you try to
> remove them, the task isn't in the project. I was trying to find  a
> better way to test if a task was in a project. Now, there are tasks that
> exist but not in any projects. For example, removed tasks in a remove
> undo command.
> 
> 
> > 
> > + 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.
> 
> Ok, I have checked all the "if's" in the file to be sure no style
> mistakes survive ;-)
> 
> > 
> > > + 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.
> 
> Done
> 
> > 
> > > + 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.
> > 
> 
> Ups, my poor english :) Corrected in all 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.
> 
> Ok, I will look at it before doing the commit.
> 
> > 
> > > +{
> > > + 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.
> > 
> 
> Yes! And also, the { and } ;-) Corrected before.
> 
> 
> > > + 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.
> 
> Ok, done!
> 
> >  
> > > + g_free (cmd_base->label);
> > > + gtk_tree_path_free (cmd->path);
> > > + 
> > > +
> > > + g_free (cmd);
> > > + cmd = NULL;
> > 
> > No need for the last row.
> > 
> 
> Ok!
> 
> > > +}
> > > +
> > > +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).
> > 
> 
> This was a debugging code I have used but no deleted. Thanks!
> 
> > Thanks again, this looks very nice! I'd say it's ready to be committed
> > after fixing the small details that I mentioned.
> > 
> 
> Ok, all the fixes done except the sibling one. I will look at it right
> now and it is easy as it seems, I will commit in the next hours all the
> work.
> 
> Thanks for que quick response to review lots of code.
> 
> Cheers
> 
> > Cheers,
> > Richard
> 
> _______________________________________________
> Planner-dev mailing list
> Planner-dev lists imendio com
> http://lists.imendio.com/mailman/listinfo/planner-dev
> 

Attachment: tasks-undo.tgz
Description: application/compressed-tar

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]