f-spot r4290 - in trunk: . extensions extensions/MergeDb
- From: sdelcroix svn gnome org
- To: svn-commits-list gnome org
- Subject: f-spot r4290 - in trunk: . extensions extensions/MergeDb
- Date: Mon, 25 Aug 2008 15:58:18 +0000 (UTC)
Author: sdelcroix
Date: Mon Aug 25 15:58:18 2008
New Revision: 4290
URL: http://svn.gnome.org/viewvc/f-spot?rev=4290&view=rev
Log:
new MergeDb extension, allowing (partial or full) db merge
Added:
trunk/extensions/MergeDb/
trunk/extensions/MergeDb/.gitignore
trunk/extensions/MergeDb/Makefile.am
trunk/extensions/MergeDb/MergeDb.addin.xml
trunk/extensions/MergeDb/MergeDb.cs
trunk/extensions/MergeDb/MergeDb.glade
Modified:
trunk/configure.in
trunk/extensions/Makefile.am
Modified: trunk/configure.in
==============================================================================
--- trunk/configure.in (original)
+++ trunk/configure.in Mon Aug 25 15:58:18 2008
@@ -367,6 +367,7 @@
extensions/FolderExport/Makefile
extensions/SmugMugExport/SmugMugNet/Makefile
extensions/SmugMugExport/Makefile
+extensions/MergeDb/Makefile
extensions/PicasaWebExport/Makefile
extensions/PicasaWebExport/google-sharp/Makefile
f-spot.pc
Modified: trunk/extensions/Makefile.am
==============================================================================
--- trunk/extensions/Makefile.am (original)
+++ trunk/extensions/Makefile.am Mon Aug 25 15:58:18 2008
@@ -6,6 +6,7 @@
GalleryExport \
FlickrExport \
FolderExport \
+ MergeDb \
PicasaWebExport \
SmugMugExport
Added: trunk/extensions/MergeDb/.gitignore
==============================================================================
--- (empty file)
+++ trunk/extensions/MergeDb/.gitignore Mon Aug 25 15:58:18 2008
@@ -0,0 +1,4 @@
+/Makefile
+/Makefile.in
+/MergeDb.dll
+/MergeDb.dll.mdb
Added: trunk/extensions/MergeDb/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/extensions/MergeDb/Makefile.am Mon Aug 25 15:58:18 2008
@@ -0,0 +1,47 @@
+include $(top_srcdir)/Makefile.include
+
+PLUGIN_NAME = MergeDb
+
+PLUGIN_MANIFEST = $(PLUGIN_NAME).addin.xml
+
+PLUGIN_ASSEMBLY = $(PLUGIN_NAME).dll
+
+PLUGIN_SOURCES = \
+ $(srcdir)/MergeDb.cs
+
+REFS = \
+ -r:../../src/f-spot.exe \
+ -r:../../src/FSpot.Core.dll \
+ -r:../../src/FSpot.Utils.dll \
+ -r:../../src/FSpot.Query.dll
+
+PKGS = \
+ -pkg:gtk-sharp-2.0 \
+ -pkg:glade-sharp-2.0
+
+RESOURCES = \
+ -resource:$(srcdir)/$(PLUGIN_MANIFEST) \
+ -resource:$(srcdir)/$(PLUGIN_NAME).glade
+
+all: $(PLUGIN_ASSEMBLY)
+
+mpack: $(PLUGIN_ASSEMBLY)
+ mautil p $(PLUGIN_ASSEMBLY)
+
+$(PLUGIN_ASSEMBLY): $(PLUGIN_SOURCES) $(PLUGIN_MANIFEST)
+ $(CSC_LIB) -out:$@ $(PLUGIN_SOURCES) $(REFS) $(PKGS) $(ASSEMBLIES) $(RESOURCES)
+
+plugindir = $(pkglibdir)/extensions
+
+plugin_DATA = \
+ $(PLUGIN_ASSEMBLY)
+
+EXTRA_DIST = \
+ $(PLUGIN_SOURCES) \
+ $(PLUGIN_MANIFEST) \
+ $(PLUGIN_NAME).glade
+
+CLEANFILES = \
+ $(PLUGIN_ASSEMBLY) \
+ $(PLUGIN_ASSEMBLY).mdb \
+ *.mpack
Added: trunk/extensions/MergeDb/MergeDb.addin.xml
==============================================================================
--- (empty file)
+++ trunk/extensions/MergeDb/MergeDb.addin.xml Mon Aug 25 15:58:18 2008
@@ -0,0 +1,16 @@
+<Addin namespace="FSpot"
+ id="MergeDb"
+ name="MergeDb"
+ version="0.4.4.99"
+ description="Merge another db back to the main one"
+ author="Stephane Delcroix"
+ url="http://f-spot.org/Extensions"
+ category="Tools"
+ defaultEnabled="false">
+ <Dependencies>
+ <Addin id="Core" version="0.4.4.102"/>
+ </Dependencies>
+ <Extension path = "/FSpot/Menus/Tools">
+ <Command id = "MergeDb" _label = "Merge Db" command_type = "MergeDbExtension.MergeDb" />
+ </Extension>
+</Addin>
Added: trunk/extensions/MergeDb/MergeDb.cs
==============================================================================
--- (empty file)
+++ trunk/extensions/MergeDb/MergeDb.cs Mon Aug 25 15:58:18 2008
@@ -0,0 +1,231 @@
+/* FSpot.MergeDb.cs
+ *
+ * Author(s):
+ * Stephane Delcroix <stephane delcroix org>
+ *
+ * This is free software. See COPYING for details
+ */
+
+using System;
+using System.Collections.Generic;
+
+using Gtk;
+
+using FSpot;
+using FSpot.Extensions;
+using FSpot.Utils;
+using FSpot.Query;
+
+namespace MergeDbExtension
+{
+ public class MergeDb : ICommand
+ {
+ [Glade.Widget] Gtk.Dialog mergedb_dialog;
+ [Glade.Widget] Gtk.Button apply_button;
+ [Glade.Widget] Gtk.Button cancel_button;
+ [Glade.Widget] Gtk.FileChooserButton db_filechooser;
+ [Glade.Widget] Gtk.RadioButton newrolls_radio;
+ [Glade.Widget] Gtk.RadioButton allrolls_radio;
+ [Glade.Widget] Gtk.RadioButton singleroll_radio;
+ [Glade.Widget] Gtk.ComboBox rolls_combo;
+
+
+ Db from_db;
+ Db to_db;
+ PhotoQuery query;
+ Roll [] new_rolls;
+
+ Dictionary<uint, Tag> tag_map; //Key is a TagId from from_db, Value is a Tag from to_db
+ Dictionary<uint, uint> roll_map;
+
+ public void Run (object o, EventArgs e)
+ {
+ from_db = new Db ();
+ to_db = Core.Database;
+
+ ShowDialog ();
+ }
+
+ public void ShowDialog () {
+ Glade.XML xml = new Glade.XML (null, "MergeDb.glade", "mergedb_dialog", "f-spot");
+ xml.Autoconnect (this);
+ mergedb_dialog.Modal = false;
+ mergedb_dialog.TransientFor = null;
+
+ db_filechooser.FileSet += HandleFileSet;
+
+ newrolls_radio.Toggled += HandleRollsChanged;
+ allrolls_radio.Toggled += HandleRollsChanged;
+ singleroll_radio.Toggled += HandleRollsChanged;
+
+ rolls_combo.Changed += HandleRollsChanged;
+
+ mergedb_dialog.Response += HandleResponse;
+ mergedb_dialog.ShowAll ();
+ }
+
+ void HandleFileSet (object o, EventArgs e)
+ {
+ Log.DebugFormat ("FileChooser Activated, trying to open {0}...", db_filechooser.Filename);
+ try {
+ from_db.Init (db_filechooser.Filename, true);
+ query = new PhotoQuery (from_db.Photos);
+
+ CheckRolls ();
+ rolls_combo.Active = 0;
+
+ newrolls_radio.Sensitive = true;
+ allrolls_radio.Sensitive = true;
+ singleroll_radio.Sensitive = true;
+
+ apply_button.Sensitive = true;
+
+ newrolls_radio.Active = true;
+ HandleRollsChanged (null, null);
+ } catch (Exception ex) {
+ Log.Exception (ex);
+ }
+ }
+
+ void CheckRolls ()
+ {
+ List<Roll> from_rolls = new List<Roll> (from_db.Rolls.GetRolls ());
+ Roll [] to_rolls = to_db.Rolls.GetRolls ();
+ foreach (Roll tr in to_rolls)
+ foreach (Roll fr in from_rolls.ToArray ())
+ if (tr.Time == fr.Time)
+ from_rolls.Remove (fr);
+ new_rolls = from_rolls.ToArray ();
+
+ foreach (Roll r in from_rolls) {
+ uint numphotos = from_db.Rolls.PhotosInRoll (r);
+ DateTime date = r.Time.ToLocalTime ();
+ rolls_combo.AppendText (String.Format ("{0} ({1})", date.ToString("%dd %MMM, %HH:%mm"), numphotos));
+ }
+ }
+
+ void HandleRollsChanged (object o, EventArgs e)
+ {
+ rolls_combo.Sensitive = singleroll_radio.Active;
+
+ if (allrolls_radio.Active)
+ query.RollSet = null;
+
+ if (newrolls_radio.Active)
+ query.RollSet = new RollSet (new_rolls);
+
+ if (singleroll_radio.Active) {
+ Console.WriteLine (rolls_combo.Active);
+ query.RollSet = new RollSet (new_rolls [rolls_combo.Active]);
+ }
+ }
+
+ void HandleResponse (object obj, ResponseArgs args) {
+ if (args.ResponseId == ResponseType.Accept) {
+ Roll [] mergerolls = singleroll_radio.Active ? new Roll [] {new_rolls [rolls_combo.Active]} : new_rolls;
+ DoMerge (query, mergerolls, false);
+ }
+ mergedb_dialog.Destroy ();
+ }
+
+
+ public static void Merge (string path, Db to_db)
+ {
+ Log.WarningFormat ("Will merge db {0} into main f-spot db {1}", path, FSpot.Global.BaseDirectory + "/photos.db" );
+ Db from_db = new Db ();
+ from_db.Init (path, true);
+ //MergeDb mdb = new MergeDb (from_db, to_db);
+
+ }
+
+ void DoMerge (PhotoQuery query, Roll [] rolls, bool copy)
+ {
+ tag_map = new Dictionary<uint, Tag> ();
+ roll_map = new Dictionary<uint, uint> ();
+
+ Log.Warning ("Merging tags");
+ MergeTags (from_db.Tags.RootCategory);
+
+ Log.Warning ("Creating the rolls");
+ CreateRolls (rolls);
+
+ Log.Warning ("Importing photos");
+ ImportPhotos (query, copy);
+
+ }
+
+ void MergeTags (Tag tag_to_merge)
+ {
+ TagStore from_store = from_db.Tags;
+ TagStore to_store = to_db.Tags;
+
+ if (tag_to_merge != from_store.RootCategory) { //Do not merge RootCategory
+ Tag dest_tag = to_store.GetTagByName (tag_to_merge.Name);
+ if (dest_tag == null) {
+ Category parent = (tag_to_merge.Category == from_store.RootCategory) ?
+ to_store.RootCategory :
+ to_store.GetTagByName (tag_to_merge.Category.Name) as Category;
+ dest_tag = to_store.CreateTag (parent, tag_to_merge.Name);
+ //FIXME: copy the tag icon and commit
+ }
+ tag_map [tag_to_merge.Id] = dest_tag;
+ }
+
+ if (!(tag_to_merge is Category))
+ return;
+
+ foreach (Tag t in (tag_to_merge as Category).Children)
+ MergeTags (t);
+ }
+
+ void CreateRolls (Roll [] rolls)
+ {
+ RollStore from_store = from_db.Rolls;
+ RollStore to_store = to_db.Rolls;
+
+ foreach (Roll roll in rolls) {
+ if (from_store.PhotosInRoll (roll) == 0)
+ continue;
+ roll_map [roll.Id] = (to_store.Create (roll.Time).Id);
+ }
+ }
+
+ void ImportPhotos (PhotoQuery query, bool copy)
+ {
+ foreach (Photo p in query.Photos)
+ ImportPhoto (p, copy);
+ }
+
+ void ImportPhoto (Photo photo, bool copy)
+ {
+ Log.WarningFormat ("Importing {0}", photo.Name);
+ PhotoStore from_store = from_db.Photos;
+ PhotoStore to_store = to_db.Photos;
+
+ Gdk.Pixbuf pixbuf;
+ Photo newp = to_store.Create (photo.VersionUri (Photo.OriginalVersionId), roll_map [photo.RollId], out pixbuf);
+
+
+ foreach (Tag t in photo.Tags) {
+ Log.WarningFormat ("Tagging with {0}", t.Name);
+ newp.AddTag (tag_map [t.Id]);
+ }
+
+ foreach (uint version_id in photo.VersionIds)
+ if (version_id != Photo.OriginalVersionId) {
+ PhotoVersion version = photo.GetVersion (version_id) as PhotoVersion;
+ uint newv = newp.AddVersion (version.Uri, version.Name, version.IsProtected);
+ if (version_id == photo.DefaultVersionId)
+ newp.DefaultVersionId = newv;
+ }
+
+ //FIXME Import extra info (time, description, rating)
+ newp.Time = photo.Time;
+ newp.Description = photo.Description;
+ newp.Rating = photo.Rating;
+
+ to_store.Commit (newp);
+ }
+ }
+}
+
Added: trunk/extensions/MergeDb/MergeDb.glade
==============================================================================
--- (empty file)
+++ trunk/extensions/MergeDb/MergeDb.glade Mon Aug 25 15:58:18 2008
@@ -0,0 +1,269 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
+<!--Generated with glade3 3.4.3 on Mon Aug 25 17:35:47 2008 -->
+<glade-interface>
+ <widget class="GtkDialog" id="mergedb_dialog">
+ <property name="border_width">5</property>
+ <property name="title" translatable="yes">Merge another f-spot collection</property>
+ <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+ <property name="has_separator">False</property>
+ <child internal-child="vbox">
+ <widget class="GtkVBox" id="dialog-vbox1">
+ <property name="visible">True</property>
+ <property name="spacing">2</property>
+ <child>
+ <widget class="GtkTable" id="table1">
+ <property name="visible">True</property>
+ <property name="n_rows">9</property>
+ <property name="n_columns">3</property>
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes"><small><i>Copy the images locally or keep them where they are. If you chose the later, be sure that this location will stay accessible from f-spot.</i></small></property>
+ <property name="use_markup">True</property>
+ <property name="wrap">True</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_END</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">8</property>
+ <property name="bottom_attach">9</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkRadioButton" id="keep_radio">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Keep the images at their original location</property>
+ <property name="response_id">0</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">copy_radio</property>
+ </widget>
+ <packing>
+ <property name="right_attach">3</property>
+ <property name="top_attach">7</property>
+ <property name="bottom_attach">8</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkRadioButton" id="copy_radio">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Copy images to Photos/</property>
+ <property name="response_id">0</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </widget>
+ <packing>
+ <property name="right_attach">3</property>
+ <property name="top_attach">6</property>
+ <property name="bottom_attach">7</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes"><small><i>Choose what to import from the selected db.
+"Everything" will import everything, creating duplicates if you already imported from that database.
+"New Rolls only" is the smart option that will avoid re-importing you could have imported during a previous operation.
+"A Single Import Roll" let you choose which roll you want to merge back.</i></small></property>
+ <property name="use_markup">True</property>
+ <property name="wrap">True</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_END</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">5</property>
+ <property name="bottom_attach">6</property>
+ <property name="y_options"></property>
+ <property name="y_padding">6</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkComboBox" id="rolls_combo">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="items"></property>
+ </widget>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkRadioButton" id="allrolls_radio">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Everything</property>
+ <property name="response_id">0</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">newrolls_radio</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkRadioButton" id="singleroll_radio">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">A Single Import Roll</property>
+ <property name="response_id">0</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">newrolls_radio</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkRadioButton" id="newrolls_radio">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">New Rolls Only</property>
+ <property name="response_id">0</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Import:</property>
+ </widget>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes"><small><i>Choose the location of the database you want to import from</i></small></property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="y_options"></property>
+ <property name="y_padding">6</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkFileChooserButton" id="db_filechooser">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">3</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Database Location:</property>
+ </widget>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child internal-child="action_area">
+ <widget class="GtkHButtonBox" id="dialog-action_area1">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_END</property>
+ <child>
+ <widget class="GtkButton" id="cancel_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="label" translatable="yes">gtk-cancel</property>
+ <property name="use_stock">True</property>
+ <property name="response_id">-6</property>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkButton" id="apply_button">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="label" translatable="yes">gtk-ok</property>
+ <property name="use_stock">True</property>
+ <property name="response_id">-3</property>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+</glade-interface>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]