[Planner Dev] Planner Phase undo/redo v0.2 for review.




All,
	my first attempt at undo/redo. It works on my simple
test cases.

Add Phase, Assign Phase to project, Remove Phase and
then UNDO will add back the phase and its assignment to
the project.

Open an existing project, delete the assigned phase and
UNDDO/REDO will remove phase and replace it including
assignment.

It also fixes the duplicate phase name and empty phase
name errors seen in testing (existing bugz).

Rgds,
Lincoln.

Index: src/planner-phase-dialog.c
===================================================================
RCS file: /cvs/gnome/planner/src/planner-phase-dialog.c,v
retrieving revision 1.2
diff -u -B -b -p -r1.2 planner-phase-dialog.c
--- src/planner-phase-dialog.c	11 Dec 2003 10:52:46 -0000	1.2
+++ src/planner-phase-dialog.c	27 Apr 2004 18:48:05 -0000
@@ -1,5 +1,6 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
+ * Copyright (C) 2004 Lincoln Phipps <lincoln phipps openmutual net>
  * Copyright (C) 2002-2003 CodeFactory AB
  * Copyright (C) 2002-2003 Richard Hult <richard imendio com>
  * Copyright (C) 2002 Mikael Hallendal <micke imendio com>
@@ -37,6 +38,25 @@ enum {
 	NUM_COLS
 };
 
+/* UNDO/REDO Structures */
+
+typedef struct {
+	PlannerCmd   base;
+
+	MrpProject  *project;
+	gchar       *phase;
+} PhaseCmdInsert;
+
+typedef struct {
+	PlannerCmd   base;
+
+	MrpProject  *project;
+	gchar       *phase;
+	gboolean    is_assigned; 
+} PhaseCmdRemove;
+
+/* END of UNDO/REDO Strutures */
+
 typedef struct {
 	PlannerWindow  *main_window;
 	MrpProject    *project;
@@ -87,6 +107,21 @@ static void     phase_dialog_remove_phas
 						     const gchar      *phase);
 static void     phase_dialog_new_dialog_run         (DialogData       *data);
 
