[f-spot/hyena-models: 2/6] Add a DatabasePhoto and PhotoProvider based on Hyena



commit 2f876a6f2b90597c8ab2b0a2d2f70567cd72b7d0
Author: Mike Gemünde <mike gemuende de>
Date:   Mon Oct 4 10:25:24 2010 +0200

    Add a DatabasePhoto and PhotoProvider based on Hyena

 build/build.environment.mk                         |    2 +-
 .../MainApp/FSpot.Database/DatabasePhoto.cs        |  127 ++++++++++++++++
 .../MainApp/FSpot.Database/DatabasePhotoVersion.cs |   97 ++++++++++++
 .../MainApp/FSpot.Database/DatabaseSource.cs       |   83 ++++++++++
 .../MainApp/FSpot.Database/PhotoModelProvider.cs   |  158 ++++++++++++++++++++
 .../FSpot.Database/PhotoVersionModelProvider.cs    |   33 ++++
 src/Clients/MainApp/MainApp.csproj                 |    5 +
 src/Clients/MainApp/Makefile.am                    |    5 +
 8 files changed, 509 insertions(+), 1 deletions(-)
---
diff --git a/build/build.environment.mk b/build/build.environment.mk
index e9ef74a..5083aa8 100644
--- a/build/build.environment.mk
+++ b/build/build.environment.mk
@@ -88,7 +88,7 @@ LINK_FSPOT_UTILS = -r:$(DIR_BIN)/FSpot.Utils.dll
 LINK_FSPOT_UTILS_DEPS = $(REF_FSPOT_UTILS) $(LINK_FSPOT_UTILS)
 
 # FSpot.Core
-REF_FSPOT_CORE = $(LINK_FSPOT_UTILS_DEPS) $(LINK_FSPOT_CMS_DEPS) $(LINK_HYENA_DATA_SQLITE_DEPS)
+REF_FSPOT_CORE = $(LINK_FSPOT_UTILS_DEPS) $(LINK_FSPOT_CMS_DEPS) $(LINK_HYENA_DATA_SQLITE_DEPS) $(LINK_SYSTEMDATA)
 LINK_FSPOT_CORE = -r:$(DIR_BIN)/FSpot.Core.dll
 LINK_FSPOT_CORE_DEPS = $(REF_FSPOT_CORE) $(LINK_FSPOT_CORE)
 
