Re: Patch to remember state of tree when editing tags



This diff adds sorting. This code made me feel dirty. Surely I'm missing
something?

On Sun, 2004-10-17 at 20:20 +0100, Laurence Hygate wrote:
> Hmm, I need to figure out how to maintain the sort order too.
> 
> Loz
> 
> On Sun, 2004-10-17 at 18:16 +0100, Laurence Hygate wrote:
> > 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
> > 
> > _______________________________________________
> > F-spot-list mailing list
> > F-spot-list gnome org
> > http://mail.gnome.org/mailman/listinfo/f-spot-list
-- 
Loz
? Makefile.solution.f-spot
? configure.scan
? f-spot.cmbx
? f-spot.mdsx
? make.sh
? po/Makefile
? po/Makefile.in
? po/Makefile.in.in
? po/POTFILES
? po/es.gmo
? src/AssemblyInfo.cs
? src/Main.cs
? src/Makefile.f-spot
? src/Makefile.solution.f-spot
? src/MyProgram.cs
? src/TagTreeModel.cs
? src/f-spot.cmbx
? src/f-spot.mdsx
? src/f-spot.pidb
? src/f-spot.prjx
? src/make.sh
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 20:21:14 -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 20:21:15 -0000
@@ -254,7 +254,121 @@
 		(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;
+	}
+	
+	// Copy a branch of the tree to a new parent
+	// (note, this doesn't work generically as it only copies the first value of each node)
+	private void CopyBranch(TreeIter src, TreeIter dest, bool is_root, bool is_parent) {
+		TreeIter copy, iter;
+		GLib.Value value = new GLib.Value();
+		TreeStore store = Model as TreeStore;
+		bool valid;
+		
+		store.GetValue(src, 0, ref value);
+		if (is_parent) {
+			Tag tag = (Tag)tag_store.Get((uint)value);
+			// we need to figure out where to insert it in the correct order
+			copy = InsertInOrder(dest, is_root, tag);
+		} else { 
+			copy = store.AppendValues(dest, (uint)value);
+		}
+		
+		valid = Model.IterChildren(out iter, src);
+		while (valid) {
+			// child nodes are already ordered
+			CopyBranch(iter, copy, false, false);
+			valid = Model.IterNext (ref iter);
+		}
+	}
+
+	// insert tag into the correct place in the tree, with parent. return the new TagIter in iter.
+	private TreeIter InsertInOrder(TreeIter parent, bool is_root, Tag tag) {
+		TreeIter iter;
+		TreeStore store = Model as TreeStore;
+		Tag compare;
+		bool valid;
+		if (is_root)
+			valid = store.GetIterFirst(out iter);
+		else
+			valid = store.IterChildren(out iter, parent);
+			
+		while (valid) {
+			//I have no desire to figure out a more performant sort over this...
+			GLib.Value value = new GLib.Value();
+			store.GetValue(iter, 0, ref value);
+			compare = (Tag)tag_store.Get((uint)value);
+			if (compare.CompareTo(tag) > 0) {
+				store.InsertBefore(out iter, iter);
+				store.SetValue(iter, 0, tag.Id);
+				return iter;
+			}
+			valid = store.IterNext(ref iter);
+		}
+		if (is_root) 
+			store.Append(out iter);
+		else
+			iter = store.Append(parent);
+		store.SetValue(iter, 0, tag.Id);
+		return 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)) {
+			// create dialog doesn't let you create a top level tag...
+			InsertInOrder(iter, false, tag);
+		}
+	}
+	
+	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, true);
+			store.Remove(ref iter);
+		}
+	}
 	// Constructor.
 
 	public TagSelectionWidget (TagStore tag_store)
@@ -275,6 +389,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 20:21:15 -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]