? PHOTOS
? PHOTOS2
? PHOTOS3
? f-spot-view.desktop.in
? patch.321770.diff
? patch.321770.diff2
? libeog/access.lo
? libeog/accessible-image-view-factory.lo
? libeog/accessible-image-view.lo
? libeog/cursors.lo
? libeog/eog-file-selection.lo
? libeog/eog-image.lo
? libeog/eog-pixbuf-util.lo
? libeog/eog-scroll-view.lo
? libeog/image-view.lo
? libeog/libeog-marshal.lo
? libeog/libfspoteog.la
? libeog/ui-image.lo
? libeog/uta.lo
? libeog/zoom.lo
? libfspot/f-image-view.lo
? libfspot/f-jpeg-utils.lo
? libfspot/f-marshal.lo
? libfspot/f-pixbuf-save.lo
? libfspot/f-pixbuf-unsharp.lo
? libfspot/f-pixbuf-utils.lo
? libfspot/f-screen-utils.lo
? libfspot/f-utils.lo
? libfspot/libfspot.la
? libjpegtran/jpeg-data.lo
? libjpegtran/jpeg-marker.lo
? libjpegtran/jpegtran.lo
? libjpegtran/libfspotjpegtran.la
? libjpegtran/transupp.lo
? po/.intltool-merge-cache
? po/stamp-it
? src/LastRollDialog.cs
? src/core.24285
? src/core.24754
? src/core.25280
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/f-spot/ChangeLog,v
retrieving revision 1.1596
diff -u -p -r1.1596 ChangeLog
--- ChangeLog	29 Sep 2006 04:43:20 -0000	1.1596
+++ ChangeLog	1 Oct 2006 13:08:35 -0000
@@ -1,3 +1,29 @@
+2006-10-01 Bengt Thuree <bengt@thuree.com> 
+ 
+ 	* : The below changes are for bug #321770
+ 	* src/ImportStore.cs: Reworked this class to track all imports (fixes #321770).
+ 	
+ 	* src/FileImportBackend.cs: Adding the import session for each 
+ 	imported photo, as well as Removing on cancel, or Finish on finish.
+ 	
+ 	* src/CameraFileSelectionDialog.cs: 
+ 	* src/ImportCommand.cs:
+ 	* src/MainWindow.cs: Added ImportStore parameter, as well as three menu entries
+ 	
+ 	* src/Updater.cs: Added Import_Session field to photos
+ 	
+ 	* src/PhotoQuery.cs: Added query on last import session id.
+ 	
+ 	* src/QueryDisplay.cs: Added indication of Import Roll filter, as well as clearing it.
+ 	
+ 	* src/PhotoStore.cs: Added PhotoStore.ImportIdRange, as well as sql filter on last import session id.
+ 	Minor modifications on creating a query to handle (AND or WHERE text)
+ 
+ 	* src/f-spot.glade:
+ 	* src/LastRollDialog.cs: Added a dialog for the Last Imported Roll history and selection.
+ 	
+ 	* src/Preferences.cs: Added gconf parameter for how m
+
 2006-09-28  Gabriel Burt  <gabriel.burt@gmail.com>
 
 	* src/ColorDialog.cs: Ensure only one dialog is created at a time.  Add
Index: src/CameraFileSelectionDialog.cs
===================================================================
RCS file: /cvs/gnome/f-spot/src/CameraFileSelectionDialog.cs,v
retrieving revision 1.14
diff -u -p -r1.14 CameraFileSelectionDialog.cs
--- src/CameraFileSelectionDialog.cs	15 Aug 2005 09:41:07 -0000	1.14
+++ src/CameraFileSelectionDialog.cs	1 Oct 2006 13:08:36 -0000
@@ -265,7 +265,7 @@ namespace FSpot {
 			
 			if (saved_files != null && import_files_checkbox.Active) {
 				ImportCommand command = new ImportCommand (null);
-				command.ImportFromPaths (db.Photos, saved_files, selected_tags);
+				command.ImportFromPaths (db.Photos, db.Imports, saved_files, selected_tags);
 			}
 		}
 		
Index: src/FileImportBackend.cs
===================================================================
RCS file: /cvs/gnome/f-spot/src/FileImportBackend.cs,v
retrieving revision 1.38
diff -u -p -r1.38 FileImportBackend.cs
--- src/FileImportBackend.cs	26 Sep 2006 16:09:43 -0000	1.38
+++ src/FileImportBackend.cs	1 Oct 2006 13:08:37 -0000
@@ -15,6 +15,7 @@ public class ImportException : System.Ex
 
 public class FileImportBackend : ImportBackend {
 	PhotoStore store;
+ 	ImportStore imports;
 	TagStore tag_store = FSpot.Core.Database.Tags;
 	bool recurse;
 	bool copy;
@@ -210,12 +211,12 @@ public class FileImportBackend : ImportB
 			// Don't copy if we are already home
 			if (info.OriginalPath == destination) {
 				info.DestinationPath = destination;
-				photo = store.Create (info.DestinationPath, out thumbnail);
+				photo = store.Create (info.DestinationPath, imports.GetImportId(), out thumbnail);
 			} else {
 				System.IO.File.Copy (info.OriginalPath, destination);
 				info.DestinationPath = destination;
 
-				photo = store.Create (info.DestinationPath, info.OriginalPath, out thumbnail);
+				photo = store.Create (info.DestinationPath, info.OriginalPath, imports.GetImportId(), out thumbnail);
 
 				try {
 					File.SetAttributes (destination, File.GetAttributes (info.DestinationPath) & ~FileAttributes.ReadOnly);
@@ -241,6 +242,8 @@ public class FileImportBackend : ImportB
 				store.Commit(photo);
 			
 			info.Photo = photo;
+
+                        
 		} catch (System.Exception e) {
 			System.Console.WriteLine ("Error importing {0}\n{1}", info.OriginalPath, e.ToString ());
 			thumbnail = null;
@@ -288,6 +291,8 @@ public class FileImportBackend : ImportB
 		}
 		// Clean up just created tags
 		xmptags.Cancel();
+ 		// Remove the imported session
+ 		imports.DeleteCurrent(); 
 	}
 
 	public override void Finish ()
@@ -303,13 +308,16 @@ public class FileImportBackend : ImportB
 		import_info = null;
 		xmptags.Finish();
 		count = 0;
+		
+		imports.EndImport();    // Clean up the imported session.
 	}
 
-	public FileImportBackend (PhotoStore store, string [] base_paths, bool recurse) : this (store, base_paths, false, recurse, null) {}
+	public FileImportBackend (PhotoStore store, ImportStore imports, string [] base_paths, bool recurse) : this (store, imports, base_paths, false, recurse, null) {}
 
-	public FileImportBackend (PhotoStore store, string [] base_paths, bool copy, bool recurse, Tag [] tags)
+	public FileImportBackend (PhotoStore store, ImportStore imports, string [] base_paths, bool copy, bool recurse, Tag [] tags)
 	{
 		this.store = store;
+		this.imports = imports;
 		this.copy = copy;
 		this.base_paths = base_paths;
 		this.recurse = recurse;
@@ -330,7 +338,7 @@ public class FileImportBackend : ImportB
 
 		Db db = new Db (path, true);
 
-		FileImportBackend import = new FileImportBackend (db.Photos, args [0],true);
+		FileImportBackend import = new FileImportBackend (db.Photos, db.Imports, args [0],true);
 
 		Console.WriteLine ("Preparing...");
 
Index: src/ImportCommand.cs
===================================================================
RCS file: /cvs/gnome/f-spot/src/ImportCommand.cs,v
retrieving revision 1.64
diff -u -p -r1.64 ImportCommand.cs
--- src/ImportCommand.cs	14 Sep 2006 18:54:07 -0000	1.64
+++ src/ImportCommand.cs	1 Oct 2006 13:08:37 -0000
@@ -313,6 +313,7 @@ public class ImportCommand : FSpot.Glade
 
 	int total;
 	PhotoStore store;
+	ImportStore import_sessions;
 	FSpot.Delay step;
 	
 	FSpot.PhotoImageView photo_view;
@@ -330,7 +331,7 @@ public class ImportCommand : FSpot.Glade
 	
 	private SourceItem Source {
 		set {
-			if (store == null || collection == null)
+			if (store == null || collection == null || import_sessions == null)
 				return;
 			
 			SourceItem item = value;
@@ -554,9 +555,10 @@ public class ImportCommand : FSpot.Glade
 		idle_start.Start ();
 	}
 
-	public int ImportFromFile (PhotoStore store, string path)
+	public int ImportFromFile (PhotoStore store, ImportStore import_sessions, string path)
 	{
 		this.store = store;
+		this.import_sessions = import_sessions;
 		this.CreateDialog ("import_dialog");
 		
 		this.Dialog.TransientFor = main_window;
@@ -733,7 +735,7 @@ public class ImportCommand : FSpot.Glade
 		if (recurse_check != null)
 			recurse = recurse_check.Active;
 		
-		importer = new FileImportBackend (store, pathimport, copy, recurse, null);
+		importer = new FileImportBackend (store, import_sessions, pathimport, copy, recurse, null);
 		AllowFinish = false;
 		
 		total = importer.Prepare ();
@@ -750,20 +752,20 @@ public class ImportCommand : FSpot.Glade
 		return false;
 	}
 
-	public int ImportFromPaths (PhotoStore store, string [] paths, bool copy)
+	public int ImportFromPaths (PhotoStore store, ImportStore import_sessions, string [] paths, bool copy)
 	{
-		return ImportFromPaths (store, paths, null, copy);
+		return ImportFromPaths (store, import_sessions, paths, null, copy);
 	}
 	
-	public int ImportFromPaths (PhotoStore store, string [] paths, Tag [] tags)
+	public int ImportFromPaths (PhotoStore store,  ImportStore import_sessions, string [] paths, Tag [] tags)
 	{
-		return ImportFromPaths (store, paths, tags, false);
+		return ImportFromPaths (store, import_sessions, paths, tags, false);
 	}
 	
-	public int ImportFromPaths (PhotoStore store, string [] paths, Tag [] tags, bool copy)
+	public int ImportFromPaths (PhotoStore store,  ImportStore import_sessions, string [] paths, Tag [] tags, bool copy)
 	{
 		collection = new FSpot.PhotoList (new Photo [0]);
-		int count = DoImport (new FileImportBackend (store, paths, copy, true, tags));
+		int count = DoImport (new FileImportBackend (store, import_sessions, paths, copy, true, tags));
 
 		Finish ();
 
Index: src/ImportStore.cs
===================================================================
RCS file: /cvs/gnome/f-spot/src/ImportStore.cs,v
retrieving revision 1.3
diff -u -p -r1.3 ImportStore.cs
--- src/ImportStore.cs	22 Jan 2006 22:43:53 -0000	1.3
+++ src/ImportStore.cs	1 Oct 2006 13:08:37 -0000
@@ -3,25 +3,29 @@ using System.Collections;
 using System.IO;
 using System;
 
-
-public class ImportStore : DbStore {
-
-	public class Import : DbItem {
-		// The time is always in UTC.
-		private DateTime time;
-		public DateTime Time {
-			get {
-				return time;
-			}
+public class Import : DbItem {
+	// The time is always in UTC.
+	private DateTime time;
+	public DateTime Time {
+		get {
+			return time;
 		}
+	}
 
 		public Import (uint id, long unix_time)
-			: base (id)
-		{
-			time = DbUtils.DateTimeFromUnixTime (unix_time);
-		}
+		: base (id)
+	{
+		time = DbUtils.DateTimeFromUnixTime (unix_time);
 	}
+}
+
 
+
+public class ImportStore : DbStore {
+        
+	Import import_session;		// This import session.
+	private int max_roll_history;	// will be populated from gconf, and indicates how many rolls we should track 
+	        
 	private class ImportComparerByDate : IComparer {
 		public int Compare (Object a, Object b) {
 			return DateTime.Compare ((a as Import).Time, (b as Import).Time);
@@ -33,6 +37,9 @@ public class ImportStore : DbStore {
 	public ImportStore (SqliteConnection connection, bool is_new)
 		: base (connection, false)
 	{
+
+                this.import_session = null;
+
 		if (! is_new)
 			return;
 		
@@ -40,15 +47,22 @@ public class ImportStore : DbStore {
 		command.Connection = Connection;
 
 		command.CommandText =
-			"CREATE TABLE imports (                            " +
+			"CREATE TABLE rolls (                              " +
 			"	id          INTEGER PRIMARY KEY NOT NULL,  " +
-			"       time        INTEGER			   " +
+			"       time        INTEGER not null               " +
 			")";
 
 		command.ExecuteNonQuery ();
 		command.Dispose ();
 	}
 
+	// Get the number of import rolls to keep, default to 20 
+	public int MaxNumberGuiRolls { 
+		get { 
+			return (int) FSpot.Preferences.Get (FSpot.Preferences.IMPORT_GUI_ROLL_HISTORY, 20);
+		}
+	}
+
 	public Import Create (DateTime time_in_utc)
 	{
 		long unix_time = DbUtils.UnixTimeFromDateTime (time_in_utc);
@@ -56,8 +70,7 @@ public class ImportStore : DbStore {
 		SqliteCommand command = new SqliteCommand ();
 		command.Connection = Connection;
 
-		command.CommandText = String.Format ("INSERT INTO import (time) VALUES ({0})  ",
-						     unix_time);
+		command.CommandText = String.Format ("INSERT INTO rolls (time) VALUES ({0})  ", unix_time);
 		command.ExecuteScalar ();
 		command.Dispose ();
 
@@ -68,6 +81,12 @@ public class ImportStore : DbStore {
 		return import;
 	}
 
+	public Import Create ()
+	{
+		return Create (System.DateTime.Now);
+	}
+
+
 	public override DbItem Get (uint id)
 	{
 		Import import = LookupInCache (id) as Import;
@@ -77,7 +96,7 @@ public class ImportStore : DbStore {
 		SqliteCommand command = new SqliteCommand ();
 		command.Connection = Connection;
 
-		command.CommandText = String.Format ("SELECT time FROM imports WHERE id = {0}", id);
+		command.CommandText = String.Format ("SELECT time FROM rolls WHERE id = {0}", id);
 		SqliteDataReader reader = command.ExecuteReader ();
 
 		if (reader.Read ()) {
@@ -97,16 +116,175 @@ public class ImportStore : DbStore {
 		SqliteCommand command = new SqliteCommand ();
 		command.Connection = Connection;
 
-		command.CommandText = String.Format ("DELETE FROM imports WHERE id = {0}", item.Id);
+		command.CommandText = String.Format ("DELETE FROM rolls WHERE id = {0}", item.Id);
 		command.ExecuteNonQuery ();
 
 		command.Dispose ();
 	}
 
 	public override void Commit (DbItem item)
+	{ 
+                // Nothing to be done here
+	}
+	
+	public uint GetImportId()
+	{
+                if (import_session == null) {
+                        import_session = Create ();
+                }
+                return import_session.Id;
+	
+	}
+	
+	public DateTime GetImportTime (uint roll_id)
+	{
+		// Check if a valid import id.
+                if ( roll_id < 1 ) 
+                	return System.DateTime.MinValue;
+		
+		return (Get (roll_id) as Import).Time;
+	}
+
+	public DateTime GetImportTime (int roll_id)
+	{
+		// roll_id is stored as an uint.
+		return GetImportTime ((uint) roll_id);
+	}
+
+	public uint GetNumberOfPhotosInRoll (uint roll_id)
+	{
+		uint number_of_photos_in_roll = 0;
+                SqliteCommand command = new SqliteCommand ();
+		command.Connection = Connection;
+
+		command.CommandText = String.Format ("SELECT count(*) FROM photos WHERE roll_id = {0}", roll_id);
+
+                SqliteDataReader reader = command.ExecuteReader ();
+                if (reader.Read ()) {
+                        number_of_photos_in_roll = Convert.ToUInt32 (reader[0]);
+                }
+                
+		command.Dispose ();
+                
+                return number_of_photos_in_roll;	
+	}
+
+	public System.DateTime GetDateForRoll (uint roll_id)
+	{
+		System.DateTime date_for_roll = System.DateTime.MinValue;
+                SqliteCommand command = new SqliteCommand ();
+		command.Connection = Connection;
+
+		command.CommandText = String.Format ("SELECT time FROM rolls WHERE id = {0}", roll_id);
+
+                SqliteDataReader reader = command.ExecuteReader ();
+                if (reader.Read ()) {
+                        date_for_roll = DbUtils.DateTimeFromUnixTime (Convert.ToUInt32 (reader[0]));
+                }
+                
+		command.Dispose ();
+                
+                return date_for_roll;	
+	}
+		
+		
+	
+	public uint [] GetActiveRolls()
+	{
+		// Before we return any rows, lets purge out any old empty rows.
+		// PurgeOldData();
+
+		// Ok, now we only should have real data there, so lets return them.
+		ArrayList result = new ArrayList();
+		SqliteCommand command = new SqliteCommand ();
+		command.Connection = Connection;
+		
+	        command.CommandText = "SELECT id, time FROM rolls ORDER BY id DESC";
+                
+                SqliteDataReader reader = command.ExecuteReader ();
+		int MaxRollsInGui = MaxNumberGuiRolls;
+		int fetched_rows = 0;
+		while (reader.Read () && (fetched_rows < MaxRollsInGui)) {
+			// Note that we get both time and ID from the database, but we have to see
+			// if the item is already in the cache first to make sure we return always
+			// the same object for a given ID.
+			
+			uint id = Convert.ToUInt32 (reader[0]);
+
+			Import import = LookupInCache (id) as Import;
+			if (import == null) {
+				import = new Import (id, Convert.ToUInt32 (reader[1]));
+				AddToCache (import);
+			}
+			result.Add (id);
+			fetched_rows++;
+//System.Console.WriteLine ("Fetched_Rows={0}, MaxRollsInGui={1}", fetched_rows, MaxRollsInGui);
+		}
+		command.Dispose ();
+		return (uint [])result.ToArray(typeof(uint));
+	}
+	
+	public uint GetLastRollId()
 	{
-		// Nothing to do here, since all the properties of an import are immutable.
+		uint last_roll_id = 0;
+                SqliteCommand command = new SqliteCommand ();
+		command.Connection = Connection;
+
+		command.CommandText = "SELECT MAX (id) FROM rolls";
+
+                SqliteDataReader reader = command.ExecuteReader ();
+                if (reader.Read ()) {
+                        last_roll_id = Convert.ToUInt32 (reader[0]);
+                }
+                
+		command.Dispose ();
+                
+                return last_roll_id;
+	}
+	
+        public uint NumberOfRows()
+        {
+                uint rows = 0;
+                SqliteCommand command = new SqliteCommand ();
+		command.Connection = Connection;
+
+		// Lets do the awkward select by searching the photos, since 
+		// if user deleted photos, the rolls table is not updated.
+//		command.CommandText = "SELECT count(*) FROM imports";
+		command.CommandText = "SELECT COUNT(roll_id) FROM (SELECT DISTINCT roll_id FROM photos)";
+
+                SqliteDataReader reader = command.ExecuteReader ();
+                if (reader.Read ()) {
+                        rows = Convert.ToUInt32 (reader[0]);
+                }
+                
+		command.Dispose ();
+                return rows;
+        }
+
+	public void EndImport ()
+	{ 
+	       import_session = null;          // So next time we import, we create a new import session.
 	}
+	
+	public void DeleteCurrent ()
+	{ 
+		if (import_session != null)
+			Remove (import_session);
+		EndImport();
+	}
+
+        public void AddPhotoToSession (uint imported_photo_id)
+        {
+        
+                // I wanted to store each imported_photo_id in an CollectionArray, 
+                // and do the database update in Commit. But if something goes wrong during the import
+                // the database would not be updated. So...
+                // Add this photo id to the import session.
+                if (import_session == null) {
+                        import_session = Create ();
+                }
+        }
 
 	// FIXME: Maybe this should be an abstract method in the base class?
 	public ArrayList GetAll ()
@@ -116,7 +294,7 @@ public class ImportStore : DbStore {
 		SqliteCommand command = new SqliteCommand ();
 		command.Connection = Connection;
 
-		command.CommandText = "SELECT id, time FROM imports";
+		command.CommandText = "SELECT id, time FROM rolls";
 		SqliteDataReader reader = command.ExecuteReader ();
 
 		while (reader.Read ()) {
Index: src/MainWindow.cs
===================================================================
RCS file: /cvs/gnome/f-spot/src/MainWindow.cs,v
retrieving revision 1.309
diff -u -p -r1.309 MainWindow.cs
--- src/MainWindow.cs	29 Sep 2006 04:43:31 -0000	1.309
+++ src/MainWindow.cs	1 Oct 2006 13:08:40 -0000
@@ -87,6 +87,10 @@ public class MainWindow {
 	[Glade.Widget] MenuItem find_tag;
 	[Glade.Widget] CheckMenuItem find_untagged;
 	
+	[Glade.Widget] CheckMenuItem last_import_roll;
+	[Glade.Widget] MenuItem last_import_rolls;
+	[Glade.Widget] MenuItem clear_last_import_filter;	
+	
 	// Tags
 	[Glade.Widget] MenuItem edit_selected_tag;
 	[Glade.Widget] MenuItem delete_selected_tag;
@@ -129,6 +133,7 @@ public class MainWindow {
 	string last_import_path;
 	ModeType view_mode;
 	bool write_metadata = false;
+	bool last_import_roll_active = false; // to ensure the checkmenuitem can be controlled from other area.
 
 	// Drag and Drop
 	enum TargetType {
@@ -1059,7 +1064,7 @@ public class MainWindow {
 	public void ImportUriList (UriList list, bool copy) 
 	{
 		ImportCommand command = new ImportCommand (main_window);
-		if (command.ImportFromPaths (db.Photos, list.ToLocalPaths (), copy) > 0) {
+		if (command.ImportFromPaths (db.Photos, db.Imports, list.ToLocalPaths (), copy) > 0) {
 			UpdateQuery ();
 		}
 	}
@@ -1067,7 +1072,7 @@ public class MainWindow {
 	public void ImportFile (string path)
 	{
 		ImportCommand command = new ImportCommand (main_window);
-		if (command.ImportFromFile (db.Photos, path) > 0) {
+		if (command.ImportFromFile (db.Photos, db.Imports, path) > 0) {
 			UpdateQuery ();
 		}
 	}
@@ -1268,7 +1273,7 @@ public class MainWindow {
 	{
 		db.Sync = false;
 		ImportCommand command = new ImportCommand (main_window);
-		if (command.ImportFromFile (db.Photos, null) > 0) {
+		if (command.ImportFromFile (db.Photos, db.Imports, null) > 0) {
 			this.last_import_path = command.ImportPath;
 			UpdateQuery ();
 		}
@@ -2341,6 +2346,36 @@ public class MainWindow {
 		}
 		query.Range = null;
 	}
+
+	void HandleSetLastImportRoll (object sender, EventArgs args) {
+		if (last_import_roll.Active) {
+			query.ImportIdRange = new PhotoStore.ImportIdRange (db.Imports.GetLastRollId());
+			last_import_roll_active = true;		
+		} else {
+			if (last_import_roll_active) {
+				query.ImportIdRange = null;
+				last_import_roll_active = false;
+			}
+		}
+	}
+
+	void HandleSetLastImportRolls (object sender, EventArgs args) {
+		LastRolls.Set set_command = new LastRolls.Set (query, db.Imports, main_window);
+		if (set_command.Execute ()) {
+			last_import_roll_active = false;
+			last_import_roll.Active = false;	// Since user manually opened the gui, we clear the last roll filter.
+		} else {
+			if (!last_import_roll_active)
+				query.ImportIdRange = null;
+		}
+	}
+
+	void HandleClearLastImportFilter (object sender, EventArgs args) {
+		query.ImportIdRange = null;
+		last_import_roll.Active = false;
+
+	}
+
 	
 	void HandleFindUntagged (object sender, EventArgs args) {
 		if (query.Untagged == find_untagged.Active)
@@ -2554,7 +2589,15 @@ public class MainWindow {
 		exif_data.Sensitive = active_selection;
 		sharpen.Sensitive = active_selection;
 		remove_from_catalog.Sensitive = active_selection;
-
+		
+		last_import_roll.Sensitive = (db.Imports.NumberOfRows() > 0);
+		last_import_rolls.Sensitive = (db.Imports.NumberOfRows() > 1);
+		clear_last_import_filter.Sensitive = (last_import_rolls.Sensitive);
+		if ((last_import_roll.Active) && (query.ImportIdRange == null))	{	// Clean up tick, if roll filter is not active.
+			last_import_roll_active = false;
+			last_import_roll.Active = false;
+		}
+		
 		delete_selected_tag.Sensitive = tag_sensitive;
 		edit_selected_tag.Sensitive = tag_sensitive;
 
Index: src/Makefile.am
===================================================================
RCS file: /cvs/gnome/f-spot/src/Makefile.am,v
retrieving revision 1.71
diff -u -p -r1.71 Makefile.am
--- src/Makefile.am	28 Sep 2006 19:46:12 -0000	1.71
+++ src/Makefile.am	1 Oct 2006 13:08:40 -0000
@@ -57,6 +57,7 @@ F_SPOT_CSDISTFILES =				\
 	$(srcdir)/JpegHeader.cs			\
 	$(srcdir)/JpegUtils.cs			\
 	$(srcdir)/Cms.cs			\
+	$(srcdir)/LastRollDialog.cs		\
 	$(srcdir)/Loupe.cs			\
 	$(srcdir)/MainWindow.cs			\
 	$(srcdir)/MetaStore.cs			\
Index: src/PhotoQuery.cs
===================================================================
RCS file: /cvs/gnome/f-spot/src/PhotoQuery.cs,v
retrieving revision 1.20
diff -u -p -r1.20 PhotoQuery.cs
--- src/PhotoQuery.cs	19 Dec 2005 04:35:17 -0000	1.20
+++ src/PhotoQuery.cs	1 Oct 2006 13:08:41 -0000
@@ -8,12 +8,13 @@ namespace FSpot {
 		private PhotoStore store;
 		private Tag [] tags;
 		private PhotoStore.DateRange range = null;
+		private PhotoStore.ImportIdRange importidrange = null;
 		
 		// Constructor
 		public PhotoQuery (PhotoStore store)
 		{
 			this.store = store;
-			photos = store.Query (null, range);
+			photos = store.Query (null, range, importidrange);
 		}
 
 		public int Count {
@@ -61,7 +62,7 @@ namespace FSpot {
 			
 			set {
 				tags = value;
-				photos = store.Query (tags, range);
+				photos = store.Query (tags, range, importidrange);
 				untagged = false;
 				RequestReload ();
 			}
@@ -75,9 +76,25 @@ namespace FSpot {
 				range = value;
 				
 				if (untagged)
-					photos = store.QueryUntagged (range);
+					photos = store.QueryUntagged (range, importidrange);
 				else
-					photos = store.Query (tags, range);
+					photos = store.Query (tags, range, importidrange);
+
+				RequestReload ();
+			}
+		}
+		
+		public PhotoStore.ImportIdRange ImportIdRange {
+			get {
+				return importidrange;
+			}
+			set {
+				importidrange = value;
+				
+				if (untagged)
+					photos = store.QueryUntagged (range, importidrange);
+				else
+					photos = store.Query (tags, range, importidrange);
 
 				RequestReload ();
 			}
@@ -94,9 +111,9 @@ namespace FSpot {
 
 					if (untagged) {
 						tags = null;
-						photos = store.QueryUntagged (range);
+						photos = store.QueryUntagged (range, importidrange);
 					} else
-						photos = store.Query (tags, range);
+						photos = store.Query (tags, range, importidrange);
 					
 					RequestReload ();
 				}
Index: src/PhotoStore.cs
===================================================================
RCS file: /cvs/gnome/f-spot/src/PhotoStore.cs,v
retrieving revision 1.97
diff -u -p -r1.97 PhotoStore.cs
--- src/PhotoStore.cs	15 Sep 2006 03:43:46 -0000	1.97
+++ src/PhotoStore.cs	1 Oct 2006 13:08:42 -0000
@@ -202,6 +202,16 @@ public class Photo : DbItem, IComparable
 		}
 	}
 
+        private uint roll_id = 0;
+	public uint RollId {
+		get { 
+		      return roll_id; 
+		}
+		set { 
+		      roll_id = value; 
+		}
+	}
+
 	// Version management
 	public const int OriginalVersionId = 1;
 	private uint highest_version_id;
@@ -669,6 +679,7 @@ public class PhotoStore : DbStore {
 			"       directory_path     STRING NOT NULL,		   " +
 			"       name               STRING NOT NULL,		   " +
 			"       description        TEXT NOT NULL,	           " +
+			"       roll_id            INTEGER NOT NULL,		   " +
 			"       default_version_id INTEGER NOT NULL		   " +
 			")";
 
@@ -706,12 +717,13 @@ public class PhotoStore : DbStore {
 	}
 
 
-	public Photo Create (string path, out Pixbuf thumbnail)
+	public Photo Create (string path, uint roll_id, out Pixbuf thumbnail)
 	{
-		return Create (path, path, out thumbnail);
+		return Create (path, path, roll_id, out thumbnail);
+
 	}
 
-	public Photo Create (string newPath, string origPath, out Pixbuf thumbnail)
+	public Photo Create (string newPath, string origPath, uint roll_id, out Pixbuf thumbnail)
 	{
 		FSpot.ImageFile img = FSpot.ImageFile.Create (origPath);
 		long unix_time = DbUtils.UnixTimeFromDateTime (img.Date);
@@ -720,12 +732,13 @@ public class PhotoStore : DbStore {
 		command.Connection = Connection;
 
 		command.CommandText = String.Format ("INSERT INTO photos (time, " +
-						     "directory_path, name, description, default_version_id) " +
-						     "       VALUES ({0}, '{1}', '{2}', '{3}', {4})",
+						     "directory_path, name, description, roll_id, default_version_id) " +
+						     "       VALUES ({0}, '{1}', '{2}', '{3}', {4}, {5})",
 						     unix_time,
 						     SqlString (System.IO.Path.GetDirectoryName (newPath)),
 						     SqlString (System.IO.Path.GetFileName (newPath)),
 						     SqlString (description),
+						     roll_id,
 						     Photo.OriginalVersionId);
 
 		command.ExecuteScalar ();
@@ -920,6 +933,7 @@ public class PhotoStore : DbStore {
 						     "       directory_path,                       " +
 						     "       name,                                 " +
 						     "       description,                          " +
+						     "       roll_id,                       " +
 						     "       default_version_id                    " +
 						     "     FROM photos                             " +
 						     "     WHERE id = {0}                          ",
@@ -933,7 +947,8 @@ public class PhotoStore : DbStore {
 					   reader [2].ToString ());
 
 			photo.Description = reader[3].ToString ();
-			photo.DefaultVersionId = Convert.ToUInt32 (reader[4]);
+			photo.RollId = Convert.ToUInt32 (reader[4]);
+			photo.DefaultVersionId = Convert.ToUInt32 (reader[5]);
 			AddToCache (photo);
 		}
 
@@ -963,6 +978,7 @@ public class PhotoStore : DbStore {
 		command.CommandText = String.Format ("SELECT id,                                   " +
 				                     "       time,                                 " +
 						     "       description,                          " +
+						     "       roll_id,                              " +
 						     "       default_version_id                    " +
 						     "  FROM photos                                " +
 						     " WHERE directory_path = \"{0}\"              " +
@@ -979,7 +995,8 @@ public class PhotoStore : DbStore {
 					   filename);
 
 			photo.Description = reader[2].ToString ();
-			photo.DefaultVersionId = Convert.ToUInt32 (reader[3]);
+			photo.RollId = Convert.ToUInt32 (reader[3]);
+			photo.DefaultVersionId = Convert.ToUInt32 (reader[4]);
 			AddToCache (photo);
 		}
 
@@ -1048,6 +1065,7 @@ public class PhotoStore : DbStore {
 		command.ExecuteNonQuery ();
 
 		command.Dispose ();
+
 	}
 
 	public override void Remove (DbItem item)
@@ -1155,15 +1173,85 @@ public class PhotoStore : DbStore {
 			this.end = end;
 		}
 	}
+	
+	public class ImportIdRange 
+	// This class contains the active import rolls the user wants to filter on.
+	// For instance, if he is interested on import rolls, 19, 20, 21 and 22
+	// the first 4 values in importidhistory would be 19, 20, 21, 22
+	{
+		private uint [] importidhistory;
+
+		public bool FilterOnImports {
+			get {
+				return importidhistory.Length > 0;
+			}
+		}		
+		public uint GetNumberOfImportFilters {
+			get {
+				return (uint) importidhistory.Length;
+			}
+		}		
+		public uint GetImportId (uint val)
+		{
+			return importidhistory[val];
+		}
+		// constructor : A range of rolls
+		public ImportIdRange (uint [] ids)
+		{
+			importidhistory = ids;
+		}
+		// constructor : just one specific roll
+		public ImportIdRange (uint id)
+		{
+			importidhistory = new uint[1];
+			importidhistory[0] = id;
+		}
+	}
 
 	// Queries.
+	
+	private String AddLastImportFilter (ImportIdRange importidrange, bool added_where)
+	{
+/* 
+Building something like this
+	where photos.roll_id in (3, 4, 5)
+*/	
+		string q = null;		// contains the resulting sub-query
+		bool add_comma = false;		// If ", " should be added before the parameter.
+		
+		if (importidrange == null)	// return directly, if importidrange is not set.
+			return q;
+
+		q = String.Format (" {0} photos.roll_id IN ( ", added_where ? " AND " : " WHERE " );
+
+		for (uint k = 0; k < importidrange.GetNumberOfImportFilters; k++) {
+				q = q + String.Format ("{0}{1}", add_comma ? ", " : "", importidrange.GetImportId(k));
+				add_comma = true;
+		} // for
+		q = q + (" ) " ); // AND id IN
+//		System.Console.WriteLine ("Last Import filter = >>{0}<<", q);
+		return q;
+	}
+
+	
+	
+	public Photo [] Query (Tag [] tags, DateTime start, DateTime end, uint [] importrange)
+	{
+		return Query (tags, new DateRange (start, end), new ImportIdRange (importrange));
+	}
+
+	public Photo [] Query (Tag [] tags, uint [] importrange)
+	{
+		return Query (tags, null, importrange == null ? null : new ImportIdRange (importrange));
+	}
+
 	public Photo [] Query (Tag [] tags, DateTime start, DateTime end)
 	{
-		return Query (tags, new DateRange (start, end));
+		return Query (tags, new DateRange (start, end), null);
 	}
 	
 	public Photo [] Query (Tag [] tags) {
-		return Query (tags, null);
+		return Query (tags, null, null);
 	}
 
 	public Photo [] Query (string query)
@@ -1172,6 +1260,7 @@ public class PhotoStore : DbStore {
 		command.Connection = Connection;
 		command.CommandText = query;
 		SqliteDataReader reader = command.ExecuteReader ();
+		//System.Console.WriteLine ("Query == >>{0}<<", query);		
 		
 		ArrayList version_list = new ArrayList ();
 		ArrayList id_list = new ArrayList ();
@@ -1186,7 +1275,8 @@ public class PhotoStore : DbStore {
 						   reader [3].ToString ());
 				
 				photo.Description = reader[4].ToString ();
-				photo.DefaultVersionId = Convert.ToUInt32 (reader[5]);		 
+				photo.RollId = Convert.ToUInt32 (reader[5]);
+				photo.DefaultVersionId = Convert.ToUInt32 (reader[6]);
 				
 				version_list.Add (photo);
 			}
@@ -1222,6 +1312,7 @@ public class PhotoStore : DbStore {
 						     "       photos.directory_path,              " +
 						     "       photos.name,                        " +
 						     "       photos.description,                 " +
+						     "       photos.roll_id,                     " +
 						     "       photos.default_version_id           " +
 						     "     FROM photos                           " +
 						     "     WHERE directory_path = \"{0}\"", dir.FullName);
@@ -1229,29 +1320,37 @@ public class PhotoStore : DbStore {
 		return Query (query_string);
 	}
 
-	public Photo [] QueryUntagged (DateRange range)
+	public Photo [] QueryUntagged (DateRange range, ImportIdRange importidrange)
 	{
 		StringBuilder query_builder = new StringBuilder ();
 
 		query_builder.Append ("SELECT * FROM photos WHERE id NOT IN " +
 					"(SELECT DISTINCT photo_id FROM photo_tags) ");
 		
+		bool added_where = true;
 		if (range != null) {
 			query_builder.Append (String.Format ("AND photos.time >= {0} AND photos.time <= {1} ",
 							     DbUtils.UnixTimeFromDateTime (range.Start), 
 							     DbUtils.UnixTimeFromDateTime (range.End)));
+			added_where = true;
 		}
 
+		if (importidrange != null) {
+			query_builder.Append (AddLastImportFilter (importidrange, added_where));
+			added_where = true;
+ 		}
+
 		query_builder.Append("ORDER BY time");
 
 		return Query (query_builder.ToString ());
 	}
 
-	public Photo [] Query (Tag [] tags, DateRange range)
+	public Photo [] Query (Tag [] tags, DateRange range, ImportIdRange importidrange)
 	{
 		string query;
 
 		bool hide = true;
+		bool added_where = false;
 		if (tags != null) {
 			foreach (Tag t in tags) {
 				if (tag_store.Hidden == null || t.Id == tag_store.Hidden.Id) 
@@ -1267,12 +1366,15 @@ public class PhotoStore : DbStore {
 		//        photos.directory_path,
 		//        photos.name,
 		//        photos.description,
+		//	  photos.roll_id,
 		//        photos.default_version_id
 		//                  FROM photos, photo_tags
 		//                  WHERE photos.id = photo_tags.photo_id
 		// 		          AND (photo_tags.tag_id = tag1
 		//			       OR photo_tags.tag_id = tag2
 		//                             OR photo_tags.tag_id = tag3 ...)
+		//			  AND (photos.roll_id = roll_id1
+		//			       OR photos.roll_id = roll_id2 ...)
 		//                  GROUP BY photos.id
 		
 		StringBuilder query_builder = new StringBuilder ();
@@ -1281,6 +1383,7 @@ public class PhotoStore : DbStore {
 				      "       photos.directory_path,              " +
 				      "       photos.name,                        " +
 				      "       photos.description,                 " +
+				      "       photos.roll_id,                     " +
 				      "       photos.default_version_id           " +
 				      "     FROM photos                      ");
 		
@@ -1288,11 +1391,18 @@ public class PhotoStore : DbStore {
 			query_builder.Append (String.Format ("WHERE photos.time >= {0} AND photos.time <= {1} ",
 							     DbUtils.UnixTimeFromDateTime (range.Start), 
 							     DbUtils.UnixTimeFromDateTime (range.End)));
+			added_where = true;
 		}
+
+		if (importidrange != null) {
+			query_builder.Append (AddLastImportFilter (importidrange, added_where));
+			added_where = true;
+		}		
 		
 		if (hide) {
 			query_builder.Append (String.Format ("{0} photos.id NOT IN (SELECT photo_id FROM photo_tags WHERE tag_id = {1})", 
-							     range != null ? " AND " : " WHERE ", tag_store.Hidden.Id));
+							     added_where ? " AND " : " WHERE ", tag_store.Hidden.Id));
+			added_where = true;
 		}
 		
 		if (tags != null && tags.Length > 0) {
@@ -1306,12 +1416,13 @@ public class PhotoStore : DbStore {
 				
 				if (first) {
 					query_builder.Append (String.Format ("{0} photos.id IN (SELECT photo_id FROM photo_tags WHERE tag_id IN (",
-									     hide || range != null ? " AND " : " WHERE "));
+									     added_where ? " AND " : " WHERE "));
+					added_where = true;
 				}
 				
 				query_builder.Append (String.Format ("{0}{1} ", first ? "" : ", ", t.Id));
 				
-					first = false;
+				first = false;
 			}
 			
 			if (!first)
@@ -1394,14 +1505,14 @@ public class PhotoStore : DbStore {
 
 		Pixbuf unused_thumbnail;
 
-		Photo ny_landscape = db.Photos.Create (DateTime.Now.ToUniversalTime (), "/home/ettore/Photos/ny_landscape.jpg",
+		Photo ny_landscape = db.Photos.Create (DateTime.Now.ToUniversalTime (), 1, "/home/ettore/Photos/ny_landscape.jpg",
 						       out unused_thumbnail);
 		ny_landscape.Description = "Pretty NY skyline";
 		ny_landscape.AddTag (landscapes_tag);
 		ny_landscape.AddTag (favorites_tag);
 		db.Photos.Commit (ny_landscape);
 
-		Photo me_in_sf = db.Photos.Create (DateTime.Now.ToUniversalTime (), "/home/ettore/Photos/me_in_sf.jpg",
+		Photo me_in_sf = db.Photos.Create (DateTime.Now.ToUniversalTime (), 2, "/home/ettore/Photos/me_in_sf.jpg",
 						   out unused_thumbnail);
 		me_in_sf.AddTag (landscapes_tag);
 		me_in_sf.AddTag (portraits_tag);
@@ -1414,7 +1525,7 @@ public class PhotoStore : DbStore {
 		me_in_sf.CreateVersion ("UM-ed", Photo.OriginalVersionId);
 		db.Photos.Commit (me_in_sf);
 
-		Photo macro_shot = db.Photos.Create (DateTime.Now.ToUniversalTime (), "/home/ettore/Photos/macro_shot.jpg",
+		Photo macro_shot = db.Photos.Create (DateTime.Now.ToUniversalTime (), 2, "/home/ettore/Photos/macro_shot.jpg",
 						     out unused_thumbnail);
 		db.Dispose ();
 
Index: src/Preferences.cs
===================================================================
RCS file: /cvs/gnome/f-spot/src/Preferences.cs,v
retrieving revision 1.17
diff -u -p -r1.17 Preferences.cs
--- src/Preferences.cs	13 Sep 2006 19:36:27 -0000	1.17
+++ src/Preferences.cs	1 Oct 2006 13:08:42 -0000
@@ -81,6 +81,8 @@ namespace FSpot
  		public const string EXPORT_EMAIL_ROTATE = "/apps/f-spot/export/email/auto_rotate";
  		public const string EXPORT_EMAIL_DELETE_TIMEOUT_SEC = "/apps/f-spot/export/email/delete_timeout_seconds";
 
+		public const string IMPORT_GUI_ROLL_HISTORY = "/apps/f-spot/import/gui_roll_history";
+
 		public const string SCREENSAVER_TAG = "/apps/f-spot/screensaver/tag_id";
 
 		public const string STORAGE_PATH = "/apps/f-spot/import/storage_path";
Index: src/QueryDisplay.cs
===================================================================
RCS file: /cvs/gnome/f-spot/src/QueryDisplay.cs,v
retrieving revision 1.7
diff -u -p -r1.7 QueryDisplay.cs
--- src/QueryDisplay.cs	19 Dec 2005 04:35:17 -0000	1.7
+++ src/QueryDisplay.cs	1 Oct 2006 13:08:42 -0000
@@ -9,6 +9,8 @@ public class QueryDisplay : Gtk.VBox {
 	Gtk.EventBox tag_view_box;
 	Gtk.Label label;
 	Gtk.Label untagged;
+	Gtk.Label comma_label;
+	Gtk.Label rollfilter;
 	Gtk.HBox warning_box;
 	Gtk.Button clear_button;
 	TagSelectionWidget selector;
@@ -40,6 +42,15 @@ public class QueryDisplay : Gtk.VBox {
 		untagged.Visible = false;
 		hbox.PackStart (untagged, false, false, 0);
 
+		comma_label = new Gtk.Label (", ");
+		comma_label.Visible = false;
+		hbox.PackStart (comma_label, false, false, 0);
+
+		rollfilter = new Gtk.Label (Catalog.GetString ("Import roll"));
+		rollfilter.Visible = false;
+		hbox.PackStart (rollfilter, false, false, 0);
+
+
 		tag_view_box = new EventBox ();
 		tag_view = new TagView (tag_view_box);
 		tag_view.Show ();
@@ -67,6 +78,7 @@ public class QueryDisplay : Gtk.VBox {
 	public void HandleClearButtonClicked (object sender, System.EventArgs args)
 	{
 		query.Untagged = false;
+		query.ImportIdRange = null;
 		selector.TagSelection = new Tag [] { };
 	}
 
@@ -76,11 +88,13 @@ public class QueryDisplay : Gtk.VBox {
 		
 		Tag [] tags = query.Tags;
 		tag_view.Tags = tags;
-		if ((tags != null && tags.Length > 0) || query.Untagged)
+		if ((tags != null && tags.Length > 0) || query.Untagged || (query.ImportIdRange != null))
 			active_search = true;
 		
 		this.Visible = active_search;
 		untagged.Visible = query.Untagged;
+		comma_label.Visible = query.Untagged && (query.ImportIdRange != null);
+		rollfilter.Visible = (query.ImportIdRange != null);
 		warning_box.Visible = (query.Count < 1);
 	}
 }
Index: src/Updater.cs
===================================================================
RCS file: /cvs/gnome/f-spot/src/Updater.cs,v
retrieving revision 1.5
diff -u -p -r1.5 Updater.cs
--- src/Updater.cs	6 Jun 2006 22:53:12 -0000	1.5
+++ src/Updater.cs	1 Oct 2006 13:08:43 -0000
@@ -61,13 +61,59 @@ namespace FSpot.Database {
 
 				System.Console.WriteLine ("Other tag restored.  Sorry about that!");
 			});
-			
+
 			// Update from version 2 to 3: ensure that Hidden is the only tag left which is a real tag (not category)
 			AddUpdate (delegate (SqliteConnection connection) {
 				ExecuteNonQuery ("UPDATE tags SET is_category = 1 WHERE name != 'Hidden'");
 			});
 			
 			// Update from version 3 to 4
+			// Creating a new table to keep the Import sessions.
+			AddUpdate (delegate (SqliteConnection connection) {
+				System.Console.WriteLine ("Will add a roll_id field to photos!");
+				
+				string tmp_photos = MoveTableToTemp ("photos");
+System.Console.WriteLine ("Copied data to tmp table!");								
+				ExecuteNonQuery (
+					"CREATE TABLE photos (                                     " +
+					"	id                 INTEGER PRIMARY KEY NOT NULL,   " +
+					"       time               INTEGER NOT NULL,	   	   " +
+					"       directory_path     STRING NOT NULL,		   " +
+					"       name               STRING NOT NULL,		   " +
+					"       description        TEXT NOT NULL,	           " +
+					"       roll_id            INTEGER NOT NULL,		   " +
+					"       default_version_id INTEGER NOT NULL		   " +
+					")");
+System.Console.WriteLine ("Created new table!");				
+				// Copy the data back from Temp table
+				ExecuteScalar (String.Format("INSERT INTO photos SELECT id, time, directory_path, name, description, 0, default_version_id FROM {0}", tmp_photos));
+System.Console.WriteLine ("Copied data back to photos!");									
+				// Delete the tmp table
+				ExecuteNonQuery (String.Format("DROP TABLE {0}", tmp_photos));
+System.Console.WriteLine ("Dropped the temp table!");									
+				System.Console.WriteLine ("Added roll_id field to photos!");
+				
+				System.Console.WriteLine ("Will rename imports to rolls!");
+				
+				string tmp_rolls = MoveTableToTemp ("imports");
+System.Console.WriteLine ("Copied data to tmp table!");								
+				ExecuteNonQuery (
+					"CREATE TABLE rolls (                                     " +
+					"	id                 INTEGER PRIMARY KEY NOT NULL,   " +
+					"       time               INTEGER NOT NULL	   	   " +
+					")");
+System.Console.WriteLine ("Created new table!");				
+				// Copy the data back from Temp table
+				ExecuteScalar (String.Format("INSERT INTO rolls SELECT id, time FROM {0}", tmp_rolls));
+System.Console.WriteLine ("Copied data back to rolls!");									
+				// Delete the tmp table
+				ExecuteNonQuery (String.Format("DROP TABLE {0}", tmp_rolls));
+System.Console.WriteLine ("Dropped the temp table!");									
+				System.Console.WriteLine ("Renamed imports to rolls!");
+				
+			});				
+			
+			// Update from version 4 to 5
 			//AddUpdate (delegate (SqliteConnection connection) {
 			//	do update here
 			//});
Index: src/f-spot.glade
===================================================================
RCS file: /cvs/gnome/f-spot/src/f-spot.glade,v
retrieving revision 1.173
diff -u -p -r1.173 f-spot.glade
--- src/f-spot.glade	26 Sep 2006 22:58:19 -0000	1.173
+++ src/f-spot.glade	1 Oct 2006 13:09:02 -0000
@@ -8888,6 +8888,40 @@ Photo Details</property>
 		  </child>
 
 		  <child>
+		    <widget class="GtkCheckMenuItem" id="last_import_roll">
+		      <property name="visible">True</property>
+		      <property name="label" translatable="yes">Last import roll</property>
+		      <property name="use_underline">True</property>
+		      <property name="active">False</property>
+		      <signal name="activate" handler="HandleSetLastImportRoll" last_modification_time="Mon, 29 May 2006 15:18:53 GMT"/>
+		    </widget>
+		  </child>
+
+		  <child>
+		    <widget class="GtkMenuItem" id="last_import_rolls">
+		      <property name="visible">True</property>
+		      <property name="label" translatable="yes">Last import rolls...</property>
+		      <property name="use_underline">True</property>
+		      <signal name="activate" handler="HandleSetLastImportRolls" last_modification_time="Mon, 29 May 2006 15:18:53 GMT"/>
+		    </widget>
+		  </child>
+
+		  <child>
+		    <widget class="GtkMenuItem" id="clear_last_import_filter">
+		      <property name="visible">True</property>
+		      <property name="label" translatable="yes">Clear Last import filter</property>
+		      <property name="use_underline">True</property>
+		      <signal name="activate" handler="HandleClearLastImportFilter" last_modification_time="Mon, 29 May 2006 15:24:10 GMT"/>
+		    </widget>
+		  </child>
+
+		  <child>
+		    <widget class="GtkSeparatorMenuItem" id="separator116">
+		      <property name="visible">True</property>
+		    </widget>
+		  </child>
+
+		  <child>
 		    <widget class="GtkMenuItem" id="find_tag">
 		      <property name="visible">True</property>
 		      <property name="label" translatable="yes">Find by _Tag</property>
@@ -14557,6 +14591,260 @@ Custom
 	</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="last_import_rolls_filter">
+  <property name="visible">True</property>
+  <property name="title" translatable="yes">Last Import Rolls Filter</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="dialog-vbox1">
+      <property name="visible">True</property>
+      <property name="homogeneous">False</property>
+      <property name="spacing">0</property>
+
+      <child internal-child="action_area">
+	<widget class="GtkHButtonBox" id="dialog-action_area1">
+	  <property name="visible">True</property>
+	  <property name="layout_style">GTK_BUTTONBOX_END</property>
+
+	  <child>
+	    <widget class="GtkButton" id="cancelbutton1">
+	      <property name="visible">True</property>
+	      <property name="tooltip" translatable="yes">Show all photos.</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="okbutton1">
+	      <property name="visible">True</property>
+	      <property name="tooltip" translatable="yes">Display only those photos that were imported in specified Rolls.</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="vbox1">
+	  <property name="width_request">450</property>
+	  <property name="visible">True</property>
+	  <property name="homogeneous">False</property>
+	  <property name="spacing">5</property>
+
+	  <child>
+	    <widget class="GtkLabel" id="label1">
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">&lt;b&gt;View all pictures imported&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="hbox1">
+	      <property name="visible">True</property>
+	      <property name="homogeneous">False</property>
+	      <property name="spacing">4</property>
+
+	      <child>
+		<widget class="GtkComboBox" id="combo_filter">
+		  <property name="visible">True</property>
+		  <property name="items" translatable="yes" comments="at, or after a date, or between dates">at
+after
+between</property>
+		  <property name="add_tearoffs">False</property>
+		  <property name="focus_on_click">True</property>
+		  <signal name="changed" handler="on_combo_filter_changed" last_modification_time="Wed, 02 Aug 2006 10:54:48 GMT"/>
+		</widget>
+		<packing>
+		  <property name="padding">0</property>
+		  <property name="expand">False</property>
+		  <property name="fill">False</property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkComboBox" id="combo_roll_1">
+		  <property name="visible">True</property>
+		  <property name="items" translatable="yes"></property>
+		  <property name="add_tearoffs">False</property>
+		  <property name="focus_on_click">True</property>
+		  <signal name="changed" handler="on_combo_roll_changed" last_modification_time="Thu, 03 Aug 2006 11:10:39 GMT"/>
+		</widget>
+		<packing>
+		  <property name="padding">0</property>
+		  <property name="expand">True</property>
+		  <property name="fill">True</property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkLabel" id="and_label">
+		  <property name="visible">True</property>
+		  <property name="label" translatable="yes">and</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="GtkComboBox" id="combo_roll_2">
+		  <property name="visible">True</property>
+		  <property name="items" translatable="yes"></property>
+		  <property name="add_tearoffs">False</property>
+		  <property name="focus_on_click">True</property>
+		  <signal name="changed" handler="on_combo_roll_changed" last_modification_time="Thu, 03 Aug 2006 11:10:51 GMT"/>
+		</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">True</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkHBox" id="hbox85">
+	      <property name="visible">True</property>
+	      <property name="homogeneous">False</property>
+	      <property name="spacing">0</property>
+
+	      <child>
+		<widget class="GtkLabel" id="label210">
+		  <property name="visible">True</property>
+		  <property name="label" translatable="yes">Number of photos in selected rolls :</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="GtkLabel" id="photos_in_selected_rolls">
+		  <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">3</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>
+	    <packing>
+	      <property name="padding">5</property>
+	      <property name="expand">True</property>
+	      <property name="fill">True</property>
+	    </packing>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">3</property>
 	  <property name="expand">True</property>
 	  <property name="fill">True</property>
 	</packing>
--- /dev/null	2006-09-27 07:46:38.000000000 +1000
+++ src/LastRollDialog.cs	2006-10-01 22:37:32.851500802 +1000
@@ -0,0 +1,169 @@
+//
+// LastRollDialog.cs: Displays a small gui, from which the user can choose 
+//	which Roll Id (of the last 20) to base the search filter upon.
+//
+// Author:
+//   Bengt Thuree (bengt@thuree.com)
+//	With great help from Stephane Delcroix (GUI and feedback)
+//
+// (C) 2006 Bengt Thuree
+//
+
+using Gtk;
+using Gnome;
+
+public class LastRolls {
+	public class Set : FSpot.GladeDialog {
+		FSpot.PhotoQuery query;
+		ImportStore imports;
+		Gtk.Window parent_window;
+		
+		uint [] ActiveRolls; // Last XX Roll Id (3, 4, 5, 6, 7, 8, 9..., 22)
+
+		[Glade.Widget] private ComboBox combo_filter; // at, after, or between
+		[Glade.Widget] private ComboBox combo_roll_1;
+		[Glade.Widget] private ComboBox combo_roll_2;
+		[Glade.Widget] private Label    and_label; // and label between two comboboxes.
+		[Glade.Widget] private Label    photos_in_selected_rolls; 
+		
+		public Set (FSpot.PhotoQuery query, ImportStore imports, Gtk.Window parent_window)
+		{
+			this.query = query;
+			this.imports = imports;
+			this.parent_window = parent_window;
+			this.ActiveRolls = imports.GetActiveRolls();	// Get the import roll history
+		}
+		
+		void on_combo_filter_changed (object o, System.EventArgs args)
+		{
+			ComboBox combo = o as ComboBox;
+			if (o == null)
+				return;
+
+			// Disable the second combobox and 'and' label if not needed.
+			combo_roll_2.Sensitive = (combo.Active == 2); // Only made combo_roll 2 active if combo_filter = 2 (between)
+			and_label.Sensitive = combo_roll_2.Sensitive; // Only display the 'and' label if roll2 is visible.
+			combo_roll_2.Visible = combo_roll_2.Sensitive; // Only made combo_roll 2 active if combo_filter = 2 (between)
+			and_label.Visible = combo_roll_2.Sensitive; // Only display the 'and' label if roll2 is visible.
+			Update_Number_Of_Photos_In_Roll();
+		}
+
+		void on_combo_roll_changed (object o, System.EventArgs args)
+		{
+			Update_Number_Of_Photos_In_Roll();
+		}
+
+		private void Update_Number_Of_Photos_In_Roll()
+		{
+			uint [] selected_rolls;
+			uint sum = 0;
+			selected_rolls = Get_ImportIDs_from_combo_rolls();
+			if (selected_rolls != null)
+				foreach (uint roll_id in selected_rolls) 
+					sum = sum + imports.GetNumberOfPhotosInRoll(roll_id);
+			photos_in_selected_rolls.Text = sum.ToString();
+		}
+		
+		private void Populate_Combo_Rolls()
+		{
+			// This function will populate the two combo rolls with "<Date> - <Imported photos> photos"
+			string header;
+
+			// For every roll in the history, prepare a header
+			for (uint k = 0; k < ActiveRolls.Length; k++)
+			{
+				header = "";
+				
+				// Get data for this import roll
+				uint numphotos = imports.GetNumberOfPhotosInRoll(ActiveRolls[k]);
+				System.DateTime dateforroll = imports.GetDateForRoll((uint) ActiveRolls[k]);
+				
+				// Prepare the header
+				header = System.String.Format ("{0} ({1})",
+					dateforroll.ToString("%dd %MMM, %HH:%mm"),
+					numphotos);		
+					
+				// Add the header we just created to both combo_rolls
+				combo_roll_1.AppendText (header);
+				combo_roll_2.AppendText (header);
+			} // for					
+		}
+		
+		private uint [] Get_ImportIDs_from_combo_rolls()
+		{
+
+			// Return null if combo boxes are not setup properly.
+			if ( (combo_roll_1.Active < 0) || ( (combo_filter.Active==2) && (combo_roll_2.Active<0) ) )
+				return null;
+				
+			// This function will convert the combo boxes to some Import Roll IDs (at, after or between import rolls) 
+			System.Collections.ArrayList result = new System.Collections.ArrayList();
+
+			switch (combo_filter.Active) {
+			
+			case 0 : // at - Return the roll the user selected
+				result.Add (ActiveRolls[ combo_roll_1.Active ]);
+				break;
+				
+			case 1 : // after - Return all rolls from latest to the one the user selected
+				for (uint k = 0; k <= combo_roll_1.Active; k++)
+					result.Add (ActiveRolls[ k ]);
+				break;
+				
+			case 2 : // between - Return all rolls between the two import rolls the user selected
+				uint k1 = (uint) combo_roll_1.Active;
+				uint k2 = (uint) combo_roll_2.Active;
+				if (k1 > k2) { // Reversed order, so lets swap the start and end :)
+					k1 = (uint) combo_roll_2.Active;
+					k2 = (uint) combo_roll_1.Active;
+				}
+				for (uint k = k1; k <= k2; k++) {
+					result.Add (ActiveRolls[ k ]);
+				}
+				break;
+				
+			default :
+				System.Console.WriteLine ("This switch case {0}, should not happend. Get_ImportIDs_from_combo_rolls", combo_filter.Active);
+				break;
+			
+			}
+			return (uint [])result.ToArray(typeof(uint));
+		}
+
+		public bool Execute ()
+		{
+			this.CreateDialog ("last_import_rolls_filter");
+			
+			// Init the dialog
+			Populate_Combo_Rolls();
+			
+			// Set default values to the combo boxes
+			combo_filter.Active = 0; // At.
+			combo_roll_1.Active = 0; // Last Roll.			
+			combo_roll_2.Active = 0; // Last Roll.			
+			
+			this.Dialog.DefaultResponse = ResponseType.Ok;
+
+			ResponseType response = (ResponseType) this.Dialog.Run ();
+
+			bool success = false;
+
+			if (response == ResponseType.Ok) {
+				uint [] resultticks = Get_ImportIDs_from_combo_rolls();
+				
+//				System.Console.Write ("Import roll " );		
+//				foreach (uint rollid in resultticks)
+//					System.Console.Write ("{0} ", rollid);		
+//				System.Console.WriteLine ("selected." );
+				
+				if (resultticks.Length > 0 ) {
+					query.ImportIdRange = new PhotoStore.ImportIdRange (resultticks);
+					success = true;
+				};
+			}
+
+			this.Dialog.Destroy ();
+			return success;
+		}
+	}
+}
