[f-spot] start make TagSelectionWidget independent from MainWindow



commit 9d0de81cfd4bb61051ec6b1cb6991c97e2d9fdb4
Author: Mike Gemuende <mike gemuende de>
Date:   Mon Jun 22 09:35:59 2009 +0200

    start make TagSelectionWidget independent from MainWindow

 src/MainWindow.cs         |  168 +++---
 src/Makefile.am           |    1 +
 src/QueryWidget.cs        |    4 +-
 src/TagQueryWidget.cs     |   51 +-
 src/TagSelectionWidget.cs | 1361 ++++++++++++++++++++++++++-------------------
 src/Term.cs               |   62 ++-
 src/Util.cs               |  320 ++++++-----
 7 files changed, 1127 insertions(+), 840 deletions(-)
---
diff --git a/src/MainWindow.cs b/src/MainWindow.cs
index 3e3402a..c79ef76 100644
--- a/src/MainWindow.cs
+++ b/src/MainWindow.cs
@@ -23,6 +23,7 @@ using FSpot.Widgets;
 using FSpot.Utils;
 using FSpot.UI.Dialog;
 using FSpot.Platform;
+using FSpot.GuiUtils;
 
 using LibGPhoto2;
 
@@ -173,38 +174,33 @@ public class MainWindow {
 		get { return photo_view; }
 	}
 
-	// Drag and Drop
-	public enum TargetType {
-		UriList,
-		TagList,
-		TagQueryItem,
-		PhotoList,
-		RootWindow
+	private static TargetEntry [] icon_source_target_table = 
+		new TargetEntry [] {
+			DragDrop.PhotoListEntry,
+			DragDrop.TagQueryEntry,
+			DragDrop.UriListEntry,
+			DragDrop.RootWindowEntry
 	};
-
-	private static TargetEntry [] icon_source_target_table = new TargetEntry [] {
-		new TargetEntry ("application/x-fspot-photos", 0, (uint) TargetType.PhotoList),
-		new TargetEntry ("application/x-fspot-tag-query-item", 0, (uint) TargetType.TagQueryItem),
-		new TargetEntry ("text/uri-list", 0, (uint) TargetType.UriList),
-		new TargetEntry ("application/x-root-window-drop", 0, (uint) TargetType.RootWindow)
-	};
-
-	private static TargetEntry [] icon_dest_target_table = new TargetEntry [] {
+	
+	private static TargetEntry [] icon_dest_target_table = 
+		new TargetEntry [] {
 #if ENABLE_REPARENTING
-		new TargetEntry ("application/x-fspot-photos", 0, (uint) TargetType.PhotoList),
+			DragDrop.PhotoListEntry,
 #endif
-		new TargetEntry ("application/x-fspot-tags", 0, (uint) TargetType.TagList),
-		new TargetEntry ("text/uri-list", 0, (uint) TargetType.UriList),
+			DragDrop.TagListEntry,
+			DragDrop.UriListEntry
 	};
-
-	private static TargetEntry [] tag_target_table = new TargetEntry [] {
-		new TargetEntry ("application/x-fspot-tags", 0, (uint) TargetType.TagList),
+	
+	private static TargetEntry [] tag_target_table = 
+		new TargetEntry [] {
+			DragDrop.TagListEntry
 	};
-
-	private static TargetEntry [] tag_dest_target_table = new TargetEntry [] {
-		new TargetEntry ("application/x-fspot-photos", 0, (uint) TargetType.PhotoList),
-		new TargetEntry ("text/uri-list", 0, (uint) TargetType.UriList),
-		new TargetEntry ("application/x-fspot-tags", 0, (uint) TargetType.TagList),
+	
+	private static TargetEntry [] tag_dest_target_table = 
+		new TargetEntry [] {
+			DragDrop.PhotoListEntry,
+			DragDrop.UriListEntry,
+			DragDrop.TagListEntry
 	};
 
 	const int PHOTO_IDX_NONE = -1;
@@ -368,17 +364,17 @@ public class MainWindow {
 		info_box.Context = ViewContext.Library;
 		
 		tag_selection_widget.Selection.Changed += HandleTagSelectionChanged;
-		tag_selection_widget.DragDataGet += HandleTagSelectionDragDataGet;
-		tag_selection_widget.DragDrop += HandleTagSelectionDragDrop;
-		tag_selection_widget.DragBegin += HandleTagSelectionDragBegin;
+//		tag_selection_widget.DragDataGet += HandleTagSelectionDragDataGet;
+//		tag_selection_widget.DragDrop += HandleTagSelectionDragDrop;
+//		tag_selection_widget.DragBegin += HandleTagSelectionDragBegin;
 		tag_selection_widget.KeyPressEvent += HandleTagSelectionKeyPress;
-		Gtk.Drag.SourceSet (tag_selection_widget, Gdk.ModifierType.Button1Mask | Gdk.ModifierType.Button3Mask,
-				    tag_target_table, DragAction.Copy | DragAction.Move);
+//		Gtk.Drag.SourceSet (tag_selection_widget, Gdk.ModifierType.Button1Mask | Gdk.ModifierType.Button3Mask,
+//				    tag_target_table, DragAction.Copy | DragAction.Move);
 
-		tag_selection_widget.DragDataReceived += HandleTagSelectionDragDataReceived;
-		tag_selection_widget.DragMotion += HandleTagSelectionDragMotion;
-		Gtk.Drag.DestSet (tag_selection_widget, DestDefaults.All, tag_dest_target_table, 
-				  DragAction.Copy | DragAction.Move ); 
+//		tag_selection_widget.DragDataReceived += HandleTagSelectionDragDataReceived;
+//		tag_selection_widget.DragMotion += HandleTagSelectionDragMotion;
+//		Gtk.Drag.DestSet (tag_selection_widget, DestDefaults.All, tag_dest_target_table, 
+//				  DragAction.Copy | DragAction.Move ); 
 
 		tag_selection_widget.ButtonPressEvent += HandleTagSelectionButtonPressEvent;
 		tag_selection_widget.PopupMenu += HandleTagSelectionPopupMenu;
@@ -424,7 +420,7 @@ public class MainWindow {
 		view_vbox.ReorderChild (find_bar, 1);
 		main_window.KeyPressEvent += HandleKeyPressEvent;
 		
-		query_widget = new FSpot.QueryWidget (query, db, tag_selection_widget);
+		query_widget = new FSpot.QueryWidget (query, db);
 		query_widget.Logic.Changed += HandleQueryLogicChanged;
 		view_vbox.PackStart (query_widget, false, false, 0);
 		view_vbox.ReorderChild (query_widget, 2);
@@ -988,7 +984,7 @@ public class MainWindow {
 		args.RetVal = true;
 	}
 
-	void HandleTagSelectionDragBegin (object sender, DragBeginArgs args)
+/*	void HandleTagSelectionDragBegin (object sender, DragBeginArgs args)
 	{
 		Tag [] tags = tag_selection_widget.TagHighlight;
 		int len = tags.Length;
@@ -1018,27 +1014,26 @@ public class MainWindow {
 			Gtk.Drag.SetIconPixbuf (args.Context, container, 0, 0);
 		container.Dispose ();
 	}
-	
-	void HandleTagSelectionDragDataGet (object sender, DragDataGetArgs args)
+*/	
+/*	void HandleTagSelectionDragDataGet (object sender, DragDataGetArgs args)
 	{		
 		UriList list = new UriList (SelectedPhotos ());
 
-		switch (args.Info) {
-		case (uint) TargetType.TagList:
+		if (args.Info == DragDrop.TagListEntry.Info) {
 			Byte [] data = Encoding.UTF8.GetBytes (list.ToString ());
 			Atom [] targets = args.Context.Targets;
 			
 			args.SelectionData.Set (targets[0], 8, data, data.Length);
-			break;
+			return;
 		}
 	}
-
-	void HandleTagSelectionDragDrop (object sender, DragDropArgs args)
+*/
+/*	void HandleTagSelectionDragDrop (object sender, DragDropArgs args)
 	{
 		args.RetVal = true;
 	}
-
-	public void HandleTagSelectionDragMotion (object o, DragMotionArgs args)
+*/
+/*	public void HandleTagSelectionDragMotion (object o, DragMotionArgs args)
 	{
 		TreePath path;
         TreeViewDropPosition position = TreeViewDropPosition.IntoOrAfter;
@@ -1066,8 +1061,8 @@ public class MainWindow {
         else if (((o as Gtk.Widget).Allocation.Height - args.Y) < 20)
 			tag_selection_scrolled.Vadjustment.Value += 30;
 	}
-
-	public void HandleTagSelectionDragDataReceived (object o, DragDataReceivedArgs args)
+*/
+/*	public void HandleTagSelectionDragDataReceived (object o, DragDataReceivedArgs args)
 	{
         TreePath path;
         TreeViewDropPosition position;
@@ -1078,14 +1073,15 @@ public class MainWindow {
 		if (tag == null)
 			return;
 
-		switch (args.Info) {
-		case (uint)TargetType.PhotoList:
+		if (args.Info == DragDrop.PhotoListEntry.Info) {
 			db.BeginTransaction ();
 			AddTagExtended (SelectedIds (), new Tag[] {tag});
 			db.CommitTransaction ();
 			query_widget.PhotoTagsChanged (new Tag[] {tag});
-			break;
-		case (uint)TargetType.UriList:
+			return;
+		}
+		
+		if (args.Info == DragDrop.UriListEntry.Info) {
 			UriList list = new UriList (args.SelectionData);
 			
 			db.BeginTransaction ();
@@ -1104,8 +1100,10 @@ public class MainWindow {
 			db.Photos.Commit (photos.ToArray ());
 			db.CommitTransaction ();
 			InvalidateViews ();
-			break;
-		case (uint)TargetType.TagList:
+			return;
+		}
+
+		if (args.Info == DragDrop.TagListEntry.Info) {
 			Category parent;
             if (position == TreeViewDropPosition.Before || position == TreeViewDropPosition.After) {
                 parent = tag.Category;
@@ -1135,10 +1133,10 @@ public class MainWindow {
             tag_selection_widget.TagHighlight = highlighted_tags;
 
             args.RetVal = moved_count > 0;
-			break;
+			return;
 		}
 	}
-
+*/
 #if SHOW_CALENDAR
 	void HandleCalendarDaySelected (object sender, System.EventArgs args)
 	{
@@ -1282,19 +1280,34 @@ public class MainWindow {
 
 	void HandleIconViewDragDataGet (object sender, DragDataGetArgs args)
 	{		
-		switch (args.Info) {
-		case (uint) TargetType.UriList:
-		case (uint) TargetType.PhotoList:
+		/*if (args.Info == DragDrop.UriListEntry.Info || args.Info == DragDrop.PhotoListEntry.Info) {
 			UriList list = new UriList (SelectedPhotos ());
 			Byte [] data = Encoding.UTF8.GetBytes (list.ToString ());
 			Atom [] targets = args.Context.Targets;
 			args.SelectionData.Set (targets[0], 8, data, data.Length);
-			break;
-		case (uint) TargetType.RootWindow:
+			return;
+		}
+		
+		if (args.Info == DragDrop.RootWindowEntry.Info) {
 			HandleSetAsBackgroundCommand (null, null);
-                        break;
+			return;
+		}
+		  */
+		
+		if (args.Info == DragDrop.UriListEntry.Info) {
+			DragDrop.SetUriListData (new UriList (SelectedPhotos ()), args);
+			return;
+		}
+		
+		if (args.Info == DragDrop.PhotoListEntry.Info) {
+			DragDrop.SetPhotosData (SelectedPhotos (), args.SelectionData);
+			return;
+		}
+		
+		if (args.Info == DragDrop.RootWindowEntry.Info) {
+			HandleSetAsBackgroundCommand (null, null);
+			return;
 		}
-		       
 	}
 
 	void HandleIconViewDragDrop (object sender, DragDropArgs args)
@@ -1357,8 +1370,7 @@ public class MainWindow {
 	{
 	 	Widget source = Gtk.Drag.GetSourceWidget (args.Context);     
 		
-		switch (args.Info) {
-		case (uint)TargetType.TagList:
+		if (args.Info == DragDrop.TagListEntry.Info) {
 			//
 			// Translate the event args from viewport space to window space,
 			// drag events use the viewport.  Owen sends his regrets.
@@ -1373,8 +1385,12 @@ public class MainWindow {
 				else 
 					AttachTags (tag_selection_widget.TagHighlight, new int [] {item});
 			}
-			break;
-		case (uint)TargetType.UriList:
+			
+			Gtk.Drag.Finish (args.Context, true, false, args.Time);
+			return;
+		}
+		
+		if (args.Info == DragDrop.UriListEntry.Info) {
 
 			/* 
 			 * If the drop is coming from inside f-spot then we don't want to import 
@@ -1384,9 +1400,13 @@ public class MainWindow {
 
 			UriList list = new UriList (args.SelectionData);
 			ImportUriList (list, (args.Context.Action & Gdk.DragAction.Copy) != 0);
-			break;
+			
+			Gtk.Drag.Finish (args.Context, true, false, args.Time);
+			return;
+		}
+		
 #if ENABLE_REPARENTING
-		case (uint)TargetType.PhotoList:
+		if (args.Info == DragDrop.PhotoListEntry.Info) {
 			int p_item = icon_view.CellAtPosition (args.X + (int) icon_view.Hadjustment.Value, 
 							     args.Y + (int) icon_view.Vadjustment.Value);
 
@@ -1398,12 +1418,10 @@ public class MainWindow {
 				cmd.Execute (db.Photos, SelectedPhotos(), query.Photos [p_item], GetToplevel (null));
 				UpdateQuery ();
 			}
-	
-			break;
-#endif
+			Gtk.Drag.Finish (args.Context, true, false, args.Time);
+			return;
 		}
-
-		Gtk.Drag.Finish (args.Context, true, false, args.Time);
+#endif
 	}
 
 	//
diff --git a/src/Makefile.am b/src/Makefile.am
index ff7e82a..a939c7c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -127,6 +127,7 @@ F_SPOT_CSDISTFILES =				\
 	$(srcdir)/DependentListStore.cs		\
 	$(srcdir)/DirectoryAdaptor.cs		\
 	$(srcdir)/DirectoryCollection.cs	\
+	$(srcdir)/DragDrop.cs				\
 	$(srcdir)/Editors/Editor.cs		\
 	$(srcdir)/Editors/AutoStretchEditor.cs		\
 	$(srcdir)/Editors/CropEditor.cs		\
diff --git a/src/QueryWidget.cs b/src/QueryWidget.cs
index de7ea3a..59b72ef 100644
--- a/src/QueryWidget.cs
+++ b/src/QueryWidget.cs
@@ -33,7 +33,7 @@ namespace FSpot {
 			get { return logic_widget; }
 		}
 
-		public QueryWidget (PhotoQuery query, Db db, TagSelectionWidget selector) : base(new HBox())
+		public QueryWidget (PhotoQuery query, Db db) : base(new HBox())
 		{
 			box = Child as HBox;
 			box.Spacing = 6;
@@ -70,7 +70,7 @@ namespace FSpot {
 			rollfilter.Visible = false;
 			box.PackStart (rollfilter, false, false, 0);
 
-			logic_widget = new LogicWidget (query, db.Tags, selector);
+			logic_widget = new LogicWidget (query, db.Tags);
 			logic_widget.Show ();
 			box.PackStart (logic_widget, true, true, 0);
 
diff --git a/src/TagQueryWidget.cs b/src/TagQueryWidget.cs
index d26e08c..c330b87 100644
--- a/src/TagQueryWidget.cs
+++ b/src/TagQueryWidget.cs
@@ -6,6 +6,7 @@ using Gtk;
 using Gdk;
 
 using FSpot.Utils;
+
 namespace FSpot
 {
 	public class LiteralPopup
@@ -206,7 +207,6 @@ namespace FSpot
 
 	public class LogicWidget : HBox {
 		private PhotoQuery query;
-		private TagSelectionWidget tag_selection_widget;
 
 		private static Tooltips tips = new Tooltips ();
 
@@ -234,16 +234,16 @@ namespace FSpot
 		}
 
 		// Drag and Drop
-		private static TargetEntry [] tag_dest_target_table = new TargetEntry [] {
-					new TargetEntry ("application/x-fspot-tags", 0, (uint) MainWindow.TargetType.TagList),
-					new TargetEntry ("application/x-fspot-tag-query-item", 0, (uint) MainWindow.TargetType.TagQueryItem),
-				};
+		private static TargetEntry [] tag_dest_target_table =
+			new TargetEntry [] {
+				FSpot.GuiUtils.DragDrop.TagListEntry,
+				FSpot.GuiUtils.DragDrop.TagQueryEntry
+			};
 
-		public LogicWidget (PhotoQuery query, TagStore tag_store, TagSelectionWidget selector) : base ()
+		public LogicWidget (PhotoQuery query, TagStore tag_store) : base ()
 		{
 			//SetFlag (WidgetFlags.NoWindow);
 			this.query = query;
-			this.tag_selection_widget = selector;
 
 			CanFocus = true;
 			Sensitive = true;
@@ -368,9 +368,9 @@ namespace FSpot
 			UpdateQuery ();
 		}
 
-		private void HandleTermAdded (Term parent, Literal after)
+		private void HandleTagsAdded (Tag[] tags, Term parent, Literal after)
 		{
-			InsertTerm (parent, after);
+			InsertTerm (tags, parent, after);
 		}
 
 		private void HandleAttachTag (Tag tag, Term parent, Literal after)
@@ -427,9 +427,24 @@ namespace FSpot
 
 		private void HandleDragDataReceived (object o, DragDataReceivedArgs args)
 		{
-			InsertTerm (rootTerm, null);
-
 			args.RetVal = true;
+			
+			if (args.Info == GuiUtils.DragDrop.TagListEntry.Info) {
+
+				InsertTerm (FSpot.GuiUtils.DragDrop.GetTagsData (args.SelectionData), rootTerm, null);
+				return;
+			}
+			
+			if (args.Info == GuiUtils.DragDrop.TagQueryEntry.Info) {
+
+				// FIXME: use drag data
+				HandleLiteralsMoved (Literal.FocusedLiterals, rootTerm, null);
+
+				// Prevent them from being removed again
+				Literal.FocusedLiterals = null;
+				
+				return;
+			}
 		}
 
 		/** Helper Functions **/
@@ -594,18 +609,6 @@ namespace FSpot
 			UpdateQuery ();
 		}
 
-		private void InsertTerm (Term parent, Literal after)
-		{
-			if (Literal.FocusedLiterals.Count != 0) {
-				HandleLiteralsMoved (Literal.FocusedLiterals, parent, after);
-
-				// Prevent them from being removed again
-				Literal.FocusedLiterals = null;
-			}
-			else
-				InsertTerm (tag_selection_widget.TagHighlight, parent, after);
-		}
-
 		public ArrayList InsertTerm (Tag [] tags, Term parent, Literal after)
 		{
 			int position;
@@ -642,7 +645,7 @@ namespace FSpot
 				}
 
 				Literal term  = new Literal (parent, tag, after);
-				term.TermAdded  += HandleTermAdded;
+				term.TagsAdded  += HandleTagsAdded;
 				term.LiteralsMoved += HandleLiteralsMoved;
 				term.AttachTag  += HandleAttachTag;
 				term.NegatedToggled += HandleNegated;
diff --git a/src/TagSelectionWidget.cs b/src/TagSelectionWidget.cs
index aab4617..e85aa19 100644
--- a/src/TagSelectionWidget.cs
+++ b/src/TagSelectionWidget.cs
@@ -1,635 +1,854 @@
-//
-// TagSelectionWidget.cs
-//
-// Copyright (C) 2004 Novell, Inc.
-//
-//
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, sublicense,
-// and/or sell copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-//
+/*
+ * TagSelectionWidget.cs
+ *
+ * Author(s)
+ * 
+ * This is free software. See COPYING for details.
+ */
+
 
-using GLib;
-using Gdk;
-using Gtk;
 using System.Collections;
 using System.Collections.Generic;
 using System.IO;
 using System;
 
-using Mono.Unix;
-using FSpot;
-using FSpot.UI.Dialog;
-
-public class TagSelectionWidget : FSpot.Widgets.SaneTreeView {
-	TagSelectionWidget widget;
-	private TagStore tag_store;
-
-	// FIXME this is a hack.
-	private static Pixbuf empty_pixbuf = new Pixbuf (Colorspace.Rgb, true, 8, 1, 1);
-
-	// If these are changed, the base () call in the constructor must be updated.
-	private const int IdColumn = 0;
-	private const int NameColumn = 1;
-
-	// Selection management.
+using GLib;
 
-	public Tag TagAtPosition (double x, double y) 
-    {
-        return TagAtPosition((int) x, (int) y);
-    }
+using Gdk;
 
-	public Tag TagAtPosition (int x, int y) 
-	{
-		TreePath path;
+using Gtk;
 
-		// Work out which tag we're dropping onto
-		if (!this.GetPathAtPos (x, y, out path))
-			return null;
+using Mono.Unix;
 
-		return TagByPath (path);
-	}
+using FSpot;
+using FSpot.Utils;
+using FSpot.Widgets;
+using FSpot.UI.Dialog;
 
-	public Tag TagByPath (TreePath path) 
-	{
-		TreeIter iter;
 
-		if (!Model.GetIter (out iter, path))
-			return null;
 
-		return TagByIter (iter);
-	}
+namespace FSpot {
 	
-	public Tag TagByIter (TreeIter iter)
-	{
-		GLib.Value val = new GLib.Value ();
- 
-		Model.GetValue (iter, IdColumn, ref val);
-		uint tag_id = (uint) val;
- 
-		return tag_store.Get (tag_id) as Tag;
- 	}
-
-	// Loading up the store.
-
-	private void LoadCategory (Category category, TreeIter parent_iter)
-	{
-		IList<Tag> tags = category.Children;
-
-		foreach (Tag t in tags) {
-			TreeIter iter = (Model as TreeStore).AppendValues (parent_iter, t.Id, t.Name);
-			if (t is Category)
-				LoadCategory (t as Category, iter);
+	public class TagSelectionWidget : SaneTreeView {
+		
+		Db database;
+		TagStore tag_store;
+	
+		// FIXME this is a hack.
+		private static Pixbuf empty_pixbuf = new Pixbuf (Colorspace.Rgb, true, 8, 1, 1);
+	
+		// If these are changed, the base () call in the constructor must be updated.
+		private const int IdColumn = 0;
+		private const int NameColumn = 1;
+	
+		// Selection management.
+	
+		public Tag TagAtPosition (double x, double y) 
+	    {
+	        return TagAtPosition((int) x, (int) y);
+	    }
+	
+		public Tag TagAtPosition (int x, int y) 
+		{
+			TreePath path;
+	
+			// Work out which tag we're dropping onto
+			if (!this.GetPathAtPos (x, y, out path))
+				return null;
+	
+			return TagByPath (path);
 		}
-	}
-
-	public void ScrollTo (Tag tag)
-	{
-		TreeIter iter;
-		if (! TreeIterForTag (tag, out iter))
-			return;
-
-		TreePath path = Model.GetPath (iter);
-
-		ScrollToCell (path, null, false, 0, 0);
-	}
-
-	public Tag [] TagHighlight {
-		get {
-			TreeModel model;
+	
+		public Tag TagByPath (TreePath path) 
+		{
 			TreeIter iter;
-
-			TreePath [] rows = Selection.GetSelectedRows(out model);
-
-			Tag [] tags = new Tag [rows.Length];
-			int i = 0;
-
-			foreach (TreePath path in rows) {
-				GLib.Value value = new GLib.Value ();
-				Model.GetIter (out iter, path);
-				Model.GetValue (iter, IdColumn, ref value);
-				uint tag_id = (uint) value;
-				tags[i] = tag_store.Get (tag_id) as Tag;
-				i++;
+	
+			if (!Model.GetIter (out iter, path))
+				return null;
+	
+			return TagByIter (iter);
+		}
+		
+		public Tag TagByIter (TreeIter iter)
+		{
+			GLib.Value val = new GLib.Value ();
+	 
+			Model.GetValue (iter, IdColumn, ref val);
+			uint tag_id = (uint) val;
+	 
+			return tag_store.Get (tag_id) as Tag;
+		}
+	
+		// Loading up the store.
+	
+		private void LoadCategory (Category category, TreeIter parent_iter)
+		{
+			IList<Tag> tags = category.Children;
+	
+			foreach (Tag t in tags) {
+				TreeIter iter = (Model as TreeStore).AppendValues (parent_iter, t.Id, t.Name);
+				if (t is Category)
+					LoadCategory (t as Category, iter);
 			}
-			return tags;
 		}
-
-		set {
-			if (value == null)
-				return;
-
-			Selection.UnselectAll ();
-
+	
+		public void ScrollTo (Tag tag)
+		{
 			TreeIter iter;
-			foreach (Tag tag in value)
-				if (TreeIterForTag (tag, out iter))
-					Selection.SelectIter (iter);
-		}
-	}
-
-	public void Update ()
-	{
-		(Model as TreeStore).Clear ();
-
-		// GRRR We have to special case the root because I can't pass null for a
-		// Gtk.TreeIter (since it's a struct, and not a class).
-		// FIXME: This should be fixed in GTK#...  It's gross.
-
-		foreach (Tag t in tag_store.RootCategory.Children) {
-			TreeIter iter = (Model as TreeStore).AppendValues (t.Id, t.Name);
-			if (t is Category)
-				LoadCategory (t as Category, iter);
+			if (! TreeIterForTag (tag, out iter))
+				return;
+	
+			TreePath path = Model.GetPath (iter);
+	
+			ScrollToCell (path, null, false, 0, 0);
 		}
-	}
-
-	// Data functions.
-	private static string ToHashColor (Gdk.Color color)
-	{
-		byte r = (byte) (color.Red >> 8);
-		byte g = (byte) (color.Green >> 8);
-		byte b = (byte) (color.Blue >> 8);
-		return String.Format ("#{0:x}{1:x}{2:x}", r, g, b);
-	}
-
-	private void SetBackground (CellRenderer renderer, Tag tag)
-	{
-		// FIXME this should be themable but Gtk# doesn't give me access to the proper
-		// members in GtkStyle for that.
-		/*
-		if (tag is Category)
-			renderer.CellBackground = ToHashColor (this.Style.MidColors [(int) Gtk.StateType.Normal]);
-		else
-			renderer.CellBackground = ToHashColor (this.Style.LightColors [(int) Gtk.StateType.Normal]);
-		*/
-	}
-
-	private void IconDataFunc (TreeViewColumn column, 
-				   CellRenderer renderer,
-				   TreeModel model,
-				   TreeIter iter)
-	{
-		GLib.Value value = new GLib.Value ();
-		Model.GetValue (iter, IdColumn, ref value);
-		uint tag_id = (uint) value;
-		Tag tag = tag_store.Get (tag_id) as Tag;
-
-		SetBackground (renderer, tag);
-
-		// FIXME I can't set the Pixbuf to null, not sure if it's a GTK# bug...
-		if (tag.SizedIcon != null) {
-			if (FSpot.ColorManagement.IsEnabled) {
-				//FIXME
-				Gdk.Pixbuf temp = tag.SizedIcon.Copy();
-				FSpot.ColorManagement.ApplyScreenProfile (temp);
-				(renderer as CellRendererPixbuf).Pixbuf = temp;
+	
+		public Tag [] TagHighlight {
+			get {
+				TreeModel model;
+				TreeIter iter;
+	
+				TreePath [] rows = Selection.GetSelectedRows(out model);
+	
+				Tag [] tags = new Tag [rows.Length];
+				int i = 0;
+	
+				foreach (TreePath path in rows) {
+					GLib.Value value = new GLib.Value ();
+					Model.GetIter (out iter, path);
+					Model.GetValue (iter, IdColumn, ref value);
+					uint tag_id = (uint) value;
+					tags[i] = tag_store.Get (tag_id) as Tag;
+					i++;
+				}
+				return tags;
+			}
+	
+			set {
+				if (value == null)
+					return;
+	
+				Selection.UnselectAll ();
+	
+				TreeIter iter;
+				foreach (Tag tag in value)
+					if (TreeIterForTag (tag, out iter))
+						Selection.SelectIter (iter);
 			}
-			else
-				(renderer as CellRendererPixbuf).Pixbuf = tag.SizedIcon;
-		}
-		else
-			(renderer as CellRendererPixbuf).Pixbuf = empty_pixbuf;
-	}
-
-	private void NameDataFunc (TreeViewColumn column,
-				   CellRenderer renderer,
-				   TreeModel model,
-				   TreeIter iter)
-	{
-		// FIXME not sure why it happens...
-		if (model == null)
-			return;
-
-		GLib.Value value = new GLib.Value ();
-		Model.GetValue (iter, IdColumn, ref value);
-		uint tag_id = (uint) value;
-
-		Tag tag = tag_store.Get (tag_id) as Tag;
-
-		SetBackground (renderer, tag);
-
-		(renderer as CellRendererText).Text = tag.Name;
-	}
-
-	private bool TreeIterForTag(Tag tag, out TreeIter iter) 
-	{
-		TreeIter root = TreeIter.Zero;
-		iter = TreeIter.Zero;
-
-		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);
+	
+		public void Update ()
+		{
+			(Model as TreeStore).Clear ();
+	
+			// GRRR We have to special case the root because I can't pass null for a
+			// Gtk.TreeIter (since it's a struct, and not a class).
+			// FIXME: This should be fixed in GTK#...  It's gross.
+	
+			foreach (Tag t in tag_store.RootCategory.Children) {
+				TreeIter iter = (Model as TreeStore).AppendValues (t.Id, t.Name);
+				if (t is Category)
+					LoadCategory (t as Category, iter);
+			}
 		}
-
-		GLib.Value value = new GLib.Value ();
-		Model.GetValue (parent, IdColumn, 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, IdColumn, ref value);
-		Tag tag = (Tag) tag_store.Get ((uint)value);
-		if (is_parent) {
-			// 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, tag.Name);
+		// Data functions.
+		private static string ToHashColor (Gdk.Color color)
+		{
+			byte r = (byte) (color.Red >> 8);
+			byte g = (byte) (color.Green >> 8);
+			byte b = (byte) (color.Blue >> 8);
+			return String.Format ("#{0:x}{1:x}{2:x}", r, g, b);
 		}
-		
-		valid = Model.IterChildren (out iter, src);
-		while (valid) {
-			// child nodes are already ordered
-			CopyBranch (iter, copy, false, false);
-			valid = Model.IterNext (ref iter);
+	
+		private void SetBackground (CellRenderer renderer, Tag tag)
+		{
+			// FIXME this should be themable but Gtk# doesn't give me access to the proper
+			// members in GtkStyle for that.
+			/*
+			if (tag is Category)
+				renderer.CellBackground = ToHashColor (this.Style.MidColors [(int) Gtk.StateType.Normal]);
+			else
+				renderer.CellBackground = ToHashColor (this.Style.LightColors [(int) Gtk.StateType.Normal]);
+			*/
 		}
-	}
-
-	// 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) 
-	{
-		TreeStore store = Model as TreeStore;
-		TreeIter iter;
-		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...
+	
+		private void IconDataFunc (TreeViewColumn column, 
+					   CellRenderer renderer,
+					   TreeModel model,
+					   TreeIter iter)
+		{
 			GLib.Value value = new GLib.Value ();
-			store.GetValue(iter, IdColumn, ref value);
-			compare = (Tag) tag_store.Get ((uint) value);
-
-			if (compare.CompareTo (tag) > 0) {
-				iter = store.InsertNodeBefore (iter);
-				store.SetValue (iter, IdColumn, tag.Id);
-				store.SetValue (iter, NameColumn, tag.Name);
-				
-				if (!is_root)
-					ExpandRow (Model.GetPath (parent), false);
-				return iter;
+			Model.GetValue (iter, IdColumn, ref value);
+			uint tag_id = (uint) value;
+			Tag tag = tag_store.Get (tag_id) as Tag;
+	
+			SetBackground (renderer, tag);
+	
+			// FIXME I can't set the Pixbuf to null, not sure if it's a GTK# bug...
+			if (tag.SizedIcon != null) {
+				if (FSpot.ColorManagement.IsEnabled) {
+					//FIXME
+					Gdk.Pixbuf temp = tag.SizedIcon.Copy();
+					FSpot.ColorManagement.ApplyScreenProfile (temp);
+					(renderer as CellRendererPixbuf).Pixbuf = temp;
+				}
+				else
+					(renderer as CellRendererPixbuf).Pixbuf = tag.SizedIcon;
 			}
-			valid = store.IterNext(ref iter);
-		}
-		
-		if (is_root) 
-			iter = store.AppendNode (); 
-		else {
-			iter = store.AppendNode (parent); 
-			ExpandRow (Model.GetPath (parent), false);
+			else
+				(renderer as CellRendererPixbuf).Pixbuf = empty_pixbuf;
 		}
-
-		store.SetValue (iter, IdColumn, tag.Id);
-		store.SetValue (iter, NameColumn, tag.Name);
-		return iter;
-	}
-
-	private void HandleTagsRemoved (object sender, DbItemEventArgs<Tag> args)
-	{
-		TreeIter iter;
-
-		foreach (Tag tag in args.Items) {
-			if (TreeIterForTag (tag, out iter)) 
-				(Model as TreeStore).Remove (ref iter);
+	
+		private void NameDataFunc (TreeViewColumn column,
+					   CellRenderer renderer,
+					   TreeModel model,
+					   TreeIter iter)
+		{
+			// FIXME not sure why it happens...
+			if (model == null)
+				return;
+	
+			GLib.Value value = new GLib.Value ();
+			Model.GetValue (iter, IdColumn, ref value);
+			uint tag_id = (uint) value;
+	
+			Tag tag = tag_store.Get (tag_id) as Tag;
+	
+			SetBackground (renderer, tag);
+	
+			(renderer as CellRendererText).Text = tag.Name;
 		}
-	}
 	
-	private void HandleTagsAdded (object sender, DbItemEventArgs<Tag> args)
-	{
-		TreeIter iter = TreeIter.Zero;
-		
-		foreach (Tag tag in args.Items) {
-			if (tag.Category != tag_store.RootCategory)
-				TreeIterForTag (tag.Category, out iter);
-
-			InsertInOrder (iter,
-				       tag.Category.Name == tag_store.RootCategory.Name,
-				       tag);
+		private bool TreeIterForTag(Tag tag, out TreeIter iter) 
+		{
+			TreeIter root = TreeIter.Zero;
+			iter = TreeIter.Zero;
+	
+			bool valid = Model.GetIterFirst (out root);
+			
+			while (valid) {
+				if (TreeIterForTagRecurse (tag, root, out iter))
+					return true;
+	
+				valid = Model.IterNext (ref root);
+			}
+			return false;
 		}
-	}
 	
-	private void HandleTagsChanged (object sender, DbItemEventArgs<Tag> args)
-	{
-		TreeStore store = Model as TreeStore;
-		TreeIter iter, category_iter, parent_iter;
-
-		foreach (Tag tag in args.Items) {
-			TreeIterForTag (tag, out iter);
+		// 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, IdColumn, 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;
 			
-			bool category_valid = TreeIterForTag(tag.Category, out category_iter);
-			bool parent_valid = Model.IterParent(out parent_iter, iter);
+			store.GetValue (src, IdColumn, ref value);
+			Tag tag = (Tag) tag_store.Get ((uint)value);
+			if (is_parent) {
+				// 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, tag.Name);
+			}
 			
-			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);
+			valid = Model.IterChildren (out iter, src);
+			while (valid) {
+				// child nodes are already ordered
+				CopyBranch (iter, copy, false, false);
+				valid = Model.IterNext (ref iter);
 			}
 		}
-	}
-
-	void ExpandDefaults ()
-	{
-		int [] tags = FSpot.Preferences.Get<int []> (FSpot.Preferences.EXPANDED_TAGS);
-		if (tags == null) {
-			ExpandAll ();
-			return;
-		}
-
-		TreeIter [] iters = ModelIters ();
-		if (iters == null || iters.Length == 0 || tags.Length == 0)
-			return;
-
-		foreach (TreeIter iter in iters)
+	
+		// 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) 
 		{
-			GLib.Value v = new GLib.Value ();
-			Model.GetValue (iter, IdColumn, ref v);
-			int tag_id = (int)(uint) v;
-			if (Array.IndexOf (tags, tag_id) > -1) {
-				ExpandRow (Model.GetPath (iter), false);
+			TreeStore store = Model as TreeStore;
+			TreeIter iter;
+			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, IdColumn, ref value);
+				compare = (Tag) tag_store.Get ((uint) value);
+	
+				if (compare.CompareTo (tag) > 0) {
+					iter = store.InsertNodeBefore (iter);
+					store.SetValue (iter, IdColumn, tag.Id);
+					store.SetValue (iter, NameColumn, tag.Name);
+					
+					if (!is_root)
+						ExpandRow (Model.GetPath (parent), false);
+					return iter;
+				}
+				valid = store.IterNext(ref iter);
+			}
+			
+			if (is_root) 
+				iter = store.AppendNode (); 
+			else {
+				iter = store.AppendNode (parent); 
+				ExpandRow (Model.GetPath (parent), false);
 			}
+	
+			store.SetValue (iter, IdColumn, tag.Id);
+			store.SetValue (iter, NameColumn, tag.Name);
+			return iter;
 		}
-	}
-
-	// Returns a flattened array of TreeIter's from the Model
-	TreeIter [] ModelIters ()
-	{
-		TreeIter root;
-		if (Model.GetIterFirst (out root))
+	
+		private void HandleTagsRemoved (object sender, DbItemEventArgs<Tag> args)
 		{
-			return ModelIters (root, true).ToArray (typeof (TreeIter)) as TreeIter [];
+			TreeIter iter;
+	
+			foreach (Tag tag in args.Items) {
+				if (TreeIterForTag (tag, out iter)) 
+					(Model as TreeStore).Remove (ref iter);
+			}
 		}
-
-		return null;
-	}
-
-	// Returns ArrayList containing the root TreeIter and all TreeIters at root's level and
-	// descended from it
-	ArrayList ModelIters (TreeIter root, bool first)
-	{
-		ArrayList model_iters = new ArrayList (Model.IterNChildren ());
-
-		model_iters.Add (root);
-
-		// Append any children
-		TreeIter child;
-		if (Model.IterChildren (out child, root))
-			model_iters.AddRange (ModelIters (child, true));
 		
-		// Append any siblings and their children
-		if (first) {
-			while (Model.IterNext (ref root)) {
-				model_iters.AddRange (ModelIters (root, false));
+		private void HandleTagsAdded (object sender, DbItemEventArgs<Tag> args)
+		{
+			TreeIter iter = TreeIter.Zero;
+			
+			foreach (Tag tag in args.Items) {
+				if (tag.Category != tag_store.RootCategory)
+					TreeIterForTag (tag.Category, out iter);
+	
+				InsertInOrder (iter,
+					       tag.Category.Name == tag_store.RootCategory.Name,
+					       tag);
 			}
 		}
-
-		return model_iters;
-	}
-
-	public void SaveExpandDefaults ()
-	{
-		ArrayList expanded_tags = new ArrayList ();
 		
-		TreeIter [] iters = ModelIters ();
-		if (iters == null)
-			return;
-
-		foreach (TreeIter iter in iters)
+		private void HandleTagsChanged (object sender, DbItemEventArgs<Tag> args)
 		{
-			if (GetRowExpanded (Model.GetPath (iter))) {
+			TreeStore store = Model as TreeStore;
+			TreeIter iter, category_iter, parent_iter;
+	
+			foreach (Tag tag in args.Items) {
+				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);
+				}
+			}
+		}
+	
+		void ExpandDefaults ()
+		{
+			int [] tags = FSpot.Preferences.Get<int []> (FSpot.Preferences.EXPANDED_TAGS);
+			if (tags == null) {
+				ExpandAll ();
+				return;
+			}
+	
+			TreeIter [] iters = ModelIters ();
+			if (iters == null || iters.Length == 0 || tags.Length == 0)
+				return;
+	
+			foreach (TreeIter iter in iters)
+			{
 				GLib.Value v = new GLib.Value ();
 				Model.GetValue (iter, IdColumn, ref v);
-				expanded_tags.Add ((int)(uint) v);
+				int tag_id = (int)(uint) v;
+				if (Array.IndexOf (tags, tag_id) > -1) {
+					ExpandRow (Model.GetPath (iter), false);
+				}
 			}
 		}
-
-#if GCONF_SHARP_2_18
-		FSpot.Preferences.Set (	FSpot.Preferences.EXPANDED_TAGS, (int []) expanded_tags.ToArray (typeof (int)));
-#else
-		if (expanded_tags.Count == 0)
-			expanded_tags.Add (-1);
-
-		FSpot.Preferences.Set (	FSpot.Preferences.EXPANDED_TAGS,
-						(int []) expanded_tags.ToArray (typeof (int)));
-#endif
-	}
-
-	public void EditSelectedTagName ()
-	{
-		TreePath [] rows = Selection.GetSelectedRows();
-		if (rows.Length != 1)
+	
+		// Returns a flattened array of TreeIter's from the Model
+		TreeIter [] ModelIters ()
+		{
+			TreeIter root;
+			if (Model.GetIterFirst (out root))
+			{
+				return ModelIters (root, true).ToArray (typeof (TreeIter)) as TreeIter [];
+			}
+	
+			return null;
+		}
+	
+		// Returns ArrayList containing the root TreeIter and all TreeIters at root's level and
+		// descended from it
+		ArrayList ModelIters (TreeIter root, bool first)
+		{
+			ArrayList model_iters = new ArrayList (Model.IterNChildren ());
+	
+			model_iters.Add (root);
+	
+			// Append any children
+			TreeIter child;
+			if (Model.IterChildren (out child, root))
+				model_iters.AddRange (ModelIters (child, true));
+			
+			// Append any siblings and their children
+			if (first) {
+				while (Model.IterNext (ref root)) {
+					model_iters.AddRange (ModelIters (root, false));
+				}
+			}
+	
+			return model_iters;
+		}
+	
+		public void SaveExpandDefaults ()
+		{
+			ArrayList expanded_tags = new ArrayList ();
+			
+			TreeIter [] iters = ModelIters ();
+			if (iters == null)
+				return;
+	
+			foreach (TreeIter iter in iters)
+			{
+				if (GetRowExpanded (Model.GetPath (iter))) {
+					GLib.Value v = new GLib.Value ();
+					Model.GetValue (iter, IdColumn, ref v);
+					expanded_tags.Add ((int)(uint) v);
+				}
+			}
+	
+	#if GCONF_SHARP_2_18
+			FSpot.Preferences.Set (	FSpot.Preferences.EXPANDED_TAGS, (int []) expanded_tags.ToArray (typeof (int)));
+	#else
+			if (expanded_tags.Count == 0)
+				expanded_tags.Add (-1);
+	
+			FSpot.Preferences.Set (	FSpot.Preferences.EXPANDED_TAGS,
+							(int []) expanded_tags.ToArray (typeof (int)));
+	#endif
+		}
+	
+		public void EditSelectedTagName ()
+		{
+			TreePath [] rows = Selection.GetSelectedRows();
+			if (rows.Length != 1)
+				return;
+			
+			//SetCursor (rows[0], NameColumn, true);
+			text_render.Editable = true;
+			text_render.Edited += HandleTagNameEdited;
+			SetCursor (rows[0], complete_column, true);
+			text_render.Editable = false;
+		}
+	
+		public void HandleTagNameEdited (object sender, EditedArgs args)
+		{
+			args.RetVal = false;
+	
+			TreeIter iter;
+	
+			if (!Model.GetIterFromString (out iter, args.Path))
+				return;
+	
+			GLib.Value value = new GLib.Value ();
+			Model.GetValue (iter, IdColumn, ref value);
+			uint tag_id = (uint) value;
+			Tag tag = tag_store.Get (tag_id) as Tag;
+	
+			// Ignore if it hasn't changed
+			if (tag.Name == args.NewText)
+				return;
+	
+			// Check that the tag doesn't already exist
+			if (String.Compare (args.NewText, tag.Name, true) != 0 &&
+			    tag_store.GetTagByName (args.NewText) != null) {
+				HigMessageDialog md = new HigMessageDialog (MainWindow.Toplevel.Window,
+					DialogFlags.DestroyWithParent, 
+					MessageType.Warning, ButtonsType.Ok, 
+					Catalog.GetString ("Error renaming tag"),
+					Catalog.GetString ("This name is already in use"));
+	
+				md.Run ();
+				md.Destroy ();
+				this.GrabFocus ();
+				return;
+			}
+	
+			tag.Name = args.NewText;
+			tag_store.Commit (tag, true);
+	
+			text_render.Edited -= HandleTagNameEdited;
+	
+			args.RetVal = true;
 			return;
+		}
 		
-		//SetCursor (rows[0], NameColumn, true);
-		text_render.Editable = true;
-		text_render.Edited += HandleTagNameEdited;
-		SetCursor (rows[0], complete_column, true);
-		text_render.Editable = false;
-	}
-
-	public void HandleTagNameEdited (object sender, EditedArgs args)
-	{
-		args.RetVal = false;
-
-		TreeIter iter;
-
-		if (!Model.GetIterFromString (out iter, args.Path))
-			return;
-
-		GLib.Value value = new GLib.Value ();
-		Model.GetValue (iter, IdColumn, ref value);
-		uint tag_id = (uint) value;
-		Tag tag = tag_store.Get (tag_id) as Tag;
-
-		// Ignore if it hasn't changed
-		if (tag.Name == args.NewText)
-			return;
-
-		// Check that the tag doesn't already exist
-		if (String.Compare (args.NewText, tag.Name, true) != 0 &&
-		    tag_store.GetTagByName (args.NewText) != null) {
-			HigMessageDialog md = new HigMessageDialog (MainWindow.Toplevel.Window,
-				DialogFlags.DestroyWithParent, 
-				MessageType.Warning, ButtonsType.Ok, 
-				Catalog.GetString ("Error renaming tag"),
-				Catalog.GetString ("This name is already in use"));
-
-			md.Run ();
-			md.Destroy ();
-			this.GrabFocus ();
-			return;
+		private static TargetEntry [] tag_source_target_table = 
+			new TargetEntry [] {
+				FSpot.GuiUtils.DragDrop.TagListEntry
+			};
+	
+		private static TargetEntry [] tag_dest_target_table = 
+			new TargetEntry [] {
+				FSpot.GuiUtils.DragDrop.PhotoListEntry,
+				FSpot.GuiUtils.DragDrop.UriListEntry,
+				FSpot.GuiUtils.DragDrop.TagListEntry
+			};
+	
+		//TreeViewColumn check_column;
+		//TreeViewColumn icon_column;
+		//TreeViewColumn name_column;
+		CellRendererPixbuf pix_render;
+		TreeViewColumn complete_column;
+		CellRendererText text_render;
+	
+		// Constructor.
+		public TagSelectionWidget (TagStore tag_store)
+			: base (new TreeStore (typeof(uint), typeof(string)))
+		{
+			database = MainWindow.Toplevel.Database;
+			
+			HeadersVisible = false;
+	
+			complete_column = new TreeViewColumn ();
+					
+			pix_render = new CellRendererPixbuf ();
+			complete_column.PackStart (pix_render, false);
+			complete_column.SetCellDataFunc (pix_render, new TreeCellDataFunc (IconDataFunc));
+			//complete_column.AddAttribute (pix_render, "pixbuf", OpenIconColumn);
+	
+			//icon_column = AppendColumn ("icon", 
+			//, new TreeCellDataFunc (IconDataFunc));
+			//icon_column = AppendColumn ("icon", new CellRendererPixbuf (), new TreeCellDataFunc (IconDataFunc));
+	
+			text_render = new CellRendererText ();
+			complete_column.PackStart (text_render, true);
+			complete_column.SetCellDataFunc (text_render, new TreeCellDataFunc (NameDataFunc));
+	
+			AppendColumn (complete_column);
+	
+			this.tag_store = tag_store;
+	
+			Update ();
+	
+			ExpandDefaults ();
+	
+			tag_store.ItemsAdded += HandleTagsAdded;
+			tag_store.ItemsRemoved += HandleTagsRemoved;
+			tag_store.ItemsChanged += HandleTagsChanged;
+	
+			// TODO make the search find tags that are not currently expanded
+			EnableSearch = true;
+			SearchColumn = NameColumn;
+	
+			// Transparent white
+			empty_pixbuf.Fill(0xffffff00);
+			
+			
+			/* set up drag and drop */
+			DragDataGet += HandleDragDataGet;
+			DragDrop += HandleDragDrop;
+			DragBegin += HandleDragBegin;
+
+			Gtk.Drag.SourceSet (this,
+			           Gdk.ModifierType.Button1Mask | Gdk.ModifierType.Button3Mask,
+			           tag_source_target_table,
+			           DragAction.Copy | DragAction.Move);
+
+			DragDataReceived += HandleDragDataReceived;
+			DragMotion += HandleDragMotion;
+			
+			Gtk.Drag.DestSet (this,
+			                  DestDefaults.All,
+			                  tag_dest_target_table,
+			                  DragAction.Copy | DragAction.Move); 
 		}
-
-		tag.Name = args.NewText;
-		tag_store.Commit (tag, true);
-
-		text_render.Edited -= HandleTagNameEdited;
-
-		args.RetVal = true;
-		return;
-	}
-
-	//TreeViewColumn check_column;
-	//TreeViewColumn icon_column;
-	//TreeViewColumn name_column;
-	CellRendererPixbuf pix_render;
-	TreeViewColumn complete_column;
-	CellRendererText text_render;
-
-	// Constructor.
-	public TagSelectionWidget (TagStore tag_store)
-		: base (new TreeStore (typeof(uint), typeof(string)))
-	{
-		HeadersVisible = false;
-
-		complete_column = new TreeViewColumn ();
+		
+		/*void HandleTagSelectionRowActivated (object sender, RowActivatedArgs args)
+		{
+			ShowQueryWidget ();
+			query_widget.Include (new Tag [] {tag_selection_widget.TagByPath (args.Path)});
+		}*/
+	
+		/*void HandleTagSelectionButtonPressEvent (object sender, ButtonPressEventArgs args)
+		{
+			if (args.Event.Button == 3) {
+				TagPopup popup = new TagPopup ();
+				popup.Activate (args.Event, tag_selection_widget.TagAtPosition (args.Event.X, args.Event.Y),
+				tag_selection_widget.TagHighlight);
+				args.RetVal = true;
+			}
+		}*/
+	
+		/*void HandleTagSelectionPopupMenu (object sender, PopupMenuArgs args)
+		{
+			TagPopup popup = new TagPopup ();
+			popup.Activate (null, null, tag_selection_widget.TagHighlight);
+			args.RetVal = true;
+		}*/
+	
+		void HandleDragBegin (object sender, DragBeginArgs args)
+		{
+			Tag [] tags = TagHighlight;
+			int len = tags.Length;
+			int size = 32;
+			int csize = size/2 + len * size / 2 + 2;
+			
+			Pixbuf container = new Pixbuf (Gdk.Colorspace.Rgb, true, 8, csize, csize);
+			container.Fill (0x00000000);
+			
+			bool use_icon = false;;
+			while (len-- > 0) {
+				Pixbuf thumbnail = tags[len].Icon;
 				
-		pix_render = new CellRendererPixbuf ();
-		complete_column.PackStart (pix_render, false);
-		complete_column.SetCellDataFunc (pix_render, new TreeCellDataFunc (IconDataFunc));
-		//complete_column.AddAttribute (pix_render, "pixbuf", OpenIconColumn);
-
-		//icon_column = AppendColumn ("icon", 
-		//, new TreeCellDataFunc (IconDataFunc));
-		//icon_column = AppendColumn ("icon", new CellRendererPixbuf (), new TreeCellDataFunc (IconDataFunc));
-
-		text_render = new CellRendererText ();
-		complete_column.PackStart (text_render, true);
-		complete_column.SetCellDataFunc (text_render, new TreeCellDataFunc (NameDataFunc));
-
-		AppendColumn (complete_column);
-
-		this.tag_store = tag_store;
-
-		Update ();
-
-		ExpandDefaults ();
-
-		tag_store.ItemsAdded += HandleTagsAdded;
-		tag_store.ItemsRemoved += HandleTagsRemoved;
-		tag_store.ItemsChanged += HandleTagsChanged;
-
-		// TODO make the search find tags that are not currently expanded
-		EnableSearch = true;
-		SearchColumn = NameColumn;
-
-		// Transparent white
-		empty_pixbuf.Fill(0xffffff00);
-	}
-
-
-#if TEST_TAG_SELECTION_WIDGET
-
-	class Test {
-
-		private TagSelectionWidget selection_widget;
-
-		private void OnSelectionChanged ()
+				if (thumbnail != null) {
+					Pixbuf small = PixbufUtils.ScaleToMaxSize (thumbnail, size, size);				
+					
+					int x = len * (size/2) + (size - small.Width)/2;
+					int y = len * (size/2) + (size - small.Height)/2;
+	
+					small.Composite (container, x, y, small.Width, small.Height, x, y, 1.0, 1.0, Gdk.InterpType.Nearest, 0xff);
+					small.Dispose ();
+	
+					use_icon = true;
+				}
+			}
+			
+			if (use_icon)
+				Gtk.Drag.SetIconPixbuf (args.Context, container, 0, 0);
+			
+			container.Dispose ();
+		}
+		
+		void HandleDragDataGet (object sender, DragDataGetArgs args)
 		{
-			Console.WriteLine ("Selection changed:");
-
-			foreach (Tag t in selection_widget.TagSelection)
-				Console.WriteLine ("\t{0}", t.Name);
+			if (args.Info == FSpot.GuiUtils.DragDrop.TagListEntry.Info) {
+				FSpot.GuiUtils.DragDrop.SetTagsData (TagHighlight, args.SelectionData);
+				return;
+			}
 		}
-
-		private Test ()
+	
+		void HandleDragDrop (object sender, DragDropArgs args)
 		{
-			const string path = "/tmp/TagSelectionTest.db";
-
-			try {
-				File.Delete (path);
-			} catch {}
-
-			Db db = new Db (path, true);
-
-			Category people_category = db.Tags.CreateCategory (null, "People");
-			db.Tags.CreateTag (people_category, "Anna");
-			db.Tags.CreateTag (people_category, "Ettore");
-			db.Tags.CreateTag (people_category, "Miggy");
-			db.Tags.CreateTag (people_category, "Nat");
-
-			Category places_category = db.Tags.CreateCategory (null, "Places");
-			db.Tags.CreateTag (places_category, "Milan");
-			db.Tags.CreateTag (places_category, "Boston");
-
-			Category exotic_category = db.Tags.CreateCategory (places_category, "Exotic");
-			db.Tags.CreateTag (exotic_category, "Bengalore");
-			db.Tags.CreateTag (exotic_category, "Manila");
-			db.Tags.CreateTag (exotic_category, "Tokyo");
-
-			selection_widget = new TagSelectionWidget (db.Tags);
-			selection_widget.SelectionChanged += new SelectionChangedHandler (OnSelectionChanged);
-
-			Window window = new Window (WindowType.Toplevel);
-			window.SetDefaultSize (400, 200);
-			ScrolledWindow scrolled = new ScrolledWindow (null, null);
-			scrolled.SetPolicy (PolicyType.Automatic, PolicyType.Automatic);
-			scrolled.Add (selection_widget);
-			window.Add (scrolled);
-
-			window.ShowAll ();
+			args.RetVal = true;
 		}
-
-		static private void Main (string [] args)
+	
+		public void HandleDragMotion (object o, DragMotionArgs args)
 		{
-			Program program = new Program ("TagSelectionWidgetTest", "0.0", Modules.UI, args);
-
-			Test test = new Test ();
+			TreePath path;
+	        TreeViewDropPosition position = TreeViewDropPosition.IntoOrAfter;
+			GetPathAtPos (args.X, args.Y, out path);
+	
+	        if (path == null)
+	            return;
+	
+	        // Tags can be dropped before, after, or into another tag
+	        if (args.Context.Targets[0].Name == "application/x-fspot-tags") {
+	            Gdk.Rectangle rect = GetCellArea(path, Columns[0]);
+	            double vpos = Math.Abs(rect.Y - args.Y) / (double)rect.Height;
+	            if (vpos < 0.2) {
+	                position = TreeViewDropPosition.Before;
+	            } else if (vpos > 0.8) {
+	                position = TreeViewDropPosition.After;
+	            }
+	        }
+	
+			SetDragDestRow (path, position);
+	
+			// Scroll if within 20 pixels of the top or bottom of the tag list
+			if (args.Y < 20)
+				Vadjustment.Value -= 30;
+	        else if (((o as Gtk.Widget).Allocation.Height - args.Y) < 20)
+				Vadjustment.Value += 30;
+		}
+	
+		public void HandleDragDataReceived (object o, DragDataReceivedArgs args)
+		{
+	        TreePath path;
+	        TreeViewDropPosition position;
+			
+	        if ( ! GetDestRowAtPos ((int)args.X, (int)args.Y, out path, out position))
+	            return;
+	
+	        Tag tag = path == null ? null : TagByPath (path);
+			if (tag == null)
+				return;
+	
+			if (args.Info == GuiUtils.DragDrop.PhotoListEntry.Info) {
+				database.BeginTransaction ();
 
-			program.Run ();
+				Photo[] photos = FSpot.GuiUtils.DragDrop.GetPhotosData (args.SelectionData);
+				
+				foreach (Photo photo in photos) {
+
+					if (photo == null)
+						continue;
+					
+					photo.AddTag (tag);
+					database.Photos.Commit (photo);
+					
+					// FIXME: AddTagExtendes from Mainwindow.cs does some tag-icon handling.
+					// this should be done here or completely located to the Tag-class.
+				}
+				database.CommitTransaction ();
+				
+				// FIXME: this needs to be done somewhere:
+				//query_widget.PhotoTagsChanged (new Tag[] {tag});
+				return;
+			}
+			
+			if (args.Info == GuiUtils.DragDrop.UriListEntry.Info) {
+				UriList list = FSpot.GuiUtils.DragDrop.GetUriListData (args.SelectionData);
+				
+				database.BeginTransaction ();
+				List<Photo> photos = new List<Photo> ();
+				foreach (Uri photo_uri in list) {
+					Photo photo = database.Photos.GetByUri (photo_uri);
+					
+					// FIXME - at this point we should import the photo, and then continue
+					if (photo == null)
+						continue;
+					
+					// FIXME this should really follow the AddTagsExtended path too
+					photo.AddTag (new Tag[] {tag});
+					photos.Add (photo);
+				}
+				database.Photos.Commit (photos.ToArray ());
+				database.CommitTransaction ();
+				
+				// FIXME: this need to be done
+				//InvalidateViews (); // but it seems not to be needed. tags are updated through in IconView through PhotoChanged
+				return;
+			}
+	
+			if (args.Info == GuiUtils.DragDrop.TagListEntry.Info) {
+				Category parent;
+	            if (position == TreeViewDropPosition.Before || position == TreeViewDropPosition.After) {
+	                parent = tag.Category;
+	            } else {
+	                parent = tag as Category;
+	            }
+	
+				if (parent == null || TagHighlight.Length < 1) {
+	                args.RetVal = false;
+					return;
+	            }
+	
+	            int moved_count = 0;
+	            Tag [] highlighted_tags = TagHighlight;
+				foreach (Tag child in TagHighlight) {
+	                // FIXME with this reparenting via dnd, you cannot move a tag to root.
+	                if (child != parent && child.Category != parent && !child.IsAncestorOf(parent)) {
+	                    child.Category = parent as Category;
+	
+	                    // Saving changes will automatically cause the TreeView to be updated
+	                    database.Tags.Commit (child);
+	                    moved_count++;
+	                }
+	            }
+	
+	            // Reselect the same tags
+	            TagHighlight = highlighted_tags;
+	
+	            args.RetVal = moved_count > 0;
+				return;
+			}
 		}
+	
+	
+	#if TEST_TAG_SELECTION_WIDGET
+	
+		class Test {
+	
+			private TagSelectionWidget selection_widget;
+	
+			private void OnSelectionChanged ()
+			{
+				Console.WriteLine ("Selection changed:");
+	
+				foreach (Tag t in selection_widget.TagSelection)
+					Console.WriteLine ("\t{0}", t.Name);
+			}
+	
+			private Test ()
+			{
+				const string path = "/tmp/TagSelectionTest.db";
+	
+				try {
+					File.Delete (path);
+				} catch {}
+	
+				Db db = new Db (path, true);
+	
+				Category people_category = db.Tags.CreateCategory (null, "People");
+				db.Tags.CreateTag (people_category, "Anna");
+				db.Tags.CreateTag (people_category, "Ettore");
+				db.Tags.CreateTag (people_category, "Miggy");
+				db.Tags.CreateTag (people_category, "Nat");
+	
+				Category places_category = db.Tags.CreateCategory (null, "Places");
+				db.Tags.CreateTag (places_category, "Milan");
+				db.Tags.CreateTag (places_category, "Boston");
+	
+				Category exotic_category = db.Tags.CreateCategory (places_category, "Exotic");
+				db.Tags.CreateTag (exotic_category, "Bengalore");
+				db.Tags.CreateTag (exotic_category, "Manila");
+				db.Tags.CreateTag (exotic_category, "Tokyo");
+	
+				selection_widget = new TagSelectionWidget (db.Tags);
+				selection_widget.SelectionChanged += new SelectionChangedHandler (OnSelectionChanged);
+	
+				Window window = new Window (WindowType.Toplevel);
+				window.SetDefaultSize (400, 200);
+				ScrolledWindow scrolled = new ScrolledWindow (null, null);
+				scrolled.SetPolicy (PolicyType.Automatic, PolicyType.Automatic);
+				scrolled.Add (selection_widget);
+				window.Add (scrolled);
+	
+				window.ShowAll ();
+			}
+	
+			static private void Main (string [] args)
+			{
+				Program program = new Program ("TagSelectionWidgetTest", "0.0", Modules.UI, args);
+	
+				Test test = new Test ();
+	
+				program.Run ();
+			}
+		}
+	
+	#endif
 	}
-
-#endif
 }
diff --git a/src/Term.cs b/src/Term.cs
index 903ec9f..7ecc1fb 100644
--- a/src/Term.cs
+++ b/src/Term.cs
@@ -12,6 +12,10 @@ using Mono.Unix;
 using Gtk;
 using Gdk;
 
+using FSpot.GuiUtils;
+
+
+
 namespace FSpot {
 	public abstract class Term {
 		private ArrayList sub_terms = new ArrayList ();
@@ -758,25 +762,25 @@ namespace FSpot {
 		void HandleDragDataGet (object sender, DragDataGetArgs args)
 		{
 			args.RetVal = true;
-			switch (args.Info) {
-			case (uint) MainWindow.TargetType.TagList:
-			case (uint) MainWindow.TargetType.TagQueryItem:
+			
+			if (args.Info == DragDrop.TagListEntry.Info || args.Info == DragDrop.TagQueryEntry.Info) {
+				
+				// FIXME: do really write data
 				Byte [] data = Encoding.UTF8.GetBytes (String.Empty);
 				Atom [] targets = args.Context.Targets;
 
 				args.SelectionData.Set (targets[0], 8, data, data.Length);
 
 				return;
-			default:
-				// Drop cancelled
-				args.RetVal = false;
+			}
+			
+			// Drop cancelled
+			args.RetVal = false;
 
-				foreach (Widget w in hiddenWidgets)
+			foreach (Widget w in hiddenWidgets)
 				w.Visible = true;
 
-				focusedLiterals = null;
-				break;
-			}
+			focusedLiterals = null;
 		}
 
 		void HandleDragBegin (object sender, DragBeginArgs args)
@@ -804,16 +808,20 @@ namespace FSpot {
 			args.RetVal = true;
 		}
 
-		private void HandleDragDataReceived (object o, EventArgs args)
+		private void HandleDragDataReceived (object o, DragDataReceivedArgs args)
 		{
-			// If focusedLiterals is not null, this is a drag of a tag that's already been placed
-			if (focusedLiterals.Count == 0)
-			{
-				if (TermAdded != null)
-					TermAdded (Parent, this);
+			args.RetVal = true;
+			
+			if (args.Info == GuiUtils.DragDrop.TagListEntry.Info) {
+
+				if (TagsAdded != null)
+					TagsAdded (FSpot.GuiUtils.DragDrop.GetTagsData (args.SelectionData), Parent, this);
+				
+				return;
 			}
-			else
-			{
+			
+			if (args.Info == GuiUtils.DragDrop.TagQueryEntry.Info) {
+
 				if (! focusedLiterals.Contains(this))
 					if (LiteralsMoved != null)
 						LiteralsMoved (focusedLiterals, Parent, this);
@@ -875,14 +883,14 @@ namespace FSpot {
 
 		private const int overlay_size = (int) (.40 * ICON_SIZE);
 
-		private static TargetEntry [] tag_target_table = new TargetEntry [] {
-					new TargetEntry ("application/x-fspot-tag-query-item", 0, (uint) MainWindow.TargetType.TagQueryItem),
-				};
+		private static TargetEntry [] tag_target_table =
+			new TargetEntry [] {FSpot.GuiUtils.DragDrop.TagQueryEntry};
 
-		private static TargetEntry [] tag_dest_target_table = new TargetEntry [] {
-					new TargetEntry ("application/x-fspot-tags", 0, (uint) MainWindow.TargetType.TagList),
-					new TargetEntry ("application/x-fspot-tag-query-item", 0, (uint) MainWindow.TargetType.TagQueryItem),
-				};
+		private static TargetEntry [] tag_dest_target_table =
+			new TargetEntry [] {
+				FSpot.GuiUtils.DragDrop.TagListEntry,
+				FSpot.GuiUtils.DragDrop.TagQueryEntry
+			};
 
 		private static ArrayList focusedLiterals = new ArrayList();
 		private static ArrayList hiddenWidgets = new ArrayList();
@@ -909,8 +917,8 @@ namespace FSpot {
 		public delegate void RemovedHandler (Literal group);
 		public event RemovedHandler Removed;
 
-		public delegate void TermAddedHandler (Term parent, Literal after);
-		public event TermAddedHandler TermAdded;
+		public delegate void TagsAddedHandler (Tag[] tags, Term parent, Literal after);
+		public event TagsAddedHandler TagsAdded;
 
 		public delegate void AttachTagHandler (Tag tag, Term parent, Literal after);
 		public event AttachTagHandler AttachTag;
diff --git a/src/Util.cs b/src/Util.cs
index 031a37b..d64cd6e 100644
--- a/src/Util.cs
+++ b/src/Util.cs
@@ -14,169 +14,207 @@ using System.IO;
 using System.Text;
 using System;
 
-using FSpot.Utils;
 
-public class UriList : ArrayList {
-	public UriList (FSpot.IBrowsableItem [] photos) {
-		foreach (FSpot.IBrowsableItem p in photos) {
-			Uri uri;
-			try {
-				uri = p.DefaultVersionUri;
-			} catch {
-				continue;
+namespace FSpot.Utils
+{
+
+	public class UriList : ArrayList {
+		public UriList (FSpot.IBrowsableItem [] photos) {
+			foreach (FSpot.IBrowsableItem p in photos) {
+				Uri uri;
+				try {
+					uri = p.DefaultVersionUri;
+				} catch {
+					continue;
+				}
+				Add (uri);
 			}
-			Add (uri);
 		}
-	}
+		
+		public UriList () : base ()
+		{
+		}
+		
+		private void LoadFromString (string data) {
+			//string [] items = System.Text.RegularExpressions.Regex.Split ("\n", data);
+			string [] items = data.Split ('\n');
+			
+			foreach (String i in items) {
+				if (!i.StartsWith ("#")) {
+					Uri uri;
+					String s = i;
 	
-	public UriList () : base ()
-	{
-	}
+					if (i.EndsWith ("\r")) {
+						s = i.Substring (0, i.Length - 1);
+						Console.WriteLine ("uri = {0}", s);
+					}
+					
+					try {
+						uri = new Uri (s);
+					} catch {
+#if true //Workaround to bgo 362016 in gnome-screenshot. Remove this hack when gnome 2.6.18 is widely distributed.
+						if (System.Text.RegularExpressions.Regex.IsMatch (s, "^file:/[^/]")) {
+							try {
+								s = "file:///" + s.Substring(6);
+								uri = new Uri (s);
+								Console.WriteLine ("Converted uri from file:/ to >>{0}<<", s);
+							} catch {
+								continue;
+							}
+						} else
+							continue;
+#else					
+						continue;
+#endif
+					}
+					Add (uri);
+				}
+			}
+		}
 	
-	private void LoadFromString (string data) {
-		//string [] items = System.Text.RegularExpressions.Regex.Split ("\n", data);
-		string [] items = data.Split ('\n');
+	/*	public UriList (string [] uris)
+		{	
+			// FIXME this is so lame do real chacking at some point
+			foreach (string str in uris) {
+				AddUnknown (str);
+			}
+		}
+	*/
+		public void AddUnknown (string unknown)
+		{
+			Uri uri;
+			
+			if (File.Exists (unknown) || Directory.Exists (unknown))
+				uri = UriUtils.PathToFileUri (unknown);
+			else 
+				uri = new Uri (unknown);
+			
+			Add (uri);
+		}
+	
+		public UriList (string data) 
+		{
+			LoadFromString (data);
+		}
 		
-		foreach (String i in items) {
-			if (!i.StartsWith ("#")) {
-				Uri uri;
-				String s = i;
-
-				if (i.EndsWith ("\r")) {
-					s = i.Substring (0, i.Length - 1);
-					Console.WriteLine ("uri = {0}", s);
-				}
-				
-				try {
-					uri = new Uri (s);
-				} catch {
+		public UriList (string [] uris)
+		{
+			foreach (String i in uris) {
+				if (!i.StartsWith ("#")) {
+					Uri uri;
+					String s = i;
+	
+					if (i.EndsWith ("\r")) {
+						s = i.Substring (0, i.Length - 1);
+						Console.WriteLine ("uri = {0}", s);
+					}
+					
+					try {
+						uri = new Uri (s);
+					} catch {
 #if true //Workaround to bgo 362016 in gnome-screenshot. Remove this hack when gnome 2.6.18 is widely distributed.
-					if (System.Text.RegularExpressions.Regex.IsMatch (s, "^file:/[^/]")) {
-						try {
-							s = "file:///" + s.Substring(6);
-							uri = new Uri (s);
-							Console.WriteLine ("Converted uri from file:/ to >>{0}<<", s);
-						} catch {
+						if (System.Text.RegularExpressions.Regex.IsMatch (s, "^file:/[^/]")) {
+							try {
+								s = "file:///" + s.Substring(6);
+								uri = new Uri (s);
+								Console.WriteLine ("Converted uri from file:/ to >>{0}<<", s);
+							} catch {
+								continue;
+							}
+						} else
 							continue;
-						}
-					} else
-						continue;
 #else					
-					continue;
+						continue;
 #endif
+					}
+					Add (uri);
 				}
-				Add (uri);
 			}
 		}
-	}
-
-	public UriList (string [] uris)
-	{	
-		// FIXME this is so lame do real chacking at some point
-		foreach (string str in uris) {
-			AddUnknown (str);
-		}
-	}
-
-	public void AddUnknown (string unknown)
-	{
-		Uri uri;
 		
-		if (File.Exists (unknown) || Directory.Exists (unknown))
-			uri = UriUtils.PathToFileUri (unknown);
-		else 
-			uri = new Uri (unknown);
+		public UriList (Gtk.SelectionData selection) 
+		{
+			// FIXME this should check the atom etc.
+			LoadFromString (System.Text.Encoding.UTF8.GetString (selection.Data));
+		}
+	
+		public new Uri [] ToArray ()
+		{
+			return ToArray (typeof (Uri)) as Uri [];
+		}
 		
-		Add (uri);
-	}
-
-	public UriList (string data) 
-	{
-		LoadFromString (data);
-	}
+		/*public void Add (string path)
+		{
+			AddUnknown (path);
+		}*/
 	
-	public UriList (Gtk.SelectionData selection) 
-	{
-		// FIXME this should check the atom etc.
-		LoadFromString (System.Text.Encoding.UTF8.GetString (selection.Data));
-	}
-
-	public new Uri [] ToArray ()
-	{
-		return ToArray (typeof (Uri)) as Uri [];
-	}
+		public void Add (Uri uri)
+		{
+			Add ((object)uri);
+		}
 	
-	public void Add (string path)
-	{
-		AddUnknown (path);
-	}
-
-	public void Add (Uri uri)
-	{
-		Add ((object)uri);
-	}
-
-	public void Add (FSpot.IBrowsableItem item)
-	{
-		Add (item.DefaultVersionUri);
-	}
-
-	public override string ToString () {
-		StringBuilder list = new StringBuilder ();
-
-		foreach (Uri uri in this) {
-			if (uri == null)
-				break;
-
-			list.Append (uri.ToString () + Environment.NewLine);
+		public void Add (FSpot.IBrowsableItem item)
+		{
+			Add (item.DefaultVersionUri);
 		}
-
-		return list.ToString ();
-	}
-
-	public string [] ToLocalPaths () {
-		int count = 0;
-		foreach (Uri uri in this) {
-			if (uri.IsFile)
-				count++;
+	
+		public override string ToString () {
+			StringBuilder list = new StringBuilder ();
+	
+			foreach (Uri uri in this) {
+				if (uri == null)
+					break;
+	
+				list.Append (uri.ToString () + Environment.NewLine);
+			}
+	
+			return list.ToString ();
 		}
-		
-		String [] paths = new String [count];
-		count = 0;
-		foreach (Uri uri in this) {
-			if (uri.IsFile)
-				paths[count++] = uri.LocalPath;
+	
+		public string [] ToLocalPaths () {
+			int count = 0;
+			foreach (Uri uri in this) {
+				if (uri.IsFile)
+					count++;
+			}
+			
+			String [] paths = new String [count];
+			count = 0;
+			foreach (Uri uri in this) {
+				if (uri.IsFile)
+					paths[count++] = uri.LocalPath;
+			}
+			return paths;
 		}
-		return paths;
 	}
-}
-
-
-public class SizeUtil {
-	[Obsolete ("Use GLib.Format.SizeForDisplay (gtk-sharp > 2.14)")]
-	public static string ToHumanReadable (long size)
-	{
-		string tmp_str = String.Empty;
-		float tmp_size = size;
-		int k = 0;
-		string[] size_abr = {"bytes", "kB", "MB", "GB", "TB" };
-		
-		while (tmp_size > 700) { //it's easier to read 0.9MB than 932kB
-			tmp_size = tmp_size / 1024;
-				k++;
+	
+	
+	public class SizeUtil {
+		[Obsolete ("Use GLib.Format.SizeForDisplay (gtk-sharp > 2.14)")]
+		public static string ToHumanReadable (long size)
+		{
+			string tmp_str = String.Empty;
+			float tmp_size = size;
+			int k = 0;
+			string[] size_abr = {"bytes", "kB", "MB", "GB", "TB" };
+			
+			while (tmp_size > 700) { //it's easier to read 0.9MB than 932kB
+				tmp_size = tmp_size / 1024;
+					k++;
+			}
+			
+			if (tmp_size < 7)
+				tmp_str = tmp_size.ToString ("0.##");
+			else if (tmp_size < 70)
+				tmp_str = tmp_size.ToString ("##.#");
+			else
+				tmp_str = tmp_size.ToString ("#,###");
+			
+			if (k < size_abr.Length)
+				return tmp_str + " " + size_abr[k];
+			else
+					return size.ToString();
 		}
-		
-		if (tmp_size < 7)
-			tmp_str = tmp_size.ToString ("0.##");
-		else if (tmp_size < 70)
-			tmp_str = tmp_size.ToString ("##.#");
-		else
-			tmp_str = tmp_size.ToString ("#,###");
-		
-		if (k < size_abr.Length)
-			return tmp_str + " " + size_abr[k];
-		else
-				return size.ToString();
 	}
 }
 



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