+/* UNDO/REDO prototypes */
+static PlannerCmd *phase_cmd_insert 		(PlannerWindow *window,
+						gchar 	*phase);
+				
+static void	phase_cmd_insert_do 		(PlannerCmd *cmd_base);
+static void	phase_cmd_insert_undo 		(PlannerCmd *cmd_base);
+static void	phase_cmd_insert_free 		(PlannerCmd *cmd_base);
+
+static PlannerCmd *phase_cmd_remove 		(PlannerWindow *window, 
+						gchar *phase);
+static void	phase_cmd_remove_do 		(PlannerCmd *cmd_base);
+static void	phase_cmd_remove_undo 		(PlannerCmd *cmd_base);
+static void	phase_cmd_remove_free 		(PlannerCmd *cmd_base);
+
+/* End of UNDO/REDO prototypes */
 
 static void
 phase_dialog_notify_phases (MrpProject  *project,  
@@ -174,6 +209,10 @@ planner_phase_dialog_new (PlannerWindow 
 	
 	data->remove_button = glade_xml_get_widget (glade, "remove_button");
 
+	/* turn remove button off initally until something later selected.*/
+	
+	gtk_widget_set_sensitive (data->remove_button, 0); 
+		
 	data->tree_view = glade_xml_get_widget (glade, "phase_treeview");
 
 	phase_dialog_setup_tree_view (data);
@@ -374,6 +413,8 @@ phase_dialog_remove_phase (DialogData  *
 	GtkListStore *store;
 	gboolean      found = FALSE;
 
+	PhaseCmdRemove *cmd;
+
 	tree_view = GTK_TREE_VIEW (data->tree_view);
 	store = GTK_LIST_STORE (gtk_tree_view_get_model (tree_view));
 
@@ -393,6 +434,7 @@ phase_dialog_remove_phase (DialogData  *
 
 	if (found) {
 		g_object_set (data->project, "phases", list, NULL);
+		cmd = (PhaseCmdRemove*) phase_cmd_remove (data->main_window, g_strdup (phase) );
 	}
 
 	mrp_string_list_free (list);
@@ -419,7 +462,9 @@ phase_dialog_new_dialog_run (DialogData 
 	GtkWidget   *dialog;
 	GtkWidget   *entry;
 	const gchar *name;
-	GList       *list;
+	GList          *list , *l;
+	gboolean	found; /* used to stop duplicated names */
+	PhaseCmdInsert *cmd;
 	
 	glade = glade_xml_new (GLADEDIR "/project-properties.glade",
 			       "new_phase_dialog",
@@ -435,19 +480,216 @@ phase_dialog_new_dialog_run (DialogData 
 			  G_CALLBACK (phase_dialog_new_name_changed_cb),
 			  data);
 
+	g_object_get (data->project, "phases", &list, NULL);
+	
 	if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
 		name = gtk_entry_get_text (GTK_ENTRY (entry));
 
-		/* Get all phases from the project, add the new one, re-set the
-		 * list.
+		if (strlen(name) > 0) { /* Don't add if its blank i.e. User just hit OK on little dialog. */
+			found = FALSE;
+			for (l = list; l ; l = l->next) {
+				if (strcmp (name, (char *) l->data) == 0 ) { 
+					found = TRUE; /* Will be a duplicated name which is messy */
+				}
+			}
+			if (found == FALSE ) {   /* If here then not a blank nor a duplicated name */
+				/* Actual stuff now done in the UNDO/REDO insert. */
+				cmd = (PhaseCmdInsert*) phase_cmd_insert (data->main_window, (gchar *) name);	
+			}
+		}
+	}
+	mrp_string_list_free (list);
+	g_object_unref (glade);
+	gtk_widget_destroy (dialog);
+}
+
+
+
+/* Start of UNDO/REDO routines */
+static void
+phase_cmd_insert_do (PlannerCmd *cmd_base)
+{
+	PhaseCmdInsert *cmd;
+	GList          *list;
+
+	cmd = (PhaseCmdInsert*) cmd_base;
+
+	g_assert (cmd->phase);
+		
+	/* Insert do code added from phase_dialog_new_dialog_run() with changes.
 		 */
-		g_object_get (data->project, "phases", &list, NULL);
-		list = g_list_append (list, g_strdup (name)); 
-		g_object_set (data->project, "phases", list, NULL);
+
+	g_object_get (cmd->project, "phases", &list, NULL);
+	
+	list = g_list_append (list, g_strdup (cmd->phase)); 
+	g_object_set (cmd->project, "phases", list, NULL);
 		mrp_string_list_free (list);
+}
+
+static void
+phase_cmd_insert_undo (PlannerCmd *cmd_base)
+{
+	PhaseCmdInsert *cmd;
+	cmd = (PhaseCmdInsert*) cmd_base;
+	
+	GList        *list, *l;
+	gboolean      found = FALSE;
+	
+
+	/* Insert undo taken from phase_dialog_remove_phase
+	 */
+	g_object_get (cmd->project, "phases", &list, NULL);
+
+	for (l = list; l; l = l->next) {
+		if (!strcmp (cmd->phase, l->data)) {
+			g_free (l->data);
+			list = g_list_remove_link (list, l);
+			found = TRUE;
+			break;
+		}
 	}
 
-	g_object_unref (glade);
-	gtk_widget_destroy (dialog);
+	if (found) {
+		g_object_set (cmd->project, "phases", list, NULL);
+	}
+
+	mrp_string_list_free (list);
+		
 }
 
+
+static void
+phase_cmd_insert_free (PlannerCmd *cmd_base)
+{
+	PhaseCmdInsert  *cmd;
+
+	cmd = (PhaseCmdInsert*) cmd_base;	
+
+	cmd->phase = NULL;  /* TODO: Check if this right regarding leaks ?*/
+	cmd->project = NULL;
+}
+
+static PlannerCmd *
+phase_cmd_insert (PlannerWindow *main_window, 
+		  gchar *phase) 
+{
+	PlannerCmd      *cmd_base;
+	PhaseCmdInsert  *cmd;
+
+	cmd = g_new0 (PhaseCmdInsert, 1);
+
+	cmd_base = (PlannerCmd*) cmd;
+
+	cmd_base->label = g_strdup (_("Insert phase"));
+	cmd_base->do_func = phase_cmd_insert_do;
+	cmd_base->undo_func = phase_cmd_insert_undo;
+	cmd_base->free_func = phase_cmd_insert_free;
+
+	cmd->project = planner_window_get_project (main_window);
+
+	cmd->phase = g_strdup (phase);
+
+	planner_cmd_manager_insert_and_do (planner_window_get_cmd_manager (main_window),
+					   cmd_base);
+
+	return cmd_base;
+}
+
+static void
+phase_cmd_remove_do (PlannerCmd *cmd_base)
+{
+	PhaseCmdRemove *cmd;
+	GList          *list, *l;
+	gchar          *assigned_phase;
+	gboolean      found = FALSE;
+
+	cmd = (PhaseCmdRemove*) cmd_base;
+
+	mrp_object_get (cmd->project, "phase", &assigned_phase, NULL);
+	if (assigned_phase == cmd->phase)
+		cmd->is_assigned = TRUE;
+	
+	/* Insert undo taken from phase_dialog_remove_phase
+	 */
+	g_object_get (cmd->project, "phases", &list, NULL);
+
+	for (l = list; l; l = l->next) {
+		if (!strcmp (cmd->phase, l->data)) {
+			g_free (l->data);
+			list = g_list_remove_link (list, l);
+			found = TRUE;
+			break;
+		}
+	}
+
+	if (found) {
+		g_object_set (cmd->project, "phases", list, NULL);
+	}
+
+	mrp_string_list_free (list);
+}
+
+static void
+phase_cmd_remove_undo (PlannerCmd *cmd_base)
+{
+	PhaseCmdRemove *cmd;
+	GList          *list;
+	
+	cmd = (PhaseCmdRemove*) cmd_base;
+
+	/* We need to recover the phase deleted */
+	
+	g_assert (cmd->phase);
+	
+	/* Insert do code added from phase_dialog_new_dialog_run() with changes.
+	 */
+
+	g_object_get (cmd->project, "phases", &list, NULL);
+	list = g_list_append (list, g_strdup (cmd->phase)); 
+	g_object_set (cmd->project, "phases", list, NULL);
+	mrp_string_list_free (list);	
+	
+
+	if (cmd->is_assigned) 
+		mrp_object_set (cmd->project, "phase", cmd->phase, NULL);
+}
+
+static void
+phase_cmd_remove_free (PlannerCmd *cmd_base)
+{
+	PhaseCmdRemove *cmd;
+
+	cmd = (PhaseCmdRemove*) cmd_base;
+
+	cmd->project = NULL;
+	cmd->phase = NULL;
+	cmd->is_assigned = FALSE;
+}
+
+static PlannerCmd *
+phase_cmd_remove (PlannerWindow *window, 
+		  gchar *phase)
+{
+	PlannerCmd      *cmd_base;
+	PhaseCmdRemove  *cmd;
+
+	cmd = g_new0 (PhaseCmdRemove, 1);
+
+	cmd_base = (PlannerCmd*) cmd;
+
+	cmd_base->label = g_strdup (_("Remove phase"));
+	cmd_base->do_func = phase_cmd_remove_do;
+	cmd_base->undo_func = phase_cmd_remove_undo;
+	cmd_base->free_func = phase_cmd_remove_free;
+
+	cmd->project = planner_window_get_project (window);
+	cmd->phase = phase;
+
+	planner_cmd_manager_insert_and_do (planner_window_get_cmd_manager (window),
+					   cmd_base);
+
+	return cmd_base;
+}
+
+
+/* END of UNDO/REDO routines */


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