diff --git a/src/Clients/MainApp/FSpot.Database/DatabasePhoto.cs b/src/Clients/MainApp/FSpot.Database/DatabasePhoto.cs
new file mode 100644
index 0000000..9416f75
--- /dev/null
+++ b/src/Clients/MainApp/FSpot.Database/DatabasePhoto.cs
@@ -0,0 +1,127 @@
+//
+// DatabasePhoto.cs
+//
+// Author:
+//   Mike Gemuende <mike gemuende de>
+// 
+// Copyright (c) 2010 Mike Gemuende <mike gemuende de>
+//
+// This is free software. See COPYING for details.
+//
+
+using System;
+using System.Collections.Generic;
+
+using Hyena.Data;
+using Hyena.Data.Sqlite;
+
+using FSpot;
+using FSpot.Core;
+
+
+namespace FSpot.Database
+{
+
+    /// <summary>
+    ///    This class implements a Photo which is stored in the database. It is for using
+    ///    it with a SqliteModelProvider.
+    /// </summary>
+    public class DatabasePhoto : IPhoto, ICacheableItem
+    {
+
+#region Constructor
+
+        public DatabasePhoto ()
+        {
+        }
+
+#endregion
+
+#region Database Columns
+
+        [DatabaseColumn("id", Constraints = DatabaseColumnConstraints.PrimaryKey)]
+        public int Id { get; private set; }
+
+        [DatabaseColumn("time")]
+        public System.DateTime Time { get; private set; }
+
+        [DatabaseColumn("base_uri")]
+        private string BaseUri { get; set; }
+
+        [DatabaseColumn("filename")]
+        private string Filename { get; set; }
+
+        [DatabaseColumn("description")]
+        public string Description { get; private set; }
+
+        [DatabaseColumn("roll_id")]
+        public int RollId { get; private set; }
+
+        [DatabaseColumn("default_version_id")]
+        public int DefaultVersionId { get; private set; }
+
+        [DatabaseColumn("rating")]
+        public int DbRating { get; private set; }
+
+#endregion
+
+#region Remaining IPhoto Implementation
+
+        public Tag[] Tags {
+            get { return tags.ToArray (); }
+        }
+
+        public IPhotoVersion DefaultVersion {
+            get {
+                foreach (var version in Versions) {
+                    if ((version as DatabasePhotoVersion).VersionId == DefaultVersionId)
+                        return version;
+                }
+                return versions[0];
+                throw new Exception (String.Format ("No default Version, something is horrible wrong (photo id {0}, default version {1} but {2})", Id, (versions[0] as DatabasePhotoVersion).VersionId, DefaultVersionId));
+                //return null;
+            }
+        }
+
+        public IEnumerable<IPhotoVersion> Versions {
+            get {
+                foreach (IPhotoVersion version in versions)
+                    yield return version;
+            }
+        }
+
+        public string Name {
+            get { return Filename; }
+        }
+
+        public uint Rating {
+            //get { return (uint) (DbRating ?? 0); }
+            get { return (uint)(DbRating); }
+        }
+
+#endregion
+
+#region Remaining IBrowsableItem Implementation
+
+        private List<DatabasePhotoVersion> versions;
+        internal List<DatabasePhotoVersion> VersionList {
+           get { return versions ?? (versions = new List<DatabasePhotoVersion> ()); }
+        }
+
+        private List<Tag> tags;
+        internal List<Tag> TagList {
+            get { return tags ?? (tags = new List<Tag> ()); }
+        }
+
+#endregion
+
+#region ICachableItem Implementation
+
+        public object CacheEntryId { get; set; }
+
+        public long CacheModelId { get; set; }
+
+#endregion
+
+    }
+}
diff --git a/src/Clients/MainApp/FSpot.Database/DatabasePhotoVersion.cs b/src/Clients/MainApp/FSpot.Database/DatabasePhotoVersion.cs
new file mode 100644
index 0000000..bfe581b
--- /dev/null
+++ b/src/Clients/MainApp/FSpot.Database/DatabasePhotoVersion.cs
@@ -0,0 +1,97 @@
+//
+// DatabasePhotoVersion.cs
+//
+// Author:
+//   Mike Gemuende <mike gemuende de>
+// 
+// Copyright (c) 2010 Mike Gemuende <mike gemuende de>
+//
+// This is free software. See COPYING for details.
+//
+
+using System;
+using System.Collections.Generic;
+
+using Hyena;
+using Hyena.Data.Sqlite;
+
+using FSpot;
+using FSpot.Core;
+
+
+namespace FSpot.Database
+{
+
+    public class DatabasePhotoVersion : IPhotoVersion
+    {
+
+#region Constructor
+
+        public DatabasePhotoVersion ()
+        {
+        }
+
+#endregion
+
+#region Database Columns
+
+        [DatabaseColumn("photo_id", Constraints = DatabaseColumnConstraints.PrimaryKey)]
+        public int PhotoId { get; private set; }
+
+        [DatabaseColumn("version_id")]
+        public int VersionId { get; private set; }
+
+        [DatabaseColumn("time")]
+        public System.DateTime Time { get; private set; }
+
+        [DatabaseColumn("base_uri")]
+        private string BaseUriDb {
+            get {
+                if (BaseUri == null)
+                    return null;
+                return BaseUri.AbsoluteUri;
+            }
+            set {
+                if (value == null) {
+                    BaseUri = null;
+                    return;
+                }
+
+                BaseUri = new SafeUri (value);
+            }
+        }
+
+        [DatabaseColumn("filename")]
+        public string Filename { get; private set; }
+
+        [DatabaseColumn("import_md5")]
+        public string ImportMD5 { get; private set; }
+
+        [DatabaseColumn("protected")]
+        public bool IsProtected { get; private set; }
+
+#endregion
+
+#region Remaining IPhotoVersion Implementation
+
+        public string Name {
+            get { return Filename; }
+        }
+
+        public SafeUri BaseUri { get; private set; }
+
+        public SafeUri Uri {
+            get { return BaseUri.Append (Filename); }
+            set {
+                if (value == null)
+                    throw new ArgumentNullException ();
+
+                BaseUri = value.GetBaseUri ();
+                Filename = value.GetFilename ();
+            }
+        }
+
+#endregion
+
+    }
+}
diff --git a/src/Clients/MainApp/FSpot.Database/DatabaseSource.cs b/src/Clients/MainApp/FSpot.Database/DatabaseSource.cs
new file mode 100644
index 0000000..43f7eca
--- /dev/null
+++ b/src/Clients/MainApp/FSpot.Database/DatabaseSource.cs
@@ -0,0 +1,83 @@
+/*
+ * DatabaseSource.cs
+ *
+ * Author(s):
+ *  Mike Gemuende <mike gemuende de>
+ *
+ * This is free software. See COPYING for details.
+ */
+
+using System;
+
+using Mono.Unix;
+
+using FSpot.Core;
+
+
+namespace FSpot.Database
+{
+
+
+    public class DatabaseSource : IPhotoSource
+    {
+
+#region Private Fields
+
+        private Db database;
+        private PhotoQuery query;
+
+#endregion
+
+#region Constructors
+
+        public DatabaseSource (Db database)
+        {
+            this.database = database;
+
+            query = new PhotoQuery (database.Photos);
+        }
+
+#endregion
+
+#region IPhotoSource Implementation
+
+        public string Name {
+            get { return Catalog.GetString ("Photo Library"); }
+        }
+
+        public bool CanAddPhotos {
+            get { return true; }
+        }
+
+        public bool CanDeletePhotos {
+            get { return true; }
+        }
+
+        public bool CanRemovePhotos {
+            get { return true; }
+        }
+
+        public void AddPhotos (IBrowsableCollection photos)
+        {
+            throw new System.NotImplementedException ();
+        }
+
+        public void DeletePhotos (IBrowsableCollection photos)
+        {
+            throw new System.NotImplementedException ();
+        }
+
+        public void RemovePhotos (IBrowsableCollection photos)
+        {
+            throw new System.NotImplementedException ();
+        }
+
+        public IBrowsableCollection Photos {
+            get { return query; }
+        }
+
+#endregion
+
+
+    }
+}
diff --git a/src/Clients/MainApp/FSpot.Database/PhotoModelProvider.cs b/src/Clients/MainApp/FSpot.Database/PhotoModelProvider.cs
new file mode 100644
index 0000000..b761bbd
--- /dev/null
+++ b/src/Clients/MainApp/FSpot.Database/PhotoModelProvider.cs
@@ -0,0 +1,158 @@
+//
+// PhotoModelProvider.cs
+//
+// Author:
+//   Mike Gemuende <mike gemuende de>
+//
+// Copyright (c) 2010 Mike Gemuende <mike gemuende de>
+//
+// This is free software. See COPYING for details.
+//
+
+using System;
+using System.Data;
+using System.Text;
+using System.Collections.Generic;
+
+using Hyena;
+using Hyena.Data.Sqlite;
+
+
+namespace FSpot.Database
+{
+
+
+    public class PhotoModelProvider : SqliteModelProvider<DatabasePhoto>
+    {
+
+#region Private Fields
+
+        private PhotoVersionModelProvider photo_versions;
+
+#endregion
+
+#region Constructor
+
+        public PhotoModelProvider (HyenaSqliteConnection connection) : base (connection, "photos")
+        {
+            photo_versions = new PhotoVersionModelProvider (connection);
+        }
+
+#endregion
+
+#region Public Methods
+
+        /// <summary>
+        ///    This method loads a bunch of photos at once. It is more efficient than loading each one, because
+        ///    The photo versions can be also loaded at once.
+        /// </summary>
+        /// <remarks>
+        ///    This method is mainly used to provide efficient loading of photos for a DatabasePhotoModelCache.
+        /// </remarks>
+        public IEnumerable<DatabasePhoto> LoadAll (IDataReader reader)
+        {
+            Dictionary<int, DatabasePhoto> photo_lookup = new Dictionary<int, DatabasePhoto> ();
+            List<DatabasePhoto> photo_list = new List<DatabasePhoto> ();
+            StringBuilder photo_id_query = new StringBuilder ("photo_id IN (");
+
+            bool first = true;
+            while (reader.Read ()) {
+                DatabasePhoto photo = base.Load (reader);
+
+                photo_lookup.Add (photo.Id, photo);
+                photo_list.Add (photo);
+
+                if ( ! first)
+                    photo_id_query.Append (", ");
+
+                photo_id_query.Append (photo.Id);
+
+                first = false;
+            }
+
+            photo_id_query.Append (")");
+
+            // Add Versions
+            foreach (DatabasePhotoVersion version in photo_versions.FetchAllMatching (photo_id_query.ToString ())) {
+                photo_lookup [version.PhotoId].VersionList.Add (version);
+            }
+
+            // Add Tags
+            IDataReader tag_reader =
+                Connection.Query (String.Format ("SELECT photo_id, tag_id FROM photo_tags WHERE {0}",
+                                               photo_id_query.ToString ()));
+
+            using (tag_reader) {
+                while (tag_reader.Read ()) {
+                    int photo_id = Convert.ToInt32 (tag_reader ["photo_id"]);
+                    int tag_id = Convert.ToInt32 (tag_reader ["tag_id"]);
+
+                    photo_lookup [photo_id].TagList.Add (App.Instance.Database.Tags.Get ((uint) tag_id));
+                }
+            }
+
+            return photo_list;
+        }
+
+#endregion
+
+#region Protected Methods
+
+        protected void Populate (DatabasePhoto photo)
+        {
+            foreach (DatabasePhotoVersion version in photo_versions.FetchAllMatching ("photo_id = ?", photo.Id)) {
+                photo.VersionList.Add (version);
+            }
+
+            if (photo.VersionList.Count == 0)
+                Log.DebugFormat ("No versions for photo ({0}) found.", photo.Id);
+
+            IDataReader tag_reader =
+                Connection.Query ("SELECT photo_id, tag_id FROM photo_tags WHERE photo_id = ?", photo.Id);
+
+            using (tag_reader) {
+                while (tag_reader.Read ()) {
+                    int tag_id = Convert.ToInt32 (tag_reader ["tag_id"]);
+
+                    photo.TagList.Add (App.Instance.Database.Tags.Get ((uint) tag_id));
+                }
+            }
+        }
+
+#endregion
+
+#region Override SqliteModelProvider Behavior
+
+        public override DatabasePhoto Load (IDataReader reader)
+        {
+            DatabasePhoto photo = base.Load (reader);
+            Populate (photo);
+
+            return photo;
+        }
+
+        public override void Delete (IEnumerable<DatabasePhoto> photos)
+        {
+            List<DatabasePhotoVersion> versions_to_delete = new List<DatabasePhotoVersion> ();
+
+            foreach (DatabasePhoto photo in photos) {
+                foreach (DatabasePhotoVersion version in photo.Versions)
+                    versions_to_delete.Add (version);
+            }
+
+            base.Delete (photos);
+            photo_versions.Delete (versions_to_delete);
+        }
+
+        public override void Delete (long id)
+        {
+            base.Delete (id);
+
+            // FIXME: this only works, because the photo id is marked as primary key
+            photo_versions.Delete (id);
+        }
+
+#endregion
+
+    }
+}
diff --git a/src/Clients/MainApp/FSpot.Database/PhotoVersionModelProvider.cs b/src/Clients/MainApp/FSpot.Database/PhotoVersionModelProvider.cs
new file mode 100644
index 0000000..7b58a3c
--- /dev/null
+++ b/src/Clients/MainApp/FSpot.Database/PhotoVersionModelProvider.cs
@@ -0,0 +1,33 @@
+//
+// PhotoVersionModelProvider.cs
+//
+// Author:
+//   Mike Gemuende <mike gemuende de>
+// 
+// Copyright (c) 2010 Mike Gemuende <mike gemuende de>
+//
+// This is free software. See COPYING for details.
+//
+
+using System;
+
+using Hyena.Data.Sqlite;
+
+
+namespace FSpot.Database
+{
+
+
+    internal class PhotoVersionModelProvider : SqliteModelProvider<DatabasePhotoVersion>
+    {
+
+#region Constructor
+
+        public PhotoVersionModelProvider (HyenaSqliteConnection connection) : base (connection, "photo_versions")
+        {
+        }
+
+#endregion
+
+    }
+}
diff --git a/src/Clients/MainApp/MainApp.csproj b/src/Clients/MainApp/MainApp.csproj
index 58a3fa4..0fc2bb4 100644
--- a/src/Clients/MainApp/MainApp.csproj
+++ b/src/Clients/MainApp/MainApp.csproj
@@ -205,6 +205,11 @@
     <Compile Include="FSpot.Widgets\SelectionCollectionGridView.cs" />
     <Compile Include="FSpot.Widgets\CollectionCellGridView.cs" />
     <Compile Include="FSpot.Widgets\BrowseablePointerGridView.cs" />
