[f-spot/rubenv-gsoc-2009: 60/86] First version management in repeatable editing.



commit 30ebd6c2f26932bd27d76802f61be992754b13b9
Author: Ruben Vermeersch <ruben savanne be>
Date:   Tue Aug 11 01:21:17 2009 +0200

    First version management in repeatable editing.
    
    Tons of bugs left to fix, but you can actually do repeatable editing
    now!

 lib/libfspotraw/fspot-librawloader.cpp |   10 +++-
 src/Core/Photo.cs                      |   12 ++--
 src/Core/PhotoVersion.cs               |   80 ++++++++++++++-----------------
 src/Core/PhotoVersionType.cs           |   32 +++++++++++++
 src/Editors/Editor.cs                  |   27 ++++++++--
 src/Editors/Processing/Pipeline.cs     |    3 +-
 src/Editors/Processing/Setting.cs      |   15 ++++++-
 src/Editors/RepeatableEditor.cs        |   73 +++++++++++++++++++++++++++--
 src/Loaders/GdkImageLoader.cs          |    3 +
 src/Loaders/IImageLoaderExtensions.cs  |    2 +-
 src/Makefile.am                        |    1 +
 src/PhotoStore.cs                      |   40 ++++++++++++----
 src/Updater.cs                         |   27 +++++++++++
 13 files changed, 250 insertions(+), 75 deletions(-)
---
diff --git a/lib/libfspotraw/fspot-librawloader.cpp b/lib/libfspotraw/fspot-librawloader.cpp
index 4642dbd..d25b394 100644
--- a/lib/libfspotraw/fspot-librawloader.cpp
+++ b/lib/libfspotraw/fspot-librawloader.cpp
@@ -225,8 +225,14 @@ fspot_librawloader_load_full (FSpotLibrawLoader *self)
 	if (!open_if_needed (self))
 		return NULL;
 
-	self->priv->raw_proc->unpack ();
-	self->priv->raw_proc->dcraw_process ();
+	result = self->priv->raw_proc->unpack ();
+	if (result != 0)
+		return NULL;
+
+	result = self->priv->raw_proc->dcraw_process ();
+	if (result != 0)
+		return NULL;
+
 	image = self->priv->raw_proc->dcraw_make_mem_image (&result);
 	if (result != 0 || image == NULL) {
 		return NULL;
diff --git a/src/Core/Photo.cs b/src/Core/Photo.cs
index 6456431..125d1f2 100644
--- a/src/Core/Photo.cs
+++ b/src/Core/Photo.cs
@@ -174,9 +174,9 @@ namespace FSpot
 	
 		// This doesn't check if a version of that name already exists, 
 		// it's supposed to be used only within the Photo and PhotoStore classes.
-		internal void AddVersionUnsafely (uint version_id, System.Uri uri, string md5_sum, string name, bool is_protected)
+		internal void AddVersionUnsafely (uint version_id, System.Uri uri, string md5_sum, string name, bool is_protected, PhotoVersionType type, uint parent_version_id)
 		{
-			versions [version_id] = new PhotoVersion (this, version_id, uri, md5_sum, name, is_protected);
+			versions [version_id] = new PhotoVersion (this, version_id, uri, md5_sum, name, is_protected, type, parent_version_id);
 	
 			highest_version_id = Math.Max (version_id, highest_version_id);
 			changes.AddVersion (version_id);
@@ -194,7 +194,7 @@ namespace FSpot
 			highest_version_id ++;
 			string md5_sum = GenerateMD5 (uri);
 
-			versions [highest_version_id] = new PhotoVersion (this, highest_version_id, uri, md5_sum, name, is_protected);
+			versions [highest_version_id] = new PhotoVersion (this, highest_version_id, uri, md5_sum, name, is_protected, PhotoVersionType.Simple, 0);
 
 			changes.AddVersion (highest_version_id);
 			return highest_version_id;
@@ -358,7 +358,7 @@ namespace FSpot
 			}
 			highest_version_id ++;
 
-			versions [highest_version_id] = new PhotoVersion (this, highest_version_id, new_uri, md5_sum, name, is_protected);
+			versions [highest_version_id] = new PhotoVersion (this, highest_version_id, new_uri, md5_sum, name, is_protected, PhotoVersionType.Simple, 0);
 
 			changes.AddVersion (highest_version_id);
 	
@@ -382,7 +382,7 @@ namespace FSpot
 					continue;
 	
 				highest_version_id ++;
-				versions [highest_version_id] = new PhotoVersion (this, highest_version_id, version.Uri, version.MD5Sum, name, is_protected);
+				versions [highest_version_id] = new PhotoVersion (this, highest_version_id, version.Uri, version.MD5Sum, name, is_protected, PhotoVersionType.Simple, 0);
 
 				changes.AddVersion (highest_version_id);
 
@@ -579,7 +579,7 @@ namespace FSpot
 	
 			// Note that the original version is never stored in the photo_versions table in the
 			// database.
-			AddVersionUnsafely (OriginalVersionId, uri, md5_sum, Catalog.GetString ("Original"), true);
+			AddVersionUnsafely (OriginalVersionId, uri, md5_sum, Catalog.GetString ("Original"), true, PhotoVersionType.Simple, 0);
 		}
 
 #region IComparable implementation
