diff --exclude CVS -urN f-spot/src/GnomeVfs.cs f-spot-open-with-menu/src/GnomeVfs.cs
--- f-spot/src/GnomeVfs.cs	1970-01-01 01:00:00.000000000 +0100
+++ f-spot-open-with-menu/src/GnomeVfs.cs	2004-10-26 19:43:13.361018465 +0100
@@ -0,0 +1,131 @@
+// created on 10/26/2004 at 14:46
+namespace GnomeVfs {
+	using GLib;
+	using System;
+	using System.Runtime.InteropServices;
+	using System.Diagnostics;
+
+	class Init {
+		[DllImport("gnomevfs-2")]
+		static extern bool gnome_vfs_init();
+
+		[DllImport("gnomevfs-2")]
+		static extern bool gnome_vfs_initialized();
+		
+		[DllImport("gnomevfs-2")]
+		static extern void gnome_vfs_shutdown ();
+		
+		public static readonly Init INIT = new Init();
+		private Init() {
+			System.Console.WriteLine("Starting GnomeVFS");
+			if (!gnome_vfs_init())
+				throw new Exception("Could not initialise Gnome VFS. Maybe there is something on stderr that will tell you more...");			
+		}
+		
+		//Probably need a Destroy or Dispose method to guarantee this being called.
+		~Init() {
+			System.Console.WriteLine("Shutting down GnomeVFS");
+			gnome_vfs_shutdown();
+		}
+	}
+
+	public class Mime {
+	
+		private static Init INIT = Init.INIT;
+		 
+		[DllImport("gnomevfs-2")]
+		static extern IntPtr gnome_vfs_mime_get_all_applications(string mime_type);
+		
+		public static MimeApplication[] GetAllApplications(string mime_type) {
+			IntPtr list_ptr = gnome_vfs_mime_get_all_applications(mime_type);
+			if (list_ptr == IntPtr.Zero) {
+				return new MimeApplication[0];
+			} else {
+				GLib.List list = new GLib.List (list_ptr, typeof (MimeApplication));
+				MimeApplication[] result = new MimeApplication[list.Count];
+				int i = 0;
+				foreach (MimeApplication val in list)
+					result [i++] = val;
+					
+				return result;
+			} 
+		}
+		
+#if TEST_GNOME_VFS
+		public static void Main(string[] args) {
+			const string EXAMPLE = "/home/loz/img/misc/llamat.jpg";
+			MimeApplication[] mas = GetAllApplications("image/jpeg");
+			foreach (MimeApplication ma in mas) {
+				
+				System.Console.WriteLine("Id: " + ma.Id);
+				System.Console.WriteLine("Name: " + ma.Name);
+				System.Console.WriteLine("Command: " + ma.Command);
+				System.Console.WriteLine("CanOpenMultipleFiles: " + ma.CanOpenMultipleFiles);
+				System.Console.WriteLine("ExpectsUris: " + ma.ExpectsUris);
+				System.Console.WriteLine("RequiresTerminal: " + ma.RequiresTerminal);
+				System.Console.WriteLine("SupportedUriSchemes:");
+				foreach (string s in ma.SupportedUriSchemes)
+					System.Console.WriteLine("--" + s);
+				System.Console.WriteLine("-----------------");
+				
+				ma.Execute("file:" + EXAMPLE);
+			}
+		}
+#endif
+	}
+	
+	public enum GnomeVFSMimeApplicationArgumentType {
+		Uris,
+		Paths,
+		Uris_For_Non_Files,
+	}
+	
+	[StructLayout(LayoutKind.Sequential)]
+	public struct MimeApplication {
+		public string Id;
+		public string Name;
+		public string Command;
+		public bool CanOpenMultipleFiles;
+		public GnomeVFSMimeApplicationArgumentType ExpectsUris;
+		private IntPtr _supported_uri_schemes;
+		/* List of strings? */
+		public string[] SupportedUriSchemes {
+			get {
+				if (_supported_uri_schemes == IntPtr.Zero) {
+					return new string[0];
+				} else {
+					GLib.List list = new GLib.List (_supported_uri_schemes, typeof (string));
+					string[] result = new string[list.Count];
+					int i = 0;
+					foreach (string val in list)
+						result [i++] = val;
+					
+					return result;
+				}
+			}
+		}
+		public bool RequiresTerminal;
+
+		/* Padded to avoid future breaks in ABI compatibility */
+		private IntPtr _reserved1;
+		private IntPtr _reserved2;
+		
+		//FIXME should use the GnomeVFS URI stuff
+		//FIXME add support for multiple files
+		//FIXME Is there a common way of doing this? 
+		public void Execute(string uri) {
+			switch (ExpectsUris) {
+				
+				case GnomeVFSMimeApplicationArgumentType.Uris: {
+					System.Diagnostics.Process.Start(Command, uri);
+					break;
+					//System.Runtime.InteropServices.
+				}
+				default: {
+					System.Console.WriteLine("Not supported yet");
+					break;
+				}
+			}
+		}   
+	}
+}
diff --exclude CVS -urN f-spot/src/MainWindow.cs f-spot-open-with-menu/src/MainWindow.cs
--- f-spot/src/MainWindow.cs	2004-10-13 07:01:55.000000000 +0100
+++ f-spot-open-with-menu/src/MainWindow.cs	2004-10-26 20:01:45.002142228 +0100
@@ -1207,7 +1207,13 @@
 		UpdateForVersionIdChange (version_id);
 	}
 
