Description: Display all images in directories passed to --view
 When a file is passed to --view, also view all the other images in the same
 directory.
Author: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
Bug-LP: https://bugs.edge.launchpad.net/ubuntu/+source/f-spot/+bug/484887
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=333189

Index: f-spot-0.6.1.5/src/SingleView.cs
===================================================================
--- f-spot-0.6.1.5.orig/src/SingleView.cs	2010-03-12 12:51:05.971832042 +1100
+++ f-spot-0.6.1.5/src/SingleView.cs	2010-03-12 12:53:02.551817808 +1100
@@ -82,28 +82,44 @@
 			string glade_name = "single_view";
 			this.uri = uris[0];
 			
+			// If we are passed the URI to a file we want to
+			// (a) Display & select that file, and 
+			// (b) Display the other files in the same directory.
+			List<Uri> uris_to_display = new List<Uri> ();
+			foreach (var uri in uris) {
+				Uri candidate_uri;
+				if (uri.IsFile) {
+					candidate_uri = uri.GetDirectoryUri ();
+				} else {
+					candidate_uri = uri;
+				}
+				if (!uris_to_display.Contains (candidate_uri)) {
+					uris_to_display.Add (candidate_uri);
+				}
+			}
+			
 			xml = new Glade.XML (null, "f-spot.glade", glade_name, "f-spot");
 			xml.Autoconnect (this);
 			window = (Gtk.Window)xml.GetWidget (glade_name);
-		
+			
 			LoadPreference (Preferences.VIEWER_WIDTH);
 			LoadPreference (Preferences.VIEWER_MAXIMIZED);
-
+			
 			Gtk.Toolbar toolbar = new Gtk.Toolbar ();
 			toolbar_hbox.PackStart (toolbar);
-		
+			
 			rl_button = GtkUtil.ToolButtonFromTheme ("object-rotate-left", Catalog.GetString ("Rotate Left"), true);
 			rl_button.Clicked += HandleRotate270Command;
 			rl_button.SetTooltip (toolTips, Catalog.GetString ("Rotate photo left"), null);
 			toolbar.Insert (rl_button, -1);
-
+			
 			rr_button = GtkUtil.ToolButtonFromTheme ("object-rotate-right", Catalog.GetString ("Rotate Right"), true);
 			rr_button.Clicked += HandleRotate90Command;
 			rr_button.SetTooltip (toolTips, Catalog.GetString ("Rotate photo right"), null);
 			toolbar.Insert (rr_button, -1);
-
+			
 			toolbar.Insert (new SeparatorToolItem (), -1);
-
+			
 			StockItem undo_info = Stock.Lookup (Stock.Undo);
 			undo = new ToolButton (undo_info.StockId);
 			undo.Label = undo_info.Label;
@@ -118,7 +134,7 @@
 			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"), true);
 			ss_button.Clicked += HandleViewSlideshow;
 			ss_button.SetTooltip (toolTips, Catalog.GetString ("View photos in a slideshow"), null);
@@ -143,9 +159,10 @@
 			toolbar.Insert (next_image, -1);
 			next_image.TooltipText = Catalog.GetString ("Next photo");
 			next_image.Clicked += (sender, args) => { image_view.Item.MoveNext (); };
-
 			
-			collection = new UriCollection (uris);
+			collection = new UriCollection (uris_to_display.ToArray ());
+			collection.LoadingComplete += HandleCollectionLoadingComplete;
+			
 			undo_history = new UndoCache ();
 			undo_history.UndoStateChanged += HandleUndoStateChanged;
 
@@ -201,7 +218,7 @@
 			
 			Window.ShowAll ();
 
-			AddinManager.AddExtensionNodeHandler ("/FSpot/Sidebar", OnSidebarExtensionChanged);	
+			AddinManager.AddExtensionNodeHandler ("/FSpot/Sidebar", OnSidebarExtensionChanged);
 			sidebar.Context = ViewContext.Single;
 
 			zoom_scale.ValueChanged += HandleZoomScaleValueChanged;