diff --git a/src/Core/PhotoVersion.cs b/src/Core/PhotoVersion.cs
index 8593b02..3f7014d 100644
--- a/src/Core/PhotoVersion.cs
+++ b/src/Core/PhotoVersion.cs
@@ -1,35 +1,24 @@
-/*
- * PhotoStore.cs
- *
- * Author(s):
- *	Ettore Perazzoli <ettore perazzoli org>
- *	Larry Ewing <lewing gnome org>
- *	Stephane Delcroix <stephane delcroix org>
- *	Thomas Van Machelen <thomas vanmachelen gmail com>
- * 
- * This is free software. See COPYING for details.
- */
+//
+// FSpot.PhotoVersion.cs
+//
+// Author(s):
+//	Ettore Perazzoli <ettore perazzoli org>
+//	Larry Ewing <lewing gnome org>
+//	Stephane Delcroix <stephane delcroix org>
+//	Thomas Van Machelen <thomas vanmachelen gmail com>
+//	Ruben Vermeersch <ruben savanne be>
+//
+// This is free software. See COPYING for details.
+//
 
 namespace FSpot
 {
 	public class PhotoVersion : IBrowsableItemVersion
 	{
-		IBrowsableItem photo;
-		uint version_id;
-		System.Uri uri;
-		string md5_sum;
-		string name;
-		bool is_protected;
-	
-		public string Name {
-			get { return name; }
-			set { name = value; }
-		}
-	
-		public IBrowsableItem Photo {
-			get { return photo; }
-		}
+		public string Name { get; set; }
+		public IBrowsableItem Photo { get; private set; }
 	
+		System.Uri uri;
 		public System.Uri Uri {
 			get { return uri; }
 			set { 
@@ -39,27 +28,30 @@ namespace FSpot
 			}
 		}
 
-		public string MD5Sum {
-			get { return md5_sum; } 
-			internal set { md5_sum = value; }
-		}
-	
-		public uint VersionId {
-			get { return version_id; }
-		}
-	
-		public bool IsProtected {
-			get { return is_protected; }
+		public string MD5Sum { get; internal set; }
+		public uint VersionId { get; private set; }
+		public bool IsProtected { get; private set; }
+		public PhotoVersionType Type { get; set; }
+		public uint ParentVersionId { get; set; }
+
+		public uint RefCount {
+			get {
+				return Core.Database.Photos.VersionRefCount (this);
+			}
 		}
 	
-		public PhotoVersion (IBrowsableItem photo, uint version_id, System.Uri uri, string md5_sum, string name, bool is_protected)
+		public PhotoVersion (Photo photo, uint version_id, System.Uri uri,
+				string md5_sum, string name, bool is_protected,
+				PhotoVersionType type, uint parent_version_id)
 		{
-			this.photo = photo;
-			this.version_id = version_id;
-			this.uri = uri;
-			this.md5_sum = md5_sum;
-			this.name = name;
-			this.is_protected = is_protected;
+			this.Photo = photo;
+			this.VersionId = version_id;
+			this.Uri = uri;
+			this.MD5Sum = md5_sum;
+			this.Name = name;
+			this.IsProtected = is_protected;
+			this.Type = type;
+			this.ParentVersionId = parent_version_id;
 		}
 	}
 }
diff --git a/src/Core/PhotoVersionType.cs b/src/Core/PhotoVersionType.cs
new file mode 100644
index 0000000..933a43e
--- /dev/null
+++ b/src/Core/PhotoVersionType.cs
@@ -0,0 +1,32 @@
+//
+// Fspot.PhotoVersionType.cs
+//
+// Author(s)
+//	Ruben Vermeersch  <ruben savanne be>
+//
+// This is free software. See COPYING for details
+//
+
+namespace FSpot
+{
+	// Denotes the type of a photo version.
+	//
+	// WARNING: Do not change the values of the enum values, unless you migrate
+	// the database along!
+	public enum PhotoVersionType
+	{
+		// A simple bitmap
+		Simple = 0,
+
+		// A version that's calculated using the associated processing
+		// settings. Obtaining the final version is a matter of taking the
+		// parent version and applying the needed processing steps.
+		Processable = 1,
+
+		// Invisible version, will be deleted as soon as there are no
+		// references anymore. Upon deletion, versions are kept around as
+		// hidden when a processable version references it as its parent
+		// version.
+		Hidden = 2
+	}
+}
diff --git a/src/Editors/Editor.cs b/src/Editors/Editor.cs
index ddd485d..c9be5ed 100644
--- a/src/Editors/Editor.cs
+++ b/src/Editors/Editor.cs
@@ -147,7 +147,15 @@ namespace FSpot.Editors {
 
 		protected virtual void SaveEditedPhoto (Photo photo, Pixbuf pixbuf)
 		{
+			// Create a new version if the original is protected...
 			bool create_version = photo.DefaultVersion.IsProtected;
+
+			// Or if there's another version based on it...
+			create_version |= photo.DefaultVersion.RefCount != 0;
+
+			// Or if it's based on a processable version.
+			create_version |= photo.DefaultVersion.Type == PhotoVersionType.Processable;
+
 			photo.SaveVersion (pixbuf, create_version);
 			photo.Changes.DataChanged = true;
 			Core.Database.Photos.Commit (photo);
@@ -159,8 +167,8 @@ namespace FSpot.Editors {
 			return Process (input, input_profile);
 		}
 
-		Pixbuf Original { get; set; }
-		Pixbuf Preview { get; set; }
+		protected Pixbuf Original { get; set; }
+		protected Pixbuf Preview { get; set; }
 
 		volatile bool preview_needed = false;
 		volatile Thread preview_thread = null;
@@ -203,7 +211,7 @@ namespace FSpot.Editors {
 		void RenderPreview ()
 		{
 			if (Original == null) {
-				Original = State.PhotoImageView.Pixbuf;
+				Original = GetOriginal ();
 			}
 
 			Pixbuf old_preview = null;
@@ -228,7 +236,12 @@ namespace FSpot.Editors {
 				});
 		}
 
-		private void CalcPreviewSize (Pixbuf input, out int width, out int height) {
+		protected virtual Pixbuf GetOriginal ()
+		{
+			return State.PhotoImageView.Pixbuf;
+		}
+
+		protected void CalcPreviewSize (Pixbuf input, out int width, out int height) {
 			int awidth = State.PhotoImageView.Allocation.Width;
 			int aheight = State.PhotoImageView.Allocation.Height;
 			int iwidth = input.Width;
@@ -264,9 +277,11 @@ namespace FSpot.Editors {
 			while (preview_thread != null)
 				preview_thread.Join ();
 
-			if (Preview != null) {
+			if (Preview != null)
 				Preview.Dispose ();
-			}
+
+			if (State.PhotoImageView.Pixbuf != Original && Original != null)
+				Original.Dispose ();
 
 			Preview = null;
 			Original = null;
diff --git a/src/Editors/Processing/Pipeline.cs b/src/Editors/Processing/Pipeline.cs
index aea09f6..a18afc8 100644
--- a/src/Editors/Processing/Pipeline.cs
+++ b/src/Editors/Processing/Pipeline.cs
@@ -125,9 +125,10 @@ namespace FSpot.Editors.Processing {
 			return setting;
 		}
 
-		public void Save ()
+		public void Save (uint version)
 		{
 			foreach (Setting setting in Settings.Values) {
+				setting.VersionId = version;
 				Core.Database.ProcessingSettings.Commit (setting);
 			}
 		}
diff --git a/src/Editors/Processing/Setting.cs b/src/Editors/Processing/Setting.cs
index bbdcd03..6cc9ac7 100644
--- a/src/Editors/Processing/Setting.cs
+++ b/src/Editors/Processing/Setting.cs
@@ -12,8 +12,21 @@ using System;
 namespace FSpot.Editors.Processing {
 	public class Setting : DbItem
 	{
+		uint version_id;
+
 		public uint PhotoId { get; private set; }
-		public uint VersionId { get; private set; }
+		public uint VersionId {
+			get { return version_id; }
+			set {
+				if (value == version_id)
+					return;
+
+				if (Id != 0 && version_id != 0)
+					throw new Exception ("Can't change version on committed setting!");
+
+				version_id = value;
+			}
+		}
 		public string Key { get; private set; }
 		public string Value { get; set; }
 
diff --git a/src/Editors/RepeatableEditor.cs b/src/Editors/RepeatableEditor.cs
index f528e69..4946967 100644
--- a/src/Editors/RepeatableEditor.cs
+++ b/src/Editors/RepeatableEditor.cs
@@ -7,13 +7,14 @@
 // This is free software. See COPYING for details.
 //
 
-using Gdk;
-using FSpot.Utils;
 using FSpot.Editors.Processing;
+using FSpot.Loaders;
+using FSpot.Utils;
+using Gdk;
+using System;
 
 namespace FSpot.Editors {
 	public abstract class RepeatableEditor : Editor {
-
 		Pipeline pipeline;
 		protected Pipeline Pipeline {
 			get {
@@ -51,13 +52,75 @@ namespace FSpot.Editors {
 
 		sealed protected override void SaveEditedPhoto (Photo photo, Pixbuf pixbuf)
 		{
-			Pipeline.Save ();
-			base.SaveEditedPhoto (photo, pixbuf);
+			// Create a new version if the original is protected...
+			bool create_version = photo.DefaultVersion.IsProtected;
+
+			// Or if it's not a Processable version.
+			create_version |= photo.DefaultVersion.Type != PhotoVersionType.Processable;
+
+			uint parent_version_id = photo.DefaultVersionId;
+			uint saved_version = photo.SaveVersion (pixbuf, create_version);
+			if (create_version) {
+				photo.DefaultVersion.Type = PhotoVersionType.Processable;
+				photo.DefaultVersion.ParentVersionId = parent_version_id;
+				photo.Changes.ChangeVersion (photo.DefaultVersionId);
+			}
+			Pipeline.Save (saved_version);
+
+			photo.Changes.DataChanged = true;
+			Core.Database.Photos.Commit (photo);
 		}
 
 		public override EditorState CreateState ()
 		{
 			return new RepeatableEditorState ();
 		}
+
+		sealed protected override Pixbuf GetOriginal ()
+		{
+			// Figure out the original version to process
+			Photo photo = State.Items [0] as Photo;
+			PhotoVersion version = photo.DefaultVersion;
+			uint parent_version = version.Type == PhotoVersionType.Processable ? version.ParentVersionId : version.VersionId;
+			Uri uri = photo.VersionUri (parent_version);
+
+			// Load the large size blocking
+			IImageLoader loader = ImageLoader.Create (uri);
+			loader.Load (ImageLoaderItem.Large);
+
+			// Load the full size in the background
+			loader.Load (ImageLoaderItem.Full, delegate (object sender, ItemsCompletedEventArgs args) {
+				if (!args.Items.Contains (ImageLoaderItem.Full))
+					return;
+
+				Pixbuf old_original = Original;
+				Pixbuf full = loader.Full;
+				if (full == null) {
+					loader.Dispose ();
+					return;
+				}
+
+				if (!StateInitialized) {
+					full.Dispose ();
+					loader.Dispose ();
+					return;
+				}
+
+				Original = full;
+				if (old_original != null)
+					old_original.Dispose ();
+
+				int width, height;
+				CalcPreviewSize (Original, out width, out height);
+				Pixbuf old_preview = Preview;
+				Preview = Original.ScaleSimple (width, height, InterpType.Nearest);
+				if (old_preview != null)
+					old_preview.Dispose ();
+
+				loader.Dispose ();
+			});
+
+			return loader.Large;
+		}
 	}
 }
diff --git a/src/Loaders/GdkImageLoader.cs b/src/Loaders/GdkImageLoader.cs
index 2caa467..2f632da 100644
--- a/src/Loaders/GdkImageLoader.cs
+++ b/src/Loaders/GdkImageLoader.cs
@@ -75,6 +75,9 @@ namespace FSpot.Loaders {
 
 		public override void Dispose ()
 		{
+			if (is_disposed)
+				return;
+
 			is_disposed = true;
 			if (image_stream != null)
 				try {
diff --git a/src/Loaders/IImageLoaderExtensions.cs b/src/Loaders/IImageLoaderExtensions.cs
index d7b39b8..07d7977 100644
--- a/src/Loaders/IImageLoaderExtensions.cs
+++ b/src/Loaders/IImageLoaderExtensions.cs
@@ -1,5 +1,5 @@
 //
-// Fspot/Loaders/IImageLoaderExtensions.cs
+// Fspot.Loaders.IImageLoaderExtensions.cs
 //
 // Author(s)
 //	Ruben Vermeersch  <ruben savanne be>
diff --git a/src/Makefile.am b/src/Makefile.am
index 24ce080..9f3dbcb 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -178,6 +178,7 @@ F_SPOT_CSDISTFILES =				\
 	$(srcdir)/Core/ColorManagement.cs	\
 	$(srcdir)/Core/Photo.cs			\
 	$(srcdir)/Core/PhotoVersion.cs		\
+	$(srcdir)/Core/PhotoVersionType.cs		\
 	$(srcdir)/Db.cs				\
 	$(srcdir)/DependentListStore.cs		\
 	$(srcdir)/DragDropTargets.cs				\
diff --git a/src/PhotoStore.cs b/src/PhotoStore.cs
index bd53a6f..345249f 100644
--- a/src/PhotoStore.cs
+++ b/src/PhotoStore.cs
@@ -92,10 +92,13 @@ public class PhotoStore : DbStore<Photo> {
 		    "	filename		STRING NOT NULL, \n" +
 			"	md5_sum		TEXT NULL, \n" +
 			"	protected	BOOLEAN, \n" +
+			"	type		INTEGER, \n" +
+			"	parent_version_id	INTEGER, \n" +
 			"	UNIQUE (photo_id, version_id)\n" +
 			")");
 
 		Database.ExecuteNonQuery ("CREATE INDEX idx_photo_versions_id ON photo_versions(photo_id)");
+		Database.ExecuteNonQuery ("CREATE INDEX idx_photo_parent_versions_id ON photo_versions(parent_version_id)");
 		Database.ExecuteNonQuery ("CREATE INDEX idx_photos_roll_id ON photos(roll_id)");
 	}
 
@@ -171,7 +174,7 @@ public class PhotoStore : DbStore<Photo> {
 	private void GetVersions (Photo photo)
 	{
 		SqliteDataReader reader = Database.Query(
-			new DbCommand("SELECT version_id, name, base_uri, filename, md5_sum, protected " + 
+			new DbCommand("SELECT version_id, name, base_uri, filename, md5_sum, protected, type, parent_version_id " +
 				      "FROM photo_versions " + 
 				      "WHERE photo_id = :id", 
 				      "id", photo.Id
@@ -184,8 +187,10 @@ public class PhotoStore : DbStore<Photo> {
 			System.Uri uri = new Uri (new Uri (reader ["base_uri"].ToString ()), reader ["filename"].ToString ());
 			string md5_sum = reader["md5_sum"] != null ? reader ["md5_sum"].ToString () : null;
 			bool is_protected = Convert.ToBoolean (reader["protected"]);
+			PhotoVersionType type = (PhotoVersionType) Enum.ToObject (typeof (PhotoVersionType), reader["type"]);
+			uint parent_version_id = Convert.ToUInt32 (reader ["parent_version_id"]);
 			                              
-			photo.AddVersionUnsafely (version_id, uri, md5_sum, name, is_protected);
+			photo.AddVersionUnsafely (version_id, uri, md5_sum, name, is_protected, type, parent_version_id);
 		}
 		reader.Close();
 	}
@@ -203,7 +208,7 @@ public class PhotoStore : DbStore<Photo> {
 	}		
 	
 	private void GetAllVersions  (string ids) {
-		SqliteDataReader reader = Database.Query ("SELECT photo_id, version_id, name, base_uri, filename, md5_sum, protected FROM photo_versions WHERE photo_id IN " + ids);
+		SqliteDataReader reader = Database.Query("SELECT photo_id, version_id, name, base_uri, filename, md5_sum, protected, type, parent_version_id FROM photo_versions WHERE photo_id IN " + ids");
 		
 		while (reader.Read ()) {
 			uint id = Convert.ToUInt32 (reader ["photo_id"]);
@@ -225,8 +230,10 @@ public class PhotoStore : DbStore<Photo> {
 				System.Uri uri = new Uri (new Uri (reader ["base_uri"].ToString ()), reader ["filename"].ToString ());
 				string md5_sum = reader["md5_sum"] != null ? reader ["md5_sum"].ToString () : null;
 				bool is_protected = Convert.ToBoolean (reader["protected"]);
+				PhotoVersionType type = (PhotoVersionType) Enum.ToObject (typeof (PhotoVersionType), reader["type"]);
+				uint parent_version_id = Convert.ToUInt32 (reader ["parent_version_id"]);
 				
-				photo.AddVersionUnsafely (version_id, uri, md5_sum, name, is_protected);
+				photo.AddVersionUnsafely (version_id, uri, md5_sum, name, is_protected, type, parent_version_id);
 			}
 
 			/*
@@ -239,6 +246,17 @@ public class PhotoStore : DbStore<Photo> {
 		reader.Close();
 	}
 
+	public uint VersionRefCount (PhotoVersion version)
+	{
+		SqliteDataReader reader = Database.Query (
+				new DbCommand ("SELECT COUNT (*) as ref_count FROM photo_versions WHERE parent_version_id = :version_id AND photo_id = :photo_id",
+				"version_id", version.VersionId,
+				"photo_id", version.Photo));
+		uint ref_count = Convert.ToUInt32 (reader ["ref_count"]);
+		reader.Close ();
+		return ref_count;
+	}
+
 	private void GetAllTags (string ids) {
 		SqliteDataReader reader = Database.Query ("SELECT photo_id, tag_id FROM photo_tags WHERE photo_id IN " + ids);
 
@@ -515,29 +533,33 @@ public class PhotoStore : DbStore<Photo> {
 			foreach (uint version_id in changes.VersionsAdded) {
 				PhotoVersion version = photo.GetVersion (version_id) as PhotoVersion;
 				Database.ExecuteNonQuery (new DbCommand (
-					"INSERT OR IGNORE INTO photo_versions (photo_id, version_id, name, base_uri, filename, protected, md5_sum) " +
-					"VALUES (:photo_id, :version_id, :name, :base_uri, :filename, :is_protected, :md5_sum)",
+					"INSERT OR IGNORE INTO photo_versions (photo_id, version_id, name, base_uri, filename, protected, md5_sum, type, parent_version_id) " +
+					"VALUES (:photo_id, :version_id, :name, :base_uri, :filename, :is_protected, :md5_sum, :type, :parent_version_id)",
 					"photo_id", photo.Id,
 					"version_id", version_id,
 					"name", version.Name,
 			        "base_uri", version.Uri.GetDirectoryUri ().ToString (),
 					"filename", version.Uri.GetFilename (),
 					"is_protected", version.IsProtected,
-					"md5_sum", (version.MD5Sum != String.Empty ? version.MD5Sum : null)));
+					"md5_sum", (version.MD5Sum != String.Empty ? version.MD5Sum : null),
+					"type", (uint) version.Type,
+					"parent_version_id", version.ParentVersionId));
 			}
 		if (changes.VersionsModified != null)
 			foreach (uint version_id in changes.VersionsModified) {
 				PhotoVersion version = photo.GetVersion (version_id) as PhotoVersion;
 				Database.ExecuteNonQuery (new DbCommand (
 					"UPDATE photo_versions SET name = :name, " +
-					"base_uri = :base_uri, filename = :filename, protected = :protected, md5_sum = :md5_sum " +
+					"base_uri = :base_uri, filename = :filename, protected = :protected, md5_sum = :md5_sum, type = :type, parent_version_id = :parent_version_id" +
 					"WHERE photo_id = :photo_id AND version_id = :version_id",
 					"name", version.Name,
 					"base_uri", version.Uri.GetDirectoryUri ().ToString (),
 					"filename", version.Uri.GetFilename (),
 					"protected", version.IsProtected,
-					"photo_id", photo.Id,
 					"md5_sum", (version.MD5Sum != String.Empty ? version.MD5Sum : null),
+					"type", (uint) version.Type,
+					"parent_version_id", version.ParentVersionId,
+					"photo_id", photo.Id,
 					"version_id", version_id));
 			}
 		photo.Changes = null;
diff --git a/src/Updater.cs b/src/Updater.cs
index bc56161..4d6dff7 100644
--- a/src/Updater.cs
+++ b/src/Updater.cs
@@ -588,6 +588,33 @@ namespace FSpot.Database {
 				Execute ("UPDATE tags SET name = 'Imported Tags' WHERE name = 'Import Tags'");
 			});
 			
+			// Update to version 17.2, add type and parent id to photo versions
+			AddUpdate (new Version (17,2),delegate () {
+				string temp_table = MoveTableToTemp ("photo_versions");
+
+				Execute (
+					"CREATE TABLE photo_versions (\n"+
+					"	photo_id	INTEGER, \n" +
+					"	version_id	INTEGER, \n" +
+					"	name		STRING, \n" +
+					"	base_uri		STRING NOT NULL, \n" +
+					"	filename		STRING NOT NULL, \n" +
+					"	md5_sum		TEXT NULL, \n" +
+					"	protected	BOOLEAN, \n" +
+					"	type		INTEGER, \n" +
+					"	parent_version_id	INTEGER, \n" +
+					"	UNIQUE (photo_id, version_id)\n" +
+					")");
+
+				Execute ("CREATE INDEX idx_photo_versions_id ON photo_versions(photo_id)");
+				Execute ("CREATE INDEX idx_photo_parent_versions_id ON photo_versions(parent_version_id)");
+
+				Execute (String.Format (
+					"INSERT OR IGNORE INTO photo_versions (photo_id, version_id, name, base_uri, filename, md5_sum, protected) " +
+					"SELECT photo_id, version_id, name, base_uri, filename, md5_sum, protected " +
+					"FROM {0}", temp_table));
+				Execute (String.Format ("UPDATE photo_versions SET type = {0}, parent_version_id = 0", (uint) PhotoVersionType.Simple));
+			});
 		}
 
 		public static void Run (Db database)



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