Import from Gallery and import changes



Hi all,

I'm working on redoing how the importing works and adding support for importing from Gallery.  I'm looking for some feedback.  With these changes I'm hoping to solve some of the problems I see with the way it's currently done.  These being:

   * For me it wasn't completely obvious how it all worked until I had used it a couple of times.

   * The current interface doesn't allow much flexiblity as far as other import sources. Specificly, importing from Gallery (which this patch adds support for as well)


The second is much more important for me since I'm used to the current import dialog. The most immediate issue is with the recursive directories checkbox.  While it is cheap to switch between recursive/non-recursive on the local disk, that changes when the images are being fetched from a remote location. (And in a more abstract sense "recursive" may not even make sense)  I see a few other benefits to the new way of doing it.  Someone on IRC mentioned it would be nice to add an option to add a tag based on the directory it comes from.  In general features like these can be added without cluttering the UI for the other import types.


Things I don't like is that is is definitely a couple extra clicks.  It also seems to break a little bit from the design of the rest of the app which reuses windoes a lot.  What does everyone think of instead of the first dialog putting the source choices in a submenu under "Import"?  (How would that work for the "+" button in the bottom left?)


The current code isn't ready to be committed, this is more of a request for comments.

Current issues that I can think of right now:
   * Needs some more testing.
   * CameraSource doesn't work because I have no way to test it.
   * The Gallery import preferences have a lot of extra UI elements that need to be removed.
   * UI in general unpolished
   * Some of the labels could definitely be improved
   * Responsiveness is bad for Gallery imports (this was working nicely before, so I must have introduced something to slow it down)

See http://www.monnahan.com/f-spot/ for screenshots if you don't want to bother patching.

Oh, and apply the patch from inside the src/ dir. (It's against current CVS)

Thanks
Ben
Index: GalleryExport.cs
===================================================================
RCS file: /cvs/gnome/f-spot/src/GalleryExport.cs,v
retrieving revision 1.31
diff -u -r1.31 GalleryExport.cs
--- GalleryExport.cs	11 Dec 2005 19:04:50 -0000	1.31
+++ GalleryExport.cs	26 Jan 2006 18:02:52 -0000
@@ -74,6 +74,9 @@
 		Gallery gallery;
 		public Gallery Gallery {
 			get {
+				if (!Connected) {
+					Connect ();
+				}
 				return gallery;
 			}
 		}
@@ -123,20 +126,28 @@
 	public class GalleryAccountManager 
 	{
 		private static GalleryAccountManager instance;
+		public static GalleryAccountManager Instance {
+			get {
+				if (instance == null) {
+					instance = new GalleryAccountManager ();
+				}
+
+				return instance;
+			}
+		}
+
 		string xml_path;
+
 		ArrayList accounts;
+		public ArrayList Accounts {
+			get {
+				return accounts;
+			}
+		}
 
 		public delegate void AccountListChangedHandler (GalleryAccountManager manager);
 		public event AccountListChangedHandler AccountListChanged;
 		
-		public static GalleryAccountManager GetInstance ()
-		{
-			if (instance == null) {
-				instance = new GalleryAccountManager ();
-			}
-
-			return instance;
-		}
 
 		private GalleryAccountManager ()
 		{
@@ -153,11 +164,6 @@
 				AccountListChanged (this);
 		}
 
-		public ArrayList GetAccounts ()
-		{
-			return accounts;
-		}
-
 		public void AddAccount (GalleryAccount account)
 		{
 			AddAccount (account, true);
@@ -321,7 +327,7 @@
 									     url, 
 									     username,
 									     password);
-				GalleryAccountManager.GetInstance ().AddAccount (account);
+				GalleryAccountManager.Instance.AddAccount (account);
 			}
 			Dialog.Destroy ();
 		}
@@ -458,7 +464,7 @@
 			view.Show ();
 			Dialog.Show ();
 
-			GalleryAccountManager manager = GalleryAccountManager.GetInstance ();
+			GalleryAccountManager manager = GalleryAccountManager.Instance;
 			manager.AccountListChanged += PopulateGalleryOptionMenu;
 			PopulateGalleryOptionMenu (manager);
 			
@@ -617,7 +623,7 @@
 		{
 			Gtk.Menu menu = new Gtk.Menu ();
 			
-			accounts = manager.GetAccounts ();
+			accounts = manager.Accounts;
 			if (accounts == null || accounts.Count == 0) {
 				Gtk.MenuItem item = new Gtk.MenuItem (Mono.Posix.Catalog.GetString ("(No Gallery)"));
 				menu.Append (item);
@@ -652,7 +658,7 @@
 
 				dialog.Dialog.Destroy ();				
 				if (response == Gtk.ResponseType.Ok) {
-					GalleryAccountManager.GetInstance ().WriteAccounts ();
+					GalleryAccountManager.Instance.WriteAccounts ();
 					Connect ();
 				}
 			} 
Index: GalleryRemote.cs
===================================================================
RCS file: /cvs/gnome/f-spot/src/GalleryRemote.cs,v
retrieving revision 1.14
diff -u -r1.14 GalleryRemote.cs
--- GalleryRemote.cs	9 Dec 2005 15:40:41 -0000	1.14
+++ GalleryRemote.cs	26 Jan 2006 18:02:53 -0000
@@ -30,7 +30,6 @@
 		public int ParentRefNum;
 		public int ResizeSize;
 		public int ThumbSize;
-		public ArrayList Images = null;
 		public string BaseURL;
 		
 		Gallery gallery;
@@ -38,6 +37,22 @@
 		public AlbumPermission Perms = AlbumPermission.None;
 		Hashtable extras = null;
 
+		protected ArrayList images = null;
+		public ArrayList Images {
+			get {
+				if (images == null) {
+					Console.WriteLine ("Need to FetchAlbumImages for this album");
+					images = gallery.FetchAlbumImages (this, false);
+				}
+
+				return images;
+			}
+
+			set {
+				images = value;
+			}
+		}
+
 		public Album Parent {
 			get {
 				if (ParentRefNum != 0)
@@ -69,7 +84,6 @@
 			Name = name;
 			this.gallery = gallery;
 			this.RefNum = ref_num;
-			Images = new ArrayList ();
 		}
 		
 		public void Rename (string name) 
@@ -244,8 +258,11 @@
 		}
 
 		protected ArrayList albums;
-		public ArrayList Albums{
+		public ArrayList Albums {
 			get {
+				if (albums == null) {
+					FetchAlbums ();
+				}
 				return albums;
 			}
 		}
@@ -268,7 +285,6 @@
 		{
 			this.name = name;
 			cookies = new CookieContainer ();	       
-			albums = new ArrayList ();
 		}
 
 		public static GalleryVersion DetectGalleryVersion (string url)
@@ -738,8 +754,7 @@
 			client.Add ("set_albumName", album.Name);
 			client.Add ("albums_too", include_ablums ? "yes" : "no");
 			
-			album.Images = ParseFetchAlbumImages (client.Submit (uri), album);
-			return album.Images;
+			return ParseFetchAlbumImages (client.Submit (uri), album);
 		}
 		
 		public override ArrayList FetchAlbumsPrune ()
@@ -756,6 +771,7 @@
 
 		public ArrayList ParseFetchAlbumImages (HttpWebResponse response, Album album)
 		{
+			ArrayList parsed_images = new ArrayList ();
 			string [] data;
 			StreamReader reader = null;
 			ResultCode status = ResultCode.UnknownResponse;
@@ -771,7 +787,7 @@
 						Console.WriteLine ("StatusText : {0}", data[1]);
 					} else if (data[0].StartsWith ("image.name")) {
 						current_image = new Image (album, data[1]);
-						album.Images.Add (current_image);
+						parsed_images.Add (current_image);
 					} else if (data[0].StartsWith ("image.raw_width")) {
 						current_image.RawWidth = int.Parse (data[1]);
 					} else if (data[0].StartsWith ("image.raw_height")) {
@@ -811,8 +827,8 @@
 					} else if (data[0].StartsWith ("baseurl")) {
 						album.BaseURL = data[1];
 					} else if (data[0].StartsWith ("image_count")) {
-						if (album.Images.Count != int.Parse (data[1]))
-							Console.WriteLine ("Parsed image count for " + album.Name + "(" + album.Images.Count + ") does not match image_count (" + data[1] + ").  Something is amiss");
+						if (parsed_images.Count != int.Parse (data[1]))
+							Console.WriteLine ("Parsed image count for " + album.Name + "(" + parsed_images.Count + ") does not match image_count (" + data[1] + ").  Something is amiss");
 					} else {
 						Console.WriteLine ("Unparsed Line in ParseFetchAlbumImages(): {0}={1}", data[0], data[1]);
 					}
@@ -826,10 +842,11 @@
 
 				//Set the Urls for downloading the images.
 				string baseUrl = album.BaseURL + "/";
-				foreach (Image image in album.Images) {
+				foreach (Image image in parsed_images) {
 					image.Url = baseUrl + image.Name;
 				}
 
+				album.Images = parsed_images;
 				return album.Images;
 			} finally {
 				if (reader != null)
@@ -967,8 +984,7 @@
 			client.Add ("g2_form[albums_too]", include_ablums ? "yes" : "no");
 			AddG2Specific (client);
 			
-			album.Images = ParseFetchAlbumImages (client.Submit (uri), album);
-			return album.Images;
+			return ParseFetchAlbumImages (client.Submit (uri), album);
 		}
 		
 		public override ArrayList FetchAlbumsPrune ()
@@ -991,6 +1007,7 @@
 
 		public ArrayList ParseFetchAlbumImages (HttpWebResponse response, Album album)
 		{
+			ArrayList parsed_images = new ArrayList ();
 			string [] data;
 			StreamReader reader = null;
 			ResultCode status = ResultCode.UnknownResponse;
@@ -1008,7 +1025,7 @@
 					} else if (data[0].StartsWith ("image.name")) {
 						//for G2 this is the number used to download the image.
 						current_image = new Image (album, "awaiting 'title'");
-						album.Images.Add (current_image);
+						parsed_images.Add (current_image);
 						current_image.Url = baseUrl + data[1];
 					} else if (data[0].StartsWith ("image.title")) {
 						//for G2 the "title" is the name"
@@ -1054,8 +1071,8 @@
 					} else if (data[0].StartsWith ("baseurl")) {
 						album.BaseURL = data[1];
 					} else if (data[0].StartsWith ("image_count")) {
-						if (album.Images.Count != int.Parse (data[1]))
-							Console.WriteLine ("Parsed image count for " + album.Name + "(" + album.Images.Count + ") does not match image_count (" + data[1] + ").  Something is amiss");
+						if (parsed_images.Count != int.Parse (data[1]))
+							Console.WriteLine ("Parsed image count for " + album.Name + "(" + parsed_images.Count + ") does not match image_count (" + data[1] + ").  Something is amiss");
 					} else {
 						Console.WriteLine ("Unparsed Line in ParseFetchAlbumImages(): {0}={1}", data[0], data[1]);
 					}
@@ -1066,6 +1083,7 @@
 					throw new GalleryCommandException (status_text, status);
 				}
 
