[f-spot: 1/3] new folderview sidepane
- From: Stephane Delcroix <sdelcroix src gnome org>
- To: svn-commits-list gnome org
- Subject: [f-spot: 1/3] new folderview sidepane
- Date: Mon, 6 Jul 2009 09:07:50 +0000 (UTC)
commit 29e51ffa2f4214ab782fe6f2266b5ef2b74598a1
Author: Mike Gemünde <mike gemuende de>
Date: Tue Jun 23 23:04:07 2009 +0200
new folderview sidepane
bump db to v17, uri spliited in base_uri and filename, new FolderTreePage widget
src/DirectoryAdaptor.cs | 131 ----------
src/DirectoryCollection.cs | 52 ----
src/FSpot.addin.xml | 1 +
src/FolderQueryWidget.cs | 115 +++++++++
src/GroupSelector.cs | 11 -
src/MainWindow.cs | 70 +-----
src/Makefile.am | 5 +-
src/PhotoQuery.cs | 1 +
src/PhotoStore.cs | 139 +++++++----
src/Preferences.cs | 2 -
src/Query/FolderSet.cs | 54 ++++
src/Query/LogicalTerm.cs | 2 +-
src/Query/OrderByTime.cs | 2 +-
src/QueryWidget.cs | 43 +++-
src/Term.cs | 2 +-
src/Updater.cs | 90 +++++++-
src/Utils/UriUtils.cs | 2 +-
src/Widgets/FolderTreePage.cs | 539 +++++++++++++++++++++++++++++++++++++++++
src/ui/main_window.ui | 20 --
19 files changed, 938 insertions(+), 343 deletions(-)
---
diff --git a/src/FSpot.addin.xml b/src/FSpot.addin.xml
index 0147759..3fd7420 100644
--- a/src/FSpot.addin.xml
+++ b/src/FSpot.addin.xml
@@ -60,6 +60,7 @@
<Condition id="ViewMode" mode="library">
<SidebarPage sidebar_page_type = "FSpot.Widgets.EditorPage" />
</Condition>
+ <SidebarPage sidebar_page_type = "FSpot.Widgets.FolderTreePage" />
</Extension>
<Extension path = "/FSpot/Editors">
diff --git a/src/FolderQueryWidget.cs b/src/FolderQueryWidget.cs
new file mode 100644
index 0000000..e150e9d
--- /dev/null
+++ b/src/FolderQueryWidget.cs
@@ -0,0 +1,115 @@
+/*
+ * FSpot.Gui.FolderQueryWidget.cs
+ *
+ * Author(s)
+ * Mike Gemuende <mike gemuende de>
+ *
+ * This is free software. See COPYING for details.
+ */
+
+
+using System;
+using System.Text;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+
+using Gtk;
+
+using FSpot;
+using FSpot.Utils;
+using FSpot.Query;
+
+namespace FSpot.Gui
+{
+
+
+ public class FolderQueryWidget : HBox
+ {
+ PhotoQuery query;
+ FolderSet folder_set;
+
+ public FolderQueryWidget ()
+ {
+ folder_set = new FolderSet ();
+ query = MainWindow.Toplevel.Query;
+
+ query.SetCondition (folder_set);
+
+ Drag.DestSet (this, DestDefaults.All,
+ folder_query_widget_source_table,
+ Gdk.DragAction.Copy | Gdk.DragAction.Move);
+ }
+
+ private void UpdateGui ()
+ {
+ while (Children.Length != 0)
+ Remove (Children[0]);
+
+ int length = folder_set.Folders.Count ();
+
+ if (length == 0) {
+ Hide ();
+ return;
+ }
+
+ if (length < 4) {
+
+ foreach (Uri uri in folder_set.Folders) {
+ Image image = new Image ("gtk-directory", IconSize.Button);
+ image.TooltipText = uri.ToString ();
+ PackStart (image);
+ }
+
+ TooltipText = String.Empty;
+
+ } else {
+
+ Label label = new Label (String.Format ("<i>{0}x</i>", length));
+ label.UseMarkup = true;
+ PackStart (label);
+
+ Image image = new Image ("gtk-directory", IconSize.Button);
+ PackStart (image);
+
+ StringBuilder builder = new StringBuilder ();
+ foreach (Uri uri in folder_set.Folders) {
+ if (builder.Length > 0)
+ builder.AppendLine ();
+
+ builder.Append (uri.ToString ());
+ }
+
+ TooltipText = builder.ToString ();
+ }
+
+ ShowAll ();
+ }
+
+ public void SetFolders (IEnumerable<Uri> uris)
+ {
+ folder_set.Folders = uris;
+
+ UpdateGui ();
+ }
+
+ public void Clear ()
+ {
+ folder_set.Folders = null;
+ }
+
+ private static TargetEntry [] folder_query_widget_source_table =
+ new TargetEntry [] {
+ DragDropTargets.UriQueryEntry
+ };
+
+ protected override void OnDragDataReceived (Gdk.DragContext context, int x, int y, Gtk.SelectionData selection_data, uint info, uint time_)
+ {
+ base.OnDragDataReceived (context, x, y, selection_data, info, time_);
+
+ SetFolders (selection_data.GetUriListData ());
+ query.RequestReload ();
+ }
+
+ }
+}
diff --git a/src/GroupSelector.cs b/src/GroupSelector.cs
index e34ae5f..0ad845b 100644
--- a/src/GroupSelector.cs
+++ b/src/GroupSelector.cs
@@ -56,9 +56,6 @@ namespace FSpot {
if (adaptor is TimeAdaptor) {
MainWindow.ToolTips.SetTip (left, Catalog.GetString ("More dates"), null);
MainWindow.ToolTips.SetTip (right, Catalog.GetString ("More dates"), null);
- } else if (adaptor is DirectoryAdaptor) {
- MainWindow.ToolTips.SetTip (left, Catalog.GetString ("More directories"), null);
- MainWindow.ToolTips.SetTip (right, Catalog.GetString ("More directories"), null);
} else {
MainWindow.ToolTips.SetTip (left, Catalog.GetString ("More"), null);
MainWindow.ToolTips.SetTip (right, Catalog.GetString ("More"), null);
@@ -512,14 +509,6 @@ namespace FSpot {
{
Gtk.Menu order_menu = new Gtk.Menu();
- GtkUtil.MakeCheckMenuItem (order_menu, Catalog.GetString ("Arrange by _Month"),
- MainWindow.Toplevel.HandleArrangeByTime, true, (adaptor is TimeAdaptor), true);
-
- GtkUtil.MakeCheckMenuItem (order_menu, Catalog.GetString ("Arrange by _Folder"),
- MainWindow.Toplevel.HandleArrangeByDirectory, true, (adaptor is DirectoryAdaptor), true);
-
- GtkUtil.MakeMenuSeparator (order_menu);
-
GtkUtil.MakeCheckMenuItem (order_menu, Catalog.GetString ("_Reverse Order"),
MainWindow.Toplevel.HandleReverseOrder, true, adaptor.OrderAscending, false);
diff --git a/src/MainWindow.cs b/src/MainWindow.cs
index 5723385..8ccb208 100644
--- a/src/MainWindow.cs
+++ b/src/MainWindow.cs
@@ -83,8 +83,6 @@ public class MainWindow {
[GtkBeans.Builder.Object] Gtk.Action remove_tag;
// View
- [GtkBeans.Builder.Object] Gtk.RadioAction month;
- [GtkBeans.Builder.Object] Gtk.RadioAction directory;
[GtkBeans.Builder.Object] Gtk.ToggleAction display_toolbar;
[GtkBeans.Builder.Object] Gtk.ToggleAction display_sidebar;
[GtkBeans.Builder.Object] Gtk.ToggleAction display_timeline;
@@ -477,7 +475,6 @@ public class MainWindow {
view_notebook.SwitchPage += HandleViewNotebookSwitchPage;
group_selector.Adaptor.GlassSet += HandleAdaptorGlassSet;
group_selector.Adaptor.Changed += HandleAdaptorChanged;
- LoadPreference (Preferences.GROUP_ADAPTOR);
LoadPreference (Preferences.GROUP_ADAPTOR_ORDER_ASC);
this.selection = new MainSelection (this);
@@ -933,6 +930,12 @@ public class MainWindow {
}
}
+ public void SetFolderQuery (IEnumerable<Uri> uri_list)
+ {
+ ShowQueryWidget ();
+ query_widget.SetFolders (uri_list);
+ }
+
public void AddTagsQuery (Tag [] tags)
{
ShowQueryWidget ();
@@ -969,22 +972,14 @@ public class MainWindow {
FSpot.SimpleCalendar cal = sender as FSpot.SimpleCalendar;
JumpTo (cal.Date);
}
-#endif
- private void JumpTo (System.DateTime time)
+ void JumpTo (System.DateTime time)
{
- //FIXME this should make sure the photos are sorted by
- //time. This should be handled via a property that
- //does all the needed switching.
- if (!(group_selector.Adaptor is FSpot.TimeAdaptor))
- HandleArrangeByTime (null, null);
-
- FSpot.TimeAdaptor time_adaptor = group_selector.Adaptor as FSpot.TimeAdaptor;
- if (time_adaptor != null)
- JumpTo (query.LookupItem (time));
+ JumpTo (query.LookupItem (time));*/
}
+#endif
- private void JumpTo (int index)
+ void JumpTo (int index)
{
switch (view_mode) {
case ModeType.PhotoView:
@@ -1618,44 +1613,6 @@ public class MainWindow {
Preferences.Set (Preferences.TAG_ICON_SIZE, TagsIconSize);
}
}
-
- public void HandleArrangeByTime (object sender, EventArgs args)
- {
- if (group_selector.Adaptor is TimeAdaptor)
- return;
-
- group_selector.Adaptor.GlassSet -= HandleAdaptorGlassSet;
- group_selector.Adaptor.Changed -= HandleAdaptorChanged;
- group_selector.Adaptor = new FSpot.TimeAdaptor (query, reverse_order.Active);
-
- group_selector.Mode = FSpot.GroupSelector.RangeType.Min;
- group_selector.Adaptor.GlassSet += HandleAdaptorGlassSet;
- group_selector.Adaptor.Changed += HandleAdaptorChanged;
-
- if (sender != month)
- month.Active = true;
-
- //update the selection in the Timeline
- if (query.Range != null)
- group_selector.SetLimitsToDates(query.Range.Start, query.Range.End);
- }
-
- public void HandleArrangeByDirectory (object sender, EventArgs args)
- {
- if (group_selector.Adaptor is DirectoryAdaptor)
- return;
-
- group_selector.Adaptor.GlassSet -= HandleAdaptorGlassSet;
- group_selector.Adaptor.Changed -= HandleAdaptorChanged;
- group_selector.Adaptor = new FSpot.DirectoryAdaptor (query, reverse_order.Active);
-
- group_selector.Mode = FSpot.GroupSelector.RangeType.Min;
- group_selector.Adaptor.GlassSet += HandleAdaptorGlassSet;
- group_selector.Adaptor.Changed += HandleAdaptorChanged;
-
- if (sender != directory)
- directory.Active = true;
- }
public void HandleReverseOrder (object sender, EventArgs args)
{
@@ -1715,8 +1672,6 @@ public class MainWindow {
Preferences.Set (Preferences.SHOW_DATES, icon_view.DisplayDates);
Preferences.Set (Preferences.SHOW_RATINGS, icon_view.DisplayRatings);
- Preferences.Set (Preferences.GROUP_ADAPTOR, (group_selector.Adaptor is DirectoryAdaptor) ? 1 : 0);
- Preferences.Set (Preferences.GROUP_ADAPTOR_ORDER_ASC, group_selector.Adaptor.OrderAscending);
Preferences.Set (Preferences.GLASS_POSITION, group_selector.GlassPosition);
Preferences.Set (Preferences.SIDEBAR_POSITION, main_hpaned.Position);
@@ -2536,11 +2491,6 @@ public class MainWindow {
if (display_ratings_menu_item.Active != Preferences.Get<bool> (key))
display_ratings_menu_item.Active = Preferences.Get<bool> (key);
break;
-
- case Preferences.GROUP_ADAPTOR:
- if (Preferences.Get<int> (key) == 1)
- directory.Active = true;
- break;
case Preferences.GROUP_ADAPTOR_ORDER_ASC:
group_selector.Adaptor.OrderAscending = Preferences.Get<bool> (key);
diff --git a/src/Makefile.am b/src/Makefile.am
index bf79e46..e31b793 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -39,6 +39,7 @@ CORE_CSDISTFILES = \
QUERY_CSDISTFILES = \
$(srcdir)/Query/DateRange.cs \
+ $(srcdir)/Query/FolderSet.cs \
$(srcdir)/Query/IOrderCondition.cs \
$(srcdir)/Query/IQueryCondition.cs \
$(srcdir)/Query/LogicalTerm.cs \
@@ -129,8 +130,6 @@ F_SPOT_CSDISTFILES = \
$(srcdir)/Core/PhotoVersion.cs \
$(srcdir)/Db.cs \
$(srcdir)/DependentListStore.cs \
- $(srcdir)/DirectoryAdaptor.cs \
- $(srcdir)/DirectoryCollection.cs \
$(srcdir)/DragDropTargets.cs \
$(srcdir)/Editors/Editor.cs \
$(srcdir)/Editors/AutoStretchEditor.cs \
@@ -168,6 +167,7 @@ F_SPOT_CSDISTFILES = \
$(srcdir)/Filters/SharpFilter.cs \
$(srcdir)/Filters/UniqueNameFilter.cs \
$(srcdir)/Filters/WhiteListFilter.cs \
+ $(srcdir)/FolderQueryWidget.cs \
$(srcdir)/FormClient.cs \
$(srcdir)/FullScreenView.cs \
$(srcdir)/GdkGlx.cs \
@@ -279,6 +279,7 @@ F_SPOT_CSDISTFILES = \
$(srcdir)/Widgets/EditorPage.cs \
$(srcdir)/Widgets/Filmstrip.cs \
$(srcdir)/Widgets/FindBar.cs \
+ $(srcdir)/Widgets/FolderTreePage.cs \
$(srcdir)/Widgets/IEffect.cs \
$(srcdir)/Widgets/ITransition.cs \
$(srcdir)/Widgets/IconView.cs \
diff --git a/src/PhotoQuery.cs b/src/PhotoQuery.cs
index 7d84aa8..1f95ae2 100644
--- a/src/PhotoQuery.cs
+++ b/src/PhotoQuery.cs
@@ -274,6 +274,7 @@ namespace FSpot {
if (Changed != null)
Changed (this);
+
Log.DebugTimerPrint (timer, "Reloading the query took {0}");
}
diff --git a/src/PhotoStore.cs b/src/PhotoStore.cs
index cd0ba39..688d171 100644
--- a/src/PhotoStore.cs
+++ b/src/PhotoStore.cs
@@ -71,7 +71,7 @@ public class PhotoStore : DbStore<Photo> {
try {
thumbnail = ((FSpot.IThumbnailContainer)img).GetEmbeddedThumbnail ();
} catch (Exception e) {
- Log.Debug ("Exception while loading embedded thumbail {0}", e.ToString ());
+ Log.DebugFormat ("Exception while loading embedded thumbail {0}", e.ToString ());
}
}
@@ -85,13 +85,6 @@ public class PhotoStore : DbStore<Photo> {
return thumbnail;
}
-
-// public static void MoveThumbnail (string old_path, string new_path)
-// {
-// System.IO.File.Move (ThumbnailGenerator.ThumbnailPath (UriUtils.PathToFileUri (old_path)),
-// ThumbnailGenerator.ThumbnailPath(UriUtils.PathToFileUri (new_path)));
-// }
-
// Constructor
public PhotoStore (QueuedSqliteDatabase database, bool is_new)
@@ -106,7 +99,8 @@ public class PhotoStore : DbStore<Photo> {
"CREATE TABLE photos (\n" +
" id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, \n" +
" time INTEGER NOT NULL, \n" +
- " uri STRING NOT NULL, \n" +
+ " base_uri STRING NOT NULL, \n" +
+ " filename STRING NOT NULL, \n" +
" description TEXT NOT NULL, \n" +
" roll_id INTEGER NOT NULL, \n" +
" default_version_id INTEGER NOT NULL, \n" +
@@ -126,7 +120,8 @@ public class PhotoStore : DbStore<Photo> {
" photo_id INTEGER, \n" +
" version_id INTEGER, \n" +
" name STRING, \n" +
- " uri STRING NOT NULL, \n" +
+ " base_uri STRING NOT NULL, \n" +
+ " filename STRING NOT NULL, \n" +
" md5_sum TEXT NULL, \n" +
" protected BOOLEAN, \n" +
" UNIQUE (photo_id, version_id)\n" +
@@ -194,10 +189,11 @@ public class PhotoStore : DbStore<Photo> {
uint id = (uint) Database.Execute (
new DbCommand (
- "INSERT INTO photos (time, uri, description, roll_id, default_version_id, rating, md5_sum) " +
- "VALUES (:time, :uri, :description, :roll_id, :default_version_id, :rating, :md5_sum)",
+ "INSERT INTO photos (time, base_uri, filename, description, roll_id, default_version_id, rating, md5_sum) " +
+ "VALUES (:time, :base_uri, :filename, :description, :roll_id, :default_version_id, :rating, :md5_sum)",
"time", unix_time,
- "uri", new_uri.OriginalString,
+ "base_uri", new_uri.GetDirectoryUri ().ToString (),
+ "filename", new_uri.GetFilename (),
"description", description,
"roll_id", roll_id,
"default_version_id", Photo.OriginalVersionId,
@@ -220,7 +216,7 @@ public class PhotoStore : DbStore<Photo> {
private void GetVersions (Photo photo)
{
SqliteDataReader reader = Database.Query(
- new DbCommand("SELECT version_id, name, uri, md5_sum, protected " +
+ new DbCommand("SELECT version_id, name, base_uri, filename, md5_sum, protected " +
"FROM photo_versions " +
"WHERE photo_id = :id",
"id", photo.Id
@@ -230,9 +226,10 @@ public class PhotoStore : DbStore<Photo> {
while (reader.Read ()) {
uint version_id = Convert.ToUInt32 (reader ["version_id"]);
string name = reader["name"].ToString ();
- System.Uri uri = new System.Uri (reader["uri"].ToString ());
+ 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"]);
+
photo.AddVersionUnsafely (version_id, uri, md5_sum, name, is_protected);
}
reader.Close();
@@ -251,7 +248,7 @@ public class PhotoStore : DbStore<Photo> {
}
private void GetAllVersions () {
- SqliteDataReader reader = Database.Query("SELECT photo_id, version_id, name, uri, md5_sum, protected FROM photo_versions");
+ SqliteDataReader reader = Database.Query("SELECT photo_id, version_id, name, base_uri, filename, md5_sum, protected FROM photo_versions");
while (reader.Read ()) {
uint id = Convert.ToUInt32 (reader ["photo_id"]);
@@ -270,9 +267,10 @@ public class PhotoStore : DbStore<Photo> {
if (reader ["version_id"] != null) {
uint version_id = Convert.ToUInt32 (reader ["version_id"]);
string name = reader["name"].ToString ();
- System.Uri uri = new System.Uri (reader["uri"].ToString ());
+ 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"]);
+
photo.AddVersionUnsafely (version_id, uri, md5_sum, name, is_protected);
}
@@ -317,9 +315,9 @@ public class PhotoStore : DbStore<Photo> {
Photo photo = LookupInCache (id);
if (photo != null)
return photo;
-
+
SqliteDataReader reader = Database.Query(
- new DbCommand("SELECT time, uri, description, roll_id, default_version_id, rating, md5_sum " +
+ new DbCommand("SELECT time, base_uri, filename, description, roll_id, default_version_id, rating, md5_sum " +
"FROM photos " +
"WHERE id = :id", "id", id
)
@@ -328,7 +326,7 @@ public class PhotoStore : DbStore<Photo> {
if (reader.Read ()) {
photo = new Photo (id,
Convert.ToInt64 (reader ["time"]),
- new System.Uri (reader ["uri"].ToString ()),
+ new Uri (new Uri (reader ["base_uri"].ToString ()), reader ["filename"].ToString ()),
reader["md5_sum"] != null ? reader["md5_sum"].ToString () : null
);
@@ -353,7 +351,7 @@ public class PhotoStore : DbStore<Photo> {
public Photo GetByPath (string path)
{
return GetByUri (UriUtils.PathToFileUri (path));
- }
+ }
public Photo GetByUri (System.Uri uri)
{
@@ -361,10 +359,14 @@ public class PhotoStore : DbStore<Photo> {
uint timer = Log.DebugTimerStart ();
- SqliteDataReader reader = Database.Query (new DbCommand ("SELECT id, time, description, roll_id, default_version_id, rating, photos.md5_sum AS md5_sum " +
- " FROM photos " +
- " LEFT JOIN photo_versions AS pv ON photos.id = pv.photo_id" +
- " WHERE photos.uri = :uri OR pv.uri = :uri", "uri", uri.ToString ()));
+ SqliteDataReader reader =
+ Database.Query (new DbCommand ("SELECT id, time, description, roll_id, default_version_id, rating, photos.md5_sum AS md5_sum " +
+ " FROM photos " +
+ " LEFT JOIN photo_versions AS pv ON photos.id = pv.photo_id" +
+ " WHERE (photos.base_uri = :base_uri AND photos.filename = :filename)" +
+ " OR (pv.base_uri = :base_uri AND pv.filename = :filename)",
+ "base_uri", uri.GetDirectoryUri ().ToString (),
+ "filename", uri.GetFilename ()));
if (reader.Read ()) {
photo = new Photo (Convert.ToUInt32 (reader ["id"]),
@@ -377,7 +379,8 @@ public class PhotoStore : DbStore<Photo> {
photo.DefaultVersionId = Convert.ToUInt32 (reader["default_version_id"]);
photo.Rating = Convert.ToUInt32 (reader ["rating"]);
}
- reader.Close();
+
+ reader.Close();
Log.DebugTimerPrint (timer, "GetByUri query took {0}");
if (photo == null)
@@ -402,7 +405,7 @@ public class PhotoStore : DbStore<Photo> {
SqliteDataReader reader = Database.Query (
new DbCommand ("SELECT DISTINCT " +
- "id, time, photos.uri AS uri, description, roll_id, default_version_id, rating " +
+ "id, time, photos.base_uri AS uri, photos.filename AS filename, description, roll_id, default_version_id, rating " +
"FROM photos " +
"LEFT JOIN photo_versions " +
"ON photos.id = photo_versions.photo_id " +
@@ -413,11 +416,11 @@ public class PhotoStore : DbStore<Photo> {
);
while (reader.Read ()) {
- Photo photo = new Photo (Convert.ToUInt32 (reader ["id"]),
- Convert.ToInt64 (reader ["time"]),
- new System.Uri (reader ["uri"].ToString ()),
- md5_sum
- );
+ Photo photo =
+ new Photo (Convert.ToUInt32 (reader ["id"]),
+ Convert.ToInt64 (reader ["time"]),
+ new Uri (new Uri (reader ["base_uri"].ToString ()), reader ["filename"].ToString ()),
+ md5_sum);
photo.Description = reader["description"].ToString ();
photo.RollId = Convert.ToUInt32 (reader["roll_id"]);
@@ -519,14 +522,16 @@ public class PhotoStore : DbStore<Photo> {
"SET description = :description, " +
" default_version_id = :default_version_id, " +
" time = :time, " +
- " uri = :uri, " +
+ " base_uri = :base_uri, " +
+ " filename = :filename, " +
" rating = :rating, " +
" md5_sum = :md5_sum " +
"WHERE id = :id ",
"description", photo.Description,
"default_version_id", photo.DefaultVersionId,
"time", DbUtils.UnixTimeFromDateTime (photo.Time),
- "uri", photo.VersionUri (Photo.OriginalVersionId).OriginalString,
+ "base_uri", photo.VersionUri (Photo.OriginalVersionId).GetDirectoryUri ().ToString (),
+ "filename", photo.VersionUri (Photo.OriginalVersionId).GetFilename (),
"rating", String.Format ("{0}", photo.Rating),
"md5_sum", (photo.MD5Sum != String.Empty ? photo.MD5Sum : null),
"id", photo.Id
@@ -561,12 +566,13 @@ 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, uri, protected, md5_sum) " +
- "VALUES (:photo_id, :version_id, :name, :uri, :is_protected, :md5_sum)",
+ "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)",
"photo_id", photo.Id,
"version_id", version_id,
"name", version.Name,
- "uri", version.Uri.ToString (),
+ "base_uri", version.Uri.GetDirectoryUri ().ToString (),
+ "filename", version.Uri.GetFilename (),
"is_protected", version.IsProtected,
"md5_sum", (version.MD5Sum != String.Empty ? version.MD5Sum : null)));
}
@@ -575,10 +581,11 @@ public class PhotoStore : DbStore<Photo> {
PhotoVersion version = photo.GetVersion (version_id) as PhotoVersion;
Database.ExecuteNonQuery (new DbCommand (
"UPDATE photo_versions SET name = :name, " +
- "uri = :uri, protected = :protected, md5_sum = :md5_sum " +
+ "base_uri = :base_uri, filename = :filename, protected = :protected, md5_sum = :md5_sum " +
"WHERE photo_id = :photo_id AND version_id = :version_id",
"name", version.Name,
- "uri", version.Uri.ToString (),
+ "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),
@@ -795,7 +802,7 @@ public class PhotoStore : DbStore<Photo> {
if (sql_clause == null || sql_clause.Trim () == String.Empty)
continue;
-
+ Log.Debug ("Type {0} provided clause: {1}", condition.GetType ().ToString (), sql_clause);
query_builder.Append (where_added ? " AND " : " WHERE ");
query_builder.Append (sql_clause);
where_added = true;
@@ -812,7 +819,7 @@ public class PhotoStore : DbStore<Photo> {
if (sql_clause == null || sql_clause.Trim () == String.Empty)
continue;
-
+ Log.Debug ("Type {0} provided clause: {1}", condition.GetType ().ToString (), sql_clause);
query_builder.Append (order_added ? " , " : "ORDER BY ");
query_builder.Append (sql_clause);
order_added = true;
@@ -834,6 +841,7 @@ public class PhotoStore : DbStore<Photo> {
public void QueryToTemp(string temp_table, string query)
{
uint timer = Log.DebugTimerStart ();
+ Log.Debug ("Query Started : {0}", query);
Database.BeginTransaction ();
Database.ExecuteNonQuery (String.Format ("DROP TABLE IF EXISTS {0}", temp_table));
//Database.ExecuteNonQuery (String.Format ("CREATE TEMPORARY TABLE {0} AS {1}", temp_table, query));
@@ -869,10 +877,11 @@ public class PhotoStore : DbStore<Photo> {
Photo photo = LookupInCache (id);
if (photo == null) {
- photo = new Photo (id,
- Convert.ToInt64 (reader ["time"]),
- new System.Uri (reader ["uri"].ToString ()),
- reader["md5_sum"] != null ? reader ["md5_sum"].ToString () : null
+ photo =
+ new Photo (id,
+ Convert.ToInt64 (reader ["time"]),
+ new Uri (new Uri (reader ["base_uri"].ToString ()), reader ["filename"].ToString ()),
+ reader["md5_sum"] != null ? reader ["md5_sum"].ToString () : null
);
photo.Description = reader["description"].ToString ();
photo.RollId = Convert.ToUInt32 (reader["roll_id"]);
@@ -925,21 +934,43 @@ public class PhotoStore : DbStore<Photo> {
public Photo [] Query (System.Uri uri)
{
- Log.Debug ("Query Uri {0}", uri);
+ Log.DebugFormat ("Query Uri {0}", uri);
+
+ /* query by file */
+ if (uri.IsFile) {
+ return Query (new DbCommand (
+ "SELECT id, " +
+ "time, " +
+ "base_uri, " +
+ "filename, " +
+ "description, " +
+ "roll_id, " +
+ "default_version_id, " +
+ "rating, " +
+ "md5_sum " +
+ "FROM photos " +
+ "WHERE base_uri LIKE :base_uri " +
+ "AND filename LIKE :filename",
+ "base_uri", uri.GetDirectoryUri ().ToString (),
+ "filename", uri.GetFilename ()));
+ }
+
+ /* query by directory */
return Query (new DbCommand (
"SELECT id, " +
"time, " +
- "uri, " +
+ "base_uri, " +
+ "filename, " +
"description, " +
"roll_id, " +
"default_version_id, " +
"rating, " +
"md5_sum " +
"FROM photos " +
- "WHERE uri LIKE :uri " +
- "AND uri NOT LIKE :uri_",
- "uri", uri.ToString () + "%",
- "uri_", uri.ToString () + "/%/%"));
+ "WHERE base_uri LIKE :base_uri " +
+ "AND base_uri NOT LIKE :base_uri_",
+ "base_uri", uri.ToString () + "%",
+ "base_uri_", uri.ToString () + "/%/%"));
}
[Obsolete ("drop this, use IQueryCondition correctly instead")]
@@ -986,7 +1017,8 @@ public class PhotoStore : DbStore<Photo> {
ArrayList where_clauses = new ArrayList ();
query_builder.Append ("SELECT id, " +
"time, " +
- "uri, " +
+ "base_uri, " +
+ "filename, " +
"description, " +
"roll_id, " +
"default_version_id, " +
@@ -1058,7 +1090,8 @@ public class PhotoStore : DbStore<Photo> {
ArrayList where_clauses = new ArrayList ();
query_builder.Append ("SELECT id, " +
"time, " +
- "uri, " +
+ "base_uri, " +
+ "filename, " +
"description, " +
"roll_id, " +
"default_version_id, " +
diff --git a/src/Preferences.cs b/src/Preferences.cs
index 29c5803..6290532 100644
--- a/src/Preferences.cs
+++ b/src/Preferences.cs
@@ -51,7 +51,6 @@ namespace FSpot
public const string TAG_ICON_AUTOMATIC = APP_FSPOT + "ui/tag_icon_automatic";
public const string GLASS_POSITION = APP_FSPOT + "ui/glass_position";
- public const string GROUP_ADAPTOR = APP_FSPOT + "ui/group_adaptor";
public const string GROUP_ADAPTOR_ORDER_ASC = APP_FSPOT + "ui/group_adaptor_sort_asc";
public const string SIDEBAR_POSITION = APP_FSPOT + "ui/sidebar_size";
@@ -118,7 +117,6 @@ namespace FSpot
case GROUP_ADAPTOR_ORDER_ASC:
return false;
- case GROUP_ADAPTOR:
case GLASS_POSITION:
return null;
diff --git a/src/Query/FolderSet.cs b/src/Query/FolderSet.cs
new file mode 100644
index 0000000..70a13ea
--- /dev/null
+++ b/src/Query/FolderSet.cs
@@ -0,0 +1,54 @@
+/*
+ * FSpot.Query.FolderSet
+ *
+ * Author(s):
+ * Mike Gemuende <mike gemuende de>
+ *
+ * This is free software. See COPYING for details.
+ */
+
+
+using System;
+using System.Collections.Generic;
+
+
+namespace FSpot.Query
+{
+ public class FolderSet : IQueryCondition
+ {
+ HashSet<Uri> uri_list;
+
+ public FolderSet ()
+ {
+ uri_list = new HashSet<Uri> ();
+ }
+
+ public IEnumerable<Uri> Folders {
+ get { return uri_list; }
+ set { uri_list = (value == null) ? new HashSet<Uri> () : new HashSet<Uri> (value); }
+ }
+
+ protected static string EscapeQuotes (string v)
+ {
+ return v == null ? String.Empty : v.Replace("'", "''");
+ }
+
+ public string SqlClause ()
+ {
+ string[] items = new string [uri_list.Count];
+
+ if (items.Length == 0)
+ return null;
+
+ int i = 0;
+ foreach (Uri uri in uri_list) {
+ items[i] =
+ String.Format ("id IN (SELECT id FROM photos WHERE base_uri LIKE '{0}%')",
+ EscapeQuotes (uri.ToString ()));
+ i++;
+ }
+
+ return String.Join (" OR ", items);
+ }
+ }
+}
diff --git a/src/Query/LogicalTerm.cs b/src/Query/LogicalTerm.cs
index 9a4640c..f9d0b23 100644
--- a/src/Query/LogicalTerm.cs
+++ b/src/Query/LogicalTerm.cs
@@ -190,7 +190,7 @@ namespace FSpot.Query
foreach (LogicalTerm t in (term as AndTerm).terms)
Add (t);
else
- terms.Add (term);
+ terms.Add (term);
}
public override string SqlClause ()
diff --git a/src/Query/OrderByTime.cs b/src/Query/OrderByTime.cs
index a1a891e..3383fd0 100644
--- a/src/Query/OrderByTime.cs
+++ b/src/Query/OrderByTime.cs
@@ -29,7 +29,7 @@ namespace FSpot.Query {
public string SqlClause ()
{
- return String.Format (" time {0}, uri {0} ", asc ? "ASC" : "DESC");
+ return String.Format (" time {0}, filename {0} ", asc ? "ASC" : "DESC");
}
}
}
diff --git a/src/QueryWidget.cs b/src/QueryWidget.cs
index 59b72ef..ee4c7e1 100644
--- a/src/QueryWidget.cs
+++ b/src/QueryWidget.cs
@@ -7,17 +7,29 @@
* This is free software. See COPYING for details.
*/
-using FSpot.Query;
-using FSpot.Widgets;
+
+using System;
+using System.Collections.Generic;
+
using Mono.Unix;
+
using Gtk;
+using FSpot.Gui;
+using FSpot.Utils;
+using FSpot.Query;
+using FSpot.Widgets;
+
+
+
namespace FSpot {
public class QueryWidget : HighlightedBox {
PhotoQuery query;
LogicWidget logic_widget;
- Gtk.HBox box;
+ FolderQueryWidget folder_query_widget;
+
+ Gtk.HBox box;
Gtk.Label label;
Gtk.Label untagged;
Gtk.Label rated;
@@ -70,6 +82,10 @@ namespace FSpot {
rollfilter.Visible = false;
box.PackStart (rollfilter, false, false, 0);
+ folder_query_widget = new FolderQueryWidget ();
+ folder_query_widget.Visible = false;
+ box.PackStart (folder_query_widget, false, false, 0);
+
logic_widget = new LogicWidget (query, db.Tags);
logic_widget.Show ();
box.PackStart (logic_widget, true, true, 0);
@@ -127,6 +143,10 @@ namespace FSpot {
query.RatingRange = null;
logic_widget.Clear = true;
logic_widget.UpdateQuery ();
+
+ folder_query_widget.Clear ();
+ query.RequestReload ();
+
HideBar ();
}
@@ -147,11 +167,14 @@ namespace FSpot {
if (query.ExtraCondition == null)
logic_widget.Clear = true;
- if (!logic_widget.Clear || query.Untagged || (query.RollSet != null) || (query.RatingRange != null)) {
- ShowBar ();
- } else {
+ if ( ! logic_widget.Clear
+ || query.Untagged
+ || (query.RollSet != null)
+ || (query.RatingRange != null)
+ || folder_query_widget.Visible)
+ ShowBar ();
+ else
HideBar ();
- }
untagged.Visible = query.Untagged;
rated.Visible = (query.RatingRange != null);
@@ -197,5 +220,11 @@ namespace FSpot {
{
return logic_widget.TagRequired (tag);
}
+
+ public void SetFolders (IEnumerable<Uri> uri_list)
+ {
+ folder_query_widget.SetFolders (uri_list);
+ query.RequestReload ();
+ }
}
}
diff --git a/src/Term.cs b/src/Term.cs
index 8c9c5f2..f6321c3 100644
--- a/src/Term.cs
+++ b/src/Term.cs
@@ -944,7 +944,7 @@ namespace FSpot {
public override string SqlCondition ()
{
return String.Format (
- "id {0}IN (SELECT id FROM photos WHERE uri LIKE '%{1}%' OR description LIKE '%{1}%')",
+ "id {0}IN (SELECT id FROM photos WHERE base_uri LIKE '%{1}%' OR filename LIKE '%{1}%' OR description LIKE '%{1}%')",
(IsNegated ? "NOT " : ""), EscapeQuotes(text)
);
}
diff --git a/src/Updater.cs b/src/Updater.cs
index eedc967..0718577 100644
--- a/src/Updater.cs
+++ b/src/Updater.cs
@@ -494,6 +494,94 @@ namespace FSpot.Database {
//AddUpdate (new Version (14,0), delegate () {
// do update here
//});
+
+ // Update to version 17.0, split uri and filename
+ AddUpdate (new Version (17,0),delegate () {
+ string tmp_photos = MoveTableToTemp ("photos");
+ string tmp_versions = MoveTableToTemp ("photo_versions");
+
+ Execute (
+ "CREATE TABLE photos (\n" +
+ " id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, \n" +
+ " time INTEGER NOT NULL, \n" +
+ " base_uri STRING NOT NULL, \n" +
+ " filename STRING NOT NULL, \n" +
+ " description TEXT NOT NULL, \n" +
+ " roll_id INTEGER NOT NULL, \n" +
+ " default_version_id INTEGER NOT NULL, \n" +
+ " rating INTEGER NULL, \n" +
+ " md5_sum TEXT NULL\n" +
+ ")");
+
+ 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" +
+ " UNIQUE (photo_id, version_id)\n" +
+ ")");
+
+ SqliteDataReader reader = ExecuteReader (String.Format (
+ "SELECT id, time, uri, description, roll_id, default_version_id, rating, md5_sum " +
+ "FROM {0} ", tmp_photos));
+
+ while (reader.Read ()) {
+ System.Uri photo_uri = new System.Uri (reader ["uri"] as string);
+
+ string filename = photo_uri.GetFilename ();
+ Uri base_uri = photo_uri.GetDirectoryUri ();
+
+ string md5 = reader["md5_sum"] != null ? reader ["md5_sum"].ToString () : null;
+
+ Execute (new DbCommand (
+ "INSERT INTO photos (id, time, base_uri, filename, description, roll_id, default_version_id, rating, md5_sum) " +
+ "VALUES (:id, :time, :base_uri, :filename, :description, :roll_id, :default_version_id, :rating, :md5_sum)",
+ "id", Convert.ToUInt32 (reader ["id"]),
+ "time", Convert.ToUInt32 (reader ["time"]),
+ "base_uri", base_uri.ToString (),
+ "filename", filename,
+ "description", reader["description"].ToString (),
+ "roll_id", Convert.ToUInt32 (reader ["roll_id"]),
+ "default_version_id", Convert.ToUInt32 (reader ["default_version_id"]),
+ "rating", Convert.ToUInt32 (reader ["rating"]),
+ "md5_sum", String.IsNullOrEmpty (md5) ? null : md5));
+ }
+
+ reader.Close ();
+
+ reader = ExecuteReader (String.Format (
+ "SELECT photo_id, version_id, name, uri, md5_sum, protected " +
+ "FROM {0} ", tmp_versions));
+
+ while (reader.Read ()) {
+ System.Uri photo_uri = new System.Uri (reader ["uri"] as string);
+
+ string filename = photo_uri.GetFilename ();
+ Uri base_uri = photo_uri.GetDirectoryUri ();
+
+ string md5 = reader["md5_sum"] != null ? reader ["md5_sum"].ToString () : null;
+
+ Execute (new DbCommand (
+ "INSERT 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)",
+ "photo_id", Convert.ToUInt32 (reader ["photo_id"]),
+ "version_id", Convert.ToUInt32 (reader ["version_id"]),
+ "name", reader["name"].ToString (),
+ "base_uri", base_uri.ToString (),
+ "filename", filename,
+ "is_protected", Convert.ToBoolean (reader["protected"]),
+ "md5_sum", String.IsNullOrEmpty (md5) ? null : md5));
+ }
+
+ Execute ("CREATE INDEX idx_photos_roll_id ON photos(roll_id)");
+ Execute ("CREATE INDEX idx_photo_versions_id ON photo_versions(photo_id)");
+
+
+ }, true);
}
public static void Run (Db database)
@@ -549,7 +637,7 @@ namespace FSpot.Database {
}
db.CommitTransaction ();
- } catch (Exception e) {
+ } catch (Exception e) {Log.DebugException (e);
Log.Warning ("Rolling back database changes because of Exception");
// There was an error, roll back the database
db.RollbackTransaction ();
diff --git a/src/Utils/UriUtils.cs b/src/Utils/UriUtils.cs
index 15b78d4..93580f6 100644
--- a/src/Utils/UriUtils.cs
+++ b/src/Utils/UriUtils.cs
@@ -14,7 +14,7 @@ using System.IO;
namespace FSpot.Utils
{
public static class UriUtils
- {
+ {
public static string UriToStringEscaped (Uri uri)
{
return EscapeString (uri.ToString (), false, true, false);
diff --git a/src/Widgets/FolderTreePage.cs b/src/Widgets/FolderTreePage.cs
new file mode 100644
index 0000000..9dd3c6c
--- /dev/null
+++ b/src/Widgets/FolderTreePage.cs
@@ -0,0 +1,539 @@
+/*
+ * FSpot.Widgets.FolderTreePage.cs
+ *
+ * Author(s)
+ * Mike Gemuende <mike gemuende de>
+ *
+ * This is free software. See COPYING for details.
+ */
+
+
+using System;
+using System.Collections.Generic;
+
+using Gtk;
+
+using GLib;
+
+using FSpot;
+using FSpot.Gui;
+using FSpot.Utils;
+
+using Banshee.Database;
+
+using Mono.Unix;
+using Mono.Data.SqliteClient;
+
+
+
+namespace FSpot.Widgets
+{
+
+
+ public class FolderTreePage : SidebarPage
+ {
+ private readonly FolderTreeWidget folder_tree_widget;
+
+
+
+ public FolderTreePage ()
+ : base (new ScrolledWindow (), Catalog.GetString ("Folders"), "gtk-directory")
+ {
+ ScrolledWindow scrolled_window = SidebarWidget as ScrolledWindow;
+ folder_tree_widget = new FolderTreeWidget ();
+ scrolled_window.Add (folder_tree_widget);
+ }
+
+ protected override void AddedToSidebar () {
+ }
+ }
+
+ public class FolderTreeWidget : SaneTreeView
+ {
+ FolderTreeModel folder_tree_model;
+
+ public FolderTreeWidget () : this (new FolderTreeModel ())
+ {
+ }
+
+ public FolderTreeWidget (FolderTreeModel tree_model) : base (tree_model)
+ {
+ folder_tree_model = tree_model;
+
+ HeadersVisible = false;
+
+ TreeViewColumn column = new TreeViewColumn ();
+
+ CellRendererPixbuf pixbuf_renderer = new CellRendererPixbuf ();
+ column.PackStart (pixbuf_renderer, false);
+ column.SetCellDataFunc (pixbuf_renderer, PixbufDataFunc as TreeCellDataFunc);
+
+ CellRendererTextProgress folder_renderer = new CellRendererTextProgress ();
+ column.PackStart (folder_renderer, true);
+ column.SetCellDataFunc (folder_renderer, FolderDataFunc as TreeCellDataFunc);
+
+ AppendColumn (column);
+
+ Gtk.Drag.SourceSet (this, Gdk.ModifierType.Button1Mask | Gdk.ModifierType.Button3Mask,
+ folder_tree_source_target_table, Gdk.DragAction.Copy | Gdk.DragAction.Move);
+ }
+
+ public UriList SelectedUris {
+ get {
+ UriList list = new UriList ();
+
+ TreePath[] selected_rows = Selection.GetSelectedRows ();
+
+ foreach (TreePath row in selected_rows)
+ list.Add (folder_tree_model.GetUriByPath (row));
+
+ return list;
+ }
+ }
+
+ private void PixbufDataFunc (TreeViewColumn tree_column, CellRenderer cell, TreeModel tree_model, TreeIter iter)
+ {
+ CellRendererPixbuf renderer = cell as CellRendererPixbuf;
+ string text = folder_tree_model.GetFolderNameByIter (iter);
+
+ string stock;
+ File file = FileFactory.NewForUri (folder_tree_model.GetUriByIter (iter));
+ try {
+ FileInfo info =
+ file.QueryInfo ("standard::icon", FileQueryInfoFlags.None, null);
+
+ ThemedIcon themed_icon = info.Icon as ThemedIcon;
+ if (themed_icon != null && themed_icon.Names.Length > 0)
+ stock = themed_icon.Names[0];
+ else
+ stock = "gtk-directory";
+
+ } catch (Exception e) {
+ stock = "gtk-directory";
+ }
+
+ TreeIter tmp;
+ if (tree_model.IterParent (out tmp, iter)) {
+ renderer.IconName = stock;
+ renderer.CellBackground = null;
+ } else {
+ renderer.IconName = stock;
+ renderer.CellBackgroundGdk = Style.Background (StateType.Selected);
+ }
+ }
+
+ private void FolderDataFunc (TreeViewColumn tree_column, CellRenderer cell, TreeModel tree_model, TreeIter iter)
+ {
+ CellRendererTextProgress renderer = cell as CellRendererTextProgress;
+
+ int progress_value = 0;
+ int count = (tree_model as FolderTreeModel).Count;
+
+ if (count != 0)
+ progress_value = (int) ((100.0 * folder_tree_model.GetPhotoCountByIter (iter)) / count);
+
+ renderer.Value = progress_value;
+
+ string text = folder_tree_model.GetFolderNameByIter (iter);
+
+ TreeIter tmp;
+ if (tree_model.IterParent (out tmp, iter)) {
+ renderer.UseMarkup = false;
+ renderer.Text = text;
+ renderer.CellBackground = null;
+ } else {
+ renderer.UseMarkup = true;
+
+ /* since import do not use GIO at the moment, no other prefix than file:/// is
+ * possible.
+ */
+ if (text == Uri.UriSchemeFile)
+ renderer.Text = String.Format ("<b>{0}</b>", Catalog.GetString ("Filesystem"));
+ else
+ renderer.Text = String.Format ("<b>{0}</b>", text);
+
+ renderer.CellBackgroundGdk = Style.Background (StateType.Selected);
+ }
+ }
+
+ private string GetStock (string scheme)
+ {
+ /* not very usefull at the moment */
+ if (scheme == Uri.UriSchemeFile)
+ return "gtk-directory";
+
+ return "gtk-directory";
+ }
+
+ private static TargetEntry [] folder_tree_source_target_table =
+ new TargetEntry [] {
+ DragDropTargets.UriQueryEntry,
+ DragDropTargets.UriListEntry,
+ DragDropTargets.PlainTextEntry
+ };
+
+
+ protected override void OnDragDataGet (Gdk.DragContext context, Gtk.SelectionData selection_data, uint info, uint time_)
+ {
+ if (info == DragDropTargets.UriQueryEntry.Info
+ || info == DragDropTargets.UriListEntry.Info
+ || info == DragDropTargets.PlainTextEntry.Info) {
+
+ selection_data.SetUriListData (SelectedUris, context.Targets[0]);
+ return;
+ }
+ }
+
+ protected override bool OnDragDrop (Gdk.DragContext context, int x, int y, uint time_)
+ {
+ return true;
+ }
+
+ protected override void OnRowActivated (Gtk.TreePath path, Gtk.TreeViewColumn column)
+ {
+ MainWindow.Toplevel.SetFolderQuery (SelectedUris);
+ }
+
+ }
+
+
+ /*
+ * Because subclassing of CellRendererText does not to work, we
+ * use a new cellrenderer, which renderes a simple text and a
+ * progress bar below the text similar to the one used in baobab (gnome-utils)
+ */
+ public class CellRendererTextProgress : CellRenderer
+ {
+ readonly int progress_width;
+ readonly int progress_height;
+
+ Gdk.Color green;
+ Gdk.Color yellow;
+ Gdk.Color red;
+
+ public CellRendererTextProgress (int progress_width, int progress_height)
+ {
+ this.progress_width = progress_width;
+ this.progress_height = progress_height;
+
+ Xalign = 0.0f;
+ Yalign = 0.5f;
+
+ Xpad = 2;
+ Ypad = 2;
+
+ green = new Gdk.Color (0xcc, 0x00, 0x00);
+ yellow = new Gdk.Color (0xed, 0xd4, 0x00);
+ red = new Gdk.Color (0x73, 0xd2, 0x16);
+ }
+
+ public CellRendererTextProgress () : this (70, 8)
+ {
+ }
+
+ int progress_value;
+
+ [GLib.PropertyAttribute ("value")]
+ public int Value {
+ get { return progress_value; }
+ set {
+ /* normalize value */
+ progress_value = Math.Max (Math.Min (value, 100), 0);
+ }
+ }
+
+ Pango.Layout text_layout;
+ string text;
+
+ [GLib.PropertyAttribute ("text")]
+ public string Text {
+ get { return text; }
+ set {
+ if (text == value)
+ return;
+
+ text = value;
+ text_layout = null;
+ }
+ }
+
+ bool use_markup;
+ public bool UseMarkup {
+ get { return use_markup; }
+ set {
+ if (use_markup == value)
+ return;
+
+ use_markup = value;
+ text_layout = null;
+ }
+ }
+
+ private void UpdateLayout (Widget widget)
+ {
+ text_layout = new Pango.Layout (widget.PangoContext);
+
+ if (UseMarkup)
+ text_layout.SetMarkup (text);
+ else
+ text_layout.SetText (text);
+ }
+
+ private Gdk.Color GetValueColor ()
+ {
+ if (progress_value <= 33)
+ return green;
+
+ if (progress_value <= 66)
+ return yellow;
+
+ return red;
+ }
+
+ public override void GetSize (Gtk.Widget widget, ref Gdk.Rectangle cell_area, out int x_offset, out int y_offset, out int width, out int height)
+ {
+ if (text_layout == null)
+ UpdateLayout (widget);
+
+ int text_width, text_height;
+
+ text_layout.GetPixelSize (out text_width, out text_height);
+
+ width = (int) (2 * Xpad + Math.Max (progress_width, text_width));
+ height = (int) (3 * Ypad + progress_height + text_height);
+
+ x_offset = Math.Max ((int) (Xalign * (cell_area.Width - width)), 0);
+ y_offset = Math.Max ((int) (Yalign * (cell_area.Height - height)), 0);
+ }
+
+ protected override void Render (Gdk.Drawable window, Gtk.Widget widget, Gdk.Rectangle background_area, Gdk.Rectangle cell_area, Gdk.Rectangle expose_area, Gtk.CellRendererState flags)
+ {
+ base.Render (window, widget, background_area, cell_area, expose_area, flags);
+
+ if (text_layout == null)
+ UpdateLayout (widget);
+
+ int x, y, width, height, text_width, text_height;
+
+ /* first render the text */
+ text_layout.GetPixelSize (out text_width, out text_height);
+
+ x = (int) (cell_area.X + Xpad + Math.Max ((int) (Xalign * (cell_area.Width - 2 * Xpad - text_width)), 0));
+ y = (int) (cell_area.Y + Ypad);
+
+ Style.PaintLayout (widget.Style,
+ window,
+ StateType.Normal,
+ true,
+ cell_area,
+ widget,
+ "cellrenderertextprogress",
+ x, y,
+ text_layout);
+
+ y += (int) (text_height + Ypad);
+ x = (int) (cell_area.X + Xpad + Math.Max ((int) (Xalign * (cell_area.Width - 2 * Xpad - progress_width)), 0));
+
+
+ /* second render the progress bar */
+
+ /* dispose cairo object after usage */
+ using (Cairo.Context cairo_context = Gdk.CairoHelper.Create (window)) {
+
+ width = progress_width;
+ height = progress_height;
+
+ cairo_context.Rectangle (x, y, width, height);
+ Gdk.CairoHelper.SetSourceColor (cairo_context, widget.Style.Dark (StateType.Normal));
+ cairo_context.Fill ();
+
+ x += widget.Style.XThickness;
+ y += widget.Style.XThickness;
+ width -= 2* widget.Style.XThickness;
+ height -= 2 * widget.Style.Ythickness;
+
+ cairo_context.Rectangle (x, y, width, height);
+ Gdk.CairoHelper.SetSourceColor (cairo_context, widget.Style.Light (StateType.Normal));
+ cairo_context.Fill ();
+
+ /* scale the value and ensure, that at least one pixel is drawn, if the value is greater than zero */
+ int scaled_width =
+ (int) Math.Max (((progress_value * width) / 100.0),
+ (progress_value == 0)? 0 : 1);
+
+ cairo_context.Rectangle (x, y, scaled_width, height);
+ Gdk.CairoHelper.SetSourceColor (cairo_context, GetValueColor ());
+ cairo_context.Fill ();
+ }
+ }
+
+ }
+
+
+ public class FolderTreeModel : TreeStore
+ {
+ Db database;
+
+ const string query_string =
+ "SELECT base_uri, COUNT(*) AS count " +
+ "FROM photos " +
+ "GROUP BY base_uri " +
+ "ORDER BY base_uri DESC";
+
+
+ public FolderTreeModel ()
+ : base (typeof (string), typeof (int), typeof (Uri))
+ {
+ database = MainWindow.Toplevel.Database;
+ database.Photos.ItemsChanged += HandlePhotoItemsChanged;
+
+ UpdateFolderTree ();
+ }
+
+ void HandlePhotoItemsChanged (object sender, DbItemEventArgs<Photo> e)
+ {
+ UpdateFolderTree ();
+ }
+
+ public string GetFolderNameByIter (TreeIter iter)
+ {
+ if ( ! IterIsValid (iter))
+ return null;
+
+ return (string) GetValue (iter, 0);
+ }
+
+ public int GetPhotoCountByIter (TreeIter iter)
+ {
+ if ( ! IterIsValid (iter))
+ return -1;
+
+ return (int) GetValue (iter, 1);
+ }
+
+ public Uri GetUriByIter (TreeIter iter)
+ {
+ if ( ! IterIsValid (iter))
+ return null;
+
+ return (Uri) GetValue (iter, 2);
+ }
+
+ public Uri GetUriByPath (TreePath row)
+ {
+ TreeIter iter;
+
+ GetIter (out iter, row);
+
+ return GetUriByIter (iter);
+ }
+
+ int count_all;
+ public int Count {
+ get { return count_all; }
+ }
+
+ /*
+ * UpdateFolderTree queries for directories in database and updates
+ * a possibly existing folder-tree to the queried structure
+ */
+ private void UpdateFolderTree ()
+ {
+ Clear ();
+
+ count_all = 0;
+
+ /* points at start of each iteration to the leaf of the last inserted uri */
+ TreeIter iter = TreeIter.Zero;
+
+ /* stores the segments of the last inserted uri */
+ string[] last_segments = new string[] {};
+
+ int last_count = 0;
+
+ SqliteDataReader reader = database.Database.Query (query_string);
+
+ while (reader.Read ()) {
+ Uri base_uri = new Uri (reader["base_uri"].ToString ());
+
+ if ( ! base_uri.IsAbsoluteUri) {
+ FSpot.Utils.Log.Error ("Uri must be absolute: {0}", base_uri.ToString ());
+ continue;
+ }
+
+ int count = Convert.ToInt32 (reader["count"]);
+
+ string[] segments = base_uri.Segments;
+
+ /*
+ * since we have an absolute uri, first segement starts with "/" according
+ * to the msdn doc. So we can overwrite the first segment for our needs and
+ * put the scheme here.
+ */
+ segments[0] = base_uri.Scheme;
+
+ int i = 0;
+
+ /* find first difference of last inserted an current uri */
+ while (i < last_segments.Length && i < segments.Length) {
+
+ /* remove suffix '/', which are appended to every directory (see msdn-doc) */
+ segments[i] = segments[i].TrimEnd ('/');
+
+ if (segments[i] != last_segments[i])
+ break;
+
+ i++;
+ }
+
+ /* points to the parent node of the current iter */
+ TreeIter parent_iter = iter;
+
+ /* step back to the level, where the difference occur */
+ for (int j = 0; j + i < last_segments.Length; j++) {
+
+ iter = parent_iter;
+
+ if (IterParent (out parent_iter, iter)) {
+ last_count += (int)GetValue (parent_iter, 1);
+ SetValue (parent_iter, 1, last_count);
+ } else
+ count_all += (int)last_count;
+ }
+
+ while (i < segments.Length) {
+ segments[i] = segments[i].TrimEnd ('/');
+
+ if (IterIsValid (parent_iter))
+ iter =
+ AppendValues (parent_iter,
+ segments[i],
+ (segments.Length - 1 == i)? count : 0,
+ new Uri ((Uri) GetValue (parent_iter, 2),
+ String.Format ("{0}/", segments[i]))
+ );
+ else
+ iter =
+ AppendValues (segments[i],
+ (segments.Length - 1 == i)? count : 0,
+ new Uri (base_uri, "/"));
+
+ parent_iter = iter;
+
+ i++;
+ }
+
+ last_count = count;
+ last_segments = segments;
+
+ }
+
+ /* and at least, step back and update photo count */
+ while (IterParent (out iter, iter)) {
+ last_count += (int)GetValue (iter, 1);
+ SetValue (iter, 1, last_count);
+ }
+ count_all += (int)last_count;
+ }
+ }
+}
diff --git a/src/ui/main_window.ui b/src/ui/main_window.ui
index 1a08198..c04452c 100644
--- a/src/ui/main_window.ui
+++ b/src/ui/main_window.ui
@@ -373,22 +373,6 @@
</object>
</child>
<child>
- <object class="GtkRadioAction" id="month">
- <property name="active">True</property>
- <property name="name">month</property>
- <property name="label" translatable="yes">_Month</property>
- <signal handler="HandleArrangeByTime" name="activate"/>
- </object>
- </child>
- <child>
- <object class="GtkRadioAction" id="directory">
- <property name="group">month</property>
- <property name="name">directory</property>
- <property name="label" translatable="yes">_Folder</property>
- <signal handler="HandleArrangeByDirectory" name="activate"/>
- </object>
- </child>
- <child>
<object class="GtkToggleAction" id="reverse_order">
<property name="name">reverse_order</property>
<property name="label" translatable="yes">_Reverse Order</property>
@@ -638,10 +622,6 @@
<menuitem action="tag_icon_large"/>
</menu>
<separator/>
- <menu action="arranged_by">
- <menuitem action="month"/>
- <menuitem action="directory"/>
- </menu>
<menuitem action="reverse_order"/>
</menu>
<menu action="find">
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]