-
+	public void HandleOpenWith(GnomeVfs.MimeApplication mime_application) {
+		// FIXME handle multiple selections less stupidly
+		foreach (Photo photo in SelectedPhotos()) {
+			mime_application.Execute(photo.Uri);
+		}
+	
+	}
 	// Queries.
 
 	void UpdateQuery ()
diff --exclude CVS -urN f-spot/src/OpenWithMenu.cs f-spot-open-with-menu/src/OpenWithMenu.cs
--- f-spot/src/OpenWithMenu.cs	1970-01-01 01:00:00.000000000 +0100
+++ f-spot-open-with-menu/src/OpenWithMenu.cs	2004-10-26 19:43:13.361018465 +0100
@@ -0,0 +1,41 @@
+// created on 10/26/2004 at 18:18
+// Provdes a context menu for opening file based uris using gnome-vfs's mime handling
+using System;
+using Gtk;
+using GnomeVfs;
+using System.Runtime.InteropServices;
+
+public class OpenWithMenu {
+
+	public delegate void OpenWithHandler(MimeApplication mime_application);
+	// How do I do this with composition instead of subclassing?
+	private class OpenWithMenuItem : MenuItem {
+		public MimeApplication Value;
+		public event OpenWithHandler OpenWith;
+
+		public OpenWithMenuItem (MimeApplication mime_application) : base (mime_application.Name) {
+			Value = mime_application;
+		}
+		// FIXME I copied this from TagMenu, I really should figure out if it is needed
+		protected OpenWithMenuItem (IntPtr raw) : base (raw) {}
+		
+		protected override void OnActivated() {
+			if (OpenWith != null)
+				OpenWith(Value);
+		}
+	}
+
+	public static Menu GetMenu() {
+		// FIXME cache this?
+		Menu menu = new Menu();
+		// f-spot currently only supports image/jpeg as a mime type	
+		MimeApplication[] mas = Mime.GetAllApplications("image/jpeg");
+		foreach (MimeApplication ma in mas) {
+			OpenWithMenuItem item = new OpenWithMenuItem(ma);
+			item.OpenWith += MainWindow.Toplevel.HandleOpenWith;
+			menu.Append(item);
+		}
+		return menu;
+	} 
+	// FIXME could listen for changes in gnome-vfs
+}
diff --exclude CVS -urN f-spot/src/PhotoPopup.cs f-spot-open-with-menu/src/PhotoPopup.cs
--- f-spot/src/PhotoPopup.cs	2004-10-12 02:02:30.000000000 +0100
+++ f-spot-open-with-menu/src/PhotoPopup.cs	2004-10-26 20:01:34.953542477 +0100
@@ -52,6 +52,7 @@
 		attach_item.ShowAll ();
 		popup_menu.Append (attach_item);
 
+		
 		//
 		// FIXME finish the IPhotoSelection stuff and move the activate handler into the class
 		// this current method is way too complicated.
@@ -64,6 +65,12 @@
 		remove_item.ShowAll ();
 		popup_menu.Append (remove_item);
 
+		MenuItem open_with_item = new MenuItem("Open With");
+		Menu open_with_menu = OpenWithMenu.GetMenu();
+		open_with_item.Submenu = open_with_menu;
+		open_with_item.ShowAll();
+		popup_menu.Append (open_with_item);
+
 		popup_menu.Popup (null, null, null, IntPtr.Zero, eb.Button, eb.Time);
 	}   
 }
diff --exclude CVS -urN f-spot/src/PhotoStore.cs f-spot-open-with-menu/src/PhotoStore.cs
--- f-spot/src/PhotoStore.cs	2004-08-24 16:56:04.000000000 +0100
+++ f-spot-open-with-menu/src/PhotoStore.cs	2004-10-26 20:01:34.954542337 +0100
@@ -96,6 +96,12 @@
 		}
 	}
 
+	public string Uri {
+		get {
+			return "file:" + Path;
+		}
+	}
+			 
 	private ArrayList tags = new ArrayList ();
 	public Tag [] Tags {
 		get {
diff --exclude CVS -urN f-spot/src/makefile.am f-spot-open-with-menu/src/makefile.am
--- f-spot/src/makefile.am	2004-10-09 21:40:12.000000000 +0100
+++ f-spot-open-with-menu/src/makefile.am	2004-10-26 20:01:34.954542337 +0100
@@ -17,9 +17,11 @@
 	$(srcdir)/FormClient.cs			\
 	$(srcdir)/GalleryRemote.cs		\
 	$(srcdir)/GalleryExport.cs		\
+	$(srcdir)/GnomeVfs.cs			\
 	$(srcdir)/GroupAdaptor.cs		\
 	$(srcdir)/GroupSelector.cs		\
 	$(srcdir)/Histogram.cs			\
+	$(srcdir)/OpenWithMenu.cs		\
 	$(srcdir)/IconView.cs			\
 	$(srcdir)/ImageView.cs			\
 	$(srcdir)/ImportBackend.cs		\