+				album.Images = parsed_images;
 				return album.Images;
 
 			} finally {
Index: ImportCommand.cs
===================================================================
RCS file: /cvs/gnome/f-spot/src/ImportCommand.cs,v
retrieving revision 1.45
diff -u -r1.45 ImportCommand.cs
--- ImportCommand.cs	24 Jan 2006 04:49:17 -0000	1.45
+++ ImportCommand.cs	26 Jan 2006 18:02:54 -0000
@@ -8,6 +8,280 @@
 using System;
 using Mono.Posix;
 
+class BrowseSource : ImportSource {
+	public BrowseSource ()
+	{
+		this.Name = Mono.Posix.Catalog.GetString ("Select Folder");
+		this.Icon = PixbufUtils.LoadThemeIcon ("stock_folder", 32);
+	}
+
+	public BrowseSource (string name, string icon)
+	{
+		this.Name = name;
+		this.Icon = PixbufUtils.LoadThemeIcon (icon, 32);
+	}
+}
+
+class VfsSource : ImportSource {
+	public string uri;
+
+	public VfsSource (string uri)
+	{ 
+		string [] components = uri.Split (new char [] { '/' });
+		this.Name = components [components.Length - 1];
+		if (this.Name == "")
+			this.Name = components [components.Length - 2];
+
+		this.uri = uri;
+		
+		this.Icon = PixbufUtils.LoadThemeIcon ("stock_folder", 32);
+	}
+
+	public virtual bool Contains (string path)
+	{
+		return false;
+	}
+
+	protected VfsSource () {}
+}
+
+class VolumeSource : VfsSource {
+	public Gnome.Vfs.Volume Volume;
+	public string mount_point;
+
+	public VolumeSource (Gnome.Vfs.Volume vol)
+	{
+		this.Volume = vol;
+		this.Name = vol.DisplayName.Replace ("_", "__");
+
+		try {
+			mount_point = new Uri (vol.ActivationUri).LocalPath;
+		} catch (System.Exception e) {
+			System.Console.WriteLine (e);
+		}
+
+		uri = mount_point;
+		
+		if (this.Icon == null)
+			this.Icon = PixbufUtils.LoadThemeIcon (vol.Icon, 32);
+		
+		if (this.IsiPodPhoto)
+			this.Icon = PixbufUtils.LoadThemeIcon ("gnome-dev-ipod", 32);
+
+		if (this.Icon == null)			if (this.Icon == null && this.IsCamera)
+			this.Icon = PixbufUtils.LoadThemeIcon ("gnome-dev-media-cf", 32);
+
+		try {
+			if (this.Icon == null)
+				this.Icon = new Gdk.Pixbuf (vol.Icon);
+		} catch (System.Exception e) {
+			System.Console.WriteLine (e.ToString ());
+		}
+	}
+
+	private bool IsCamera {
+		get {
+			try {
+				return (Directory.Exists (System.IO.Path.Combine (mount_point, "DCIM")));
+			} catch {
+				return false;
+			}
+		}
+	}
+
+	private bool IsiPodPhoto {
+		get {
+			try {
+				return (Directory.Exists (System.IO.Path.Combine (mount_point, "Photos")) &&
+					Directory.Exists (System.IO.Path.Combine (mount_point, "iPod_Control")));
+			} catch {
+				return false;
+			}
+		}
+	}
+}
+
+class DriveSource : ImportSource {
+	public Gnome.Vfs.Drive Drive;
+	
+	public DriveSource (Gnome.Vfs.Drive drive) 
+	{
+		this.Name = drive.DisplayName.Replace ("_", "__");
+		this.Drive = drive;
+
+		if (drive.IsMounted) {
+			this.Icon = PixbufUtils.LoadThemeIcon (drive.MountedVolume.Icon, 32);
+			//this.Sensitive = drive.MountedVolume.IsMounted;
+		} else {
+			this.Icon = PixbufUtils.LoadThemeIcon (drive.Icon, 32);
+		}
+	}
+}
+
+class CameraSource : ImportSource {
+	GPhotoCamera cam;
+	int CameraIndex;
+	
+	public CameraSource (GPhotoCamera cam, int index)
+	{
+		this.cam = cam;
+		this.CameraIndex = index;
+
+		//this.Name = String.Format ("{0} ({1})", cam.CameraList.GetName (index), cam.CameraList.GetValue (index));
+		this.Name = String.Format ("{0}", cam.CameraList.GetName (index));
+		this.Icon = PixbufUtils.LoadThemeIcon ("gnome-dev-camera", 32);
+		if (this.Icon == null)
+			this.Icon = PixbufUtils.LoadThemeIcon ("gnome-dev-media-cf", 32);
+	}
+
+	public string Port {
+		get {
+			return cam.CameraList.GetValue (CameraIndex);
+		}
+	}
+}
+
+class GallerySource : ImportSource {
+	public FSpot.GalleryAccount Account;
+	public GallerySource (FSpot.GalleryAccount account)
+	{
+		this.Name = "Gallery: " + account.Name;
+		this.Icon = null;
+		this.Account = account;
+	}
+
+}
+
+abstract class ImportSource {
+	public ImportBackend Backend;
+	public Gdk.Pixbuf Icon;
+	public string Name;
+}
+
+class ImportSourceChooser : FSpot.GladeDialog {
+
+	[Glade.Widget] Gtk.VBox import_source_main_box;
+	private Box sources_box = new VBox ();
+
+	int source_count;
+	private RadioButton buttonGroupButton = new RadioButton("Not used"); //this is to create the button group and avoid special logic in AddChoice()
+
+	private Hashtable choices;
+
+	public ImportSource Source;
+
+	public ImportSourceChooser () : base ("import_source_chooser") {
+		// Populate the source choices
+		choices = new Hashtable ();
+		import_source_main_box.PackStart(sources_box);
+		source_count = 0;
+		Gnome.Vfs.VolumeMonitor monitor = Gnome.Vfs.VolumeMonitor.Get ();
+		
+		AddChoice (new BrowseSource(), true);
+		
+		AddSeparator ();
+
+		foreach (Gnome.Vfs.Volume vol in monitor.MountedVolumes) {
+			System.Console.WriteLine ("{0} - {1} - {2} {3} {4} {5} {6}",
+						  vol.DisplayName, 
+						   vol.Icon, 
+						  vol.VolumeType.ToString (), 
+						  vol.ActivationUri, 
+						  vol.IsUserVisible,
+						  vol.IsMounted,
+						  vol.DeviceType);
+			
+			 if (vol.Drive != null)
+				 System.Console.WriteLine (vol.Drive.DeviceType.ToString ());
+			 
+#if true
+			 if (vol.IsUserVisible && vol.DeviceType != Gnome.Vfs.DeviceType.Unknown) {
+				 ImportSource source = new VolumeSource (vol);
+				 AddChoice (source);
+				 source_count++;
+			 }
+#else
+			 
+			 ImportSource source = new VolumeSource (vol);
+			 AddChoice (source);
+#endif
+		}
+
+
+		GPhotoCamera cam = new GPhotoCamera ();
+		cam.DetectCameras ();
+		
+		if (cam.CameraList.Count () > 0)
+			AddSeparator ();
+		
+		source_count += cam.CameraList.Count ();
+		for (int i = 0; i < cam.CameraList.Count (); i++) {
+			if (source_count == 1 || cam.CameraList.GetValue (i) != "usb:") {
+				ImportSource source = new CameraSource (cam, i);
+				AddChoice (source);
+			}
+		}
+
+		if (source_count == 0) {
+			ImportSource source = new BrowseSource (Mono.Posix.Catalog.GetString ("(No Cameras Detected)"),
+								"emblem-camera");
+			AddChoice (source, false);
+		}
+
+
+		AddSeparator ();
+
+		ArrayList accounts = FSpot.GalleryAccountManager.Instance.Accounts;
+		if (accounts.Count > 0) {
+
+			foreach (FSpot.GalleryAccount account in accounts) {
+				ImportSource gal_source = new GallerySource (account);
+				AddChoice (gal_source);
+			}
+		}
+		//FIXME Need to add an "Add New Gallery Account" option
+
+
+		/*
+		AddSeparator ();
+		
+		foreach (Gnome.Vfs.Drive drive in monitor.ConnectedDrives) {
+			ImportSource source = new DriveSource (drive);
+			AddChoice (source, drive.IsMounted);
+		}
+		*/
+
+		Dialog.ShowAll ();
+
+	}
+	private void AddChoice (ImportSource source) {
+		AddChoice (source, true);
+	}
+
+	private void AddChoice (ImportSource source, bool enabled) {
+		choices.Add(source.Name, source);
+
+		RadioButton radio = new RadioButton (buttonGroupButton, source.Name);
+		radio.Toggled += HandleSourceToggled;
+		if (!enabled) {
+			radio.Sensitive = false;
+		}
+
+		sources_box.PackStart (radio);
+	}
+
+	private void AddSeparator () {
+		sources_box.PackStart (new HSeparator ());
+	}
+
+	private void HandleSourceToggled(object sender, EventArgs args) {
+		Gtk.ToggleButton toggle_button = sender as Gtk.ToggleButton;
+		if (toggle_button.Active) {
+			Source = (ImportSource) choices [toggle_button.Label];
+		}
+	}
+}
+
 public class ImportCommand : FSpot.GladeDialog {
 	internal class SourceItem : ImageMenuItem {
 		public ImportSource Source;
@@ -22,6 +296,7 @@
 		}
 	} 
 
+	/*
 	internal class BrowseSource : ImportSource {
 		public BrowseSource ()
 		{
@@ -159,12 +434,26 @@
 		}
 	}
 
+	internal class GallerySource : ImportSource {
+		public FSpot.GalleryAccount Account;
+		public GallerySource (FSpot.GalleryAccount account)
+		{
+			this.Name = "Gallery: " + account.Name;
+			this.Icon = null;
+			this.Account = account;
+		}
+
+	}
+
 	internal abstract class ImportSource {
-		public object Backend;
+		public ImportBackend Backend;
 		public Gdk.Pixbuf Icon;
 		public string Name;
 	}
+	*/
 	
+	/* This not currently used in favor of ImportSourceChooser */
+	/*
 	private class SourceMenu : Gtk.Menu {
 		public int source_count;
 
@@ -226,6 +515,20 @@
 				item.Sensitive = false;
 				this.Append (item);
 			}
+
+
+			ArrayList accounts = FSpot.GalleryAccountManager.Instance.Accounts;
+			this.Append (new Gtk.SeparatorMenuItem ());
+			if (accounts.Count > 0) {
+
+				foreach (FSpot.GalleryAccount account in accounts) {
+					ImportSource gal_source = new GallerySource (account);
+					this.Append (new SourceItem (gal_source));
+				}
+			}
+			//FIXME Need to add an "Add New Gallery Account" option
+
+
 			/*
 			this.Append (new Gtk.SeparatorMenuItem ());
 			
@@ -236,7 +539,7 @@
 				item.Sensitive = drive.IsMounted;
 				this.Append (item);
 			}
-			*/
+			*------------------------/
 
 			this.ShowAll ();
 		}
