Patch to remember state of tree when editing tags



This is getting complex enough that there is a case for a separate
TreeModel implementation. The API for trees seems pretty grim to me.

cheers

Loz

Index: src/MainWindow.cs
===================================================================
RCS file: /cvs/gnome/f-spot/src/MainWindow.cs,v
retrieving revision 1.102
diff -u -r1.102 MainWindow.cs
--- src/MainWindow.cs	13 Oct 2004 06:01:55 -0000	1.102
+++ src/MainWindow.cs	17 Oct 2004 17:13:27 -0000
@@ -877,15 +877,13 @@
 	public void HandleCreateNewTagCommand (object sender, EventArgs args)
 	{
 		TagCommands.Create command = new TagCommands.Create (db.Tags, main_window);
-		if (command.Execute (TagCommands.TagType.Tag))
-			tag_selection_widget.Update ();
+		command.Execute (TagCommands.TagType.Tag);
 	}
 
 	public void HandleCreateNewCategoryCommand (object sender, EventArgs args)
 	{
 		TagCommands.Create command = new TagCommands.Create (db.Tags, main_window);
-		if (command.Execute (TagCommands.TagType.Category))
-			tag_selection_widget.Update ();
+		command.Execute (TagCommands.TagType.Category);
 	}
 
 	public void HandleAttachTagCommand (object obj, EventArgs args)
@@ -919,8 +917,7 @@
 			return;
 		
 		TagCommands.Edit command = new TagCommands.Edit (db, main_window);
-		if (command.Execute (tags [0]))
-			tag_selection_widget.Update ();
+		command.Execute (tags [0]);
 	}
 
 	void HandleViewSmall (object sender, EventArgs args)
@@ -1112,7 +1109,6 @@
 		Tag [] tags = this.tag_selection_widget.TagHighlight ();
 		
 		db.Photos.Remove (tags);
-		tag_selection_widget.Update ();
 		icon_view.QueueDraw ();
 	}
 
Index: src/TagSelectionWidget.cs
===================================================================
RCS file: /cvs/gnome/f-spot/src/TagSelectionWidget.cs,v
retrieving revision 1.11
diff -u -r1.11 TagSelectionWidget.cs
--- src/TagSelectionWidget.cs	17 Jun 2004 04:05:57 -0000	1.11
+++ src/TagSelectionWidget.cs	17 Oct 2004 17:13:27 -0000
@@ -254,7 +254,86 @@
 		(renderer as CellRendererText).Text = tag.Name;
 	}
 
+	// Someone show me how I should have done this?
+	// Or is the API as diseased as I have made it look?
+	private bool TreeIterForTag(Tag tag, out TreeIter iter) {
+		TreeIter root;
+		bool valid = Model.GetIterFirst(out root);
+		while (valid) {
+			if (TreeIterForTagRecurse(tag, root, out iter))
+				return true;
+			valid = Model.IterNext (ref root);
+		}
+		return false;
+    }
 
+	// Depth first traversal
+	private bool TreeIterForTagRecurse(Tag tag, TreeIter parent, out TreeIter iter) {
+		bool valid = Model.IterChildren(out iter, parent);
+		while (valid) {
+			if (TreeIterForTagRecurse(tag, iter, out iter))
+				return true;
+			valid = Model.IterNext (ref iter);
+		}
+		GLib.Value value = new GLib.Value();
+		Model.GetValue(parent, 0, ref value);
+		iter = parent;
+		if (tag.Id == (uint) value)
+			return true;
+		return false;
+	}
+	
+	// Not generic, just copying single values
+	private void CopyBranch(TreeIter src, TreeIter dest, bool is_root) {
+		TreeIter copy, iter;
+		GLib.Value value = new GLib.Value();
+		TreeStore store = Model as TreeStore;
+		bool valid;
+		
+		store.GetValue(src, 0, ref value);
+		if (is_root) {
+			store.Prepend(out copy);
+			store.SetValue(copy, 0, (uint)value);
+		} else { 
+			copy = store.AppendValues(dest, (uint)value);
+		}
+		
+		valid = Model.IterChildren(out iter, src);
+		while (valid) {
+			CopyBranch(iter, copy, false);
+			valid = Model.IterNext (ref iter);
+		}
+	}
+	
+	private void HandleTagDeleted(Tag tag) {
+		TreeIter iter;
+		if (TreeIterForTag(tag, out iter)) 
+			(Model as TreeStore).Remove(ref iter);
+	}
+	
+	private void HandleTagCreated(Tag tag) {
+		TreeIter iter;
+		if (TreeIterForTag(tag.Category, out iter)) {
+			iter = (Model as TreeStore).AppendValues(iter, tag.Id);
+		}
+	}
+	
+	private void HandleTagChanged(Tag tag) {
+		TreeStore store = Model as TreeStore;
+		TreeIter iter, category_iter, parent_iter;
+		TreeIterForTag(tag, out iter);
+		bool category_valid = TreeIterForTag(tag.Category, out category_iter);
+		bool parent_valid = Model.IterParent(out parent_iter, iter);
+		if ((category_valid && (category_iter.Equals(parent_iter))) || (!category_valid && !parent_valid)) {
+			// if we haven't been reparented
+			TreePath path = store.GetPath(iter); 
+			store.EmitRowChanged(path, iter);
+		} else {
+			// It is a bit tougher. We need to do an annoying clone of structs...
+			CopyBranch(iter, category_iter, !category_valid);
+			store.Remove(ref iter);
+		}
+	}
 	// Constructor.
 
 	public TagSelectionWidget (TagStore tag_store)
@@ -275,6 +354,9 @@
 
 		Update ();
 		ExpandAll ();
+		tag_store.TagDeleted += new TagDeletedHandler(HandleTagDeleted);
+		tag_store.TagCreated += new TagCreatedHandler(HandleTagCreated);
+		tag_store.TagChanged += new TagChangedHandler(HandleTagChanged);
 	}
 
 
Index: src/TagStore.cs
===================================================================
RCS file: /cvs/gnome/f-spot/src/TagStore.cs,v
retrieving revision 1.13
diff -u -r1.13 TagStore.cs
--- src/TagStore.cs	18 Aug 2004 00:23:35 -0000	1.13
+++ src/TagStore.cs	17 Oct 2004 17:13:28 -0000
@@ -173,9 +173,16 @@
 	}
 }
 
+public delegate void TagCreatedHandler(Tag t);
+public delegate void TagChangedHandler(Tag t);
+public delegate void TagDeletedHandler(Tag t);
 
 public class TagStore : DbStore {
 
+	public event TagCreatedHandler TagCreated;
+	public event TagChangedHandler TagChanged;
+	public event TagDeletedHandler TagDeleted;
+	
 	Category root_category;
 	public Category RootCategory {
 		get {
@@ -365,7 +372,7 @@
 
 		Tag tag = new Tag (category, id, name);
 		AddToCache (tag);
-
+		TagCreated(tag);		
 		return tag;
 	}
 
@@ -378,7 +385,7 @@
 
 		Category new_category = new Category (parent_category, id, name);
 		AddToCache (new_category);
-
+		TagCreated(new_category);
 		return new_category;
 	}
 
@@ -411,6 +418,7 @@
 		command.ExecuteNonQuery ();
 
 		command.Dispose ();
+		TagDeleted((Tag)item);
 	}
 
 
@@ -448,6 +456,8 @@
 		command.ExecuteNonQuery ();
 
 		command.Dispose ();
+		
+		TagChanged(tag);
 	}
 
 


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