Merge lp:~codygarver/pantheon-photos/fix-1322215 into lp:~pantheon-photos/pantheon-photos/trunk

Proposed by Cody Garver
Status: Merged
Approved by: meese
Approved revision: 2602
Merged at revision: 2603
Proposed branch: lp:~codygarver/pantheon-photos/fix-1322215
Merge into: lp:~pantheon-photos/pantheon-photos/trunk
Diff against target: 4098 lines (+6/-3870)
28 files modified
plugins/plugins.mk (+1/-3)
plugins/shotwell-data-imports/FSpotDatabase.vala (+0/-58)
plugins/shotwell-data-imports/FSpotDatabaseBehavior.vala (+0/-208)
plugins/shotwell-data-imports/FSpotDatabaseTable.vala (+0/-54)
plugins/shotwell-data-imports/FSpotImporter.vala (+0/-567)
plugins/shotwell-data-imports/FSpotMetaTable.vala (+0/-113)
plugins/shotwell-data-imports/FSpotPhotoTagsTable.vala (+0/-57)
plugins/shotwell-data-imports/FSpotPhotoVersionsTable.vala (+0/-275)
plugins/shotwell-data-imports/FSpotPhotosTable.vala (+0/-363)
plugins/shotwell-data-imports/FSpotRollsTable.vala (+0/-111)
plugins/shotwell-data-imports/FSpotTableBehavior.vala (+0/-28)
plugins/shotwell-data-imports/FSpotTagsTable.vala (+0/-129)
plugins/shotwell-data-imports/Makefile (+0/-30)
plugins/shotwell-data-imports/shotwell-data-imports.vala (+0/-46)
src/Dialogs.vala (+1/-5)
src/data_imports/DataImportJob.vala (+0/-177)
src/data_imports/DataImportSource.vala (+0/-135)
src/data_imports/DataImports.vala (+0/-30)
src/data_imports/DataImportsPluginHost.vala (+0/-483)
src/data_imports/DataImportsUI.vala (+0/-445)
src/data_imports/mk/data_imports.mk (+0/-31)
src/library/LibraryWindow.vala (+0/-13)
src/library/mk/library.mk (+1/-2)
src/plugins/DataImportsInterfaces.vala (+0/-489)
src/plugins/mk/interfaces.mk (+1/-2)
src/plugins/mk/plugins.mk (+1/-2)
src/tags/HierarchicalTagUtilities.vala (+0/-12)
units.mk (+1/-2)
To merge this branch: bzr merge lp:~codygarver/pantheon-photos/fix-1322215
Reviewer Review Type Date Requested Status
meese Approve
Review via email: mp+232505@code.launchpad.net

Commit message

Drop shotwell-data-imports, includes FSpot plugin (lp:1322215)

To post a comment you must log in.
Revision history for this message
Cody Garver (codygarver) wrote :

The modifications to src/tags/HierarchicalTagUtilities.vala were to satisfy the build failure due to an unused code warning

2602. By Cody Garver

Merge in trunk and resolve conflicts