@@ -237,14 +254,43 @@
 			UpdateStatusLabel ();
 			UpdateToolbar (image_view.Item.Collection);
 			
-			if (collection.Count > 0)
-				directory_view.Selection.Add (0);
+			if (collection.Count > 0) {
+				if (File.Exists (uris[0].AbsolutePath)) {
+					Log.Debug ("File {0} exists, displaying", uris[0].AbsolutePath);
+					var selected_image = collection.Items.FirstOrDefault ((item) => item.DefaultVersionUri == uris[0]);
+					if (selected_image != null) {
+						directory_view.Selection.Add (selected_image);
+					} else {
+						Log.Warning ("Unable to open requested file {0}", uris[0].AbsolutePath);
+					}
+				} else {
+					directory_view.Selection.Add (0);
+				}
+			}
 
 			export.Submenu = (Mono.Addins.AddinManager.GetExtensionNode ("/FSpot/Menus/Exports") as FSpot.Extensions.SubmenuNode).GetMenuItem (this).Submenu;
 			export.Submenu.ShowAll ();
 			export.Activated += HandleExportActivated ;
 		}
 
+		void HandleCollectionLoadingComplete (object sender, EventArgs e)
+		{
+			if (collection.Count > 0) {
+				if (File.Exists (Uri.UnescapeDataString (uri.AbsolutePath))) {
+					Log.Debug ("{0} exists, displaying", uri);
+					var selected_image = collection.Items.FirstOrDefault ((item) => item.DefaultVersionUri == uri);
+					
+					if (selected_image != null && directory_view != null) {
+						directory_view.Selection.Clear ();
+						directory_view.Selection.Add (selected_image);
+					}
+				} else {
+					Log.Warning ("Unable to open requested file {0}", uri);
+				}
+			}
+			collection.LoadingComplete -= HandleCollectionLoadingComplete;
+		}
+
 		void ToggleFilmstrip (bool enabled)
 		{
 			Gtk.Widget packed_filmstrip = display_vbox.AllChildren.Cast<Gtk.Widget> ().FirstOrDefault ((widget) => {return widget == filmstrip;});
Index: f-spot-0.6.1.5/src/UriCollection.cs
===================================================================
--- f-spot-0.6.1.5.orig/src/UriCollection.cs	2010-03-12 12:51:09.221817566 +1100
+++ f-spot-0.6.1.5/src/UriCollection.cs	2010-03-12 12:51:16.751832536 +1100
@@ -21,25 +21,31 @@
 
 namespace FSpot {
 	public class UriCollection : PhotoList {
-		public UriCollection () : base (new IBrowsableItem [0])
+		public UriCollection () : base(new IBrowsableItem[0])
 		{
+			loading_count = 0;
 		}
 
-		public UriCollection (System.IO.FileInfo [] files) : this ()
+		public UriCollection (System.IO.FileInfo[] files) : this()
 		{
+			loading_count = 0;
+			LoaderStarting ();
 			LoadItems (files);
 		}
 
-		public UriCollection (Uri [] uri) : this ()
+		public UriCollection (Uri[] uri) : this()
 		{
+			loading_count = 0;
 			LoadItems (uri);
 		}
 
 		public void Add (Uri uri)
 		{
+			LoaderStarting ();
 			if (FSpot.ImageFile.HasLoader (uri)) {
 				//Console.WriteLine ("using image loader {0}", uri.ToString ());
 				Add (new FileBrowsableItem (uri));
+				LoaderComplete ();
 			} else {
 				GLib.FileInfo info = FileFactory.NewForUri (uri).QueryInfo ("standard::type,standard::content-type", FileQueryInfoFlags.None, null);
 
@@ -57,13 +63,37 @@
 			}
 		}
 
-		public void LoadItems (Uri [] uris)
+		public void LoadItems (Uri[] uris)
 		{
+			// Prime the count with 1, so that if everything is synchronous the LoadingCount-- at the end
+			// will trigger LoadingComplete.
+			LoaderStarting ();
 			foreach (Uri uri in uris) {
 				Add (uri);
 			}
+			LoaderComplete ();
 		}
 
+		public event EventHandler LoadingComplete;
+		
+		int loading_count;
+		void LoaderStarting ()
+		{
+			System.Threading.Interlocked.Increment (ref loading_count);
+		}
+		
+		void LoaderComplete ()
+		{
+			if (System.Threading.Interlocked.Decrement (ref loading_count) == 0) {
+				FSpot.Utils.Log.Debug ("Final loader finished, triggering LoadingComplete signal");
+				var handler = LoadingComplete;
+				if (handler != null) {
+					handler (this, EventArgs.Empty);
+				}
+			}
+		}
+		
+		
 		private class RssLoader
 		{
 			public RssLoader (UriCollection collection, System.Uri uri)
@@ -74,15 +104,15 @@
 				ns.AddNamespace ("media", "http://search.yahoo.com/mrss/");
 				ns.AddNamespace ("pheed", "http://www.pheed.com/pheed/");
 				ns.AddNamespace ("apple", "http://www.apple.com/ilife/wallpapers");
-
+				
 				ArrayList items = new ArrayList ();
 				XmlNodeList list = doc.SelectNodes ("/rss/channel/item/media:content", ns);
 				foreach (XmlNode item in list) {
-					Uri image_uri = new Uri (item.Attributes ["url"].Value);
+					Uri image_uri = new Uri (item.Attributes["url"].Value);
 					System.Console.WriteLine ("flickr uri = {0}", image_uri.ToString ());
 					items.Add (new FileBrowsableItem (image_uri));
 				}
-
+				
 				if (list.Count < 1) {
 					list = doc.SelectNodes ("/rss/channel/item/pheed:imgsrc", ns);
 					foreach (XmlNode item in list) {
@@ -91,7 +121,7 @@
 						items.Add (new FileBrowsableItem (image_uri));
 					}
 				}
-
+				
 				if (list.Count < 1) {
 					list = doc.SelectNodes ("/rss/channel/item/apple:image", ns);
 					foreach (XmlNode item in list) {
@@ -100,7 +130,8 @@
 						items.Add (new FileBrowsableItem (image_uri));
 					}
 				}
-				collection.Add (items.ToArray (typeof (FileBrowsableItem)) as FileBrowsableItem []);
+				collection.Add (items.ToArray (typeof(FileBrowsableItem)) as FileBrowsableItem[]);
+				collection.LoaderComplete ();
 			}
 		}
 
@@ -120,7 +151,6 @@
 							     500,
 							     null,
 							     InfoLoaded);
-										    
 			}
 
 			void InfoLoaded (GLib.Object o, GLib.AsyncResult res)
@@ -132,13 +162,14 @@
 					if (FSpot.ImageFile.HasLoader (i))
 						items.Add (new FileBrowsableItem (i));
 				}
-				Gtk.Application.Invoke (items, System.EventArgs.Empty, delegate (object sender, EventArgs args) {
+				Gtk.Application.Invoke (items, System.EventArgs.Empty, delegate(object sender, EventArgs args) {
 					collection.Add (items.ToArray ());
+					collection.LoaderComplete ();
 				});
 			}
 		}
 
-		protected void LoadItems (System.IO.FileInfo [] files)
+		protected void LoadItems (System.IO.FileInfo[] files)
 		{
 			List<IBrowsableItem> items = new List<IBrowsableItem> ();
 			foreach (var f in files) {
@@ -149,6 +180,7 @@
 			}
 
 			list = items;
+			LoaderComplete ();
 			this.Reload ();
 		}
 	}