@@ -261,7 +564,6 @@
 		public int FindItemPosition (string path)
 		{
 			Gtk.Widget [] children = this.Children;
-			System.Console.WriteLine ("looking for {0}", path);
 			for (int i = 0; i < children.Length; i++) {
 				if (children [i] is SourceItem) {
 					VfsSource vfs = ((SourceItem)(children [i])).Source as VfsSource;
@@ -272,6 +574,7 @@
 			return -1;
 		}
 	}		
+	*/
 	
 	private class PhotoGrid : Table {
 		const int NUM_COLUMNS = 5;
@@ -362,12 +665,13 @@
 
 
 	[Glade.Widget] Gtk.OptionMenu tag_option_menu;
-	[Glade.Widget] Gtk.OptionMenu source_option_menu;
+	//[Glade.Widget] Gtk.OptionMenu source_option_menu;
+	[Glade.Widget] Gtk.Label import_source_value_label;
 	[Glade.Widget] Gtk.ScrolledWindow icon_scrolled;
 	[Glade.Widget] Gtk.ScrolledWindow photo_scrolled;
 	[Glade.Widget] Gtk.CheckButton attach_check;
-	[Glade.Widget] Gtk.CheckButton recurse_check;
-	[Glade.Widget] Gtk.CheckButton copy_check;
+	//[Glade.Widget] Gtk.CheckButton recurse_check;
+	//[Glade.Widget] Gtk.CheckButton copy_check;
 	[Glade.Widget] Gtk.Button ok_button;
 	[Glade.Widget] Gtk.Image tag_image;
 	[Glade.Widget] Gtk.Label tag_label;
@@ -412,11 +716,22 @@
 
 	private void UpdateProgressBar (int count, int total)
 	{
+		string text = String.Format (loading_string, count, total);
+		UpdateProgressBar (count, total, text);
+	}
+	private void UpdateProgressBar (int count, int total, string text)
+	{
+		double percentage =(double) count / System.Math.Max (total, 1);
+		UpdateProgressBar (text, percentage);
+	}
+	private void UpdateProgressBar (string text, double percentage)
+	{
+		Console.WriteLine ("In UpdateProgressBar");
 		if (progress_bar == null)
 			return;
-
-		progress_bar.Text = String.Format (loading_string, count, total);
-		progress_bar.Fraction = (double) count / System.Math.Max (total, 1);
+		
+		progress_bar.Text = text;
+		progress_bar.Fraction = percentage;
 	}
 
 	private void HandleCollectionChanged (FSpot.IBrowsableCollection col)
@@ -478,20 +793,26 @@
 
 	private int DoImport (ImportBackend imp)
 	{
-		if (collection == null)
+		if (collection == null) {
+			Console.WriteLine ("collection is null, aborting DoImport()");
 			return 0;
+		}
 
 		this.importer = imp;
 		AllowFinish = false;
 		
 		total = importer.Prepare ();
 
-		if (total > 0)
+		if (total > 0) {
 			UpdateProgressBar (1, total);
-		
+		} else {
+			UpdateProgressBar ("No new pictures to import", 1);
+			return 0;
+		}
+
 		collection.Clear ();
 		collection.Capacity = total;
-
+		
 		cancelled = false;
 		FSpot.ThumbnailGenerator.Default.PushBlock ();
 
@@ -534,14 +855,6 @@
 		tag_option_menu.Sensitive = attach_check.Active;
 	}
 
-	public void HandleImportBrowse (object o, EventArgs args) 
-	{
-		string path = ChoosePath ();
-		if (path != null) {
-			SetImportPath (path);
-		}
-	}
-	
 	public string ChoosePath ()
 	{
 		string path = null;
@@ -580,60 +893,102 @@
 	
 	}
 
-	private void HandleSourceChanged (object sender, EventArgs args)
+	private bool PrepareSource (ref ImportSource source)
 	{
-		if (store == null || collection == null)
-			return;
-		
-		this.Cancel ();
-		this.copy = copy_check.Active;
-		AllowFinish = false;
-
-		Gtk.OptionMenu option = (Gtk.OptionMenu) sender;
-		Gtk.Menu menu = (Gtk.Menu)(option.Menu);
-		SourceItem item =  (SourceItem)(menu.Active);
-		System.Console.WriteLine ("item {0}", item);
-
-		if (!item.Sensitive)
-			return;
+		// prompt for import type specific information
+		if (source is BrowseSource) {
+			FSpot.VfsImportDialog vid = new FSpot.VfsImportDialog (null, true);
+			ResponseType response = (ResponseType) vid.Dialog.Run ();
+			if (response != ResponseType.Ok) {
+				return false;
+			}
 
-		if (item.Source is BrowseSource) {
-			string path = ChoosePath ();
+			string path = vid.path;
 			
 			if (path != null) {
-				SourceItem path_item = new SourceItem (new VfsSource (path));
-				menu.Prepend (path_item);
-				path_item.ShowAll ();
-				//option.SetHistory (0);
+				string [] pathimport =  {path};
+		
+				source = new VfsSource (path);
+				source.Backend = new FileImportBackend (store, pathimport, vid.copy, vid.recurse, null);
+
 				SetImportPath (path);
 			}
-		} else if (item.Source is VfsSource) {
-			VfsSource vfs = item.Source as VfsSource;
+
+		} else if (source is VfsSource) {
+			VfsSource vfs = source as VfsSource;
+
+			FSpot.VfsImportDialog vid = new FSpot.VfsImportDialog (vfs.Name, false);
+			Gtk.ResponseType response = (Gtk.ResponseType) vid.Dialog.Run ();
+			if (response != ResponseType.Ok) {
+				return false;
+			}
+
+			string [] pathimport =  {vfs.uri};
+			source.Backend = new FileImportBackend (store, pathimport, vid.copy, vid.recurse, null);
 			SetImportPath (vfs.uri);
-		} else if (item.Source is CameraSource) {
-			CameraSource csource = item.Source as CameraSource;
+
+		} else if (source is GallerySource) {
+			GallerySource galSource = source as GallerySource;
+			FSpot.GalleryImportDialog gid = new FSpot.GalleryImportDialog (galSource.Account);
+			gid.Dialog.Show ();
+			Gtk.ResponseType response = (Gtk.ResponseType) gid.Dialog.Run ();
+			gid.Dialog.Destroy ();
+			if (response == Gtk.ResponseType.Ok) {
+
+				GalleryImportBackend galleryBackend = new GalleryImportBackend (galSource.Account, MainWindow.Toplevel.Database, gid.downloadDir);
+				galleryBackend.AlbumsToImport = gid.selectedAlbums;
+				galleryBackend.ImportTitles = gid.importTitles;
+				galleryBackend.AlbumTag = gid.albumTag;
+				galleryBackend.CustomTagValue = gid.customTagValue;
+				galleryBackend.UpdateProgress += UpdateProgressBar;
+
+				galSource.Backend = galleryBackend;
+			} else {
+				return false;
+			}
+				
+		} else if (source is CameraSource) {
+			//FIXME This needs to be converted to be like the rest, or removed
+			Console.WriteLine("Warning: CameraSource not currently working");
+			return false;
+			/*
+			CameraSource csource = source as CameraSource;
 			string port = "gphoto2:" + csource.Port;
 			this.Cancel ();
 			this.Dialog.Destroy ();
 			MainWindow.Toplevel.ImportCamera (port);
+			*/
 		}
 
-		Start ();
-	}
-
-	private void HandleRecurseToggled (object sender, System.EventArgs args)
-	{
-		this.Cancel ();
-		while (Application.EventsPending ())
-			Application.RunIteration ();
-		this.Start ();
-	}
+		return true;
+	}	
 
-	public int ImportFromFile (PhotoStore store, string path)
+	public int ImportFromDialog (PhotoStore store, string path)
 	{
 		this.store = store;
-		this.CreateDialog ("import_dialog");
+
+		// Ask the user where to import from
+		ImportSourceChooser sourceChooser = new ImportSourceChooser ();
+		ResponseType response = (ResponseType) sourceChooser.Dialog.Run ();
+		sourceChooser.Dialog.Destroy ();
+		if (response != ResponseType.Ok ) {
+			return 0;
+		}
+
+		ImportSource source = sourceChooser.Source;
 		
+
+		// Gather type specific information
+		bool retval = PrepareSource (ref source);
+		if (!retval) {
+			return 0;
+		}
+
+
+		// Create the preview dialog
+		this.CreateDialog ("import_dialog");
+		//FIXME Update source.Name to be more informative for GallerySource (listing the albums)
+		import_source_value_label.Markup = "<b>" + source.Name + "</b>";
 		this.Dialog.TransientFor = main_window;
 		this.Dialog.WindowPosition = Gtk.WindowPosition.CenterOnParent;
 		this.Dialog.Response += HandleDialogResponse;
@@ -645,11 +1000,6 @@
 		this.Dialog.DefaultResponse = ResponseType.Ok;
 		
 		//import_folder_entry.Activated += HandleEntryActivate;
-		recurse_check.Toggled += HandleRecurseToggled;
-		copy_check.Toggled += HandleRecurseToggled;
-
-		SourceMenu menu = new SourceMenu ();
-		source_option_menu.Menu = menu;
 
 		collection = new FSpot.PhotoList (new Photo [0]);
 		collection.Changed += HandleCollectionChanged;
@@ -679,39 +1029,14 @@
 		}				
 
 		this.Dialog.Show ();
-		source_option_menu.Changed += HandleSourceChanged;
-		if (path != null) {
-			SetImportPath (path);
-			int i = menu.FindItemPosition (path);
-
-			if (i > 0) {
-				source_option_menu.SetHistory ((uint)i);
-			} else if (System.IO.Directory.Exists (path)) {
-				SourceItem path_item = new SourceItem (new VfsSource (path));
-				menu.Prepend (path_item);
-				path_item.ShowAll ();
-				SetImportPath (path);
-				source_option_menu.SetHistory (0);
-			} 
-		}
-						
-		ResponseType response = (ResponseType) this.Dialog.Run ();
-		
-		while (response == ResponseType.Ok) {
-			if (System.IO.Directory.Exists (this.ImportPath))
-			    break;
-
-			HigMessageDialog md = new HigMessageDialog (this.Dialog,
-								    DialogFlags.DestroyWithParent,
-								    MessageType.Error,
-								    ButtonsType.Ok,
-								    Mono.Posix.Catalog.GetString ("Directory does not exist."),
-									    String.Format (Mono.Posix.Catalog.GetString ("The directory you selected \"{0}\" does not exist.  Please choose a different directory"), this.ImportPath));
-			md.Run ();
-			md.Destroy ();
 
-			response = (Gtk.ResponseType) this.Dialog.Run ();
-		}
+
+		// do the import (everthing but finalize)
+		DoImport (source.Backend);
+
+
+		// Wait for user to import or cancel
+		response = (ResponseType) this.Dialog.Run ();
 
 		if (response == ResponseType.Ok) {
 			if (attach_check.Active && tag_selected != null) {
@@ -727,6 +1052,7 @@
 			}
 
 			this.Dialog.Destroy ();
+			//FIXME why do we call Destroy here and not in the else case?
 			return collection.Count;
 		} else {
 			this.Cancel ();
@@ -777,33 +1103,15 @@
 		store.Remove (photos);
 	}
 
-	public int Start ()
-	{
-		if (import_path == null)
-			return 0;
-
-		string [] pathimport =  {ImportPath};
-		//this.Dialog.Destroy();
-		
-		bool recurse = true;
-		if (recurse_check != null)
-			recurse = recurse_check.Active;
-		
-		if (collection == null)
-			return 0;
-
-		return DoImport (new FileImportBackend (store, pathimport, copy, recurse, null));
-	}
-
 	public int ImportFromPaths (PhotoStore store, string [] paths)
 	{
 		return ImportFromPaths (store, paths, null);
 	}
 
-    public int ImportFromPaths (PhotoStore store, string [] paths, bool copy)
-    {
-        return ImportFromPaths (store, paths, null, copy);
-    }
+	public int ImportFromPaths (PhotoStore store, string [] paths, bool copy)
+	{
+		return ImportFromPaths (store, paths, null, copy);
+	}
 
 	public int ImportFromPaths (PhotoStore store, string [] paths, Tag [] tags)
 	{
Index: MainWindow.cs
===================================================================
RCS file: /cvs/gnome/f-spot/src/MainWindow.cs,v
retrieving revision 1.265
diff -u -r1.265 MainWindow.cs
--- MainWindow.cs	17 Jan 2006 03:13:06 -0000	1.265
+++ MainWindow.cs	26 Jan 2006 18:02:56 -0000
@@ -18,7 +18,7 @@
 
 public class MainWindow {
 
-        public static MainWindow Toplevel;
+	public static MainWindow Toplevel;
 
 	Db db;
 
@@ -1005,7 +1005,7 @@
 	public void ImportFile (string path)
 	{
 		ImportCommand command = new ImportCommand (main_window);
-		if (command.ImportFromFile (db.Photos, path) > 0) {
+		if (command.ImportFromDialog (db.Photos, path) > 0) {
 			UpdateQuery ();
 		}
 	}
@@ -1183,9 +1183,11 @@
 
 	void HandleImportCommand (object sender, EventArgs e)
 	{
+		//show main window
+
 		db.Sync = false;
 		ImportCommand command = new ImportCommand (main_window);
-		if (command.ImportFromFile (db.Photos, this.last_import_path) > 0) {
+		if (command.ImportFromDialog (db.Photos, this.last_import_path) > 0) {
 			this.last_import_path = command.ImportPath;
 			UpdateQuery ();
 		}
@@ -1259,7 +1261,7 @@
 			cam.ReleaseGPhotoResources ();
 		}
 	}
-	
+
 	void HandlePrintCommand (object sender, EventArgs e)
 	{
 		new FSpot.PrintDialog (SelectedPhotos ());
Index: Preferences.cs
===================================================================
RCS file: /cvs/gnome/f-spot/src/Preferences.cs,v
retrieving revision 1.5
diff -u -r1.5 Preferences.cs
--- Preferences.cs	19 Jan 2006 01:06:27 -0000	1.5
+++ Preferences.cs	26 Jan 2006 18:02:56 -0000
@@ -41,6 +41,14 @@
 		public const string EXPORT_GALLERY_BROWSER = "/apps/f-spot/export/gallery/browser";
 		public const string EXPORT_GALLERY_META = "/apps/f-spot/export/gallery/meta";
 
+		public const string IMPORT_VFS_RECURSE =  "/apps/f-spot/import/vfs/recurse";
+		public const string IMPORT_VFS_COPY =  "/apps/f-spot/import/vfs/copy";
+
+		public const string IMPORT_GALLERY_DIRECTORY =  "/apps/f-spot/import/gallery/directory";
+		public const string IMPORT_GALLERY_TITLES =  "/apps/f-spot/import/gallery/titles";
+		public const string IMPORT_GALLERY_ALBUM_TAG =  "/apps/f-spot/import/gallery/album_tag";
+		public const string IMPORT_GALLERY_CUSTOM_TAG_VALUE =  "/apps/f-spot/import/gallery/custom_tag_value";
+
 		public const string METADATA_EMBED_IN_IMAGE = "/apps/f-spot/metadata/embed_in_image";
 
 		static GConf.Client client;
Index: Makefile.am
===================================================================
RCS file: /cvs/gnome/f-spot/src/Makefile.am,v
retrieving revision 1.56
diff -u -r1.56 Makefile.am
--- Makefile.am	24 Jan 2006 04:49:17 -0000	1.56
+++ Makefile.am	26 Jan 2006 18:02:57 -0000
@@ -48,6 +48,7 @@
 	$(srcdir)/FullScreenView.cs		\
 	$(srcdir)/GalleryRemote.cs		\
 	$(srcdir)/GalleryExport.cs		\
+	$(srcdir)/GalleryImportBackend.cs	\
 	$(srcdir)/GladeDialog.cs		\
 	$(srcdir)/Global.cs			\
 	$(srcdir)/GroupAdaptor.cs		\
@@ -60,6 +61,7 @@
 	$(srcdir)/ImageView.cs			\
 	$(srcdir)/ImportBackend.cs		\
 	$(srcdir)/ImportCommand.cs		\
+	$(srcdir)/ImportPreferences.cs		\
 	$(srcdir)/ImportStore.cs		\
 	$(srcdir)/InfoBox.cs			\
 	$(srcdir)/InfoDisplay.cs		\
Index: f-spot.glade
===================================================================
RCS file: /cvs/gnome/f-spot/src/f-spot.glade,v
retrieving revision 1.143
diff -u -r1.143 f-spot.glade
--- f-spot.glade	20 Jan 2006 07:29:59 -0000	1.143
+++ f-spot.glade	26 Jan 2006 18:03:12 -0000
@@ -9157,26 +9157,6 @@
 	  <property name="spacing">6</property>
 
 	  <child>
-	    <widget class="GtkCheckButton" id="recurse_check">
-	      <property name="visible">True</property>
-	      <property name="can_focus">True</property>
-	      <property name="label" translatable="yes">Include subdirectories</property>
-	      <property name="use_underline">True</property>
-	      <property name="relief">GTK_RELIEF_NORMAL</property>
-	      <property name="focus_on_click">True</property>
-	      <property name="active">True</property>
-	      <property name="inconsistent">False</property>
-	      <property name="draw_indicator">True</property>
-	    </widget>
-	    <packing>
-	      <property name="padding">0</property>
-	      <property name="expand">False</property>
-	      <property name="fill">False</property>
-	      <property name="pack_type">GTK_PACK_END</property>
-	    </packing>
-	  </child>
-
-	  <child>
 	    <widget class="GtkVBox" id="vbox65">
 	      <property name="visible">True</property>
 	      <property name="homogeneous">False</property>
@@ -9189,7 +9169,7 @@
 		  <property name="spacing">6</property>
 
 		  <child>
-		    <widget class="GtkLabel" id="import_label">
+		    <widget class="GtkLabel" id="import_source_label">
 		      <property name="visible">True</property>
 		      <property name="label" translatable="yes">Import Source:</property>
 		      <property name="use_underline">False</property>
@@ -9214,10 +9194,22 @@
 		  </child>
 
 		  <child>
-		    <widget class="GtkOptionMenu" id="source_option_menu">
+		    <widget class="GtkLabel" id="import_source_value_label">
 		      <property name="visible">True</property>
-		      <property name="can_focus">True</property>
-		      <property name="history">-1</property>
+		      <property name="label" translatable="yes">???</property>
+		      <property name="use_underline">False</property>
+		      <property name="use_markup">False</property>
+		      <property name="justify">GTK_JUSTIFY_LEFT</property>
+		      <property name="wrap">False</property>
+		      <property name="selectable">False</property>
+		      <property name="xalign">0.5</property>
+		      <property name="yalign">0.5</property>
+		      <property name="xpad">0</property>
+		      <property name="ypad">0</property>
+		      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+		      <property name="width_chars">-1</property>
+		      <property name="single_line_mode">False</property>
+		      <property name="angle">0</property>
 		    </widget>
 		    <packing>
 		      <property name="padding">0</property>
@@ -9433,25 +9425,6 @@
 	      <property name="fill">False</property>
 	    </packing>
 	  </child>
-
-	  <child>
-	    <widget class="GtkCheckButton" id="copy_check">
-	      <property name="visible">True</property>
-	      <property name="can_focus">True</property>
-	      <property name="label" translatable="yes">Copy file to the Photos folder</property>
-	      <property name="use_underline">True</property>
-	      <property name="relief">GTK_RELIEF_NORMAL</property>
-	      <property name="focus_on_click">True</property>
-	      <property name="active">True</property>
-	      <property name="inconsistent">False</property>
-	      <property name="draw_indicator">True</property>
-	    </widget>
-	    <packing>
-	      <property name="padding">0</property>
-	      <property name="expand">False</property>
-	      <property name="fill">False</property>
-	    </packing>
-	  </child>
 	</widget>
 	<packing>
 	  <property name="padding">0</property>
@@ -12758,6 +12731,966 @@
 	      <property name="padding">0</property>
 	      <property name="expand">True</property>
 	      <property name="fill">True</property>
+	    </packing>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">True</property>
+	  <property name="fill">True</property>
+	</packing>
+      </child>
+    </widget>
+  </child>
+</widget>
+
+<widget class="GtkDialog" id="import_source_chooser">
+  <property name="visible">True</property>
+  <property name="title" translatable="yes">Choose Source</property>
+  <property name="type">GTK_WINDOW_TOPLEVEL</property>
+  <property name="window_position">GTK_WIN_POS_NONE</property>
+  <property name="modal">False</property>
+  <property name="resizable">True</property>
+  <property name="destroy_with_parent">False</property>
+  <property name="decorated">True</property>
+  <property name="skip_taskbar_hint">False</property>
+  <property name="skip_pager_hint">False</property>
+  <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+  <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+  <property name="focus_on_map">True</property>
+  <property name="urgency_hint">False</property>
+  <property name="has_separator">True</property>
+
+  <child internal-child="vbox">
+    <widget class="GtkVBox" id="import_source_main_box">
+      <property name="visible">True</property>
+      <property name="homogeneous">False</property>
+      <property name="spacing">0</property>
+
+      <child internal-child="action_area">
+	<widget class="GtkHButtonBox" id="hbuttonbox13">
+	  <property name="visible">True</property>
+	  <property name="layout_style">GTK_BUTTONBOX_END</property>
+
+	  <child>
+	    <widget class="GtkButton" id="button28">
+	      <property name="visible">True</property>
+	      <property name="can_default">True</property>
+	      <property name="can_focus">True</property>
+	      <property name="label">gtk-cancel</property>
+	      <property name="use_stock">True</property>
+	      <property name="relief">GTK_RELIEF_NORMAL</property>
+	      <property name="focus_on_click">True</property>
+	      <property name="response_id">-6</property>
+	    </widget>
+	  </child>
+
+	  <child>
+	    <widget class="GtkButton" id="button29">
+	      <property name="visible">True</property>
+	      <property name="can_default">True</property>
+	      <property name="can_focus">True</property>
+	      <property name="label">gtk-ok</property>
+	      <property name="use_stock">True</property>
+	      <property name="relief">GTK_RELIEF_NORMAL</property>
+	      <property name="focus_on_click">True</property>
+	      <property name="response_id">-5</property>
+	    </widget>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">True</property>
+	  <property name="pack_type">GTK_PACK_END</property>
+	</packing>
+      </child>
+
+      <child>
+	<placeholder/>
+      </child>
+    </widget>
+  </child>
+</widget>
+
+<widget class="GtkDialog" id="import_vfs_dialog">
+  <property name="visible">True</property>
+  <property name="title" translatable="yes">Import</property>
+  <property name="type">GTK_WINDOW_TOPLEVEL</property>
+  <property name="window_position">GTK_WIN_POS_NONE</property>
+  <property name="modal">False</property>
+  <property name="resizable">True</property>
+  <property name="destroy_with_parent">False</property>
+  <property name="decorated">True</property>
+  <property name="skip_taskbar_hint">False</property>
+  <property name="skip_pager_hint">False</property>
+  <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+  <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+  <property name="focus_on_map">True</property>
+  <property name="urgency_hint">False</property>
+  <property name="has_separator">True</property>
+
+  <child internal-child="vbox">
+    <widget class="GtkVBox" id="vbox81">
+      <property name="visible">True</property>
+      <property name="homogeneous">False</property>
+      <property name="spacing">0</property>
+
+      <child internal-child="action_area">
+	<widget class="GtkHButtonBox" id="hbuttonbox14">
+	  <property name="visible">True</property>
+	  <property name="layout_style">GTK_BUTTONBOX_END</property>
+
+	  <child>
+	    <widget class="GtkButton" id="button30">
+	      <property name="visible">True</property>
+	      <property name="can_default">True</property>
+	      <property name="can_focus">True</property>
+	      <property name="label">gtk-cancel</property>
+	      <property name="use_stock">True</property>
+	      <property name="relief">GTK_RELIEF_NORMAL</property>
+	      <property name="focus_on_click">True</property>
+	      <property name="response_id">-6</property>
+	    </widget>
+	  </child>
+
+	  <child>
+	    <widget class="GtkButton" id="import_vfs_ok_button">
+	      <property name="visible">True</property>
+	      <property name="can_default">True</property>
+	      <property name="can_focus">True</property>
+	      <property name="label">gtk-ok</property>
+	      <property name="use_stock">True</property>
+	      <property name="relief">GTK_RELIEF_NORMAL</property>
+	      <property name="focus_on_click">True</property>
+	      <property name="response_id">-5</property>
+	    </widget>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">True</property>
+	  <property name="pack_type">GTK_PACK_END</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkVBox" id="vbox82">
+	  <property name="visible">True</property>
+	  <property name="homogeneous">False</property>
+	  <property name="spacing">0</property>
+
+	  <child>
+	    <widget class="GtkVBox" id="vbox83">
+	      <property name="border_width">6</property>
+	      <property name="visible">True</property>
+	      <property name="homogeneous">False</property>
+	      <property name="spacing">10</property>
+
+	      <child>
+		<widget class="GtkVBox" id="vbox84">
+		  <property name="visible">True</property>
+		  <property name="homogeneous">False</property>
+		  <property name="spacing">2</property>
+
+		  <child>
+		    <widget class="GtkLabel" id="label204">
+		      <property name="visible">True</property>
+		      <property name="label" translatable="yes">&lt;b&gt;Import From:&lt;/b&gt;</property>
+		      <property name="use_underline">False</property>
+		      <property name="use_markup">True</property>
+		      <property name="justify">GTK_JUSTIFY_LEFT</property>
+		      <property name="wrap">False</property>
+		      <property name="selectable">False</property>
+		      <property name="xalign">0</property>
+		      <property name="yalign">0.5</property>
+		      <property name="xpad">0</property>
+		      <property name="ypad">0</property>
+		      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+		      <property name="width_chars">-1</property>
+		      <property name="single_line_mode">False</property>
+		      <property name="angle">0</property>
+		    </widget>
+		    <packing>
+		      <property name="padding">0</property>
+		      <property name="expand">False</property>
+		      <property name="fill">False</property>
+		    </packing>
+		  </child>
+
+		  <child>
+		    <widget class="GtkHBox" id="hbox83">
+		      <property name="visible">True</property>
+		      <property name="homogeneous">False</property>
+		      <property name="spacing">0</property>
+
+		      <child>
+			<widget class="GtkLabel" id="import_vfs_path_label">
+			  <property name="visible">True</property>
+			  <property name="label" translatable="yes">(empty)</property>
+			  <property name="use_underline">False</property>
+			  <property name="use_markup">False</property>
+			  <property name="justify">GTK_JUSTIFY_LEFT</property>
+			  <property name="wrap">False</property>
+			  <property name="selectable">False</property>
+			  <property name="xalign">0.5</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			  <property name="width_chars">-1</property>
+			  <property name="single_line_mode">False</property>
+			  <property name="angle">0</property>
+			</widget>
+			<packing>
+			  <property name="padding">0</property>
+			  <property name="expand">True</property>
+			  <property name="fill">True</property>
+			</packing>
+		      </child>
+
+		      <child>
+			<widget class="GtkEntry" id="import_vfs_path_entry">
+			  <property name="visible">True</property>
+			  <property name="can_focus">True</property>
+			  <property name="editable">True</property>
+			  <property name="visibility">True</property>
+			  <property name="max_length">0</property>
+			  <property name="text" translatable="yes"></property>
+			  <property name="has_frame">True</property>
+			  <property name="invisible_char">*</property>
+			  <property name="activates_default">False</property>
+			</widget>
+			<packing>
+			  <property name="padding">1</property>
+			  <property name="expand">True</property>
+			  <property name="fill">True</property>
+			</packing>
+		      </child>
+
+		      <child>
+			<widget class="GtkButton" id="import_vfs_choosepath_button">
+			  <property name="visible">True</property>
+			  <property name="can_focus">True</property>
+			  <property name="label" translatable="yes">...</property>
+			  <property name="use_underline">True</property>
+			  <property name="relief">GTK_RELIEF_NORMAL</property>
+			  <property name="focus_on_click">True</property>
+			  <signal name="clicked" handler="HandleDirChooserClicked" last_modification_time="Fri, 18 Nov 2005 10:39:32 GMT"/>
+			</widget>
+			<packing>
+			  <property name="padding">2</property>
+			  <property name="expand">False</property>
+			  <property name="fill">False</property>
+			</packing>
+		      </child>
+		    </widget>
+		    <packing>
+		      <property name="padding">4</property>
+		      <property name="expand">False</property>
+		      <property name="fill">False</property>
+		    </packing>
+		  </child>
+		</widget>
+		<packing>
+		  <property name="padding">1</property>
+		  <property name="expand">False</property>
+		  <property name="fill">False</property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkVBox" id="vbox85">
+		  <property name="visible">True</property>
+		  <property name="homogeneous">False</property>
+		  <property name="spacing">4</property>
+
+		  <child>
+		    <widget class="GtkCheckButton" id="import_vfs_recurse_check">
+		      <property name="visible">True</property>
+		      <property name="can_focus">True</property>
+		      <property name="label" translatable="yes">Include subdirectories</property>
+		      <property name="use_underline">True</property>
+		      <property name="relief">GTK_RELIEF_NORMAL</property>
+		      <property name="focus_on_click">True</property>
+		      <property name="active">False</property>
+		      <property name="inconsistent">False</property>
+		      <property name="draw_indicator">True</property>
+		    </widget>
+		    <packing>
+		      <property name="padding">0</property>
+		      <property name="expand">False</property>
+		      <property name="fill">False</property>
+		    </packing>
+		  </child>
+
+		  <child>
+		    <widget class="GtkCheckButton" id="import_vfs_copy_check">
+		      <property name="visible">True</property>
+		      <property name="can_focus">True</property>
+		      <property name="label" translatable="yes">Copy file to the Photos folder</property>
+		      <property name="use_underline">True</property>
+		      <property name="relief">GTK_RELIEF_NORMAL</property>
+		      <property name="focus_on_click">True</property>
+		      <property name="active">False</property>
+		      <property name="inconsistent">False</property>
+		      <property name="draw_indicator">True</property>
+		    </widget>
+		    <packing>
+		      <property name="padding">0</property>
+		      <property name="expand">False</property>
+		      <property name="fill">False</property>
+		    </packing>
+		  </child>
+		</widget>
+		<packing>
+		  <property name="padding">6</property>
+		  <property name="expand">True</property>
+		  <property name="fill">True</property>
+		</packing>
+	      </child>
+	    </widget>
+	    <packing>
+	      <property name="padding">0</property>
+	      <property name="expand">True</property>
+	      <property name="fill">True</property>
+	    </packing>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">False</property>
+	</packing>
+      </child>
+    </widget>
+  </child>
+</widget>
+
+<widget class="GtkDialog" id="gallery_import_dialog">
+  <property name="title" translatable="yes">Import</property>
+  <property name="type">GTK_WINDOW_TOPLEVEL</property>
+  <property name="window_position">GTK_WIN_POS_NONE</property>
+  <property name="modal">False</property>
+  <property name="resizable">True</property>
+  <property name="destroy_with_parent">False</property>
+  <property name="decorated">True</property>
+  <property name="skip_taskbar_hint">False</property>
+  <property name="skip_pager_hint">False</property>
+  <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+  <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+  <property name="focus_on_map">True</property>
+  <property name="urgency_hint">False</property>
+  <property name="has_separator">False</property>
+
+  <child internal-child="vbox">
+    <widget class="GtkVBox" id="vbox68">
+      <property name="visible">True</property>
+      <property name="homogeneous">False</property>
+      <property name="spacing">0</property>
+
+      <child internal-child="action_area">
+	<widget class="GtkHButtonBox" id="hbuttonbox10">
+	  <property name="visible">True</property>
+	  <property name="layout_style">GTK_BUTTONBOX_END</property>
+
+	  <child>
+	    <widget class="GtkButton" id="button26">
+	      <property name="visible">True</property>
+	      <property name="can_default">True</property>
+	      <property name="can_focus">True</property>
+	      <property name="label">gtk-cancel</property>
+	      <property name="use_stock">True</property>
+	      <property name="relief">GTK_RELIEF_NORMAL</property>
+	      <property name="focus_on_click">True</property>
+	      <property name="response_id">-6</property>
+	    </widget>
+	  </child>
+
+	  <child>
+	    <widget class="GtkButton" id="ok_button">
+	      <property name="visible">True</property>
+	      <property name="can_default">True</property>
+	      <property name="can_focus">True</property>
+	      <property name="label">gtk-ok</property>
+	      <property name="use_stock">True</property>
+	      <property name="relief">GTK_RELIEF_NORMAL</property>
+	      <property name="focus_on_click">True</property>
+	      <property name="response_id">-5</property>
+	    </widget>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">True</property>
+	  <property name="pack_type">GTK_PACK_END</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkVBox" id="vbox72">
+	  <property name="visible">True</property>
+	  <property name="homogeneous">False</property>
+	  <property name="spacing">6</property>
+
+	  <child>
+	    <widget class="GtkFrame" id="frame44">
+	      <property name="visible">True</property>
+	      <property name="label_xalign">0</property>
+	      <property name="label_yalign">0.5</property>
+	      <property name="shadow_type">GTK_SHADOW_NONE</property>
+
+	      <child>
+		<widget class="GtkAlignment" id="alignment53">
+		  <property name="visible">True</property>
+		  <property name="xalign">0.5</property>
+		  <property name="yalign">0.5</property>
+		  <property name="xscale">1</property>
+		  <property name="yscale">1</property>
+		  <property name="top_padding">0</property>
+		  <property name="bottom_padding">0</property>
+		  <property name="left_padding">12</property>
+		  <property name="right_padding">0</property>
+
+		  <child>
+		    <widget class="GtkVBox" id="vbox73">
+		      <property name="visible">True</property>
+		      <property name="homogeneous">False</property>
+		      <property name="spacing">6</property>
+
+		      <child>
+			<widget class="GtkHBox" id="hbox74">
+			  <property name="visible">True</property>
+			  <property name="homogeneous">False</property>
+			  <property name="spacing">6</property>
+
+			  <child>
+			    <widget class="GtkLabel" id="label168">
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">Gallery:</property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">False</property>
+			      <property name="xalign">0.5</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="padding">0</property>
+			      <property name="expand">False</property>
+			      <property name="fill">False</property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkOptionMenu" id="gallery_import_accounts_optionmenu">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="history">-1</property>
+			      <signal name="changed" handler="HandleAccountSelected" last_modification_time="Fri, 08 Oct 2004 22:18:26 GMT"/>
+
+			      <child>
+				<widget class="GtkMenu" id="menu3">
+				</widget>
+			      </child>
+			    </widget>
+			    <packing>
+			      <property name="padding">0</property>
+			      <property name="expand">True</property>
+			      <property name="fill">True</property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkButton" id="gallery_import_add_account_button">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="label">gtk-add</property>
+			      <property name="use_stock">True</property>
+			      <property name="relief">GTK_RELIEF_NORMAL</property>
+			      <property name="focus_on_click">True</property>
+			      <signal name="clicked" handler="HandleAddGallery" last_modification_time="Fri, 08 Oct 2004 22:16:40 GMT"/>
+			    </widget>
+			    <packing>
+			      <property name="padding">0</property>
+			      <property name="expand">False</property>
+			      <property name="fill">False</property>
+			    </packing>
+			  </child>
+			</widget>
+			<packing>
+			  <property name="padding">0</property>
+			  <property name="expand">True</property>
+			  <property name="fill">True</property>
+			</packing>
+		      </child>
+
+		      <child>
+			<widget class="GtkLabel" id="label169">
+			  <property name="visible">True</property>
+			  <property name="label" translatable="yes"></property>
+			  <property name="use_underline">False</property>
+			  <property name="use_markup">False</property>
+			  <property name="justify">GTK_JUSTIFY_LEFT</property>
+			  <property name="wrap">False</property>
+			  <property name="selectable">False</property>
+			  <property name="xalign">0.5</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			  <property name="width_chars">-1</property>
+			  <property name="single_line_mode">False</property>
+			  <property name="angle">0</property>
+			</widget>
+			<packing>
+			  <property name="padding">0</property>
+			  <property name="expand">False</property>
+			  <property name="fill">False</property>
+			</packing>
+		      </child>
+		    </widget>
+		  </child>
+		</widget>
+	      </child>
+
+	      <child>
+		<widget class="GtkLabel" id="label170">
+		  <property name="visible">True</property>
+		  <property name="label" translatable="yes">&lt;b&gt;Gallery&lt;/b&gt;</property>
+		  <property name="use_underline">False</property>
+		  <property name="use_markup">True</property>
+		  <property name="justify">GTK_JUSTIFY_LEFT</property>
+		  <property name="wrap">False</property>
+		  <property name="selectable">False</property>
+		  <property name="xalign">0.5</property>
+		  <property name="yalign">0.5</property>
+		  <property name="xpad">0</property>
+		  <property name="ypad">0</property>
+		  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+		  <property name="width_chars">-1</property>
+		  <property name="single_line_mode">False</property>
+		  <property name="angle">0</property>
+		</widget>
+		<packing>
+		  <property name="type">label_item</property>
+		</packing>
+	      </child>
+	    </widget>
+	    <packing>
+	      <property name="padding">0</property>
+	      <property name="expand">False</property>
+	      <property name="fill">False</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkFrame" id="frame46">
+	      <property name="visible">True</property>
+	      <property name="label_xalign">0</property>
+	      <property name="label_yalign">0.5</property>
+	      <property name="shadow_type">GTK_SHADOW_NONE</property>
+
+	      <child>
+		<widget class="GtkAlignment" id="alignment55">
+		  <property name="visible">True</property>
+		  <property name="xalign">0.5</property>
+		  <property name="yalign">0.5</property>
+		  <property name="xscale">1</property>
+		  <property name="yscale">1</property>
+		  <property name="top_padding">0</property>
+		  <property name="bottom_padding">0</property>
+		  <property name="left_padding">12</property>
+		  <property name="right_padding">0</property>
+
+		  <child>
+		    <widget class="GtkVBox" id="vbox75">
+		      <property name="visible">True</property>
+		      <property name="homogeneous">False</property>
+		      <property name="spacing">6</property>
+
+		      <child>
+			<widget class="GtkHBox" id="hbox76">
+			  <property name="visible">True</property>
+			  <property name="homogeneous">False</property>
+			  <property name="spacing">0</property>
+
+			  <child>
+			    <widget class="GtkVBox" id="vbox76">
+			      <property name="visible">True</property>
+			      <property name="homogeneous">False</property>
+			      <property name="spacing">0</property>
+
+			      <child>
+				<widget class="GtkHBox" id="hbox77">
+				  <property name="visible">True</property>
+				  <property name="homogeneous">False</property>
+				  <property name="spacing">0</property>
+
+				  <child>
+				    <widget class="GtkLabel" id="label171">
+				      <property name="visible">True</property>
+				      <property name="label" translatable="yes">&lt;b&gt;Albums:&lt;/b&gt;</property>
+				      <property name="use_underline">False</property>
+				      <property name="use_markup">True</property>
+				      <property name="justify">GTK_JUSTIFY_LEFT</property>
+				      <property name="wrap">False</property>
+				      <property name="selectable">False</property>
+				      <property name="xalign">0.5</property>
+				      <property name="yalign">0.5</property>
+				      <property name="xpad">0</property>
+				      <property name="ypad">5</property>
+				      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+				      <property name="width_chars">-1</property>
+				      <property name="single_line_mode">False</property>
+				      <property name="angle">0</property>
+				    </widget>
+				    <packing>
+				      <property name="padding">0</property>
+				      <property name="expand">False</property>
+				      <property name="fill">False</property>
+				    </packing>
+				  </child>
+				</widget>
+				<packing>
+				  <property name="padding">0</property>
+				  <property name="expand">True</property>
+				  <property name="fill">True</property>
+				</packing>
+			      </child>
+
+			      <child>
+				<widget class="GtkHBox" id="hbox78">
+				  <property name="visible">True</property>
+				  <property name="homogeneous">False</property>
+				  <property name="spacing">0</property>
+
+				  <child>
+				    <placeholder/>
+				  </child>
+
+				  <child>
+				    <widget class="GtkScrolledWindow" id="scrolledwindow5">
+				      <property name="width_request">200</property>
+				      <property name="height_request">316</property>
+				      <property name="visible">True</property>
+				      <property name="can_focus">True</property>
+				      <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property>
+				      <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
+				      <property name="shadow_type">GTK_SHADOW_NONE</property>
+				      <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+				      <child>
+					<widget class="GtkTreeView" id="gallery_import_album_list_treeview">
+					  <property name="visible">True</property>
+					  <property name="can_focus">True</property>
+					  <property name="headers_visible">False</property>
+					  <property name="rules_hint">False</property>
+					  <property name="reorderable">False</property>
+					  <property name="enable_search">False</property>
+					  <property name="fixed_height_mode">False</property>
+					  <property name="hover_selection">False</property>
+					  <property name="hover_expand">False</property>
+					</widget>
+				      </child>
+				    </widget>
+				    <packing>
+				      <property name="padding">6</property>
+				      <property name="expand">True</property>
+				      <property name="fill">True</property>
+				    </packing>
+				  </child>
+				</widget>
+				<packing>
+				  <property name="padding">0</property>
+				  <property name="expand">True</property>
+				  <property name="fill">True</property>
+				  <property name="pack_type">GTK_PACK_END</property>
+				</packing>
+			      </child>
+
+			      <child>
+				<widget class="GtkRadioButton" id="gallery_import_all_radio">
+				  <property name="visible">True</property>
+				  <property name="can_focus">True</property>
+				  <property name="label" translatable="yes">All</property>
+				  <property name="use_underline">True</property>
+				  <property name="relief">GTK_RELIEF_NORMAL</property>
+				  <property name="focus_on_click">True</property>
+				  <property name="active">True</property>
+				  <property name="inconsistent">False</property>
+				  <property name="draw_indicator">True</property>
+				  <signal name="toggled" handler="HandleImportAllToggled" last_modification_time="Thu, 17 Nov 2005 11:18:46 GMT"/>
+				</widget>
+				<packing>
+				  <property name="padding">0</property>
+				  <property name="expand">False</property>
+				  <property name="fill">False</property>
+				</packing>
+			      </child>
+
+			      <child>
+				<widget class="GtkRadioButton" id="gallery_import_selected_radio">
+				  <property name="visible">True</property>
+				  <property name="can_focus">True</property>
+				  <property name="label" translatable="yes">Selected</property>
+				  <property name="use_underline">True</property>
+				  <property name="relief">GTK_RELIEF_NORMAL</property>
+				  <property name="focus_on_click">True</property>
+				  <property name="active">False</property>
+				  <property name="inconsistent">False</property>
+				  <property name="draw_indicator">True</property>
+				  <property name="group">gallery_import_all_radio</property>
+				  <signal name="toggled" handler="HandleImportSelectedToggled" last_modification_time="Thu, 17 Nov 2005 11:08:42 GMT"/>
+				</widget>
+				<packing>
+				  <property name="padding">0</property>
+				  <property name="expand">False</property>
+				  <property name="fill">False</property>
+				</packing>
+			      </child>
+			    </widget>
+			    <packing>
+			      <property name="padding">0</property>
+			      <property name="expand">False</property>
+			      <property name="fill">False</property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkVBox" id="vbox77">
+			      <property name="visible">True</property>
+			      <property name="homogeneous">False</property>
+			      <property name="spacing">0</property>
+
+			      <child>
+				<widget class="GtkLabel" id="label172">
+				  <property name="visible">True</property>
+				  <property name="label" translatable="yes">&lt;b&gt;Options:&lt;/b&gt;</property>
+				  <property name="use_underline">False</property>
+				  <property name="use_markup">True</property>
+				  <property name="justify">GTK_JUSTIFY_LEFT</property>
+				  <property name="wrap">False</property>
+				  <property name="selectable">False</property>
+				  <property name="xalign">0.5</property>
+				  <property name="yalign">0.5</property>
+				  <property name="xpad">0</property>
+				  <property name="ypad">5</property>
+				  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+				  <property name="width_chars">-1</property>
+				  <property name="single_line_mode">False</property>
+				  <property name="angle">0</property>
+				</widget>
+				<packing>
+				  <property name="padding">0</property>
+				  <property name="expand">False</property>
+				  <property name="fill">False</property>
+				</packing>
+			      </child>
+
+			      <child>
+				<widget class="GtkLabel" id="label173">
+				  <property name="visible">True</property>
+				  <property name="label" translatable="yes">Download directory</property>
+				  <property name="use_underline">False</property>
+				  <property name="use_markup">False</property>
+				  <property name="justify">GTK_JUSTIFY_LEFT</property>
+				  <property name="wrap">False</property>
+				  <property name="selectable">False</property>
+				  <property name="xalign">0.5</property>
+				  <property name="yalign">0.5</property>
+				  <property name="xpad">0</property>
+				  <property name="ypad">0</property>
+				  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+				  <property name="width_chars">-1</property>
+				  <property name="single_line_mode">False</property>
+				  <property name="angle">0</property>
+				</widget>
+				<packing>
+				  <property name="padding">0</property>
+				  <property name="expand">False</property>
+				  <property name="fill">False</property>
+				</packing>
+			      </child>
+
+			      <child>
+				<widget class="GtkHBox" id="hbox80">
+				  <property name="visible">True</property>
+				  <property name="homogeneous">False</property>
+				  <property name="spacing">0</property>
+
+				  <child>
+				    <widget class="GtkEntry" id="gallery_import_directory_entry">
+				      <property name="visible">True</property>
+				      <property name="can_focus">True</property>
+				      <property name="editable">True</property>
+				      <property name="visibility">True</property>
+				      <property name="max_length">0</property>
+				      <property name="text" translatable="yes"></property>
+				      <property name="has_frame">True</property>
+				      <property name="invisible_char">*</property>
+				      <property name="activates_default">False</property>
+				    </widget>
+				    <packing>
+				      <property name="padding">0</property>
+				      <property name="expand">True</property>
+				      <property name="fill">True</property>
+				    </packing>
+				  </child>
+
+				  <child>
+				    <widget class="GtkButton" id="gallery_import_dir_chooser_button">
+				      <property name="visible">True</property>
+				      <property name="can_focus">True</property>
+				      <property name="label" translatable="yes">...</property>
+				      <property name="use_underline">True</property>
+				      <property name="relief">GTK_RELIEF_NORMAL</property>
+				      <property name="focus_on_click">True</property>
+				      <signal name="clicked" handler="HandleDirChooserClicked" last_modification_time="Fri, 18 Nov 2005 10:39:32 GMT"/>
+				    </widget>
+				    <packing>
+				      <property name="padding">2</property>
+				      <property name="expand">False</property>
+				      <property name="fill">False</property>
+				    </packing>
+				  </child>
+				</widget>
+				<packing>
+				  <property name="padding">0</property>
+				  <property name="expand">False</property>
+				  <property name="fill">False</property>
+				</packing>
+			      </child>
+
+			      <child>
+				<placeholder/>
+			      </child>
+
+			      <child>
+				<widget class="GtkCheckButton" id="gallery_import_title_desc_check">
+				  <property name="visible">True</property>
+				  <property name="can_focus">True</property>
+				  <property name="label" translatable="yes">Import title and description</property>
+				  <property name="use_underline">True</property>
+				  <property name="relief">GTK_RELIEF_NORMAL</property>
+				  <property name="focus_on_click">True</property>
+				  <property name="active">True</property>
+				  <property name="inconsistent">False</property>
+				  <property name="draw_indicator">True</property>
+				</widget>
+				<packing>
+				  <property name="padding">0</property>
+				  <property name="expand">False</property>
+				  <property name="fill">False</property>
+				</packing>
+			      </child>
+
+			      <child>
+				<widget class="GtkCheckButton" id="gallery_import_album_tag_check">
+				  <property name="visible">True</property>
+				  <property name="can_focus">True</property>
+				  <property name="label" translatable="yes">Add tag with album title</property>
+				  <property name="use_underline">True</property>
+				  <property name="relief">GTK_RELIEF_NORMAL</property>
+				  <property name="focus_on_click">True</property>
+				  <property name="active">True</property>
+				  <property name="inconsistent">False</property>
+				  <property name="draw_indicator">True</property>
+				</widget>
+				<packing>
+				  <property name="padding">0</property>
+				  <property name="expand">False</property>
+				  <property name="fill">False</property>
+				</packing>
+			      </child>
+
+			      <child>
+				<widget class="GtkCheckButton" id="gallery_import_custom_tag_check">
+				  <property name="visible">True</property>
+				  <property name="can_focus">True</property>
+				  <property name="label" translatable="yes">Add custom tag</property>
+				  <property name="use_underline">True</property>
+				  <property name="relief">GTK_RELIEF_NORMAL</property>
+				  <property name="focus_on_click">True</property>
+				  <property name="active">False</property>
+				  <property name="inconsistent">False</property>
+				  <property name="draw_indicator">True</property>
+				</widget>
+				<packing>
+				  <property name="padding">0</property>
+				  <property name="expand">False</property>
+				  <property name="fill">False</property>
+				</packing>
+			      </child>
+
+			      <child>
+				<widget class="GtkHBox" id="hbox79">
+				  <property name="visible">True</property>
+				  <property name="homogeneous">False</property>
+				  <property name="spacing">0</property>
+
+				  <child>
+				    <placeholder/>
+				  </child>
+
+				  <child>
+				    <widget class="GtkEntry" id="gallery_import_custom_tag_entry">
+				      <property name="visible">True</property>
+				      <property name="can_focus">True</property>
+				      <property name="editable">True</property>
+				      <property name="visibility">True</property>
+				      <property name="max_length">0</property>
+				      <property name="text" translatable="yes"></property>
+				      <property name="has_frame">True</property>
+				      <property name="invisible_char">*</property>
+				      <property name="activates_default">False</property>
+				    </widget>
+				    <packing>
+				      <property name="padding">0</property>
+				      <property name="expand">True</property>
+				      <property name="fill">False</property>
+				    </packing>
+				  </child>
+				</widget>
+				<packing>
+				  <property name="padding">0</property>
+				  <property name="expand">False</property>
+				  <property name="fill">False</property>
+				</packing>
+			      </child>
+			    </widget>
+			    <packing>
+			      <property name="padding">0</property>
+			      <property name="expand">True</property>
+			      <property name="fill">False</property>
+			    </packing>
+			  </child>
+			</widget>
+			<packing>
+			  <property name="padding">0</property>
+			  <property name="expand">True</property>
+			  <property name="fill">True</property>
+			  <property name="pack_type">GTK_PACK_END</property>
+			</packing>
+		      </child>
+		    </widget>
+		  </child>
+		</widget>
+	      </child>
+	    </widget>
+	    <packing>
+	      <property name="padding">0</property>
+	      <property name="expand">False</property>
+	      <property name="fill">False</property>
 	    </packing>
 	  </child>
 	</widget>
--- /dev/null	2006-01-24 10:00:38.523813344 +0100
+++ ImportPreferences.cs	2006-01-17 10:41:38.000000000 +0100
@@ -0,0 +1,520 @@
+using System.Collections;
+using System;
+namespace FSpot {
+	public class VfsImportDialog : GladeDialog { 
+
+		[Glade.Widget] Gtk.Label import_vfs_path_label;
+		[Glade.Widget] Gtk.Entry import_vfs_path_entry;
+		[Glade.Widget] Gtk.Button import_vfs_choosepath_button;
+
+		[Glade.Widget] Gtk.CheckButton import_vfs_recurse_check;
+		[Glade.Widget] Gtk.CheckButton import_vfs_copy_check;
+
+		[Glade.Widget] Gtk.Button import_vfs_ok_button;
+
+		public bool recurse;
+		public bool copy;
+		public string path;
+
+		public VfsImportDialog (string path, bool path_modifiable) : base ("import_vfs_dialog") {
+			if (path == null) {
+				path = "";
+			}
+
+			this.path = path;
+
+			if (!path_modifiable) {
+				import_vfs_path_label.Markup = "<b>" + path + "</b>";
+				import_vfs_path_entry.Hide ();
+				import_vfs_choosepath_button.Hide ();
+			} else {
+				import_vfs_path_label.Hide ();
+				import_vfs_path_entry.Text = path;
+				HandleImportPathChanged(null, null);
+				import_vfs_path_entry.Changed += HandleImportPathChanged;
+			}
+			
+			LoadPreference (Preferences.IMPORT_VFS_RECURSE);
+			LoadPreference (Preferences.IMPORT_VFS_COPY);
+
+			Dialog.Response += HandleResponse;
+		}
+
+		private void LoadPreference (string key)
+		{
+			object val = Preferences.Get (key);
+
+			if (val == null)
+				return;
+			
+			//Console.WriteLine("Setting {0} to {1}", key, val);
+
+			switch (key) {
+				case Preferences.IMPORT_VFS_RECURSE:
+					if (import_vfs_recurse_check.Active != (bool) val)
+						import_vfs_recurse_check.Active = (bool) val;
+					break;
+
+				case Preferences.IMPORT_VFS_COPY:
+					if (import_vfs_copy_check.Active != (bool) val)
+						import_vfs_copy_check.Active = (bool) val;
+					break;
+			}
+		}
+
+		private void HandleDirChooserClicked (object sender, EventArgs args)
+		{
+			string path = ChoosePath ();
+			import_vfs_path_entry.Text = path;
+		}
+
+		private string ChoosePath ()
+		{
+			string path = null;
+
+			CompatFileChooserDialog fileSelector =
+				new CompatFileChooserDialog ("Choose Import Directory", this.Dialog,
+						CompatFileChooserDialog.Action.SelectFolder);
+
+			fileSelector.SelectMultiple = false;
+
+			//Set the initial directory based on what is in the entry.
+			string initialDir = import_vfs_path_entry.Text;
+			if (!System.IO.Directory.Exists(initialDir))
+				initialDir = Environment.GetEnvironmentVariable ("HOME");
+			fileSelector.Filename = initialDir;
+
+			int response = fileSelector.Run ();
+
+			if ((Gtk.ResponseType) response == Gtk.ResponseType.Ok) {
+				path = fileSelector.Filename;
+			}
+
+			fileSelector.Destroy ();
+			return path;
+		}
+
+		private void HandleImportPathChanged (object sender, EventArgs args)
+		{
+			// Make sure we have a valid directory to import from, otherwise disable the ok button.
+			string new_path = import_vfs_path_entry.Text;
+			if (new_path != "" && System.IO.Directory.Exists(new_path)) {
+				import_vfs_ok_button.Sensitive = true;
+			} else {
+				import_vfs_ok_button.Sensitive = false;
+			}
+		}
+
+		private void HandleResponse (object sender, Gtk.ResponseArgs args)
+		{
+			if (args.ResponseId != Gtk.ResponseType.Ok) {
+				Dialog.Destroy ();
+				return;
+			}
+
+
+			// Get the import options the user selected
+			path = import_vfs_path_entry.Text;
+			recurse = import_vfs_recurse_check.Active;
+			copy = import_vfs_copy_check.Active;
+
+
+			// Save these as the defaults for next time
+			Preferences.Set (Preferences.IMPORT_VFS_RECURSE, recurse);
+			Preferences.Set (Preferences.IMPORT_VFS_COPY, copy);
+
+			this.Dialog.Destroy ();
+		}
+
+	}
+
+	public class GalleryImportDialog : GladeDialog {
+		//Db db;
+
+		ArrayList accounts;
+		private GalleryAccount account;
+		private bool connect;
+
+		//private GalleryImportBackend importer;
+
+		Gtk.ListStore albumList;
+
+		public bool importTitles;
+		public bool albumTag;
+		public string customTagValue;
+		public string downloadDir;
+
+		public ArrayList selectedAlbums;
+		//ArrayList availableAlbums;
+
+		//int count;
+		//int total;
+
+		System.Threading.Thread command_thread;
+		FSpot.ThreadProgressDialog progress_dialog;
+
+		[Glade.Widget] Gtk.OptionMenu gallery_import_accounts_optionmenu;
+		[Glade.Widget] Gtk.Button gallery_import_add_account_button;
+
+		[Glade.Widget] Gtk.TreeView gallery_import_album_list_treeview;
+
+		[Glade.Widget] Gtk.RadioButton gallery_import_selected_radio;
+		[Glade.Widget] Gtk.RadioButton gallery_import_all_radio;
+
+		[Glade.Widget] Gtk.Entry gallery_import_directory_entry;
+		[Glade.Widget] Gtk.CheckButton gallery_import_title_desc_check;
+		[Glade.Widget] Gtk.CheckButton gallery_import_album_tag_check;
+		[Glade.Widget] Gtk.CheckButton gallery_import_custom_tag_check;
+		[Glade.Widget] Gtk.Entry gallery_import_custom_tag_entry;
+
+		//public GalleryImport (Db db) : base ("gallery_import_dialog")
+		public GalleryImportDialog () : this (null) {}
+		public GalleryImportDialog (GalleryAccount account) : base ("gallery_import_dialog")
+		{
+			//this.db = db;
+
+			Dialog.Modal = false;
+			Dialog.TransientFor = null;
+
+			GalleryAccountManager manager = GalleryAccountManager.Instance;
+			manager.AccountListChanged += PopulateGalleryOptionMenu;
+			PopulateGalleryOptionMenu (manager);
+			
+			if (account != null) {
+				int account_index = 0;
+				foreach (GalleryAccount a in GalleryAccountManager.Instance.Accounts) {
+					if (a == account) {
+						break;
+					}
+					account_index++;
+				}
+				gallery_import_accounts_optionmenu.SetHistory ((uint)account_index);
+				gallery_import_accounts_optionmenu.Sensitive = false;
+				gallery_import_add_account_button.Sensitive = false;
+				PopulateAlbumSelection(account.Gallery);
+			}
+
+
+			Dialog.Show ();
+
+			Dialog.Response += HandleResponse;
+
+			connect = true;
+			//Connect ();
+
+			Gtk.TreeViewColumn column = new Gtk.TreeViewColumn ();
+			column.Title = "Albums";
+			Gtk.CellRendererText renderer = new Gtk.CellRendererText();
+			column.PackStart (renderer, true);
+			column.AddAttribute(renderer, "text", 0);
+
+			gallery_import_album_list_treeview.AppendColumn (column);
+			gallery_import_all_radio.Toggle ();
+			gallery_import_album_list_treeview.Selection.Mode = Gtk.SelectionMode.Extended;
+
+			LoadPreference (Preferences.IMPORT_GALLERY_DIRECTORY);
+			LoadPreference (Preferences.IMPORT_GALLERY_TITLES);
+			LoadPreference (Preferences.IMPORT_GALLERY_ALBUM_TAG);
+			LoadPreference (Preferences.IMPORT_GALLERY_CUSTOM_TAG_VALUE);
+		}
+
+		private void LoadPreference (string key)
+		{
+			object val = Preferences.Get (key);
+
+			if (val == null)
+				return;
+			
+			//Console.WriteLine("Setting {0} to {1}", key, val);
+
+			switch (key) {
+			case Preferences.IMPORT_GALLERY_DIRECTORY:
+				if (gallery_import_directory_entry.Text != (string) val)
+					gallery_import_directory_entry.Text = (string) val;
+				break;
+			
+			case Preferences.IMPORT_GALLERY_ALBUM_TAG:
+				if (gallery_import_album_tag_check.Active != (bool) val)
+					gallery_import_album_tag_check.Active = (bool) val;
+				break;
+
+			case Preferences.IMPORT_GALLERY_TITLES:
+				if (gallery_import_title_desc_check.Active != (bool) val)
+					gallery_import_title_desc_check.Active = (bool) val;
+				break;
+
+			case Preferences.IMPORT_GALLERY_CUSTOM_TAG_VALUE:
+				if (val as string != "") {
+					if (gallery_import_custom_tag_entry.Text != (string) val)
+						gallery_import_custom_tag_entry.Text = (string) val;
+					gallery_import_custom_tag_check.Active = true;
+				}else {
+					gallery_import_custom_tag_check.Active = false;
+				}
+				break;
+			}
+		}
+
+		private void HandleAddGallery (object sender, EventArgs args)
+		{
+			new AccountDialog (this.Dialog);
+		}
+
+		private void HandleAccountSelected (object sender, EventArgs args)
+		{
+			Connect ();
+		}
+
+		private void HandleDirChooserClicked (object sender, EventArgs args)
+		{
+			string path = ChoosePath ();
+			gallery_import_directory_entry.Text = path;
+		}
+
+		private string ChoosePath ()
+		{
+			string path = null;
+
+			CompatFileChooserDialog fileSelector =
+				new CompatFileChooserDialog ("Download Directory", this.Dialog,
+						CompatFileChooserDialog.Action.SelectFolder);
+
+			fileSelector.SelectMultiple = false;
+
+			//Set the initial directory based on what is in the entry.
+			string initialDir = gallery_import_directory_entry.Text;
+			if (!System.IO.Directory.Exists(initialDir))
+				initialDir = Environment.GetEnvironmentVariable ("HOME");
+			fileSelector.Filename = initialDir;
+
+			int response = fileSelector.Run ();
+
+			if ((Gtk.ResponseType) response == Gtk.ResponseType.Ok) {
+				path = fileSelector.Filename;
+			}
+
+			fileSelector.Destroy ();
+			return path;
+		}
+
+		private void HandleResponse (object sender, Gtk.ResponseArgs args)
+		{
+			if (args.ResponseId != Gtk.ResponseType.Ok) {
+				Dialog.Destroy ();
+				return;
+			}
+
+			// Make sure we have a valid directory to download to
+			string dirEntryText = gallery_import_directory_entry.Text;
+			if (!DirWriteable(dirEntryText)) {
+				try {
+					//see if we can create it
+					System.IO.Directory.CreateDirectory(dirEntryText);
+
+				} catch (Exception e) {
+					//Pop up an error message
+					Console.WriteLine ("Exception with the Gallery import download directory: " + e);
+					Gtk.MessageDialog md = new Gtk.MessageDialog (this.Dialog, Gtk.DialogFlags.DestroyWithParent, Gtk.MessageType.Info, Gtk.ButtonsType.Close, "Please set download directory to one that is writeable by you.");
+					md.Run ();
+					md.Destroy();
+
+					return;
+				}
+
+			}
+			downloadDir = dirEntryText;
+
+
+			// Create a list of albums to import, or null if all
+			if (gallery_import_selected_radio.Active) {
+				selectedAlbums = new ArrayList ();
+
+				Gtk.TreeSelection selection = gallery_import_album_list_treeview.Selection;	
+				Gtk.TreePath[] list = selection.GetSelectedRows();
+				Gtk.TreeIter iter;
+				for(int i=0; i < list.Length; i++) {
+					albumList.GetIter(out iter, list[i]);
+					if ( selection.IterIsSelected(iter)) {
+						string albumName= albumList.GetValue(iter, 1) as string;
+						selectedAlbums.Add(albumName);
+						//Console.WriteLine("Added ablum " + albumName + " to the import list");
+					}
+				}
+
+			} else {
+				selectedAlbums = null;
+			}
+
+
+			// Get the import options the user selected
+			albumTag = gallery_import_album_tag_check.Active;
+			importTitles = gallery_import_title_desc_check.Active;
+
+			if (gallery_import_custom_tag_check.Active)
+				customTagValue = gallery_import_custom_tag_entry.Text;
+			else
+				customTagValue = null;
+
+			// Save these as the defaults for next time
+			Preferences.Set (Preferences.IMPORT_GALLERY_DIRECTORY, downloadDir);
+			Preferences.Set (Preferences.IMPORT_GALLERY_TITLES, importTitles);
+			Preferences.Set (Preferences.IMPORT_GALLERY_ALBUM_TAG, albumTag);
+			Preferences.Set (Preferences.IMPORT_GALLERY_CUSTOM_TAG_VALUE, customTagValue);
+
+			this.Dialog.Destroy ();
+			
+			//gallerySource.Backend = new GalleryImportBackend(account, db, selectedAlbums, downloadDir, importTitles, albumTag, customTagValue);
+
+			/*
+			// Do the import
+			if (account != null) { 
+				Dialog.Destroy ();
+
+				command_thread = new System.Threading.Thread (new System.Threading.ThreadStart (this.Import));
+				command_thread.Name = Mono.Posix.Catalog.GetString ("Importing Albums");
+				
+				int numAlbums = selectedAlbums == null ? availableAlbums.Count : selectedAlbums.Count;
+				progress_dialog = new FSpot.ThreadProgressDialog (command_thread, numAlbums);
+				progress_dialog.Response += HandleProgressResponse;
+				progress_dialog.Start ();
+
+			}
+			*/
+		}
+
+		private bool DirWriteable (string dir)
+		{ 
+			if (!System.IO.Directory.Exists(dir))
+				return false;
+
+			//FIXME Add a check for ability to write to the dir
+
+			return true;
+			
+		}
+
+		/*
+		private void Import()
+		{
+			progress_dialog.Message = "Preparing";
+
+			count = 0;
+			importer = new GalleryImportBackend(account, db, selectedAlbums, downloadDir, importTitles, albumTag, customTagValue);
+			total = importer.Prepare ();
+			
+			try {
+				SetProgress(0, total, Mono.Posix.Catalog.GetString ("Starting import"));
+				Photo photo;
+				Gdk.Pixbuf thumbnail;
+				for(int i = 0; i < total; i++) {
+					lock (progress_dialog.ThreadSync) {
+						importer.Step (out photo, out thumbnail, out count);
+					}
+					SetProgress(i+1, total, String.Format (Mono.Posix.Catalog.GetString ("Imported picture \"{0}\""), photo.Name));
+				}
+
+				importer.Finish ();
+
+				SetProgress(total, total, Mono.Posix.Catalog.GetString ("Done Importing Photos"));
+				progress_dialog.ButtonLabel = Gtk.Stock.Ok;
+			} catch (Exception e) {
+				progress_dialog.Message = e.ToString ();
+				progress_dialog.ProgressText = Mono.Posix.Catalog.GetString ("Error Importing From Gallery");
+			}
+		}
+
+		private void SetProgress(int count, int total, string message)
+		{
+				progress_dialog.Message = message;
+				progress_dialog.Fraction = count / (double) total;
+				progress_dialog.ProgressText = String.Format (Mono.Posix.Catalog.GetString ("{0} of {1}"), count, total);
+		}
+
+		private void HandleProgressResponse (object obj, Gtk.ResponseArgs args)
+		{
+			if (progress_dialog.ButtonLabel != Gtk.Stock.Ok) {
+				progress_dialog.Message = "Cancelling";
+				importer.Cancel();
+			}
+		}
+		*/
+
+		private void Connect ()
+		{
+			try {
+				if (accounts.Count != 0 && connect) {
+					account = (GalleryAccount) accounts [gallery_import_accounts_optionmenu.History];
+					
+					if (!account.Connected)
+						account.Connect ();
+
+					PopulateAlbumSelection(account.Gallery);
+				}
+			} catch (Exception ex) {
+				PopulateAlbumSelection(account.Gallery);
+				
+				
+				AccountDialog dialog = new AccountDialog (this.Dialog, account);
+				Gtk.ResponseType response = (Gtk.ResponseType) dialog.Dialog.Run ();
+
+				dialog.Dialog.Destroy ();				
+				if (response == Gtk.ResponseType.Ok) {
+					GalleryAccountManager.Instance.WriteAccounts ();
+					Connect ();
+				}
+			
+			} 
+		}
+
+		private void PopulateGalleryOptionMenu (GalleryAccountManager manager)
+		{
+			Gtk.Menu menu = new Gtk.Menu ();
+			
+			accounts = manager.Accounts;
+			if (accounts == null || accounts.Count == 0) {
+				Gtk.MenuItem item = new Gtk.MenuItem (Mono.Posix.Catalog.GetString ("(No Gallery)"));
+				menu.Append (item);
+				gallery_import_accounts_optionmenu.Sensitive = false;
+			} else {
+				foreach (GalleryAccount account in accounts) {
+					Gtk.MenuItem item = new Gtk.MenuItem (account.Name);
+					menu.Append (item);		
+				}
+				
+				gallery_import_accounts_optionmenu.Sensitive = true;
+			}
+
+			menu.ShowAll ();
+			gallery_import_accounts_optionmenu.Menu = menu;
+		}
+
+		private void PopulateAlbumSelection(GalleryRemote.Gallery gallery) {
+			Console.WriteLine("Updating the album list");
+			//availableAlbums = null;
+			
+			albumList = new Gtk.ListStore (typeof (string), typeof (string));
+			gallery_import_album_list_treeview.Model = albumList;
+			gallery_import_album_list_treeview.Show ();
+
+			if (gallery != null && gallery.Albums != null) {
+				foreach (GalleryRemote.Album album in gallery.Albums) {
+					albumList.AppendValues (album.Title, album.Name);
+				}
+			}
+		}
+
+		private void HandleImportAllToggled(object sender, EventArgs args) {
+			if ((sender as Gtk.CheckButton).Active) {
+				gallery_import_album_list_treeview.Selection.UnselectAll ();
+				gallery_import_album_list_treeview.Sensitive = false;
+			}
+		}
+
+		private void HandleImportSelectedToggled (object sender, EventArgs args) {
+			if ((sender as Gtk.CheckButton).Active) {
+				gallery_import_album_list_treeview.Sensitive = true;
+			}
+		}
+
+	}
+}
--- /dev/null	2006-01-24 10:00:38.523813344 +0100
+++ GalleryImportBackend.cs	2005-12-22 21:35:47.000000000 +0100
@@ -0,0 +1,256 @@
+using System.Collections;
+using System;
+using FSpot;
+
+
+public class GalleryImportBackend : ImportBackend {
+	private Db db;
+	private GalleryAccount account;
+	public string DownloadDir; 
+
+	public ArrayList AlbumsToImport;
+
+	public bool ImportTitles; 
+	public bool AlbumTag; 
+	public string CustomTagValue; 
+
+	public delegate void ProgressChangedHandler (int count, int total, string message);
+	public event ProgressChangedHandler UpdateProgress;
+	bool cancelled = false;
+
+	private ArrayList downloadedImages;
+	private ArrayList importedPhotos;
+	private int count = 0;
+
+	public GalleryImportBackend (GalleryAccount account, Db db, string downloadDir) : this (account, db, downloadDir, null, true, true, null) {}
+	public GalleryImportBackend (GalleryAccount account, Db db, string downloadDir, ArrayList albumsToImport, bool importTitles, bool albumTag, string customTagValue)
+	{
+		Console.WriteLine("GalleryImportBackend constructor");
+		this.account = account;
+		this.db = db;
+		this.DownloadDir = downloadDir;
+		this.AlbumsToImport = albumsToImport;
+		this.ImportTitles = importTitles;
+		this.AlbumTag = albumTag;
+		this.CustomTagValue = customTagValue;
+	}
+
+	public override int Prepare ()
+	{
+		if (downloadedImages != null)
+			throw new Exception ("Busy");
+
+		Console.WriteLine("Preparing");
+		downloadedImages = new ArrayList ();
+		importedPhotos = new ArrayList ();
+
+		GalleryRemote.Gallery gallery = account.Gallery;
+
+		if (AlbumsToImport == null) {
+			Console.WriteLine ("Importing all albums");
+			// import all albums
+			foreach (GalleryRemote.Album album in gallery.Albums) {
+				PrepareAlbum(gallery, album);
+			}
+
+		} else {
+			Console.WriteLine ("Importing selected albums");
+			// import selected albums
+			foreach (string albumName in AlbumsToImport) {
+				GalleryRemote.Album album = gallery.LookupAlbum(albumName);
+				PrepareAlbum(gallery, album);
+			}
+		}
+
+		DoProgressUpdate (downloadedImages.Count, downloadedImages.Count, "Finished downloading new images:");
+		
+		if (cancelled) {
+			return -1;
+		} else {
+			return downloadedImages.Count;
+		}
+	}
+	
+	private void PrepareAlbum (GalleryRemote.Gallery gallery, GalleryRemote.Album album)
+	{
+		if(album == null) {
+			throw new Exception ("Trying to call PrepareAlbum on a null album");
+		}
+
+		int numImages = album.Images.Count;
+
+		//make sure the location where the image will go exists
+		string albumImageDir = GetDirectory(album);
+		System.IO.Directory.CreateDirectory(albumImageDir);
+
+		Console.WriteLine("Preparing to import " + numImages + " images from: " + album.Name);
+		int count = 0;
+		string baseMessageString = "Downloading images from album {0}";
+		string message = String.Format (Mono.Posix.Catalog.GetString (baseMessageString), album.Title);
+		DoProgressUpdate (count, numImages, message);
+		LetEventsHappen (300);
+
+		foreach (GalleryRemote.Image image in album.Images) {
+			lock (this) {
+				if (cancelled)
+					return;
+
+				//save image to disk skipping the files that already exist.
+				string filename = GetFilename(image);
+				if (!System.IO.File.Exists(filename)) {
+					System.Console.WriteLine("Fetching " + image.Url + " to " + filename);
+					System.Net.WebClient Client = new System.Net.WebClient ();
+
+					downloadedImages.Add (image);
+					Client.DownloadFile(image.Url, filename);
+
+					LetEventsHappen (100);
+
+				}
+			}
+
+			message = String.Format (Mono.Posix.Catalog.GetString (baseMessageString + ": {1} of {2}"), album.Title, count+1, numImages);
+			DoProgressUpdate (count+1, numImages, message);
+			count++;
+		}
+
+	}
+
+	private void LetEventsHappen (int maxDurationInMS)
+	{
+		//Let the events stuff work
+		System.DateTime start_time = System.DateTime.Now;
+		System.TimeSpan span = start_time - start_time;
+		while (Gtk.Application.EventsPending () && span.TotalMilliseconds < maxDurationInMS) {
+			span = System.DateTime.Now - start_time;
+			Gtk.Application.RunIteration ();
+		}
+	}
+
+	private void DoProgressUpdate (int count, int total, string message)
+	{
+		Console.WriteLine ("Trying to update progress");
+		if (UpdateProgress != null) {
+			UpdateProgress (count, total, message);
+		}
+	}
+
+	private string GetDirectory (GalleryRemote.Album album)
+	{
+		return DownloadDir + "/" + album.Title; 
+	}
+	private string GetFilename (GalleryRemote.Image image)
+	{
+		return GetDirectory (image.Owner) + "/" + image.Name;
+	}
+
+	public override bool Step (out Photo photo, out Gdk.Pixbuf thumbnail, out int count)
+	{
+		if (downloadedImages == null)
+			throw new Exception ("Prepare() was not called before calling Step()");
+
+		GalleryRemote.Image image = downloadedImages [this.count] as GalleryRemote.Image;
+		GalleryRemote.Album album = image.Owner;
+
+		lock (this) {
+			if (cancelled)
+				return false;
+
+			photo = db.Photos.Create (GetFilename (image), out thumbnail);
+
+			if (ImportTitles) {
+				string str = "";
+
+				if (image.Caption != null && image.Caption.Length > 0) {
+					str = image.Caption;
+				}
+
+				if (image.Description != null && image.Description.Length > 0) {
+					str = str + "::: " + image.Description;
+				}
+
+				photo.Description = str;
+			}
+
+			if (AlbumTag)
+				photo.AddTag (CreateTag (album.Title));
+
+			if (CustomTagValue != null)
+				photo.AddTag (CreateTag (CustomTagValue));
+			
+
+			db.Photos.Commit(photo);
+			importedPhotos.Add (photo);
+		}
+
+		this.count ++;
+		count = this.count;
+
+		return count != downloadedImages.Count;
+	}
+
+	private Tag CreateTag(string tagname) {
+
+		Tag t = db.Tags.GetTagByName (tagname);
+		if (t == null) {
+			t = db.Tags.CreateCategory (null, tagname);
+			db.Tags.Commit (t);
+		}
+
+		return t;
+	}
+
+	public override void Cancel ()
+	{
+		if (downloadedImages == null)
+			throw new Exception ("Not doing anything");
+			
+		lock (this) {
+			cancelled = true;
+
+			foreach (GalleryRemote.Image image in downloadedImages) {
+				string filename = GetFilename(image);
+				// remove the image file from the system
+				try {
+					System.IO.File.Delete (filename);
+				} catch (Exception e) {
+					Console.WriteLine (e);
+				}
+
+				// if photo dir is empty remove it
+				try {
+					System.IO.Directory.Delete (GetDirectory(image.Owner));	
+				} catch (System.IO.IOException e) {
+					// directory not empty, no big deal
+				}
+			}
+				
+			foreach (Photo p in importedPhotos) {
+				db.Photos.Remove (p);
+			}
+
+			importedPhotos.Clear ();
+		}
+
+		Finish ();
+
+	}
+
+	public override void Finish ()
+	{
+		lock (this) {
+			if (downloadedImages == null)
+				throw new Exception ("Not doing anything");
+
+			downloadedImages = null;
+
+			foreach (Photo p in importedPhotos) {
+				Console.WriteLine("Finalizing: " + p.Name);
+				FSpot.ThumbnailGenerator.Default.Request (p.DefaultVersionPath, 0, 256, 256);
+			}
+
+			importedPhotos = null;
+			count = 0;
+		}
+	}
+}



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