Re: Revamped Duplicates Patch
- From: Thomas Van Machelen <thomas vanmachelen gmail com>
- To: Larry Ewing <lewing novell com>
- Cc: f-spot-list gnome org
- Subject: Re: Revamped Duplicates Patch
- Date: Tue, 21 Mar 2006 08:15:06 +0100
Hi all,
Thanks for the comments on the duplicates patch. I think I managed to
get a lot of the raised issues out of the way.
> It would be worth while to look over the critique of the original patch
> http://mail.gnome.org/archives/f-spot-list/2005-October/msg00044.html
> as well (Gabriel already covered a lot of it though).
>
* The md5 sum field of photo is no longer a string but remains a byte
array
* I have marked the updater code as "slow"
* all md5sums are kept into a hashtable making looking for duplicates
quite a lot faster, because it omits the "all photos" query. There is a
temporary hack though: the md5sums are stored as strings into the
hashtable, because byte arrays didn't seem to be very good hashtable
keys. This could easily be improved though.
* I dropped the use of the special "Duplicate" tag. Finding duplicates
now works like querying untagged pictures.
* the "Include Duplicates" checkbox in the import window no longer
appears next to the other checkboxes but below them.
I hope this removes most of the issues raised, but feel free to send
additional comments if you have any.
Regards,
Thomas
* src/ImportCommand.cs: Added "Include Duplicates" checkbox, and update progressbar text accordingly
* src/MainWindow.cs: Added method to find duplicates from Main Window
* src/PhotoQuery.cs: Added Duplicate property to allow searching for duplicates
* src/PhotoStore.cs: Added MD5 Sum field to Photo and updated all methods accordingly, implemented some additional method to make querying duplicates easy
* src/QueryDisplay.cs: Reflect change in PhotoQuery.cs, so that QueryDisplay shows when you are looking for Duplicates
* src/Updater.cs: Implemented Updater code to add md5 field to photos
* src/f-spot.glade: Import dialog has duplicate checkbox, Main window has "Find Duplicates" menu item
Patch based on a patch by Alvaro Del Castillo
Index: src/ImportCommand.cs
===================================================================
RCS file: /cvs/gnome/f-spot/src/ImportCommand.cs,v
retrieving revision 1.60
diff -u -r1.60 ImportCommand.cs
--- src/ImportCommand.cs 13 Mar 2006 21:30:49 -0000 1.60
+++ src/ImportCommand.cs 21 Mar 2006 06:56:33 -0000
@@ -298,6 +298,7 @@
[Glade.Widget] Gtk.CheckButton attach_check;
[Glade.Widget] Gtk.CheckButton recurse_check;
[Glade.Widget] Gtk.CheckButton copy_check;
+ [Glade.Widget] Gtk.CheckButton duplicate_check;
[Glade.Widget] Gtk.Button ok_button;
[Glade.Widget] Gtk.Image tag_image;
[Glade.Widget] Gtk.Label tag_label;
@@ -312,6 +313,9 @@
SourceMenu menu;
int total;
+
+ private int duplicates;
+
PhotoStore store;
FSpot.Delay step;
@@ -319,7 +323,8 @@
ImportBackend importer;
IconView tray;
- string loading_string;
+ string default_loading = Mono.Posix.Catalog.GetString ("Loading {0} of {1}");
+ string duplicate_loading = Mono.Posix.Catalog.GetString ("Importing {0} of {1}, {2} duplicate(s)");
string import_path;
public string ImportPath {
@@ -371,7 +376,6 @@
{
main_window = mw;
step = new FSpot.Delay (10, new GLib.IdleHandler (Step));
- loading_string = Catalog.GetString ("Loading {0} of {1}");
}
private void HandleDialogResponse (object obj, ResponseArgs args)
@@ -383,12 +387,16 @@
}
}
- private void UpdateProgressBar (int count, int total)
+ private void UpdateProgressBar (int count, int total, int duplicates)
{
if (progress_bar == null)
return;
- progress_bar.Text = String.Format (loading_string, count, total);
+ if (duplicates > 0)
+ progress_bar.Text = String.Format (duplicate_loading, count, total, duplicates);
+ else
+ progress_bar.Text = String.Format (default_loading, count, total);
+
progress_bar.Fraction = (double) count / System.Math.Max (total, 1);
}
@@ -406,6 +414,7 @@
int count;
bool ongoing = true;
+ //Console.WriteLine ("Start importing the photo ...");
if (importer == null)
return false;
@@ -419,16 +428,22 @@
if (photo == null || thumbnail == null) {
Console.WriteLine ("Could not import file");
- } else {
- //icon_scrolled.Visible = true;
- collection.Add (photo);
-
- //grid.AddThumbnail (thumbnail);
+ }
+ else {
+ if (store.IsDuplicate (photo)) {
+ duplicates++;
+ if (duplicate_check.Active)
+ collection.Add (photo);
+ else
+ store.Remove (photo);
+ }
+ else {
+ collection.Add (photo);
+ }
+ UpdateProgressBar (count, total, duplicate_check.Active ? duplicates : 0);
thumbnail.Dispose ();
}
- if (count < total)
- UpdateProgressBar (count + 1, total);
if (ongoing && total > 0)
return true;
@@ -454,10 +469,11 @@
this.importer = imp;
AllowFinish = false;
+ duplicates = 0;
total = importer.Prepare ();
if (total > 0)
- UpdateProgressBar (1, total);
+ UpdateProgressBar (1, total, 0);
collection.Clear ();
collection.Capacity = total;
@@ -488,9 +504,8 @@
{
if (importer != null)
importer.Finish ();
-
+
importer = null;
-
}
public void HandleTagToggled (object o, EventArgs args)
@@ -539,12 +554,17 @@
private void HandleTagMenuSelected (Tag t)
{
tag_selected = t;
- //tag_image.Pixbuf = t.Icon;
- //tag_label.Text = t.Name;
+ }
+
+ private void HandleRecurseToggled (object sender, System.EventArgs args)
+ {
+ this.Cancel ();
+ this.Dialog.Sensitive = false;
+ Idle.Add (new IdleHandler (Start));
}
- private void HandleRecurseToggled (object sender, System.EventArgs args)
+ private void HandleDuplicateToggled (object sender, System.EventArgs args)
{
this.Cancel ();
this.Dialog.Sensitive = false;
@@ -570,6 +590,7 @@
//import_folder_entry.Activated += HandleEntryActivate;
recurse_check.Toggled += HandleRecurseToggled;
copy_check.Toggled += HandleRecurseToggled;
+ duplicate_check.Toggled += HandleDuplicateToggled;
menu = new SourceMenu (this);
source_option_menu.Menu = menu;
@@ -762,7 +783,7 @@
{
Db db = new Db (db_path, true);
- ImportCommand command = new ImportCommand ();
+ ImportCommand command = new ImportCommand (main_window);
command.ImportFromPath (db.Photos, directory_path, true);
Index: src/MainWindow.cs
===================================================================
RCS file: /cvs/gnome/f-spot/src/MainWindow.cs,v
retrieving revision 1.286
diff -u -r1.286 MainWindow.cs
--- src/MainWindow.cs 6 Mar 2006 22:13:57 -0000 1.286
+++ src/MainWindow.cs 21 Mar 2006 06:56:37 -0000
@@ -84,6 +84,7 @@
// Find
[Glade.Widget] MenuItem find_tag;
[Glade.Widget] CheckMenuItem find_untagged;
+ [Glade.Widget] CheckMenuItem find_duplicate;
// Tags
[Glade.Widget] MenuItem edit_selected_tag;
@@ -1432,6 +1433,7 @@
"Grahm Orr",
"Ewen Cheslack-Postava",
"Gabriel Burt",
+ "Thomas Van Machelen",
"Patanjali Somayaji",
"Matt Jones",
"Martin Willemoes Hansen",
@@ -1959,6 +1961,9 @@
{
if (find_untagged.Active != query.Untagged)
find_untagged.Active = query.Untagged;
+
+ if (find_duplicate.Active != query.Duplicate)
+ find_duplicate.Active = query.Duplicate;
}
void HandleZoomChanged (object sender, System.EventArgs args)
@@ -2256,6 +2261,22 @@
tag_selection_widget.SelectionChanged += OnTagSelectionChanged;
query.Untagged = true;
+ }
+ }
+
+ void HandleFindDuplicates (object sender, EventArgs args) {
+ if (query.Duplicate == find_duplicate.Active)
+ return;
+
+ if (query.Duplicate)
+ query.Duplicate = false;
+ else {
+ // Having tags selected wouldn't make sense
+ tag_selection_widget.SelectionChanged -= OnTagSelectionChanged;
+ tag_selection_widget.TagSelection = new Tag [] {};
+ tag_selection_widget.SelectionChanged += OnTagSelectionChanged;
+
+ query.Duplicate = true;
}
}
Index: src/PhotoQuery.cs
===================================================================
RCS file: /cvs/gnome/f-spot/src/PhotoQuery.cs,v
retrieving revision 1.20
diff -u -r1.20 PhotoQuery.cs
--- src/PhotoQuery.cs 19 Dec 2005 04:35:17 -0000 1.20
+++ src/PhotoQuery.cs 21 Mar 2006 06:56:37 -0000
@@ -63,6 +63,7 @@
tags = value;
photos = store.Query (tags, range);
untagged = false;
+ duplicate = false;
RequestReload ();
}
}
@@ -73,9 +74,11 @@
}
set {
range = value;
-
+
if (untagged)
photos = store.QueryUntagged (range);
+ else if (duplicate)
+ photos = store.QueryDuplicate (range);
else
photos = store.Query (tags, range);
@@ -89,17 +92,41 @@
return untagged;
}
set {
- if (untagged != value) {
- untagged = value;
+ if (untagged == value)
+ return;
+
+ untagged = value;
+
+ if (untagged) {
+ duplicate = false;
+ tags = null;
+ photos = store.QueryUntagged (range);
+ } else
+ photos = store.Query (tags, range);
+
+ RequestReload ();
+ }
+ }
- if (untagged) {
- tags = null;
- photos = store.QueryUntagged (range);
- } else
- photos = store.Query (tags, range);
-
- RequestReload ();
- }
+ private bool duplicate = false;
+ public bool Duplicate {
+ get {
+ return duplicate;
+ }
+ set {
+ if (duplicate == value)
+ return;
+
+ duplicate = value;
+
+ if (duplicate) {
+ untagged = false;
+ tags = null;
+ photos = store.QueryDuplicate (range);
+ } else
+ photos = store.Query (tags, range);
+
+ RequestReload ();
}
}
Index: src/PhotoStore.cs
===================================================================
RCS file: /cvs/gnome/f-spot/src/PhotoStore.cs,v
retrieving revision 1.91
diff -u -r1.91 PhotoStore.cs
--- src/PhotoStore.cs 7 Mar 2006 17:54:54 -0000 1.91
+++ src/PhotoStore.cs 21 Mar 2006 06:56:39 -0000
@@ -154,7 +154,7 @@
private string directory_path;
private string name;
- private string Path {
+ public string Path {
get {
return directory_path + "/" + name;
}
@@ -202,6 +202,16 @@
}
}
+ private byte[] md5sum;
+ public byte[] MD5Sum {
+ get {
+ return md5sum;
+ }
+ set {
+ md5sum = value;
+ }
+ }
+
// Version management
public const int OriginalVersionId = 1;
private uint highest_version_id;
@@ -547,7 +557,23 @@
return version;
}
+ public static byte[] GetMD5Sum (string filename)
+ {
+ FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read);
+ System.Security.Cryptography.MD5 md5ServiceProvider = new System.Security.Cryptography.MD5CryptoServiceProvider();
+
+ return md5ServiceProvider.ComputeHash(fs);
+ }
+
// Constructor
+ public Photo (uint id, long unix_time, string directory_path, string name, string description, uint default_version_id, byte[] md5sum)
+ : this (id, unix_time, directory_path, name)
+ {
+ this.description = description;
+ this.default_version_id = default_version_id;
+ this.md5sum = md5sum;
+ }
+
public Photo (uint id, long unix_time, string directory_path, string name)
: base (id)
{
@@ -557,6 +583,7 @@
this.name = name;
description = "";
+ md5sum = new byte[0];
// Note that the original version is never stored in the photo_versions table in the
// database.
@@ -564,10 +591,7 @@
}
public Photo (uint id, long unix_time, string path)
- : this (id, unix_time,
-
- System.IO.Path.GetDirectoryName (path),
- System.IO.Path.GetFileName (path))
+ : this (id, unix_time, System.IO.Path.GetDirectoryName (path), System.IO.Path.GetFileName (path))
{
}
@@ -575,6 +599,12 @@
public class PhotoStore : DbStore {
TagStore tag_store;
+
+ private Hashtable md5_cache;
+ public Hashtable MD5Cache {
+ get { return md5_cache;}
+ }
+
public static ThumbnailFactory ThumbnailFactory = new ThumbnailFactory (ThumbnailSize.Large);
@@ -642,6 +672,7 @@
: base (connection, false)
{
this.tag_store = tag_store;
+ this.md5_cache = new Hashtable ();
EnsureThumbnailDirectory ();
if (! is_new)
@@ -657,7 +688,8 @@
" directory_path STRING NOT NULL, " +
" name STRING NOT NULL, " +
" description TEXT NOT NULL, " +
- " default_version_id INTEGER NOT NULL " +
+ " default_version_id INTEGER NOT NULL, " +
+ " md5sum STRING NOT NULL " +
")";
command.ExecuteNonQuery ();
@@ -704,24 +736,30 @@
FSpot.ImageFile img = FSpot.ImageFile.Create (origPath);
long unix_time = DbUtils.UnixTimeFromDateTime (img.Date);
string description = img.Description != null ? img.Description.Split ('\0') [0] : "";
+ string directory = System.IO.Path.GetDirectoryName (newPath);
+ string name = System.IO.Path.GetFileName (newPath);
+ byte[] md5sum = Photo.GetMD5Sum(newPath);
+
SqliteCommand command = new SqliteCommand ();
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, default_version_id, md5sum) " +
+ " VALUES ({0}, '{1}', '{2}', '{3}', {4}, '{5}')",
unix_time,
- SqlString (System.IO.Path.GetDirectoryName (newPath)),
- SqlString (System.IO.Path.GetFileName (newPath)),
+ SqlString (directory),
+ SqlString (name),
SqlString (description),
- Photo.OriginalVersionId);
+ Photo.OriginalVersionId,
+ SqlString (Convert.ToBase64String (md5sum)));
command.ExecuteScalar ();
command.Dispose ();
uint id = (uint) Connection.LastInsertRowId;
- Photo photo = new Photo (id, unix_time, newPath);
+ Photo photo = new Photo (id, unix_time, directory, name, description, Photo.OriginalVersionId, md5sum);
AddToCache (photo);
+ AddToMD5Cache (photo);
photo.Loaded = true;
thumbnail = GenerateThumbnail (newPath);
@@ -791,20 +829,12 @@
photo.AddVersionUnsafely (version_id, name);
}
-
- /*
- string directory_path = null;
- if (reader [3] != null)
- directory_path = reader [3].ToString ();
- System.Console.WriteLine ("directory_path = {0}", directory_path);
- */
-
-
}
}
- private void GetAllTags () {
- SqliteCommand command = new SqliteCommand ();
+ private void GetAllTags ()
+ {
+ SqliteCommand command = new SqliteCommand ();
command.Connection = Connection;
command.CommandText = String.Format ("SELECT photo_id, tag_id " +
"FROM photo_tags ");
@@ -908,7 +938,8 @@
" directory_path, " +
" name, " +
" description, " +
- " default_version_id " +
+ " default_version_id, " +
+ " md5sum " +
" FROM photos " +
" WHERE id = {0} ",
id);
@@ -918,11 +949,13 @@
photo = new Photo (id,
Convert.ToInt64 (reader [0]),
reader [1].ToString (),
- reader [2].ToString ());
+ reader [2].ToString (),
+ reader[3].ToString (),
+ Convert.ToUInt32 (reader[4]),
+ Convert.FromBase64String (reader[5].ToString ()));
- photo.Description = reader[3].ToString ();
- photo.DefaultVersionId = Convert.ToUInt32 (reader[4]);
AddToCache (photo);
+ AddToMD5Cache (photo);
}
command.Dispose ();
@@ -953,7 +986,8 @@
command.CommandText = String.Format ("SELECT id, " +
" time, " +
" description, " +
- " default_version_id " +
+ " default_version_id, " +
+ " md5sum " +
" FROM photos " +
" WHERE directory_path = \"{0}\" " +
" AND name = \"{1}\" ",
@@ -966,11 +1000,13 @@
photo = new Photo (Convert.ToUInt32 (reader [0]),
Convert.ToInt64 (reader [1]),
directory_path,
- filename);
+ filename,
+ reader[2].ToString(),
+ Convert.ToUInt32 (reader[3]),
+ Convert.FromBase64String (reader[5].ToString ()));
- photo.Description = reader[2].ToString ();
- photo.DefaultVersionId = Convert.ToUInt32 (reader[3]);
AddToCache (photo);
+ AddToMD5Cache (photo);
}
command.Dispose ();
@@ -1012,6 +1048,7 @@
query_builder.Append (String.Format ("id = {0}", items[i].Id));
tv_query_builder.Append (String.Format ("photo_id = {0}", items[i].Id));
+ RemoveFromMD5Cache (items[i]);
RemoveFromCache (items[i]);
}
@@ -1045,6 +1082,8 @@
Remove (new Photo [] { (Photo)item });
}
+
+
public override void Commit (DbItem item)
{
DbItemEventArgs args = new DbItemEventArgs (item);
@@ -1070,14 +1109,18 @@
SqliteCommand command = new SqliteCommand ();
command.Connection = Connection;
- command.CommandText = String.Format ("UPDATE photos SET description = '{0}', " +
- " default_version_id = {1}, " +
- " time = {2} " +
- " WHERE id = {3}",
- SqlString (photo.Description),
- photo.DefaultVersionId,
- DbUtils.UnixTimeFromDateTime (photo.Time),
- photo.Id);
+ command.CommandText = String.Format (
+ "UPDATE photos " +
+ " SET description = '{0}', " +
+ " default_version_id = {1}, " +
+ " time = {2}, " +
+ " md5sum = '{3}' " +
+ " WHERE id = {4}",
+ SqlString (photo.Description),
+ photo.DefaultVersionId,
+ DbUtils.UnixTimeFromDateTime (photo.Time),
+ SqlString (Convert.ToBase64String (photo.MD5Sum)),
+ photo.Id);
command.ExecuteNonQuery ();
command.Dispose ();
@@ -1090,6 +1133,7 @@
command.Dispose ();
foreach (Tag tag in photo.Tags) {
+
command = new SqliteCommand ();
command.Connection = Connection;
command.CommandText = String.Format ("INSERT INTO photo_tags (photo_id, tag_id) " +
@@ -1122,6 +1166,38 @@
command.Dispose ();
}
}
+
+ public bool IsDuplicate (Photo photo)
+ {
+ if (photo.Id != (uint)md5_cache[Convert.ToBase64String(photo.MD5Sum)])
+ return true;
+
+ return false;
+ }
+
+ protected void AddToMD5Cache (Photo photo)
+ {
+ if (md5_cache[Convert.ToBase64String(photo.MD5Sum)] == null)
+ md5_cache.Add(Convert.ToBase64String(photo.MD5Sum), photo.Id);
+ }
+
+ protected void RemoveFromMD5Cache (Photo photo)
+ {
+ object id = md5_cache[Convert.ToBase64String(photo.MD5Sum)];
+
+ if (id == null)
+ return;
+
+ if ((uint)id != photo.Id)
+ return;
+
+ Photo[] photos = QueryMD5Sum (photo);
+
+ if (photos.Length == 0)
+ md5_cache.Remove (Convert.ToBase64String(photo.MD5Sum));
+ else
+ md5_cache[Convert.ToBase64String(photo.MD5Sum)] = photos[0].Id;
+ }
public class DateRange
{
@@ -1173,10 +1249,10 @@
photo = new Photo (id,
Convert.ToInt64 (reader [1]),
reader [2].ToString (),
- reader [3].ToString ());
-
- photo.Description = reader[4].ToString ();
- photo.DefaultVersionId = Convert.ToUInt32 (reader[5]);
+ reader [3].ToString (),
+ reader [4].ToString (),
+ Convert.ToUInt32 (reader[5]),
+ Convert.FromBase64String (reader [6].ToString ()));
version_list.Add (photo);
}
@@ -1187,6 +1263,7 @@
bool need_load = false;
foreach (Photo photo in version_list) {
AddToCache (photo);
+ AddToMD5Cache (photo);
need_load |= !photo.Loaded;
}
@@ -1212,7 +1289,8 @@
" photos.directory_path, " +
" photos.name, " +
" photos.description, " +
- " photos.default_version_id " +
+ " photos.default_version_id, " +
+ " photos.md5sum " +
" FROM photos " +
" WHERE directory_path = \"{0}\"", dir.FullName);
@@ -1237,6 +1315,29 @@
return Query (query_builder.ToString ());
}
+ public Photo[] QueryDuplicate (DateRange range)
+ {
+ Photo[] photos = Query (null, range);
+
+ ArrayList duplicates = new ArrayList ();
+
+ foreach (Photo photo in photos) {
+ if (IsDuplicate (photo))
+ duplicates.Add (photo);
+ }
+
+ return duplicates.ToArray (typeof (Photo)) as Photo[];
+ }
+
+ private Photo[] QueryMD5Sum (Photo original)
+ {
+ string query = String.Format("SELECT * FROM photos WHERE md5sum = '{0}' AND id <> {1}",
+ Convert.ToBase64String(original.MD5Sum),
+ original.Id);
+
+ return Query (query);
+ }
+
public Photo [] Query (Tag [] tags, DateRange range)
{
string query;
@@ -1271,7 +1372,8 @@
" photos.directory_path, " +
" photos.name, " +
" photos.description, " +
- " photos.default_version_id " +
+ " photos.default_version_id, " +
+ " photos.md5sum " +
" FROM photos ");
if (range != null) {
Index: src/QueryDisplay.cs
===================================================================
RCS file: /cvs/gnome/f-spot/src/QueryDisplay.cs,v
retrieving revision 1.7
diff -u -r1.7 QueryDisplay.cs
--- src/QueryDisplay.cs 19 Dec 2005 04:35:17 -0000 1.7
+++ src/QueryDisplay.cs 21 Mar 2006 06:56:39 -0000
@@ -9,6 +9,7 @@
Gtk.EventBox tag_view_box;
Gtk.Label label;
Gtk.Label untagged;
+ Gtk.Label duplicate;
Gtk.HBox warning_box;
Gtk.Button clear_button;
TagSelectionWidget selector;
@@ -40,6 +41,10 @@
untagged.Visible = false;
hbox.PackStart (untagged, false, false, 0);
+ duplicate = new Gtk.Label (Catalog.GetString ("Duplicate photos"));
+ duplicate.Visible = false;
+ hbox.PackStart (duplicate, false, false, 0);
+
tag_view_box = new EventBox ();
tag_view = new TagView (tag_view_box);
tag_view.Show ();
@@ -76,11 +81,12 @@
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.Duplicate)
active_search = true;
this.Visible = active_search;
untagged.Visible = query.Untagged;
+ duplicate.Visible = query.Duplicate;
warning_box.Visible = (query.Count < 1);
}
}
Index: src/Updater.cs
===================================================================
RCS file: /cvs/gnome/f-spot/src/Updater.cs,v
retrieving revision 1.4
diff -u -r1.4 Updater.cs
--- src/Updater.cs 13 Feb 2006 07:27:36 -0000 1.4
+++ src/Updater.cs 21 Mar 2006 06:56:39 -0000
@@ -62,11 +62,51 @@
System.Console.WriteLine ("Other tag restored. Sorry about that!");
});
- // Update from version 2 to 3
- //AddUpdate (delegate (SqliteConnection connection) {
- // do update here
- //});
- }
+ // Update from version 2 to 3: add md5sum column to photos table
+ AddUpdate (delegate (SqliteConnection connection) {
+ System.Console.WriteLine("Adding MD5 field to photos");
+
+ string temp_table = MoveTableToTemp ("photos");
+
+ 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, " +
+ " default_version_id INTEGER NOT NULL, " +
+ " md5sum STRING NOT NULL " +
+ ")");
+
+ ExecuteScalar (String.Format ( "INSERT INTO photos (id, time, directory_path, " +
+ " name, description, default_version_id, md5sum)" +
+ "SELECT id, time, directory_path, " +
+ " name, description, default_version_id, '' " +
+ "FROM {0} ",
+ temp_table));
+
+ SqliteCommand command = new SqliteCommand ();
+ command.Connection = db.Connection;
+ command.CommandText = "SELECT id, directory_path, name FROM photos";
+ SqliteDataReader reader = command.ExecuteReader ();
+
+ while (reader.Read ()) {
+ uint photo_id = Convert.ToUInt32 (reader [0]);
+ string directory = reader[1].ToString();
+ string name = reader[2].ToString();
+
+ string path = System.IO.Path.Combine(directory, name);
+
+ ExecuteScalar (String.Format ( "UPDATE photos " +
+ "SET md5sum = '{0}' " +
+ "WHERE id = {1}",
+ Convert.ToBase64String(Photo.GetMD5Sum(path)),
+ photo_id));
+ }
+
+ command.Dispose ();
+ }, true);
+ }
public static void Run (Db database)
{
Index: src/f-spot.glade
===================================================================
RCS file: /cvs/gnome/f-spot/src/f-spot.glade,v
retrieving revision 1.159
diff -u -r1.159 f-spot.glade
--- src/f-spot.glade 25 Feb 2006 08:54:05 -0000 1.159
+++ src/f-spot.glade 21 Mar 2006 06:57:01 -0000
@@ -7243,7 +7243,7 @@
<signal name="activate" handler="HandleSendMailCommand" last_modification_time="Mon, 07 Jun 2004 22:31:01 GMT"/>
<child internal-child="image">
- <widget class="GtkImage" id="image40">
+ <widget class="GtkImage" id="image43">
<property name="visible">True</property>
<property name="stock">gnome-stock-mail-fwd</property>
<property name="icon_size">1</property>
@@ -7596,7 +7596,7 @@
<property name="visible">True</property>
<property name="label" translatable="yes">_Month</property>
<property name="use_underline">True</property>
- <property name="active">True</property>
+ <property name="active">False</property>
<signal name="activate" handler="HandleArrangeByTime" last_modification_time="Fri, 20 Aug 2004 22:26:32 GMT"/>
</widget>
</child>
@@ -7606,7 +7606,7 @@
<property name="visible">True</property>
<property name="label" translatable="yes">_Folder</property>
<property name="use_underline">True</property>
- <property name="active">False</property>
+ <property name="active">True</property>
<property name="group">month</property>
<signal name="activate" handler="HandleArrangeByDirectory" last_modification_time="Fri, 20 Aug 2004 22:26:32 GMT"/>
</widget>
@@ -7664,6 +7664,16 @@
</child>
<child>
+ <widget class="GtkCheckMenuItem" id="find_duplicate">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Find Duplicates</property>
+ <property name="use_underline">True</property>
+ <property name="active">False</property>
+ <signal name="activate" handler="HandleFindDuplicates" last_modification_time="Tue, 10 Aug 2004 07:08:24 GMT"/>
+ </widget>
+ </child>
+
+ <child>
<widget class="GtkCheckMenuItem" id="find_untagged">
<property name="visible">True</property>
<property name="label" translatable="yes">_Untagged Photos</property>
@@ -9325,26 +9335,6 @@
<property name="spacing">6</property>
<child>
- <widget class="GtkCheckButton" id="recurse_check">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="label" translatable="yes">Include subdirectories</property>
- <property name="use_underline">True</property>
- <property name="relief">GTK_RELIEF_NORMAL</property>
- <property name="focus_on_click">True</property>
- <property name="active">True</property>
- <property name="inconsistent">False</property>
- <property name="draw_indicator">True</property>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="pack_type">GTK_PACK_END</property>
- </packing>
- </child>
-
- <child>
<widget class="GtkVBox" id="vbox65">
<property name="visible">True</property>
<property name="homogeneous">False</property>
@@ -9611,6 +9601,44 @@
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="active">True</property>
+ <property name="inconsistent">False</property>
+ <property name="draw_indicator">True</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkCheckButton" id="recurse_check">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Include subdirectories</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="active">True</property>
+ <property name="inconsistent">False</property>
+ <property name="draw_indicator">True</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkCheckButton" id="duplicate_check">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Include duplicates.</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="active">False</property>
<property name="inconsistent">False</property>
<property name="draw_indicator">True</property>
</widget>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]