Revision history for this message
meese (meese) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/plugins.mk'
2--- plugins/plugins.mk 2013-11-14 22:27:35 +0000
3+++ plugins/plugins.mk 2014-08-28 06:03:26 +0000
4@@ -1,8 +1,7 @@
5
6 PLUGINS := \
7 shotwell-transitions \
8- shotwell-publishing \
9- shotwell-data-imports
10+ shotwell-publishing
11
12 PLUGINS_RC := \
13 plugins/shotwell-publishing/facebook.png \
14@@ -24,7 +23,6 @@
15
16 EXTRA_PLUGINS_RC := \
17 plugins/shotwell-publishing-extras/yandex_publish_model.glade \
18- plugins/shotwell-data-imports/f-spot-24.png \
19 plugins/shotwell-publishing-extras/tumblr.png \
20 plugins/shotwell-publishing-extras/tumblr_authentication_pane.glade \
21 plugins/shotwell-publishing-extras/tumblr_publishing_options_pane.glade
22
23=== removed directory 'plugins/shotwell-data-imports'
24=== removed file 'plugins/shotwell-data-imports/FSpotDatabase.vala'
25--- plugins/shotwell-data-imports/FSpotDatabase.vala 2014-08-08 21:13:09 +0000
26+++ plugins/shotwell-data-imports/FSpotDatabase.vala 1970-01-01 00:00:00 +0000
27@@ -1,58 +0,0 @@
28-/* Copyright 2011-2013 Yorba Foundation
29- *
30- * This software is licensed under the GNU Lesser General Public License
31- * (version 2.1 or later). See the COPYING file in this distribution.
32- */
33-
34-namespace DataImports.FSpot.Db {
35-
36-public const int64 NULL_ID = 0;
37-public const int64 INVALID_ID = -1;
38-
39-/**
40- * Initialization method for the whole module.
41- */
42-public void init () {
43- FSpotDatabaseBehavior.create_behavior_map ();
44-}
45-
46-/**
47- * An object that is able to read from the F-Spot
48- * database and extract the relevant objects.
49- */
50-public class FSpotDatabase : Object {
51- private Sqlite.Database fspot_db;
52- private FSpotMetaTable meta_table;
53- public FSpotPhotosTable photos_table;
54- public FSpotPhotoVersionsTable photo_versions_table;
55- public FSpotTagsTable tags_table;
56- public FSpotRollsTable rolls_table;
57- public int64 hidden_tag_id;
58-
59- public FSpotDatabase (File db_file) throws DatabaseError, Spit.DataImports.DataImportError {
60- string filename = db_file.get_path ();
61- int res = Sqlite.Database.open_v2 (filename, out fspot_db,
62- Sqlite.OPEN_READONLY, null);
63- if (res != Sqlite.OK)
64- throw new DatabaseError.ERROR ("Unable to open F-Spot database %s: %d", filename, res);
65- meta_table = new FSpotMetaTable (fspot_db);
66- hidden_tag_id = meta_table.get_hidden_tag_id ();
67-
68- FSpotDatabaseBehavior db_behavior = new FSpotDatabaseBehavior (get_version ());
69-
70- photos_table = new FSpotPhotosTable (fspot_db, db_behavior);
71- photo_versions_table = new FSpotPhotoVersionsTable (fspot_db, db_behavior);
72- tags_table = new FSpotTagsTable (fspot_db, db_behavior);
73- rolls_table = new FSpotRollsTable (fspot_db, db_behavior);
74- }
75-
76- ~FSpotDatabase () {
77- }
78-
79- private Utils.VersionNumber get_version () throws DatabaseError {
80- return new Utils.VersionNumber.from_string (meta_table.get_db_version ());
81- }
82-}
83-
84-}
85-
86
87=== removed file 'plugins/shotwell-data-imports/FSpotDatabaseBehavior.vala'
88--- plugins/shotwell-data-imports/FSpotDatabaseBehavior.vala 2014-08-08 21:13:09 +0000
89+++ plugins/shotwell-data-imports/FSpotDatabaseBehavior.vala 1970-01-01 00:00:00 +0000
90@@ -1,208 +0,0 @@
91-/* Copyright 2011-2013 Yorba Foundation
92- *
93- * This software is licensed under the GNU Lesser General Public License
94- * (version 2.1 or later). See the COPYING file in this distribution.
95- */
96-
97-namespace DataImports.FSpot.Db {
98-
99-private class FSpotBehaviorEntry {
100- private Utils.VersionNumber version;
101- private FSpotTableBehavior behavior;
102-
103- public FSpotBehaviorEntry (Utils.VersionNumber version, FSpotTableBehavior behavior) {
104- this.version = version;
105- this.behavior = behavior;
106- }
107-
108- public Utils.VersionNumber get_version () {
109- return version;
110- }
111-
112- public FSpotTableBehavior get_behavior () {
113- return behavior;
114- }
115-}
116-
117-/**
118- * A class that consolidates the behavior of all F-Spot tables (apart from meta)
119- * and is the one place to check whether the database version is supported.
120- */
121-public class FSpotDatabaseBehavior : Object {
122- // Minimum unsupported version: any database from that version and above
123- // is not supported as it's too new and support has not been provided
124- // In practice, the code may work with future versions but this cannot be
125- // guaranteed as it hasn't been tested so it's probably better to just
126- // bomb out at that point rather than risk importing incorrect data
127- public static Utils.VersionNumber MIN_UNSUPPORTED_VERSION =
128- new Utils.VersionNumber ({ 19 });
129- private static Gee.Map<string, Gee.List<FSpotBehaviorEntry>> behavior_map;
130-
131- private FSpotTableBehavior<FSpotPhotoRow> photos_behavior;
132- private FSpotTableBehavior<FSpotTagRow> tags_behavior;
133- private FSpotTableBehavior<FSpotPhotoTagRow> photo_tags_behavior;
134- private FSpotTableBehavior<FSpotPhotoVersionRow> photo_versions_behavior;
135- private FSpotTableBehavior<FSpotRollRow> rolls_behavior;
136-
137- public static void create_behavior_map () {
138- behavior_map = new Gee.HashMap<string, Gee.List<FSpotBehaviorEntry>> ();
139- // photos table
140- Gee.List<FSpotBehaviorEntry> photos_list = new Gee.ArrayList<FSpotBehaviorEntry> ();
141- // v0-4
142- photos_list.add (new FSpotBehaviorEntry (
143- new Utils.VersionNumber ({ 0 }),
144- FSpotPhotosV0Behavior.get_instance ()
145- ));
146- // v5-6
147- photos_list.add (new FSpotBehaviorEntry (
148- new Utils.VersionNumber ({ 5 }),
149- FSpotPhotosV5Behavior.get_instance ()
150- ));
151- // v7-10
152- photos_list.add (new FSpotBehaviorEntry (
153- new Utils.VersionNumber ({ 7 }),
154- FSpotPhotosV7Behavior.get_instance ()
155- ));
156- // v11-15
157- photos_list.add (new FSpotBehaviorEntry (
158- new Utils.VersionNumber ({ 11 }),
159- FSpotPhotosV11Behavior.get_instance ()
160- ));
161- // v16
162- photos_list.add (new FSpotBehaviorEntry (
163- new Utils.VersionNumber ({ 16 }),
164- FSpotPhotosV16Behavior.get_instance ()
165- ));
166- // v17
167- photos_list.add (new FSpotBehaviorEntry (
168- new Utils.VersionNumber ({ 17 }),
169- FSpotPhotosV17Behavior.get_instance ()
170- ));
171- // v18+
172- photos_list.add (new FSpotBehaviorEntry (
173- new Utils.VersionNumber ({ 18 }),
174- FSpotPhotosV18Behavior.get_instance ()
175- ));
176- behavior_map.set (FSpotPhotosTable.TABLE_NAME, photos_list);
177- // tags table
178- Gee.List<FSpotBehaviorEntry> tags_list = new Gee.ArrayList<FSpotBehaviorEntry> ();
179- // v0+
180- tags_list.add (new FSpotBehaviorEntry (
181- new Utils.VersionNumber ({ 0 }),
182- FSpotTagsV0Behavior.get_instance ()
183- ));
184- behavior_map.set (FSpotTagsTable.TABLE_NAME, tags_list);
185- // photo_tags table
186- Gee.List<FSpotBehaviorEntry> photo_tags_list = new Gee.ArrayList<FSpotBehaviorEntry> ();
187- // v0+
188- photo_tags_list.add (new FSpotBehaviorEntry (
189- new Utils.VersionNumber ({ 0 }),
190- FSpotPhotoTagsV0Behavior.get_instance ()
191- ));
192- behavior_map.set (FSpotPhotoTagsTable.TABLE_NAME, photo_tags_list);
193- // photo_versions table
194- Gee.List<FSpotBehaviorEntry> photo_versions_list = new Gee.ArrayList<FSpotBehaviorEntry> ();
195- // v0-8
196- photo_versions_list.add (new FSpotBehaviorEntry (
197- new Utils.VersionNumber ({ 0 }),
198- FSpotPhotoVersionsV0Behavior.get_instance ()
199- ));
200- // v9-15
201- photo_versions_list.add (new FSpotBehaviorEntry (
202- new Utils.VersionNumber ({ 9 }),
203- FSpotPhotoVersionsV9Behavior.get_instance ()
204- ));
205- // v16
206- photo_versions_list.add (new FSpotBehaviorEntry (
207- new Utils.VersionNumber ({ 16 }),
208- FSpotPhotoVersionsV16Behavior.get_instance ()
209- ));
210- // v17
211- photo_versions_list.add (new FSpotBehaviorEntry (
212- new Utils.VersionNumber ({ 17 }),
213- FSpotPhotoVersionsV17Behavior.get_instance ()
214- ));
215- // v18+
216- photo_versions_list.add (new FSpotBehaviorEntry (
217- new Utils.VersionNumber ({ 18 }),
218- FSpotPhotoVersionsV18Behavior.get_instance ()
219- ));
220- behavior_map.set (FSpotPhotoVersionsTable.TABLE_NAME, photo_versions_list);
221- // rolls table
222- Gee.List<FSpotBehaviorEntry> rolls_list = new Gee.ArrayList<FSpotBehaviorEntry> ();
223- // v0-4
224- rolls_list.add (new FSpotBehaviorEntry (
225- new Utils.VersionNumber ({ 0 }),
226- FSpotRollsV0Behavior.get_instance ()
227- ));
228- // v5+
229- rolls_list.add (new FSpotBehaviorEntry (
230- new Utils.VersionNumber ({ 5 }),
231- FSpotRollsV5Behavior.get_instance ()
232- ));
233- behavior_map.set (FSpotRollsTable.TABLE_NAME, rolls_list);
234- }
235-
236- public static FSpotTableBehavior? find_behavior (string table_name, Utils.VersionNumber version) {
237- FSpotTableBehavior behavior = null;
238- Gee.List<FSpotBehaviorEntry> behavior_list = behavior_map.get (table_name);
239- if (behavior_list != null)
240- foreach (FSpotBehaviorEntry entry in behavior_list) {
241- if (version.compare_to (entry.get_version ()) >= 0)
242- behavior = entry.get_behavior ();
243- }
244- else
245- warning ("Could not find behavior list for table %s", table_name);
246- return behavior;
247-
248- }
249- public FSpotDatabaseBehavior (Utils.VersionNumber version) throws Spit.DataImports.DataImportError {
250- if (version.compare_to (MIN_UNSUPPORTED_VERSION) >= 0)
251- throw new Spit.DataImports.DataImportError.UNSUPPORTED_VERSION ("Version %s is not yet supported", version.to_string ());
252-
253- FSpotTableBehavior? photos_generic_behavior = find_behavior (FSpotPhotosTable.TABLE_NAME, version);
254- if (photos_generic_behavior != null)
255- photos_behavior = photos_generic_behavior as FSpotTableBehavior<FSpotPhotoRow>;
256- FSpotTableBehavior? tags_generic_behavior = find_behavior (FSpotTagsTable.TABLE_NAME, version);
257- if (tags_generic_behavior != null)
258- tags_behavior = tags_generic_behavior as FSpotTableBehavior<FSpotTagRow>;
259- FSpotTableBehavior? photo_tags_generic_behavior = find_behavior (FSpotPhotoTagsTable.TABLE_NAME, version);
260- if (photo_tags_generic_behavior != null)
261- photo_tags_behavior = photo_tags_generic_behavior as FSpotTableBehavior<FSpotPhotoTagRow>;
262- FSpotTableBehavior? photo_versions_generic_behavior = find_behavior (FSpotPhotoVersionsTable.TABLE_NAME, version);
263- if (photo_versions_generic_behavior != null)
264- photo_versions_behavior = photo_versions_generic_behavior as FSpotTableBehavior<FSpotPhotoVersionRow>;
265- FSpotTableBehavior? rolls_generic_behavior = find_behavior (FSpotRollsTable.TABLE_NAME, version);
266- if (rolls_generic_behavior != null)
267- rolls_behavior = rolls_generic_behavior as FSpotTableBehavior<FSpotRollRow>;
268-
269- if (photos_behavior == null || tags_behavior == null ||
270- photo_tags_behavior == null || photo_versions_behavior == null ||
271- rolls_behavior == null
272- )
273- throw new Spit.DataImports.DataImportError.UNSUPPORTED_VERSION ("Version %s is not supported", version.to_string ());
274- }
275-
276- public FSpotTableBehavior<FSpotPhotoRow> get_photos_behavior () {
277- return photos_behavior;
278- }
279-
280- public FSpotTableBehavior<FSpotTagRow> get_tags_behavior () {
281- return tags_behavior;
282- }
283-
284- public FSpotTableBehavior<FSpotPhotoTagRow> get_photo_tags_behavior () {
285- return photo_tags_behavior;
286- }
287-
288- public FSpotTableBehavior<FSpotPhotoVersionRow> get_photo_versions_behavior () {
289- return photo_versions_behavior;
290- }
291-
292- public FSpotTableBehavior<FSpotRollRow> get_rolls_behavior () {
293- return rolls_behavior;
294- }
295-}
296-
297-}
298-
299
300=== removed file 'plugins/shotwell-data-imports/FSpotDatabaseTable.vala'
301--- plugins/shotwell-data-imports/FSpotDatabaseTable.vala 2014-08-08 21:13:09 +0000
302+++ plugins/shotwell-data-imports/FSpotDatabaseTable.vala 1970-01-01 00:00:00 +0000
303@@ -1,54 +0,0 @@
304-/* Copyright 2009-2013 Yorba Foundation
305- *
306- * This software is licensed under the GNU LGPL (version 2.1 or later).
307- * See the COPYING file in this distribution.
308- */
309-
310-namespace DataImports.FSpot.Db {
311-
312-/**
313- * This class represents a generic F-Spot table.
314- */
315-public abstract class FSpotDatabaseTable<T> : ImportableDatabaseTable {
316- protected unowned Sqlite.Database fspot_db;
317- protected FSpotTableBehavior<T> behavior;
318-
319- public FSpotDatabaseTable (Sqlite.Database db) {
320- this.fspot_db = db;
321- }
322-
323- public void set_behavior (FSpotTableBehavior<T> behavior) {
324- this.behavior = behavior;
325- set_table_name (behavior.get_table_name ());
326- }
327-
328- public FSpotTableBehavior<T> get_behavior () {
329- return behavior;
330- }
331-
332- protected string get_joined_column_list (bool with_table = false) {
333- string[] columns = behavior.list_columns ();
334- if (with_table)
335- for (int i = 0; i < columns.length; i++)
336- columns[i] = "%s.%s".printf (table_name, columns[i]);
337- return string.joinv (", ", columns);
338- }
339-
340- protected int select_all (out Sqlite.Statement stmt) throws DatabaseError {
341- string column_list = get_joined_column_list ();
342- string sql = "SELECT %s FROM %s".printf (column_list, table_name);
343-
344- int res = fspot_db.prepare_v2 (sql, -1, out stmt);
345- if (res != Sqlite.OK)
346- throw_error ("Statement failed: %s".printf (sql), res);
347-
348- res = stmt.step ();
349- if (res != Sqlite.ROW && res != Sqlite.DONE)
350- throw_error ("select_all %s %s".printf (table_name, column_list), res);
351-
352- return res;
353- }
354-}
355-
356-}
357-
358
359=== removed file 'plugins/shotwell-data-imports/FSpotImporter.vala'
360--- plugins/shotwell-data-imports/FSpotImporter.vala 2014-08-08 21:13:09 +0000
361+++ plugins/shotwell-data-imports/FSpotImporter.vala 1970-01-01 00:00:00 +0000
362@@ -1,567 +0,0 @@
363-/* Copyright 2009-2013 Yorba Foundation
364- *
365- * This software is licensed under the GNU Lesser General Public License
366- * (version 2.1 or later). See the COPYING file in this distribution.
367- */
368-
369-public class FSpotService : Object, Spit.Pluggable, Spit.DataImports.Service {
370- private const string ICON_FILENAME = "f-spot-24.png";
371-
372- private static Gdk.Pixbuf[] icon_pixbuf_set = null;
373-
374- public FSpotService (GLib.File resource_directory) {
375- // initialize the database layer
376- DataImports.FSpot.Db.init ();
377- if (icon_pixbuf_set == null)
378- icon_pixbuf_set = Resources.load_icon_set (resource_directory.get_child (ICON_FILENAME));
379- }
380-
381- public int get_pluggable_interface (int min_host_interface, int max_host_interface) {
382- return Spit.negotiate_interfaces (min_host_interface, max_host_interface,
383- Spit.DataImports.CURRENT_INTERFACE);
384- }
385-
386- public unowned string get_id () {
387- return "org.yorba.shotwell.dataimports.fspot";
388- }
389-
390- public unowned string get_pluggable_name () {
391- return "F-Spot";
392- }
393-
394- public void get_info (ref Spit.PluggableInfo info) {
395- info.authors = "Bruno Girin";
396- info.copyright = _ ("Copyright 2009-2013 Yorba Foundation");
397- info.translators = Resources.TRANSLATORS;
398- info.version = _VERSION;
399- info.website_name = Resources.WEBSITE_NAME;
400- info.website_url = Resources.WEBSITE_URL;
401- info.is_license_wordwrapped = false;
402- info.license = Resources.LICENSE;
403- info.icons = icon_pixbuf_set;
404- }
405-
406- public void activation (bool enabled) {
407- }
408-
409- public Spit.DataImports.DataImporter create_data_importer (Spit.DataImports.PluginHost host) {
410- return new DataImports.FSpot.FSpotDataImporter (this, host);
411- }
412-}
413-
414-namespace DataImports.FSpot {
415-
416-internal const string SERVICE_NAME = "F-Spot";
417-internal const string SERVICE_WELCOME_MESSAGE =
418- _ ("Welcome to the F-Spot library import service.\n\nPlease select a library to import, either by selecting one of the existing libraries found by Shotwell or by selecting an alternative F-Spot database file.");
419-internal const string SERVICE_WELCOME_MESSAGE_FILE_ONLY =
420- _ ("Welcome to the F-Spot library import service.\n\nPlease select an F-Spot database file.");
421-internal const string FILE_IMPORT_LABEL =
422- _ ("Manually select an F-Spot database file to import:");
423-internal const string ERROR_CANT_OPEN_DB_FILE =
424- _ ("Cannot open the selected F-Spot database file: the file does not exist or is not an F-Spot database");
425-internal const string ERROR_UNSUPPORTED_DB_VERSION =
426- _ ("Cannot open the selected F-Spot database file: this version of the F-Spot database is not supported by Shotwell");
427-internal const string ERROR_CANT_READ_TAGS_TABLE =
428- _ ("Cannot read the selected F-Spot database file: error while reading tags table");
429-internal const string ERROR_CANT_READ_PHOTOS_TABLE =
430- _ ("Cannot read the selected F-Spot database file: error while reading photos table");
431-internal const string MESSAGE_FINAL_SCREEN =
432- _ ("Shotwell has found %d photos in the F-Spot library and is currently importing them. Duplicates will be automatically detected and removed.\n\nYou can close this dialog and start using Shotwell while the import is taking place in the background.");
433-
434-public class FSpotImportableLibrary : Spit.DataImports.ImportableLibrary, GLib.Object {
435- private File db_file;
436-
437- public FSpotImportableLibrary (File db_file) {
438- this.db_file = db_file;
439- }
440-
441- public File get_db_file () {
442- return db_file;
443- }
444-
445- public string get_display_name () {
446- return _ ("F-Spot library: %s").printf (db_file.get_path ());
447- }
448-}
449-
450-public class FSpotImportableItem : Spit.DataImports.ImportableMediaItem, GLib.Object {
451- private DataImports.FSpot.Db.FSpotPhotoRow photo_row;
452- private DataImports.FSpot.Db.FSpotPhotoVersionRow? photo_version_row;
453- private DataImports.FSpot.Db.FSpotRollRow? roll_row;
454- private FSpotImportableTag[] tags;
455- private FSpotImportableEvent? event;
456- private FSpotImportableRating rating;
457- private string folder_path;
458- private string filename;
459-
460- public FSpotImportableItem (
461- DataImports.FSpot.Db.FSpotPhotoRow photo_row,
462- DataImports.FSpot.Db.FSpotPhotoVersionRow? photo_version_row,
463- DataImports.FSpot.Db.FSpotRollRow? roll_row,
464- FSpotImportableTag[] tags,
465- FSpotImportableEvent? event,
466- bool is_hidden,
467- bool is_favorite
468- ) {
469- this.photo_row = photo_row;
470- this.photo_version_row = photo_version_row;
471- this.roll_row = roll_row;
472- this.tags = tags;
473- this.event = event;
474- if (photo_row.rating > 0)
475- this.rating = new FSpotImportableRating (photo_row.rating);
476- else if (is_hidden)
477- this.rating = new FSpotImportableRating (FSpotImportableRating.REJECTED);
478- else if (is_favorite)
479- this.rating = new FSpotImportableRating (5);
480- else
481- this.rating = new FSpotImportableRating (FSpotImportableRating.UNRATED);
482-
483- // store path and filename
484- folder_path = (photo_version_row != null) ?
485- photo_version_row.base_path.get_path () :
486- photo_row.base_path.get_path ();
487- filename = (photo_version_row != null) ?
488- photo_version_row.filename :
489- photo_row.filename;
490-
491- // In theory, neither field should be null at that point but belts
492- // and braces don't hurt
493- if (folder_path != null && filename != null) {
494- // check if file exist and if not decode as URL
495- File photo = File.new_for_path (folder_path).get_child (filename);
496-
497- // If file not found, parse as URI and store back
498- if (!photo.query_exists ()) {
499- folder_path = decode_url (folder_path);
500- filename = decode_url (filename);
501- }
502- }
503- }
504-
505- public Spit.DataImports.ImportableTag[] get_tags () {
506- Spit.DataImports.ImportableTag[] importable_tags = new Spit.DataImports.ImportableTag[0];
507- foreach (FSpotImportableTag tag in tags)
508- importable_tags += tag;
509- return importable_tags;
510- }
511-
512- public Spit.DataImports.ImportableEvent? get_event () {
513- return event;
514- }
515-
516- public string get_folder_path () {
517- return folder_path;
518- }
519-
520- public string get_filename () {
521- return filename;
522- }
523-
524- public string? get_title () {
525- return (photo_row.description == null || photo_row.description == "") ? null : photo_row.description;
526- }
527-
528- public Spit.DataImports.ImportableRating get_rating () {
529- return rating;
530- }
531-
532- private string decode_url (string url) {
533- StringBuilder builder = new StringBuilder ();
534- for (int idx = 0; idx < url.length; ) {
535- int cidx = url.index_of_char ('%', idx);
536- if (cidx > idx) {
537- builder.append (url.slice (idx, cidx));
538- }
539- if (cidx >= 0) {
540- if (cidx < url.length - 2) {
541- char c1 = url.get (cidx + 1);
542- char c2 = url.get (cidx + 2);
543- if (c1.isxdigit () && c1.isxdigit ()) {
544- int ccode = 0x10 * c1.xdigit_value () + c2.xdigit_value ();
545- builder.append_c ((char)ccode);
546- }
547- idx = cidx + 3;
548- } else {
549- idx = cidx + 1;
550- }
551- } else {
552- builder.append (url.substring (idx));
553- idx = url.length;
554- }
555- }
556- return builder.str;
557- }
558-}
559-
560-public class FSpotImportableTag : Spit.DataImports.ImportableTag, GLib.Object {
561- private DataImports.FSpot.Db.FSpotTagRow row;
562- private FSpotImportableTag? parent;
563-
564- public FSpotImportableTag (DataImports.FSpot.Db.FSpotTagRow row, FSpotImportableTag? parent) {
565- this.row = row;
566- this.parent = parent;
567- }
568-
569- public int64 get_id () {
570- return row.tag_id;
571- }
572-
573- public string get_name () {
574- return row.name;
575- }
576-
577- public Spit.DataImports.ImportableTag? get_parent () {
578- return parent;
579- }
580-
581- public FSpotImportableTag? get_fspot_parent () {
582- return parent;
583- }
584-
585- public string get_stock_icon () {
586- return row.stock_icon;
587- }
588-
589- public bool is_stock () {
590- return (row.stock_icon.has_prefix (DataImports.FSpot.Db.FSpotTagsTable.PREFIX_STOCK_ICON));
591- }
592-
593- public FSpotImportableEvent to_event () {
594- return new FSpotImportableEvent (this.row);
595- }
596-}
597-
598-public class FSpotImportableEvent : Spit.DataImports.ImportableEvent, GLib.Object {
599- private DataImports.FSpot.Db.FSpotTagRow row;
600-
601- public FSpotImportableEvent (DataImports.FSpot.Db.FSpotTagRow row) {
602- this.row = row;
603- }
604-
605- public string get_name () {
606- return row.name;
607- }
608-}
609-
610-public class FSpotImportableRating : Spit.DataImports.ImportableRating, GLib.Object {
611- public static const int REJECTED = -1;
612- public static const int UNRATED = 0;
613-
614- private int rating_value;
615-
616- public FSpotImportableRating (int rating_value) {
617- if (rating_value < -1)
618- rating_value = -1;
619- else if (rating_value > 5)
620- rating_value = 5;
621- this.rating_value = rating_value;
622- }
623-
624- public bool is_rejected () {
625- return (rating_value == REJECTED);
626- }
627-
628- public bool is_unrated () {
629- return (rating_value == UNRATED);
630- }
631-
632- public int get_value () {
633- return rating_value;
634- }
635-}
636-
637-internal class FSpotTagsCache : Object {
638- private DataImports.FSpot.Db.FSpotTagsTable tags_table;
639- private Gee.HashMap < int64?, FSpotImportableTag > tags_map;
640-
641- public FSpotTagsCache (DataImports.FSpot.Db.FSpotTagsTable tags_table) throws DatabaseError {
642- this.tags_table = tags_table;
643- tags_map = new Gee.HashMap < int64?, FSpotImportableTag > ();
644- }
645-
646- public FSpotImportableTag get_tag (DataImports.FSpot.Db.FSpotTagRow tag_row) throws DatabaseError {
647- FSpotImportableTag? tag = tags_map.get (tag_row.tag_id);
648- if (tag != null) {
649- return tag;
650- } else {
651- FSpotImportableTag? parent_tag = get_tag_from_id (tag_row.category_id);
652- FSpotImportableTag new_tag = new FSpotImportableTag (tag_row, parent_tag);
653- tags_map[tag_row.tag_id] = new_tag;
654- return new_tag;
655- }
656- }
657-
658- private FSpotImportableTag? get_tag_from_id (int64 tag_id) throws DatabaseError {
659- // check whether the tag ID is valid first, otherwise return null
660- if (tag_id < 1)
661- return null;
662- FSpotImportableTag? tag = tags_map.get (tag_id);
663- if (tag != null)
664- return tag;
665- DataImports.FSpot.Db.FSpotTagRow? tag_row = tags_table.get_by_id (tag_id);
666- if (tag_row != null) {
667- FSpotImportableTag? parent_tag = get_tag_from_id (tag_row.category_id);
668- FSpotImportableTag new_tag = new FSpotImportableTag (tag_row, parent_tag);
669- tags_map[tag_id] = new_tag;
670- return new_tag;
671- }
672- return null;
673- }
674-}
675-
676-public class FSpotDataImporter : Spit.DataImports.DataImporter, GLib.Object {
677-
678- private weak Spit.DataImports.PluginHost host = null;
679- private weak Spit.DataImports.Service service = null;
680- private bool running = false;
681-
682- public FSpotDataImporter (Spit.DataImports.Service service,
683- Spit.DataImports.PluginHost host) {
684- debug ("FSpotDataImporter instantiated.");
685- this.service = service;
686- this.host = host;
687- }
688-
689- private bool is_running () {
690- return running;
691- }
692-
693- public Spit.DataImports.Service get_service () {
694- return service;
695- }
696-
697- public void start () {
698- if (is_running ())
699- return;
700-
701- debug ("FSpotDataImporter: starting interaction.");
702-
703- running = true;
704-
705- do_discover_importable_libraries ();
706- }
707-
708- public void stop () {
709- debug ("FSpotDataImporter: stopping interaction.");
710-
711- running = false;
712- }
713-
714- // Actions and event implementation
715-
716- /**
717- * Action that discovers importable libraries based on standard locations.
718- */
719- private void do_discover_importable_libraries () {
720- Spit.DataImports.ImportableLibrary[] discovered_libraries =
721- new Spit.DataImports.ImportableLibrary[0];
722-
723- File[] db_files = {
724- // where the DB is in Ubuntu Lucid
725- File.new_for_path (Environment.get_user_config_dir ()).
726- get_child ("f-spot").get_child ("photos.db"),
727- // where it seems to be in Ubuntu Jaunty
728- File.new_for_path (Environment.get_home_dir ()).get_child (".gnome2").
729- get_child ("f-spot").get_child ("photos.db"),
730- // where it should really be if it followed the XDG spec
731- File.new_for_path (Environment.get_user_data_dir ()).
732- get_child ("f-spot").get_child ("photos.db")
733- };
734-
735- foreach (File db_file in db_files) {
736- if (db_file.query_exists (null)) {
737- discovered_libraries += new FSpotImportableLibrary (db_file);
738- message ("Discovered importable library: %s", db_file.get_path ());
739- }
740- }
741-
742- host.install_library_selection_pane (
743- (discovered_libraries.length > 0 ? SERVICE_WELCOME_MESSAGE : SERVICE_WELCOME_MESSAGE_FILE_ONLY),
744- discovered_libraries,
745- FILE_IMPORT_LABEL
746- );
747- }
748-
749- public void on_library_selected (Spit.DataImports.ImportableLibrary library) {
750- on_file_selected (((FSpotImportableLibrary)library).get_db_file ());
751- }
752-
753- public void on_file_selected (File file) {
754- DataImports.FSpot.Db.FSpotDatabase database;
755- FSpotTagsCache tags_cache;
756- Gee.ArrayList<DataImports.FSpot.Db.FSpotPhotoRow> all_photos;
757- double progress_delta_per_photo = 1.0;
758- double progress_plugin_to_host_ratio = 0.5;
759- double current_progress = 0.0;
760- try {
761- database = new DataImports.FSpot.Db.FSpotDatabase (file);
762- } catch (DatabaseError e) {
763- debug ("FSpotDataImporter: Can't open database file: %s".printf (e.message));
764- host.post_error_message (ERROR_CANT_OPEN_DB_FILE);
765- return;
766- } catch (Spit.DataImports.DataImportError e) {
767- debug ("FSpotDataImporter: Unsupported F-Spot database version: %s".printf (e.message));
768- host.post_error_message (ERROR_UNSUPPORTED_DB_VERSION);
769- return;
770- }
771- try {
772- tags_cache = new FSpotTagsCache (database.tags_table);
773- } catch (DatabaseError e) {
774- debug ("FSpotDataImporter: Can't read tags table: %s".printf (e.message));
775- host.post_error_message (ERROR_CANT_READ_TAGS_TABLE);
776- return;
777- }
778- host.install_import_progress_pane (_ ("Preparing to import"));
779- try {
780- all_photos = database.photos_table.get_all ();
781- } catch (DatabaseError e) {
782- debug ("FSpotDataImporter: Can't read photos table: %s".printf (e.message));
783- host.post_error_message (ERROR_CANT_READ_PHOTOS_TABLE);
784- return;
785- }
786- if (all_photos.size > 0)
787- progress_delta_per_photo = 1.0 / all_photos.size;
788- foreach (DataImports.FSpot.Db.FSpotPhotoRow photo_row in all_photos) {
789- bool hidden = false;
790- bool favorite = false;
791- FSpotImportableTag[] tags = new FSpotImportableTag[0];
792- FSpotImportableEvent? event = null;
793- DataImports.FSpot.Db.FSpotRollRow? roll_row = null;
794-
795- // TODO: We do not convert F-Spot events to Shotwell events because F-Spot's events
796- // are essentially tags. We would need to detect if the tag is an event (use
797- // is_tag_event) and then assign the event to the photo ... since a photo can be
798- // in multiple F-Spot events, we would need to pick one, and since their tags
799- // are hierarchical, we would need to pick a name (probably the leaf)
800- try {
801- foreach (
802- DataImports.FSpot.Db.FSpotTagRow tag_row in
803- database.tags_table.get_by_photo_id (photo_row.photo_id)
804- ) {
805- FSpotImportableTag tag = tags_cache.get_tag (tag_row);
806- if (is_tag_hidden (tag, database.hidden_tag_id))
807- hidden = true;
808- else if (is_tag_favorite (tag))
809- favorite = true;
810- else
811- tags += tag;
812- }
813- } catch (DatabaseError e) {
814- // log the error and leave the tag list empty
815- message ("Failed to retrieve tags for photo ID %ld: %s", (long) photo_row.photo_id,
816- e.message);
817- }
818-
819- try {
820- roll_row = database.rolls_table.get_by_id (photo_row.roll_id);
821- } catch (DatabaseError e) {
822- // log the error and leave the roll row null
823- message ("Failed to retrieve roll for photo ID %ld: %s", (long) photo_row.photo_id,
824- e.message);
825- }
826-
827- Spit.DataImports.ImportableMediaItem[] importable_items = new Spit.DataImports.ImportableMediaItem[0];
828- try {
829- Gee.ArrayList<DataImports.FSpot.Db.FSpotPhotoVersionRow> photo_versions =
830- database.photo_versions_table.get_by_photo_id (photo_row.photo_id);
831- bool photo_versions_added = false; // set to true if at least one version was added
832- bool photo_versions_skipped = false; // set to true if at least one version was skipped due to missing file details
833- foreach (DataImports.FSpot.Db.FSpotPhotoVersionRow photo_version_row in photo_versions) {
834- if (photo_version_row.base_path != null && photo_version_row.filename != null) {
835- importable_items += new FSpotImportableItem (
836- photo_row, photo_version_row, roll_row, tags, event, hidden, favorite
837- );
838- photo_versions_added = true;
839- } else {
840- photo_versions_skipped = true;
841- }
842- }
843-
844- // Older versions of F-Spot (0.4.3.1 at least, perhaps later) did not maintain photo_versions,
845- // this handles that case
846- // It also handles the case when we had to skip any photo version due to missing
847- // file details
848- if (photo_versions_skipped || !photo_versions_added) {
849- if (photo_row.base_path != null && photo_row.filename != null) {
850- importable_items += new FSpotImportableItem (
851- photo_row, null, roll_row, tags, event, hidden, favorite
852- );
853- }
854- }
855- } catch (DatabaseError e) {
856- // if we can't load the different versions, do the best we can
857- // and create one photo from the photo row that was found earlier
858- message ("Failed to retrieve versions for photo ID %ld: %s", (long) photo_row.photo_id,
859- e.message);
860- if (photo_row.base_path != null && photo_row.filename != null) {
861- importable_items += new FSpotImportableItem (
862- photo_row, null, roll_row, tags, event, hidden, favorite
863- );
864- }
865- }
866- // If the importer is still running, import the items and loop,
867- // otherwise break the loop
868- if (running) {
869- host.prepare_media_items_for_import (
870- importable_items,
871- current_progress + (progress_delta_per_photo * progress_plugin_to_host_ratio),
872- progress_delta_per_photo * (1 - progress_plugin_to_host_ratio),
873- null
874- );
875- current_progress += progress_delta_per_photo;
876- host.update_import_progress_pane (current_progress);
877- } else {
878- break;
879- }
880- }
881- host.finalize_import (on_imported_items_count);
882- }
883-
884- public void on_imported_items_count (int imported_items_count) {
885- host.install_static_message_pane (
886- MESSAGE_FINAL_SCREEN.printf (imported_items_count),
887- Spit.DataImports.PluginHost.ButtonMode.CLOSE
888- );
889- }
890-
891- private bool is_tag_event (FSpotImportableTag tag) {
892- bool result = (DataImports.FSpot.Db.FSpotTagsTable.STOCK_ICON_EVENTS == tag.get_stock_icon ());
893- if (!result) {
894- FSpotImportableTag? parent = tag.get_fspot_parent ();
895- if (parent == null)
896- result = false;
897- else
898- result = is_tag_event (parent);
899- }
900- return result;
901- }
902-
903- private bool is_tag_hidden (FSpotImportableTag tag, int64 hidden_tag_id) {
904- bool result = (hidden_tag_id == tag.get_id ());
905- if (!result) {
906- FSpotImportableTag? parent = tag.get_fspot_parent ();
907- if (parent == null)
908- result = false;
909- else
910- result = is_tag_hidden (parent, hidden_tag_id);
911- }
912- return result;
913- }
914-
915- private bool is_tag_favorite (FSpotImportableTag tag) {
916- bool result = (DataImports.FSpot.Db.FSpotTagsTable.STOCK_ICON_FAV == tag.get_stock_icon ());
917- if (!result) {
918- FSpotImportableTag? parent = tag.get_fspot_parent ();
919- if (parent == null)
920- result = false;
921- else
922- result = is_tag_favorite (parent);
923- }
924- return result;
925- }
926-}
927-
928-} // namespace
929-
930
931=== removed file 'plugins/shotwell-data-imports/FSpotMetaTable.vala'
932--- plugins/shotwell-data-imports/FSpotMetaTable.vala 2014-08-08 21:13:09 +0000
933+++ plugins/shotwell-data-imports/FSpotMetaTable.vala 1970-01-01 00:00:00 +0000
934@@ -1,113 +0,0 @@
935-/* Copyright 2011-2013 Yorba Foundation
936- *
937- * This software is licensed under the GNU Lesser General Public License
938- * (version 2.1 or later). See the COPYING file in this distribution.
939- */
940-
941-namespace DataImports.FSpot.Db {
942-
943-/**
944- * The value object for the "meta" table, representing a single database row.
945- */
946-public class FSpotMetaRow : Object {
947- // ignore the ID
948- public string name;
949- public string data;
950-}
951-
952-/**
953- * This class represents the F-Spot meta table, which stores some essential
954- * meta-data for the whole database. It is implemented as a simple dictionary
955- * where each row in the table is a key/value pair.
956- *
957- * The meta table implementation is the only one that throws a database error
958- * if something goes wrong because:
959- * * it is essential to read the content of that table in order to identify
960- * the version of the database and select the correct behavior,
961- * * this table is read at the very beginning of the process so any failure
962- * will occur immediately,
963- * * failing to read this table means that there is no point in reading the
964- * attempting to read the rest of the database so we might as well abort.
965- */
966-public class FSpotMetaTable : FSpotDatabaseTable<FSpotMetaRow> {
967-
968- public FSpotMetaTable (Sqlite.Database db) {
969- base (db);
970- set_behavior (FSpotMetaBehavior.get_instance ());
971- }
972-
973- public string? get_data (string name) throws DatabaseError {
974- string[] columns = behavior.list_columns ();
975- string column_list = string.joinv (", ", columns);
976- string sql = "SELECT %s FROM %s WHERE name=?".printf (column_list, table_name);
977- Sqlite.Statement stmt;
978- int res = fspot_db.prepare_v2 (sql, -1, out stmt);
979- if (res != Sqlite.OK)
980- throw_error ("Statement failed: %s".printf (sql), res);
981-
982- res = stmt.bind_text (1, name);
983- if (res != Sqlite.OK)
984- throw_error ("Bind failed for name %s".printf (name), res);
985-
986- res = stmt.step ();
987- if (res != Sqlite.ROW) {
988- if (res != Sqlite.DONE)
989- throw_error ("FSpotMetaTable.get_data", res);
990-
991- return null;
992- }
993-
994- FSpotMetaRow row;
995- behavior.build_row (stmt, out row);
996- return row.data;
997- }
998-
999- public string? get_app_version () throws DatabaseError {
1000- return get_data ("F-Spot Version");
1001- }
1002-
1003- public string? get_db_version () throws DatabaseError {
1004- return get_data ("F-Spot Database Version");
1005- }
1006-
1007- public int64 get_hidden_tag_id () throws DatabaseError {
1008- string id_str = get_data ("Hidden Tag Id");
1009- if (id_str != null) {
1010- return int64.parse (id_str);
1011- } else {
1012- return -1;
1013- }
1014- }
1015-}
1016-
1017-public class FSpotMetaBehavior : FSpotTableBehavior<FSpotMetaRow>, Object {
1018- public static const string TABLE_NAME = "Meta";
1019-
1020- private static FSpotMetaBehavior instance;
1021-
1022- private FSpotMetaBehavior () {
1023- }
1024-
1025- public static FSpotMetaBehavior get_instance () {
1026- if (instance == null)
1027- instance = new FSpotMetaBehavior ();
1028- return instance;
1029- }
1030-
1031- public string get_table_name () {
1032- return TABLE_NAME;
1033- }
1034-
1035- public string[] list_columns () {
1036- return { "name", "data" };
1037- }
1038-
1039- public void build_row (Sqlite.Statement stmt, out FSpotMetaRow row, int offset = 0) {
1040- row = new FSpotMetaRow ();
1041- row.name = stmt.column_text (offset + 0);
1042- row.data = stmt.column_text (offset + 1);
1043- }
1044-}
1045-
1046-}
1047-
1048
1049=== removed file 'plugins/shotwell-data-imports/FSpotPhotoTagsTable.vala'
1050--- plugins/shotwell-data-imports/FSpotPhotoTagsTable.vala 2014-08-08 21:13:09 +0000
1051+++ plugins/shotwell-data-imports/FSpotPhotoTagsTable.vala 1970-01-01 00:00:00 +0000
1052@@ -1,57 +0,0 @@
1053-/* Copyright 2011-2013 Yorba Foundation
1054- *
1055- * This software is licensed under the GNU Lesser General Public License
1056- * (version 2.1 or later). See the COPYING file in this distribution.
1057- */
1058-
1059-namespace DataImports.FSpot.Db {
1060-
1061-/**
1062- * The value object for the "photo_tags" table, representing a single database row.
1063- */
1064-public class FSpotPhotoTagRow : Object {
1065- public int64 photo_id;
1066- public int64 tag_id;
1067-}
1068-
1069-/**
1070- * This class represents the F-Spot photo_tags table.
1071- */
1072-public class FSpotPhotoTagsTable : FSpotDatabaseTable<FSpotPhotoTagRow> {
1073- public static const string TABLE_NAME = "Photo_Tags";
1074-
1075- public FSpotPhotoTagsTable (Sqlite.Database db, FSpotDatabaseBehavior db_behavior) {
1076- base (db);
1077- set_behavior (db_behavior.get_photo_tags_behavior ());
1078- }
1079-}
1080-
1081-public class FSpotPhotoTagsV0Behavior : FSpotTableBehavior<FSpotPhotoTagRow>, Object {
1082- private static FSpotPhotoTagsV0Behavior instance;
1083-
1084- private FSpotPhotoTagsV0Behavior () {
1085- }
1086-
1087- public static FSpotPhotoTagsV0Behavior get_instance () {
1088- if (instance == null)
1089- instance = new FSpotPhotoTagsV0Behavior ();
1090- return instance;
1091- }
1092-
1093- public string get_table_name () {
1094- return FSpotPhotoTagsTable.TABLE_NAME;
1095- }
1096-
1097- public string[] list_columns () {
1098- return { "photo_id", "tag_id" };
1099- }
1100-
1101- public void build_row (Sqlite.Statement stmt, out FSpotPhotoTagRow row, int offset = 0) {
1102- row = new FSpotPhotoTagRow ();
1103- row.photo_id = stmt.column_int64 (offset + 0);
1104- row.tag_id = stmt.column_int64 (offset + 1);
1105- }
1106-}
1107-
1108-}
1109-
1110
1111=== removed file 'plugins/shotwell-data-imports/FSpotPhotoVersionsTable.vala'
1112--- plugins/shotwell-data-imports/FSpotPhotoVersionsTable.vala 2014-08-08 21:13:09 +0000
1113+++ plugins/shotwell-data-imports/FSpotPhotoVersionsTable.vala 1970-01-01 00:00:00 +0000
1114@@ -1,275 +0,0 @@
1115-/* Copyright 2011-2013 Yorba Foundation
1116- *
1117- * This software is licensed under the GNU Lesser General Public License
1118- * (version 2.1 or later). See the COPYING file in this distribution.
1119- */
1120-
1121-namespace DataImports.FSpot.Db {
1122-
1123-/**
1124- * The value object for the "photo_versions" table, representing a single database row.
1125- */
1126-public class FSpotPhotoVersionRow : Object {
1127- public int64 photo_id;
1128- public int64 version_id;
1129- public string name;
1130- public File? base_path;
1131- public string? filename;
1132- public string md5_sum;
1133- public bool is_protected;
1134-}
1135-
1136-/**
1137- * This class represents the F-Spot photo_versions table.
1138- */
1139-public class FSpotPhotoVersionsTable : FSpotDatabaseTable<FSpotPhotoVersionRow> {
1140- public static const string TABLE_NAME = "Photo_versions";
1141-
1142- public FSpotPhotoVersionsTable (Sqlite.Database db, FSpotDatabaseBehavior db_behavior) {
1143- base (db);
1144- set_behavior (db_behavior.get_photo_versions_behavior ());
1145- }
1146-
1147- public Gee.ArrayList<FSpotPhotoVersionRow> get_by_photo_id (int64 photo_id) throws DatabaseError {
1148- Gee.ArrayList<FSpotPhotoVersionRow> rows = new Gee.ArrayList < FSpotPhotoVersionRow?> ();
1149-
1150- Sqlite.Statement stmt;
1151-
1152- string column_list = get_joined_column_list ();
1153- string sql = "SELECT %s FROM %s WHERE photo_id=?".printf (
1154- column_list, table_name
1155- );
1156-
1157- int res = fspot_db.prepare_v2 (sql, -1, out stmt);
1158- if (res != Sqlite.OK)
1159- throw_error ("Statement failed: %s".printf (sql), res);
1160-
1161- res = stmt.bind_int64 (1, photo_id);
1162- if (res != Sqlite.OK)
1163- throw_error ("Bind failed for photo_id", res);
1164-
1165- res = stmt.step ();
1166- while (res == Sqlite.ROW) {
1167- FSpotPhotoVersionRow row;
1168- behavior.build_row (stmt, out row);
1169- rows.add (row);
1170- res = stmt.step ();
1171- }
1172-
1173- return rows;
1174- }
1175-}
1176-
1177-// Photo_versions table behavior for v0-8
1178-// Note: there is a change in the URI format in version 8 but the File.new_for_uri
1179-// constructor should be able to deal with the variation, so the v8 behavior should
1180-// be handled in a way identical to v0-7
1181-public class FSpotPhotoVersionsV0Behavior : FSpotTableBehavior<FSpotPhotoVersionRow>, Object {
1182- private static FSpotPhotoVersionsV0Behavior instance;
1183-
1184- private FSpotPhotoVersionsV0Behavior () {
1185- }
1186-
1187- public static FSpotPhotoVersionsV0Behavior get_instance () {
1188- if (instance == null)
1189- instance = new FSpotPhotoVersionsV0Behavior ();
1190- return instance;
1191- }
1192-
1193- public string get_table_name () {
1194- return FSpotPhotoVersionsTable.TABLE_NAME;
1195- }
1196-
1197- public string[] list_columns () {
1198- return { "photo_id", "version_id", "name", "uri" };
1199- }
1200-
1201- public void build_row (Sqlite.Statement stmt, out FSpotPhotoVersionRow row, int offset = 0) {
1202- row = new FSpotPhotoVersionRow ();
1203- row.photo_id = stmt.column_int64 (offset + 0);
1204- row.version_id = stmt.column_int64 (offset + 1);
1205- row.name = stmt.column_text (offset + 2);
1206-
1207- string? full_path = stmt.column_text (offset + 3);
1208- if (full_path != null) {
1209- File uri = File.new_for_uri (full_path);
1210- row.base_path = uri.get_parent ();
1211- row.filename = uri.get_basename ();
1212- }
1213-
1214- row.md5_sum = "";
1215- row.is_protected = false;
1216- }
1217-}
1218-
1219-// Photo_versions table behavior for v9-15
1220-// add protected field
1221-public class FSpotPhotoVersionsV9Behavior : FSpotTableBehavior<FSpotPhotoVersionRow>, Object {
1222- private static FSpotPhotoVersionsV9Behavior instance;
1223-
1224- private FSpotPhotoVersionsV9Behavior () {
1225- }
1226-
1227- public static FSpotPhotoVersionsV9Behavior get_instance () {
1228- if (instance == null)
1229- instance = new FSpotPhotoVersionsV9Behavior ();
1230- return instance;
1231- }
1232-
1233- public string get_table_name () {
1234- return FSpotPhotoVersionsTable.TABLE_NAME;
1235- }
1236-
1237- public string[] list_columns () {
1238- return { "photo_id", "version_id", "name", "uri",
1239- "protected"
1240- };
1241- }
1242-
1243- public void build_row (Sqlite.Statement stmt, out FSpotPhotoVersionRow row, int offset = 0) {
1244- row = new FSpotPhotoVersionRow ();
1245- row.photo_id = stmt.column_int64 (offset + 0);
1246- row.version_id = stmt.column_int64 (offset + 1);
1247- row.name = stmt.column_text (offset + 2);
1248-
1249- string? full_path = stmt.column_text (offset + 3);
1250- if (full_path != null) {
1251- File uri = File.new_for_uri (full_path);
1252- row.base_path = uri.get_parent ();
1253- row.filename = uri.get_basename ();
1254- }
1255-
1256- row.md5_sum = "";
1257- row.is_protected = (stmt.column_int (offset + 4) > 0);
1258- }
1259-}
1260-
1261-// Photo_versions table behavior for v16
1262-// add md5_sum in photo_versions
1263-public class FSpotPhotoVersionsV16Behavior : FSpotTableBehavior<FSpotPhotoVersionRow>, Object {
1264- private static FSpotPhotoVersionsV16Behavior instance;
1265-
1266- private FSpotPhotoVersionsV16Behavior () {
1267- }
1268-
1269- public static FSpotPhotoVersionsV16Behavior get_instance () {
1270- if (instance == null)
1271- instance = new FSpotPhotoVersionsV16Behavior ();
1272- return instance;
1273- }
1274-
1275- public string get_table_name () {
1276- return FSpotPhotoVersionsTable.TABLE_NAME;
1277- }
1278-
1279- public string[] list_columns () {
1280- return { "photo_id", "version_id", "name", "uri",
1281- "md5_sum", "protected"
1282- };
1283- }
1284-
1285- public void build_row (Sqlite.Statement stmt, out FSpotPhotoVersionRow row, int offset = 0) {
1286- row = new FSpotPhotoVersionRow ();
1287- row.photo_id = stmt.column_int64 (offset + 0);
1288- row.version_id = stmt.column_int64 (offset + 1);
1289- row.name = stmt.column_text (offset + 2);
1290-
1291- string? full_path = stmt.column_text (offset + 3);
1292- if (full_path != null) {
1293- File uri = File.new_for_uri (full_path);
1294- row.base_path = uri.get_parent ();
1295- row.filename = uri.get_basename ();
1296- }
1297-
1298- row.md5_sum = stmt.column_text (offset + 4);
1299- row.is_protected = (stmt.column_int (offset + 5) > 0);
1300- }
1301-}
1302-
1303-// Photo_versions table behavior for v17
1304-// v17 split the URI into base_uri and filename (reverting back to the original
1305-// design introduced in v0, albeit with a URI rather than a file system path)
1306-public class FSpotPhotoVersionsV17Behavior : FSpotTableBehavior<FSpotPhotoVersionRow>, Object {
1307- private static FSpotPhotoVersionsV17Behavior instance;
1308-
1309- private FSpotPhotoVersionsV17Behavior () {
1310- }
1311-
1312- public static FSpotPhotoVersionsV17Behavior get_instance () {
1313- if (instance == null)
1314- instance = new FSpotPhotoVersionsV17Behavior ();
1315- return instance;
1316- }
1317-
1318- public string get_table_name () {
1319- return FSpotPhotoVersionsTable.TABLE_NAME;
1320- }
1321-
1322- public string[] list_columns () {
1323- return { "photo_id", "version_id", "name", "base_uri", "filename",
1324- "md5_sum", "protected"
1325- };
1326- }
1327-
1328- public void build_row (Sqlite.Statement stmt, out FSpotPhotoVersionRow row, int offset = 0) {
1329- row = new FSpotPhotoVersionRow ();
1330- row.photo_id = stmt.column_int64 (offset + 0);
1331- row.version_id = stmt.column_int64 (offset + 1);
1332- row.name = stmt.column_text (offset + 2);
1333-
1334- string? base_path = stmt.column_text (offset + 3);
1335- string? filename = stmt.column_text (offset + 4);
1336- if (base_path != null && filename != null) {
1337- row.base_path = File.new_for_uri (base_path);
1338- row.filename = filename;
1339- }
1340-
1341- row.md5_sum = stmt.column_text (offset + 5);
1342- row.is_protected = (stmt.column_int (offset + 6) > 0);
1343- }
1344-}
1345-
1346-// Photo_versions table behavior for v18
1347-// md5_sum renamed import_md5
1348-public class FSpotPhotoVersionsV18Behavior : FSpotTableBehavior<FSpotPhotoVersionRow>, Object {
1349- private static FSpotPhotoVersionsV18Behavior instance;
1350-
1351- private FSpotPhotoVersionsV18Behavior () {
1352- }
1353-
1354- public static FSpotPhotoVersionsV18Behavior get_instance () {
1355- if (instance == null)
1356- instance = new FSpotPhotoVersionsV18Behavior ();
1357- return instance;
1358- }
1359-
1360- public string get_table_name () {
1361- return FSpotPhotoVersionsTable.TABLE_NAME;
1362- }
1363-
1364- public string[] list_columns () {
1365- return { "photo_id", "version_id", "name", "base_uri", "filename",
1366- "import_md5", "protected"
1367- };
1368- }
1369-
1370- public void build_row (Sqlite.Statement stmt, out FSpotPhotoVersionRow row, int offset = 0) {
1371- row = new FSpotPhotoVersionRow ();
1372- row.photo_id = stmt.column_int64 (offset + 0);
1373- row.version_id = stmt.column_int64 (offset + 1);
1374- row.name = stmt.column_text (offset + 2);
1375-
1376- string? base_path = stmt.column_text (offset + 3);
1377- string? filename = stmt.column_text (offset + 4);
1378- if (base_path != null && filename != null) {
1379- row.base_path = File.new_for_uri (base_path);
1380- row.filename = filename;
1381- }
1382-
1383- row.md5_sum = stmt.column_text (offset + 5);
1384- row.is_protected = (stmt.column_int (offset + 6) > 0);
1385- }
1386-}
1387-
1388-}
1389-
1390
1391=== removed file 'plugins/shotwell-data-imports/FSpotPhotosTable.vala'
1392--- plugins/shotwell-data-imports/FSpotPhotosTable.vala 2014-08-08 21:13:09 +0000
1393+++ plugins/shotwell-data-imports/FSpotPhotosTable.vala 1970-01-01 00:00:00 +0000
1394@@ -1,363 +0,0 @@
1395-/* Copyright 2011-2013 Yorba Foundation
1396- *
1397- * This software is licensed under the GNU Lesser General Public License
1398- * (version 2.1 or later). See the COPYING file in this distribution.
1399- */
1400-
1401-namespace DataImports.FSpot.Db {
1402-
1403-/**
1404- * The value object for the "photos" table, representing a single database row.
1405- */
1406-public class FSpotPhotoRow : Object {
1407- public int64 photo_id;
1408- public time_t time;
1409- public File? base_path;
1410- public string? filename;
1411- public string description;
1412- public int64 roll_id;
1413- public int64 default_version_id;
1414- public int rating;
1415- public string md5_sum;
1416-}
1417-
1418-/**
1419- * This class represents the F-Spot photos table.
1420- */
1421-public class FSpotPhotosTable : FSpotDatabaseTable<FSpotPhotoRow> {
1422- public static const string TABLE_NAME = "Photos";
1423-
1424- public FSpotPhotosTable (Sqlite.Database db, FSpotDatabaseBehavior db_behavior) {
1425- base (db);
1426- set_behavior (db_behavior.get_photos_behavior ());
1427- }
1428-
1429- public Gee.ArrayList<FSpotPhotoRow> get_all () throws DatabaseError {
1430- Gee.ArrayList<FSpotPhotoRow> all = new Gee.ArrayList < FSpotPhotoRow?> ();
1431-
1432- Sqlite.Statement stmt;
1433- int res = select_all (out stmt);
1434- while (res == Sqlite.ROW) {
1435- FSpotPhotoRow row;
1436- behavior.build_row (stmt, out row);
1437- all.add (row);
1438- res = stmt.step ();
1439- }
1440-
1441- return all;
1442- }
1443-}
1444-
1445-// Photos table behavior for v0-4
1446-// The original table format
1447-public class FSpotPhotosV0Behavior : FSpotTableBehavior<FSpotPhotoRow>, Object {
1448- private static FSpotPhotosV0Behavior instance;
1449-
1450- private FSpotPhotosV0Behavior () {
1451- }
1452-
1453- public static FSpotPhotosV0Behavior get_instance () {
1454- if (instance == null)
1455- instance = new FSpotPhotosV0Behavior ();
1456- return instance;
1457- }
1458-
1459- public string get_table_name () {
1460- return FSpotPhotosTable.TABLE_NAME;
1461- }
1462-
1463- public string[] list_columns () {
1464- return { "id", "time", "directory_path", "name", "description",
1465- "default_version_id"
1466- };
1467- }
1468-
1469- public void build_row (Sqlite.Statement stmt, out FSpotPhotoRow row, int offset = 0) {
1470- row = new FSpotPhotoRow ();
1471- row.photo_id = stmt.column_int64 (offset + 0);
1472- row.time = (time_t) stmt.column_int64 (offset + 1);
1473-
1474- string? base_path = stmt.column_text (offset + 2);
1475- string? filename = stmt.column_text (offset + 3);
1476- if (base_path != null && filename != null) {
1477- row.base_path = File.new_for_uri (base_path);
1478- row.filename = filename;
1479- }
1480-
1481- row.description = stmt.column_text (offset + 4);
1482- row.roll_id = INVALID_ID;
1483- row.default_version_id = stmt.column_int64 (offset + 5);
1484- row.rating = 0;
1485- row.md5_sum = "";
1486- }
1487-}
1488-
1489-// Photos table behavior for v5-6
1490-// v5 introduced a roll_id to reference the imported roll (rolls were a new
1491-// table migrated from imports)
1492-public class FSpotPhotosV5Behavior : FSpotTableBehavior<FSpotPhotoRow>, Object {
1493- private static FSpotPhotosV5Behavior instance;
1494-
1495- private FSpotPhotosV5Behavior () {
1496- }
1497-
1498- public static FSpotPhotosV5Behavior get_instance () {
1499- if (instance == null)
1500- instance = new FSpotPhotosV5Behavior ();
1501- return instance;
1502- }
1503-
1504- public string get_table_name () {
1505- return FSpotPhotosTable.TABLE_NAME;
1506- }
1507-
1508- public string[] list_columns () {
1509- return { "id", "time", "directory_path", "name", "description", "roll_id",
1510- "default_version_id"
1511- };
1512- }
1513-
1514- public void build_row (Sqlite.Statement stmt, out FSpotPhotoRow row, int offset = 0) {
1515- row = new FSpotPhotoRow ();
1516- row.photo_id = stmt.column_int64 (offset + 0);
1517- row.time = (time_t) stmt.column_int64 (offset + 1);
1518-
1519- string? base_path = stmt.column_text (offset + 2);
1520- string? filename = stmt.column_text (offset + 3);
1521- if (base_path != null && filename != null) {
1522- row.base_path = File.new_for_uri (base_path);
1523- row.filename = filename;
1524- }
1525-
1526- row.description = stmt.column_text (offset + 4);
1527- row.roll_id = stmt.column_int64 (offset + 5);
1528- row.default_version_id = stmt.column_int64 (offset + 6);
1529- row.rating = 0;
1530- row.md5_sum = "";
1531- }
1532-}
1533-
1534-// Photos table behavior for v7-10
1535-// v7 merged directory_path and name into a single URI value with a file://
1536-// prefix; presumaly this is meant to be able to handle remote files using a
1537-// different URI prefix such as remote files
1538-public class FSpotPhotosV7Behavior : FSpotTableBehavior<FSpotPhotoRow>, Object {
1539- private static FSpotPhotosV7Behavior instance;
1540-
1541- private FSpotPhotosV7Behavior () {
1542- }
1543-
1544- public static FSpotPhotosV7Behavior get_instance () {
1545- if (instance == null)
1546- instance = new FSpotPhotosV7Behavior ();
1547- return instance;
1548- }
1549-
1550- public string get_table_name () {
1551- return FSpotPhotosTable.TABLE_NAME;
1552- }
1553-
1554- public string[] list_columns () {
1555- return { "id", "time", "uri", "description", "roll_id",
1556- "default_version_id"
1557- };
1558- }
1559-
1560- public void build_row (Sqlite.Statement stmt, out FSpotPhotoRow row, int offset = 0) {
1561- row = new FSpotPhotoRow ();
1562- row.photo_id = stmt.column_int64 (offset + 0);
1563- row.time = (time_t) stmt.column_int64 (offset + 1);
1564-
1565- string? full_path = stmt.column_text (offset + 2);
1566- if (full_path != null) {
1567- File uri = File.new_for_uri (full_path);
1568- row.base_path = uri.get_parent ();
1569- row.filename = uri.get_basename ();
1570- }
1571-
1572- row.description = stmt.column_text (offset + 3);
1573- row.roll_id = stmt.column_int64 (offset + 4);
1574- row.default_version_id = stmt.column_int64 (offset + 5);
1575- row.rating = 0;
1576- row.md5_sum = "";
1577- }
1578-}
1579-
1580-// Photos table behavior for v11-15
1581-// v11 introduced the concept of rating so add this to the list of fields
1582-public class FSpotPhotosV11Behavior : FSpotTableBehavior<FSpotPhotoRow>, Object {
1583- private static FSpotPhotosV11Behavior instance;
1584-
1585- private FSpotPhotosV11Behavior () {
1586- }
1587-
1588- public static FSpotPhotosV11Behavior get_instance () {
1589- if (instance == null)
1590- instance = new FSpotPhotosV11Behavior ();
1591- return instance;
1592- }
1593-
1594- public string get_table_name () {
1595- return FSpotPhotosTable.TABLE_NAME;
1596- }
1597-
1598- public string[] list_columns () {
1599- return { "id", "time", "uri", "description", "roll_id",
1600- "default_version_id", "rating"
1601- };
1602- }
1603-
1604- public void build_row (Sqlite.Statement stmt, out FSpotPhotoRow row, int offset = 0) {
1605- row = new FSpotPhotoRow ();
1606- row.photo_id = stmt.column_int64 (offset + 0);
1607- row.time = (time_t) stmt.column_int64 (offset + 1);
1608-
1609- string? full_path = stmt.column_text (offset + 2);
1610- if (full_path != null) {
1611- File uri = File.new_for_uri (full_path);
1612- row.base_path = uri.get_parent ();
1613- row.filename = uri.get_basename ();
1614- }
1615-
1616- row.description = stmt.column_text (offset + 3);
1617- row.roll_id = stmt.column_int64 (offset + 4);
1618- row.default_version_id = stmt.column_int64 (offset + 5);
1619- row.rating = stmt.column_int (offset + 6);
1620- row.md5_sum = "";
1621- }
1622-}
1623-
1624-// Photos table behavior for v16
1625-// v16 introduced the MD5 sum so add this to the list of fields
1626-public class FSpotPhotosV16Behavior : FSpotTableBehavior<FSpotPhotoRow>, Object {
1627- private static FSpotPhotosV16Behavior instance;
1628-
1629- private FSpotPhotosV16Behavior () {
1630- }
1631-
1632- public static FSpotPhotosV16Behavior get_instance () {
1633- if (instance == null)
1634- instance = new FSpotPhotosV16Behavior ();
1635- return instance;
1636- }
1637-
1638- public string get_table_name () {
1639- return FSpotPhotosTable.TABLE_NAME;
1640- }
1641-
1642- public string[] list_columns () {
1643- return { "id", "time", "uri", "description", "roll_id",
1644- "default_version_id", "rating", "md5_sum"
1645- };
1646- }
1647-
1648- public void build_row (Sqlite.Statement stmt, out FSpotPhotoRow row, int offset = 0) {
1649- row = new FSpotPhotoRow ();
1650- row.photo_id = stmt.column_int64 (offset + 0);
1651- row.time = (time_t) stmt.column_int64 (offset + 1);
1652-
1653- string? full_path = stmt.column_text (offset + 2);
1654- if (full_path != null) {
1655- File uri = File.new_for_uri (full_path);
1656- row.base_path = uri.get_parent ();
1657- row.filename = uri.get_basename ();
1658- }
1659-
1660- row.description = stmt.column_text (offset + 3);
1661- row.roll_id = stmt.column_int64 (offset + 4);
1662- row.default_version_id = stmt.column_int64 (offset + 5);
1663- row.rating = stmt.column_int (offset + 6);
1664- row.md5_sum = stmt.column_text (offset + 7);
1665- }
1666-}
1667-
1668-// Photos table behavior for v17
1669-// v17 split the URI into base_uri and filename (reverting back to the original
1670-// design introduced in v0, albeit with a URI rather than a file system path)
1671-public class FSpotPhotosV17Behavior : FSpotTableBehavior<FSpotPhotoRow>, Object {
1672- private static FSpotPhotosV17Behavior instance;
1673-
1674- private FSpotPhotosV17Behavior () {
1675- }
1676-
1677- public static FSpotPhotosV17Behavior get_instance () {
1678- if (instance == null)
1679- instance = new FSpotPhotosV17Behavior ();
1680- return instance;
1681- }
1682-
1683- public string get_table_name () {
1684- return FSpotPhotosTable.TABLE_NAME;
1685- }
1686-
1687- public string[] list_columns () {
1688- return { "id", "time", "base_uri", "filename", "description", "roll_id",
1689- "default_version_id", "rating", "md5_sum"
1690- };
1691- }
1692-
1693- public void build_row (Sqlite.Statement stmt, out FSpotPhotoRow row, int offset = 0) {
1694- row = new FSpotPhotoRow ();
1695- row.photo_id = stmt.column_int64 (offset + 0);
1696- row.time = (time_t) stmt.column_int64 (offset + 1);
1697-
1698- string? base_path = stmt.column_text (offset + 2);
1699- string? filename = stmt.column_text (offset + 3);
1700- if (base_path != null && filename != null) {
1701- row.base_path = File.new_for_uri (base_path);
1702- row.filename = filename;
1703- }
1704-
1705- row.description = stmt.column_text (offset + 4);
1706- row.roll_id = stmt.column_int64 (offset + 5);
1707- row.default_version_id = stmt.column_int64 (offset + 6);
1708- row.rating = stmt.column_int (offset + 7);
1709- row.md5_sum = stmt.column_text (offset + 8);
1710- }
1711-}
1712-
1713-// v18: no more MD5 hash in the photos table: moved to photo_versions table
1714-public class FSpotPhotosV18Behavior : FSpotTableBehavior<FSpotPhotoRow>, Object {
1715- private static FSpotPhotosV18Behavior instance;
1716-
1717- private FSpotPhotosV18Behavior () {
1718- }
1719-
1720- public static FSpotPhotosV18Behavior get_instance () {
1721- if (instance == null)
1722- instance = new FSpotPhotosV18Behavior ();
1723- return instance;
1724- }
1725-
1726- public string get_table_name () {
1727- return FSpotPhotosTable.TABLE_NAME;
1728- }
1729-
1730- public string[] list_columns () {
1731- return { "id", "time", "base_uri", "filename", "description", "roll_id",
1732- "default_version_id", "rating"
1733- };
1734- }
1735-
1736- public void build_row (Sqlite.Statement stmt, out FSpotPhotoRow row, int offset = 0) {
1737- row = new FSpotPhotoRow ();
1738- row.photo_id = stmt.column_int64 (offset + 0);
1739- row.time = (time_t) stmt.column_int64 (offset + 1);
1740-
1741- string? base_path = stmt.column_text (offset + 2);
1742- string? filename = stmt.column_text (offset + 3);
1743- if (base_path != null && filename != null) {
1744- row.base_path = File.new_for_uri (base_path);
1745- row.filename = filename;
1746- }
1747-
1748- row.description = stmt.column_text (offset + 4);
1749- row.roll_id = stmt.column_int64 (offset + 5);
1750- row.default_version_id = stmt.column_int64 (offset + 6);
1751- row.rating = stmt.column_int (offset + 7);
1752- row.md5_sum = "";
1753- }
1754-}
1755-
1756-}
1757-
1758
1759=== removed file 'plugins/shotwell-data-imports/FSpotRollsTable.vala'
1760--- plugins/shotwell-data-imports/FSpotRollsTable.vala 2014-08-08 21:13:09 +0000
1761+++ plugins/shotwell-data-imports/FSpotRollsTable.vala 1970-01-01 00:00:00 +0000
1762@@ -1,111 +0,0 @@
1763-/* Copyright 2011-2013 Yorba Foundation
1764- *
1765- * This software is licensed under the GNU Lesser General Public License
1766- * (version 2.1 or later). See the COPYING file in this distribution.
1767- */
1768-
1769-namespace DataImports.FSpot.Db {
1770-
1771-/**
1772- * The value object for the "rolls" table, representing a single database row.
1773- */
1774-public class FSpotRollRow : Object {
1775- public int64 id;
1776- public time_t time;
1777-}
1778-
1779-/**
1780- * This class represents the F-Spot rolls table.
1781- */
1782-public class FSpotRollsTable : FSpotDatabaseTable<FSpotRollRow> {
1783- public static const string TABLE_NAME = "Rolls";
1784- public static const string TABLE_NAME_PRE_V5 = "Imports";
1785-
1786- public FSpotRollsTable (Sqlite.Database db, FSpotDatabaseBehavior db_behavior) {
1787- base (db);
1788- set_behavior (db_behavior.get_rolls_behavior ());
1789- }
1790-
1791- public FSpotRollRow? get_by_id (int64 roll_id) throws DatabaseError {
1792- Sqlite.Statement stmt;
1793- FSpotRollRow? row = null;
1794- string column_list = get_joined_column_list ();
1795- string sql = "SELECT %s FROM %s WHERE id=?".printf (column_list, table_name);
1796-
1797- int res = fspot_db.prepare_v2 (sql, -1, out stmt);
1798- if (res != Sqlite.OK)
1799- throw_error ("Statement failed: %s".printf (sql), res);
1800-
1801- res = stmt.bind_int64 (1, roll_id);
1802- if (res != Sqlite.OK)
1803- throw_error ("Bind failed for roll_id", res);
1804-
1805- res = stmt.step ();
1806- if (res == Sqlite.ROW)
1807- behavior.build_row (stmt, out row);
1808- else if (res == Sqlite.DONE)
1809- message ("Could not find roll row with ID %d", (int)roll_id);
1810-
1811- return row;
1812- }
1813-}
1814-
1815-// Rolls table behavior for v0-4
1816-public class FSpotRollsV0Behavior : FSpotTableBehavior<FSpotRollRow>, Object {
1817- private static FSpotRollsV0Behavior instance;
1818-
1819- private FSpotRollsV0Behavior () {
1820- }
1821-
1822- public static FSpotRollsV0Behavior get_instance () {
1823- if (instance == null)
1824- instance = new FSpotRollsV0Behavior ();
1825- return instance;
1826- }
1827-
1828- public string get_table_name () {
1829- return FSpotRollsTable.TABLE_NAME_PRE_V5;
1830- }
1831-
1832- public string[] list_columns () {
1833- return { "id", "time" };
1834- }
1835-
1836- public void build_row (Sqlite.Statement stmt, out FSpotRollRow row, int offset = 0) {
1837- row = new FSpotRollRow ();
1838- row.id = stmt.column_int64 (offset + 0);
1839- row.time = (time_t) stmt.column_int64 (offset + 1);
1840- }
1841-}
1842-
1843-// Rolls table behavior for v5+
1844-// Table name changed from "imports" to "rolls"
1845-public class FSpotRollsV5Behavior : FSpotTableBehavior<FSpotRollRow>, Object {
1846- private static FSpotRollsV5Behavior instance;
1847-
1848- private FSpotRollsV5Behavior () {
1849- }
1850-
1851- public static FSpotRollsV5Behavior get_instance () {
1852- if (instance == null)
1853- instance = new FSpotRollsV5Behavior ();
1854- return instance;
1855- }
1856-
1857- public string get_table_name () {
1858- return FSpotRollsTable.TABLE_NAME;
1859- }
1860-
1861- public string[] list_columns () {
1862- return { "id", "time" };
1863- }
1864-
1865- public void build_row (Sqlite.Statement stmt, out FSpotRollRow row, int offset = 0) {
1866- row = new FSpotRollRow ();
1867- row.id = stmt.column_int64 (offset + 0);
1868- row.time = (time_t) stmt.column_int64 (offset + 1);
1869- }
1870-}
1871-
1872-}
1873-
1874
1875=== removed file 'plugins/shotwell-data-imports/FSpotTableBehavior.vala'
1876--- plugins/shotwell-data-imports/FSpotTableBehavior.vala 2014-08-08 21:13:09 +0000
1877+++ plugins/shotwell-data-imports/FSpotTableBehavior.vala 1970-01-01 00:00:00 +0000
1878@@ -1,28 +0,0 @@
1879-/* Copyright 2011-2013 Yorba Foundation
1880- *
1881- * This software is licensed under the GNU Lesser General Public License
1882- * (version 2.1 or later). See the COPYING file in this distribution.
1883- */
1884-
1885-namespace DataImports.FSpot.Db {
1886-
1887-/**
1888- * This class defines a generic table behavior. In practice, it implements
1889- * the concept of a DAO (Data Access Object) in ORM terms and is responsible
1890- * for transforming the data extracted from a relational statement into a
1891- * lightweight value object.
1892- *
1893- * The type T defined in the generic is the value object type a behavior
1894- * implementation is designed to handle. Value object types are designed to
1895- * contain the data for a single database row.
1896- */
1897-public interface FSpotTableBehavior<T> : Object {
1898- public abstract string get_table_name ();
1899-
1900- public abstract string[] list_columns ();
1901-
1902- public abstract void build_row (Sqlite.Statement stmt, out T row, int offset = 0);
1903-}
1904-
1905-}
1906-
1907
1908=== removed file 'plugins/shotwell-data-imports/FSpotTagsTable.vala'
1909--- plugins/shotwell-data-imports/FSpotTagsTable.vala 2014-08-08 21:13:09 +0000
1910+++ plugins/shotwell-data-imports/FSpotTagsTable.vala 1970-01-01 00:00:00 +0000
1911@@ -1,129 +0,0 @@
1912-/* Copyright 2011-2013 Yorba Foundation
1913- *
1914- * This software is licensed under the GNU Lesser General Public License
1915- * (version 2.1 or later). See the COPYING file in this distribution.
1916- */
1917-
1918-namespace DataImports.FSpot.Db {
1919-
1920-/**
1921- * The value object for the "tags" table, representing a single database row.
1922- */
1923-public class FSpotTagRow : Object {
1924- public int64 tag_id;
1925- public string name;
1926- public int64 category_id;
1927- public bool is_category;
1928- public int sort_priority;
1929- public string stock_icon; // only store stock icons
1930-}
1931-
1932-/**
1933- * This class represents the F-Spot tags table.
1934- */
1935-public class FSpotTagsTable : FSpotDatabaseTable<FSpotTagRow> {
1936- public static const string TABLE_NAME = "Tags";
1937-
1938- public static const string PREFIX_STOCK_ICON = "stock_icon:";
1939- public static const string STOCK_ICON_FAV = "stock_icon:emblem-favorite";
1940- public static const string STOCK_ICON_PEOPLE = "stock_icon:emblem-people";
1941- public static const string STOCK_ICON_PLACES = "stock_icon:emblem-places";
1942- public static const string STOCK_ICON_EVENTS = "stock_icon:emblem-event";
1943-
1944- private FSpotTableBehavior<FSpotPhotoTagRow> photo_tags_behavior;
1945-
1946- public FSpotTagsTable (Sqlite.Database db, FSpotDatabaseBehavior db_behavior) {
1947- base (db);
1948- set_behavior (db_behavior.get_tags_behavior ());
1949- photo_tags_behavior = db_behavior.get_photo_tags_behavior ();
1950- }
1951-
1952- public FSpotTagRow? get_by_id (int64 tag_id) throws DatabaseError {
1953- Sqlite.Statement stmt;
1954- FSpotTagRow? row = null;
1955- string column_list = get_joined_column_list ();
1956- string sql = "SELECT %s FROM %s WHERE id=?".printf (column_list, table_name);
1957-
1958- int res = fspot_db.prepare_v2 (sql, -1, out stmt);
1959- if (res != Sqlite.OK)
1960- throw_error ("Statement failed: %s".printf (sql), res);
1961-
1962- res = stmt.bind_int64 (1, tag_id);
1963- assert (res == Sqlite.OK);
1964-
1965- res = stmt.step ();
1966- if (res == Sqlite.ROW)
1967- behavior.build_row (stmt, out row);
1968- else if (res == Sqlite.DONE)
1969- message ("Could not find tag row with ID %d", (int)tag_id);
1970-
1971- return row;
1972- }
1973-
1974- public Gee.ArrayList<FSpotTagRow> get_by_photo_id (int64 photo_id) throws DatabaseError {
1975- Gee.ArrayList<FSpotTagRow> rows = new Gee.ArrayList < FSpotTagRow?> ();
1976-
1977- Sqlite.Statement stmt;
1978-
1979- string column_list = get_joined_column_list (true);
1980- string sql = "SELECT %1$s FROM %2$s, %3$s WHERE %3$s.photo_id=? AND %3$s.tag_id = %2$s.id".printf (
1981- column_list, table_name, photo_tags_behavior.get_table_name ()
1982- );
1983-
1984- int res = fspot_db.prepare_v2 (sql, -1, out stmt);
1985- if (res != Sqlite.OK)
1986- throw_error ("Statement failed: %s".printf (sql), res);
1987-
1988- res = stmt.bind_int64 (1, photo_id);
1989- if (res != Sqlite.OK)
1990- throw_error ("Bind failed for photo_id", res);
1991-
1992- res = stmt.step ();
1993- while (res == Sqlite.ROW) {
1994- FSpotTagRow row;
1995- behavior.build_row (stmt, out row);
1996- rows.add (row);
1997- res = stmt.step ();
1998- }
1999-
2000- return rows;
2001- }
2002-}
2003-
2004-public class FSpotTagsV0Behavior : FSpotTableBehavior<FSpotTagRow>, Object {
2005- private static FSpotTagsV0Behavior instance;
2006-
2007- private FSpotTagsV0Behavior () {
2008- }
2009-
2010- public static FSpotTagsV0Behavior get_instance () {
2011- if (instance == null)
2012- instance = new FSpotTagsV0Behavior ();
2013- return instance;
2014- }
2015-
2016- public string get_table_name () {
2017- return FSpotTagsTable.TABLE_NAME;
2018- }
2019-
2020- public string[] list_columns () {
2021- return { "id", "name", "category_id", "is_category", "sort_priority", "icon" };
2022- }
2023-
2024- public void build_row (Sqlite.Statement stmt, out FSpotTagRow row, int offset = 0) {
2025- row = new FSpotTagRow ();
2026- row.tag_id = stmt.column_int64 (offset + 0);
2027- row.name = stmt.column_text (offset + 1);
2028- row.category_id = stmt.column_int64 (offset + 2);
2029- row.is_category = (stmt.column_int (offset + 3) > 0);
2030- row.sort_priority = stmt.column_int (offset + 4);
2031- string icon_str = stmt.column_text (offset + 5);
2032- if (icon_str != null && icon_str.has_prefix (FSpotTagsTable.PREFIX_STOCK_ICON))
2033- row.stock_icon = icon_str;
2034- else
2035- row.stock_icon = "";
2036- }
2037-}
2038-
2039-}
2040-
2041
2042=== removed file 'plugins/shotwell-data-imports/Makefile'
2043--- plugins/shotwell-data-imports/Makefile 2013-04-25 00:53:04 +0000
2044+++ plugins/shotwell-data-imports/Makefile 1970-01-01 00:00:00 +0000
2045@@ -1,30 +0,0 @@
2046-
2047-PLUGIN := shotwell-data-imports
2048-
2049-PLUGIN_PKGS := \
2050- gtk+-3.0 \
2051- gexiv2 \
2052- gee-0.8 \
2053- sqlite3
2054-
2055-SRC_FILES := \
2056- shotwell-data-imports.vala \
2057- ../common/VersionNumber.vala \
2058- ../common/SqliteSupport.vala \
2059- FSpotImporter.vala \
2060- FSpotDatabaseBehavior.vala \
2061- FSpotDatabase.vala \
2062- FSpotDatabaseTable.vala \
2063- FSpotTableBehavior.vala \
2064- FSpotMetaTable.vala \
2065- FSpotPhotosTable.vala \
2066- FSpotPhotoTagsTable.vala \
2067- FSpotPhotoVersionsTable.vala \
2068- FSpotRollsTable.vala \
2069- FSpotTagsTable.vala
2070-
2071-RC_FILES := \
2072- f-spot-24.png
2073-
2074-include ../Makefile.plugin.mk
2075-
2076
2077=== removed file 'plugins/shotwell-data-imports/f-spot-24.png'
2078Binary files plugins/shotwell-data-imports/f-spot-24.png 2012-02-02 22:56:06 +0000 and plugins/shotwell-data-imports/f-spot-24.png 1970-01-01 00:00:00 +0000 differ
2079=== removed file 'plugins/shotwell-data-imports/shotwell-data-imports.vala'
2080--- plugins/shotwell-data-imports/shotwell-data-imports.vala 2014-08-08 21:13:09 +0000
2081+++ plugins/shotwell-data-imports/shotwell-data-imports.vala 1970-01-01 00:00:00 +0000
2082@@ -1,46 +0,0 @@
2083-/* Copyright 2011-2013 Yorba Foundation
2084- *
2085- * This software is licensed under the GNU Lesser General Public License
2086- * (version 2.1 or later). See the COPYING file in this distribution.
2087- */
2088-
2089-extern const string _VERSION;
2090-
2091-// "core services" are: F-Spot
2092-private class ShotwellDataImportsCoreServices : Object, Spit.Module {
2093- private Spit.Pluggable[] pluggables = new Spit.Pluggable[0];
2094-
2095- // we need to get a module file handle because our pluggables have to load resources from the
2096- // module file directory
2097- public ShotwellDataImportsCoreServices (GLib.File module_file) {
2098- GLib.File resource_directory = module_file.get_parent ();
2099-
2100- pluggables += new FSpotService (resource_directory);
2101- }
2102-
2103- public unowned string get_module_name () {
2104- return _ ("Core Data Import Services");
2105- }
2106-
2107- public unowned string get_version () {
2108- return _VERSION;
2109- }
2110-
2111- public unowned string get_id () {
2112- return "org.yorba.shotwell.data_imports.core_services";
2113- }
2114-
2115- public unowned Spit.Pluggable[]? get_pluggables () {
2116- return pluggables;
2117- }
2118-}
2119-
2120-// This entry point is required for all SPIT modules.
2121-public Spit.Module? spit_entry_point (Spit.EntryPointParams *params) {
2122- params->module_spit_interface = Spit.negotiate_interfaces (params->host_min_spit_interface,
2123- params->host_max_spit_interface, Spit.CURRENT_INTERFACE);
2124-
2125- return (params->module_spit_interface != Spit.UNSUPPORTED_INTERFACE)
2126- ? new ShotwellDataImportsCoreServices (params->module_file) : null;
2127-}
2128-
2129
2130=== modified file 'src/Dialogs.vala'
2131--- src/Dialogs.vala 2014-08-20 20:14:47 +0000
2132+++ src/Dialogs.vala 2014-08-28 06:03:26 +0000
2133@@ -1884,12 +1884,10 @@
2134 Gtk.Box import_content;
2135 Gtk.Box import_action_checkbox_packer;
2136 Gtk.Box external_import_action_checkbox_packer;
2137- Spit.DataImports.WelcomeImportMetaHost import_meta_host;
2138 bool import_content_already_installed = false;
2139 bool ok_clicked = false;
2140
2141 public WelcomeDialog (Gtk.Window owner) {
2142- import_meta_host = new Spit.DataImports.WelcomeImportMetaHost (this);
2143 bool show_system_pictures_import = is_system_pictures_import_possible ();
2144 Gtk.Widget ok_button = add_button (_ ("_Close"), Gtk.ResponseType.OK);
2145 set_title (_ ("Welcome!"));
2146@@ -1966,8 +1964,6 @@
2147 ok_button.grab_focus ();
2148
2149 install_import_content ();
2150-
2151- import_meta_host.start ();
2152 }
2153
2154 private void install_import_content () {
2155@@ -2498,4 +2494,4 @@
2156 progress.close ();
2157
2158 AppWindow.get_instance ().set_normal_cursor ();
2159-}
2160\ No newline at end of file
2161+}
2162
2163=== removed directory 'src/data_imports'
2164=== removed file 'src/data_imports/DataImportJob.vala'
2165--- src/data_imports/DataImportJob.vala 2014-08-08 21:13:09 +0000
2166+++ src/data_imports/DataImportJob.vala 1970-01-01 00:00:00 +0000
2167@@ -1,177 +0,0 @@
2168-/* Copyright 2009-2013 Yorba Foundation
2169- *
2170- * This software is licensed under the GNU LGPL (version 2.1 or later).
2171- * See the COPYING file in this distribution.
2172- */
2173-
2174-namespace Spit.DataImports {
2175-
2176-/**
2177- * A specialized import job implementation for alien databases.
2178- */
2179-public class DataImportJob : BatchImportJob {
2180- private DataImportSource import_source;
2181- private File? src_file;
2182- private uint64 filesize;
2183- private time_t exposure_time;
2184- private DataImportJob? associated = null;
2185- private HierarchicalTagIndex? detected_htags = null;
2186-
2187- public DataImportJob (DataImportSource import_source) {
2188- this.import_source = import_source;
2189-
2190- // stash everything called in prepare (), as it may/will be called from a separate thread
2191- src_file = import_source.get_file ();
2192- filesize = import_source.get_filesize ();
2193- exposure_time = import_source.get_exposure_time ();
2194- }
2195-
2196- private HierarchicalTagIndex? build_exclusion_index (ImportableTag[] src_tags) {
2197- Gee.Set<string> detected_htags = new Gee.HashSet<string> ();
2198-
2199- foreach (ImportableTag src_tag in src_tags) {
2200- string? prepped = HierarchicalTagUtilities.join_path_components (
2201- Tag.prep_tag_names (
2202- build_path_components (src_tag)
2203- )
2204- );
2205-
2206- if (prepped != null && prepped.has_prefix (Tag.PATH_SEPARATOR_STRING)) {
2207- detected_htags.add (prepped);
2208-
2209- Gee.List<string> parents = HierarchicalTagUtilities.enumerate_parent_paths (prepped);
2210- foreach (string parent in parents)
2211- detected_htags.add (parent);
2212- }
2213- }
2214-
2215- return (detected_htags.size > 0) ? HierarchicalTagIndex.from_paths (detected_htags) : null;
2216- }
2217-
2218- public time_t get_exposure_time () {
2219- return exposure_time;
2220- }
2221-
2222- public override string get_dest_identifier () {
2223- return import_source.get_filename ();
2224- }
2225-
2226- public override string get_source_identifier () {
2227- return import_source.get_filename ();
2228- }
2229-
2230- public override bool is_directory () {
2231- return false;
2232- }
2233-
2234- public override string get_basename () {
2235- return src_file.get_basename ();
2236- }
2237-
2238- public override string get_path () {
2239- return src_file.get_parent ().get_path ();
2240- }
2241-
2242- public override void set_associated (BatchImportJob associated) {
2243- this.associated = associated as DataImportJob;
2244- }
2245-
2246- public override bool determine_file_size (out uint64 filesize, out File file) {
2247- file = null;
2248- filesize = this.filesize;
2249-
2250- return true;
2251- }
2252-
2253- public override bool prepare (out File file_to_import, out bool copy_to_library) throws Error {
2254- file_to_import = src_file;
2255- copy_to_library = false;
2256-
2257- detected_htags = build_exclusion_index (import_source.get_photo ().get_tags ());
2258-
2259- return true;
2260- }
2261-
2262- public override bool complete (MediaSource source, BatchImportRoll import_roll) throws Error {
2263- LibraryPhoto? photo = source as LibraryPhoto;
2264- if (photo == null)
2265- return false;
2266-
2267- ImportableMediaItem src_photo = import_source.get_photo ();
2268-
2269- // tags
2270- if (detected_htags != null) {
2271- Gee.Collection<string> paths = detected_htags.get_all_paths ();
2272-
2273- foreach (string path in paths)
2274- Tag.for_path (path);
2275- }
2276-
2277- ImportableTag[] src_tags = src_photo.get_tags ();
2278- foreach (ImportableTag src_tag in src_tags) {
2279- string? prepped = HierarchicalTagUtilities.join_path_components (
2280- Tag.prep_tag_names (
2281- build_path_components (src_tag)
2282- )
2283- );
2284- if (prepped != null) {
2285- if (HierarchicalTagUtilities.enumerate_path_components (prepped).size == 1) {
2286- if (prepped.has_prefix (Tag.PATH_SEPARATOR_STRING))
2287- prepped = HierarchicalTagUtilities.hierarchical_to_flat (prepped);
2288- } else {
2289- Gee.List<string> parents =
2290- HierarchicalTagUtilities.enumerate_parent_paths (prepped);
2291-
2292- assert (parents.size > 0);
2293-
2294- string top_level_parent = parents.get (0);
2295- string flat_top_level_parent =
2296- HierarchicalTagUtilities.hierarchical_to_flat (top_level_parent);
2297-
2298- if (Tag.global.exists (flat_top_level_parent))
2299- Tag.for_path (flat_top_level_parent).promote ();
2300- }
2301-
2302- Tag.for_path (prepped).attach (photo);
2303- }
2304- }
2305- // event
2306- ImportableEvent? src_event = src_photo.get_event ();
2307- if (src_event != null) {
2308- string? prepped = prepare_input_text (src_event.get_name (),
2309- PrepareInputTextOptions.DEFAULT, -1);
2310- if (prepped != null)
2311- Event.generate_single_event (photo, import_roll.generated_events, prepped);
2312- }
2313- // rating
2314- Rating dst_rating;
2315- ImportableRating src_rating = src_photo.get_rating ();
2316- if (src_rating.is_rejected ())
2317- dst_rating = Rating.REJECTED;
2318- else if (src_rating.is_unrated ())
2319- dst_rating = Rating.UNRATED;
2320- else
2321- dst_rating = Rating.unserialize (src_rating.get_value ());
2322- photo.set_rating (dst_rating);
2323- // title
2324- string? title = src_photo.get_title ();
2325- if (title != null)
2326- photo.set_title (title);
2327- // import ID
2328- photo.set_import_id (import_roll.import_id);
2329-
2330- return true;
2331- }
2332-
2333- private string[] build_path_components (ImportableTag tag) {
2334- // use a linked list as we are always inserting in head position
2335- Gee.List<string> components = new Gee.LinkedList<string> ();
2336- for (ImportableTag current_tag = tag; current_tag != null; current_tag = current_tag.get_parent ()) {
2337- components.insert (0, HierarchicalTagUtilities.make_flat_tag_safe (current_tag.get_name ()));
2338- }
2339- return components.to_array ();
2340- }
2341-}
2342-
2343-}
2344-
2345
2346=== removed file 'src/data_imports/DataImportSource.vala'
2347--- src/data_imports/DataImportSource.vala 2014-08-08 21:13:09 +0000
2348+++ src/data_imports/DataImportSource.vala 1970-01-01 00:00:00 +0000
2349@@ -1,135 +0,0 @@
2350-/* Copyright 2011-2013 Yorba Foundation
2351- *
2352- * This software is licensed under the GNU Lesser General Public License
2353- * (version 2.1 or later). See the COPYING file in this distribution.
2354- */
2355-
2356-namespace Spit.DataImports {
2357-
2358-/**
2359- * Photo source implementation for alien databases. This class is responsible
2360- * for extracting meta-data out of a source photo to support the import
2361- * process.
2362- *
2363- * This class does not extend PhotoSource in order to minimise the API to the
2364- * absolute minimum required to run the import job.
2365- */
2366-public class DataImportSource {
2367- private bool backing_file_found;
2368- private ImportableMediaItem db_photo;
2369- private string? title = null;
2370- private string? preview_md5 = null;
2371- private uint64 file_size;
2372- private time_t modification_time;
2373- private MetadataDateTime? exposure_time;
2374-
2375- public DataImportSource (ImportableMediaItem db_photo) {
2376- this.db_photo = db_photo;
2377-
2378- // A well-behaved plugin will ensure that the path and file name are
2379- // not null but we check just in case
2380- string folder_path = db_photo.get_folder_path ();
2381- string filename = db_photo.get_filename ();
2382- File? photo = null;
2383- if (folder_path != null && filename != null) {
2384- photo = File.new_for_path (db_photo.get_folder_path ()).
2385- get_child (db_photo.get_filename ());
2386-
2387- backing_file_found = photo.query_exists ();
2388- } else {
2389- backing_file_found = false;
2390- }
2391-
2392- if (photo != null && backing_file_found) {
2393- PhotoMetadata? metadata = new PhotoMetadata ();
2394- try {
2395- metadata.read_from_file (photo);
2396- } catch (Error e) {
2397- warning ("Could not get file metadata for %s: %s", get_filename (), e.message);
2398- metadata = null;
2399- }
2400-
2401- title = (metadata != null) ? metadata.get_title () : null;
2402- exposure_time = (metadata != null) ? metadata.get_exposure_date_time () : null;
2403- PhotoPreview ? preview = metadata != null ? metadata.get_preview (0) : null;
2404- if (preview != null) {
2405- try {
2406- uint8[] preview_raw = preview.flatten ();
2407- preview_md5 = md5_binary (preview_raw, preview_raw.length);
2408- } catch (Error e) {
2409- warning ("Could not get raw preview for %s: %s", get_filename (), e.message);
2410- }
2411- }
2412-#if TRACE_MD5
2413- debug ("Photo MD5 %s: preview=%s", get_filename (), preview_md5);
2414-#endif
2415-
2416- try {
2417- file_size = query_total_file_size (photo);
2418- } catch (Error e) {
2419- warning ("Could not get file size for %s: %s", get_filename (), e.message);
2420- }
2421- try {
2422- modification_time = query_file_modified (photo);
2423- } catch (Error e) {
2424- warning ("Could not get modification time for %s: %s", get_filename (), e.message);
2425- }
2426- } else {
2427- debug ("Photo file %s not found".printf (photo.get_path ()));
2428- }
2429- }
2430-
2431- public string get_filename () {
2432- return db_photo.get_filename ();
2433- }
2434-
2435- public string get_fulldir () {
2436- return db_photo.get_folder_path ();
2437- }
2438-
2439- public File get_file () {
2440- return File.new_for_path (get_fulldir ()).get_child (get_filename ());
2441- }
2442-
2443- public string get_name () {
2444- return !is_string_empty (title) ? title : get_filename ();
2445- }
2446-
2447- public string? get_title () {
2448- return title;
2449- }
2450-
2451- public PhotoFileFormat get_file_format () {
2452- return PhotoFileFormat.get_by_basename_extension (get_filename ());
2453- }
2454-
2455- public string to_string () {
2456- return get_name ();
2457- }
2458-
2459- public time_t get_exposure_time () {
2460- return (exposure_time != null) ? exposure_time.get_timestamp () : modification_time;
2461- }
2462-
2463- public uint64 get_filesize () {
2464- return file_size;
2465- }
2466-
2467- public ImportableMediaItem get_photo () {
2468- return db_photo;
2469- }
2470-
2471- public bool is_already_imported () {
2472- // ignore trashed duplicates
2473- return (preview_md5 != null)
2474- ? LibraryPhoto.has_nontrash_duplicate (null, preview_md5, null, get_file_format ())
2475- : false;
2476- }
2477-
2478- public bool was_backing_file_found () {
2479- return backing_file_found;
2480- }
2481-}
2482-
2483-}
2484-
2485
2486=== removed file 'src/data_imports/DataImports.vala'
2487--- src/data_imports/DataImports.vala 2014-08-08 21:13:09 +0000
2488+++ src/data_imports/DataImports.vala 1970-01-01 00:00:00 +0000
2489@@ -1,30 +0,0 @@
2490-/* Copyright 2011-2013 Yorba Foundation
2491- *
2492- * This software is licensed under the GNU Lesser General Public License
2493- * (version 2.1 or later). See the COPYING file in this distribution.
2494- */
2495-
2496-/* This file is the master unit file for the DataImports unit. It should be edited to include
2497- * whatever code is deemed necessary.
2498- *
2499- * The init () and terminate () methods are mandatory.
2500- *
2501- * If the unit needs to be configured prior to initialization, add the proper parameters to
2502- * the preconfigure () method, implement it, and ensure in init () that it's been called.
2503- */
2504-
2505-namespace DataImports {
2506-
2507-public void init () throws Error {
2508- string[] core_ids = new string[0];
2509- core_ids += "org.yorba.shotwell.dataimports.fspot";
2510-
2511- Plugins.register_extension_point (typeof (Spit.DataImports.Service), _ ("Data Imports"),
2512- Resources.IMPORT, core_ids);
2513-}
2514-
2515-public void terminate () {
2516-}
2517-
2518-}
2519-
2520
2521=== removed file 'src/data_imports/DataImportsPluginHost.vala'
2522--- src/data_imports/DataImportsPluginHost.vala 2014-08-08 21:13:09 +0000
2523+++ src/data_imports/DataImportsPluginHost.vala 1970-01-01 00:00:00 +0000
2524@@ -1,483 +0,0 @@
2525-/* Copyright 2011-2013 Yorba Foundation
2526- *
2527- * This software is licensed under the GNU Lesser General Public License
2528- * (version 2.1 or later). See the COPYING file in this distribution.
2529- */
2530-
2531-namespace Spit.DataImports {
2532-
2533-private class CoreImporter {
2534- private weak Spit.DataImports.PluginHost host;
2535- public int imported_items_count = 0;
2536- public BatchImportRoll? current_import_roll = null;
2537-
2538- public CoreImporter (Spit.DataImports.PluginHost host) {
2539- this.host = host;
2540- }
2541-
2542- public void prepare_media_items_for_import (
2543- ImportableMediaItem[] items,
2544- double progress,
2545- double host_progress_delta = 0.0,
2546- string? progress_message = null
2547- ) {
2548- host.update_import_progress_pane (progress, progress_message);
2549- //
2550- SortedList<DataImportJob> jobs =
2551- new SortedList<DataImportJob> (import_job_comparator);
2552- Gee.ArrayList<DataImportJob> already_imported =
2553- new Gee.ArrayList<DataImportJob> ();
2554- Gee.ArrayList<DataImportJob> failed =
2555- new Gee.ArrayList<DataImportJob> ();
2556-
2557- int item_idx = 0;
2558- double item_progress_delta = host_progress_delta / items.length;
2559- foreach (ImportableMediaItem src_item in items) {
2560- DataImportSource import_source = new DataImportSource (src_item);
2561-
2562- if (!import_source.was_backing_file_found ()) {
2563- message ("Skipping import of %s: backing file not found",
2564- import_source.get_filename ());
2565- failed.add (new DataImportJob (import_source));
2566-
2567- continue;
2568- }
2569-
2570- if (import_source.is_already_imported ()) {
2571- message ("Skipping import of %s: checksum detected in library",
2572- import_source.get_filename ());
2573- already_imported.add (new DataImportJob (import_source));
2574-
2575- continue;
2576- }
2577-
2578- jobs.add (new DataImportJob (import_source));
2579- item_idx++;
2580- host.update_import_progress_pane (progress + item_idx * item_progress_delta);
2581- }
2582-
2583- if (jobs.size > 0) {
2584- // If there it no current import roll, create one to ensure that all
2585- // imported items end up in the same roll even if this method is called
2586- // several times
2587- if (current_import_roll == null)
2588- current_import_roll = new BatchImportRoll ();
2589- string db_name = _ ("%s Database").printf (host.get_data_importer ().get_service ().get_pluggable_name ());
2590- BatchImport batch_import = new BatchImport (jobs, db_name, data_import_reporter,
2591- failed, already_imported, null, current_import_roll);
2592-
2593- LibraryWindow.get_app ().enqueue_batch_import (batch_import, true);
2594- imported_items_count += jobs.size;
2595- }
2596-
2597- host.update_import_progress_pane (progress + host_progress_delta);
2598- }
2599-
2600- public void finalize_import () {
2601- // Send an empty job to the queue to mark the end of the import
2602- string db_name = _ ("%s Database").printf (host.get_data_importer ().get_service ().get_pluggable_name ());
2603- BatchImport batch_import = new BatchImport (
2604- new Gee.ArrayList<BatchImportJob> (), db_name, data_import_reporter, null, null, null, current_import_roll
2605- );
2606- LibraryWindow.get_app ().enqueue_batch_import (batch_import, true);
2607- current_import_roll = null;
2608- }
2609-}
2610-
2611-public class ConcreteDataImportsHost : Plugins.StandardHostInterface,
2612- Spit.DataImports.PluginHost {
2613-
2614- private Spit.DataImports.DataImporter active_importer = null;
2615- private weak DataImportsUI.DataImportsDialog dialog = null;
2616- private DataImportsUI.ProgressPane? progress_pane = null;
2617- private bool importing_halted = false;
2618- private CoreImporter core_importer;
2619-
2620- public ConcreteDataImportsHost (Service service, DataImportsUI.DataImportsDialog dialog) {
2621- base (service, "data_imports");
2622- this.dialog = dialog;
2623-
2624- this.active_importer = service.create_data_importer (this);
2625- this.core_importer = new CoreImporter (this);
2626- }
2627-
2628- public DataImporter get_data_importer () {
2629- return active_importer;
2630- }
2631-
2632- public void start_importing () {
2633- if (get_data_importer ().is_running ())
2634- return;
2635-
2636- debug ("ConcreteDataImportsHost.start_importing( ): invoked.");
2637-
2638- get_data_importer ().start ();
2639- }
2640-
2641- public void stop_importing () {
2642- debug ("ConcreteDataImportsHost.stop_importing( ): invoked.");
2643-
2644- if (get_data_importer ().is_running ())
2645- get_data_importer ().stop ();
2646-
2647- clean_up ();
2648-
2649- importing_halted = true;
2650- }
2651-
2652- private void clean_up () {
2653- progress_pane = null;
2654- }
2655-
2656- public void set_button_mode (Spit.DataImports.PluginHost.ButtonMode mode) {
2657- if (mode == Spit.DataImports.PluginHost.ButtonMode.CLOSE)
2658- dialog.set_close_button_mode ();
2659- else if (mode == Spit.DataImports.PluginHost.ButtonMode.CANCEL)
2660- dialog.set_cancel_button_mode ();
2661- else
2662- error ("unrecognized button mode enumeration value");
2663- }
2664-
2665- // Pane handling methods
2666-
2667- public void post_error (Error err) {
2668- post_error_message (err.message);
2669- }
2670-
2671- public void post_error_message (string message) {
2672- string msg = _ ("Importing from %s can't continue because an error occurred:").printf (
2673- active_importer.get_service ().get_pluggable_name ());
2674- msg += GLib.Markup.printf_escaped ("\n\n<i>%s</i>\n\n", message);
2675- msg += _ ("To try importing from another service, select one from the above menu.");
2676-
2677- dialog.install_pane (new DataImportsUI.StaticMessagePane.with_pango (msg));
2678- dialog.set_close_button_mode ();
2679- dialog.unlock_service ();
2680-
2681- get_data_importer ().stop ();
2682-
2683- // post_error_message( ) tells the active_importer to stop importing and displays a
2684- // non-removable error pane that effectively ends the publishing interaction,
2685- // so no problem calling clean_up( ) here.
2686- clean_up ();
2687- }
2688-
2689- public void install_dialog_pane (Spit.DataImports.DialogPane pane,
2690- Spit.DataImports.PluginHost.ButtonMode button_mode = Spit.DataImports.PluginHost.ButtonMode.CANCEL) {
2691- debug ("DataImports.PluginHost: install_dialog_pane( ): invoked.");
2692-
2693- if (get_data_importer () == null || (!get_data_importer ().is_running ()))
2694- return;
2695-
2696- dialog.install_pane (pane);
2697-
2698- set_button_mode (button_mode);
2699- }
2700-
2701- public void install_static_message_pane (string message,
2702- Spit.DataImports.PluginHost.ButtonMode button_mode = Spit.DataImports.PluginHost.ButtonMode.CANCEL) {
2703-
2704- set_button_mode (button_mode);
2705-
2706- dialog.install_pane (new DataImportsUI.StaticMessagePane.with_pango (message));
2707- }
2708-
2709- public void install_library_selection_pane (
2710- string welcome_message,
2711- ImportableLibrary[] discovered_libraries,
2712- string? file_select_label
2713- ) {
2714- if (discovered_libraries.length == 0 && file_select_label == null)
2715- post_error_message ("Libraries or file option needed");
2716- else
2717- dialog.install_pane (new DataImportsUI.LibrarySelectionPane (
2718- this,
2719- welcome_message,
2720- discovered_libraries,
2721- file_select_label
2722- ));
2723- set_button_mode (Spit.DataImports.PluginHost.ButtonMode.CLOSE);
2724- }
2725-
2726- public void install_import_progress_pane (
2727- string message
2728- ) {
2729- progress_pane = new DataImportsUI.ProgressPane (message);
2730- dialog.install_pane (progress_pane);
2731- set_button_mode (Spit.DataImports.PluginHost.ButtonMode.CANCEL);
2732- // initialize the import
2733- core_importer.imported_items_count = 0;
2734- core_importer.current_import_roll = null;
2735- }
2736-
2737- public void update_import_progress_pane (
2738- double progress,
2739- string? progress_message = null
2740- ) {
2741- if (progress_pane != null) {
2742- progress_pane.update_progress (progress, progress_message);
2743- }
2744- }
2745-
2746- public void prepare_media_items_for_import (
2747- ImportableMediaItem[] items,
2748- double progress,
2749- double host_progress_delta = 0.0,
2750- string? progress_message = null
2751- ) {
2752- core_importer.prepare_media_items_for_import (items, progress, host_progress_delta, progress_message);
2753- }
2754-
2755- public void finalize_import (
2756- ImportedItemsCountCallback report_imported_items_count,
2757- string? finalize_message = null
2758- ) {
2759- update_import_progress_pane (1.0, finalize_message);
2760- set_button_mode (Spit.DataImports.PluginHost.ButtonMode.CLOSE);
2761- core_importer.finalize_import ();
2762- report_imported_items_count (core_importer.imported_items_count);
2763- if (core_importer.imported_items_count > 0)
2764- LibraryWindow.get_app ().switch_to_import_queue_page ();
2765- }
2766-}
2767-
2768-public class WelcomeDataImportsHost : Plugins.StandardHostInterface,
2769- Spit.DataImports.PluginHost {
2770-
2771- private weak WelcomeImportMetaHost meta_host;
2772- private Spit.DataImports.DataImporter active_importer = null;
2773- private bool importing_halted = false;
2774- private CoreImporter core_importer;
2775-
2776- public WelcomeDataImportsHost (Service service, WelcomeImportMetaHost meta_host) {
2777- base (service, "data_imports");
2778-
2779- this.active_importer = service.create_data_importer (this);
2780- this.core_importer = new CoreImporter (this);
2781- this.meta_host = meta_host;
2782- }
2783-
2784- public DataImporter get_data_importer () {
2785- return active_importer;
2786- }
2787-
2788- public void start_importing () {
2789- if (get_data_importer ().is_running ())
2790- return;
2791-
2792- debug ("WelcomeDataImportsHost.start_importing( ): invoked.");
2793-
2794- get_data_importer ().start ();
2795- }
2796-
2797- public void stop_importing () {
2798- debug ("WelcomeDataImportsHost.stop_importing( ): invoked.");
2799-
2800- if (get_data_importer ().is_running ())
2801- get_data_importer ().stop ();
2802-
2803- clean_up ();
2804-
2805- importing_halted = true;
2806- }
2807-
2808- private void clean_up () {
2809- }
2810-
2811- // Pane handling methods
2812-
2813- public void post_error (Error err) {
2814- post_error_message (err.message);
2815- }
2816-
2817- public void post_error_message (string message) {
2818- string msg = _ ("Importing from %s can't continue because an error occurred:").printf (
2819- active_importer.get_service ().get_pluggable_name ());
2820-
2821- debug (msg);
2822-
2823- get_data_importer ().stop ();
2824-
2825- // post_error_message( ) tells the active_importer to stop importing and displays a
2826- // non-removable error pane that effectively ends the publishing interaction,
2827- // so no problem calling clean_up( ) here.
2828- clean_up ();
2829- }
2830-
2831- public void install_dialog_pane (Spit.DataImports.DialogPane pane,
2832- Spit.DataImports.PluginHost.ButtonMode button_mode = Spit.DataImports.PluginHost.ButtonMode.CANCEL) {
2833- // do nothing
2834- }
2835-
2836- public void install_static_message_pane (string message,
2837- Spit.DataImports.PluginHost.ButtonMode button_mode = Spit.DataImports.PluginHost.ButtonMode.CANCEL) {
2838- // do nothing
2839- }
2840-
2841- public void install_library_selection_pane (
2842- string welcome_message,
2843- ImportableLibrary[] discovered_libraries,
2844- string? file_select_label
2845- ) {
2846- debug ("WelcomeDataImportsHost: Installing library selection pane for %s".printf (get_data_importer ().get_service ().get_pluggable_name ()));
2847- if (discovered_libraries.length > 0) {
2848- meta_host.install_service_entry (new WelcomeImportServiceEntry (
2849- this,
2850- get_data_importer ().get_service ().get_pluggable_name (),
2851- discovered_libraries
2852- ));
2853- }
2854- }
2855-
2856- public void install_import_progress_pane (
2857- string message
2858- ) {
2859- // empty implementation
2860- }
2861-
2862- public void update_import_progress_pane (
2863- double progress,
2864- string? progress_message = null
2865- ) {
2866- // empty implementation
2867- }
2868-
2869- public void prepare_media_items_for_import (
2870- ImportableMediaItem[] items,
2871- double progress,
2872- double host_progress_delta = 0.0,
2873- string? progress_message = null
2874- ) {
2875- core_importer.prepare_media_items_for_import (items, progress, host_progress_delta, progress_message);
2876- }
2877-
2878- public void finalize_import (
2879- ImportedItemsCountCallback report_imported_items_count,
2880- string? finalize_message = null
2881- ) {
2882- core_importer.finalize_import ();
2883- report_imported_items_count (core_importer.imported_items_count);
2884- meta_host.finalize_import (this);
2885- }
2886-}
2887-
2888-
2889-//public delegate void WelcomeImporterCallback ();
2890-
2891-public class WelcomeImportServiceEntry : GLib.Object, WelcomeServiceEntry {
2892- private string pluggable_name;
2893- private ImportableLibrary[] discovered_libraries;
2894- private Spit.DataImports.PluginHost host;
2895-
2896- public WelcomeImportServiceEntry (
2897- Spit.DataImports.PluginHost host,
2898- string pluggable_name, ImportableLibrary[] discovered_libraries) {
2899-
2900- this.host = host;
2901- this.pluggable_name = pluggable_name;
2902- this.discovered_libraries = discovered_libraries;
2903- }
2904-
2905- public string get_service_name () {
2906- return pluggable_name;
2907- }
2908-
2909- public void execute () {
2910- foreach (ImportableLibrary library in discovered_libraries) {
2911- host.get_data_importer ().on_library_selected (library);
2912- }
2913- }
2914-}
2915-
2916-public class WelcomeImportMetaHost : GLib.Object {
2917- private WelcomeDialog dialog;
2918-
2919- public WelcomeImportMetaHost (WelcomeDialog dialog) {
2920- this.dialog = dialog;
2921- }
2922-
2923- public void start () {
2924- Service[] services = load_all_services ();
2925- foreach (Service service in services) {
2926- WelcomeDataImportsHost host = new WelcomeDataImportsHost (service, this);
2927- host.start_importing ();
2928- }
2929- }
2930-
2931- public void finalize_import (WelcomeDataImportsHost host) {
2932- host.stop_importing ();
2933- }
2934-
2935- public void install_service_entry (WelcomeServiceEntry entry) {
2936- debug ("WelcomeImportMetaHost: Installing service entry for %s".printf (entry.get_service_name ()));
2937- dialog.install_service_entry (entry);
2938- }
2939-}
2940-
2941-public static Spit.DataImports.Service[] load_all_services () {
2942- return load_services (true);
2943-}
2944-
2945-public static Spit.DataImports.Service[] load_services (bool load_all = false) {
2946- Spit.DataImports.Service[] loaded_services = new Spit.DataImports.Service[0];
2947-
2948- // load publishing services from plug-ins
2949- Gee.Collection<Spit.Pluggable> pluggables = Plugins.get_pluggables_for_type (
2950- typeof (Spit.DataImports.Service), null, load_all);
2951- // TODO: include sorting function to ensure consistent order
2952-
2953- debug ("DataImportsDialog: discovered %d pluggable data import services.", pluggables.size);
2954-
2955- foreach (Spit.Pluggable pluggable in pluggables) {
2956- int pluggable_interface = pluggable.get_pluggable_interface (
2957- Spit.DataImports.CURRENT_INTERFACE, Spit.DataImports.CURRENT_INTERFACE);
2958- if (pluggable_interface != Spit.DataImports.CURRENT_INTERFACE) {
2959- warning ("Unable to load data import plugin %s: reported interface %d.",
2960- Plugins.get_pluggable_module_id (pluggable), pluggable_interface);
2961-
2962- continue;
2963- }
2964-
2965- Spit.DataImports.Service service =
2966- (Spit.DataImports.Service) pluggable;
2967-
2968- debug ("DataImportsDialog: discovered pluggable data import service '%s'.",
2969- service.get_pluggable_name ());
2970-
2971- loaded_services += service;
2972- }
2973-
2974- // Sort import services by name.
2975- // TODO: extract to a function to sort it on initial request
2976- Posix.qsort (loaded_services, loaded_services.length, sizeof (Spit.DataImports.Service),
2977- (a, b) => {
2978- return utf8_cs_compare ((* ((Spit.DataImports.Service **) a))->get_pluggable_name (),
2979- (* ((Spit.DataImports.Service **) b))->get_pluggable_name ());
2980- });
2981-
2982- return loaded_services;
2983-}
2984-
2985-private ImportManifest? meta_manifest = null;
2986-
2987-private void data_import_reporter (ImportManifest manifest, BatchImportRoll import_roll) {
2988- if (manifest.all.size > 0) {
2989- if (meta_manifest == null)
2990- meta_manifest = new ImportManifest ();
2991- foreach (BatchImportResult result in manifest.all) {
2992- meta_manifest.add_result (result);
2993- }
2994- } else {
2995- DataImportsUI.DataImportsDialog.terminate_instance ();
2996- ImportUI.report_manifest (meta_manifest, true);
2997- meta_manifest = null;
2998- }
2999-}
3000-
3001-private int64 import_job_comparator (void *a, void *b) {
3002- return ((DataImportJob *) a)->get_exposure_time ()
3003- - ((DataImportJob *) b)->get_exposure_time ();
3004-}
3005-
3006-}
3007-
3008
3009=== removed file 'src/data_imports/DataImportsUI.vala'
3010--- src/data_imports/DataImportsUI.vala 2014-08-08 21:13:09 +0000
3011+++ src/data_imports/DataImportsUI.vala 1970-01-01 00:00:00 +0000
3012@@ -1,445 +0,0 @@
3013-/* Copyright 2011-2013 Yorba Foundation
3014- *
3015- * This software is licensed under the GNU Lesser General Public License
3016- * (version 2.1 or later). See the COPYING file in this distribution.
3017- */
3018-
3019-namespace DataImportsUI {
3020-
3021-internal const string NO_PLUGINS_ENABLED_MESSAGE =
3022- _ ("You do not have any data imports plugins enabled.\n\nIn order to use the Import From Application functionality, you need to have at least one data imports plugin enabled. Plugins can be enabled in the Preferences dialog.");
3023-
3024-public class ConcreteDialogPane : Spit.DataImports.DialogPane, GLib.Object {
3025- private Gtk.Box pane_widget;
3026-
3027- public ConcreteDialogPane () {
3028- pane_widget = new Gtk.Box (Gtk.Orientation.VERTICAL, 8);
3029- }
3030-
3031- public Gtk.Widget get_widget () {
3032- return pane_widget;
3033- }
3034-
3035- public Spit.DataImports.DialogPane.GeometryOptions get_preferred_geometry () {
3036- return Spit.DataImports.DialogPane.GeometryOptions.NONE;
3037- }
3038-
3039- public void on_pane_installed () {
3040- }
3041-
3042- public void on_pane_uninstalled () {
3043- }
3044-}
3045-
3046-public class StaticMessagePane : ConcreteDialogPane {
3047- public StaticMessagePane (string message_string) {
3048- Gtk.Label message_label = new Gtk.Label (message_string);
3049- (get_widget () as Gtk.Box).pack_start (message_label, true, true, 0);
3050- }
3051-
3052- public StaticMessagePane.with_pango (string msg) {
3053- Gtk.Label label = new Gtk.Label (null);
3054- label.set_markup (msg);
3055- label.set_line_wrap (true);
3056-
3057- (get_widget () as Gtk.Box).pack_start (label, true, true, 0);
3058- }
3059-}
3060-
3061-public class LibrarySelectionPane : ConcreteDialogPane {
3062- private weak Spit.DataImports.PluginHost host;
3063- private Spit.DataImports.ImportableLibrary? selected_library = null;
3064- private File? selected_file = null;
3065- private Gtk.Button import_button;
3066- private Gtk.RadioButton? file_radio = null;
3067-
3068- public LibrarySelectionPane (
3069- Spit.DataImports.PluginHost host,
3070- string welcome_message,
3071- Spit.DataImports.ImportableLibrary[] discovered_libraries,
3072- string? file_select_label
3073- ) {
3074- assert (discovered_libraries.length > 0 || on_file_selected != null);
3075-
3076- this.host = host;
3077-
3078- Gtk.Box content_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 8);
3079- content_box.set_margin_left (30);
3080- content_box.set_margin_right (30);
3081- Gtk.Label welcome_label = new Gtk.Label (null);
3082- welcome_label.set_markup (welcome_message);
3083- welcome_label.set_line_wrap (true);
3084- welcome_label.set_halign (Gtk.Align.START);
3085- content_box.pack_start (welcome_label, true, true, 6);
3086-
3087- // margins for buttons
3088- int radio_margin_left = 20;
3089- int radio_margin_right = 20;
3090- int chooser_margin_left = radio_margin_left;
3091- int chooser_margin_right = radio_margin_right;
3092-
3093- Gtk.RadioButton lib_radio = null;
3094- if (discovered_libraries.length > 0) {
3095- chooser_margin_left = radio_margin_left + 20;
3096- foreach (Spit.DataImports.ImportableLibrary library in discovered_libraries) {
3097- string lib_radio_label = library.get_display_name ();
3098- lib_radio = create_radio_button (
3099- content_box, lib_radio, library, lib_radio_label,
3100- radio_margin_left, radio_margin_right
3101- );
3102- }
3103- if (file_select_label != null) {
3104- lib_radio = create_radio_button (
3105- content_box, lib_radio, null, file_select_label,
3106- radio_margin_left, radio_margin_right
3107- );
3108- file_radio = lib_radio;
3109- }
3110- }
3111- if (file_select_label != null) {
3112- Gtk.FileChooserButton file_chooser = new Gtk.FileChooserButton (_ ("Database file:"), Gtk.FileChooserAction.OPEN);
3113- file_chooser.selection_changed.connect ( () => {
3114- selected_file = file_chooser.get_file ();
3115- if (file_radio != null)
3116- file_radio.active = true;
3117- set_import_button_sensitivity ();
3118- });
3119- file_chooser.set_margin_left (chooser_margin_left);
3120- file_chooser.set_margin_right (chooser_margin_right);
3121- content_box.pack_start (file_chooser, false, false, 6);
3122- }
3123-
3124- import_button = new Gtk.Button.with_mnemonic (_ ("_Import"));
3125- import_button.clicked.connect ( () => {
3126- if (selected_library != null)
3127- on_library_selected (selected_library);
3128- else if (selected_file != null)
3129- on_file_selected (selected_file);
3130- else
3131- debug ("LibrarySelectionPane: Library or file should be selected.");
3132- });
3133- Gtk.ButtonBox button_box = new Gtk.ButtonBox (Gtk.Orientation.HORIZONTAL);
3134- button_box.layout_style = Gtk.ButtonBoxStyle.CENTER;
3135- button_box.add (import_button);
3136- content_box.pack_end (button_box, true, false, 6);
3137-
3138- (get_widget () as Gtk.Box).pack_start (content_box, true, true, 0);
3139-
3140- set_import_button_sensitivity ();
3141- }
3142-
3143- private Gtk.RadioButton create_radio_button (
3144- Gtk.Box box, Gtk.RadioButton? group, Spit.DataImports.ImportableLibrary? library, string label,
3145- int margin_left, int margin_right
3146- ) {
3147- var button = new Gtk.RadioButton.with_label_from_widget (group, label);
3148- if (group == null) { // first radio button is active
3149- button.active = true;
3150- selected_library = library;
3151- }
3152- button.toggled.connect ( () => {
3153- if (button.active) {
3154- this.selected_library = library;
3155- set_import_button_sensitivity ();
3156- }
3157-
3158- });
3159- button.set_margin_left (margin_left);
3160- button.set_margin_right (margin_right);
3161- box.pack_start (button, false, false, 6);
3162- return button;
3163- }
3164-
3165- private void set_import_button_sensitivity () {
3166- import_button.set_sensitive (selected_library != null || selected_file != null);
3167- }
3168-
3169- private void on_library_selected (Spit.DataImports.ImportableLibrary library) {
3170- host.get_data_importer ().on_library_selected (library);
3171- }
3172-
3173- private void on_file_selected (File file) {
3174- host.get_data_importer ().on_file_selected (file);
3175- }
3176-}
3177-
3178-public class ProgressPane : ConcreteDialogPane {
3179- private Gtk.Label message_label;
3180- private Gtk.Label progress_label;
3181- private Gtk.ProgressBar progress_bar;
3182-
3183- public ProgressPane (string message) {
3184- Gtk.Box content_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 8);
3185- message_label = new Gtk.Label (message);
3186- content_box.pack_start (message_label, true, true, 6);
3187- progress_bar = new Gtk.ProgressBar ();
3188- content_box.pack_start (progress_bar, false, true, 6);
3189- progress_label = new Gtk.Label ("");
3190- content_box.pack_start (progress_label, false, true, 6);
3191-
3192- (get_widget () as Gtk.Container).add (content_box);
3193- }
3194-
3195- public void update_progress (double progress, string? progress_message) {
3196- progress_bar.set_fraction (progress);
3197- if (progress_message != null)
3198- progress_label.set_label (progress_message);
3199- spin_event_loop ();
3200- }
3201-}
3202-
3203-public class DataImportsDialog : Gtk.Dialog {
3204- private const int LARGE_WINDOW_WIDTH = 860;
3205- private const int LARGE_WINDOW_HEIGHT = 688;
3206- private const int COLOSSAL_WINDOW_WIDTH = 1024;
3207- private const int COLOSSAL_WINDOW_HEIGHT = 688;
3208- private const int STANDARD_WINDOW_WIDTH = 600;
3209- private const int STANDARD_WINDOW_HEIGHT = 510;
3210- private const int BORDER_REGION_WIDTH = 16;
3211- private const int BORDER_REGION_HEIGHT = 100;
3212-
3213- public const int STANDARD_CONTENT_LABEL_WIDTH = 500;
3214- public const int STANDARD_ACTION_BUTTON_WIDTH = 128;
3215-
3216- private Gtk.ComboBoxText service_selector_box;
3217- private Gtk.Label service_selector_box_label;
3218- private Gtk.Box central_area_layouter;
3219- private Gtk.Button close_cancel_button;
3220- private Spit.DataImports.DialogPane active_pane;
3221- private Spit.DataImports.ConcreteDataImportsHost host;
3222-
3223- protected DataImportsDialog () {
3224-
3225- resizable = false;
3226- delete_event.connect (on_window_close);
3227-
3228- string title = _ ("Import From Application");
3229- string label = _ ("Import media _from:");
3230-
3231- set_title (title);
3232-
3233- Spit.DataImports.Service[] loaded_services = Spit.DataImports.load_services ();
3234-
3235- if (loaded_services.length > 0) {
3236- // Install the service selector part only if there is at least one
3237- // service to select from
3238- service_selector_box = new Gtk.ComboBoxText ();
3239- service_selector_box.set_active (0);
3240- service_selector_box_label = new Gtk.Label.with_mnemonic (label);
3241- service_selector_box_label.set_mnemonic_widget (service_selector_box);
3242- service_selector_box_label.set_alignment (0.0f, 0.5f);
3243-
3244- // get the name of the service the user last used
3245- string? last_used_service = Config.Facade.get_instance ().get_last_used_dataimports_service ();
3246-
3247- int ticker = 0;
3248- int last_used_index = -1;
3249- foreach (Spit.DataImports.Service service in loaded_services) {
3250- string curr_service_id = service.get_id ();
3251- if (last_used_service != null && last_used_service == curr_service_id)
3252- last_used_index = ticker;
3253-
3254- service_selector_box.append_text (service.get_pluggable_name ());
3255- ticker++;
3256- }
3257- if (last_used_index >= 0)
3258- service_selector_box.set_active (last_used_index);
3259- else
3260- service_selector_box.set_active (0);
3261-
3262- service_selector_box.changed.connect (on_service_changed);
3263-
3264- /* the wrapper is not an extraneous widget -- it's necessary to prevent the service
3265- selection box from growing and shrinking whenever its parent's size changes.
3266- When wrapped inside a Gtk.Alignment, the Alignment grows and shrinks instead of
3267- the service selection box. */
3268- Gtk.Alignment service_selector_box_wrapper = new Gtk.Alignment (1.0f, 0.5f, 0.0f, 0.0f);
3269- service_selector_box_wrapper.add (service_selector_box);
3270-
3271- Gtk.Box service_selector_layouter = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 8);
3272- service_selector_layouter.set_border_width (12);
3273- service_selector_layouter.add (service_selector_box_label);
3274- service_selector_layouter.pack_start (service_selector_box_wrapper, true, true, 0);
3275-
3276- /* 'service area' is the selector assembly plus the horizontal rule dividing it from the
3277- rest of the dialog */
3278- Gtk.Box service_area_layouter = new Gtk.Box (Gtk.Orientation.VERTICAL, 0);
3279- service_area_layouter.pack_start (service_selector_layouter, true, true, 0);
3280- Gtk.Separator service_central_separator = new Gtk.Separator (Gtk.Orientation.HORIZONTAL);
3281- service_area_layouter.add (service_central_separator);
3282-
3283- Gtk.Alignment service_area_wrapper = new Gtk.Alignment (0.0f, 0.0f, 1.0f, 0.0f);
3284- service_area_wrapper.add (service_area_layouter);
3285-
3286- ((Gtk.Box) get_content_area ()).pack_start (service_area_wrapper, false, false, 0);
3287- }
3288-
3289- // Intall the central area in all cases
3290- central_area_layouter = new Gtk.Box (Gtk.Orientation.VERTICAL, 0);
3291- ((Gtk.Box) get_content_area ()).pack_start (central_area_layouter, true, true, 0);
3292-
3293- close_cancel_button = new Gtk.Button.with_mnemonic ("_Cancel");
3294- close_cancel_button.set_can_default (true);
3295- close_cancel_button.clicked.connect (on_close_cancel_clicked);
3296- ((Gtk.Box) get_action_area ()).add (close_cancel_button);
3297-
3298- set_standard_window_mode ();
3299-
3300- if (loaded_services.length > 0) {
3301- // trigger the selected service if at least one service is available
3302- on_service_changed ();
3303- } else {
3304- // otherwise, install a message pane advising the user what to do
3305- install_pane (new StaticMessagePane.with_pango (NO_PLUGINS_ENABLED_MESSAGE));
3306- set_close_button_mode ();
3307- }
3308-
3309- show_all ();
3310- }
3311-
3312- public static DataImportsDialog get_or_create_instance () {
3313- if (instance == null) {
3314- instance = new DataImportsDialog ();
3315- }
3316- return instance;
3317- }
3318-
3319- public static void terminate_instance () {
3320- if (instance != null) {
3321- instance.terminate ();
3322- }
3323- instance = null;
3324- }
3325-
3326- private bool on_window_close (Gdk.EventAny evt) {
3327- debug ("DataImportsDialog: on_window_close( ): invoked.");
3328- terminate ();
3329-
3330- return true;
3331- }
3332-
3333- private void on_service_changed () {
3334- debug ("DataImportsDialog: on_service_changed invoked.");
3335- string service_name = service_selector_box.get_active_text ();
3336-
3337- Spit.DataImports.Service? selected_service = null;
3338- Spit.DataImports.Service[] services = Spit.DataImports.load_all_services ();
3339- foreach (Spit.DataImports.Service service in services) {
3340- if (service.get_pluggable_name () == service_name) {
3341- selected_service = service;
3342- break;
3343- }
3344- }
3345- assert (selected_service != null);
3346-
3347- Config.Facade.get_instance ().set_last_used_dataimports_service (selected_service.get_id ());
3348-
3349- host = new Spit.DataImports.ConcreteDataImportsHost (selected_service, this);
3350- host.start_importing ();
3351- }
3352-
3353- private void on_close_cancel_clicked () {
3354- debug ("DataImportsDialog: on_close_cancel_clicked( ): invoked.");
3355-
3356- terminate ();
3357- }
3358-
3359- private void terminate () {
3360- debug ("DataImportsDialog: terminate( ): invoked.");
3361-
3362- if (host != null) {
3363- host.stop_importing ();
3364- host = null;
3365- }
3366-
3367- hide ();
3368- destroy ();
3369- instance = null;
3370- }
3371-
3372- private void set_large_window_mode () {
3373- set_size_request (LARGE_WINDOW_WIDTH, LARGE_WINDOW_HEIGHT);
3374- central_area_layouter.set_size_request (LARGE_WINDOW_WIDTH - BORDER_REGION_WIDTH,
3375- LARGE_WINDOW_HEIGHT - BORDER_REGION_HEIGHT);
3376- resizable = false;
3377- }
3378-
3379- private void set_colossal_window_mode () {
3380- set_size_request (COLOSSAL_WINDOW_WIDTH, COLOSSAL_WINDOW_HEIGHT);
3381- central_area_layouter.set_size_request (COLOSSAL_WINDOW_WIDTH - BORDER_REGION_WIDTH,
3382- COLOSSAL_WINDOW_HEIGHT - BORDER_REGION_HEIGHT);
3383- resizable = false;
3384- }
3385-
3386- private void set_standard_window_mode () {
3387- set_size_request (STANDARD_WINDOW_WIDTH, STANDARD_WINDOW_HEIGHT);
3388- central_area_layouter.set_size_request (STANDARD_WINDOW_WIDTH - BORDER_REGION_WIDTH,
3389- STANDARD_WINDOW_HEIGHT - BORDER_REGION_HEIGHT);
3390- resizable = false;
3391- }
3392-
3393- private void set_free_sizable_window_mode () {
3394- resizable = true;
3395- }
3396-
3397- private void clear_free_sizable_window_mode () {
3398- resizable = false;
3399- }
3400-
3401- public Spit.DataImports.DialogPane get_active_pane () {
3402- return active_pane;
3403- }
3404-
3405- public void set_close_button_mode () {
3406- close_cancel_button.set_label (_ ("_Close"));
3407- set_default (close_cancel_button);
3408- }
3409-
3410- public void set_cancel_button_mode () {
3411- close_cancel_button.set_label (_ ("_Cancel"));
3412- }
3413-
3414- public void lock_service () {
3415- service_selector_box.set_sensitive (false);
3416- }
3417-
3418- public void unlock_service () {
3419- service_selector_box.set_sensitive (true);
3420- }
3421-
3422- public void install_pane (Spit.DataImports.DialogPane pane) {
3423- debug ("DataImportsDialog: install_pane( ): invoked.");
3424-
3425- if (active_pane != null) {
3426- debug ("DataImportsDialog: install_pane( ): a pane is already installed; removing it.");
3427-
3428- active_pane.on_pane_uninstalled ();
3429- central_area_layouter.remove (active_pane.get_widget ());
3430- }
3431-
3432- central_area_layouter.pack_start (pane.get_widget (), true, true, 0);
3433- show_all ();
3434-
3435- Spit.DataImports.DialogPane.GeometryOptions geometry_options =
3436- pane.get_preferred_geometry ();
3437- if ((geometry_options & Spit.Publishing.DialogPane.GeometryOptions.EXTENDED_SIZE) != 0)
3438- set_large_window_mode ();
3439- else if ((geometry_options & Spit.Publishing.DialogPane.GeometryOptions.COLOSSAL_SIZE) != 0)
3440- set_colossal_window_mode ();
3441- else
3442- set_standard_window_mode ();
3443-
3444- if ((geometry_options & Spit.Publishing.DialogPane.GeometryOptions.RESIZABLE) != 0)
3445- set_free_sizable_window_mode ();
3446- else
3447- clear_free_sizable_window_mode ();
3448-
3449- active_pane = pane;
3450- pane.on_pane_installed ();
3451- }
3452-
3453- private static DataImportsDialog? instance;
3454-}
3455-
3456-}
3457-
3458
3459=== removed directory 'src/data_imports/mk'
3460=== removed file 'src/data_imports/mk/data_imports.mk'
3461--- src/data_imports/mk/data_imports.mk 2012-02-02 22:56:06 +0000
3462+++ src/data_imports/mk/data_imports.mk 1970-01-01 00:00:00 +0000
3463@@ -1,31 +0,0 @@
3464-
3465-# UNIT_NAME is the Vala namespace. A file named UNIT_NAME.vala must be in this directory with
3466-# a init() and terminate() function declared in the namespace.
3467-UNIT_NAME := DataImports
3468-
3469-# UNIT_DIR should match the subdirectory the files are located in. Generally UNIT_NAME in all
3470-# lowercase. The name of this file should be UNIT_DIR.mk.
3471-UNIT_DIR := data_imports
3472-
3473-# All Vala files in the unit should be listed here with no subdirectory prefix.
3474-#
3475-# NOTE: Do *not* include the unit's master file, i.e. UNIT_NAME.vala.
3476-UNIT_FILES := \
3477- DataImportsPluginHost.vala \
3478- DataImportsUI.vala \
3479- DataImportJob.vala \
3480- DataImportSource.vala
3481-
3482-# Any unit this unit relies upon (and should be initialized before it's initialized) should
3483-# be listed here using its Vala namespace.
3484-#
3485-# NOTE: All units are assumed to rely upon the unit-unit. Do not include that here.
3486-UNIT_USES :=
3487-
3488-# List any additional files that are used in the build process as a part of this unit that should
3489-# be packaged in the tarball. File names should be relative to the unit's home directory.
3490-UNIT_RC :=
3491-
3492-# unitize.mk must be called at the end of each UNIT_DIR.mk file.
3493-include unitize.mk
3494-
3495
3496=== modified file 'src/library/LibraryWindow.vala'
3497--- src/library/LibraryWindow.vala 2014-08-28 03:37:44 +0000
3498+++ src/library/LibraryWindow.vala 2014-08-28 06:03:26 +0000
3499@@ -288,13 +288,6 @@
3500 import.tooltip = _ ("Import photos from disk to library");
3501 actions += import;
3502
3503- Gtk.ActionEntry import_from_external = {
3504- "ExternalLibraryImport", Resources.IMPORT, TRANSLATABLE,
3505- null, TRANSLATABLE, on_external_library_import
3506- };
3507- import_from_external.label = _ ("Import From _Application...");
3508- actions += import_from_external;
3509-
3510 Gtk.ActionEntry sort = { "CommonSortEvents", null, TRANSLATABLE, null, null, null };
3511 sort.label = _ ("Sort _Events");
3512 actions += sort;
3513@@ -667,12 +660,6 @@
3514 import_dialog.destroy ();
3515 }
3516
3517- private void on_external_library_import () {
3518- Gtk.Dialog import_dialog = DataImportsUI.DataImportsDialog.get_or_create_instance ();
3519-
3520- import_dialog.run ();
3521- }
3522-
3523 protected override void update_common_action_availability (Page? old_page, Page? new_page) {
3524 base.update_common_action_availability (old_page, new_page);
3525
3526
3527=== modified file 'src/library/mk/library.mk'
3528--- src/library/mk/library.mk 2014-08-28 03:37:44 +0000
3529+++ src/library/mk/library.mk 2014-08-28 06:03:26 +0000
3530@@ -41,8 +41,7 @@
3531 Events \
3532 Tags \
3533 Camera \
3534- Searches \
3535- DataImports
3536+ Searches
3537
3538 # List any additional files that are used in the build process as a part of this unit that should
3539 # be packaged in the tarball. File names should be relative to the unit's home directory.
3540
3541=== removed file 'src/plugins/DataImportsInterfaces.vala'
3542--- src/plugins/DataImportsInterfaces.vala 2014-08-08 21:13:09 +0000
3543+++ src/plugins/DataImportsInterfaces.vala 1970-01-01 00:00:00 +0000
3544@@ -1,489 +0,0 @@
3545-/* Copyright 2011-2013 Yorba Foundation
3546- *
3547- * This software is licensed under the GNU Lesser General Public License
3548- * (version 2.1 or later). See the COPYING file in this distribution.
3549- */
3550-
3551-/**
3552- * Shotwell Pluggable Data Imports API
3553- *
3554- * The Shotwell Pluggable Data Imports API allows you to write plugins that import
3555- * information from other media library databases to help migration to Shotwell.
3556- * The Shotwell distribution includes import support for F-Spot.
3557- * To enable Shotwell to import from additional libaries, developers like you write
3558- * data import plugins, dynamically-loadable shared objects that are linked into the
3559- * Shotwell process at runtime. Data import plugins are just one of several kinds of
3560- * plugins supported by {@link Spit}, the Shotwell Pluggable Interfaces Technology.
3561- */
3562-namespace Spit.DataImports {
3563-
3564-/**
3565- * The current version of the Pluggable Data Import API
3566- */
3567-public const int CURRENT_INTERFACE = 0;
3568-
3569-/**
3570- * The error domain for alien databases
3571- */
3572-public errordomain DataImportError {
3573- /**
3574- * Indicates that the version of the external database being imported is
3575- * not supported by this version of the plugin.
3576- *
3577- * This occurs for example when trying to import an F-Spot database that
3578- * has a version that is more recent than what the current plugin supports.
3579- */
3580- UNSUPPORTED_VERSION
3581-}
3582-
3583-/**
3584- * Represents a module that is able to import data from a specific database format.
3585- *
3586- * Developers of data import plugins provide a class that implements this interface. At
3587- * any given time, only one DataImporter can be running. When a data importer is running, it
3588- * has exclusive use of the shared user-interface and
3589- * configuration services provided by the {@link PluginHost}. Data importers are created in
3590- * a non-running state and do not begin running until start( ) is invoked. Data importers
3591- * run until stop( ) is invoked.
3592- */
3593-public interface DataImporter : GLib.Object {
3594- /**
3595- * Returns a {@link Service} object describing the service to which this connects.
3596- */
3597- public abstract Service get_service ();
3598-
3599- /**
3600- * Makes this data importer enter the running state and endows it with exclusive access
3601- * to the shared services provided by the {@link PluginHost}. Through the host’s interface,
3602- * this data importer can install user interface panes and query configuration information.
3603- */
3604- public abstract void start ();
3605-
3606- /**
3607- * Returns true if this data importer is in the running state; false otherwise.
3608- */
3609- public abstract bool is_running ();
3610-
3611- /**
3612- * Causes this data importer to enter a non-running state. This data importer should stop all
3613- * data access operations and cease use of the shared services provided by the {@link PluginHost}.
3614- */
3615- public abstract void stop ();
3616-
3617- /**
3618- * Causes this data importer to enter start the import of a library.
3619- */
3620- public abstract void on_library_selected (ImportableLibrary library);
3621-
3622- /**
3623- * Causes this data importer to enter start the import of a library file.
3624- */
3625- public abstract void on_file_selected (File file);
3626-
3627- //
3628- // For future expansion.
3629- //
3630- protected virtual void reserved0 () {}
3631- protected virtual void reserved1 () {}
3632- protected virtual void reserved2 () {}
3633- protected virtual void reserved3 () {}
3634- protected virtual void reserved4 () {}
3635- protected virtual void reserved5 () {}
3636- protected virtual void reserved6 () {}
3637- protected virtual void reserved7 () {}
3638-}
3639-
3640-/**
3641- * Represents a library of importable media items.
3642- *
3643- * Developers of data import plugins provide a class that implements this interface.
3644- */
3645-public interface ImportableLibrary : GLib.Object {
3646- public abstract string get_display_name ();
3647-}
3648-
3649-/**
3650- * Represents an importable media item such as a photo or a video file.
3651- *
3652- * Developers of data import plugins provide a class that implements this interface.
3653- */
3654-public interface ImportableMediaItem : GLib.Object {
3655- public abstract ImportableTag[] get_tags ();
3656-
3657- public abstract ImportableEvent? get_event ();
3658-
3659- public abstract ImportableRating get_rating ();
3660-
3661- public abstract string? get_title ();
3662-
3663- public abstract string get_folder_path ();
3664-
3665- public abstract string get_filename ();
3666-}
3667-
3668-/**
3669- * Represents an importable tag.
3670- *
3671- * Developers of data import plugins provide a class that implements this interface.
3672- */
3673-public interface ImportableTag : GLib.Object {
3674- public abstract string get_name ();
3675-
3676- public abstract ImportableTag? get_parent ();
3677-}
3678-
3679-/**
3680- * Represents an importable event.
3681- *
3682- * Developers of data import plugins provide a class that implements this interface.
3683- */
3684-public interface ImportableEvent : GLib.Object {
3685- public abstract string get_name ();
3686-}
3687-
3688-/**
3689- * Represents an importable rating value.
3690- *
3691- * Developers of data import plugins provide a class that implements this interface.
3692- * Note that the value returned by the get_value method should be a value between
3693- * 1 and 5, unless the rating object is unrated or rejected, in which case the
3694- * value is unspecified.
3695- */
3696-public interface ImportableRating : GLib.Object {
3697- public abstract bool is_unrated ();
3698-
3699- public abstract bool is_rejected ();
3700-
3701- public abstract int get_value ();
3702-}
3703-
3704-/**
3705- * Encapsulates a pane that can be installed in the on-screen import dialog box to
3706- * communicate status to and to get information from the user.
3707- *
3708- */
3709-public interface DialogPane : GLib.Object {
3710-
3711- /**
3712- * Describes how the on-screen publishing dialog box should look and behave when an associated
3713- * pane is installed in the on-screen publishing dialog box.
3714- */
3715- public enum GeometryOptions {
3716-
3717- /**
3718- * When the associated pane is installed, the on-screen publishing dialog box will be
3719- * sized normally and will not allow the user to change its size.
3720- */
3721- NONE = 0,
3722-
3723- /**
3724- * If this bit is set, when the associated pane is installed, the on-screen publishing
3725- * dialog box will grow to a larger size.
3726- */
3727- EXTENDED_SIZE = 1 << 0,
3728-
3729- /**
3730- * If this bit is set, when the associated pane is installed, the on-screen publishing
3731- * dialog box will allow the user to change its size.
3732- */
3733- RESIZABLE = 1 << 1,
3734-
3735- /**
3736- * If this bit is set, when the associated pane is installed, the on-screen publishing
3737- * dialog box will grow to accommodate a full-width 1024 pixel web page. If both
3738- * EXTENDED_SIZE and COLOSSAL_SIZE are set, EXTENDED_SIZE takes precedence.
3739- */
3740- COLOSSAL_SIZE = 1 << 2;
3741- }
3742-
3743- /**
3744- * Returns the Gtk.Widget that is this pane's on-screen representation.
3745- */
3746- public abstract Gtk.Widget get_widget ();
3747-
3748- /**
3749- * Returns a {@link GeometryOptions} bitfield describing how the on-screen publishing dialog
3750- * box should look and behave when this pane is installed.
3751- */
3752- public abstract GeometryOptions get_preferred_geometry ();
3753-
3754- /**
3755- * Invoked automatically by Shotwell when this pane has been installed into the on-screen
3756- * publishing dialog box and become visible to the user.
3757- */
3758- public abstract void on_pane_installed ();
3759-
3760- /**
3761- * Invoked automatically by Shotwell when this pane has been removed from the on-screen
3762- * publishing dialog box and is no longer visible to the user.
3763- */
3764- public abstract void on_pane_uninstalled ();
3765-
3766- //
3767- // For future expansion.
3768- //
3769- protected virtual void reserved0 () {}
3770- protected virtual void reserved1 () {}
3771- protected virtual void reserved2 () {}
3772- protected virtual void reserved3 () {}
3773- protected virtual void reserved4 () {}
3774- protected virtual void reserved5 () {}
3775- protected virtual void reserved6 () {}
3776- protected virtual void reserved7 () {}
3777-}
3778-
3779-/**
3780- * Called by the data imports system at the end of an import batch to report
3781- * to the plugin the number of items that were really imported. This enables
3782- * the plugin to display a final message to the user. However, the plugin
3783- * should not rely on this callback being called in order to clean up.
3784- */
3785-public delegate void ImportedItemsCountCallback (int imported_items_count);
3786-
3787-/**
3788- * Manages and provides services for data import plugins.
3789- *
3790- * Implemented inside Shotwell, the PluginHost provides an interface through which the
3791- * developers of data import plugins can query and make changes to the import
3792- * environment. Plugins can use the services of the PluginHost only when their
3793- * {@link DataImporter} is in the running state. This ensures that non-running data importers
3794- * don’t destructively interfere with the actively running importer.
3795- */
3796-public interface PluginHost : GLib.Object, Spit.HostInterface {
3797-
3798- /**
3799- * Specifies the label text on the push button control that appears in the
3800- * lower-right-hand corner of the on-screen publishing dialog box.
3801- */
3802- public enum ButtonMode {
3803- CLOSE = 0,
3804- CANCEL = 1
3805- }
3806-
3807- /**
3808- * Notifies the user that an unrecoverable import error has occurred and halts
3809- * the import process.
3810- *
3811- * @param err An error object that describes the kind of error that occurred.
3812- */
3813- public abstract void post_error (Error err);
3814-
3815- /**
3816- * Notifies the user that an unrecoverable import error has occurred and halts
3817- * the import process.
3818- *
3819- * @param msg A message that describes the kind of error that occurred.
3820- */
3821- public abstract void post_error_message (string msg);
3822-
3823- /**
3824- * Starts the import process.
3825- *
3826- * Calling this method starts the import activity for this host.
3827- */
3828- public abstract void start_importing ();
3829-
3830- /**
3831- * Halts the import process.
3832- *
3833- * Calling this method stops all import activity and hides the on-screen import
3834- * dialog box.
3835- */
3836- public abstract void stop_importing ();
3837-
3838- /**
3839- * Returns a reference to the {@link DataImporter} object that this is currently hosting.
3840- */
3841- public abstract DataImporter get_data_importer ();
3842-
3843- /**
3844- * Attempts to install a pane in the on-screen data import dialog box, making the pane visible
3845- * and allowing it to interact with the user.
3846- *
3847- * If an error has posted, the {@link PluginHost} will not honor this request.
3848- *
3849- * @param pane the pane to install
3850- *
3851- * @param mode allows you to set the text displayed on the close/cancel button in the
3852- * lower-right-hand corner of the on-screen data import dialog box when pane is installed.
3853- * If mode is ButtonMode.CLOSE, the button will have the title "Close." If mode is
3854- * ButtonMode.CANCEL, the button will be titled "Cancel." You should set mode depending on
3855- * whether a cancellable action is in progress. For example, if your importer is in the
3856- * middle of processing 3 of 8 videos, then mode should be ButtonMode.CANCEL. However, if
3857- * the processing operation has completed and the success pane is displayed, then mode
3858- * should be ButtonMode.CLOSE, because all cancellable actions have already
3859- * occurred.
3860- */
3861- public abstract void install_dialog_pane (Spit.DataImports.DialogPane pane,
3862- ButtonMode mode = ButtonMode.CANCEL);
3863-
3864- /**
3865- * Attempts to install a pane in the on-screen data import dialog box that contains
3866- * static text.
3867- *
3868- * The text appears centered in the data import dialog box and is drawn in
3869- * the system font. This is a convenience method only; similar results could be
3870- * achieved by manually constructing a Gtk.Label widget, wrapping it inside a
3871- * {@link DialogPane}, and installing it manually with a call to
3872- * install_dialog_pane( ). To provide visual consistency across data import services,
3873- * however, always use this convenience method instead of constructing label panes when
3874- * you need to display static text to the user.
3875- *
3876- * If an error has posted, the {@link PluginHost} will not honor this request.
3877- *
3878- * @param message the text to show in the pane
3879- *
3880- * @param mode allows you to set the text displayed on the close/cancel button in the
3881- * lower-right-hand corner of the on-screen data import dialog box when pane is installed.
3882- * If mode is ButtonMode.CLOSE, the button will have the title "Close." If mode is
3883- * ButtonMode.CANCEL, the button will be titled "Cancel." You should set mode depending on
3884- * whether a cancellable action is in progress. For example, if your importer is in the
3885- * middle of processing 3 of 8 videos, then mode should be ButtonMode.CANCEL. However, if
3886- * the processing operation has completed and the success pane is displayed, then mode
3887- * should be ButtonMode.CLOSE, because all cancellable actions have already
3888- * occurred.
3889- */
3890- public abstract void install_static_message_pane (string message,
3891- ButtonMode mode = ButtonMode.CANCEL);
3892-
3893- /**
3894- * Attempts to install a library selection pane that presents a list of
3895- * discovered libraries to the user.
3896- *
3897- * When the user clicks the “OK” button, you’ll be notified of the user’s action through
3898- * the 'on_library_selected' callback if a discovered library was selected or through
3899- * the 'on_file_selected' callback if a file was selected.
3900- *
3901- * If an error has posted, the {@link PluginHost} will not honor this request.
3902- *
3903- * @param welcome_message the text to be displayed above the list of discovered
3904- * libraries.
3905- *
3906- * @param discovered_libraries the list of importable libraries that the plugin
3907- * has discovered in well known locations.
3908- *
3909- * @param file_select_label the label to display for the file selection
3910- * option. If this label is null, the
3911- * user will not be presented with a file selection option.
3912- */
3913- public abstract void install_library_selection_pane (
3914- string welcome_message,
3915- ImportableLibrary[] discovered_libraries,
3916- string? file_select_label
3917- );
3918-
3919- /**
3920- * Attempts to install a progress pane that provides the user with feedback
3921- * on import preparation.
3922- *
3923- * If an error has posted, the {@link PluginHost} will not honor this request.
3924- *
3925- * @param message the text to be displayed above the progress bar.
3926- */
3927- public abstract void install_import_progress_pane (
3928- string message
3929- );
3930-
3931- /**
3932- * Update the progress bar installed by install_import_progress_pane.
3933- *
3934- * If an error has posted, the {@link PluginHost} will not honor this request.
3935- *
3936- * @param progress a value between 0.0 and 1.0 identifying progress for the
3937- * plugin.
3938- *
3939- * @param progress_label the text to be displayed below the progress bar. If that
3940- * parameter is null, the message will be left unchanged.
3941- */
3942- public abstract void update_import_progress_pane (
3943- double progress,
3944- string? progress_message = null
3945- );
3946-
3947- /**
3948- * Sends an importable media item to the host in order to prepare it for import
3949- * and update the progress bar installed by install_import_progress_pane.
3950- *
3951- * If an error has posted, the {@link PluginHost} will not honor this request.
3952- *
3953- * @param item the importable media item to prepare for import.
3954- *
3955- * @param progress a value between 0.0 and 1.0 identifying progress for the
3956- * plugin.
3957- *
3958- * @param host_progress_delta the amount of progress the host should update
3959- * the progress bar during import preparation. Plugins should ensure that
3960- * a proportion of progress for each media item is set aside for the host
3961- * in oder to ensure a smoother update to the progress bar.
3962- *
3963- * @param progress_message the text to be displayed below the progress bar. If that
3964- * parameter is null, the message will be left unchanged.
3965- */
3966- public abstract void prepare_media_items_for_import (
3967- ImportableMediaItem[] items,
3968- double progress,
3969- double host_progress_delta = 0.0,
3970- string? progress_message = null
3971- );
3972-
3973- /**
3974- * Finalize the import sequence for the plugin. This tells the host that
3975- * all media items have been processed and that the plugin has finished all
3976- * import work. Once this method has been called, all resources used by the
3977- * plugin for import should be released and the plugin should be back to the
3978- * state it had just after running the start method. The host will then display
3979- * the final message and show progress as fully complete. In a standard import
3980- * scenario, the user is expected to click the Close button to dismiss the
3981- * dialog. On first run, the host may call the LibrarySelectedCallback again
3982- * to import another library handled by the same plugin.
3983- *
3984- * If an error has posted, the {@link PluginHost} will not honor this request.
3985- *
3986- * @param finalize_message the text to be displayed below the progress bar. If that
3987- * parameter is null, the message will be left unchanged.
3988- */
3989- public abstract void finalize_import (
3990- ImportedItemsCountCallback report_imported_items_count,
3991- string? finalize_message = null
3992- );
3993-
3994- //
3995- // For future expansion.
3996- //
3997- protected virtual void reserved0 () {}
3998- protected virtual void reserved1 () {}
3999- protected virtual void reserved2 () {}
4000- protected virtual void reserved3 () {}
4001- protected virtual void reserved4 () {}
4002- protected virtual void reserved5 () {}
4003- protected virtual void reserved6 () {}
4004- protected virtual void reserved7 () {}
4005-}
4006-
4007-/**
4008- * Describes the features and capabilities of a data import service.
4009- *
4010- * Developers of data import plugins provide a class that implements this interface.
4011- */
4012-public interface Service : Object, Spit.Pluggable {
4013- /**
4014- * A factory method that instantiates and returns a new {@link DataImporter} object
4015- * that this Service describes.
4016- */
4017- public abstract Spit.DataImports.DataImporter create_data_importer (Spit.DataImports.PluginHost host);
4018-
4019- //
4020- // For future expansion.
4021- //
4022- protected virtual void reserved0 () {}
4023- protected virtual void reserved1 () {}
4024- protected virtual void reserved2 () {}
4025- protected virtual void reserved3 () {}
4026- protected virtual void reserved4 () {}
4027- protected virtual void reserved5 () {}
4028- protected virtual void reserved6 () {}
4029- protected virtual void reserved7 () {}
4030-}
4031-
4032-}
4033-
4034
4035=== modified file 'src/plugins/mk/interfaces.mk'
4036--- src/plugins/mk/interfaces.mk 2013-04-25 00:53:04 +0000
4037+++ src/plugins/mk/interfaces.mk 2014-08-28 06:03:26 +0000
4038@@ -2,8 +2,7 @@
4039 PLUGIN_INTERFACES := \
4040 src/plugins/SpitInterfaces.vala \
4041 src/plugins/TransitionsInterfaces.vala \
4042- src/plugins/PublishingInterfaces.vala \
4043- src/plugins/DataImportsInterfaces.vala
4044+ src/plugins/PublishingInterfaces.vala
4045
4046 PLUGIN_PKG_REQS := \
4047 gobject-2.0 \
4048
4049=== modified file 'src/plugins/mk/plugins.mk'
4050--- src/plugins/mk/plugins.mk 2012-02-02 22:56:06 +0000
4051+++ src/plugins/mk/plugins.mk 2014-08-28 06:03:26 +0000
4052@@ -15,8 +15,7 @@
4053 SpitInterfaces.vala \
4054 TransitionsInterfaces.vala \
4055 StandardHostInterface.vala \
4056- ManifestWidget.vala \
4057- DataImportsInterfaces.vala
4058+ ManifestWidget.vala
4059
4060 # Any unit this unit relies upon (and should be initialized before it's initialized) should
4061 # be listed here using its Vala namespace.
4062
4063=== modified file 'src/tags/HierarchicalTagUtilities.vala'
4064--- src/tags/HierarchicalTagUtilities.vala 2014-08-08 21:13:09 +0000
4065+++ src/tags/HierarchicalTagUtilities.vala 2014-08-28 06:03:26 +0000
4066@@ -78,18 +78,6 @@
4067 return components;
4068 }
4069
4070- /**
4071- * given a list of path elements, create a fully qualified path string.
4072- * For example if 'path_elements' is the list { "Animals", "Mammals", "Elephant" }
4073- * the path "/Animals/Mammals/Elephant" will be returned
4074- */
4075- public static string? join_path_components (string[] path_components) {
4076- if (path_components.length <= 0)
4077- return null;
4078- string tmp = string.joinv (Tag.PATH_SEPARATOR_STRING, path_components);
4079- return string.joinv (Tag.PATH_SEPARATOR_STRING, { "", tmp });
4080- }
4081-
4082 public static string get_basename (string in_path) {
4083 string path = flat_to_hierarchical (in_path);
4084
4085
4086=== modified file 'units.mk'
4087--- units.mk 2014-08-28 03:37:44 +0000
4088+++ units.mk 2014-08-28 06:03:26 +0000
4089@@ -24,8 +24,7 @@
4090 tags \
4091 camera \
4092 searches \
4093- config \
4094- data_imports
4095+ config
4096
4097 # Name(s) of units that represent application entry points. These units will have init and
4098 # termination entry points generated: Name.unitize_init() and Name.unitize_terminate(). These

Subscribers

People subscribed via source and target branches

to all changes: