[f-spot] minor MainWindow cleanups



commit ec04b69264563d9b221b2b2fc28f7b1a3a08abd3
Author: Stephane Delcroix <stephane delcroix org>
Date:   Thu Oct 15 15:19:12 2009 +0200

    minor MainWindow cleanups

 src/MainWindow.cs | 5658 ++++++++++++++++++++++++++---------------------------
 1 files changed, 2822 insertions(+), 2836 deletions(-)
---
diff --git a/src/MainWindow.cs b/src/MainWindow.cs
index 73b9293..528106c 100644
--- a/src/MainWindow.cs
+++ b/src/MainWindow.cs
@@ -1,18 +1,21 @@
-using Gdk;
-using Gtk;
+/*
+ * FSpot.MainWindow.cs
+ *
+ * Copyright (c) 2003-2009 Novell, Inc.
+ *
+ * This is open source software. See COPYING for details.
+ */
 
-using Glade;
-using Mono.Addins;
-using Mono.Unix;
 using System;
 using System.Text;
-
 using System.Collections;
 using System.Collections.Generic;
-using System.Runtime.InteropServices;
-using System.Text.RegularExpressions;
-using System.Web;
-using System.Web.Mail;
+
+using Gdk;
+using Gtk;
+
+using Mono.Addins;
+using Mono.Unix;
 
 using Banshee.Kernel;
 
@@ -26,3062 +29,3045 @@ using FSpot.Platform;
 
 using LibGPhoto2;
 