+    <Compile Include="FSpot.Database\DatabasePhoto.cs" />
+    <Compile Include="FSpot.Database\DatabasePhotoVersion.cs" />
+    <Compile Include="FSpot.Database\PhotoModelProvider.cs" />
+    <Compile Include="FSpot.Database\PhotoVersionModelProvider.cs" />
+    <Compile Include="FSpot.Database\DatabaseSource.cs" />
   </ItemGroup>
   <ItemGroup>
     <EmbeddedResource Include="..\..\..\COPYING">
diff --git a/src/Clients/MainApp/Makefile.am b/src/Clients/MainApp/Makefile.am
index 4962f67..1aa85d9 100644
--- a/src/Clients/MainApp/Makefile.am
+++ b/src/Clients/MainApp/Makefile.am
@@ -10,10 +10,15 @@ SOURCES =  \
 	FSpot.ColorAdjustment/Desaturate.cs \
 	FSpot.ColorAdjustment/FullColorAdjustment.cs \
 	FSpot.ColorAdjustment/SepiaTone.cs \
+	FSpot.Database/DatabasePhoto.cs \
+	FSpot.Database/DatabasePhotoVersion.cs \
+	FSpot.Database/DatabaseSource.cs \
 	FSpot.Database/Db.cs \
 	FSpot.Database/DbException.cs \
 	FSpot.Database/DbStore.cs \
 	FSpot.Database/FSpotDatabaseConnection.cs \
+	FSpot.Database/PhotoModelProvider.cs \
+	FSpot.Database/PhotoVersionModelProvider.cs \
 	FSpot.Database/Tests/UpdaterTests.cs \
 	FSpot.Database/Updater.cs \
 	FSpot.Editors/AutoStretchEditor.cs \



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