-public class MainWindow {
-
-    public static MainWindow Toplevel;
-
-	Db db;
-
-	public Sidebar Sidebar;
-
-	TagSelectionWidget tag_selection_widget;
-	[GtkBeans.Builder.Object] Gtk.Window main_window;
-
-	[GtkBeans.Builder.Object] Gtk.HPaned main_hpaned;
-	[GtkBeans.Builder.Object] Gtk.VBox left_vbox;
-	[GtkBeans.Builder.Object] Gtk.VBox group_vbox;
-	[GtkBeans.Builder.Object] Gtk.VBox view_vbox;
-
-	[GtkBeans.Builder.Object] Gtk.VBox toolbar_vbox;
-
-	[GtkBeans.Builder.Object] ScrolledWindow icon_view_scrolled;
-	[GtkBeans.Builder.Object] Box photo_box;
-	[GtkBeans.Builder.Object] Notebook view_notebook;
+namespace FSpot
+{
+	public class MainWindow
+	{
+		public static MainWindow Toplevel;
+		public Sidebar Sidebar { get; private set; }
 	
-	ScrolledWindow tag_selection_scrolled;
-
-	[GtkBeans.Builder.Object] Label status_label;
-
-	[GtkBeans.Builder.Object] Gtk.UIManager uimanager;
-	// File
-	[GtkBeans.Builder.Object] Gtk.Action create_version_menu_item;
-	[GtkBeans.Builder.Object] Gtk.Action delete_version_menu_item;
-	[GtkBeans.Builder.Object] Gtk.Action rename_version_menu_item;
-	
-	[GtkBeans.Builder.Object] Gtk.Action tools;
-	[GtkBeans.Builder.Object] Gtk.Action export;
-	[GtkBeans.Builder.Object] Gtk.Action pagesetup_menu_item;
-	[GtkBeans.Builder.Object] Gtk.Action print;
-	[GtkBeans.Builder.Object] Gtk.Action send_mail;
-
-	// Edit
-	[GtkBeans.Builder.Object] Gtk.Action copy_location;
-	[GtkBeans.Builder.Object] Gtk.Action select_none;
-	[GtkBeans.Builder.Object] Gtk.Action rotate_left;
-	[GtkBeans.Builder.Object] Gtk.Action rotate_right;
-
-	[GtkBeans.Builder.Object] Gtk.Action sharpen;
-	[GtkBeans.Builder.Object] Gtk.Action adjust_time;
-
-	[GtkBeans.Builder.Object] Gtk.Action update_thumbnail;
-	[GtkBeans.Builder.Object] Gtk.Action delete_from_drive;
-	[GtkBeans.Builder.Object] Gtk.Action remove_from_catalog;
-	[GtkBeans.Builder.Object] Gtk.Action set_as_background;
-
-	[GtkBeans.Builder.Object] Gtk.Action attach_tag;
-	[GtkBeans.Builder.Object] Gtk.Action remove_tag;
-
-	// View
-	[GtkBeans.Builder.Object] Gtk.ToggleAction display_toolbar;
-	[GtkBeans.Builder.Object] Gtk.ToggleAction display_sidebar;
-	[GtkBeans.Builder.Object] Gtk.ToggleAction display_timeline;
-	[GtkBeans.Builder.Object] Gtk.ToggleAction display_filmstrip;
-	[GtkBeans.Builder.Object] Gtk.ToggleAction display_dates_menu_item;
-	[GtkBeans.Builder.Object] Gtk.ToggleAction display_tags_menu_item;
-	[GtkBeans.Builder.Object] Gtk.ToggleAction display_ratings_menu_item;
-
-	[GtkBeans.Builder.Object] Gtk.Action zoom_in;
-	[GtkBeans.Builder.Object] Gtk.Action zoom_out;
-	[GtkBeans.Builder.Object] Gtk.ToggleAction loupe_menu_item;
-
-	[GtkBeans.Builder.Object] Gtk.RadioAction tag_icon_hidden;
-	[GtkBeans.Builder.Object] Gtk.RadioAction tag_icon_small;
-	[GtkBeans.Builder.Object] Gtk.RadioAction tag_icon_medium;
-	[GtkBeans.Builder.Object] Gtk.RadioAction tag_icon_large;
-
-	[GtkBeans.Builder.Object] Gtk.ToggleAction reverse_order;
-	public Gtk.ToggleAction ReverseOrderAction {
-		get { return reverse_order; }
-	}
-
-	// Find
-	[GtkBeans.Builder.Object] Gtk.Action clear_date_range;
-	[GtkBeans.Builder.Object] Gtk.Action clear_rating_filter;
-
-	[GtkBeans.Builder.Object] Gtk.ToggleAction find_untagged;
+		TagSelectionWidget tag_selection_widget;
+		[GtkBeans.Builder.Object] Gtk.Window main_window;
+		public Gtk.Window Window { 
+			get { return main_window; }
+		}
 	
-	[GtkBeans.Builder.Object] Gtk.Action clear_roll_filter;	
+		[GtkBeans.Builder.Object] Gtk.HPaned main_hpaned;
+		[GtkBeans.Builder.Object] Gtk.VBox left_vbox;
+		[GtkBeans.Builder.Object] Gtk.VBox group_vbox;
+		[GtkBeans.Builder.Object] Gtk.VBox view_vbox;
 	
-	// Tags
-	[GtkBeans.Builder.Object] Gtk.Action edit_selected_tag;
-	[GtkBeans.Builder.Object] Gtk.Action delete_selected_tag;
-
-	[GtkBeans.Builder.Object] Gtk.Action attach_tag_to_selection;
-	[GtkBeans.Builder.Object] Gtk.Action remove_tag_from_selection;
+		[GtkBeans.Builder.Object] Gtk.VBox toolbar_vbox;
 	
-	// Other Widgets
-	[GtkBeans.Builder.Object] Scale zoom_scale;
-
-	[GtkBeans.Builder.Object] VBox info_vbox;
-
-	[GtkBeans.Builder.Object] Gtk.HBox tagbar;
-	[GtkBeans.Builder.Object] Gtk.VBox tag_entry_container;
-	[GtkBeans.Builder.Object] Gtk.VBox sidebar_vbox;
-	TagEntry tag_entry;
-
-	Gtk.Toolbar toolbar;
-
-	FindBar find_bar;
-
-	PhotoVersionMenu versions_submenu;
-
-	Gtk.ToggleToolButton browse_button;
-	Gtk.ToggleToolButton edit_button;
-
-	InfoBox info_box;
-	QueryView icon_view;
-	PhotoView photo_view;
-	FSpot.FullScreenView fsview;
-	FSpot.PhotoQuery query;
-	FSpot.GroupSelector group_selector;
-	FSpot.QueryWidget query_widget;
-	MainSelection selection;
-	
-	ToolButton rl_button;
-	ToolButton rr_button;
-
-	Label count_label;
-
-	Gtk.ToolButton display_next_button;
-	Gtk.ToolButton display_previous_button;
+		[GtkBeans.Builder.Object] ScrolledWindow icon_view_scrolled;
+		[GtkBeans.Builder.Object] Box photo_box;
+		[GtkBeans.Builder.Object] Notebook view_notebook;
+		
+		ScrolledWindow tag_selection_scrolled;
 	
-	ModeType view_mode;
-	bool write_metadata = false;
-
-	Gdk.Cursor watch = new Gdk.Cursor (Gdk.CursorType.Watch);
-
-	// Tag Icon Sizes
-	public int TagsIconSize {
-		get { return (int) Tag.TagIconSize; }
-		set { Tag.TagIconSize = (Tag.IconSize) value; }
-	}
-
-	public PhotoView PhotoView {
-		get { return photo_view; }
-	}
-
-	private static TargetEntry [] icon_source_target_table = 
-		new TargetEntry [] {
-			DragDropTargets.PhotoListEntry,
-			DragDropTargets.TagQueryEntry,
-			DragDropTargets.UriListEntry,
-			DragDropTargets.RootWindowEntry
-	};
-	
-	private static TargetEntry [] icon_dest_target_table = 
-		new TargetEntry [] {
-#if ENABLE_REPARENTING
-			DragDropTargets.PhotoListEntry,
-#endif
-			DragDropTargets.TagListEntry,
-			DragDropTargets.UriListEntry
-	};
-	
-	private static TargetEntry [] tag_target_table = 
-		new TargetEntry [] {
-			DragDropTargets.TagListEntry
-	};
-	
-	private static TargetEntry [] tag_dest_target_table = 
-		new TargetEntry [] {
-			DragDropTargets.PhotoListEntry,
-			DragDropTargets.UriListEntry,
-			DragDropTargets.TagListEntry
-	};
-
-	const int PHOTO_IDX_NONE = -1;
-
-	private static Gtk.Tooltips toolTips;
-	public static Gtk.Tooltips ToolTips {
-		get {
-			if (toolTips == null)
-				toolTips = new Gtk.Tooltips ();
-			return toolTips;
+		[GtkBeans.Builder.Object] Label status_label;
+	
+		[GtkBeans.Builder.Object] Gtk.UIManager uimanager;
+		// File
+		[GtkBeans.Builder.Object] Gtk.Action create_version_menu_item;
+		[GtkBeans.Builder.Object] Gtk.Action delete_version_menu_item;
+		[GtkBeans.Builder.Object] Gtk.Action rename_version_menu_item;
+		
+		[GtkBeans.Builder.Object] Gtk.Action tools;
+		[GtkBeans.Builder.Object] Gtk.Action export;
+		[GtkBeans.Builder.Object] Gtk.Action pagesetup_menu_item;
+		[GtkBeans.Builder.Object] Gtk.Action print;
+		[GtkBeans.Builder.Object] Gtk.Action send_mail;
+	
+		// Edit
+		[GtkBeans.Builder.Object] Gtk.Action copy_location;
+		[GtkBeans.Builder.Object] Gtk.Action select_none;
+		[GtkBeans.Builder.Object] Gtk.Action rotate_left;
+		[GtkBeans.Builder.Object] Gtk.Action rotate_right;
+	
+		[GtkBeans.Builder.Object] Gtk.Action sharpen;
+		[GtkBeans.Builder.Object] Gtk.Action adjust_time;
+	
+		[GtkBeans.Builder.Object] Gtk.Action update_thumbnail;
+		[GtkBeans.Builder.Object] Gtk.Action delete_from_drive;
+		[GtkBeans.Builder.Object] Gtk.Action remove_from_catalog;
+		[GtkBeans.Builder.Object] Gtk.Action set_as_background;
+	
+		[GtkBeans.Builder.Object] Gtk.Action attach_tag;
+		[GtkBeans.Builder.Object] Gtk.Action remove_tag;
+	
+		// View
+		[GtkBeans.Builder.Object] Gtk.ToggleAction display_toolbar;
+		[GtkBeans.Builder.Object] Gtk.ToggleAction display_sidebar;
+		[GtkBeans.Builder.Object] Gtk.ToggleAction display_timeline;
+		[GtkBeans.Builder.Object] Gtk.ToggleAction display_filmstrip;
+		[GtkBeans.Builder.Object] Gtk.ToggleAction display_dates_menu_item;
+		[GtkBeans.Builder.Object] Gtk.ToggleAction display_tags_menu_item;
+		[GtkBeans.Builder.Object] Gtk.ToggleAction display_ratings_menu_item;
+	
+		[GtkBeans.Builder.Object] Gtk.Action zoom_in;
+		[GtkBeans.Builder.Object] Gtk.Action zoom_out;
+		[GtkBeans.Builder.Object] Gtk.ToggleAction loupe_menu_item;
+	
+		[GtkBeans.Builder.Object] Gtk.RadioAction tag_icon_hidden;
+		[GtkBeans.Builder.Object] Gtk.RadioAction tag_icon_small;
+		[GtkBeans.Builder.Object] Gtk.RadioAction tag_icon_medium;
+		[GtkBeans.Builder.Object] Gtk.RadioAction tag_icon_large;
+	
+		[GtkBeans.Builder.Object] Gtk.ToggleAction reverse_order;
+		public Gtk.ToggleAction ReverseOrderAction {
+			get { return reverse_order; }
 		}
-	}
-
-	//
-	// Public Properties
-	//
-
-	public Db Database {
-		get { return db; }
-	}
-
-	public Gtk.Window Window {
-		get { return main_window; }
-	}
 	
-	public ModeType ViewMode {
-		get { return view_mode; }
-	}
-
-	public MainSelection Selection {
-		get { return selection; }
-	}
-
-	public MenuItem FindByTag {
-		get { return uimanager.GetWidget ("/ui/menubar1/find/find_by_tag") as MenuItem; }
-	}
-
-	public InfoBox InfoBox {
-		get { return info_box; }
-	}
-
-	//
-	// Constructor
-	//
-	public MainWindow (Db db)
-	{
-		this.db = db;
-
-		if (Toplevel == null)
-			Toplevel = this;
-
-		GtkBeans.Builder builder = new GtkBeans.Builder ("main_window.ui");
-		builder.Autoconnect (this);
-
-		LoadPreference (Preferences.MAIN_WINDOW_WIDTH);
-		LoadPreference (Preferences.MAIN_WINDOW_X);
-		LoadPreference (Preferences.MAIN_WINDOW_MAXIMIZED);
-		main_window.ShowAll ();
-
-		LoadPreference (Preferences.SIDEBAR_POSITION);
-		LoadPreference (Preferences.METADATA_EMBED_IN_IMAGE);
-
-		pagesetup_menu_item.Activated += HandlePageSetupActivated;
-
-		toolbar = new Gtk.Toolbar ();
-		toolbar_vbox.PackStart (toolbar);
-
-		ToolButton import_button = GtkUtil.ToolButtonFromTheme ("gtk-add", Catalog.GetString ("Import"), true);
-		import_button.Clicked += HandleImportCommand;
-		import_button.SetTooltip (ToolTips, Catalog.GetString ("Import new images"), null);
-		toolbar.Insert (import_button, -1);
+		// Find
+		[GtkBeans.Builder.Object] Gtk.Action clear_date_range;
+		[GtkBeans.Builder.Object] Gtk.Action clear_rating_filter;
 	
-		toolbar.Insert (new SeparatorToolItem (), -1);
-
-		rl_button = GtkUtil.ToolButtonFromTheme ("object-rotate-left", Catalog.GetString ("Rotate Left"), false);
-		rl_button.Clicked += HandleRotate270Command;
-		toolbar.Insert (rl_button, -1);
-
-		rr_button = GtkUtil.ToolButtonFromTheme ("object-rotate-right", Catalog.GetString ("Rotate Right"), false);
-		rr_button.Clicked += HandleRotate90Command;
-		toolbar.Insert (rr_button, -1);
-
-		toolbar.Insert (new SeparatorToolItem (), -1);
-
-		browse_button = new ToggleToolButton ();
-		browse_button.Label = Catalog.GetString ("Browse");
-		browse_button.IconName = "mode-browse";
-		browse_button.IsImportant = true;
-		browse_button.Toggled += HandleToggleViewBrowse;
-		browse_button.SetTooltip (ToolTips, Catalog.GetString ("Browse many photos simultaneously"), null);
-		toolbar.Insert (browse_button, -1);
-
-		edit_button = new ToggleToolButton ();
-		edit_button.Label = Catalog.GetString ("Edit Image");
-		edit_button.IconName = "mode-image-edit";
-		edit_button.IsImportant = true;
-		edit_button.Toggled += HandleToggleViewPhoto;
-		edit_button.SetTooltip (ToolTips, Catalog.GetString ("View and edit a photo"), null);
-		toolbar.Insert (edit_button, -1);
-
-		toolbar.Insert (new SeparatorToolItem (), -1);
-
-		ToolButton fs_button = GtkUtil.ToolButtonFromTheme ("view-fullscreen", Catalog.GetString ("Fullscreen"), false);
-		fs_button.Clicked += HandleViewFullscreen;
-		fs_button.SetTooltip (ToolTips, Catalog.GetString ("View photos fullscreen"), null);
-		toolbar.Insert (fs_button, -1);
-
-		ToolButton ss_button = GtkUtil.ToolButtonFromTheme ("media-playback-start", Catalog.GetString ("Slideshow"), false);
-		ss_button.Clicked += HandleViewSlideShow;
-		ss_button.SetTooltip (ToolTips, Catalog.GetString ("View photos in a slideshow"), null);
-		toolbar.Insert (ss_button, -1);
-
-		SeparatorToolItem white_space = new SeparatorToolItem ();
-		white_space.Draw = false;
-		white_space.Expand = true;
-		toolbar.Insert (white_space, -1);
-
-		ToolItem label_item = new ToolItem ();
-		count_label = new Label (String.Empty);
-		label_item.Child = count_label;
-		toolbar.Insert (label_item, -1);
-
-		display_previous_button = new ToolButton (Stock.GoBack);
-		toolbar.Insert (display_previous_button, -1);
-		display_previous_button.SetTooltip (ToolTips, Catalog.GetString ("Previous photo"), String.Empty);
-		display_previous_button.Clicked += new EventHandler (HandleDisplayPreviousButtonClicked);
-
-		display_next_button = new ToolButton (Stock.GoForward);
-		toolbar.Insert (display_next_button, -1);
-		display_next_button.SetTooltip (ToolTips, Catalog.GetString ("Next photo"), String.Empty);
-		display_next_button.Clicked += new EventHandler (HandleDisplayNextButtonClicked);
-
-		Sidebar = new Sidebar ();
-		ViewModeChanged += Sidebar.HandleMainWindowViewModeChanged;
-		sidebar_vbox.Add (Sidebar);
-
-		tag_selection_scrolled = new ScrolledWindow ();
-		tag_selection_scrolled.ShadowType = ShadowType.In;
+		[GtkBeans.Builder.Object] Gtk.ToggleAction find_untagged;
 		
-		tag_selection_widget = new TagSelectionWidget (db.Tags);
-		tag_selection_scrolled.Add (tag_selection_widget);
-
-		Sidebar.AppendPage (tag_selection_scrolled, Catalog.GetString ("Tags"), "tag");
-
-		AddinManager.AddExtensionNodeHandler ("/FSpot/Sidebar", OnSidebarExtensionChanged);
-
-		Sidebar.Context = ViewContext.Library;
- 		
-		Sidebar.CloseRequested += HideSidebar;
-		Sidebar.Show ();
-
-		info_box = new InfoBox ();
-		ViewModeChanged += info_box.HandleMainWindowViewModeChanged;
-		info_box.VersionIdChanged += delegate (InfoBox box, uint version_id) { UpdateForVersionIdChange (version_id);};
-		sidebar_vbox.PackEnd (info_box, false, false, 0);
-
-		info_box.Context = ViewContext.Library;
+		[GtkBeans.Builder.Object] Gtk.Action clear_roll_filter;	
 		
-		tag_selection_widget.Selection.Changed += HandleTagSelectionChanged;
-		tag_selection_widget.KeyPressEvent += HandleTagSelectionKeyPress;
-		tag_selection_widget.ButtonPressEvent += HandleTagSelectionButtonPressEvent;
-		tag_selection_widget.PopupMenu += HandleTagSelectionPopupMenu;
-		tag_selection_widget.RowActivated += HandleTagSelectionRowActivated;
-		
-		LoadPreference (Preferences.TAG_ICON_SIZE);
+		// Tags
+		[GtkBeans.Builder.Object] Gtk.Action edit_selected_tag;
+		[GtkBeans.Builder.Object] Gtk.Action delete_selected_tag;
+	
+		[GtkBeans.Builder.Object] Gtk.Action attach_tag_to_selection;
+		[GtkBeans.Builder.Object] Gtk.Action remove_tag_from_selection;
 		
-		try {
-			query = new FSpot.PhotoQuery (db.Photos);
-		} catch (System.Exception e) {
-			//FIXME assume any exception here is due to a corrupt db and handle that.
-			new RepairDbDialog (e, db.Repair (), main_window);
-			query = new FSpot.PhotoQuery (db.Photos);
-		}
-
-		UpdateStatusLabel ();
-		query.Changed += HandleQueryChanged;
-
-		db.Photos.ItemsChanged += HandleDbItemsChanged;
-		db.Tags.ItemsChanged += HandleTagsChanged;
-		db.Tags.ItemsAdded += HandleTagsChanged;
-		db.Tags.ItemsRemoved += HandleTagsChanged;
-#if SHOW_CALENDAR
-		FSpot.SimpleCalendar cal = new FSpot.SimpleCalendar (query);
-		cal.DaySelected += HandleCalendarDaySelected;
-		left_vbox.PackStart (cal, false, true, 0);
-#endif
-
-		group_selector = new FSpot.GroupSelector ();
-		group_selector.Adaptor = new FSpot.TimeAdaptor (query, Preferences.Get<bool> (Preferences.GROUP_ADAPTOR_ORDER_ASC));
+		// Other Widgets
+		[GtkBeans.Builder.Object] Scale zoom_scale;
+	
+		[GtkBeans.Builder.Object] VBox info_vbox;
+	
+		[GtkBeans.Builder.Object] Gtk.HBox tagbar;
+		[GtkBeans.Builder.Object] Gtk.VBox tag_entry_container;
+		[GtkBeans.Builder.Object] Gtk.VBox sidebar_vbox;
+		TagEntry tag_entry;
+	
+		Gtk.Toolbar toolbar;
+	
+		FindBar find_bar;
+	
+		PhotoVersionMenu versions_submenu;
+	
+		Gtk.ToggleToolButton browse_button;
+		Gtk.ToggleToolButton edit_button;
+	
+		QueryView icon_view;
 
-		group_selector.ShowAll ();
-		
-		if (zoom_scale != null) {
-			zoom_scale.ValueChanged += HandleZoomScaleValueChanged;
+		PhotoView photo_view;
+		public PhotoView PhotoView {
+			get { return photo_view; }
 		}
-
-		view_vbox.PackStart (group_selector, false, false, 0);
-		view_vbox.ReorderChild (group_selector, 0);
-
-		find_bar = new FindBar (query, tag_selection_widget.Model);
-		view_vbox.PackStart (find_bar, false, false, 0);
-		view_vbox.ReorderChild (find_bar, 1);
-		main_window.KeyPressEvent += HandleKeyPressEvent;
-		
-		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);
-
-		icon_view = new QueryView (query);
-		icon_view.ZoomChanged += HandleZoomChanged;
-		LoadPreference (Preferences.ZOOM);
-		LoadPreference (Preferences.SHOW_TAGS);
-		LoadPreference (Preferences.SHOW_DATES);
-		LoadPreference (Preferences.SHOW_RATINGS);
-		icon_view_scrolled.Add (icon_view);
-		icon_view.DoubleClicked += HandleDoubleClicked;
-		icon_view.Vadjustment.ValueChanged += HandleIconViewScroll;
-		icon_view.GrabFocus ();
-
-		new FSpot.PreviewPopup (icon_view);
-
-		Gtk.Drag.SourceSet (icon_view, Gdk.ModifierType.Button1Mask | Gdk.ModifierType.Button3Mask,
-				    icon_source_target_table, DragAction.Copy | DragAction.Move);
-		
-		icon_view.DragBegin += HandleIconViewDragBegin;
-		icon_view.DragDataGet += HandleIconViewDragDataGet;
-
-		TagMenu tag_menu = new TagMenu (null, Database.Tags);
-		tag_menu.NewTagHandler += delegate { HandleCreateTagAndAttach (this, null); };
-		tag_menu.TagSelected += HandleAttachTagMenuSelected;
-		tag_menu.Populate();
-		(uimanager.GetWidget("/ui/menubar1/edit2/attach_tag") as MenuItem).Submenu = tag_menu;
-		
-		PhotoTagMenu pmenu = new PhotoTagMenu ();
-		pmenu.TagSelected += HandleRemoveTagMenuSelected;
-		(uimanager.GetWidget("/ui/menubar1/edit2/remove_tag") as MenuItem).Submenu = pmenu;
-		
-		Gtk.Drag.DestSet (icon_view, DestDefaults.All, icon_dest_target_table, 
-				  DragAction.Copy | DragAction.Move); 
-
-		//		icon_view.DragLeave += new DragLeaveHandler (HandleIconViewDragLeave);
-		icon_view.DragMotion += HandleIconViewDragMotion;
-		icon_view.DragDrop += HandleIconViewDragDrop;
-		icon_view.DragDataReceived += HandleIconViewDragDataReceived;
-		icon_view.KeyPressEvent += HandleIconViewKeyPressEvent;
-
-		photo_view = new PhotoView (query);
-		photo_box.Add (photo_view);
-
-		photo_view.DoubleClicked += HandleDoubleClicked;
-		photo_view.KeyPressEvent += HandlePhotoViewKeyPressEvent;
-		photo_view.UpdateStarted += HandlePhotoViewUpdateStarted;
-		photo_view.UpdateFinished += HandlePhotoViewUpdateFinished;
-
-		photo_view.View.ZoomChanged += HandleZoomChanged;
-
-		// Tag typing: focus the tag entry if the user starts typing a tag
-		icon_view.KeyPressEvent += HandlePossibleTagTyping;
-		photo_view.KeyPressEvent += HandlePossibleTagTyping;
-		tag_entry = new TagEntry (db.Tags);
-		tag_entry.KeyPressEvent += HandleTagEntryKeyPressEvent;
-		tag_entry.TagsAttached += HandleTagEntryTagsAttached;
-		tag_entry.TagsRemoved += HandleTagEntryRemoveTags;
-		tag_entry.Activated += HandleTagEntryActivate;
-		tag_entry_container.Add (tag_entry);
-
-		Gtk.Drag.DestSet (photo_view, DestDefaults.All, tag_target_table, 
-				  DragAction.Copy | DragAction.Move); 
-
-		photo_view.DragMotion += HandlePhotoViewDragMotion;
-		photo_view.DragDrop += HandlePhotoViewDragDrop;
-		photo_view.DragDataReceived += HandlePhotoViewDragDataReceived;
-
-		view_notebook.SwitchPage += HandleViewNotebookSwitchPage;
-		group_selector.Adaptor.GlassSet += HandleAdaptorGlassSet;
-		group_selector.Adaptor.Changed += HandleAdaptorChanged;
-		LoadPreference (Preferences.GROUP_ADAPTOR_ORDER_ASC);
-		LoadPreference (Preferences.FILMSTRIP_ORIENTATION);
-
-		this.selection = new MainSelection (this);
-		this.selection.Changed += HandleSelectionChanged;
-		this.selection.ItemsChanged += HandleSelectionItemsChanged;
-		this.selection.Changed += Sidebar.HandleSelectionChanged;
-		this.selection.ItemsChanged += Sidebar.HandleSelectionItemsChanged;
-
-		Mono.Addins.AddinManager.ExtensionChanged += PopulateExtendableMenus;
-		PopulateExtendableMenus (null, null);
-
-		UpdateMenus ();
-
-		main_window.ShowAll ();
-
-		tagbar.Hide ();
-		find_bar.Hide ();
-
-		UpdateFindByTagMenu ();
-
-		LoadPreference (Preferences.SHOW_TOOLBAR);
-		LoadPreference (Preferences.SHOW_SIDEBAR);
-		LoadPreference (Preferences.SHOW_TIMELINE);
-		LoadPreference (Preferences.SHOW_FILMSTRIP);
-
-		LoadPreference (Preferences.GNOME_MAILTO_ENABLED);
+	
+		FSpot.FullScreenView fsview;
+		FSpot.PhotoQuery query;
+		FSpot.GroupSelector group_selector;
+		FSpot.QueryWidget query_widget;
 		
-		Preferences.SettingChanged += OnPreferencesChanged;
-
-		main_window.DeleteEvent += HandleDeleteEvent;
+		ToolButton rl_button;
+		ToolButton rr_button;
+	
+		Label count_label;
+	
+		Gtk.ToolButton display_next_button;
+		Gtk.ToolButton display_previous_button;
 		
-		query_widget.HandleChanged (query);
-		query_widget.Close ();
-
-		// When the icon_view is loaded, set it's initial scroll position
-		icon_view.SizeAllocated += HandleIconViewReady;
-
-		export.Activated += HandleExportActivated;
-		UpdateToolbar ();
-
-		(uimanager.GetWidget("/ui/menubar1/file1/close1") as MenuItem).Hide ();
-
-		Banshee.Kernel.Scheduler.Resume ();
-	}
-
-	private void HandleDisplayNextButtonClicked (object sender, EventArgs args)
-	{
-		PhotoView.View.Item.MoveNext ();
-	}
-
-	private void HandleDisplayPreviousButtonClicked (object sender, EventArgs args)
-	{
-		PhotoView.View.Item.MovePrevious ();
-	}
-
-	private void OnSidebarExtensionChanged (object s, ExtensionNodeEventArgs args) {
-		// FIXME: No sidebar page removal yet!
-		if (args.Change == ExtensionChange.Add)
-			Sidebar.AppendPage ((args.ExtensionNode as SidebarPageNode).GetSidebarPage ());
-	}
-
-	private Photo CurrentPhoto {
-		get {
-			int active = ActiveIndex ();
-			if (active >= 0)
-				return query [active] as Photo;
-			else
-				return null;
+		bool write_metadata = false;
+	
+		Gdk.Cursor watch = new Gdk.Cursor (Gdk.CursorType.Watch);
+	
+		// Tag Icon Sizes
+		public int TagsIconSize {
+			get { return (int) Tag.TagIconSize; }
+			set { Tag.TagIconSize = (Tag.IconSize) value; }
 		}
-	}
-
-	// Index into the PhotoQuery.  If -1, no photo is selected or multiple photos are selected.
-	private int ActiveIndex () 
-	{
-		if (selection.Count == 1)
-			return SelectedIds() [0];
-		else
-			return PHOTO_IDX_NONE;
-	}
-
-	// Switching mode.
-	public enum ModeType {
-		IconView,
-		PhotoView
-	};
-
-	public event EventHandler ViewModeChanged;
-
-	public void SetViewMode (ModeType value)
-	{
-		if (view_mode == value)
-			return;
-
-		view_mode = value;
-		switch (view_mode) {
-		case ModeType.IconView:
-			if (view_notebook.CurrentPage != 0)
-				view_notebook.CurrentPage = 0;
-
-			display_timeline.Sensitive = true;
-			display_filmstrip.Sensitive = false;
-			group_selector.Visible = display_timeline.Active;
-
-			if (photo_view.View.Loupe != null)
-				loupe_menu_item.Active = false;
-			JumpTo (photo_view.Item.Index);
-			zoom_scale.Value = icon_view.Zoom;
-			break;
-		case ModeType.PhotoView:
-			if (view_notebook.CurrentPage != 1)
-				view_notebook.CurrentPage = 1;
-
-			display_timeline.Sensitive = false;
-			display_filmstrip.Sensitive = true;
-			group_selector.Visible = false;
-			
-			JumpTo (icon_view.FocusCell);
-			zoom_scale.Value = photo_view.NormalizedZoom;
-
-			photo_view.View.GrabFocus();
-			break;
+	
+		private static TargetEntry [] icon_source_target_table = 
+			new TargetEntry [] {
+				DragDropTargets.PhotoListEntry,
+				DragDropTargets.TagQueryEntry,
+				DragDropTargets.UriListEntry,
+				DragDropTargets.RootWindowEntry
+		};
+		
+		private static TargetEntry [] icon_dest_target_table = 
+			new TargetEntry [] {
+	#if ENABLE_REPARENTING
+				DragDropTargets.PhotoListEntry,
+	#endif
+				DragDropTargets.TagListEntry,
+				DragDropTargets.UriListEntry
+		};
+		
+		private static TargetEntry [] tag_target_table = 
+			new TargetEntry [] {
+				DragDropTargets.TagListEntry
+		};
+		
+		private static TargetEntry [] tag_dest_target_table = 
+			new TargetEntry [] {
+				DragDropTargets.PhotoListEntry,
+				DragDropTargets.UriListEntry,
+				DragDropTargets.TagListEntry
+		};
+	
+		const int PHOTO_IDX_NONE = -1;
+	
+		private static Gtk.Tooltips toolTips;
+		public static Gtk.Tooltips ToolTips {
+			get {
+				if (toolTips == null)
+					toolTips = new Gtk.Tooltips ();
+				return toolTips;
+			}
 		}
-		Selection.MarkChanged ();
-		UpdateToolbar ();
-		if (ViewModeChanged != null) 
-			ViewModeChanged (this, null);
-	}
 	
-	void UpdateToolbar ()
-	{
-		if (browse_button != null) {
-			bool state = view_mode == ModeType.IconView;
-			
-			if (browse_button.Active != state)
-				browse_button.Active = state;
+		public Db Database { get; private set; }
+		public ModeType ViewMode { get; private set; }
+		public MainSelection Selection { get; private set; }
+		public InfoBox InfoBox { get; private set; }
+	
+		public MenuItem FindByTag {
+			get { return uimanager.GetWidget ("/ui/menubar1/find/find_by_tag") as MenuItem; }
 		}
-
-		if (edit_button != null) {
-			bool state = view_mode == ModeType.PhotoView;
+	
+	
+		//
+		// Constructor
+		//
+		public MainWindow (Db db)
+		{
+			Database = db;
+	
+			if (Toplevel == null)
+				Toplevel = this;
+	
+			GtkBeans.Builder builder = new GtkBeans.Builder ("main_window.ui");
+			builder.Autoconnect (this);
+	
+			LoadPreference (Preferences.MAIN_WINDOW_WIDTH);
+			LoadPreference (Preferences.MAIN_WINDOW_X);
+			LoadPreference (Preferences.MAIN_WINDOW_MAXIMIZED);
+			main_window.ShowAll ();
+	
+			LoadPreference (Preferences.SIDEBAR_POSITION);
+			LoadPreference (Preferences.METADATA_EMBED_IN_IMAGE);
+	
+			pagesetup_menu_item.Activated += HandlePageSetupActivated;
+	
+			toolbar = new Gtk.Toolbar ();
+			toolbar_vbox.PackStart (toolbar);
+	
+			ToolButton import_button = GtkUtil.ToolButtonFromTheme ("gtk-add", Catalog.GetString ("Import"), true);
+			import_button.Clicked += HandleImportCommand;
+			import_button.SetTooltip (ToolTips, Catalog.GetString ("Import new images"), null);
+			toolbar.Insert (import_button, -1);
+		
+			toolbar.Insert (new SeparatorToolItem (), -1);
+	
+			rl_button = GtkUtil.ToolButtonFromTheme ("object-rotate-left", Catalog.GetString ("Rotate Left"), false);
+			rl_button.Clicked += HandleRotate270Command;
+			toolbar.Insert (rl_button, -1);
+	
+			rr_button = GtkUtil.ToolButtonFromTheme ("object-rotate-right", Catalog.GetString ("Rotate Right"), false);
+			rr_button.Clicked += HandleRotate90Command;
+			toolbar.Insert (rr_button, -1);
+	
+			toolbar.Insert (new SeparatorToolItem (), -1);
+	
+			browse_button = new ToggleToolButton ();
+			browse_button.Label = Catalog.GetString ("Browse");
+			browse_button.IconName = "mode-browse";
+			browse_button.IsImportant = true;
+			browse_button.Toggled += HandleToggleViewBrowse;
+			browse_button.SetTooltip (ToolTips, Catalog.GetString ("Browse many photos simultaneously"), null);
+			toolbar.Insert (browse_button, -1);
+	
+			edit_button = new ToggleToolButton ();
+			edit_button.Label = Catalog.GetString ("Edit Image");
+			edit_button.IconName = "mode-image-edit";
+			edit_button.IsImportant = true;
+			edit_button.Toggled += HandleToggleViewPhoto;
+			edit_button.SetTooltip (ToolTips, Catalog.GetString ("View and edit a photo"), null);
+			toolbar.Insert (edit_button, -1);
+	
+			toolbar.Insert (new SeparatorToolItem (), -1);
+	
+			ToolButton fs_button = GtkUtil.ToolButtonFromTheme ("view-fullscreen", Catalog.GetString ("Fullscreen"), false);
+			fs_button.Clicked += HandleViewFullscreen;
+			fs_button.SetTooltip (ToolTips, Catalog.GetString ("View photos fullscreen"), null);
+			toolbar.Insert (fs_button, -1);
+	
+			ToolButton ss_button = GtkUtil.ToolButtonFromTheme ("media-playback-start", Catalog.GetString ("Slideshow"), false);
+			ss_button.Clicked += HandleViewSlideShow;
+			ss_button.SetTooltip (ToolTips, Catalog.GetString ("View photos in a slideshow"), null);
+			toolbar.Insert (ss_button, -1);
+	
+			SeparatorToolItem white_space = new SeparatorToolItem ();
+			white_space.Draw = false;
+			white_space.Expand = true;
+			toolbar.Insert (white_space, -1);
+	
+			ToolItem label_item = new ToolItem ();
+			count_label = new Label (String.Empty);
+			label_item.Child = count_label;
+			toolbar.Insert (label_item, -1);
+	
+			display_previous_button = new ToolButton (Stock.GoBack);
+			toolbar.Insert (display_previous_button, -1);
+			display_previous_button.SetTooltip (ToolTips, Catalog.GetString ("Previous photo"), String.Empty);
+			display_previous_button.Clicked += new EventHandler (HandleDisplayPreviousButtonClicked);
+	
+			display_next_button = new ToolButton (Stock.GoForward);
+			toolbar.Insert (display_next_button, -1);
+			display_next_button.SetTooltip (ToolTips, Catalog.GetString ("Next photo"), String.Empty);
+			display_next_button.Clicked += new EventHandler (HandleDisplayNextButtonClicked);
+	
+			Sidebar = new Sidebar ();
+			ViewModeChanged += Sidebar.HandleMainWindowViewModeChanged;
+			sidebar_vbox.Add (Sidebar);
+	
+			tag_selection_scrolled = new ScrolledWindow ();
+			tag_selection_scrolled.ShadowType = ShadowType.In;
+			
+			tag_selection_widget = new TagSelectionWidget (Database.Tags);
+			tag_selection_scrolled.Add (tag_selection_widget);
+	
+			Sidebar.AppendPage (tag_selection_scrolled, Catalog.GetString ("Tags"), "tag");
+	
+			AddinManager.AddExtensionNodeHandler ("/FSpot/Sidebar", OnSidebarExtensionChanged);
+	
+			Sidebar.Context = ViewContext.Library;
+	 		
+			Sidebar.CloseRequested += HideSidebar;
+			Sidebar.Show ();
+	
+			InfoBox = new InfoBox ();
+			ViewModeChanged += InfoBox.HandleMainWindowViewModeChanged;
+			InfoBox.VersionIdChanged += delegate (InfoBox box, uint version_id) { UpdateForVersionIdChange (version_id);};
+			sidebar_vbox.PackEnd (InfoBox, false, false, 0);
+	
+			InfoBox.Context = ViewContext.Library;
+			
+			tag_selection_widget.Selection.Changed += HandleTagSelectionChanged;
+			tag_selection_widget.KeyPressEvent += HandleTagSelectionKeyPress;
+			tag_selection_widget.ButtonPressEvent += HandleTagSelectionButtonPressEvent;
+			tag_selection_widget.PopupMenu += HandleTagSelectionPopupMenu;
+			tag_selection_widget.RowActivated += HandleTagSelectionRowActivated;
+			
+			LoadPreference (Preferences.TAG_ICON_SIZE);
+			
+			try {
+				query = new FSpot.PhotoQuery (Database.Photos);
+			} catch (System.Exception e) {
+				//FIXME assume any exception here is due to a corrupt db and handle that.
+				new RepairDbDialog (e, Database.Repair (), main_window);
+				query = new FSpot.PhotoQuery (Database.Photos);
+			}
+	
+			UpdateStatusLabel ();
+			query.Changed += HandleQueryChanged;
+	
+			Database.Photos.ItemsChanged += HandleDbItemsChanged;
+			Database.Tags.ItemsChanged += HandleTagsChanged;
+			Database.Tags.ItemsAdded += HandleTagsChanged;
+			Database.Tags.ItemsRemoved += HandleTagsChanged;
+	#if SHOW_CALENDAR
+			FSpot.SimpleCalendar cal = new FSpot.SimpleCalendar (query);
+			cal.DaySelected += HandleCalendarDaySelected;
+			left_vbox.PackStart (cal, false, true, 0);
+	#endif
+	
+			group_selector = new FSpot.GroupSelector ();
+			group_selector.Adaptor = new FSpot.TimeAdaptor (query, Preferences.Get<bool> (Preferences.GROUP_ADAPTOR_ORDER_ASC));
+	
+			group_selector.ShowAll ();
+			
+			if (zoom_scale != null) {
+				zoom_scale.ValueChanged += HandleZoomScaleValueChanged;
+			}
+	
+			view_vbox.PackStart (group_selector, false, false, 0);
+			view_vbox.ReorderChild (group_selector, 0);
+	
+			find_bar = new FindBar (query, tag_selection_widget.Model);
+			view_vbox.PackStart (find_bar, false, false, 0);
+			view_vbox.ReorderChild (find_bar, 1);
+			main_window.KeyPressEvent += HandleKeyPressEvent;
+			
+			query_widget = new FSpot.QueryWidget (query, Database);
+			query_widget.Logic.Changed += HandleQueryLogicChanged;
+			view_vbox.PackStart (query_widget, false, false, 0);
+			view_vbox.ReorderChild (query_widget, 2);
+	
+			icon_view = new QueryView (query);
+			icon_view.ZoomChanged += HandleZoomChanged;
+			LoadPreference (Preferences.ZOOM);
+			LoadPreference (Preferences.SHOW_TAGS);
+			LoadPreference (Preferences.SHOW_DATES);
+			LoadPreference (Preferences.SHOW_RATINGS);
+			icon_view_scrolled.Add (icon_view);
+			icon_view.DoubleClicked += HandleDoubleClicked;
+			icon_view.Vadjustment.ValueChanged += HandleIconViewScroll;
+			icon_view.GrabFocus ();
+	
+			new FSpot.PreviewPopup (icon_view);
+	
+			Gtk.Drag.SourceSet (icon_view, Gdk.ModifierType.Button1Mask | Gdk.ModifierType.Button3Mask,
+					    icon_source_target_table, DragAction.Copy | DragAction.Move);
 			
-			if (edit_button.Active != state)
-				edit_button.Active = state;
+			icon_view.DragBegin += HandleIconViewDragBegin;
+			icon_view.DragDataGet += HandleIconViewDragDataGet;
+	
+			TagMenu tag_menu = new TagMenu (null, Database.Tags);
+			tag_menu.NewTagHandler += delegate { HandleCreateTagAndAttach (this, null); };
+			tag_menu.TagSelected += HandleAttachTagMenuSelected;
+			tag_menu.Populate();
+			(uimanager.GetWidget("/ui/menubar1/edit2/attach_tag") as MenuItem).Submenu = tag_menu;
+			
+			PhotoTagMenu pmenu = new PhotoTagMenu ();
+			pmenu.TagSelected += HandleRemoveTagMenuSelected;
+			(uimanager.GetWidget("/ui/menubar1/edit2/remove_tag") as MenuItem).Submenu = pmenu;
+			
+			Gtk.Drag.DestSet (icon_view, DestDefaults.All, icon_dest_target_table, 
+					  DragAction.Copy | DragAction.Move); 
+	
+			//		icon_view.DragLeave += new DragLeaveHandler (HandleIconViewDragLeave);
+			icon_view.DragMotion += HandleIconViewDragMotion;
+			icon_view.DragDrop += HandleIconViewDragDrop;
+			icon_view.DragDataReceived += HandleIconViewDragDataReceived;
+			icon_view.KeyPressEvent += HandleIconViewKeyPressEvent;
+	
+			photo_view = new PhotoView (query);
+			photo_box.Add (photo_view);
+	
+			photo_view.DoubleClicked += HandleDoubleClicked;
+			photo_view.KeyPressEvent += HandlePhotoViewKeyPressEvent;
+			photo_view.UpdateStarted += HandlePhotoViewUpdateStarted;
+			photo_view.UpdateFinished += HandlePhotoViewUpdateFinished;
+	
+			photo_view.View.ZoomChanged += HandleZoomChanged;
+	
+			// Tag typing: focus the tag entry if the user starts typing a tag
+			icon_view.KeyPressEvent += HandlePossibleTagTyping;
+			photo_view.KeyPressEvent += HandlePossibleTagTyping;
+			tag_entry = new TagEntry (Database.Tags);
+			tag_entry.KeyPressEvent += HandleTagEntryKeyPressEvent;
+			tag_entry.TagsAttached += HandleTagEntryTagsAttached;
+			tag_entry.TagsRemoved += HandleTagEntryRemoveTags;
+			tag_entry.Activated += HandleTagEntryActivate;
+			tag_entry_container.Add (tag_entry);
+	
+			Gtk.Drag.DestSet (photo_view, DestDefaults.All, tag_target_table, 
+					  DragAction.Copy | DragAction.Move); 
+	
+			photo_view.DragMotion += HandlePhotoViewDragMotion;
+			photo_view.DragDrop += HandlePhotoViewDragDrop;
+			photo_view.DragDataReceived += HandlePhotoViewDragDataReceived;
+	
+			view_notebook.SwitchPage += HandleViewNotebookSwitchPage;
+			group_selector.Adaptor.GlassSet += HandleAdaptorGlassSet;
+			group_selector.Adaptor.Changed += HandleAdaptorChanged;
+			LoadPreference (Preferences.GROUP_ADAPTOR_ORDER_ASC);
+			LoadPreference (Preferences.FILMSTRIP_ORIENTATION);
+	
+			Selection = new MainSelection (this);
+			Selection.Changed += HandleSelectionChanged;
+			Selection.ItemsChanged += HandleSelectionItemsChanged;
+			Selection.Changed += Sidebar.HandleSelectionChanged;
+			Selection.ItemsChanged += Sidebar.HandleSelectionItemsChanged;
+	
+			Mono.Addins.AddinManager.ExtensionChanged += PopulateExtendableMenus;
+			PopulateExtendableMenus (null, null);
+	
+			UpdateMenus ();
+	
+			main_window.ShowAll ();
+	
+			tagbar.Hide ();
+			find_bar.Hide ();
+	
+			UpdateFindByTagMenu ();
+	
+			LoadPreference (Preferences.SHOW_TOOLBAR);
+			LoadPreference (Preferences.SHOW_SIDEBAR);
+			LoadPreference (Preferences.SHOW_TIMELINE);
+			LoadPreference (Preferences.SHOW_FILMSTRIP);
+	
+			LoadPreference (Preferences.GNOME_MAILTO_ENABLED);
+			
+			Preferences.SettingChanged += OnPreferencesChanged;
+	
+			main_window.DeleteEvent += HandleDeleteEvent;
+			
+			query_widget.HandleChanged (query);
+			query_widget.Close ();
+	
+			// When the icon_view is loaded, set it's initial scroll position
+			icon_view.SizeAllocated += HandleIconViewReady;
+	
+			export.Activated += HandleExportActivated;
+			UpdateToolbar ();
+	
+			(uimanager.GetWidget("/ui/menubar1/file1/close1") as MenuItem).Hide ();
+	
+			Banshee.Kernel.Scheduler.Resume ();
 		}
-
-		if (view_mode == ModeType.PhotoView) {
-			display_previous_button.Visible = true;
-			display_next_button.Visible = true;
-			count_label.Visible = true;
-
-			bool valid = photo_view.View.Item.IsValid;
-			bool prev = valid && photo_view.View.Item.Index > 0;
-			bool next = valid && photo_view.View.Item.Index < query.Count - 1;
-
-			display_previous_button.Sensitive = prev;
-			display_next_button.Sensitive = next;
-
-			if (Query == null)
-				count_label.Text = String.Empty;
-			else
-				// Note for translators: This indicates the current photo is photo {0} of {1} out of photos
-				count_label.Text = String.Format (Catalog.GetString ("{0} of {1}"), Query.Count == 0 ? 0 : photo_view.View.Item.Index + 1, Query.Count == 0 ? 0 : Query.Count);
-		} else {
-			display_previous_button.Visible = false;
-			display_next_button.Visible = false;
-			count_label.Visible = false;
+	
+		private void HandleDisplayNextButtonClicked (object sender, EventArgs args)
+		{
+			PhotoView.View.Item.MoveNext ();
 		}
-
-	}
-
-	private void HandleExportActivated (object o, EventArgs e)
-	{
-		FSpot.Extensions.ExportMenuItemNode.SelectedImages = delegate () {return new FSpot.PhotoArray (SelectedPhotos ()); };
-	}
-
-	private void HandleDbItemsChanged (object sender, DbItemEventArgs<Photo> args)
-	{
-		foreach (Photo p in args.Items) {
-			if (p == null)
-				continue;
-			if (write_metadata)
-				FSpot.Jobs.SyncMetadataJob.Create (db.Jobs, p);
+	
+		private void HandleDisplayPreviousButtonClicked (object sender, EventArgs args)
+		{
+			PhotoView.View.Item.MovePrevious ();
 		}
-		
-		if (args is PhotoEventArgs && (args as PhotoEventArgs).Changes.TimeChanged)
-			query.RequestReload ();
-	}
-
-	private void HandleTagsChanged (object sender, DbItemEventArgs<Tag> args)
-	{
-		icon_view.QueueDraw ();
-		UpdateTagEntryFromSelection ();	
-	}
-
-	void HandleViewNotebookSwitchPage (object sender, SwitchPageArgs args)
-	{
-		switch (view_notebook.CurrentPage) {
-		case 0:
-			SetViewMode (ModeType.IconView);
-			break;
-		case 1:
-			SetViewMode (ModeType.PhotoView);
-			break;
+	
+		private void OnSidebarExtensionChanged (object s, ExtensionNodeEventArgs args) {
+			// FIXME: No sidebar page removal yet!
+			if (args.Change == ExtensionChange.Add)
+				Sidebar.AppendPage ((args.ExtensionNode as SidebarPageNode).GetSidebarPage ());
 		}
-	}
-
-	private int [] SelectedIds () {
-		int [] ids = new int [0];
-
-		if (fsview != null && fsview.View.Item.IsValid)
-			ids = new int [] { fsview.View.Item.Index };
-		else {
-			switch (view_mode) {
+	
+		private Photo CurrentPhoto {
+			get {
+				int active = ActiveIndex ();
+				if (active >= 0)
+					return query [active] as Photo;
+				else
+					return null;
+			}
+		}
+	
+		// Index into the PhotoQuery.  If -1, no photo is selected or multiple photos are selected.
+		private int ActiveIndex () 
+		{
+			if (Selection.Count == 1)
+				return SelectedIds() [0];
+			else
+				return PHOTO_IDX_NONE;
+		}
+	
+		// Switching mode.
+		public enum ModeType {
+			IconView,
+			PhotoView
+		};
+	
+		public event EventHandler ViewModeChanged;
+	
+		public void SetViewMode (ModeType value)
+		{
+			if (ViewMode == value)
+				return;
+	
+			ViewMode = value;
+			switch (ViewMode) {
 			case ModeType.IconView:
-				ids = icon_view.Selection.Ids;
+				if (view_notebook.CurrentPage != 0)
+					view_notebook.CurrentPage = 0;
+	
+				display_timeline.Sensitive = true;
+				display_filmstrip.Sensitive = false;
+				group_selector.Visible = display_timeline.Active;
+	
+				if (photo_view.View.Loupe != null)
+					loupe_menu_item.Active = false;
+				JumpTo (photo_view.Item.Index);
+				zoom_scale.Value = icon_view.Zoom;
 				break;
-			default:
 			case ModeType.PhotoView:
-				if (photo_view.Item.IsValid)
-					ids = new int [] { photo_view.Item.Index };
+				if (view_notebook.CurrentPage != 1)
+					view_notebook.CurrentPage = 1;
+	
+				display_timeline.Sensitive = false;
+				display_filmstrip.Sensitive = true;
+				group_selector.Visible = false;
+				
+				JumpTo (icon_view.FocusCell);
+				zoom_scale.Value = photo_view.NormalizedZoom;
+	
+				photo_view.View.GrabFocus();
 				break;
 			}
-		}
-
-		return ids;
-	}
-
-	public class MainSelection : IBrowsableCollection {
-		MainWindow win;
-
-		public MainSelection (MainWindow win)
-		{
-			this.win = win;
-			win.icon_view.Selection.Changed += HandleSelectionChanged;
-			win.icon_view.Selection.ItemsChanged += HandleSelectionItemsChanged;
-			win.photo_view.PhotoChanged += HandlePhotoChanged;
-			win.query.ItemsChanged += HandleQueryItemsChanged;
+			Selection.MarkChanged ();
+			UpdateToolbar ();
+			if (ViewModeChanged != null) 
+				ViewModeChanged (this, null);
 		}
 		
-		public int Count {
-			get {
-				switch (win.view_mode) {
-				case ModeType.PhotoView:
-					return win.photo_view.Item.IsValid ? 1 : 0;
-				case ModeType.IconView:
-					return win.icon_view.Selection.Count;
-				}
-				return 0;
+		void UpdateToolbar ()
+		{
+			if (browse_button != null) {
+				bool state = ViewMode == ModeType.IconView;
+				
+				if (browse_button.Active != state)
+					browse_button.Active = state;
+			}
+	
+			if (edit_button != null) {
+				bool state = ViewMode == ModeType.PhotoView;
+				
+				if (edit_button.Active != state)
+					edit_button.Active = state;
 			}
+	
+			if (ViewMode == ModeType.PhotoView) {
+				display_previous_button.Visible = true;
+				display_next_button.Visible = true;
+				count_label.Visible = true;
+	
+				bool valid = photo_view.View.Item.IsValid;
+				bool prev = valid && photo_view.View.Item.Index > 0;
+				bool next = valid && photo_view.View.Item.Index < query.Count - 1;
+	
+				display_previous_button.Sensitive = prev;
+				display_next_button.Sensitive = next;
+	
+				if (Query == null)
+					count_label.Text = String.Empty;
+				else
+					// Note for translators: This indicates the current photo is photo {0} of {1} out of photos
+					count_label.Text = String.Format (Catalog.GetString ("{0} of {1}"), Query.Count == 0 ? 0 : photo_view.View.Item.Index + 1, Query.Count == 0 ? 0 : Query.Count);
+			} else {
+				display_previous_button.Visible = false;
+				display_next_button.Visible = false;
+				count_label.Visible = false;
+			}
+	
 		}
-
-		public int IndexOf (IBrowsableItem item)
+	
+		private void HandleExportActivated (object o, EventArgs e)
 		{
-			switch (win.view_mode) {
-			case ModeType.PhotoView:
-				return item == win.photo_view.Item.Current ? 0 : -1;
-			case ModeType.IconView:
-				return win.icon_view.Selection.IndexOf (item);
-			}
-			return -1;
+			FSpot.Extensions.ExportMenuItemNode.SelectedImages = delegate () {return new FSpot.PhotoArray (SelectedPhotos ()); };
 		}
-		
-		public bool Contains (IBrowsableItem item)
+	
+		private void HandleDbItemsChanged (object sender, DbItemEventArgs<Photo> args)
 		{
-			switch (win.view_mode) {
-			case ModeType.PhotoView:
-				return item == win.photo_view.Item.Current ? true : false;
-			case ModeType.IconView:
-				return win.icon_view.Selection.Contains (item);
+			foreach (Photo p in args.Items) {
+				if (p == null)
+					continue;
+				if (write_metadata)
+					FSpot.Jobs.SyncMetadataJob.Create (Database.Jobs, p);
 			}
-			return false;
+			
+			if (args is PhotoEventArgs && (args as PhotoEventArgs).Changes.TimeChanged)
+				query.RequestReload ();
 		}
-		
-		public void MarkChanged ()
+	
+		private void HandleTagsChanged (object sender, DbItemEventArgs<Tag> args)
 		{
-			if (Changed != null)
-				Changed (this);
+			icon_view.QueueDraw ();
+			UpdateTagEntryFromSelection ();	
 		}
-
-		public void MarkChanged (int index, IBrowsableItemChanges changes)
+	
+		void HandleViewNotebookSwitchPage (object sender, SwitchPageArgs args)
 		{
-			throw new System.NotImplementedException ("I didn't think you'd find me");
+			switch (view_notebook.CurrentPage) {
+			case 0:
+				SetViewMode (ModeType.IconView);
+				break;
+			case 1:
+				SetViewMode (ModeType.PhotoView);
+				break;
+			}
 		}
-		
-		public IBrowsableItem this [int index] {
-			get {
-				switch (win.view_mode) {
+	
+		private int [] SelectedIds () {
+			int [] ids = new int [0];
+	
+			if (fsview != null && fsview.View.Item.IsValid)
+				ids = new int [] { fsview.View.Item.Index };
+			else {
+				switch (ViewMode) {
+				case ModeType.IconView:
+					ids = icon_view.Selection.Ids;
+					break;
+				default:
 				case ModeType.PhotoView:
-					if (index == 0)
-						return win.photo_view.Item.Current;
+					if (photo_view.Item.IsValid)
+						ids = new int [] { photo_view.Item.Index };
 					break;
-				case ModeType.IconView:
-					return win.icon_view.Selection [index];
 				}
-				throw new ArgumentOutOfRangeException ();
 			}
+	
+			return ids;
 		}
-		 
-		public IBrowsableItem [] Items {
-			get {
-				switch (win.view_mode) {
+	
+		public class MainSelection : IBrowsableCollection {
+			MainWindow win;
+	
+			public MainSelection (MainWindow win)
+			{
+				this.win = win;
+				win.icon_view.Selection.Changed += HandleSelectionChanged;
+				win.icon_view.Selection.ItemsChanged += HandleSelectionItemsChanged;
+				win.photo_view.PhotoChanged += HandlePhotoChanged;
+				win.query.ItemsChanged += HandleQueryItemsChanged;
+			}
+			
+			public int Count {
+				get {
+					switch (win.ViewMode) {
+					case ModeType.PhotoView:
+						return win.photo_view.Item.IsValid ? 1 : 0;
+					case ModeType.IconView:
+						return win.icon_view.Selection.Count;
+					}
+					return 0;
+				}
+			}
+	
+			public int IndexOf (IBrowsableItem item)
+			{
+				switch (win.ViewMode) {
 				case ModeType.PhotoView:
-					if (win.photo_view.Item.IsValid)
-						return new IBrowsableItem [] {win.photo_view.Item.Current};
-
-					break;
+					return item == win.photo_view.Item.Current ? 0 : -1;
 				case ModeType.IconView:
-					return win.icon_view.Selection.Items;
+					return win.icon_view.Selection.IndexOf (item);
 				}
-				return new IBrowsableItem [0];
+				return -1;
 			}
-		}
-
-		private void HandleQueryItemsChanged (IBrowsableCollection collection, BrowsableEventArgs args)
-		{
-			// FIXME for now we only listen to changes directly from the query
-			// when we are in PhotoView mode because we presume that we'll get
-			// proper notification from the icon view selection in icon view mode
-			if (win.view_mode != ModeType.PhotoView || ItemsChanged == null) 
-				return;
-
-			foreach (int item in args.Items) {
-				if (win.photo_view.Item.Index == item ) {
-					ItemsChanged (this, new BrowsableEventArgs (item, args.Changes));
-					break;
+			
+			public bool Contains (IBrowsableItem item)
+			{
+				switch (win.ViewMode) {
+				case ModeType.PhotoView:
+					return item == win.photo_view.Item.Current ? true : false;
+				case ModeType.IconView:
+					return win.icon_view.Selection.Contains (item);
+				}
+				return false;
+			}
+			
+			public void MarkChanged ()
+			{
+				if (Changed != null)
+					Changed (this);
+			}
+	
+			public void MarkChanged (int index, IBrowsableItemChanges changes)
+			{
+				throw new System.NotImplementedException ("I didn't think you'd find me");
+			}
+			
+			public IBrowsableItem this [int index] {
+				get {
+					switch (win.ViewMode) {
+					case ModeType.PhotoView:
+						if (index == 0)
+							return win.photo_view.Item.Current;
+						break;
+					case ModeType.IconView:
+						return win.icon_view.Selection [index];
+					}
+					throw new ArgumentOutOfRangeException ();
+				}
+			}
+			 
+			public IBrowsableItem [] Items {
+				get {
+					switch (win.ViewMode) {
+					case ModeType.PhotoView:
+						if (win.photo_view.Item.IsValid)
+							return new IBrowsableItem [] {win.photo_view.Item.Current};
+	
+						break;
+					case ModeType.IconView:
+						return win.icon_view.Selection.Items;
+					}
+					return new IBrowsableItem [0];
+				}
+			}
+	
+			private void HandleQueryItemsChanged (IBrowsableCollection collection, BrowsableEventArgs args)
+			{
+				// FIXME for now we only listen to changes directly from the query
+				// when we are in PhotoView mode because we presume that we'll get
+				// proper notification from the icon view selection in icon view mode
+				if (win.ViewMode != ModeType.PhotoView || ItemsChanged == null) 
+					return;
+	
+				foreach (int item in args.Items) {
+					if (win.photo_view.Item.Index == item ) {
+						ItemsChanged (this, new BrowsableEventArgs (item, args.Changes));
+						break;
+					}
 				}
 			}
+	
+			private void HandlePhotoChanged (PhotoView sender)
+			{
+				if (win.ViewMode == ModeType.PhotoView && Changed != null)
+					Changed (this);
+			}
+	
+			public void HandleSelectionChanged (IBrowsableCollection collection)
+			{
+				if (win.ViewMode == ModeType.IconView && Changed != null)
+					Changed (this);
+	
+	
+			}
+	
+			private void HandleSelectionItemsChanged (IBrowsableCollection collection,  BrowsableEventArgs args)
+			{
+				if (win.ViewMode == ModeType.IconView && ItemsChanged != null)
+					ItemsChanged (this, args);
+			}
+	
+			public event IBrowsableCollectionChangedHandler Changed;
+			public event IBrowsableCollectionItemsChangedHandler ItemsChanged;
 		}
-
-		private void HandlePhotoChanged (PhotoView sender)
+	
+		private void HandleSelectionChanged (IBrowsableCollection collection)
 		{
-			if (win.view_mode == ModeType.PhotoView && Changed != null)
-				Changed (this);
+			UpdateMenus ();
+			UpdateTagEntryFromSelection ();
+			UpdateStatusLabel ();
+			UpdateToolbar ();
+	
+			InfoBox.Photos = SelectedPhotos ();
 		}
-
-		public void HandleSelectionChanged (IBrowsableCollection collection)
+	
+		private void HandleSelectionItemsChanged (IBrowsableCollection collection, BrowsableEventArgs args)
 		{
-			if (win.view_mode == ModeType.IconView && Changed != null)
-				Changed (this);
-
-
+			UpdateMenus ();
+			UpdateTagEntryFromSelection ();
+			photo_view.UpdateTagView ();
+			InfoBox.Photos = SelectedPhotos ();
 		}
-
-		private void HandleSelectionItemsChanged (IBrowsableCollection collection,  BrowsableEventArgs args)
+	
+	
+		//
+		// Selection Interface
+		//
+	
+		private Photo [] SelectedPhotos (int [] selected_ids)
 		{
-			if (win.view_mode == ModeType.IconView && ItemsChanged != null)
-				ItemsChanged (this, args);
+			Photo [] photo_list = new Photo [selected_ids.Length];
+		
+			int i = 0;
+			foreach (int num in selected_ids)
+				photo_list [i ++] = query [num] as Photo;
+			
+			return photo_list;
 		}
-
-		public event IBrowsableCollectionChangedHandler Changed;
-		public event IBrowsableCollectionItemsChangedHandler ItemsChanged;
-	}
-
-	private void HandleSelectionChanged (IBrowsableCollection collection)
-	{
-		UpdateMenus ();
-		UpdateTagEntryFromSelection ();
-		UpdateStatusLabel ();
-		UpdateToolbar ();
-
-		info_box.Photos = SelectedPhotos ();
-	}
-
-	private void HandleSelectionItemsChanged (IBrowsableCollection collection, BrowsableEventArgs args)
-	{
-		UpdateMenus ();
-		UpdateTagEntryFromSelection ();
-		photo_view.UpdateTagView ();
-		info_box.Photos = SelectedPhotos ();
-	}
-
-
-	//
-	// Selection Interface
-	//
-
-	private Photo [] SelectedPhotos (int [] selected_ids)
-	{
-		Photo [] photo_list = new Photo [selected_ids.Length];
 	
-		int i = 0;
-		foreach (int num in selected_ids)
-			photo_list [i ++] = query [num] as Photo;
+		public Photo [] SelectedPhotos () 
+		{
+			return SelectedPhotos (SelectedIds ());
+		}
+	
+		public PhotoQuery Query {
+			get { return query; }
+		}
+	
+		//
+		// Change Notification functions
+		//
+	
+		private void InvalidateViews ()
+		{
+			icon_view.QueueDraw ();
+			photo_view.Reload ();
+			if (fsview != null)
+				fsview.View.Reload ();
+		}
+			
+		//
+		// Commands
+		//
+	
+		private void RotateSelectedPictures (Gtk.Window parent, RotateDirection direction)
+		{
+			RotateCommand command = new RotateCommand (parent);
+			
+			int [] selected_ids = SelectedIds ();
+			if (command.Execute (direction, SelectedPhotos (selected_ids)))
+				query.MarkChanged (selected_ids, new PhotoChanges () {DataChanged = true});
+		}
+	
+		//
+		// Tag Selection Drag Handlers
+		//
 		
-		return photo_list;
-	}
-
-	public Photo [] SelectedPhotos () 
-	{
-		return SelectedPhotos (SelectedIds ());
-	}
-
-	public PhotoQuery Query {
-		get { return query; }
-	}
-
-	//
-	// Change Notification functions
-	//
-
-	private void InvalidateViews ()
-	{
-		icon_view.QueueDraw ();
-		photo_view.Reload ();
-		if (fsview != null)
-			fsview.View.Reload ();
-	}
+		public void AddTagExtended (int [] nums, Tag [] tags)
+		{
+			foreach (int num in nums)
+				(query[num] as Photo).AddTag (tags);
+			query.Commit (nums);
+	
+			foreach (Tag t in tags) {
+				if (t.Icon != null || t.IconWasCleared)
+					continue;
+				// FIXME this needs a lot more work.
+				Pixbuf icon = null;
+				try {
+					Pixbuf tmp = FSpot.PhotoLoader.LoadAtMaxSize (query [nums[0]], 128, 128);
+					icon = PixbufUtils.TagIconFromPixbuf (tmp);
+					tmp.Dispose ();
+				} catch {
+					icon = null;
+				}
+				
+				t.Icon = icon;
+				Database.Tags.Commit (t);
+			}
+		}
 		
-	//
-	// Commands
-	//
-
-	private void RotateSelectedPictures (Gtk.Window parent, RotateDirection direction)
-	{
-		RotateCommand command = new RotateCommand (parent);
+		public void SetFolderQuery (IEnumerable<Uri> uri_list)
+		{
+			ShowQueryWidget ();
+			query_widget.SetFolders (uri_list);
+		}
 		
-		int [] selected_ids = SelectedIds ();
-		if (command.Execute (direction, SelectedPhotos (selected_ids)))
-			query.MarkChanged (selected_ids, new PhotoChanges () {DataChanged = true});
-	}
-
-	//
-	// Tag Selection Drag Handlers
-	//
+		public void RemoveTags (int [] nums, Tag [] tags)
+		{
+			foreach (int num in nums)
+				(query[num] as Photo).RemoveTag (tags);
+			query.Commit (nums);
+		}
 	
-	public void AddTagExtended (int [] nums, Tag [] tags)
-	{
-		foreach (int num in nums)
-			(query[num] as Photo).AddTag (tags);
-		query.Commit (nums);
-
-		foreach (Tag t in tags) {
-			if (t.Icon != null || t.IconWasCleared)
-				continue;
-			// FIXME this needs a lot more work.
-			Pixbuf icon = null;
-			try {
-				Pixbuf tmp = FSpot.PhotoLoader.LoadAtMaxSize (query [nums[0]], 128, 128);
-				icon = PixbufUtils.TagIconFromPixbuf (tmp);
-				tmp.Dispose ();
-			} catch {
-				icon = null;
+		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;
 			}
-			
-			t.Icon = icon;
-			db.Tags.Commit (t);
 		}
-	}
 	
-	public void SetFolderQuery (IEnumerable<Uri> uri_list)
-	{
-		ShowQueryWidget ();
-		query_widget.SetFolders (uri_list);
-	}
-	
-	public void RemoveTags (int [] nums, Tag [] tags)
-	{
-		foreach (int num in nums)
-			(query[num] as Photo).RemoveTag (tags);
-		query.Commit (nums);
-	}
-
-	void HandleTagSelectionButtonPressEvent (object sender, ButtonPressEventArgs args)
-	{
-		if (args.Event.Button == 3) {
+		void HandleTagSelectionPopupMenu (object sender, PopupMenuArgs args)
+		{
 			TagPopup popup = new TagPopup ();
-			popup.Activate (args.Event, tag_selection_widget.TagAtPosition (args.Event.X, args.Event.Y),
-			tag_selection_widget.TagHighlight);
+			popup.Activate (null, null, 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 HandleTagSelectionRowActivated (object sender, RowActivatedArgs args)
- 	{
- 		ShowQueryWidget ();
- 		query_widget.Include (new Tag [] {tag_selection_widget.TagByPath (args.Path)});
-	}
-
-
-#if SHOW_CALENDAR
-	void HandleCalendarDaySelected (object sender, System.EventArgs args)
-	{
-		FSpot.SimpleCalendar cal = sender as FSpot.SimpleCalendar;
-		JumpTo (cal.Date);
-	}
-
-	void JumpTo (System.DateTime time)
-	{
-		JumpTo (query.LookupItem (time));*/
-	}
-#endif
-
-	void JumpTo (int index)
-	{
-		switch (view_mode) {
-		case ModeType.PhotoView:
-			photo_view.Item.Index = index;
-			break;
-		case ModeType.IconView:
-			icon_view.ScrollTo (index);
-			icon_view.Throb (index);
-			break;
+	
+		void HandleTagSelectionRowActivated (object sender, RowActivatedArgs args)
+	 	{
+	 		ShowQueryWidget ();
+	 		query_widget.Include (new Tag [] {tag_selection_widget.TagByPath (args.Path)});
 		}
-	}
-
-	void HandleAdaptorGlassSet (FSpot.GroupAdaptor sender, int index)
-	{
-		JumpTo (index);
-	}
-
-	void HandleAdaptorChanged (FSpot.GroupAdaptor sender)
-	{
-		UpdateGlass ();
-	}
-
-	/*
-	 * Keep the glass temporal slider in sync with the user's scrolling in the icon_view
-	 */
-	private void UpdateGlass ()
-	{
-		// If people cant see the timeline don't update it.
-		if (! display_timeline.Active)
-			return;
-
-		int cell_num = icon_view.TopLeftVisibleCell();
-		if (cell_num == -1 /*|| cell_num == lastTopLeftCell*/)
-			return;
-
-		FSpot.IBrowsableItem photo = icon_view.Collection [cell_num];
-#if false
-		group_selector.Adaptor.GlassSet -= HandleAdaptorGlassSet;
-		group_selector.Adaptor.SetGlass (group_selector.Adaptor.IndexFromPhoto (photo));
-		group_selector.Adaptor.GlassSet = HandleAdaptorGlassSet;
-#else
-		/* 
-		 * FIXME this is a lame hack to get around a delegate chain.  This should 
-		 * actually operate directly on the adaptor not on the selector but I don't have 
-		 * time to fix it right now.
+	
+	
+	#if SHOW_CALENDAR
+		void HandleCalendarDaySelected (object sender, System.EventArgs args)
+		{
+			FSpot.SimpleCalendar cal = sender as FSpot.SimpleCalendar;
+			JumpTo (cal.Date);
+		}
+	
+		void JumpTo (System.DateTime time)
+		{
+			JumpTo (query.LookupItem (time));*/
+		}
+	#endif
+	
+		void JumpTo (int index)
+		{
+			switch (ViewMode) {
+			case ModeType.PhotoView:
+				photo_view.Item.Index = index;
+				break;
+			case ModeType.IconView:
+				icon_view.ScrollTo (index);
+				icon_view.Throb (index);
+				break;
+			}
+		}
+	
+		void HandleAdaptorGlassSet (FSpot.GroupAdaptor sender, int index)
+		{
+			JumpTo (index);
+		}
+	
+		void HandleAdaptorChanged (FSpot.GroupAdaptor sender)
+		{
+			UpdateGlass ();
+		}
+	
+		/*
+		 * Keep the glass temporal slider in sync with the user's scrolling in the icon_view
 		 */
-		group_selector.SetPosition (group_selector.Adaptor.IndexFromPhoto (photo));
-#endif
-	}
+		private void UpdateGlass ()
+		{
+			// If people cant see the timeline don't update it.
+			if (! display_timeline.Active)
+				return;
 	
-	void HandleIconViewScroll (object sender, EventArgs args)
-	{
-		UpdateGlass ();
-	}
-
-	void HandleIconViewReady (object sender, EventArgs args)
-	{
-		LoadPreference (Preferences.GLASS_POSITION);
-
-		// We only want to set the position the first time
-		// the icon_view is ready (eg on startup)
-		icon_view.SizeAllocated -= HandleIconViewReady;
-	}
-
-	//
-	// IconView Drag Handlers
-	//
-
-	void HandleIconViewDragBegin (object sender, DragBeginArgs args)
-	{
-		Photo [] photos = SelectedPhotos ();
+			int cell_num = icon_view.TopLeftVisibleCell();
+			if (cell_num == -1 /*|| cell_num == lastTopLeftCell*/)
+				return;
+	
+			FSpot.IBrowsableItem photo = icon_view.Collection [cell_num];
+	#if false
+			group_selector.Adaptor.GlassSet -= HandleAdaptorGlassSet;
+			group_selector.Adaptor.SetGlass (group_selector.Adaptor.IndexFromPhoto (photo));
+			group_selector.Adaptor.GlassSet = HandleAdaptorGlassSet;
+	#else
+			/* 
+			 * FIXME this is a lame hack to get around a delegate chain.  This should 
+			 * actually operate directly on the adaptor not on the selector but I don't have 
+			 * time to fix it right now.
+			 */
+			group_selector.SetPosition (group_selector.Adaptor.IndexFromPhoto (photo));
+	#endif
+		}
 		
-		if (photos.Length > 0) {
-			int len = Math.Min (photos.Length, 4);
-			int size = 48;
-			int border  = 2;
-			int csize = size/2 + len * size / 2 + 2 * border ;
-			
-			Pixbuf container = new Pixbuf (Gdk.Colorspace.Rgb, true, 8, csize, csize);
-			container.Fill (0x00000000);
-
-			bool use_icon = false;;
-			while (len-- > 0) {
-				FSpot.PixbufCache.CacheEntry entry = icon_view.Cache.Lookup (photos [len].DefaultVersionUri);
-
-				Pixbuf thumbnail = null;
-				if (entry != null) {
-					Cms.Profile screen_profile;
-					if (FSpot.ColorManagement.Profiles.TryGetValue (Preferences.Get<string> (Preferences.COLOR_MANAGEMENT_DISPLAY_PROFILE), out screen_profile)) {
-						thumbnail = entry.Pixbuf.Copy ();
-						FSpot.ColorManagement.ApplyProfile (thumbnail, screen_profile);
-					} else
-						thumbnail = entry.ShallowCopyPixbuf ();
-				}
+		void HandleIconViewScroll (object sender, EventArgs args)
+		{
+			UpdateGlass ();
+		}
+	
+		void HandleIconViewReady (object sender, EventArgs args)
+		{
+			LoadPreference (Preferences.GLASS_POSITION);
+	
+			// We only want to set the position the first time
+			// the icon_view is ready (eg on startup)
+			icon_view.SizeAllocated -= HandleIconViewReady;
+		}
+	
+		//
+		// IconView Drag Handlers
+		//
+	
+		void HandleIconViewDragBegin (object sender, DragBeginArgs args)
+		{
+			Photo [] photos = SelectedPhotos ();
+			
+			if (photos.Length > 0) {
+				int len = Math.Min (photos.Length, 4);
+				int size = 48;
+				int border  = 2;
+				int csize = size/2 + len * size / 2 + 2 * border ;
 				
-				if (thumbnail != null) {
-					Pixbuf small = PixbufUtils.ScaleToMaxSize (thumbnail, size, size);				
-
-					int x = border + len * (size/2) + (size - small.Width)/2;
-					int y = border + len * (size/2) + (size - small.Height)/2;
-					Pixbuf box = new Pixbuf (container, x - border, y - border, 
-								 small.Width + 2 * border, small.Height + 2 * border);
-
-					box.Fill (0x000000ff);
-					small.CopyArea (0, 0, small.Width, small.Height, container, x, y); 
+				Pixbuf container = new Pixbuf (Gdk.Colorspace.Rgb, true, 8, csize, csize);
+				container.Fill (0x00000000);
+	
+				bool use_icon = false;;
+				while (len-- > 0) {
+					FSpot.PixbufCache.CacheEntry entry = icon_view.Cache.Lookup (photos [len].DefaultVersionUri);
+	
+					Pixbuf thumbnail = null;
+					if (entry != null) {
+						Cms.Profile screen_profile;
+						if (FSpot.ColorManagement.Profiles.TryGetValue (Preferences.Get<string> (Preferences.COLOR_MANAGEMENT_DISPLAY_PROFILE), out screen_profile)) {
+							thumbnail = entry.Pixbuf.Copy ();
+							FSpot.ColorManagement.ApplyProfile (thumbnail, screen_profile);
+						} else
+							thumbnail = entry.ShallowCopyPixbuf ();
+					}
 					
-					thumbnail.Dispose ();
-					small.Dispose ();
-					use_icon = true;
+					if (thumbnail != null) {
+						Pixbuf small = PixbufUtils.ScaleToMaxSize (thumbnail, size, size);				
+	
+						int x = border + len * (size/2) + (size - small.Width)/2;
+						int y = border + len * (size/2) + (size - small.Height)/2;
+						Pixbuf box = new Pixbuf (container, x - border, y - border, 
+									 small.Width + 2 * border, small.Height + 2 * border);
+	
+						box.Fill (0x000000ff);
+						small.CopyArea (0, 0, small.Width, small.Height, container, x, y); 
+						
+						thumbnail.Dispose ();
+						small.Dispose ();
+						use_icon = true;
+					}
 				}
+				if (use_icon)
+					Gtk.Drag.SetIconPixbuf (args.Context, container, 0, 0);
+				container.Dispose ();
 			}
-			if (use_icon)
-				Gtk.Drag.SetIconPixbuf (args.Context, container, 0, 0);
-			container.Dispose ();
 		}
-	}
-
-	void HandleIconViewDragDataGet (object sender, DragDataGetArgs args)
-	{	
-		if (args.Info == DragDropTargets.UriListEntry.Info) {
-			args.SelectionData.SetUriListData (new UriList (SelectedPhotos ()), args.Context.Targets[0]);
-			return;
+	
+		void HandleIconViewDragDataGet (object sender, DragDataGetArgs args)
+		{	
+			if (args.Info == DragDropTargets.UriListEntry.Info) {
+				args.SelectionData.SetUriListData (new UriList (SelectedPhotos ()), args.Context.Targets[0]);
+				return;
+			}
+			
+			if (args.Info == DragDropTargets.PhotoListEntry.Info) {
+				args.SelectionData.SetPhotosData (SelectedPhotos (), args.Context.Targets[0]);
+				return;
+			}
+			
+			if (args.Info == DragDropTargets.RootWindowEntry.Info) {
+				HandleSetAsBackgroundCommand (null, null);
+				return;
+			}
 		}
-		
-		if (args.Info == DragDropTargets.PhotoListEntry.Info) {
-			args.SelectionData.SetPhotosData (SelectedPhotos (), args.Context.Targets[0]);
-			return;
+	
+		void HandleIconViewDragDrop (object sender, DragDropArgs args)
+		{
+			args.RetVal = true;
 		}
-		
-		if (args.Info == DragDropTargets.RootWindowEntry.Info) {
-			HandleSetAsBackgroundCommand (null, null);
-			return;
+	
+		void HandleIconViewDragMotion (object sender, DragMotionArgs args)
+		{
+			Gdk.Drag.Status (args.Context, args.Context.SuggestedAction, args.Time);
+			args.RetVal = true;
 		}
-	}
-
-	void HandleIconViewDragDrop (object sender, DragDropArgs args)
-	{
-		args.RetVal = true;
-	}
-
-	void HandleIconViewDragMotion (object sender, DragMotionArgs args)
-	{
-		Gdk.Drag.Status (args.Context, args.Context.SuggestedAction, args.Time);
-		args.RetVal = true;
-	}
-
-	public void ImportUriList (UriList list, bool copy) 
-	{
-		ImportCommand command = new ImportCommand (main_window);
-		if (command.ImportFromPaths (db.Photos, list.ToLocalPaths (), copy) > 0) {
-			query.RollSet = new RollSet (db.Rolls.GetRolls (1)[0]);
-			UpdateQuery ();
+	
+		public void ImportUriList (UriList list, bool copy) 
+		{
+			ImportCommand command = new ImportCommand (main_window);
+			if (command.ImportFromPaths (Database.Photos, list.ToLocalPaths (), copy) > 0) {
+				query.RollSet = new RollSet (Database.Rolls.GetRolls (1)[0]);
+				UpdateQuery ();
+			}
 		}
-	}
-
-	public void ImportFile (string path)
-	{
-		ImportCommand command = new ImportCommand (main_window);
-		if (command.ImportFromFile (db.Photos, path) > 0) {
-			query.RollSet = new RollSet (db.Rolls.GetRolls (1)[0]);
-			UpdateQuery ();
+	
+		public void ImportFile (string path)
+		{
+			ImportCommand command = new ImportCommand (main_window);
+			if (command.ImportFromFile (Database.Photos, path) > 0) {
+				query.RollSet = new RollSet (Database.Rolls.GetRolls (1)[0]);
+				UpdateQuery ();
+			}
 		}
-	}
-
-#if false
-	public void ImportUdi (string udi)
-	{
-		/* probably a camera we need to contruct on of our gphoto2 uris */
-		Hal.Device dev = new Hal.Device (Core.HalContext, udi);
-		string mount_point = dev.GetPropertyString ("volume.mount_point");
-		int bus = dev.GetPropertyInt ("usb.bus_number");
-		int device = dev.GetPropertyInt ("usb.linux.device_number");
-		System.Console.WriteLine ("dev = {1} exists = {2} mount_point = {0} {3},{4}", mount_point, dev, dev.Exists, bus, device);
-
-		if (! dev.Exists || mount_point != null) {
-			ImportFile (mount_point);
-		} else {
-			string gphoto_uri = String.Format ("gphoto2:usb:{0},{1}", bus.ToString ("d3") , device.ToString ("d3"));
-			System.Console.WriteLine ("gphoto_uri = {0}", gphoto_uri);
-			ImportCamera (gphoto_uri);
-		} 
+	
+	#if false
+		public void ImportUdi (string udi)
+		{
+			/* probably a camera we need to contruct on of our gphoto2 uris */
+			Hal.Device dev = new Hal.Device (Core.HalContext, udi);
+			string mount_point = dev.GetPropertyString ("volume.mount_point");
+			int bus = dev.GetPropertyInt ("usb.bus_number");
+			int device = dev.GetPropertyInt ("usb.linux.device_number");
+			System.Console.WriteLine ("dev = {1} exists = {2} mount_point = {0} {3},{4}", mount_point, dev, dev.Exists, bus, device);
+	
+			if (! dev.Exists || mount_point != null) {
+				ImportFile (mount_point);
+			} else {
+				string gphoto_uri = String.Format ("gphoto2:usb:{0},{1}", bus.ToString ("d3") , device.ToString ("d3"));
+				System.Console.WriteLine ("gphoto_uri = {0}", gphoto_uri);
+				ImportCamera (gphoto_uri);
+			} 
+				
+		}
+	#endif
+	
+		void HandleIconViewDragDataReceived (object sender, DragDataReceivedArgs args)
+		{
+		 	Widget source = Gtk.Drag.GetSourceWidget (args.Context);     
 			
-	}
-#endif
-
-	void HandleIconViewDragDataReceived (object sender, DragDataReceivedArgs args)
-	{
-	 	Widget source = Gtk.Drag.GetSourceWidget (args.Context);     
-		
-		if (args.Info == DragDropTargets.TagListEntry.Info) {
-			//
-			// Translate the event args from viewport space to window space,
-			// drag events use the viewport.  Owen sends his regrets.
-			//
-			int item = icon_view.CellAtPosition (args.X + (int) icon_view.Hadjustment.Value, 
-							     args.Y + (int) icon_view.Vadjustment.Value);
-
-			//Console.WriteLine ("Drop cell = {0} ({1},{2})", item, args.X, args.Y);
-			if (item >= 0) {
-				if (icon_view.Selection.Contains (item))
-					AttachTags (tag_selection_widget.TagHighlight, SelectedIds());
-				else 
-					AttachTags (tag_selection_widget.TagHighlight, new int [] {item});
+			if (args.Info == DragDropTargets.TagListEntry.Info) {
+				//
+				// Translate the event args from viewport space to window space,
+				// drag events use the viewport.  Owen sends his regrets.
+				//
+				int item = icon_view.CellAtPosition (args.X + (int) icon_view.Hadjustment.Value, 
+								     args.Y + (int) icon_view.Vadjustment.Value);
+	
+				//Console.WriteLine ("Drop cell = {0} ({1},{2})", item, args.X, args.Y);
+				if (item >= 0) {
+					if (icon_view.Selection.Contains (item))
+						AttachTags (tag_selection_widget.TagHighlight, SelectedIds());
+					else 
+						AttachTags (tag_selection_widget.TagHighlight, new int [] {item});
+				}
+				
+				Gtk.Drag.Finish (args.Context, true, false, args.Time);
+				return;
 			}
 			
-			Gtk.Drag.Finish (args.Context, true, false, args.Time);
-			return;
+			if (args.Info == DragDropTargets.UriListEntry.Info) {
+	
+				/* 
+				 * If the drop is coming from inside f-spot then we don't want to import 
+				 */
+				if (source != null)
+					return;
+	
+				UriList list = args.SelectionData.GetUriListData (); 
+				ImportUriList (list, (args.Context.Action & Gdk.DragAction.Copy) != 0);
+				
+				Gtk.Drag.Finish (args.Context, true, false, args.Time);
+				return;
+			}
+			
+	#if ENABLE_REPARENTING
+			if (args.Info == DragDropTargets.PhotoListEntry.Info) {
+				int p_item = icon_view.CellAtPosition (args.X + (int) icon_view.Hadjustment.Value, 
+								     args.Y + (int) icon_view.Vadjustment.Value);
+	
+				if (p_item >= 0) {
+					if (icon_view.Selection.Contains (p_item)) //We don't want to reparent ourselves!
+						return;
+					PhotoVersionCommands.Reparent cmd = new PhotoVersionCommands.Reparent ();
+					
+					cmd.Execute (Database.Photos, SelectedPhotos(), query.Photos [p_item], GetToplevel (null));
+					UpdateQuery ();
+				}
+				Gtk.Drag.Finish (args.Context, true, false, args.Time);
+				return;
+			}
+	#endif
 		}
-		
-		if (args.Info == DragDropTargets.UriListEntry.Info) {
-
-			/* 
-			 * If the drop is coming from inside f-spot then we don't want to import 
-			 */
-			if (source != null)
+	
+		//
+		// IconView event handlers
+		// 
+	
+		void HandleDoubleClicked (object sender, BrowsableEventArgs args)
+		{
+			Widget widget = sender as Widget;
+			if (widget == null)
 				return;
-
-			UriList list = args.SelectionData.GetUriListData (); 
-			ImportUriList (list, (args.Context.Action & Gdk.DragAction.Copy) != 0);
+	
+			switch (ViewMode) {
+			case ModeType.IconView:
+				icon_view.FocusCell = args.Items[0];
+				SetViewMode (ModeType.PhotoView);
+				break;
+			case ModeType.PhotoView:
+				SetViewMode (ModeType.IconView);
+				break;
+			}
+		}
+	
+		public void HandleCommonPhotoCommands (object sender, Gtk.KeyPressEventArgs args) {
+			bool alt = ModifierType.Mod1Mask == (args.Event.State & ModifierType.Mod1Mask);
+			bool shift = ModifierType.ShiftMask == (args.Event.State & ModifierType.ShiftMask);
+	
+			if (args.RetVal == null)
+				args.RetVal = false;
 			
-			Gtk.Drag.Finish (args.Context, true, false, args.Time);
-			return;
+			switch (args.Event.Key) {
+			case Gdk.Key.Delete:
+				if (shift)
+					HandleDeleteCommand (sender, args);
+				else
+					HandleRemoveCommand (sender, args);
+				break;
+			case Gdk.Key.Key_0:
+			case Gdk.Key.KP_0:
+				if (alt)
+					HandleRatingMenuSelected (0);
+				break;
+			case Gdk.Key.Key_1:
+			case Gdk.Key.KP_1:
+				if (alt)
+					HandleRatingMenuSelected (1);
+				break;
+			case Gdk.Key.Key_2:
+			case Gdk.Key.KP_2:
+				if (alt)
+					HandleRatingMenuSelected (2);
+				break;
+			case Gdk.Key.Key_3:
+			case Gdk.Key.KP_3:
+				if (alt)
+					HandleRatingMenuSelected (3);
+				break;
+			case Gdk.Key.Key_4:
+			case Gdk.Key.KP_4:
+				if (alt)
+					HandleRatingMenuSelected (4);
+				break;
+			case Gdk.Key.Key_5:
+			case Gdk.Key.KP_5:
+				if (alt)
+					HandleRatingMenuSelected (5);
+				break;
+			default:
+				return; //do not set the RetVal to true
+			}
+			args.RetVal = true;
 		}
-		
-#if ENABLE_REPARENTING
-		if (args.Info == DragDropTargets.PhotoListEntry.Info) {
-			int p_item = icon_view.CellAtPosition (args.X + (int) icon_view.Hadjustment.Value, 
-							     args.Y + (int) icon_view.Vadjustment.Value);
-
-			if (p_item >= 0) {
-				if (icon_view.Selection.Contains (p_item)) //We don't want to reparent ourselves!
-					return;
-				PhotoVersionCommands.Reparent cmd = new PhotoVersionCommands.Reparent ();
-				
-				cmd.Execute (db.Photos, SelectedPhotos(), query.Photos [p_item], GetToplevel (null));
-				UpdateQuery ();
+	
+		void HandleIconViewKeyPressEvent (object sender, Gtk.KeyPressEventArgs args)
+		{
+			HandleCommonPhotoCommands (sender, args);
+			if ((bool)args.RetVal)
+				return;
+	
+			switch (args.Event.Key) {
+			case Gdk.Key.F:
+			case Gdk.Key.f:
+				HandleViewFullscreen (sender, args);
+				args.RetVal = true;
+				break;
 			}
-			Gtk.Drag.Finish (args.Context, true, false, args.Time);
-			return;
 		}
-#endif
-	}
-
-	//
-	// IconView event handlers
-	// 
-
-	void HandleDoubleClicked (object sender, BrowsableEventArgs args)
-	{
-		Widget widget = sender as Widget;
-		if (widget == null)
-			return;
-
-		switch (ViewMode) {
-		case ModeType.IconView:
-			icon_view.FocusCell = args.Items[0];
-			SetViewMode (ModeType.PhotoView);
-			break;
-		case ModeType.PhotoView:
-			SetViewMode (ModeType.IconView);
-			break;
+	
+		//
+		// FullScreenView event handlers.
+		//
+	
+		void HandleFullScreenViewKeyPressEvent (object sender, Gtk.KeyPressEventArgs args)
+		{
+			HandleCommonPhotoCommands (sender, args);
+			if ((bool)args.RetVal)
+				// this will hide any panels again that might have appeared above the fullscreen view
+				fsview.Present ();
 		}
-	}
-
-	public void HandleCommonPhotoCommands (object sender, Gtk.KeyPressEventArgs args) {
-		bool alt = ModifierType.Mod1Mask == (args.Event.State & ModifierType.Mod1Mask);
-		bool shift = ModifierType.ShiftMask == (args.Event.State & ModifierType.ShiftMask);
-
-		if (args.RetVal == null)
-			args.RetVal = false;
-		
-		switch (args.Event.Key) {
-		case Gdk.Key.Delete:
-			if (shift)
-				HandleDeleteCommand (sender, args);
-			else
-				HandleRemoveCommand (sender, args);
-			break;
-		case Gdk.Key.Key_0:
-		case Gdk.Key.KP_0:
-			if (alt)
-				HandleRatingMenuSelected (0);
-			break;
-		case Gdk.Key.Key_1:
-		case Gdk.Key.KP_1:
-			if (alt)
-				HandleRatingMenuSelected (1);
-			break;
-		case Gdk.Key.Key_2:
-		case Gdk.Key.KP_2:
-			if (alt)
-				HandleRatingMenuSelected (2);
-			break;
-		case Gdk.Key.Key_3:
-		case Gdk.Key.KP_3:
-			if (alt)
-				HandleRatingMenuSelected (3);
-			break;
-		case Gdk.Key.Key_4:
-		case Gdk.Key.KP_4:
-			if (alt)
-				HandleRatingMenuSelected (4);
-			break;
-		case Gdk.Key.Key_5:
-		case Gdk.Key.KP_5:
-			if (alt)
-				HandleRatingMenuSelected (5);
-			break;
-		default:
-			return; //do not set the RetVal to true
-		}
-		args.RetVal = true;
-	}
-
-	void HandleIconViewKeyPressEvent (object sender, Gtk.KeyPressEventArgs args)
-	{
-		HandleCommonPhotoCommands (sender, args);
-		if ((bool)args.RetVal)
-			return;
-
-		switch (args.Event.Key) {
-		case Gdk.Key.F:
-		case Gdk.Key.f:
-			HandleViewFullscreen (sender, args);
-			args.RetVal = true;
-			break;
+	
+		//
+		// PhotoView event handlers.
+		//
+	
+		void HandlePhotoViewKeyPressEvent (object sender, Gtk.KeyPressEventArgs args)
+		{
+			HandleCommonPhotoCommands (sender, args);
+			if ((bool)args.RetVal)
+				return;
+	
+			switch (args.Event.Key) {
+			case Gdk.Key.F:
+			case Gdk.Key.f:
+				HandleViewFullscreen (sender, args);
+				args.RetVal = true;
+				break;
+			case Gdk.Key.Escape:
+				SetViewMode (ModeType.IconView);
+				args.RetVal = true;
+				break;
+			}
 		}
-	}
-
-	//
-	// FullScreenView event handlers.
-	//
-
-	void HandleFullScreenViewKeyPressEvent (object sender, Gtk.KeyPressEventArgs args)
-	{
-		HandleCommonPhotoCommands (sender, args);
-		if ((bool)args.RetVal)
-			// this will hide any panels again that might have appeared above the fullscreen view
-			fsview.Present ();
-	}
-
-	//
-	// PhotoView event handlers.
-	//
-
-	void HandlePhotoViewKeyPressEvent (object sender, Gtk.KeyPressEventArgs args)
-	{
-		HandleCommonPhotoCommands (sender, args);
-		if ((bool)args.RetVal)
-			return;
-
-		switch (args.Event.Key) {
-		case Gdk.Key.F:
-		case Gdk.Key.f:
-			HandleViewFullscreen (sender, args);
+	
+		void HandlePhotoViewUpdateStarted (PhotoView sender)
+		{
+			main_window.GdkWindow.Cursor = watch;
+			// FIXME: use gdk_display_flush() when available
+			main_window.GdkWindow.Display.Sync ();
+		}
+	
+		void HandlePhotoViewUpdateFinished (PhotoView sender)
+		{
+			main_window.GdkWindow.Cursor = null;
+			// FIXME: use gdk_display_flush() when available
+			main_window.GdkWindow.Display.Sync ();
+		}
+	
+		//
+		// PhotoView drag handlers.
+		//
+	
+		void HandlePhotoViewDragDrop (object sender, DragDropArgs args)
+		{
+			//Widget source = Gtk.Drag.GetSourceWidget (args.Context);
+			//Console.WriteLine ("Drag Drop {0}", source == null ? "null" : source.TypeName);
+	
 			args.RetVal = true;
-			break;
-		case Gdk.Key.Escape:
-			SetViewMode (ModeType.IconView);
+		}
+	
+		void HandlePhotoViewDragMotion (object sender, DragMotionArgs args)
+		{
+			//Widget source = Gtk.Drag.GetSourceWidget (args.Context);
+			//Console.WriteLine ("Drag Motion {0}", source == null ? "null" : source.TypeName);
+	
+			Gdk.Drag.Status (args.Context, args.Context.SuggestedAction, args.Time);
 			args.RetVal = true;
-			break;
 		}
-	}
-
-	void HandlePhotoViewUpdateStarted (PhotoView sender)
-	{
-		main_window.GdkWindow.Cursor = watch;
-		// FIXME: use gdk_display_flush() when available
-		main_window.GdkWindow.Display.Sync ();
-	}
-
-	void HandlePhotoViewUpdateFinished (PhotoView sender)
-	{
-		main_window.GdkWindow.Cursor = null;
-		// FIXME: use gdk_display_flush() when available
-		main_window.GdkWindow.Display.Sync ();
-	}
-
-	//
-	// PhotoView drag handlers.
-	//
-
-	void HandlePhotoViewDragDrop (object sender, DragDropArgs args)
-	{
-		//Widget source = Gtk.Drag.GetSourceWidget (args.Context);
-		//Console.WriteLine ("Drag Drop {0}", source == null ? "null" : source.TypeName);
-
-		args.RetVal = true;
-	}
-
-	void HandlePhotoViewDragMotion (object sender, DragMotionArgs args)
-	{
-		//Widget source = Gtk.Drag.GetSourceWidget (args.Context);
-		//Console.WriteLine ("Drag Motion {0}", source == null ? "null" : source.TypeName);
-
-		Gdk.Drag.Status (args.Context, args.Context.SuggestedAction, args.Time);
-		args.RetVal = true;
-	}
-
-	void HandlePhotoViewDragDataReceived (object sender, DragDataReceivedArgs args)
-	{
-	 	//Widget source = Gtk.Drag.GetSourceWidget (args.Context);     
-		//Console.WriteLine ("Drag received {0}", source == null ? "null" : source.TypeName);
-
-		HandleAttachTagCommand (sender, null);
+	
+		void HandlePhotoViewDragDataReceived (object sender, DragDataReceivedArgs args)
+		{
+		 	//Widget source = Gtk.Drag.GetSourceWidget (args.Context);     
+			//Console.WriteLine ("Drag received {0}", source == null ? "null" : source.TypeName);
+	
+			HandleAttachTagCommand (sender, null);
+			
+			Gtk.Drag.Finish (args.Context, true, false, args.Time);
+	
+	 		photo_view.View.GrabFocus();
+		}	
+	
+		//
+		// RatingMenu commands
+		//
 		
-		Gtk.Drag.Finish (args.Context, true, false, args.Time);
-
- 		photo_view.View.GrabFocus();
-	}	
-
-	//
-	// RatingMenu commands
-	//
+		public void HandleRatingMenuSelected (int r) 
+		{
+			if (ViewMode == ModeType.PhotoView)
+				this.photo_view.UpdateRating(r);
 	
-	public void HandleRatingMenuSelected (int r) 
-	{
-		if (view_mode == ModeType.PhotoView)
-			this.photo_view.UpdateRating(r);
-
-		Photo p;
-		db.BeginTransaction ();
-		int [] selected_photos = SelectedIds ();
-		foreach (int num in selected_photos) {
-			p = query [num] as Photo;
-			p.Rating = (uint) r;
-		}
-		query.Commit (selected_photos);
-		db.CommitTransaction ();
-	}
-
-	//
-	// TagMenu commands.
-	//
-
-	public void HandleTagMenuActivate (object sender, EventArgs args)
-	{
-
-		MenuItem parent = sender as MenuItem;
-		if (parent == null) // We have a Gtk.Action for UI menus, so the "Edit > Remove tag" item needs special treatment
-			parent = uimanager.GetWidget("/ui/menubar1/edit2/remove_tag") as MenuItem;
-		if (parent != null && parent.Submenu is PhotoTagMenu) {
-			PhotoTagMenu menu = (PhotoTagMenu) parent.Submenu;
-			menu.Populate (SelectedPhotos ()); 
+			Photo p;
+			Database.BeginTransaction ();
+			int [] selected_photos = SelectedIds ();
+			foreach (int num in selected_photos) {
+				p = query [num] as Photo;
+				p.Rating = (uint) r;
+			}
+			query.Commit (selected_photos);
+			Database.CommitTransaction ();
 		}
-	}
-
-	public void HandleAttachTagMenuSelected (Tag t) 
-	{
-		db.BeginTransaction ();
-		AddTagExtended (SelectedIds (), new Tag [] {t});
-		db.CommitTransaction ();
-		query_widget.PhotoTagsChanged (new Tag[] {t});
-	}
 	
-	public void HandleRequireTag (object sender, EventArgs args)
- 	{
-		ShowQueryWidget ();
-		query_widget.Require (tag_selection_widget.TagHighlight);
- 	}
- 
-	public void HandleUnRequireTag (object sender, EventArgs args)
-	{
-		query_widget.UnRequire (tag_selection_widget.TagHighlight);
- 	}
-
-	public void HandleRemoveTagMenuSelected (Tag t)
-	{
-		db.BeginTransaction ();
-		RemoveTags (SelectedIds (), new Tag [] {t});
-		db.CommitTransaction ();
-		query_widget.PhotoTagsChanged (new Tag [] {t});
-	}
-
-	//
-	// Main menu commands
-	//
-
-	void HandleOpenCommand (object sender, EventArgs e)
-	{
-		new FSpot.SingleView ();
-	}
-
-	void HandleImportCommand (object sender, EventArgs e)
-	{
-		db.Sync = false;
-		ImportCommand command = new ImportCommand (main_window);
-		if (command.ImportFromFile (db.Photos, null) > 0) {
-			query.RollSet = new RollSet (db.Rolls.GetRolls (1)[0]);
-			UpdateQuery ();
+		//
+		// TagMenu commands.
+		//
+	
+		public void HandleTagMenuActivate (object sender, EventArgs args)
+		{
+	
+			MenuItem parent = sender as MenuItem;
+			if (parent == null) // We have a Gtk.Action for UI menus, so the "Edit > Remove tag" item needs special treatment
+				parent = uimanager.GetWidget("/ui/menubar1/edit2/remove_tag") as MenuItem;
+			if (parent != null && parent.Submenu is PhotoTagMenu) {
+				PhotoTagMenu menu = (PhotoTagMenu) parent.Submenu;
+				menu.Populate (SelectedPhotos ()); 
+			}
 		}
-		db.Sync = true;		
-	}
-
-	void HandleImportFromCameraCommand (object sender, EventArgs e)
-	{
-		ImportCamera (null);
-	}
-
-	public void ImportCamera (string camera_device)
-	{
-		Log.Debug ("ImportCamera {0}", camera_device);
-		GPhotoCamera cam = new GPhotoCamera();
-
-		try {
-			int num_cameras = cam.DetectCameras();
-			int selected_cam = 0;
-
-			if (num_cameras < 1) {
+	
+		public void HandleAttachTagMenuSelected (Tag t) 
+		{
+			Database.BeginTransaction ();
+			AddTagExtended (SelectedIds (), new Tag [] {t});
+			Database.CommitTransaction ();
+			query_widget.PhotoTagsChanged (new Tag[] {t});
+		}
+		
+		public void HandleRequireTag (object sender, EventArgs args)
+	 	{
+			ShowQueryWidget ();
+			query_widget.Require (tag_selection_widget.TagHighlight);
+	 	}
+	 
+		public void HandleUnRequireTag (object sender, EventArgs args)
+		{
+			query_widget.UnRequire (tag_selection_widget.TagHighlight);
+	 	}
+	
+		public void HandleRemoveTagMenuSelected (Tag t)
+		{
+			Database.BeginTransaction ();
+			RemoveTags (SelectedIds (), new Tag [] {t});
+			Database.CommitTransaction ();
+			query_widget.PhotoTagsChanged (new Tag [] {t});
+		}
+	
+		//
+		// Main menu commands
+		//
+	
+		void HandleOpenCommand (object sender, EventArgs e)
+		{
+			new FSpot.SingleView ();
+		}
+	
+		void HandleImportCommand (object sender, EventArgs e)
+		{
+			Database.Sync = false;
+			ImportCommand command = new ImportCommand (main_window);
+			if (command.ImportFromFile (Database.Photos, null) > 0) {
+				query.RollSet = new RollSet (Database.Rolls.GetRolls (1)[0]);
+				UpdateQuery ();
+			}
+			Database.Sync = true;		
+		}
+	
+		void HandleImportFromCameraCommand (object sender, EventArgs e)
+		{
+			ImportCamera (null);
+		}
+	
+		public void ImportCamera (string camera_device)
+		{
+			Log.Debug ("ImportCamera {0}", camera_device);
+			GPhotoCamera cam = new GPhotoCamera();
+	
+			try {
+				int num_cameras = cam.DetectCameras();
+				int selected_cam = 0;
+	
+				if (num_cameras < 1) {
+					HigMessageDialog md = new HigMessageDialog (main_window, DialogFlags.DestroyWithParent, 
+						MessageType.Warning, ButtonsType.Ok, 
+						Catalog.GetString ("No cameras detected."),
+						Catalog.GetString ("F-Spot was unable to find any cameras attached to this system." + 
+									      "  Double check that the camera is connected and has power")); 
+	
+					md.Run ();
+					md.Destroy ();
+					return;
+				} else if (num_cameras == 1) {
+					selected_cam = 0;
+				} else {
+					bool found = false;
+					if (camera_device != null)
+						for (int i = 0; i < num_cameras; i++) {
+							if (camera_device.IndexOf (cam.CameraList.GetValue(i)) != 0) {
+								selected_cam = i;
+								found = true;
+								break;
+							}
+					}
+					
+					if (!found) {
+						FSpot.CameraSelectionDialog camselect = new FSpot.CameraSelectionDialog (cam.CameraList);
+						selected_cam = camselect.Run ();
+					}
+				}
+	
+				if (selected_cam >= 0) {
+					cam.SelectCamera (selected_cam);	
+					cam.InitializeCamera ();
+	
+					FSpot.CameraFileSelectionDialog selector = new FSpot.CameraFileSelectionDialog (cam, Database);
+					if (selector.Run() > 0)
+						query.RollSet = new RollSet (Database.Rolls.GetRolls (1)[0]);
+					UpdateQuery ();
+				}
+			}
+			catch (GPhotoException ge) {
+				System.Console.WriteLine (ge.ToString ());
 				HigMessageDialog md = new HigMessageDialog (main_window, DialogFlags.DestroyWithParent, 
-					MessageType.Warning, ButtonsType.Ok, 
-					Catalog.GetString ("No cameras detected."),
-					Catalog.GetString ("F-Spot was unable to find any cameras attached to this system." + 
-								      "  Double check that the camera is connected and has power")); 
-
+					MessageType.Error, ButtonsType.Ok, 
+					Catalog.GetString ("Error connecting to camera"),
+					String.Format (Catalog.GetString ("Received error \"{0}\" while connecting to camera"), 
+					ge.Message));
+	
 				md.Run ();
 				md.Destroy ();
+			} finally {
+				cam.ReleaseGPhotoResources ();
+			}
+		}
+		void HandlePageSetupActivated (object o, EventArgs e)
+		{
+			FSpot.Global.PageSetup = Print.RunPageSetupDialog (this.Window, FSpot.Global.PageSetup, null);
+		}
+		
+		void HandlePrintCommand (object sender, EventArgs e)
+		{
+			FSpot.PrintOperation print = new FSpot.PrintOperation (SelectedPhotos ());
+			print.Run (PrintOperationAction.PrintDialog, null);
+		}
+	
+		public void HandlePreferences (object sender, EventArgs args)
+		{
+			var pref = new PreferenceDialog (GetToplevel (sender));
+			pref.Run ();
+			pref.Destroy ();
+		}
+	
+		public void HandleManageExtensions (object sender, EventArgs args)
+		{
+			Mono.Addins.Gui.AddinManagerWindow.Run (main_window);
+		}
+	
+		private void TestDisplay ()
+		{
+			Gtk.Window win = new Gtk.Window ("hello");
+			VBox box = new VBox ();
+			box.PackStart (new FSpot.Widgets.ImageDisplay (new BrowsablePointer (new FSpot.PhotoArray (SelectedPhotos ()), 0)));
+			win.Add (box);
+			win.ShowAll ();
+		}
+	
+		void HandleSendMailCommand (object sender, EventArgs args)
+		{
+			//TestDisplay ();
+			new FSpot.SendEmail (new FSpot.PhotoArray (SelectedPhotos ()), Window);
+		}
+	
+		public static void HandleHelp (object sender, EventArgs args)
+		{
+			GtkBeans.Global.ShowUri (Toplevel.Window.Screen, "ghelp:f-spot");
+		}
+	
+		public static void HandleAbout (object sender, EventArgs args)
+		{
+			FSpot.UI.Dialog.AboutDialog.ShowUp ();
+		}
+	
+		void HandleTagSizeChange (object sender, EventArgs args)
+		{
+			RadioAction choice = sender as RadioAction;
+		
+			//Get this callback twice. Once for the active going menuitem,
+			//once for the inactive leaving one. Ignore the inactive.
+			if (!choice.Active)
 				return;
-			} else if (num_cameras == 1) {
-				selected_cam = 0;
+	
+			int old_size = TagsIconSize;
+			
+			if (choice == tag_icon_hidden) {
+				TagsIconSize = (int) Tag.IconSize.Hidden;
+			} else if (choice == tag_icon_small) {
+				TagsIconSize = (int) Tag.IconSize.Small;
+			} else if (choice == tag_icon_medium) {
+				TagsIconSize = (int) Tag.IconSize.Medium;
+			} else if (choice == tag_icon_large) {
+				TagsIconSize = (int) Tag.IconSize.Large;
 			} else {
-				bool found = false;
-				if (camera_device != null)
-					for (int i = 0; i < num_cameras; i++) {
-						if (camera_device.IndexOf (cam.CameraList.GetValue(i)) != 0) {
-							selected_cam = i;
-							found = true;
-							break;
-						}
-				}
-				
-				if (!found) {
-					FSpot.CameraSelectionDialog camselect = new FSpot.CameraSelectionDialog (cam.CameraList);
-					selected_cam = camselect.Run ();
-				}
+				return;
 			}
-
-			if (selected_cam >= 0) {
-				cam.SelectCamera (selected_cam);	
-				cam.InitializeCamera ();
-
-				FSpot.CameraFileSelectionDialog selector = new FSpot.CameraFileSelectionDialog (cam, db);
-				if (selector.Run() > 0)
-					query.RollSet = new RollSet (db.Rolls.GetRolls (1)[0]);
-				UpdateQuery ();
+			
+			if (old_size != TagsIconSize) {
+				tag_selection_widget.ColumnsAutosize();
+				Preferences.Set (Preferences.TAG_ICON_SIZE, TagsIconSize);
 			}
 		}
-		catch (GPhotoException ge) {
-			System.Console.WriteLine (ge.ToString ());
-			HigMessageDialog md = new HigMessageDialog (main_window, DialogFlags.DestroyWithParent, 
-				MessageType.Error, ButtonsType.Ok, 
-				Catalog.GetString ("Error connecting to camera"),
-				String.Format (Catalog.GetString ("Received error \"{0}\" while connecting to camera"), 
-				ge.Message));
-
-			md.Run ();
-			md.Destroy ();
-		} finally {
-			cam.ReleaseGPhotoResources ();
+	
+		public void HandleFilmstripHorizontal (object sender, EventArgs args)
+		{
+			if (photo_view.FilmstripOrientation == Orientation.Horizontal)
+				return;
+			(sender as Gtk.CheckMenuItem).Active = false;
+			photo_view.PlaceFilmstrip (Orientation.Horizontal);
 		}
-	}
-	void HandlePageSetupActivated (object o, EventArgs e)
-	{
-		FSpot.Global.PageSetup = Print.RunPageSetupDialog (this.Window, FSpot.Global.PageSetup, null);
-	}
 	
-	void HandlePrintCommand (object sender, EventArgs e)
-	{
-		FSpot.PrintOperation print = new FSpot.PrintOperation (SelectedPhotos ());
-		print.Run (PrintOperationAction.PrintDialog, null);
-	}
-
-	public void HandlePreferences (object sender, EventArgs args)
-	{
-		var pref = new PreferenceDialog (GetToplevel (sender));
-		pref.Run ();
-		pref.Destroy ();
-	}
-
-	public void HandleManageExtensions (object sender, EventArgs args)
-	{
-		Mono.Addins.Gui.AddinManagerWindow.Run (main_window);
-	}
-
-	private void TestDisplay ()
-	{
-		Gtk.Window win = new Gtk.Window ("hello");
-		VBox box = new VBox ();
-		box.PackStart (new FSpot.Widgets.ImageDisplay (new BrowsablePointer (new FSpot.PhotoArray (SelectedPhotos ()), 0)));
-		win.Add (box);
-		win.ShowAll ();
-	}
-
-	void HandleSendMailCommand (object sender, EventArgs args)
-	{
-		//TestDisplay ();
-		new FSpot.SendEmail (new FSpot.PhotoArray (SelectedPhotos ()), Window);
-	}
-
-	public static void HandleHelp (object sender, EventArgs args)
-	{
-		GtkBeans.Global.ShowUri (Toplevel.Window.Screen, "ghelp:f-spot");
-	}
-
-	public static void HandleAbout (object sender, EventArgs args)
-	{
-		FSpot.UI.Dialog.AboutDialog.ShowUp ();
-	}
-
-	void HandleTagSizeChange (object sender, EventArgs args)
-	{
-		RadioAction choice = sender as RadioAction;
+		public void HandleFilmstripVertical (object sender, EventArgs args)
+		{
+			if (photo_view.FilmstripOrientation == Orientation.Vertical)
+				return;
+			(sender as Gtk.CheckMenuItem).Active = false;
+			photo_view.PlaceFilmstrip (Orientation.Vertical);
+		}
 	
-		//Get this callback twice. Once for the active going menuitem,
-		//once for the inactive leaving one. Ignore the inactive.
-		if (!choice.Active)
-			return;
-
-		int old_size = TagsIconSize;
-		
-		if (choice == tag_icon_hidden) {
-			TagsIconSize = (int) Tag.IconSize.Hidden;
-		} else if (choice == tag_icon_small) {
-			TagsIconSize = (int) Tag.IconSize.Small;
-		} else if (choice == tag_icon_medium) {
-			TagsIconSize = (int) Tag.IconSize.Medium;
-		} else if (choice == tag_icon_large) {
-			TagsIconSize = (int) Tag.IconSize.Large;
-		} else {
-			return;
+		public void HandleReverseOrder (object sender, EventArgs args)
+		{
+			ToggleAction item = sender as ToggleAction;
+	
+			if (group_selector.Adaptor.OrderAscending == item.Active)
+				return;
+			
+			group_selector.Adaptor.OrderAscending = item.Active;
+			query.TimeOrderAsc = item.Active;
+	
+			// FIXME this is blah...we need UIManager love here
+			if (item != reverse_order)
+				reverse_order.Active = item.Active;
+			
+			//update the selection in the timeline
+			if ( query.Range != null && group_selector.Adaptor is TimeAdaptor) {
+				group_selector.SetLimitsToDates(query.Range.Start, query.Range.End);
+				
+			}
+	
+		}
+	
+		// Called when the user clicks the X button	
+		void HandleDeleteEvent (object sender, DeleteEventArgs args)
+		{
+			Close();
+			args.RetVal = true;
+		}
+	
+		void HandleCloseCommand (object sender, EventArgs args)
+		{
+			Close();
 		}
 		
-		if (old_size != TagsIconSize) {
-			tag_selection_widget.ColumnsAutosize();
-			Preferences.Set (Preferences.TAG_ICON_SIZE, TagsIconSize);
+		public void Close ()
+		{
+			int x, y, width, height;
+			main_window.GetPosition (out x, out y);
+			main_window.GetSize (out width, out height);
+	
+			bool maximized = ((main_window.GdkWindow.State & Gdk.WindowState.Maximized) > 0);
+			Preferences.Set (Preferences.MAIN_WINDOW_MAXIMIZED, maximized);
+	
+			if (!maximized) {
+				Preferences.Set (Preferences.MAIN_WINDOW_X,		x);
+				Preferences.Set (Preferences.MAIN_WINDOW_Y,		y);
+				Preferences.Set (Preferences.MAIN_WINDOW_WIDTH,		width);
+				Preferences.Set (Preferences.MAIN_WINDOW_HEIGHT,	height);
+			}
+	
+			Preferences.Set (Preferences.SHOW_TOOLBAR,		toolbar.Visible);
+			Preferences.Set (Preferences.SHOW_SIDEBAR,		info_vbox.Visible);
+			Preferences.Set (Preferences.SHOW_TIMELINE,		display_timeline.Active);
+			Preferences.Set (Preferences.SHOW_FILMSTRIP,		display_filmstrip.Active);
+			Preferences.Set (Preferences.SHOW_TAGS,			icon_view.DisplayTags);
+			Preferences.Set (Preferences.SHOW_DATES,		icon_view.DisplayDates);
+			Preferences.Set (Preferences.SHOW_RATINGS,		icon_view.DisplayRatings);
+	
+			Preferences.Set (Preferences.GLASS_POSITION,		group_selector.GlassPosition);
+			
+			Preferences.Set (Preferences.SIDEBAR_POSITION,		main_hpaned.Position);
+			Preferences.Set (Preferences.ZOOM,			icon_view.Zoom);
+	
+			tag_selection_widget.SaveExpandDefaults ();
+	
+			this.Window.Destroy ();
 		}
-	}
-
-	public void HandleFilmstripHorizontal (object sender, EventArgs args)
-	{
-		if (photo_view.FilmstripOrientation == Orientation.Horizontal)
-			return;
-		(sender as Gtk.CheckMenuItem).Active = false;
-		photo_view.PlaceFilmstrip (Orientation.Horizontal);
-	}
-
-	public void HandleFilmstripVertical (object sender, EventArgs args)
-	{
-		if (photo_view.FilmstripOrientation == Orientation.Vertical)
-			return;
-		(sender as Gtk.CheckMenuItem).Active = false;
-		photo_view.PlaceFilmstrip (Orientation.Vertical);
-	}
-
-	public void HandleReverseOrder (object sender, EventArgs args)
-	{
-		ToggleAction item = sender as ToggleAction;
-
-		if (group_selector.Adaptor.OrderAscending == item.Active)
-			return;
 		
-		group_selector.Adaptor.OrderAscending = item.Active;
-		query.TimeOrderAsc = item.Active;
-
-		// FIXME this is blah...we need UIManager love here
-		if (item != reverse_order)
-			reverse_order.Active = item.Active;
+		void HandleCreateVersionCommand (object obj, EventArgs args)
+		{
+			PhotoVersionCommands.Create cmd = new PhotoVersionCommands.Create ();
+	
+			cmd.Execute (Database.Photos, CurrentPhoto, GetToplevel (null));
+	//		if (cmd.Execute (db.Photos, CurrentPhoto, GetToplevel (null))) {
+	//			query.MarkChanged (ActiveIndex (), true, false);
+	//		}
+		}
+	
+		void HandleDeleteVersionCommand (object obj, EventArgs args)
+		{
+			PhotoVersionCommands.Delete cmd = new PhotoVersionCommands.Delete ();
+	
+			cmd.Execute (Database.Photos, CurrentPhoto, GetToplevel (null));
+	//		if (cmd.Execute (db.Photos, CurrentPhoto, GetToplevel (null))) {
+	//			query.MarkChanged (ActiveIndex (), true, true);
+	//		}
+		}
+	
+		void HandleRenameVersionCommand (object obj, EventArgs args)
+		{
+			PhotoVersionCommands.Rename cmd = new PhotoVersionCommands.Rename ();
+	
+			cmd.Execute (Database.Photos, CurrentPhoto, main_window);
+	//		if (cmd.Execute (db.Photos, CurrentPhoto, main_window)) {
+	//			query.MarkChanged (ActiveIndex (), true, false);
+	//		}
+		}
 		
-		//update the selection in the timeline
-		if ( query.Range != null && group_selector.Adaptor is TimeAdaptor) {
-			group_selector.SetLimitsToDates(query.Range.Start, query.Range.End);
+		public void HandleCreateTagAndAttach (object sender, EventArgs args)
+		{
+			Tag new_tag = CreateTag (sender, args);
+	
+			if (new_tag != null)
+				HandleAttachTagMenuSelected (new_tag);
+		}
+	
+		public void HandleCreateNewCategoryCommand (object sender, EventArgs args)
+		{
+			Tag new_tag = CreateTag (sender, args);
 			
+			if (new_tag != null) {
+				tag_selection_widget.ScrollTo (new_tag);
+				tag_selection_widget.TagHighlight = new Tag [] {new_tag};
+			}
 		}
-
-	}
-
-	// Called when the user clicks the X button	
-	void HandleDeleteEvent (object sender, DeleteEventArgs args)
-	{
-		Close();
-		args.RetVal = true;
-	}
-
-	void HandleCloseCommand (object sender, EventArgs args)
-	{
-		Close();
-	}
 	
-	public void Close ()
-	{
-		int x, y, width, height;
-		main_window.GetPosition (out x, out y);
-		main_window.GetSize (out width, out height);
-
-		bool maximized = ((main_window.GdkWindow.State & Gdk.WindowState.Maximized) > 0);
-		Preferences.Set (Preferences.MAIN_WINDOW_MAXIMIZED, maximized);
-
-		if (!maximized) {
-			Preferences.Set (Preferences.MAIN_WINDOW_X,		x);
-			Preferences.Set (Preferences.MAIN_WINDOW_Y,		y);
-			Preferences.Set (Preferences.MAIN_WINDOW_WIDTH,		width);
-			Preferences.Set (Preferences.MAIN_WINDOW_HEIGHT,	height);
+		public Tag CreateTag (object sender, EventArgs args)
+		{
+			TagCommands.Create command = new TagCommands.Create (Database.Tags, GetToplevel (sender));
+			return command.Execute (TagCommands.TagType.Category, tag_selection_widget.TagHighlight);
 		}
-
-		Preferences.Set (Preferences.SHOW_TOOLBAR,		toolbar.Visible);
-		Preferences.Set (Preferences.SHOW_SIDEBAR,		info_vbox.Visible);
-		Preferences.Set (Preferences.SHOW_TIMELINE,		display_timeline.Active);
-		Preferences.Set (Preferences.SHOW_FILMSTRIP,		display_filmstrip.Active);
-		Preferences.Set (Preferences.SHOW_TAGS,			icon_view.DisplayTags);
-		Preferences.Set (Preferences.SHOW_DATES,		icon_view.DisplayDates);
-		Preferences.Set (Preferences.SHOW_RATINGS,		icon_view.DisplayRatings);
-
-		Preferences.Set (Preferences.GLASS_POSITION,		group_selector.GlassPosition);
-		
-		Preferences.Set (Preferences.SIDEBAR_POSITION,		main_hpaned.Position);
-		Preferences.Set (Preferences.ZOOM,			icon_view.Zoom);
-
-		tag_selection_widget.SaveExpandDefaults ();
-
-		this.Window.Destroy ();
-	}
 	
-	void HandleCreateVersionCommand (object obj, EventArgs args)
-	{
-		PhotoVersionCommands.Create cmd = new PhotoVersionCommands.Create ();
-
-		cmd.Execute (db.Photos, CurrentPhoto, GetToplevel (null));
-//		if (cmd.Execute (db.Photos, CurrentPhoto, GetToplevel (null))) {
-//			query.MarkChanged (ActiveIndex (), true, false);
-//		}
-	}
-
-	void HandleDeleteVersionCommand (object obj, EventArgs args)
-	{
-		PhotoVersionCommands.Delete cmd = new PhotoVersionCommands.Delete ();
-
-		cmd.Execute (db.Photos, CurrentPhoto, GetToplevel (null));
-//		if (cmd.Execute (db.Photos, CurrentPhoto, GetToplevel (null))) {
-//			query.MarkChanged (ActiveIndex (), true, true);
-//		}
-	}
-
-	void HandleRenameVersionCommand (object obj, EventArgs args)
-	{
-		PhotoVersionCommands.Rename cmd = new PhotoVersionCommands.Rename ();
-
-		cmd.Execute (db.Photos, CurrentPhoto, main_window);
-//		if (cmd.Execute (db.Photos, CurrentPhoto, main_window)) {
-//			query.MarkChanged (ActiveIndex (), true, false);
-//		}
-	}
+		public void HandleAttachTagCommand (object obj, EventArgs args)
+		{
+			AttachTags (tag_selection_widget.TagHighlight, SelectedIds ());
+		}
 	
-	public void HandleCreateTagAndAttach (object sender, EventArgs args)
-	{
-		Tag new_tag = CreateTag (sender, args);
-
-		if (new_tag != null)
-			HandleAttachTagMenuSelected (new_tag);
-	}
-
-	public void HandleCreateNewCategoryCommand (object sender, EventArgs args)
-	{
-		Tag new_tag = CreateTag (sender, args);
-		
-		if (new_tag != null) {
-			tag_selection_widget.ScrollTo (new_tag);
-			tag_selection_widget.TagHighlight = new Tag [] {new_tag};
+		void AttachTags (Tag [] tags, int [] ids) 
+		{
+			Database.BeginTransaction ();
+			AddTagExtended (ids, tags);
+			Database.CommitTransaction ();
+			query_widget.PhotoTagsChanged (tags);
 		}
-	}
-
-	public Tag CreateTag (object sender, EventArgs args)
-	{
-		TagCommands.Create command = new TagCommands.Create (db.Tags, GetToplevel (sender));
-		return command.Execute (TagCommands.TagType.Category, tag_selection_widget.TagHighlight);
-	}
-
-	public void HandleAttachTagCommand (object obj, EventArgs args)
-	{
-		AttachTags (tag_selection_widget.TagHighlight, SelectedIds ());
-	}
-
-	void AttachTags (Tag [] tags, int [] ids) 
-	{
-		db.BeginTransaction ();
-		AddTagExtended (ids, tags);
-		db.CommitTransaction ();
-		query_widget.PhotoTagsChanged (tags);
-	}
-
-	public void HandleRemoveTagCommand (object obj, EventArgs args)
-	{
-		Tag [] tags = this.tag_selection_widget.TagHighlight;
-
-		db.BeginTransaction ();
-		RemoveTags (SelectedIds (), tags);
-		db.CommitTransaction ();
-		query_widget.PhotoTagsChanged (tags);
-	}
-
-	public void HandleEditSelectedTag (object sender, EventArgs ea)
-	{
-		Tag [] tags = this.tag_selection_widget.TagHighlight;
-		if (tags.Length != 1)
-			return;
-
-		HandleEditSelectedTagWithTag (tags [0]);
-	}
-
-	public void HandleEditSelectedTagWithTag (Tag tag)
-	{
-		if (tag == null)
-			return;
-		
-		EditTagDialog dialog = new EditTagDialog (db, tag, main_window);
-		if ((ResponseType)dialog.Run () == ResponseType.Ok) {
-			bool name_changed = false;
-			try {
-				if (tag.Name != dialog.TagName) {
-					tag.Name = dialog.TagName;
-					name_changed = true;
+	
+		public void HandleRemoveTagCommand (object obj, EventArgs args)
+		{
+			Tag [] tags = this.tag_selection_widget.TagHighlight;
+	
+			Database.BeginTransaction ();
+			RemoveTags (SelectedIds (), tags);
+			Database.CommitTransaction ();
+			query_widget.PhotoTagsChanged (tags);
+		}
+	
+		public void HandleEditSelectedTag (object sender, EventArgs ea)
+		{
+			Tag [] tags = this.tag_selection_widget.TagHighlight;
+			if (tags.Length != 1)
+				return;
+	
+			HandleEditSelectedTagWithTag (tags [0]);
+		}
+	
+		public void HandleEditSelectedTagWithTag (Tag tag)
+		{
+			if (tag == null)
+				return;
+			
+			EditTagDialog dialog = new EditTagDialog (Database, tag, main_window);
+			if ((ResponseType)dialog.Run () == ResponseType.Ok) {
+				bool name_changed = false;
+				try {
+					if (tag.Name != dialog.TagName) {
+						tag.Name = dialog.TagName;
+						name_changed = true;
+					}
+					tag.Category = dialog.TagCategory;
+					Database.Tags.Commit (tag, name_changed);
+				} catch (Exception ex) {
+					Log.Exception (ex);
 				}
-				tag.Category = dialog.TagCategory;
-				db.Tags.Commit (tag, name_changed);
-			} catch (Exception ex) {
-				Log.Exception (ex);
 			}
+	
+			dialog.Destroy ();
 		}
-
-		dialog.Destroy ();
-	}
-
-	public void HandleMergeTagsCommand (object obj, EventArgs args)
-	{
-		Tag [] tags = this.tag_selection_widget.TagHighlight;
-		if (tags.Length < 2)
-			return;
-		
-		// Translators, The singular case will never happen here.
-		string header = Catalog.GetPluralString ("Merge the selected tag",
-								    "Merge the {0} selected tags?", tags.Length);
-		header = String.Format (header, tags.Length);
-
-		// If a tag with children tags is selected for merging, we
-		// should also merge its children..
-		List<Tag> all_tags = new List<Tag> (tags.Length);
-		foreach (Tag tag in tags) {
-			if (! all_tags.Contains (tag))
-				all_tags.Add (tag);
+	
+		public void HandleMergeTagsCommand (object obj, EventArgs args)
+		{
+			Tag [] tags = this.tag_selection_widget.TagHighlight;
+			if (tags.Length < 2)
+				return;
+			
+			// Translators, The singular case will never happen here.
+			string header = Catalog.GetPluralString ("Merge the selected tag",
+									    "Merge the {0} selected tags?", tags.Length);
+			header = String.Format (header, tags.Length);
+	
+			// If a tag with children tags is selected for merging, we
+			// should also merge its children..
+			List<Tag> all_tags = new List<Tag> (tags.Length);
+			foreach (Tag tag in tags) {
+				if (! all_tags.Contains (tag))
+					all_tags.Add (tag);
+				else
+					continue;
+	
+				if (! (tag is Category))
+					continue;
+	
+				(tag as Category).AddDescendentsTo (all_tags);
+			}
+	
+			// debug..
+			tags = all_tags.ToArray ();
+			System.Array.Sort (tags, new TagRemoveComparer ());
+	
+			foreach (Tag tag in tags) {
+				System.Console.WriteLine ("tag: {0}", tag.Name);
+			}
+	
+			string msg = Catalog.GetString("This operation will merge the selected tags and any sub-tags into a single tag.");
+	
+			string ok_caption = Catalog.GetString ("_Merge Tags");
+			
+			if (ResponseType.Ok != HigMessageDialog.RunHigConfirmation(main_window, 
+										   DialogFlags.DestroyWithParent, 
+										   MessageType.Warning, 
+										   header, 
+										   msg, 
+										   ok_caption))
+				return;
+			
+			// The surviving tag is the last tag, as it is definitely not a child of any other the
+			// other tags.  removetags will contain the tags to be merged.
+			Tag survivor = tags[tags.Length - 1];
+			
+			Tag [] removetags = new Tag [tags.Length - 1];
+			Array.Copy (tags, 0, removetags, 0, tags.Length - 1);
+	
+			// Add the surviving tag to all the photos with the other tags
+			Photo [] photos = Database.Photos.Query (removetags);
+			foreach (Photo p in photos) {
+				p.AddTag (survivor);
+			}
+	
+			// Remove the defunct tags, which removes them from the photos, commits
+			// the photos, and removes the tags from the TagStore
+			Database.BeginTransaction ();
+			Database.Photos.Remove (removetags);
+			Database.CommitTransaction ();
+	
+			HandleEditSelectedTagWithTag (survivor);
+		}
+	
+		void HandleAdjustTime (object sender, EventArgs args)
+		{
+			PhotoList list = new PhotoList (Selection.Items);
+			list.Sort (new Photo.CompareDateName ());
+			(new AdjustTimeDialog (Database, list)).Run ();
+		}
+	
+		public void HideLoupe ()
+		{
+			loupe_menu_item.Active = false;
+		}
+	
+		void HandleLoupe (object sender, EventArgs args)
+		{
+			// Don't steal characters from any text entries
+			if (Window.Focus is Gtk.Entry && Gtk.Global.CurrentEvent is Gdk.EventKey) {
+				Window.Focus.ProcessEvent (Gtk.Global.CurrentEvent);
+				return;
+			}
+			
+			photo_view.View.ShowHideLoupe ();
+		}
+	
+		void HandleSharpen (object sender, EventArgs args)
+		{
+			// Don't steal characters from any text entries
+			if (Window.Focus is Gtk.Entry && Gtk.Global.CurrentEvent is Gdk.EventKey) {
+				Window.Focus.ProcessEvent (Gtk.Global.CurrentEvent);
+				return;
+			}
+			
+			photo_view.View.ShowSharpener ();
+		}
+	
+		void HandleDisplayToolbar (object sender, EventArgs args)
+		{
+			if (display_toolbar.Active)
+				toolbar.Show ();
 			else
-				continue;
-
-			if (! (tag is Category))
-				continue;
-
-			(tag as Category).AddDescendentsTo (all_tags);
+				toolbar.Hide ();
 		}
-
-		// debug..
-		tags = all_tags.ToArray ();
-		System.Array.Sort (tags, new TagRemoveComparer ());
-
-		foreach (Tag tag in tags) {
-			System.Console.WriteLine ("tag: {0}", tag.Name);
+	
+		void HandleDisplayTags (object sender, EventArgs args)
+		{
+			icon_view.DisplayTags = !icon_view.DisplayTags;
 		}
-
-		string msg = Catalog.GetString("This operation will merge the selected tags and any sub-tags into a single tag.");
-
-		string ok_caption = Catalog.GetString ("_Merge Tags");
 		
-		if (ResponseType.Ok != HigMessageDialog.RunHigConfirmation(main_window, 
-									   DialogFlags.DestroyWithParent, 
-									   MessageType.Warning, 
-									   header, 
-									   msg, 
-									   ok_caption))
-			return;
-		
-		// The surviving tag is the last tag, as it is definitely not a child of any other the
-		// other tags.  removetags will contain the tags to be merged.
-		Tag survivor = tags[tags.Length - 1];
-		
-		Tag [] removetags = new Tag [tags.Length - 1];
-		Array.Copy (tags, 0, removetags, 0, tags.Length - 1);
-
-		// Add the surviving tag to all the photos with the other tags
-		Photo [] photos = db.Photos.Query (removetags);
-		foreach (Photo p in photos) {
-			p.AddTag (survivor);
+		void HandleDisplayDates (object sender, EventArgs args)
+		{
+			// Peg the icon_view's value to the MenuItem's active state,
+			// as icon_view.DisplayDates's get won't always be equal to it's true value
+			// because of logic to hide dates when zoomed way out.
+			icon_view.DisplayDates = display_dates_menu_item.Active;
 		}
-
-		// Remove the defunct tags, which removes them from the photos, commits
-		// the photos, and removes the tags from the TagStore
-		db.BeginTransaction ();
-		db.Photos.Remove (removetags);
-		db.CommitTransaction ();
-
-		HandleEditSelectedTagWithTag (survivor);
-	}
-
-	void HandleAdjustTime (object sender, EventArgs args)
-	{
-		PhotoList list = new PhotoList (Selection.Items);
-		list.Sort (new Photo.CompareDateName ());
-		(new AdjustTimeDialog (db, list)).Run ();
-	}
-
-	public void HideLoupe ()
-	{
-		loupe_menu_item.Active = false;
-	}
-
-	void HandleLoupe (object sender, EventArgs args)
-	{
-		// Don't steal characters from any text entries
-		if (Window.Focus is Gtk.Entry && Gtk.Global.CurrentEvent is Gdk.EventKey) {
-			Window.Focus.ProcessEvent (Gtk.Global.CurrentEvent);
-			return;
+	
+		void HandleDisplayRatings (object sender, EventArgs args)
+		{
+			icon_view.DisplayRatings = display_ratings_menu_item.Active;
 		}
-		
-		photo_view.View.ShowHideLoupe ();
-	}
-
-	void HandleSharpen (object sender, EventArgs args)
-	{
-		// Don't steal characters from any text entries
-		if (Window.Focus is Gtk.Entry && Gtk.Global.CurrentEvent is Gdk.EventKey) {
-			Window.Focus.ProcessEvent (Gtk.Global.CurrentEvent);
-			return;
+	
+		void HandleDisplayGroupSelector (object sender, EventArgs args)
+		{
+			if (group_selector.Visible)
+				group_selector.Hide ();
+			else
+				group_selector.Show ();
 		}
-		
-		photo_view.View.ShowSharpener ();
-	}
-
-	void HandleDisplayToolbar (object sender, EventArgs args)
-	{
-		if (display_toolbar.Active)
-			toolbar.Show ();
-		else
-			toolbar.Hide ();
-	}
-
-	void HandleDisplayTags (object sender, EventArgs args)
-	{
-		icon_view.DisplayTags = !icon_view.DisplayTags;
-	}
 	
-	void HandleDisplayDates (object sender, EventArgs args)
-	{
-		// Peg the icon_view's value to the MenuItem's active state,
-		// as icon_view.DisplayDates's get won't always be equal to it's true value
-		// because of logic to hide dates when zoomed way out.
-		icon_view.DisplayDates = display_dates_menu_item.Active;
-	}
-
-	void HandleDisplayRatings (object sender, EventArgs args)
-	{
-		icon_view.DisplayRatings = display_ratings_menu_item.Active;
-	}
-
-	void HandleDisplayGroupSelector (object sender, EventArgs args)
-	{
-		if (group_selector.Visible)
-			group_selector.Hide ();
-		else
-			group_selector.Show ();
-	}
-
-	void HandleDisplayFilmstrip (object sender, EventArgs args)
-	{
-		photo_view.FilmStripVisibility = display_filmstrip.Active;
-		if (view_mode == ModeType.PhotoView)
-			photo_view.QueueDraw ();
-	}
-
-	void HandleDisplayInfoSidebar (object sender, EventArgs args)
-	{
-		if (info_vbox.Visible)
-			info_vbox.Hide ();
-		else
-			info_vbox.Show ();
-	}
-
-	void HandleViewSlideShow (object sender, EventArgs args)
-	{
-		HandleViewFullscreen (sender, args);
-		fsview.PlayPause ();
-	}
-
-	void HandleToggleViewBrowse (object sender, EventArgs args)
-	{
-		if (view_mode == ModeType.IconView)
-			browse_button.Active = true;
-		else if (browse_button.Active)
-			SetViewMode (ModeType.IconView);
-	}
-
-	void HandleToggleViewPhoto (object sender, EventArgs args)
-	{
-		if (view_mode == ModeType.PhotoView)
-			edit_button.Active = true;
-		else if (edit_button.Active)
-			SetViewMode (ModeType.PhotoView);
-	}
-
-	void HandleViewBrowse (object sender, EventArgs args)
-	{
-		SetViewMode (ModeType.IconView);
-	}
-
-	void HandleViewPhoto (object sender, EventArgs args)
-	{
-		SetViewMode (ModeType.PhotoView);
-	}
-
-	void HandleViewFullscreen (object sender, EventArgs args)
-	{
-		int active = (selection.Count > 0 ? SelectedIds() [0] : 0);
-		if (fsview == null) {
-			fsview = new FSpot.FullScreenView (query, main_window);
-			fsview.Destroyed += HandleFullScreenViewDestroy;
-			fsview.KeyPressEvent += HandleFullScreenViewKeyPressEvent;
-			fsview.View.Item.Index = active;
-		} else {
-			// FIXME this needs to be another mode like PhotoView and IconView mode.
-			fsview.View.Item.Index = active;
+		void HandleDisplayFilmstrip (object sender, EventArgs args)
+		{
+			photo_view.FilmStripVisibility = display_filmstrip.Active;
+			if (ViewMode == ModeType.PhotoView)
+				photo_view.QueueDraw ();
 		}
-		
-		fsview.Show ();
-	}
-
-	void HandleFullScreenViewDestroy (object sender, EventArgs args)
-	{
-		JumpTo (fsview.View.Item.Index);
-		fsview = null;
-	}
 	
-	void HandleZoomScaleValueChanged (object sender, System.EventArgs args)
-	{
-		switch (view_mode) {
-		case ModeType.PhotoView:
-			photo_view.View.ZoomChanged -= HandleZoomChanged;
-			photo_view.NormalizedZoom = zoom_scale.Value;
-			photo_view.View.ZoomChanged += HandleZoomChanged;
-			break;
-		case ModeType.IconView:
-			icon_view.ZoomChanged -= HandleZoomChanged;
-			icon_view.Zoom = zoom_scale.Value;
-			icon_view.ZoomChanged += HandleZoomChanged;
-			break;
+		void HandleDisplayInfoSidebar (object sender, EventArgs args)
+		{
+			if (info_vbox.Visible)
+				info_vbox.Hide ();
+			else
+				info_vbox.Show ();
 		}
-		
-		zoom_in.Sensitive = (zoom_scale.Value != 1.0);
-		zoom_out.Sensitive = (zoom_scale.Value != 0.0);
-	}
 	
-	void HandleQueryChanged (IBrowsableCollection sender)
-	{
-		if (find_untagged.Active != query.Untagged)
-			find_untagged.Active = query.Untagged;
-		
-		clear_date_range.Sensitive = (query.Range != null);
-		clear_rating_filter.Sensitive = (query.RatingRange != null);
-		update_status_label = true;
-		GLib.Idle.Add (UpdateStatusLabel);
-	}
-
-	bool update_status_label;
-	private bool UpdateStatusLabel ()
-	{
-		update_status_label = false;
-		int total_photos = Database.Photos.TotalPhotos;
-		if (total_photos != query.Count)
-			status_label.Text = String.Format (Catalog.GetPluralString ("{0} Photo out of {1}", "{0} Photos out of {1}", query.Count), query.Count, total_photos);
-		else
-			status_label.Text = String.Format (Catalog.GetPluralString ("{0} Photo", "{0} Photos", query.Count), query.Count);
-	
-		if ((selection != null) && (selection.Count > 0))
-			status_label.Text += String.Format (Catalog.GetPluralString (" ({0} selected)", " ({0} selected)", selection.Count), selection.Count);
-		status_label.UseMarkup = true;
-		return update_status_label;
-	}
+		void HandleViewSlideShow (object sender, EventArgs args)
+		{
+			HandleViewFullscreen (sender, args);
+			fsview.PlayPause ();
+		}
 	
-	void HandleZoomChanged (object sender, System.EventArgs args)
-	{
-		zoom_scale.ValueChanged -= HandleZoomScaleValueChanged;
-
-		double zoom = .5;
-		switch (view_mode) {
-		case ModeType.PhotoView:
-			zoom = photo_view.NormalizedZoom;
-			zoom_scale.Value = zoom;
-			break;
-		case ModeType.IconView:
-			zoom = icon_view.Zoom;
-			if (zoom == 0.0 || zoom == 100.0 || zoom != zoom_scale.Value)
-				zoom_scale.Value = zoom;
-
-			break;
+		void HandleToggleViewBrowse (object sender, EventArgs args)
+		{
+			if (ViewMode == ModeType.IconView)
+				browse_button.Active = true;
+			else if (browse_button.Active)
+				SetViewMode (ModeType.IconView);
 		}
-		
-		zoom_in.Sensitive = (zoom != 1.0);
-		zoom_out.Sensitive = (zoom != 0.0);
-		
-		zoom_scale.ValueChanged += HandleZoomScaleValueChanged;
-	}
-
-	void HandleZoomOut (object sender, ButtonPressEventArgs args)
-	{
-		ZoomOut ();
-	}
 	
-	void HandleZoomOut (object sender, EventArgs args)
-	{
-		ZoomOut ();
-	}
+		void HandleToggleViewPhoto (object sender, EventArgs args)
+		{
+			if (ViewMode == ModeType.PhotoView)
+				edit_button.Active = true;
+			else if (edit_button.Active)
+				SetViewMode (ModeType.PhotoView);
+		}
 	
-	void HandleZoomIn (object sender, ButtonPressEventArgs args)
-	{
-		ZoomIn ();
-	}
+		void HandleViewBrowse (object sender, EventArgs args)
+		{
+			SetViewMode (ModeType.IconView);
+		}
 	
-	void HandleZoomIn (object sender, EventArgs args)
-	{
-		ZoomIn ();
-	}
+		void HandleViewPhoto (object sender, EventArgs args)
+		{
+			SetViewMode (ModeType.PhotoView);
+		}
 	
-	private void ZoomOut ()
-	{
-		switch (view_mode) {
-		case ModeType.PhotoView:
-			photo_view.ZoomOut ();
-			break;
-		case ModeType.IconView:
-			icon_view.ZoomOut ();
-			break;
+		void HandleViewFullscreen (object sender, EventArgs args)
+		{
+			int active = (Selection.Count > 0 ? SelectedIds() [0] : 0);
+			if (fsview == null) {
+				fsview = new FSpot.FullScreenView (query, main_window);
+				fsview.Destroyed += HandleFullScreenViewDestroy;
+				fsview.KeyPressEvent += HandleFullScreenViewKeyPressEvent;
+				fsview.View.Item.Index = active;
+			} else {
+				// FIXME this needs to be another mode like PhotoView and IconView mode.
+				fsview.View.Item.Index = active;
+			}
+			
+			fsview.Show ();
 		}
-	}
 	
-	private void ZoomIn ()
-	{
-		switch (view_mode) {
-		case ModeType.PhotoView:
-			double old_zoom = photo_view.Zoom;
-			try {
-				photo_view.ZoomIn ();
-			} catch {
-				photo_view.Zoom = old_zoom;
+		void HandleFullScreenViewDestroy (object sender, EventArgs args)
+		{
+			JumpTo (fsview.View.Item.Index);
+			fsview = null;
+		}
+		
+		void HandleZoomScaleValueChanged (object sender, System.EventArgs args)
+		{
+			switch (ViewMode) {
+			case ModeType.PhotoView:
+				photo_view.View.ZoomChanged -= HandleZoomChanged;
+				photo_view.NormalizedZoom = zoom_scale.Value;
+				photo_view.View.ZoomChanged += HandleZoomChanged;
+				break;
+			case ModeType.IconView:
+				icon_view.ZoomChanged -= HandleZoomChanged;
+				icon_view.Zoom = zoom_scale.Value;
+				icon_view.ZoomChanged += HandleZoomChanged;
+				break;
 			}
 			
-			break;
-		case ModeType.IconView:
-			icon_view.ZoomIn ();
-			break;
+			zoom_in.Sensitive = (zoom_scale.Value != 1.0);
+			zoom_out.Sensitive = (zoom_scale.Value != 0.0);
 		}
-	}
-
-	public void DeleteException (Exception e, string fname)
-	{
-		string ok_caption = Catalog.GetString ("_Ok");
-		string error = Catalog.GetString ("Error Deleting Picture");
-		string msg;
-
-		if (e is UnauthorizedAccessException)
-			msg = String.Format (
-				Catalog.GetString ("No permission to delete the file:{1}{0}"), 
-				fname, Environment.NewLine).Replace ("_", "__");
-		else
-			msg = String.Format (
-				Catalog.GetString ("An error of type {0} occurred while deleting the file:{2}{1}"),
-				e.GetType (), fname.Replace ("_", "__"), Environment.NewLine);
 		
-		HigMessageDialog.RunHigConfirmation (
-			main_window, DialogFlags.DestroyWithParent, MessageType.Error,
-			error, msg, ok_caption);
-	}
-
-	public Gtk.Window GetToplevel (object sender)
-	{
-		Widget wsender = sender as Widget;
-		Gtk.Window toplevel = null;
-
-		if (wsender != null && !(wsender is MenuItem))
-			toplevel = (Gtk.Window) wsender.Toplevel;
-		else if (fsview != null)
-			toplevel = fsview;
-		else 
-			toplevel = main_window;
-
-		return toplevel;
-	}
-
-	public void HandleDeleteCommand (object sender, EventArgs args)
-	{
-		// Don't steal characters from any text entries
-		if (Window.Focus is Gtk.Entry && Gtk.Global.CurrentEvent is Gdk.EventKey) {
-			Window.Focus.ProcessEvent (Gtk.Global.CurrentEvent);
-			return;
+		void HandleQueryChanged (IBrowsableCollection sender)
+		{
+			if (find_untagged.Active != query.Untagged)
+				find_untagged.Active = query.Untagged;
+			
+			clear_date_range.Sensitive = (query.Range != null);
+			clear_rating_filter.Sensitive = (query.RatingRange != null);
+			update_status_label = true;
+			GLib.Idle.Add (UpdateStatusLabel);
 		}
+	
+		bool update_status_label;
+		private bool UpdateStatusLabel ()
+		{
+			update_status_label = false;
+			int total_photos = Database.Photos.TotalPhotos;
+			if (total_photos != query.Count)
+				status_label.Text = String.Format (Catalog.GetPluralString ("{0} Photo out of {1}", "{0} Photos out of {1}", query.Count), query.Count, total_photos);
+			else
+				status_label.Text = String.Format (Catalog.GetPluralString ("{0} Photo", "{0} Photos", query.Count), query.Count);
 		
-   		Photo[] photos = SelectedPhotos();
-   		string header = Catalog.GetPluralString ("Delete the selected photo permanently?", 
-								    "Delete the {0} selected photos permanently?", 
-								    photos.Length);
-		header = String.Format (header, photos.Length);
-		string msg = Catalog.GetPluralString ("This deletes all versions of the selected photo from your drive.", 
-								 "This deletes all versions of the selected photos from your drive.", 
-								 photos.Length);
-		string ok_caption = Catalog.GetPluralString ("_Delete photo", "_Delete photos", photos.Length);
+			if ((Selection != null) && (Selection.Count > 0))
+				status_label.Text += String.Format (Catalog.GetPluralString (" ({0} selected)", " ({0} selected)", Selection.Count), Selection.Count);
+			status_label.UseMarkup = true;
+			return update_status_label;
+		}
 		
-		if (ResponseType.Ok == HigMessageDialog.RunHigConfirmation(GetToplevel (sender), 
-									   DialogFlags.DestroyWithParent, 
-									   MessageType.Warning, 
-									   header, msg, ok_caption)) {                              
-			
-			uint timer = Log.DebugTimerStart ();
-			foreach (Photo photo in photos) {
-				foreach (uint id in photo.VersionIds) {
-					try {
-						photo.DeleteVersion (id, true);
-					} catch (Exception e) {
-						DeleteException (e, photo.VersionUri (id).ToString ());
-					}
-				}
+		void HandleZoomChanged (object sender, System.EventArgs args)
+		{
+			zoom_scale.ValueChanged -= HandleZoomScaleValueChanged;
+	
+			double zoom = .5;
+			switch (ViewMode) {
+			case ModeType.PhotoView:
+				zoom = photo_view.NormalizedZoom;
+				zoom_scale.Value = zoom;
+				break;
+			case ModeType.IconView:
+				zoom = icon_view.Zoom;
+				if (zoom == 0.0 || zoom == 100.0 || zoom != zoom_scale.Value)
+					zoom_scale.Value = zoom;
+	
+				break;
 			}
-			db.Photos.Remove (photos);
 			
-			UpdateQuery ();
-			Log.DebugTimerPrint (timer, "HandleDeleteCommand took {0}");
+			zoom_in.Sensitive = (zoom != 1.0);
+			zoom_out.Sensitive = (zoom != 0.0);
+			
+			zoom_scale.ValueChanged += HandleZoomScaleValueChanged;
 		}
-	}
-
-	public void HandleRemoveCommand (object sender, EventArgs args)
-	{
-		// Don't steal characters from any text entries
-		if (Window.Focus is Gtk.Entry && Gtk.Global.CurrentEvent is Gdk.EventKey) {
-			Window.Focus.ProcessEvent (Gtk.Global.CurrentEvent);
-			return;
+	
+		void HandleZoomOut (object sender, ButtonPressEventArgs args)
+		{
+			ZoomOut ();
 		}
-
-   		Photo[] photos = SelectedPhotos();
-		if (photos.Length == 0) 
-			return;
-
-   		string header = Catalog.GetPluralString ("Remove the selected photo from F-Spot?",
-								    "Remove the {0} selected photos from F-Spot?", 
-								    photos.Length);
-
-		header = String.Format (header, photos.Length);
-		string msg = Catalog.GetString("If you remove photos from the F-Spot catalog all tag information will be lost. The photos remain on your computer and can be imported into F-Spot again.");
-		string ok_caption = Catalog.GetString("_Remove from Catalog");
-		if (ResponseType.Ok == HigMessageDialog.RunHigConfirmation(GetToplevel (sender), DialogFlags.DestroyWithParent, 
-									   MessageType.Warning, header, msg, ok_caption)) {                              
-			db.Photos.Remove (photos);
-			UpdateQuery ();
+		
+		void HandleZoomOut (object sender, EventArgs args)
+		{
+			ZoomOut ();
 		}
-	}
-
-	void HandleSelectAllCommand (object sender, EventArgs args)
-	{
-		icon_view.SelectAllCells ();
-		UpdateStatusLabel();
-	}
-
-	void HandleSelectNoneCommand (object sender, EventArgs args)
-	{
-		icon_view.Selection.Clear ();
-		UpdateStatusLabel();
-	}
-
-	// This ConnectBefore is needed because otherwise the editability of the name
-	// column will steal returns, spaces, and clicks if the tag name is focused
-	[GLib.ConnectBefore]
-	public void HandleTagSelectionKeyPress (object sender, Gtk.KeyPressEventArgs args)
-	{
-		args.RetVal = true;
-
-		switch (args.Event.Key) {
-		case Gdk.Key.Delete:
- 			HandleDeleteSelectedTagCommand (sender, (EventArgs) args);
-			break;
 		
-		case Gdk.Key.space:
-		case Gdk.Key.Return:
-		case Gdk.Key.KP_Enter:
-			ShowQueryWidget ();
-			query_widget.Include (tag_selection_widget.TagHighlight);
-			break;
-
-		case Gdk.Key.F2:
-			tag_selection_widget.EditSelectedTagName ();
-			break;
+		void HandleZoomIn (object sender, ButtonPressEventArgs args)
+		{
+			ZoomIn ();
+		}
 		
-		default:
-			args.RetVal = false;
-			break;
+		void HandleZoomIn (object sender, EventArgs args)
+		{
+			ZoomIn ();
 		}
-	}
-
-	public void HandleDeleteSelectedTagCommand (object sender, EventArgs args)
-	{
-		Tag [] tags = this.tag_selection_widget.TagHighlight;
-
-		System.Array.Sort (tags, new TagRemoveComparer ());
-	
-		//How many pictures are associated to these tags?
-		Db db = MainWindow.Toplevel.Database;
-		FSpot.PhotoQuery count_query = new FSpot.PhotoQuery(db.Photos);
-		count_query.Terms = FSpot.OrTerm.FromTags(tags);
-		int associated_photos = count_query.Count;
-
-		string header;
-		if (tags.Length == 1)
-			header = String.Format (Catalog.GetString ("Delete tag \"{0}\"?"), tags [0].Name.Replace ("_", "__"));
-		else
-			header = String.Format (Catalog.GetString ("Delete the {0} selected tags?"), tags.Length);
 		
-		header = String.Format (header, tags.Length);
-		string msg = String.Empty;
-		if (associated_photos > 0) {
-			string photodesc = Catalog.GetPluralString ("photo", "photos", associated_photos);
-			msg = String.Format( 
-				Catalog.GetPluralString("If you delete this tag, the association with {0} {1} will be lost.",
-							"If you delete these tags, the association with {0} {1} will be lost.",
-							tags.Length),
-				associated_photos, photodesc);
-		}
-		string ok_caption = Catalog.GetPluralString ("_Delete tag", "_Delete tags", tags.Length);
+		private void ZoomOut ()
+		{
+			switch (ViewMode) {
+			case ModeType.PhotoView:
+				photo_view.ZoomOut ();
+				break;
+			case ModeType.IconView:
+				icon_view.ZoomOut ();
+				break;
+			}
+		}
 		
-		if (ResponseType.Ok == HigMessageDialog.RunHigConfirmation(main_window, 
-									   DialogFlags.DestroyWithParent, 
-									   MessageType.Warning, 
-									   header, 
-									   msg, 
-									   ok_caption)) {                              
-			try { 				
-				db.Photos.Remove (tags);
-			} catch (InvalidTagOperationException e) {
-				System.Console.WriteLine ("this is something or another");
-
-				// A Category is not empty. Can not delete it.
-				string error_msg = Catalog.GetString ("Tag is not empty");
-				string error_desc = String.Format (Catalog.GetString ("Can not delete tags that have tags within them.  " + 
-												 "Please delete tags under \"{0}\" first"),
-								   e.Tag.Name.Replace ("_", "__"));
+		private void ZoomIn ()
+		{
+			switch (ViewMode) {
+			case ModeType.PhotoView:
+				double old_zoom = photo_view.Zoom;
+				try {
+					photo_view.ZoomIn ();
+				} catch {
+					photo_view.Zoom = old_zoom;
+				}
 				
-				HigMessageDialog md = new HigMessageDialog (main_window, DialogFlags.DestroyWithParent, 
-									    Gtk.MessageType.Error, ButtonsType.Ok, 
-									    error_msg,
-									    error_desc);
-				md.Run ();
-				md.Destroy ();
+				break;
+			case ModeType.IconView:
+				icon_view.ZoomIn ();
+				break;
 			}
 		}
-	}
-
-	void HandleUpdateThumbnailCommand (object sender, EventArgs args)
-	{
-		ThumbnailCommand command = new ThumbnailCommand (main_window);
-
-		int [] selected_ids = SelectedIds ();
-		if (command.Execute (SelectedPhotos (selected_ids)))
-			query.MarkChanged (selected_ids, new PhotoChanges {DataChanged = true});
-	}
-
-	public void HandleRotate90Command (object sender, EventArgs args)
-	{
-		// Don't steal characters from any text entries
-		if (Window.Focus is Gtk.Entry && Gtk.Global.CurrentEvent is Gdk.EventKey) {
-			Window.Focus.ProcessEvent (Gtk.Global.CurrentEvent);
-			return;
+	
+		public void DeleteException (Exception e, string fname)
+		{
+			string ok_caption = Catalog.GetString ("_Ok");
+			string error = Catalog.GetString ("Error Deleting Picture");
+			string msg;
+	
+			if (e is UnauthorizedAccessException)
+				msg = String.Format (
+					Catalog.GetString ("No permission to delete the file:{1}{0}"), 
+					fname, Environment.NewLine).Replace ("_", "__");
+			else
+				msg = String.Format (
+					Catalog.GetString ("An error of type {0} occurred while deleting the file:{2}{1}"),
+					e.GetType (), fname.Replace ("_", "__"), Environment.NewLine);
+			
+			HigMessageDialog.RunHigConfirmation (
+				main_window, DialogFlags.DestroyWithParent, MessageType.Error,
+				error, msg, ok_caption);
 		}
-		
-		RotateSelectedPictures (GetToplevel (sender), RotateDirection.Clockwise);
-	}
-
-	public void HandleRotate270Command (object sender, EventArgs args)
-	{
-		// Don't steal characters from any text entries
-		if (Window.Focus is Gtk.Entry && Gtk.Global.CurrentEvent is Gdk.EventKey) {
-			Window.Focus.ProcessEvent (Gtk.Global.CurrentEvent);
-			return;
+	
+		public Gtk.Window GetToplevel (object sender)
+		{
+			Widget wsender = sender as Widget;
+			Gtk.Window toplevel = null;
+	
+			if (wsender != null && !(wsender is MenuItem))
+				toplevel = (Gtk.Window) wsender.Toplevel;
+			else if (fsview != null)
+				toplevel = fsview;
+			else 
+				toplevel = main_window;
+	
+			return toplevel;
 		}
-
-		RotateSelectedPictures (GetToplevel (sender), RotateDirection.Counterclockwise);
-	}
-
-	public void HandleCopyLocation (object sender, EventArgs args)
-	{
-		/*
-		 * FIXME this should really set uri atoms as well as string atoms
-		 */
-		Clipboard primary = Clipboard.Get (Atom.Intern ("PRIMARY", false));
-		Clipboard clipboard = Clipboard.Get (Atom.Intern ("CLIPBOARD", false));
-
-		StringBuilder paths = new StringBuilder ();
-		
-		int i = 0;
-		foreach (Photo p in SelectedPhotos ()) {
-			if (i++ > 0)
-				paths.Append (" ");
-
-			paths.Append (System.IO.Path.GetFullPath (p.DefaultVersionUri.LocalPath));
+	
+		public void HandleDeleteCommand (object sender, EventArgs args)
+		{
+			// Don't steal characters from any text entries
+			if (Window.Focus is Gtk.Entry && Gtk.Global.CurrentEvent is Gdk.EventKey) {
+				Window.Focus.ProcessEvent (Gtk.Global.CurrentEvent);
+				return;
+			}
+			
+	   		Photo[] photos = SelectedPhotos();
+	   		string header = Catalog.GetPluralString ("Delete the selected photo permanently?", 
+									    "Delete the {0} selected photos permanently?", 
+									    photos.Length);
+			header = String.Format (header, photos.Length);
+			string msg = Catalog.GetPluralString ("This deletes all versions of the selected photo from your drive.", 
+									 "This deletes all versions of the selected photos from your drive.", 
+									 photos.Length);
+			string ok_caption = Catalog.GetPluralString ("_Delete photo", "_Delete photos", photos.Length);
+			
+			if (ResponseType.Ok == HigMessageDialog.RunHigConfirmation(GetToplevel (sender), 
+										   DialogFlags.DestroyWithParent, 
+										   MessageType.Warning, 
+										   header, msg, ok_caption)) {                              
+				
+				uint timer = Log.DebugTimerStart ();
+				foreach (Photo photo in photos) {
+					foreach (uint id in photo.VersionIds) {
+						try {
+							photo.DeleteVersion (id, true);
+						} catch (Exception e) {
+							DeleteException (e, photo.VersionUri (id).ToString ());
+						}
+					}
+				}
+				Database.Photos.Remove (photos);
+				
+				UpdateQuery ();
+				Log.DebugTimerPrint (timer, "HandleDeleteCommand took {0}");
+			}
 		}
-		
-		String data = paths.ToString ();
-		primary.Text = data;
-		clipboard.Text = data;
-	}
-
-	void HandleSetAsBackgroundCommand (object sender, EventArgs args)
-	{
-		Photo current = CurrentPhoto;
-
-		if (current == null)
-			return;
-
-		Desktop.SetBackgroundImage (current.DefaultVersionUri.LocalPath);
-	}
-
-	void HandleSetDateRange (object sender, EventArgs args) {
-		var date_range_dialog = new DateRangeDialog (query.Range, main_window);
-		if ((ResponseType)date_range_dialog.Run () == ResponseType.Ok)
-			query.Range = date_range_dialog.Range;
-		date_range_dialog.Destroy ();
-
-		//update the TimeLine
-		if (group_selector.Adaptor is TimeAdaptor && query.Range != null) 
-			group_selector.SetLimitsToDates(query.Range.Start, query.Range.End);
-	}
-
-	public void HandleClearDateRange (object sender, EventArgs args) {
-		if (group_selector.Adaptor is FSpot.TimeAdaptor) {
-			group_selector.ResetLimits();
+	
+		public void HandleRemoveCommand (object sender, EventArgs args)
+		{
+			// Don't steal characters from any text entries
+			if (Window.Focus is Gtk.Entry && Gtk.Global.CurrentEvent is Gdk.EventKey) {
+				Window.Focus.ProcessEvent (Gtk.Global.CurrentEvent);
+				return;
+			}
+	
+	   		Photo[] photos = SelectedPhotos();
+			if (photos.Length == 0) 
+				return;
+	
+	   		string header = Catalog.GetPluralString ("Remove the selected photo from F-Spot?",
+									    "Remove the {0} selected photos from F-Spot?", 
+									    photos.Length);
+	
+			header = String.Format (header, photos.Length);
+			string msg = Catalog.GetString("If you remove photos from the F-Spot catalog all tag information will be lost. The photos remain on your computer and can be imported into F-Spot again.");
+			string ok_caption = Catalog.GetString("_Remove from Catalog");
+			if (ResponseType.Ok == HigMessageDialog.RunHigConfirmation(GetToplevel (sender), DialogFlags.DestroyWithParent, 
+										   MessageType.Warning, header, msg, ok_caption)) {                              
+				Database.Photos.Remove (photos);
+				UpdateQuery ();
+			}
 		}
-		query.Range = null;
-	}
-
-	void HandleSelectLastRoll (object sender, EventArgs args) {
-		query.RollSet = new RollSet (db.Rolls.GetRolls (1));
-	}
-
-	void HandleSelectRolls (object sender, EventArgs args) {
-		new LastRolls (query, db.Rolls, main_window);
-	}
-
-	void HandleClearRollFilter (object sender, EventArgs args) {
-		query.RollSet = null;
-	}
-
-	void HandleSetRatingFilter (object sender, EventArgs args) {
-		new RatingFilterDialog (query, main_window);
-	}
-
-	public void HandleClearRatingFilter (object sender, EventArgs args) {
-		query.RatingRange = null;
-	}
-
-	void HandleFindUntagged (object sender, EventArgs args) {
-		if (query.Untagged == find_untagged.Active)
-			return;
-
-		query.Untagged = !query.Untagged;
-	}
 	
-	void OnPreferencesChanged (object sender, NotifyEventArgs args)
-	{
-		LoadPreference (args.Key);
-	}
-
-	void LoadPreference (String key)
-	{
-		switch (key) {
-		case Preferences.MAIN_WINDOW_MAXIMIZED:
-			if (Preferences.Get<bool> (key))
-				main_window.Maximize ();
-			else
-				main_window.Unmaximize ();
-			break;
-
-		case Preferences.MAIN_WINDOW_X:
-		case Preferences.MAIN_WINDOW_Y:
-			main_window.Move(Preferences.Get<int> (Preferences.MAIN_WINDOW_X),
-					 Preferences.Get<int> (Preferences.MAIN_WINDOW_Y));
-			break;
-		
-		case Preferences.MAIN_WINDOW_WIDTH:
-		case Preferences.MAIN_WINDOW_HEIGHT:
-			if (Preferences.Get<int> (Preferences.MAIN_WINDOW_WIDTH) > 0 &&
-						  Preferences.Get<int> (Preferences.MAIN_WINDOW_HEIGHT) > 0)
-				main_window.Resize(Preferences.Get<int> (Preferences.MAIN_WINDOW_WIDTH),
-						   Preferences.Get<int> (Preferences.MAIN_WINDOW_HEIGHT));
-
-			break;
-		
-		case Preferences.SHOW_TOOLBAR:
-			if (display_toolbar.Active != Preferences.Get<bool> (key))
-				display_toolbar.Active = Preferences.Get<bool> (key);
-			break;
-		
-		case Preferences.SHOW_SIDEBAR:
-			if (display_sidebar.Active != Preferences.Get<bool> (key))
-				display_sidebar.Active = Preferences.Get<bool> (key);
-			break;
-		
-		case Preferences.SHOW_TIMELINE:
-			if (display_timeline.Active != Preferences.Get<bool> (key))
-				display_timeline.Active = Preferences.Get<bool> (key);
-			break;
-		
-		case Preferences.SHOW_FILMSTRIP:
-			if (display_filmstrip.Active != Preferences.Get<bool> (key)) {
-				display_filmstrip.Active = Preferences.Get<bool> (key);
+		void HandleSelectAllCommand (object sender, EventArgs args)
+		{
+			icon_view.SelectAllCells ();
+			UpdateStatusLabel();
+		}
+	
+		void HandleSelectNoneCommand (object sender, EventArgs args)
+		{
+			icon_view.Selection.Clear ();
+			UpdateStatusLabel();
+		}
+	
+		// This ConnectBefore is needed because otherwise the editability of the name
+		// column will steal returns, spaces, and clicks if the tag name is focused
+		[GLib.ConnectBefore]
+		public void HandleTagSelectionKeyPress (object sender, Gtk.KeyPressEventArgs args)
+		{
+			args.RetVal = true;
+	
+			switch (args.Event.Key) {
+			case Gdk.Key.Delete:
+	 			HandleDeleteSelectedTagCommand (sender, (EventArgs) args);
+				break;
+			
+			case Gdk.Key.space:
+			case Gdk.Key.Return:
+			case Gdk.Key.KP_Enter:
+				ShowQueryWidget ();
+				query_widget.Include (tag_selection_widget.TagHighlight);
+				break;
+	
+			case Gdk.Key.F2:
+				tag_selection_widget.EditSelectedTagName ();
+				break;
+			
+			default:
+				args.RetVal = false;
+				break;
 			}
-			break;
-		
-		case Preferences.SHOW_TAGS:
-			if (display_tags_menu_item.Active != Preferences.Get<bool> (key))
-				display_tags_menu_item.Active = Preferences.Get<bool> (key);
-			break;
-		
-		case Preferences.SHOW_DATES:
-			if (display_dates_menu_item.Active != Preferences.Get<bool> (key))
-				display_dates_menu_item.Active = Preferences.Get<bool> (key);
-				//display_dates_menu_item.Toggle ();
-			break;
+		}
+	
+		public void HandleDeleteSelectedTagCommand (object sender, EventArgs args)
+		{
+			Tag [] tags = this.tag_selection_widget.TagHighlight;
+	
+			System.Array.Sort (tags, new TagRemoveComparer ());
 		
-		case Preferences.SHOW_RATINGS:
-			if (display_ratings_menu_item.Active != Preferences.Get<bool> (key))
-				display_ratings_menu_item.Active = Preferences.Get<bool> (key);
-			break;
-
-		case Preferences.GROUP_ADAPTOR_ORDER_ASC:
-			group_selector.Adaptor.OrderAscending = Preferences.Get<bool> (key);
-			reverse_order.Active = Preferences.Get<bool> (key);
-			query.TimeOrderAsc = group_selector.Adaptor.OrderAscending;
-			break;
-
-		case Preferences.GLASS_POSITION:
-			if (query.Count > 0) {
-				// If the database has changed since this pref was saved, this could cause
-				// an exception to be thrown.
-				try {
-					IBrowsableItem photo = group_selector.Adaptor.PhotoFromIndex (Preferences.Get<int> (key));
+			//How many pictures are associated to these tags?
+			Db db = MainWindow.Toplevel.Database;
+			FSpot.PhotoQuery count_query = new FSpot.PhotoQuery(db.Photos);
+			count_query.Terms = FSpot.OrTerm.FromTags(tags);
+			int associated_photos = count_query.Count;
+	
+			string header;
+			if (tags.Length == 1)
+				header = String.Format (Catalog.GetString ("Delete tag \"{0}\"?"), tags [0].Name.Replace ("_", "__"));
+			else
+				header = String.Format (Catalog.GetString ("Delete the {0} selected tags?"), tags.Length);
+			
+			header = String.Format (header, tags.Length);
+			string msg = String.Empty;
+			if (associated_photos > 0) {
+				string photodesc = Catalog.GetPluralString ("photo", "photos", associated_photos);
+				msg = String.Format( 
+					Catalog.GetPluralString("If you delete this tag, the association with {0} {1} will be lost.",
+								"If you delete these tags, the association with {0} {1} will be lost.",
+								tags.Length),
+					associated_photos, photodesc);
+			}
+			string ok_caption = Catalog.GetPluralString ("_Delete tag", "_Delete tags", tags.Length);
+			
+			if (ResponseType.Ok == HigMessageDialog.RunHigConfirmation(main_window, 
+										   DialogFlags.DestroyWithParent, 
+										   MessageType.Warning, 
+										   header, 
+										   msg, 
+										   ok_caption)) {                              
+				try { 				
+					db.Photos.Remove (tags);
+				} catch (InvalidTagOperationException e) {
+					System.Console.WriteLine ("this is something or another");
+	
+					// A Category is not empty. Can not delete it.
+					string error_msg = Catalog.GetString ("Tag is not empty");
+					string error_desc = String.Format (Catalog.GetString ("Can not delete tags that have tags within them.  " + 
+													 "Please delete tags under \"{0}\" first"),
+									   e.Tag.Name.Replace ("_", "__"));
 					
-					if (photo != null)
-						JumpTo (query.IndexOf (photo));
-				} catch (Exception) {}
+					HigMessageDialog md = new HigMessageDialog (main_window, DialogFlags.DestroyWithParent, 
+										    Gtk.MessageType.Error, ButtonsType.Ok, 
+										    error_msg,
+										    error_desc);
+					md.Run ();
+					md.Destroy ();
+				}
 			}
-
-			icon_view.GrabFocus ();
-			break;
-		case Preferences.SIDEBAR_POSITION:
-			if (main_hpaned.Position !=Preferences.Get<int> (key) )
-				main_hpaned.Position = Preferences.Get<int> (key);
-			break;
-
-		case Preferences.TAG_ICON_SIZE:
-			int s = Preferences.Get<int> (key);
-			tag_icon_hidden.Active = (s == (int) Tag.IconSize.Hidden);
-			tag_icon_small.Active = (s == (int) Tag.IconSize.Small);
-			tag_icon_medium.Active = (s == (int) Tag.IconSize.Medium);
-			tag_icon_large.Active = (s == (int) Tag.IconSize.Large);
-
-			break;
-
-		case Preferences.ZOOM:
-			icon_view.Zoom = Preferences.Get<double> (key);
-			break;
-		
-		case Preferences.METADATA_EMBED_IN_IMAGE:
-			write_metadata =Preferences.Get<bool> (key) ;
-			break;
-		case Preferences.GNOME_MAILTO_ENABLED:
-			send_mail.Visible = Preferences.Get<bool> (key);
-			break;
 		}
-	}
-
-	// Version Id updates.
-
-	void UpdateForVersionIdChange (uint version_id)
-	{
-		CurrentPhoto.DefaultVersionId = version_id;
-		query.Commit (ActiveIndex ());
-	}
-
-	// Queries.
-
-	public void UpdateQuery ()
-	{
-		main_window.GdkWindow.Cursor = watch;
-		main_window.GdkWindow.Display.Sync ();
-		query.RequestReload ();
-		main_window.GdkWindow.Cursor = null;
-	}
-
-	void HandleTagSelectionChanged (object obj, EventArgs args)
-	{
-		UpdateMenus ();
-	}
-
-	public bool TagIncluded (Tag tag)
-	{
-		return query_widget.TagIncluded (tag);
-	}
 	
-	public bool TagRequired (Tag tag)
-	{
-		return query_widget.TagRequired (tag);
-	}
-
-	private void HandleQueryLogicChanged (object sender, EventArgs args)
-	{
-		HandleFindAddTagWith (null, null);
-	}
+		void HandleUpdateThumbnailCommand (object sender, EventArgs args)
+		{
+			ThumbnailCommand command = new ThumbnailCommand (main_window);
 	
-	public void HandleIncludeTag (object sender, EventArgs args)
-	{
-		ShowQueryWidget ();
-		query_widget.Include (tag_selection_widget.TagHighlight);
-	}
+			int [] selected_ids = SelectedIds ();
+			if (command.Execute (SelectedPhotos (selected_ids)))
+				query.MarkChanged (selected_ids, new PhotoChanges {DataChanged = true});
+		}
 	
-	public void HandleUnIncludeTag (object sender, EventArgs args)
-	{
-		query_widget.UnInclude (tag_selection_widget.TagHighlight);
- 	}
+		public void HandleRotate90Command (object sender, EventArgs args)
+		{
+			// Don't steal characters from any text entries
+			if (Window.Focus is Gtk.Entry && Gtk.Global.CurrentEvent is Gdk.EventKey) {
+				Window.Focus.ProcessEvent (Gtk.Global.CurrentEvent);
+				return;
+			}
+			
+			RotateSelectedPictures (GetToplevel (sender), RotateDirection.Clockwise);
+		}
 	
-	void HandleFindByTag (object sender, EventArgs args)
-	{
-		UpdateFindByTagMenu ();
-	}
+		public void HandleRotate270Command (object sender, EventArgs args)
+		{
+			// Don't steal characters from any text entries
+			if (Window.Focus is Gtk.Entry && Gtk.Global.CurrentEvent is Gdk.EventKey) {
+				Window.Focus.ProcessEvent (Gtk.Global.CurrentEvent);
+				return;
+			}
 	
-	public void UpdateFindByTagMenu ()
-	{
-		if (query_widget.Visible) {
-			query_widget.Close ();
-		} else {
-			ShowQueryWidget ();
+			RotateSelectedPictures (GetToplevel (sender), RotateDirection.Counterclockwise);
 		}
-	}
 	
-	void HandleFindAddTagWith (object sender, EventArgs args)
-	{
-		MenuItem find_add_tag_with = uimanager.GetWidget ("/ui/menubar1/find/find_add_tag_with") as MenuItem;
-		if (find_add_tag_with.Submenu != null)
-			find_add_tag_with.Submenu.Dispose ();
-		
-		Gtk.Menu submenu = FSpot.TermMenuItem.GetSubmenu (tag_selection_widget.TagHighlight);
-		find_add_tag_with.Sensitive = (submenu != null);
-		if (submenu != null) 
-			find_add_tag_with.Submenu = submenu;	
-	}
+		public void HandleCopyLocation (object sender, EventArgs args)
+		{
+			/*
+			 * FIXME this should really set uri atoms as well as string atoms
+			 */
+			Clipboard primary = Clipboard.Get (Atom.Intern ("PRIMARY", false));
+			Clipboard clipboard = Clipboard.Get (Atom.Intern ("CLIPBOARD", false));
 	
-	public void HandleAddTagToTerm (object sender, EventArgs args)
-	{
-		MenuItem item = sender as MenuItem;
-		
-		int item_pos = 0;
-		foreach (MenuItem i in (item.Parent as Menu).Children) {
-			if (item == i) {
-				break;
+			StringBuilder paths = new StringBuilder ();
+			
+			int i = 0;
+			foreach (Photo p in SelectedPhotos ()) {
+				if (i++ > 0)
+					paths.Append (" ");
+	
+				paths.Append (System.IO.Path.GetFullPath (p.DefaultVersionUri.LocalPath));
 			}
 			
-			item_pos++;
+			String data = paths.ToString ();
+			primary.Text = data;
+			clipboard.Text = data;
 		}
-		// account for All and separator menu items
-		item_pos -= 2;
-		
-		FSpot.Term parent_term = (FSpot.Term) FSpot.LogicWidget.Root.SubTerms [item_pos];
-		
-		if (FSpot.LogicWidget.Box != null) {
-			FSpot.Literal after = parent_term.Last as FSpot.Literal;
-			FSpot.LogicWidget.Box.InsertTerm (tag_selection_widget.TagHighlight, parent_term, after);
+	
+		void HandleSetAsBackgroundCommand (object sender, EventArgs args)
+		{
+			Photo current = CurrentPhoto;
+	
+			if (current == null)
+				return;
+	
+			Desktop.SetBackgroundImage (current.DefaultVersionUri.LocalPath);
 		}
-	}
 	
-	void HandleFindTagIncluded (Tag t)
-	{
-		ShowQueryWidget ();
-		query_widget.Include (new Tag [] {t});
- 	}
+		void HandleSetDateRange (object sender, EventArgs args) {
+			var date_range_dialog = new DateRangeDialog (query.Range, main_window);
+			if ((ResponseType)date_range_dialog.Run () == ResponseType.Ok)
+				query.Range = date_range_dialog.Range;
+			date_range_dialog.Destroy ();
 	
-	void HandleFindTagRequired (Tag t)
-	{
-		ShowQueryWidget ();
-		query_widget.Require (new Tag [] {t});
-	}
-
-	//
-	// Handle Main Menu 
-
-	void UpdateMenus ()
-	{
-		int tags_selected = tag_selection_widget.Selection.CountSelectedRows ();
-		bool tag_sensitive = tags_selected > 0;
-		bool active_selection = selection.Count > 0;
-		bool single_active = CurrentPhoto != null;
-		MenuItem version_menu_item = uimanager.GetWidget ("/ui/menubar1/file1/version_menu_item") as MenuItem;
+			//update the TimeLine
+			if (group_selector.Adaptor is TimeAdaptor && query.Range != null) 
+				group_selector.SetLimitsToDates(query.Range.Start, query.Range.End);
+		}
+	
+		public void HandleClearDateRange (object sender, EventArgs args) {
+			if (group_selector.Adaptor is FSpot.TimeAdaptor) {
+				group_selector.ResetLimits();
+			}
+			query.Range = null;
+		}
+	
+		void HandleSelectLastRoll (object sender, EventArgs args) {
+			query.RollSet = new RollSet (Database.Rolls.GetRolls (1));
+		}
+	
+		void HandleSelectRolls (object sender, EventArgs args) {
+			new LastRolls (query, Database.Rolls, main_window);
+		}
+	
+		void HandleClearRollFilter (object sender, EventArgs args) {
+			query.RollSet = null;
+		}
+	
+		void HandleSetRatingFilter (object sender, EventArgs args) {
+			new RatingFilterDialog (query, main_window);
+		}
+	
+		public void HandleClearRatingFilter (object sender, EventArgs args) {
+			query.RatingRange = null;
+		}
+	
+		void HandleFindUntagged (object sender, EventArgs args) {
+			if (query.Untagged == find_untagged.Active)
+				return;
+	
+			query.Untagged = !query.Untagged;
+		}
 		
-		if (!single_active) {
-			version_menu_item.Sensitive = false;
-			version_menu_item.Submenu = new Menu ();
-
-			create_version_menu_item.Sensitive = false;
-			delete_version_menu_item.Sensitive = false;
-			rename_version_menu_item.Sensitive = false;
-
-			sharpen.Sensitive = false;
-			loupe_menu_item.Sensitive = false;
-		} else {
-			version_menu_item.Sensitive = true;
-			create_version_menu_item.Sensitive = true;
+		void OnPreferencesChanged (object sender, NotifyEventArgs args)
+		{
+			LoadPreference (args.Key);
+		}
+	
+		void LoadPreference (String key)
+		{
+			switch (key) {
+			case Preferences.MAIN_WINDOW_MAXIMIZED:
+				if (Preferences.Get<bool> (key))
+					main_window.Maximize ();
+				else
+					main_window.Unmaximize ();
+				break;
+	
+			case Preferences.MAIN_WINDOW_X:
+			case Preferences.MAIN_WINDOW_Y:
+				main_window.Move(Preferences.Get<int> (Preferences.MAIN_WINDOW_X),
+						 Preferences.Get<int> (Preferences.MAIN_WINDOW_Y));
+				break;
 			
-			if (CurrentPhoto.DefaultVersionId == Photo.OriginalVersionId) {
-				delete_version_menu_item.Sensitive = false;
-				rename_version_menu_item.Sensitive = false;
-			} else {
-				delete_version_menu_item.Sensitive = true;
-				rename_version_menu_item.Sensitive = true;
+			case Preferences.MAIN_WINDOW_WIDTH:
+			case Preferences.MAIN_WINDOW_HEIGHT:
+				if (Preferences.Get<int> (Preferences.MAIN_WINDOW_WIDTH) > 0 &&
+							  Preferences.Get<int> (Preferences.MAIN_WINDOW_HEIGHT) > 0)
+					main_window.Resize(Preferences.Get<int> (Preferences.MAIN_WINDOW_WIDTH),
+							   Preferences.Get<int> (Preferences.MAIN_WINDOW_HEIGHT));
+	
+				break;
+			
+			case Preferences.SHOW_TOOLBAR:
+				if (display_toolbar.Active != Preferences.Get<bool> (key))
+					display_toolbar.Active = Preferences.Get<bool> (key);
+				break;
+			
+			case Preferences.SHOW_SIDEBAR:
+				if (display_sidebar.Active != Preferences.Get<bool> (key))
+					display_sidebar.Active = Preferences.Get<bool> (key);
+				break;
+			
+			case Preferences.SHOW_TIMELINE:
+				if (display_timeline.Active != Preferences.Get<bool> (key))
+					display_timeline.Active = Preferences.Get<bool> (key);
+				break;
+			
+			case Preferences.SHOW_FILMSTRIP:
+				if (display_filmstrip.Active != Preferences.Get<bool> (key)) {
+					display_filmstrip.Active = Preferences.Get<bool> (key);
+				}
+				break;
+			
+			case Preferences.SHOW_TAGS:
+				if (display_tags_menu_item.Active != Preferences.Get<bool> (key))
+					display_tags_menu_item.Active = Preferences.Get<bool> (key);
+				break;
+			
+			case Preferences.SHOW_DATES:
+				if (display_dates_menu_item.Active != Preferences.Get<bool> (key))
+					display_dates_menu_item.Active = Preferences.Get<bool> (key);
+					//display_dates_menu_item.Toggle ();
+				break;
+			
+			case Preferences.SHOW_RATINGS:
+				if (display_ratings_menu_item.Active != Preferences.Get<bool> (key))
+					display_ratings_menu_item.Active = Preferences.Get<bool> (key);
+				break;
+	
+			case Preferences.GROUP_ADAPTOR_ORDER_ASC:
+				group_selector.Adaptor.OrderAscending = Preferences.Get<bool> (key);
+				reverse_order.Active = Preferences.Get<bool> (key);
+				query.TimeOrderAsc = group_selector.Adaptor.OrderAscending;
+				break;
+	
+			case Preferences.GLASS_POSITION:
+				if (query.Count > 0) {
+					// If the database has changed since this pref was saved, this could cause
+					// an exception to be thrown.
+					try {
+						IBrowsableItem photo = group_selector.Adaptor.PhotoFromIndex (Preferences.Get<int> (key));
+						
+						if (photo != null)
+							JumpTo (query.IndexOf (photo));
+					} catch (Exception) {}
+				}
+	
+				icon_view.GrabFocus ();
+				break;
+			case Preferences.SIDEBAR_POSITION:
+				if (main_hpaned.Position !=Preferences.Get<int> (key) )
+					main_hpaned.Position = Preferences.Get<int> (key);
+				break;
+	
+			case Preferences.TAG_ICON_SIZE:
+				int s = Preferences.Get<int> (key);
+				tag_icon_hidden.Active = (s == (int) Tag.IconSize.Hidden);
+				tag_icon_small.Active = (s == (int) Tag.IconSize.Small);
+				tag_icon_medium.Active = (s == (int) Tag.IconSize.Medium);
+				tag_icon_large.Active = (s == (int) Tag.IconSize.Large);
+	
+				break;
+	
+			case Preferences.ZOOM:
+				icon_view.Zoom = Preferences.Get<double> (key);
+				break;
+			
+			case Preferences.METADATA_EMBED_IN_IMAGE:
+				write_metadata =Preferences.Get<bool> (key) ;
+				break;
+			case Preferences.GNOME_MAILTO_ENABLED:
+				send_mail.Visible = Preferences.Get<bool> (key);
+				break;
 			}
-
-			versions_submenu = new PhotoVersionMenu (CurrentPhoto);
-			versions_submenu.VersionIdChanged += delegate (PhotoVersionMenu menu) { UpdateForVersionIdChange (menu.VersionId);};
-			version_menu_item.Submenu = versions_submenu;
-
-			sharpen.Sensitive = (view_mode == ModeType.IconView ? false : true);
-			loupe_menu_item.Sensitive = (view_mode == ModeType.IconView ? false : true);
 		}
-
-		set_as_background.Sensitive = single_active;
-		adjust_time.Sensitive = active_selection;
-
-		attach_tag.Sensitive = active_selection;
-		remove_tag.Sensitive = active_selection;
-
-		rotate_left.Sensitive = active_selection;
-		rotate_right.Sensitive = active_selection;
-		update_thumbnail.Sensitive = active_selection;
-		delete_from_drive.Sensitive = active_selection;
+	
+		// Version Id updates.
+	
+		void UpdateForVersionIdChange (uint version_id)
+		{
+			CurrentPhoto.DefaultVersionId = version_id;
+			query.Commit (ActiveIndex ());
+		}
+	
+		// Queries.
+	
+		public void UpdateQuery ()
+		{
+			main_window.GdkWindow.Cursor = watch;
+			main_window.GdkWindow.Display.Sync ();
+			query.RequestReload ();
+			main_window.GdkWindow.Cursor = null;
+		}
+	
+		void HandleTagSelectionChanged (object obj, EventArgs args)
+		{
+			UpdateMenus ();
+		}
+	
+		public bool TagIncluded (Tag tag)
+		{
+			return query_widget.TagIncluded (tag);
+		}
+		
+		public bool TagRequired (Tag tag)
+		{
+			return query_widget.TagRequired (tag);
+		}
+	
+		private void HandleQueryLogicChanged (object sender, EventArgs args)
+		{
+			HandleFindAddTagWith (null, null);
+		}
 		
-		send_mail.Sensitive = active_selection;
-		print.Sensitive = active_selection;
-		select_none.Sensitive = active_selection;
-		copy_location.Sensitive = active_selection;
-		remove_from_catalog.Sensitive = active_selection;
+		public void HandleIncludeTag (object sender, EventArgs args)
+		{
+			ShowQueryWidget ();
+			query_widget.Include (tag_selection_widget.TagHighlight);
+		}
 		
-		clear_rating_filter.Sensitive = (query.RatingRange != null);
-
-		clear_roll_filter.Sensitive = (query.RollSet != null);
+		public void HandleUnIncludeTag (object sender, EventArgs args)
+		{
+			query_widget.UnInclude (tag_selection_widget.TagHighlight);
+	 	}
 		
-		delete_selected_tag.Sensitive = tag_sensitive;
-		edit_selected_tag.Sensitive = tag_sensitive;
-
-
-		attach_tag_to_selection.Sensitive = tag_sensitive && active_selection;
-		remove_tag_from_selection.Sensitive = tag_sensitive && active_selection;
-	
-		export.Sensitive = active_selection;
-
-		MenuItem toolsmenu = uimanager.GetWidget ("/ui/menubar1/tools") as MenuItem;
-		try {
-			tools.Visible = (toolsmenu.Submenu as Menu).Children.Length > 0;
-		} catch {
-			tools.Visible = false;
+		void HandleFindByTag (object sender, EventArgs args)
+		{
+			UpdateFindByTagMenu ();
 		}
-
-		if (rl_button != null) {
-			if (selection.Count == 0) {
-				rl_button.Sensitive = false;
-				rl_button.SetTooltip (ToolTips, Catalog.GetString (String.Empty), null);
+		
+		public void UpdateFindByTagMenu ()
+		{
+			if (query_widget.Visible) {
+				query_widget.Close ();
 			} else {
-				rl_button.Sensitive = true;
-
-				string msg = Catalog.GetPluralString ("Rotate selected photo left",
-								      "Rotate selected photos left", selection.Count);
-				rl_button.SetTooltip (ToolTips, String.Format (msg, selection.Count), null);
+				ShowQueryWidget ();
 			}
 		}
 		
-		if (rr_button != null) {
-			if (selection.Count == 0) {
-				rr_button.Sensitive = false;
-				rr_button.SetTooltip (ToolTips, Catalog.GetString (String.Empty), null);
-			} else {
-				rr_button.Sensitive = true;
-
-				string msg = Catalog.GetPluralString ("Rotate selected photo right",
-								      "Rotate selected photos right", selection.Count);
-				rr_button.SetTooltip (ToolTips, String.Format (msg, selection.Count), null);
+		void HandleFindAddTagWith (object sender, EventArgs args)
+		{
+			MenuItem find_add_tag_with = uimanager.GetWidget ("/ui/menubar1/find/find_add_tag_with") as MenuItem;
+			if (find_add_tag_with.Submenu != null)
+				find_add_tag_with.Submenu.Dispose ();
+			
+			Gtk.Menu submenu = FSpot.TermMenuItem.GetSubmenu (tag_selection_widget.TagHighlight);
+			find_add_tag_with.Sensitive = (submenu != null);
+			if (submenu != null) 
+				find_add_tag_with.Submenu = submenu;	
+		}
+		
+		public void HandleAddTagToTerm (object sender, EventArgs args)
+		{
+			MenuItem item = sender as MenuItem;
+			
+			int item_pos = 0;
+			foreach (MenuItem i in (item.Parent as Menu).Children) {
+				if (item == i) {
+					break;
+				}
+				
+				item_pos++;
+			}
+			// account for All and separator menu items
+			item_pos -= 2;
+			
+			FSpot.Term parent_term = (FSpot.Term) FSpot.LogicWidget.Root.SubTerms [item_pos];
+			
+			if (FSpot.LogicWidget.Box != null) {
+				FSpot.Literal after = parent_term.Last as FSpot.Literal;
+				FSpot.LogicWidget.Box.InsertTerm (tag_selection_widget.TagHighlight, parent_term, after);
 			}
 		}
-
-		//if (last_tags_selected_count != tags_selected) {
-		MenuItem find_add_tag = uimanager.GetWidget ("/ui/menubar1/find/find_add_tag") as MenuItem;
-		MenuItem find_add_tag_with = uimanager.GetWidget ("/ui/menubar1/find/find_add_tag_with") as MenuItem;
-
-		((Gtk.Label)find_add_tag.Child).TextWithMnemonic = String.Format (
-			Catalog.GetPluralString ("Find _Selected Tag", "Find _Selected Tags", tags_selected), tags_selected
-		);
-
-		((Gtk.Label)find_add_tag_with.Child).TextWithMnemonic = String.Format (
-			Catalog.GetPluralString ("Find Selected Tag _With", "Find Selected Tags _With", tags_selected), tags_selected
-		);
-
-		find_add_tag.Sensitive = tag_sensitive;
-		find_add_tag_with.Sensitive = tag_sensitive && find_add_tag_with.Submenu != null;
-
-		//last_tags_selected_count = tags_selected;
-		//}
-	}
-
-	void PopulateExtendableMenus (object o, EventArgs args)
-	{
-		MenuItem exportmenu = uimanager.GetWidget ("/ui/menubar1/file1/export") as MenuItem;
-		MenuItem toolsmenu = uimanager.GetWidget ("/ui/menubar1/tools") as MenuItem;
-		try {
-			if (exportmenu.Submenu != null)
-				exportmenu.Submenu.Dispose ();
-			if (toolsmenu.Submenu != null)
-				toolsmenu.RemoveSubmenu ();
-
-			exportmenu.Submenu = (Mono.Addins.AddinManager.GetExtensionNode ("/FSpot/Menus/Exports") as FSpot.Extensions.SubmenuNode).GetSubmenu ();
-			exportmenu.Submenu.ShowAll ();
-
-			toolsmenu.Submenu = (Mono.Addins.AddinManager.GetExtensionNode ("/FSpot/Menus/Tools") as FSpot.Extensions.SubmenuNode).GetSubmenu ();
-			toolsmenu.Submenu.ShowAll ();
-
-			tools.Visible = (toolsmenu.Submenu as Menu).Children.Length > 0;
-		} catch {
-			Log.Warning ("There's (maybe) something wrong with some of the installed extensions. You can try removing the directory addin-db-000 from ~/.config/f-spot/");
-			toolsmenu.Visible = false;
+		
+		void HandleFindTagIncluded (Tag t)
+		{
+			ShowQueryWidget ();
+			query_widget.Include (new Tag [] {t});
+	 	}
+		
+		void HandleFindTagRequired (Tag t)
+		{
+			ShowQueryWidget ();
+			query_widget.Require (new Tag [] {t});
 		}
-	}
-
-	public void HandleOpenWith (object sender, ApplicationActivatedEventArgs e)
-	{
-		GLib.AppInfo application = e.AppInfo;
-		Photo[] selected = SelectedPhotos ();
-
-		if (selected == null || selected.Length < 1)
-			return;
-
-		string header = Catalog.GetPluralString ("Create New Version?", "Create New Versions?", selected.Length); 
-		string msg = String.Format (Catalog.GetPluralString (
-				"Before launching {1}, should F-Spot create a new version of the selected photo to preserve the original?",
-				"Before launching {1}, should F-Spot create new versions of the selected photos to preserve the originals?", selected.Length),
-				selected.Length, application.Name);
-
-		// FIXME add cancel button? add help button?
-		HigMessageDialog hmd = new HigMessageDialog(GetToplevel (sender), DialogFlags.DestroyWithParent, 
-							    MessageType.Question, Gtk.ButtonsType.None,
-							    header, msg);
-
-		hmd.AddButton (Gtk.Stock.No, Gtk.ResponseType.No, false);
-		//hmd.AddButton (Gtk.Stock.Cancel, Gtk.ResponseType.Cancel, false);
-		hmd.AddButton (Gtk.Stock.Yes, Gtk.ResponseType.Yes, true);
-
-		bool support_xcf = false;;
-		if (application.Id == "gimp.desktop") 
-			foreach (Gdk.PixbufFormat format in Gdk.Pixbuf.Formats)
-				if (format.Name == "xcf")
-					support_xcf = true;
-
-		//This allows creating a version with a .xcf extension.
-		//There's no need to convert the file to xcf file format, gimp will take care of this
-		if (support_xcf) {	
-			CheckButton cb = new CheckButton (Catalog.GetString ("XCF version"));
-			cb.Active = Preferences.Get<bool> (Preferences.EDIT_CREATE_XCF_VERSION);
-			hmd.VBox.Add (cb);
-			cb.Toggled += delegate (object s, EventArgs ea) {
-				Preferences.Set (Preferences.EDIT_CREATE_XCF_VERSION, (s as CheckButton).Active);
-			};
-			cb.Show ();
+	
+		//
+		// Handle Main Menu 
+	
+		void UpdateMenus ()
+		{
+			int tags_selected = tag_selection_widget.Selection.CountSelectedRows ();
+			bool tag_sensitive = tags_selected > 0;
+			bool active_selection = Selection.Count > 0;
+			bool single_active = CurrentPhoto != null;
+			MenuItem version_menu_item = uimanager.GetWidget ("/ui/menubar1/file1/version_menu_item") as MenuItem;
+			
+			if (!single_active) {
+				version_menu_item.Sensitive = false;
+				version_menu_item.Submenu = new Menu ();
+	
+				create_version_menu_item.Sensitive = false;
+				delete_version_menu_item.Sensitive = false;
+				rename_version_menu_item.Sensitive = false;
+	
+				sharpen.Sensitive = false;
+				loupe_menu_item.Sensitive = false;
+			} else {
+				version_menu_item.Sensitive = true;
+				create_version_menu_item.Sensitive = true;
+				
+				if (CurrentPhoto.DefaultVersionId == Photo.OriginalVersionId) {
+					delete_version_menu_item.Sensitive = false;
+					rename_version_menu_item.Sensitive = false;
+				} else {
+					delete_version_menu_item.Sensitive = true;
+					rename_version_menu_item.Sensitive = true;
+				}
+	
+				versions_submenu = new PhotoVersionMenu (CurrentPhoto);
+				versions_submenu.VersionIdChanged += delegate (PhotoVersionMenu menu) { UpdateForVersionIdChange (menu.VersionId);};
+				version_menu_item.Submenu = versions_submenu;
+	
+				sharpen.Sensitive = (ViewMode == ModeType.IconView ? false : true);
+				loupe_menu_item.Sensitive = (ViewMode == ModeType.IconView ? false : true);
+			}
+	
+			set_as_background.Sensitive = single_active;
+			adjust_time.Sensitive = active_selection;
+	
+			attach_tag.Sensitive = active_selection;
+			remove_tag.Sensitive = active_selection;
+	
+			rotate_left.Sensitive = active_selection;
+			rotate_right.Sensitive = active_selection;
+			update_thumbnail.Sensitive = active_selection;
+			delete_from_drive.Sensitive = active_selection;
+			
+			send_mail.Sensitive = active_selection;
+			print.Sensitive = active_selection;
+			select_none.Sensitive = active_selection;
+			copy_location.Sensitive = active_selection;
+			remove_from_catalog.Sensitive = active_selection;
+			
+			clear_rating_filter.Sensitive = (query.RatingRange != null);
+	
+			clear_roll_filter.Sensitive = (query.RollSet != null);
+			
+			delete_selected_tag.Sensitive = tag_sensitive;
+			edit_selected_tag.Sensitive = tag_sensitive;
+	
+	
+			attach_tag_to_selection.Sensitive = tag_sensitive && active_selection;
+			remove_tag_from_selection.Sensitive = tag_sensitive && active_selection;
+		
+			export.Sensitive = active_selection;
+	
+			MenuItem toolsmenu = uimanager.GetWidget ("/ui/menubar1/tools") as MenuItem;
+			try {
+				tools.Visible = (toolsmenu.Submenu as Menu).Children.Length > 0;
+			} catch {
+				tools.Visible = false;
+			}
+	
+			if (rl_button != null) {
+				if (Selection.Count == 0) {
+					rl_button.Sensitive = false;
+					rl_button.SetTooltip (ToolTips, Catalog.GetString (String.Empty), null);
+				} else {
+					rl_button.Sensitive = true;
+	
+					string msg = Catalog.GetPluralString ("Rotate selected photo left",
+									      "Rotate selected photos left", Selection.Count);
+					rl_button.SetTooltip (ToolTips, String.Format (msg, Selection.Count), null);
+				}
+			}
+			
+			if (rr_button != null) {
+				if (Selection.Count == 0) {
+					rr_button.Sensitive = false;
+					rr_button.SetTooltip (ToolTips, Catalog.GetString (String.Empty), null);
+				} else {
+					rr_button.Sensitive = true;
+	
+					string msg = Catalog.GetPluralString ("Rotate selected photo right",
+									      "Rotate selected photos right", Selection.Count);
+					rr_button.SetTooltip (ToolTips, String.Format (msg, Selection.Count), null);
+				}
+			}
+	
+			//if (last_tags_selected_count != tags_selected) {
+			MenuItem find_add_tag = uimanager.GetWidget ("/ui/menubar1/find/find_add_tag") as MenuItem;
+			MenuItem find_add_tag_with = uimanager.GetWidget ("/ui/menubar1/find/find_add_tag_with") as MenuItem;
+	
+			((Gtk.Label)find_add_tag.Child).TextWithMnemonic = String.Format (
+				Catalog.GetPluralString ("Find _Selected Tag", "Find _Selected Tags", tags_selected), tags_selected
+			);
+	
+			((Gtk.Label)find_add_tag_with.Child).TextWithMnemonic = String.Format (
+				Catalog.GetPluralString ("Find Selected Tag _With", "Find Selected Tags _With", tags_selected), tags_selected
+			);
+	
+			find_add_tag.Sensitive = tag_sensitive;
+			find_add_tag_with.Sensitive = tag_sensitive && find_add_tag_with.Submenu != null;
+	
+			//last_tags_selected_count = tags_selected;
+			//}
 		}
-
-		Gtk.ResponseType response = Gtk.ResponseType.Cancel;
-
-		try {
-			response = (Gtk.ResponseType) hmd.Run();
-		} finally {
-			hmd.Destroy ();
+	
+		void PopulateExtendableMenus (object o, EventArgs args)
+		{
+			MenuItem exportmenu = uimanager.GetWidget ("/ui/menubar1/file1/export") as MenuItem;
+			MenuItem toolsmenu = uimanager.GetWidget ("/ui/menubar1/tools") as MenuItem;
+			try {
+				if (exportmenu.Submenu != null)
+					exportmenu.Submenu.Dispose ();
+				if (toolsmenu.Submenu != null)
+					toolsmenu.RemoveSubmenu ();
+	
+				exportmenu.Submenu = (Mono.Addins.AddinManager.GetExtensionNode ("/FSpot/Menus/Exports") as FSpot.Extensions.SubmenuNode).GetSubmenu ();
+				exportmenu.Submenu.ShowAll ();
+	
+				toolsmenu.Submenu = (Mono.Addins.AddinManager.GetExtensionNode ("/FSpot/Menus/Tools") as FSpot.Extensions.SubmenuNode).GetSubmenu ();
+				toolsmenu.Submenu.ShowAll ();
+	
+				tools.Visible = (toolsmenu.Submenu as Menu).Children.Length > 0;
+			} catch {
+				Log.Warning ("There's (maybe) something wrong with some of the installed extensions. You can try removing the directory addin-db-000 from ~/.config/f-spot/");
+				toolsmenu.Visible = false;
+			}
 		}
-		
-		bool create_xcf = false;
-		if (support_xcf)
-			create_xcf = Preferences.Get<bool> (Preferences.EDIT_CREATE_XCF_VERSION);
-
-		Console.WriteLine ("XCF ? {0}", create_xcf);
-
-		if (response == Gtk.ResponseType.Cancel)
-			return;
-
-		bool create_new_versions = (response == Gtk.ResponseType.Yes);
-
-		ArrayList errors = new ArrayList ();
-		GLib.List uri_list = new GLib.List (typeof (string));
-		foreach (Photo photo in selected) {
+	
+		public void HandleOpenWith (object sender, ApplicationActivatedEventArgs e)
+		{
+			GLib.AppInfo application = e.AppInfo;
+			Photo[] selected = SelectedPhotos ();
+	
+			if (selected == null || selected.Length < 1)
+				return;
+	
+			string header = Catalog.GetPluralString ("Create New Version?", "Create New Versions?", selected.Length); 
+			string msg = String.Format (Catalog.GetPluralString (
+					"Before launching {1}, should F-Spot create a new version of the selected photo to preserve the original?",
+					"Before launching {1}, should F-Spot create new versions of the selected photos to preserve the originals?", selected.Length),
+					selected.Length, application.Name);
+	
+			// FIXME add cancel button? add help button?
+			HigMessageDialog hmd = new HigMessageDialog(GetToplevel (sender), DialogFlags.DestroyWithParent, 
+								    MessageType.Question, Gtk.ButtonsType.None,
+								    header, msg);
+	
+			hmd.AddButton (Gtk.Stock.No, Gtk.ResponseType.No, false);
+			//hmd.AddButton (Gtk.Stock.Cancel, Gtk.ResponseType.Cancel, false);
+			hmd.AddButton (Gtk.Stock.Yes, Gtk.ResponseType.Yes, true);
+	
+			bool support_xcf = false;;
+			if (application.Id == "gimp.desktop") 
+				foreach (Gdk.PixbufFormat format in Gdk.Pixbuf.Formats)
+					if (format.Name == "xcf")
+						support_xcf = true;
+	
+			//This allows creating a version with a .xcf extension.
+			//There's no need to convert the file to xcf file format, gimp will take care of this
+			if (support_xcf) {	
+				CheckButton cb = new CheckButton (Catalog.GetString ("XCF version"));
+				cb.Active = Preferences.Get<bool> (Preferences.EDIT_CREATE_XCF_VERSION);
+				hmd.VBox.Add (cb);
+				cb.Toggled += delegate (object s, EventArgs ea) {
+					Preferences.Set (Preferences.EDIT_CREATE_XCF_VERSION, (s as CheckButton).Active);
+				};
+				cb.Show ();
+			}
+	
+			Gtk.ResponseType response = Gtk.ResponseType.Cancel;
+	
 			try {
-				if (create_new_versions) {
-					uint version = photo.CreateNamedVersion (application.Name, create_xcf ? ".xcf" : null, photo.DefaultVersionId, true);
-					photo.DefaultVersionId = version;
+				response = (Gtk.ResponseType) hmd.Run();
+			} finally {
+				hmd.Destroy ();
+			}
+			
+			bool create_xcf = false;
+			if (support_xcf)
+				create_xcf = Preferences.Get<bool> (Preferences.EDIT_CREATE_XCF_VERSION);
+	
+			Console.WriteLine ("XCF ? {0}", create_xcf);
+	
+			if (response == Gtk.ResponseType.Cancel)
+				return;
+	
+			bool create_new_versions = (response == Gtk.ResponseType.Yes);
+	
+			ArrayList errors = new ArrayList ();
+			GLib.List uri_list = new GLib.List (typeof (string));
+			foreach (Photo photo in selected) {
+				try {
+					if (create_new_versions) {
+						uint version = photo.CreateNamedVersion (application.Name, create_xcf ? ".xcf" : null, photo.DefaultVersionId, true);
+						photo.DefaultVersionId = version;
+					}
+				} catch (Exception ex) {
+					errors.Add (new EditException (photo, ex));
 				}
-			} catch (Exception ex) {
-				errors.Add (new EditException (photo, ex));
+	
+				uri_list.Append (photo.DefaultVersionUri.ToString ());
+			}
+	
+			// FIXME need to clean up the error dialog here.
+			if (errors.Count > 0) {
+				Dialog md = new EditExceptionDialog (GetToplevel (sender), errors.ToArray (typeof (EditException)) as EditException []);
+				md.Run ();
+				md.Destroy ();
+			}
+	
+			if (create_new_versions)
+				Database.Photos.Commit (selected);
+	
+			try {
+				application.LaunchUris (uri_list, null);
+			} catch (System.Exception) {
+				Log.Error ("Failed to lauch {0}", application.Name);
 			}
-
-			uri_list.Append (photo.DefaultVersionUri.ToString ());
 		}
-
-		// FIXME need to clean up the error dialog here.
-		if (errors.Count > 0) {
-			Dialog md = new EditExceptionDialog (GetToplevel (sender), errors.ToArray (typeof (EditException)) as EditException []);
-			md.Run ();
-			md.Destroy ();
+	
+		public void GetWidgetPosition(Widget widget, out int x, out int y)
+	    {
+			main_window.GdkWindow.GetOrigin(out x, out y);
+			
+			x += widget.Allocation.X;
+			y += widget.Allocation.Y;
+	 	}
+	
+		// Tag typing ...
+	
+		private void UpdateTagEntryFromSelection ()
+		{
+			if (!tagbar.Visible)
+				return;
+			tag_entry.UpdateFromSelection (SelectedPhotos ());
 		}
-
-		if (create_new_versions)
-			db.Photos.Commit (selected);
-
-		try {
-			application.LaunchUris (uri_list, null);
-		} catch (System.Exception) {
-			Log.Error ("Failed to lauch {0}", application.Name);
+	
+		public void HandlePossibleTagTyping (object sender, Gtk.KeyPressEventArgs args)
+		{
+			if (Selection.Count == 0 || tagbar.Visible && tag_entry.HasFocus)
+				return;
+	
+	#if !ALLOW_TAG_TYPING_WITHOUT_HOTKEY
+			if (args.Event.Key != Gdk.Key.t)
+				return;
+	#endif
+	
+	#if ALLOW_TAG_TYPING_WITHOUT_HOTKEY
+			char c = System.Convert.ToChar (Gdk.Keyval.ToUnicode ((uint) args.Event.Key));
+			if (! System.Char.IsLetter (c))
+				return;
+	#endif
+			
+	#if ALLOW_TAG_TYPING_WITHOUT_HOTKEY
+			tag_entry.Text += c;
+	#endif
+	
+			tagbar.Show ();
+			UpdateTagEntryFromSelection ();
+			tag_entry.GrabFocus ();
+			tag_entry.SelectRegion (-1, -1);
 		}
-	}
-
-	public void GetWidgetPosition(Widget widget, out int x, out int y)
-    {
-		main_window.GdkWindow.GetOrigin(out x, out y);
-		
-		x += widget.Allocation.X;
-		y += widget.Allocation.Y;
- 	}
-
-	// Tag typing ...
-
-	private void UpdateTagEntryFromSelection ()
-	{
-		if (!tagbar.Visible)
-			return;
-		tag_entry.UpdateFromSelection (SelectedPhotos ());
-	}
-
-	public void HandlePossibleTagTyping (object sender, Gtk.KeyPressEventArgs args)
-	{
-		if (Selection.Count == 0 || tagbar.Visible && tag_entry.HasFocus)
-			return;
-
-#if !ALLOW_TAG_TYPING_WITHOUT_HOTKEY
-		if (args.Event.Key != Gdk.Key.t)
-			return;
-#endif
-
-#if ALLOW_TAG_TYPING_WITHOUT_HOTKEY
-		char c = System.Convert.ToChar (Gdk.Keyval.ToUnicode ((uint) args.Event.Key));
-		if (! System.Char.IsLetter (c))
-			return;
-#endif
-		
-#if ALLOW_TAG_TYPING_WITHOUT_HOTKEY
-		tag_entry.Text += c;
-#endif
-
-		tagbar.Show ();
-		UpdateTagEntryFromSelection ();
-		tag_entry.GrabFocus ();
-		tag_entry.SelectRegion (-1, -1);
-	}
-
-	// "Activate" means the user pressed the enter key
-	public void HandleTagEntryActivate (object sender, EventArgs args)
-	{
-	       if (view_mode == ModeType.IconView) {
-		       icon_view.GrabFocus ();
-	       } else {
-		       photo_view.QueueDraw ();
-		       photo_view.View.GrabFocus ();
-	       }
-	}
-
-	private void HandleTagEntryTagsAttached (object o, string [] new_tags)
-	{
-		int [] selected_photos = SelectedIds ();
-		if (selected_photos == null || new_tags == null || new_tags.Length == 0)
-			return;
-
-		Category default_category = null;
-		Tag [] selection = tag_selection_widget.TagHighlight;
-		if (selection.Length > 0) {
-			if (selection [0] is Category)
-				default_category = (Category) selection [0];
-			else
-				default_category = selection [0].Category;
+	
+		// "Activate" means the user pressed the enter key
+		public void HandleTagEntryActivate (object sender, EventArgs args)
+		{
+		       if (ViewMode == ModeType.IconView) {
+			       icon_view.GrabFocus ();
+		       } else {
+			       photo_view.QueueDraw ();
+			       photo_view.View.GrabFocus ();
+		       }
 		}
-		Tag [] tags = new Tag [new_tags.Length];
-		int i = 0;
-		db.BeginTransaction ();
-		foreach (string tagname in new_tags) {
-			Tag t = db.Tags.GetTagByName (tagname);
-			if (t == null) {
-				t = db.Tags.CreateCategory (default_category, tagname, true) as Tag;
-				db.Tags.Commit (t);
+	
+		private void HandleTagEntryTagsAttached (object o, string [] new_tags)
+		{
+			int [] selected_photos = SelectedIds ();
+			if (selected_photos == null || new_tags == null || new_tags.Length == 0)
+				return;
+	
+			Category default_category = null;
+			Tag [] selection = tag_selection_widget.TagHighlight;
+			if (selection.Length > 0) {
+				if (selection [0] is Category)
+					default_category = (Category) selection [0];
+				else
+					default_category = selection [0].Category;
+			}
+			Tag [] tags = new Tag [new_tags.Length];
+			int i = 0;
+			Database.BeginTransaction ();
+			foreach (string tagname in new_tags) {
+				Tag t = Database.Tags.GetTagByName (tagname);
+				if (t == null) {
+					t = Database.Tags.CreateCategory (default_category, tagname, true) as Tag;
+					Database.Tags.Commit (t);
+				}
+				tags [i++] = t;
 			}
-			tags [i++] = t;
+			AddTagExtended (selected_photos, tags);
+			Database.CommitTransaction ();
 		}
-		AddTagExtended (selected_photos, tags);
-		db.CommitTransaction ();
-	}
-
-	private void HandleTagEntryRemoveTags (object o, Tag [] remove_tags)
-	{
-		int [] selected_photos = SelectedIds ();
-		if (selected_photos == null || remove_tags == null || remove_tags.Length == 0)
-			return;
-
-		db.BeginTransaction ();
-		RemoveTags (selected_photos, remove_tags);
-		db.CommitTransaction ();
-	}
-
-	private void HideTagbar ()
-	{
-		if (! tagbar.Visible)
-			return;
-		
-		UpdateTagEntryFromSelection ();
-
-		// Cancel any pending edits...
-		tagbar.Hide ();
-
-		if (view_mode == ModeType.IconView)
-			icon_view.GrabFocus ();
-		else {
-			photo_view.QueueDraw ();
-			photo_view.View.GrabFocus ();
+	
+		private void HandleTagEntryRemoveTags (object o, Tag [] remove_tags)
+		{
+			int [] selected_photos = SelectedIds ();
+			if (selected_photos == null || remove_tags == null || remove_tags.Length == 0)
+				return;
+	
+			Database.BeginTransaction ();
+			RemoveTags (selected_photos, remove_tags);
+			Database.CommitTransaction ();
 		}
-
-		tag_entry.ClearTagCompletions ();
-	}
-
-	public void HandleTagBarCloseButtonPressed (object sender, EventArgs args)
-	{
-		HideTagbar ();
-	}
-
-	public void HandleTagEntryKeyPressEvent (object sender, Gtk.KeyPressEventArgs args)
-	{
-		args.RetVal = false;
-
-		if (args.Event.Key == Gdk.Key.Escape) { 
+	
+		private void HideTagbar ()
+		{
+			if (! tagbar.Visible)
+				return;
+			
+			UpdateTagEntryFromSelection ();
+	
+			// Cancel any pending edits...
+			tagbar.Hide ();
+	
+			if (ViewMode == ModeType.IconView)
+				icon_view.GrabFocus ();
+			else {
+				photo_view.QueueDraw ();
+				photo_view.View.GrabFocus ();
+			}
+	
+			tag_entry.ClearTagCompletions ();
+		}
+	
+		public void HandleTagBarCloseButtonPressed (object sender, EventArgs args)
+		{
 			HideTagbar ();
-			args.RetVal = true;
 		}
-	}
-
-	public List<string> SelectedMimeTypes ()
-	{
-		List<string> contents = new List<string> ();
-
-		foreach (Photo p in SelectedPhotos ()) {
-			string content;
-			try {
-				content = GLib.FileFactory.NewForUri (p.DefaultVersionUri).QueryInfo ("standard::content-type", GLib.FileQueryInfoFlags.None, null).ContentType;
-			} catch (GLib.GException) {
-				content = null;
+	
+		public void HandleTagEntryKeyPressEvent (object sender, Gtk.KeyPressEventArgs args)
+		{
+			args.RetVal = false;
+	
+			if (args.Event.Key == Gdk.Key.Escape) { 
+				HideTagbar ();
+				args.RetVal = true;
 			}
-
-			if (! contents.Contains (content))
-				contents.Add (content);
 		}
-
-		return contents;
-	}
-
-	private void ShowQueryWidget ()
-	{
-		if (find_bar.Visible) {
-			find_bar.Entry.Text = String.Empty;
-			find_bar.Hide ();
-		}
-		
-		query_widget.ShowBar ();
-		return;
-	}
-
-	public void HideSidebar (object o, EventArgs args) {
-		display_sidebar.Active = false;
-	}
 	
-	public void HandleKeyPressEvent (object sender, Gtk.KeyPressEventArgs args)
-	{
-		bool ctrl = ModifierType.ControlMask == (args.Event.State & ModifierType.ControlMask);
-
-		if ((ctrl && args.Event.Key == Gdk.Key.F) || args.Event.Key == Gdk.Key.slash) {
-			if (!find_bar.Visible) {
-				if (query_widget.Visible) {
-					query_widget.Close ();
+		public List<string> SelectedMimeTypes ()
+		{
+			List<string> contents = new List<string> ();
+	
+			foreach (Photo p in SelectedPhotos ()) {
+				string content;
+				try {
+					content = GLib.FileFactory.NewForUri (p.DefaultVersionUri).QueryInfo ("standard::content-type", GLib.FileQueryInfoFlags.None, null).ContentType;
+				} catch (GLib.GException) {
+					content = null;
 				}
-				
-				find_bar.ShowAll();
+	
+				if (! contents.Contains (content))
+					contents.Add (content);
 			}
-
-			// Grab the focus even if it's already shown
-			find_bar.Entry.GrabFocus ();
-			args.RetVal = true;
+	
+			return contents;
+		}
+	
+		private void ShowQueryWidget ()
+		{
+			if (find_bar.Visible) {
+				find_bar.Entry.Text = String.Empty;
+				find_bar.Hide ();
+			}
+			
+			query_widget.ShowBar ();
 			return;
 		}
+	
+		public void HideSidebar (object o, EventArgs args) {
+			display_sidebar.Active = false;
+		}
 		
-		args.RetVal = false;
+		public void HandleKeyPressEvent (object sender, Gtk.KeyPressEventArgs args)
+		{
+			bool ctrl = ModifierType.ControlMask == (args.Event.State & ModifierType.ControlMask);
+	
+			if ((ctrl && args.Event.Key == Gdk.Key.F) || args.Event.Key == Gdk.Key.slash) {
+				if (!find_bar.Visible) {
+					if (query_widget.Visible) {
+						query_widget.Close ();
+					}
+					
+					find_bar.ShowAll();
+				}
+	
+				// Grab the focus even if it's already shown
+				find_bar.Entry.GrabFocus ();
+				args.RetVal = true;
+				return;
+			}
+			
+			args.RetVal = false;
+		}
 	}
 }



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